diff options
100 files changed, 25797 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9f44b2e --- /dev/null +++ b/.gitignore @@ -0,0 +1,37 @@ +# +.deps +.libs +.perf +# +aclocal.m4 +autom4te.cache +autoscan.log +config.cache +config.h +config.h.in +config.log +config.status +configure +configure.scan +depcomp +doltcompile +doltlibtool +install-sh +libtool +Makefile +Makefile.in +missing +py-compile +pycairo.pc +releases +stamp-h +stamp-h1 +stamp-h.in +# +*~ +.*.sw? +*.la +*.lo +*.orig +*.rej +*-uninstalled.pc @@ -0,0 +1,11 @@ +Original Author +--------------- +James Henstridge <james@daa.com.au> + +Maintainer +---------- +Steve Chaplin <stevech1097 # yahoo.com.au> + +Contributors +------------ +Maarten Breddels @@ -0,0 +1,17 @@ +PyCairo is free software. + +Every source file in the implementation of PyCairo is available to be +redistributed and/or modified under the terms of either the GNU Lesser +General Public License (LGPL) version 2.1 or the Mozilla Public +License (MPL) version 1.1. Some files are available under more +liberal terms, but we believe that in all cases, each file may be used +under either the LGPL or the MPL. + +See the following files in this directory for the precise terms and +conditions of either license: + + COPYING-LGPL-2.1 + COPYING-MPL-1.1 + +Please see each file in the implementation for Copyright and licensing +information. diff --git a/COPYING-LGPL-2.1 b/COPYING-LGPL-2.1 new file mode 100644 index 0000000..b124cf5 --- /dev/null +++ b/COPYING-LGPL-2.1 @@ -0,0 +1,510 @@ + + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 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. + + + <one line to give the library's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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. + + <signature of Ty Coon>, 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + diff --git a/COPYING-MPL-1.1 b/COPYING-MPL-1.1 new file mode 100644 index 0000000..7714141 --- /dev/null +++ b/COPYING-MPL-1.1 @@ -0,0 +1,470 @@ + MOZILLA PUBLIC LICENSE + Version 1.1 + + --------------- + +1. Definitions. + + 1.0.1. "Commercial Use" means distribution or otherwise making the + Covered Code available to a third party. + + 1.1. "Contributor" means each entity that creates or contributes to + the creation of Modifications. + + 1.2. "Contributor Version" means the combination of the Original + Code, prior Modifications used by a Contributor, and the Modifications + made by that particular Contributor. + + 1.3. "Covered Code" means the Original Code or Modifications or the + combination of the Original Code and Modifications, in each case + including portions thereof. + + 1.4. "Electronic Distribution Mechanism" means a mechanism generally + accepted in the software development community for the electronic + transfer of data. + + 1.5. "Executable" means Covered Code in any form other than Source + Code. + + 1.6. "Initial Developer" means the individual or entity identified + as the Initial Developer in the Source Code notice required by Exhibit + A. + + 1.7. "Larger Work" means a work which combines Covered Code or + portions thereof with code not governed by the terms of this License. + + 1.8. "License" means this document. + + 1.8.1. "Licensable" means having the right to grant, to the maximum + extent possible, whether at the time of the initial grant or + subsequently acquired, any and all of the rights conveyed herein. + + 1.9. "Modifications" means any addition to or deletion from the + substance or structure of either the Original Code or any previous + Modifications. When Covered Code is released as a series of files, a + Modification is: + A. Any addition to or deletion from the contents of a file + containing Original Code or previous Modifications. + + B. Any new file that contains any part of the Original Code or + previous Modifications. + + 1.10. "Original Code" means Source Code of computer software code + which is described in the Source Code notice required by Exhibit A as + Original Code, and which, at the time of its release under this + License is not already Covered Code governed by this License. + + 1.10.1. "Patent Claims" means any patent claim(s), now owned or + hereafter acquired, including without limitation, method, process, + and apparatus claims, in any patent Licensable by grantor. + + 1.11. "Source Code" means the preferred form of the Covered Code for + making modifications to it, including all modules it contains, plus + any associated interface definition files, scripts used to control + compilation and installation of an Executable, or source code + differential comparisons against either the Original Code or another + well known, available Covered Code of the Contributor's choice. The + Source Code can be in a compressed or archival form, provided the + appropriate decompression or de-archiving software is widely available + for no charge. + + 1.12. "You" (or "Your") means an individual or a legal entity + exercising rights under, and complying with all of the terms of, this + License or a future version of this License issued under Section 6.1. + For legal entities, "You" includes any entity which controls, is + controlled by, or is under common control with You. For purposes of + this definition, "control" means (a) the power, direct or indirect, + to cause the direction or management of such entity, whether by + contract or otherwise, or (b) ownership of more than fifty percent + (50%) of the outstanding shares or beneficial ownership of such + entity. + +2. Source Code License. + + 2.1. The Initial Developer Grant. + The Initial Developer hereby grants You a world-wide, royalty-free, + non-exclusive license, subject to third party intellectual property + claims: + (a) under intellectual property rights (other than patent or + trademark) Licensable by Initial Developer to use, reproduce, + modify, display, perform, sublicense and distribute the Original + Code (or portions thereof) with or without Modifications, and/or + as part of a Larger Work; and + + (b) under Patents Claims infringed by the making, using or + selling of Original Code, to make, have made, use, practice, + sell, and offer for sale, and/or otherwise dispose of the + Original Code (or portions thereof). + + (c) the licenses granted in this Section 2.1(a) and (b) are + effective on the date Initial Developer first distributes + Original Code under the terms of this License. + + (d) Notwithstanding Section 2.1(b) above, no patent license is + granted: 1) for code that You delete from the Original Code; 2) + separate from the Original Code; or 3) for infringements caused + by: i) the modification of the Original Code or ii) the + combination of the Original Code with other software or devices. + + 2.2. Contributor Grant. + Subject to third party intellectual property claims, each Contributor + hereby grants You a world-wide, royalty-free, non-exclusive license + + (a) under intellectual property rights (other than patent or + trademark) Licensable by Contributor, to use, reproduce, modify, + display, perform, sublicense and distribute the Modifications + created by such Contributor (or portions thereof) either on an + unmodified basis, with other Modifications, as Covered Code + and/or as part of a Larger Work; and + + (b) under Patent Claims infringed by the making, using, or + selling of Modifications made by that Contributor either alone + and/or in combination with its Contributor Version (or portions + of such combination), to make, use, sell, offer for sale, have + made, and/or otherwise dispose of: 1) Modifications made by that + Contributor (or portions thereof); and 2) the combination of + Modifications made by that Contributor with its Contributor + Version (or portions of such combination). + + (c) the licenses granted in Sections 2.2(a) and 2.2(b) are + effective on the date Contributor first makes Commercial Use of + the Covered Code. + + (d) Notwithstanding Section 2.2(b) above, no patent license is + granted: 1) for any code that Contributor has deleted from the + Contributor Version; 2) separate from the Contributor Version; + 3) for infringements caused by: i) third party modifications of + Contributor Version or ii) the combination of Modifications made + by that Contributor with other software (except as part of the + Contributor Version) or other devices; or 4) under Patent Claims + infringed by Covered Code in the absence of Modifications made by + that Contributor. + +3. Distribution Obligations. + + 3.1. Application of License. + The Modifications which You create or to which You contribute are + governed by the terms of this License, including without limitation + Section 2.2. The Source Code version of Covered Code may be + distributed only under the terms of this License or a future version + of this License released under Section 6.1, and You must include a + copy of this License with every copy of the Source Code You + distribute. You may not offer or impose any terms on any Source Code + version that alters or restricts the applicable version of this + License or the recipients' rights hereunder. However, You may include + an additional document offering the additional rights described in + Section 3.5. + + 3.2. Availability of Source Code. + Any Modification which You create or to which You contribute must be + made available in Source Code form under the terms of this License + either on the same media as an Executable version or via an accepted + Electronic Distribution Mechanism to anyone to whom you made an + Executable version available; and if made available via Electronic + Distribution Mechanism, must remain available for at least twelve (12) + months after the date it initially became available, or at least six + (6) months after a subsequent version of that particular Modification + has been made available to such recipients. You are responsible for + ensuring that the Source Code version remains available even if the + Electronic Distribution Mechanism is maintained by a third party. + + 3.3. Description of Modifications. + You must cause all Covered Code to which You contribute to contain a + file documenting the changes You made to create that Covered Code and + the date of any change. You must include a prominent statement that + the Modification is derived, directly or indirectly, from Original + Code provided by the Initial Developer and including the name of the + Initial Developer in (a) the Source Code, and (b) in any notice in an + Executable version or related documentation in which You describe the + origin or ownership of the Covered Code. + + 3.4. Intellectual Property Matters + (a) Third Party Claims. + If Contributor has knowledge that a license under a third party's + intellectual property rights is required to exercise the rights + granted by such Contributor under Sections 2.1 or 2.2, + Contributor must include a text file with the Source Code + distribution titled "LEGAL" which describes the claim and the + party making the claim in sufficient detail that a recipient will + know whom to contact. If Contributor obtains such knowledge after + the Modification is made available as described in Section 3.2, + Contributor shall promptly modify the LEGAL file in all copies + Contributor makes available thereafter and shall take other steps + (such as notifying appropriate mailing lists or newsgroups) + reasonably calculated to inform those who received the Covered + Code that new knowledge has been obtained. + + (b) Contributor APIs. + If Contributor's Modifications include an application programming + interface and Contributor has knowledge of patent licenses which + are reasonably necessary to implement that API, Contributor must + also include this information in the LEGAL file. + + (c) Representations. + Contributor represents that, except as disclosed pursuant to + Section 3.4(a) above, Contributor believes that Contributor's + Modifications are Contributor's original creation(s) and/or + Contributor has sufficient rights to grant the rights conveyed by + this License. + + 3.5. Required Notices. + You must duplicate the notice in Exhibit A in each file of the Source + Code. If it is not possible to put such notice in a particular Source + Code file due to its structure, then You must include such notice in a + location (such as a relevant directory) where a user would be likely + to look for such a notice. If You created one or more Modification(s) + You may add your name as a Contributor to the notice described in + Exhibit A. You must also duplicate this License in any documentation + for the Source Code where You describe recipients' rights or ownership + rights relating to Covered Code. You may choose to offer, and to + charge a fee for, warranty, support, indemnity or liability + obligations to one or more recipients of Covered Code. However, You + may do so only on Your own behalf, and not on behalf of the Initial + Developer or any Contributor. You must make it absolutely clear than + any such warranty, support, indemnity or liability obligation is + offered by You alone, and You hereby agree to indemnify the Initial + Developer and every Contributor for any liability incurred by the + Initial Developer or such Contributor as a result of warranty, + support, indemnity or liability terms You offer. + + 3.6. Distribution of Executable Versions. + You may distribute Covered Code in Executable form only if the + requirements of Section 3.1-3.5 have been met for that Covered Code, + and if You include a notice stating that the Source Code version of + the Covered Code is available under the terms of this License, + including a description of how and where You have fulfilled the + obligations of Section 3.2. The notice must be conspicuously included + in any notice in an Executable version, related documentation or + collateral in which You describe recipients' rights relating to the + Covered Code. You may distribute the Executable version of Covered + Code or ownership rights under a license of Your choice, which may + contain terms different from this License, provided that You are in + compliance with the terms of this License and that the license for the + Executable version does not attempt to limit or alter the recipient's + rights in the Source Code version from the rights set forth in this + License. If You distribute the Executable version under a different + license You must make it absolutely clear that any terms which differ + from this License are offered by You alone, not by the Initial + Developer or any Contributor. You hereby agree to indemnify the + Initial Developer and every Contributor for any liability incurred by + the Initial Developer or such Contributor as a result of any such + terms You offer. + + 3.7. Larger Works. + You may create a Larger Work by combining Covered Code with other code + not governed by the terms of this License and distribute the Larger + Work as a single product. In such a case, You must make sure the + requirements of this License are fulfilled for the Covered Code. + +4. Inability to Comply Due to Statute or Regulation. + + If it is impossible for You to comply with any of the terms of this + License with respect to some or all of the Covered Code due to + statute, judicial order, or regulation then You must: (a) comply with + the terms of this License to the maximum extent possible; and (b) + describe the limitations and the code they affect. Such description + must be included in the LEGAL file described in Section 3.4 and must + be included with all distributions of the Source Code. Except to the + extent prohibited by statute or regulation, such description must be + sufficiently detailed for a recipient of ordinary skill to be able to + understand it. + +5. Application of this License. + + This License applies to code to which the Initial Developer has + attached the notice in Exhibit A and to related Covered Code. + +6. Versions of the License. + + 6.1. New Versions. + Netscape Communications Corporation ("Netscape") may publish revised + and/or new versions of the License from time to time. Each version + will be given a distinguishing version number. + + 6.2. Effect of New Versions. + Once Covered Code has been published under a particular version of the + License, You may always continue to use it under the terms of that + version. You may also choose to use such Covered Code under the terms + of any subsequent version of the License published by Netscape. No one + other than Netscape has the right to modify the terms applicable to + Covered Code created under this License. + + 6.3. Derivative Works. + If You create or use a modified version of this License (which you may + only do in order to apply it to code which is not already Covered Code + governed by this License), You must (a) rename Your license so that + the phrases "Mozilla", "MOZILLAPL", "MOZPL", "Netscape", + "MPL", "NPL" or any confusingly similar phrase do not appear in your + license (except to note that your license differs from this License) + and (b) otherwise make it clear that Your version of the license + contains terms which differ from the Mozilla Public License and + Netscape Public License. (Filling in the name of the Initial + Developer, Original Code or Contributor in the notice described in + Exhibit A shall not of themselves be deemed to be modifications of + this License.) + +7. DISCLAIMER OF WARRANTY. + + COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF + DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING. + THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED CODE + IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, + YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE + COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER + OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF + ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER. + +8. TERMINATION. + + 8.1. This License and the rights granted hereunder will terminate + automatically if You fail to comply with terms herein and fail to cure + such breach within 30 days of becoming aware of the breach. All + sublicenses to the Covered Code which are properly granted shall + survive any termination of this License. Provisions which, by their + nature, must remain in effect beyond the termination of this License + shall survive. + + 8.2. If You initiate litigation by asserting a patent infringement + claim (excluding declatory judgment actions) against Initial Developer + or a Contributor (the Initial Developer or Contributor against whom + You file such action is referred to as "Participant") alleging that: + + (a) such Participant's Contributor Version directly or indirectly + infringes any patent, then any and all rights granted by such + Participant to You under Sections 2.1 and/or 2.2 of this License + shall, upon 60 days notice from Participant terminate prospectively, + unless if within 60 days after receipt of notice You either: (i) + agree in writing to pay Participant a mutually agreeable reasonable + royalty for Your past and future use of Modifications made by such + Participant, or (ii) withdraw Your litigation claim with respect to + the Contributor Version against such Participant. If within 60 days + of notice, a reasonable royalty and payment arrangement are not + mutually agreed upon in writing by the parties or the litigation claim + is not withdrawn, the rights granted by Participant to You under + Sections 2.1 and/or 2.2 automatically terminate at the expiration of + the 60 day notice period specified above. + + (b) any software, hardware, or device, other than such Participant's + Contributor Version, directly or indirectly infringes any patent, then + any rights granted to You by such Participant under Sections 2.1(b) + and 2.2(b) are revoked effective as of the date You first made, used, + sold, distributed, or had made, Modifications made by that + Participant. + + 8.3. If You assert a patent infringement claim against Participant + alleging that such Participant's Contributor Version directly or + indirectly infringes any patent where such claim is resolved (such as + by license or settlement) prior to the initiation of patent + infringement litigation, then the reasonable value of the licenses + granted by such Participant under Sections 2.1 or 2.2 shall be taken + into account in determining the amount or value of any payment or + license. + + 8.4. In the event of termination under Sections 8.1 or 8.2 above, + all end user license agreements (excluding distributors and resellers) + which have been validly granted by You or any distributor hereunder + prior to termination shall survive termination. + +9. LIMITATION OF LIABILITY. + + UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT + (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE INITIAL + DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED CODE, + OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR + ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY + CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL, + WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER + COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN + INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF + LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY + RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW + PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE + EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO + THIS EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU. + +10. U.S. GOVERNMENT END USERS. + + The Covered Code is a "commercial item," as that term is defined in + 48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial computer + software" and "commercial computer software documentation," as such + terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48 + C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995), + all U.S. Government End Users acquire Covered Code with only those + rights set forth herein. + +11. MISCELLANEOUS. + + This License represents the complete agreement concerning subject + matter hereof. If any provision of this License is held to be + unenforceable, such provision shall be reformed only to the extent + necessary to make it enforceable. This License shall be governed by + California law provisions (except to the extent applicable law, if + any, provides otherwise), excluding its conflict-of-law provisions. + With respect to disputes in which at least one party is a citizen of, + or an entity chartered or registered to do business in the United + States of America, any litigation relating to this License shall be + subject to the jurisdiction of the Federal Courts of the Northern + District of California, with venue lying in Santa Clara County, + California, with the losing party responsible for costs, including + without limitation, court costs and reasonable attorneys' fees and + expenses. The application of the United Nations Convention on + Contracts for the International Sale of Goods is expressly excluded. + Any law or regulation which provides that the language of a contract + shall be construed against the drafter shall not apply to this + License. + +12. RESPONSIBILITY FOR CLAIMS. + + As between Initial Developer and the Contributors, each party is + responsible for claims and damages arising, directly or indirectly, + out of its utilization of rights under this License and You agree to + work with Initial Developer and Contributors to distribute such + responsibility on an equitable basis. Nothing herein is intended or + shall be deemed to constitute any admission of liability. + +13. MULTIPLE-LICENSED CODE. + + Initial Developer may designate portions of the Covered Code as + "Multiple-Licensed". "Multiple-Licensed" means that the Initial + Developer permits you to utilize portions of the Covered Code under + Your choice of the NPL or the alternative licenses, if any, specified + by the Initial Developer in the file described in Exhibit A. + +EXHIBIT A -Mozilla Public License. + + ``The contents of this file are subject to the Mozilla Public License + Version 1.1 (the "License"); you may not use this file except in + compliance with the License. You may obtain a copy of the License at + http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" + basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the + License for the specific language governing rights and limitations + under the License. + + The Original Code is ______________________________________. + + The Initial Developer of the Original Code is ________________________. + Portions created by ______________________ are Copyright (C) ______ + _______________________. All Rights Reserved. + + Contributor(s): ______________________________________. + + Alternatively, the contents of this file may be used under the terms + of the _____ license (the "[___] License"), in which case the + provisions of [______] License are applicable instead of those + above. If you wish to allow use of your version of this file only + under the terms of the [____] License and not to allow others to use + your version of this file under the MPL, indicate your decision by + deleting the provisions above and replace them with the notice and + other provisions required by the [___] License. If you do not delete + the provisions above, a recipient may use your version of this file + under either the MPL or the [___] License." + + [NOTE: The text of this Exhibit A may differ slightly from the text of + the notices in the Source Code files of the Original Code. You should + use the text of this Exhibit A rather than the text found in the + Original Code Source Code for Your Modifications.] + @@ -0,0 +1,32 @@ +Install method1 - preferred method +--------------- +Using the same install method of install as cairo - GNU autotools. + + $ python -c "import sys; print sys.prefix" + # make a note of the python prefix + $ ./configure --prefix=<python_prefix> + $ make + $ make install # may require superuser access + +To build from CVS, use this line instead of the configure line above: + $ ./autogen.sh --prefix=<python_prefix> + +If you're installing to another prefix than the one where Python is installed +Python will not be able to find the cairo module until you add +$prefix/lib/pythonX.Y/site-packages to the PYTHONPATH variable. + + +Install method2 - alternative install method +--------------- + 1. Untar the .tar.gz file + 2. cd into the resulting directory + 3. python setup.py install + + +Testing +------- +testing uses py.test from pylib +http://codespeak.net/py/dist/ + +$ cd test +$ py.test diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..147f546 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,90 @@ +SUBDIRS = src examples test doc + +EXTRA_DIST = \ + COPYING \ + COPYING-LGPL-2.1 \ + COPYING-MPL-1.1 \ + pycairo.pc.in \ + setup.py + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = pycairo.pc + +# release targets from cairo/Makefile.am +# Some custom targets to make it easier to release things. +# Use either: +# make release-check +# or make release-publish + +RELEASE_UPLOAD_HOST = cairographics.org +RELEASE_UPLOAD_BASE = /srv/cairo.freedesktop.org/www + +RELEASE_UPLOAD_DIR = $(RELEASE_UPLOAD_BASE)/releases +RELEASE_URL_BASE = http://cairographics.org/releases +#RELEASE_UPLOAD_DIR = $(RELEASE_UPLOAD_BASE)/snapshots +#RELEASE_URL_BASE = http://cairographics.org/snapshots + +RELEASE_ANNOUNCE_LIST = cairo-announce@cairographics.org (and CC python-announce-list@python.org) + +tar_file = $(PACKAGE)-$(VERSION).tar.gz +md5_file = $(tar_file).md5 + +$(md5_file): $(tar_file) + md5sum $^ > $@ + +release-verify-even-micro: + @echo -n "Checking that $(VERSION) has an even micro component..." + @test "$(PYCAIRO_VERSION_MICRO)" = "`echo $(PYCAIRO_VERSION_MICRO)/2*2 | bc`" \ + || (echo "Ouch." && echo "The version micro component '$(PYCAIRO_VERSION_MICRO)' is not an even number." \ + && echo "The version in configure.in must be incremented before a new release." \ + && false) + @echo "Good." + +release-verify-newer: + @echo -n "Checking that no $(VERSION) release already exists..." + @ssh $(RELEASE_UPLOAD_HOST) test ! -e $(RELEASE_UPLOAD_DIR)/$(tar_file) \ + || (echo "Ouch." && echo "Found: $(RELEASE_UPLOAD_HOST):$(RELEASE_UPLOAD_DIR)/$(tar_file)" \ + && echo "Are you sure you have an updated CVS checkout?" \ + && echo "This should never happen." \ + && false) + @echo "Good." + +release-remove-old: + rm -f $(tar_file) $(md5_file) + +release-check: release-verify-even-micro release-verify-newer release-remove-old distcheck $(md5_file) + +release-upload: release-check $(tar_file) $(md5_file) + mkdir -p releases + scp $(tar_file) $(md5_file) $(RELEASE_UPLOAD_HOST):$(RELEASE_UPLOAD_DIR) + mv $(tar_file) $(md5_file) releases + ssh $(RELEASE_UPLOAD_HOST) "rm -f $(RELEASE_UPLOAD_DIR)/LATEST-$(PACKAGE)-[0-9]* && ln -s $(tar_file) $(RELEASE_UPLOAD_DIR)/LATEST-$(PACKAGE)-$(VERSION)" + cvs tag RELEASE_$(PYCAIRO_VERSION_MAJOR)_$(PYCAIRO_VERSION_MINOR)_$(PYCAIRO_VERSION_MICRO) + +release-publish: release-upload releases/$(md5_file) + @echo "" + @echo "Please send an announcement to $(RELEASE_ANNOUNCE_LIST)" + @echo "including the following:" + @echo "" + @echo "Subject: ANN: $(PACKAGE) release $(VERSION) now available" + @echo "" + @echo "============================== CUT HERE ==============================" + @echo "Pycairo is a set of Python bindings for the multi-platform 2D graphics library cairo." + @echo " http://cairographics.org" + @echo " http://cairographics.org/pycairo" + @echo "" + @echo "A new $(PACKAGE) release $(VERSION) is now available from:" + @echo "" + @echo " $(RELEASE_URL_BASE)/$(tar_file)" + @echo " $(RELEASE_URL_BASE)/$(md5_file)" + @echo "" + @echo -n " " + @cat releases/$(md5_file) + @echo "" + @echo "============================== CUT HERE ==============================" + @echo "Also, please include the new entries from the NEWS file." + @echo "" + @echo "Last but not least, do not forget to bump up the micro" + @echo "version component to the next (odd) number and commit." + +.PHONY: release-verify-even-micro release-verify-newer release-remove-old release-check release-upload release-publish @@ -0,0 +1,450 @@ +Overview of changes from pycairo 1.8.4 to pycairo 1.8.6 +======================================================= +General Changes: + Pycairo 1.8.6 requires cairo 1.8.6 (or later) + +Bug Fixes: + ImageSurface.create_from_png _read_func fix + ToyFontFace type fix + 19221: restore cairo.Matrix '*' operator to the way it originally worked. + +Other Changes: + Documentation completed. + + +Overview of changes from pycairo 1.8.2 to pycairo 1.8.4 +======================================================= +General Changes: + Pycairo 1.8.4 requires cairo 1.8.4 (or later) and Python 2.6 + +Bug Fixes: + 20674: Add get/set_extend for Gradient Patterns + +New Classes: + cairo.ToyFontFace + +New Methods: + Pattern.get_extend + Pattern.set_extend + ToyFontFace.get_family + ToyFontFace.get_slant + ToyFontFace.get_weight + +Deleted Methods: + SurfacePattern.get_extend + SurfacePattern.set_extend + +Other Changes: + Threading for surfaces with stream functions has been reenabled. + Documentation updates. + + +Overview of changes from pycairo 1.8.0 to pycairo 1.8.2 +======================================================= + +Pycairo 1.8.0 resulted in crashes for some applications using threads. So +upgrading to 1.8.2 is recommended for threaded applications. + +Bug Fixes: #19287: Threading support results in crashes in cairo.ImageSurface + +New Methods: + Context.set_scaled_font + +API Changes: + Matrix multiplication: + old code: matrix3 = matrix1 * matrix2 + new equivalent code: matrix3 = matrix1.multiply(matrix2) + matrix3 = matrix1 * matrix2 + is now equivalent to matrix3 = matrix2.multiply(matrix1) + which is consistent with standard matrix multiplication. + + +Overview of changes from pycairo 1.6.4 to pycairo 1.8.0 +======================================================= +General Changes: + Pycairo 1.8.0 requires cairo 1.8.0 (or later). + Add documentation (available separately) + +Bug Fixes: + 18101: Add support for threading + 18947: cairo.SurfacePattern should INCREF the used surface + +New Methods: + ScaledFont.get_scale_matrix + Surface.mark_dirty_rectangle + Surface.set_fallback_resolution + +New Constants: + cairo.EXTEND_PAD + cairo.HAS_IMAGE_SURFACE + cairo.HAS_USER_FONT + +API Changes: + Surface.mark_dirty: no longer accepts keyword arguments with default + values. + PycairoPattern_FromPattern (C API): has a new 'base' argument - to fix + #18947. + +Other Changes: + Allow unknown cairo Pattern/Surface types to use the pycairo base + Pattern/Surface type. + + +Overview of changes from pycairo 1.4.12 to pycairo 1.6.4 +======================================================== +General changes: + Pycairo 1.6.4 requires cairo 1.6.4 (or later). + requires Python 2.5 (or later). + +Bug fixes: + 16112: Fix win32 'python setup.py ...' build -- use double quotes + +New Methods: + Context.has_current_point + Context.path_extents + ImageSurface.format_stride_for_width + PSSurface.get_eps + PSSurface.set_eps + PSSurface.ps_level_to_string + PSSurface.restrict_to_level + Surface.copy_page + Surface.show_page + +New Constants: + cairo.PS_LEVEL_2, cairo.PS_LEVEL_3 + +Other changes: + test/pygame-test1.py, test/pygame-test2.py : pygame tests + + examples/cairo_snippets/snippets/ellipse.py : Update + so line-width is a constant width in device-space not user-space + + +Overview of changes from pycairo 1.4.0 to pycairo 1.4.12 +======================================================== +General changes: + Pycairo 1.4.12 requires cairo 1.4.12 (or later). + requires Python 2.4 (or later). + +Bug fixes: + 10006: update autogen.sh to support automake >= 1.10 + 13460: use python-config to get python includes + +Other changes: + - allow cairo.Context to be subclassed + - create a 'doc' subdirectory and start a FAQ file + + +Overview of changes from pycairo 1.2.6 to pycairo 1.4.0 +======================================================= +General changes: +Pycairo 1.4.0 requires cairo 1.4.0 (or later). + +New methods: + Context.clip_extents + Context.copy_clip_rectangles + Context.get_dash + Context.get_dash_count + Context.get_scaled_font + Context.glyph_extents + Context.glyph_path + Context.show_glyphs + LinearGradient.get_linear_points + RadialGradient.get_radial_circles + SolidPattern.get_rgba + SurfacePattern.get_surface + +Deleted methods: + ImageSurface.create_for_array + Remove Numeric Python support, since Numeric has been made obsolete by + numpy, and numpy data can be read using ImageSurface.create_for_data. + +Other changes: + the module cairo.gtk has been removed (pygtk 2.7.0 onwards has cairo + support built in). + + +Overview of changes from pycairo 1.2.2 to pycairo 1.2.6 +======================================================= + +* Pycairo 1.2.6 requires cairo 1.2.6 (or later). + +* mingw32 compiler fixes (Cedric Gustin) + +* setup.py improvements (Cedric Gustin) + +* ImageSurface.get_data() new method added + ImageSurface.get_data_as_rgba() method removed + + +Overview of changes from pycairo 1.2.0 to pycairo 1.2.2 +======================================================= + +* Pycairo requires cairo 1.2.2 (or later). + +* setup.py has been updated to allow installation by executing + $ python setup.py install + +* examples/cairo_snippets/snippets/gradient_mask.py + A new example to demonstrate pattern masks. + +* The cairo.svg module has been removed because: + 1) Cairo does not include SVG parsing, so this module does not belong + in pycairo. + 2) libsvg-cairo (the underlying C library) is unmaintained. + + +Overview of changes from pycairo 1.1.6 to pycairo 1.2.0 +======================================================= +General changes: +Pycairo has been updated to work with cairo 1.2.0. + +New methods: + Surface.set_fallback_resolution + Surface_get_content + ImageSurface_get_format + Image_surface_get_stride + +Deleted methods: + PDFSurface.set_dpi, PSSurface.set_dpi, SVGSurface.set_dpi + - replaced by Surface.set_fallback_resolution + +Other changes: + cairo.FORMAT_RGB16_565 added + + +Overview of changes from pycairo 1.0.2 to pycairo 1.1.6 +======================================================= +General changes: +Pycairo has been updated to work with cairo 1.1.6. + +New objects: + SVGSurface + +New methods: + Context.get_group_target + Context.new_sub_path + Context.pop_group + Context.pop_group_to_source + Context.push_group + Context.push_group_with_content + FontOptions.get_antialias + FontOptions.get_hint_metrics + FontOptions.get_hint_style + FontOptions.get_subpixel_order + FontOptions.set_antialias + FontOptions.set_hint_metrics + FontOptions.set_hint_style + FontOptions.set_subpixel_order + PDFSurface.set_size + PSSurface.dsc_begin_page_setup + PSSurface.dsc_begin_setup + PSSurface.dsc_comment + PSSurface.set_size + ScaledFont.get_font_face + ScaledFont.text_extents + Surface.get_device_offset + XlibSurface.get_depth + +Updated methods: + PDFSurface()/PSSurface() - can now write to file-like objects (like + StringIO). + + surface.write_to_png() and ImageSurface.create_from_png() can now write to + file-like objects (like StringIO). + + select_font_face, show_text, text_extents and text_path now accept unicode + objects. + +Other changes: + misc bug fixes. + +New examples: + examples/cairo_snippets/snippets_svg.py + examples/cairo_snippets/snippets/ellipse.py + examples/cairo_snippets/snippets/group.py + examples/svg/svgconvert.py + + +Overview of changes from pycairo 1.0.0 to pycairo 1.0.2 +======================================================= +General changes: +Pycairo has been updated to work with cairo 1.0.2. + +New cairo functions supported: + cairo.ImageSurface.create_for_data() + +Updated functions: + ctx.set_source_rgba (r, g, b, a=1.0) now supports a default alpha argument + +Other changes: + cairo.Matrix now supports the Python sequence protocol, so you can do: + xx, yx, xy, yy, x0, y0 = matrix + + +Overview of changes from pycairo 0.9.0 to pycairo 1.0.0 +======================================================= +General changes: +Pycairo has been updated to work with cairo 1.0.0. + +New cairo functions supported: + cairo.cairo_version() + cairo.cairo_version_string() + PSSurface.set_dpi() + +Patterns are now implemented in a class hierarchy, the new constructors are: + cairo.SolidPattern (r, g, b, a=1.0) + cairo.SurfacePattern (surface) + cairo.LinearGradient (x0, y0, x1, y1) + cairo.RadialGradient (cx0, cy0, radius0, cx1, cy1, radius1) + +Updated functions: + Surface.write_to_png() now accepts a file object as well as a filename + +Updated examples: + The gtk examples now work with pygtk >= 2.7.0 without requiring the + cairo.gtk module + +Bug Fixes + fix "initializer element is not constant" compiler warnings + + +Overview of changes from pycairo 0.6.0 to pycairo 0.9.0 +======================================================= +General changes: +Pycairo has been updated to work with cairo 0.9.0. + +New cairo functions supported: + cairo_get_antialias + cairo_set_antialias + cairo_surface_mark_dirty_rectangle + cairo_surface_flush + +Bug Fixes +- double buffering now works with the cairo.gtk module + + +Overview of changes from pycairo 0.5.1 to pycairo 0.6.0 +======================================================= +General changes: + Pycairo has been updated to work with cairo 0.6.0, including using cairo's new + error handling scheme. + +New features: + cairo.CONTENT_COLOR, cairo.ALPHA, cairo.COLOR_ALPHA have been added for + working with surfaces. + + A new class cairo.FontOptions has been added. + + cairo.ImageSurface.create_from_png() now accepts a filename string or a file + object + + New wrapper functions have been added for cairo_get_font_options, + cairo_set_font_options and cairo_surface_get_font_options. + + +Overview of changes from pycairo 0.5.0 to pycairo 0.5.1 +======================================================= +New features: +- new class cairo.Win32Surface (Niki Spahiev) +- cairo.HAS_WIN32_SURFACE, cairo.HAS_PS_SURFACE etc are defined to give access + to the values from cairo-features.h + +Fixes: +- fix cairo_mask, cairo_mask_surface and cairo_stroke_preserve wrappers +- compile properly against GTK+ 2.7 (Gustavo Carneiro) +- other small fixes, including fixes for gcc 4.0 warnings + + +Overview of changes from pycairo 0.5.1 to pycairo 0.6.0 +======================================================= +This version has many changes which update Pycairo to the new cairo API. The +change list is not duplicated here, instead see the cairo/NEWS file for full +details of all these API changes. + +Pycairo method names that were different from the underlying cairo function +names have been changed to make Pycairo more closely follow cairo and so +enable the cairo documentation to be used for writing Pycairo programs. +NOTES has been updated to list the differences between the C API and the +Pycairo API. + +Context.copy_path() has been implemented, it returns a Path instance which +supports the iterator protocol. + +Python 2.3 is now required. + +New examples: +examples/warpedtext.py + shows usage of the Path iterator + +examples/cairo_snippets/ + shows many of the 'cairo-demo/cairo_snippets' examples + +examples/gtk/png_view.py + example using cairo.ImageSurface.create_from_png() + + +Overview of changes from pycairo 0.1.4 to pycairo 0.4.0 +======================================================= +New cairo bindings: + cairo_font_extents + +Bindings removed: + cairo_font_set_transform + cairo_font_current_transform + +New examples: + gtk/hangman.py + +Other: + Changed version numbering to correspond directly with the Cairo + version Pycairo was developed to work with. So, for example, + Pycairo version 0.4.0 represents the Pycairo version that has been + developed and tested with Cairo 0.4.0. + +Overview of changes from pycairo 0.1.3 to pycairo 0.1.4 +======================================================= +The Pycairo license has changed so that it is now dual-licensed under the LGPL +and the MPL, the same as Cairo itself. For details see the COPYING file as +well as COPYING-LGPL-2.1 and COPYING-MPL-1.1. + +New cairo bindings: + cairo_pdf_surface_create + cairo_set_target_pdf + +New libsvg-cairo bindings: + svg_cairo_parse + svg_cairo_parse_buffer + svg_cairo_render + svg_cairo_get_size + +Other: + Added --without-pygtk configure option. + Renamed the Pycairo API _new() functions to _wrap() to allow _new() to + be used for python __new__ functions. + New examples: svg2png.py and svgview.py. + + +Overview of changes for pycairo 0.1.3 +===================================== +After the recent server compromise we discarded all unsigned +snapshots. That left us without a pycairo snapshot. + +Additionally, there were no tags in the source repository so I +couldn't recreate the 0.1.2 snapshot, so here's a new 0.1.3 snapshot. + +I apologize if I botched the version number or left something +significant out of this announcement---I'm not the one who will +usually be doing pycairo maintenance. + +New bindings: + current_path + current_path_flat + current_font_extents + +Changes: + fill_extents,stroke_extents: Remove unnecessary args and + change from a method to an attribute. + +Other: + Added two new examples: context-subclass.py and warpedtext.py @@ -0,0 +1,41 @@ +Pycairo - Python bindings for cairo +http://www.cairographics.org/pycairo + +Dependencies +------------ + cairo >= 1.8.6 + Python >= 2.6 + +Compiling +--------- +See the INSTALL document for build instructions. + +Documentation +------------- +The 'doc' directory contains reStructuredText files which are used by Sphinx +to generate html (and other format) documentation. + +License +------- +Pycairo is free software and is available to be redistributed and/or modified +under the terms of either the GNU Lesser General Public License (LGPL) version +2.1 or the Mozilla Public License (MPL) version 1.1. + +Contact +------- +Mailing List: +If you have some ideas for how cairo or Pycairo could be improved, please feel +free to send a message to cairo@cairographics.org + http://cairographics.org/cgi-bin/mailman/listinfo/cairo + +Bugzilla: +If you find a bug in Pycairo, please go to + https://bugs.freedesktop.org/enter_bug.cgi?product=pycairo +and submit a bugreport. + +IMPORTANT: make sure you state which version of cairo and pycairo you are +using when you report a problem or bug. + +>>> import cairo +>>> cairo.cairo_version_string() # shows the cairo version +>>> cairo.version # shows the pycairo version diff --git a/RELEASING b/RELEASING new file mode 100644 index 0000000..99b6b4d --- /dev/null +++ b/RELEASING @@ -0,0 +1,98 @@ +Here are the steps to follow to create a new pycairo release: + +1) Ensure that there are no local, uncommitted modifications. The best + thing to do here may be to begin with a fresh checkout from CVS: + + cvs -d cairographics.org:/cvs/cairo co pycairo + + But it's probably good enough if "cvs -q update -Ad" generates no + output. + +2) Fill out an entry in the NEWS file + + Sift through the information in ChangeLog since the last release. Summarize + major changes briefly in a style similar to other entries in NEWS. + +3) Increment version numbers in: + cairo/cairomodule.c + configure.ac + doc/conf.py + README + setup.py + + Increment pycairo_major/minor/micro_version in configure.ac + Increase the cairo_required_version - to an even numbered version. + Increment pycairo_major/minor version to match the cairo major/minor + version that pycairo requires (and increment the micro version if + necessary for any subsequent pycairo updates). + +(install fresh copy, run examples, run any other tests) + +4) Commit the changes to NEWS, configure.ac etc + + Don't forget to fill out the ChangeLog just like with any other commit. + It's especially important to mention the new version number in the + ChangeLog. + Add a '=== Pycairo x.x.x ===' header to ChangeLog + Do "cvs -q update -Ad" to confirm there are no uncommitted changes. + +5) Run "make distcheck" and verify that it gives in no warnings or errors and + ends with a message of the form: + + =============================================== + pycairo-X.Y.Z archives ready for distribution: + pycairo-X.Y.Z.tar.gz + =============================================== + +6) Edit Makefile.am and select either 'snapshot' or 'release'. + Run "make release-publish" which will perform the following steps for you: + + * Check that the version number ends with an even micro component + * Check that no release exists with the current version + * Verify that make distcheck completes successfully + * Generate the final tar file + * Generate an md5sum file + * scp both files to appear on http://cairographics.org/releases + * Place local copies of the files in the releases directory + * Create a LATEST-package-version file (after deleting any old one) + * Tag the entire source tree with a tag of the form RELEASE_X_Y_Z + * Provide some text for the release announcement (see below). + +7) Verify that the tar file arrived at the website. + Check tar file has read permissions for all. + Update the pycairo webpage to reference the new release. + Update http://cheeseshop.python.org entry for pycairo. + +8) Edit: + cairo/cairomodule.c + configure.ac + setup.py + to increment pycairo_version_micro to the next larger (odd) number and + commit. + +9) Send a message to cairo-announce@cairographics.org + and CC python-announce-list@python.org + to announce the new release using the text provided from + "make release-publish". + + +Generating documentation archives +--------------------------------- +$ cd doc/ +$ vi conf.py # update the version and release numbers +$ make clean +$ make html +$ cd .build/ +$ mv html pycairo-x.x.x-docs-html +$ tar cjf /tmp/pycairo-x.x.x-docs-html.tar.bz2 pycairo-x.x.x-docs-html +$ zip -r /tmp/pycairo-x.x.x-docs-html.zip pycairo-x.x.x-docs-html +$ chmod a+r /tmp/pycairo* + +untar docs in /tmp and check that they have correct version number and view +OK. +copy file to the 'releases' directory on cairo website: + scp pycairo-xxx cairographics.org:/srv/cairo.freedesktop.org/www/releases + +cd doc + html_docs_create.sh + html_docs_upload.sh diff --git a/acinclude.m4 b/acinclude.m4 new file mode 100644 index 0000000..8ef2000 --- /dev/null +++ b/acinclude.m4 @@ -0,0 +1,67 @@ +## this one is commonly used with AM_PATH_PYTHONDIR ... +dnl AM_CHECK_PYMOD(MODNAME [,SYMBOL [,ACTION-IF-FOUND [,ACTION-IF-NOT-FOUND]]]) +dnl Check if a module containing a given symbol is visible to python. +AC_DEFUN([AM_CHECK_PYMOD], +[AC_REQUIRE([AM_PATH_PYTHON]) +py_mod_var=`echo $1['_']$2 | sed 'y%./+-%__p_%'` +AC_MSG_CHECKING(for ifelse([$2],[],,[$2 in ])python module $1) +AC_CACHE_VAL(py_cv_mod_$py_mod_var, [ +ifelse([$2],[], [prog=" +import sys +try: + import $1 +except ImportError: + sys.exit(1) +except: + sys.exit(0) +sys.exit(0)"], [prog=" +import $1 +$1.$2"]) +if $PYTHON -c "$prog" 1>&AC_FD_CC 2>&AC_FD_CC + then + eval "py_cv_mod_$py_mod_var=yes" + else + eval "py_cv_mod_$py_mod_var=no" + fi +]) +py_val=`eval "echo \`echo '$py_cv_mod_'$py_mod_var\`"` +if test "x$py_val" != xno; then + AC_MSG_RESULT(yes) + ifelse([$3], [],, [$3 +])dnl +else + AC_MSG_RESULT(no) + ifelse([$4], [],, [$4 +])dnl +fi +]) + +dnl a macro to check for ability to create python extensions +dnl AM_CHECK_PYTHON_HEADERS([ACTION-IF-POSSIBLE], [ACTION-IF-NOT-POSSIBLE]) +dnl function also defines PYTHON_INCLUDES +AC_DEFUN([AM_CHECK_PYTHON_HEADERS], +[AC_REQUIRE([AM_PATH_PYTHON]) +AC_MSG_CHECKING(for headers required to compile python extensions) +dnl deduce PYTHON_INCLUDES +if test -x "$PYTHON-config"; then + PYTHON_INCLUDES=`$PYTHON-config --includes 2>/dev/null` +else + py_prefix=`$PYTHON -c "import sys; print sys.prefix"` + py_exec_prefix=`$PYTHON -c "import sys; print sys.exec_prefix"` + PYTHON_INCLUDES="-I${py_prefix}/include/python${PYTHON_VERSION}" + if test "$py_prefix" != "$py_exec_prefix"; then + PYTHON_INCLUDES="$PYTHON_INCLUDES -I${py_exec_prefix}/include/python${PYTHON_VERSION}" + fi +fi +AC_SUBST(PYTHON_INCLUDES) +dnl check if the headers exist: +save_CPPFLAGS="$CPPFLAGS" +CPPFLAGS="$CPPFLAGS $PYTHON_INCLUDES" +AC_TRY_CPP([#include <Python.h>],dnl +[AC_MSG_RESULT(found) +$1],dnl +[AC_MSG_RESULT(not found) +$2]) +CPPFLAGS="$save_CPPFLAGS" +]) + diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 0000000..7e22288 --- /dev/null +++ b/autogen.sh @@ -0,0 +1,196 @@ +#!/bin/sh +# Run this to generate all the initial makefiles, etc. +set -e + +ARGV0=$0 + +# Allow invocation from a separate build directory; in that case, we change +# to the source directory to run the auto*, then change back before running configure +srcdir=`dirname $ARGV0` +test -z "$srcdir" && srcdir=. + +ORIGDIR=`pwd` +cd $srcdir + +PACKAGE=Pycairo + +LIBTOOLIZE=${LIBTOOLIZE-libtoolize} +LIBTOOLIZE_FLAGS="--copy --force" +AUTOHEADER=${AUTOHEADER-autoheader} +AUTOMAKE_FLAGS="--add-missing --foreign" +AUTOCONF=${AUTOCONF-autoconf} + + +CONFIGURE_IN= +test -f configure.in && CONFIGURE_IN=configure.in +test -f configure.ac && CONFIGURE_IN=configure.ac + +if test "X$CONFIGURE_IN" = X; then + echo "$ARGV0: ERROR: No $srcdir/configure.in or $srcdir/configure.ac found." + exit 1 +fi + +extract_version() { # modified from cairo/autogen.sh + grep "^ *$1" $CONFIGURE_IN | sed 's/.*(\[*\([^]) ]*\).*/\1/'; +} + +autoconf_min_vers=`extract_version AC_PREREQ` +automake_min_vers=`extract_version AM_INIT_AUTOMAKE` +libtoolize_min_vers=`extract_version AC_PROG_LIBTOOL` +aclocal_min_vers=$automake_min_vers + + +# Not all echo versions allow -n, so we check what is possible. This test is +# based on the one in autoconf. +case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in + *c*,-n*) ECHO_N= ;; + *c*,* ) ECHO_N=-n ;; + *) ECHO_N= ;; +esac + + +# some terminal codes ... +boldface="`tput bold 2>/dev/null`" +normal="`tput sgr0 2>/dev/null`" +printbold() { + echo $ECHO_N "$boldface" + echo "$@" + echo $ECHO_N "$normal" +} +printerr() { + echo "$@" >&2 +} + + +# Usage: +# compare_versions MIN_VERSION ACTUAL_VERSION +# returns true if ACTUAL_VERSION >= MIN_VERSION +compare_versions() { + ch_min_version=$1 + ch_actual_version=$2 + ch_status=0 + IFS="${IFS= }"; ch_save_IFS="$IFS"; IFS="." + set $ch_actual_version + for ch_min in $ch_min_version; do + ch_cur=`echo $1 | sed 's/[^0-9].*$//'`; shift # remove letter suffixes + if [ -z "$ch_min" ]; then break; fi + if [ -z "$ch_cur" ]; then ch_status=1; break; fi + if [ $ch_cur -gt $ch_min ]; then break; fi + if [ $ch_cur -lt $ch_min ]; then ch_status=1; break; fi + done + IFS="$ch_save_IFS" + return $ch_status +} + +# Usage: +# version_check PACKAGE VARIABLE CHECKPROGS MIN_VERSION SOURCE +# checks to see if the package is available +version_check() { + vc_package=$1 + vc_variable=$2 + vc_checkprogs=$3 + vc_min_version=$4 + vc_source=$5 + vc_status=1 + + vc_checkprog=`eval echo "\\$$vc_variable"` + if [ -n "$vc_checkprog" ]; then + printbold "using $vc_checkprog for $vc_package" + return 0 + fi + + printbold "checking for $vc_package >= $vc_min_version..." + for vc_checkprog in $vc_checkprogs; do + echo $ECHO_N " testing $vc_checkprog... " + if $vc_checkprog --version < /dev/null > /dev/null 2>&1; then + vc_actual_version=`$vc_checkprog --version | head -n 1 | \ + sed 's/^.*[ ]\([0-9.]*[a-z]*\).*$/\1/'` + if compare_versions $vc_min_version $vc_actual_version; then + echo "found $vc_actual_version" + # set variable + eval "$vc_variable=$vc_checkprog" + vc_status=0 + break + else + echo "too old (found version $vc_actual_version)" + fi + else + echo "not found." + fi + done + if [ "$vc_status" != 0 ]; then + printerr "***Error***: You must have $vc_package >= $vc_min_version installed" + printerr " to build $PROJECT. Download the appropriate package for" + printerr " from your distribution or get the source tarball at" + printerr " $vc_source" + printerr + fi + return $vc_status +} + + +version_check autoconf AUTOCONF $AUTOCONF $autoconf_min_vers \ + "http://ftp.gnu.org/pub/gnu/autoconf/autoconf-${autoconf_min_vers}.tar.gz" || DIE=1 + +# +# Hunt for an appropriate version of automake and aclocal; we can't +# assume that 'automake' is necessarily the most recent installed version +# +# We check automake first to allow it to be a newer version than we know about. +# +version_check automake AUTOMAKE "$AUTOMAKE automake automake-1.10 automake-1.9 automake-1.8 automake-1.7" $automake_min_vers \ + "http://ftp.gnu.org/pub/gnu/automake/automake-${automake_min_vers}.tar.gz" || DIE=1 +ACLOCAL=`echo $AUTOMAKE | sed s/automake/aclocal/` + + +version_check libtool LIBTOOLIZE $LIBTOOLIZE $libtoolize_min_vers \ + "http://ftp.gnu.org/pub/gnu/libtool/libtool-${libtool_min_vers}.tar.gz" || DIE=1 + +if test -z "$ACLOCAL_FLAGS"; then + acdir=`$ACLOCAL --print-ac-dir` + if [ ! -f $acdir/pkg.m4 ]; then + echo "$ARGV0: Error: Could not find pkg-config macros." + echo " (Looked in $acdir/pkg.m4)" + echo " If pkg.m4 is available in /another/directory, please set" + echo " ACLOCAL_FLAGS=\"-I /another/directory\"" + echo " Otherwise, please install pkg-config." + echo "" + echo "pkg-config is available from:" + echo "http://www.freedesktop.org/software/pkgconfig/" + DIE=yes + fi +fi + +if test "X$DIE" != X; then + exit 1 +fi + + +if test -z "$*"; then + echo "$ARGV0: Note: \`./configure' will be run with no arguments." + echo " If you wish to pass any to it, please specify them on the" + echo " \`$0' command line." + echo +fi + +do_cmd() { + echo "$ARGV0: running \`$@'" + $@ +} + +do_cmd $LIBTOOLIZE $LIBTOOLIZE_FLAGS + +do_cmd $ACLOCAL $ACLOCAL_FLAGS + +do_cmd $AUTOHEADER + +do_cmd $AUTOMAKE $AUTOMAKE_FLAGS + +do_cmd $AUTOCONF + +cd $ORIGDIR || exit 1 + +# don't use 'do_cmd' since it prevents +# './autogen.sh --prefix=/usr CFLAGS="$CFLAGS -Werror"' from working +#do_cmd $srcdir/configure --enable-maintainer-mode ${1+"$@"} && echo "Now type \`make' to compile" || exit 1 +$srcdir/configure --enable-maintainer-mode ${1+"$@"} && echo "Now type \`make' to compile" || exit 1 diff --git a/config.guess b/config.guess new file mode 100644 index 0000000..f32079a --- /dev/null +++ b/config.guess @@ -0,0 +1,1526 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 +# Free Software Foundation, Inc. + +timestamp='2008-01-23' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program 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 +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA +# 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Originally written by Per Bothner <per@bothner.com>. +# Please send patches to <config-patches@gnu.org>. Submit a context +# diff and a properly formatted ChangeLog entry. +# +# This script attempts to guess a canonical system name similar to +# config.sub. If it succeeds, it prints the system name on stdout, and +# exits with 0. Otherwise, it exits with 1. +# +# The plan is that this can be called by configure scripts if you +# don't specify an explicit build system type. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to <config-patches@gnu.org>." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, +2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +trap 'exit 1' 1 2 15 + +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. + +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +# Portable tmp directory creation inspired by the Autoconf team. + +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; +: ${TMPDIR=/tmp} ; + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > $dummy.c ; + for c in cc gcc c89 c99 ; do + if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac ; set_cc_for_build= ;' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || echo unknown)` + case "${UNAME_MACHINE_ARCH}" in + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + sh5el) machine=sh5le-unknown ;; + *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently, or will in the future. + case "${UNAME_MACHINE_ARCH}" in + arm*|i386|m68k|ns32k|sh3*|sparc|vax) + eval $set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep __ELF__ >/dev/null + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # The OS release + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case "${UNAME_VERSION}" in + Debian*) + release='-gnu' + ;; + *) + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + ;; + esac + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "${machine}-${os}${release}" + exit ;; + *:OpenBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} + exit ;; + *:ekkoBSD:*:*) + echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + exit ;; + *:SolidBSD:*:*) + echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} + exit ;; + macppc:MirBSD:*:*) + echo powerpc-unknown-mirbsd${UNAME_RELEASE} + exit ;; + *:MirBSD:*:*) + echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + exit ;; + alpha:OSF1:*:*) + case $UNAME_RELEASE in + *4.0) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + ;; + *5.*) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE="alpha" ;; + "EV4.5 (21064)") + UNAME_MACHINE="alpha" ;; + "LCA4 (21066/21068)") + UNAME_MACHINE="alpha" ;; + "EV5 (21164)") + UNAME_MACHINE="alphaev5" ;; + "EV5.6 (21164A)") + UNAME_MACHINE="alphaev56" ;; + "EV5.6 (21164PC)") + UNAME_MACHINE="alphapca56" ;; + "EV5.7 (21164PC)") + UNAME_MACHINE="alphapca57" ;; + "EV6 (21264)") + UNAME_MACHINE="alphaev6" ;; + "EV6.7 (21264A)") + UNAME_MACHINE="alphaev67" ;; + "EV6.8CB (21264C)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8AL (21264B)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8CX (21264D)") + UNAME_MACHINE="alphaev68" ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE="alphaev69" ;; + "EV7 (21364)") + UNAME_MACHINE="alphaev7" ;; + "EV7.9 (21364A)") + UNAME_MACHINE="alphaev79" ;; + esac + # A Pn.n version is a patched version. + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + exit ;; + Alpha\ *:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # Should we change UNAME_MACHINE based on the output of uname instead + # of the specific Alpha model? + echo alpha-pc-interix + exit ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit ;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos + exit ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit ;; + *:z/VM:*:*) + echo s390-ibm-zvmoe + exit ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit ;; + arm:riscos:*:*|arm:RISCOS:*:*) + echo arm-unknown-riscos + exit ;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit ;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit ;; + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7; exit ;; + esac ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) + echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit ;; + m68k:machten:*:*) + echo m68k-apple-machten${UNAME_RELEASE} + exit ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus +#include <stdio.h> /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && + dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`$dummy $dummyarg` && + { echo "$SYSTEM_NAME"; exit; } + echo mips-mips-riscos${UNAME_RELEASE} + exit ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${TARGET_BINARY_INTERFACE}x = x ] + then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else + echo i586-dg-dgux${UNAME_RELEASE} + fi + exit ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + exit ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include <sys/systemcfg.h> + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` + then + echo "$SYSTEM_NAME" + else + echo rs6000-ibm-aix3.2.5 + fi + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit ;; + *:AIX:*:[456]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; + '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + + #define _HPUX_SOURCE + #include <stdlib.h> + #include <unistd.h> + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + test -z "$HP_ARCH" && HP_ARCH=hppa + fi ;; + esac + if [ ${HP_ARCH} = "hppa2.0w" ] + then + eval $set_cc_for_build + + # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating + # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler + # generating 64-bit code. GNU and HP use different nomenclature: + # + # $ CC_FOR_BUILD=cc ./config.guess + # => hppa2.0w-hp-hpux11.23 + # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess + # => hppa64-hp-hpux11.23 + + if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | + grep __LP64__ >/dev/null + then + HP_ARCH="hppa2.0w" + else + HP_ARCH="hppa64" + fi + fi + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit ;; + 3050*:HI-UX:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include <unistd.h> + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + echo unknown-hitachi-hiuxwe2 + exit ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + *:UNICOS/mp:*:*) + echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:FreeBSD:*:*) + case ${UNAME_MACHINE} in + pc98) + echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + amd64) + echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + *) + echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + esac + exit ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit ;; + *:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit ;; + i*:windows32*:*) + # uname -m includes "-pc" on this system. + echo ${UNAME_MACHINE}-mingw32 + exit ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit ;; + *:Interix*:[3456]*) + case ${UNAME_MACHINE} in + x86) + echo i586-pc-interix${UNAME_RELEASE} + exit ;; + EM64T | authenticamd) + echo x86_64-unknown-interix${UNAME_RELEASE} + exit ;; + IA64) + echo ia64-unknown-interix${UNAME_RELEASE} + exit ;; + esac ;; + [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) + echo i${UNAME_MACHINE}-pc-mks + exit ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # UNAME_MACHINE based on the output of uname instead of i386? + echo i586-pc-interix + exit ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit ;; + amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) + echo x86_64-unknown-cygwin + exit ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + *:GNU:*:*) + # the GNU system + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu + exit ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit ;; + arm*:Linux:*:*) + eval $set_cc_for_build + if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_EABI__ + then + echo ${UNAME_MACHINE}-unknown-linux-gnu + else + echo ${UNAME_MACHINE}-unknown-linux-gnueabi + fi + exit ;; + avr32*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + cris:Linux:*:*) + echo cris-axis-linux-gnu + exit ;; + crisv32:Linux:*:*) + echo crisv32-axis-linux-gnu + exit ;; + frv:Linux:*:*) + echo frv-unknown-linux-gnu + exit ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m32r*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + mips:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef mips + #undef mipsel + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=mipsel + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=mips + #else + CPU= + #endif + #endif +EOF + eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' + /^CPU/{ + s: ::g + p + }'`" + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } + ;; + mips64:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef mips64 + #undef mips64el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=mips64el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=mips64 + #else + CPU= + #endif + #endif +EOF + eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' + /^CPU/{ + s: ::g + p + }'`" + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } + ;; + or32:Linux:*:*) + echo or32-unknown-linux-gnu + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-gnu + exit ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-gnu + exit ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null + if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi + echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} + exit ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-gnu ;; + PA8*) echo hppa2.0-unknown-linux-gnu ;; + *) echo hppa-unknown-linux-gnu ;; + esac + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-gnu + exit ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux + exit ;; + sh64*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + vax:Linux:*:*) + echo ${UNAME_MACHINE}-dec-linux-gnu + exit ;; + x86_64:Linux:*:*) + echo x86_64-unknown-linux-gnu + exit ;; + xtensa*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + i*86:Linux:*:*) + # The BFD linker knows what the default object file format is, so + # first see if it will tell us. cd to the root directory to prevent + # problems with other programs or directories called `ld' in the path. + # Set LC_ALL=C to ensure ld outputs messages in English. + ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \ + | sed -ne '/supported targets:/!d + s/[ ][ ]*/ /g + s/.*supported targets: *// + s/ .*// + p'` + case "$ld_supported_targets" in + elf32-i386) + TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" + ;; + a.out-i386-linux) + echo "${UNAME_MACHINE}-pc-linux-gnuaout" + exit ;; + coff-i386) + echo "${UNAME_MACHINE}-pc-linux-gnucoff" + exit ;; + "") + # Either a pre-BFD a.out linker (linux-gnuoldld) or + # one that does not give us useful --help. + echo "${UNAME_MACHINE}-pc-linux-gnuoldld" + exit ;; + esac + # Determine whether the default compiler is a.out or elf + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include <features.h> + #ifdef __ELF__ + # ifdef __GLIBC__ + # if __GLIBC__ >= 2 + LIBC=gnu + # else + LIBC=gnulibc1 + # endif + # else + LIBC=gnulibc1 + # endif + #else + #if defined(__INTEL_COMPILER) || defined(__PGI) || defined(__SUNPRO_C) || defined(__SUNPRO_CC) + LIBC=gnu + #else + LIBC=gnuaout + #endif + #endif + #ifdef __dietlibc__ + LIBC=dietlibc + #endif +EOF + eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' + /^LIBC/{ + s: ::g + p + }'`" + test x"${LIBC}" != x && { + echo "${UNAME_MACHINE}-pc-linux-${LIBC}" + exit + } + test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; } + ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit ;; + i*86:syllable:*:*) + echo ${UNAME_MACHINE}-pc-syllable + exit ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit ;; + i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + fi + exit ;; + i*86:*:5:[678]*) + # UnixWare 7.x, OpenUNIX and OpenServer 6. + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + exit ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name` + echo ${UNAME_MACHINE}-pc-isc$UNAME_REL + elif /bin/uname -X 2>/dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i386. + echo i386-pc-msdosdjgpp + exit ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit ;; + M68*:*:R3V[5678]*:*) + test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says <Richard.M.Bartel@ccMail.Census.GOV> + echo i586-unisys-sysv4 + exit ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes <hewes@openmarket.com>. + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit ;; + i*86:VOS:*:*) + # From Paul.Green@stratus.com. + echo ${UNAME_MACHINE}-stratus-vos + exit ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux${UNAME_RELEASE} + exit ;; + SX-7:SUPER-UX:*:*) + echo sx7-nec-superux${UNAME_RELEASE} + exit ;; + SX-8:SUPER-UX:*:*) + echo sx8-nec-superux${UNAME_RELEASE} + exit ;; + SX-8R:SUPER-UX:*:*) + echo sx8r-nec-superux${UNAME_RELEASE} + exit ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Darwin:*:*) + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + case $UNAME_PROCESSOR in + unknown) UNAME_PROCESSOR=powerpc ;; + esac + echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + exit ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = "x86"; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + exit ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit ;; + NSE-?:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk${UNAME_RELEASE} + exit ;; + NSR-?:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = "386"; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo ${UNAME_MACHINE}-unknown-plan9 + exit ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit ;; + SEI:*:*:SEIUX) + echo mips-sei-seiux${UNAME_RELEASE} + exit ;; + *:DragonFly:*:*) + echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "${UNAME_MACHINE}" in + A*) echo alpha-dec-vms ; exit ;; + I*) echo ia64-dec-vms ; exit ;; + V*) echo vax-dec-vms ; exit ;; + esac ;; + *:XENIX:*:SysV) + echo i386-pc-xenix + exit ;; + i*86:skyos:*:*) + echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' + exit ;; + i*86:rdos:*:*) + echo ${UNAME_MACHINE}-pc-rdos + exit ;; +esac + +#echo '(No uname command or uname output not recognized.)' 1>&2 +#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 + +eval $set_cc_for_build +cat >$dummy.c <<EOF +#ifdef _SEQUENT_ +# include <sys/types.h> +# include <sys/utsname.h> +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include <sys/param.h> + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (__arm) && defined (__acorn) && defined (__unix) + printf ("arm-acorn-riscix\n"); exit (0); +#endif + +#if defined (hp300) && !defined (hpux) + printf ("m68k-hp-bsd\n"); exit (0); +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; + if (version < 4) + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); + else + printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-pc-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); + +#endif + +#if defined (vax) +# if !defined (ultrix) +# include <sys/param.h> +# if defined (BSD) +# if BSD == 43 + printf ("vax-dec-bsd4.3\n"); exit (0); +# else +# if BSD == 199006 + printf ("vax-dec-bsd4.3reno\n"); exit (0); +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# endif +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# else + printf ("vax-dec-ultrix\n"); exit (0); +# endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + +# Apollos put the system type in the environment. + +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } + +# Convex versions that predate uname can use getsysinfo(1) + +if [ -x /usr/convex/getsysinfo ] +then + case `getsysinfo -f cpu_type` in + c1*) + echo c1-convex-bsd + exit ;; + c2*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + c34*) + echo c34-convex-bsd + exit ;; + c38*) + echo c38-convex-bsd + exit ;; + c4*) + echo c4-convex-bsd + exit ;; + esac +fi + +cat >&2 <<EOF +$0: unable to guess system type + +This script, last modified $timestamp, has failed to recognize +the operating system you are using. It is advised that you +download the most up to date version of the config scripts from + + http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD +and + http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD + +If the version you run ($0) is already up to date, please +send the following data and any information you think might be +pertinent to <config-patches@gnu.org> in order to provide the needed +information to handle your system. + +config.guess timestamp = $timestamp + +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = ${UNAME_MACHINE} +UNAME_RELEASE = ${UNAME_RELEASE} +UNAME_SYSTEM = ${UNAME_SYSTEM} +UNAME_VERSION = ${UNAME_VERSION} +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/config.sub b/config.sub new file mode 100644 index 0000000..6759825 --- /dev/null +++ b/config.sub @@ -0,0 +1,1658 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 +# Free Software Foundation, Inc. + +timestamp='2008-01-16' + +# This file is (in principle) common to ALL GNU software. +# The presence of a machine in this file suggests that SOME GNU software +# can handle that machine. It does not imply ALL GNU software can. +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA +# 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Please send patches to <config-patches@gnu.org>. Submit a context +# diff and a properly formatted ChangeLog entry. +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS + $0 [OPTION] ALIAS + +Canonicalize a configuration name. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to <config-patches@gnu.org>." + +version="\ +GNU config.sub ($timestamp) + +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, +2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo $1 + exit ;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \ + uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \ + storm-chaos* | os2-emx* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis | -knuth | -cray) + os= + basic_machine=$1 + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -chorusos*) + os=-chorusos + basic_machine=$1 + ;; + -chorusrdb) + os=-chorusrdb + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco6) + os=-sco5v6 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5v6*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | am33_2.0 \ + | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \ + | bfin \ + | c4x | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | fido | fr30 | frv \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | i370 | i860 | i960 | ia64 \ + | ip2k | iq2000 \ + | m32c | m32r | m32rle | m68000 | m68k | m88k \ + | maxq | mb | microblaze | mcore | mep \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64vr | mips64vrel \ + | mips64orion | mips64orionel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | mt \ + | msp430 \ + | nios | nios2 \ + | ns16k | ns32k \ + | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ + | pyramid \ + | score \ + | sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ + | spu | strongarm \ + | tahoe | thumb | tic4x | tic80 | tron \ + | v850 | v850e \ + | we32k \ + | x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \ + | z8k) + basic_machine=$basic_machine-unknown + ;; + m6811 | m68hc11 | m6812 | m68hc12) + # Motorola 68HC11/12. + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + ;; + ms1) + basic_machine=mt-unknown + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* | avr32-* \ + | bfin-* | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \ + | clipper-* | craynv-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | elxsi-* \ + | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | i*86-* | i860-* | i960-* | ia64-* \ + | ip2k-* | iq2000-* \ + | m32c-* | m32r-* | m32rle-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | maxq-* | mcore-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mips64vr5900-* | mips64vr5900el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipstx39-* | mipstx39el-* \ + | mmix-* \ + | mt-* \ + | msp430-* \ + | nios-* | nios2-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ + | pyramid-* \ + | romp-* | rs6000-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ + | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ + | sparclite-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \ + | tahoe-* | thumb-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ + | tron-* \ + | v850-* | v850e-* | vax-* \ + | we32k-* \ + | x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \ + | xstormy16-* | xtensa*-* \ + | ymp-* \ + | z8k-*) + ;; + # Recognize the basic CPU types without company name, with glob match. + xtensa*) + basic_machine=$basic_machine-unknown + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-unknown + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + abacus) + basic_machine=abacus-unknown + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amd64) + basic_machine=x86_64-pc + ;; + amd64-*) + basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + blackfin) + basic_machine=bfin-unknown + os=-linux + ;; + blackfin-*) + basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | j90) + basic_machine=j90-cray + os=-unicos + ;; + craynv) + basic_machine=craynv-cray + os=-unicosmp + ;; + cr16) + basic_machine=cr16-unknown + os=-elf + ;; + crds | unos) + basic_machine=m68k-crds + ;; + crisv32 | crisv32-* | etraxfs*) + basic_machine=crisv32-axis + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + crx) + basic_machine=crx-unknown + os=-elf + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + decsystem10* | dec10*) + basic_machine=pdp10-dec + os=-tops10 + ;; + decsystem20* | dec20*) + basic_machine=pdp10-dec + os=-tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + djgpp) + basic_machine=i586-pc + os=-msdosdjgpp + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; +# I'm not sure what "Sysv32" means. Should this be sysv3.2? + i*86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i*86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i*86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i*86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + m68knommu) + basic_machine=m68k-unknown + os=-linux + ;; + m68knommu-*) + basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + mingw32) + basic_machine=i386-pc + os=-mingw32 + ;; + mingw32ce) + basic_machine=arm-unknown + os=-mingw32ce + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + ms1-*) + basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; + np1) + basic_machine=np1-gould + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + openrisc | openrisc-*) + basic_machine=or32-unknown + ;; + os400) + basic_machine=powerpc-ibm + os=-os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + parisc) + basic_machine=hppa-unknown + os=-linux + ;; + parisc-*) + basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pc98) + basic_machine=i386-pc + ;; + pc98-*) + basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon | athlon_*) + basic_machine=i686-pc + ;; + pentiumii | pentium2 | pentiumiii | pentium3) + basic_machine=i686-pc + ;; + pentium4) + basic_machine=i786-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium4-*) + basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc) basic_machine=powerpc-unknown + ;; + ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle | ppc-le | powerpc-little) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little | ppc64-le | powerpc64-little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rdos) + basic_machine=i386-pc + os=-rdos + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + s390 | s390-*) + basic_machine=s390-ibm + ;; + s390x | s390x-*) + basic_machine=s390x-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sb1) + basic_machine=mipsisa64sb1-unknown + ;; + sb1el) + basic_machine=mipsisa64sb1el-unknown + ;; + sde) + basic_machine=mipsisa32-sde + os=-elf + ;; + sei) + basic_machine=mips-sei + os=-seiux + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sh5el) + basic_machine=sh5le-unknown + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparclite-wrs | simso-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3e) + basic_machine=alphaev5-cray + os=-unicos + ;; + t90) + basic_machine=t90-cray + os=-unicos + ;; + tic54x | c54x*) + basic_machine=tic54x-unknown + os=-coff + ;; + tic55x | c55x*) + basic_machine=tic55x-unknown + os=-coff + ;; + tic6x | c6x*) + basic_machine=tic6x-unknown + os=-coff + ;; + tile*) + basic_machine=tile-unknown + os=-linux-gnu + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + toad1) + basic_machine=pdp10-xkl + os=-tops20 + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + tpf) + basic_machine=s390x-ibm + os=-tpf + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + xbox) + basic_machine=i686-pc + os=-mingw32 + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + z8k-*-coff) + basic_machine=z8k-unknown + os=-sim + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + romp) + basic_machine=romp-ibm + ;; + mmix) + basic_machine=mmix-knuth + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp10) + # there are many clones, so DEC is not a safe bet + basic_machine=pdp10-unknown + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele) + basic_machine=sh-unknown + ;; + sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative MUST END IN A *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ + | -openbsd* | -solidbsd* \ + | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ + | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* \ + | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \ + | -uxpv* | -beos* | -mpeix* | -udk* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ + | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ + | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ + | -skyos* | -haiku* | -rdos* | -toppers* | -drops*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto-qnx*) + ;; + -nto*) + os=`echo $os | sed -e 's|nto|nto-qnx|'` + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -linux-dietlibc) + os=-linux-dietlibc + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -os400*) + os=-os400 + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -atheos*) + os=-atheos + ;; + -syllable*) + os=-syllable + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -nova*) + os=-rtmk-nova + ;; + -ns2 ) + os=-nextstep2 + ;; + -nsk*) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -tpf*) + os=-tpf + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -es1800*) + os=-ose + ;; + -xenix) + os=-xenix + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -aros*) + os=-aros + ;; + -kaos*) + os=-kaos + ;; + -zvmoe) + os=-zvmoe + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + score-*) + os=-elf + ;; + spu-*) + os=-elf + ;; + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + c4x-* | tic4x-*) + os=-coff + ;; + # This must come before the *-dec entry. + pdp10-*) + os=-tops20 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + # This also exists in the configure program, but was not the + # default. + # os=-sunos4 + ;; + m68*-cisco) + os=-aout + ;; + mep-*) + os=-elf + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + or32-*) + os=-coff + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-be) + os=-beos + ;; + *-haiku) + os=-haiku + ;; + *-ibm) + os=-aix + ;; + *-knuth) + os=-mmixware + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -os400*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -tpf*) + vendor=ibm + ;; + -vxsim* | -vxworks* | -windiss*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + vendor=atari + ;; + -vos*) + vendor=stratus + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os +exit + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..d3e0759 --- /dev/null +++ b/configure.ac @@ -0,0 +1,110 @@ +-*- mode: m4 -*- +AC_PREREQ(2.59) + +# the pycairo version number +m4_define(pycairo_version_major, 1) +m4_define(pycairo_version_minor, 8) +m4_define(pycairo_version_micro, 7) +m4_define(pycairo_version, pycairo_version_major.pycairo_version_minor.pycairo_version_micro) + +# versions of packages we require +m4_define(cairo_required_version, 1.8.6) + +AC_INIT([pycairo], + [pycairo_version], + [http://bugs.freedesktop.org/enter_bug.cgi?product=pycairo]) + +AC_SUBST(PYCAIRO_VERSION_MAJOR, [pycairo_version_major]) +AC_SUBST(PYCAIRO_VERSION_MINOR, [pycairo_version_minor]) +AC_SUBST(PYCAIRO_VERSION_MICRO, [pycairo_version_micro]) +AC_SUBST(VERSION_INFO, + [pycairo_version_major,pycairo_version_minor,pycairo_version_micro]) + +AC_CONFIG_SRCDIR([src/pycairo.h]) +AC_CONFIG_HEADERS(config.h) + +AM_INIT_AUTOMAKE([1.9.6 -Wall]) + +# Options --- + +# put the ACLOCAL flags in the makefile +ACLOCAL="$ACLOCAL $ACLOCAL_FLAGS" + +# Checks for programs --- +AC_DISABLE_STATIC +AC_PROG_LIBTOOL dnl required version (1.4) DON'T REMOVE - used by autogen.sh + +AM_PATH_PYTHON(2.6) + +# Checks for libraries --- + +# get rid of the -export-dynamic stuff from the configure flags ... +export_dynamic=`(./libtool --config; echo eval echo \\$export_dynamic_flag_spec) | sh` + +# cairo +PKG_CHECK_MODULES(CAIRO, cairo >= cairo_required_version) +if test -n "$export_dynamic"; then + CAIRO_LIBS=`echo $CAIRO_LIBS | sed -e "s/$export_dynamic//"` +fi + +# Checks for header files --- +AM_CHECK_PYTHON_HEADERS(,[AC_MSG_ERROR(could not find Python headers)]) + +# checks for types and compilers --- +AC_C_CONST + +# add gcc debugging options +changequote(,)dnl +if test "x$GCC" = xyes; then + case " $CFLAGS " in + *[\ \ ]-std=c99[\ \ ]*) ;; + *[\ \ ]-std=c9x[\ \ ]*) ;; + *) CFLAGS="$CFLAGS -std=c99" ;; + esac + + case " $CFLAGS " in + *[\ \ ]-Wall[\ \ ]*) ;; + *) CFLAGS="$CFLAGS -Wall" ;; + esac +fi +changequote([,])dnl + +case $GCC in +yes) + # code using Py_True, Py_False will receive + # "warning: dereferencing type-punned pointer will break strict-aliasing rules" + # -fno-strict-aliasing (as used in Python build) switches warnings off + AC_MSG_CHECKING(whether $CC accepts -fno-strict-aliasing) + ac_save_cc="$CC" + CC="$CC -fno-strict-aliasing" + AC_TRY_RUN([int main() { return 0; }], + ac_cv_no_strict_aliasing_ok=yes, + ac_cv_no_strict_aliasing_ok=no, + ac_cv_no_strict_aliasing_ok=no) + CC="$ac_save_cc" + AC_MSG_RESULT($ac_cv_no_strict_aliasing_ok) + if test $ac_cv_no_strict_aliasing_ok = yes + then + CFLAGS="$CFLAGS -fno-strict-aliasing" + fi +esac + +# Checks for library functions --- +# Checks for system services --- + +# Output --- +AC_CONFIG_FILES([ +Makefile +pycairo.pc +src/Makefile +doc/Makefile +examples/Makefile +test/Makefile +]) + +AC_OUTPUT + +echo " +Configuration: +Installation prefix ${prefix} +" diff --git a/doc/.gitignore b/doc/.gitignore new file mode 100644 index 0000000..d72cc23 --- /dev/null +++ b/doc/.gitignore @@ -0,0 +1,7 @@ +.build +.static +.templates +html_docs_create.sh +html_docs_upload.sh +Makefile +Makefile.in diff --git a/doc/Makefile.am b/doc/Makefile.am new file mode 100644 index 0000000..dacf544 --- /dev/null +++ b/doc/Makefile.am @@ -0,0 +1,96 @@ +# distribute the Sphinx source files only, +# the generated html files are distributed separately +EXTRA_DIST = \ + conf.py \ + faq.rst \ + index.rst \ + overview.rst \ + pycairo_c_api.rst \ + README \ + reference/constants.rst \ + reference/context.rst \ + reference/exceptions.rst \ + reference/index.rst \ + reference/matrix.rst \ + reference/paths.rst \ + reference/patterns.rst \ + reference/surfaces.rst \ + reference/text.rst + +# Makefile for Sphinx documentation - autogenerated by Sphinx +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +PAPER = + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d .build/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . + +.PHONY: help clean html web pickle htmlhelp latex changes linkcheck + +help: + @echo "Please use \`make <target>' where <target> is one of" + @echo " html to make standalone HTML files" + @echo " pickle to make pickle files" + @echo " json to make JSON files" + @echo " htmlhelp to make HTML files and a HTML help project" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " changes to make an overview over all changed/added/deprecated items" + @echo " linkcheck to check all external links for integrity" + +clean: + -rm -rf .build/* + +html: + mkdir -p .build/html .build/doctrees + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) .build/html + @echo + @echo "Build finished. The HTML pages are in .build/html." + +pickle: + mkdir -p .build/pickle .build/doctrees + $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) .build/pickle + @echo + @echo "Build finished; now you can process the pickle files." + +web: pickle + +json: + mkdir -p .build/json .build/doctrees + $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) .build/json + @echo + @echo "Build finished; now you can process the JSON files." + +htmlhelp: + mkdir -p .build/htmlhelp .build/doctrees + $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) .build/htmlhelp + @echo + @echo "Build finished; now you can run HTML Help Workshop with the" \ + ".hhp project file in .build/htmlhelp." + +latex: + mkdir -p .build/latex .build/doctrees + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) .build/latex + @echo + @echo "Build finished; the LaTeX files are in .build/latex." + @echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \ + "run these through (pdf)latex." + +changes: + mkdir -p .build/changes .build/doctrees + $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) .build/changes + @echo + @echo "The overview file is in .build/changes." + +linkcheck: + mkdir -p .build/linkcheck .build/doctrees + $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) .build/linkcheck + @echo + @echo "Link check complete; look for any errors in the above output " \ + "or in .build/linkcheck/output.txt." + +# Makefile for Sphinx documentation -- end -- diff --git a/doc/README b/doc/README new file mode 100644 index 0000000..4bf7671 --- /dev/null +++ b/doc/README @@ -0,0 +1,89 @@ +Pycairo Documentation README +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This directory contains the reStructuredText (reST) sources to the Pycairo +documentation. + +Options for accessing pycairo documentation: +1. Read the documentation online at http://cairographics.org/documentation/pycairo/ + +2. Download the latest 'pycairo-x.x.x-docs-html.tar.gz' prebuilt documents +from http://www.cairographics.org/releases/. Uncompress the docs and point +your browser at the index.html file. + +3. Build the documentation yourself - the hardest option, see details below. + + +Building the docs +================= +You need to install Python 2.4 or higher; the toolset used to build the docs are +written in Python. The toolset used to build the documentation is called +*Sphinx*, it is not included in this tree, but maintained separately in the +Python Subversion repository. Also needed are Jinja, a templating engine +(included in Sphinx as a Subversion external), and optionally Pygments, a code +highlighter. + + +Using make +---------- + make html + +Available make targets are: + + * "html", which builds standalone HTML files for offline viewing. + + * "htmlhelp", which builds HTML files and a HTML Help project file usable to + convert them into a single Compiled HTML (.chm) file -- these are popular + under Microsoft Windows, but very handy on every platform. + + To create the CHM file, you need to run the Microsoft HTML Help Workshop + over the generated project (.hhp) file. + + * "latex", which builds LaTeX source files that can be run with "pdflatex" + to produce PDF documents. + + * "text", which builds a plain text file for each source file. + + * "linkcheck", which checks all external references to see whether they are + broken, redirected or malformed, and outputs this information to stdout + as well as a plain-text (.txt) file. + + * "changes", which builds an overview over all versionadded/versionchanged/ + deprecated items in the current version. This is meant as a help for the + writer of the "What's New" document. + + * "pydoc-topics", which builds a Python module containing a dictionary + with plain text documentation for the labels defined in + `tools/sphinxext/pyspecific.py` -- pydoc needs these to show topic + and keyword help. + +A "make update" updates the Subversion checkouts in `tools/`. + + +Without make +------------ + +You'll need to checkout the Sphinx package to the `tools/` directory:: + + svn co http://svn.python.org/projects/doctools/trunk/sphinx tools/sphinx + +Then, you need to install Docutils 0.4 (the SVN snapshot won't work), either +by checking it out via :: + + svn co http://svn.python.org/projects/external/docutils-0.4/docutils tools/docutils + +or by installing it from http://docutils.sf.net/. + +You can optionally also install Pygments, either as a checkout via :: + + svn co http://svn.python.org/projects/external/Pygments-0.9/pygments tools/pygments + +or from PyPI at http://pypi.python.org/pypi/Pygments. + + +Then, make an output directory, e.g. under `build/`, and run :: + + python tools/sphinx-build.py -b<builder> . build/<outputdirectory> + +where `<builder>` is one of html, web or htmlhelp (for explanations see the make +targets above). diff --git a/doc/conf.py b/doc/conf.py new file mode 100755 index 0000000..748ec99 --- /dev/null +++ b/doc/conf.py @@ -0,0 +1,187 @@ +# -*- coding: utf-8 -*- +# +# pycairo documentation build configuration file, created by +# sphinx-quickstart on Tue Nov 25 23:21:00 2008. +# +# This file is execfile()d with the current directory set to its containing dir. +# +# The contents of this file are pickled, so don't put values in the namespace +# that aren't pickleable (module imports are okay, they're removed automatically). +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +import sys, os + +# If your extensions are in another directory, add it here. If the directory +# is relative to the documentation root, use os.path.abspath to make it +# absolute, like shown here. +#sys.path.append(os.path.abspath('.')) + +# General configuration +# --------------------- + +# Add any Sphinx extension module names here, as strings. They can be extensions +# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. +extensions = [] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['.templates'] + +# The suffix of source filenames. +source_suffix = '.rst' + +# The encoding of source files. +#source_encoding = 'utf-8' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = u'pycairo' +copyright = u'2008, Steve Chaplin' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +version = '1.8' +# The full version, including alpha/beta/rc tags. +release = '1.8.6' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +#language = None + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +#today = '' +# Else, today_fmt is used as the format for a strftime call. +#today_fmt = '%B %d, %Y' + +# List of documents that shouldn't be included in the build. +#unused_docs = [] + +# List of directories, relative to source directory, that shouldn't be searched +# for source files. +exclude_trees = ['.build'] + +# The reST default role (used for this markup: `text`) to use for all documents. +#default_role = None + +# If true, '()' will be appended to :func: etc. cross-reference text. +#add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +#add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +#show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + + +# Options for HTML output +# ----------------------- + +# The style sheet to use for HTML and HTML Help pages. A file of that name +# must exist either in Sphinx' static/ path, or in one of the custom paths +# given in html_static_path. +html_style = 'default.css' + +# The name for this set of Sphinx documents. If None, it defaults to +# "<project> v<release> documentation". +#html_title = None + +# A shorter title for the navigation bar. Default is the same as html_title. +#html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +#html_logo = None + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +#html_favicon = None + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['.static'] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +#html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +#html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +#html_additional_pages = {} + +# If false, no module index is generated. +#html_use_modindex = True + +# If false, no index is generated. +#html_use_index = True + +# If true, the index is split into individual pages for each letter. +#html_split_index = False + +# If true, the reST sources are included in the HTML build as _sources/<name>. +#html_copy_source = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a <link> tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +#html_use_opensearch = '' + +# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml"). +#html_file_suffix = '' + +# Output file base name for HTML help builder. +htmlhelp_basename = 'pycairodoc' + + +# Options for LaTeX output +# ------------------------ + +# The paper size ('letter' or 'a4'). +#latex_paper_size = 'letter' + +# The font size ('10pt', '11pt' or '12pt'). +#latex_font_size = '10pt' + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, author, document class [howto/manual]). +latex_documents = [ + ('index', 'pycairo.tex', ur'pycairo Documentation', + ur'Steve Chaplin', 'manual'), +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +#latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +#latex_use_parts = False + +# Additional stuff for the LaTeX preamble. +#latex_preamble = '' + +# Documents to append as an appendix to all manuals. +#latex_appendices = [] + +# If false, no module index is generated. +#latex_use_modindex = True diff --git a/doc/faq.rst b/doc/faq.rst new file mode 100644 index 0000000..2cd986d --- /dev/null +++ b/doc/faq.rst @@ -0,0 +1,41 @@ +*** +FAQ +*** + +.. currentmodule:: cairo + + +Pycairo FAQ - Frequently Asked Questions +======================================== + +Q: Can I subclass pycairo classes? + +A: Cairo, the C library, is not an object oriented library, so a Python +binding can never be a truly object oriented interface to cairo. One way to +write the Python bindings for cairo would be as a single long list of module +functions - this would be the most accurate representation of the underlying C +library. Pycairo (and most other cairo language bindings?) instead chose to +implement the bindings using Context, Surface, Pattern, etc classes. An +advantage is that the classes organise cairo into groups of similar functions. +A disadvantage is that creates an illusion that cairo is object oriented +library, and people are then tempted to create subclasses to override cairo +methods. When in fact there are no methods to override, just cairo functions +which can't be overridden. + +The cairo documentation Appendix A "Creating a language binding for cairo" +section "Memory Management" describes why deriving from a Surface creates +problems and is best avoided. + +cairo.Context can be subclassed. +All other pycairo subclasses cannot be subclassed. + + +Q: How do I use pycairo with numpy? + +A: See test/isurface_create_for_data2.py + + +Q: How do I use pycairo with pygame? + +A: See test/pygame-test1.py + test/pygame-test2.py diff --git a/doc/index.rst b/doc/index.rst new file mode 100644 index 0000000..df9f5ae --- /dev/null +++ b/doc/index.rst @@ -0,0 +1,19 @@ +Pycairo Documentation +===================== + +.. module:: cairo + +.. toctree:: + :maxdepth: 1 + + overview + reference/index + faq + pycairo_c_api + + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`search` diff --git a/doc/overview.rst b/doc/overview.rst new file mode 100644 index 0000000..e862335 --- /dev/null +++ b/doc/overview.rst @@ -0,0 +1,31 @@ +******** +Overview +******** + +.. currentmodule:: cairo + +Pycairo is a Python binding for the cairo graphics library. + +The Pycairo bindings are designed to match the cairo C API as closely as +possible, and to deviate only in cases which are clearly better implemented in +a more 'Pythonic' way. + +Features of the Pycairo bindings: + +* Provides an object oriented interface to cairo, using Python 2.2 new style classes. +* Pycairo_Check_Status() is called to check the status of cairo operations, and raise exceptions as appropriate. +* Provides a C API that can be used by other Python extensions. + +The C cairo functions cairo_reference(), cairo_destroy(), +cairo_surface_reference(), cairo_surface_destroy() (and their equivalents for +surfaces and patterns) are not made public by the pycairo bindings. This is +because pycairo handles cairo object construction and destruction. + +To use the pycairo library:: + + import cairo + +See :ref:`Reference <reference_index>` for further details. + +For examples of pycairo code see the 'examples' directory that comes with the +pycairo distribution. diff --git a/doc/pycairo_c_api.rst b/doc/pycairo_c_api.rst new file mode 100644 index 0000000..d7d3bd8 --- /dev/null +++ b/doc/pycairo_c_api.rst @@ -0,0 +1,116 @@ +.. highlightlang:: c + + +************* +Pycairo C API +************* + +.. currentmodule:: cairo + +This manual documents the API used by C and C++ programmers who want to write +extension modules that use pycairo. + + +.. _api-includes: + +To access the Pycairo C API +=========================== +Edit the client module file to add the following lines:: + + /* All function, type and macro definitions needed to use the Pycairo/C API + * are included in your code by the following line + */ + #include "Pycairo.h" + + /* define a variable for the C API */ + static Pycairo_CAPI_t *Pycairo_CAPI; + + /* import pycairo - add to the init<module> function */ + Pycairo_IMPORT; + + +Pycairo Objects +=============== +Objects:: + + PycairoContext + PycairoFontFace + PycairoToyFontFace + PycairoFontOptions + PycairoMatrix + PycairoPath + PycairoPattern + PycairoSolidPattern + PycairoSurfacePattern + PycairoGradient + PycairoLinearGradient + PycairoRadialGradient + PycairoScaledFont + PycairoSurface + PycairoImageSurface + PycairoPDFSurface + PycairoPSSurface + PycairoSVGSurface + PycairoWin32Surface + PycairoXlibSurface + + +Pycairo Types +============= +Types:: + + PyTypeObject *Context_Type; + PyTypeObject *FontFace_Type; + PyTypeObject *ToyFontFace_Type; + PyTypeObject *FontOptions_Type; + PyTypeObject *Matrix_Type; + PyTypeObject *Path_Type; + PyTypeObject *Pattern_Type; + PyTypeObject *SolidPattern_Type; + PyTypeObject *SurfacePattern_Type; + PyTypeObject *Gradient_Type; + PyTypeObject *LinearGradient_Type; + PyTypeObject *RadialGradient_Type; + PyTypeObject *ScaledFont_Type; + PyTypeObject *Surface_Type; + PyTypeObject *ImageSurface_Type; + PyTypeObject *PDFSurface_Type; + PyTypeObject *PSSurface_Type; + PyTypeObject *SVGSurface_Type; + PyTypeObject *Win32Surface_Type; + PyTypeObject *XlibSurface_Type; + + +Functions +========= + +.. cfunction:: cairo_t * PycairoContext_GET(obj) + + get the C cairo_t * object out of the PycairoContext *obj + + +.. cfunction:: PyObject * PycairoContext_FromContext(cairo_t *ctx, PyTypeObject *type, PyObject *base) + + +.. cfunction:: PyObject * PycairoFontFace_FromFontFace(cairo_font_face_t *font_face) + + +.. cfunction:: PyObject * PycairoFontOptions_FromFontOptions(cairo_font_options_t *font_options) + + +.. cfunction:: PyObject * PycairoMatrix_FromMatrix(const cairo_matrix_t *matrix) + + +.. cfunction:: PyObject * PycairoPath_FromPath(cairo_path_t *path) + + +.. cfunction:: PyObject * PycairoPattern_FromPattern(cairo_pattern_t *pattern, PyObject *base) + + +.. cfunction:: PyObject * PycairoScaledFont_FromScaledFont(cairo_scaled_font_t *scaled_font) + + +.. cfunction:: PyObject * PycairoSurface_FromSurface(cairo_surface_t *surface, PyObject *base) + + +.. cfunction:: int PycairoCheck_Status(cairo_status_t status) diff --git a/doc/reference/constants.rst b/doc/reference/constants.rst new file mode 100644 index 0000000..18454d6 --- /dev/null +++ b/doc/reference/constants.rst @@ -0,0 +1,525 @@ +.. _constants: + +****************************** +Module Functions and Constants +****************************** + +.. currentmodule:: cairo + + +Module Functions +================ + +.. function:: cairo_version() + + :returns: the encoded version + :rtype: int + + Returns the version of the underlying C cairo library, encoded in a single + integer. + +.. function:: cairo_version_string() + + :returns: the encoded version + :rtype: str + + Returns the version of the underlying C cairo library as a human-readable + string of the form "X.Y.Z". + + +Module Constants +================ + +.. data:: version + + the pycairo version, as a string + +.. data:: version_info + + the pycairo version, as a tuple + + +.. _constants_HAS: + +cairo.HAS +--------- +.. data:: HAS_ATSUI_FONT + HAS_FT_FONT + HAS_GLITZ_SURFACE + HAS_IMAGE_SURFACE + HAS_PDF_SURFACE + HAS_PNG_FUNCTIONS + HAS_PS_SURFACE + HAS_SVG_SURFACE + HAS_USER_FONT + HAS_QUARTZ_SURFACE + HAS_WIN32_FONT + HAS_WIN32_SURFACE + HAS_XCB_SURFACE + HAS_XLIB_SURFACE + + 1 if the feature is present in the underlying C cairo library, + 0 otherwise + + +.. _constants_ANTIALIAS: + +cairo.ANTIALIAS +--------------- +ANTIALIAS specifies the type of antialiasing to do when rendering text or +shapes. + +.. data:: ANTIALIAS_DEFAULT + + Use the default antialiasing for the subsystem and target device + +.. data:: ANTIALIAS_NONE + + Use a bilevel alpha mask + +.. data:: ANTIALIAS_GRAY + + Perform single-color antialiasing (using shades of gray for black text on a + white background, for example). + +.. data:: ANTIALIAS_SUBPIXEL + + Perform antialiasing by taking advantage of the order of subpixel elements + on devices such as LCD panels. + + +.. _constants_CONTENT: + +cairo.CONTENT +------------- +These constants are used to describe the content that a :class:`Surface` will +contain, whether color information, alpha information (translucence +vs. opacity), or both. + +.. data:: CONTENT_COLOR + + The surface will hold color content only. + +.. data:: CONTENT_ALPHA + + The surface will hold alpha content only. + +.. data:: CONTENT_COLOR_ALPHA + + The surface will hold color and alpha content. + + +.. _constants_EXTEND: + +cairo.EXTEND +------------ +These constants are used to describe how :class:`Pattern` color/alpha will be +determined for areas "outside" the pattern's natural area, (for example, +outside the surface bounds or outside the gradient geometry). + +The default extend mode is *EXTEND_NONE* for :class:`SurfacePattern` and +*EXTEND_PAD* for :class:`Gradient` patterns. + +.. data:: EXTEND_NONE + + pixels outside of the source pattern are fully transparent + +.. data:: EXTEND_REPEAT + + the pattern is tiled by repeating + +.. data:: EXTEND_REFLECT + + the pattern is tiled by reflecting at the edges (Implemented for surface + patterns since 1.6) + +.. data:: EXTEND_PAD + + pixels outside of the pattern copy the closest pixel from the source (Since + 1.2; but only implemented for surface patterns since 1.6) + +New entries may be added in future versions. + + +.. _constants_FILL_RULE: + +cairo.FILL_RULE +--------------- +These constants are used to select how paths are filled. For both fill +rules, whether or not a point is included in the fill is determined by taking +a ray from that point to infinity and looking at intersections with the +path. The ray can be in any direction, as long as it doesn't pass through the +end point of a segment or have a tricky intersection such as intersecting +tangent to the path. (Note that filling is not actually implemented in this +way. This is just a description of the rule that is applied.) + +The default fill rule is *FILL_RULE_WINDING*. + +.. data:: FILL_RULE_WINDING + + If the path crosses the ray from left-to-right, counts +1. If the path + crosses the ray from right to left, counts -1. (Left and right are + determined from the perspective of looking along the ray from the starting + point.) If the total count is non-zero, the point will be filled. + +.. data:: FILL_RULE_EVEN_ODD + + Counts the total number of intersections, without regard to the orientation + of the contour. If the total number of intersections is odd, the point will + be filled. + +New entries may be added in future versions. + + +.. _constants_FILTER: + +cairo.FILTER +------------ +These constants are used to indicate what filtering should be applied when +reading pixel values from patterns. See :meth:`SurfacePattern.set_filter` for +indicating the desired filter to be used with a particular pattern. + +.. data:: FILTER_FAST + + A high-performance filter, with quality similar *FILTER_NEAREST* + +.. data:: FILTER_GOOD + + A reasonable-performance filter, with quality similar to *FILTER_BILINEAR* + +.. data:: FILTER_BEST + + The highest-quality available, performance may not be suitable for + interactive use. + +.. data:: FILTER_NEAREST + + Nearest-neighbor filtering + +.. data:: FILTER_BILINEAR + + Linear interpolation in two dimensions + +.. data:: FILTER_GAUSSIAN + + This filter value is currently unimplemented, and should not be used in + current code. + + +.. _constants_FONT_SLANT: + +cairo.FONT_SLANT +---------------- +These constants specify variants of a :class:`FontFace` based on their slant. + +.. data:: FONT_SLANT_NORMAL + + Upright font style + +.. data:: FONT_SLANT_ITALIC + + Italic font style + +.. data:: FONT_SLANT_OBLIQUE + + Oblique font style + + +.. _constants_FONT_WEIGHT: + +cairo.FONT_WEIGHT +----------------- +These constants specify variants of a :class:`FontFace` based on their weight. + +.. data:: FONT_WEIGHT_NORMAL + + Normal font weight + +.. data:: FONT_WEIGHT_BOLD + + Bold font weight + + +.. _constants_FORMAT: + +cairo.FORMAT +------------ +These constants are used to identify the memory format of +:class:`ImageSurface` data. + +.. data:: FORMAT_ARGB32 + + each pixel is a 32-bit quantity, with alpha in the upper 8 bits, then red, + then green, then blue. The 32-bit quantities are stored + native-endian. Pre-multiplied alpha is used. (That is, 50% transparent red + is 0x80800000, not 0x80ff0000.) + +.. data:: FORMAT_RGB24 + + each pixel is a 32-bit quantity, with the upper 8 bits unused. Red, Green, + and Blue are stored in the remaining 24 bits in that order. + +.. data:: FORMAT_A8 + + each pixel is a 8-bit quantity holding an alpha value. + +.. data:: FORMAT_A1 + + each pixel is a 1-bit quantity holding an alpha value. Pixels are packed + together into 32-bit quantities. The ordering of the bits matches the + endianess of the platform. On a big-endian machine, the first pixel is in + the uppermost bit, on a little-endian machine the first pixel is in the + least-significant bit. + +New entries may be added in future versions. + + +.. _constants_HINT_METRICS: + +cairo.HINT_METRICS +------------------ +These constants specify whether to hint font metrics; hinting font metrics +means quantizing them so that they are integer values in device space. Doing +this improves the consistency of letter and line spacing, however it also +means that text will be laid out differently at different zoom factors. + +.. data:: HINT_METRICS_DEFAULT + + Hint metrics in the default manner for the font backend and target device + +.. data:: HINT_METRICS_OFF + + Do not hint font metrics + +.. data:: HINT_METRICS_ON + + Hint font metrics + + +.. _constants_HINT_STYLE: + +cairo.HINT_STYLE +---------------- +These constants specify the type of hinting to do on font outlines. Hinting is +the process of fitting outlines to the pixel grid in order to improve the +appearance of the result. Since hinting outlines involves distorting them, it +also reduces the faithfulness to the original outline shapes. Not all of the +outline hinting styles are supported by all font backends. + +.. data:: HINT_STYLE_DEFAULT + + Use the default hint style for font backend and target device + +.. data:: HINT_STYLE_NONE + + Do not hint outlines + +.. data:: HINT_STYLE_SLIGHT + + Hint outlines slightly to improve contrast while retaining good fidelity to + the original shapes. + +.. data:: HINT_STYLE_MEDIUM + + Hint outlines with medium strength giving a compromise between fidelity to + the original shapes and contrast + +.. data:: HINT_STYLE_FULL + + Hint outlines to maximize contrast + +New entries may be added in future versions. + + +.. _constants_LINE_CAP: + +cairo.LINE_CAP +-------------- +These constants specify how to render the endpoints of the path when stroking. + +The default line cap style is *LINE_CAP_BUTT* + +.. data:: LINE_CAP_BUTT + + start(stop) the line exactly at the start(end) point + +.. data:: LINE_CAP_ROUND + + use a round ending, the center of the circle is the end point + +.. data:: LINE_CAP_SQUARE + + use squared ending, the center of the square is the end point + + +.. _constants_LINE_JOIN: + +cairo.LINE_JOIN +--------------- +These constants specify how to render the junction of two lines when stroking. + +The default line join style is *LINE_JOIN_MITER* + +.. data:: LINE_JOIN_MITER + + use a sharp (angled) corner, see :meth:`Context.set_miter_limit` + +.. data:: LINE_JOIN_ROUND + + use a rounded join, the center of the circle is the joint point + +.. data:: LINE_JOIN_BEVEL + + use a cut-off join, the join is cut off at half the line width from the + joint point + + +.. _constants_OPERATOR: + +cairo.OPERATOR +-------------- +These constants are used to set the compositing operator for all cairo drawing +operations. + +The default operator is *OPERATOR_OVER*. + +The operators marked as *unbounded* modify their destination even outside of +the mask layer (that is, their effect is not bound by the mask layer). +However, their effect can still be limited by way of clipping. + +To keep things simple, the operator descriptions here document the behavior +for when both source and destination are either fully transparent or fully +opaque. The actual implementation works for translucent layers too. + +For a more detailed explanation of the effects of each operator, including the +mathematical definitions, see http://cairographics.org/operators. + +.. data:: OPERATOR_CLEAR + + clear destination layer (bounded) + +.. data:: OPERATOR_SOURCE + + replace destination layer (bounded) + +.. data:: OPERATOR_OVER + + draw source layer on top of destination layer (bounded) + +.. data:: OPERATOR_IN + + draw source where there was destination content (unbounded) + +.. data:: OPERATOR_OUT + + draw source where there was no destination content (unbounded) + +.. data:: OPERATOR_ATOP + + draw source on top of destination content and only there + +.. data:: OPERATOR_DEST + + ignore the source + +.. data:: OPERATOR_DEST_OVER + + draw destination on top of source + +.. data:: OPERATOR_DEST_IN + + leave destination only where there was source content (unbounded) + +.. data:: OPERATOR_DEST_OUT + + leave destination only where there was no source content + +.. data:: OPERATOR_DEST_ATOP + + leave destination on top of source content and only there (unbounded) + +.. data:: OPERATOR_XOR + + source and destination are shown where there is only one of them + +.. data:: OPERATOR_ADD + + source and destination layers are accumulated + +.. data:: OPERATOR_SATURATE + + like over, but assuming source and dest are disjoint geometries + + +.. _constants_PATH: + +cairo.PATH +---------- +These constants are used to describe the type of one portion of a path when +represented as a :class:`Path`. + +.. See #cairo_path_data_t for details. + +.. data:: PATH_MOVE_TO + + A move-to operation + +.. data:: PATH_LINE_TO + + A line-to operation + +.. data:: PATH_CURVE_TO + + A curve-to operation + +.. data:: PATH_CLOSE_PATH + + A close-path operation + + +.. _constants_PS_LEVEL: + +cairo.PS_LEVEL +-------------- +These constants are used to describe the language level of the PostScript +Language Reference that a generated PostScript file will conform to. Note: +the constants are only defined when cairo has been compiled with PS support +enabled. + +.. data:: PS_LEVEL_2 + + The language level 2 of the PostScript specification. + +.. data:: PS_LEVEL_3 + + The language level 3 of the PostScript specification. + + +.. _constants_SUBPIXEL_ORDER: + +cairo.SUBPIXEL_ORDER +-------------------- +The subpixel order specifies the order of color elements within each pixel on +the display device when rendering with an antialiasing mode of +:data:`ANTIALIAS_SUBPIXEL`. + +.. data:: SUBPIXEL_ORDER_DEFAULT + + Use the default subpixel order for for the target device + +.. data:: SUBPIXEL_ORDER_RGB + + Subpixel elements are arranged horizontally with red at the left + +.. data:: SUBPIXEL_ORDER_BGR + + Subpixel elements are arranged horizontally with blue at the left + +.. data:: SUBPIXEL_ORDER_VRGB + + Subpixel elements are arranged vertically with red at the top + +.. data:: SUBPIXEL_ORDER_VBGR + + Subpixel elements are arranged vertically with blue at the top + diff --git a/doc/reference/context.rst b/doc/reference/context.rst new file mode 100644 index 0000000..277bd16 --- /dev/null +++ b/doc/reference/context.rst @@ -0,0 +1,1485 @@ +.. _context: + +************* +Cairo Context +************* + +.. currentmodule:: cairo + +.. comment block + example reST: + (add back '..' where required at column 0) + . class:: module.C[(signature)] + .. classmethod:: name(signature) + .. staticmethod:: name(signature) + .. method:: method(signature) + + :param p1: xxx + :type p1: int + :param p2: xxx + :type p2: str + :returns: xxx + :rtype: list of strings + :raises: xxx + + .. versionadded:: 1.6 + links: + :data:`cairo.ANTIALIAS_SUBPIXEL` + :class:`Context` + :exc:`cairo.Error` + :meth:`.copy_page` + :meth:`Context.copy_page` + :ref:`LINE_CAP <constants_LINE_CAP>` + + +class Context() +=============== + +*Context* is the main object used when drawing with cairo. To draw with cairo, +you create a *Context*, set the target surface, and drawing options for the +*Context*, create shapes with functions like :meth:`Context.move_to` and +:meth:`Context.line_to`, and then draw shapes with :meth:`Context.stroke` or +:meth:`Context.fill`. + +*Contexts* can be pushed to a stack via :meth:`Context.save`. They may then +safely be changed, without loosing the current state. Use +:meth:`Context.restore` to restore to the saved state. + +.. class:: Context(target) + + :param target: target :class:`Surface` for the context + :returns: a newly allocated *Context* + :raises: *MemoryError* in case of no memory + + Creates a new *Context* with all graphics state parameters set to default + values and with *target* as a target surface. The target surface should be + constructed with a backend-specific function such as :class:`ImageSurface` + (or any other cairo backend surface create variant). + + .. method:: append_path(path) + + :param path: :class:`Path` to be appended + + Append the *path* onto the current path. The *path* may be either the + return value from one of :meth:`Context.copy_path` or + :meth:`Context.copy_path_flat` or it may be constructed manually (in C). + + .. method:: arc(xc, yc, radius, angle1, angle2) + + :param xc: X position of the center of the arc + :type xc: float + :param yc: Y position of the center of the arc + :type yc: float + :param radius: the radius of the arc + :type radius: float + :param angle1: the start angle, in radians + :type angle1: float + :param angle2: the end angle, in radians + :type angle2: float + + Adds a circular arc of the given *radius* to the current path. The arc + is centered at (*xc, yc*), begins at *angle1* and proceeds in the + direction of increasing angles to end at *angle2*. If *angle2* is less + than *angle1* it will be progressively increased by 2*PI until it is + greater than *angle1*. + + If there is a current point, an initial line segment will be added to + the path to connect the current point to the beginning of the arc. If + this initial line is undesired, it can be avoided by calling + :meth:`Context.new_sub_path` before calling :meth:`Context.arc`. + + Angles are measured in radians. An angle of 0.0 is in the direction of + the positive X axis (in user space). An angle of PI/2.0 radians (90 + degrees) is in the direction of the positive Y axis (in user + space). Angles increase in the direction from the positive X axis toward + the positive Y axis. So with the default transformation matrix, angles + increase in a clockwise direction. + + To convert from degrees to radians, use ``degrees * (math.pi / 180)``. + + This function gives the arc in the direction of increasing angles; see + :meth:`Context.arc_negative` to get the arc in the direction of + decreasing angles. + + The arc is circular in user space. To achieve an elliptical arc, + you can scale the current transformation matrix by different + amounts in the X and Y directions. For example, to draw an ellipse + in the box given by *x, y, width, height*:: + + ctx.save() + ctx.translate(x + width / 2., y + height / 2.) + ctx.scale(width / 2., height / 2.) + ctx.arc(0., 0., 1., 0., 2 * math.pi) + ctx.restore() + + + .. method:: arc_negative(xc, yc, radius, angle1, angle2) + + :param xc: X position of the center of the arc + :type xc: float + :param yc: Y position of the center of the arc + :type yc: float + :param radius: the radius of the arc + :type radius: float + :param angle1: the start angle, in radians + :type angle1: float + :param angle2: the end angle, in radians + :type angle2: float + + Adds a circular arc of the given *radius* to the current path. The arc + is centered at (*xc, yc*), begins at *angle1* and proceeds in the + direction of decreasing angles to end at *angle2*. If *angle2* is + greater than *angle1* it will be progressively decreased by 2*PI until + it is less than *angle1*. + + See :meth:`Context.arc` for more details. This function differs only in + the direction of the arc between the two angles. + + .. method:: clip() + + Establishes a new clip region by intersecting the current clip region + with the current path as it would be filled by :meth:`Context.fill` and + according to the current :ref:`FILL RULE <constants_FILL_RULE>` (see + :meth:`Context.set_fill_rule`). + + After :meth:`.clip`, the current path will be cleared from the + :class:`Context`. + + The current clip region affects all drawing operations by effectively + masking out any changes to the surface that are outside the current clip + region. + + Calling :meth:`.clip` can only make the clip region smaller, never + larger. But the current clip is part of the graphics state, so a + temporary restriction of the clip region can be achieved by calling + :meth:`.clip` within a :meth:`Context.save`/:meth:`Context.restore` + pair. The only other means of increasing the size of the clip region is + :meth:`Context.reset_clip`. + + .. method:: clip_extents() + + :returns: (x1, y1, x2, y2) + :rtype: (float, float, float, float) + + * *x1*: left of the resulting extents + * *y1*: top of the resulting extents + * *x2*: right of the resulting extents + * *y2*: bottom of the resulting extents + + Computes a bounding box in user coordinates covering the area inside the + current clip. + + .. versionadded:: 1.4 + + .. method:: clip_preserve() + + Establishes a new clip region by intersecting the current clip region + with the current path as it would be filled by :meth:`Context.fill` and + according to the current :ref:`FILL RULE <constants_FILL_RULE>` (see + :meth:`Context.set_fill_rule`). + + Unlike :meth:`Context.clip`, :meth:`.clip_preserve` preserves the path + within the :class:`Context`. + + The current clip region affects all drawing operations by effectively + masking out any changes to the surface that are outside the current clip + region. + + Calling :meth:`.clip_preserve` can only make the clip region smaller, + never larger. But the current clip is part of the graphics state, so a + temporary restriction of the clip region can be achieved by calling + :meth:`.clip_preserve` within a + :meth:`Context.save`/:meth:`Context.restore` pair. The only other means + of increasing the size of the clip region is :meth:`Context.reset_clip`. + + .. method:: close_path() + + Adds a line segment to the path from the current point to the beginning + of the current sub-path, (the most recent point passed to + :meth:`Context.move_to`), and closes this sub-path. After this call the + current point will be at the joined endpoint of the sub-path. + + The behavior of :meth:`.close_path` is distinct from simply calling + :meth:`Context.line_to` with the equivalent coordinate in the case of + stroking. When a closed sub-path is stroked, there are no caps on the + ends of the sub-path. Instead, there is a line join connecting the final + and initial segments of the sub-path. + + If there is no current point before the call to :meth:`.close_path`, + this function will have no effect. + + Note: As of cairo version 1.2.4 any call to :meth:`.close_path` will + place an explicit MOVE_TO element into the path immediately after the + CLOSE_PATH element, (which can be seen in :meth:`Context.copy_path` for + example). This can simplify path processing in some cases as it may not + be necessary to save the "last move_to point" during processing as the + MOVE_TO immediately after the CLOSE_PATH will provide that point. + + .. method:: copy_clip_rectangle_list() + + :returns: the current clip region as a list of rectangles in user + coordinates + :rtype: list of 4-tuples of float + + (The status in the list may be %CAIRO_STATUS_CLIP_NOT_REPRESENTABLE to + indicate that the clip region cannot be represented as a list of + user-space rectangles. The status may have other values to indicate + other errors. - not implemented in pycairo) + + .. versionadded:: 1.4 + + .. method:: copy_page() + + Emits the current page for backends that support multiple pages, but + doesn't clear it, so, the contents of the current page will be retained + for the next page too. Use :meth:`Context.show_page` if you want to get + an empty page after the emission. + + This is a convenience function that simply calls + :meth:`Surface.copy_page` on *Context's* target. + + .. method:: copy_path() + + :returns: :class:`Path` + :raises: *MemoryError* in case of no memory + + Creates a copy of the current path and returns it to the user as a + :class:`Path`. + + .. method:: copy_path_flat() + + :returns: :class:`Path` + :raises: *MemoryError* in case of no memory + + Gets a flattened copy of the current path and returns it to the + user as a :class:`Path`. + + This function is like :meth:`Context.copy_path` except that any curves + in the path will be approximated with piecewise-linear approximations, + (accurate to within the current tolerance value). That is, the result is + guaranteed to not have any elements of type CAIRO_PATH_CURVE_TO which + will instead be replaced by a series of CAIRO_PATH_LINE_TO elements. + + .. method:: curve_to(x1, y1, x2, y2, x3, y3) + + :param x1: the X coordinate of the first control point + :type x1: float + :param y1: the Y coordinate of the first control point + :type y1: float + :param x2: the X coordinate of the second control point + :type x2: float + :param y2: the Y coordinate of the second control point + :type y2: float + :param x3: the X coordinate of the end of the curve + :type x3: float + :param y3: the Y coordinate of the end of the curve + :type y3: float + + Adds a cubic Bézier spline to the path from the current point to + position *(x3, y3)* in user-space coordinates, using *(x1, y1)* and + *(x2, y2)* as the control points. After this call the current point will + be *(x3, y3)*. + + If there is no current point before the call to :meth:`.curve_to` + this function will behave as if preceded by a call to + ``ctx.move_to(x1, y1)``. + + .. method:: device_to_user(x, y) + + :param x: X value of coordinate + :type x: float + :param y: Y value of coordinate + :type y: float + :returns: (x, y) + :rtype: (float, float) + + Transform a coordinate from device space to user space by multiplying + the given point by the inverse of the current transformation matrix + (CTM). + + .. method:: device_to_user_distance(dx, dy) + + :param dx: X component of a distance vector + :type dx: float + :param dy: Y component of a distance vector + :type dy: float + :returns: (dx, dy) + :rtype: (float, float) + + Transform a distance vector from device space to user space. This + function is similar to :meth:`Context.device_to_user` except that the + translation components of the inverse CTM will be ignored when + transforming *(dx,dy)*. + + .. method:: fill() + + A drawing operator that fills the current path according to the current + :ref:`FILL RULE <constants_FILL_RULE>`, (each sub-path is implicitly + closed before being filled). After :meth:`.fill`, the current path will + be cleared from the :class:`Context`. See :meth:`Context.set_fill_rule` + and :meth:`Context.fill_preserve`. + + .. method:: fill_extents() + + :returns: (x1, y1, x2, y2) + :rtype: (float, float, float, float) + + * *x1*: left of the resulting extents + * *y1*: top of the resulting extents + * *x2*: right of the resulting extents + * *y2*: bottom of the resulting extents + + Computes a bounding box in user coordinates covering the area that would + be affected, (the "inked" area), by a :meth:`Context.fill` operation + given the current path and fill parameters. If the current path is + empty, returns an empty rectangle (0,0,0,0). Surface dimensions and + clipping are not taken into account. + + Contrast with :meth:`Context.path_extents`, which is similar, but returns + non-zero extents for some paths with no inked area, (such as a + simple line segment). + + Note that :meth:`.fill_extents` must necessarily do more work to compute + the precise inked areas in light of the fill rule, so + :meth:`Context.path_extents` may be more desirable for sake of + performance if the non-inked path extents are desired. + + See :meth:`Context.fill`, :meth:`Context.set_fill_rule` and + :meth:`Context.fill_preserve`. + + .. method:: fill_preserve() + + A drawing operator that fills the current path according to the current + :ref:`FILL RULE <constants_FILL_RULE>`, (each sub-path is implicitly + closed before being filled). Unlike :meth:`Context.fill`, + :meth:`.fill_preserve` preserves the path within the :class:`Context`. + + See :meth:`Context.set_fill_rule` and :meth:`Context.fill`. + + .. method:: font_extents() + + :returns: (ascent, descent, height, max_x_advance, max_y_advance) + :rtype: (float, float, float, float, float) + + Gets the font extents for the currently selected font. + + .. method:: get_antialias() + + :returns: the current :ref:`ANTIALIAS <constants_ANTIALIAS>` mode, + as set by :meth:`Context.set_antialias`. + + .. method:: get_current_point() + + :returns: (x, y) + :rtype: (float, float) + + * *x*: X coordinate of the current point + * *y*: Y coordinate of the current point + + Gets the current point of the current path, which is conceptually the + final point reached by the path so far. + + The current point is returned in the user-space coordinate system. If + there is no defined current point or if :class:`Context` is in an error + status, *x* and *y* will both be set to 0.0. It is possible to check this + in advance with :meth:`Context.has_current_point`. + + Most path construction functions alter the current point. See the + following for details on how they affect the current point: + :meth:`Context.new_path`, :meth:`Context.new_sub_path`, + :meth:`Context.append_path`, :meth:`Context.close_path`, + :meth:`Context.move_to`, :meth:`Context.line_to`, + :meth:`Context.curve_to`, :meth:`Context.rel_move_to`, + :meth:`Context.rel_line_to`, :meth:`Context.rel_curve_to`, + :meth:`Context.arc`, :meth:`Context.arc_negative`, + :meth:`Context.rectangle`, :meth:`Context.text_path`, + :meth:`Context.glyph_path`, :meth:`Context.stroke_to_path`. + + Some functions use and alter the current point but do not otherwise + change current path: + :meth:`Context.show_text`. + + Some functions unset the current path and as a result, current point: + :meth:`Context.fill`, :meth:`Context.stroke`. + + .. method:: get_dash() + + :returns: (dashes, offset) + :rtype: (tuple, float) + + * *dashes*: return value for the dash array + * *offset*: return value for the current dash offset + + Gets the current dash array. + + .. versionadded:: 1.4 + + .. method:: get_dash_count() + + :returns: the length of the dash array, or 0 if no dash array set. + :rtype: int + + See also :meth:`Context.set_dash` and :meth:`Context.get_dash`. + + .. versionadded:: 1.4 + + .. method:: get_fill_rule() + + :returns: the current :ref:`FILL RULE <constants_FILL_RULE>`, as + set by :meth:`Context.set_fill_rule`. + + .. method:: get_font_face() + + :returns: the current :class:`FontFace` for the :class:`Context`. + + .. method:: get_font_matrix() + + :returns: the current :class:`Matrix` for the :class:`Context`. + + See :meth:`Context.set_font_matrix`. + + .. method:: get_font_options() + + :returns: the current :class:`FontOptions` for the :class:`Context`. + + Retrieves font rendering options set via + :meth:`Context.set_font_options`. Note that the returned options do not + include any options derived from the underlying surface; they are + literally the options passed to :meth:`Context.set_font_options`. + + .. method:: get_group_target() + + :returns: the target :class:`Surface`. + + Gets the current destination :class:`Surface` for the + :class:`Context`. This is either the original target surface as passed + to :class:`Context` or the target surface for the current group as + started by the most recent call to :meth:`Context.push_group` or + :meth:`Context.push_group_with_content`. + + .. versionadded:: 1.2 + + .. method:: get_line_cap() + + :returns: the current :ref:`LINE_CAP <constants_LINE_CAP>` style, as + set by :meth:`Context.set_line_cap`. + + .. method:: get_line_join() + + :returns: the current :ref:`LINE_JOIN <constants_LINE_JOIN>` style, as + set by :meth:`Context.set_line_join`. + + .. method:: get_line_width() + + :returns: the current line width + :rtype: float + + This function returns the current line width value exactly as set by + :meth:`Context.set_line_width`. Note that the value is unchanged even if + the CTM has changed between the calls to :meth:`Context.set_line_width` + and :meth:`.get_line_width`. + + .. method:: get_matrix() + + :returns: the current transformation :class:`Matrix` (CTM) + + .. method:: get_miter_limit() + + :returns: the current miter limit, as set by + :meth:`Context.set_miter_limit`. + :rtype: float + + .. method:: get_operator() + + :returns: the current compositing :ref:`OPERATOR <constants_OPERATOR>` + for a :class:`Context`. + + .. method:: get_scaled_font() + + :returns: the current :class:`ScaledFont` for a :class:`Context`. + + .. versionadded:: 1.4 + + .. method:: get_source() + + :returns: the current source :class:`Pattern` for a :class:`Context`. + + .. method:: get_target() + + :returns: the target :class:`Surface` for the :class:`Context` + + .. method:: get_tolerance() + + :returns: the current tolerance value, as set by + :meth:`Context.set_tolerance` + :rtype: float + + .. method:: glyph_extents(glyphs, [num_glyphs]) + + :param glyphs: glyphs + :type glyphs: a sequence of (int, float, float) + :param num_glyphs: number of glyphs to measure, defaults to using all + :type num_glyphs: int + :returns: x_bearing, y_bearing, width, height, x_advance, y_advance + :rtype: 6-tuple of float + + Gets the extents for an array of glyphs. The extents describe a + user-space rectangle that encloses the "inked" portion of the glyphs, + (as they would be drawn by :meth:`Context.show_glyphs`). Additionally, + the x_advance and y_advance values indicate the amount by which the + current point would be advanced by :meth:`Context.show_glyphs`. + + Note that whitespace glyphs do not contribute to the size of the + rectangle (extents.width and extents.height). + + .. method:: glyph_path(glyphs[, num_glyphs]) + + :param glyphs: glyphs to show + :type glyphs: a sequence of (int, float, float) + :param num_glyphs: number of glyphs to show, defaults to showing all + :type num_glyphs: int + + Adds closed paths for the glyphs to the current path. The generated path + if filled, achieves an effect similar to that of + :meth:`Context.show_glyphs`. + + .. method:: has_current_point() + + returns: True iff a current point is defined on the current path. + See :meth:`Context.get_current_point` for details on the current point. + + .. versionadded:: 1.6 + + .. method:: identity_matrix() + + Resets the current transformation :class:`Matrix` (CTM) by setting it + equal to the identity matrix. That is, the user-space and device-space + axes will be aligned and one user-space unit will transform to one + device-space unit. + + .. method:: in_fill(x, y) + + :param x: X coordinate of the point to test + :type x: float + :param y: Y coordinate of the point to test + :type y: float + :returns: True iff the point is inside the area that would be affected + by a :meth:`Context.fill` operation given the current path and filling + parameters. Surface dimensions and clipping are not taken into account. + + See :meth:`Context.fill`, :meth:`Context.set_fill_rule` and + :meth:`Context.fill_preserve`. + + .. method:: in_stroke(x, y) + + :param x: X coordinate of the point to test + :type x: float + :param y: Y coordinate of the point to test + :type y: float + + :returns: True iff the point is inside the area that would be affected + by a :meth:`Context.stroke` operation given the current path and + stroking parameters. Surface dimensions and clipping are not taken + into account. + + See :meth:`Context.stroke`, :meth:`Context.set_line_width`, + :meth:`Context.set_line_join`, :meth:`Context.set_line_cap`, + :meth:`Context.set_dash`, and :meth:`Context.stroke_preserve`. + + .. method:: line_to(x, y) + + :param x: the X coordinate of the end of the new line + :type x: float + :param y: the Y coordinate of the end of the new line + :type y: float + + Adds a line to the path from the current point to position *(x, y)* in + user-space coordinates. After this call the current point will be *(x, + y)*. + + If there is no current point before the call to :meth:`.line_to` + this function will behave as ``ctx.move_to(x, y)``. + + .. method:: mask(pattern) + + :param pattern: a :class:`Pattern` + + A drawing operator that paints the current source using the alpha + channel of *pattern* as a mask. (Opaque areas of *pattern* are painted + with the source, transparent areas are not painted.) + + .. method:: mask_surface(surface, x=0.0, y=0.0) + + :param surface: a :class:`Surface` + :param x: X coordinate at which to place the origin of *surface* + :type x: float + :param y: Y coordinate at which to place the origin of *surface* + :type y: float + + A drawing operator that paints the current source using the alpha + channel of *surface* as a mask. (Opaque areas of *surface* are painted + with the source, transparent areas are not painted.) + + .. method:: move_to(x, y) + + :param x: the X coordinate of the new position + :type x: float + :param y: the Y coordinate of the new position + :type y: float + + Begin a new sub-path. After this call the current point will be *(x, + y)*. + + .. method:: new_path() + + Clears the current path. After this call there will be no path and no + current point. + + .. method:: new_sub_path() + + Begin a new sub-path. Note that the existing path is not affected. After + this call there will be no current point. + + In many cases, this call is not needed since new sub-paths are + frequently started with :meth:`Context.move_to`. + + A call to :meth:`.new_sub_path` is particularly useful when beginning a + new sub-path with one of the :meth:`Context.arc` calls. This makes + things easier as it is no longer necessary to manually compute the arc's + initial coordinates for a call to :meth:`Context.move_to`. + + .. versionadded:: 1.6 + + .. method:: paint() + + A drawing operator that paints the current source everywhere within the + current clip region. + + .. method:: paint_with_alpha(alpha) + + :param alpha: alpha value, between 0 (transparent) and 1 (opaque) + :type alpha: float + + A drawing operator that paints the current source everywhere within the + current clip region using a mask of constant alpha value *alpha*. The + effect is similar to :meth:`Context.paint`, but the drawing is faded out + using the alpha value. + + .. method:: path_extents() + + :returns: (x1, y1, x2, y2) + :rtype: (float, float, float, float) + + * *x1*: left of the resulting extents + * *y1*: top of the resulting extents + * *x2*: right of the resulting extents + * *y2*: bottom of the resulting extents + + Computes a bounding box in user-space coordinates covering the points on + the current path. If the current path is empty, returns an empty + rectangle (0, 0, 0, 0). Stroke parameters, fill rule, surface + dimensions and clipping are not taken into account. + + Contrast with :meth:`Context.fill_extents` and + :meth:`Context.stroke_extents` which return the extents of only the area + that would be "inked" by the corresponding drawing operations. + + The result of :meth:`.path_extents` is defined as equivalent to the + limit of :meth:`Context.stroke_extents` with cairo.LINE_CAP_ROUND as the + line width approaches 0.0, (but never reaching the empty-rectangle + returned by :meth:`Context.stroke_extents` for a line width of 0.0). + + Specifically, this means that zero-area sub-paths such as + :meth:`Context.move_to`; :meth:`Context.line_to` segments, (even + degenerate cases where the coordinates to both calls are identical), + will be considered as contributing to the extents. However, a lone + :meth:`Context.move_to` will not contribute to the results of + :meth:`Context.path_extents`. + + .. versionadded:: 1.6 + + .. method:: pop_group() + + :returns: a newly created :class:`SurfacePattern` containing the results + of all drawing operations performed to the group. + + Terminates the redirection begun by a call to :meth:`Context.push_group` + or :meth:`Context.push_group_with_content` and returns a new pattern + containing the results of all drawing operations performed to the group. + + The :meth:`.pop_group` function calls :meth:`Context.restore`, + (balancing a call to :meth:`Context.save` by the + :meth:`Context.push_group` function), so that any changes to the graphics + state will not be visible outside the group. + + .. versionadded:: 1.2 + + .. method:: pop_group_to_source() + + Terminates the redirection begun by a call to :meth:`Context.push_group` + or :meth:`Context.push_group_with_content` and installs the resulting + pattern as the source :class:`Pattern` in the given :class:`Context`. + + The behavior of this function is equivalent to the sequence of + operations:: + + group = cairo_pop_group() + ctx.set_source(group) + + but is more convenient as their is no need for a variable to store + the short-lived pointer to the pattern. + + The :meth:`Context.pop_group` function calls :meth:`Context.restore`, + (balancing a call to :meth:`Context.save` by the + :meth:`Context.push_group` function), so that any changes to the graphics + state will not be visible outside the group. + + .. versionadded:: 1.2 + + .. method:: push_group() + + Temporarily redirects drawing to an intermediate surface known as a + group. The redirection lasts until the group is completed by a call to + :meth:`Context.pop_group` or :meth:`Context.pop_group_to_source`. These + calls provide the result of any drawing to the group as a pattern, + (either as an explicit object, or set as the source pattern). + + This group functionality can be convenient for performing intermediate + compositing. One common use of a group is to render objects as opaque + within the group, (so that they occlude each other), and then blend the + result with translucence onto the destination. + + Groups can be nested arbitrarily deep by making balanced calls to + :meth:`Context.push_group`/:meth:`Context.pop_group`. Each call + pushes/pops the new target group onto/from a stack. + + The :meth:`.push_group` function calls :meth:`Context.save` so that any + changes to the graphics state will not be visible outside the group, + (the pop_group functions call :meth:`Context.restore`). + + By default the intermediate group will have a :ref:`CONTENT + <constants_CONTENT>` type of cairo.CONTENT_COLOR_ALPHA. Other content + types can be chosen for the group by using + :meth:`Context.push_group_with_content` instead. + + As an example, here is how one might fill and stroke a path with + translucence, but without any portion of the fill being visible + under the stroke:: + + ctx.push_group() + ctx.set_source(fill_pattern) + ctx.fill_preserve() + ctx.set_source(stroke_pattern) + ctx.stroke() + ctx.pop_group_to_source() + ctx.paint_with_alpha(alpha) + + .. versionadded:: 1.2 + + .. method:: push_group_with_content(content) + + :param content: a :ref:`CONTENT <constants_CONTENT>` indicating the + type of group that will be created + + Temporarily redirects drawing to an intermediate surface known as a + group. The redirection lasts until the group is completed by a call to + :meth:`Context.pop_group` or :meth:`Context.pop_group_to_source`. These + calls provide the result of any drawing to the group as a pattern, + (either as an explicit object, or set as the source pattern). + + The group will have a content type of *content*. The ability to control + this content type is the only distinction between this function and + :meth:`Context.push_group` which you should see for a more detailed + description of group rendering. + + .. versionadded:: 1.2 + + .. method:: rectangle(x, y, width, height) + + :param x: the X coordinate of the top left corner of the rectangle + :type x: float + :param y: the Y coordinate to the top left corner of the rectangle + :type y: float + :param width: the width of the rectangle + :type width: float + :param height: the height of the rectangle + :type height: float + + Adds a closed sub-path rectangle of the given size to the current path + at position *(x, y)* in user-space coordinates. + + This function is logically equivalent to:: + + ctx.move_to(x, y) + ctx.rel_line_to(width, 0) + ctx.rel_line_to(0, height) + ctx.rel_line_to(-width, 0) + ctx.close_path() + + .. method:: rel_curve_to(dx1, dy1, dx2, dy2, dx3, dy4) + + :param dx1: the X offset to the first control point + :type dx1: float + :param dy1: the Y offset to the first control point + :type dy1: float + :param dx2: the X offset to the second control point + :type dx2: float + :param dy2: the Y offset to the second control point + :type dy2: float + :param dx3: the X offset to the end of the curve + :type dx3: float + :param dy3: the Y offset to the end of the curve + :type dy3: float + :raises: :exc:`cairo.Error` if called with no current point. + + Relative-coordinate version of :meth:`Context.curve_to`. All + offsets are relative to the current point. Adds a cubic Bézier spline to + the path from the current point to a point offset from the current point + by *(dx3, dy3)*, using points offset by *(dx1, dy1)* and *(dx2, dy2)* as + the control points. After this call the current point will be offset by + *(dx3, dy3)*. + + Given a current point of (x, y), ``ctx.rel_curve_to(dx1, dy1, dx2, dy2, + dx3, dy3)`` is logically equivalent to ``ctx.curve_to(x+dx1, y+dy1, + x+dx2, y+dy2, x+dx3, y+dy3)``. + + .. method:: rel_line_to(dx, dy) + + :param dx: the X offset to the end of the new line + :type dx: float + :param dy: the Y offset to the end of the new line + :type dy: float + :raises: :exc:`cairo.Error` if called with no current point. + + Relative-coordinate version of :meth:`Context.line_to`. Adds a line to + the path from the current point to a point that is offset from the + current point by *(dx, dy)* in user space. After this call the current + point will be offset by *(dx, dy)*. + + Given a current point of (x, y), ``ctx.rel_line_to(dx, dy)`` is logically + equivalent to ``ctx.line_to(x + dx, y + dy)``. + + .. method:: rel_move_to(dx, dy) + + :param dx: the X offset + :type dx: float + :param dy: the Y offset + :type dy: float + :raises: :exc:`cairo.Error` if called with no current point. + + Begin a new sub-path. After this call the current point will offset by + *(dx, dy)*. + + Given a current point of (x, y), ``ctx.rel_move_to(dx, dy)`` is logically + equivalent to ``ctx.(x + dx, y + dy)``. + + .. method:: reset_clip() + + Reset the current clip region to its original, unrestricted state. That + is, set the clip region to an infinitely large shape containing the + target surface. Equivalently, if infinity is too hard to grasp, one can + imagine the clip region being reset to the exact bounds of the target + surface. + + Note that code meant to be reusable should not call :meth:`.reset_clip` + as it will cause results unexpected by higher-level code which calls + :meth:`.clip`. Consider using :meth:`.save` and :meth:`.restore` around + :meth:`.clip` as a more robust means of temporarily restricting the clip + region. + + .. method:: restore() + + Restores :class:`Context` to the state saved by a preceding call to + :meth:`.save` and removes that state from the stack of saved states. + + .. method:: rotate(angle) + + :param angle: angle (in radians) by which the user-space axes will be + rotated + :type angle: float + + Modifies the current transformation matrix (CTM) by rotating the + user-space axes by *angle* radians. The rotation of the axes takes places + after any existing transformation of user space. The rotation direction + for positive angles is from the positive X axis toward the positive Y + axis. + + .. method:: save() + + Makes a copy of the current state of :class:`Context` and saves it on an + internal stack of saved states. When :meth:`.restore` is called, + :class:`Context` will be restored to the saved state. Multiple calls to + :meth:`.save` and :meth:`.restore` can be nested; each call to + :meth:`.restore` restores the state from the matching paired + :meth:`.save`. + + .. method:: scale(sx, sy) + + :param sx: scale factor for the X dimension + :type sx: float + :param sy: scale factor for the Y dimension + :type sy: float + + Modifies the current transformation matrix (CTM) by scaling the X and Y + user-space axes by *sx* and *sy* respectively. The scaling of the axes + takes place after any existing transformation of user space. + + .. method:: select_font_face(family[, slant[, weight]]) + + :param family: a font family name + :type family: str or unicode + :param slant: the :ref:`FONT_SLANT <constants_FONT_SLANT>` of the font, + defaults to :data:`cairo.FONT_SLANT_NORMAL`. + :param weight: the :ref:`FONT_WEIGHT <constants_FONT_WEIGHT>` of the + font, defaults to :data:`cairo.FONT_WEIGHT_NORMAL`. + + Note: The :meth:`.select_font_face` function call is part of what the + cairo designers call the "toy" text API. It is convenient for short + demos and simple programs, but it is not expected to be adequate for + serious text-using applications. + + Selects a family and style of font from a simplified description as a + family name, slant and weight. Cairo provides no operation to list + available family names on the system (this is a "toy", remember), but + the standard CSS2 generic family names, ("serif", "sans-serif", + "cursive", "fantasy", "monospace"), are likely to work as expected. + + For "real" font selection, see the font-backend-specific + font_face_create functions for the font backend you are using. (For + example, if you are using the freetype-based cairo-ft font backend, see + cairo_ft_font_face_create_for_ft_face() or + cairo_ft_font_face_create_for_pattern().) The resulting font face could + then be used with cairo_scaled_font_create() and + cairo_set_scaled_font(). + + Similarly, when using the "real" font support, you can call directly + into the underlying font system, (such as fontconfig or freetype), for + operations such as listing available fonts, etc. + + It is expected that most applications will need to use a more + comprehensive font handling and text layout library, (for example, + pango), in conjunction with cairo. + + If text is drawn without a call to :meth:`.select_font_face`, (nor + :meth:`.set_font_face` nor :meth:`.set_scaled_font`), the default family + is platform-specific, but is essentially "sans-serif". Default slant is + cairo.FONT_SLANT_NORMAL, and default weight is + cairo.FONT_WEIGHT_NORMAL. + + This function is equivalent to a call to :class:`ToyFontFace` + followed by :meth:`.set_font_face`. + + .. method:: set_antialias(antialias) + + :param antialias: the new :ref:`ANTIALIAS <constants_ANTIALIAS>` mode + + Set the antialiasing mode of the rasterizer used for drawing shapes. + This value is a hint, and a particular backend may or may not support a + particular value. At the current time, no backend supports + :data:`cairo.ANTIALIAS_SUBPIXEL` when drawing shapes. + + Note that this option does not affect text rendering, instead see + :meth:`FontOptions.set_antialias`. + + .. method:: set_dash(dashes, [offset=0]) + + :param dashes: a sequence specifying alternate lengths of on and off + stroke portions. + :type dashes: sequence of float + :param offset: an offset into the dash pattern at which the stroke + should start, defaults to 0. + :type offset: int + :raises: :exc:`cairo.Error` if any value in *dashes* is negative, or if + all values are 0. + + Sets the dash pattern to be used by :meth:`.stroke`. A dash pattern is + specified by *dashes* - a sequence of positive values. Each value + provides the length of alternate "on" and "off" portions of the + stroke. The *offset* specifies an offset into the pattern at which the + stroke begins. + + Each "on" segment will have caps applied as if the segment were a + separate sub-path. In particular, it is valid to use an "on" length of + 0.0 with :data:`cairo.LINE_CAP_ROUND` or :data:`cairo.LINE_CAP_SQUARE` + in order to distributed dots or squares along a path. + + Note: The length values are in user-space units as evaluated at the time + of stroking. This is not necessarily the same as the user space at the + time of :meth:`.set_dash`. + + If the number of dashes is 0 dashing is disabled. + + If the number of dashes is 1 a symmetric pattern is assumed with + alternating on and off portions of the size specified by the single + value in *dashes*. + + .. method:: set_fill_rule(fill_rule) + + :param fill_rule: a :ref:`FILL RULE <constants_FILL_RULE>` to set the + within the cairo context. The fill rule is used to determine which + regions are inside or outside a complex (potentially + self-intersecting) path. The current fill rule affects both + :meth:`.fill` and :meth:`.clip`. + + The default fill rule is :data:`cairo.FILL_RULE_WINDING`. + + .. method:: set_font_face(font_face) + + :param font_face: a :class:`FontFace`, or None to restore to the + default :class:`FontFace` + + Replaces the current :class:`FontFace` object in the :class:`Context` + with *font_face*. + + .. method:: set_font_matrix(matrix) + + :param matrix: a :class:`Matrix` describing a transform to be applied to + the current font. + + Sets the current font matrix to *matrix*. The font matrix gives a + transformation from the design space of the font (in this space, the + em-square is 1 unit by 1 unit) to user space. Normally, a simple scale + is used (see :meth:`.set_font_size`), but a more complex font matrix can + be used to shear the font or stretch it unequally along the two axes + + .. method:: set_font_options(options) + + :param options: :class:`FontOptions` to use + + Sets a set of custom font rendering options for the :class:`Context`. + Rendering options are derived by merging these options with the options + derived from underlying surface; if the value in *options* has a default + value (like :data:`cairo.ANTIALIAS_DEFAULT`), then the value from the + surface is used. + + .. method:: set_font_size(size) + + :param size: the new font size, in user space units + :type size: float + + Sets the current font matrix to a scale by a factor of *size*, replacing + any font matrix previously set with :meth:`.set_font_size` or + :meth:`.set_font_matrix`. This results in a font size of *size* user + space units. (More precisely, this matrix will result in the font's + em-square being a *size* by *size* square in user space.) + + If text is drawn without a call to :meth:`.set_font_size`, (nor + :meth:`.set_font_matrix` nor :meth:`.set_scaled_font`), the default font + size is 10.0. + + .. method:: set_line_cap(line_cap) + + :param line_cap: a :ref:`LINE_CAP <constants_LINE_CAP>` style + + Sets the current line cap style within the :class:`Context`. + + As with the other stroke parameters, the current line cap style is + examined by :meth:`.stroke`, :meth:`.stroke_extents`, and + :meth:`.stroke_to_path`, but does not have any effect during path + construction. + + The default line cap style is :data:`cairo.LINE_CAP_BUTT`. + + .. method:: set_line_join(line_join) + + :param line_join: a :ref:`LINE_JOIN <constants_LINE_JOIN>` style + + Sets the current line join style within the :class:`Context`. + + As with the other stroke parameters, the current line join style is + examined by :meth:`.stroke`, :meth:`.stroke_extents`, and + :meth:`.stroke_to_path`, but does not have any effect during path + construction. + + The default line join style is :data:`cairo.LINE_JOIN_MITER`. + + .. method:: set_line_width(width) + + :param width: a line width + :type width: float + + Sets the current line width within the :class:`Context`. The line width + value specifies the diameter of a pen that is circular in user space, + (though device-space pen may be an ellipse in general due to + scaling/shear/rotation of the CTM). + + Note: When the description above refers to user space and CTM it refers + to the user space and CTM in effect at the time of the stroking + operation, not the user space and CTM in effect at the time of the call + to :meth:`.set_line_width`. The simplest usage makes both of these + spaces identical. That is, if there is no change to the CTM between a + call to :meth:`.set_line_width` and the stroking operation, then one can + just pass user-space values to :meth:`.set_line_width` and ignore this + note. + + As with the other stroke parameters, the current line width is examined + by :meth:`.stroke`, :meth:`.stroke_extents`, and + :meth:`.stroke_to_path`, but does not have any effect during path + construction. + + The default line width value is 2.0. + + .. method:: set_matrix(matrix) + + :param matrix: a transformation :class:`Matrix` from user space to + device space. + + Modifies the current transformation matrix (CTM) by setting it equal to + *matrix*. + + .. method:: set_miter_limit(limit) + + :param limit: miter limit to set + :type width: float + + Sets the current miter limit within the :class:`Context`. + + If the current line join style is set to :data:`cairo.LINE_JOIN_MITER` + (see :meth:`.set_line_join`), the miter limit is used to determine + whether the lines should be joined with a bevel instead of a miter. + Cairo divides the length of the miter by the line width. If the result + is greater than the miter limit, the style is converted to a bevel. + + As with the other stroke parameters, the current line miter limit is + examined by :meth:`.stroke`, :meth:`.stroke_extents`, and + :meth:`.stroke_to_path`, but does not have any effect during path + construction. + + The default miter limit value is 10.0, which will convert joins with + interior angles less than 11 degrees to bevels instead of miters. For + reference, a miter limit of 2.0 makes the miter cutoff at 60 degrees, + and a miter limit of 1.414 makes the cutoff at 90 degrees. + + A miter limit for a desired angle can be computed as:: + + miter limit = 1/math.sin(angle/2) + + .. method:: set_operator(op) + + :param op: the compositing :ref:`OPERATOR <constants_OPERATOR>` to set + for use in all drawing operations. + + The default operator is :data:`cairo.OPERATOR_OVER`. + + .. method:: set_scaled_font(scaled_font) + + :param scaled_font: a :class:`ScaledFont` + + Replaces the current font face, font matrix, and font options in the + :class:`Context` with those of the :class:`ScaledFont`. Except for some + translation, the current CTM of the :class:`Context` should be the same + as that of the :class:`ScaledFont`, which can be accessed using + :meth:`ScaledFont.get_ctm`. + + .. versionadded:: 1.2 + + .. method:: set_source(source) + + :param source: a :class:`Pattern` to be used as the source for + subsequent drawing operations. + + Sets the source pattern within :class:`Context` to *source*. This + pattern will then be used for any subsequent drawing operation until a + new source pattern is set. + + Note: The pattern's transformation matrix will be locked to the user + space in effect at the time of :meth:`.set_source`. This means that + further modifications of the current transformation matrix will not + affect the source pattern. See :meth:`Pattern.set_matrix`. + + The default source pattern is a solid pattern that is opaque black, + (that is, it is equivalent to ``set_source_rgb(0.0, 0.0, 0.0)``. + + .. method:: set_source_rgb(red, green, blue) + + :param red: red component of color + :type red: float + :param green: green component of color + :type green: float + :param blue: blue component of color + :type blue: float + + Sets the source pattern within :class:`Context` to an opaque color. This + opaque color will then be used for any subsequent drawing operation + until a new source pattern is set. + + The color components are floating point numbers in the range 0 to + 1. If the values passed in are outside that range, they will be + clamped. + + The default source pattern is opaque black, (that is, it is + equivalent to ``set_source_rgb(0.0, 0.0, 0.0)``. + + .. method:: set_source_rgba(red, green, blue[, alpha=1.0]) + + :param red: red component of color + :type red: float + :param green: green component of color + :type green: float + :param blue: blue component of color + :type blue: float + :param alpha: alpha component of color + :type alpha: float + + Sets the source pattern within :class:`Context` to a translucent + color. This color will then be used for any subsequent drawing operation + until a new source pattern is set. + + The color and alpha components are floating point numbers in the range 0 + to 1. If the values passed in are outside that range, they will be + clamped. + + The default source pattern is opaque black, (that is, it is + equivalent to ``set_source_rgba(0.0, 0.0, 0.0, 1.0)``. + + .. method:: set_source_surface(surface[, x=0.0[, y=0.0]]) + + :param surface: a :class:`Surface` to be used to set the source pattern + :param x: User-space X coordinate for surface origin + :type x: float + :param y: User-space Y coordinate for surface origin + :type y: float + + This is a convenience function for creating a pattern from a + :class:`Surface` and setting it as the source in :class:`Context` with + :meth:`.set_source`. + + The *x* and *y* parameters give the user-space coordinate at which the + surface origin should appear. (The surface origin is its upper-left + corner before any transformation has been applied.) The *x* and *y* + patterns are negated and then set as translation values in the pattern + matrix. + + Other than the initial translation pattern matrix, as described above, + all other pattern attributes, (such as its extend mode), are set to the + default values as in :class:`SurfacePattern`. The resulting pattern can + be queried with :meth:`.get_source` so that these attributes can be + modified if desired, (eg. to create a repeating pattern with + :meth:`.Pattern.set_extend`). + + .. method:: set_tolerance(tolerance) + + :param tolerance: the tolerance, in device units (typically pixels) + :type tolerance: float + + Sets the tolerance used when converting paths into trapezoids. Curved + segments of the path will be subdivided until the maximum deviation + between the original path and the polygonal approximation is less than + *tolerance*. The default value is 0.1. A larger value will give better + performance, a smaller value, better appearance. (Reducing the value + from the default value of 0.1 is unlikely to improve appearance + significantly.) The accuracy of paths within Cairo is limited by the + precision of its internal arithmetic, and the prescribed *tolerance* is + restricted to the smallest representable internal value. + + .. method:: show_glyphs(glyphs[, num_glyphs]) + + :param glyphs: glyphs to show + :type glyphs: a sequence of (int, float, float) + :param num_glyphs: number of glyphs to show, defaults to showing all + glyphs + :type num_glyphs: int + + A drawing operator that generates the shape from an array of glyphs, + rendered according to the current font face, font size (font matrix), + and font options. + + .. method:: show_page() + + Emits and clears the current page for backends that support multiple + pages. Use :meth:`.copy_page` if you don't want to clear the page. + + This is a convenience function that simply calls + ``ctx.get_target() . show_page()`` + + .. method:: show_text(text) + + :param text: text + :type text: str or unicode + + A drawing operator that generates the shape from a string of text, + rendered according to the current font_face, font_size (font_matrix), + and font_options. + + This function first computes a set of glyphs for the string of text. The + first glyph is placed so that its origin is at the current point. The + origin of each subsequent glyph is offset from that of the previous + glyph by the advance values of the previous glyph. + + After this call the current point is moved to the origin of where the + next glyph would be placed in this same progression. That is, the + current point will be at the origin of the final glyph offset by its + advance values. This allows for easy display of a single logical string + with multiple calls to :meth:`.show_text`. + + Note: The :meth:`.show_text` function call is part of what the cairo + designers call the "toy" text API. It is convenient for short demos + and simple programs, but it is not expected to be adequate for + serious text-using applications. See :meth:`.show_glyphs` for the + "real" text display API in cairo. + + .. method:: stroke() + + A drawing operator that strokes the current path according to the + current line width, line join, line cap, and dash settings. After + :meth:`.stroke`, the current path will be cleared from the cairo + context. See :meth:`.set_line_width`, :meth:`.set_line_join`, + :meth:`.set_line_cap`, :meth:`.set_dash`, and :meth:`.stroke_preserve`. + + Note: Degenerate segments and sub-paths are treated specially and + provide a useful result. These can result in two different situations: + + 1. Zero-length "on" segments set in :meth:`.set_dash`. If the cap + style is :data:`cairo.LINE_CAP_ROUND` or :data:`cairo.LINE_CAP_SQUARE` + then these segments will be drawn as circular dots or squares + respectively. In the case of :data:`cairo.LINE_CAP_SQUARE`, the + orientation of the squares is determined by the direction of the + underlying path. + + 2. A sub-path created by :meth:`.move_to` followed by either a + :meth:`.close_path` or one or more calls to :meth:`.line_to` to the same + coordinate as the :meth:`.move_to`. If the cap style is + :data:`cairo.LINE_CAP_ROUND` then these sub-paths will be drawn as + circular dots. Note that in the case of :data:`cairo.LINE_CAP_SQUARE` a + degenerate sub-path will not be drawn at all, (since the correct + orientation is indeterminate). + + In no case will a cap style of :data:`cairo.LINE_CAP_BUTT` cause anything + to be drawn in the case of either degenerate segments or sub-paths. + + .. method:: stroke_extents() + + :returns: (x1, y1, x2, y2) + :rtype: (float, float, float, float) + + * *x1*: left of the resulting extents + * *y1*: top of the resulting extents + * *x2*: right of the resulting extents + * *y2*: bottom of the resulting extents + + Computes a bounding box in user coordinates covering the area that would + be affected, (the "inked" area), by a :meth:`.stroke` operation given + the current path and stroke parameters. If the current path is empty, + returns an empty rectangle (0, 0, 0, 0). Surface dimensions and + clipping are not taken into account. + + Note that if the line width is set to exactly zero, then + :meth:`.stroke_extents` will return an empty rectangle. Contrast with + :meth:`.path_extents` which can be used to compute the non-empty bounds + as the line width approaches zero. + + Note that :meth:`.stroke_extents` must necessarily do more work to + compute the precise inked areas in light of the stroke parameters, so + :meth:`.path_extents` may be more desirable for sake of performance if + non-inked path extents are desired. + + See :meth:`.stroke`, :meth:`.set_line_width`, :meth:`.set_line_join`, + :meth:`.set_line_cap`, :meth:`.set_dash`, and :meth:`.stroke_preserve`. + + .. method:: stroke_preserve() + + A drawing operator that strokes the current path according to the + current line width, line join, line cap, and dash settings. Unlike + :meth:`.stroke`, :meth:`.stroke_preserve` preserves the path within the + cairo context. + + See :meth:`.set_line_width`, :meth:`.set_line_join`, + :meth:`.set_line_cap`, :meth:`.set_dash`, and :meth:`.stroke_preserve`. + + .. method:: text_extents(text) + + :param text: text to get extents for + :type text: string or unicode + :returns: x_bearing, y_bearing, width, height, x_advance, y_advance + :rtype: 6-tuple of float + + Gets the extents for a string of text. The extents describe a user-space + rectangle that encloses the "inked" portion of the text, (as it would be + drawn by :meth:`Context.show_text`). Additionally, the x_advance and + y_advance values indicate the amount by which the current point would be + advanced by :meth:`Context.show_text`. + + Note that whitespace characters do not directly contribute to the size + of the rectangle (extents.width and extents.height). They do contribute + indirectly by changing the position of non-whitespace characters. In + particular, trailing whitespace characters are likely to not affect the + size of the rectangle, though they will affect the x_advance and + y_advance values. + + .. method:: text_path(text) + + :param text: text + :type text: string or unicode + + Adds closed paths for text to the current path. The generated path if + filled, achieves an effect similar to that of :meth:`Context.show_text`. + + Text conversion and positioning is done similar to + :meth:`Context.show_text`. + + Like :meth:`Context.show_text`, After this call the current point is + moved to the origin of where the next glyph would be placed in this same + progression. That is, the current point will be at the origin of the + final glyph offset by its advance values. This allows for chaining + multiple calls to to :meth:`Context.text_path` without having to set + current point in between. + + Note: The :meth:`.text_path` function call is part of what the cairo + designers call the "toy" text API. It is convenient for short demos and + simple programs, but it is not expected to be adequate for serious + text-using applications. See :meth:`Context.glyph_path` for the "real" + text path API in cairo. + + .. method:: transform(matrix) + + :param matrix: a transformation :class:`Matrix` to be applied to the + user-space axes + + Modifies the current transformation matrix (CTM) by applying *matrix* as + an additional transformation. The new transformation of user space takes + place after any existing transformation. + + .. method:: translate(tx, ty) + + :param tx: amount to translate in the X direction + :type tx: float + :param ty: amount to translate in the Y direction + :type ty: float + + Modifies the current transformation matrix (CTM) by translating the + user-space origin by *(tx, ty)*. This offset is interpreted as a + user-space coordinate according to the CTM in place before the new call + to :meth:`.translate`. In other words, the translation of the user-space + origin takes place after any existing transformation. + + .. method:: user_to_device(x, y) + + :param x: X value of coordinate + :type x: float + :param y: Y value of coordinate + :type y: float + :returns: (x, y) + :rtype: (float, float) + + * *x*: X value of coordinate + * *y*: Y value of coordinate + + Transform a coordinate from user space to device space by multiplying + the given point by the current transformation matrix (CTM). + + .. method:: user_to_device_distance(dx, dy) + + :param dx: X value of a distance vector + :type dx: float + :param dy: Y value of a distance vector + :type dy: float + :returns: (dx, dy) + :rtype: (float, float) + + * *dx*: X value of a distance vector + * *dy*: Y value of a distance vector + + Transform a distance vector from user space to device space. This + function is similar to :meth:`Context.user_to_device` except that the + translation components of the CTM will be ignored when transforming + *(dx,dy)*. diff --git a/doc/reference/exceptions.rst b/doc/reference/exceptions.rst new file mode 100644 index 0000000..ce1bfa2 --- /dev/null +++ b/doc/reference/exceptions.rst @@ -0,0 +1,18 @@ +.. _exceptions: + +********** +Exceptions +********** + +.. currentmodule:: cairo + +When a cairo function or method call fails an exception is raised. I/O errors +raise IOError, memory errors raise MemoryError, and all other errors raise +cairo.Error. + +cairo.Error() +============= + +.. exception:: cairo.Error + + This exception is raised when a cairo object returns an error status. diff --git a/doc/reference/index.rst b/doc/reference/index.rst new file mode 100644 index 0000000..2b1b9ac --- /dev/null +++ b/doc/reference/index.rst @@ -0,0 +1,19 @@ +.. _reference_index: + +********* +Reference +********* + +.. currentmodule:: cairo + +.. toctree:: + :maxdepth: 2 + + constants + context + exceptions + matrix + paths + patterns + surfaces + text diff --git a/doc/reference/matrix.rst b/doc/reference/matrix.rst new file mode 100644 index 0000000..cb3ec3e --- /dev/null +++ b/doc/reference/matrix.rst @@ -0,0 +1,181 @@ +.. _matrix: + +****** +Matrix +****** + +.. currentmodule:: cairo + + +class Matrix() +============== + +*Matrix* is used throughout cairo to convert between different coordinate +spaces. A *Matrix* holds an affine transformation, such as a scale, rotation, +shear, or a combination of these. The transformation of a point (x,y) is +given by:: + + x_new = xx * x + xy * y + x0 + y_new = yx * x + yy * y + y0 + +The current transformation matrix of a :class:`Context`, represented as a +*Matrix*, defines the transformation from user-space coordinates to device-space +coordinates. + +Some standard Python operators can be used with matrices: + +To read the values from a *Matrix*:: + + xx, yx, xy, yy, x0, y0 = matrix + +To multiply two matrices:: + + matrix3 = matrix1.multiply(matrix2) + # or equivalently + matrix3 = matrix1 * matrix2 + +To compare two matrices:: + + matrix1 == matrix2 + matrix1 != matrix2 + +For more information on matrix transformation see http://www.cairographics.org/matrix_transform + + +.. class:: Matrix(xx = 1.0, yx = 0.0, xy = 0.0, yy = 1.0, x0 = 0.0, y0 = 0.0) + + :param xx: xx component of the affine transformation + :type xx: float + :param yx: yx component of the affine transformation + :type yx: float + :param xy: xy component of the affine transformation + :type xy: float + :param yy: yy component of the affine transformation + :type yy: float + :param x0: X translation component of the affine transformation + :type x0: float + :param y0: Y translation component of the affine transformation + :type y0: float + + Create a new *Matrix* with the affine transformation given by *xx, yx, xy, + yy, x0, y0*. The transformation is given by:: + + x_new = xx * x + xy * y + x0 + y_new = yx * x + yy * y + y0 + + To create a new identity matrix:: + + matrix = cairo.Matrix() + + To create a matrix with a transformation which translates by tx and ty in the X and Y dimensions, respectively:: + + matrix = cairo.Matrix(x0=tx, y0=ty) + + To create a matrix with a transformation that scales by sx and sy in the X and Y dimensions, respectively:: + + matrix = cairo.Matrix(xx=sy, yy=sy) + + + .. classmethod:: init_rotate(radians) + + :param radians: angle of rotation, in radians. The direction of rotation + is defined such that positive angles rotate in the direction from the + positive X axis toward the positive Y axis. With the default axis + orientation of cairo, positive angles rotate in a clockwise direction. + :type radians: float + :returns: a new *Matrix* set to a transformation that rotates by *radians*. + + + .. method:: invert() + + :returns: If *Matrix* has an inverse, modifies *Matrix* to be the + inverse matrix and returns *None* + :raises: :exc:`cairo.Error` if the *Matrix* as no inverse + + Changes *Matrix* to be the inverse of it's original value. Not all + transformation matrices have inverses; if the matrix collapses points + together (it is *degenerate*), then it has no inverse and this function + will fail. + + + .. method:: multiply(matrix2) + + :param matrix2: a second matrix + :type matrix2: cairo.Matrix + :returns: a new *Matrix* + + Multiplies the affine transformations in *Matrix* and *matrix2* + together. The effect of the resulting transformation is to first apply + the transformation in *Matrix* to the coordinates and then apply the + transformation in *matrix2* to the coordinates. + + It is allowable for result to be identical to either *Matrix* or *matrix2*. + + + .. method:: rotate(radians) + + :param radians: angle of rotation, in radians. The direction of rotation + is defined such that positive angles rotate in the direction from the + positive X axis toward the positive Y axis. With the default axis + orientation of cairo, positive angles rotate in a clockwise direction. + :type radians: float + + Initialize *Matrix* to a transformation that rotates by *radians*. + + .. method:: scale(sx, sy) + + :param sx: scale factor in the X direction + :type sx: float + :param sy: scale factor in the Y direction + :type sy: float + + Applies scaling by *sx, sy* to the transformation in *Matrix*. The + effect of the new transformation is to first scale the coordinates by + *sx* and *sy*, then apply the original transformation to the + coordinates. + + .. method:: transform_distance(dx, dy) + + :param dx: X component of a distance vector. + :type dx: float + :param dy: Y component of a distance vector. + :type dy: float + :returns: the transformed distance vector (dx,dy) + :rtype: (float, float) + + Transforms the distance vector *(dx,dy)* by *Matrix*. This is similar to + :meth:`.transform_point` except that the translation components of + the transformation are ignored. The calculation of the returned vector + is as follows:: + + dx2 = dx1 * a + dy1 * c + dy2 = dx1 * b + dy1 * d + + Affine transformations are position invariant, so the same vector always + transforms to the same vector. If *(x1,y1)* transforms to *(x2,y2)* then + *(x1+dx1,y1+dy1)* will transform to *(x1+dx2,y1+dy2)* for all values + of *x1* and *x2*. + + + .. method:: transform_point(x, y) + + :param x: X position. + :type x: float + :param y: Y position. + :type y: float + :returns: the transformed point (x,y) + :rtype: (float, float) + + Transforms the point *(x, y)* by *Matrix*. + + .. method:: translate(tx, ty) + + :param tx: amount to translate in the X direction + :type tx: float + :param ty: amount to translate in the Y direction + :type ty: float + + Applies a transformation by *tx, ty* to the transformation in + *Matrix*. The effect of the new transformation is to first translate the + coordinates by *tx* and *ty*, then apply the original transformation to the + coordinates. diff --git a/doc/reference/paths.rst b/doc/reference/paths.rst new file mode 100644 index 0000000..ebaac59 --- /dev/null +++ b/doc/reference/paths.rst @@ -0,0 +1,23 @@ +.. _paths: + +***** +Paths +***** + +.. currentmodule:: cairo + +class Path() +============ + +.. class:: Path() + + *Path* cannot be instantiated directly, it is created by calling + :meth:`Context.copy_path` and :meth:`Context.copy_path_flat`. + + str(path) lists the path elements. + + See :ref:`PATH attributes <constants_PATH>` + + Path is an iterator. + + See examples/warpedtext.py for example usage. diff --git a/doc/reference/patterns.rst b/doc/reference/patterns.rst new file mode 100644 index 0000000..9fab1d2 --- /dev/null +++ b/doc/reference/patterns.rst @@ -0,0 +1,286 @@ +.. _patterns: + +******** +Patterns +******** + +.. currentmodule:: cairo + + +Patterns are the paint with which cairo draws. The primary use of patterns is +as the source for all cairo drawing operations, although they can also be used +as masks, that is, as the brush too. + +A cairo *Pattern* is created by using one of the *PatternType* constructors +listed below, or implicitly through *Context.set_source_<type>()* methods. + + +class Pattern() +=============== + +*Pattern* is the abstract base class from which all the other pattern classes +derive. It cannot be instantiated directly. + +.. class:: Pattern() + + .. method:: get_extend() + + :returns: the current extend strategy used for drawing the *Pattern*. + :rtype: int + + Gets the current extend mode for the *Pattern*. See + :ref:`EXTEND attributes <constants_EXTEND>` + for details on the semantics of each extend strategy. + + .. method:: get_matrix() + + :returns: a new :class:`Matrix` which stores a copy of the *Pattern's* transformation matrix + + .. method:: set_extend(extend) + + :param extend: an :ref:`EXTEND <constants_EXTEND>` describing how the + area outside of the *Pattern* will be drawn + + Sets the mode to be used for drawing outside the area of a *Pattern*. + + The default extend mode is :data:`cairo.EXTEND_NONE` for + :class:`SurfacePattern` and :data:`cairo.EXTEND_PAD` for + :class:`Gradient` Patterns. + + .. method:: set_matrix(matrix) + + :param matrix: a :class:`Matrix` + + Sets the *Pattern's* transformation matrix to *matrix*. This matrix is a + transformation from user space to pattern space. + + When a *Pattern* is first created it always has the identity matrix for + its transformation matrix, which means that pattern space is initially + identical to user space. + + Important: Please note that the direction of this transformation matrix + is from user space to pattern space. This means that if you imagine the + flow from a *Pattern* to user space (and on to device space), then + coordinates in that flow will be transformed by the inverse of the + *Pattern* matrix. + + For example, if you want to make a *Pattern* appear twice as large as it + does by default the correct code to use is:: + + matrix = cairo.Matrix(xx=0.5,yy=0.5) + pattern.set_matrix(matrix) + + Meanwhile, using values of 2.0 rather than 0.5 in the code above would + cause the *Pattern* to appear at half of its default size. + + Also, please note the discussion of the user-space locking semantics of + :class:`Context.set_source`. + + +class SolidPattern(:class:`Pattern`) +==================================== + +.. class:: SolidPattern(red, green, blue, alpha=1.0) + + :param red: red component of the color + :type red: float + :param green: green component of the color + :type green: float + :param blue: blue component of the color + :type blue: float + :param alpha: alpha component of the color + :type alpha: float + :returns: a new *SolidPattern* + :raises: *MemoryError* in case of no memory + + Creates a new *SolidPattern* corresponding to a translucent color. The + color components are floating point numbers in the range 0 to 1. If the + values passed in are outside that range, they will be clamped. + + + .. method:: get_rgba() + + :returns: (red, green, blue, alpha) a tuple of float + + Gets the solid color for a *SolidPattern*. + + .. versionadded:: 1.4 + + +class SurfacePattern(:class:`Pattern`) +====================================== + +.. class:: SurfacePattern(surface) + + :param surface: a cairo :class:`Surface` + :returns: a newly created *SurfacePattern* for the given surface. + :raises: *MemoryError* in case of no memory. + + .. method:: get_filter() + + :returns: the current :ref:`FILTER <constants_filter>` used for + resizing the *SurfacePattern*. + + .. method:: get_surface() + + :returns: the :class:`Surface` of the *SurfacePattern*. + + .. versionadded:: 1.4 + + .. method:: set_filter(filter) + + :param filter: a :ref:`FILTER <constants_filter>` describing the filter + to use for resizing the *Pattern* + + Note that you might want to control filtering even when you do not have + an explicit *Pattern* object, (for example when using + :meth:`Context.set_source_surface`). In these cases, it is convenient to use + :meth:`Context.get_source` to get access to the pattern that cairo creates + implicitly. For example:: + + context.set_source_surface(image, x, y) + surfacepattern.set_filter(context.get_source(), cairo.FILTER_NEAREST) + + +class Gradient(:class:`Pattern`) +================================ + +*Gradient* is an abstract base class from which other *Pattern* classes +derive. It cannot be instantiated directly. + +.. class:: Gradient() + + .. method:: add_color_stop_rgb(offset, red, green, blue) + + :param offset: an offset in the range [0.0 .. 1.0] + :type offset: float + :param red: red component of color + :type red: float + :param green: green component of color + :type green: float + :param blue: blue component of color + :type blue: float + + Adds an opaque color stop to a *Gradient* pattern. The offset specifies + the location along the gradient's control vector. For example, a + *LinearGradient's* control vector is from (x0,y0) to (x1,y1) while a + *RadialGradient's* control vector is from any point on the start circle + to the corresponding point on the end circle. + + The color is specified in the same way as in :meth:`Context.set_source_rgb`. + + If two (or more) stops are specified with identical offset values, they + will be sorted according to the order in which the stops are added, + (stops added earlier will compare less than stops added later). This can + be useful for reliably making sharp color transitions instead of the + typical blend. + + .. method:: add_color_stop_rgba(offset, red, green, blue, alpha) + + :param offset: an offset in the range [0.0 .. 1.0] + :type offset: float + :param red: red component of color + :type red: float + :param green: green component of color + :type green: float + :param blue: blue component of color + :type blue: float + :param alpha: alpha component of color + :type alpha: float + + Adds an opaque color stop to a *Gradient* pattern. The offset specifies + the location along the gradient's control vector. For example, a + *LinearGradient's* control vector is from (x0,y0) to (x1,y1) while a + *RadialGradient's* control vector is from any point on the start circle + to the corresponding point on the end circle. + + The color is specified in the same way as in :meth:`Context.set_source_rgb`. + + If two (or more) stops are specified with identical offset values, they + will be sorted according to the order in which the stops are added, + (stops added earlier will compare less than stops added later). This can + be useful for reliably making sharp color transitions instead of the + typical blend. + + +class LinearGradient(:class:`Gradient`) +======================================= +.. class:: LinearGradient(x0, y0, x1, y1) + + :param x0: x coordinate of the start point + :type x0: float + :param y0: y coordinate of the start point + :type y0: float + :param x1: x coordinate of the end point + :type x1: float + :param y1: y coordinate of the end point + :type y1: float + :returns: a new *LinearGradient* + :raises: *MemoryError* in case of no memory + + Create a new *LinearGradient* along the line defined by (x0, y0) and (x1, + y1). Before using the *Gradient* pattern, a number of color stops should + be defined using :meth:`Gradient.add_color_stop_rgb` or + :meth:`Gradient.add_color_stop_rgba` + + Note: The coordinates here are in pattern space. For a new *Pattern*, + pattern space is identical to user space, but the relationship between the + spaces can be changed with :meth:`Pattern.set_matrix` + + .. method:: get_linear_points() + + :returns: (x0, y0, x1, y1) - a tuple of float + + * x0: return value for the x coordinate of the first point + * y0: return value for the y coordinate of the first point + * x1: return value for the x coordinate of the second point + * y1: return value for the y coordinate of the second point + + Gets the gradient endpoints for a *LinearGradient*. + + .. versionadded:: 1.4 + + +class RadialGradient(:class:`Gradient`) +======================================= +.. class:: RadialGradient(cx0, cy0, radius0, cx1, cy1, radius1) + + :param cx0: x coordinate for the center of the start circle + :type cx0: float + :param cy0: y coordinate for the center of the start circle + :type cy0: float + :param radius0: radius of the start circle + :type radius0: float + :param cx1: x coordinate for the center of the end circle + :type cx1: float + :param cy1: y coordinate for the center of the end circle + :type cy1: float + :param radius1: radius of the end circle + :type radius1: float + :returns: the newly created *RadialGradient* + :raises: *MemoryError* in case of no memory + + Creates a new *RadialGradient* pattern between the two circles defined by + (cx0, cy0, radius0) and (cx1, cy1, radius1). Before using the gradient + pattern, a number of color stops should be defined using + :meth:`Gradient.add_color_stop_rgb` or :meth:`Gradient.add_color_stop_rgba`. + + Note: The coordinates here are in pattern space. For a new pattern, pattern + space is identical to user space, but the relationship between the spaces + can be changed with :meth:`Pattern.set_matrix`. + + .. method:: get_radial_circles() + + :returns: (x0, y0, r0, x1, y1, r1) - a tuple of float + + * x0: return value for the x coordinate of the center of the first circle + * y0: return value for the y coordinate of the center of the first circle + * r0: return value for the radius of the first circle + * x1: return value for the x coordinate of the center of the second circle + * y1: return value for the y coordinate of the center of the second circle + * r1: return value for the radius of the second circle + + Gets the *Gradient* endpoint circles for a *RadialGradient*, each + specified as a center coordinate and a radius. + + .. versionadded:: 1.4 diff --git a/doc/reference/surfaces.rst b/doc/reference/surfaces.rst new file mode 100644 index 0000000..aea848c --- /dev/null +++ b/doc/reference/surfaces.rst @@ -0,0 +1,659 @@ +.. _surfaces: + +******** +Surfaces +******** + +.. currentmodule:: cairo + +.. comment block + example reST: + (add back '..' where required at column 0) + . class:: module.C[(signature)] + .. classmethod:: name(signature) + .. staticmethod:: name(signature) + .. method:: method(signature) + + :param p1: xxx + :type p1: int + :param p2: xxx + :type p2: str + :returns: xxx + :rtype: list of strings + :raises: xxx + + .. versionadded:: 1.6 + links: + :data:`cairo.ANTIALIAS_SUBPIXEL` + :class:`Context` + :exc:`cairo.Error` + :meth:`.copy_page` + :meth:`Context.copy_page` + :ref:`LINE_CAP <constants_LINE_CAP>` + + ``ctx.rel_move_to(dx, dy)`` # code snippet + + +cairo.Surface is the abstract type representing all different drawing targets +that cairo can render to. The actual drawings are performed using a +:class:`Context`. + +A cairo.Surface is created by using backend-specific constructors +of the form cairo.<XXX>Surface(). + +class Surface() +=============== + +.. class:: Surface() + + *Surface* is the abstract base class from which all the other surface + classes derive. It cannot be instantiated directly. + + .. method:: copy_page() + + Emits the current page for backends that support multiple pages, but + doesn't clear it, so that the contents of the current page will be + retained for the next page. Use :meth:`.show_page` if you want to get an + empty page after the emission. + + :meth:`Context.copy_page` is a convenience function for this. + + .. versionadded:: 1.6 + + .. method:: create_similar(content, width, height) + + :param content: the :ref:`CONTENT <constants_CONTENT>` for the new + surface + :param width: width of the new surface, (in device-space units) + :type width: int + :param height: height of the new surface (in device-space units) + :type width: int + + :returns: a newly allocated *Surface*. + + Create a *Surface* that is as compatible as possible with the existing + surface. For example the new surface will have the same fallback + resolution and :class:`FontOptions`. Generally, the new surface will + also use the same backend, unless that is not possible for some + reason. + + Initially the surface contents are all 0 (transparent if contents have + transparency, black otherwise.) + + .. method:: finish() + + This method finishes the *Surface* and drops all references to external + resources. For example, for the Xlib backend it means that cairo will no + longer access the drawable, which can be freed. After calling finish() + the only valid operations on a *Surface* are flushing and finishing it. + Further drawing to the surface will not affect the surface but will + instead trigger a :exc:`cairo.Error` exception. + + .. method:: flush() + + Do any pending drawing for the *Surface* and also restore any temporary + modification's cairo has made to the *Surface's* state. This method + must be called before switching from drawing on the *Surface* with cairo + to drawing on it directly with native APIs. If the *Surface* doesn't + support direct access, then this function does nothing. + + .. method:: get_content() + + :returns: The :ref:`CONTENT <constants_CONTENT>` type of *Surface*, + which indicates whether the *Surface* contains color and/or alpha + information. + + .. versionadded:: 1.2 + + .. method:: get_device_offset() + + :returns: (x_offset, y_offset) a tuple of float + + * x_offset: the offset in the X direction, in device units + * y_offset: the offset in the Y direction, in device units + + This method returns the previous device offset set by + :meth:`.set_device_offset`. + + .. versionadded:: 1.2 + + .. method:: get_fallback_resolution() + + :returns: (x_pixels_per_inch, y_pixels_per_inch) a tuple of float + + * x_pixels_per_inch: horizontal pixels per inch + * y_pixels_per_inch: vertical pixels per inch + + This method returns the previous fallback resolution set by + :meth:`.set_fallback_resolution`, or default fallback resolution if + never set. + + .. versionadded:: 1.8 + + .. method:: get_font_options() + + :returns: a :class:`FontOptions` + + Retrieves the default font rendering options for the *Surface*. This + allows display surfaces to report the correct subpixel order for + rendering on them, print surfaces to disable hinting of metrics and so + forth. The result can then be used with :class:`ScaledFont`. + + .. method:: mark_dirty() + + Tells cairo that drawing has been done to *Surface* using means other + than cairo, and that cairo should reread any cached areas. Note that you + must call :meth:`.flush` before doing such drawing. + + .. method:: mark_dirty_rectangle(x, y, width, height) + + :param x: X coordinate of dirty rectangle + :type x: int + :param y: Y coordinate of dirty rectangle + :type y: int + :param width: width of dirty rectangle + :type width: int + :param height: height of dirty rectangle + :type height: int + + Like :meth:`.mark_dirty`, but drawing has been done only to the + specified rectangle, so that cairo can retain cached contents for other + parts of the surface. + + Any cached clip set on the *Surface* will be reset by this function, to + make sure that future cairo calls have the clip set that they expect. + + .. method:: set_device_offset(x_offset, y_offset) + + :param x_offset: the offset in the X direction, in device units + :type x_offset: float + :param y_offset: the offset in the Y direction, in device units + :type y_offset: float + + Sets an offset that is added to the device coordinates determined by the + CTM when drawing to *Surface*. One use case for this function is when we + want to create a *Surface* that redirects drawing for a portion of an + onscreen surface to an offscreen surface in a way that is completely + invisible to the user of the cairo API. Setting a transformation via + :meth:`Context.translate` isn't sufficient to do this, since functions + like :meth:`Context.device_to_user` will expose the hidden offset. + + Note that the offset affects drawing to the surface as well as using the + surface in a source pattern. + + .. method:: set_fallback_resolution(x_pixels_per_inch, y_pixels_per_inch) + + :param x_pixels_per_inch: horizontal setting for pixels per inch + :type x_pixels_per_inch: float + :param y_pixels_per_inch: vertical setting for pixels per inch + :type y_pixels_per_inch: float + + Set the horizontal and vertical resolution for image fallbacks. + + When certain operations aren't supported natively by a backend, cairo + will fallback by rendering operations to an image and then overlaying + that image onto the output. For backends that are natively + vector-oriented, this function can be used to set the resolution used + for these image fallbacks, (larger values will result in more detailed + images, but also larger file sizes). + + Some examples of natively vector-oriented backends are the ps, pdf, and + svg backends. + + For backends that are natively raster-oriented, image fallbacks are + still possible, but they are always performed at the native device + resolution. So this function has no effect on those backends. + + Note: The fallback resolution only takes effect at the time of + completing a page (with :meth:`Context.show_page` or + :meth:`Context.copy_page`) so there is currently no way to have more + than one fallback resolution in effect on a single page. + + The default fallback resoultion is 300 pixels per inch in both + dimensions. + + .. versionadded:: 1.2 + + .. method:: show_page() + + Emits and clears the current page for backends that support multiple + pages. Use :meth:`.copy_page` if you don't want to clear the page. + + There is a convenience function for this that takes a + :meth:`Context.show_page`. + + .. versionadded:: 1.6 + + .. method:: write_to_png(fobj) + + :param fobj: the file to write to + :type fobj: str, file or file-like object + :raises: *MemoryError* if memory could not be allocated for the operation + + *IOError* if an I/O error occurs while attempting to write the file + + Writes the contents of *Surface* to *fobj* as a PNG image. + + +class ImageSurface(:class:`Surface`) +==================================== + +A *cairo.ImageSurface* provides the ability to render to memory buffers either +allocated by cairo or by the calling code. The supported image formats are +those defined in :ref:`FORMAT attributes <constants_FORMAT>`. + +.. class:: ImageSurface(format, width, height) + + :param format: :ref:`FORMAT <constants_FORMAT>` of pixels in the surface to create + :param width: width of the surface, in pixels + :param height: height of the surface, in pixels + :returns: a new *ImageSurface* + :raises: *MemoryError* in case of no memory + + Creates an *ImageSurface* of the specified format and dimensions. Initially + the surface contents are all 0. (Specifically, within each pixel, each + color or alpha channel belonging to format will be 0. The contents of bits + within a pixel, but not belonging to the given format are undefined). + + .. classmethod:: create_for_data(data, format, width, height[, stride]) + + :param data: a writable Python buffer object + :param format: the :ref:`FORMAT <constants_FORMAT>` of pixels in the + buffer + :param width: the width of the image to be stored in the buffer + :param height: the height of the image to be stored in the buffer + :param stride: the number of bytes between the start of rows in the + buffer as allocated. If not given the value from + ``format_stride_for_width(format, width)`` is used. + :returns: a new *ImageSurface* + :raises: *MemoryError* in case of no memory. + + :exc:`cairo.Error` in case of invalid *stride* value. + + Creates an *ImageSurface* for the provided pixel data. The initial + contents of buffer will be used as the initial image contents; you must + explicitly clear the buffer, using, for example, cairo_rectangle() and + cairo_fill() if you want it cleared. + + Note that the *stride* may be larger than width*bytes_per_pixel to + provide proper alignment for each pixel and row. This alignment is + required to allow high-performance rendering within cairo. The correct + way to obtain a legal stride value is to call + :meth:`.format_stride_for_width` with the desired format and maximum + image width value, and use the resulting stride value to allocate the + data and to create the *ImageSurface*. See + :meth:`.format_stride_for_width` for example code. + + .. classmethod:: create_from_png(fobj) + + :param fobj: a filename, file, or file-like object of the PNG to load. + :returns: a new *ImageSurface* initialized the contents to the given + PNG file. + + .. staticmethod:: format_stride_for_width(format, width) + + :param format: a cairo :ref:`FORMAT <constants_FORMAT>` value + :param width: the desired width of an *ImageSurface* to be created. + :returns: the appropriate stride to use given the desired format and + width, or -1 if either the format is invalid or the width too large. + :rtype: int + + This method provides a stride value that will respect all alignment + requirements of the accelerated image-rendering code within + cairo. Typical usage will be of the form:: + + stride = cairo.ImageSurface.format_stride_for_width (format, width) + surface = cairo.ImageSurface.create_for_data (data, format, width, height, stride) + + .. versionadded:: 1.6 + + .. method:: get_data() + + :returns: a Python buffer object for the data of the *ImageSurface*, for direct inspection or modification. + + .. versionadded:: 1.2 + + .. method:: get_format() + + :returns: the :ref:`FORMAT <constants_FORMAT>` of the *ImageSurface*. + + .. versionadded:: 1.2 + + .. method:: get_height() + + :returns: the height of the *ImageSurface* in pixels. + + .. method:: get_stride() + + :returns: the stride of the *ImageSurface* in bytes. The stride is the distance in bytes from the beginning of one row of the image data to the beginning of the next row. + + .. method:: get_width() + + :returns: the width of the *ImageSurface* in pixels. + + +class PDFSurface(:class:`Surface`) +================================== + +The PDFSurface is used to render cairo graphics to Adobe PDF files and is a +multi-page vector surface backend. + +.. class:: PDFSurface(fobj, width_in_points, height_in_points) + + :param fobj: a filename or writable file object + :type fobj: str, file or file-like object + :param width_in_points: width of the surface, in points + (1 point == 1/72.0 inch) + :type width_in_points: float + :param height_in_points: height of the surface, in points + (1 point == 1/72.0 inch) + :type height_in_points: float + :returns: a new *PDFSurface* of the specified size in points to be written + to *fobj*. + :raises: *MemoryError* in case of no memory + + .. versionadded:: 1.2 + + .. method:: set_size() + + :param width_in_points: new surface width, in points + (1 point == 1/72.0 inch) + :type width_in_points: float + :param height_in_points: new surface height, in points + (1 point == 1/72.0 inch) + :type height_in_points: float + + Changes the size of a *PDFSurface* for the current (and subsequent) pages. + + This function should only be called before any drawing operations have + been performed on the current page. The simplest way to do this is to + call this function immediately after creating the surface or immediately + after completing a page with either :meth:`Context.show_page` or + :meth:`Context.copy_page`. + + .. versionadded:: 1.2 + + +class PSSurface(:class:`Surface`) +================================= + +The *PSSurface* is used to render cairo graphics to Adobe PostScript files and +is a multi-page vector surface backend. + +.. class:: PSSurface(fobj, width_in_points, height_in_points) + + :param fobj: a filename or writable file object + :type fobj: str, file or file-like object + :param width_in_points: width of the surface, in points + (1 point == 1/72.0 inch) + :type width_in_points: float + :param height_in_points: height of the surface, in points + (1 point == 1/72.0 inch) + :type height_in_points: float + :returns: a new *PDFSurface* of the specified size in points to be written + to *fobj*. + :raises: *MemoryError* in case of no memory + + Note that the size of individual pages of the PostScript output can + vary. See :meth:`.set_size`. + + .. method:: dsc_begin_page_setup() + + This method indicates that subsequent calls to + :meth:`.dsc_comment` should direct comments to the PageSetup + section of the PostScript output. + + This method call is only needed for the first page of a surface. It + should be called after any call to :meth:`.dsc_begin_setup` and + before any drawing is performed to the surface. + + See :meth:`.dsc_comment` for more details. + + .. versionadded:: 1.2 + + .. method:: dsc_begin_setup() + + This function indicates that subsequent calls to :meth:`.dsc_comment` + should direct comments to the Setup section of the PostScript output. + + This function should be called at most once per surface, and must be + called before any call to :meth:`.dsc_begin_page_setup` and before any + drawing is performed to the surface. + + See :meth:`.dsc_comment` for more details. + + .. versionadded:: 1.2 + + .. method:: dsc_comment(comment) + + :param comment: a comment string to be emitted into the PostScript output + :type comment: str + + Emit a comment into the PostScript output for the given surface. + + The comment is expected to conform to the PostScript Language + Document Structuring Conventions (DSC). Please see that manual for + details on the available comments and their meanings. In + particular, the %%IncludeFeature comment allows a + device-independent means of controlling printer device features. So + the PostScript Printer Description Files Specification will also be + a useful reference. + + The comment string must begin with a percent character (%) and the + total length of the string (including any initial percent + characters) must not exceed 255 characters. Violating either of + these conditions will place *PSSurface* into an error state. But + beyond these two conditions, this function will not enforce + conformance of the comment with any particular specification. + + The comment string should not have a trailing newline. + + The DSC specifies different sections in which particular comments + can appear. This function provides for comments to be emitted + within three sections: the header, the Setup section, and the + PageSetup section. Comments appearing in the first two sections + apply to the entire document while comments in the BeginPageSetup + section apply only to a single page. + + For comments to appear in the header section, this function should + be called after the surface is created, but before a call to + :meth:`.dsc_begin_setup`. + + For comments to appear in the Setup section, this function should be + called after a call to :meth:`.dsc_begin_setup` but before a call to + :meth:`.dsc_begin_page_setup`. + + For comments to appear in the PageSetup section, this function should be + called after a call to :meth:`.dsc_begin_page_setup`. + + Note that it is only necessary to call :meth:`.dsc_begin_page_setup` for + the first page of any surface. After a call to :meth:`Context.show_page` + or :meth:`Context.copy_page` comments are unambiguously directed to the + PageSetup section of the current page. But it doesn't hurt to call this + function at the beginning of every page as that consistency may make the + calling code simpler. + + As a final note, cairo automatically generates several comments on + its own. As such, applications must not manually generate any of + the following comments: + + Header section: %!PS-Adobe-3.0, %Creator, %CreationDate, %Pages, + %BoundingBox, %DocumentData, %LanguageLevel, %EndComments. + + Setup section: %BeginSetup, %EndSetup + + PageSetup section: %BeginPageSetup, %PageBoundingBox, + %EndPageSetup. + + Other sections: %BeginProlog, %EndProlog, %Page, %Trailer, %EOF + + Here is an example sequence showing how this function might be used:: + + surface = PSSurface (filename, width, height) + ... + surface.dsc_comment (surface, "%%Title: My excellent document") + surface.dsc_comment (surface, "%%Copyright: Copyright (C) 2006 Cairo Lover") + ... + surface.dsc_begin_setup (surface) + surface.dsc_comment (surface, "%%IncludeFeature: *MediaColor White") + ... + surface.dsc_begin_page_setup (surface) + surface.dsc_comment (surface, "%%IncludeFeature: *PageSize A3") + surface.dsc_comment (surface, "%%IncludeFeature: *InputSlot LargeCapacity") + surface.dsc_comment (surface, "%%IncludeFeature: *MediaType Glossy") + surface.dsc_comment (surface, "%%IncludeFeature: *MediaColor Blue") + ... draw to first page here .. + ctx.show_page (cr) + ... + surface.dsc_comment (surface, "%%IncludeFeature: PageSize A5"); + ... + + .. versionadded:: 1.2 + + .. method:: get_eps() + + :returns: True iff the *PSSurface* will output Encapsulated PostScript. + + .. versionadded:: 1.6 + + .. staticmethod:: ps_level_to_string(level) + + :param level: a :ref:`PS_LEVEL <constants_PS_LEVEL>` + :returns: the string associated to given level. + :rtype: str + :raises: :exc:`cairo.Error` if *level* isn't valid. + + Get the string representation of the given *level*. See + :meth:`.ps_get_levels` for a way to get the list of valid level + ids. + + .. versionadded:: 1.6 + + .. method:: restrict_to_level(level) + + :param level: a :ref:`PS_LEVEL <constants_PS_LEVEL>` + + Restricts the generated PostSript file to *level*. See + :meth:`.ps_get_levels` for a list of available level values that + can be used here. + + This function should only be called before any drawing operations have + been performed on the given surface. The simplest way to do this is to + call this function immediately after creating the surface. + + .. versionadded:: 1.6 + + .. method:: set_eps(eps) + + :param eps: True to output EPS format PostScript + :type eps: bool + + If *eps* is True, the PostScript surface will output Encapsulated + PostScript. + + This function should only be called before any drawing operations have + been performed on the current page. The simplest way to do this is to + call this function immediately after creating the surface. An + Encapsulated PostScript file should never contain more than one page. + + .. versionadded:: 1.6 + + .. method:: set_size(width_in_points, height_in_points) + + :param width_in_points: new surface width, in points (1 point == 1/72.0 inch) + :param height_in_points: new surface height, in points (1 point == 1/72.0 inch) + :type width_in_points: float + :type height_in_points: float + + Changes the size of a PostScript surface for the current (and + subsequent) pages. + + This function should only be called before any drawing operations + have been performed on the current page. The simplest way to do + this is to call this function immediately after creating the + surface or immediately after completing a page with either + :meth:`Context.show_page` or :meth:`Context.copy_page`. + + .. versionadded:: 1.2 + + +class SVGSurface(:class:`Surface`) +================================== + +The *SVGSurface* is used to render cairo graphics to SVG files and is a +multi-page vector surface backend + +.. class:: SVGSurface(fobj, width_in_points, height_in_points) + + :param fobj: a filename or writable file object + :type fobj: str, file or file-like object + :param width_in_points: width of the surface, in points (1 point == 1/72.0 inch) + :type width_in_points: float + :param height_in_points: height of the surface, in points (1 point == 1/72.0 inch) + :type height_in_points: float + :returns: a new *SVGSurface* of the specified size in points to be written to *fobj*. + :raises: *MemoryError* in case of no memory + + + .. method:: get_versions + + Not implemented in pycairo (yet) + + .. method:: restrict_to_version + + Not implemented in pycairo (yet) + + .. method:: version_to_string + + Not implemented in pycairo (yet) + + +class Win32Surface(:class:`Surface`) +==================================== + +The Microsoft Windows surface is used to render cairo graphics to Microsoft +Windows windows, bitmaps, and printing device contexts. + +.. class:: Win32Surface(hdc) + + :param hdc: the DC to create a surface for + :type hdc: int + :returns: the newly created surface + + Creates a cairo surface that targets the given DC. The DC will be queried + for its initial clip extents, and this will be used as the size of the + cairo surface. The resulting surface will always be of format + cairo.FORMAT_RGB24, see :ref:`FORMAT attributes <constants_FORMAT>`. + + +class XlibSurface(:class:`Surface`) +=================================== + +The XLib surface is used to render cairo graphics to X Window System windows +and pixmaps using the XLib library. + +Note that the XLib surface automatically takes advantage of X render extension +if it is available. + +.. class:: XlibSurface + + *XlibSurface* cannot be instantiated directly. But an XlibSurface instance + can be returned from a function call when using pygtk. + + .. method:: get_depth() + + :returns: the number of bits used to represent each pixel value. + + .. versionadded:: 1.2 + + .. method:: get_height() + + :returns: the height of the X Drawable underlying the surface in pixels. + + .. versionadded:: 1.2 + + .. method:: get_width() + + :returns: the width of the X Drawable underlying the surface in pixels. + + .. versionadded:: 1.2 diff --git a/doc/reference/text.rst b/doc/reference/text.rst new file mode 100644 index 0000000..58a0e7d --- /dev/null +++ b/doc/reference/text.rst @@ -0,0 +1,255 @@ +.. _text: + +**** +Text +**** + +.. currentmodule:: cairo + +Cairo has two sets of text rendering capabilities: + +* The functions with text in their name form cairo's toy text API. The toy API + takes UTF-8 encoded text and is limited in its functionality to rendering + simple left-to-right text with no advanced features. That means for example + that most complex scripts like Hebrew, Arabic, and Indic scripts are out of + question. No kerning or correct positioning of diacritical marks either. The + font selection is pretty limited too and doesn't handle the case that the + selected font does not cover the characters in the text. This set of + functions are really that, a toy text API, for testing and demonstration + purposes. Any serious application should avoid them. + +* The functions with glyphs in their name form cairo's low-level text API. The + low-level API relies on the user to convert text to a set of glyph indexes + and positions. This is a very hard problem and is best handled by external + libraries, like the pangocairo that is part of the Pango text layout and + rendering library. Pango is available from http://www.pango.org/. + + + +class FontFace() +================ + +A *cairo.FontFace* specifies all aspects of a font other than the size or font +matrix (a font matrix is used to distort a font by sheering it or scaling it +unequally in the two directions). A *FontFace* can be set on a +:class:`Context` by using :meth:`Context.set_font_face` the size and font +matrix are set with :meth:`Context.set_font_size` and +:meth:`Context.set_font_matrix`. + +There are various types of *FontFace*, depending on the font backend they +use. + +.. class:: FontFace() + + .. note:: This class cannot be instantiated directly, it is returned by + :meth:`Context.get_font_face`. + + + +class ToyFontFace(:class:`FontFace`) +==================================== + +The *cairo.ToyFontFace* class can be used instead of :meth:`Context.select_font_face` to create a toy font independently of a context. + +.. class:: ToyFontFace(family[, slant[, weight]]) + + :param family: a font family name + :type family: str or unicode + :param slant: the :ref:`FONT_SLANT <constants_FONT_SLANT>` of the font, + defaults to :data:`cairo.FONT_SLANT_NORMAL`. + :param weight: the :ref:`FONT_WEIGHT <constants_FONT_WEIGHT>` of the font, + defaults to :data:`cairo.FONT_WEIGHT_NORMAL`. + :returns: a new *ToyFontFace* + + Creates a *ToyFontFace* from a triplet of family, slant, and weight. These + font faces are used in implementation of the the "toy" font API. + + If family is the zero-length string "", the platform-specific default + family is assumed. The default family then can be queried using + :meth:`.get_family`. + + The :meth:`Context.select_font_face` method uses this to create font + faces. See that function for limitations of toy font faces. + + .. versionadded:: 1.8.4 + + .. method:: get_family() + + :returns: the family name of a toy font + :rtype: str + + .. versionadded:: 1.8.4 + + .. method:: get_slant() + + :returns: the :ref:`FONT_SLANT <constants_FONT_SLANT>` value + + .. versionadded:: 1.8.4 + + .. method:: get_weight() + + :returns: the :ref:`FONT_WEIGHT <constants_FONT_WEIGHT>` value + + .. versionadded:: 1.8.4 + + +class ScaledFont() +================== + +A *ScaledFont* is a font scaled to a particular size and device resolution. A +*ScaledFont* is most useful for low-level font usage where a library or +application wants to cache a reference to a scaled font to speed up the +computation of metrics. + +There are various types of scaled fonts, depending on the font backend they +use. + +.. class:: ScaledFont(font_face, font_matrix, ctm, options) + + :param font_face: a :class:`FontFace` instance + :param font_matrix: font space to user space transformation :class:`Matrix` + for the font. In the simplest case of a N point font, this matrix is just + a scale by N, but it can also be used to shear the font or stretch it + unequally along the two axes. See :meth:`Context.set_font_matrix`. + :param ctm: user to device transformation :class:`Matrix` with which the + font will be used. + :param options: a :class:`FontOptions` instance to use when getting metrics + for the font and rendering with it. + + Creates a *ScaledFont* object from a *FontFace* and matrices that describe + the size of the font and the environment in which it will be used. + + .. method:: extents() + + :returns: (ascent, descent, height, max_x_advance, max_y_advance), a tuple of float values. + + Gets the metrics for a *ScaledFont*. + + .. method:: get_ctm() + + Not implemented in pycairo (yet) + + .. method:: get_font_face() + + :returns: the :class:`FontFace` that this *ScaledFont* was created for. + + .. versionadded:: 1.2 + + .. method:: get_font_matrix() + + Not implemented in pycairo (yet) + + .. method:: get_font_options() + + Not implemented in pycairo (yet) + + .. method:: get_scale_matrix() + + :returns: the scale :class:`Matrix` + + The scale matrix is product of the font matrix and the ctm associated + with the scaled font, and hence is the matrix mapping from font space to + device space. + + .. versionadded:: 1.8 + + + .. method:: glyph_extents() + + Not implemented in pycairo (yet) + + + .. method:: text_extents(text) + + :param text: text + :type text: str or unicode + :returns: (x_bearing, y_bearing, width, height, x_advance, y_advance) + :rtype: 6-tuple of float + + Gets the extents for a string of text. The extents describe a user-space + rectangle that encloses the "inked" portion of the text drawn at the + origin (0,0) (as it would be drawn by :meth:`Context.show_text` if the + cairo graphics state were set to the same font_face, font_matrix, ctm, + and font_options as *ScaledFont*). Additionally, the x_advance and + y_advance values indicate the amount by which the current point would be + advanced by :meth:`Context.show_text`. + + Note that whitespace characters do not directly contribute to the size + of the rectangle (width and height). They do contribute indirectly by + changing the position of non-whitespace characters. In particular, + trailing whitespace characters are likely to not affect the size of the + rectangle, though they will affect the x_advance and y_advance values. + + .. versionadded:: 1.2 + + .. method:: text_to_glyphs() + + Not implemented in pycairo (yet) + + + +class FontOptions() +=================== + +An opaque structure holding all options that are used when rendering fonts. + +Individual features of a *FontOptions* can be set or accessed using functions +named *FontOptions.set_<feature_name>* and +*FontOptions.get_<feature_name>*, like :meth:`FontOptions.set_antialias` +and :meth:`FontOptions.get_antialias`. + +New features may be added to a *FontOptions* in the future. For this reason, +:meth:`FontOptions.copy()`, :meth:`FontOptions.equal()`, +:meth:`FontOptions.merge()`, and :meth:`FontOptions.hash()` should be used to +copy, check for equality, merge, or compute a hash value of FontOptions +objects. + +.. class:: FontOptions() + + :returns: a newly allocated *FontOptions*. + + Allocates a new *FontOptions* object with all options initialized to default values. + + .. method:: get_antialias() + + :returns: the :ref:`ANTIALIAS <constants_ANTIALIAS>` mode for the *FontOptions* object + + .. method:: get_hint_metrics() + + :returns: the :ref:`HINT METRICS <constants_HINT_METRICS>` mode for the *FontOptions* object + + .. method:: get_hint_style() + + :returns: the :ref:`HINT STYLE <constants_HINT_STYLE>` for the *FontOptions* object + + .. method:: get_subpixel_order() + + :returns: the :ref:`SUBPIXEL_ORDER <constants_SUBPIXEL_ORDER>` for the *FontOptions* object + + .. method:: set_antialias(antialias) + + :param antialias: the :ref:`ANTIALIAS <constants_ANTIALIAS>` mode + + This specifies the type of antialiasing to do when rendering text. + + .. method:: set_hint_metrics(hint_metrics) + + :param hint_metrics: the :ref:`HINT METRICS <constants_HINT_METRICS>` mode + + This controls whether metrics are quantized to integer values in device + units. + + .. method:: set_hint_style(hint_style) + + :param hint_style: the :ref:`HINT STYLE <constants_HINT_STYLE>` + + This controls whether to fit font outlines to the pixel grid, and if so, + whether to optimize for fidelity or contrast. + + .. method:: set_subpixel_order(subpixel_order) + + :param subpixel_order: the :ref:`SUBPIXEL_ORDER <constants_SUBPIXEL_ORDER>` + + The subpixel order specifies the order of color elements within each + pixel on the display device when rendering with an antialiasing mode of + :data:`cairo.ANTIALIAS_SUBPIXEL`. diff --git a/examples/.gitignore b/examples/.gitignore new file mode 100644 index 0000000..f54b062 --- /dev/null +++ b/examples/.gitignore @@ -0,0 +1,7 @@ +Makefile +Makefile.in +*.pdf +*.pyc +*.pyo +*.png +*.ps diff --git a/examples/Makefile.am b/examples/Makefile.am new file mode 100644 index 0000000..a15a963 --- /dev/null +++ b/examples/Makefile.am @@ -0,0 +1,40 @@ +EXTRA_DIST = \ + gradient.py \ + hering.py \ + spiral.py \ + warpedtext.py \ + cairo_snippets/snippets_gtk.py \ + cairo_snippets/snippets_pdf.py \ + cairo_snippets/snippets_png.py \ + cairo_snippets/snippets_ps.py \ + cairo_snippets/snippets_svg.py \ + cairo_snippets/data/romedalen.png \ + cairo_snippets/snippets/arc_negative.py \ + cairo_snippets/snippets/arc.py \ + cairo_snippets/snippets/clip_image.py \ + cairo_snippets/snippets/clip.py \ + cairo_snippets/snippets/curve_rectangle.py \ + cairo_snippets/snippets/curve_to.py \ + cairo_snippets/snippets/ellipse.py \ + cairo_snippets/snippets/fill_and_stroke2.py \ + cairo_snippets/snippets/fill_and_stroke.py \ + cairo_snippets/snippets/glyph_path.py \ + cairo_snippets/snippets/gradient.py \ + cairo_snippets/snippets/gradient_mask.py \ + cairo_snippets/snippets/group.py \ + cairo_snippets/snippets/imagepattern.py \ + cairo_snippets/snippets/image.py \ + cairo_snippets/snippets/__init__.py \ + cairo_snippets/snippets/path.py \ + cairo_snippets/snippets/set_line_cap.py \ + cairo_snippets/snippets/set_line_join.py \ + cairo_snippets/snippets/show_glyphs.py \ + cairo_snippets/snippets/text_align_center.py \ + cairo_snippets/snippets/text_extents.py \ + cairo_snippets/snippets/text.py \ + gtk/cairo-demo.py \ + gtk/cairo-knockout.py \ + gtk/hangman.py \ + gtk/lsystem.py \ + gtk/png_view.py \ + gtk/text.py diff --git a/examples/cairo_snippets/c_to_python.py b/examples/cairo_snippets/c_to_python.py new file mode 100755 index 0000000..c01ebe5 --- /dev/null +++ b/examples/cairo_snippets/c_to_python.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python +""" +translate C <snippet>.cairo to Python <snippet>.py + +; -> '' +cairo_ -> cr. +'(cr, ' -> ( but not snippet_normalize (cr, width, height) +(cr) -> () +/* -> #/* +CAIRO_ -> cairo. +""" + +import sys + + +if len(sys.argv) != 2 or not sys.argv[1].endswith('.cairo'): + raise SystemExit('usage: c_to_python.py <file>.cairo') + +filename_in = sys.argv[1] +filename_out = filename_in.replace('.cairo', '.py') + +file_in = file(filename_in) +file_out = file(filename_out, 'w') + +for line in file_in: + line = line.replace(';', '') # should be ';' and whitespace to EOL only -> \n + if not line.startswith('snippet_'): + line = line.replace('cairo_', 'cr.') + line = line.replace('(cr, ', '(') + line = line.replace('(cr)', '()') + line = line.replace('/*', '#/*') + line = line.replace(' ', '') + line = line.replace('CAIRO_', 'cairo.') + + file_out.write (line) diff --git a/examples/cairo_snippets/snippets/.gitignore b/examples/cairo_snippets/snippets/.gitignore new file mode 100644 index 0000000..6be9629 --- /dev/null +++ b/examples/cairo_snippets/snippets/.gitignore @@ -0,0 +1,5 @@ +*.pdf +*.png +*.ps +*.pyc +*.svg diff --git a/examples/cairo_snippets/snippets/__init__.py b/examples/cairo_snippets/snippets/__init__.py new file mode 100755 index 0000000..70b4813 --- /dev/null +++ b/examples/cairo_snippets/snippets/__init__.py @@ -0,0 +1,12 @@ +# snippet list generation +import os + +# list of snippet files +snip_list = [x[:-3] for x in os.listdir (os.path.dirname (__file__)) + if not x.startswith('_') and x.endswith('.py')] +snip_list.sort() + +# function used by some or all snippets +def snippet_normalize (ctx, width, height): + ctx.scale (width, height) + ctx.set_line_width (0.04) diff --git a/examples/cairo_snippets/snippets/arc.py b/examples/cairo_snippets/snippets/arc.py new file mode 100755 index 0000000..b4e6e5d --- /dev/null +++ b/examples/cairo_snippets/snippets/arc.py @@ -0,0 +1,21 @@ +xc = 0.5 +yc = 0.5 +radius = 0.4 +angle1 = 45.0 * (M_PI/180.0) #/* angles are specified */ +angle2 = 180.0 * (M_PI/180.0) #/* in radians */ + +snippet_normalize (cr, width, height) + +cr.arc (xc, yc, radius, angle1, angle2) +cr.stroke () + +#/* draw helping lines */ +cr.set_source_rgba (1,0.2,0.2,0.6) +cr.arc (xc, yc, 0.05, 0, 2*M_PI) +cr.fill () +cr.set_line_width (0.03) +cr.arc (xc, yc, radius, angle1, angle1) +cr.line_to (xc, yc) +cr.arc (xc, yc, radius, angle2, angle2) +cr.line_to (xc, yc) +cr.stroke () diff --git a/examples/cairo_snippets/snippets/arc_negative.py b/examples/cairo_snippets/snippets/arc_negative.py new file mode 100755 index 0000000..ca6a85d --- /dev/null +++ b/examples/cairo_snippets/snippets/arc_negative.py @@ -0,0 +1,22 @@ +xc = 0.5 +yc = 0.5 +radius = 0.4 +angle1 = 45.0 * (M_PI/180.0) #/* angles are specified */ +angle2 = 180.0 * (M_PI/180.0) #/* in radians */ + +snippet_normalize (cr, width, height) + +cr.arc_negative (xc, yc, radius, angle1, angle2) +cr.stroke () + +#/* draw helping lines */ +cr.set_source_rgba (1,0.2,0.2,0.6) +cr.arc (xc, yc, 0.05, 0, 2*M_PI) +cr.fill () +cr.set_line_width (0.03) +cr.arc (xc, yc, radius, angle1, angle1) +cr.line_to (xc, yc) +cr.arc (xc, yc, radius, angle2, angle2) +cr.line_to (xc, yc) +cr.stroke () +#cr.stroke (10) diff --git a/examples/cairo_snippets/snippets/clip.py b/examples/cairo_snippets/snippets/clip.py new file mode 100755 index 0000000..8456235 --- /dev/null +++ b/examples/cairo_snippets/snippets/clip.py @@ -0,0 +1,13 @@ +snippet_normalize (cr, width, height) + +cr.arc (0.5, 0.5, 0.3, 0, 2 * M_PI) +cr.clip () + +cr.rectangle (0, 0, 1, 1) +cr.fill () +cr.set_source_rgb (0, 1, 0) +cr.move_to (0, 0) +cr.line_to (1, 1) +cr.move_to (1, 0) +cr.line_to (0, 1) +cr.stroke () diff --git a/examples/cairo_snippets/snippets/clip_image.py b/examples/cairo_snippets/snippets/clip_image.py new file mode 100755 index 0000000..39a84ab --- /dev/null +++ b/examples/cairo_snippets/snippets/clip_image.py @@ -0,0 +1,13 @@ +snippet_normalize (cr, width, height) + +cr.arc (0.5, 0.5, 0.3, 0, 2*M_PI) +cr.clip () + +image = cairo.ImageSurface.create_from_png ("data/romedalen.png") +w = image.get_width() +h = image.get_height() + +cr.scale (1.0/w, 1.0/h) + +cr.set_source_surface (image, 0, 0) +cr.paint () diff --git a/examples/cairo_snippets/snippets/curve_rectangle.py b/examples/cairo_snippets/snippets/curve_rectangle.py new file mode 100755 index 0000000..3fb3c4a --- /dev/null +++ b/examples/cairo_snippets/snippets/curve_rectangle.py @@ -0,0 +1,53 @@ +#/* a custom shape, that could be wrapped in a function */ +x0 = 0.1 #/*< parameters like cairo_rectangle */ +y0 = 0.1 +rect_width = 0.8 +rect_height = 0.8 +radius = 0.4 #/*< and an approximate curvature radius */ + +snippet_normalize (cr, width, height) + +x1=x0+rect_width +y1=y0+rect_height +#if (!rect_width || !rect_height) +# return +if rect_width/2<radius: + if rect_height/2<radius: + cr.move_to (x0, (y0 + y1)/2) + cr.curve_to (x0 ,y0, x0, y0, (x0 + x1)/2, y0) + cr.curve_to (x1, y0, x1, y0, x1, (y0 + y1)/2) + cr.curve_to (x1, y1, x1, y1, (x1 + x0)/2, y1) + cr.curve_to (x0, y1, x0, y1, x0, (y0 + y1)/2) + else: + cr.move_to (x0, y0 + radius) + cr.curve_to (x0 ,y0, x0, y0, (x0 + x1)/2, y0) + cr.curve_to (x1, y0, x1, y0, x1, y0 + radius) + cr.line_to (x1 , y1 - radius) + cr.curve_to (x1, y1, x1, y1, (x1 + x0)/2, y1) + cr.curve_to (x0, y1, x0, y1, x0, y1- radius) + +else: + if rect_height/2<radius: + cr.move_to (x0, (y0 + y1)/2) + cr.curve_to (x0 , y0, x0 , y0, x0 + radius, y0) + cr.line_to (x1 - radius, y0) + cr.curve_to (x1, y0, x1, y0, x1, (y0 + y1)/2) + cr.curve_to (x1, y1, x1, y1, x1 - radius, y1) + cr.line_to (x0 + radius, y1) + cr.curve_to (x0, y1, x0, y1, x0, (y0 + y1)/2) + else: + cr.move_to (x0, y0 + radius) + cr.curve_to (x0 , y0, x0 , y0, x0 + radius, y0) + cr.line_to (x1 - radius, y0) + cr.curve_to (x1, y0, x1, y0, x1, y0 + radius) + cr.line_to (x1 , y1 - radius) + cr.curve_to (x1, y1, x1, y1, x1 - radius, y1) + cr.line_to (x0 + radius, y1) + cr.curve_to (x0, y1, x0, y1, x0, y1- radius) + +cr.close_path () + +cr.set_source_rgb (0.5,0.5,1) +cr.fill_preserve () +cr.set_source_rgba (0.5,0,0,0.5) +cr.stroke () diff --git a/examples/cairo_snippets/snippets/curve_to.py b/examples/cairo_snippets/snippets/curve_to.py new file mode 100755 index 0000000..59e3b00 --- /dev/null +++ b/examples/cairo_snippets/snippets/curve_to.py @@ -0,0 +1,17 @@ +x, y = 0.1, 0.5 +x1, y1 = 0.4, 0.9 +x2, y2 = 0.6, 0.1 +x3, y3 = 0.9, 0.5 + +snippet_normalize (cr, width, height) + +cr.move_to (x, y) +cr.curve_to (x1, y1, x2, y2, x3, y3) + +cr.stroke () + +cr.set_source_rgba (1,0.2,0.2,0.6) +cr.set_line_width (0.03) +cr.move_to (x,y); cr.line_to (x1,y1) +cr.move_to (x2,y2); cr.line_to (x3,y3) +cr.stroke () diff --git a/examples/cairo_snippets/snippets/ellipse.py b/examples/cairo_snippets/snippets/ellipse.py new file mode 100755 index 0000000..9afd4f2 --- /dev/null +++ b/examples/cairo_snippets/snippets/ellipse.py @@ -0,0 +1,33 @@ +snippet_normalize(cr, width, height) + +def path_ellipse(cr, x, y, width, height, angle=0): + """ + x - center x + y - center y + width - width of ellipse (in x direction when angle=0) + height - height of ellipse (in y direction when angle=0) + angle - angle in radians to rotate, clockwise + """ + cr.save() + cr.translate(x, y) + cr.rotate(angle) + cr.scale(width / 2.0, height / 2.0) + cr.arc(0.0, 0.0, 1.0, 0.0, 2.0 * M_PI) + cr.restore() + + +path_ellipse(cr, 0.5, 0.5, 1.0, 0.3, M_PI/4.0) + +# fill +cr.set_source_rgba(1,0,0,1) +cr.fill_preserve() + +# stroke +# reset identity matrix so line_width is a constant +# width in device-space, not user-space +cr.save() +cr.identity_matrix() +cr.set_source_rgba(0,0,0,1) +cr.set_line_width(3) +cr.stroke() +cr.restore() diff --git a/examples/cairo_snippets/snippets/fill_and_stroke.py b/examples/cairo_snippets/snippets/fill_and_stroke.py new file mode 100755 index 0000000..6d66192 --- /dev/null +++ b/examples/cairo_snippets/snippets/fill_and_stroke.py @@ -0,0 +1,12 @@ +snippet_normalize (cr, width, height) + +cr.move_to (0.5, 0.1) +cr.line_to (0.9, 0.9) +cr.rel_line_to (-0.4, 0.0) +cr.curve_to (0.2, 0.9, 0.2, 0.5, 0.5, 0.5) +cr.close_path() + +cr.set_source_rgb (0, 0, 1) +cr.fill_preserve () +cr.set_source_rgb (0, 0, 0) +cr.stroke () diff --git a/examples/cairo_snippets/snippets/fill_and_stroke2.py b/examples/cairo_snippets/snippets/fill_and_stroke2.py new file mode 100755 index 0000000..c520630 --- /dev/null +++ b/examples/cairo_snippets/snippets/fill_and_stroke2.py @@ -0,0 +1,18 @@ +snippet_normalize (cr, width, height) + +cr.move_to (0.5, 0.1) +cr.line_to (0.9, 0.9) +cr.rel_line_to (-0.4, 0.0) +cr.curve_to (0.2, 0.9, 0.2, 0.5, 0.5, 0.5) +cr.close_path () + +cr.move_to (0.25, 0.1) +cr.rel_line_to (0.2, 0.2) +cr.rel_line_to (-0.2, 0.2) +cr.rel_line_to (-0.2, -0.2) +cr.close_path () + +cr.set_source_rgb (0, 0, 1) +cr.fill_preserve () +cr.set_source_rgb (0, 0, 0) +cr.stroke () diff --git a/examples/cairo_snippets/snippets/glyph_path.py b/examples/cairo_snippets/snippets/glyph_path.py new file mode 100755 index 0000000..2b73193 --- /dev/null +++ b/examples/cairo_snippets/snippets/glyph_path.py @@ -0,0 +1,21 @@ +snippet_normalize (cr, width, height) + +cr.select_font_face ("Sans", cairo.FONT_SLANT_NORMAL, + cairo.FONT_WEIGHT_NORMAL) +# draw 0.16 glyphs in 0.20 squares, at (0.02, 0.04) from left corner +cr.set_font_size (0.16) + +glyphs = [] +index = 20 +for y in range(5): + for x in range(5): + glyphs.append ((index, x/5.0 + 0.02, y/5.0 + 0.16)) + index += 1 + +cr.glyph_path (glyphs) +cr.set_source_rgb (0.5,0.5,1.0) +cr.fill_preserve () +cr.set_source_rgb (0,0,0) +cr.set_line_width (0.005) +cr.stroke () + diff --git a/examples/cairo_snippets/snippets/gradient.py b/examples/cairo_snippets/snippets/gradient.py new file mode 100755 index 0000000..22f0658 --- /dev/null +++ b/examples/cairo_snippets/snippets/gradient.py @@ -0,0 +1,16 @@ +snippet_normalize (cr, width, height) + +pat = cairo.LinearGradient (0.0, 0.0, 0.0, 1.0) +pat.add_color_stop_rgba (1, 0, 0, 0, 1) +pat.add_color_stop_rgba (0, 1, 1, 1, 1) +cr.rectangle (0,0,1,1) +cr.set_source (pat) +cr.fill () + +pat = cairo.RadialGradient (0.45, 0.4, 0.1, + 0.4, 0.4, 0.5) +pat.add_color_stop_rgba (0, 1, 1, 1, 1) +pat.add_color_stop_rgba (1, 0, 0, 0, 1) +cr.set_source (pat) +cr.arc (0.5, 0.5, 0.3, 0, 2 * M_PI) +cr.fill () diff --git a/examples/cairo_snippets/snippets/gradient_mask.py b/examples/cairo_snippets/snippets/gradient_mask.py new file mode 100755 index 0000000..4a0eba4 --- /dev/null +++ b/examples/cairo_snippets/snippets/gradient_mask.py @@ -0,0 +1,12 @@ +snippet_normalize (cr, width, height) + +pattern = cairo.LinearGradient (0, 0, 1, 1) +pattern.add_color_stop_rgb (0, 0, 0.3, 0.8) +pattern.add_color_stop_rgb (1, 0, 0.8, 0.3) + +mask = cairo.RadialGradient (0.5, 0.5, 0.25, 0.5, 0.5, 0.5) +mask.add_color_stop_rgba (0, 0, 0, 0, 1) +mask.add_color_stop_rgba (0.5, 0, 0, 0, 0) + +cr.set_source (pattern) +cr.mask (mask) diff --git a/examples/cairo_snippets/snippets/group.py b/examples/cairo_snippets/snippets/group.py new file mode 100755 index 0000000..a787f4d --- /dev/null +++ b/examples/cairo_snippets/snippets/group.py @@ -0,0 +1,16 @@ +# demo/test for group functions +snippet_normalize (cr, width, height) + +cr.rectangle (0.1, 0.1, 0.6, 0.6) +cr.set_line_width (0.03) +cr.set_source_rgb (0.8, 0.8, 0.8) +cr.fill() + +cr.push_group() +cr.rectangle (0.3, 0.3, 0.6, 0.6) +cr.set_source (cairo.SolidPattern (1, 0, 0)) +cr.fill_preserve() +cr.set_source (cairo.SolidPattern (0, 0, 0)) +cr.stroke () +cr.pop_group_to_source() +cr.paint_with_alpha (0.5) diff --git a/examples/cairo_snippets/snippets/image.py b/examples/cairo_snippets/snippets/image.py new file mode 100755 index 0000000..ccadc4f --- /dev/null +++ b/examples/cairo_snippets/snippets/image.py @@ -0,0 +1,14 @@ +snippet_normalize (cr, width, height) + +image = cairo.ImageSurface.create_from_png ("data/romedalen.png") +w = image.get_width() +h = image.get_height() + +cr.translate (0.5, 0.5) +cr.rotate (45* M_PI/180) +cr.scale (1.0/w, 1.0/h) +cr.translate (-0.5*w, -0.5*h) + +cr.set_source_surface (image, 0, 0) +cr.paint () + diff --git a/examples/cairo_snippets/snippets/imagepattern.py b/examples/cairo_snippets/snippets/imagepattern.py new file mode 100755 index 0000000..5d07c07 --- /dev/null +++ b/examples/cairo_snippets/snippets/imagepattern.py @@ -0,0 +1,23 @@ +import math + +snippet_normalize (cr, width, height) + +image = cairo.ImageSurface.create_from_png ("data/romedalen.png") +w = image.get_width() +h = image.get_height() + +pattern = cairo.SurfacePattern (image) +pattern.set_extend (cairo.EXTEND_REPEAT) + +cr.translate (0.5, 0.5) +cr.rotate (M_PI / 4) +cr.scale (1 / math.sqrt (2), 1 / math.sqrt (2)) +cr.translate (- 0.5, - 0.5) + +matrix = cairo.Matrix(xx=w * 5, yy=h * 5) +pattern.set_matrix (matrix) + +cr.set_source (pattern) + +cr.rectangle (0, 0, 1.0, 1.0) +cr.fill () diff --git a/examples/cairo_snippets/snippets/path.py b/examples/cairo_snippets/snippets/path.py new file mode 100755 index 0000000..cce8aec --- /dev/null +++ b/examples/cairo_snippets/snippets/path.py @@ -0,0 +1,7 @@ +snippet_normalize (cr, width, height) +cr.move_to (0.5, 0.1) +cr.line_to (0.9, 0.9) +cr.rel_line_to (-0.4, 0.0) +cr.curve_to (0.2, 0.9, 0.2, 0.5, 0.5, 0.5) + +cr.stroke () diff --git a/examples/cairo_snippets/snippets/set_line_cap.py b/examples/cairo_snippets/snippets/set_line_cap.py new file mode 100755 index 0000000..6de1fae --- /dev/null +++ b/examples/cairo_snippets/snippets/set_line_cap.py @@ -0,0 +1,19 @@ +snippet_normalize (cr, width, height) +cr.set_line_width (0.12) +cr.set_line_cap (cairo.LINE_CAP_BUTT) #/* default */ +cr.move_to (0.25, 0.2); cr.line_to (0.25, 0.8) +cr.stroke () +cr.set_line_cap (cairo.LINE_CAP_ROUND) +cr.move_to (0.5, 0.2); cr.line_to (0.5, 0.8) +cr.stroke () +cr.set_line_cap (cairo.LINE_CAP_SQUARE) +cr.move_to (0.75, 0.2); cr.line_to (0.75, 0.8) +cr.stroke () + +#/* draw helping lines */ +cr.set_source_rgb (1,0.2,0.2) +cr.set_line_width (0.01) +cr.move_to (0.25, 0.2); cr.line_to (0.25, 0.8) +cr.move_to (0.5, 0.2); cr.line_to (0.5, 0.8) +cr.move_to (0.75, 0.2); cr.line_to (0.75, 0.8) +cr.stroke () diff --git a/examples/cairo_snippets/snippets/set_line_join.py b/examples/cairo_snippets/snippets/set_line_join.py new file mode 100755 index 0000000..b2e1919 --- /dev/null +++ b/examples/cairo_snippets/snippets/set_line_join.py @@ -0,0 +1,21 @@ +snippet_normalize (cr, width, height) +cr.set_line_width (0.16) +cr.move_to (0.3, 0.33) +cr.rel_line_to (0.2, -0.2) +cr.rel_line_to (0.2, 0.2) +cr.set_line_join (cairo.LINE_JOIN_MITER) #/* default */ +cr.stroke () + +cr.move_to (0.3, 0.63) +cr.rel_line_to (0.2, -0.2) +cr.rel_line_to (0.2, 0.2) +cr.set_line_join (cairo.LINE_JOIN_BEVEL) +cr.stroke () + +cr.move_to (0.3, 0.93) +cr.rel_line_to (0.2, -0.2) +cr.rel_line_to (0.2, 0.2) +cr.set_line_join (cairo.LINE_JOIN_ROUND) +cr.stroke () + + diff --git a/examples/cairo_snippets/snippets/show_glyphs.py b/examples/cairo_snippets/snippets/show_glyphs.py new file mode 100755 index 0000000..a41cf61 --- /dev/null +++ b/examples/cairo_snippets/snippets/show_glyphs.py @@ -0,0 +1,15 @@ +snippet_normalize (cr, width, height) + +cr.select_font_face ("Sans", cairo.FONT_SLANT_NORMAL, + cairo.FONT_WEIGHT_NORMAL) +# draw 0.08 glyphs in 0.10 squares, at (0.01, 0.02) from left corner +cr.set_font_size (0.08) + +glyphs = [] +index = 0 +for y in range(10): + for x in range(10): + glyphs.append ((index, x/10.0 + 0.01, y/10.0 + 0.08)) + index += 1 + +cr.show_glyphs (glyphs) diff --git a/examples/cairo_snippets/snippets/text.py b/examples/cairo_snippets/snippets/text.py new file mode 100755 index 0000000..1ba80e6 --- /dev/null +++ b/examples/cairo_snippets/snippets/text.py @@ -0,0 +1,22 @@ +snippet_normalize (cr, width, height) +cr.select_font_face ("Sans", cairo.FONT_SLANT_NORMAL, + cairo.FONT_WEIGHT_BOLD) +cr.set_font_size (0.35) + +cr.move_to (0.04, 0.53) +cr.show_text ("Hello") + +cr.move_to (0.27, 0.65) +cr.text_path ("void") +cr.set_source_rgb (0.5,0.5,1) +cr.fill_preserve () +cr.set_source_rgb (0,0,0) +cr.set_line_width (0.01) +cr.stroke () + +#/* draw helping lines */ +cr.set_source_rgba (1,0.2,0.2, 0.6) +cr.arc (0.04, 0.53, 0.02, 0, 2*M_PI) +cr.arc (0.27, 0.65, 0.02, 0, 2*M_PI) +cr.fill () + diff --git a/examples/cairo_snippets/snippets/text_align_center.py b/examples/cairo_snippets/snippets/text_align_center.py new file mode 100755 index 0000000..4bc3124 --- /dev/null +++ b/examples/cairo_snippets/snippets/text_align_center.py @@ -0,0 +1,26 @@ +utf8 = "cairo" + +snippet_normalize (cr, width, height) + +cr.select_font_face ("Sans", + cairo.FONT_SLANT_NORMAL, + cairo.FONT_WEIGHT_NORMAL) + +cr.set_font_size (0.2) +x_bearing, y_bearing, width, height, x_advance, y_advance = cr.text_extents (utf8) +x = 0.5-(width/2 + x_bearing) +y = 0.5-(height/2 + y_bearing) + +cr.move_to (x, y) +cr.show_text (utf8) + +#/* draw helping lines */ +cr.set_source_rgba (1,0.2,0.2,0.6) +cr.arc (x, y, 0.05, 0, 2*M_PI) +cr.fill () +cr.move_to (0.5, 0) +cr.rel_line_to (0, 1) +cr.move_to (0, 0.5) +cr.rel_line_to (1, 0) +cr.stroke () + diff --git a/examples/cairo_snippets/snippets/text_extents.py b/examples/cairo_snippets/snippets/text_extents.py new file mode 100755 index 0000000..890fb88 --- /dev/null +++ b/examples/cairo_snippets/snippets/text_extents.py @@ -0,0 +1,27 @@ +utf8 = "cairo" + +snippet_normalize (cr, width, height) + +cr.select_font_face ("Sans", + cairo.FONT_SLANT_NORMAL, + cairo.FONT_WEIGHT_NORMAL) + +cr.set_font_size (0.4) +x_bearing, y_bearing, width, height, x_advance, y_advance = cr.text_extents (utf8) + +x=0.1 +y=0.6 + +cr.move_to (x,y) +cr.show_text (utf8) + +#/* draw helping lines */ +cr.set_source_rgba (1,0.2,0.2,0.6) +cr.arc (x, y, 0.05, 0, 2*M_PI) +cr.fill () +cr.move_to (x,y) +cr.rel_line_to (0, -height) +cr.rel_line_to (width, 0) +cr.rel_line_to (x_bearing, -y_bearing) +cr.stroke () + diff --git a/examples/cairo_snippets/snippets_gtk.py b/examples/cairo_snippets/snippets_gtk.py new file mode 100755 index 0000000..c7796ea --- /dev/null +++ b/examples/cairo_snippets/snippets_gtk.py @@ -0,0 +1,140 @@ +#!/usr/bin/env python +"""Python version of cairo-demo/cairo_snippets/cairo_snippets_gtk.c +""" +from __future__ import division +from math import pi as M_PI # used by many snippets +import os.path +import sys + +import cairo +import gtk +import pango + +from snippets import snip_list, snippet_normalize + + +Width, Height = 400, 400 + +snippets_path = os.path.join(os.path.dirname(__file__), 'snippets') + + +def gdkcolor_to_rgb (gdkcolor): + return gdkcolor.red/65535, gdkcolor.green/65535, gdkcolor.blue/65535 + + +class Window (gtk.Window): + """Composite widget""" + def __init__ (self, title=None, type=gtk.WINDOW_TOPLEVEL): + gtk.Window.__init__ (self, type) + self.set_default_size (Width, Height) + + self.da = gtk.DrawingArea() + self.da.connect('expose-event', self.da_expose_event) + + def put_in_frame (widget): + frame = gtk.Frame (label=None) + frame.set_property ('shadow_type', gtk.SHADOW_IN) + frame.add (widget) + return frame + + vpaned = gtk.VPaned() + self.add (vpaned) + + sv = self.create_text_view() + vpaned.pack1 (put_in_frame (sv), True, True) + sv.set_size_request (Width, int(Height/2)) + + hpaned = gtk.HPaned() + vpaned.pack2 (hpaned, True, False) + + sl = self.create_snippet_list() + hpaned.pack1 (put_in_frame (sl), True, True) + + hpaned.pack2 (put_in_frame (self.da), True, True) + self.da.set_size_request (int(Width/2), int(Height/2)) + + # set focus to snippet list + sl.get_child().grab_focus() + + + def da_expose_event (self, da, event, data=None): + x, y, width, height = da.allocation + + cr = da.window.cairo_create() + + try: + exec (self.snippet_str, globals(), locals()) + except: + exc_type, exc_value = sys.exc_info()[:2] + print >> sys.stderr, exc_type, exc_value + + return True + + + def create_text_view (self): + sw = gtk.ScrolledWindow() + sw.set_property ('shadow-type', gtk.SHADOW_IN) + sw.set_policy (hscrollbar_policy=gtk.POLICY_AUTOMATIC, + vscrollbar_policy=gtk.POLICY_AUTOMATIC) + + text_view = gtk.TextView() + sw.add (text_view) + # set a fixed width font, so any tabs line up + text_view.modify_font(pango.FontDescription ("Fixed")) + + self.text_buffer = text_view.get_buffer() + + return sw + + + def cb_selection_changed (self, tselection, data=None): + model, iter = tselection.get_selected() + if iter: + filename = model[iter][0] + '.py' + try: + path = os.path.join(snippets_path, filename) + file_obj = open(path, 'r') + self.snippet_str = file_obj.read() + file_obj.close() + self.text_buffer.set_text(self.snippet_str) + except IOError, exc: + print "%s: %s" % (exc.filename, exc.strerror) + + self._draw_pixmap = True + self.da.queue_draw() + + + def create_snippet_list (self): + sw = gtk.ScrolledWindow() + sw.set_property ('shadow-type', gtk.SHADOW_IN) + sw.set_policy (hscrollbar_policy=gtk.POLICY_NEVER, + vscrollbar_policy=gtk.POLICY_AUTOMATIC) + + model = gtk.ListStore (str,) + for row in snip_list: + model.append (row=(row,)) + + tree_view = gtk.TreeView (model) + sw.add (tree_view) + tree_view.set_property ('headers-visible', False) + tree_view.set_property ('search-column', 0) + tree_view.set_property ('rules-hint', False) + + tselection = tree_view.get_selection() + tselection.connect ("changed", self.cb_selection_changed) + tselection.set_mode (gtk.SELECTION_BROWSE) + + cr = gtk.CellRendererText() + tvc = gtk.TreeViewColumn (None, cr, text=0) + tree_view.append_column (tvc) + + tselection.select_path(0,) # select first item + + return sw + + +if __name__ == '__main__': + app = Window () + app.connect('destroy', gtk.main_quit) + app.show_all() + gtk.main() diff --git a/examples/cairo_snippets/snippets_pdf.py b/examples/cairo_snippets/snippets_pdf.py new file mode 100755 index 0000000..0606804 --- /dev/null +++ b/examples/cairo_snippets/snippets_pdf.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python +"""Python version of cairo-demo/cairo_snippets/cairo_snippets_pdf.c +create a file for each example rather than one large file for all examples +""" + +from __future__ import division +from math import pi as M_PI # used by many snippets +import sys + +import cairo +if not cairo.HAS_PDF_SURFACE: + raise SystemExit ('cairo was not compiled with PDF support') + +from snippets import snip_list, snippet_normalize + + +width_in_inches, height_in_inches = 2, 2 +width_in_points, height_in_points = width_in_inches * 72, height_in_inches * 72 +width, height = width_in_points, height_in_points # used by snippet_normalize() + + +def do_snippet (snippet): + if verbose_mode: + print 'processing %s' % snippet, + + filename = 'snippets/%s.pdf' % snippet + surface = cairo.PDFSurface (filename, width_in_points, height_in_points) + cr = cairo.Context (surface) + + cr.save() + try: + execfile ('snippets/%s.py' % snippet, globals(), locals()) + except: + exc_type, exc_value = sys.exc_info()[:2] + print >> sys.stderr, exc_type, exc_value + else: + cr.restore() + cr.show_page() + surface.finish() + + if verbose_mode: + print + +if __name__ == '__main__': + verbose_mode = True + if len(sys.argv) > 1 and sys.argv[1] == '-s': + verbose_mode = False + del sys.argv[1] + + if len(sys.argv) > 1: # do specified snippets + snippet_list = sys.argv[1:] + else: # do all snippets + snippet_list = snip_list + + for s in snippet_list: + do_snippet (s) diff --git a/examples/cairo_snippets/snippets_png.py b/examples/cairo_snippets/snippets_png.py new file mode 100755 index 0000000..b499c6c --- /dev/null +++ b/examples/cairo_snippets/snippets_png.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python +"""Python version of cairo-demo/cairo_snippets/cairo_snippets_png.c +""" + +from __future__ import division +from math import pi as M_PI # used by many snippets +import sys + +import cairo +if not cairo.HAS_PNG_FUNCTIONS: + raise SystemExit ('cairo was not compiled with PNG support') + +from snippets import snip_list, snippet_normalize + + +width, height = 256, 256 # used by snippet_normalize() + + +def do_snippet (snippet): + if verbose_mode: + print 'processing %s' % snippet, + + surface = cairo.ImageSurface (cairo.FORMAT_ARGB32, width, height) + cr = cairo.Context (surface) + + cr.save() + try: + execfile ('snippets/%s.py' % snippet, globals(), locals()) + except: +# exc_type, exc_value = sys.exc_info()[:2] +# print >> sys.stderr, exc_type, exc_value + raise + else: + cr.restore() + surface.write_to_png ('snippets/%s.png' % snippet) + + if verbose_mode: + print + +if __name__ == '__main__': + verbose_mode = True + if len(sys.argv) > 1 and sys.argv[1] == '-s': + verbose_mode = False + del sys.argv[1] + + if len(sys.argv) > 1: # do specified snippets + snippet_list = sys.argv[1:] + else: # do all snippets + snippet_list = snip_list + + for s in snippet_list: + do_snippet (s) diff --git a/examples/cairo_snippets/snippets_ps.py b/examples/cairo_snippets/snippets_ps.py new file mode 100755 index 0000000..364402a --- /dev/null +++ b/examples/cairo_snippets/snippets_ps.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python +"""Python version of cairo-demo/cairo_snippets/cairo_snippets_ps.c +create a file for each example rather than one large file for all examples +""" + +from __future__ import division +from math import pi as M_PI # used by many snippets +import sys + +import cairo +if not cairo.HAS_PS_SURFACE: + raise SystemExit ('cairo was not compiled with PS support') + +from snippets import snip_list, snippet_normalize + + +width_in_inches, height_in_inches = 2, 2 +width_in_points, height_in_points = width_in_inches * 72, height_in_inches * 72 +width, height = width_in_points, height_in_points # used by snippet_normalize() + + +def do_snippet (snippet): + if verbose_mode: + print 'processing %s' % snippet, + + filename = 'snippets/%s.ps' % snippet + surface = cairo.PSSurface (filename, width_in_points, height_in_points) + cr = cairo.Context (surface) + + cr.save() + try: + execfile ('snippets/%s.py' % snippet, globals(), locals()) + except: + exc_type, exc_value = sys.exc_info()[:2] + print >> sys.stderr, exc_type, exc_value + else: + cr.restore() + cr.show_page() + surface.finish() + + if verbose_mode: + print + +if __name__ == '__main__': + verbose_mode = True + if len(sys.argv) > 1 and sys.argv[1] == '-s': + verbose_mode = False + del sys.argv[1] + + if len(sys.argv) > 1: # do specified snippets + snippet_list = sys.argv[1:] + else: # do all snippets + snippet_list = snip_list + + for s in snippet_list: + do_snippet (s) diff --git a/examples/cairo_snippets/snippets_svg.py b/examples/cairo_snippets/snippets_svg.py new file mode 100755 index 0000000..3620ee7 --- /dev/null +++ b/examples/cairo_snippets/snippets_svg.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python + +from __future__ import division +from math import pi as M_PI # used by many snippets +import sys + +import cairo +if not cairo.HAS_SVG_SURFACE: + raise SystemExit ('cairo was not compiled with SVG support') + +from snippets import snip_list, snippet_normalize + + +width_in_inches, height_in_inches = 2, 2 +width_in_points, height_in_points = width_in_inches * 72, height_in_inches * 72 +width, height = width_in_points, height_in_points # used by snippet_normalize() + + +def do_snippet (snippet): + if verbose_mode: + print 'processing %s' % snippet, + + filename = 'snippets/%s.svg' % snippet + surface = cairo.SVGSurface (filename, width_in_points, height_in_points) + cr = cairo.Context (surface) + + cr.save() + try: + execfile ('snippets/%s.py' % snippet, globals(), locals()) + except: + exc_type, exc_value = sys.exc_info()[:2] + print >> sys.stderr, exc_type, exc_value + else: + cr.restore() + cr.show_page() + surface.finish() + + if verbose_mode: + print + +if __name__ == '__main__': + verbose_mode = True + if len(sys.argv) > 1 and sys.argv[1] == '-s': + verbose_mode = False + del sys.argv[1] + + if len(sys.argv) > 1: # do specified snippets + snippet_list = sys.argv[1:] + else: # do all snippets + snippet_list = snip_list + + for s in snippet_list: + do_snippet (s) diff --git a/examples/gradient.py b/examples/gradient.py new file mode 100755 index 0000000..9ebbf76 --- /dev/null +++ b/examples/gradient.py @@ -0,0 +1,33 @@ +#!/usr/bin/env python +"""/cairo-demo/cairo_snippets/gradient.cairo translated to Python +""" + +import math +import cairo + +WIDTH, HEIGHT = 256, 256 + +surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, WIDTH, HEIGHT) +ctx = cairo.Context(surface) + +ctx.scale (WIDTH/1.0, HEIGHT/1.0) + +pat = cairo.LinearGradient (0.0, 0.0, 0.0, 1.0) +pat.add_color_stop_rgba (1, 0, 0, 0, 1) +pat.add_color_stop_rgba (0, 1, 1, 1, 1) + +ctx.rectangle (0,0,1,1) +ctx.set_source (pat) +ctx.fill () + +pat = cairo.RadialGradient (0.45, 0.4, 0.1, + 0.4, 0.4, 0.5) +pat.add_color_stop_rgba (0, 1, 1, 1, 1) +pat.add_color_stop_rgba (1, 0, 0, 0, 1) + +ctx.set_source (pat) +ctx.arc (0.5, 0.5, 0.3, 0, 2 * math.pi) +ctx.fill () + +surface.write_to_png('gradient.png') +#surface.write_to_png(10) diff --git a/examples/gtk/cairo-demo.py b/examples/gtk/cairo-demo.py new file mode 100755 index 0000000..76795ce --- /dev/null +++ b/examples/gtk/cairo-demo.py @@ -0,0 +1,121 @@ +#!/usr/bin/env python +"""Based on cairo-demo/X11/cairo-demo.c +""" +import cairo +import gtk + +SIZE = 30 + +def triangle(ctx): + ctx.move_to(SIZE, 0) + ctx.rel_line_to(SIZE, 2*SIZE) + ctx.rel_line_to(-2*SIZE, 0) + ctx.close_path() + +def square(ctx): + ctx.move_to(0, 0) + ctx.rel_line_to(2*SIZE, 0) + ctx.rel_line_to(0, 2*SIZE) + ctx.rel_line_to(-2*SIZE, 0) + ctx.close_path() + +def bowtie(ctx): + ctx.move_to(0, 0) + ctx.rel_line_to(2*SIZE, 2*SIZE) + ctx.rel_line_to(-2*SIZE, 0) + ctx.rel_line_to(2*SIZE, -2*SIZE) + ctx.close_path() + +def inf(ctx): + ctx.move_to(0, SIZE) + ctx.rel_curve_to(0,SIZE, SIZE,SIZE, 2*SIZE,0) + ctx.rel_curve_to(SIZE,-SIZE, 2*SIZE,-SIZE, 2*SIZE,0) + ctx.rel_curve_to(0,SIZE, -SIZE,SIZE, -2*SIZE,0) + ctx.rel_curve_to(-SIZE,-SIZE, -2*SIZE,-SIZE, -2*SIZE,0) + ctx.close_path() + +def draw_shapes(ctx, x, y, fill): + ctx.save() + + ctx.new_path() + ctx.translate(x+SIZE, y+SIZE) + bowtie(ctx) + if fill: + ctx.fill() + else: + ctx.stroke() + + ctx.new_path() + ctx.translate(3*SIZE, 0) + square(ctx) + if fill: + ctx.fill() + else: + ctx.stroke() + + ctx.new_path() + ctx.translate(3*SIZE, 0) + triangle(ctx) + if fill: + ctx.fill() + else: + ctx.stroke() + + ctx.new_path() + ctx.translate(3*SIZE, 0) + inf(ctx) + if fill: + ctx.fill() + else: + ctx.stroke() + + ctx.restore() + +def fill_shapes(ctx, x, y): + draw_shapes(ctx, x, y, True) + +def stroke_shapes(ctx, x, y): + draw_shapes(ctx, x, y, False) + +def expose (da, event): + ctx = da.window.cairo_create() + + ctx.set_source_rgb(0, 0, 0) + + ctx.set_line_width(SIZE / 4) + ctx.set_tolerance(0.1) + + ctx.set_line_join(cairo.LINE_JOIN_ROUND) + ctx.set_dash([SIZE/4.0, SIZE/4.0], 0) + stroke_shapes(ctx, 0, 0) + + ctx.set_dash([], 0) + stroke_shapes(ctx, 0, 3*SIZE) + + ctx.set_line_join(cairo.LINE_JOIN_BEVEL) + stroke_shapes(ctx, 0, 6*SIZE) + + ctx.set_line_join(cairo.LINE_JOIN_MITER) + stroke_shapes(ctx, 0, 9*SIZE) + + fill_shapes(ctx, 0, 12*SIZE) + + ctx.set_line_join(cairo.LINE_JOIN_BEVEL) + fill_shapes(ctx, 0, 15*SIZE) + ctx.set_source_rgb(1,0,0) + stroke_shapes(ctx, 0, 15*SIZE) + +def main(): + win = gtk.Window() + win.connect('destroy', gtk.main_quit) + win.set_default_size(450, 550) + + drawingarea = gtk.DrawingArea() + win.add(drawingarea) + drawingarea.connect('expose_event', expose) + + win.show_all() + gtk.main() + +if __name__ == '__main__': + main() diff --git a/examples/gtk/cairo-knockout.py b/examples/gtk/cairo-knockout.py new file mode 100755 index 0000000..e8c2c90 --- /dev/null +++ b/examples/gtk/cairo-knockout.py @@ -0,0 +1,128 @@ +#!/usr/bin/env python +"""Based on gtk+/test/testcairo.c +""" + +from __future__ import division +import math +import sys + +import cairo +import gtk + + +def oval_path(ctx, xc, yc, xr, yr): + ctx.save() + + ctx.translate (xc, yc) + ctx.scale (1.0, yr / xr) + ctx.move_to (xr, 0.0) + ctx.arc (0, 0, xr, 0, 2 * math.pi) + ctx.close_path () + + ctx.restore() + +def fill_checks(ctx, x, y, width, height): + CHECK_SIZE = 32 + + ctx.rectangle (x, y, width, height) + ctx.set_source_rgb (0.4, 0.4, 0.4) + ctx.fill () + + # Only works for CHECK_SIZE a power of 2 + for j in range (x & -CHECK_SIZE, height, CHECK_SIZE): + for i in range (y & -CHECK_SIZE, width, CHECK_SIZE): + if ((i / CHECK_SIZE + j / CHECK_SIZE) % 2 == 0): + ctx.rectangle (i, j, CHECK_SIZE, CHECK_SIZE) + + ctx.set_source_rgb (0.7, 0.7, 0.7) + ctx.fill () + +def draw_3circles(ctx, xc, yc, radius, alpha): + subradius = radius * (2 / 3. - 0.1) + + ctx.set_source_rgba(1, 0, 0, alpha) + oval_path(ctx, + xc + radius / 3. * math.cos(math.pi * 0.5), + yc - radius / 3. * math.sin(math.pi * 0.5), + subradius, subradius) + ctx.fill() + + ctx.set_source_rgba(0, 1, 0, alpha) + oval_path(ctx, + xc + radius / 3. * math.cos(math.pi * (0.5 + 2/.3)), + yc - radius / 3. * math.sin(math.pi * (0.5 + 2/.3)), + subradius, subradius) + ctx.fill() + + ctx.set_source_rgba(0, 0, 1, alpha) + oval_path(ctx, + xc + radius / 3. * math.cos(math.pi * (0.5 + 4/.3)), + yc - radius / 3. * math.sin(math.pi * (0.5 + 4/.3)), + subradius, subradius) + ctx.fill() + +def draw (ctx, width, height): + radius = 0.5 * min(width, height) - 10 + xc = width / 2. + yc = height / 2. + + target = ctx.get_target() + overlay = target.create_similar(cairo.CONTENT_COLOR_ALPHA, width, height) + punch = target.create_similar(cairo.CONTENT_ALPHA, width, height) + circles = target.create_similar(cairo.CONTENT_COLOR_ALPHA, width, height) + + fill_checks(ctx, 0, 0, width, height) + + # Draw a black circle on the overlay + overlay_cr = cairo.Context (overlay) + overlay_cr.set_source_rgb (0, 0, 0) + oval_path (overlay_cr, xc, yc, radius, radius) + overlay_cr.fill() + + # Draw 3 circles to the punch surface, then cut + # that out of the main circle in the overlay + punch_cr = cairo.Context (punch) + draw_3circles (punch_cr, xc, yc, radius, 1.0) + + overlay_cr.set_operator (cairo.OPERATOR_DEST_OUT) + overlay_cr.set_source_surface (punch, 0, 0) + overlay_cr.paint() + + # Now draw the 3 circles in a subgroup again + # at half intensity, and use OperatorAdd to join up + # without seams. + circles_cr = cairo.Context (circles) + + circles_cr.set_operator (cairo.OPERATOR_OVER) + draw_3circles (circles_cr, xc, yc, radius, 0.5) + + overlay_cr.set_operator (cairo.OPERATOR_ADD) + overlay_cr.set_source_surface (circles, 0, 0) + overlay_cr.paint() + + ctx.set_source_surface (overlay, 0, 0) + ctx.paint() + +def expose(drawingarea, event): + ctx = drawingarea.window.cairo_create() + + _, _, width, height = drawingarea.allocation + draw (ctx, width, height) + + return False + +def main(): + win = gtk.Window() + win.connect('destroy', gtk.main_quit) + win.set_title('Knockout Groups') + win.set_default_size(400, 400) + + drawingarea = gtk.DrawingArea() + win.add(drawingarea) + drawingarea.connect('expose_event', expose) + + win.show_all() + gtk.main() + +if __name__ == '__main__': + main() diff --git a/examples/gtk/hangman.py b/examples/gtk/hangman.py new file mode 100755 index 0000000..8aa16ce --- /dev/null +++ b/examples/gtk/hangman.py @@ -0,0 +1,257 @@ +#!/usr/bin/env python +# -*- coding: iso8859-1 -*- +# +# Copyright © 2004 Kevin Worth +# +# Permission to use, copy, modify, distribute, and sell this software +# and its documentation for any purpose is hereby granted without fee, +# provided that the above copyright notice appear in all copies and +# that both that copyright notice and this permission notice appear in +# supporting documentation, and that the name of the Kevin Worth not +# be used in advertising or publicity pertaining to distribution of +# the software without specific, written prior permission. Kevin Worth +# California makes no representations about the suitability of this +# software for any purpose. It is provided "as is" without express or +# implied warranty. +# +# KEVIN WORTH DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN +# NO EVENT SHALL KEVIN WORTH BE LIABLE FOR ANY SPECIAL, INDIRECT OR +# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS +# OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, +# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION +# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# +# Author: Kevin Worth <kevin@theworths.org> + +from math import pi +from random import randint + +import cairo +import gtk + +letters_guessed = "" +letters_guessed_right = "" +letters_guessed_wrong = "" + +body_parts = 6 +words = ['cairo', 'graphics', 'pencil', 'keyboard', 'science', 'ricochet', 'flood', 'president', 'sanity'] + +idxRandom = randint(0, len(words) -1) +word_chosen = words[idxRandom] + +#print "The secret word is " + word_chosen + +def guess_letter(widget, event): + global letters_guessed, letters_guessed_right, letters_guessed_wrong + if event.string in letters_guessed: + print "What?!?! You already guessed '" + event.string + "'!" + else: + letters_guessed += event.string + if word_chosen.lower().find(event.string) != -1: + letters_guessed_right += event.string + else: + letters_guessed_wrong += event.string + widget.queue_draw() + +def expose_event(widget, event): + _, _, width, height = widget.allocation + + if width < height: + size = width + else: + size = height + + pixmap = gtk.gdk.Pixmap (widget.window, width, height) + ctx = pixmap.cairo_create() + + # set the background + ctx.set_source_rgb(0.7,0.7,0.7) + ctx.set_operator (cairo.OPERATOR_SOURCE) + ctx.paint() + + ctx.translate ((width - size) / 2, (height - size) / 2) + ctx.scale(size / 150.0, size / 160.0) + + def man_hung(): + return len(letters_guessed_wrong) == body_parts + + ctx.set_font_size(10) + ctx.set_source_rgb(0,0,0) + for idxLetter in range(len(word_chosen)): + #print "Examining letter: " + word_chosen[idxLetter] + if word_chosen[idxLetter].lower() in letters_guessed_right or man_hung(): + if idxLetter == 0: + ctx.move_to(0, 150) + ctx.show_text(word_chosen[idxLetter].upper()) + else: + ctx.move_to(idxLetter * 15, 150) + ctx.show_text(word_chosen[idxLetter].lower()) + else: + ctx.move_to(idxLetter * 15, 150) + ctx.show_text('_') + + # Draw Letters Guessed + + ctx.move_to(0, 160) + ctx.set_source_rgb(0, 0, 0) + ctx.show_text(letters_guessed) + + # Draw noose + + ctx.move_to(100, 12.5) + ctx.line_to(100, 5) + ctx.line_to(130, 5) + ctx.line_to(130, 100) + ctx.set_source_rgb(0, 0, 0) + ctx.stroke() + + # Draw base fill color + + ctx.move_to(130, 100) + ctx.line_to(130, 140) + ctx.line_to(40, 140) + ctx.line_to(40, 130) + ctx.line_to(50, 130) + ctx.line_to(50, 122) + ctx.line_to(60, 122) + ctx.line_to(60, 114) + ctx.line_to(70, 114) + ctx.line_to(70, 106) + ctx.line_to(130, 106) + ctx.set_source_rgb(.4, .2, .1) + ctx.fill() + + # Draw base outline color + + ctx.move_to(130, 100) + ctx.line_to(130, 140) + ctx.line_to(40, 140) + + # Draw 1st(lowest) stair + + ctx.line_to(40, 130) + ctx.line_to(50, 130) + ctx.line_to(130, 130) + ctx.set_source_rgb(0, 0, 0) + ctx.stroke() + + # Draw 2nd stair + + ctx.move_to(50, 130) + ctx.line_to(50, 121) + ctx.line_to(60, 121) + ctx.line_to(130, 121) + ctx.stroke() + + # Draw 3rd stair + + ctx.move_to(60, 121) + ctx.line_to(60, 113) + ctx.line_to(70, 113) + ctx.line_to(130, 113) + ctx.stroke() + + # Draw 4th(top) stair + + ctx.move_to(70, 113) + ctx.line_to(70, 105) + ctx.line_to(130, 105) + ctx.stroke() + + # Draw Head + + if len(letters_guessed_wrong) > 0: + ctx.move_to(107.5, 20) + ctx.arc(100, 20, 7.5, 0, 2*pi) + ctx.set_line_width(1) + ctx.stroke() + + # Draw Eye 1 + + ctx.move_to(104, 17) + ctx.arc(103, 17, 1, 0, 2*pi) + ctx.move_to(103.1, 17) + ctx.arc(103, 17, .1, 0, 2*pi) + + # Draw Eye 2 + + ctx.move_to(98, 17) + ctx.arc(97, 17, 1, 0, 2*pi) + ctx.move_to(97.1, 17) + ctx.arc(97, 17, .1, 0, 2*pi) + + # Draw Nose + + ctx.move_to(100.5, 19) + ctx.line_to(99.5, 21) + ctx.line_to(100.5, 21) + + # Draw Mouth + + if len(letters_guessed_wrong) < 6: + ctx.move_to(97, 23) + ctx.curve_to(97, 23, 100, 27.5, 103, 23) + ctx.set_line_width(.5) + ctx.stroke() + else: + ctx.move_to(100.5, 24) + ctx.arc(100, 24, .5, 0, 2*pi) + ctx.set_line_width(.5) + ctx.stroke() + + ctx.set_source_rgb(0, 0, 0) + ctx.set_line_width(1) + + # Draw Body + + if len(letters_guessed_wrong) > 1: + ctx.move_to(100, 27.5) + ctx.line_to(100, 70) + ctx.stroke() + + # Draw Arm 1 + + if len(letters_guessed_wrong) > 2: + ctx.move_to(100, 35) + ctx.line_to(110, 50) + ctx.stroke() + + # Draw Arm 2 + + if len(letters_guessed_wrong) > 3: + ctx.move_to(100, 35) + ctx.line_to(90, 50) + ctx.stroke() + + # Draw Leg 1 + + if len(letters_guessed_wrong) > 4: + ctx.move_to(100, 70) + ctx.line_to(112, 95) + ctx.stroke() + + # Draw Leg 2 + + if len(letters_guessed_wrong) > 5: + ctx.move_to(100, 70) + ctx.line_to(88, 95) + ctx.stroke() + + # draw pixmap to gdk.window + gc = gtk.gdk.GC(widget.window) + widget.window.draw_drawable(gc, pixmap, 0,0, 0,0, -1,-1) + + +win = gtk.Window() +win.connect('destroy', gtk.main_quit) +win.connect('key_press_event', guess_letter) +win.set_title('Kevin\'s cairo demo') + +drawingarea = gtk.DrawingArea() +win.add(drawingarea) +drawingarea.connect('expose_event', expose_event) +drawingarea.set_size_request(300,320) + +win.show_all() +gtk.main() diff --git a/examples/gtk/lsystem.py b/examples/gtk/lsystem.py new file mode 100755 index 0000000..e08c8dc --- /dev/null +++ b/examples/gtk/lsystem.py @@ -0,0 +1,123 @@ +#!/usr/bin/env python + +import cairo +import gtk + +# Copyright 2003 Jesse Andrews (jdandr2@uky.edu) under GPL + + +class lindenmayer: + def __init__( self ): + self.str = '' + self.prod = {'[':'[','f':'f',']':']','+':'+','-':'-'} + self.SIZE = 10 + self.THETA = 90 + + def addProd( self, let, pro ): + self.prod[let]=pro + + def iterate( self, qty=1 ): + for i in xrange(qty): + self.str = ''.join([ self.prod[l] for l in self.str]) + print 'Done iterating' + + def expose( self, drawingarea, event ): + drawable = drawingarea.window + x, y, width, height = drawingarea.allocation + + ctx = drawable.cairo_create() + ctx.set_source_rgb(0, 0, 0) + + ctx.set_line_width(self.SIZE / 4) + ctx.set_tolerance(0.1) + ctx.set_line_join(cairo.LINE_JOIN_BEVEL) + + ctx.new_path() + ctx.move_to(100,100) + + for c in self.str: + if c == 'f': line(ctx, self.SIZE ) + if c == '+': rotate( ctx, +self.THETA ) + if c == '-': rotate( ctx, -self.THETA ) + if c == '[': ctx.save() + if c == ']': ctx.restore() + + ctx.stroke() + +def line(ctx, len): + ctx.rel_line_to( 0, len ) + +def rotate(ctx, deg): + ctx.rotate( 2*3.141592653589793*deg/360.0 ) + +def lin_setup(): + cls = lindenmayer() + ################# SETUP LSYSTEM HERE ################ + + ### Generic stuff ### + + cls.str = 'f' # the starting string + + cls.SIZE = 5 # length of a line + + ############################################## + ############################################## + #### Uncomment the one you want to use... #### + #### only one at a time right now! #### + ############################################## + ############################################## + + ###### Kock Square Curve ####### + cls.addProd('f','f-f+f+f-f') + cls.THETA = 90 + + ###### Kock Snowflake ###### + +# cls.addProd('f','f-f++f-f') +# cls.THETA = 60 + + ######## Peano Curve ######## +# cls.addProd('x', 'xfyfx+f+yfxfy-f-xfyfx') +# cls.addProd('y', 'yfxfy-f-xfyfx+f+yfxfy') +# cls.addProd('f', 'f') +# cls.THETA = 90 +# cls.str = 'y' + + ###### the plant ###### + ## doesn't seem to work ... .save & .restore messed up ## + +# cls.addProd( 'f','f[+f]f[-f]f' ) +# cls.THETA = 25 + + ####### the tree ######### + ## doesn't seem to work ... .save & .restore messed up ## + +# cls.addProd( 'f', 'ff+[+f-f-f]-[-f+f+f]' ) +# cls.THETA = 22 + + + ### times to iterate string rewriting ### + #this grows QUICKLY, so start only inc by 1 each run! + cls.iterate(4) + + ################ DONE SETUP ############### + return cls + +def main(): + win = gtk.Window() + win.connect('destroy', lambda x: gtk.main_quit()) + win.set_title('cairo Lindenmayer System') + win.set_default_size(600, 600) + + cls = lin_setup() + + drawingarea = gtk.DrawingArea() + win.add(drawingarea) + drawingarea.connect('expose_event', cls.expose) + + win.show_all() + gtk.main() + +if __name__ == '__main__': + main() + diff --git a/examples/gtk/png_view.py b/examples/gtk/png_view.py new file mode 100755 index 0000000..1100c75 --- /dev/null +++ b/examples/gtk/png_view.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python +"""Display a png file +""" + +import sys + +import cairo +import gtk + + +def expose_event(widget, event, surface): + ctx = widget.window.cairo_create() + ctx.set_source_surface(surface, 0,0) + ctx.paint() + + +if len(sys.argv) != 2: + raise SystemExit('usage: png_view.py png_file') + +filename = sys.argv[1] + +surface = cairo.ImageSurface.create_from_png(filename) +Width = surface.get_width() +Height = surface.get_height() + +win = gtk.Window() +win.connect('destroy', gtk.main_quit) + +drawingarea = gtk.DrawingArea() +win.add(drawingarea) +drawingarea.connect('expose_event', expose_event, surface) +drawingarea.set_size_request(Width,Height) + +win.show_all() +gtk.main() diff --git a/examples/gtk/text.py b/examples/gtk/text.py new file mode 100755 index 0000000..2bef98b --- /dev/null +++ b/examples/gtk/text.py @@ -0,0 +1,41 @@ +#!/usr/bin/env python + +import cairo +import gtk + + +def expose_event(widget, event): + ctx = widget.window.cairo_create() + + ctx.set_line_width(6) + ctx.set_tolerance(.1) + + ctx.select_font_face('sans-serif') + ctx.set_font_size(48) + (x, y, width, height, dx, dy) = ctx.text_extents('Hello World') + + ctx.translate (100, 100) + + ctx.new_path() + ctx.move_to(x-10,y-10) + ctx.rel_line_to(width + 20, 0) + ctx.rel_line_to(0, height + 20) + ctx.rel_line_to(-(width + 20), 0) + ctx.close_path() + ctx.set_source_rgb(0,0,1) + ctx.stroke() + + ctx.move_to(0, 0) + ctx.set_source_rgb(0,0,0) + ctx.show_text('Hello World') + +win = gtk.Window() +win.connect('destroy', gtk.main_quit) + +drawingarea = gtk.DrawingArea() +win.add(drawingarea) +drawingarea.connect('expose_event', expose_event) +drawingarea.set_size_request(400,150) + +win.show_all() +gtk.main() diff --git a/examples/hering.py b/examples/hering.py new file mode 100755 index 0000000..e400e15 --- /dev/null +++ b/examples/hering.py @@ -0,0 +1,55 @@ +#!/usr/bin/env python +"""cairo/cairo-demo/png/hering.c translated into Python +""" + +import math + +import cairo + +WIDTH = 300 +HEIGHT = 600 + +def draw_hering (ctx, width, height): + LINES= 32 + MAX_THETA = .80 * math.pi * 2 + THETA_INC = 2.0 * MAX_THETA / (LINES-1) + + ctx.set_source_rgb (0, 0, 0) + ctx.set_line_width (2.0) + + ctx.save() + + ctx.translate (width / 2, height / 2) + ctx.rotate (MAX_THETA) + + for i in range (LINES): + ctx.move_to (-2 * width, 0) + ctx.line_to (2 * width, 0) + ctx.stroke() + + ctx.rotate (- THETA_INC) + + ctx.restore() + + ctx.set_line_width (6) + ctx.set_source_rgb (1, 0, 0) + + ctx.move_to (width / 4.0, 0) + ctx.rel_line_to (0, height) + ctx.stroke() + + ctx.move_to (3 * width / 4.0, 0) + ctx.rel_line_to (0, height) + ctx.stroke() + + +surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, WIDTH, HEIGHT) +ctx = cairo.Context(surface) + +ctx.set_source_rgb (1, 1, 1) +ctx.set_operator (cairo.OPERATOR_SOURCE) +ctx.paint() + +draw_hering (ctx, WIDTH, HEIGHT) + +surface.write_to_png('hering.png') diff --git a/examples/spiral.py b/examples/spiral.py new file mode 100755 index 0000000..7be9af2 --- /dev/null +++ b/examples/spiral.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python +"""cairo/cairo-demo/png/spiral.c translated into Python +""" + +import cairo + +WIDTH, HEIGHT = 600, 600 + +def draw_spiral (ctx, width, height): + wd = .02 * width + hd = .02 * height + + width -= 2 + height -= 2 + + ctx.move_to (width + 1, 1-hd) + for i in range(9): + ctx.rel_line_to (0, height - hd * (2 * i - 1)) + ctx.rel_line_to (- (width - wd * (2 *i)), 0) + ctx.rel_line_to (0, - (height - hd * (2*i))) + ctx.rel_line_to (width - wd * (2 * i + 1), 0) + + ctx.set_source_rgb (0, 0, 1) + ctx.stroke() + + +surface = cairo.ImageSurface (cairo.FORMAT_ARGB32, WIDTH, HEIGHT) +ctx = cairo.Context(surface) + +ctx.set_source_rgb (1, 1, 1) +ctx.set_operator (cairo.OPERATOR_SOURCE) +ctx.paint() + +draw_spiral (ctx, WIDTH, HEIGHT) + +surface.write_to_png('spiral.png') diff --git a/examples/warpedtext.py b/examples/warpedtext.py new file mode 100755 index 0000000..cd83ee7 --- /dev/null +++ b/examples/warpedtext.py @@ -0,0 +1,85 @@ +#!/usr/bin/env python + +import cairo +import math + +def warpPath(ctx, function): + first = True + + for type, points in ctx.copy_path(): + if type == cairo.PATH_MOVE_TO: + if first: + ctx.new_path() + first = False + x, y = function(*points) + ctx.move_to(x, y) + + elif type == cairo.PATH_LINE_TO: + x, y = function(*points) + ctx.line_to(x, y) + + elif type == cairo.PATH_CURVE_TO: + x1, y1, x2, y2, x3, y3 = points + x1, y1 = function(x1, y1) + x2, y2 = function(x2, y2) + x3, y3 = function(x3, y3) + ctx.curve_to(x1, y1, x2, y2, x3, y3) + + elif type == cairo.PATH_CLOSE_PATH: + ctx.close_path() + +def spiral(x, y): + theta0 = -math.pi * 3 / 4 + theta = x / Width * math.pi * 2 + theta0 + radius = y + 200 - x/7 + xnew = radius*math.cos(theta) + ynew = radius*math.sin(-theta) + return xnew + Width/2, ynew + Height/2 + +def curl(x, y): + xn = x - Textwidth/2 + #yn = y - Textheight/2 + xnew = xn + ynew = y + xn ** 3 / ((Textwidth/2)**3) * 70 + return xnew + Width/2, ynew + Height*2/5 + + +Width, Height = 512, 512 +surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, Width, Height) +ctx = cairo.Context(surface) +solidpattern = ctx.get_source() + +# background +pat = cairo.LinearGradient (0.0, 0.0, 0, Height) +pat.add_color_stop_rgba (1, 0, 0, 0, 1) +pat.add_color_stop_rgba (0, 1, 1, 1, 1) + +ctx.rectangle (0,0,Width,Height) +ctx.set_source (pat) +ctx.fill () + +# foreground +ctx.set_source (solidpattern) +ctx.set_source_rgb (1,1,1) + +ctx.select_font_face("Sans") +ctx.set_font_size(80) + +# spiral text +ctx.new_path() +ctx.move_to(0, 0) +ctx.text_path("pycairo - " + "spam " * 5) +warpPath(ctx, spiral) +ctx.fill() + +# curly text +ctx.new_path() +ctx.move_to(0, 0) +ctx.set_source_rgb(0.3, 0.3, 0.3) +text = "I am curly :)" +ctx.text_path(text) +Textwidth, Textheight = ctx.text_extents(text)[2:4] +warpPath(ctx, curl) +ctx.fill() + +surface.write_to_png("warpedtext.png") diff --git a/ltmain.sh b/ltmain.sh new file mode 100755 index 0000000..6939dcc --- /dev/null +++ b/ltmain.sh @@ -0,0 +1,8406 @@ +# Generated from ltmain.m4sh. + +# ltmain.sh (GNU libtool) 2.2.6 +# Written by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996 + +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, 2007 2008 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# GNU Libtool is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# As a special exception to the GNU General Public License, +# if you distribute this file as part of a program or library that +# is built using GNU Libtool, you may include this file under the +# same distribution terms that you use for the rest of that program. +# +# GNU Libtool 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 +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Libtool; see the file COPYING. If not, a copy +# can be downloaded from http://www.gnu.org/licenses/gpl.html, +# or obtained by writing to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +# Usage: $progname [OPTION]... [MODE-ARG]... +# +# Provide generalized library-building support services. +# +# --config show all configuration variables +# --debug enable verbose shell tracing +# -n, --dry-run display commands without modifying any files +# --features display basic configuration information and exit +# --mode=MODE use operation mode MODE +# --preserve-dup-deps don't remove duplicate dependency libraries +# --quiet, --silent don't print informational messages +# --tag=TAG use configuration variables from tag TAG +# -v, --verbose print informational messages (default) +# --version print version information +# -h, --help print short or long help message +# +# MODE must be one of the following: +# +# clean remove files from the build directory +# compile compile a source file into a libtool object +# execute automatically set library path, then run a program +# finish complete the installation of libtool libraries +# install install libraries or executables +# link create a library or an executable +# uninstall remove libraries from an installed directory +# +# MODE-ARGS vary depending on the MODE. +# Try `$progname --help --mode=MODE' for a more detailed description of MODE. +# +# When reporting a bug, please describe a test case to reproduce it and +# include the following information: +# +# host-triplet: $host +# shell: $SHELL +# compiler: $LTCC +# compiler flags: $LTCFLAGS +# linker: $LD (gnu? $with_gnu_ld) +# $progname: (GNU libtool) 2.2.6 +# automake: $automake_version +# autoconf: $autoconf_version +# +# Report bugs to <bug-libtool@gnu.org>. + +PROGRAM=ltmain.sh +PACKAGE=libtool +VERSION=2.2.6 +TIMESTAMP="" +package_revision=1.3012 + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac +fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + +# NLS nuisances: We save the old values to restore during execute mode. +# Only set LANG and LC_ALL to C if already set. +# These must not be set unconditionally because not all systems understand +# e.g. LANG=C (notably SCO). +lt_user_locale= +lt_safe_locale= +for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES +do + eval "if test \"\${$lt_var+set}\" = set; then + save_$lt_var=\$$lt_var + $lt_var=C + export $lt_var + lt_user_locale=\"$lt_var=\\\$save_\$lt_var; \$lt_user_locale\" + lt_safe_locale=\"$lt_var=C; \$lt_safe_locale\" + fi" +done + +$lt_unset CDPATH + + + + + +: ${CP="cp -f"} +: ${ECHO="echo"} +: ${EGREP="/bin/grep -E"} +: ${FGREP="/bin/grep -F"} +: ${GREP="/bin/grep"} +: ${LN_S="ln -s"} +: ${MAKE="make"} +: ${MKDIR="mkdir"} +: ${MV="mv -f"} +: ${RM="rm -f"} +: ${SED="/bin/sed"} +: ${SHELL="${CONFIG_SHELL-/bin/sh}"} +: ${Xsed="$SED -e 1s/^X//"} + +# Global variables: +EXIT_SUCCESS=0 +EXIT_FAILURE=1 +EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing. +EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake. + +exit_status=$EXIT_SUCCESS + +# Make sure IFS has a sensible default +lt_nl=' +' +IFS=" $lt_nl" + +dirname="s,/[^/]*$,," +basename="s,^.*/,," + +# func_dirname_and_basename file append nondir_replacement +# perform func_basename and func_dirname in a single function +# call: +# dirname: Compute the dirname of FILE. If nonempty, +# add APPEND to the result, otherwise set result +# to NONDIR_REPLACEMENT. +# value returned in "$func_dirname_result" +# basename: Compute filename of FILE. +# value retuned in "$func_basename_result" +# Implementation must be kept synchronized with func_dirname +# and func_basename. For efficiency, we do not delegate to +# those functions but instead duplicate the functionality here. +func_dirname_and_basename () +{ + # Extract subdirectory from the argument. + func_dirname_result=`$ECHO "X${1}" | $Xsed -e "$dirname"` + if test "X$func_dirname_result" = "X${1}"; then + func_dirname_result="${3}" + else + func_dirname_result="$func_dirname_result${2}" + fi + func_basename_result=`$ECHO "X${1}" | $Xsed -e "$basename"` +} + +# Generated shell functions inserted here. + +# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh +# is ksh but when the shell is invoked as "sh" and the current value of +# the _XPG environment variable is not equal to 1 (one), the special +# positional parameter $0, within a function call, is the name of the +# function. +progpath="$0" + +# The name of this program: +# In the unlikely event $progname began with a '-', it would play havoc with +# func_echo (imagine progname=-n), so we prepend ./ in that case: +func_dirname_and_basename "$progpath" +progname=$func_basename_result +case $progname in + -*) progname=./$progname ;; +esac + +# Make sure we have an absolute path for reexecution: +case $progpath in + [\\/]*|[A-Za-z]:\\*) ;; + *[\\/]*) + progdir=$func_dirname_result + progdir=`cd "$progdir" && pwd` + progpath="$progdir/$progname" + ;; + *) + save_IFS="$IFS" + IFS=: + for progdir in $PATH; do + IFS="$save_IFS" + test -x "$progdir/$progname" && break + done + IFS="$save_IFS" + test -n "$progdir" || progdir=`pwd` + progpath="$progdir/$progname" + ;; +esac + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +Xsed="${SED}"' -e 1s/^X//' +sed_quote_subst='s/\([`"$\\]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\(["`\\]\)/\\\1/g' + +# Re-`\' parameter expansions in output of double_quote_subst that were +# `\'-ed in input to the same. If an odd number of `\' preceded a '$' +# in input to double_quote_subst, that '$' was protected from expansion. +# Since each input `\' is now two `\'s, look for any number of runs of +# four `\'s followed by two `\'s and then a '$'. `\' that '$'. +bs='\\' +bs2='\\\\' +bs4='\\\\\\\\' +dollar='\$' +sed_double_backslash="\ + s/$bs4/&\\ +/g + s/^$bs2$dollar/$bs&/ + s/\\([^$bs]\\)$bs2$dollar/\\1$bs2$bs$dollar/g + s/\n//g" + +# Standard options: +opt_dry_run=false +opt_help=false +opt_quiet=false +opt_verbose=false +opt_warning=: + +# func_echo arg... +# Echo program name prefixed message, along with the current mode +# name if it has been set yet. +func_echo () +{ + $ECHO "$progname${mode+: }$mode: $*" +} + +# func_verbose arg... +# Echo program name prefixed message in verbose mode only. +func_verbose () +{ + $opt_verbose && func_echo ${1+"$@"} + + # A bug in bash halts the script if the last line of a function + # fails when set -e is in force, so we need another command to + # work around that: + : +} + +# func_error arg... +# Echo program name prefixed message to standard error. +func_error () +{ + $ECHO "$progname${mode+: }$mode: "${1+"$@"} 1>&2 +} + +# func_warning arg... +# Echo program name prefixed warning message to standard error. +func_warning () +{ + $opt_warning && $ECHO "$progname${mode+: }$mode: warning: "${1+"$@"} 1>&2 + + # bash bug again: + : +} + +# func_fatal_error arg... +# Echo program name prefixed message to standard error, and exit. +func_fatal_error () +{ + func_error ${1+"$@"} + exit $EXIT_FAILURE +} + +# func_fatal_help arg... +# Echo program name prefixed message to standard error, followed by +# a help hint, and exit. +func_fatal_help () +{ + func_error ${1+"$@"} + func_fatal_error "$help" +} +help="Try \`$progname --help' for more information." ## default + + +# func_grep expression filename +# Check whether EXPRESSION matches any line of FILENAME, without output. +func_grep () +{ + $GREP "$1" "$2" >/dev/null 2>&1 +} + + +# func_mkdir_p directory-path +# Make sure the entire path to DIRECTORY-PATH is available. +func_mkdir_p () +{ + my_directory_path="$1" + my_dir_list= + + if test -n "$my_directory_path" && test "$opt_dry_run" != ":"; then + + # Protect directory names starting with `-' + case $my_directory_path in + -*) my_directory_path="./$my_directory_path" ;; + esac + + # While some portion of DIR does not yet exist... + while test ! -d "$my_directory_path"; do + # ...make a list in topmost first order. Use a colon delimited + # list incase some portion of path contains whitespace. + my_dir_list="$my_directory_path:$my_dir_list" + + # If the last portion added has no slash in it, the list is done + case $my_directory_path in */*) ;; *) break ;; esac + + # ...otherwise throw away the child directory and loop + my_directory_path=`$ECHO "X$my_directory_path" | $Xsed -e "$dirname"` + done + my_dir_list=`$ECHO "X$my_dir_list" | $Xsed -e 's,:*$,,'` + + save_mkdir_p_IFS="$IFS"; IFS=':' + for my_dir in $my_dir_list; do + IFS="$save_mkdir_p_IFS" + # mkdir can fail with a `File exist' error if two processes + # try to create one of the directories concurrently. Don't + # stop in that case! + $MKDIR "$my_dir" 2>/dev/null || : + done + IFS="$save_mkdir_p_IFS" + + # Bail out if we (or some other process) failed to create a directory. + test -d "$my_directory_path" || \ + func_fatal_error "Failed to create \`$1'" + fi +} + + +# func_mktempdir [string] +# Make a temporary directory that won't clash with other running +# libtool processes, and avoids race conditions if possible. If +# given, STRING is the basename for that directory. +func_mktempdir () +{ + my_template="${TMPDIR-/tmp}/${1-$progname}" + + if test "$opt_dry_run" = ":"; then + # Return a directory name, but don't create it in dry-run mode + my_tmpdir="${my_template}-$$" + else + + # If mktemp works, use that first and foremost + my_tmpdir=`mktemp -d "${my_template}-XXXXXXXX" 2>/dev/null` + + if test ! -d "$my_tmpdir"; then + # Failing that, at least try and use $RANDOM to avoid a race + my_tmpdir="${my_template}-${RANDOM-0}$$" + + save_mktempdir_umask=`umask` + umask 0077 + $MKDIR "$my_tmpdir" + umask $save_mktempdir_umask + fi + + # If we're not in dry-run mode, bomb out on failure + test -d "$my_tmpdir" || \ + func_fatal_error "cannot create temporary directory \`$my_tmpdir'" + fi + + $ECHO "X$my_tmpdir" | $Xsed +} + + +# func_quote_for_eval arg +# Aesthetically quote ARG to be evaled later. +# This function returns two values: FUNC_QUOTE_FOR_EVAL_RESULT +# is double-quoted, suitable for a subsequent eval, whereas +# FUNC_QUOTE_FOR_EVAL_UNQUOTED_RESULT has merely all characters +# which are still active within double quotes backslashified. +func_quote_for_eval () +{ + case $1 in + *[\\\`\"\$]*) + func_quote_for_eval_unquoted_result=`$ECHO "X$1" | $Xsed -e "$sed_quote_subst"` ;; + *) + func_quote_for_eval_unquoted_result="$1" ;; + esac + + case $func_quote_for_eval_unquoted_result in + # Double-quote args containing shell metacharacters to delay + # word splitting, command substitution and and variable + # expansion for a subsequent eval. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + func_quote_for_eval_result="\"$func_quote_for_eval_unquoted_result\"" + ;; + *) + func_quote_for_eval_result="$func_quote_for_eval_unquoted_result" + esac +} + + +# func_quote_for_expand arg +# Aesthetically quote ARG to be evaled later; same as above, +# but do not quote variable references. +func_quote_for_expand () +{ + case $1 in + *[\\\`\"]*) + my_arg=`$ECHO "X$1" | $Xsed \ + -e "$double_quote_subst" -e "$sed_double_backslash"` ;; + *) + my_arg="$1" ;; + esac + + case $my_arg in + # Double-quote args containing shell metacharacters to delay + # word splitting and command substitution for a subsequent eval. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + my_arg="\"$my_arg\"" + ;; + esac + + func_quote_for_expand_result="$my_arg" +} + + +# func_show_eval cmd [fail_exp] +# Unless opt_silent is true, then output CMD. Then, if opt_dryrun is +# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP +# is given, then evaluate it. +func_show_eval () +{ + my_cmd="$1" + my_fail_exp="${2-:}" + + ${opt_silent-false} || { + func_quote_for_expand "$my_cmd" + eval "func_echo $func_quote_for_expand_result" + } + + if ${opt_dry_run-false}; then :; else + eval "$my_cmd" + my_status=$? + if test "$my_status" -eq 0; then :; else + eval "(exit $my_status); $my_fail_exp" + fi + fi +} + + +# func_show_eval_locale cmd [fail_exp] +# Unless opt_silent is true, then output CMD. Then, if opt_dryrun is +# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP +# is given, then evaluate it. Use the saved locale for evaluation. +func_show_eval_locale () +{ + my_cmd="$1" + my_fail_exp="${2-:}" + + ${opt_silent-false} || { + func_quote_for_expand "$my_cmd" + eval "func_echo $func_quote_for_expand_result" + } + + if ${opt_dry_run-false}; then :; else + eval "$lt_user_locale + $my_cmd" + my_status=$? + eval "$lt_safe_locale" + if test "$my_status" -eq 0; then :; else + eval "(exit $my_status); $my_fail_exp" + fi + fi +} + + + + + +# func_version +# Echo version message to standard output and exit. +func_version () +{ + $SED -n '/^# '$PROGRAM' (GNU /,/# warranty; / { + s/^# // + s/^# *$// + s/\((C)\)[ 0-9,-]*\( [1-9][0-9]*\)/\1\2/ + p + }' < "$progpath" + exit $? +} + +# func_usage +# Echo short help message to standard output and exit. +func_usage () +{ + $SED -n '/^# Usage:/,/# -h/ { + s/^# // + s/^# *$// + s/\$progname/'$progname'/ + p + }' < "$progpath" + $ECHO + $ECHO "run \`$progname --help | more' for full usage" + exit $? +} + +# func_help +# Echo long help message to standard output and exit. +func_help () +{ + $SED -n '/^# Usage:/,/# Report bugs to/ { + s/^# // + s/^# *$// + s*\$progname*'$progname'* + s*\$host*'"$host"'* + s*\$SHELL*'"$SHELL"'* + s*\$LTCC*'"$LTCC"'* + s*\$LTCFLAGS*'"$LTCFLAGS"'* + s*\$LD*'"$LD"'* + s/\$with_gnu_ld/'"$with_gnu_ld"'/ + s/\$automake_version/'"`(automake --version) 2>/dev/null |$SED 1q`"'/ + s/\$autoconf_version/'"`(autoconf --version) 2>/dev/null |$SED 1q`"'/ + p + }' < "$progpath" + exit $? +} + +# func_missing_arg argname +# Echo program name prefixed message to standard error and set global +# exit_cmd. +func_missing_arg () +{ + func_error "missing argument for $1" + exit_cmd=exit +} + +exit_cmd=: + + + + + +# Check that we have a working $ECHO. +if test "X$1" = X--no-reexec; then + # Discard the --no-reexec flag, and continue. + shift +elif test "X$1" = X--fallback-echo; then + # Avoid inline document here, it may be left over + : +elif test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t'; then + # Yippee, $ECHO works! + : +else + # Restart under the correct shell, and then maybe $ECHO will work. + exec $SHELL "$progpath" --no-reexec ${1+"$@"} +fi + +if test "X$1" = X--fallback-echo; then + # used as fallback echo + shift + cat <<EOF +$* +EOF + exit $EXIT_SUCCESS +fi + +magic="%%%MAGIC variable%%%" +magic_exe="%%%MAGIC EXE variable%%%" + +# Global variables. +# $mode is unset +nonopt= +execute_dlfiles= +preserve_args= +lo2o="s/\\.lo\$/.${objext}/" +o2lo="s/\\.${objext}\$/.lo/" +extracted_archives= +extracted_serial=0 + +opt_dry_run=false +opt_duplicate_deps=false +opt_silent=false +opt_debug=: + +# If this variable is set in any of the actions, the command in it +# will be execed at the end. This prevents here-documents from being +# left over by shells. +exec_cmd= + +# func_fatal_configuration arg... +# Echo program name prefixed message to standard error, followed by +# a configuration failure hint, and exit. +func_fatal_configuration () +{ + func_error ${1+"$@"} + func_error "See the $PACKAGE documentation for more information." + func_fatal_error "Fatal configuration error." +} + + +# func_config +# Display the configuration for all the tags in this script. +func_config () +{ + re_begincf='^# ### BEGIN LIBTOOL' + re_endcf='^# ### END LIBTOOL' + + # Default configuration. + $SED "1,/$re_begincf CONFIG/d;/$re_endcf CONFIG/,\$d" < "$progpath" + + # Now print the configurations for the tags. + for tagname in $taglist; do + $SED -n "/$re_begincf TAG CONFIG: $tagname\$/,/$re_endcf TAG CONFIG: $tagname\$/p" < "$progpath" + done + + exit $? +} + +# func_features +# Display the features supported by this script. +func_features () +{ + $ECHO "host: $host" + if test "$build_libtool_libs" = yes; then + $ECHO "enable shared libraries" + else + $ECHO "disable shared libraries" + fi + if test "$build_old_libs" = yes; then + $ECHO "enable static libraries" + else + $ECHO "disable static libraries" + fi + + exit $? +} + +# func_enable_tag tagname +# Verify that TAGNAME is valid, and either flag an error and exit, or +# enable the TAGNAME tag. We also add TAGNAME to the global $taglist +# variable here. +func_enable_tag () +{ + # Global variable: + tagname="$1" + + re_begincf="^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\$" + re_endcf="^# ### END LIBTOOL TAG CONFIG: $tagname\$" + sed_extractcf="/$re_begincf/,/$re_endcf/p" + + # Validate tagname. + case $tagname in + *[!-_A-Za-z0-9,/]*) + func_fatal_error "invalid tag name: $tagname" + ;; + esac + + # Don't test for the "default" C tag, as we know it's + # there but not specially marked. + case $tagname in + CC) ;; + *) + if $GREP "$re_begincf" "$progpath" >/dev/null 2>&1; then + taglist="$taglist $tagname" + + # Evaluate the configuration. Be careful to quote the path + # and the sed script, to avoid splitting on whitespace, but + # also don't use non-portable quotes within backquotes within + # quotes we have to do it in 2 steps: + extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"` + eval "$extractedcf" + else + func_error "ignoring unknown tag $tagname" + fi + ;; + esac +} + +# Parse options once, thoroughly. This comes as soon as possible in +# the script to make things like `libtool --version' happen quickly. +{ + + # Shorthand for --mode=foo, only valid as the first argument + case $1 in + clean|clea|cle|cl) + shift; set dummy --mode clean ${1+"$@"}; shift + ;; + compile|compil|compi|comp|com|co|c) + shift; set dummy --mode compile ${1+"$@"}; shift + ;; + execute|execut|execu|exec|exe|ex|e) + shift; set dummy --mode execute ${1+"$@"}; shift + ;; + finish|finis|fini|fin|fi|f) + shift; set dummy --mode finish ${1+"$@"}; shift + ;; + install|instal|insta|inst|ins|in|i) + shift; set dummy --mode install ${1+"$@"}; shift + ;; + link|lin|li|l) + shift; set dummy --mode link ${1+"$@"}; shift + ;; + uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u) + shift; set dummy --mode uninstall ${1+"$@"}; shift + ;; + esac + + # Parse non-mode specific arguments: + while test "$#" -gt 0; do + opt="$1" + shift + + case $opt in + --config) func_config ;; + + --debug) preserve_args="$preserve_args $opt" + func_echo "enabling shell trace mode" + opt_debug='set -x' + $opt_debug + ;; + + -dlopen) test "$#" -eq 0 && func_missing_arg "$opt" && break + execute_dlfiles="$execute_dlfiles $1" + shift + ;; + + --dry-run | -n) opt_dry_run=: ;; + --features) func_features ;; + --finish) mode="finish" ;; + + --mode) test "$#" -eq 0 && func_missing_arg "$opt" && break + case $1 in + # Valid mode arguments: + clean) ;; + compile) ;; + execute) ;; + finish) ;; + install) ;; + link) ;; + relink) ;; + uninstall) ;; + + # Catch anything else as an error + *) func_error "invalid argument for $opt" + exit_cmd=exit + break + ;; + esac + + mode="$1" + shift + ;; + + --preserve-dup-deps) + opt_duplicate_deps=: ;; + + --quiet|--silent) preserve_args="$preserve_args $opt" + opt_silent=: + ;; + + --verbose| -v) preserve_args="$preserve_args $opt" + opt_silent=false + ;; + + --tag) test "$#" -eq 0 && func_missing_arg "$opt" && break + preserve_args="$preserve_args $opt $1" + func_enable_tag "$1" # tagname is set here + shift + ;; + + # Separate optargs to long options: + -dlopen=*|--mode=*|--tag=*) + func_opt_split "$opt" + set dummy "$func_opt_split_opt" "$func_opt_split_arg" ${1+"$@"} + shift + ;; + + -\?|-h) func_usage ;; + --help) opt_help=: ;; + --version) func_version ;; + + -*) func_fatal_help "unrecognized option \`$opt'" ;; + + *) nonopt="$opt" + break + ;; + esac + done + + + case $host in + *cygwin* | *mingw* | *pw32* | *cegcc*) + # don't eliminate duplications in $postdeps and $predeps + opt_duplicate_compiler_generated_deps=: + ;; + *) + opt_duplicate_compiler_generated_deps=$opt_duplicate_deps + ;; + esac + + # Having warned about all mis-specified options, bail out if + # anything was wrong. + $exit_cmd $EXIT_FAILURE +} + +# func_check_version_match +# Ensure that we are using m4 macros, and libtool script from the same +# release of libtool. +func_check_version_match () +{ + if test "$package_revision" != "$macro_revision"; then + if test "$VERSION" != "$macro_version"; then + if test -z "$macro_version"; then + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, but the +$progname: definition of this LT_INIT comes from an older release. +$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION +$progname: and run autoconf again. +_LT_EOF + else + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, but the +$progname: definition of this LT_INIT comes from $PACKAGE $macro_version. +$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION +$progname: and run autoconf again. +_LT_EOF + fi + else + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, revision $package_revision, +$progname: but the definition of this LT_INIT comes from revision $macro_revision. +$progname: You should recreate aclocal.m4 with macros from revision $package_revision +$progname: of $PACKAGE $VERSION and run autoconf again. +_LT_EOF + fi + + exit $EXIT_MISMATCH + fi +} + + +## ----------- ## +## Main. ## +## ----------- ## + +$opt_help || { + # Sanity checks first: + func_check_version_match + + if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then + func_fatal_configuration "not configured to build any kind of library" + fi + + test -z "$mode" && func_fatal_error "error: you must specify a MODE." + + + # Darwin sucks + eval std_shrext=\"$shrext_cmds\" + + + # Only execute mode is allowed to have -dlopen flags. + if test -n "$execute_dlfiles" && test "$mode" != execute; then + func_error "unrecognized option \`-dlopen'" + $ECHO "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # Change the help message to a mode-specific one. + generic_help="$help" + help="Try \`$progname --help --mode=$mode' for more information." +} + + +# func_lalib_p file +# True iff FILE is a libtool `.la' library or `.lo' object file. +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_lalib_p () +{ + test -f "$1" && + $SED -e 4q "$1" 2>/dev/null \ + | $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1 +} + +# func_lalib_unsafe_p file +# True iff FILE is a libtool `.la' library or `.lo' object file. +# This function implements the same check as func_lalib_p without +# resorting to external programs. To this end, it redirects stdin and +# closes it afterwards, without saving the original file descriptor. +# As a safety measure, use it only where a negative result would be +# fatal anyway. Works if `file' does not exist. +func_lalib_unsafe_p () +{ + lalib_p=no + if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then + for lalib_p_l in 1 2 3 4 + do + read lalib_p_line + case "$lalib_p_line" in + \#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;; + esac + done + exec 0<&5 5<&- + fi + test "$lalib_p" = yes +} + +# func_ltwrapper_script_p file +# True iff FILE is a libtool wrapper script +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_script_p () +{ + func_lalib_p "$1" +} + +# func_ltwrapper_executable_p file +# True iff FILE is a libtool wrapper executable +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_executable_p () +{ + func_ltwrapper_exec_suffix= + case $1 in + *.exe) ;; + *) func_ltwrapper_exec_suffix=.exe ;; + esac + $GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1 +} + +# func_ltwrapper_scriptname file +# Assumes file is an ltwrapper_executable +# uses $file to determine the appropriate filename for a +# temporary ltwrapper_script. +func_ltwrapper_scriptname () +{ + func_ltwrapper_scriptname_result="" + if func_ltwrapper_executable_p "$1"; then + func_dirname_and_basename "$1" "" "." + func_stripname '' '.exe' "$func_basename_result" + func_ltwrapper_scriptname_result="$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper" + fi +} + +# func_ltwrapper_p file +# True iff FILE is a libtool wrapper script or wrapper executable +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_p () +{ + func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1" +} + + +# func_execute_cmds commands fail_cmd +# Execute tilde-delimited COMMANDS. +# If FAIL_CMD is given, eval that upon failure. +# FAIL_CMD may read-access the current command in variable CMD! +func_execute_cmds () +{ + $opt_debug + save_ifs=$IFS; IFS='~' + for cmd in $1; do + IFS=$save_ifs + eval cmd=\"$cmd\" + func_show_eval "$cmd" "${2-:}" + done + IFS=$save_ifs +} + + +# func_source file +# Source FILE, adding directory component if necessary. +# Note that it is not necessary on cygwin/mingw to append a dot to +# FILE even if both FILE and FILE.exe exist: automatic-append-.exe +# behavior happens only for exec(3), not for open(2)! Also, sourcing +# `FILE.' does not work on cygwin managed mounts. +func_source () +{ + $opt_debug + case $1 in + */* | *\\*) . "$1" ;; + *) . "./$1" ;; + esac +} + + +# func_infer_tag arg +# Infer tagged configuration to use if any are available and +# if one wasn't chosen via the "--tag" command line option. +# Only attempt this if the compiler in the base compile +# command doesn't match the default compiler. +# arg is usually of the form 'gcc ...' +func_infer_tag () +{ + $opt_debug + if test -n "$available_tags" && test -z "$tagname"; then + CC_quoted= + for arg in $CC; do + func_quote_for_eval "$arg" + CC_quoted="$CC_quoted $func_quote_for_eval_result" + done + case $@ in + # Blanks in the command may have been stripped by the calling shell, + # but not from the CC environment variable when configure was run. + " $CC "* | "$CC "* | " `$ECHO $CC` "* | "`$ECHO $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$ECHO $CC_quoted` "* | "`$ECHO $CC_quoted` "*) ;; + # Blanks at the start of $base_compile will cause this to fail + # if we don't check for them as well. + *) + for z in $available_tags; do + if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then + # Evaluate the configuration. + eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" + CC_quoted= + for arg in $CC; do + # Double-quote args containing other shell metacharacters. + func_quote_for_eval "$arg" + CC_quoted="$CC_quoted $func_quote_for_eval_result" + done + case "$@ " in + " $CC "* | "$CC "* | " `$ECHO $CC` "* | "`$ECHO $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$ECHO $CC_quoted` "* | "`$ECHO $CC_quoted` "*) + # The compiler in the base compile command matches + # the one in the tagged configuration. + # Assume this is the tagged configuration we want. + tagname=$z + break + ;; + esac + fi + done + # If $tagname still isn't set, then no tagged configuration + # was found and let the user know that the "--tag" command + # line option must be used. + if test -z "$tagname"; then + func_echo "unable to infer tagged configuration" + func_fatal_error "specify a tag with \`--tag'" +# else +# func_verbose "using $tagname tagged configuration" + fi + ;; + esac + fi +} + + + +# func_write_libtool_object output_name pic_name nonpic_name +# Create a libtool object file (analogous to a ".la" file), +# but don't create it if we're doing a dry run. +func_write_libtool_object () +{ + write_libobj=${1} + if test "$build_libtool_libs" = yes; then + write_lobj=\'${2}\' + else + write_lobj=none + fi + + if test "$build_old_libs" = yes; then + write_oldobj=\'${3}\' + else + write_oldobj=none + fi + + $opt_dry_run || { + cat >${write_libobj}T <<EOF +# $write_libobj - a libtool object file +# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# Name of the PIC object. +pic_object=$write_lobj + +# Name of the non-PIC object +non_pic_object=$write_oldobj + +EOF + $MV "${write_libobj}T" "${write_libobj}" + } +} + +# func_mode_compile arg... +func_mode_compile () +{ + $opt_debug + # Get the compilation command and the source file. + base_compile= + srcfile="$nonopt" # always keep a non-empty value in "srcfile" + suppress_opt=yes + suppress_output= + arg_mode=normal + libobj= + later= + pie_flag= + + for arg + do + case $arg_mode in + arg ) + # do not "continue". Instead, add this to base_compile + lastarg="$arg" + arg_mode=normal + ;; + + target ) + libobj="$arg" + arg_mode=normal + continue + ;; + + normal ) + # Accept any command-line options. + case $arg in + -o) + test -n "$libobj" && \ + func_fatal_error "you cannot specify \`-o' more than once" + arg_mode=target + continue + ;; + + -pie | -fpie | -fPIE) + pie_flag="$pie_flag $arg" + continue + ;; + + -shared | -static | -prefer-pic | -prefer-non-pic) + later="$later $arg" + continue + ;; + + -no-suppress) + suppress_opt=no + continue + ;; + + -Xcompiler) + arg_mode=arg # the next one goes into the "base_compile" arg list + continue # The current "srcfile" will either be retained or + ;; # replaced later. I would guess that would be a bug. + + -Wc,*) + func_stripname '-Wc,' '' "$arg" + args=$func_stripname_result + lastarg= + save_ifs="$IFS"; IFS=',' + for arg in $args; do + IFS="$save_ifs" + func_quote_for_eval "$arg" + lastarg="$lastarg $func_quote_for_eval_result" + done + IFS="$save_ifs" + func_stripname ' ' '' "$lastarg" + lastarg=$func_stripname_result + + # Add the arguments to base_compile. + base_compile="$base_compile $lastarg" + continue + ;; + + *) + # Accept the current argument as the source file. + # The previous "srcfile" becomes the current argument. + # + lastarg="$srcfile" + srcfile="$arg" + ;; + esac # case $arg + ;; + esac # case $arg_mode + + # Aesthetically quote the previous argument. + func_quote_for_eval "$lastarg" + base_compile="$base_compile $func_quote_for_eval_result" + done # for arg + + case $arg_mode in + arg) + func_fatal_error "you must specify an argument for -Xcompile" + ;; + target) + func_fatal_error "you must specify a target with \`-o'" + ;; + *) + # Get the name of the library object. + test -z "$libobj" && { + func_basename "$srcfile" + libobj="$func_basename_result" + } + ;; + esac + + # Recognize several different file suffixes. + # If the user specifies -o file.o, it is replaced with file.lo + case $libobj in + *.[cCFSifmso] | \ + *.ada | *.adb | *.ads | *.asm | \ + *.c++ | *.cc | *.ii | *.class | *.cpp | *.cxx | \ + *.[fF][09]? | *.for | *.java | *.obj | *.sx) + func_xform "$libobj" + libobj=$func_xform_result + ;; + esac + + case $libobj in + *.lo) func_lo2o "$libobj"; obj=$func_lo2o_result ;; + *) + func_fatal_error "cannot determine name of library object from \`$libobj'" + ;; + esac + + func_infer_tag $base_compile + + for arg in $later; do + case $arg in + -shared) + test "$build_libtool_libs" != yes && \ + func_fatal_configuration "can not build a shared library" + build_old_libs=no + continue + ;; + + -static) + build_libtool_libs=no + build_old_libs=yes + continue + ;; + + -prefer-pic) + pic_mode=yes + continue + ;; + + -prefer-non-pic) + pic_mode=no + continue + ;; + esac + done + + func_quote_for_eval "$libobj" + test "X$libobj" != "X$func_quote_for_eval_result" \ + && $ECHO "X$libobj" | $GREP '[]~#^*{};<>?"'"'"' &()|`$[]' \ + && func_warning "libobj name \`$libobj' may not contain shell special characters." + func_dirname_and_basename "$obj" "/" "" + objname="$func_basename_result" + xdir="$func_dirname_result" + lobj=${xdir}$objdir/$objname + + test -z "$base_compile" && \ + func_fatal_help "you must specify a compilation command" + + # Delete any leftover library objects. + if test "$build_old_libs" = yes; then + removelist="$obj $lobj $libobj ${libobj}T" + else + removelist="$lobj $libobj ${libobj}T" + fi + + # On Cygwin there's no "real" PIC flag so we must build both object types + case $host_os in + cygwin* | mingw* | pw32* | os2* | cegcc*) + pic_mode=default + ;; + esac + if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then + # non-PIC code in shared libraries is not supported + pic_mode=default + fi + + # Calculate the filename of the output object if compiler does + # not support -o with -c + if test "$compiler_c_o" = no; then + output_obj=`$ECHO "X$srcfile" | $Xsed -e 's%^.*/%%' -e 's%\.[^.]*$%%'`.${objext} + lockfile="$output_obj.lock" + else + output_obj= + need_locks=no + lockfile= + fi + + # Lock this critical section if it is needed + # We use this script file to make the link, it avoids creating a new file + if test "$need_locks" = yes; then + until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do + func_echo "Waiting for $lockfile to be removed" + sleep 2 + done + elif test "$need_locks" = warn; then + if test -f "$lockfile"; then + $ECHO "\ +*** ERROR, $lockfile exists and contains: +`cat $lockfile 2>/dev/null` + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + removelist="$removelist $output_obj" + $ECHO "$srcfile" > "$lockfile" + fi + + $opt_dry_run || $RM $removelist + removelist="$removelist $lockfile" + trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15 + + if test -n "$fix_srcfile_path"; then + eval srcfile=\"$fix_srcfile_path\" + fi + func_quote_for_eval "$srcfile" + qsrcfile=$func_quote_for_eval_result + + # Only build a PIC object if we are building libtool libraries. + if test "$build_libtool_libs" = yes; then + # Without this assignment, base_compile gets emptied. + fbsd_hideous_sh_bug=$base_compile + + if test "$pic_mode" != no; then + command="$base_compile $qsrcfile $pic_flag" + else + # Don't build PIC code + command="$base_compile $qsrcfile" + fi + + func_mkdir_p "$xdir$objdir" + + if test -z "$output_obj"; then + # Place PIC objects in $objdir + command="$command -o $lobj" + fi + + func_show_eval_locale "$command" \ + 'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE' + + if test "$need_locks" = warn && + test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then + $ECHO "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + + # Just move the object if needed, then go on to compile the next one + if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then + func_show_eval '$MV "$output_obj" "$lobj"' \ + 'error=$?; $opt_dry_run || $RM $removelist; exit $error' + fi + + # Allow error messages only from the first compilation. + if test "$suppress_opt" = yes; then + suppress_output=' >/dev/null 2>&1' + fi + fi + + # Only build a position-dependent object if we build old libraries. + if test "$build_old_libs" = yes; then + if test "$pic_mode" != yes; then + # Don't build PIC code + command="$base_compile $qsrcfile$pie_flag" + else + command="$base_compile $qsrcfile $pic_flag" + fi + if test "$compiler_c_o" = yes; then + command="$command -o $obj" + fi + + # Suppress compiler output if we already did a PIC compilation. + command="$command$suppress_output" + func_show_eval_locale "$command" \ + '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' + + if test "$need_locks" = warn && + test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then + $ECHO "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + + # Just move the object if needed + if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then + func_show_eval '$MV "$output_obj" "$obj"' \ + 'error=$?; $opt_dry_run || $RM $removelist; exit $error' + fi + fi + + $opt_dry_run || { + func_write_libtool_object "$libobj" "$objdir/$objname" "$objname" + + # Unlock the critical section if it was locked + if test "$need_locks" != no; then + removelist=$lockfile + $RM "$lockfile" + fi + } + + exit $EXIT_SUCCESS +} + +$opt_help || { +test "$mode" = compile && func_mode_compile ${1+"$@"} +} + +func_mode_help () +{ + # We need to display help for each of the modes. + case $mode in + "") + # Generic help is extracted from the usage comments + # at the start of this file. + func_help + ;; + + clean) + $ECHO \ +"Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE... + +Remove files from the build directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed +to RM. + +If FILE is a libtool library, object or program, all the files associated +with it are deleted. Otherwise, only FILE itself is deleted using RM." + ;; + + compile) + $ECHO \ +"Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE + +Compile a source file into a libtool library object. + +This mode accepts the following additional options: + + -o OUTPUT-FILE set the output file name to OUTPUT-FILE + -no-suppress do not suppress compiler output for multiple passes + -prefer-pic try to building PIC objects only + -prefer-non-pic try to building non-PIC objects only + -shared do not build a \`.o' file suitable for static linking + -static only build a \`.o' file suitable for static linking + +COMPILE-COMMAND is a command to be used in creating a \`standard' object file +from the given SOURCEFILE. + +The output file name is determined by removing the directory component from +SOURCEFILE, then substituting the C source code suffix \`.c' with the +library object suffix, \`.lo'." + ;; + + execute) + $ECHO \ +"Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]... + +Automatically set library path, then run a program. + +This mode accepts the following additional options: + + -dlopen FILE add the directory containing FILE to the library path + +This mode sets the library path environment variable according to \`-dlopen' +flags. + +If any of the ARGS are libtool executable wrappers, then they are translated +into their corresponding uninstalled binary, and any of their required library +directories are added to the library path. + +Then, COMMAND is executed, with ARGS as arguments." + ;; + + finish) + $ECHO \ +"Usage: $progname [OPTION]... --mode=finish [LIBDIR]... + +Complete the installation of libtool libraries. + +Each LIBDIR is a directory that contains libtool libraries. + +The commands that this mode executes may require superuser privileges. Use +the \`--dry-run' option if you just want to see what would be executed." + ;; + + install) + $ECHO \ +"Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND... + +Install executables or libraries. + +INSTALL-COMMAND is the installation command. The first component should be +either the \`install' or \`cp' program. + +The following components of INSTALL-COMMAND are treated specially: + + -inst-prefix PREFIX-DIR Use PREFIX-DIR as a staging area for installation + +The rest of the components are interpreted as arguments to that command (only +BSD-compatible install options are recognized)." + ;; + + link) + $ECHO \ +"Usage: $progname [OPTION]... --mode=link LINK-COMMAND... + +Link object files or libraries together to form another library, or to +create an executable program. + +LINK-COMMAND is a command using the C compiler that you would use to create +a program from several object files. + +The following components of LINK-COMMAND are treated specially: + + -all-static do not do any dynamic linking at all + -avoid-version do not add a version suffix if possible + -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime + -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols + -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) + -export-symbols SYMFILE + try to export only the symbols listed in SYMFILE + -export-symbols-regex REGEX + try to export only the symbols matching REGEX + -LLIBDIR search LIBDIR for required installed libraries + -lNAME OUTPUT-FILE requires the installed library libNAME + -module build a library that can dlopened + -no-fast-install disable the fast-install mode + -no-install link a not-installable executable + -no-undefined declare that a library does not refer to external symbols + -o OUTPUT-FILE create OUTPUT-FILE from the specified objects + -objectlist FILE Use a list of object files found in FILE to specify objects + -precious-files-regex REGEX + don't remove output files matching REGEX + -release RELEASE specify package release information + -rpath LIBDIR the created library will eventually be installed in LIBDIR + -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries + -shared only do dynamic linking of libtool libraries + -shrext SUFFIX override the standard shared library file extension + -static do not do any dynamic linking of uninstalled libtool libraries + -static-libtool-libs + do not do any dynamic linking of libtool libraries + -version-info CURRENT[:REVISION[:AGE]] + specify library version info [each variable defaults to 0] + -weak LIBNAME declare that the target provides the LIBNAME interface + +All other options (arguments beginning with \`-') are ignored. + +Every other argument is treated as a filename. Files ending in \`.la' are +treated as uninstalled libtool libraries, other files are standard or library +object files. + +If the OUTPUT-FILE ends in \`.la', then a libtool library is created, +only library objects (\`.lo' files) may be specified, and \`-rpath' is +required, except when creating a convenience library. + +If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created +using \`ar' and \`ranlib', or on Windows using \`lib'. + +If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file +is created, otherwise an executable program is created." + ;; + + uninstall) + $ECHO \ +"Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... + +Remove libraries from an installation directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed +to RM. + +If FILE is a libtool library, all the files associated with it are deleted. +Otherwise, only FILE itself is deleted using RM." + ;; + + *) + func_fatal_help "invalid operation mode \`$mode'" + ;; + esac + + $ECHO + $ECHO "Try \`$progname --help' for more information about other modes." + + exit $? +} + + # Now that we've collected a possible --mode arg, show help if necessary + $opt_help && func_mode_help + + +# func_mode_execute arg... +func_mode_execute () +{ + $opt_debug + # The first argument is the command name. + cmd="$nonopt" + test -z "$cmd" && \ + func_fatal_help "you must specify a COMMAND" + + # Handle -dlopen flags immediately. + for file in $execute_dlfiles; do + test -f "$file" \ + || func_fatal_help "\`$file' is not a file" + + dir= + case $file in + *.la) + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$file" \ + || func_fatal_help "\`$lib' is not a valid libtool archive" + + # Read the libtool library. + dlname= + library_names= + func_source "$file" + + # Skip this library if it cannot be dlopened. + if test -z "$dlname"; then + # Warn if it was a shared library. + test -n "$library_names" && \ + func_warning "\`$file' was not linked with \`-export-dynamic'" + continue + fi + + func_dirname "$file" "" "." + dir="$func_dirname_result" + + if test -f "$dir/$objdir/$dlname"; then + dir="$dir/$objdir" + else + if test ! -f "$dir/$dlname"; then + func_fatal_error "cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" + fi + fi + ;; + + *.lo) + # Just add the directory containing the .lo file. + func_dirname "$file" "" "." + dir="$func_dirname_result" + ;; + + *) + func_warning "\`-dlopen' is ignored for non-libtool libraries and objects" + continue + ;; + esac + + # Get the absolute pathname. + absdir=`cd "$dir" && pwd` + test -n "$absdir" && dir="$absdir" + + # Now add the directory to shlibpath_var. + if eval "test -z \"\$$shlibpath_var\""; then + eval "$shlibpath_var=\"\$dir\"" + else + eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" + fi + done + + # This variable tells wrapper scripts just to set shlibpath_var + # rather than running their programs. + libtool_execute_magic="$magic" + + # Check if any of the arguments is a wrapper script. + args= + for file + do + case $file in + -*) ;; + *) + # Do a test to see if this is really a libtool program. + if func_ltwrapper_script_p "$file"; then + func_source "$file" + # Transform arg to wrapped name. + file="$progdir/$program" + elif func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + func_source "$func_ltwrapper_scriptname_result" + # Transform arg to wrapped name. + file="$progdir/$program" + fi + ;; + esac + # Quote arguments (to preserve shell metacharacters). + func_quote_for_eval "$file" + args="$args $func_quote_for_eval_result" + done + + if test "X$opt_dry_run" = Xfalse; then + if test -n "$shlibpath_var"; then + # Export the shlibpath_var. + eval "export $shlibpath_var" + fi + + # Restore saved environment variables + for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES + do + eval "if test \"\${save_$lt_var+set}\" = set; then + $lt_var=\$save_$lt_var; export $lt_var + else + $lt_unset $lt_var + fi" + done + + # Now prepare to actually exec the command. + exec_cmd="\$cmd$args" + else + # Display what would be done. + if test -n "$shlibpath_var"; then + eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\"" + $ECHO "export $shlibpath_var" + fi + $ECHO "$cmd$args" + exit $EXIT_SUCCESS + fi +} + +test "$mode" = execute && func_mode_execute ${1+"$@"} + + +# func_mode_finish arg... +func_mode_finish () +{ + $opt_debug + libdirs="$nonopt" + admincmds= + + if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then + for dir + do + libdirs="$libdirs $dir" + done + + for libdir in $libdirs; do + if test -n "$finish_cmds"; then + # Do each command in the finish commands. + func_execute_cmds "$finish_cmds" 'admincmds="$admincmds +'"$cmd"'"' + fi + if test -n "$finish_eval"; then + # Do the single finish_eval. + eval cmds=\"$finish_eval\" + $opt_dry_run || eval "$cmds" || admincmds="$admincmds + $cmds" + fi + done + fi + + # Exit here if they wanted silent mode. + $opt_silent && exit $EXIT_SUCCESS + + $ECHO "X----------------------------------------------------------------------" | $Xsed + $ECHO "Libraries have been installed in:" + for libdir in $libdirs; do + $ECHO " $libdir" + done + $ECHO + $ECHO "If you ever happen to want to link against installed libraries" + $ECHO "in a given directory, LIBDIR, you must either use libtool, and" + $ECHO "specify the full pathname of the library, or use the \`-LLIBDIR'" + $ECHO "flag during linking and do at least one of the following:" + if test -n "$shlibpath_var"; then + $ECHO " - add LIBDIR to the \`$shlibpath_var' environment variable" + $ECHO " during execution" + fi + if test -n "$runpath_var"; then + $ECHO " - add LIBDIR to the \`$runpath_var' environment variable" + $ECHO " during linking" + fi + if test -n "$hardcode_libdir_flag_spec"; then + libdir=LIBDIR + eval flag=\"$hardcode_libdir_flag_spec\" + + $ECHO " - use the \`$flag' linker flag" + fi + if test -n "$admincmds"; then + $ECHO " - have your system administrator run these commands:$admincmds" + fi + if test -f /etc/ld.so.conf; then + $ECHO " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'" + fi + $ECHO + + $ECHO "See any operating system documentation about shared libraries for" + case $host in + solaris2.[6789]|solaris2.1[0-9]) + $ECHO "more information, such as the ld(1), crle(1) and ld.so(8) manual" + $ECHO "pages." + ;; + *) + $ECHO "more information, such as the ld(1) and ld.so(8) manual pages." + ;; + esac + $ECHO "X----------------------------------------------------------------------" | $Xsed + exit $EXIT_SUCCESS +} + +test "$mode" = finish && func_mode_finish ${1+"$@"} + + +# func_mode_install arg... +func_mode_install () +{ + $opt_debug + # There may be an optional sh(1) argument at the beginning of + # install_prog (especially on Windows NT). + if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh || + # Allow the use of GNU shtool's install command. + $ECHO "X$nonopt" | $GREP shtool >/dev/null; then + # Aesthetically quote it. + func_quote_for_eval "$nonopt" + install_prog="$func_quote_for_eval_result " + arg=$1 + shift + else + install_prog= + arg=$nonopt + fi + + # The real first argument should be the name of the installation program. + # Aesthetically quote it. + func_quote_for_eval "$arg" + install_prog="$install_prog$func_quote_for_eval_result" + + # We need to accept at least all the BSD install flags. + dest= + files= + opts= + prev= + install_type= + isdir=no + stripme= + for arg + do + if test -n "$dest"; then + files="$files $dest" + dest=$arg + continue + fi + + case $arg in + -d) isdir=yes ;; + -f) + case " $install_prog " in + *[\\\ /]cp\ *) ;; + *) prev=$arg ;; + esac + ;; + -g | -m | -o) + prev=$arg + ;; + -s) + stripme=" -s" + continue + ;; + -*) + ;; + *) + # If the previous option needed an argument, then skip it. + if test -n "$prev"; then + prev= + else + dest=$arg + continue + fi + ;; + esac + + # Aesthetically quote the argument. + func_quote_for_eval "$arg" + install_prog="$install_prog $func_quote_for_eval_result" + done + + test -z "$install_prog" && \ + func_fatal_help "you must specify an install program" + + test -n "$prev" && \ + func_fatal_help "the \`$prev' option requires an argument" + + if test -z "$files"; then + if test -z "$dest"; then + func_fatal_help "no file or destination specified" + else + func_fatal_help "you must specify a destination" + fi + fi + + # Strip any trailing slash from the destination. + func_stripname '' '/' "$dest" + dest=$func_stripname_result + + # Check to see that the destination is a directory. + test -d "$dest" && isdir=yes + if test "$isdir" = yes; then + destdir="$dest" + destname= + else + func_dirname_and_basename "$dest" "" "." + destdir="$func_dirname_result" + destname="$func_basename_result" + + # Not a directory, so check to see that there is only one file specified. + set dummy $files; shift + test "$#" -gt 1 && \ + func_fatal_help "\`$dest' is not a directory" + fi + case $destdir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + for file in $files; do + case $file in + *.lo) ;; + *) + func_fatal_help "\`$destdir' must be an absolute directory name" + ;; + esac + done + ;; + esac + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic="$magic" + + staticlibs= + future_libdirs= + current_libdirs= + for file in $files; do + + # Do each installation. + case $file in + *.$libext) + # Do the static libraries later. + staticlibs="$staticlibs $file" + ;; + + *.la) + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$file" \ + || func_fatal_help "\`$file' is not a valid libtool archive" + + library_names= + old_library= + relink_command= + func_source "$file" + + # Add the libdir to current_libdirs if it is the destination. + if test "X$destdir" = "X$libdir"; then + case "$current_libdirs " in + *" $libdir "*) ;; + *) current_libdirs="$current_libdirs $libdir" ;; + esac + else + # Note the libdir as a future libdir. + case "$future_libdirs " in + *" $libdir "*) ;; + *) future_libdirs="$future_libdirs $libdir" ;; + esac + fi + + func_dirname "$file" "/" "" + dir="$func_dirname_result" + dir="$dir$objdir" + + if test -n "$relink_command"; then + # Determine the prefix the user has applied to our future dir. + inst_prefix_dir=`$ECHO "X$destdir" | $Xsed -e "s%$libdir\$%%"` + + # Don't allow the user to place us outside of our expected + # location b/c this prevents finding dependent libraries that + # are installed to the same prefix. + # At present, this check doesn't affect windows .dll's that + # are installed into $libdir/../bin (currently, that works fine) + # but it's something to keep an eye on. + test "$inst_prefix_dir" = "$destdir" && \ + func_fatal_error "error: cannot install \`$file' to a directory not ending in $libdir" + + if test -n "$inst_prefix_dir"; then + # Stick the inst_prefix_dir data into the link command. + relink_command=`$ECHO "X$relink_command" | $Xsed -e "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` + else + relink_command=`$ECHO "X$relink_command" | $Xsed -e "s%@inst_prefix_dir@%%"` + fi + + func_warning "relinking \`$file'" + func_show_eval "$relink_command" \ + 'func_fatal_error "error: relink \`$file'\'' with the above command before installing it"' + fi + + # See the names of the shared library. + set dummy $library_names; shift + if test -n "$1"; then + realname="$1" + shift + + srcname="$realname" + test -n "$relink_command" && srcname="$realname"T + + # Install the shared library and build the symlinks. + func_show_eval "$install_prog $dir/$srcname $destdir/$realname" \ + 'exit $?' + tstripme="$stripme" + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + case $realname in + *.dll.a) + tstripme="" + ;; + esac + ;; + esac + if test -n "$tstripme" && test -n "$striplib"; then + func_show_eval "$striplib $destdir/$realname" 'exit $?' + fi + + if test "$#" -gt 0; then + # Delete the old symlinks, and create new ones. + # Try `ln -sf' first, because the `ln' binary might depend on + # the symlink we replace! Solaris /bin/ln does not understand -f, + # so we also need to try rm && ln -s. + for linkname + do + test "$linkname" != "$realname" \ + && func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })" + done + fi + + # Do each command in the postinstall commands. + lib="$destdir/$realname" + func_execute_cmds "$postinstall_cmds" 'exit $?' + fi + + # Install the pseudo-library for information purposes. + func_basename "$file" + name="$func_basename_result" + instname="$dir/$name"i + func_show_eval "$install_prog $instname $destdir/$name" 'exit $?' + + # Maybe install the static library, too. + test -n "$old_library" && staticlibs="$staticlibs $dir/$old_library" + ;; + + *.lo) + # Install (i.e. copy) a libtool object. + + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile="$destdir/$destname" + else + func_basename "$file" + destfile="$func_basename_result" + destfile="$destdir/$destfile" + fi + + # Deduce the name of the destination old-style object file. + case $destfile in + *.lo) + func_lo2o "$destfile" + staticdest=$func_lo2o_result + ;; + *.$objext) + staticdest="$destfile" + destfile= + ;; + *) + func_fatal_help "cannot copy a libtool object to \`$destfile'" + ;; + esac + + # Install the libtool object if requested. + test -n "$destfile" && \ + func_show_eval "$install_prog $file $destfile" 'exit $?' + + # Install the old object if enabled. + if test "$build_old_libs" = yes; then + # Deduce the name of the old-style object file. + func_lo2o "$file" + staticobj=$func_lo2o_result + func_show_eval "$install_prog \$staticobj \$staticdest" 'exit $?' + fi + exit $EXIT_SUCCESS + ;; + + *) + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile="$destdir/$destname" + else + func_basename "$file" + destfile="$func_basename_result" + destfile="$destdir/$destfile" + fi + + # If the file is missing, and there is a .exe on the end, strip it + # because it is most likely a libtool script we actually want to + # install + stripped_ext="" + case $file in + *.exe) + if test ! -f "$file"; then + func_stripname '' '.exe' "$file" + file=$func_stripname_result + stripped_ext=".exe" + fi + ;; + esac + + # Do a test to see if this is really a libtool program. + case $host in + *cygwin* | *mingw*) + if func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + wrapper=$func_ltwrapper_scriptname_result + else + func_stripname '' '.exe' "$file" + wrapper=$func_stripname_result + fi + ;; + *) + wrapper=$file + ;; + esac + if func_ltwrapper_script_p "$wrapper"; then + notinst_deplibs= + relink_command= + + func_source "$wrapper" + + # Check the variables that should have been set. + test -z "$generated_by_libtool_version" && \ + func_fatal_error "invalid libtool wrapper script \`$wrapper'" + + finalize=yes + for lib in $notinst_deplibs; do + # Check to see that each library is installed. + libdir= + if test -f "$lib"; then + func_source "$lib" + fi + libfile="$libdir/"`$ECHO "X$lib" | $Xsed -e 's%^.*/%%g'` ### testsuite: skip nested quoting test + if test -n "$libdir" && test ! -f "$libfile"; then + func_warning "\`$lib' has not been installed in \`$libdir'" + finalize=no + fi + done + + relink_command= + func_source "$wrapper" + + outputname= + if test "$fast_install" = no && test -n "$relink_command"; then + $opt_dry_run || { + if test "$finalize" = yes; then + tmpdir=`func_mktempdir` + func_basename "$file$stripped_ext" + file="$func_basename_result" + outputname="$tmpdir/$file" + # Replace the output file specification. + relink_command=`$ECHO "X$relink_command" | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g'` + + $opt_silent || { + func_quote_for_expand "$relink_command" + eval "func_echo $func_quote_for_expand_result" + } + if eval "$relink_command"; then : + else + func_error "error: relink \`$file' with the above command before installing it" + $opt_dry_run || ${RM}r "$tmpdir" + continue + fi + file="$outputname" + else + func_warning "cannot relink \`$file'" + fi + } + else + # Install the binary that we compiled earlier. + file=`$ECHO "X$file$stripped_ext" | $Xsed -e "s%\([^/]*\)$%$objdir/\1%"` + fi + fi + + # remove .exe since cygwin /usr/bin/install will append another + # one anyway + case $install_prog,$host in + */usr/bin/install*,*cygwin*) + case $file:$destfile in + *.exe:*.exe) + # this is ok + ;; + *.exe:*) + destfile=$destfile.exe + ;; + *:*.exe) + func_stripname '' '.exe' "$destfile" + destfile=$func_stripname_result + ;; + esac + ;; + esac + func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?' + $opt_dry_run || if test -n "$outputname"; then + ${RM}r "$tmpdir" + fi + ;; + esac + done + + for file in $staticlibs; do + func_basename "$file" + name="$func_basename_result" + + # Set up the ranlib parameters. + oldlib="$destdir/$name" + + func_show_eval "$install_prog \$file \$oldlib" 'exit $?' + + if test -n "$stripme" && test -n "$old_striplib"; then + func_show_eval "$old_striplib $oldlib" 'exit $?' + fi + + # Do each command in the postinstall commands. + func_execute_cmds "$old_postinstall_cmds" 'exit $?' + done + + test -n "$future_libdirs" && \ + func_warning "remember to run \`$progname --finish$future_libdirs'" + + if test -n "$current_libdirs"; then + # Maybe just do a dry run. + $opt_dry_run && current_libdirs=" -n$current_libdirs" + exec_cmd='$SHELL $progpath $preserve_args --finish$current_libdirs' + else + exit $EXIT_SUCCESS + fi +} + +test "$mode" = install && func_mode_install ${1+"$@"} + + +# func_generate_dlsyms outputname originator pic_p +# Extract symbols from dlprefiles and create ${outputname}S.o with +# a dlpreopen symbol table. +func_generate_dlsyms () +{ + $opt_debug + my_outputname="$1" + my_originator="$2" + my_pic_p="${3-no}" + my_prefix=`$ECHO "$my_originator" | sed 's%[^a-zA-Z0-9]%_%g'` + my_dlsyms= + + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + if test -n "$NM" && test -n "$global_symbol_pipe"; then + my_dlsyms="${my_outputname}S.c" + else + func_error "not configured to extract global symbols from dlpreopened files" + fi + fi + + if test -n "$my_dlsyms"; then + case $my_dlsyms in + "") ;; + *.c) + # Discover the nlist of each of the dlfiles. + nlist="$output_objdir/${my_outputname}.nm" + + func_show_eval "$RM $nlist ${nlist}S ${nlist}T" + + # Parse the name list into a source file. + func_verbose "creating $output_objdir/$my_dlsyms" + + $opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\ +/* $my_dlsyms - symbol resolution table for \`$my_outputname' dlsym emulation. */ +/* Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION */ + +#ifdef __cplusplus +extern \"C\" { +#endif + +/* External symbol declarations for the compiler. */\ +" + + if test "$dlself" = yes; then + func_verbose "generating symbol list for \`$output'" + + $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist" + + # Add our own program objects to the symbol list. + progfiles=`$ECHO "X$objs$old_deplibs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + for progfile in $progfiles; do + func_verbose "extracting global C symbols from \`$progfile'" + $opt_dry_run || eval "$NM $progfile | $global_symbol_pipe >> '$nlist'" + done + + if test -n "$exclude_expsyms"; then + $opt_dry_run || { + eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + } + fi + + if test -n "$export_symbols_regex"; then + $opt_dry_run || { + eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + } + fi + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + export_symbols="$output_objdir/$outputname.exp" + $opt_dry_run || { + $RM $export_symbols + eval "${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' + case $host in + *cygwin* | *mingw* | *cegcc* ) + eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"' + ;; + esac + } + else + $opt_dry_run || { + eval "${SED} -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' + eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + case $host in + *cygwin | *mingw* | *cegcc* ) + eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' + ;; + esac + } + fi + fi + + for dlprefile in $dlprefiles; do + func_verbose "extracting global C symbols from \`$dlprefile'" + func_basename "$dlprefile" + name="$func_basename_result" + $opt_dry_run || { + eval '$ECHO ": $name " >> "$nlist"' + eval "$NM $dlprefile 2>/dev/null | $global_symbol_pipe >> '$nlist'" + } + done + + $opt_dry_run || { + # Make sure we have at least an empty file. + test -f "$nlist" || : > "$nlist" + + if test -n "$exclude_expsyms"; then + $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T + $MV "$nlist"T "$nlist" + fi + + # Try sorting and uniquifying the output. + if $GREP -v "^: " < "$nlist" | + if sort -k 3 </dev/null >/dev/null 2>&1; then + sort -k 3 + else + sort +2 + fi | + uniq > "$nlist"S; then + : + else + $GREP -v "^: " < "$nlist" > "$nlist"S + fi + + if test -f "$nlist"S; then + eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"' + else + $ECHO '/* NONE */' >> "$output_objdir/$my_dlsyms" + fi + + $ECHO >> "$output_objdir/$my_dlsyms" "\ + +/* The mapping between symbol names and symbols. */ +typedef struct { + const char *name; + void *address; +} lt_dlsymlist; +" + case $host in + *cygwin* | *mingw* | *cegcc* ) + $ECHO >> "$output_objdir/$my_dlsyms" "\ +/* DATA imports from DLLs on WIN32 con't be const, because + runtime relocations are performed -- see ld's documentation + on pseudo-relocs. */" + lt_dlsym_const= ;; + *osf5*) + echo >> "$output_objdir/$my_dlsyms" "\ +/* This system does not cope well with relocations in const data */" + lt_dlsym_const= ;; + *) + lt_dlsym_const=const ;; + esac + + $ECHO >> "$output_objdir/$my_dlsyms" "\ +extern $lt_dlsym_const lt_dlsymlist +lt_${my_prefix}_LTX_preloaded_symbols[]; +$lt_dlsym_const lt_dlsymlist +lt_${my_prefix}_LTX_preloaded_symbols[] = +{\ + { \"$my_originator\", (void *) 0 }," + + case $need_lib_prefix in + no) + eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms" + ;; + *) + eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms" + ;; + esac + $ECHO >> "$output_objdir/$my_dlsyms" "\ + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt_${my_prefix}_LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif\ +" + } # !$opt_dry_run + + pic_flag_for_symtable= + case "$compile_command " in + *" -static "*) ;; + *) + case $host in + # compiling the symbol table file with pic_flag works around + # a FreeBSD bug that causes programs to crash when -lm is + # linked before any other PIC object. But we must not use + # pic_flag when linking with -static. The problem exists in + # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. + *-*-freebsd2*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) + pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;; + *-*-hpux*) + pic_flag_for_symtable=" $pic_flag" ;; + *) + if test "X$my_pic_p" != Xno; then + pic_flag_for_symtable=" $pic_flag" + fi + ;; + esac + ;; + esac + symtab_cflags= + for arg in $LTCFLAGS; do + case $arg in + -pie | -fpie | -fPIE) ;; + *) symtab_cflags="$symtab_cflags $arg" ;; + esac + done + + # Now compile the dynamic symbol file. + func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?' + + # Clean up the generated files. + func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T"' + + # Transform the symbol file into the correct name. + symfileobj="$output_objdir/${my_outputname}S.$objext" + case $host in + *cygwin* | *mingw* | *cegcc* ) + if test -f "$output_objdir/$my_outputname.def"; then + compile_command=`$ECHO "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` + finalize_command=`$ECHO "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` + else + compile_command=`$ECHO "X$compile_command" | $Xsed -e "s%@SYMFILE@%$symfileobj%"` + finalize_command=`$ECHO "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$symfileobj%"` + fi + ;; + *) + compile_command=`$ECHO "X$compile_command" | $Xsed -e "s%@SYMFILE@%$symfileobj%"` + finalize_command=`$ECHO "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$symfileobj%"` + ;; + esac + ;; + *) + func_fatal_error "unknown suffix for \`$my_dlsyms'" + ;; + esac + else + # We keep going just in case the user didn't refer to + # lt_preloaded_symbols. The linker will fail if global_symbol_pipe + # really was required. + + # Nullify the symbol file. + compile_command=`$ECHO "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"` + finalize_command=`$ECHO "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"` + fi +} + +# func_win32_libid arg +# return the library type of file 'arg' +# +# Need a lot of goo to handle *both* DLLs and import libs +# Has to be a shell function in order to 'eat' the argument +# that is supplied when $file_magic_command is called. +func_win32_libid () +{ + $opt_debug + win32_libid_type="unknown" + win32_fileres=`file -L $1 2>/dev/null` + case $win32_fileres in + *ar\ archive\ import\ library*) # definitely import + win32_libid_type="x86 archive import" + ;; + *ar\ archive*) # could be an import, or static + if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | + $EGREP 'file format pe-i386(.*architecture: i386)?' >/dev/null ; then + win32_nmres=`eval $NM -f posix -A $1 | + $SED -n -e ' + 1,100{ + / I /{ + s,.*,import, + p + q + } + }'` + case $win32_nmres in + import*) win32_libid_type="x86 archive import";; + *) win32_libid_type="x86 archive static";; + esac + fi + ;; + *DLL*) + win32_libid_type="x86 DLL" + ;; + *executable*) # but shell scripts are "executable" too... + case $win32_fileres in + *MS\ Windows\ PE\ Intel*) + win32_libid_type="x86 DLL" + ;; + esac + ;; + esac + $ECHO "$win32_libid_type" +} + + + +# func_extract_an_archive dir oldlib +func_extract_an_archive () +{ + $opt_debug + f_ex_an_ar_dir="$1"; shift + f_ex_an_ar_oldlib="$1" + func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" 'exit $?' + if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then + : + else + func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" + fi +} + + +# func_extract_archives gentop oldlib ... +func_extract_archives () +{ + $opt_debug + my_gentop="$1"; shift + my_oldlibs=${1+"$@"} + my_oldobjs="" + my_xlib="" + my_xabs="" + my_xdir="" + + for my_xlib in $my_oldlibs; do + # Extract the objects. + case $my_xlib in + [\\/]* | [A-Za-z]:[\\/]*) my_xabs="$my_xlib" ;; + *) my_xabs=`pwd`"/$my_xlib" ;; + esac + func_basename "$my_xlib" + my_xlib="$func_basename_result" + my_xlib_u=$my_xlib + while :; do + case " $extracted_archives " in + *" $my_xlib_u "*) + func_arith $extracted_serial + 1 + extracted_serial=$func_arith_result + my_xlib_u=lt$extracted_serial-$my_xlib ;; + *) break ;; + esac + done + extracted_archives="$extracted_archives $my_xlib_u" + my_xdir="$my_gentop/$my_xlib_u" + + func_mkdir_p "$my_xdir" + + case $host in + *-darwin*) + func_verbose "Extracting $my_xabs" + # Do not bother doing anything if just a dry run + $opt_dry_run || { + darwin_orig_dir=`pwd` + cd $my_xdir || exit $? + darwin_archive=$my_xabs + darwin_curdir=`pwd` + darwin_base_archive=`basename "$darwin_archive"` + darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true` + if test -n "$darwin_arches"; then + darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'` + darwin_arch= + func_verbose "$darwin_base_archive has multiple architectures $darwin_arches" + for darwin_arch in $darwin_arches ; do + func_mkdir_p "unfat-$$/${darwin_base_archive}-${darwin_arch}" + $LIPO -thin $darwin_arch -output "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" "${darwin_archive}" + cd "unfat-$$/${darwin_base_archive}-${darwin_arch}" + func_extract_an_archive "`pwd`" "${darwin_base_archive}" + cd "$darwin_curdir" + $RM "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" + done # $darwin_arches + ## Okay now we've a bunch of thin objects, gotta fatten them up :) + darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$basename" | sort -u` + darwin_file= + darwin_files= + for darwin_file in $darwin_filelist; do + darwin_files=`find unfat-$$ -name $darwin_file -print | $NL2SP` + $LIPO -create -output "$darwin_file" $darwin_files + done # $darwin_filelist + $RM -rf unfat-$$ + cd "$darwin_orig_dir" + else + cd $darwin_orig_dir + func_extract_an_archive "$my_xdir" "$my_xabs" + fi # $darwin_arches + } # !$opt_dry_run + ;; + *) + func_extract_an_archive "$my_xdir" "$my_xabs" + ;; + esac + my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | $NL2SP` + done + + func_extract_archives_result="$my_oldobjs" +} + + + +# func_emit_wrapper_part1 [arg=no] +# +# Emit the first part of a libtool wrapper script on stdout. +# For more information, see the description associated with +# func_emit_wrapper(), below. +func_emit_wrapper_part1 () +{ + func_emit_wrapper_part1_arg1=no + if test -n "$1" ; then + func_emit_wrapper_part1_arg1=$1 + fi + + $ECHO "\ +#! $SHELL + +# $output - temporary wrapper script for $objdir/$outputname +# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION +# +# The $output program cannot be directly executed until all the libtool +# libraries that it depends on are installed. +# +# This wrapper script should never be moved out of the build directory. +# If it is, it will not operate correctly. + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +Xsed='${SED} -e 1s/^X//' +sed_quote_subst='$sed_quote_subst' + +# Be Bourne compatible +if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac +fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +relink_command=\"$relink_command\" + +# This environment variable determines our operation mode. +if test \"\$libtool_install_magic\" = \"$magic\"; then + # install mode needs the following variables: + generated_by_libtool_version='$macro_version' + notinst_deplibs='$notinst_deplibs' +else + # When we are sourced in execute mode, \$file and \$ECHO are already set. + if test \"\$libtool_execute_magic\" != \"$magic\"; then + ECHO=\"$qecho\" + file=\"\$0\" + # Make sure echo works. + if test \"X\$1\" = X--no-reexec; then + # Discard the --no-reexec flag, and continue. + shift + elif test \"X\`{ \$ECHO '\t'; } 2>/dev/null\`\" = 'X\t'; then + # Yippee, \$ECHO works! + : + else + # Restart under the correct shell, and then maybe \$ECHO will work. + exec $SHELL \"\$0\" --no-reexec \${1+\"\$@\"} + fi + fi\ +" + $ECHO "\ + + # Find the directory that this script lives in. + thisdir=\`\$ECHO \"X\$file\" | \$Xsed -e 's%/[^/]*$%%'\` + test \"x\$thisdir\" = \"x\$file\" && thisdir=. + + # Follow symbolic links until we get to the real thisdir. + file=\`ls -ld \"\$file\" | ${SED} -n 's/.*-> //p'\` + while test -n \"\$file\"; do + destdir=\`\$ECHO \"X\$file\" | \$Xsed -e 's%/[^/]*\$%%'\` + + # If there was a directory component, then change thisdir. + if test \"x\$destdir\" != \"x\$file\"; then + case \"\$destdir\" in + [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; + *) thisdir=\"\$thisdir/\$destdir\" ;; + esac + fi + + file=\`\$ECHO \"X\$file\" | \$Xsed -e 's%^.*/%%'\` + file=\`ls -ld \"\$thisdir/\$file\" | ${SED} -n 's/.*-> //p'\` + done +" +} +# end: func_emit_wrapper_part1 + +# func_emit_wrapper_part2 [arg=no] +# +# Emit the second part of a libtool wrapper script on stdout. +# For more information, see the description associated with +# func_emit_wrapper(), below. +func_emit_wrapper_part2 () +{ + func_emit_wrapper_part2_arg1=no + if test -n "$1" ; then + func_emit_wrapper_part2_arg1=$1 + fi + + $ECHO "\ + + # Usually 'no', except on cygwin/mingw when embedded into + # the cwrapper. + WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_part2_arg1 + if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then + # special case for '.' + if test \"\$thisdir\" = \".\"; then + thisdir=\`pwd\` + fi + # remove .libs from thisdir + case \"\$thisdir\" in + *[\\\\/]$objdir ) thisdir=\`\$ECHO \"X\$thisdir\" | \$Xsed -e 's%[\\\\/][^\\\\/]*$%%'\` ;; + $objdir ) thisdir=. ;; + esac + fi + + # Try to get the absolute directory name. + absdir=\`cd \"\$thisdir\" && pwd\` + test -n \"\$absdir\" && thisdir=\"\$absdir\" +" + + if test "$fast_install" = yes; then + $ECHO "\ + program=lt-'$outputname'$exeext + progdir=\"\$thisdir/$objdir\" + + if test ! -f \"\$progdir/\$program\" || + { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\ + test \"X\$file\" != \"X\$progdir/\$program\"; }; then + + file=\"\$\$-\$program\" + + if test ! -d \"\$progdir\"; then + $MKDIR \"\$progdir\" + else + $RM \"\$progdir/\$file\" + fi" + + $ECHO "\ + + # relink executable if necessary + if test -n \"\$relink_command\"; then + if relink_command_output=\`eval \$relink_command 2>&1\`; then : + else + $ECHO \"\$relink_command_output\" >&2 + $RM \"\$progdir/\$file\" + exit 1 + fi + fi + + $MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || + { $RM \"\$progdir/\$program\"; + $MV \"\$progdir/\$file\" \"\$progdir/\$program\"; } + $RM \"\$progdir/\$file\" + fi" + else + $ECHO "\ + program='$outputname' + progdir=\"\$thisdir/$objdir\" +" + fi + + $ECHO "\ + + if test -f \"\$progdir/\$program\"; then" + + # Export our shlibpath_var if we have one. + if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then + $ECHO "\ + # Add our own library path to $shlibpath_var + $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" + + # Some systems cannot cope with colon-terminated $shlibpath_var + # The second colon is a workaround for a bug in BeOS R4 sed + $shlibpath_var=\`\$ECHO \"X\$$shlibpath_var\" | \$Xsed -e 's/::*\$//'\` + + export $shlibpath_var +" + fi + + # fixup the dll searchpath if we need to. + if test -n "$dllsearchpath"; then + $ECHO "\ + # Add the dll search path components to the executable PATH + PATH=$dllsearchpath:\$PATH +" + fi + + $ECHO "\ + if test \"\$libtool_execute_magic\" != \"$magic\"; then + # Run the actual program with our arguments. +" + case $host in + # Backslashes separate directories on plain windows + *-*-mingw | *-*-os2* | *-cegcc*) + $ECHO "\ + exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} +" + ;; + + *) + $ECHO "\ + exec \"\$progdir/\$program\" \${1+\"\$@\"} +" + ;; + esac + $ECHO "\ + \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2 + exit 1 + fi + else + # The program doesn't exist. + \$ECHO \"\$0: error: \\\`\$progdir/\$program' does not exist\" 1>&2 + \$ECHO \"This script is just a wrapper for \$program.\" 1>&2 + $ECHO \"See the $PACKAGE documentation for more information.\" 1>&2 + exit 1 + fi +fi\ +" +} +# end: func_emit_wrapper_part2 + + +# func_emit_wrapper [arg=no] +# +# Emit a libtool wrapper script on stdout. +# Don't directly open a file because we may want to +# incorporate the script contents within a cygwin/mingw +# wrapper executable. Must ONLY be called from within +# func_mode_link because it depends on a number of variables +# set therein. +# +# ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR +# variable will take. If 'yes', then the emitted script +# will assume that the directory in which it is stored is +# the $objdir directory. This is a cygwin/mingw-specific +# behavior. +func_emit_wrapper () +{ + func_emit_wrapper_arg1=no + if test -n "$1" ; then + func_emit_wrapper_arg1=$1 + fi + + # split this up so that func_emit_cwrapperexe_src + # can call each part independently. + func_emit_wrapper_part1 "${func_emit_wrapper_arg1}" + func_emit_wrapper_part2 "${func_emit_wrapper_arg1}" +} + + +# func_to_host_path arg +# +# Convert paths to host format when used with build tools. +# Intended for use with "native" mingw (where libtool itself +# is running under the msys shell), or in the following cross- +# build environments: +# $build $host +# mingw (msys) mingw [e.g. native] +# cygwin mingw +# *nix + wine mingw +# where wine is equipped with the `winepath' executable. +# In the native mingw case, the (msys) shell automatically +# converts paths for any non-msys applications it launches, +# but that facility isn't available from inside the cwrapper. +# Similar accommodations are necessary for $host mingw and +# $build cygwin. Calling this function does no harm for other +# $host/$build combinations not listed above. +# +# ARG is the path (on $build) that should be converted to +# the proper representation for $host. The result is stored +# in $func_to_host_path_result. +func_to_host_path () +{ + func_to_host_path_result="$1" + if test -n "$1" ; then + case $host in + *mingw* ) + lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' + case $build in + *mingw* ) # actually, msys + # awkward: cmd appends spaces to result + lt_sed_strip_trailing_spaces="s/[ ]*\$//" + func_to_host_path_tmp1=`( cmd //c echo "$1" |\ + $SED -e "$lt_sed_strip_trailing_spaces" ) 2>/dev/null || echo ""` + func_to_host_path_result=`echo "$func_to_host_path_tmp1" |\ + $SED -e "$lt_sed_naive_backslashify"` + ;; + *cygwin* ) + func_to_host_path_tmp1=`cygpath -w "$1"` + func_to_host_path_result=`echo "$func_to_host_path_tmp1" |\ + $SED -e "$lt_sed_naive_backslashify"` + ;; + * ) + # Unfortunately, winepath does not exit with a non-zero + # error code, so we are forced to check the contents of + # stdout. On the other hand, if the command is not + # found, the shell will set an exit code of 127 and print + # *an error message* to stdout. So we must check for both + # error code of zero AND non-empty stdout, which explains + # the odd construction: + func_to_host_path_tmp1=`winepath -w "$1" 2>/dev/null` + if test "$?" -eq 0 && test -n "${func_to_host_path_tmp1}"; then + func_to_host_path_result=`echo "$func_to_host_path_tmp1" |\ + $SED -e "$lt_sed_naive_backslashify"` + else + # Allow warning below. + func_to_host_path_result="" + fi + ;; + esac + if test -z "$func_to_host_path_result" ; then + func_error "Could not determine host path corresponding to" + func_error " '$1'" + func_error "Continuing, but uninstalled executables may not work." + # Fallback: + func_to_host_path_result="$1" + fi + ;; + esac + fi +} +# end: func_to_host_path + +# func_to_host_pathlist arg +# +# Convert pathlists to host format when used with build tools. +# See func_to_host_path(), above. This function supports the +# following $build/$host combinations (but does no harm for +# combinations not listed here): +# $build $host +# mingw (msys) mingw [e.g. native] +# cygwin mingw +# *nix + wine mingw +# +# Path separators are also converted from $build format to +# $host format. If ARG begins or ends with a path separator +# character, it is preserved (but converted to $host format) +# on output. +# +# ARG is a pathlist (on $build) that should be converted to +# the proper representation on $host. The result is stored +# in $func_to_host_pathlist_result. +func_to_host_pathlist () +{ + func_to_host_pathlist_result="$1" + if test -n "$1" ; then + case $host in + *mingw* ) + lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' + # Remove leading and trailing path separator characters from + # ARG. msys behavior is inconsistent here, cygpath turns them + # into '.;' and ';.', and winepath ignores them completely. + func_to_host_pathlist_tmp2="$1" + # Once set for this call, this variable should not be + # reassigned. It is used in tha fallback case. + func_to_host_pathlist_tmp1=`echo "$func_to_host_pathlist_tmp2" |\ + $SED -e 's|^:*||' -e 's|:*$||'` + case $build in + *mingw* ) # Actually, msys. + # Awkward: cmd appends spaces to result. + lt_sed_strip_trailing_spaces="s/[ ]*\$//" + func_to_host_pathlist_tmp2=`( cmd //c echo "$func_to_host_pathlist_tmp1" |\ + $SED -e "$lt_sed_strip_trailing_spaces" ) 2>/dev/null || echo ""` + func_to_host_pathlist_result=`echo "$func_to_host_pathlist_tmp2" |\ + $SED -e "$lt_sed_naive_backslashify"` + ;; + *cygwin* ) + func_to_host_pathlist_tmp2=`cygpath -w -p "$func_to_host_pathlist_tmp1"` + func_to_host_pathlist_result=`echo "$func_to_host_pathlist_tmp2" |\ + $SED -e "$lt_sed_naive_backslashify"` + ;; + * ) + # unfortunately, winepath doesn't convert pathlists + func_to_host_pathlist_result="" + func_to_host_pathlist_oldIFS=$IFS + IFS=: + for func_to_host_pathlist_f in $func_to_host_pathlist_tmp1 ; do + IFS=$func_to_host_pathlist_oldIFS + if test -n "$func_to_host_pathlist_f" ; then + func_to_host_path "$func_to_host_pathlist_f" + if test -n "$func_to_host_path_result" ; then + if test -z "$func_to_host_pathlist_result" ; then + func_to_host_pathlist_result="$func_to_host_path_result" + else + func_to_host_pathlist_result="$func_to_host_pathlist_result;$func_to_host_path_result" + fi + fi + fi + IFS=: + done + IFS=$func_to_host_pathlist_oldIFS + ;; + esac + if test -z "$func_to_host_pathlist_result" ; then + func_error "Could not determine the host path(s) corresponding to" + func_error " '$1'" + func_error "Continuing, but uninstalled executables may not work." + # Fallback. This may break if $1 contains DOS-style drive + # specifications. The fix is not to complicate the expression + # below, but for the user to provide a working wine installation + # with winepath so that path translation in the cross-to-mingw + # case works properly. + lt_replace_pathsep_nix_to_dos="s|:|;|g" + func_to_host_pathlist_result=`echo "$func_to_host_pathlist_tmp1" |\ + $SED -e "$lt_replace_pathsep_nix_to_dos"` + fi + # Now, add the leading and trailing path separators back + case "$1" in + :* ) func_to_host_pathlist_result=";$func_to_host_pathlist_result" + ;; + esac + case "$1" in + *: ) func_to_host_pathlist_result="$func_to_host_pathlist_result;" + ;; + esac + ;; + esac + fi +} +# end: func_to_host_pathlist + +# func_emit_cwrapperexe_src +# emit the source code for a wrapper executable on stdout +# Must ONLY be called from within func_mode_link because +# it depends on a number of variable set therein. +func_emit_cwrapperexe_src () +{ + cat <<EOF + +/* $cwrappersource - temporary wrapper executable for $objdir/$outputname + Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION + + The $output program cannot be directly executed until all the libtool + libraries that it depends on are installed. + + This wrapper executable should never be moved out of the build directory. + If it is, it will not operate correctly. + + Currently, it simply execs the wrapper *script* "$SHELL $output", + but could eventually absorb all of the scripts functionality and + exec $objdir/$outputname directly. +*/ +EOF + cat <<"EOF" +#include <stdio.h> +#include <stdlib.h> +#ifdef _MSC_VER +# include <direct.h> +# include <process.h> +# include <io.h> +# define setmode _setmode +#else +# include <unistd.h> +# include <stdint.h> +# ifdef __CYGWIN__ +# include <io.h> +# define HAVE_SETENV +# ifdef __STRICT_ANSI__ +char *realpath (const char *, char *); +int putenv (char *); +int setenv (const char *, const char *, int); +# endif +# endif +#endif +#include <malloc.h> +#include <stdarg.h> +#include <assert.h> +#include <string.h> +#include <ctype.h> +#include <errno.h> +#include <fcntl.h> +#include <sys/stat.h> + +#if defined(PATH_MAX) +# define LT_PATHMAX PATH_MAX +#elif defined(MAXPATHLEN) +# define LT_PATHMAX MAXPATHLEN +#else +# define LT_PATHMAX 1024 +#endif + +#ifndef S_IXOTH +# define S_IXOTH 0 +#endif +#ifndef S_IXGRP +# define S_IXGRP 0 +#endif + +#ifdef _MSC_VER +# define S_IXUSR _S_IEXEC +# define stat _stat +# ifndef _INTPTR_T_DEFINED +# define intptr_t int +# endif +#endif + +#ifndef DIR_SEPARATOR +# define DIR_SEPARATOR '/' +# define PATH_SEPARATOR ':' +#endif + +#if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \ + defined (__OS2__) +# define HAVE_DOS_BASED_FILE_SYSTEM +# define FOPEN_WB "wb" +# ifndef DIR_SEPARATOR_2 +# define DIR_SEPARATOR_2 '\\' +# endif +# ifndef PATH_SEPARATOR_2 +# define PATH_SEPARATOR_2 ';' +# endif +#endif + +#ifndef DIR_SEPARATOR_2 +# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) +#else /* DIR_SEPARATOR_2 */ +# define IS_DIR_SEPARATOR(ch) \ + (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) +#endif /* DIR_SEPARATOR_2 */ + +#ifndef PATH_SEPARATOR_2 +# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR) +#else /* PATH_SEPARATOR_2 */ +# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2) +#endif /* PATH_SEPARATOR_2 */ + +#ifdef __CYGWIN__ +# define FOPEN_WB "wb" +#endif + +#ifndef FOPEN_WB +# define FOPEN_WB "w" +#endif +#ifndef _O_BINARY +# define _O_BINARY 0 +#endif + +#define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) +#define XFREE(stale) do { \ + if (stale) { free ((void *) stale); stale = 0; } \ +} while (0) + +#undef LTWRAPPER_DEBUGPRINTF +#if defined DEBUGWRAPPER +# define LTWRAPPER_DEBUGPRINTF(args) ltwrapper_debugprintf args +static void +ltwrapper_debugprintf (const char *fmt, ...) +{ + va_list args; + va_start (args, fmt); + (void) vfprintf (stderr, fmt, args); + va_end (args); +} +#else +# define LTWRAPPER_DEBUGPRINTF(args) +#endif + +const char *program_name = NULL; + +void *xmalloc (size_t num); +char *xstrdup (const char *string); +const char *base_name (const char *name); +char *find_executable (const char *wrapper); +char *chase_symlinks (const char *pathspec); +int make_executable (const char *path); +int check_executable (const char *path); +char *strendzap (char *str, const char *pat); +void lt_fatal (const char *message, ...); +void lt_setenv (const char *name, const char *value); +char *lt_extend_str (const char *orig_value, const char *add, int to_end); +void lt_opt_process_env_set (const char *arg); +void lt_opt_process_env_prepend (const char *arg); +void lt_opt_process_env_append (const char *arg); +int lt_split_name_value (const char *arg, char** name, char** value); +void lt_update_exe_path (const char *name, const char *value); +void lt_update_lib_path (const char *name, const char *value); + +static const char *script_text_part1 = +EOF + + func_emit_wrapper_part1 yes | + $SED -e 's/\([\\"]\)/\\\1/g' \ + -e 's/^/ "/' -e 's/$/\\n"/' + echo ";" + cat <<EOF + +static const char *script_text_part2 = +EOF + func_emit_wrapper_part2 yes | + $SED -e 's/\([\\"]\)/\\\1/g' \ + -e 's/^/ "/' -e 's/$/\\n"/' + echo ";" + + cat <<EOF +const char * MAGIC_EXE = "$magic_exe"; +const char * LIB_PATH_VARNAME = "$shlibpath_var"; +EOF + + if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then + func_to_host_pathlist "$temp_rpath" + cat <<EOF +const char * LIB_PATH_VALUE = "$func_to_host_pathlist_result"; +EOF + else + cat <<"EOF" +const char * LIB_PATH_VALUE = ""; +EOF + fi + + if test -n "$dllsearchpath"; then + func_to_host_pathlist "$dllsearchpath:" + cat <<EOF +const char * EXE_PATH_VARNAME = "PATH"; +const char * EXE_PATH_VALUE = "$func_to_host_pathlist_result"; +EOF + else + cat <<"EOF" +const char * EXE_PATH_VARNAME = ""; +const char * EXE_PATH_VALUE = ""; +EOF + fi + + if test "$fast_install" = yes; then + cat <<EOF +const char * TARGET_PROGRAM_NAME = "lt-$outputname"; /* hopefully, no .exe */ +EOF + else + cat <<EOF +const char * TARGET_PROGRAM_NAME = "$outputname"; /* hopefully, no .exe */ +EOF + fi + + + cat <<"EOF" + +#define LTWRAPPER_OPTION_PREFIX "--lt-" +#define LTWRAPPER_OPTION_PREFIX_LENGTH 5 + +static const size_t opt_prefix_len = LTWRAPPER_OPTION_PREFIX_LENGTH; +static const char *ltwrapper_option_prefix = LTWRAPPER_OPTION_PREFIX; + +static const char *dumpscript_opt = LTWRAPPER_OPTION_PREFIX "dump-script"; + +static const size_t env_set_opt_len = LTWRAPPER_OPTION_PREFIX_LENGTH + 7; +static const char *env_set_opt = LTWRAPPER_OPTION_PREFIX "env-set"; + /* argument is putenv-style "foo=bar", value of foo is set to bar */ + +static const size_t env_prepend_opt_len = LTWRAPPER_OPTION_PREFIX_LENGTH + 11; +static const char *env_prepend_opt = LTWRAPPER_OPTION_PREFIX "env-prepend"; + /* argument is putenv-style "foo=bar", new value of foo is bar${foo} */ + +static const size_t env_append_opt_len = LTWRAPPER_OPTION_PREFIX_LENGTH + 10; +static const char *env_append_opt = LTWRAPPER_OPTION_PREFIX "env-append"; + /* argument is putenv-style "foo=bar", new value of foo is ${foo}bar */ + +int +main (int argc, char *argv[]) +{ + char **newargz; + int newargc; + char *tmp_pathspec; + char *actual_cwrapper_path; + char *actual_cwrapper_name; + char *target_name; + char *lt_argv_zero; + intptr_t rval = 127; + + int i; + + program_name = (char *) xstrdup (base_name (argv[0])); + LTWRAPPER_DEBUGPRINTF (("(main) argv[0] : %s\n", argv[0])); + LTWRAPPER_DEBUGPRINTF (("(main) program_name : %s\n", program_name)); + + /* very simple arg parsing; don't want to rely on getopt */ + for (i = 1; i < argc; i++) + { + if (strcmp (argv[i], dumpscript_opt) == 0) + { +EOF + case "$host" in + *mingw* | *cygwin* ) + # make stdout use "unix" line endings + echo " setmode(1,_O_BINARY);" + ;; + esac + + cat <<"EOF" + printf ("%s", script_text_part1); + printf ("%s", script_text_part2); + return 0; + } + } + + newargz = XMALLOC (char *, argc + 1); + tmp_pathspec = find_executable (argv[0]); + if (tmp_pathspec == NULL) + lt_fatal ("Couldn't find %s", argv[0]); + LTWRAPPER_DEBUGPRINTF (("(main) found exe (before symlink chase) at : %s\n", + tmp_pathspec)); + + actual_cwrapper_path = chase_symlinks (tmp_pathspec); + LTWRAPPER_DEBUGPRINTF (("(main) found exe (after symlink chase) at : %s\n", + actual_cwrapper_path)); + XFREE (tmp_pathspec); + + actual_cwrapper_name = xstrdup( base_name (actual_cwrapper_path)); + strendzap (actual_cwrapper_path, actual_cwrapper_name); + + /* wrapper name transforms */ + strendzap (actual_cwrapper_name, ".exe"); + tmp_pathspec = lt_extend_str (actual_cwrapper_name, ".exe", 1); + XFREE (actual_cwrapper_name); + actual_cwrapper_name = tmp_pathspec; + tmp_pathspec = 0; + + /* target_name transforms -- use actual target program name; might have lt- prefix */ + target_name = xstrdup (base_name (TARGET_PROGRAM_NAME)); + strendzap (target_name, ".exe"); + tmp_pathspec = lt_extend_str (target_name, ".exe", 1); + XFREE (target_name); + target_name = tmp_pathspec; + tmp_pathspec = 0; + + LTWRAPPER_DEBUGPRINTF (("(main) libtool target name: %s\n", + target_name)); +EOF + + cat <<EOF + newargz[0] = + XMALLOC (char, (strlen (actual_cwrapper_path) + + strlen ("$objdir") + 1 + strlen (actual_cwrapper_name) + 1)); + strcpy (newargz[0], actual_cwrapper_path); + strcat (newargz[0], "$objdir"); + strcat (newargz[0], "/"); +EOF + + cat <<"EOF" + /* stop here, and copy so we don't have to do this twice */ + tmp_pathspec = xstrdup (newargz[0]); + + /* do NOT want the lt- prefix here, so use actual_cwrapper_name */ + strcat (newargz[0], actual_cwrapper_name); + + /* DO want the lt- prefix here if it exists, so use target_name */ + lt_argv_zero = lt_extend_str (tmp_pathspec, target_name, 1); + XFREE (tmp_pathspec); + tmp_pathspec = NULL; +EOF + + case $host_os in + mingw*) + cat <<"EOF" + { + char* p; + while ((p = strchr (newargz[0], '\\')) != NULL) + { + *p = '/'; + } + while ((p = strchr (lt_argv_zero, '\\')) != NULL) + { + *p = '/'; + } + } +EOF + ;; + esac + + cat <<"EOF" + XFREE (target_name); + XFREE (actual_cwrapper_path); + XFREE (actual_cwrapper_name); + + lt_setenv ("BIN_SH", "xpg4"); /* for Tru64 */ + lt_setenv ("DUALCASE", "1"); /* for MSK sh */ + lt_update_lib_path (LIB_PATH_VARNAME, LIB_PATH_VALUE); + lt_update_exe_path (EXE_PATH_VARNAME, EXE_PATH_VALUE); + + newargc=0; + for (i = 1; i < argc; i++) + { + if (strncmp (argv[i], env_set_opt, env_set_opt_len) == 0) + { + if (argv[i][env_set_opt_len] == '=') + { + const char *p = argv[i] + env_set_opt_len + 1; + lt_opt_process_env_set (p); + } + else if (argv[i][env_set_opt_len] == '\0' && i + 1 < argc) + { + lt_opt_process_env_set (argv[++i]); /* don't copy */ + } + else + lt_fatal ("%s missing required argument", env_set_opt); + continue; + } + if (strncmp (argv[i], env_prepend_opt, env_prepend_opt_len) == 0) + { + if (argv[i][env_prepend_opt_len] == '=') + { + const char *p = argv[i] + env_prepend_opt_len + 1; + lt_opt_process_env_prepend (p); + } + else if (argv[i][env_prepend_opt_len] == '\0' && i + 1 < argc) + { + lt_opt_process_env_prepend (argv[++i]); /* don't copy */ + } + else + lt_fatal ("%s missing required argument", env_prepend_opt); + continue; + } + if (strncmp (argv[i], env_append_opt, env_append_opt_len) == 0) + { + if (argv[i][env_append_opt_len] == '=') + { + const char *p = argv[i] + env_append_opt_len + 1; + lt_opt_process_env_append (p); + } + else if (argv[i][env_append_opt_len] == '\0' && i + 1 < argc) + { + lt_opt_process_env_append (argv[++i]); /* don't copy */ + } + else + lt_fatal ("%s missing required argument", env_append_opt); + continue; + } + if (strncmp (argv[i], ltwrapper_option_prefix, opt_prefix_len) == 0) + { + /* however, if there is an option in the LTWRAPPER_OPTION_PREFIX + namespace, but it is not one of the ones we know about and + have already dealt with, above (inluding dump-script), then + report an error. Otherwise, targets might begin to believe + they are allowed to use options in the LTWRAPPER_OPTION_PREFIX + namespace. The first time any user complains about this, we'll + need to make LTWRAPPER_OPTION_PREFIX a configure-time option + or a configure.ac-settable value. + */ + lt_fatal ("Unrecognized option in %s namespace: '%s'", + ltwrapper_option_prefix, argv[i]); + } + /* otherwise ... */ + newargz[++newargc] = xstrdup (argv[i]); + } + newargz[++newargc] = NULL; + + LTWRAPPER_DEBUGPRINTF (("(main) lt_argv_zero : %s\n", (lt_argv_zero ? lt_argv_zero : "<NULL>"))); + for (i = 0; i < newargc; i++) + { + LTWRAPPER_DEBUGPRINTF (("(main) newargz[%d] : %s\n", i, (newargz[i] ? newargz[i] : "<NULL>"))); + } + +EOF + + case $host_os in + mingw*) + cat <<"EOF" + /* execv doesn't actually work on mingw as expected on unix */ + rval = _spawnv (_P_WAIT, lt_argv_zero, (const char * const *) newargz); + if (rval == -1) + { + /* failed to start process */ + LTWRAPPER_DEBUGPRINTF (("(main) failed to launch target \"%s\": errno = %d\n", lt_argv_zero, errno)); + return 127; + } + return rval; +EOF + ;; + *) + cat <<"EOF" + execv (lt_argv_zero, newargz); + return rval; /* =127, but avoids unused variable warning */ +EOF + ;; + esac + + cat <<"EOF" +} + +void * +xmalloc (size_t num) +{ + void *p = (void *) malloc (num); + if (!p) + lt_fatal ("Memory exhausted"); + + return p; +} + +char * +xstrdup (const char *string) +{ + return string ? strcpy ((char *) xmalloc (strlen (string) + 1), + string) : NULL; +} + +const char * +base_name (const char *name) +{ + const char *base; + +#if defined (HAVE_DOS_BASED_FILE_SYSTEM) + /* Skip over the disk name in MSDOS pathnames. */ + if (isalpha ((unsigned char) name[0]) && name[1] == ':') + name += 2; +#endif + + for (base = name; *name; name++) + if (IS_DIR_SEPARATOR (*name)) + base = name + 1; + return base; +} + +int +check_executable (const char *path) +{ + struct stat st; + + LTWRAPPER_DEBUGPRINTF (("(check_executable) : %s\n", + path ? (*path ? path : "EMPTY!") : "NULL!")); + if ((!path) || (!*path)) + return 0; + + if ((stat (path, &st) >= 0) + && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) + return 1; + else + return 0; +} + +int +make_executable (const char *path) +{ + int rval = 0; + struct stat st; + + LTWRAPPER_DEBUGPRINTF (("(make_executable) : %s\n", + path ? (*path ? path : "EMPTY!") : "NULL!")); + if ((!path) || (!*path)) + return 0; + + if (stat (path, &st) >= 0) + { + rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR); + } + return rval; +} + +/* Searches for the full path of the wrapper. Returns + newly allocated full path name if found, NULL otherwise + Does not chase symlinks, even on platforms that support them. +*/ +char * +find_executable (const char *wrapper) +{ + int has_slash = 0; + const char *p; + const char *p_next; + /* static buffer for getcwd */ + char tmp[LT_PATHMAX + 1]; + int tmp_len; + char *concat_name; + + LTWRAPPER_DEBUGPRINTF (("(find_executable) : %s\n", + wrapper ? (*wrapper ? wrapper : "EMPTY!") : "NULL!")); + + if ((wrapper == NULL) || (*wrapper == '\0')) + return NULL; + + /* Absolute path? */ +#if defined (HAVE_DOS_BASED_FILE_SYSTEM) + if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':') + { + concat_name = xstrdup (wrapper); + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } + else + { +#endif + if (IS_DIR_SEPARATOR (wrapper[0])) + { + concat_name = xstrdup (wrapper); + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } +#if defined (HAVE_DOS_BASED_FILE_SYSTEM) + } +#endif + + for (p = wrapper; *p; p++) + if (*p == '/') + { + has_slash = 1; + break; + } + if (!has_slash) + { + /* no slashes; search PATH */ + const char *path = getenv ("PATH"); + if (path != NULL) + { + for (p = path; *p; p = p_next) + { + const char *q; + size_t p_len; + for (q = p; *q; q++) + if (IS_PATH_SEPARATOR (*q)) + break; + p_len = q - p; + p_next = (*q == '\0' ? q : q + 1); + if (p_len == 0) + { + /* empty path: current directory */ + if (getcwd (tmp, LT_PATHMAX) == NULL) + lt_fatal ("getcwd failed"); + tmp_len = strlen (tmp); + concat_name = + XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, tmp, tmp_len); + concat_name[tmp_len] = '/'; + strcpy (concat_name + tmp_len + 1, wrapper); + } + else + { + concat_name = + XMALLOC (char, p_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, p, p_len); + concat_name[p_len] = '/'; + strcpy (concat_name + p_len + 1, wrapper); + } + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } + } + /* not found in PATH; assume curdir */ + } + /* Relative path | not found in path: prepend cwd */ + if (getcwd (tmp, LT_PATHMAX) == NULL) + lt_fatal ("getcwd failed"); + tmp_len = strlen (tmp); + concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, tmp, tmp_len); + concat_name[tmp_len] = '/'; + strcpy (concat_name + tmp_len + 1, wrapper); + + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + return NULL; +} + +char * +chase_symlinks (const char *pathspec) +{ +#ifndef S_ISLNK + return xstrdup (pathspec); +#else + char buf[LT_PATHMAX]; + struct stat s; + char *tmp_pathspec = xstrdup (pathspec); + char *p; + int has_symlinks = 0; + while (strlen (tmp_pathspec) && !has_symlinks) + { + LTWRAPPER_DEBUGPRINTF (("checking path component for symlinks: %s\n", + tmp_pathspec)); + if (lstat (tmp_pathspec, &s) == 0) + { + if (S_ISLNK (s.st_mode) != 0) + { + has_symlinks = 1; + break; + } + + /* search backwards for last DIR_SEPARATOR */ + p = tmp_pathspec + strlen (tmp_pathspec) - 1; + while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) + p--; + if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) + { + /* no more DIR_SEPARATORS left */ + break; + } + *p = '\0'; + } + else + { + char *errstr = strerror (errno); + lt_fatal ("Error accessing file %s (%s)", tmp_pathspec, errstr); + } + } + XFREE (tmp_pathspec); + + if (!has_symlinks) + { + return xstrdup (pathspec); + } + + tmp_pathspec = realpath (pathspec, buf); + if (tmp_pathspec == 0) + { + lt_fatal ("Could not follow symlinks for %s", pathspec); + } + return xstrdup (tmp_pathspec); +#endif +} + +char * +strendzap (char *str, const char *pat) +{ + size_t len, patlen; + + assert (str != NULL); + assert (pat != NULL); + + len = strlen (str); + patlen = strlen (pat); + + if (patlen <= len) + { + str += len - patlen; + if (strcmp (str, pat) == 0) + *str = '\0'; + } + return str; +} + +static void +lt_error_core (int exit_status, const char *mode, + const char *message, va_list ap) +{ + fprintf (stderr, "%s: %s: ", program_name, mode); + vfprintf (stderr, message, ap); + fprintf (stderr, ".\n"); + + if (exit_status >= 0) + exit (exit_status); +} + +void +lt_fatal (const char *message, ...) +{ + va_list ap; + va_start (ap, message); + lt_error_core (EXIT_FAILURE, "FATAL", message, ap); + va_end (ap); +} + +void +lt_setenv (const char *name, const char *value) +{ + LTWRAPPER_DEBUGPRINTF (("(lt_setenv) setting '%s' to '%s'\n", + (name ? name : "<NULL>"), + (value ? value : "<NULL>"))); + { +#ifdef HAVE_SETENV + /* always make a copy, for consistency with !HAVE_SETENV */ + char *str = xstrdup (value); + setenv (name, str, 1); +#else + int len = strlen (name) + 1 + strlen (value) + 1; + char *str = XMALLOC (char, len); + sprintf (str, "%s=%s", name, value); + if (putenv (str) != EXIT_SUCCESS) + { + XFREE (str); + } +#endif + } +} + +char * +lt_extend_str (const char *orig_value, const char *add, int to_end) +{ + char *new_value; + if (orig_value && *orig_value) + { + int orig_value_len = strlen (orig_value); + int add_len = strlen (add); + new_value = XMALLOC (char, add_len + orig_value_len + 1); + if (to_end) + { + strcpy (new_value, orig_value); + strcpy (new_value + orig_value_len, add); + } + else + { + strcpy (new_value, add); + strcpy (new_value + add_len, orig_value); + } + } + else + { + new_value = xstrdup (add); + } + return new_value; +} + +int +lt_split_name_value (const char *arg, char** name, char** value) +{ + const char *p; + int len; + if (!arg || !*arg) + return 1; + + p = strchr (arg, (int)'='); + + if (!p) + return 1; + + *value = xstrdup (++p); + + len = strlen (arg) - strlen (*value); + *name = XMALLOC (char, len); + strncpy (*name, arg, len-1); + (*name)[len - 1] = '\0'; + + return 0; +} + +void +lt_opt_process_env_set (const char *arg) +{ + char *name = NULL; + char *value = NULL; + + if (lt_split_name_value (arg, &name, &value) != 0) + { + XFREE (name); + XFREE (value); + lt_fatal ("bad argument for %s: '%s'", env_set_opt, arg); + } + + lt_setenv (name, value); + XFREE (name); + XFREE (value); +} + +void +lt_opt_process_env_prepend (const char *arg) +{ + char *name = NULL; + char *value = NULL; + char *new_value = NULL; + + if (lt_split_name_value (arg, &name, &value) != 0) + { + XFREE (name); + XFREE (value); + lt_fatal ("bad argument for %s: '%s'", env_prepend_opt, arg); + } + + new_value = lt_extend_str (getenv (name), value, 0); + lt_setenv (name, new_value); + XFREE (new_value); + XFREE (name); + XFREE (value); +} + +void +lt_opt_process_env_append (const char *arg) +{ + char *name = NULL; + char *value = NULL; + char *new_value = NULL; + + if (lt_split_name_value (arg, &name, &value) != 0) + { + XFREE (name); + XFREE (value); + lt_fatal ("bad argument for %s: '%s'", env_append_opt, arg); + } + + new_value = lt_extend_str (getenv (name), value, 1); + lt_setenv (name, new_value); + XFREE (new_value); + XFREE (name); + XFREE (value); +} + +void +lt_update_exe_path (const char *name, const char *value) +{ + LTWRAPPER_DEBUGPRINTF (("(lt_update_exe_path) modifying '%s' by prepending '%s'\n", + (name ? name : "<NULL>"), + (value ? value : "<NULL>"))); + + if (name && *name && value && *value) + { + char *new_value = lt_extend_str (getenv (name), value, 0); + /* some systems can't cope with a ':'-terminated path #' */ + int len = strlen (new_value); + while (((len = strlen (new_value)) > 0) && IS_PATH_SEPARATOR (new_value[len-1])) + { + new_value[len-1] = '\0'; + } + lt_setenv (name, new_value); + XFREE (new_value); + } +} + +void +lt_update_lib_path (const char *name, const char *value) +{ + LTWRAPPER_DEBUGPRINTF (("(lt_update_lib_path) modifying '%s' by prepending '%s'\n", + (name ? name : "<NULL>"), + (value ? value : "<NULL>"))); + + if (name && *name && value && *value) + { + char *new_value = lt_extend_str (getenv (name), value, 0); + lt_setenv (name, new_value); + XFREE (new_value); + } +} + + +EOF +} +# end: func_emit_cwrapperexe_src + +# func_mode_link arg... +func_mode_link () +{ + $opt_debug + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + # It is impossible to link a dll without this setting, and + # we shouldn't force the makefile maintainer to figure out + # which system we are compiling for in order to pass an extra + # flag for every libtool invocation. + # allow_undefined=no + + # FIXME: Unfortunately, there are problems with the above when trying + # to make a dll which has undefined symbols, in which case not + # even a static library is built. For now, we need to specify + # -no-undefined on the libtool link line when we can be certain + # that all symbols are satisfied, otherwise we get a static library. + allow_undefined=yes + ;; + *) + allow_undefined=yes + ;; + esac + libtool_args=$nonopt + base_compile="$nonopt $@" + compile_command=$nonopt + finalize_command=$nonopt + + compile_rpath= + finalize_rpath= + compile_shlibpath= + finalize_shlibpath= + convenience= + old_convenience= + deplibs= + old_deplibs= + compiler_flags= + linker_flags= + dllsearchpath= + lib_search_path=`pwd` + inst_prefix_dir= + new_inherited_linker_flags= + + avoid_version=no + dlfiles= + dlprefiles= + dlself=no + export_dynamic=no + export_symbols= + export_symbols_regex= + generated= + libobjs= + ltlibs= + module=no + no_install=no + objs= + non_pic_objects= + precious_files_regex= + prefer_static_libs=no + preload=no + prev= + prevarg= + release= + rpath= + xrpath= + perm_rpath= + temp_rpath= + thread_safe=no + vinfo= + vinfo_number=no + weak_libs= + single_module="${wl}-single_module" + func_infer_tag $base_compile + + # We need to know -static, to get the right output filenames. + for arg + do + case $arg in + -shared) + test "$build_libtool_libs" != yes && \ + func_fatal_configuration "can not build a shared library" + build_old_libs=no + break + ;; + -all-static | -static | -static-libtool-libs) + case $arg in + -all-static) + if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then + func_warning "complete static linking is impossible in this configuration" + fi + if test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=yes + ;; + -static) + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=built + ;; + -static-libtool-libs) + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=yes + ;; + esac + build_libtool_libs=no + build_old_libs=yes + break + ;; + esac + done + + # See if our shared archives depend on static archives. + test -n "$old_archive_from_new_cmds" && build_old_libs=yes + + # Go through the arguments, transforming them on the way. + while test "$#" -gt 0; do + arg="$1" + shift + func_quote_for_eval "$arg" + qarg=$func_quote_for_eval_unquoted_result + func_append libtool_args " $func_quote_for_eval_result" + + # If the previous option needs an argument, assign it. + if test -n "$prev"; then + case $prev in + output) + func_append compile_command " @OUTPUT@" + func_append finalize_command " @OUTPUT@" + ;; + esac + + case $prev in + dlfiles|dlprefiles) + if test "$preload" = no; then + # Add the symbol object into the linking commands. + func_append compile_command " @SYMFILE@" + func_append finalize_command " @SYMFILE@" + preload=yes + fi + case $arg in + *.la | *.lo) ;; # We handle these cases below. + force) + if test "$dlself" = no; then + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + self) + if test "$prev" = dlprefiles; then + dlself=yes + elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then + dlself=yes + else + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + *) + if test "$prev" = dlfiles; then + dlfiles="$dlfiles $arg" + else + dlprefiles="$dlprefiles $arg" + fi + prev= + continue + ;; + esac + ;; + expsyms) + export_symbols="$arg" + test -f "$arg" \ + || func_fatal_error "symbol file \`$arg' does not exist" + prev= + continue + ;; + expsyms_regex) + export_symbols_regex="$arg" + prev= + continue + ;; + framework) + case $host in + *-*-darwin*) + case "$deplibs " in + *" $qarg.ltframework "*) ;; + *) deplibs="$deplibs $qarg.ltframework" # this is fixed later + ;; + esac + ;; + esac + prev= + continue + ;; + inst_prefix) + inst_prefix_dir="$arg" + prev= + continue + ;; + objectlist) + if test -f "$arg"; then + save_arg=$arg + moreargs= + for fil in `cat "$save_arg"` + do +# moreargs="$moreargs $fil" + arg=$fil + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if func_lalib_unsafe_p "$arg"; then + pic_object= + non_pic_object= + + # Read the .lo file + func_source "$arg" + + if test -z "$pic_object" || + test -z "$non_pic_object" || + test "$pic_object" = none && + test "$non_pic_object" = none; then + func_fatal_error "cannot find name of object for \`$arg'" + fi + + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir="$func_dirname_result" + + if test "$pic_object" != none; then + # Prepend the subdirectory the object is found in. + pic_object="$xdir$pic_object" + + if test "$prev" = dlfiles; then + if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then + dlfiles="$dlfiles $pic_object" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + # CHECK ME: I think I busted this. -Ossama + if test "$prev" = dlprefiles; then + # Preload the old-style object. + dlprefiles="$dlprefiles $pic_object" + prev= + fi + + # A PIC object. + func_append libobjs " $pic_object" + arg="$pic_object" + fi + + # Non-PIC object. + if test "$non_pic_object" != none; then + # Prepend the subdirectory the object is found in. + non_pic_object="$xdir$non_pic_object" + + # A standard non-PIC object + func_append non_pic_objects " $non_pic_object" + if test -z "$pic_object" || test "$pic_object" = none ; then + arg="$non_pic_object" + fi + else + # If the PIC object exists, use it instead. + # $xdir was prepended to $pic_object above. + non_pic_object="$pic_object" + func_append non_pic_objects " $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if $opt_dry_run; then + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir="$func_dirname_result" + + func_lo2o "$arg" + pic_object=$xdir$objdir/$func_lo2o_result + non_pic_object=$xdir$func_lo2o_result + func_append libobjs " $pic_object" + func_append non_pic_objects " $non_pic_object" + else + func_fatal_error "\`$arg' is not a valid libtool object" + fi + fi + done + else + func_fatal_error "link input file \`$arg' does not exist" + fi + arg=$save_arg + prev= + continue + ;; + precious_regex) + precious_files_regex="$arg" + prev= + continue + ;; + release) + release="-$arg" + prev= + continue + ;; + rpath | xrpath) + # We need an absolute path. + case $arg in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + func_fatal_error "only absolute run-paths are allowed" + ;; + esac + if test "$prev" = rpath; then + case "$rpath " in + *" $arg "*) ;; + *) rpath="$rpath $arg" ;; + esac + else + case "$xrpath " in + *" $arg "*) ;; + *) xrpath="$xrpath $arg" ;; + esac + fi + prev= + continue + ;; + shrext) + shrext_cmds="$arg" + prev= + continue + ;; + weak) + weak_libs="$weak_libs $arg" + prev= + continue + ;; + xcclinker) + linker_flags="$linker_flags $qarg" + compiler_flags="$compiler_flags $qarg" + prev= + func_append compile_command " $qarg" + func_append finalize_command " $qarg" + continue + ;; + xcompiler) + compiler_flags="$compiler_flags $qarg" + prev= + func_append compile_command " $qarg" + func_append finalize_command " $qarg" + continue + ;; + xlinker) + linker_flags="$linker_flags $qarg" + compiler_flags="$compiler_flags $wl$qarg" + prev= + func_append compile_command " $wl$qarg" + func_append finalize_command " $wl$qarg" + continue + ;; + *) + eval "$prev=\"\$arg\"" + prev= + continue + ;; + esac + fi # test -n "$prev" + + prevarg="$arg" + + case $arg in + -all-static) + if test -n "$link_static_flag"; then + # See comment for -static flag below, for more details. + func_append compile_command " $link_static_flag" + func_append finalize_command " $link_static_flag" + fi + continue + ;; + + -allow-undefined) + # FIXME: remove this flag sometime in the future. + func_fatal_error "\`-allow-undefined' must not be used because it is the default" + ;; + + -avoid-version) + avoid_version=yes + continue + ;; + + -dlopen) + prev=dlfiles + continue + ;; + + -dlpreopen) + prev=dlprefiles + continue + ;; + + -export-dynamic) + export_dynamic=yes + continue + ;; + + -export-symbols | -export-symbols-regex) + if test -n "$export_symbols" || test -n "$export_symbols_regex"; then + func_fatal_error "more than one -exported-symbols argument is not allowed" + fi + if test "X$arg" = "X-export-symbols"; then + prev=expsyms + else + prev=expsyms_regex + fi + continue + ;; + + -framework) + prev=framework + continue + ;; + + -inst-prefix-dir) + prev=inst_prefix + continue + ;; + + # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* + # so, if we see these flags be careful not to treat them like -L + -L[A-Z][A-Z]*:*) + case $with_gcc/$host in + no/*-*-irix* | /*-*-irix*) + func_append compile_command " $arg" + func_append finalize_command " $arg" + ;; + esac + continue + ;; + + -L*) + func_stripname '-L' '' "$arg" + dir=$func_stripname_result + if test -z "$dir"; then + if test "$#" -gt 0; then + func_fatal_error "require no space between \`-L' and \`$1'" + else + func_fatal_error "need path for \`-L' option" + fi + fi + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + absdir=`cd "$dir" && pwd` + test -z "$absdir" && \ + func_fatal_error "cannot determine absolute directory name of \`$dir'" + dir="$absdir" + ;; + esac + case "$deplibs " in + *" -L$dir "*) ;; + *) + deplibs="$deplibs -L$dir" + lib_search_path="$lib_search_path $dir" + ;; + esac + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + testbindir=`$ECHO "X$dir" | $Xsed -e 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$dir:"*) ;; + ::) dllsearchpath=$dir;; + *) dllsearchpath="$dllsearchpath:$dir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + ::) dllsearchpath=$testbindir;; + *) dllsearchpath="$dllsearchpath:$testbindir";; + esac + ;; + esac + continue + ;; + + -l*) + if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc*) + # These systems don't actually have a C or math library (as such) + continue + ;; + *-*-os2*) + # These systems don't actually have a C library (as such) + test "X$arg" = "X-lc" && continue + ;; + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + # Do not include libc due to us having libc/libc_r. + test "X$arg" = "X-lc" && continue + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C and math libraries are in the System framework + deplibs="$deplibs System.ltframework" + continue + ;; + *-*-sco3.2v5* | *-*-sco5v6*) + # Causes problems with __ctype + test "X$arg" = "X-lc" && continue + ;; + *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) + # Compiler inserts libc in the correct place for threads to work + test "X$arg" = "X-lc" && continue + ;; + esac + elif test "X$arg" = "X-lc_r"; then + case $host in + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + # Do not include libc_r directly, use -pthread flag. + continue + ;; + esac + fi + deplibs="$deplibs $arg" + continue + ;; + + -module) + module=yes + continue + ;; + + # Tru64 UNIX uses -model [arg] to determine the layout of C++ + # classes, name mangling, and exception handling. + # Darwin uses the -arch flag to determine output architecture. + -model|-arch|-isysroot) + compiler_flags="$compiler_flags $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + prev=xcompiler + continue + ;; + + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe|-threads) + compiler_flags="$compiler_flags $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + case "$new_inherited_linker_flags " in + *" $arg "*) ;; + * ) new_inherited_linker_flags="$new_inherited_linker_flags $arg" ;; + esac + continue + ;; + + -multi_module) + single_module="${wl}-multi_module" + continue + ;; + + -no-fast-install) + fast_install=no + continue + ;; + + -no-install) + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*) + # The PATH hackery in wrapper scripts is required on Windows + # and Darwin in order for the loader to find any dlls it needs. + func_warning "\`-no-install' is ignored for $host" + func_warning "assuming \`-no-fast-install' instead" + fast_install=no + ;; + *) no_install=yes ;; + esac + continue + ;; + + -no-undefined) + allow_undefined=no + continue + ;; + + -objectlist) + prev=objectlist + continue + ;; + + -o) prev=output ;; + + -precious-files-regex) + prev=precious_regex + continue + ;; + + -release) + prev=release + continue + ;; + + -rpath) + prev=rpath + continue + ;; + + -R) + prev=xrpath + continue + ;; + + -R*) + func_stripname '-R' '' "$arg" + dir=$func_stripname_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + func_fatal_error "only absolute run-paths are allowed" + ;; + esac + case "$xrpath " in + *" $dir "*) ;; + *) xrpath="$xrpath $dir" ;; + esac + continue + ;; + + -shared) + # The effects of -shared are defined in a previous loop. + continue + ;; + + -shrext) + prev=shrext + continue + ;; + + -static | -static-libtool-libs) + # The effects of -static are defined in a previous loop. + # We used to do the same as -all-static on platforms that + # didn't have a PIC flag, but the assumption that the effects + # would be equivalent was wrong. It would break on at least + # Digital Unix and AIX. + continue + ;; + + -thread-safe) + thread_safe=yes + continue + ;; + + -version-info) + prev=vinfo + continue + ;; + + -version-number) + prev=vinfo + vinfo_number=yes + continue + ;; + + -weak) + prev=weak + continue + ;; + + -Wc,*) + func_stripname '-Wc,' '' "$arg" + args=$func_stripname_result + arg= + save_ifs="$IFS"; IFS=',' + for flag in $args; do + IFS="$save_ifs" + func_quote_for_eval "$flag" + arg="$arg $wl$func_quote_for_eval_result" + compiler_flags="$compiler_flags $func_quote_for_eval_result" + done + IFS="$save_ifs" + func_stripname ' ' '' "$arg" + arg=$func_stripname_result + ;; + + -Wl,*) + func_stripname '-Wl,' '' "$arg" + args=$func_stripname_result + arg= + save_ifs="$IFS"; IFS=',' + for flag in $args; do + IFS="$save_ifs" + func_quote_for_eval "$flag" + arg="$arg $wl$func_quote_for_eval_result" + compiler_flags="$compiler_flags $wl$func_quote_for_eval_result" + linker_flags="$linker_flags $func_quote_for_eval_result" + done + IFS="$save_ifs" + func_stripname ' ' '' "$arg" + arg=$func_stripname_result + ;; + + -Xcompiler) + prev=xcompiler + continue + ;; + + -Xlinker) + prev=xlinker + continue + ;; + + -XCClinker) + prev=xcclinker + continue + ;; + + # -msg_* for osf cc + -msg_*) + func_quote_for_eval "$arg" + arg="$func_quote_for_eval_result" + ;; + + # -64, -mips[0-9] enable 64-bit mode on the SGI compiler + # -r[0-9][0-9]* specifies the processor on the SGI compiler + # -xarch=*, -xtarget=* enable 64-bit mode on the Sun compiler + # +DA*, +DD* enable 64-bit mode on the HP compiler + # -q* pass through compiler args for the IBM compiler + # -m*, -t[45]*, -txscale* pass through architecture-specific + # compiler args for GCC + # -F/path gives path to uninstalled frameworks, gcc on darwin + # -p, -pg, --coverage, -fprofile-* pass through profiling flag for GCC + # @file GCC response files + -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ + -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*) + func_quote_for_eval "$arg" + arg="$func_quote_for_eval_result" + func_append compile_command " $arg" + func_append finalize_command " $arg" + compiler_flags="$compiler_flags $arg" + continue + ;; + + # Some other compiler flag. + -* | +*) + func_quote_for_eval "$arg" + arg="$func_quote_for_eval_result" + ;; + + *.$objext) + # A standard object. + objs="$objs $arg" + ;; + + *.lo) + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if func_lalib_unsafe_p "$arg"; then + pic_object= + non_pic_object= + + # Read the .lo file + func_source "$arg" + + if test -z "$pic_object" || + test -z "$non_pic_object" || + test "$pic_object" = none && + test "$non_pic_object" = none; then + func_fatal_error "cannot find name of object for \`$arg'" + fi + + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir="$func_dirname_result" + + if test "$pic_object" != none; then + # Prepend the subdirectory the object is found in. + pic_object="$xdir$pic_object" + + if test "$prev" = dlfiles; then + if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then + dlfiles="$dlfiles $pic_object" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + # CHECK ME: I think I busted this. -Ossama + if test "$prev" = dlprefiles; then + # Preload the old-style object. + dlprefiles="$dlprefiles $pic_object" + prev= + fi + + # A PIC object. + func_append libobjs " $pic_object" + arg="$pic_object" + fi + + # Non-PIC object. + if test "$non_pic_object" != none; then + # Prepend the subdirectory the object is found in. + non_pic_object="$xdir$non_pic_object" + + # A standard non-PIC object + func_append non_pic_objects " $non_pic_object" + if test -z "$pic_object" || test "$pic_object" = none ; then + arg="$non_pic_object" + fi + else + # If the PIC object exists, use it instead. + # $xdir was prepended to $pic_object above. + non_pic_object="$pic_object" + func_append non_pic_objects " $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if $opt_dry_run; then + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir="$func_dirname_result" + + func_lo2o "$arg" + pic_object=$xdir$objdir/$func_lo2o_result + non_pic_object=$xdir$func_lo2o_result + func_append libobjs " $pic_object" + func_append non_pic_objects " $non_pic_object" + else + func_fatal_error "\`$arg' is not a valid libtool object" + fi + fi + ;; + + *.$libext) + # An archive. + deplibs="$deplibs $arg" + old_deplibs="$old_deplibs $arg" + continue + ;; + + *.la) + # A libtool-controlled library. + + if test "$prev" = dlfiles; then + # This library was specified with -dlopen. + dlfiles="$dlfiles $arg" + prev= + elif test "$prev" = dlprefiles; then + # The library was specified with -dlpreopen. + dlprefiles="$dlprefiles $arg" + prev= + else + deplibs="$deplibs $arg" + fi + continue + ;; + + # Some other compiler argument. + *) + # Unknown arguments in both finalize_command and compile_command need + # to be aesthetically quoted because they are evaled later. + func_quote_for_eval "$arg" + arg="$func_quote_for_eval_result" + ;; + esac # arg + + # Now actually substitute the argument into the commands. + if test -n "$arg"; then + func_append compile_command " $arg" + func_append finalize_command " $arg" + fi + done # argument parsing loop + + test -n "$prev" && \ + func_fatal_help "the \`$prevarg' option requires an argument" + + if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then + eval arg=\"$export_dynamic_flag_spec\" + func_append compile_command " $arg" + func_append finalize_command " $arg" + fi + + oldlibs= + # calculate the name of the file, without its directory + func_basename "$output" + outputname="$func_basename_result" + libobjs_save="$libobjs" + + if test -n "$shlibpath_var"; then + # get the directories listed in $shlibpath_var + eval shlib_search_path=\`\$ECHO \"X\${$shlibpath_var}\" \| \$Xsed -e \'s/:/ /g\'\` + else + shlib_search_path= + fi + eval sys_lib_search_path=\"$sys_lib_search_path_spec\" + eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" + + func_dirname "$output" "/" "" + output_objdir="$func_dirname_result$objdir" + # Create the object directory. + func_mkdir_p "$output_objdir" + + # Determine the type of output + case $output in + "") + func_fatal_help "you must specify an output file" + ;; + *.$libext) linkmode=oldlib ;; + *.lo | *.$objext) linkmode=obj ;; + *.la) linkmode=lib ;; + *) linkmode=prog ;; # Anything else should be a program. + esac + + specialdeplibs= + + libs= + # Find all interdependent deplibs by searching for libraries + # that are linked more than once (e.g. -la -lb -la) + for deplib in $deplibs; do + if $opt_duplicate_deps ; then + case "$libs " in + *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; + esac + fi + libs="$libs $deplib" + done + + if test "$linkmode" = lib; then + libs="$predeps $libs $compiler_lib_search_path $postdeps" + + # Compute libraries that are listed more than once in $predeps + # $postdeps and mark them as special (i.e., whose duplicates are + # not to be eliminated). + pre_post_deps= + if $opt_duplicate_compiler_generated_deps; then + for pre_post_dep in $predeps $postdeps; do + case "$pre_post_deps " in + *" $pre_post_dep "*) specialdeplibs="$specialdeplibs $pre_post_deps" ;; + esac + pre_post_deps="$pre_post_deps $pre_post_dep" + done + fi + pre_post_deps= + fi + + deplibs= + newdependency_libs= + newlib_search_path= + need_relink=no # whether we're linking any uninstalled libtool libraries + notinst_deplibs= # not-installed libtool libraries + notinst_path= # paths that contain not-installed libtool libraries + + case $linkmode in + lib) + passes="conv dlpreopen link" + for file in $dlfiles $dlprefiles; do + case $file in + *.la) ;; + *) + func_fatal_help "libraries can \`-dlopen' only libtool libraries: $file" + ;; + esac + done + ;; + prog) + compile_deplibs= + finalize_deplibs= + alldeplibs=no + newdlfiles= + newdlprefiles= + passes="conv scan dlopen dlpreopen link" + ;; + *) passes="conv" + ;; + esac + + for pass in $passes; do + # The preopen pass in lib mode reverses $deplibs; put it back here + # so that -L comes before libs that need it for instance... + if test "$linkmode,$pass" = "lib,link"; then + ## FIXME: Find the place where the list is rebuilt in the wrong + ## order, and fix it there properly + tmp_deplibs= + for deplib in $deplibs; do + tmp_deplibs="$deplib $tmp_deplibs" + done + deplibs="$tmp_deplibs" + fi + + if test "$linkmode,$pass" = "lib,link" || + test "$linkmode,$pass" = "prog,scan"; then + libs="$deplibs" + deplibs= + fi + if test "$linkmode" = prog; then + case $pass in + dlopen) libs="$dlfiles" ;; + dlpreopen) libs="$dlprefiles" ;; + link) libs="$deplibs %DEPLIBS% $dependency_libs" ;; + esac + fi + if test "$linkmode,$pass" = "lib,dlpreopen"; then + # Collect and forward deplibs of preopened libtool libs + for lib in $dlprefiles; do + # Ignore non-libtool-libs + dependency_libs= + case $lib in + *.la) func_source "$lib" ;; + esac + + # Collect preopened libtool deplibs, except any this library + # has declared as weak libs + for deplib in $dependency_libs; do + deplib_base=`$ECHO "X$deplib" | $Xsed -e "$basename"` + case " $weak_libs " in + *" $deplib_base "*) ;; + *) deplibs="$deplibs $deplib" ;; + esac + done + done + libs="$dlprefiles" + fi + if test "$pass" = dlopen; then + # Collect dlpreopened libraries + save_deplibs="$deplibs" + deplibs= + fi + + for deplib in $libs; do + lib= + found=no + case $deplib in + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe|-threads) + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + compiler_flags="$compiler_flags $deplib" + if test "$linkmode" = lib ; then + case "$new_inherited_linker_flags " in + *" $deplib "*) ;; + * ) new_inherited_linker_flags="$new_inherited_linker_flags $deplib" ;; + esac + fi + fi + continue + ;; + -l*) + if test "$linkmode" != lib && test "$linkmode" != prog; then + func_warning "\`-l' is ignored for archives/objects" + continue + fi + func_stripname '-l' '' "$deplib" + name=$func_stripname_result + if test "$linkmode" = lib; then + searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path" + else + searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path" + fi + for searchdir in $searchdirs; do + for search_ext in .la $std_shrext .so .a; do + # Search the libtool library + lib="$searchdir/lib${name}${search_ext}" + if test -f "$lib"; then + if test "$search_ext" = ".la"; then + found=yes + else + found=no + fi + break 2 + fi + done + done + if test "$found" != yes; then + # deplib doesn't seem to be a libtool library + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" + fi + continue + else # deplib is a libtool library + # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, + # We need to do some special things here, and not later. + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + case " $predeps $postdeps " in + *" $deplib "*) + if func_lalib_p "$lib"; then + library_names= + old_library= + func_source "$lib" + for l in $old_library $library_names; do + ll="$l" + done + if test "X$ll" = "X$old_library" ; then # only static version available + found=no + func_dirname "$lib" "" "." + ladir="$func_dirname_result" + lib=$ladir/$old_library + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" + fi + continue + fi + fi + ;; + *) ;; + esac + fi + fi + ;; # -l + *.ltframework) + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + if test "$linkmode" = lib ; then + case "$new_inherited_linker_flags " in + *" $deplib "*) ;; + * ) new_inherited_linker_flags="$new_inherited_linker_flags $deplib" ;; + esac + fi + fi + continue + ;; + -L*) + case $linkmode in + lib) + deplibs="$deplib $deplibs" + test "$pass" = conv && continue + newdependency_libs="$deplib $newdependency_libs" + func_stripname '-L' '' "$deplib" + newlib_search_path="$newlib_search_path $func_stripname_result" + ;; + prog) + if test "$pass" = conv; then + deplibs="$deplib $deplibs" + continue + fi + if test "$pass" = scan; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + func_stripname '-L' '' "$deplib" + newlib_search_path="$newlib_search_path $func_stripname_result" + ;; + *) + func_warning "\`-L' is ignored for archives/objects" + ;; + esac # linkmode + continue + ;; # -L + -R*) + if test "$pass" = link; then + func_stripname '-R' '' "$deplib" + dir=$func_stripname_result + # Make sure the xrpath contains only unique directories. + case "$xrpath " in + *" $dir "*) ;; + *) xrpath="$xrpath $dir" ;; + esac + fi + deplibs="$deplib $deplibs" + continue + ;; + *.la) lib="$deplib" ;; + *.$libext) + if test "$pass" = conv; then + deplibs="$deplib $deplibs" + continue + fi + case $linkmode in + lib) + # Linking convenience modules into shared libraries is allowed, + # but linking other static libraries is non-portable. + case " $dlpreconveniencelibs " in + *" $deplib "*) ;; + *) + valid_a_lib=no + case $deplibs_check_method in + match_pattern*) + set dummy $deplibs_check_method; shift + match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` + if eval "\$ECHO \"X$deplib\"" 2>/dev/null | $Xsed -e 10q \ + | $EGREP "$match_pattern_regex" > /dev/null; then + valid_a_lib=yes + fi + ;; + pass_all) + valid_a_lib=yes + ;; + esac + if test "$valid_a_lib" != yes; then + $ECHO + $ECHO "*** Warning: Trying to link with static lib archive $deplib." + $ECHO "*** I have the capability to make that library automatically link in when" + $ECHO "*** you link to this library. But I can only do this if you have a" + $ECHO "*** shared version of the library, which you do not appear to have" + $ECHO "*** because the file extensions .$libext of this argument makes me believe" + $ECHO "*** that it is just a static archive that I should not use here." + else + $ECHO + $ECHO "*** Warning: Linking the shared library $output against the" + $ECHO "*** static library $deplib is not portable!" + deplibs="$deplib $deplibs" + fi + ;; + esac + continue + ;; + prog) + if test "$pass" != link; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + continue + ;; + esac # linkmode + ;; # *.$libext + *.lo | *.$objext) + if test "$pass" = conv; then + deplibs="$deplib $deplibs" + elif test "$linkmode" = prog; then + if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then + # If there is no dlopen support or we're linking statically, + # we need to preload. + newdlprefiles="$newdlprefiles $deplib" + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + newdlfiles="$newdlfiles $deplib" + fi + fi + continue + ;; + %DEPLIBS%) + alldeplibs=yes + continue + ;; + esac # case $deplib + + if test "$found" = yes || test -f "$lib"; then : + else + func_fatal_error "cannot find the library \`$lib' or unhandled argument \`$deplib'" + fi + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$lib" \ + || func_fatal_error "\`$lib' is not a valid libtool archive" + + func_dirname "$lib" "" "." + ladir="$func_dirname_result" + + dlname= + dlopen= + dlpreopen= + libdir= + library_names= + old_library= + inherited_linker_flags= + # If the library was installed with an old release of libtool, + # it will not redefine variables installed, or shouldnotlink + installed=yes + shouldnotlink=no + avoidtemprpath= + + + # Read the .la file + func_source "$lib" + + # Convert "-framework foo" to "foo.ltframework" + if test -n "$inherited_linker_flags"; then + tmp_inherited_linker_flags=`$ECHO "X$inherited_linker_flags" | $Xsed -e 's/-framework \([^ $]*\)/\1.ltframework/g'` + for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do + case " $new_inherited_linker_flags " in + *" $tmp_inherited_linker_flag "*) ;; + *) new_inherited_linker_flags="$new_inherited_linker_flags $tmp_inherited_linker_flag";; + esac + done + fi + dependency_libs=`$ECHO "X $dependency_libs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` + if test "$linkmode,$pass" = "lib,link" || + test "$linkmode,$pass" = "prog,scan" || + { test "$linkmode" != prog && test "$linkmode" != lib; }; then + test -n "$dlopen" && dlfiles="$dlfiles $dlopen" + test -n "$dlpreopen" && dlprefiles="$dlprefiles $dlpreopen" + fi + + if test "$pass" = conv; then + # Only check for convenience libraries + deplibs="$lib $deplibs" + if test -z "$libdir"; then + if test -z "$old_library"; then + func_fatal_error "cannot find name of link library for \`$lib'" + fi + # It is a libtool convenience library, so add in its objects. + convenience="$convenience $ladir/$objdir/$old_library" + old_convenience="$old_convenience $ladir/$objdir/$old_library" + elif test "$linkmode" != prog && test "$linkmode" != lib; then + func_fatal_error "\`$lib' is not a convenience library" + fi + tmp_libs= + for deplib in $dependency_libs; do + deplibs="$deplib $deplibs" + if $opt_duplicate_deps ; then + case "$tmp_libs " in + *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; + esac + fi + tmp_libs="$tmp_libs $deplib" + done + continue + fi # $pass = conv + + + # Get the name of the library we link against. + linklib= + for l in $old_library $library_names; do + linklib="$l" + done + if test -z "$linklib"; then + func_fatal_error "cannot find name of link library for \`$lib'" + fi + + # This library was specified with -dlopen. + if test "$pass" = dlopen; then + if test -z "$libdir"; then + func_fatal_error "cannot -dlopen a convenience library: \`$lib'" + fi + if test -z "$dlname" || + test "$dlopen_support" != yes || + test "$build_libtool_libs" = no; then + # If there is no dlname, no dlopen support or we're linking + # statically, we need to preload. We also need to preload any + # dependent libraries so libltdl's deplib preloader doesn't + # bomb out in the load deplibs phase. + dlprefiles="$dlprefiles $lib $dependency_libs" + else + newdlfiles="$newdlfiles $lib" + fi + continue + fi # $pass = dlopen + + # We need an absolute path. + case $ladir in + [\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;; + *) + abs_ladir=`cd "$ladir" && pwd` + if test -z "$abs_ladir"; then + func_warning "cannot determine absolute directory name of \`$ladir'" + func_warning "passing it literally to the linker, although it might fail" + abs_ladir="$ladir" + fi + ;; + esac + func_basename "$lib" + laname="$func_basename_result" + + # Find the relevant object directory and library name. + if test "X$installed" = Xyes; then + if test ! -f "$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then + func_warning "library \`$lib' was moved." + dir="$ladir" + absdir="$abs_ladir" + libdir="$abs_ladir" + else + dir="$libdir" + absdir="$libdir" + fi + test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes + else + if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then + dir="$ladir" + absdir="$abs_ladir" + # Remove this search path later + notinst_path="$notinst_path $abs_ladir" + else + dir="$ladir/$objdir" + absdir="$abs_ladir/$objdir" + # Remove this search path later + notinst_path="$notinst_path $abs_ladir" + fi + fi # $installed = yes + func_stripname 'lib' '.la' "$laname" + name=$func_stripname_result + + # This library was specified with -dlpreopen. + if test "$pass" = dlpreopen; then + if test -z "$libdir" && test "$linkmode" = prog; then + func_fatal_error "only libraries may -dlpreopen a convenience library: \`$lib'" + fi + # Prefer using a static library (so that no silly _DYNAMIC symbols + # are required to link). + if test -n "$old_library"; then + newdlprefiles="$newdlprefiles $dir/$old_library" + # Keep a list of preopened convenience libraries to check + # that they are being used correctly in the link pass. + test -z "$libdir" && \ + dlpreconveniencelibs="$dlpreconveniencelibs $dir/$old_library" + # Otherwise, use the dlname, so that lt_dlopen finds it. + elif test -n "$dlname"; then + newdlprefiles="$newdlprefiles $dir/$dlname" + else + newdlprefiles="$newdlprefiles $dir/$linklib" + fi + fi # $pass = dlpreopen + + if test -z "$libdir"; then + # Link the convenience library + if test "$linkmode" = lib; then + deplibs="$dir/$old_library $deplibs" + elif test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$dir/$old_library $compile_deplibs" + finalize_deplibs="$dir/$old_library $finalize_deplibs" + else + deplibs="$lib $deplibs" # used for prog,scan pass + fi + continue + fi + + + if test "$linkmode" = prog && test "$pass" != link; then + newlib_search_path="$newlib_search_path $ladir" + deplibs="$lib $deplibs" + + linkalldeplibs=no + if test "$link_all_deplibs" != no || test -z "$library_names" || + test "$build_libtool_libs" = no; then + linkalldeplibs=yes + fi + + tmp_libs= + for deplib in $dependency_libs; do + case $deplib in + -L*) func_stripname '-L' '' "$deplib" + newlib_search_path="$newlib_search_path $func_stripname_result" + ;; + esac + # Need to link against all dependency_libs? + if test "$linkalldeplibs" = yes; then + deplibs="$deplib $deplibs" + else + # Need to hardcode shared library paths + # or/and link against static libraries + newdependency_libs="$deplib $newdependency_libs" + fi + if $opt_duplicate_deps ; then + case "$tmp_libs " in + *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; + esac + fi + tmp_libs="$tmp_libs $deplib" + done # for deplib + continue + fi # $linkmode = prog... + + if test "$linkmode,$pass" = "prog,link"; then + if test -n "$library_names" && + { { test "$prefer_static_libs" = no || + test "$prefer_static_libs,$installed" = "built,yes"; } || + test -z "$old_library"; }; then + # We need to hardcode the library path + if test -n "$shlibpath_var" && test -z "$avoidtemprpath" ; then + # Make sure the rpath contains only unique directories. + case "$temp_rpath:" in + *"$absdir:"*) ;; + *) temp_rpath="$temp_rpath$absdir:" ;; + esac + fi + + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) compile_rpath="$compile_rpath $absdir" + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) finalize_rpath="$finalize_rpath $libdir" + esac + ;; + esac + fi # $linkmode,$pass = prog,link... + + if test "$alldeplibs" = yes && + { test "$deplibs_check_method" = pass_all || + { test "$build_libtool_libs" = yes && + test -n "$library_names"; }; }; then + # We only need to search for static libraries + continue + fi + fi + + link_static=no # Whether the deplib will be linked statically + use_static_libs=$prefer_static_libs + if test "$use_static_libs" = built && test "$installed" = yes; then + use_static_libs=no + fi + if test -n "$library_names" && + { test "$use_static_libs" = no || test -z "$old_library"; }; then + case $host in + *cygwin* | *mingw* | *cegcc*) + # No point in relinking DLLs because paths are not encoded + notinst_deplibs="$notinst_deplibs $lib" + need_relink=no + ;; + *) + if test "$installed" = no; then + notinst_deplibs="$notinst_deplibs $lib" + need_relink=yes + fi + ;; + esac + # This is a shared library + + # Warn about portability, can't link against -module's on some + # systems (darwin). Don't bleat about dlopened modules though! + dlopenmodule="" + for dlpremoduletest in $dlprefiles; do + if test "X$dlpremoduletest" = "X$lib"; then + dlopenmodule="$dlpremoduletest" + break + fi + done + if test -z "$dlopenmodule" && test "$shouldnotlink" = yes && test "$pass" = link; then + $ECHO + if test "$linkmode" = prog; then + $ECHO "*** Warning: Linking the executable $output against the loadable module" + else + $ECHO "*** Warning: Linking the shared library $output against the loadable module" + fi + $ECHO "*** $linklib is not portable!" + fi + if test "$linkmode" = lib && + test "$hardcode_into_libs" = yes; then + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) compile_rpath="$compile_rpath $absdir" + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) finalize_rpath="$finalize_rpath $libdir" + esac + ;; + esac + fi + + if test -n "$old_archive_from_expsyms_cmds"; then + # figure out the soname + set dummy $library_names + shift + realname="$1" + shift + libname=`eval "\\$ECHO \"$libname_spec\""` + # use dlname if we got it. it's perfectly good, no? + if test -n "$dlname"; then + soname="$dlname" + elif test -n "$soname_spec"; then + # bleh windows + case $host in + *cygwin* | mingw* | *cegcc*) + func_arith $current - $age + major=$func_arith_result + versuffix="-$major" + ;; + esac + eval soname=\"$soname_spec\" + else + soname="$realname" + fi + + # Make a new name for the extract_expsyms_cmds to use + soroot="$soname" + func_basename "$soroot" + soname="$func_basename_result" + func_stripname 'lib' '.dll' "$soname" + newlib=libimp-$func_stripname_result.a + + # If the library has no export list, then create one now + if test -f "$output_objdir/$soname-def"; then : + else + func_verbose "extracting exported symbol list from \`$soname'" + func_execute_cmds "$extract_expsyms_cmds" 'exit $?' + fi + + # Create $newlib + if test -f "$output_objdir/$newlib"; then :; else + func_verbose "generating import library for \`$soname'" + func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?' + fi + # make sure the library variables are pointing to the new library + dir=$output_objdir + linklib=$newlib + fi # test -n "$old_archive_from_expsyms_cmds" + + if test "$linkmode" = prog || test "$mode" != relink; then + add_shlibpath= + add_dir= + add= + lib_linked=yes + case $hardcode_action in + immediate | unsupported) + if test "$hardcode_direct" = no; then + add="$dir/$linklib" + case $host in + *-*-sco3.2v5.0.[024]*) add_dir="-L$dir" ;; + *-*-sysv4*uw2*) add_dir="-L$dir" ;; + *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \ + *-*-unixware7*) add_dir="-L$dir" ;; + *-*-darwin* ) + # if the lib is a (non-dlopened) module then we can not + # link against it, someone is ignoring the earlier warnings + if /usr/bin/file -L $add 2> /dev/null | + $GREP ": [^:]* bundle" >/dev/null ; then + if test "X$dlopenmodule" != "X$lib"; then + $ECHO "*** Warning: lib $linklib is a module, not a shared library" + if test -z "$old_library" ; then + $ECHO + $ECHO "*** And there doesn't seem to be a static archive available" + $ECHO "*** The link will probably fail, sorry" + else + add="$dir/$old_library" + fi + elif test -n "$old_library"; then + add="$dir/$old_library" + fi + fi + esac + elif test "$hardcode_minus_L" = no; then + case $host in + *-*-sunos*) add_shlibpath="$dir" ;; + esac + add_dir="-L$dir" + add="-l$name" + elif test "$hardcode_shlibpath_var" = no; then + add_shlibpath="$dir" + add="-l$name" + else + lib_linked=no + fi + ;; + relink) + if test "$hardcode_direct" = yes && + test "$hardcode_direct_absolute" = no; then + add="$dir/$linklib" + elif test "$hardcode_minus_L" = yes; then + add_dir="-L$dir" + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case $libdir in + [\\/]*) + add_dir="$add_dir -L$inst_prefix_dir$libdir" + ;; + esac + fi + add="-l$name" + elif test "$hardcode_shlibpath_var" = yes; then + add_shlibpath="$dir" + add="-l$name" + else + lib_linked=no + fi + ;; + *) lib_linked=no ;; + esac + + if test "$lib_linked" != yes; then + func_fatal_configuration "unsupported hardcode properties" + fi + + if test -n "$add_shlibpath"; then + case :$compile_shlibpath: in + *":$add_shlibpath:"*) ;; + *) compile_shlibpath="$compile_shlibpath$add_shlibpath:" ;; + esac + fi + if test "$linkmode" = prog; then + test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" + test -n "$add" && compile_deplibs="$add $compile_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + if test "$hardcode_direct" != yes && + test "$hardcode_minus_L" != yes && + test "$hardcode_shlibpath_var" = yes; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;; + esac + fi + fi + fi + + if test "$linkmode" = prog || test "$mode" = relink; then + add_shlibpath= + add_dir= + add= + # Finalize command for both is simple: just hardcode it. + if test "$hardcode_direct" = yes && + test "$hardcode_direct_absolute" = no; then + add="$libdir/$linklib" + elif test "$hardcode_minus_L" = yes; then + add_dir="-L$libdir" + add="-l$name" + elif test "$hardcode_shlibpath_var" = yes; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;; + esac + add="-l$name" + elif test "$hardcode_automatic" = yes; then + if test -n "$inst_prefix_dir" && + test -f "$inst_prefix_dir$libdir/$linklib" ; then + add="$inst_prefix_dir$libdir/$linklib" + else + add="$libdir/$linklib" + fi + else + # We cannot seem to hardcode it, guess we'll fake it. + add_dir="-L$libdir" + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case $libdir in + [\\/]*) + add_dir="$add_dir -L$inst_prefix_dir$libdir" + ;; + esac + fi + add="-l$name" + fi + + if test "$linkmode" = prog; then + test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" + test -n "$add" && finalize_deplibs="$add $finalize_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + fi + fi + elif test "$linkmode" = prog; then + # Here we assume that one of hardcode_direct or hardcode_minus_L + # is not unsupported. This is valid on all known static and + # shared platforms. + if test "$hardcode_direct" != unsupported; then + test -n "$old_library" && linklib="$old_library" + compile_deplibs="$dir/$linklib $compile_deplibs" + finalize_deplibs="$dir/$linklib $finalize_deplibs" + else + compile_deplibs="-l$name -L$dir $compile_deplibs" + finalize_deplibs="-l$name -L$dir $finalize_deplibs" + fi + elif test "$build_libtool_libs" = yes; then + # Not a shared library + if test "$deplibs_check_method" != pass_all; then + # We're trying link a shared library against a static one + # but the system doesn't support it. + + # Just print a warning and add the library to dependency_libs so + # that the program can be linked against the static library. + $ECHO + $ECHO "*** Warning: This system can not link to static lib archive $lib." + $ECHO "*** I have the capability to make that library automatically link in when" + $ECHO "*** you link to this library. But I can only do this if you have a" + $ECHO "*** shared version of the library, which you do not appear to have." + if test "$module" = yes; then + $ECHO "*** But as you try to build a module library, libtool will still create " + $ECHO "*** a static module, that should work as long as the dlopening application" + $ECHO "*** is linked with the -dlopen flag to resolve symbols at runtime." + if test -z "$global_symbol_pipe"; then + $ECHO + $ECHO "*** However, this would only work if libtool was able to extract symbol" + $ECHO "*** lists from a program, using \`nm' or equivalent, but libtool could" + $ECHO "*** not find such a program. So, this module is probably useless." + $ECHO "*** \`nm' from GNU binutils and a full rebuild may help." + fi + if test "$build_old_libs" = no; then + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + else + deplibs="$dir/$old_library $deplibs" + link_static=yes + fi + fi # link shared/static library? + + if test "$linkmode" = lib; then + if test -n "$dependency_libs" && + { test "$hardcode_into_libs" != yes || + test "$build_old_libs" = yes || + test "$link_static" = yes; }; then + # Extract -R from dependency_libs + temp_deplibs= + for libdir in $dependency_libs; do + case $libdir in + -R*) func_stripname '-R' '' "$libdir" + temp_xrpath=$func_stripname_result + case " $xrpath " in + *" $temp_xrpath "*) ;; + *) xrpath="$xrpath $temp_xrpath";; + esac;; + *) temp_deplibs="$temp_deplibs $libdir";; + esac + done + dependency_libs="$temp_deplibs" + fi + + newlib_search_path="$newlib_search_path $absdir" + # Link against this library + test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs" + # ... and its dependency_libs + tmp_libs= + for deplib in $dependency_libs; do + newdependency_libs="$deplib $newdependency_libs" + if $opt_duplicate_deps ; then + case "$tmp_libs " in + *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; + esac + fi + tmp_libs="$tmp_libs $deplib" + done + + if test "$link_all_deplibs" != no; then + # Add the search paths of all dependency libraries + for deplib in $dependency_libs; do + case $deplib in + -L*) path="$deplib" ;; + *.la) + func_dirname "$deplib" "" "." + dir="$func_dirname_result" + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;; + *) + absdir=`cd "$dir" && pwd` + if test -z "$absdir"; then + func_warning "cannot determine absolute directory name of \`$dir'" + absdir="$dir" + fi + ;; + esac + if $GREP "^installed=no" $deplib > /dev/null; then + case $host in + *-*-darwin*) + depdepl= + eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` + if test -n "$deplibrary_names" ; then + for tmp in $deplibrary_names ; do + depdepl=$tmp + done + if test -f "$absdir/$objdir/$depdepl" ; then + depdepl="$absdir/$objdir/$depdepl" + darwin_install_name=`${OTOOL} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` + if test -z "$darwin_install_name"; then + darwin_install_name=`${OTOOL64} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` + fi + compiler_flags="$compiler_flags ${wl}-dylib_file ${wl}${darwin_install_name}:${depdepl}" + linker_flags="$linker_flags -dylib_file ${darwin_install_name}:${depdepl}" + path= + fi + fi + ;; + *) + path="-L$absdir/$objdir" + ;; + esac + else + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` + test -z "$libdir" && \ + func_fatal_error "\`$deplib' is not a valid libtool archive" + test "$absdir" != "$libdir" && \ + func_warning "\`$deplib' seems to be moved" + + path="-L$absdir" + fi + ;; + esac + case " $deplibs " in + *" $path "*) ;; + *) deplibs="$path $deplibs" ;; + esac + done + fi # link_all_deplibs != no + fi # linkmode = lib + done # for deplib in $libs + if test "$pass" = link; then + if test "$linkmode" = "prog"; then + compile_deplibs="$new_inherited_linker_flags $compile_deplibs" + finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs" + else + compiler_flags="$compiler_flags "`$ECHO "X $new_inherited_linker_flags" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` + fi + fi + dependency_libs="$newdependency_libs" + if test "$pass" = dlpreopen; then + # Link the dlpreopened libraries before other libraries + for deplib in $save_deplibs; do + deplibs="$deplib $deplibs" + done + fi + if test "$pass" != dlopen; then + if test "$pass" != conv; then + # Make sure lib_search_path contains only unique directories. + lib_search_path= + for dir in $newlib_search_path; do + case "$lib_search_path " in + *" $dir "*) ;; + *) lib_search_path="$lib_search_path $dir" ;; + esac + done + newlib_search_path= + fi + + if test "$linkmode,$pass" != "prog,link"; then + vars="deplibs" + else + vars="compile_deplibs finalize_deplibs" + fi + for var in $vars dependency_libs; do + # Add libraries to $var in reverse order + eval tmp_libs=\"\$$var\" + new_libs= + for deplib in $tmp_libs; do + # FIXME: Pedantically, this is the right thing to do, so + # that some nasty dependency loop isn't accidentally + # broken: + #new_libs="$deplib $new_libs" + # Pragmatically, this seems to cause very few problems in + # practice: + case $deplib in + -L*) new_libs="$deplib $new_libs" ;; + -R*) ;; + *) + # And here is the reason: when a library appears more + # than once as an explicit dependence of a library, or + # is implicitly linked in more than once by the + # compiler, it is considered special, and multiple + # occurrences thereof are not removed. Compare this + # with having the same library being listed as a + # dependency of multiple other libraries: in this case, + # we know (pedantically, we assume) the library does not + # need to be listed more than once, so we keep only the + # last copy. This is not always right, but it is rare + # enough that we require users that really mean to play + # such unportable linking tricks to link the library + # using -Wl,-lname, so that libtool does not consider it + # for duplicate removal. + case " $specialdeplibs " in + *" $deplib "*) new_libs="$deplib $new_libs" ;; + *) + case " $new_libs " in + *" $deplib "*) ;; + *) new_libs="$deplib $new_libs" ;; + esac + ;; + esac + ;; + esac + done + tmp_libs= + for deplib in $new_libs; do + case $deplib in + -L*) + case " $tmp_libs " in + *" $deplib "*) ;; + *) tmp_libs="$tmp_libs $deplib" ;; + esac + ;; + *) tmp_libs="$tmp_libs $deplib" ;; + esac + done + eval $var=\"$tmp_libs\" + done # for var + fi + # Last step: remove runtime libs from dependency_libs + # (they stay in deplibs) + tmp_libs= + for i in $dependency_libs ; do + case " $predeps $postdeps $compiler_lib_search_path " in + *" $i "*) + i="" + ;; + esac + if test -n "$i" ; then + tmp_libs="$tmp_libs $i" + fi + done + dependency_libs=$tmp_libs + done # for pass + if test "$linkmode" = prog; then + dlfiles="$newdlfiles" + fi + if test "$linkmode" = prog || test "$linkmode" = lib; then + dlprefiles="$newdlprefiles" + fi + + case $linkmode in + oldlib) + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + func_warning "\`-dlopen' is ignored for archives" + fi + + case " $deplibs" in + *\ -l* | *\ -L*) + func_warning "\`-l' and \`-L' are ignored for archives" ;; + esac + + test -n "$rpath" && \ + func_warning "\`-rpath' is ignored for archives" + + test -n "$xrpath" && \ + func_warning "\`-R' is ignored for archives" + + test -n "$vinfo" && \ + func_warning "\`-version-info/-version-number' is ignored for archives" + + test -n "$release" && \ + func_warning "\`-release' is ignored for archives" + + test -n "$export_symbols$export_symbols_regex" && \ + func_warning "\`-export-symbols' is ignored for archives" + + # Now set the variables for building old libraries. + build_libtool_libs=no + oldlibs="$output" + objs="$objs$old_deplibs" + ;; + + lib) + # Make sure we only generate libraries of the form `libNAME.la'. + case $outputname in + lib*) + func_stripname 'lib' '.la' "$outputname" + name=$func_stripname_result + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + ;; + *) + test "$module" = no && \ + func_fatal_help "libtool library \`$output' must begin with \`lib'" + + if test "$need_lib_prefix" != no; then + # Add the "lib" prefix for modules if required + func_stripname '' '.la' "$outputname" + name=$func_stripname_result + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + else + func_stripname '' '.la' "$outputname" + libname=$func_stripname_result + fi + ;; + esac + + if test -n "$objs"; then + if test "$deplibs_check_method" != pass_all; then + func_fatal_error "cannot build libtool library \`$output' from non-libtool objects on this host:$objs" + else + $ECHO + $ECHO "*** Warning: Linking the shared library $output against the non-libtool" + $ECHO "*** objects $objs is not portable!" + libobjs="$libobjs $objs" + fi + fi + + test "$dlself" != no && \ + func_warning "\`-dlopen self' is ignored for libtool libraries" + + set dummy $rpath + shift + test "$#" -gt 1 && \ + func_warning "ignoring multiple \`-rpath's for a libtool library" + + install_libdir="$1" + + oldlibs= + if test -z "$rpath"; then + if test "$build_libtool_libs" = yes; then + # Building a libtool convenience library. + # Some compilers have problems with a `.al' extension so + # convenience libraries should have the same extension an + # archive normally would. + oldlibs="$output_objdir/$libname.$libext $oldlibs" + build_libtool_libs=convenience + build_old_libs=yes + fi + + test -n "$vinfo" && \ + func_warning "\`-version-info/-version-number' is ignored for convenience libraries" + + test -n "$release" && \ + func_warning "\`-release' is ignored for convenience libraries" + else + + # Parse the version information argument. + save_ifs="$IFS"; IFS=':' + set dummy $vinfo 0 0 0 + shift + IFS="$save_ifs" + + test -n "$7" && \ + func_fatal_help "too many parameters to \`-version-info'" + + # convert absolute version numbers to libtool ages + # this retains compatibility with .la files and attempts + # to make the code below a bit more comprehensible + + case $vinfo_number in + yes) + number_major="$1" + number_minor="$2" + number_revision="$3" + # + # There are really only two kinds -- those that + # use the current revision as the major version + # and those that subtract age and use age as + # a minor version. But, then there is irix + # which has an extra 1 added just for fun + # + case $version_type in + darwin|linux|osf|windows|none) + func_arith $number_major + $number_minor + current=$func_arith_result + age="$number_minor" + revision="$number_revision" + ;; + freebsd-aout|freebsd-elf|sunos) + current="$number_major" + revision="$number_minor" + age="0" + ;; + irix|nonstopux) + func_arith $number_major + $number_minor + current=$func_arith_result + age="$number_minor" + revision="$number_minor" + lt_irix_increment=no + ;; + esac + ;; + no) + current="$1" + revision="$2" + age="$3" + ;; + esac + + # Check that each of the things are valid numbers. + case $current in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "CURRENT \`$current' must be a nonnegative integer" + func_fatal_error "\`$vinfo' is not valid version information" + ;; + esac + + case $revision in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "REVISION \`$revision' must be a nonnegative integer" + func_fatal_error "\`$vinfo' is not valid version information" + ;; + esac + + case $age in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "AGE \`$age' must be a nonnegative integer" + func_fatal_error "\`$vinfo' is not valid version information" + ;; + esac + + if test "$age" -gt "$current"; then + func_error "AGE \`$age' is greater than the current interface number \`$current'" + func_fatal_error "\`$vinfo' is not valid version information" + fi + + # Calculate the version variables. + major= + versuffix= + verstring= + case $version_type in + none) ;; + + darwin) + # Like Linux, but with the current version available in + # verstring for coding it into the library header + func_arith $current - $age + major=.$func_arith_result + versuffix="$major.$age.$revision" + # Darwin ld doesn't like 0 for these options... + func_arith $current + 1 + minor_current=$func_arith_result + xlcverstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision" + verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" + ;; + + freebsd-aout) + major=".$current" + versuffix=".$current.$revision"; + ;; + + freebsd-elf) + major=".$current" + versuffix=".$current" + ;; + + irix | nonstopux) + if test "X$lt_irix_increment" = "Xno"; then + func_arith $current - $age + else + func_arith $current - $age + 1 + fi + major=$func_arith_result + + case $version_type in + nonstopux) verstring_prefix=nonstopux ;; + *) verstring_prefix=sgi ;; + esac + verstring="$verstring_prefix$major.$revision" + + # Add in all the interfaces that we are compatible with. + loop=$revision + while test "$loop" -ne 0; do + func_arith $revision - $loop + iface=$func_arith_result + func_arith $loop - 1 + loop=$func_arith_result + verstring="$verstring_prefix$major.$iface:$verstring" + done + + # Before this point, $major must not contain `.'. + major=.$major + versuffix="$major.$revision" + ;; + + linux) + func_arith $current - $age + major=.$func_arith_result + versuffix="$major.$age.$revision" + ;; + + osf) + func_arith $current - $age + major=.$func_arith_result + versuffix=".$current.$age.$revision" + verstring="$current.$age.$revision" + + # Add in all the interfaces that we are compatible with. + loop=$age + while test "$loop" -ne 0; do + func_arith $current - $loop + iface=$func_arith_result + func_arith $loop - 1 + loop=$func_arith_result + verstring="$verstring:${iface}.0" + done + + # Make executables depend on our current version. + verstring="$verstring:${current}.0" + ;; + + qnx) + major=".$current" + versuffix=".$current" + ;; + + sunos) + major=".$current" + versuffix=".$current.$revision" + ;; + + windows) + # Use '-' rather than '.', since we only want one + # extension on DOS 8.3 filesystems. + func_arith $current - $age + major=$func_arith_result + versuffix="-$major" + ;; + + *) + func_fatal_configuration "unknown library version type \`$version_type'" + ;; + esac + + # Clear the version info if we defaulted, and they specified a release. + if test -z "$vinfo" && test -n "$release"; then + major= + case $version_type in + darwin) + # we can't check for "0.0" in archive_cmds due to quoting + # problems, so we reset it completely + verstring= + ;; + *) + verstring="0.0" + ;; + esac + if test "$need_version" = no; then + versuffix= + else + versuffix=".0.0" + fi + fi + + # Remove version info from name if versioning should be avoided + if test "$avoid_version" = yes && test "$need_version" = no; then + major= + versuffix= + verstring="" + fi + + # Check to see if the archive will have undefined symbols. + if test "$allow_undefined" = yes; then + if test "$allow_undefined_flag" = unsupported; then + func_warning "undefined symbols not allowed in $host shared libraries" + build_libtool_libs=no + build_old_libs=yes + fi + else + # Don't allow undefined symbols. + allow_undefined_flag="$no_undefined_flag" + fi + + fi + + func_generate_dlsyms "$libname" "$libname" "yes" + libobjs="$libobjs $symfileobj" + test "X$libobjs" = "X " && libobjs= + + if test "$mode" != relink; then + # Remove our outputs, but don't remove object files since they + # may have been created when compiling PIC objects. + removelist= + tempremovelist=`$ECHO "$output_objdir/*"` + for p in $tempremovelist; do + case $p in + *.$objext | *.gcno) + ;; + $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*) + if test "X$precious_files_regex" != "X"; then + if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 + then + continue + fi + fi + removelist="$removelist $p" + ;; + *) ;; + esac + done + test -n "$removelist" && \ + func_show_eval "${RM}r \$removelist" + fi + + # Now set the variables for building old libraries. + if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then + oldlibs="$oldlibs $output_objdir/$libname.$libext" + + # Transform .lo files to .o files. + oldobjs="$objs "`$ECHO "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e "$lo2o" | $NL2SP` + fi + + # Eliminate all temporary directories. + #for path in $notinst_path; do + # lib_search_path=`$ECHO "X$lib_search_path " | $Xsed -e "s% $path % %g"` + # deplibs=`$ECHO "X$deplibs " | $Xsed -e "s% -L$path % %g"` + # dependency_libs=`$ECHO "X$dependency_libs " | $Xsed -e "s% -L$path % %g"` + #done + + if test -n "$xrpath"; then + # If the user specified any rpath flags, then add them. + temp_xrpath= + for libdir in $xrpath; do + temp_xrpath="$temp_xrpath -R$libdir" + case "$finalize_rpath " in + *" $libdir "*) ;; + *) finalize_rpath="$finalize_rpath $libdir" ;; + esac + done + if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then + dependency_libs="$temp_xrpath $dependency_libs" + fi + fi + + # Make sure dlfiles contains only unique files that won't be dlpreopened + old_dlfiles="$dlfiles" + dlfiles= + for lib in $old_dlfiles; do + case " $dlprefiles $dlfiles " in + *" $lib "*) ;; + *) dlfiles="$dlfiles $lib" ;; + esac + done + + # Make sure dlprefiles contains only unique files + old_dlprefiles="$dlprefiles" + dlprefiles= + for lib in $old_dlprefiles; do + case "$dlprefiles " in + *" $lib "*) ;; + *) dlprefiles="$dlprefiles $lib" ;; + esac + done + + if test "$build_libtool_libs" = yes; then + if test -n "$rpath"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc*) + # these systems don't actually have a c library (as such)! + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C library is in the System framework + deplibs="$deplibs System.ltframework" + ;; + *-*-netbsd*) + # Don't link with libc until the a.out ld.so is fixed. + ;; + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + # Do not include libc due to us having libc/libc_r. + ;; + *-*-sco3.2v5* | *-*-sco5v6*) + # Causes problems with __ctype + ;; + *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) + # Compiler inserts libc in the correct place for threads to work + ;; + *) + # Add libc to deplibs on all other systems if necessary. + if test "$build_libtool_need_lc" = "yes"; then + deplibs="$deplibs -lc" + fi + ;; + esac + fi + + # Transform deplibs into only deplibs that can be linked in shared. + name_save=$name + libname_save=$libname + release_save=$release + versuffix_save=$versuffix + major_save=$major + # I'm not sure if I'm treating the release correctly. I think + # release should show up in the -l (ie -lgmp5) so we don't want to + # add it in twice. Is that correct? + release="" + versuffix="" + major="" + newdeplibs= + droppeddeps=no + case $deplibs_check_method in + pass_all) + # Don't check for shared/static. Everything works. + # This might be a little naive. We might want to check + # whether the library exists or not. But this is on + # osf3 & osf4 and I'm not really sure... Just + # implementing what was already the behavior. + newdeplibs=$deplibs + ;; + test_compile) + # This code stresses the "libraries are programs" paradigm to its + # limits. Maybe even breaks it. We compile a program, linking it + # against the deplibs as a proxy for the library. Then we can check + # whether they linked in statically or dynamically with ldd. + $opt_dry_run || $RM conftest.c + cat > conftest.c <<EOF + int main() { return 0; } +EOF + $opt_dry_run || $RM conftest + if $LTCC $LTCFLAGS -o conftest conftest.c $deplibs; then + ldd_output=`ldd conftest` + for i in $deplibs; do + case $i in + -l*) + func_stripname -l '' "$i" + name=$func_stripname_result + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + case " $predeps $postdeps " in + *" $i "*) + newdeplibs="$newdeplibs $i" + i="" + ;; + esac + fi + if test -n "$i" ; then + libname=`eval "\\$ECHO \"$libname_spec\""` + deplib_matches=`eval "\\$ECHO \"$library_names_spec\""` + set dummy $deplib_matches; shift + deplib_match=$1 + if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then + newdeplibs="$newdeplibs $i" + else + droppeddeps=yes + $ECHO + $ECHO "*** Warning: dynamic linker does not accept needed library $i." + $ECHO "*** I have the capability to make that library automatically link in when" + $ECHO "*** you link to this library. But I can only do this if you have a" + $ECHO "*** shared version of the library, which I believe you do not have" + $ECHO "*** because a test_compile did reveal that the linker did not use it for" + $ECHO "*** its dynamic dependency list that programs get resolved with at runtime." + fi + fi + ;; + *) + newdeplibs="$newdeplibs $i" + ;; + esac + done + else + # Error occurred in the first compile. Let's try to salvage + # the situation: Compile a separate program for each library. + for i in $deplibs; do + case $i in + -l*) + func_stripname -l '' "$i" + name=$func_stripname_result + $opt_dry_run || $RM conftest + if $LTCC $LTCFLAGS -o conftest conftest.c $i; then + ldd_output=`ldd conftest` + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + case " $predeps $postdeps " in + *" $i "*) + newdeplibs="$newdeplibs $i" + i="" + ;; + esac + fi + if test -n "$i" ; then + libname=`eval "\\$ECHO \"$libname_spec\""` + deplib_matches=`eval "\\$ECHO \"$library_names_spec\""` + set dummy $deplib_matches; shift + deplib_match=$1 + if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then + newdeplibs="$newdeplibs $i" + else + droppeddeps=yes + $ECHO + $ECHO "*** Warning: dynamic linker does not accept needed library $i." + $ECHO "*** I have the capability to make that library automatically link in when" + $ECHO "*** you link to this library. But I can only do this if you have a" + $ECHO "*** shared version of the library, which you do not appear to have" + $ECHO "*** because a test_compile did reveal that the linker did not use this one" + $ECHO "*** as a dynamic dependency that programs can get resolved with at runtime." + fi + fi + else + droppeddeps=yes + $ECHO + $ECHO "*** Warning! Library $i is needed by this library but I was not able to" + $ECHO "*** make it link in! You will probably need to install it or some" + $ECHO "*** library that it depends on before this library will be fully" + $ECHO "*** functional. Installing it before continuing would be even better." + fi + ;; + *) + newdeplibs="$newdeplibs $i" + ;; + esac + done + fi + ;; + file_magic*) + set dummy $deplibs_check_method; shift + file_magic_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` + for a_deplib in $deplibs; do + case $a_deplib in + -l*) + func_stripname -l '' "$a_deplib" + name=$func_stripname_result + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + case " $predeps $postdeps " in + *" $a_deplib "*) + newdeplibs="$newdeplibs $a_deplib" + a_deplib="" + ;; + esac + fi + if test -n "$a_deplib" ; then + libname=`eval "\\$ECHO \"$libname_spec\""` + for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do + potential_libs=`ls $i/$libname[.-]* 2>/dev/null` + for potent_lib in $potential_libs; do + # Follow soft links. + if ls -lLd "$potent_lib" 2>/dev/null | + $GREP " -> " >/dev/null; then + continue + fi + # The statement above tries to avoid entering an + # endless loop below, in case of cyclic links. + # We might still enter an endless loop, since a link + # loop can be closed while we follow links, + # but so what? + potlib="$potent_lib" + while test -h "$potlib" 2>/dev/null; do + potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'` + case $potliblink in + [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";; + *) potlib=`$ECHO "X$potlib" | $Xsed -e 's,[^/]*$,,'`"$potliblink";; + esac + done + if eval $file_magic_cmd \"\$potlib\" 2>/dev/null | + $SED -e 10q | + $EGREP "$file_magic_regex" > /dev/null; then + newdeplibs="$newdeplibs $a_deplib" + a_deplib="" + break 2 + fi + done + done + fi + if test -n "$a_deplib" ; then + droppeddeps=yes + $ECHO + $ECHO "*** Warning: linker path does not have real file for library $a_deplib." + $ECHO "*** I have the capability to make that library automatically link in when" + $ECHO "*** you link to this library. But I can only do this if you have a" + $ECHO "*** shared version of the library, which you do not appear to have" + $ECHO "*** because I did check the linker path looking for a file starting" + if test -z "$potlib" ; then + $ECHO "*** with $libname but no candidates were found. (...for file magic test)" + else + $ECHO "*** with $libname and none of the candidates passed a file format test" + $ECHO "*** using a file magic. Last file checked: $potlib" + fi + fi + ;; + *) + # Add a -L argument. + newdeplibs="$newdeplibs $a_deplib" + ;; + esac + done # Gone through all deplibs. + ;; + match_pattern*) + set dummy $deplibs_check_method; shift + match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` + for a_deplib in $deplibs; do + case $a_deplib in + -l*) + func_stripname -l '' "$a_deplib" + name=$func_stripname_result + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + case " $predeps $postdeps " in + *" $a_deplib "*) + newdeplibs="$newdeplibs $a_deplib" + a_deplib="" + ;; + esac + fi + if test -n "$a_deplib" ; then + libname=`eval "\\$ECHO \"$libname_spec\""` + for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do + potential_libs=`ls $i/$libname[.-]* 2>/dev/null` + for potent_lib in $potential_libs; do + potlib="$potent_lib" # see symlink-check above in file_magic test + if eval "\$ECHO \"X$potent_lib\"" 2>/dev/null | $Xsed -e 10q | \ + $EGREP "$match_pattern_regex" > /dev/null; then + newdeplibs="$newdeplibs $a_deplib" + a_deplib="" + break 2 + fi + done + done + fi + if test -n "$a_deplib" ; then + droppeddeps=yes + $ECHO + $ECHO "*** Warning: linker path does not have real file for library $a_deplib." + $ECHO "*** I have the capability to make that library automatically link in when" + $ECHO "*** you link to this library. But I can only do this if you have a" + $ECHO "*** shared version of the library, which you do not appear to have" + $ECHO "*** because I did check the linker path looking for a file starting" + if test -z "$potlib" ; then + $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)" + else + $ECHO "*** with $libname and none of the candidates passed a file format test" + $ECHO "*** using a regex pattern. Last file checked: $potlib" + fi + fi + ;; + *) + # Add a -L argument. + newdeplibs="$newdeplibs $a_deplib" + ;; + esac + done # Gone through all deplibs. + ;; + none | unknown | *) + newdeplibs="" + tmp_deplibs=`$ECHO "X $deplibs" | $Xsed \ + -e 's/ -lc$//' -e 's/ -[LR][^ ]*//g'` + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + for i in $predeps $postdeps ; do + # can't use Xsed below, because $i might contain '/' + tmp_deplibs=`$ECHO "X $tmp_deplibs" | $Xsed -e "s,$i,,"` + done + fi + if $ECHO "X $tmp_deplibs" | $Xsed -e 's/[ ]//g' | + $GREP . >/dev/null; then + $ECHO + if test "X$deplibs_check_method" = "Xnone"; then + $ECHO "*** Warning: inter-library dependencies are not supported in this platform." + else + $ECHO "*** Warning: inter-library dependencies are not known to be supported." + fi + $ECHO "*** All declared inter-library dependencies are being dropped." + droppeddeps=yes + fi + ;; + esac + versuffix=$versuffix_save + major=$major_save + release=$release_save + libname=$libname_save + name=$name_save + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library with the System framework + newdeplibs=`$ECHO "X $newdeplibs" | $Xsed -e 's/ -lc / System.ltframework /'` + ;; + esac + + if test "$droppeddeps" = yes; then + if test "$module" = yes; then + $ECHO + $ECHO "*** Warning: libtool could not satisfy all declared inter-library" + $ECHO "*** dependencies of module $libname. Therefore, libtool will create" + $ECHO "*** a static module, that should work as long as the dlopening" + $ECHO "*** application is linked with the -dlopen flag." + if test -z "$global_symbol_pipe"; then + $ECHO + $ECHO "*** However, this would only work if libtool was able to extract symbol" + $ECHO "*** lists from a program, using \`nm' or equivalent, but libtool could" + $ECHO "*** not find such a program. So, this module is probably useless." + $ECHO "*** \`nm' from GNU binutils and a full rebuild may help." + fi + if test "$build_old_libs" = no; then + oldlibs="$output_objdir/$libname.$libext" + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + else + $ECHO "*** The inter-library dependencies that have been dropped here will be" + $ECHO "*** automatically added whenever a program is linked with this library" + $ECHO "*** or is declared to -dlopen it." + + if test "$allow_undefined" = no; then + $ECHO + $ECHO "*** Since this library must not contain undefined symbols," + $ECHO "*** because either the platform does not support them or" + $ECHO "*** it was explicitly requested with -no-undefined," + $ECHO "*** libtool will only create a static version of it." + if test "$build_old_libs" = no; then + oldlibs="$output_objdir/$libname.$libext" + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + fi + fi + # Done checking deplibs! + deplibs=$newdeplibs + fi + # Time to change all our "foo.ltframework" stuff back to "-framework foo" + case $host in + *-*-darwin*) + newdeplibs=`$ECHO "X $newdeplibs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` + new_inherited_linker_flags=`$ECHO "X $new_inherited_linker_flags" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` + deplibs=`$ECHO "X $deplibs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` + ;; + esac + + # move library search paths that coincide with paths to not yet + # installed libraries to the beginning of the library search list + new_libs= + for path in $notinst_path; do + case " $new_libs " in + *" -L$path/$objdir "*) ;; + *) + case " $deplibs " in + *" -L$path/$objdir "*) + new_libs="$new_libs -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) new_libs="$new_libs $deplib" ;; + esac + ;; + *) new_libs="$new_libs $deplib" ;; + esac + done + deplibs="$new_libs" + + # All the library-specific variables (install_libdir is set above). + library_names= + old_library= + dlname= + + # Test again, we may have decided not to build it any more + if test "$build_libtool_libs" = yes; then + if test "$hardcode_into_libs" = yes; then + # Hardcode the library paths + hardcode_libdirs= + dep_rpath= + rpath="$finalize_rpath" + test "$mode" != relink && rpath="$compile_rpath$rpath" + for libdir in $rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs="$libdir" + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + dep_rpath="$dep_rpath $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) perm_rpath="$perm_rpath $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir="$hardcode_libdirs" + if test -n "$hardcode_libdir_flag_spec_ld"; then + eval dep_rpath=\"$hardcode_libdir_flag_spec_ld\" + else + eval dep_rpath=\"$hardcode_libdir_flag_spec\" + fi + fi + if test -n "$runpath_var" && test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + rpath="$rpath$dir:" + done + eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" + fi + test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" + fi + + shlibpath="$finalize_shlibpath" + test "$mode" != relink && shlibpath="$compile_shlibpath$shlibpath" + if test -n "$shlibpath"; then + eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" + fi + + # Get the real and link names of the library. + eval shared_ext=\"$shrext_cmds\" + eval library_names=\"$library_names_spec\" + set dummy $library_names + shift + realname="$1" + shift + + if test -n "$soname_spec"; then + eval soname=\"$soname_spec\" + else + soname="$realname" + fi + if test -z "$dlname"; then + dlname=$soname + fi + + lib="$output_objdir/$realname" + linknames= + for link + do + linknames="$linknames $link" + done + + # Use standard objects if they are pic + test -z "$pic_flag" && libobjs=`$ECHO "X$libobjs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + test "X$libobjs" = "X " && libobjs= + + delfiles= + if test -n "$export_symbols" && test -n "$include_expsyms"; then + $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp" + export_symbols="$output_objdir/$libname.uexp" + delfiles="$delfiles $export_symbols" + fi + + orig_export_symbols= + case $host_os in + cygwin* | mingw* | cegcc*) + if test -n "$export_symbols" && test -z "$export_symbols_regex"; then + # exporting using user supplied symfile + if test "x`$SED 1q $export_symbols`" != xEXPORTS; then + # and it's NOT already a .def file. Must figure out + # which of the given symbols are data symbols and tag + # them as such. So, trigger use of export_symbols_cmds. + # export_symbols gets reassigned inside the "prepare + # the list of exported symbols" if statement, so the + # include_expsyms logic still works. + orig_export_symbols="$export_symbols" + export_symbols= + always_export_symbols=yes + fi + fi + ;; + esac + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then + func_verbose "generating symbol list for \`$libname.la'" + export_symbols="$output_objdir/$libname.exp" + $opt_dry_run || $RM $export_symbols + cmds=$export_symbols_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + func_len " $cmd" + len=$func_len_result + if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then + func_show_eval "$cmd" 'exit $?' + skipped_export=false + else + # The command line is too long to execute in one step. + func_verbose "using reloadable object file for export list..." + skipped_export=: + # Break out early, otherwise skipped_export may be + # set to false by a later but shorter cmd. + break + fi + done + IFS="$save_ifs" + if test -n "$export_symbols_regex" && test "X$skipped_export" != "X:"; then + func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + func_show_eval '$MV "${export_symbols}T" "$export_symbols"' + fi + fi + fi + + if test -n "$export_symbols" && test -n "$include_expsyms"; then + tmp_export_symbols="$export_symbols" + test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" + $opt_dry_run || eval '$ECHO "X$include_expsyms" | $Xsed | $SP2NL >> "$tmp_export_symbols"' + fi + + if test "X$skipped_export" != "X:" && test -n "$orig_export_symbols"; then + # The given exports_symbols file has to be filtered, so filter it. + func_verbose "filter symbol list for \`$libname.la' to tag DATA exports" + # FIXME: $output_objdir/$libname.filter potentially contains lots of + # 's' commands which not all seds can handle. GNU sed should be fine + # though. Also, the filter scales superlinearly with the number of + # global variables. join(1) would be nice here, but unfortunately + # isn't a blessed tool. + $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter + delfiles="$delfiles $export_symbols $output_objdir/$libname.filter" + export_symbols=$output_objdir/$libname.def + $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols + fi + + tmp_deplibs= + for test_deplib in $deplibs; do + case " $convenience " in + *" $test_deplib "*) ;; + *) + tmp_deplibs="$tmp_deplibs $test_deplib" + ;; + esac + done + deplibs="$tmp_deplibs" + + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec" && + test "$compiler_needs_object" = yes && + test -z "$libobjs"; then + # extract the archives, so we have objects to list. + # TODO: could optimize this to just extract one archive. + whole_archive_flag_spec= + fi + if test -n "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + test "X$libobjs" = "X " && libobjs= + else + gentop="$output_objdir/${outputname}x" + generated="$generated $gentop" + + func_extract_archives $gentop $convenience + libobjs="$libobjs $func_extract_archives_result" + test "X$libobjs" = "X " && libobjs= + fi + fi + + if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then + eval flag=\"$thread_safe_flag_spec\" + linker_flags="$linker_flags $flag" + fi + + # Make a backup of the uninstalled library when relinking + if test "$mode" = relink; then + $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $? + fi + + # Do each of the archive commands. + if test "$module" = yes && test -n "$module_cmds" ; then + if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then + eval test_cmds=\"$module_expsym_cmds\" + cmds=$module_expsym_cmds + else + eval test_cmds=\"$module_cmds\" + cmds=$module_cmds + fi + else + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + eval test_cmds=\"$archive_expsym_cmds\" + cmds=$archive_expsym_cmds + else + eval test_cmds=\"$archive_cmds\" + cmds=$archive_cmds + fi + fi + + if test "X$skipped_export" != "X:" && + func_len " $test_cmds" && + len=$func_len_result && + test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then + : + else + # The command line is too long to link in one step, link piecewise + # or, if using GNU ld and skipped_export is not :, use a linker + # script. + + # Save the value of $output and $libobjs because we want to + # use them later. If we have whole_archive_flag_spec, we + # want to use save_libobjs as it was before + # whole_archive_flag_spec was expanded, because we can't + # assume the linker understands whole_archive_flag_spec. + # This may have to be revisited, in case too many + # convenience libraries get linked in and end up exceeding + # the spec. + if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + fi + save_output=$output + output_la=`$ECHO "X$output" | $Xsed -e "$basename"` + + # Clear the reloadable object creation command queue and + # initialize k to one. + test_cmds= + concat_cmds= + objlist= + last_robj= + k=1 + + if test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "$with_gnu_ld" = yes; then + output=${output_objdir}/${output_la}.lnkscript + func_verbose "creating GNU ld script: $output" + $ECHO 'INPUT (' > $output + for obj in $save_libobjs + do + $ECHO "$obj" >> $output + done + $ECHO ')' >> $output + delfiles="$delfiles $output" + elif test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "X$file_list_spec" != X; then + output=${output_objdir}/${output_la}.lnk + func_verbose "creating linker input file list: $output" + : > $output + set x $save_libobjs + shift + firstobj= + if test "$compiler_needs_object" = yes; then + firstobj="$1 " + shift + fi + for obj + do + $ECHO "$obj" >> $output + done + delfiles="$delfiles $output" + output=$firstobj\"$file_list_spec$output\" + else + if test -n "$save_libobjs"; then + func_verbose "creating reloadable object files..." + output=$output_objdir/$output_la-${k}.$objext + eval test_cmds=\"$reload_cmds\" + func_len " $test_cmds" + len0=$func_len_result + len=$len0 + + # Loop over the list of objects to be linked. + for obj in $save_libobjs + do + func_len " $obj" + func_arith $len + $func_len_result + len=$func_arith_result + if test "X$objlist" = X || + test "$len" -lt "$max_cmd_len"; then + func_append objlist " $obj" + else + # The command $test_cmds is almost too long, add a + # command to the queue. + if test "$k" -eq 1 ; then + # The first file doesn't have a previous command to add. + eval concat_cmds=\"$reload_cmds $objlist $last_robj\" + else + # All subsequent reloadable object files will link in + # the last one created. + eval concat_cmds=\"\$concat_cmds~$reload_cmds $objlist $last_robj~\$RM $last_robj\" + fi + last_robj=$output_objdir/$output_la-${k}.$objext + func_arith $k + 1 + k=$func_arith_result + output=$output_objdir/$output_la-${k}.$objext + objlist=$obj + func_len " $last_robj" + func_arith $len0 + $func_len_result + len=$func_arith_result + fi + done + # Handle the remaining objects by creating one last + # reloadable object file. All subsequent reloadable object + # files will link in the last one created. + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\${concat_cmds}$reload_cmds $objlist $last_robj\" + if test -n "$last_robj"; then + eval concat_cmds=\"\${concat_cmds}~\$RM $last_robj\" + fi + delfiles="$delfiles $output" + + else + output= + fi + + if ${skipped_export-false}; then + func_verbose "generating symbol list for \`$libname.la'" + export_symbols="$output_objdir/$libname.exp" + $opt_dry_run || $RM $export_symbols + libobjs=$output + # Append the command to create the export file. + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\" + if test -n "$last_robj"; then + eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" + fi + fi + + test -n "$save_libobjs" && + func_verbose "creating a temporary reloadable object file: $output" + + # Loop through the commands generated above and execute them. + save_ifs="$IFS"; IFS='~' + for cmd in $concat_cmds; do + IFS="$save_ifs" + $opt_silent || { + func_quote_for_expand "$cmd" + eval "func_echo $func_quote_for_expand_result" + } + $opt_dry_run || eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test "$mode" = relink; then + ( cd "$output_objdir" && \ + $RM "${realname}T" && \ + $MV "${realname}U" "$realname" ) + fi + + exit $lt_exit + } + done + IFS="$save_ifs" + + if test -n "$export_symbols_regex" && ${skipped_export-false}; then + func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + func_show_eval '$MV "${export_symbols}T" "$export_symbols"' + fi + fi + + if ${skipped_export-false}; then + if test -n "$export_symbols" && test -n "$include_expsyms"; then + tmp_export_symbols="$export_symbols" + test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" + $opt_dry_run || eval '$ECHO "X$include_expsyms" | $Xsed | $SP2NL >> "$tmp_export_symbols"' + fi + + if test -n "$orig_export_symbols"; then + # The given exports_symbols file has to be filtered, so filter it. + func_verbose "filter symbol list for \`$libname.la' to tag DATA exports" + # FIXME: $output_objdir/$libname.filter potentially contains lots of + # 's' commands which not all seds can handle. GNU sed should be fine + # though. Also, the filter scales superlinearly with the number of + # global variables. join(1) would be nice here, but unfortunately + # isn't a blessed tool. + $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter + delfiles="$delfiles $export_symbols $output_objdir/$libname.filter" + export_symbols=$output_objdir/$libname.def + $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols + fi + fi + + libobjs=$output + # Restore the value of output. + output=$save_output + + if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + test "X$libobjs" = "X " && libobjs= + fi + # Expand the library linking commands again to reset the + # value of $libobjs for piecewise linking. + + # Do each of the archive commands. + if test "$module" = yes && test -n "$module_cmds" ; then + if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then + cmds=$module_expsym_cmds + else + cmds=$module_cmds + fi + else + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + cmds=$archive_expsym_cmds + else + cmds=$archive_cmds + fi + fi + fi + + if test -n "$delfiles"; then + # Append the command to remove temporary files to $cmds. + eval cmds=\"\$cmds~\$RM $delfiles\" + fi + + # Add any objects from preloaded convenience libraries + if test -n "$dlprefiles"; then + gentop="$output_objdir/${outputname}x" + generated="$generated $gentop" + + func_extract_archives $gentop $dlprefiles + libobjs="$libobjs $func_extract_archives_result" + test "X$libobjs" = "X " && libobjs= + fi + + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $opt_silent || { + func_quote_for_expand "$cmd" + eval "func_echo $func_quote_for_expand_result" + } + $opt_dry_run || eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test "$mode" = relink; then + ( cd "$output_objdir" && \ + $RM "${realname}T" && \ + $MV "${realname}U" "$realname" ) + fi + + exit $lt_exit + } + done + IFS="$save_ifs" + + # Restore the uninstalled library and exit + if test "$mode" = relink; then + $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $? + + if test -n "$convenience"; then + if test -z "$whole_archive_flag_spec"; then + func_show_eval '${RM}r "$gentop"' + fi + fi + + exit $EXIT_SUCCESS + fi + + # Create links to the real library. + for linkname in $linknames; do + if test "$realname" != "$linkname"; then + func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?' + fi + done + + # If -module or -export-dynamic was specified, set the dlname. + if test "$module" = yes || test "$export_dynamic" = yes; then + # On all known operating systems, these are identical. + dlname="$soname" + fi + fi + ;; + + obj) + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + func_warning "\`-dlopen' is ignored for objects" + fi + + case " $deplibs" in + *\ -l* | *\ -L*) + func_warning "\`-l' and \`-L' are ignored for objects" ;; + esac + + test -n "$rpath" && \ + func_warning "\`-rpath' is ignored for objects" + + test -n "$xrpath" && \ + func_warning "\`-R' is ignored for objects" + + test -n "$vinfo" && \ + func_warning "\`-version-info' is ignored for objects" + + test -n "$release" && \ + func_warning "\`-release' is ignored for objects" + + case $output in + *.lo) + test -n "$objs$old_deplibs" && \ + func_fatal_error "cannot build library object \`$output' from non-libtool objects" + + libobj=$output + func_lo2o "$libobj" + obj=$func_lo2o_result + ;; + *) + libobj= + obj="$output" + ;; + esac + + # Delete the old objects. + $opt_dry_run || $RM $obj $libobj + + # Objects from convenience libraries. This assumes + # single-version convenience libraries. Whenever we create + # different ones for PIC/non-PIC, this we'll have to duplicate + # the extraction. + reload_conv_objs= + gentop= + # reload_cmds runs $LD directly, so let us get rid of + # -Wl from whole_archive_flag_spec and hope we can get by with + # turning comma into space.. + wl= + + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec"; then + eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\" + reload_conv_objs=$reload_objs\ `$ECHO "X$tmp_whole_archive_flags" | $Xsed -e 's|,| |g'` + else + gentop="$output_objdir/${obj}x" + generated="$generated $gentop" + + func_extract_archives $gentop $convenience + reload_conv_objs="$reload_objs $func_extract_archives_result" + fi + fi + + # Create the old-style object. + reload_objs="$objs$old_deplibs "`$ECHO "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}$'/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test + + output="$obj" + func_execute_cmds "$reload_cmds" 'exit $?' + + # Exit if we aren't doing a library object file. + if test -z "$libobj"; then + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + exit $EXIT_SUCCESS + fi + + if test "$build_libtool_libs" != yes; then + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + # Create an invalid libtool object if no PIC, so that we don't + # accidentally link it into a program. + # $show "echo timestamp > $libobj" + # $opt_dry_run || eval "echo timestamp > $libobj" || exit $? + exit $EXIT_SUCCESS + fi + + if test -n "$pic_flag" || test "$pic_mode" != default; then + # Only do commands if we really have different PIC objects. + reload_objs="$libobjs $reload_conv_objs" + output="$libobj" + func_execute_cmds "$reload_cmds" 'exit $?' + fi + + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + exit $EXIT_SUCCESS + ;; + + prog) + case $host in + *cygwin*) func_stripname '' '.exe' "$output" + output=$func_stripname_result.exe;; + esac + test -n "$vinfo" && \ + func_warning "\`-version-info' is ignored for programs" + + test -n "$release" && \ + func_warning "\`-release' is ignored for programs" + + test "$preload" = yes \ + && test "$dlopen_support" = unknown \ + && test "$dlopen_self" = unknown \ + && test "$dlopen_self_static" = unknown && \ + func_warning "\`LT_INIT([dlopen])' not used. Assuming no dlopen support." + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library is the System framework + compile_deplibs=`$ECHO "X $compile_deplibs" | $Xsed -e 's/ -lc / System.ltframework /'` + finalize_deplibs=`$ECHO "X $finalize_deplibs" | $Xsed -e 's/ -lc / System.ltframework /'` + ;; + esac + + case $host in + *-*-darwin*) + # Don't allow lazy linking, it breaks C++ global constructors + # But is supposedly fixed on 10.4 or later (yay!). + if test "$tagname" = CXX ; then + case ${MACOSX_DEPLOYMENT_TARGET-10.0} in + 10.[0123]) + compile_command="$compile_command ${wl}-bind_at_load" + finalize_command="$finalize_command ${wl}-bind_at_load" + ;; + esac + fi + # Time to change all our "foo.ltframework" stuff back to "-framework foo" + compile_deplibs=`$ECHO "X $compile_deplibs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` + finalize_deplibs=`$ECHO "X $finalize_deplibs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` + ;; + esac + + + # move library search paths that coincide with paths to not yet + # installed libraries to the beginning of the library search list + new_libs= + for path in $notinst_path; do + case " $new_libs " in + *" -L$path/$objdir "*) ;; + *) + case " $compile_deplibs " in + *" -L$path/$objdir "*) + new_libs="$new_libs -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $compile_deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) new_libs="$new_libs $deplib" ;; + esac + ;; + *) new_libs="$new_libs $deplib" ;; + esac + done + compile_deplibs="$new_libs" + + + compile_command="$compile_command $compile_deplibs" + finalize_command="$finalize_command $finalize_deplibs" + + if test -n "$rpath$xrpath"; then + # If the user specified any rpath flags, then add them. + for libdir in $rpath $xrpath; do + # This is the magic to use -rpath. + case "$finalize_rpath " in + *" $libdir "*) ;; + *) finalize_rpath="$finalize_rpath $libdir" ;; + esac + done + fi + + # Now hardcode the library paths + rpath= + hardcode_libdirs= + for libdir in $compile_rpath $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs="$libdir" + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + rpath="$rpath $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) perm_rpath="$perm_rpath $libdir" ;; + esac + fi + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + testbindir=`${ECHO} "$libdir" | ${SED} -e 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$libdir:"*) ;; + ::) dllsearchpath=$libdir;; + *) dllsearchpath="$dllsearchpath:$libdir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + ::) dllsearchpath=$testbindir;; + *) dllsearchpath="$dllsearchpath:$testbindir";; + esac + ;; + esac + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir="$hardcode_libdirs" + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + compile_rpath="$rpath" + + rpath= + hardcode_libdirs= + for libdir in $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs="$libdir" + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + rpath="$rpath $flag" + fi + elif test -n "$runpath_var"; then + case "$finalize_perm_rpath " in + *" $libdir "*) ;; + *) finalize_perm_rpath="$finalize_perm_rpath $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir="$hardcode_libdirs" + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + finalize_rpath="$rpath" + + if test -n "$libobjs" && test "$build_old_libs" = yes; then + # Transform all the library objects into standard objects. + compile_command=`$ECHO "X$compile_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + finalize_command=`$ECHO "X$finalize_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + fi + + func_generate_dlsyms "$outputname" "@PROGRAM@" "no" + + # template prelinking step + if test -n "$prelink_cmds"; then + func_execute_cmds "$prelink_cmds" 'exit $?' + fi + + wrappers_required=yes + case $host in + *cygwin* | *mingw* ) + if test "$build_libtool_libs" != yes; then + wrappers_required=no + fi + ;; + *cegcc) + # Disable wrappers for cegcc, we are cross compiling anyway. + wrappers_required=no + ;; + *) + if test "$need_relink" = no || test "$build_libtool_libs" != yes; then + wrappers_required=no + fi + ;; + esac + if test "$wrappers_required" = no; then + # Replace the output file specification. + compile_command=`$ECHO "X$compile_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` + link_command="$compile_command$compile_rpath" + + # We have no uninstalled library dependencies, so finalize right now. + exit_status=0 + func_show_eval "$link_command" 'exit_status=$?' + + # Delete the generated files. + if test -f "$output_objdir/${outputname}S.${objext}"; then + func_show_eval '$RM "$output_objdir/${outputname}S.${objext}"' + fi + + exit $exit_status + fi + + if test -n "$compile_shlibpath$finalize_shlibpath"; then + compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" + fi + if test -n "$finalize_shlibpath"; then + finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" + fi + + compile_var= + finalize_var= + if test -n "$runpath_var"; then + if test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + rpath="$rpath$dir:" + done + compile_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + if test -n "$finalize_perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $finalize_perm_rpath; do + rpath="$rpath$dir:" + done + finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + fi + + if test "$no_install" = yes; then + # We don't need to create a wrapper script. + link_command="$compile_var$compile_command$compile_rpath" + # Replace the output file specification. + link_command=`$ECHO "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` + # Delete the old output file. + $opt_dry_run || $RM $output + # Link the executable and exit + func_show_eval "$link_command" 'exit $?' + exit $EXIT_SUCCESS + fi + + if test "$hardcode_action" = relink; then + # Fast installation is not supported + link_command="$compile_var$compile_command$compile_rpath" + relink_command="$finalize_var$finalize_command$finalize_rpath" + + func_warning "this platform does not like uninstalled shared libraries" + func_warning "\`$output' will be relinked during installation" + else + if test "$fast_install" != no; then + link_command="$finalize_var$compile_command$finalize_rpath" + if test "$fast_install" = yes; then + relink_command=`$ECHO "X$compile_var$compile_command$compile_rpath" | $Xsed -e 's%@OUTPUT@%\$progdir/\$file%g'` + else + # fast_install is set to needless + relink_command= + fi + else + link_command="$compile_var$compile_command$compile_rpath" + relink_command="$finalize_var$finalize_command$finalize_rpath" + fi + fi + + # Replace the output file specification. + link_command=`$ECHO "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` + + # Delete the old output files. + $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname + + func_show_eval "$link_command" 'exit $?' + + # Now create the wrapper script. + func_verbose "creating $output" + + # Quote the relink command for shipping. + if test -n "$relink_command"; then + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + func_quote_for_eval "$var_value" + relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" + fi + done + relink_command="(cd `pwd`; $relink_command)" + relink_command=`$ECHO "X$relink_command" | $Xsed -e "$sed_quote_subst"` + fi + + # Quote $ECHO for shipping. + if test "X$ECHO" = "X$SHELL $progpath --fallback-echo"; then + case $progpath in + [\\/]* | [A-Za-z]:[\\/]*) qecho="$SHELL $progpath --fallback-echo";; + *) qecho="$SHELL `pwd`/$progpath --fallback-echo";; + esac + qecho=`$ECHO "X$qecho" | $Xsed -e "$sed_quote_subst"` + else + qecho=`$ECHO "X$ECHO" | $Xsed -e "$sed_quote_subst"` + fi + + # Only actually do things if not in dry run mode. + $opt_dry_run || { + # win32 will think the script is a binary if it has + # a .exe suffix, so we strip it off here. + case $output in + *.exe) func_stripname '' '.exe' "$output" + output=$func_stripname_result ;; + esac + # test for cygwin because mv fails w/o .exe extensions + case $host in + *cygwin*) + exeext=.exe + func_stripname '' '.exe' "$outputname" + outputname=$func_stripname_result ;; + *) exeext= ;; + esac + case $host in + *cygwin* | *mingw* ) + func_dirname_and_basename "$output" "" "." + output_name=$func_basename_result + output_path=$func_dirname_result + cwrappersource="$output_path/$objdir/lt-$output_name.c" + cwrapper="$output_path/$output_name.exe" + $RM $cwrappersource $cwrapper + trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15 + + func_emit_cwrapperexe_src > $cwrappersource + + # The wrapper executable is built using the $host compiler, + # because it contains $host paths and files. If cross- + # compiling, it, like the target executable, must be + # executed on the $host or under an emulation environment. + $opt_dry_run || { + $LTCC $LTCFLAGS -o $cwrapper $cwrappersource + $STRIP $cwrapper + } + + # Now, create the wrapper script for func_source use: + func_ltwrapper_scriptname $cwrapper + $RM $func_ltwrapper_scriptname_result + trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15 + $opt_dry_run || { + # note: this script will not be executed, so do not chmod. + if test "x$build" = "x$host" ; then + $cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result + else + func_emit_wrapper no > $func_ltwrapper_scriptname_result + fi + } + ;; + * ) + $RM $output + trap "$RM $output; exit $EXIT_FAILURE" 1 2 15 + + func_emit_wrapper no > $output + chmod +x $output + ;; + esac + } + exit $EXIT_SUCCESS + ;; + esac + + # See if we need to build an old-fashioned archive. + for oldlib in $oldlibs; do + + if test "$build_libtool_libs" = convenience; then + oldobjs="$libobjs_save $symfileobj" + addlibs="$convenience" + build_libtool_libs=no + else + if test "$build_libtool_libs" = module; then + oldobjs="$libobjs_save" + build_libtool_libs=no + else + oldobjs="$old_deplibs $non_pic_objects" + if test "$preload" = yes && test -f "$symfileobj"; then + oldobjs="$oldobjs $symfileobj" + fi + fi + addlibs="$old_convenience" + fi + + if test -n "$addlibs"; then + gentop="$output_objdir/${outputname}x" + generated="$generated $gentop" + + func_extract_archives $gentop $addlibs + oldobjs="$oldobjs $func_extract_archives_result" + fi + + # Do each command in the archive commands. + if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then + cmds=$old_archive_from_new_cmds + else + + # Add any objects from preloaded convenience libraries + if test -n "$dlprefiles"; then + gentop="$output_objdir/${outputname}x" + generated="$generated $gentop" + + func_extract_archives $gentop $dlprefiles + oldobjs="$oldobjs $func_extract_archives_result" + fi + + # POSIX demands no paths to be encoded in archives. We have + # to avoid creating archives with duplicate basenames if we + # might have to extract them afterwards, e.g., when creating a + # static archive out of a convenience library, or when linking + # the entirety of a libtool archive into another (currently + # not supported by libtool). + if (for obj in $oldobjs + do + func_basename "$obj" + $ECHO "$func_basename_result" + done | sort | sort -uc >/dev/null 2>&1); then + : + else + $ECHO "copying selected object files to avoid basename conflicts..." + gentop="$output_objdir/${outputname}x" + generated="$generated $gentop" + func_mkdir_p "$gentop" + save_oldobjs=$oldobjs + oldobjs= + counter=1 + for obj in $save_oldobjs + do + func_basename "$obj" + objbase="$func_basename_result" + case " $oldobjs " in + " ") oldobjs=$obj ;; + *[\ /]"$objbase "*) + while :; do + # Make sure we don't pick an alternate name that also + # overlaps. + newobj=lt$counter-$objbase + func_arith $counter + 1 + counter=$func_arith_result + case " $oldobjs " in + *[\ /]"$newobj "*) ;; + *) if test ! -f "$gentop/$newobj"; then break; fi ;; + esac + done + func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" + oldobjs="$oldobjs $gentop/$newobj" + ;; + *) oldobjs="$oldobjs $obj" ;; + esac + done + fi + eval cmds=\"$old_archive_cmds\" + + func_len " $cmds" + len=$func_len_result + if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then + cmds=$old_archive_cmds + else + # the command line is too long to link in one step, link in parts + func_verbose "using piecewise archive linking..." + save_RANLIB=$RANLIB + RANLIB=: + objlist= + concat_cmds= + save_oldobjs=$oldobjs + oldobjs= + # Is there a better way of finding the last object in the list? + for obj in $save_oldobjs + do + last_oldobj=$obj + done + eval test_cmds=\"$old_archive_cmds\" + func_len " $test_cmds" + len0=$func_len_result + len=$len0 + for obj in $save_oldobjs + do + func_len " $obj" + func_arith $len + $func_len_result + len=$func_arith_result + func_append objlist " $obj" + if test "$len" -lt "$max_cmd_len"; then + : + else + # the above command should be used before it gets too long + oldobjs=$objlist + if test "$obj" = "$last_oldobj" ; then + RANLIB=$save_RANLIB + fi + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\${concat_cmds}$old_archive_cmds\" + objlist= + len=$len0 + fi + done + RANLIB=$save_RANLIB + oldobjs=$objlist + if test "X$oldobjs" = "X" ; then + eval cmds=\"\$concat_cmds\" + else + eval cmds=\"\$concat_cmds~\$old_archive_cmds\" + fi + fi + fi + func_execute_cmds "$cmds" 'exit $?' + done + + test -n "$generated" && \ + func_show_eval "${RM}r$generated" + + # Now create the libtool archive. + case $output in + *.la) + old_library= + test "$build_old_libs" = yes && old_library="$libname.$libext" + func_verbose "creating $output" + + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + func_quote_for_eval "$var_value" + relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" + fi + done + # Quote the link command for shipping. + relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" + relink_command=`$ECHO "X$relink_command" | $Xsed -e "$sed_quote_subst"` + if test "$hardcode_automatic" = yes ; then + relink_command= + fi + + # Only create the output if not a dry run. + $opt_dry_run || { + for installed in no yes; do + if test "$installed" = yes; then + if test -z "$install_libdir"; then + break + fi + output="$output_objdir/$outputname"i + # Replace all uninstalled libtool libraries with the installed ones + newdependency_libs= + for deplib in $dependency_libs; do + case $deplib in + *.la) + func_basename "$deplib" + name="$func_basename_result" + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` + test -z "$libdir" && \ + func_fatal_error "\`$deplib' is not a valid libtool archive" + newdependency_libs="$newdependency_libs $libdir/$name" + ;; + *) newdependency_libs="$newdependency_libs $deplib" ;; + esac + done + dependency_libs="$newdependency_libs" + newdlfiles= + + for lib in $dlfiles; do + case $lib in + *.la) + func_basename "$lib" + name="$func_basename_result" + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + test -z "$libdir" && \ + func_fatal_error "\`$lib' is not a valid libtool archive" + newdlfiles="$newdlfiles $libdir/$name" + ;; + *) newdlfiles="$newdlfiles $lib" ;; + esac + done + dlfiles="$newdlfiles" + newdlprefiles= + for lib in $dlprefiles; do + case $lib in + *.la) + # Only pass preopened files to the pseudo-archive (for + # eventual linking with the app. that links it) if we + # didn't already link the preopened objects directly into + # the library: + func_basename "$lib" + name="$func_basename_result" + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + test -z "$libdir" && \ + func_fatal_error "\`$lib' is not a valid libtool archive" + newdlprefiles="$newdlprefiles $libdir/$name" + ;; + esac + done + dlprefiles="$newdlprefiles" + else + newdlfiles= + for lib in $dlfiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; + *) abs=`pwd`"/$lib" ;; + esac + newdlfiles="$newdlfiles $abs" + done + dlfiles="$newdlfiles" + newdlprefiles= + for lib in $dlprefiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; + *) abs=`pwd`"/$lib" ;; + esac + newdlprefiles="$newdlprefiles $abs" + done + dlprefiles="$newdlprefiles" + fi + $RM $output + # place dlname in correct position for cygwin + tdlname=$dlname + case $host,$output,$installed,$module,$dlname in + *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) tdlname=../bin/$dlname ;; + esac + $ECHO > $output "\ +# $outputname - a libtool library file +# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# The name that we can dlopen(3). +dlname='$tdlname' + +# Names of this library. +library_names='$library_names' + +# The name of the static archive. +old_library='$old_library' + +# Linker flags that can not go in dependency_libs. +inherited_linker_flags='$new_inherited_linker_flags' + +# Libraries that this one depends upon. +dependency_libs='$dependency_libs' + +# Names of additional weak libraries provided by this library +weak_library_names='$weak_libs' + +# Version information for $libname. +current=$current +age=$age +revision=$revision + +# Is this an already installed library? +installed=$installed + +# Should we warn about portability when linking against -modules? +shouldnotlink=$module + +# Files to dlopen/dlpreopen +dlopen='$dlfiles' +dlpreopen='$dlprefiles' + +# Directory that this library needs to be installed in: +libdir='$install_libdir'" + if test "$installed" = no && test "$need_relink" = yes; then + $ECHO >> $output "\ +relink_command=\"$relink_command\"" + fi + done + } + + # Do a symbolic link so that the libtool archive can be found in + # LD_LIBRARY_PATH before the program is installed. + func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?' + ;; + esac + exit $EXIT_SUCCESS +} + +{ test "$mode" = link || test "$mode" = relink; } && + func_mode_link ${1+"$@"} + + +# func_mode_uninstall arg... +func_mode_uninstall () +{ + $opt_debug + RM="$nonopt" + files= + rmforce= + exit_status=0 + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic="$magic" + + for arg + do + case $arg in + -f) RM="$RM $arg"; rmforce=yes ;; + -*) RM="$RM $arg" ;; + *) files="$files $arg" ;; + esac + done + + test -z "$RM" && \ + func_fatal_help "you must specify an RM program" + + rmdirs= + + origobjdir="$objdir" + for file in $files; do + func_dirname "$file" "" "." + dir="$func_dirname_result" + if test "X$dir" = X.; then + objdir="$origobjdir" + else + objdir="$dir/$origobjdir" + fi + func_basename "$file" + name="$func_basename_result" + test "$mode" = uninstall && objdir="$dir" + + # Remember objdir for removal later, being careful to avoid duplicates + if test "$mode" = clean; then + case " $rmdirs " in + *" $objdir "*) ;; + *) rmdirs="$rmdirs $objdir" ;; + esac + fi + + # Don't error if the file doesn't exist and rm -f was used. + if { test -L "$file"; } >/dev/null 2>&1 || + { test -h "$file"; } >/dev/null 2>&1 || + test -f "$file"; then + : + elif test -d "$file"; then + exit_status=1 + continue + elif test "$rmforce" = yes; then + continue + fi + + rmfiles="$file" + + case $name in + *.la) + # Possibly a libtool archive, so verify it. + if func_lalib_p "$file"; then + func_source $dir/$name + + # Delete the libtool libraries and symlinks. + for n in $library_names; do + rmfiles="$rmfiles $objdir/$n" + done + test -n "$old_library" && rmfiles="$rmfiles $objdir/$old_library" + + case "$mode" in + clean) + case " $library_names " in + # " " in the beginning catches empty $dlname + *" $dlname "*) ;; + *) rmfiles="$rmfiles $objdir/$dlname" ;; + esac + test -n "$libdir" && rmfiles="$rmfiles $objdir/$name $objdir/${name}i" + ;; + uninstall) + if test -n "$library_names"; then + # Do each command in the postuninstall commands. + func_execute_cmds "$postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1' + fi + + if test -n "$old_library"; then + # Do each command in the old_postuninstall commands. + func_execute_cmds "$old_postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1' + fi + # FIXME: should reinstall the best remaining shared library. + ;; + esac + fi + ;; + + *.lo) + # Possibly a libtool object, so verify it. + if func_lalib_p "$file"; then + + # Read the .lo file + func_source $dir/$name + + # Add PIC object to the list of files to remove. + if test -n "$pic_object" && + test "$pic_object" != none; then + rmfiles="$rmfiles $dir/$pic_object" + fi + + # Add non-PIC object to the list of files to remove. + if test -n "$non_pic_object" && + test "$non_pic_object" != none; then + rmfiles="$rmfiles $dir/$non_pic_object" + fi + fi + ;; + + *) + if test "$mode" = clean ; then + noexename=$name + case $file in + *.exe) + func_stripname '' '.exe' "$file" + file=$func_stripname_result + func_stripname '' '.exe' "$name" + noexename=$func_stripname_result + # $file with .exe has already been added to rmfiles, + # add $file without .exe + rmfiles="$rmfiles $file" + ;; + esac + # Do a test to see if this is a libtool program. + if func_ltwrapper_p "$file"; then + if func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + relink_command= + func_source $func_ltwrapper_scriptname_result + rmfiles="$rmfiles $func_ltwrapper_scriptname_result" + else + relink_command= + func_source $dir/$noexename + fi + + # note $name still contains .exe if it was in $file originally + # as does the version of $file that was added into $rmfiles + rmfiles="$rmfiles $objdir/$name $objdir/${name}S.${objext}" + if test "$fast_install" = yes && test -n "$relink_command"; then + rmfiles="$rmfiles $objdir/lt-$name" + fi + if test "X$noexename" != "X$name" ; then + rmfiles="$rmfiles $objdir/lt-${noexename}.c" + fi + fi + fi + ;; + esac + func_show_eval "$RM $rmfiles" 'exit_status=1' + done + objdir="$origobjdir" + + # Try to remove the ${objdir}s in the directories where we deleted files + for dir in $rmdirs; do + if test -d "$dir"; then + func_show_eval "rmdir $dir >/dev/null 2>&1" + fi + done + + exit $exit_status +} + +{ test "$mode" = uninstall || test "$mode" = clean; } && + func_mode_uninstall ${1+"$@"} + +test -z "$mode" && { + help="$generic_help" + func_fatal_help "you must specify a MODE" +} + +test -z "$exec_cmd" && \ + func_fatal_help "invalid operation mode \`$mode'" + +if test -n "$exec_cmd"; then + eval exec "$exec_cmd" + exit $EXIT_FAILURE +fi + +exit $exit_status + + +# The TAGs below are defined such that we never get into a situation +# in which we disable both kinds of libraries. Given conflicting +# choices, we go for a static library, that is the most portable, +# since we can't tell whether shared libraries were disabled because +# the user asked for that or because the platform doesn't support +# them. This is particularly important on AIX, because we don't +# support having both static and shared libraries enabled at the same +# time on that platform, so we default to a shared-only configuration. +# If a disable-shared tag is given, we'll fallback to a static-only +# configuration. But we'll never go from static-only to shared-only. + +# ### BEGIN LIBTOOL TAG CONFIG: disable-shared +build_libtool_libs=no +build_old_libs=yes +# ### END LIBTOOL TAG CONFIG: disable-shared + +# ### BEGIN LIBTOOL TAG CONFIG: disable-static +build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` +# ### END LIBTOOL TAG CONFIG: disable-static + +# Local Variables: +# mode:shell-script +# sh-indentation:2 +# End: +# vi:sw=2 + diff --git a/pycairo.pc.in b/pycairo.pc.in new file mode 100644 index 0000000..dbe9a39 --- /dev/null +++ b/pycairo.pc.in @@ -0,0 +1,8 @@ +prefix=@prefix@ + +Name: Pycairo +Description: Python bindings for cairo +Version: @VERSION@ +Requires: cairo +Cflags: -I@includedir@/pycairo +Libs: diff --git a/setup.py b/setup.py new file mode 100755 index 0000000..4bcdbda --- /dev/null +++ b/setup.py @@ -0,0 +1,84 @@ +#!/usr/bin/env python + +import distutils.core as dic +import distutils.dir_util as dut +import distutils.file_util as fut +import subprocess +import sys + +pycairo_version = '1.8.7' +cairo_version_required = '1.8.6' + +def call(command): + pipe = subprocess.Popen(command, shell=True, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + pipe.wait() + return pipe + +def pkg_config_version_check(pkg, version): + pipe = call('pkg-config --print-errors --exists "%s >= %s"' % + (pkg, version)) + if pipe.returncode == 0: + print '%s >= %s detected' % (pkg, version) + else: + print pipe.stderr.read() + raise SystemExit('Error: %s >= %s not found' % (pkg, version)) + +def pkg_config_parse(opt, pkg): + pipe = call("pkg-config %s %s" % (opt, pkg)) + output = pipe.stdout.read() + opt = opt[-2:] + return [x.lstrip(opt) for x in output.split()] + + +if sys.version_info < (2,6): + raise SystemExit('Error: Python >= 2.6 is required') + +pkg_config_version_check ('cairo', cairo_version_required) +if sys.platform == 'win32': + runtime_library_dirs = [] +else: + runtime_library_dirs = pkg_config_parse('--libs-only-L', 'cairo') + +pkgconfig_file='pycairo.pc' +print 'creating %s' % pkgconfig_file +fo = open (pkgconfig_file, 'w') +fo.write ("""\ +prefix=%s + +Name: Pycairo +Description: Python bindings for cairo +Version: %s +Requires: cairo +Cflags: -I${prefix}/include/pycairo +Libs: +""" % (sys.prefix, pycairo_version) + ) +fo.close() + +cairo = dic.Extension( + name = 'cairo._cairo', + sources = ['cairo/cairomodule.c', + 'cairo/pycairo-context.c', + 'cairo/pycairo-font.c', + 'cairo/pycairo-matrix.c', + 'cairo/pycairo-path.c', + 'cairo/pycairo-pattern.c', + 'cairo/pycairo-surface.c', + ], + include_dirs = pkg_config_parse('--cflags-only-I', 'cairo'), + library_dirs = pkg_config_parse('--libs-only-L', 'cairo'), + libraries = pkg_config_parse('--libs-only-l', 'cairo'), + runtime_library_dirs = runtime_library_dirs, + ) + +dic.setup( + name = "pycairo", + version = pycairo_version, + description = "python interface for cairo", + packages = ['cairo'], + ext_modules = [cairo], + data_files=[('include/pycairo',['cairo/pycairo.h']), + ('lib/pkgconfig',[pkgconfig_file])], + ) diff --git a/src/.gitignore b/src/.gitignore new file mode 100644 index 0000000..599e3f3 --- /dev/null +++ b/src/.gitignore @@ -0,0 +1,9 @@ +.deps +.libs +__init__.py +Makefile +Makefile.in +*.la +*.lo +*.pyc +*.pyo diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..68a123f --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,22 @@ + +pycairoexecdir = $(pyexecdir)/cairo + +pkgincludedir = $(includedir)/pycairo +pkginclude_HEADERS = pycairo.h + +pycairoexec_PYTHON = __init__.py + +pycairoexec_LTLIBRARIES = _cairo.la +_cairo_la_LDFLAGS = -module -avoid-version -export-symbols-regex init_cairo +_cairo_la_LIBADD = $(CAIRO_LIBS) +_cairo_la_CPPFLAGS = $(PYTHON_INCLUDES) $(CAIRO_CFLAGS) +_cairo_la_SOURCES = \ + pycairo.h \ + pycairo-private.h \ + pycairo-context.c \ + pycairo-font.c \ + pycairo-matrix.c \ + pycairo-path.c \ + pycairo-pattern.c \ + pycairo-surface.c \ + cairomodule.c diff --git a/src/cairomodule.c b/src/cairomodule.c new file mode 100644 index 0000000..d328985 --- /dev/null +++ b/src/cairomodule.c @@ -0,0 +1,498 @@ +/* -*- mode: C; c-basic-offset: 4 -*- + * + * Pycairo - Python bindings for cairo + * + * Copyright © 2003 James Henstridge, Steven Chaplin + * + * This library is free software; you can redistribute it and/or + * modify it either under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation + * (the "LGPL") or, at your option, under the terms of the Mozilla + * Public License Version 1.1 (the "MPL"). If you do not alter this + * notice, a recipient may use your version of this file under either + * the MPL or the LGPL. + * + * You should have received a copy of the LGPL along with this library + * in the file COPYING-LGPL-2.1; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * You should have received a copy of the MPL along with this library + * in the file COPYING-MPL-1.1 + * + * The contents of this file are subject to the Mozilla Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY + * OF ANY KIND, either express or implied. See the LGPL or the MPL for + * the specific language governing rights and limitations. + */ + +#define PY_SSIZE_T_CLEAN +#include <Python.h> + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif +#include "pycairo-private.h" + +/* to read CAIRO_PS_LEVEL_* constants */ +#ifdef CAIRO_HAS_PS_SURFACE +# include <cairo-ps.h> +#endif + +#define VERSION_MAJOR 1 +#define VERSION_MINOR 8 +#define VERSION_MICRO 7 +static char pycairo_version_string[] = "1.8.7"; + + +/* A module specific exception */ +PyObject *CairoError = NULL; + +int +Pycairo_Check_Status (cairo_status_t status) +{ + if (PyErr_Occurred() != NULL) + return 1; + + switch (status) { + case CAIRO_STATUS_SUCCESS: + return 0; + /* if appropriate - translate the status string into Python, + * else - use cairo_status_to_string() + */ + case CAIRO_STATUS_NO_MEMORY: + PyErr_NoMemory(); + break; + case CAIRO_STATUS_READ_ERROR: + case CAIRO_STATUS_WRITE_ERROR: + PyErr_SetString(PyExc_IOError, cairo_status_to_string (status)); + break; + case CAIRO_STATUS_INVALID_RESTORE: + PyErr_SetString(CairoError, "Context.restore without matching " + "Context.save"); + break; + case CAIRO_STATUS_INVALID_POP_GROUP: + PyErr_SetString(CairoError, "Context.pop_group without matching " + "Context.push_group"); + break; + default: + PyErr_SetString(CairoError, cairo_status_to_string (status)); + } + return 1; +} + + +/* C API. Clients get at this via Pycairo_IMPORT, defined in pycairo.h. + */ +static Pycairo_CAPI_t CAPI = { + &PycairoContext_Type, PycairoContext_FromContext, + + &PycairoFontFace_Type, + &PycairoToyFontFace_Type, PycairoFontFace_FromFontFace, + + &PycairoFontOptions_Type, PycairoFontOptions_FromFontOptions, + &PycairoMatrix_Type, PycairoMatrix_FromMatrix, + &PycairoPath_Type, PycairoPath_FromPath, + + &PycairoPattern_Type, + &PycairoSolidPattern_Type, + &PycairoSurfacePattern_Type, + &PycairoGradient_Type, + &PycairoLinearGradient_Type, + &PycairoRadialGradient_Type, + PycairoPattern_FromPattern, + + &PycairoScaledFont_Type, PycairoScaledFont_FromScaledFont, + + &PycairoSurface_Type, +#ifdef CAIRO_HAS_IMAGE_SURFACE + &PycairoImageSurface_Type, +#else + 0, +#endif +#ifdef CAIRO_HAS_PDF_SURFACE + &PycairoPDFSurface_Type, +#else + 0, +#endif +#ifdef CAIRO_HAS_PS_SURFACE + &PycairoPSSurface_Type, +#else + 0, +#endif +#ifdef CAIRO_HAS_SVG_SURFACE + &PycairoSVGSurface_Type, +#else + 0, +#endif +#ifdef CAIRO_HAS_WIN32_SURFACE + &PycairoWin32Surface_Type, +#else + 0, +#endif +#ifdef CAIRO_HAS_XLIB_SURFACE + &PycairoXlibSurface_Type, +#else + 0, +#endif + PycairoSurface_FromSurface, + + Pycairo_Check_Status, +}; + +static PyObject * +pycairo_cairo_version (PyObject *self) +{ + return PyInt_FromLong (cairo_version()); +} + +static PyObject * +pycairo_cairo_version_string (PyObject *self) +{ + return PyString_FromString (cairo_version_string()); +} + +static PyMethodDef cairo_functions[] = { + {"cairo_version", (PyCFunction)pycairo_cairo_version, METH_NOARGS}, + {"cairo_version_string", (PyCFunction)pycairo_cairo_version_string, + METH_NOARGS}, + {NULL, NULL, 0, NULL}, +}; + + +DL_EXPORT(void) +init_cairo(void) +{ + PyObject *m; + + /* initialise 'tp_base' here to work round problem with MinGW compiler */ + PycairoContext_Type.tp_base = &PyBaseObject_Type; + if (PyType_Ready(&PycairoContext_Type) < 0) + return; + PycairoFontFace_Type.tp_base = &PyBaseObject_Type; + if (PyType_Ready(&PycairoFontFace_Type) < 0) + return; + PycairoToyFontFace_Type.tp_base = &PycairoFontFace_Type; + if (PyType_Ready(&PycairoToyFontFace_Type) < 0) + return; + PycairoFontOptions_Type.tp_base = &PyBaseObject_Type; + if (PyType_Ready(&PycairoFontOptions_Type) < 0) + return; + PycairoMatrix_Type.tp_base = &PyBaseObject_Type; + if (PyType_Ready(&PycairoMatrix_Type) < 0) + return; + PycairoPath_Type.tp_base = &PyBaseObject_Type; + if (PyType_Ready(&PycairoPath_Type) < 0) + return; + PycairoPathiter_Type.tp_iter=&PyObject_SelfIter; + + PycairoPattern_Type.tp_base = &PyBaseObject_Type; + if (PyType_Ready(&PycairoPattern_Type) < 0) + return; + PycairoSolidPattern_Type.tp_base = &PycairoPattern_Type; + if (PyType_Ready(&PycairoSolidPattern_Type) < 0) + return; + PycairoSurfacePattern_Type.tp_base = &PycairoPattern_Type; + if (PyType_Ready(&PycairoSurfacePattern_Type) < 0) + return; + PycairoGradient_Type.tp_base = &PycairoPattern_Type; + if (PyType_Ready(&PycairoGradient_Type) < 0) + return; + PycairoLinearGradient_Type.tp_base = &PycairoGradient_Type; + if (PyType_Ready(&PycairoLinearGradient_Type) < 0) + return; + PycairoRadialGradient_Type.tp_base = &PycairoGradient_Type; + if (PyType_Ready(&PycairoRadialGradient_Type) < 0) + return; + + PycairoScaledFont_Type.tp_base = &PyBaseObject_Type; + if (PyType_Ready(&PycairoScaledFont_Type) < 0) + return; + + PycairoSurface_Type.tp_base = &PyBaseObject_Type; + if (PyType_Ready(&PycairoSurface_Type) < 0) + return; +#ifdef CAIRO_HAS_IMAGE_SURFACE + PycairoImageSurface_Type.tp_base = &PycairoSurface_Type; + if (PyType_Ready(&PycairoImageSurface_Type) < 0) + return; +#endif +#ifdef CAIRO_HAS_PDF_SURFACE + PycairoPDFSurface_Type.tp_base = &PycairoSurface_Type; + if (PyType_Ready(&PycairoPDFSurface_Type) < 0) + return; +#endif +#ifdef CAIRO_HAS_PS_SURFACE + PycairoPSSurface_Type.tp_base = &PycairoSurface_Type; + if (PyType_Ready(&PycairoPSSurface_Type) < 0) + return; +#endif +#ifdef CAIRO_HAS_SVG_SURFACE + PycairoSVGSurface_Type.tp_base = &PycairoSurface_Type; + if (PyType_Ready(&PycairoSVGSurface_Type) < 0) + return; +#endif +#ifdef CAIRO_HAS_WIN32_SURFACE + PycairoWin32Surface_Type.tp_base = &PycairoSurface_Type; + if (PyType_Ready(&PycairoWin32Surface_Type) < 0) + return; +#endif +#ifdef CAIRO_HAS_XLIB_SURFACE + PycairoXlibSurface_Type.tp_base = &PycairoSurface_Type; + if (PyType_Ready(&PycairoXlibSurface_Type) < 0) + return; +#endif + + m = Py_InitModule("cairo._cairo", cairo_functions); + + PyModule_AddStringConstant(m, "version", pycairo_version_string); + PyModule_AddObject(m, "version_info", + Py_BuildValue("(iii)", VERSION_MAJOR, VERSION_MINOR, + VERSION_MICRO)); + + Py_INCREF(&PycairoContext_Type); + PyModule_AddObject(m, "Context", (PyObject *)&PycairoContext_Type); + Py_INCREF(&PycairoFontFace_Type); + PyModule_AddObject(m, "FontFace",(PyObject *)&PycairoFontFace_Type); + Py_INCREF(&PycairoToyFontFace_Type); + PyModule_AddObject(m, "ToyFontFace",(PyObject *)&PycairoToyFontFace_Type); + Py_INCREF(&PycairoFontOptions_Type); + PyModule_AddObject(m, "FontOptions",(PyObject *)&PycairoFontOptions_Type); + Py_INCREF(&PycairoMatrix_Type); + PyModule_AddObject(m, "Matrix", (PyObject *)&PycairoMatrix_Type); + Py_INCREF(&PycairoPath_Type); + /* Don't add Path object since it is not accessed directly as 'cairo.Path' + * PyModule_AddObject(m, "Path", (PyObject *)&PycairoPath_Type); + */ + Py_INCREF(&PycairoPattern_Type); + PyModule_AddObject(m, "Pattern", (PyObject *)&PycairoPattern_Type); + Py_INCREF(&PycairoSolidPattern_Type); + PyModule_AddObject(m, "SolidPattern", + (PyObject *)&PycairoSolidPattern_Type); + Py_INCREF(&PycairoSurfacePattern_Type); + PyModule_AddObject(m, "SurfacePattern", + (PyObject *)&PycairoSurfacePattern_Type); + Py_INCREF(&PycairoGradient_Type); + PyModule_AddObject(m, "Gradient", (PyObject *)&PycairoGradient_Type); + Py_INCREF(&PycairoLinearGradient_Type); + PyModule_AddObject(m, "LinearGradient", + (PyObject *)&PycairoLinearGradient_Type); + Py_INCREF(&PycairoRadialGradient_Type); + PyModule_AddObject(m, "RadialGradient", + (PyObject *)&PycairoRadialGradient_Type); + + Py_INCREF(&PycairoScaledFont_Type); + PyModule_AddObject(m, "ScaledFont", (PyObject *)&PycairoScaledFont_Type); + + Py_INCREF(&PycairoSurface_Type); + PyModule_AddObject(m, "Surface", (PyObject *)&PycairoSurface_Type); + +#ifdef CAIRO_HAS_IMAGE_SURFACE + Py_INCREF(&PycairoImageSurface_Type); + PyModule_AddObject(m, "ImageSurface", + (PyObject *)&PycairoImageSurface_Type); +#endif + +#ifdef CAIRO_HAS_PDF_SURFACE + Py_INCREF(&PycairoPDFSurface_Type); + PyModule_AddObject(m, "PDFSurface", (PyObject *)&PycairoPDFSurface_Type); +#endif + +#ifdef CAIRO_HAS_PS_SURFACE + Py_INCREF(&PycairoPSSurface_Type); + PyModule_AddObject(m, "PSSurface", (PyObject *)&PycairoPSSurface_Type); +#endif + +#ifdef CAIRO_HAS_SVG_SURFACE + Py_INCREF(&PycairoSVGSurface_Type); + PyModule_AddObject(m, "SVGSurface", (PyObject *)&PycairoSVGSurface_Type); +#endif + +#ifdef CAIRO_HAS_WIN32_SURFACE + Py_INCREF(&PycairoWin32Surface_Type); + PyModule_AddObject(m, "Win32Surface", + (PyObject *)&PycairoWin32Surface_Type); +#endif + +#ifdef CAIRO_HAS_XLIB_SURFACE + Py_INCREF(&PycairoXlibSurface_Type); + PyModule_AddObject(m, "XlibSurface", + (PyObject *)&PycairoXlibSurface_Type); +#endif + + PyModule_AddObject(m, "CAPI", PyCObject_FromVoidPtr(&CAPI, NULL)); + + /* Add 'cairo.Error' to the module */ + if (CairoError == NULL) { + CairoError = PyErr_NewException("cairo.Error", NULL, NULL); + if (CairoError == NULL) + return; + } + Py_INCREF(CairoError); + if (PyModule_AddObject(m, "Error", CairoError) < 0) + return; + + /* constants */ +#if CAIRO_HAS_ATSUI_FONT + PyModule_AddIntConstant(m, "HAS_ATSUI_FONT", 1); +#else + PyModule_AddIntConstant(m, "HAS_ATSUI_FONT", 0); +#endif +#if CAIRO_HAS_FT_FONT + PyModule_AddIntConstant(m, "HAS_FT_FONT", 1); +#else + PyModule_AddIntConstant(m, "HAS_FT_FONT", 0); +#endif +#if CAIRO_HAS_GLITZ_SURFACE + PyModule_AddIntConstant(m, "HAS_GLITZ_SURFACE", 1); +#else + PyModule_AddIntConstant(m, "HAS_GLITZ_SURFACE", 0); +#endif +#if CAIRO_HAS_IMAGE_SURFACE + PyModule_AddIntConstant(m, "HAS_IMAGE_SURFACE", 1); +#else + PyModule_AddIntConstant(m, "HAS_IMAGE_SURFACE", 0); +#endif +#if CAIRO_HAS_PDF_SURFACE + PyModule_AddIntConstant(m, "HAS_PDF_SURFACE", 1); +#else + PyModule_AddIntConstant(m, "HAS_PDF_SURFACE", 0); +#endif +#if CAIRO_HAS_PNG_FUNCTIONS + PyModule_AddIntConstant(m, "HAS_PNG_FUNCTIONS", 1); +#else + PyModule_AddIntConstant(m, "HAS_PNG_FUNCTIONS", 0); +#endif +#if CAIRO_HAS_PS_SURFACE + PyModule_AddIntConstant(m, "HAS_PS_SURFACE", 1); +#else + PyModule_AddIntConstant(m, "HAS_PS_SURFACE", 0); +#endif +#if CAIRO_HAS_SVG_SURFACE + PyModule_AddIntConstant(m, "HAS_SVG_SURFACE", 1); +#else + PyModule_AddIntConstant(m, "HAS_SVG_SURFACE", 0); +#endif +#if CAIRO_HAS_USER_FONT + PyModule_AddIntConstant(m, "HAS_USER_FONT", 1); +#else + PyModule_AddIntConstant(m, "HAS_USER_FONT", 0); +#endif +#if CAIRO_HAS_QUARTZ_SURFACE + PyModule_AddIntConstant(m, "HAS_QUARTZ_SURFACE", 1); +#else + PyModule_AddIntConstant(m, "HAS_QUARTZ_SURFACE", 0); +#endif +#if CAIRO_HAS_WIN32_FONT + PyModule_AddIntConstant(m, "HAS_WIN32_FONT", 1); +#else + PyModule_AddIntConstant(m, "HAS_WIN32_FONT", 0); +#endif +#if CAIRO_HAS_WIN32_SURFACE + PyModule_AddIntConstant(m, "HAS_WIN32_SURFACE", 1); +#else + PyModule_AddIntConstant(m, "HAS_WIN32_SURFACE", 0); +#endif +#if CAIRO_HAS_XCB_SURFACE + PyModule_AddIntConstant(m, "HAS_XCB_SURFACE", 1); +#else + PyModule_AddIntConstant(m, "HAS_XCB_SURFACE", 0); +#endif +#if CAIRO_HAS_XLIB_SURFACE + PyModule_AddIntConstant(m, "HAS_XLIB_SURFACE", 1); +#else + PyModule_AddIntConstant(m, "HAS_XLIB_SURFACE", 0); +#endif + +#define CONSTANT(x) PyModule_AddIntConstant(m, #x, CAIRO_##x) + CONSTANT(ANTIALIAS_DEFAULT); + CONSTANT(ANTIALIAS_NONE); + CONSTANT(ANTIALIAS_GRAY); + CONSTANT(ANTIALIAS_SUBPIXEL); + + CONSTANT(CONTENT_COLOR); + CONSTANT(CONTENT_ALPHA); + CONSTANT(CONTENT_COLOR_ALPHA); + + CONSTANT(EXTEND_NONE); + CONSTANT(EXTEND_REPEAT); + CONSTANT(EXTEND_REFLECT); + CONSTANT(EXTEND_PAD); + + CONSTANT(FILL_RULE_WINDING); + CONSTANT(FILL_RULE_EVEN_ODD); + + CONSTANT(FILTER_FAST); + CONSTANT(FILTER_GOOD); + CONSTANT(FILTER_BEST); + CONSTANT(FILTER_NEAREST); + CONSTANT(FILTER_BILINEAR); + CONSTANT(FILTER_GAUSSIAN); + + CONSTANT(FONT_WEIGHT_NORMAL); + CONSTANT(FONT_WEIGHT_BOLD); + + CONSTANT(FONT_SLANT_NORMAL); + CONSTANT(FONT_SLANT_ITALIC); + CONSTANT(FONT_SLANT_OBLIQUE); + + CONSTANT(FORMAT_ARGB32); + CONSTANT(FORMAT_RGB24); + CONSTANT(FORMAT_A8); + CONSTANT(FORMAT_A1); + + CONSTANT(HINT_METRICS_DEFAULT); + CONSTANT(HINT_METRICS_OFF); + CONSTANT(HINT_METRICS_ON); + + CONSTANT(HINT_STYLE_DEFAULT); + CONSTANT(HINT_STYLE_NONE); + CONSTANT(HINT_STYLE_SLIGHT); + CONSTANT(HINT_STYLE_MEDIUM); + CONSTANT(HINT_STYLE_FULL); + + CONSTANT(LINE_CAP_BUTT); + CONSTANT(LINE_CAP_ROUND); + CONSTANT(LINE_CAP_SQUARE); + + CONSTANT(LINE_JOIN_MITER); + CONSTANT(LINE_JOIN_ROUND); + CONSTANT(LINE_JOIN_BEVEL); + + CONSTANT(OPERATOR_CLEAR); + + CONSTANT(OPERATOR_SOURCE); + CONSTANT(OPERATOR_OVER); + CONSTANT(OPERATOR_IN); + CONSTANT(OPERATOR_OUT); + CONSTANT(OPERATOR_ATOP); + + CONSTANT(OPERATOR_DEST); + CONSTANT(OPERATOR_DEST_OVER); + CONSTANT(OPERATOR_DEST_IN); + CONSTANT(OPERATOR_DEST_OUT); + CONSTANT(OPERATOR_DEST_ATOP); + + CONSTANT(OPERATOR_XOR); + CONSTANT(OPERATOR_ADD); + CONSTANT(OPERATOR_SATURATE); + + CONSTANT(PATH_MOVE_TO); + CONSTANT(PATH_LINE_TO); + CONSTANT(PATH_CURVE_TO); + CONSTANT(PATH_CLOSE_PATH); + +#ifdef CAIRO_HAS_PS_SURFACE + CONSTANT(PS_LEVEL_2); + CONSTANT(PS_LEVEL_3); +#endif + + CONSTANT(SUBPIXEL_ORDER_DEFAULT); + CONSTANT(SUBPIXEL_ORDER_RGB); + CONSTANT(SUBPIXEL_ORDER_BGR); + CONSTANT(SUBPIXEL_ORDER_VRGB); + CONSTANT(SUBPIXEL_ORDER_VBGR); +#undef CONSTANT +} diff --git a/src/pycairo-context.c b/src/pycairo-context.c new file mode 100644 index 0000000..86f9a96 --- /dev/null +++ b/src/pycairo-context.c @@ -0,0 +1,1547 @@ +/* -*- mode: C; c-basic-offset: 4 -*- + * + * Pycairo - Python bindings for cairo + * + * Copyright © 2003 James Henstridge, Steven Chaplin + * + * This library is free software; you can redistribute it and/or + * modify it either under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation + * (the "LGPL") or, at your option, under the terms of the Mozilla + * Public License Version 1.1 (the "MPL"). If you do not alter this + * notice, a recipient may use your version of this file under either + * the MPL or the LGPL. + * + * You should have received a copy of the LGPL along with this library + * in the file COPYING-LGPL-2.1; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * You should have received a copy of the MPL along with this library + * in the file COPYING-MPL-1.1 + * + * The contents of this file are subject to the Mozilla Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY + * OF ANY KIND, either express or implied. See the LGPL or the MPL for + * the specific language governing rights and limitations. + */ + +#define PY_SSIZE_T_CLEAN +#include <Python.h> + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif +#include "pycairo-private.h" + + +/* PycairoContext_FromContext + * Create a new PycairoContext from a cairo_t + * ctx - a cairo_t to 'wrap' into a Python object. + * It is unreferenced if the PycairoContext creation fails, or if + * the cairo_t has an error status. + * type - a pointer to the type to instantiate. + * It can be &PycairoContext_Type, or a PycairoContext_Type subtype. + * (cairo.Context or a cairo.Context subclass) + * base - the base object used to create the context, or NULL. + * it is referenced to keep it alive while the cairo_t is being used + * Return value: New reference or NULL on failure + */ +PyObject * +PycairoContext_FromContext(cairo_t *ctx, PyTypeObject *type, PyObject *base) +{ + PyObject *o; + + assert (ctx != NULL); + + if (Pycairo_Check_Status (cairo_status (ctx))) { + cairo_destroy (ctx); + return NULL; + } + + o = PycairoContext_Type.tp_alloc (type, 0); + if (o) { + ((PycairoContext *)o)->ctx = ctx; + Py_XINCREF(base); + ((PycairoContext *)o)->base = base; + } else { + cairo_destroy (ctx); + } + return o; +} + +static void +pycairo_dealloc(PycairoContext *o) +{ + if (o->ctx) { + cairo_destroy(o->ctx); + o->ctx = NULL; + } + Py_CLEAR(o->base); + + o->ob_type->tp_free((PyObject *)o); +} + +static PyObject * +pycairo_new (PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + PycairoSurface *s; + if (!PyArg_ParseTuple(args, "O!:Context.__new__", + &PycairoSurface_Type, &s)) + return NULL; + return PycairoContext_FromContext (cairo_create (s->surface), type, NULL); +} + +static PyObject * +pycairo_append_path (PycairoContext *o, PyObject *args) +{ + PycairoPath *p; + + if (!PyArg_ParseTuple(args, "O!:Context.append_path", + &PycairoPath_Type, &p)) + return NULL; + + Py_BEGIN_ALLOW_THREADS + cairo_append_path (o->ctx, p->path); + Py_END_ALLOW_THREADS + RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); + Py_RETURN_NONE; +} + +static PyObject * +pycairo_arc (PycairoContext *o, PyObject *args) +{ + double xc, yc, radius, angle1, angle2; + + if (!PyArg_ParseTuple (args, "ddddd:Context.arc", + &xc, &yc, &radius, &angle1, &angle2)) + return NULL; + + cairo_arc (o->ctx, xc, yc, radius, angle1, angle2); + RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); + Py_RETURN_NONE; +} + +static PyObject * +pycairo_arc_negative (PycairoContext *o, PyObject *args) +{ + double xc, yc, radius, angle1, angle2; + + if (!PyArg_ParseTuple (args, "ddddd:Context.arc_negative", + &xc, &yc, &radius, &angle1, &angle2)) + return NULL; + + cairo_arc_negative (o->ctx, xc, yc, radius, angle1, angle2); + RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); + Py_RETURN_NONE; +} + +static PyObject * +pycairo_clip (PycairoContext *o) +{ + Py_BEGIN_ALLOW_THREADS + cairo_clip (o->ctx); + Py_END_ALLOW_THREADS + RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); + Py_RETURN_NONE; +} + +static PyObject * +pycairo_clip_extents (PycairoContext *o) +{ + double x1, y1, x2, y2; + cairo_clip_extents (o->ctx, &x1, &y1, &x2, &y2); + RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); + return Py_BuildValue("(dddd)", x1, y1, x2, y2); +} + +static PyObject * +pycairo_clip_preserve (PycairoContext *o) +{ + Py_BEGIN_ALLOW_THREADS + cairo_clip_preserve (o->ctx); + Py_END_ALLOW_THREADS + RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); + Py_RETURN_NONE; +} + +static PyObject * +pycairo_close_path (PycairoContext *o) +{ + Py_BEGIN_ALLOW_THREADS + cairo_close_path (o->ctx); + Py_END_ALLOW_THREADS + RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); + Py_RETURN_NONE; +} + +static PyObject * +pycairo_copy_clip_rectangle_list (PycairoContext *o) +{ + int i; + PyObject *rv = NULL; + cairo_rectangle_t *r; + cairo_rectangle_list_t *rlist = cairo_copy_clip_rectangle_list (o->ctx); + if (rlist->status != CAIRO_STATUS_SUCCESS) { + Pycairo_Check_Status (rlist->status); + goto exit; + } + + rv = PyTuple_New(rlist->num_rectangles); + if (rv == NULL) + goto exit; + + for (i = 0, r = rlist->rectangles; i < rlist->num_rectangles; i++, r++) { + PyObject *py_rect = Py_BuildValue("(dddd)", r->x, r->y, + r->width, r->height); + if (py_rect == NULL) { + Py_CLEAR(rv); + goto exit; + } + PyTuple_SET_ITEM (rv, i, py_rect); + } + exit: + cairo_rectangle_list_destroy(rlist); + return rv; +} + +static PyObject * +pycairo_copy_page (PycairoContext *o) +{ + Py_BEGIN_ALLOW_THREADS + cairo_copy_page (o->ctx); + Py_END_ALLOW_THREADS + RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); + Py_RETURN_NONE; +} + +static PyObject * +pycairo_copy_path (PycairoContext *o) +{ + cairo_path_t *cp; + Py_BEGIN_ALLOW_THREADS + cp = cairo_copy_path (o->ctx); + Py_END_ALLOW_THREADS + return PycairoPath_FromPath (cp); +} + +static PyObject * +pycairo_copy_path_flat (PycairoContext *o) +{ + cairo_path_t *cp; + Py_BEGIN_ALLOW_THREADS + cp = cairo_copy_path_flat (o->ctx); + Py_END_ALLOW_THREADS + return PycairoPath_FromPath (cp); +} + +static PyObject * +pycairo_curve_to (PycairoContext *o, PyObject *args) +{ + double x1, y1, x2, y2, x3, y3; + + if (!PyArg_ParseTuple (args, "dddddd:Context.curve_to", + &x1, &y1, &x2, &y2, &x3, &y3)) + return NULL; + + cairo_curve_to (o->ctx, x1, y1, x2, y2, x3, y3); + RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); + Py_RETURN_NONE; +} + +static PyObject * +pycairo_device_to_user(PycairoContext *o, PyObject *args) +{ + double x, y; + + if (!PyArg_ParseTuple(args, "dd:Context.device_to_user", &x, &y)) + return NULL; + + cairo_device_to_user(o->ctx, &x, &y); + RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); + return Py_BuildValue("(dd)", x, y); +} + +static PyObject * +pycairo_device_to_user_distance (PycairoContext *o, PyObject *args) +{ + double dx, dy; + + if (!PyArg_ParseTuple (args, "dd:Context.device_to_user_distance", + &dx, &dy)) + return NULL; + + cairo_device_to_user_distance (o->ctx, &dx, &dy); + RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); + return Py_BuildValue("(dd)", dx, dy); +} + +static PyObject * +pycairo_fill (PycairoContext *o) +{ + Py_BEGIN_ALLOW_THREADS + cairo_fill (o->ctx); + Py_END_ALLOW_THREADS + RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); + Py_RETURN_NONE; +} + +static PyObject * +pycairo_fill_extents (PycairoContext *o) +{ + double x1, y1, x2, y2; + cairo_fill_extents (o->ctx, &x1, &y1, &x2, &y2); + RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); + return Py_BuildValue("(dddd)", x1, y1, x2, y2); +} + +static PyObject * +pycairo_fill_preserve (PycairoContext *o) +{ + Py_BEGIN_ALLOW_THREADS + cairo_fill_preserve (o->ctx); + Py_END_ALLOW_THREADS + RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); + Py_RETURN_NONE; +} + +static PyObject * +pycairo_font_extents (PycairoContext *o) +{ + cairo_font_extents_t e; + + cairo_font_extents (o->ctx, &e); + RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); + return Py_BuildValue("(ddddd)", e.ascent, e.descent, e.height, + e.max_x_advance, e.max_y_advance); +} + +static PyObject * +pycairo_get_antialias (PycairoContext *o) +{ + return PyInt_FromLong (cairo_get_antialias (o->ctx)); +} + +static PyObject * +pycairo_get_current_point (PycairoContext *o) +{ + double x, y; + cairo_get_current_point (o->ctx, &x, &y); + return Py_BuildValue("(dd)", x, y); +} + +static PyObject * +pycairo_get_dash (PycairoContext *o) +{ + double *dashes = NULL, offset; + int count, i; + PyObject *py_dashes = NULL, *rv = NULL; + + count = cairo_get_dash_count (o->ctx); + dashes = PyMem_Malloc (count * sizeof(double)); + if (dashes == NULL) + return PyErr_NoMemory(); + + cairo_get_dash (o->ctx, dashes, &offset); + py_dashes = PyTuple_New(count); + if (py_dashes == NULL) + goto exit; + + for (i = 0; i < count; i++) { + PyObject *dash = PyFloat_FromDouble(dashes[i]); + if (dash == NULL) + goto exit; + PyTuple_SET_ITEM (py_dashes, i, dash); + } + rv = Py_BuildValue("(Od)", py_dashes, offset); + + exit: + PyMem_Free (dashes); + Py_XDECREF(py_dashes); + return rv; +} + +static PyObject * +pycairo_get_dash_count (PycairoContext *o) +{ + return PyInt_FromLong (cairo_get_dash_count (o->ctx)); +} + +static PyObject * +pycairo_get_fill_rule (PycairoContext *o) +{ + return PyInt_FromLong(cairo_get_fill_rule (o->ctx)); +} + +static PyObject * +pycairo_get_font_face (PycairoContext *o) +{ + return PycairoFontFace_FromFontFace ( + cairo_font_face_reference (cairo_get_font_face (o->ctx))); +} + +static PyObject * +pycairo_get_font_matrix (PycairoContext *o) +{ + cairo_matrix_t matrix; + cairo_get_font_matrix (o->ctx, &matrix); + return PycairoMatrix_FromMatrix (&matrix); +} + +static PyObject * +pycairo_get_font_options (PycairoContext *o) +{ + cairo_font_options_t *options = cairo_font_options_create(); + cairo_get_font_options (o->ctx, options); + /* there is no reference fn */ + return PycairoFontOptions_FromFontOptions (options); +} + +static PyObject * +pycairo_get_group_target (PycairoContext *o) +{ + cairo_surface_t *surface = cairo_get_group_target (o->ctx); + if (surface != NULL) + return PycairoSurface_FromSurface (cairo_surface_reference (surface), + NULL); + Py_RETURN_NONE; +} + +static PyObject * +pycairo_get_line_cap (PycairoContext *o) +{ + return PyInt_FromLong(cairo_get_line_cap (o->ctx)); +} + +static PyObject * +pycairo_get_line_join (PycairoContext *o) +{ + return PyInt_FromLong(cairo_get_line_join (o->ctx)); +} + +static PyObject * +pycairo_get_line_width (PycairoContext *o) +{ + return PyFloat_FromDouble(cairo_get_line_width (o->ctx)); +} + +static PyObject * +pycairo_get_matrix (PycairoContext *o) +{ + cairo_matrix_t matrix; + cairo_get_matrix (o->ctx, &matrix); + return PycairoMatrix_FromMatrix (&matrix); +} + +static PyObject * +pycairo_get_miter_limit (PycairoContext *o) +{ + return PyFloat_FromDouble (cairo_get_miter_limit (o->ctx)); +} + +static PyObject * +pycairo_get_operator (PycairoContext *o) +{ + return PyInt_FromLong (cairo_get_operator (o->ctx)); +} + +static PyObject * +pycairo_get_scaled_font (PycairoContext *o) +{ + return PycairoScaledFont_FromScaledFont ( + cairo_scaled_font_reference (cairo_get_scaled_font (o->ctx))); +} + +static PyObject * +pycairo_get_source (PycairoContext *o) +{ + return PycairoPattern_FromPattern ( + cairo_pattern_reference (cairo_get_source (o->ctx)), NULL); +} + +static PyObject * +pycairo_get_target (PycairoContext *o) +{ + return PycairoSurface_FromSurface ( + cairo_surface_reference (cairo_get_target (o->ctx)), + NULL); +} + +static PyObject * +pycairo_get_tolerance (PycairoContext *o) +{ + return PyFloat_FromDouble (cairo_get_tolerance (o->ctx)); +} + +/* read a Python sequence of (i,x,y) sequences + * return cairo_glyph_t * + * num_glyphs + * must call PyMem_Free(glyphs) when finished using the glyphs + */ +static cairo_glyph_t * +_PyGlyphs_AsGlyphs (PyObject *py_object, int *num_glyphs) +{ + int length, i; + cairo_glyph_t *glyphs = NULL, *glyph; + PyObject *py_glyphs, *py_seq = NULL; + + py_glyphs = PySequence_Fast (py_object, "glyphs must be a sequence"); + if (py_glyphs == NULL) + return NULL; + + length = PySequence_Fast_GET_SIZE(py_glyphs); + if (*num_glyphs < 0 || *num_glyphs > length) + *num_glyphs = length; + + glyphs = PyMem_Malloc (*num_glyphs * sizeof(cairo_glyph_t)); + if (glyphs == NULL) { + PyErr_NoMemory(); + goto error; + } + for (i = 0, glyph = glyphs; i < *num_glyphs; i++, glyph++) { + PyObject *py_item = PySequence_Fast_GET_ITEM(py_glyphs, i); + py_seq = PySequence_Fast (py_item, "glyph items must be a sequence"); + if (py_seq == NULL) + goto error; + if (PySequence_Fast_GET_SIZE(py_seq) != 3) { + PyErr_SetString(PyExc_ValueError, + "each glyph item must be an (i,x,y) sequence"); + goto error; + } + glyph->index = PyInt_AsLong(PySequence_Fast_GET_ITEM(py_seq, 0)); + glyph->x = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(py_seq, 1)); + glyph->y = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(py_seq, 2)); + if (PyErr_Occurred()) + goto error; + Py_DECREF(py_seq); + } + Py_DECREF(py_glyphs); + return glyphs; + error: + Py_DECREF(py_glyphs); + Py_XDECREF(py_seq); + PyMem_Free(glyphs); + return NULL; +} + +static PyObject * +pycairo_glyph_extents (PycairoContext *o, PyObject *args) +{ + int num_glyphs = -1; + cairo_glyph_t *glyphs; + cairo_text_extents_t extents; + PyObject *py_object; + + if (!PyArg_ParseTuple (args, "O|i:Context.glyph_extents", + &py_object, &num_glyphs)) + return NULL; + + glyphs = _PyGlyphs_AsGlyphs (py_object, &num_glyphs); + if (glyphs == NULL) + return NULL; + cairo_glyph_extents (o->ctx, glyphs, num_glyphs, &extents); + PyMem_Free (glyphs); + RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); + return Py_BuildValue("(dddddd)", extents.x_bearing, extents.y_bearing, + extents.width, extents.height, extents.x_advance, + extents.y_advance); +} + +static PyObject * +pycairo_glyph_path (PycairoContext *o, PyObject *args) +{ + int num_glyphs = -1; + cairo_glyph_t *glyphs; + PyObject *py_object; + + if (!PyArg_ParseTuple (args, "O|i:Context.glyph_path", + &py_object, &num_glyphs)) + return NULL; + + glyphs = _PyGlyphs_AsGlyphs (py_object, &num_glyphs); + if (glyphs == NULL) + return NULL; + cairo_glyph_path (o->ctx, glyphs, num_glyphs); + PyMem_Free (glyphs); + RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); + Py_RETURN_NONE; +} + +static PyObject * +pycairo_has_current_point (PycairoContext *o) +{ + PyObject *b = cairo_has_current_point (o->ctx) ? Py_True : Py_False; + RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); + Py_INCREF(b); + return b; +} + +static PyObject * +pycairo_identity_matrix (PycairoContext *o) +{ + cairo_identity_matrix (o->ctx); + RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); + Py_RETURN_NONE; +} + +static PyObject * +pycairo_in_fill (PycairoContext *o, PyObject *args) +{ + double x, y; + PyObject *result; + + if (!PyArg_ParseTuple (args, "dd:Context.in_fill", &x, &y)) + return NULL; + + result = cairo_in_fill (o->ctx, x, y) ? Py_True : Py_False; + RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); + Py_INCREF(result); + return result; +} + +static PyObject * +pycairo_in_stroke (PycairoContext *o, PyObject *args) +{ + double x, y; + PyObject *result; + + if (!PyArg_ParseTuple (args, "dd:Context.in_stroke", &x, &y)) + return NULL; + + result = cairo_in_stroke (o->ctx, x, y) ? Py_True : Py_False; + RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); + Py_INCREF(result); + return result; +} + +static PyObject * +pycairo_line_to (PycairoContext *o, PyObject *args) +{ + double x, y; + + if (!PyArg_ParseTuple (args, "dd:Context.line_to", &x, &y)) + return NULL; + + cairo_line_to (o->ctx, x, y); + RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); + Py_RETURN_NONE; +} + +static PyObject * +pycairo_mask (PycairoContext *o, PyObject *args) +{ + PycairoPattern *p; + + if (!PyArg_ParseTuple(args, "O!:Context.mask", &PycairoPattern_Type, &p)) + return NULL; + + Py_BEGIN_ALLOW_THREADS + cairo_mask (o->ctx, p->pattern); + Py_END_ALLOW_THREADS + RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); + Py_RETURN_NONE; +} + +static PyObject * +pycairo_mask_surface (PycairoContext *o, PyObject *args) +{ + PycairoSurface *s; + double surface_x = 0.0, surface_y = 0.0; + + if (!PyArg_ParseTuple (args, "O!|dd:Context.mask_surface", + &PycairoSurface_Type, &s, &surface_x, &surface_y)) + return NULL; + + Py_BEGIN_ALLOW_THREADS + cairo_mask_surface (o->ctx, s->surface, surface_x, surface_y); + Py_END_ALLOW_THREADS + RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); + Py_RETURN_NONE; +} + +static PyObject * +pycairo_move_to (PycairoContext *o, PyObject *args) +{ + double x, y; + + if (!PyArg_ParseTuple (args, "dd:Context.move_to", &x, &y)) + return NULL; + + cairo_move_to (o->ctx, x, y); + RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); + Py_RETURN_NONE; +} + +static PyObject * +pycairo_new_path (PycairoContext *o) +{ + cairo_new_path (o->ctx); + RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); + Py_RETURN_NONE; +} + +static PyObject * +pycairo_new_sub_path (PycairoContext *o) +{ + cairo_new_sub_path (o->ctx); + RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); + Py_RETURN_NONE; +} + +static PyObject * +pycairo_paint (PycairoContext *o) +{ + Py_BEGIN_ALLOW_THREADS + cairo_paint (o->ctx); + Py_END_ALLOW_THREADS + RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); + Py_RETURN_NONE; +} + +static PyObject * +pycairo_paint_with_alpha (PycairoContext *o, PyObject *args) +{ + double alpha; + + if (!PyArg_ParseTuple (args, "d:Context.paint_with_alpha", &alpha)) + return NULL; + + Py_BEGIN_ALLOW_THREADS + cairo_paint_with_alpha (o->ctx, alpha); + Py_END_ALLOW_THREADS + RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); + Py_RETURN_NONE; +} + +static PyObject * +pycairo_path_extents (PycairoContext *o) +{ + double x1, y1, x2, y2; + cairo_path_extents (o->ctx, &x1, &y1, &x2, &y2); + RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); + return Py_BuildValue("(dddd)", x1, y1, x2, y2); +} + +static PyObject * +pycairo_pop_group (PycairoContext *o) +{ + return PycairoPattern_FromPattern (cairo_pop_group (o->ctx), NULL); +} + +static PyObject * +pycairo_pop_group_to_source (PycairoContext *o) +{ + cairo_pop_group_to_source (o->ctx); + Py_RETURN_NONE; +} + +static PyObject * +pycairo_push_group (PycairoContext *o) +{ + cairo_push_group (o->ctx); + RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); + Py_RETURN_NONE; +} + +static PyObject * +pycairo_push_group_with_content (PycairoContext *o, PyObject *args) +{ + cairo_content_t content; + + if (!PyArg_ParseTuple(args, "i:Context.push_group_with_content", + &content)) + return NULL; + cairo_push_group_with_content (o->ctx, content); + RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); + Py_RETURN_NONE; +} + +static PyObject * +pycairo_rectangle (PycairoContext *o, PyObject *args) +{ + double x, y, width, height; + + if (!PyArg_ParseTuple (args, "dddd:Context.rectangle", + &x, &y, &width, &height)) + return NULL; + + cairo_rectangle (o->ctx, x, y, width, height); + RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); + Py_RETURN_NONE; +} + +static PyObject * +pycairo_rel_curve_to (PycairoContext *o, PyObject *args) +{ + double dx1, dy1, dx2, dy2, dx3, dy3; + + if (!PyArg_ParseTuple (args, "dddddd:Context.rel_curve_to", + &dx1, &dy1, &dx2, &dy2, &dx3, &dy3)) + return NULL; + + cairo_rel_curve_to (o->ctx, dx1, dy1, dx2, dy2, dx3, dy3); + RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); + Py_RETURN_NONE; +} + +static PyObject * +pycairo_rel_line_to (PycairoContext *o, PyObject *args) +{ + double dx, dy; + + if (!PyArg_ParseTuple (args, "dd:Context.rel_line_to", &dx, &dy)) + return NULL; + + cairo_rel_line_to (o->ctx, dx, dy); + RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); + Py_RETURN_NONE; +} + +static PyObject * +pycairo_rel_move_to (PycairoContext *o, PyObject *args) +{ + double dx, dy; + + if (!PyArg_ParseTuple (args, "dd:Context.rel_move_to", &dx, &dy)) + return NULL; + + cairo_rel_move_to (o->ctx, dx, dy); + RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); + Py_RETURN_NONE; +} + +static PyObject * +pycairo_reset_clip (PycairoContext *o) +{ + cairo_reset_clip (o->ctx); + RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); + Py_RETURN_NONE; +} + +static PyObject * +pycairo_restore (PycairoContext *o) +{ + cairo_restore (o->ctx); + RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); + Py_RETURN_NONE; +} + +static PyObject * +pycairo_rotate (PycairoContext *o, PyObject *args) +{ + double angle; + + if (!PyArg_ParseTuple(args, "d:Context.rotate", &angle)) + return NULL; + + cairo_rotate (o->ctx, angle); + RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); + Py_RETURN_NONE; +} + +static PyObject * +pycairo_save (PycairoContext *o) +{ + cairo_save (o->ctx); + RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); + Py_RETURN_NONE; +} + +static PyObject * +pycairo_scale (PycairoContext *o, PyObject *args) +{ + double sx, sy; + + if (!PyArg_ParseTuple (args, "dd:Context.scale", &sx, &sy)) + return NULL; + + cairo_scale (o->ctx, sx, sy); + RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); + Py_RETURN_NONE; +} + +static PyObject * +pycairo_select_font_face (PycairoContext *o, PyObject *args) +{ + PyObject *obj; + PyObject *pyUTF8 = NULL; + const char *utf8family = NULL; + cairo_font_slant_t slant = CAIRO_FONT_SLANT_NORMAL; + cairo_font_weight_t weight = CAIRO_FONT_WEIGHT_NORMAL; + + if (!PyArg_ParseTuple(args, "O!|ii:Context.select_font_face", + &PyBaseString_Type, &obj, &slant, &weight)) + return NULL; + + /* accept str and unicode family, auto convert to utf8 as required */ + if (PyString_Check(obj)) { + /* A plain ASCII string is also a valid UTF-8 string */ + utf8family = PyString_AS_STRING(obj); + } else if (PyUnicode_Check(obj)) { + pyUTF8 = PyUnicode_AsUTF8String(obj); + if (pyUTF8 != NULL) { + utf8family = PyString_AS_STRING(pyUTF8); + } + } else { + PyErr_SetString(PyExc_TypeError, + "Context.select_font_face: family must be str or unicode"); + } + if (utf8family == NULL) + return NULL; + + cairo_select_font_face (o->ctx, utf8family, slant, weight); + Py_XDECREF(pyUTF8); + RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); + Py_RETURN_NONE; +} + +static PyObject * +pycairo_set_antialias (PycairoContext *o, PyObject *args) +{ + cairo_antialias_t antialias = CAIRO_ANTIALIAS_DEFAULT; + + if (!PyArg_ParseTuple(args, "|i:Context.set_antialias", &antialias)) + return NULL; + + cairo_set_antialias (o->ctx, antialias); + RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); + Py_RETURN_NONE; +} + +static PyObject * +pycairo_set_dash (PycairoContext *o, PyObject *args) +{ + double *dashes, offset = 0; + int num_dashes, i; + PyObject *py_dashes; + + if (!PyArg_ParseTuple (args, "O|d:Context.set_dash", &py_dashes, &offset)) + return NULL; + + py_dashes = PySequence_Fast (py_dashes, + "first argument must be a sequence"); + if (py_dashes == NULL) + return NULL; + + num_dashes = PySequence_Fast_GET_SIZE(py_dashes); + dashes = PyMem_Malloc (num_dashes * sizeof(double)); + if (dashes == NULL) { + Py_DECREF(py_dashes); + return PyErr_NoMemory(); + } + + for (i = 0; i < num_dashes; i++) { + dashes[i] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(py_dashes, i)); + if (PyErr_Occurred()) { + PyMem_Free (dashes); + Py_DECREF(py_dashes); + return NULL; + } + } + cairo_set_dash (o->ctx, dashes, num_dashes, offset); + PyMem_Free (dashes); + Py_DECREF(py_dashes); + RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); + Py_RETURN_NONE; +} + +static PyObject * +pycairo_set_fill_rule (PycairoContext *o, PyObject *args) +{ + cairo_fill_rule_t fill_rule; + + if (!PyArg_ParseTuple (args, "i:Context.set_fill_rule", &fill_rule)) + return NULL; + + cairo_set_fill_rule (o->ctx, fill_rule); + RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); + Py_RETURN_NONE; +} + +static PyObject * +pycairo_set_font_face (PycairoContext *o, PyObject *obj) +{ + if (PyObject_TypeCheck(obj, &PycairoFontFace_Type)) + cairo_set_font_face (o->ctx, ((PycairoFontFace *)obj)->font_face); + else if (obj == Py_None) + cairo_set_font_face (o->ctx, NULL); + else { + PyErr_SetString(PyExc_TypeError, + "Context.set_font_face() argument must be " + "cairo.FontFace or None"); + return NULL; + } + RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); + Py_RETURN_NONE; +} + +static PyObject * +pycairo_set_font_matrix (PycairoContext *o, PyObject *args) +{ + PycairoMatrix *matrix; + + if (!PyArg_ParseTuple (args, "O!:Context.set_font_matrix", + &PycairoMatrix_Type, &matrix)) + return NULL; + + cairo_set_font_matrix (o->ctx, &matrix->matrix); + RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); + Py_RETURN_NONE; +} + +static PyObject * +pycairo_set_font_options (PycairoContext *o, PyObject *args) +{ + PycairoFontOptions *options; + + if (!PyArg_ParseTuple (args, "O!:Context.set_font_options", + &PycairoFontOptions_Type, &options)) + return NULL; + + cairo_set_font_options (o->ctx, options->font_options); + RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); + Py_RETURN_NONE; +} + +static PyObject * +pycairo_set_font_size (PycairoContext *o, PyObject *args) +{ + double size; + + if (!PyArg_ParseTuple (args, "d:Context.set_font_size", &size)) + return NULL; + + cairo_set_font_size (o->ctx, size); + RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); + Py_RETURN_NONE; +} + +static PyObject * +pycairo_set_line_cap (PycairoContext *o, PyObject *args) +{ + cairo_line_cap_t line_cap; + + if (!PyArg_ParseTuple (args, "i:Context.set_line_cap", &line_cap)) + return NULL; + + cairo_set_line_cap (o->ctx, line_cap); + RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); + Py_RETURN_NONE; +} + +static PyObject * +pycairo_set_line_join (PycairoContext *o, PyObject *args) +{ + cairo_line_join_t line_join; + + if (!PyArg_ParseTuple (args, "i:Context.set_line_join", &line_join)) + return NULL; + + cairo_set_line_join (o->ctx, line_join); + RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); + Py_RETURN_NONE; +} + +static PyObject * +pycairo_set_line_width (PycairoContext *o, PyObject *args) +{ + double width; + + if (!PyArg_ParseTuple (args, "d:Context.set_line_width", &width)) + return NULL; + + cairo_set_line_width (o->ctx, width); + RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); + Py_RETURN_NONE; +} + +static PyObject * +pycairo_set_matrix (PycairoContext *o, PyObject *args) +{ + PycairoMatrix *matrix; + + if (!PyArg_ParseTuple (args, "O!:Context.set_matrix", + &PycairoMatrix_Type, &matrix)) + return NULL; + + cairo_set_matrix (o->ctx, &matrix->matrix); + RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); + Py_RETURN_NONE; +} + +static PyObject * +pycairo_set_miter_limit (PycairoContext *o, PyObject *args) +{ + double limit; + + if (!PyArg_ParseTuple (args, "d:Context.set_miter_limit", &limit)) + return NULL; + + cairo_set_miter_limit (o->ctx, limit); + RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); + Py_RETURN_NONE; +} + +static PyObject * +pycairo_set_operator(PycairoContext *o, PyObject *args) +{ + cairo_operator_t op; + + if (!PyArg_ParseTuple(args, "i:Context.set_operator", &op)) + return NULL; + + cairo_set_operator(o->ctx, op); + RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); + Py_RETURN_NONE; +} + +static PyObject * +pycairo_set_scaled_font(PycairoContext *o, PyObject *args) +{ + PycairoScaledFont *f; + if (!PyArg_ParseTuple( args, "O!:Context.set_scaled_font", + &PycairoScaledFont_Type, &f)) + return NULL; + + cairo_set_scaled_font(o->ctx, f->scaled_font); + RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); + Py_RETURN_NONE; +} + +static PyObject * +pycairo_set_source (PycairoContext *o, PyObject *args) +{ + PycairoPattern *p; + + if (!PyArg_ParseTuple( args, "O!:Context.set_source", + &PycairoPattern_Type, &p)) + return NULL; + + cairo_set_source (o->ctx, p->pattern); + RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); + Py_RETURN_NONE; +} + +static PyObject * +pycairo_set_source_rgb (PycairoContext *o, PyObject *args) +{ + double red, green, blue; + + if (!PyArg_ParseTuple (args, "ddd:Context.set_source_rgb", + &red, &green, &blue)) + return NULL; + + cairo_set_source_rgb (o->ctx, red, green, blue); + RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); + Py_RETURN_NONE; +} + +static PyObject * +pycairo_set_source_rgba (PycairoContext *o, PyObject *args) +{ + double red, green, blue; + double alpha = 1.0; + + if (!PyArg_ParseTuple (args, "ddd|d:Context.set_source_rgba", + &red, &green, &blue, &alpha)) + return NULL; + + cairo_set_source_rgba (o->ctx, red, green, blue, alpha); + RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); + Py_RETURN_NONE; +} + +static PyObject * +pycairo_set_source_surface (PycairoContext *o, PyObject *args) +{ + PycairoSurface *surface; + double x = 0.0, y = 0.0; + + if (!PyArg_ParseTuple (args, "O!|dd:Context.set_source_surface", + &PycairoSurface_Type, &surface, &x, &y)) + return NULL; + + cairo_set_source_surface (o->ctx, surface->surface, x, y); + RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); + Py_RETURN_NONE; +} + +static PyObject * +pycairo_set_tolerance (PycairoContext *o, PyObject *args) +{ + double tolerance; + if (!PyArg_ParseTuple (args, "d:Context.set_tolerance", &tolerance)) + return NULL; + cairo_set_tolerance (o->ctx, tolerance); + RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); + Py_RETURN_NONE; +} + +static PyObject * +pycairo_show_glyphs (PycairoContext *o, PyObject *args) +{ + int num_glyphs = -1; + cairo_glyph_t *glyphs; + PyObject *py_object; + + if (!PyArg_ParseTuple (args, "O|i:Context.show_glyphs", + &py_object, &num_glyphs)) + return NULL; + + glyphs = _PyGlyphs_AsGlyphs (py_object, &num_glyphs); + if (glyphs == NULL) + return NULL; + Py_BEGIN_ALLOW_THREADS + cairo_show_glyphs (o->ctx, glyphs, num_glyphs); + Py_END_ALLOW_THREADS + PyMem_Free (glyphs); + RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); + Py_RETURN_NONE; +} + +static PyObject * +pycairo_show_page (PycairoContext *o) +{ + Py_BEGIN_ALLOW_THREADS + cairo_show_page (o->ctx); + Py_END_ALLOW_THREADS + RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); + Py_RETURN_NONE; +} + +static PyObject * +pycairo_show_text (PycairoContext *o, PyObject *obj) +{ + PyObject *pyUTF8 = NULL; + const char *utf8 = NULL; + + /* accept str and unicode text, auto convert to utf8 as required */ + if (PyString_Check(obj)) { + /* A plain ASCII string is also a valid UTF-8 string */ + utf8 = PyString_AS_STRING(obj); + } else if (PyUnicode_Check(obj)) { + pyUTF8 = PyUnicode_AsUTF8String(obj); + if (pyUTF8 != NULL) { + utf8 = PyString_AS_STRING(pyUTF8); + } + } else { + PyErr_SetString(PyExc_TypeError, + "Context.show_text: text must be str or unicode"); + } + if (utf8 == NULL) + return NULL; + + Py_BEGIN_ALLOW_THREADS + cairo_show_text (o->ctx, utf8); + Py_END_ALLOW_THREADS + Py_XDECREF(pyUTF8); + RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); + Py_RETURN_NONE; +} + +static PyObject * +pycairo_stroke (PycairoContext *o) +{ + Py_BEGIN_ALLOW_THREADS + cairo_stroke (o->ctx); + Py_END_ALLOW_THREADS + RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); + Py_RETURN_NONE; +} + +static PyObject * +pycairo_stroke_extents (PycairoContext *o) +{ + double x1, y1, x2, y2; + cairo_stroke_extents (o->ctx, &x1, &y1, &x2, &y2); + RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); + return Py_BuildValue("(dddd)", x1, y1, x2, y2); +} + +static PyObject * +pycairo_stroke_preserve (PycairoContext *o) +{ + Py_BEGIN_ALLOW_THREADS + cairo_stroke_preserve (o->ctx); + Py_END_ALLOW_THREADS + RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); + Py_RETURN_NONE; +} + +static PyObject * +pycairo_text_extents (PycairoContext *o, PyObject *obj) +{ + cairo_text_extents_t extents; + PyObject *pyUTF8 = NULL; + const char *utf8 = NULL; + + /* accept str and unicode text, auto convert to utf8 as required */ + if (PyString_Check(obj)) { + /* A plain ASCII string is also a valid UTF-8 string */ + utf8 = PyString_AS_STRING(obj); + } else if (PyUnicode_Check(obj)) { + pyUTF8 = PyUnicode_AsUTF8String(obj); + if (pyUTF8 != NULL) { + utf8 = PyString_AS_STRING(pyUTF8); + } + } else { + PyErr_SetString(PyExc_TypeError, + "Context.text_extents: text must be str or unicode"); + } + if (utf8 == NULL) + return NULL; + + cairo_text_extents (o->ctx, utf8, &extents); + Py_XDECREF(pyUTF8); + RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); + return Py_BuildValue("(dddddd)", extents.x_bearing, extents.y_bearing, + extents.width, extents.height, extents.x_advance, + extents.y_advance); +} + +static PyObject * +pycairo_text_path (PycairoContext *o, PyObject *obj) +{ + PyObject *pyUTF8 = NULL; + const char *utf8 = NULL; + + /* accept str and unicode text, auto convert to utf8 as required */ + if (PyString_Check(obj)) { + /* A plain ASCII string is also a valid UTF-8 string */ + utf8 = PyString_AS_STRING(obj); + } else if (PyUnicode_Check(obj)) { + pyUTF8 = PyUnicode_AsUTF8String(obj); + if (pyUTF8 != NULL) { + utf8 = PyString_AS_STRING(pyUTF8); + } + } else { + PyErr_SetString(PyExc_TypeError, + "Context.text_path: text must be str or unicode"); + } + if (utf8 == NULL) + return NULL; + + cairo_text_path (o->ctx, utf8); + Py_XDECREF(pyUTF8); + RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); + Py_RETURN_NONE; +} + +static PyObject * +pycairo_transform (PycairoContext *o, PyObject *args) +{ + PycairoMatrix *matrix; + + if (!PyArg_ParseTuple (args, "O!:Context.transform", + &PycairoMatrix_Type, &matrix)) + return NULL; + + cairo_transform (o->ctx, &matrix->matrix); + RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); + Py_RETURN_NONE; +} + +static PyObject * +pycairo_translate (PycairoContext *o, PyObject *args) +{ + double tx, ty; + + if (!PyArg_ParseTuple (args, "dd:Context.translate", &tx, &ty)) + return NULL; + + cairo_translate (o->ctx, tx, ty); + RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); + Py_RETURN_NONE; +} + +static PyObject * +pycairo_user_to_device (PycairoContext *o, PyObject *args) +{ + double x, y; + + if (!PyArg_ParseTuple (args, "dd:Context.user_to_device", &x, &y)) + return NULL; + + cairo_user_to_device (o->ctx, &x, &y); + RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); + return Py_BuildValue("(dd)", x, y); +} + +static PyObject * +pycairo_user_to_device_distance (PycairoContext *o, PyObject *args) +{ + double dx, dy; + + if (!PyArg_ParseTuple (args, "dd:Context.user_to_device_distance", + &dx, &dy)) + return NULL; + + cairo_user_to_device_distance (o->ctx, &dx, &dy); + RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); + return Py_BuildValue("(dd)", dx, dy); +} + + +static PyMethodDef pycairo_methods[] = { + /* methods never exposed in a language binding: + * cairo_destroy() + * cairo_reference() + * cairo_rectangle_list_destroy() + * + * cairo_status() + * cairo_status_string() + * - not needed since Pycairo calls Pycairo_Check_Status() to check + * for errors and raise exceptions + */ + {"append_path", (PyCFunction)pycairo_append_path, METH_VARARGS}, + {"arc", (PyCFunction)pycairo_arc, METH_VARARGS}, + {"arc_negative", (PyCFunction)pycairo_arc_negative, METH_VARARGS}, + {"clip", (PyCFunction)pycairo_clip, METH_NOARGS}, + {"clip_extents", (PyCFunction)pycairo_clip_extents, METH_NOARGS}, + {"clip_preserve", (PyCFunction)pycairo_clip_preserve, METH_NOARGS}, + {"close_path", (PyCFunction)pycairo_close_path, METH_NOARGS}, + {"copy_clip_rectangle_list", (PyCFunction)pycairo_copy_clip_rectangle_list, + METH_NOARGS}, + {"copy_page", (PyCFunction)pycairo_copy_page, METH_NOARGS}, + {"copy_path", (PyCFunction)pycairo_copy_path, METH_NOARGS}, + {"copy_path_flat", (PyCFunction)pycairo_copy_path_flat, METH_NOARGS}, + {"curve_to", (PyCFunction)pycairo_curve_to, METH_VARARGS}, + {"device_to_user", (PyCFunction)pycairo_device_to_user, METH_VARARGS}, + {"device_to_user_distance", + (PyCFunction)pycairo_device_to_user_distance, METH_VARARGS}, + {"fill", (PyCFunction)pycairo_fill, METH_NOARGS}, + {"fill_extents", (PyCFunction)pycairo_fill_extents, METH_NOARGS}, + {"fill_preserve", (PyCFunction)pycairo_fill_preserve, METH_NOARGS}, + {"font_extents", (PyCFunction)pycairo_font_extents, METH_NOARGS}, + {"get_antialias", (PyCFunction)pycairo_get_antialias, METH_NOARGS}, + {"get_current_point",(PyCFunction)pycairo_get_current_point,METH_NOARGS}, + {"get_dash", (PyCFunction)pycairo_get_dash, METH_NOARGS}, + {"get_dash_count", (PyCFunction)pycairo_get_dash_count, METH_NOARGS}, + {"get_fill_rule", (PyCFunction)pycairo_get_fill_rule, METH_NOARGS}, + {"get_font_face", (PyCFunction)pycairo_get_font_face, METH_NOARGS}, + {"get_font_matrix", (PyCFunction)pycairo_get_font_matrix, METH_NOARGS}, + {"get_font_options",(PyCFunction)pycairo_get_font_options, METH_NOARGS}, + {"get_group_target",(PyCFunction)pycairo_get_group_target, METH_NOARGS}, + {"get_line_cap", (PyCFunction)pycairo_get_line_cap, METH_NOARGS}, + {"get_line_join", (PyCFunction)pycairo_get_line_join, METH_NOARGS}, + {"get_line_width", (PyCFunction)pycairo_get_line_width, METH_NOARGS}, + {"get_matrix", (PyCFunction)pycairo_get_matrix, METH_NOARGS}, + {"get_miter_limit", (PyCFunction)pycairo_get_miter_limit, METH_NOARGS}, + {"get_operator", (PyCFunction)pycairo_get_operator, METH_NOARGS}, + {"get_scaled_font", (PyCFunction)pycairo_get_scaled_font, METH_NOARGS}, + {"get_source", (PyCFunction)pycairo_get_source, METH_NOARGS}, + {"get_target", (PyCFunction)pycairo_get_target, METH_NOARGS}, + {"get_tolerance", (PyCFunction)pycairo_get_tolerance, METH_NOARGS}, + {"glyph_extents", (PyCFunction)pycairo_glyph_extents, METH_VARARGS}, + {"glyph_path", (PyCFunction)pycairo_glyph_path, METH_VARARGS}, + {"has_current_point",(PyCFunction)pycairo_has_current_point, METH_NOARGS}, + {"identity_matrix", (PyCFunction)pycairo_identity_matrix, METH_NOARGS}, + {"in_fill", (PyCFunction)pycairo_in_fill, METH_VARARGS}, + {"in_stroke", (PyCFunction)pycairo_in_stroke, METH_VARARGS}, + {"line_to", (PyCFunction)pycairo_line_to, METH_VARARGS}, + {"mask", (PyCFunction)pycairo_mask, METH_VARARGS}, + {"mask_surface", (PyCFunction)pycairo_mask_surface, METH_VARARGS}, + {"move_to", (PyCFunction)pycairo_move_to, METH_VARARGS}, + {"new_path", (PyCFunction)pycairo_new_path, METH_NOARGS}, + {"new_sub_path", (PyCFunction)pycairo_new_sub_path, METH_NOARGS}, + {"paint", (PyCFunction)pycairo_paint, METH_NOARGS}, + {"paint_with_alpha",(PyCFunction)pycairo_paint_with_alpha, METH_VARARGS}, + {"path_extents", (PyCFunction)pycairo_path_extents, METH_NOARGS}, + {"pop_group", (PyCFunction)pycairo_pop_group, METH_NOARGS}, + {"pop_group_to_source", + (PyCFunction)pycairo_pop_group_to_source, METH_NOARGS}, + {"push_group", (PyCFunction)pycairo_push_group, METH_NOARGS}, + {"push_group_with_content", + (PyCFunction)pycairo_push_group_with_content, METH_VARARGS}, + {"rectangle", (PyCFunction)pycairo_rectangle, METH_VARARGS}, + {"rel_curve_to", (PyCFunction)pycairo_rel_curve_to, METH_VARARGS}, + {"rel_line_to", (PyCFunction)pycairo_rel_line_to, METH_VARARGS}, + {"rel_move_to", (PyCFunction)pycairo_rel_move_to, METH_VARARGS}, + {"reset_clip", (PyCFunction)pycairo_reset_clip, METH_NOARGS}, + {"restore", (PyCFunction)pycairo_restore, METH_NOARGS}, + {"rotate", (PyCFunction)pycairo_rotate, METH_VARARGS}, + {"save", (PyCFunction)pycairo_save, METH_NOARGS}, + {"scale", (PyCFunction)pycairo_scale, METH_VARARGS}, + {"select_font_face",(PyCFunction)pycairo_select_font_face, METH_VARARGS}, + {"set_antialias", (PyCFunction)pycairo_set_antialias, METH_VARARGS}, + {"set_dash", (PyCFunction)pycairo_set_dash, METH_VARARGS}, + {"set_fill_rule", (PyCFunction)pycairo_set_fill_rule, METH_VARARGS}, + {"set_font_face", (PyCFunction)pycairo_set_font_face, METH_O}, + {"set_font_matrix", (PyCFunction)pycairo_set_font_matrix, METH_VARARGS}, + {"set_font_options",(PyCFunction)pycairo_set_font_options, METH_VARARGS}, + {"set_font_size", (PyCFunction)pycairo_set_font_size, METH_VARARGS}, + {"set_line_cap", (PyCFunction)pycairo_set_line_cap, METH_VARARGS}, + {"set_line_join", (PyCFunction)pycairo_set_line_join, METH_VARARGS}, + {"set_line_width", (PyCFunction)pycairo_set_line_width, METH_VARARGS}, + {"set_matrix", (PyCFunction)pycairo_set_matrix, METH_VARARGS}, + {"set_miter_limit", (PyCFunction)pycairo_set_miter_limit, METH_VARARGS}, + {"set_operator", (PyCFunction)pycairo_set_operator, METH_VARARGS}, + {"set_scaled_font", (PyCFunction)pycairo_set_scaled_font, METH_VARARGS}, + {"set_source", (PyCFunction)pycairo_set_source, METH_VARARGS}, + {"set_source_rgb", (PyCFunction)pycairo_set_source_rgb, METH_VARARGS}, + {"set_source_rgba", (PyCFunction)pycairo_set_source_rgba, METH_VARARGS}, + {"set_source_surface",(PyCFunction)pycairo_set_source_surface, + METH_VARARGS}, + {"set_tolerance", (PyCFunction)pycairo_set_tolerance, METH_VARARGS}, + {"show_glyphs", (PyCFunction)pycairo_show_glyphs, METH_VARARGS}, + {"show_page", (PyCFunction)pycairo_show_page, METH_NOARGS}, + {"show_text", (PyCFunction)pycairo_show_text, METH_O}, + {"stroke", (PyCFunction)pycairo_stroke, METH_NOARGS}, + {"stroke_extents", (PyCFunction)pycairo_stroke_extents, METH_NOARGS}, + {"stroke_preserve", (PyCFunction)pycairo_stroke_preserve, METH_NOARGS}, + {"text_extents", (PyCFunction)pycairo_text_extents, METH_O}, + {"text_path", (PyCFunction)pycairo_text_path, METH_O}, + {"transform", (PyCFunction)pycairo_transform, METH_VARARGS}, + {"translate", (PyCFunction)pycairo_translate, METH_VARARGS}, + {"user_to_device", (PyCFunction)pycairo_user_to_device, METH_VARARGS}, + {"user_to_device_distance",(PyCFunction)pycairo_user_to_device_distance, + METH_VARARGS}, + {NULL, NULL, 0, NULL}, +}; + +PyTypeObject PycairoContext_Type = { + PyObject_HEAD_INIT(NULL) + 0, /* ob_size */ + "cairo.Context", /* tp_name */ + sizeof(PycairoContext), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)pycairo_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,/* tp_flags */ + 0, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + pycairo_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* &PyBaseObject_Type, */ /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + (newfunc)pycairo_new, /* tp_new */ + 0, /* tp_free */ + 0, /* tp_is_gc */ + 0, /* tp_bases */ +}; diff --git a/src/pycairo-font.c b/src/pycairo-font.c new file mode 100644 index 0000000..8b1215c --- /dev/null +++ b/src/pycairo-font.c @@ -0,0 +1,641 @@ +/* -*- mode: C; c-basic-offset: 4 -*- + * + * Pycairo - Python bindings for cairo + * + * Copyright © 2003 James Henstridge, Steven Chaplin + * + * This library is free software; you can redistribute it and/or + * modify it either under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation + * (the "LGPL") or, at your option, under the terms of the Mozilla + * Public License Version 1.1 (the "MPL"). If you do not alter this + * notice, a recipient may use your version of this file under either + * the MPL or the LGPL. + * + * You should have received a copy of the LGPL along with this library + * in the file COPYING-LGPL-2.1; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * You should have received a copy of the MPL along with this library + * in the file COPYING-MPL-1.1 + * + * The contents of this file are subject to the Mozilla Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY + * OF ANY KIND, either express or implied. See the LGPL or the MPL for + * the specific language governing rights and limitations. + */ + +#define PY_SSIZE_T_CLEAN +#include <Python.h> + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif +#include "pycairo-private.h" + + +/* class cairo.FontFace --------------------------------------------------- */ + +/* PycairoFontFace_FromFontFace + * Create a new PycairoFontFace from a cairo_font_face_t + * font_face - a cairo_font_face_t to 'wrap' into a Python object. + * it is unreferenced if the PycairoFontFace creation fails + * Return value: New reference or NULL on failure + */ +PyObject * +PycairoFontFace_FromFontFace (cairo_font_face_t *font_face) +{ + PyTypeObject *type = NULL; + PyObject *o; + + assert (font_face != NULL); + + if (Pycairo_Check_Status (cairo_font_face_status (font_face))) { + cairo_font_face_destroy (font_face); + return NULL; + } + + switch (cairo_font_face_get_type (font_face)) { + case CAIRO_FONT_TYPE_TOY: + type = &PycairoToyFontFace_Type; + break; + default: + type = &PycairoFontFace_Type; + break; + } + o = type->tp_alloc (type, 0); + if (o == NULL) + cairo_font_face_destroy (font_face); + else + ((PycairoFontFace *)o)->font_face = font_face; + return o; +} + +static void +font_face_dealloc (PycairoFontFace *o) +{ + if (o->font_face) { + cairo_font_face_destroy (o->font_face); + o->font_face = NULL; + } + o->ob_type->tp_free((PyObject *) o); +} + +static PyObject * +font_face_new (PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + PyErr_SetString (PyExc_TypeError, "The FontFace type cannot be " + "instantiated directly, use Context.get_font_face()"); + return NULL; +} + +/* +static PyMethodDef font_face_methods[] = { + * methods never exposed in a language binding: + * cairo_font_face_destroy() + * cairo_font_face_get_user_data() + * cairo_font_face_get_type() + * cairo_font_face_reference() + * cairo_font_face_set_user_data(), + {NULL, NULL, 0, NULL}, +}; +*/ + +PyTypeObject PycairoFontFace_Type = { + PyObject_HEAD_INIT(NULL) + 0, /* ob_size */ + "cairo.FontFace", /* tp_name */ + sizeof(PycairoFontFace), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)font_face_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ + 0, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* &PyBaseObject_Type, */ /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + (newfunc)font_face_new, /* tp_new */ + 0, /* tp_free */ + 0, /* tp_is_gc */ + 0, /* tp_bases */ +}; + + +/* class cairo.ToyFontFace ------------------------------------------------- */ + +static PyObject * +toy_font_face_new (PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + PyObject *obj; + PyObject *pyUTF8 = NULL; + const char *utf8family = NULL; + cairo_font_slant_t slant = CAIRO_FONT_SLANT_NORMAL; + cairo_font_weight_t weight = CAIRO_FONT_WEIGHT_NORMAL; + + if (!PyArg_ParseTuple(args, "O!|ii:ToyFontFace.__new__", + &PyBaseString_Type, &obj, &slant, &weight)) + return NULL; + + /* accept str and unicode family, auto convert to utf8 as required */ + if (PyString_Check(obj)) { + /* A plain ASCII string is also a valid UTF-8 string */ + utf8family = PyString_AS_STRING(obj); + } else if (PyUnicode_Check(obj)) { + pyUTF8 = PyUnicode_AsUTF8String(obj); + if (pyUTF8 != NULL) { + utf8family = PyString_AS_STRING(pyUTF8); + } + } else { + PyErr_SetString(PyExc_TypeError, + "ToyFontFace.__new__: family must be str or unicode"); + } + if (utf8family == NULL) + return NULL; + + PyObject *o = PycairoFontFace_FromFontFace ( + cairo_toy_font_face_create (utf8family, slant, weight)); + Py_XDECREF(pyUTF8); + return o; +} + +static PyObject * +toy_font_get_family (PycairoToyFontFace *o) +{ + return PyString_FromString (cairo_toy_font_face_get_family (o->font_face)); +} + +static PyObject * +toy_font_get_slant (PycairoToyFontFace *o) +{ + return PyInt_FromLong (cairo_toy_font_face_get_slant (o->font_face)); +} + +static PyObject * +toy_font_get_weight (PycairoToyFontFace *o) +{ + return PyInt_FromLong (cairo_toy_font_face_get_weight (o->font_face)); +} + +static PyMethodDef toy_font_face_methods[] = { + {"get_family", (PyCFunction)toy_font_get_family, METH_NOARGS}, + {"get_slant", (PyCFunction)toy_font_get_slant, METH_NOARGS}, + {"get_weight", (PyCFunction)toy_font_get_weight, METH_NOARGS}, + {NULL, NULL, 0, NULL}, +}; + + +PyTypeObject PycairoToyFontFace_Type = { + PyObject_HEAD_INIT(NULL) + 0, /* ob_size */ + "cairo.ToyFontFace", /* tp_name */ + sizeof(PycairoToyFontFace), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ + 0, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + toy_font_face_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* &PycairoFontFace_Type, */ /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + (newfunc)toy_font_face_new, /* tp_new */ + 0, /* tp_free */ + 0, /* tp_is_gc */ + 0, /* tp_bases */ +}; + + +/* class cairo.ScaledFont ------------------------------------------------- */ + +/* PycairoScaledFont_FromScaledFont + * Create a new PycairoScaledFont from a cairo_scaled_font_t + * scaled_font - a cairo_scaled_font_t to 'wrap' into a Python object. + * it is unreferenced if the PycairoScaledFont creation fails + * Return value: New reference or NULL on failure + */ +PyObject * +PycairoScaledFont_FromScaledFont (cairo_scaled_font_t *scaled_font) +{ + PyObject *o; + + assert (scaled_font != NULL); + + if (Pycairo_Check_Status (cairo_scaled_font_status (scaled_font))) { + cairo_scaled_font_destroy (scaled_font); + return NULL; + } + + o = PycairoScaledFont_Type.tp_alloc (&PycairoScaledFont_Type, 0); + if (o == NULL) + cairo_scaled_font_destroy (scaled_font); + else + ((PycairoScaledFont *)o)->scaled_font = scaled_font; + return o; +} + +static void +scaled_font_dealloc(PycairoScaledFont *o) +{ + if (o->scaled_font) { + cairo_scaled_font_destroy (o->scaled_font); + o->scaled_font = NULL; + } + o->ob_type->tp_free((PyObject *) o); +} + +static PyObject * +scaled_font_new (PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + PycairoFontFace *ff; + PycairoFontOptions *fo; + PycairoMatrix *mx1, *mx2; + + if (!PyArg_ParseTuple(args, "O!O!O!O!:ScaledFont.__new__", + &PycairoFontFace_Type, &ff, + &PycairoMatrix_Type, &mx1, + &PycairoMatrix_Type, &mx2, + &PycairoFontOptions_Type, &fo)) + return NULL; + return PycairoScaledFont_FromScaledFont ( + cairo_scaled_font_create (ff->font_face, &mx1->matrix, + &mx2->matrix, fo->font_options)); +} + +static PyObject * +scaled_font_extents (PycairoScaledFont *o) +{ + cairo_font_extents_t e; + + cairo_scaled_font_extents (o->scaled_font, &e); + RETURN_NULL_IF_CAIRO_SCALED_FONT_ERROR(o->scaled_font); + return Py_BuildValue ("(ddddd)", e.ascent, e.descent, e.height, + e.max_x_advance, e.max_y_advance); +} + +static PyObject * +scaled_font_get_font_face (PycairoScaledFont *o) +{ + return PycairoFontFace_FromFontFace ( + cairo_font_face_reference ( + cairo_scaled_font_get_font_face (o->scaled_font))); +} + +static PyObject * +scaled_font_get_scale_matrix (PycairoScaledFont *o) +{ + cairo_matrix_t matrix; + cairo_scaled_font_get_scale_matrix (o->scaled_font, &matrix); + return PycairoMatrix_FromMatrix (&matrix); +} + +static PyObject * +scaled_font_text_extents (PycairoScaledFont *o, PyObject *obj) +{ + cairo_text_extents_t extents; + PyObject *pyUTF8 = NULL; + const char *utf8 = NULL; + + /* accept str and unicode text, auto convert to utf8 as required */ + if (PyString_Check(obj)) { + /* A plain ASCII string is also a valid UTF-8 string */ + utf8 = PyString_AS_STRING(obj); + } else if (PyUnicode_Check(obj)) { + pyUTF8 = PyUnicode_AsUTF8String(obj); + if (pyUTF8 != NULL) { + utf8 = PyString_AS_STRING(pyUTF8); + } + } else { + PyErr_SetString(PyExc_TypeError, + "ScaledFont.text_extents: text must be str or unicode"); + } + if (utf8 == NULL) + return NULL; + + cairo_scaled_font_text_extents (o->scaled_font, utf8, &extents); + Py_XDECREF(pyUTF8); + RETURN_NULL_IF_CAIRO_SCALED_FONT_ERROR(o->scaled_font); + return Py_BuildValue("(dddddd)", extents.x_bearing, extents.y_bearing, + extents.width, extents.height, extents.x_advance, + extents.y_advance); +} + +static PyMethodDef scaled_font_methods[] = { + /* methods never exposed in a language binding: + * cairo_scaled_font_destroy() + * cairo_scaled_font_get_type() + * cairo_scaled_font_reference() + * + * TODO if requested: + * cairo_scaled_font_get_ctm + * cairo_scaled_font_get_font_matrix + * cairo_scaled_font_get_font_options + * cairo_scaled_font_glyph_extents + * cairo_scaled_font_text_to_glyphs + */ + {"extents", (PyCFunction)scaled_font_extents, METH_NOARGS}, + {"get_font_face", (PyCFunction)scaled_font_get_font_face, METH_NOARGS}, + {"get_scale_matrix", (PyCFunction)scaled_font_get_scale_matrix, + METH_VARARGS}, + {"text_extents", (PyCFunction)scaled_font_text_extents, METH_O}, + {NULL, NULL, 0, NULL}, +}; + + +PyTypeObject PycairoScaledFont_Type = { + PyObject_HEAD_INIT(NULL) + 0, /* ob_size */ + "cairo.ScaledFont", /* tp_name */ + sizeof(PycairoScaledFont), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)scaled_font_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ + 0, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + scaled_font_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* &PyBaseObject_Type, */ /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + (newfunc)scaled_font_new, /* tp_new */ + 0, /* tp_free */ + 0, /* tp_is_gc */ + 0, /* tp_bases */ +}; + + +/* class cairo.FontOptions ------------------------------------------------ */ + +/* PycairoFontOptions_FromFontOptions + * Create a new PycairoFontOptions from a cairo_font_options_t + * font_options - a cairo_font_options_t to 'wrap' into a Python object. + * it is unreferenced if the PycairoFontOptions creation fails + * Return value: New reference or NULL on failure + */ +PyObject * +PycairoFontOptions_FromFontOptions (cairo_font_options_t *font_options) +{ + PyObject *o; + + assert (font_options != NULL); + + if (Pycairo_Check_Status (cairo_font_options_status (font_options))) { + cairo_font_options_destroy (font_options); + return NULL; + } + + o = PycairoFontOptions_Type.tp_alloc (&PycairoFontOptions_Type, 0); + if (o == NULL) + cairo_font_options_destroy (font_options); + else + ((PycairoFontOptions *)o)->font_options = font_options; + return o; +} + +static void +font_options_dealloc(PycairoFontOptions *o) +{ + if (o->font_options) { + cairo_font_options_destroy (o->font_options); + o->font_options = NULL; + } + o->ob_type->tp_free((PyObject *) o); +} + +static PyObject * +font_options_new (PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + return PycairoFontOptions_FromFontOptions (cairo_font_options_create()); +} + +static PyObject * +font_options_get_antialias (PycairoFontOptions *o) +{ + return PyInt_FromLong (cairo_font_options_get_antialias (o->font_options)); +} + +static PyObject * +font_options_get_hint_metrics (PycairoFontOptions *o) +{ + return PyInt_FromLong (cairo_font_options_get_hint_metrics + (o->font_options)); +} + +static PyObject * +font_options_get_hint_style (PycairoFontOptions *o) +{ + return PyInt_FromLong (cairo_font_options_get_hint_style + (o->font_options)); +} + +static PyObject * +font_options_get_subpixel_order (PycairoFontOptions *o) +{ + return PyInt_FromLong (cairo_font_options_get_subpixel_order + (o->font_options)); +} + +static PyObject * +font_options_set_antialias (PycairoFontOptions *o, PyObject *args) +{ + cairo_antialias_t aa = CAIRO_ANTIALIAS_DEFAULT; + + if (!PyArg_ParseTuple(args, "|i:FontOptions.set_antialias", &aa)) + return NULL; + + cairo_font_options_set_antialias (o->font_options, aa); + RETURN_NULL_IF_CAIRO_FONT_OPTIONS_ERROR(o->font_options); + Py_RETURN_NONE; +} + +static PyObject * +font_options_set_hint_metrics (PycairoFontOptions *o, PyObject *args) +{ + cairo_hint_metrics_t hm = CAIRO_HINT_METRICS_DEFAULT; + + if (!PyArg_ParseTuple(args, "|i:FontOptions.set_hint_metrics", &hm)) + return NULL; + + cairo_font_options_set_hint_metrics (o->font_options, hm); + RETURN_NULL_IF_CAIRO_FONT_OPTIONS_ERROR(o->font_options); + Py_RETURN_NONE; +} + +static PyObject * +font_options_set_hint_style (PycairoFontOptions *o, PyObject *args) +{ + cairo_hint_style_t hs = CAIRO_HINT_STYLE_DEFAULT; + + if (!PyArg_ParseTuple(args, "|i:FontOptions.set_hint_style", &hs)) + return NULL; + + cairo_font_options_set_hint_style (o->font_options, hs); + RETURN_NULL_IF_CAIRO_FONT_OPTIONS_ERROR(o->font_options); + Py_RETURN_NONE; +} + +static PyObject * +font_options_set_subpixel_order (PycairoFontOptions *o, PyObject *args) +{ + cairo_subpixel_order_t so = CAIRO_SUBPIXEL_ORDER_DEFAULT; + + if (!PyArg_ParseTuple(args, "|i:FontOptions.set_subpixel_order", &so)) + return NULL; + + cairo_font_options_set_subpixel_order (o->font_options, so); + RETURN_NULL_IF_CAIRO_FONT_OPTIONS_ERROR(o->font_options); + Py_RETURN_NONE; +} + + +static PyMethodDef font_options_methods[] = { + /* methods never exposed in a language binding: + * cairo_font_options_destroy() + * cairo_font_options_reference() + */ + /* TODO: */ + /* copy */ + /* hash */ + /* merge */ + /* equal (richcmp?) */ + {"get_antialias", (PyCFunction)font_options_get_antialias, + METH_NOARGS}, + {"get_hint_metrics", (PyCFunction)font_options_get_hint_metrics, + METH_NOARGS}, + {"get_hint_style", (PyCFunction)font_options_get_hint_style, + METH_NOARGS}, + {"get_subpixel_order",(PyCFunction)font_options_get_subpixel_order, + METH_NOARGS}, + {"set_antialias", (PyCFunction)font_options_set_antialias, + METH_VARARGS}, + {"set_hint_metrics", (PyCFunction)font_options_set_hint_metrics, + METH_VARARGS}, + {"set_hint_style", (PyCFunction)font_options_set_hint_style, + METH_VARARGS}, + {"set_subpixel_order",(PyCFunction)font_options_set_subpixel_order, + METH_VARARGS}, + {NULL, NULL, 0, NULL}, +}; + + +PyTypeObject PycairoFontOptions_Type = { + PyObject_HEAD_INIT(NULL) + 0, /* ob_size */ + "cairo.FontOptions", /* tp_name */ + sizeof(PycairoFontOptions), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)font_options_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ + 0, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + font_options_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* &PyBaseObject_Type, */ /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + (newfunc)font_options_new, /* tp_new */ + 0, /* tp_free */ + 0, /* tp_is_gc */ + 0, /* tp_bases */ +}; diff --git a/src/pycairo-matrix.c b/src/pycairo-matrix.c new file mode 100644 index 0000000..73f1845 --- /dev/null +++ b/src/pycairo-matrix.c @@ -0,0 +1,365 @@ +/* -*- mode: C; c-basic-offset: 4 -*- + * + * Pycairo - Python bindings for cairo + * + * Copyright © 2003 James Henstridge, Steven Chaplin + * + * This library is free software; you can redistribute it and/or + * modify it either under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation + * (the "LGPL") or, at your option, under the terms of the Mozilla + * Public License Version 1.1 (the "MPL"). If you do not alter this + * notice, a recipient may use your version of this file under either + * the MPL or the LGPL. + * + * You should have received a copy of the LGPL along with this library + * in the file COPYING-LGPL-2.1; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * You should have received a copy of the MPL along with this library + * in the file COPYING-MPL-1.1 + * + * The contents of this file are subject to the Mozilla Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY + * OF ANY KIND, either express or implied. See the LGPL or the MPL for + * the specific language governing rights and limitations. + */ + +#define PY_SSIZE_T_CLEAN +#include <Python.h> + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif +#include "pycairo-private.h" + + +/* PycairoMatrix_FromMatrix + * Create a new PycairoMatrix from a cairo_matrix_t + * matrix - a cairo_matrix_t to 'wrap' into a Python object + * Return value: New reference or NULL on failure + */ +PyObject * +PycairoMatrix_FromMatrix (const cairo_matrix_t *matrix) +{ + PyObject *o; + assert (matrix != NULL); + o = PycairoMatrix_Type.tp_alloc (&PycairoMatrix_Type, 0); + if (o != NULL) + ((PycairoMatrix *)o)->matrix = *matrix; + return o; +} + +static void +matrix_dealloc (PycairoMatrix *o) +{ + o->ob_type->tp_free((PyObject *)o); +} + +static PyObject * +matrix_new (PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + PyObject *o; + static char *kwlist[] = { "xx", "yx", "xy", "yy", "x0", "y0", NULL }; + double xx = 1.0, yx = 0.0, xy = 0.0, yy = 1.0, x0 = 0.0, y0 = 0.0; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, + "|dddddd:Matrix.__init__", kwlist, + &xx, &yx, &xy, &yy, &x0, &y0)) + return NULL; + + o = type->tp_alloc(type, 0); + if (o) + cairo_matrix_init (&((PycairoMatrix *)o)->matrix, + xx, yx, xy, yy, x0, y0); + return o; +} + +static PyObject * +matrix_init_rotate (PyTypeObject *type, PyObject *args) +{ + cairo_matrix_t matrix; + double radians; + + if (!PyArg_ParseTuple(args, "d:Matrix.init_rotate", &radians)) + return NULL; + + cairo_matrix_init_rotate (&matrix, radians); + return PycairoMatrix_FromMatrix (&matrix); +} + +static PyObject * +matrix_invert (PycairoMatrix *o) +{ + if (Pycairo_Check_Status (cairo_matrix_invert (&o->matrix))) + return NULL; + Py_RETURN_NONE; +} + +/* cairo_matrix_multiply */ +static PyObject * +matrix_multiply (PycairoMatrix *o, PyObject *args) +{ + PycairoMatrix *mx2; + + if (!PyArg_ParseTuple(args, "O!:Matrix.multiply", + &PycairoMatrix_Type, &mx2)) + return NULL; + + cairo_matrix_t result; + cairo_matrix_multiply (&result, &o->matrix, &mx2->matrix); + return PycairoMatrix_FromMatrix (&result); +} + +/* standard matrix multiply, for use by '*' operator */ +static PyObject * +matrix_operator_multiply (PycairoMatrix *o, PycairoMatrix *o2) +{ + cairo_matrix_t result; + cairo_matrix_multiply (&result, &o->matrix, &o2->matrix); + return PycairoMatrix_FromMatrix (&result); +} + +static PyObject * +matrix_repr (PycairoMatrix *o) +{ + char buf[256]; + + PyOS_snprintf(buf, sizeof(buf), "cairo.Matrix(%g, %g, %g, %g, %g, %g)", + o->matrix.xx, o->matrix.yx, + o->matrix.xy, o->matrix.yy, + o->matrix.x0, o->matrix.y0); + return PyString_FromString(buf); +} + +static PyObject * +matrix_richcmp (PycairoMatrix *m1, PycairoMatrix *m2, int op) +{ + int equal; + PyObject *ret; + cairo_matrix_t *mx1 = &m1->matrix; + cairo_matrix_t *mx2 = &m2->matrix; + + if (!PyObject_TypeCheck(m2, &PycairoMatrix_Type) || + !(op == Py_EQ || op == Py_NE)) { + Py_INCREF(Py_NotImplemented); + return Py_NotImplemented; + } + + equal = mx1->xx == mx2->xx && mx1->yx == mx2->yx && + mx1->xy == mx2->xy && mx1->yy == mx2->yy && + mx1->x0 == mx2->x0 && mx1->y0 == mx2->y0; + + if (op == Py_EQ) + ret = equal ? Py_True : Py_False; + else + ret = equal ? Py_False : Py_True; + Py_INCREF(ret); + return ret; +} + +static PyObject * +matrix_rotate (PycairoMatrix *o, PyObject *args) +{ + double radians; + + if (!PyArg_ParseTuple(args, "d:Matrix.rotate", &radians)) + return NULL; + + cairo_matrix_rotate (&o->matrix, radians); + Py_RETURN_NONE; +} + +static PyObject * +matrix_scale (PycairoMatrix *o, PyObject *args) +{ + double sx, sy; + + if (!PyArg_ParseTuple(args, "dd:Matrix.scale", &sx, &sy)) + return NULL; + + cairo_matrix_scale (&o->matrix, sx, sy); + Py_RETURN_NONE; +} + +static PyObject * +matrix_transform_distance (PycairoMatrix *o, PyObject *args) +{ + double dx, dy; + + if (!PyArg_ParseTuple(args, "dd:Matrix.transform_distance", &dx, &dy)) + return NULL; + + cairo_matrix_transform_distance (&o->matrix, &dx, &dy); + return Py_BuildValue("(dd)", dx, dy); +} + +static PyObject * +matrix_transform_point (PycairoMatrix *o, PyObject *args) +{ + double x, y; + + if (!PyArg_ParseTuple(args, "dd:Matrix.transform_point", &x, &y)) + return NULL; + + cairo_matrix_transform_point (&o->matrix, &x, &y); + return Py_BuildValue("(dd)", x, y); +} + +static PyObject * +matrix_translate (PycairoMatrix *o, PyObject *args) +{ + double tx, ty; + + if (!PyArg_ParseTuple(args, "dd:Matrix.translate", &tx, &ty)) + return NULL; + + cairo_matrix_translate (&o->matrix, tx, ty); + Py_RETURN_NONE; +} + +static PyObject * +matrix_item (PycairoMatrix *o, Py_ssize_t i) +{ + switch (i) { + case 0: + return Py_BuildValue("d", o->matrix.xx); + case 1: + return Py_BuildValue("d", o->matrix.yx); + case 2: + return Py_BuildValue("d", o->matrix.xy); + case 3: + return Py_BuildValue("d", o->matrix.yy); + case 4: + return Py_BuildValue("d", o->matrix.x0); + case 5: + return Py_BuildValue("d", o->matrix.y0); + default: + PyErr_SetString(PyExc_IndexError, "Matrix index out of range"); + return NULL; + } +} + +static PyNumberMethods matrix_as_number = { + (binaryfunc)0, /*nb_add*/ + (binaryfunc)0, /*nb_subtract*/ + (binaryfunc)matrix_operator_multiply, /*nb_multiply*/ + (binaryfunc)0, /*nb_divide*/ + (binaryfunc)0, /*nb_remainder*/ + (binaryfunc)0, /*nb_divmod*/ + (ternaryfunc)0, /*nb_power*/ + (unaryfunc)0, /*nb_negative*/ + (unaryfunc)0, /*nb_positive*/ + (unaryfunc)0, /*nb_absolute*/ + (inquiry)0, /*nb_nonzero*/ + (unaryfunc)0, /*nb_invert*/ + (binaryfunc)0, /*nb_lshift*/ + (binaryfunc)0, /*nb_rshift*/ + (binaryfunc)0, /*nb_and*/ + (binaryfunc)0, /*nb_xor*/ + (binaryfunc)0, /*nb_or*/ + (coercion)0, /*nb_coerce*/ + (unaryfunc)0, /*nb_int*/ + (unaryfunc)0, /*nb_long*/ + (unaryfunc)0, /*nb_float*/ + (unaryfunc)0, /*nb_oct*/ + (unaryfunc)0, /*nb_hex*/ + 0, /*nb_inplace_add*/ + 0, /*nb_inplace_subtract*/ + 0, /*nb_inplace_multiply*/ + 0, /*nb_inplace_divide*/ + 0, /*nb_inplace_remainder*/ + 0, /*nb_inplace_power*/ + 0, /*nb_inplace_lshift*/ + 0, /*nb_inplace_rshift*/ + 0, /*nb_inplace_and*/ + 0, /*nb_inplace_xor*/ + 0, /*nb_inplace_or*/ + (binaryfunc)0, /* nb_floor_divide */ + 0, /* nb_true_divide */ + 0, /* nb_inplace_floor_divide */ + 0, /* nb_inplace_true_divide */ + (unaryfunc)0, /* nb_index */ +}; + +static PySequenceMethods matrix_as_sequence = { + 0, /* sq_length */ + 0, /* sq_concat */ + 0, /* sq_repeat */ + (ssizeargfunc)matrix_item, /* sq_item */ + 0, /* sq_slice */ + 0, /* sq_ass_item */ + 0, /* sq_ass_slice */ + 0, /* sq_contains */ +}; + +static PyMethodDef matrix_methods[] = { + /* Do not need to wrap all cairo_matrix_init_*() functions + * C API Matrix constructors Python equivalents + * cairo_matrix_init() cairo.Matrix(xx,yx,xy,yy,x0,y0) + * cairo_matrix_init_rotate() cairo.Matrix.init_rotate(radians) + + * cairo_matrix_init_identity() cairo.Matrix() + * cairo_matrix_init_translate() cairo.Matrix(x0=x0,y0=y0) + * cairo_matrix_init_scale() cairo.Matrix(xx=xx,yy=yy) + */ + {"init_rotate", (PyCFunction)matrix_init_rotate, + METH_VARARGS | METH_CLASS }, + {"invert", (PyCFunction)matrix_invert, METH_NOARGS }, + {"multiply", (PyCFunction)matrix_multiply, METH_VARARGS }, + {"rotate", (PyCFunction)matrix_rotate, METH_VARARGS }, + {"scale", (PyCFunction)matrix_scale, METH_VARARGS }, + {"transform_distance",(PyCFunction)matrix_transform_distance, + METH_VARARGS }, + {"transform_point", (PyCFunction)matrix_transform_point, METH_VARARGS }, + {"translate", (PyCFunction)matrix_translate, METH_VARARGS }, + {NULL, NULL, 0, NULL}, +}; + +PyTypeObject PycairoMatrix_Type = { + PyObject_HEAD_INIT(NULL) + 0, /* ob_size */ + "cairo.Matrix", /* tp_name */ + sizeof(PycairoMatrix), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)matrix_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + (reprfunc)matrix_repr, /* tp_repr */ + &matrix_as_number, /* tp_as_number */ + &matrix_as_sequence, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ + NULL, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + (richcmpfunc)matrix_richcmp, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + matrix_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* &PyBaseObject_Type, */ /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + (newfunc)matrix_new, /* tp_new */ + 0, /* tp_free */ + 0, /* tp_is_gc */ + 0, /* tp_bases */ +}; diff --git a/src/pycairo-path.c b/src/pycairo-path.c new file mode 100644 index 0000000..7473f14 --- /dev/null +++ b/src/pycairo-path.c @@ -0,0 +1,337 @@ +/* -*- mode: C; c-basic-offset: 4 -*- + * + * Pycairo - Python bindings for cairo + * + * Copyright © 2005 Steve Chaplin + * + * This library is free software; you can redistribute it and/or + * modify it either under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation + * (the "LGPL") or, at your option, under the terms of the Mozilla + * Public License Version 1.1 (the "MPL"). If you do not alter this + * notice, a recipient may use your version of this file under either + * the MPL or the LGPL. + * + * You should have received a copy of the LGPL along with this library + * in the file COPYING-LGPL-2.1; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * You should have received a copy of the MPL along with this library + * in the file COPYING-MPL-1.1 + * + * The contents of this file are subject to the Mozilla Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY + * OF ANY KIND, either express or implied. See the LGPL or the MPL for + * the specific language governing rights and limitations. + */ + +#define PY_SSIZE_T_CLEAN +#include <Python.h> + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif +#include "pycairo-private.h" + + +/* PycairoPath iterator object + * modelled on Python-2.4/Objects/rangeobject.c and tupleobject.c + */ + +/* PycairoPath_FromPath + * Create a new PycairoPath from a cairo_path_t + * path - a cairo_path_t to 'wrap' into a Python object. + * path is unreferenced if the PycairoPath creation fails, or if path + * is in an error status. + * Return value: New reference or NULL on failure + */ +PyObject * +PycairoPath_FromPath (cairo_path_t *path) +{ + PyObject *o; + + assert (path != NULL); + + if (Pycairo_Check_Status (path->status)) { + cairo_path_destroy (path); + return NULL; + } + + o = PycairoPath_Type.tp_alloc (&PycairoPath_Type, 0); + if (o) + ((PycairoPath *)o)->path = path; + else + cairo_path_destroy (path); + return o; +} + +static void +path_dealloc(PycairoPath *p) +{ +#ifdef DEBUG + printf("path_dealloc start\n"); +#endif + if (p->path) { + cairo_path_destroy(p->path); + p->path = NULL; + } + p->ob_type->tp_free((PyObject *)p); +#ifdef DEBUG + printf("path_dealloc end\n"); +#endif +} + +static PyObject * +path_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + return type->tp_alloc(type, 0); + /* initializes memory to zeros */ +} + +static int +path_init(PycairoPath *p, PyObject *args, PyObject *kwds) +{ + PyErr_SetString(PyExc_TypeError, "The Path type cannot be instantiated, " + "use Context.copy_path()"); + return -1; +} + +static PyObject * +path_str(PycairoPath *p) +{ + PyObject *s, *pieces = NULL, *result = NULL; + cairo_path_t *path = p->path; + cairo_path_data_t *data; + int i, ret; + char buf[80]; + + pieces = PyList_New(0); + if (pieces == NULL) + goto Done; + + /* loop reading elements */ + for (i=0; i < path->num_data; i += path->data[i].header.length) { + data = &path->data[i]; + switch (data->header.type) { + + case CAIRO_PATH_MOVE_TO: + PyOS_snprintf(buf, sizeof(buf), "move_to %f %f", + data[1].point.x, data[1].point.y); + s = PyString_FromString(buf); + if (!s) + goto Done; + ret = PyList_Append(pieces, s); + Py_DECREF(s); + if (ret < 0) + goto Done; + break; + + case CAIRO_PATH_LINE_TO: + PyOS_snprintf(buf, sizeof(buf), "line_to %f %f", + data[1].point.x, data[1].point.y); + s = PyString_FromString(buf); + if (!s) + goto Done; + ret = PyList_Append(pieces, s); + Py_DECREF(s); + if (ret < 0) + goto Done; + break; + + case CAIRO_PATH_CURVE_TO: + PyOS_snprintf(buf, sizeof(buf), "curve_to %f %f %f %f %f %f", + data[1].point.x, data[1].point.y, + data[2].point.x, data[2].point.y, + data[3].point.x, data[3].point.y); + s = PyString_FromString(buf); + if (!s) + goto Done; + ret = PyList_Append(pieces, s); + Py_DECREF(s); + if (ret < 0) + goto Done; + break; + + case CAIRO_PATH_CLOSE_PATH: + s = PyString_FromString("close path"); + if (!s) + goto Done; + ret = PyList_Append(pieces, s); + Py_DECREF(s); + if (ret < 0) + goto Done; + break; + } + } + /* result = "\n".join(pieces) */ + s = PyString_FromString("\n"); + if (s == NULL) + goto Done; + result = _PyString_Join(s, pieces); + Py_DECREF(s); + +Done: + Py_XDECREF(pieces); + return result; +} + +static PyObject * path_iter(PyObject *seq); /* forward declaration */ + + +PyTypeObject PycairoPath_Type = { + PyObject_HEAD_INIT(NULL) + 0, /* ob_size */ + "cairo.Path", /* tp_name */ + sizeof(PycairoPath), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)path_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + (reprfunc)path_str, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ + 0, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + (getiterfunc)path_iter, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* &PyBaseObject_Type, */ /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)path_init, /* tp_init */ + 0, /* tp_alloc */ + (newfunc)path_new, /* tp_new */ +}; + +/*********************** PycairoPath Iterator **************************/ + +typedef struct { + PyObject_HEAD + int index; /* position within PycairoPath */ + PycairoPath *pypath; /* Set to NULL when iterator is exhausted */ +} PycairoPathiter; + +PyTypeObject PycairoPathiter_Type; + + +static void +pathiter_dealloc(PycairoPathiter *it) +{ + Py_XDECREF(it->pypath); + PyObject_Del(it); +} + +static PyObject * +path_iter(PyObject *pypath) +{ + PycairoPathiter *it; + + if (!PyObject_TypeCheck (pypath, &PycairoPath_Type)) { + PyErr_BadInternalCall(); + return NULL; + } + it = PyObject_New(PycairoPathiter, &PycairoPathiter_Type); + if (it == NULL) + return NULL; + + it->index = 0; + Py_INCREF(pypath); + it->pypath = (PycairoPath *)pypath; + return (PyObject *) it; +} + +static PyObject * +pathiter_next(PycairoPathiter *it) +{ + PycairoPath *pypath; + cairo_path_t *path; + + assert(it != NULL); + pypath = it->pypath; + if (pypath == NULL) + return NULL; + assert (PyObject_TypeCheck (pypath, &PycairoPath_Type)); + path = pypath->path; + + /* return the next path element, advance index */ + if (it->index < path->num_data) { + cairo_path_data_t *data = &path->data[it->index]; + int type = data->header.type; + + it->index += data[0].header.length; + + switch (type) { + case CAIRO_PATH_MOVE_TO: + case CAIRO_PATH_LINE_TO: + return Py_BuildValue("(i(dd))", type, + data[1].point.x, data[1].point.y); + case CAIRO_PATH_CURVE_TO: + return Py_BuildValue("(i(dddddd))", type, + data[1].point.x, data[1].point.y, + data[2].point.x, data[2].point.y, + data[3].point.x, data[3].point.y); + case CAIRO_PATH_CLOSE_PATH: + return Py_BuildValue("i()", type); + default: + PyErr_SetString(PyExc_RuntimeError, "unknown CAIRO_PATH type"); + return NULL; + } + } + + /* iterator has no remaining items */ + Py_DECREF(pypath); + it->pypath = NULL; + return NULL; +} + +PyTypeObject PycairoPathiter_Type = { + PyObject_HEAD_INIT(NULL) + 0, /* ob_size */ + "cairo.Pathiter", /* tp_name */ + sizeof(PycairoPathiter), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)pathiter_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ + 0, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* PyObject_SelfIter, */ /* tp_iter */ + (iternextfunc)pathiter_next, /* tp_iternext */ + 0, /* tp_methods */ +}; diff --git a/src/pycairo-pattern.c b/src/pycairo-pattern.c new file mode 100644 index 0000000..3a793f7 --- /dev/null +++ b/src/pycairo-pattern.c @@ -0,0 +1,618 @@ +/* -*- mode: C; c-basic-offset: 4 -*- + * + * Pycairo - Python bindings for cairo + * + * Copyright © 2004-2006 Steve Chaplin + * + * This library is free software; you can redistribute it and/or + * modify it either under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation + * (the "LGPL") or, at your option, under the terms of the Mozilla + * Public License Version 1.1 (the "MPL"). If you do not alter this + * notice, a recipient may use your version of this file under either + * the MPL or the LGPL. + * + * You should have received a copy of the LGPL along with this library + * in the file COPYING-LGPL-2.1; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * You should have received a copy of the MPL along with this library + * in the file COPYING-MPL-1.1 + * + * The contents of this file are subject to the Mozilla Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY + * OF ANY KIND, either express or implied. See the LGPL or the MPL for + * the specific language governing rights and limitations. + */ + +#define PY_SSIZE_T_CLEAN +#include <Python.h> + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif +#include "pycairo-private.h" + + +/* Class Pattern ---------------------------------------------------------- */ + +/* PycairoPattern_FromPattern + * Create a new + * PycairoSolidPattern, + * PycairoSurfacePattern, + * PycairoLinearGradient, or + * PycairoRadialGradient from a cairo_pattern_t. + * pattern - a cairo_pattern_t to 'wrap' into a Python object. + * It is unreferenced if the PycairoPattern creation fails, or if the + * pattern has an error status. + * base - the base object used to create the pattern, or NULL. + * It is referenced to keep it alive while the cairo_pattern_t is being used. + * For PycairoSurfacePattern base should be the PycairoSurface, for other + # patterns it should be NULL. + * Return value: New reference or NULL on failure + */ +PyObject * +PycairoPattern_FromPattern (cairo_pattern_t *pattern, PyObject *base) +{ + PyTypeObject *type = NULL; + PyObject *o; + + assert (pattern != NULL); + + if (Pycairo_Check_Status (cairo_pattern_status (pattern))) { + cairo_pattern_destroy (pattern); + return NULL; + } + + switch (cairo_pattern_get_type (pattern)) { + case CAIRO_PATTERN_TYPE_SOLID: + type = &PycairoSolidPattern_Type; + break; + case CAIRO_PATTERN_TYPE_SURFACE: + type = &PycairoSurfacePattern_Type; + break; + case CAIRO_PATTERN_TYPE_LINEAR: + type = &PycairoLinearGradient_Type; + break; + case CAIRO_PATTERN_TYPE_RADIAL: + type = &PycairoRadialGradient_Type; + break; + default: + type = &PycairoPattern_Type; + break; + } + + o = type->tp_alloc(type, 0); + if (o == NULL) { + cairo_pattern_destroy (pattern); + } else { + ((PycairoPattern *)o)->pattern = pattern; + Py_XINCREF(base); + ((PycairoPattern *)o)->base = base; + } + return o; +} + +static void +pattern_dealloc (PycairoPattern *o) +{ + if (o->pattern) { + cairo_pattern_destroy (o->pattern); + o->pattern = NULL; + } + Py_CLEAR(o->base); + + o->ob_type->tp_free((PyObject *)o); +} + +static PyObject * +pattern_new (PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + PyErr_SetString(PyExc_TypeError, + "The Pattern type cannot be instantiated"); + return NULL; +} + +static PyObject * +pattern_get_extend (PycairoPattern *o) +{ + return PyInt_FromLong (cairo_pattern_get_extend (o->pattern)); +} + +static PyObject * +pattern_get_matrix (PycairoPattern *o) +{ + cairo_matrix_t matrix; + cairo_pattern_get_matrix (o->pattern, &matrix); + return PycairoMatrix_FromMatrix (&matrix); +} + +static PyObject * +pattern_set_extend (PycairoPattern *o, PyObject *args) +{ + int extend; + + if (!PyArg_ParseTuple(args, "i:Pattern.set_extend", &extend)) + return NULL; + + cairo_pattern_set_extend (o->pattern, extend); + Py_RETURN_NONE; +} + +static PyObject * +pattern_set_matrix (PycairoPattern *o, PyObject *args) +{ + PycairoMatrix *m; + + if (!PyArg_ParseTuple (args, "O!:Pattern.set_matrix", + &PycairoMatrix_Type, &m)) + return NULL; + + cairo_pattern_set_matrix (o->pattern, &m->matrix); + Py_RETURN_NONE; +} + +static PyMethodDef pattern_methods[] = { + /* methods never exposed in a language binding: + * cairo_pattern_destroy() + * cairo_pattern_get_type() + * cairo_pattern_reference() + * + * cairo_pattern_status() + * - not needed since Pycairo handles status checking + */ + {"get_extend", (PyCFunction)pattern_get_extend, METH_NOARGS }, + {"get_matrix", (PyCFunction)pattern_get_matrix, METH_NOARGS }, + {"set_extend", (PyCFunction)pattern_set_extend, METH_VARARGS }, + {"set_matrix", (PyCFunction)pattern_set_matrix, METH_VARARGS }, + {NULL, NULL, 0, NULL}, +}; + +PyTypeObject PycairoPattern_Type = { + PyObject_HEAD_INIT(NULL) + 0, /* ob_size */ + "cairo.Pattern", /* tp_name */ + sizeof(PycairoPattern), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)pattern_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,/* tp_flags */ + 0, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + pattern_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* &PyBaseObject_Type, */ /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + (newfunc)pattern_new, /* tp_new */ + 0, /* tp_free */ + 0, /* tp_is_gc */ + 0, /* tp_bases */ +}; + + +/* Class SolidPattern ----------------------------------------------------- */ + +static PyObject * +solid_pattern_new (PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + double r, g, b, a = 1.0; + if (!PyArg_ParseTuple (args, "ddd|d:SolidPattern.__new__", &r, &g, &b, &a)) + return NULL; + return PycairoPattern_FromPattern (cairo_pattern_create_rgba (r, g, b, a), + NULL); +} + +static PyObject * +solid_pattern_get_rgba (PycairoSolidPattern *o) +{ + double red, green, blue, alpha; + cairo_pattern_get_rgba (o->pattern, &red, &green, &blue, &alpha); + return Py_BuildValue("(dddd)", red, green, blue, alpha); +} + +static PyMethodDef solid_pattern_methods[] = { + {"get_rgba", (PyCFunction)solid_pattern_get_rgba, METH_NOARGS }, + {NULL, NULL, 0, NULL}, +}; + +PyTypeObject PycairoSolidPattern_Type = { + PyObject_HEAD_INIT(NULL) + 0, /* ob_size */ + "cairo.SolidPattern", /* tp_name */ + sizeof(PycairoSolidPattern), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ + 0, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + solid_pattern_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* &PyPattern_Type, */ /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + (newfunc)solid_pattern_new, /* tp_new */ + 0, /* tp_free */ + 0, /* tp_is_gc */ + 0, /* tp_bases */ +}; + +/* Class SurfacePattern --------------------------------------------------- */ + +static PyObject * +surface_pattern_new (PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + PycairoSurface *s; + if (!PyArg_ParseTuple (args, "O!:SurfacePattern.__new__", + &PycairoSurface_Type, &s)) + return NULL; + return PycairoPattern_FromPattern ( + cairo_pattern_create_for_surface (s->surface), (PyObject *)s); +} + +static PyObject * +surface_pattern_get_filter (PycairoSurfacePattern *o) +{ + return PyInt_FromLong (cairo_pattern_get_filter (o->pattern)); +} + +static PyObject * +surface_pattern_get_surface (PycairoSurfacePattern *o) +{ + /* + cairo_surface_t *surface; + cairo_pattern_get_surface (o->pattern, &surface); + return PycairoSurface_FromSurface ( + cairo_surface_reference (surface), NULL); + */ + /* return the surface used to create the pattern */ + return Py_BuildValue("O", o->base); +} + +static PyObject * +surface_pattern_set_filter (PycairoSurfacePattern *o, PyObject *args) +{ + int filter; + + if (!PyArg_ParseTuple (args, "i:SurfacePattern.set_filter", &filter)) + return NULL; + + cairo_pattern_set_filter (o->pattern, filter); + Py_RETURN_NONE; +} + +static PyMethodDef surface_pattern_methods[] = { + {"get_filter", (PyCFunction)surface_pattern_get_filter, METH_NOARGS }, + {"get_surface", (PyCFunction)surface_pattern_get_surface, METH_NOARGS }, + {"set_filter", (PyCFunction)surface_pattern_set_filter, METH_VARARGS }, + {NULL, NULL, 0, NULL}, +}; + +PyTypeObject PycairoSurfacePattern_Type = { + PyObject_HEAD_INIT(NULL) + 0, /* ob_size */ + "cairo.SurfacePattern", /* tp_name */ + sizeof(PycairoSurfacePattern), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ + 0, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + surface_pattern_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* &PycairoPattern_Type, */ /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + (newfunc)surface_pattern_new, /* tp_new */ + 0, /* tp_free */ + 0, /* tp_is_gc */ + 0, /* tp_bases */ +}; + +/* Class Gradient --------------------------------------------------------- */ + +static PyObject * +gradient_new (PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + PyErr_SetString(PyExc_TypeError, + "The Gradient type cannot be instantiated"); + return NULL; +} + +static PyObject * +gradient_add_color_stop_rgb (PycairoGradient *o, PyObject *args) +{ + double offset, red, green, blue; + if (!PyArg_ParseTuple(args, "dddd:Gradient.add_color_stop_rgb", + &offset, &red, &green, &blue)) + return NULL; + cairo_pattern_add_color_stop_rgb (o->pattern, offset, red, green, blue); + RETURN_NULL_IF_CAIRO_PATTERN_ERROR(o->pattern); + Py_RETURN_NONE; +} + +static PyObject * +gradient_add_color_stop_rgba (PycairoGradient *o, PyObject *args) +{ + double offset, red, green, blue, alpha; + if (!PyArg_ParseTuple(args, "ddddd:Gradient.add_color_stop_rgba", + &offset, &red, &green, &blue, &alpha)) + return NULL; + cairo_pattern_add_color_stop_rgba (o->pattern, offset, red, + green, blue, alpha); + RETURN_NULL_IF_CAIRO_PATTERN_ERROR(o->pattern); + Py_RETURN_NONE; +} + +static PyMethodDef gradient_methods[] = { + {"add_color_stop_rgb",(PyCFunction)gradient_add_color_stop_rgb, + METH_VARARGS }, + {"add_color_stop_rgba",(PyCFunction)gradient_add_color_stop_rgba, + METH_VARARGS }, + {NULL, NULL, 0, NULL}, +}; + +PyTypeObject PycairoGradient_Type = { + PyObject_HEAD_INIT(NULL) + 0, /* ob_size */ + "cairo.Gradient", /* tp_name */ + sizeof(PycairoGradient), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,/* tp_flags */ + 0, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + gradient_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* &PycairoPattern_Type, */ /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + (newfunc)gradient_new, /* tp_new */ + 0, /* tp_free */ + 0, /* tp_is_gc */ + 0, /* tp_bases */ +}; + +/* Class LinearGradient --------------------------------------------------- */ + +static PyObject * +linear_gradient_new (PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + double x0, y0, x1, y1; + if (!PyArg_ParseTuple(args, "dddd:LinearGradient.__new__", + &x0, &y0, &x1, &y1)) + return NULL; + return PycairoPattern_FromPattern ( + cairo_pattern_create_linear (x0, y0, x1, y1), NULL); +} + +static PyObject * +linear_gradient_get_linear_points (PycairoLinearGradient *o) +{ + double x0, y0, x1, y1; + cairo_pattern_get_linear_points (o->pattern, &x0, &y0, &x1, &y1); + return Py_BuildValue("(dddd)", x0, y0, x1, y1); +} + +static PyMethodDef linear_gradient_methods[] = { + {"get_linear_points", (PyCFunction)linear_gradient_get_linear_points, + METH_NOARGS }, + {NULL, NULL, 0, NULL}, +}; + +PyTypeObject PycairoLinearGradient_Type = { + PyObject_HEAD_INIT(NULL) + 0, /* ob_size */ + "cairo.LinearGradient", /* tp_name */ + sizeof(PycairoLinearGradient), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ + 0, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + linear_gradient_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* &PycairoGradient_Type, */ /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + (newfunc)linear_gradient_new, /* tp_new */ + 0, /* tp_free */ + 0, /* tp_is_gc */ + 0, /* tp_bases */ +}; + +/* Class RadialGradient --------------------------------------------------- */ + +static PyObject * +radial_gradient_new (PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + double cx0, cy0, radius0, cx1, cy1, radius1; + if (!PyArg_ParseTuple(args, "dddddd:RadialGradient.__new__", + &cx0, &cy0, &radius0, &cx1, &cy1, &radius1)) + return NULL; + return PycairoPattern_FromPattern ( + cairo_pattern_create_radial (cx0, cy0, radius0, cx1, cy1, radius1), + NULL); +} + +static PyObject * +radial_gradient_get_radial_circles (PycairoRadialGradient *o) +{ + double x0, y0, r0, x1, y1, r1; + cairo_pattern_get_radial_circles (o->pattern, &x0, &y0, &r0, + &x1, &y1, &r1); + return Py_BuildValue("(dddddd)", x0, y0, r0, x1, y1, r1); +} + +static PyMethodDef radial_gradient_methods[] = { + {"get_radial_circles", (PyCFunction)radial_gradient_get_radial_circles, + METH_NOARGS }, + {NULL, NULL, 0, NULL}, +}; + +PyTypeObject PycairoRadialGradient_Type = { + PyObject_HEAD_INIT(NULL) + 0, /* ob_size */ + "cairo.RadialGradient", /* tp_name */ + sizeof(PycairoRadialGradient), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ + 0, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + radial_gradient_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* &PycairoGradient_Type, */ /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + (newfunc)radial_gradient_new, /* tp_new */ + 0, /* tp_free */ + 0, /* tp_is_gc */ + 0, /* tp_bases */ +}; diff --git a/src/pycairo-private.h b/src/pycairo-private.h new file mode 100644 index 0000000..d04e66e --- /dev/null +++ b/src/pycairo-private.h @@ -0,0 +1,161 @@ +/* -*- mode: C; c-basic-offset: 4 -*- + * + * Pycairo - Python bindings for cairo + * + * Copyright © 2003 James Henstridge, Steven Chaplin + * + * This library is free software; you can redistribute it and/or + * modify it either under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation + * (the "LGPL") or, at your option, under the terms of the Mozilla + * Public License Version 1.1 (the "MPL"). If you do not alter this + * notice, a recipient may use your version of this file under either + * the MPL or the LGPL. + * + * You should have received a copy of the LGPL along with this library + * in the file COPYING-LGPL-2.1; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * You should have received a copy of the MPL along with this library + * in the file COPYING-MPL-1.1 + * + * The contents of this file are subject to the Mozilla Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY + * OF ANY KIND, either express or implied. See the LGPL or the MPL for + * the specific language governing rights and limitations. + */ + +#ifndef _PYCAIRO_PRIVATE_H_ +#define _PYCAIRO_PRIVATE_H_ + +#ifdef _PYCAIRO_H_ +# error "don't include pycairo.h and pycairo-private.h together" +#endif + +#define _INSIDE_PYCAIRO_ +#include <Python.h> + +#include "pycairo.h" + + +extern PyObject *CairoError; + +extern PyTypeObject PycairoContext_Type; +PyObject *PycairoContext_FromContext (cairo_t *ctx, PyTypeObject *type, + PyObject *base); + +extern PyTypeObject PycairoFontFace_Type; +extern PyTypeObject PycairoToyFontFace_Type; +PyObject *PycairoFontFace_FromFontFace (cairo_font_face_t *font_face); + +extern PyTypeObject PycairoFontOptions_Type; +PyObject *PycairoFontOptions_FromFontOptions ( + cairo_font_options_t *font_options); + +extern PyTypeObject PycairoMatrix_Type; +PyObject *PycairoMatrix_FromMatrix (const cairo_matrix_t *matrix); + +extern PyTypeObject PycairoPath_Type; +PyObject *PycairoPath_FromPath (cairo_path_t *path); + +extern PyTypeObject PycairoPathiter_Type; + +extern PyTypeObject PycairoPattern_Type; +extern PyTypeObject PycairoSolidPattern_Type; +extern PyTypeObject PycairoSurfacePattern_Type; +extern PyTypeObject PycairoGradient_Type; +extern PyTypeObject PycairoLinearGradient_Type; +extern PyTypeObject PycairoRadialGradient_Type; +PyObject *PycairoPattern_FromPattern (cairo_pattern_t *pattern, + PyObject *base); + +extern PyTypeObject PycairoScaledFont_Type; +PyObject *PycairoScaledFont_FromScaledFont (cairo_scaled_font_t *scaled_font); + +extern PyTypeObject PycairoSurface_Type; +extern PyTypeObject PycairoImageSurface_Type; + +#if CAIRO_HAS_PDF_SURFACE +extern PyTypeObject PycairoPDFSurface_Type; +#endif + +#if CAIRO_HAS_PS_SURFACE +extern PyTypeObject PycairoPSSurface_Type; +#endif + +#if CAIRO_HAS_SVG_SURFACE +extern PyTypeObject PycairoSVGSurface_Type; +#endif + +#if CAIRO_HAS_WIN32_SURFACE +extern PyTypeObject PycairoWin32Surface_Type; +#endif + +#if CAIRO_HAS_XLIB_SURFACE +extern PyTypeObject PycairoXlibSurface_Type; +#endif + +PyObject *PycairoSurface_FromSurface (cairo_surface_t *surface, + PyObject *base); + +int Pycairo_Check_Status (cairo_status_t status); + +/* error checking macros */ +#define RETURN_NULL_IF_CAIRO_ERROR(status) \ + do { \ + if (status != CAIRO_STATUS_SUCCESS) { \ + Pycairo_Check_Status (status); \ + return NULL; \ + } \ + } while (0) + +#define RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(ctx) \ + do { \ + cairo_status_t status = cairo_status (ctx); \ + if (status != CAIRO_STATUS_SUCCESS) { \ + Pycairo_Check_Status (status); \ + return NULL; \ + } \ + } while (0) + +#define RETURN_NULL_IF_CAIRO_PATTERN_ERROR(pattern) \ + do { \ + cairo_status_t status = cairo_pattern_status (pattern); \ + if (status != CAIRO_STATUS_SUCCESS) { \ + Pycairo_Check_Status (status); \ + return NULL; \ + } \ + } while (0) + +#define RETURN_NULL_IF_CAIRO_SURFACE_ERROR(surface) \ + do { \ + cairo_status_t status = cairo_surface_status (surface); \ + if (status != CAIRO_STATUS_SUCCESS) { \ + Pycairo_Check_Status (status); \ + return NULL; \ + } \ + } while (0) + +#define RETURN_NULL_IF_CAIRO_SCALED_FONT_ERROR(sc_font) \ + do { \ + cairo_status_t status = cairo_scaled_font_status (sc_font); \ + if (status != CAIRO_STATUS_SUCCESS) { \ + Pycairo_Check_Status (status); \ + return NULL; \ + } \ + } while (0) + +#define RETURN_NULL_IF_CAIRO_FONT_OPTIONS_ERROR(fo) \ + do { \ + cairo_status_t status = cairo_font_options_status (fo); \ + if (status != CAIRO_STATUS_SUCCESS) { \ + Pycairo_Check_Status (status); \ + return NULL; \ + } \ + } while (0) + + +#endif /* _PYCAIRO_PRIVATE_H_ */ diff --git a/src/pycairo-surface.c b/src/pycairo-surface.c new file mode 100644 index 0000000..65af7f5 --- /dev/null +++ b/src/pycairo-surface.c @@ -0,0 +1,1236 @@ +/* -*- mode: C; c-basic-offset: 4 -*- + * + * Pycairo - Python bindings for cairo + * + * Copyright © 2003 James Henstridge, Steven Chaplin + * + * This library is free software; you can redistribute it and/or + * modify it either under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation + * (the "LGPL") or, at your option, under the terms of the Mozilla + * Public License Version 1.1 (the "MPL"). If you do not alter this + * notice, a recipient may use your version of this file under either + * the MPL or the LGPL. + * + * You should have received a copy of the LGPL along with this library + * in the file COPYING-LGPL-2.1; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * You should have received a copy of the MPL along with this library + * in the file COPYING-MPL-1.1 + * + * The contents of this file are subject to the Mozilla Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY + * OF ANY KIND, either express or implied. See the LGPL or the MPL for + * the specific language governing rights and limitations. + */ + +#define PY_SSIZE_T_CLEAN +#include <Python.h> + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "pycairo-private.h" + + +/* Class Surface ---------------------------------------------------------- */ + +/* PycairoSurface_FromSurface + * Create a new + * PycairoImageSurface, + * PycairoPDFSurface, + * PycairoPSSurface, + * PycairoSVGSurface, + * PycairoWin32Surface, or + * PycairoXlibSurface from a cairo_surface_t. + * surface - a cairo_surface_t to 'wrap' into a Python object. + * It is unreferenced if the PycairoSurface creation fails, or if the + * cairo_surface_t has an error status. + * base - the base object used to create the surface, or NULL. + * It is referenced to keep it alive while the cairo_surface_t is being used. + * Return value: New reference or NULL on failure + */ +PyObject * +PycairoSurface_FromSurface (cairo_surface_t *surface, PyObject *base) +{ + PyTypeObject *type = NULL; + PyObject *o; + + assert (surface != NULL); + + if (Pycairo_Check_Status (cairo_surface_status (surface))) { + cairo_surface_destroy (surface); + return NULL; + } + + switch (cairo_surface_get_type (surface)) { +#if CAIRO_HAS_IMAGE_SURFACE + case CAIRO_SURFACE_TYPE_IMAGE: + type = &PycairoImageSurface_Type; + break; +#endif +#if CAIRO_HAS_PDF_SURFACE + case CAIRO_SURFACE_TYPE_PDF: + type = &PycairoPDFSurface_Type; + break; +#endif +#if CAIRO_HAS_PS_SURFACE + case CAIRO_SURFACE_TYPE_PS: + type = &PycairoPSSurface_Type; + break; +#endif +#if CAIRO_HAS_SVG_SURFACE + case CAIRO_SURFACE_TYPE_SVG: + type = &PycairoSVGSurface_Type; + break; +#endif +#if CAIRO_HAS_WIN32_SURFACE + case CAIRO_SURFACE_TYPE_WIN32: + type = &PycairoWin32Surface_Type; + break; +#endif +#if CAIRO_HAS_XLIB_SURFACE + case CAIRO_SURFACE_TYPE_XLIB: + type = &PycairoXlibSurface_Type; + break; +#endif + default: + type = &PycairoSurface_Type; + break; + } + o = type->tp_alloc (type, 0); + if (o == NULL) { + cairo_surface_destroy (surface); + } else { + ((PycairoSurface *)o)->surface = surface; + Py_XINCREF(base); + ((PycairoSurface *)o)->base = base; + } + return o; +} + +/* for use with + * cairo_surface_write_to_png_stream() + * cairo_pdf/ps/svg_surface_create_for_stream() + */ +static cairo_status_t +_write_func (void *closure, const unsigned char *data, unsigned int length) +{ + PyGILState_STATE gstate = PyGILState_Ensure(); + PyObject *res = PyObject_CallMethod ((PyObject *)closure, "write", "(s#)", + data, (Py_ssize_t)length); + if (res == NULL) { + /* an exception has occurred, it will be picked up later by + * Pycairo_Check_Status() + */ + PyGILState_Release(gstate); + return CAIRO_STATUS_WRITE_ERROR; + } + Py_DECREF(res); + PyGILState_Release(gstate); + return CAIRO_STATUS_SUCCESS; +} + +static void +surface_dealloc (PycairoSurface *o) +{ + if (o->surface) { + cairo_surface_destroy(o->surface); + o->surface = NULL; + } + Py_CLEAR(o->base); + + o->ob_type->tp_free((PyObject *)o); +} + +static PyObject * +surface_new (PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + PyErr_SetString(PyExc_TypeError, + "The Surface type cannot be instantiated"); + return NULL; +} + +static PyObject * +surface_copy_page (PycairoSurface *o) +{ + Py_BEGIN_ALLOW_THREADS + cairo_surface_copy_page (o->surface); + Py_END_ALLOW_THREADS + RETURN_NULL_IF_CAIRO_SURFACE_ERROR(o->surface); + Py_RETURN_NONE; +} + +static PyObject * +surface_create_similar (PycairoSurface *o, PyObject *args) +{ + cairo_content_t content; + int width, height; + + if (!PyArg_ParseTuple (args, "iii:Surface.create_similar", + &content, &width, &height)) + return NULL; + return PycairoSurface_FromSurface ( + cairo_surface_create_similar (o->surface, content, width, height), + NULL); +} + +static PyObject * +surface_finish (PycairoSurface *o) +{ + cairo_surface_finish (o->surface); + Py_CLEAR(o->base); + RETURN_NULL_IF_CAIRO_SURFACE_ERROR(o->surface); + Py_RETURN_NONE; +} + +static PyObject * +surface_flush (PycairoSurface *o) +{ + Py_BEGIN_ALLOW_THREADS + cairo_surface_flush (o->surface); + Py_END_ALLOW_THREADS + RETURN_NULL_IF_CAIRO_SURFACE_ERROR(o->surface); + Py_RETURN_NONE; +} + +static PyObject * +surface_get_content (PycairoSurface *o) +{ + return PyInt_FromLong (cairo_surface_get_content (o->surface)); +} + +static PyObject * +surface_get_device_offset (PycairoSurface *o) +{ + double x_offset, y_offset; + cairo_surface_get_device_offset (o->surface, &x_offset, &y_offset); + return Py_BuildValue("(dd)", x_offset, y_offset); +} + +static PyObject * +surface_get_fallback_resolution (PycairoSurface *o) +{ + double x_ppi, y_ppi; + cairo_surface_get_fallback_resolution (o->surface, &x_ppi, &y_ppi); + return Py_BuildValue("(dd)", x_ppi, y_ppi); +} + +static PyObject * +surface_get_font_options (PycairoSurface *o) +{ + cairo_font_options_t *options = cairo_font_options_create(); + + cairo_surface_get_font_options (o->surface, options); + /* there is no reference fn */ + return PycairoFontOptions_FromFontOptions (options); +} + +static PyObject * +surface_mark_dirty (PycairoSurface *o) +{ + cairo_surface_mark_dirty (o->surface); + RETURN_NULL_IF_CAIRO_SURFACE_ERROR(o->surface); + Py_RETURN_NONE; +} + +static PyObject * +surface_mark_dirty_rectangle (PycairoSurface *o, PyObject *args) +{ + int x, y, width, height; + + if (!PyArg_ParseTuple(args, "iiii:Surface.mark_dirty_rectangle", + &x, &y, &width, &height)) + return NULL; + + cairo_surface_mark_dirty_rectangle (o->surface, x, y, width, height); + RETURN_NULL_IF_CAIRO_SURFACE_ERROR(o->surface); + Py_RETURN_NONE; +} + +static PyObject * +surface_set_device_offset (PycairoSurface *o, PyObject *args) +{ + double x_offset, y_offset; + + if (!PyArg_ParseTuple (args, "dd:Surface.set_device_offset", + &x_offset, &y_offset)) + return NULL; + + cairo_surface_set_device_offset (o->surface, x_offset, y_offset); + Py_RETURN_NONE; +} + +static PyObject * +surface_set_fallback_resolution (PycairoSurface *o, PyObject *args) +{ + double x_ppi, y_ppi; + + if (!PyArg_ParseTuple(args, "dd:Surface.set_fallback_resolution", + &x_ppi, &y_ppi)) + return NULL; + cairo_surface_set_fallback_resolution (o->surface, x_ppi, y_ppi); + Py_RETURN_NONE; +} + +static PyObject * +surface_show_page (PycairoSurface *o) +{ + Py_BEGIN_ALLOW_THREADS + cairo_surface_show_page (o->surface); + Py_END_ALLOW_THREADS + RETURN_NULL_IF_CAIRO_SURFACE_ERROR(o->surface); + Py_RETURN_NONE; +} + +#ifdef CAIRO_HAS_PNG_FUNCTIONS +/* METH_O */ +static PyObject * +surface_write_to_png (PycairoSurface *o, PyObject *file) +{ + cairo_status_t status; + + if (PyObject_TypeCheck (file, &PyBaseString_Type)) { + /* string (filename) argument */ + Py_BEGIN_ALLOW_THREADS + status = cairo_surface_write_to_png (o->surface, + PyString_AsString(file)); + Py_END_ALLOW_THREADS + + } else { /* file or file-like object argument */ + PyObject* writer = PyObject_GetAttrString (file, "write"); + if (writer == NULL || !PyCallable_Check (writer)) { + Py_XDECREF(writer); + PyErr_SetString(PyExc_TypeError, +"Surface.write_to_png takes one argument which must be a filename (str), file " +"object, or a file-like object which has a \"write\" method (like StringIO)"); + return NULL; + } + Py_DECREF(writer); + Py_BEGIN_ALLOW_THREADS + status = cairo_surface_write_to_png_stream (o->surface, _write_func, + file); + Py_END_ALLOW_THREADS + } + RETURN_NULL_IF_CAIRO_ERROR(status); + Py_RETURN_NONE; +} +#endif /* CAIRO_HAS_PNG_FUNCTIONS */ + + +static PyMethodDef surface_methods[] = { + /* methods never exposed in a language binding: + * cairo_surface_destroy() + * cairo_surface_get_type() + * cairo_surface_get_user_data() + * cairo_surface_reference() + * cairo_surface_set_user_data() + */ + {"copy_page", (PyCFunction)surface_copy_page, METH_NOARGS}, + {"create_similar", (PyCFunction)surface_create_similar, METH_VARARGS}, + {"finish", (PyCFunction)surface_finish, METH_NOARGS}, + {"flush", (PyCFunction)surface_flush, METH_NOARGS}, + {"get_content", (PyCFunction)surface_get_content, METH_NOARGS}, + {"get_device_offset",(PyCFunction)surface_get_device_offset,METH_NOARGS}, + {"get_fallback_resolution",(PyCFunction)surface_get_fallback_resolution, + METH_NOARGS}, + {"get_font_options",(PyCFunction)surface_get_font_options, METH_NOARGS}, + {"mark_dirty", (PyCFunction)surface_mark_dirty, METH_NOARGS}, + {"mark_dirty_rectangle", (PyCFunction)surface_mark_dirty_rectangle, + METH_VARARGS}, + {"set_device_offset",(PyCFunction)surface_set_device_offset,METH_VARARGS}, + {"set_fallback_resolution",(PyCFunction)surface_set_fallback_resolution, + METH_VARARGS}, + {"show_page", (PyCFunction)surface_show_page, METH_NOARGS}, +#ifdef CAIRO_HAS_PNG_FUNCTIONS + {"write_to_png", (PyCFunction)surface_write_to_png, METH_O }, +#endif + {NULL, NULL, 0, NULL}, +}; + + +PyTypeObject PycairoSurface_Type = { + PyObject_HEAD_INIT(NULL) + 0, /* ob_size */ + "cairo.Surface", /* tp_name */ + sizeof(PycairoSurface), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)surface_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,/* tp_flags */ + 0, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + surface_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* &PyBaseObject_Type, */ /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + (newfunc)surface_new, /* tp_new */ + 0, /* tp_free */ + 0, /* tp_is_gc */ + 0, /* tp_bases */ +}; + + +/* Class ImageSurface(Surface) -------------------------------------------- */ +#ifdef CAIRO_HAS_IMAGE_SURFACE + +static PyObject * +image_surface_new (PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + cairo_format_t format; + int width, height; + + if (!PyArg_ParseTuple (args, "iii:ImageSurface.__new__", + &format, &width, &height)) + return NULL; + return PycairoSurface_FromSurface ( + cairo_image_surface_create (format, width, height), + NULL); +} + +static PyObject * +image_surface_create_for_data (PyTypeObject *type, PyObject *args) +{ + cairo_surface_t *surface; + cairo_format_t format; + unsigned char *buffer; + int width, height, stride = -1, res; + Py_ssize_t buffer_len; + PyObject *obj; + + if (!PyArg_ParseTuple(args, "Oiii|i:Surface.create_for_data", + &obj, &format, &width, &height, &stride)) + return NULL; + + res = PyObject_AsWriteBuffer (obj, (void **)&buffer, &buffer_len); + if (res == -1) + return NULL; + + if (width <= 0) { + PyErr_SetString(PyExc_ValueError, "width must be positive"); + return NULL; + } + if (height <= 0) { + PyErr_SetString(PyExc_ValueError, "height must be positive"); + return NULL; + } + /* if stride is missing, calculate it from width */ + if (stride < 0) { + stride = cairo_format_stride_for_width (format, width); + if (stride == -1){ + PyErr_SetString(CairoError, + "format is invalid or the width too large"); + return NULL; + } + } + if (height * stride > buffer_len) { + PyErr_SetString(PyExc_TypeError, "buffer is not long enough"); + return NULL; + } + Py_BEGIN_ALLOW_THREADS + surface = cairo_image_surface_create_for_data (buffer, format, width, + height, stride); + Py_END_ALLOW_THREADS + return PycairoSurface_FromSurface(surface, obj); +} + + +#ifdef CAIRO_HAS_PNG_FUNCTIONS +static cairo_status_t +_read_func (void *closure, unsigned char *data, unsigned int length) +{ + char *buffer; + Py_ssize_t str_length; + cairo_status_t status = CAIRO_STATUS_READ_ERROR; + PyGILState_STATE gstate = PyGILState_Ensure(); + PyObject *pystr = PyObject_CallMethod ((PyObject *)closure, "read", "(i)", + length); + if (pystr == NULL) { + /* an exception has occurred, it will be picked up later by + * Pycairo_Check_Status() + */ + goto end; + } + int ret = PyString_AsStringAndSize(pystr, &buffer, &str_length); + if (ret == -1 || str_length < length) { + goto end; + } + /* don't use strncpy() since png data may contain NUL bytes */ + memcpy (data, buffer, str_length); + status = CAIRO_STATUS_SUCCESS; + end: + Py_XDECREF(pystr); + PyGILState_Release(gstate); + return status; +} + +/* METH_O | METH_CLASS */ +static PyObject * +image_surface_create_from_png (PyTypeObject *type, PyObject *file) +{ + PyObject* reader; + cairo_surface_t *is; + + if (PyObject_TypeCheck (file, &PyBaseString_Type)) { + Py_BEGIN_ALLOW_THREADS + is = cairo_image_surface_create_from_png (PyString_AsString(file)); + Py_END_ALLOW_THREADS + return PycairoSurface_FromSurface (is, NULL); + } + + /* file or file-like object argument */ + reader = PyObject_GetAttrString (file, "read"); + if (reader == NULL || !PyCallable_Check (reader)) { + Py_XDECREF(reader); + PyErr_SetString(PyExc_TypeError, +"ImageSurface.create_from_png argument must be a filename (str), file object, " +"or an object that has a \"read\" method (like StringIO)"); + return NULL; + } + Py_DECREF(reader); + + Py_BEGIN_ALLOW_THREADS + is = cairo_image_surface_create_from_png_stream (_read_func, file); + Py_END_ALLOW_THREADS + return PycairoSurface_FromSurface (is, NULL); +} +#endif /* CAIRO_HAS_PNG_FUNCTIONS */ + +/* METH_STATIC */ +static PyObject * +image_surface_format_stride_for_width (PyObject *self, PyObject *args) +{ + cairo_format_t format; + int width; + if (!PyArg_ParseTuple(args, "ii:format_stride_for_width", &format, &width)) + return NULL; + return PyInt_FromLong (cairo_format_stride_for_width (format, width)); +} + +static PyObject * +image_surface_get_data (PycairoImageSurface *o) +{ + return PyBuffer_FromReadWriteObject((PyObject *)o, 0, Py_END_OF_BUFFER); +} + +static PyObject * +image_surface_get_format (PycairoImageSurface *o) +{ + return PyInt_FromLong (cairo_image_surface_get_format (o->surface)); +} + +static PyObject * +image_surface_get_height (PycairoImageSurface *o) +{ + return PyInt_FromLong (cairo_image_surface_get_height (o->surface)); +} + +static PyObject * +image_surface_get_stride (PycairoImageSurface *o) +{ + return PyInt_FromLong (cairo_image_surface_get_stride (o->surface)); +} + +static PyObject * +image_surface_get_width (PycairoImageSurface *o) +{ + return PyInt_FromLong (cairo_image_surface_get_width (o->surface)); +} + + +/* Buffer interface functions, used by ImageSurface.get_data() */ +static int +image_surface_buffer_getreadbuf (PycairoImageSurface *o, int segment, + const void **ptr) +{ + cairo_surface_t *surface = o->surface; + int height, stride; + + if (segment != 0) { + PyErr_SetString(PyExc_SystemError, + "accessing non-existent ImageSurface segment"); + return -1; + } + height = cairo_image_surface_get_height (surface); + stride = cairo_image_surface_get_stride (surface); + *ptr = (void *) cairo_image_surface_get_data (surface); + return height * stride; +} + +static int +image_surface_buffer_getwritebuf (PycairoImageSurface *o, int segment, + const void **ptr) +{ + cairo_surface_t *surface = o->surface; + int height, stride; + + if (segment != 0) { + PyErr_SetString(PyExc_SystemError, + "accessing non-existent ImageSurface segment"); + return -1; + } + height = cairo_image_surface_get_height (surface); + stride = cairo_image_surface_get_stride (surface); + *ptr = (void *) cairo_image_surface_get_data (surface); + return height * stride; +} + +static int +image_surface_buffer_getsegcount (PycairoImageSurface *o, int *lenp) +{ + if (lenp) { + /* report the sum of the sizes (in bytes) of all segments */ + cairo_surface_t *surface = o->surface; + int height = cairo_image_surface_get_height (surface); + int stride = cairo_image_surface_get_stride (surface); + *lenp = height * stride; + } + return 1; /* surface data is all in one segment */ +} + +/* See Python C API Manual 10.7 */ +static PyBufferProcs image_surface_as_buffer = { + (readbufferproc) image_surface_buffer_getreadbuf, + (writebufferproc)image_surface_buffer_getwritebuf, + (segcountproc) image_surface_buffer_getsegcount, + (charbufferproc) NULL, +}; + +static PyMethodDef image_surface_methods[] = { + {"create_for_data",(PyCFunction)image_surface_create_for_data, + METH_VARARGS | METH_CLASS}, +#ifdef CAIRO_HAS_PNG_FUNCTIONS + {"create_from_png", (PyCFunction)image_surface_create_from_png, + METH_O | METH_CLASS}, +#endif + {"format_stride_for_width", + (PyCFunction)image_surface_format_stride_for_width, + METH_VARARGS | METH_STATIC}, + {"get_data", (PyCFunction)image_surface_get_data, METH_NOARGS}, + {"get_format", (PyCFunction)image_surface_get_format, METH_NOARGS}, + {"get_height", (PyCFunction)image_surface_get_height, METH_NOARGS}, + {"get_stride", (PyCFunction)image_surface_get_stride, METH_NOARGS}, + {"get_width", (PyCFunction)image_surface_get_width, METH_NOARGS}, + {NULL, NULL, 0, NULL}, +}; + + +PyTypeObject PycairoImageSurface_Type = { + PyObject_HEAD_INIT(NULL) + 0, /* ob_size */ + "cairo.ImageSurface", /* tp_name */ + sizeof(PycairoImageSurface), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + &image_surface_as_buffer, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ + 0, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + image_surface_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* &PycairoSurface_Type, */ /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + (newfunc)image_surface_new, /* tp_new */ + 0, /* tp_free */ + 0, /* tp_is_gc */ + 0, /* tp_bases */ +}; +#endif /* CAIRO_HAS_IMAGE_SURFACE */ + + +/* Class PDFSurface(Surface) ---------------------------------------------- */ +#ifdef CAIRO_HAS_PDF_SURFACE +#include <cairo-pdf.h> + +static PyObject * +pdf_surface_new (PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + double width_in_points, height_in_points; + PyObject *file, *writer; + cairo_surface_t *sfc; + + if (!PyArg_ParseTuple(args, "Odd:PDFSurface.__new__", + &file, &width_in_points, &height_in_points)) + return NULL; + + if (PyObject_TypeCheck (file, &PyBaseString_Type)) { + /* string (filename) argument */ + Py_BEGIN_ALLOW_THREADS + sfc = cairo_pdf_surface_create (PyString_AsString(file), + width_in_points, height_in_points); + Py_END_ALLOW_THREADS + return PycairoSurface_FromSurface (sfc, NULL); + } + /* file or file-like object argument */ + writer = PyObject_GetAttrString (file, "write"); + if (writer == NULL || !PyCallable_Check (writer)) { + Py_XDECREF(writer); + PyErr_SetString(PyExc_TypeError, +"PDFSurface argument 1 must be a filename (str), file object, or an object " +"that has a \"write\" method (like StringIO)"); + return NULL; + } + Py_DECREF(writer); + + Py_BEGIN_ALLOW_THREADS + sfc = cairo_pdf_surface_create_for_stream (_write_func, file, + width_in_points, height_in_points); + Py_END_ALLOW_THREADS + return PycairoSurface_FromSurface (sfc, file); +} + +static PyObject * +pdf_surface_set_size (PycairoPDFSurface *o, PyObject *args) +{ + double width_in_points, height_in_points; + + if (!PyArg_ParseTuple(args, "dd:PDFSurface.set_size", &width_in_points, + &height_in_points)) + return NULL; + cairo_pdf_surface_set_size (o->surface, width_in_points, + height_in_points); + Py_RETURN_NONE; +} + +static PyMethodDef pdf_surface_methods[] = { + {"set_size", (PyCFunction)pdf_surface_set_size, METH_VARARGS }, + {NULL, NULL, 0, NULL}, +}; + +PyTypeObject PycairoPDFSurface_Type = { + PyObject_HEAD_INIT(NULL) + 0, /* ob_size */ + "cairo.PDFSurface", /* tp_name */ + sizeof(PycairoPDFSurface), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ + 0, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + pdf_surface_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* &PycairoSurface_Type, */ /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + (newfunc)pdf_surface_new, /* tp_new */ + 0, /* tp_free */ + 0, /* tp_is_gc */ + 0, /* tp_bases */ +}; +#endif /* CAIRO_HAS_PDF_SURFACE */ + + +/* Class PSSurface(Surface) ----------------------------------------------- */ +#ifdef CAIRO_HAS_PS_SURFACE +#include <cairo-ps.h> + +static PyObject * +ps_surface_new (PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + double width_in_points, height_in_points; + PyObject *file, *writer; + cairo_surface_t *sfc; + + if (!PyArg_ParseTuple(args, "Odd:PSSurface.__new__", + &file, &width_in_points, &height_in_points)) + return NULL; + + if (PyObject_TypeCheck (file, &PyBaseString_Type)) { + /* string (filename) argument */ + Py_BEGIN_ALLOW_THREADS + sfc = cairo_ps_surface_create (PyString_AsString(file), + width_in_points, height_in_points); + Py_END_ALLOW_THREADS + return PycairoSurface_FromSurface (sfc, NULL); + } + /* else: file or file-like object argument */ + writer = PyObject_GetAttrString (file, "write"); + if (writer == NULL || !PyCallable_Check (writer)) { + Py_XDECREF(writer); + PyErr_SetString(PyExc_TypeError, +"PSSurface argument 1 must be a filename (str), file object, or an object " +"that has a \"write\" method (like StringIO)"); + return NULL; + } + Py_DECREF(writer); + + Py_BEGIN_ALLOW_THREADS + sfc = cairo_ps_surface_create_for_stream (_write_func, file, + width_in_points, height_in_points); + Py_END_ALLOW_THREADS + return PycairoSurface_FromSurface (sfc, file); +} + +static PyObject * +ps_surface_dsc_begin_page_setup (PycairoPSSurface *o) +{ + cairo_ps_surface_dsc_begin_page_setup (o->surface); + RETURN_NULL_IF_CAIRO_SURFACE_ERROR(o->surface); + Py_RETURN_NONE; +} + +static PyObject * +ps_surface_dsc_begin_setup (PycairoPSSurface *o) +{ + cairo_ps_surface_dsc_begin_setup (o->surface); + RETURN_NULL_IF_CAIRO_SURFACE_ERROR(o->surface); + Py_RETURN_NONE; +} + +static PyObject * +ps_surface_dsc_comment (PycairoPSSurface *o, PyObject *args) +{ + const char *comment; + if (!PyArg_ParseTuple(args, "s:PSSurface.dsc_comment", &comment)) + return NULL; + cairo_ps_surface_dsc_comment (o->surface, comment); + RETURN_NULL_IF_CAIRO_SURFACE_ERROR(o->surface); + Py_RETURN_NONE; +} + +static PyObject * +ps_surface_get_eps (PycairoPSSurface *o) +{ + PyObject *eps = cairo_ps_surface_get_eps (o->surface) ? Py_True : Py_False; + RETURN_NULL_IF_CAIRO_SURFACE_ERROR(o->surface); + Py_INCREF(eps); + return eps; +} + +/* METH_STATIC */ +static PyObject * +ps_surface_ps_level_to_string (PyObject *self, PyObject *args) +{ + int level; + if (!PyArg_ParseTuple(args, "i:ps_level_to_string", &level)) + return NULL; + const char *s = cairo_ps_level_to_string (level); + if (s == NULL){ + PyErr_SetString(CairoError, "ps_level_to_string: " + "invalid level argument"); + return NULL; + } + return PyString_FromString(s); +} + +static PyObject * +ps_surface_restrict_to_level (PycairoPSSurface *o, PyObject *args) +{ + int level; + + if (!PyArg_ParseTuple(args, "i:PSSurface.restrict_to_level", &level)) + return NULL; + cairo_ps_surface_restrict_to_level (o->surface, level); + RETURN_NULL_IF_CAIRO_SURFACE_ERROR(o->surface); + Py_RETURN_NONE; +} + +static PyObject * +ps_surface_set_eps (PycairoPSSurface *o, PyObject *args) +{ + PyObject *py_eps; + if (!PyArg_ParseTuple(args, "O!:PSSurface.set_eps", + &PyBool_Type, &py_eps)) + return NULL; + cairo_ps_surface_set_eps (o->surface, (py_eps == Py_True)); + RETURN_NULL_IF_CAIRO_SURFACE_ERROR(o->surface); + Py_RETURN_NONE; +} + +static PyObject * +ps_surface_set_size (PycairoPSSurface *o, PyObject *args) +{ + double width_in_points, height_in_points; + + if (!PyArg_ParseTuple(args, "dd:PSSurface.set_size", + &width_in_points, &height_in_points)) + return NULL; + cairo_ps_surface_set_size (o->surface, width_in_points, height_in_points); + Py_RETURN_NONE; +} + +static PyMethodDef ps_surface_methods[] = { + {"dsc_begin_page_setup", + (PyCFunction)ps_surface_dsc_begin_page_setup, METH_NOARGS }, + {"dsc_begin_setup", (PyCFunction)ps_surface_dsc_begin_setup, METH_NOARGS }, + {"dsc_comment", (PyCFunction)ps_surface_dsc_comment, METH_VARARGS }, + {"get_eps", (PyCFunction)ps_surface_get_eps, METH_NOARGS }, + /* ps_get_levels - not implemented yet*/ + {"ps_level_to_string", (PyCFunction)ps_surface_ps_level_to_string, + METH_VARARGS | METH_STATIC}, + {"restrict_to_level", (PyCFunction)ps_surface_restrict_to_level, + METH_VARARGS }, + {"set_eps", (PyCFunction)ps_surface_set_eps, METH_VARARGS }, + {"set_size", (PyCFunction)ps_surface_set_size, METH_VARARGS }, + {NULL, NULL, 0, NULL}, +}; + +PyTypeObject PycairoPSSurface_Type = { + PyObject_HEAD_INIT(NULL) + 0, /* ob_size */ + "cairo.PSSurface", /* tp_name */ + sizeof(PycairoPSSurface), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ + 0, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + ps_surface_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* &PycairoSurface_Type, */ /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + (newfunc)ps_surface_new, /* tp_new */ + 0, /* tp_free */ + 0, /* tp_is_gc */ + 0, /* tp_bases */ +}; +#endif /* CAIRO_HAS_PS_SURFACE */ + + +/* Class SVGSurface(Surface) ----------------------------------------------- */ +#ifdef CAIRO_HAS_SVG_SURFACE +#include <cairo-svg.h> + +static PyObject * +svg_surface_new (PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + double width_in_points, height_in_points; + PyObject *file, *writer; + cairo_surface_t *sfc; + + if (!PyArg_ParseTuple(args, "Odd:SVGSurface.__new__", + &file, &width_in_points, &height_in_points)) + return NULL; + + if (PyObject_TypeCheck (file, &PyBaseString_Type)) { + /* string (filename) argument */ + Py_BEGIN_ALLOW_THREADS + sfc = cairo_svg_surface_create (PyString_AsString(file), + width_in_points, height_in_points); + Py_END_ALLOW_THREADS + return PycairoSurface_FromSurface (sfc, NULL); + } + /* else: file or file-like object argument */ + writer = PyObject_GetAttrString (file, "write"); + if (writer == NULL || !PyCallable_Check (writer)) { + Py_XDECREF(writer); + PyErr_SetString(PyExc_TypeError, +"SVGSurface argument 1 must be a filename (str), file object, or an object " +"that has a \"write\" method (like StringIO)"); + return NULL; + } + Py_DECREF(writer); + + Py_BEGIN_ALLOW_THREADS + sfc = cairo_svg_surface_create_for_stream (_write_func, file, + width_in_points, height_in_points); + Py_END_ALLOW_THREADS + return PycairoSurface_FromSurface (sfc, file); +} + +static PyMethodDef svg_surface_methods[] = { + /* TODO + * cairo_svg_surface_restrict_to_version + * cairo_svg_get_versions + * cairo_svg_version_to_string + */ + {NULL, NULL, 0, NULL}, +}; + +PyTypeObject PycairoSVGSurface_Type = { + PyObject_HEAD_INIT(NULL) + 0, /* ob_size */ + "cairo.SVGSurface", /* tp_name */ + sizeof(PycairoSVGSurface), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ + 0, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + svg_surface_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* &PycairoSurface_Type, */ /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + (newfunc)svg_surface_new, /* tp_new */ + 0, /* tp_free */ + 0, /* tp_is_gc */ + 0, /* tp_bases */ +}; +#endif /* CAIRO_HAS_SVG_SURFACE */ + + +/* Class Win32Surface(Surface) -------------------------------------------- */ +#if CAIRO_HAS_WIN32_SURFACE +#include <cairo-win32.h> + +static PyObject * +win32_surface_new (PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + int hdc; + + if (!PyArg_ParseTuple(args, "i:Win32Surface.__new__", &hdc)) + return NULL; + return PycairoSurface_FromSurface ( + cairo_win32_surface_create ((HDC)hdc), NULL); +} + +static PyMethodDef win32_surface_methods[] = { + {NULL, NULL, 0, NULL}, +}; + +PyTypeObject PycairoWin32Surface_Type = { + PyObject_HEAD_INIT(NULL) + 0, /* ob_size */ + "cairo.Win32Surface", /* tp_name */ + sizeof(PycairoWin32Surface), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ + 0, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + win32_surface_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* &PycairoSurface_Type, */ /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + (newfunc)win32_surface_new, /* tp_new */ + 0, /* tp_free */ + 0, /* tp_is_gc */ + 0, /* tp_bases */ +}; +#endif /* CAIRO_HAS_WIN32_SURFACE */ + + +/* Class XlibSurface(Surface) --------------------------------------------- */ +#ifdef CAIRO_HAS_XLIB_SURFACE +#include <cairo-xlib.h> + +static PyObject * +xlib_surface_new (PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + PyErr_SetString(PyExc_TypeError, + "The XlibSurface type cannot be directly instantiated"); + return NULL; +} + +static PyObject * +xlib_surface_get_depth (PycairoXlibSurface *o) +{ + return PyInt_FromLong (cairo_xlib_surface_get_depth (o->surface)); +} + +static PyObject * +xlib_surface_get_height (PycairoXlibSurface *o) +{ + return PyInt_FromLong (cairo_xlib_surface_get_height (o->surface)); +} + +static PyObject * +xlib_surface_get_width (PycairoXlibSurface *o) +{ + return PyInt_FromLong (cairo_xlib_surface_get_width (o->surface)); +} + +static PyMethodDef xlib_surface_methods[] = { + {"get_depth", (PyCFunction)xlib_surface_get_depth, METH_NOARGS }, + {"get_height",(PyCFunction)xlib_surface_get_height, METH_NOARGS }, + {"get_width", (PyCFunction)xlib_surface_get_width, METH_NOARGS }, + {NULL, NULL, 0, NULL}, +}; + +PyTypeObject PycairoXlibSurface_Type = { + PyObject_HEAD_INIT(NULL) + 0, /* ob_size */ + "cairo.XlibSurface", /* tp_name */ + sizeof(PycairoXlibSurface), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ + 0, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + xlib_surface_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* &PycairoSurface_Type, */ /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + (newfunc)xlib_surface_new, /* tp_new */ + 0, /* tp_free */ + 0, /* tp_is_gc */ + 0, /* tp_bases */ +}; +#endif /* CAIRO_HAS_XLIB_SURFACE */ diff --git a/src/pycairo.h b/src/pycairo.h new file mode 100644 index 0000000..ba56801 --- /dev/null +++ b/src/pycairo.h @@ -0,0 +1,208 @@ +/* -*- mode: C; c-basic-offset: 4 -*- + * + * Pycairo - Python bindings for cairo + * + * Copyright © 2003 James Henstridge, Steven Chaplin + * + * This library is free software; you can redistribute it and/or + * modify it either under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation + * (the "LGPL") or, at your option, under the terms of the Mozilla + * Public License Version 1.1 (the "MPL"). If you do not alter this + * notice, a recipient may use your version of this file under either + * the MPL or the LGPL. + * + * You should have received a copy of the LGPL along with this library + * in the file COPYING-LGPL-2.1; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * You should have received a copy of the MPL along with this library + * in the file COPYING-MPL-1.1 + * + * The contents of this file are subject to the Mozilla Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY + * OF ANY KIND, either express or implied. See the LGPL or the MPL for + * the specific language governing rights and limitations. + */ + +#ifndef _PYCAIRO_H_ +#define _PYCAIRO_H_ + +#include <Python.h> + +#include <cairo.h> + + +typedef struct { + PyObject_HEAD + cairo_t *ctx; + PyObject *base; /* base object used to create context, or NULL */ +} PycairoContext; + +typedef struct { + PyObject_HEAD + cairo_font_face_t *font_face; +} PycairoFontFace; + +#define PycairoToyFontFace PycairoFontFace + +typedef struct { + PyObject_HEAD + cairo_font_options_t *font_options; +} PycairoFontOptions; + +typedef struct { + PyObject_HEAD + cairo_matrix_t matrix; +} PycairoMatrix; + +typedef struct { + PyObject_HEAD + cairo_path_t *path; +} PycairoPath; + +typedef struct { + PyObject_HEAD + cairo_pattern_t *pattern; + PyObject *base; /* base object used to create pattern, or NULL */ +} PycairoPattern; + +#define PycairoSolidPattern PycairoPattern +#define PycairoSurfacePattern PycairoPattern +#define PycairoGradient PycairoPattern +#define PycairoLinearGradient PycairoPattern +#define PycairoRadialGradient PycairoPattern + +typedef struct { + PyObject_HEAD + cairo_scaled_font_t *scaled_font; +} PycairoScaledFont; + +typedef struct { + PyObject_HEAD + cairo_surface_t *surface; + PyObject *base; /* base object used to create surface, or NULL */ +} PycairoSurface; + +#define PycairoImageSurface PycairoSurface +#define PycairoPDFSurface PycairoSurface +#define PycairoPSSurface PycairoSurface +#define PycairoSVGSurface PycairoSurface +#define PycairoWin32Surface PycairoSurface +#define PycairoXlibSurface PycairoSurface + +/* get C object out of the Python wrapper */ +#define PycairoContext_GET(obj) (((PycairoContext *)(obj))->ctx) + +/* Define structure for C API. */ +typedef struct { + /* (type object, constructor) pairs */ + PyTypeObject *Context_Type; + PyObject *(*Context_FromContext)(cairo_t *ctx, PyTypeObject *type, + PyObject *base); + PyTypeObject *FontFace_Type; + PyTypeObject *ToyFontFace_Type; + PyObject *(*FontFace_FromFontFace)(cairo_font_face_t *font_face); + PyTypeObject *FontOptions_Type; + PyObject *(*FontOptions_FromFontOptions)( + cairo_font_options_t *font_options); + PyTypeObject *Matrix_Type; + PyObject *(*Matrix_FromMatrix)(const cairo_matrix_t *matrix); + PyTypeObject *Path_Type; + PyObject *(*Path_FromPath)(cairo_path_t *path); + + PyTypeObject *Pattern_Type; + PyTypeObject *SolidPattern_Type; + PyTypeObject *SurfacePattern_Type; + PyTypeObject *Gradient_Type; + PyTypeObject *LinearGradient_Type; + PyTypeObject *RadialGradient_Type; + PyObject *(*Pattern_FromPattern)(cairo_pattern_t *pattern, PyObject *base); + + PyTypeObject *ScaledFont_Type; + PyObject *(*ScaledFont_FromScaledFont)(cairo_scaled_font_t *scaled_font); + + PyTypeObject *Surface_Type; + PyTypeObject *ImageSurface_Type; + PyTypeObject *PDFSurface_Type; + PyTypeObject *PSSurface_Type; + PyTypeObject *SVGSurface_Type; + PyTypeObject *Win32Surface_Type; + PyTypeObject *XlibSurface_Type; + PyObject *(*Surface_FromSurface)(cairo_surface_t *surface, PyObject *base); + + /* misc functions */ + int (*Check_Status)(cairo_status_t status); +} Pycairo_CAPI_t; + + +#ifndef _INSIDE_PYCAIRO_ + +/* Macros for accessing the C API */ +#define PycairoContext_Type *(Pycairo_CAPI->Context_Type) +#define PycairoContext_FromContext (Pycairo_CAPI->Context_FromContext) +#define PycairoFontFace_Type *(Pycairo_CAPI->FontFace_Type) +#define PycairoToyFontFace_Type *(Pycairo_CAPI->ToyFontFace_Type) +#define PycairoFontFace_FromFontFace (Pycairo_CAPI->FontFace_FromFontFace) +#define PycairoFontOptions_Type *(Pycairo_CAPI->FontOptions_Type) +#define PycairoFontOptions_FromFontOptions \ + (Pycairo_CAPI->FontOptions_FromFontOptions) +#define PycairoMatrix_Type *(Pycairo_CAPI->Matrix_Type) +#define PycairoMatrix_FromMatrix (Pycairo_CAPI->Matrix_FromMatrix) +#define PycairoPath_Type *(Pycairo_CAPI->Path_Type) +#define PycairoPath_FromPath (Pycairo_CAPI->Path_FromPath) + +#define PycairoPattern_Type *(Pycairo_CAPI->Pattern_Type) +#define PycairoSolidPattern_Type *(Pycairo_CAPI->SolidPattern_Type) +#define PycairoSurfacePattern_Type *(Pycairo_CAPI->SurfacePattern_Type) +#define PycairoGradient_Type *(Pycairo_CAPI->Gradient_Type) +#define PycairoLinearGradient_Type *(Pycairo_CAPI->LinearGradient_Type) +#define PycairoRadialGradient_Type *(Pycairo_CAPI->RadialGradient_Type) +#define PycairoPattern_FromPattern (Pycairo_CAPI->Pattern_FromPattern) + +#define PycairoScaledFont_Type *(Pycairo_CAPI->ScaledFont_Type) +#define PycairoScaledFont_FromScaledFont \ + (Pycairo_CAPI->ScaledFont_FromScaledFont) + +#define PycairoSurface_Type *(Pycairo_CAPI->Surface_Type) +#define PycairoImageSurface_Type *(Pycairo_CAPI->ImageSurface_Type) + +#if CAIRO_HAS_PDF_SURFACE +#define PycairoPDFSurface_Type *(Pycairo_CAPI->PDFSurface_Type) +#endif + +#if CAIRO_HAS_PS_SURFACE +#define PycairoPSSurface_Type *(Pycairo_CAPI->PSSurface_Type) +#endif + +#if CAIRO_HAS_SVG_SURFACE +#define PycairoSVGSurface_Type *(Pycairo_CAPI->SVGSurface_Type) +#endif + +#if CAIRO_HAS_WIN32_SURFACE +#define PycairoWin32Surface_Type *(Pycairo_CAPI->Win32Surface_Type) +#endif + +#if CAIRO_HAS_XLIB_SURFACE +#define PycairoXlibSurface_Type *(Pycairo_CAPI->XlibSurface_Type) +#endif + +#define PycairoSurface_FromSurface (Pycairo_CAPI->Surface_FromSurface) + +#define Pycairo_Check_Status (Pycairo_CAPI->Check_Status) + + +/* To access the Pycairo C API, edit the client module file to: + * 1) Add the following line to define a global variable for the C API + * static Pycairo_CAPI_t *Pycairo_CAPI; + * 2) Add 'Pycairo_IMPORT;' to the init<module> function + */ +#define Pycairo_IMPORT \ + Pycairo_CAPI = (Pycairo_CAPI_t*) PyCObject_Import("cairo", "CAPI") + +#endif /* ifndef _INSIDE_PYCAIRO_ */ + +#endif /* ifndef _PYCAIRO_H_ */ diff --git a/test/.gitignore b/test/.gitignore new file mode 100644 index 0000000..39ca8f9 --- /dev/null +++ b/test/.gitignore @@ -0,0 +1,5 @@ +Makefile +Makefile.in +*.png +*.pyc +*.pyo diff --git a/test/Makefile.am b/test/Makefile.am new file mode 100644 index 0000000..af0a436 --- /dev/null +++ b/test/Makefile.am @@ -0,0 +1,11 @@ +EXTRA_DIST = \ + examples_test.py + isurface_create_for_data1.py \ + isurface_create_for_data2.py \ + isurface_create_from_png.py \ + isurface_get_data.py \ + pygame-test1.py \ + pygame-test2.py \ + surface_create_for_stream.py \ + surface_write_to_png.py + diff --git a/test/api_test.py b/test/api_test.py new file mode 100644 index 0000000..6a8db8c --- /dev/null +++ b/test/api_test.py @@ -0,0 +1,54 @@ +'''test pycairo API +- can be expanded later as required. +- is not able to test the quality of images created. We assume cairo itself + tests for this. +''' +from __future__ import division # new in 2.2, redundant in 3.0 +from __future__ import absolute_import # new in 2.5, redundant in 2.7/3.0 +from __future__ import print_function # new in 2.6, redundant in 3.0 + +import tempfile as tfi + +import cairo +import py.test as test + + +def test_context(): + pass + +def test_matrix(): + pass + +def test_path(): + pass + +def test_patterns(): + pass + + +def test_surfaces(): + # The Surface type cannot be instantiated + test.raises(TypeError, "s = cairo.Surface()") + + if cairo.HAS_IMAGE_SURFACE: + f, w, h = cairo.FORMAT_ARGB32, 100, 100 + s = cairo.ImageSurface(f, w, h) + assert s.get_format() == f + assert s.get_width() == w + assert s.get_height() == h + + if cairo.HAS_PDF_SURFACE: + f, w, h = tfi.TemporaryFile(mode='w+b'), 100, 100 + s = cairo.PDFSurface(f, w, h) + + if cairo.HAS_PS_SURFACE: + f, w, h = tfi.TemporaryFile(mode='w+b'), 100, 100 + s = cairo.PSSurface(f, w, h) + + if cairo.HAS_SVG_SURFACE: + f, w, h = tfi.TemporaryFile(mode='w+b'), 100, 100 + s = cairo.SVGSurface(f, w, h) + + +def test_text(): + pass diff --git a/test/examples_test.py b/test/examples_test.py new file mode 100644 index 0000000..f5fe924 --- /dev/null +++ b/test/examples_test.py @@ -0,0 +1,29 @@ +'''test by running example scripts +''' +from __future__ import division # new in 2.2, redundant in 3.0 +from __future__ import absolute_import # new in 2.5, redundant in 2.7/3.0 +from __future__ import print_function # new in 2.6, redundant in 3.0 + +import os +import os.path +import subprocess + +#import py.test as test + + +def test_examples(): + '''run non-gui example scripts and check they exit successfully. + ''' + os.chdir(os.path.join(os.path.dirname(__file__), '..', 'examples')) + for f in (x for x in os.listdir('.') if x.endswith('.py')): + retcode = subprocess.call('python %s' % f, shell=True) + assert retcode == 0, 'Error: {0} retcode == {1}'.format(f, retcode) + + +def test_snippets_png(): + '''run all snippets in png mode and check they exit successfully. + ''' + os.chdir(os.path.join(os.path.dirname(__file__), '..', 'examples', + 'cairo_snippets')) + retcode = subprocess.call('python snippets_png.py -s', shell=True) + assert retcode == 0, 'Error: retcode == {0}'.format(retcode) diff --git a/test/isurface_create_for_data1.py b/test/isurface_create_for_data1.py new file mode 100755 index 0000000..c497991 --- /dev/null +++ b/test/isurface_create_for_data1.py @@ -0,0 +1,27 @@ +#!/usr/bin/env python +"""test cairo.ImageSurface.create_for_data() with a Python array +""" + +import array + +import cairo + +dir_ = "/tmp/" +width, height = 255, 255 +data = array.array('B', [0] * width * height * 4) + +for y in range(height): + for x in range(width): + offset = (x + (y * width)) * 4 + alpha = y + + # cairo.FORMAT_ARGB32 uses pre-multiplied alpha + data[offset+0] = int(x * alpha/255.0) # B + data[offset+1] = int(y * alpha/255.0) # G + data[offset+2] = 0 # R + data[offset+3] = alpha # A + +surface = cairo.ImageSurface.create_for_data(data, cairo.FORMAT_ARGB32, + width, height) +ctx = cairo.Context(surface) +surface.write_to_png(dir_ + 'for_data1.png') diff --git a/test/isurface_create_for_data2.py b/test/isurface_create_for_data2.py new file mode 100755 index 0000000..88b4c5c --- /dev/null +++ b/test/isurface_create_for_data2.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python +"""test cairo.ImageSurface.create_for_data() with a numpy array +""" + +import cairo + +import numpy + +dir_ = "/tmp/" +width, height = 255, 255 +data = numpy.ndarray (shape=(height,width,4), dtype=numpy.uint8) + +for x in range(width): + for y in range(height): + alpha = y + + # cairo.FORMAT_ARGB32 uses pre-multiplied alpha + data[y][x][0] = int(x * alpha/255.0) + data[y][x][1] = int(y * alpha/255.0) + data[y][x][2] = 0 + data[y][x][3] = alpha + +surface = cairo.ImageSurface.create_for_data (data, cairo.FORMAT_ARGB32, + width, height) +ctx = cairo.Context(surface) +surface.write_to_png(dir_ + 'for_data2.png') diff --git a/test/isurface_create_from_png.py b/test/isurface_create_from_png.py new file mode 100755 index 0000000..951acb3 --- /dev/null +++ b/test/isurface_create_from_png.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python +# test cairo.ImageSurface.create_from_png() + +import cairo + +surface = cairo.ImageSurface.create_from_png("/tmp/warpedtext.png") + +# write to filename +surface.write_to_png("/tmp/t1.png") + +# write to file object +f2=file("/tmp/t2.png", "w") +surface.write_to_png(f2) +f2.close() + +# write to object that has a "write" method +import StringIO +buffer = StringIO.StringIO() +surface.write_to_png(buffer) +png_string = buffer.getvalue() +buffer.close() +f3=file("/tmp/t3.png", "w") +f3.write(png_string) +f3.close() + +# write to object that has a "write" method +import cStringIO +buffer = cStringIO.StringIO() +surface.write_to_png(buffer) +png_string = buffer.getvalue() +buffer.close() +f4=file("/tmp/t4.png", "w") +f4.write(png_string) +f4.close() + +# error test - to check the error message, should raise TypeError +#surface.write_to_png(101) diff --git a/test/isurface_get_data.py b/test/isurface_get_data.py new file mode 100755 index 0000000..c19a17e --- /dev/null +++ b/test/isurface_get_data.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python +""" +Test ImageSurface.get_data() +""" + +import cairo +import numpy + +dir_ = "/tmp/" +w, h = 128, 128 + +surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, w, h) +ctx = cairo.Context(surface) + +ctx.set_source_rgb(1, 1, 1) # white +ctx.set_operator(cairo.OPERATOR_SOURCE) +ctx.paint() + +# Draw out the triangle using absolute coordinates +ctx.move_to(w/2, h/3) +ctx.line_to(2*w/3, 2*h/3) +ctx.rel_line_to(-1*w/3, 0) +ctx.close_path() + +ctx.set_source_rgb(0, 0, 0) # black +ctx.set_line_width(15) +ctx.stroke() +surface.write_to_png(dir_ + "get_data_test1.png") + +# modify surface using numpy +buf = surface.get_data() +# alternative which should work (?) but reports +# TypeError: buffer is read-only +# - is a Python bug? +#buf = buffer (surface1) + +a = numpy.ndarray(shape=(w,h,4), dtype=numpy.uint8, buffer=buf) + +# draw a vertical line +a[:,40,0] = 255 # byte 0 is blue on little-endian systems +a[:,40,1] = 0 +a[:,40,2] = 0 +surface.write_to_png(dir_ + "get_data_test2.png") diff --git a/test/pygame-test1.py b/test/pygame-test1.py new file mode 100755 index 0000000..25871e5 --- /dev/null +++ b/test/pygame-test1.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python +"""demonstrate pycairo and pygame +method1: use pycairo and pygame directly +""" + +import array +import math +import sys + +import cairo +import pygame + +def draw(surface): + x,y, radius = (250,250, 200) + ctx = cairo.Context(surface) + ctx.set_line_width(15) + ctx.arc(x, y, radius, 0, 2.0 * math.pi) + ctx.set_source_rgb(0.8, 0.8, 0.8) + ctx.fill_preserve() + ctx.set_source_rgb(1, 1, 1) + ctx.stroke() + +def input(events): + for event in events: + if event.type == pygame.QUIT: + sys.exit(0) + else: + print event + + +Width, Height = 512, 512 +surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, Width, Height) + +pygame.init() +window = pygame.display.set_mode( (Width,Height) ) +screen = pygame.display.get_surface() + +draw(surface) + +#Create PyGame surface from Cairo Surface +buf = surface.get_data() +image = pygame.image.frombuffer(buf,(Width,Height),"ARGB",) +#Tranfer to Screen +screen.blit(image, (0,0)) +pygame.display.flip() + +while True: + input(pygame.event.get()) + + +""" +with pycairo 1.4.12 and pygame 1.7.1 you get the error message: + +Traceback (most recent call last): + File "./pygame-test1.py", line 42, in <module> + image = pygame.image.frombuffer(buf,(Width,Height),"ARGB",) +TypeError: char buffer type not available + +This is because with + buf = surface.get_data() +pycairo provides a binary image buffer, +whereas with + image = pygame.image.frombuffer(buf,(Width,Height),"ARGB",) +pygame is expecting a text-based character buffer! +""" diff --git a/test/pygame-test2.py b/test/pygame-test2.py new file mode 100755 index 0000000..9ebc1ae --- /dev/null +++ b/test/pygame-test2.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python +"""demonstrate pycairo and pygame +method1: use an intermediate Python array object +""" + +import array +import math +import sys + +import cairo +import pygame + +def draw(surface): + x,y, radius = (250,250, 200) + ctx = cairo.Context(surface) + ctx.set_line_width(15) + ctx.arc(x, y, radius, 0, 2.0 * math.pi) + ctx.set_source_rgb(0.8, 0.8, 0.8) + ctx.fill_preserve() + ctx.set_source_rgb(1, 1, 1) + ctx.stroke() + +def input(events): + for event in events: + if event.type == pygame.QUIT: + sys.exit(0) + else: + print event + + +Width, Height = 512, 512 +data = array.array('c', chr(0) * Width * Height * 4) +stride = Width * 4 +surface = cairo.ImageSurface.create_for_data(data, cairo.FORMAT_ARGB32,Width, Height, stride) + +pygame.init() +window = pygame.display.set_mode( (Width,Height) ) +screen = pygame.display.get_surface() + +draw(surface) + +#Create PyGame surface from Cairo Surface +image = pygame.image.frombuffer(data.tostring(),(Width,Height),"ARGB",) +#Tranfer to Screen +screen.blit(image, (0,0)) +pygame.display.flip() + +while True: + input(pygame.event.get()) diff --git a/test/surface_create_for_stream.py b/test/surface_create_for_stream.py new file mode 100755 index 0000000..210badd --- /dev/null +++ b/test/surface_create_for_stream.py @@ -0,0 +1,81 @@ +#!/usr/bin/env python +""" +Test PDF/PS/SVG constructors (using streams) +""" + +import cStringIO +import gc +import math +import sys +import StringIO + +import cairo + + +class C(object): + """a file-like object (for testing), it simulates sys.stdout + """ + def __init__ (self): + self.closed = False + + def write(self, s): + """just echo to stdout, without newlines""" + if self.closed: + raise ValueError ("I/O operation on closed file") + sys.stdout.write (s) + + def close(self): + self.closed = True + + +# a selection of possible args to surface.write_to_png() +#fo = '/tmp/f.ps' +fo = file('/tmp/f.svg', 'w') +#fo = StringIO.StringIO() +#fo = cStringIO.StringIO() +#fo = sys.stdout +#fo = C() + +#fo.close() # this should cause: ValueError: I/O operation on closed file + +WIDTH, HEIGHT = 256, 256 + +#surface = cairo.PDFSurface (fo, WIDTH, HEIGHT) +#surface = cairo.PSSurface (fo, WIDTH, HEIGHT) +surface = cairo.SVGSurface (fo, WIDTH, HEIGHT) + +#sys.stdout.write ('1\n'); sys.stdout.flush() +ctx = cairo.Context (surface) + +#del fo # test that 'fo' is referenced to keep it alive +#gc.collect() + +#fo.close() # this should cause: ValueError: I/O operation on closed file + +ctx.scale (WIDTH/1.0, HEIGHT/1.0) + +pat = cairo.LinearGradient (0.0, 0.0, 0.0, 1.0) +pat.add_color_stop_rgba (1, 0, 0, 0, 1) +pat.add_color_stop_rgba (0, 1, 1, 1, 1) + +ctx.rectangle (0,0,1,1) +ctx.set_source (pat) +ctx.fill () + +pat = cairo.RadialGradient (0.45, 0.4, 0.1, + 0.4, 0.4, 0.5) +pat.add_color_stop_rgba (0, 1, 1, 1, 1) +pat.add_color_stop_rgba (1, 0, 0, 0, 1) + +ctx.set_source (pat) +ctx.arc (0.5, 0.5, 0.3, 0, 2 * math.pi) +ctx.fill () + +ctx.show_page() +surface.finish() + +# for testing StringIO: get data and write to file +#string = fo.getvalue() +#f2 = file('/tmp/f.ps', 'w') +#f2.write(string) +#f2.close() diff --git a/test/surface_write_to_png.py b/test/surface_write_to_png.py new file mode 100755 index 0000000..f4ba83b --- /dev/null +++ b/test/surface_write_to_png.py @@ -0,0 +1,69 @@ +#!/usr/bin/env python +""" +Test Surface.write_to_png() +""" + +import cStringIO +import math +import sys +import StringIO + +import cairo + + +class C(object): + """a file-like object (for testing), it simulates sys.stdout + """ + def __init__(self): + self.closed = False + + def write(self, s): + """just echo to stdout, without newlines""" + if self.closed: + raise ValueError("I/O operation on closed file") + sys.stdout.write(s) + + def close(self): + self.closed = True + + +WIDTH, HEIGHT = 256, 256 + +surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, WIDTH, HEIGHT) +ctx = cairo.Context(surface) + +ctx.scale(WIDTH/1.0, HEIGHT/1.0) + +pat = cairo.LinearGradient(0.0, 0.0, 0.0, 1.0) +pat.add_color_stop_rgba(1, 0, 0, 0, 1) +pat.add_color_stop_rgba(0, 1, 1, 1, 1) + +ctx.rectangle(0,0,1,1) +ctx.set_source(pat) +ctx.fill() + +pat = cairo.RadialGradient(0.45, 0.4, 0.1, + 0.4, 0.4, 0.5) +pat.add_color_stop_rgba(0, 1, 1, 1, 1) +pat.add_color_stop_rgba(1, 0, 0, 0, 1) + +ctx.set_source(pat) +ctx.arc(0.5, 0.5, 0.3, 0, 2 * math.pi) +ctx.fill() + +# a selection of possible args to surface.write_to_png() +#fo = '/tmp/f.png' +fo = file('/tmp/f.png', 'w') +#fo = StringIO.StringIO() +#fo = cStringIO.StringIO() +#fo = sys.stdout +#fo = C() + +fo.close() # this should cause: ValueError: I/O operation on closed file +surface.write_to_png(fo) + +# for testing StringIO: get data and write to file +#string = fo.getvalue() +#f2 = file('/tmp/f.png', 'w') +#f2.write(string) +#f2.close() |