diff options
author | dov-g <dov-g> | 2005-12-20 19:35:22 +0000 |
---|---|---|
committer | dov-g <dov-g> | 2005-12-20 19:35:22 +0000 |
commit | 3cd9710852f772065b83eccdc9669b3409d7702f (patch) | |
tree | 017b7abaf4e35cf1a3844054a4db098f35b9ff3e | |
download | paps-3cd9710852f772065b83eccdc9669b3409d7702f.tar.gz paps-3cd9710852f772065b83eccdc9669b3409d7702f.tar.xz paps-3cd9710852f772065b83eccdc9669b3409d7702f.zip |
Initial revision
-rw-r--r-- | AUTHORS | 1 | ||||
-rw-r--r-- | COPYING.LIB | 481 | ||||
-rw-r--r-- | ChangeLog | 22 | ||||
-rw-r--r-- | Doxyfile | 275 | ||||
-rw-r--r-- | INSTALL | 167 | ||||
-rw-r--r-- | Makefile.am | 2 | ||||
-rw-r--r-- | NEWS | 0 | ||||
-rw-r--r-- | README | 5 | ||||
-rw-r--r-- | TODO | 4 | ||||
-rwxr-xr-x | autogen.sh | 37 | ||||
-rw-r--r-- | config.h.in | 55 | ||||
-rw-r--r-- | configure.in | 10 | ||||
-rw-r--r-- | doc/Doxyfile | 227 | ||||
-rw-r--r-- | doc/Makefile.am | 16 | ||||
-rw-r--r-- | doc/example-output.png | bin | 0 -> 95289 bytes | |||
-rw-r--r-- | doc/mainpage.h | 170 | ||||
-rw-r--r-- | src/Makefile.am | 26 | ||||
-rw-r--r-- | src/libpaps.c | 640 | ||||
-rw-r--r-- | src/libpaps.h | 110 | ||||
-rw-r--r-- | src/paps.c | 751 | ||||
-rw-r--r-- | src/test_libpaps.c | 138 |
21 files changed, 3137 insertions, 0 deletions
@@ -0,0 +1 @@ +Dov Grobgeld <dov.grobgeld@gmail.com> diff --git a/COPYING.LIB b/COPYING.LIB new file mode 100644 index 0000000..e38ffa8 --- /dev/null +++ b/COPYING.LIB @@ -0,0 +1,481 @@ + GNU LIBRARY GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1991 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 library GPL. It is + numbered 2 because it goes with version 2 of the ordinary GPL.] + + 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 Library General Public License, applies to some +specially designated Free Software Foundation software, and to any +other libraries whose authors decide to use it. You can use it for +your libraries, too. + + When we speak of free software, we are referring to freedom, 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 or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the 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 a program 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. + + Our method of protecting your rights has two steps: (1) copyright +the library, and (2) offer you this license which gives you legal +permission to copy, distribute and/or modify the library. + + Also, for each distributor's protection, we want to make certain +that everyone understands that there is no warranty for this free +library. If the library is modified by someone else and passed on, we +want its recipients to know that what they have is not the original +version, so that any problems introduced by others will not reflect on +the original authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that companies distributing free +software will individually obtain patent licenses, thus in effect +transforming the program into proprietary software. To prevent this, +we have made it clear that any patent must be licensed for everyone's +free use or not licensed at all. + + Most GNU software, including some libraries, is covered by the ordinary +GNU General Public License, which was designed for utility programs. This +license, the GNU Library General Public License, applies to certain +designated libraries. This license is quite different from the ordinary +one; be sure to read it in full, and don't assume that anything in it is +the same as in the ordinary license. + + The reason we have a separate public license for some libraries is that +they blur the distinction we usually make between modifying or adding to a +program and simply using it. Linking a program with a library, without +changing the library, is in some sense simply using the library, and is +analogous to running a utility program or application program. However, in +a textual and legal sense, the linked executable is a combined work, a +derivative of the original library, and the ordinary General Public License +treats it as such. + + Because of this blurred distinction, using the ordinary General +Public License for libraries did not effectively promote software +sharing, because most developers did not use the libraries. We +concluded that weaker conditions might promote sharing better. + + However, unrestricted linking of non-free programs would deprive the +users of those programs of all benefit from the free status of the +libraries themselves. This Library General Public License is intended to +permit developers of non-free programs to use free libraries, while +preserving your freedom as a user of such programs to change the free +libraries that are incorporated in them. (We have not seen how to achieve +this as regards changes in header files, but we have achieved it as regards +changes in the actual functions of the Library.) The hope is that this +will lead to faster development of free libraries. + + 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, while the latter only +works together with the library. + + Note that it is possible for a library to be covered by the ordinary +General Public License rather than by this special one. + + GNU LIBRARY GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library which +contains a notice placed by the copyright holder or other authorized +party saying it may be distributed under the terms of this Library +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 compile 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) 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. + + c) 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. + + d) 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 source code 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 to +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 Library 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 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/ChangeLog b/ChangeLog new file mode 100644 index 0000000..b8959e1 --- /dev/null +++ b/ChangeLog @@ -0,0 +1,22 @@ +2005-11-24 Dov Grobgeld <dov.grobgeld@weizmann.ac.il> + + * src/libpaps.c: Fixed potential sprintf buffer overrun bug. + + * src/paps.c: Added options for letter and legal paper sizes + + * src/paps.c: Added postscript commands for setting page size + + * src/paps.c: Added DSC comments for orientation + +2005-11-19 Dov Grobgeld <dov.grobgeld@weizmann.ac.il> + + * Released new version 0.6.1 + + * src/libpaps.c: Fixed scaling bug in output postscript. The + characters were to small by a factor of 72/64 due to different + coordinate systems in PostScript and freetype2. + + * src/libpaps.c: Various cleanup of the library. + + + diff --git a/Doxyfile b/Doxyfile new file mode 100644 index 0000000..17fc909 --- /dev/null +++ b/Doxyfile @@ -0,0 +1,275 @@ +# Doxyfile 1.4.1-KDevelop + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- +PROJECT_NAME = libpaps +PROJECT_NUMBER = 0.1 +OUTPUT_DIRECTORY = +CREATE_SUBDIRS = NO +OUTPUT_LANGUAGE = English +USE_WINDOWS_ENCODING = NO +BRIEF_MEMBER_DESC = YES +REPEAT_BRIEF = YES +ABBREVIATE_BRIEF = "The $name class" \ + "The $name widget" \ + "The $name file" \ + is \ + provides \ + specifies \ + contains \ + represents \ + a \ + an \ + the +ALWAYS_DETAILED_SEC = NO +INLINE_INHERITED_MEMB = NO +FULL_PATH_NAMES = YES +STRIP_FROM_PATH = /home/dov/svn/ +STRIP_FROM_INC_PATH = +SHORT_NAMES = NO +JAVADOC_AUTOBRIEF = NO +MULTILINE_CPP_IS_BRIEF = NO +DETAILS_AT_TOP = NO +INHERIT_DOCS = YES +DISTRIBUTE_GROUP_DOC = NO +TAB_SIZE = 8 +ALIASES = +OPTIMIZE_OUTPUT_FOR_C = NO +OPTIMIZE_OUTPUT_JAVA = NO +SUBGROUPING = YES +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- +EXTRACT_ALL = NO +EXTRACT_PRIVATE = NO +EXTRACT_STATIC = NO +EXTRACT_LOCAL_CLASSES = YES +EXTRACT_LOCAL_METHODS = NO +HIDE_UNDOC_MEMBERS = NO +HIDE_UNDOC_CLASSES = NO +HIDE_FRIEND_COMPOUNDS = NO +HIDE_IN_BODY_DOCS = NO +INTERNAL_DOCS = NO +CASE_SENSE_NAMES = YES +HIDE_SCOPE_NAMES = NO +SHOW_INCLUDE_FILES = YES +INLINE_INFO = YES +SORT_MEMBER_DOCS = YES +SORT_BRIEF_DOCS = NO +SORT_BY_SCOPE_NAME = NO +GENERATE_TODOLIST = YES +GENERATE_TESTLIST = YES +GENERATE_BUGLIST = YES +GENERATE_DEPRECATEDLIST= YES +ENABLED_SECTIONS = +MAX_INITIALIZER_LINES = 30 +SHOW_USED_FILES = YES +SHOW_DIRECTORIES = YES +FILE_VERSION_FILTER = +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- +QUIET = NO +WARNINGS = YES +WARN_IF_UNDOCUMENTED = YES +WARN_IF_DOC_ERROR = YES +WARN_NO_PARAMDOC = NO +WARN_FORMAT = "$file:$line: $text" +WARN_LOGFILE = +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- +INPUT = /home/dov/svn/libpaps +FILE_PATTERNS = *.c \ + *.cc \ + *.cxx \ + *.cpp \ + *.c++ \ + *.java \ + *.ii \ + *.ixx \ + *.ipp \ + *.i++ \ + *.inl \ + *.h \ + *.hh \ + *.hxx \ + *.hpp \ + *.h++ \ + *.idl \ + *.odl \ + *.cs \ + *.php \ + *.php3 \ + *.inc \ + *.m \ + *.mm \ + *.dox \ + *.C \ + *.CC \ + *.C++ \ + *.II \ + *.I++ \ + *.H \ + *.HH \ + *.H++ \ + *.CS \ + *.PHP \ + *.PHP3 \ + *.M \ + *.MM \ + *.C \ + *.H \ + *.tlh \ + *.diff \ + *.patch \ + *.moc \ + *.xpm \ + *.dox +RECURSIVE = yes +EXCLUDE = +EXCLUDE_SYMLINKS = NO +EXCLUDE_PATTERNS = +EXAMPLE_PATH = +EXAMPLE_PATTERNS = * +EXAMPLE_RECURSIVE = NO +IMAGE_PATH = +INPUT_FILTER = +FILTER_PATTERNS = +FILTER_SOURCE_FILES = NO +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- +SOURCE_BROWSER = NO +INLINE_SOURCES = NO +STRIP_CODE_COMMENTS = YES +REFERENCED_BY_RELATION = YES +REFERENCES_RELATION = YES +VERBATIM_HEADERS = YES +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- +ALPHABETICAL_INDEX = NO +COLS_IN_ALPHA_INDEX = 5 +IGNORE_PREFIX = +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- +GENERATE_HTML = YES +HTML_OUTPUT = html +HTML_FILE_EXTENSION = .html +HTML_HEADER = +HTML_FOOTER = +HTML_STYLESHEET = +HTML_ALIGN_MEMBERS = YES +GENERATE_HTMLHELP = NO +CHM_FILE = +HHC_LOCATION = +GENERATE_CHI = NO +BINARY_TOC = NO +TOC_EXPAND = NO +DISABLE_INDEX = NO +ENUM_VALUES_PER_LINE = 4 +GENERATE_TREEVIEW = NO +TREEVIEW_WIDTH = 250 +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- +GENERATE_LATEX = YES +LATEX_OUTPUT = latex +LATEX_CMD_NAME = latex +MAKEINDEX_CMD_NAME = makeindex +COMPACT_LATEX = NO +PAPER_TYPE = a4wide +EXTRA_PACKAGES = +LATEX_HEADER = +PDF_HYPERLINKS = NO +USE_PDFLATEX = NO +LATEX_BATCHMODE = NO +LATEX_HIDE_INDICES = NO +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- +GENERATE_RTF = NO +RTF_OUTPUT = rtf +COMPACT_RTF = NO +RTF_HYPERLINKS = NO +RTF_STYLESHEET_FILE = +RTF_EXTENSIONS_FILE = +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- +GENERATE_MAN = NO +MAN_OUTPUT = man +MAN_EXTENSION = .3 +MAN_LINKS = NO +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- +GENERATE_XML = yes +XML_OUTPUT = xml +XML_SCHEMA = +XML_DTD = +XML_PROGRAMLISTING = YES +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- +GENERATE_AUTOGEN_DEF = NO +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- +GENERATE_PERLMOD = NO +PERLMOD_LATEX = NO +PERLMOD_PRETTY = YES +PERLMOD_MAKEVAR_PREFIX = +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- +ENABLE_PREPROCESSING = YES +MACRO_EXPANSION = NO +EXPAND_ONLY_PREDEF = NO +SEARCH_INCLUDES = YES +INCLUDE_PATH = +INCLUDE_FILE_PATTERNS = +PREDEFINED = +EXPAND_AS_DEFINED = +SKIP_FUNCTION_MACROS = YES +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- +TAGFILES = +GENERATE_TAGFILE = libpaps.tag +ALLEXTERNALS = NO +EXTERNAL_GROUPS = YES +PERL_PATH = /usr/bin/perl +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- +CLASS_DIAGRAMS = YES +HIDE_UNDOC_RELATIONS = YES +HAVE_DOT = NO +CLASS_GRAPH = YES +COLLABORATION_GRAPH = YES +GROUP_GRAPHS = YES +UML_LOOK = NO +TEMPLATE_RELATIONS = NO +INCLUDE_GRAPH = YES +INCLUDED_BY_GRAPH = YES +CALL_GRAPH = NO +GRAPHICAL_HIERARCHY = YES +DIRECTORY_GRAPH = YES +DOT_IMAGE_FORMAT = png +DOT_PATH = +DOTFILE_DIRS = +MAX_DOT_GRAPH_WIDTH = 1024 +MAX_DOT_GRAPH_HEIGHT = 1024 +MAX_DOT_GRAPH_DEPTH = 1000 +DOT_TRANSPARENT = NO +DOT_MULTI_TARGETS = NO +GENERATE_LEGEND = YES +DOT_CLEANUP = YES +#--------------------------------------------------------------------------- +# Configuration::additions related to the search engine +#--------------------------------------------------------------------------- +SEARCHENGINE = NO @@ -0,0 +1,167 @@ +Basic Installation +================== + + These are generic installation instructions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, a file +`config.cache' that saves the results of its tests to speed up +reconfiguring, and a file `config.log' containing compiler output +(useful mainly for debugging `configure'). + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If at some point `config.cache' +contains results you don't want to keep, you may remove or edit it. + + The file `configure.in' is used to create `configure' by a program +called `autoconf'. You only need `configure.in' if you want to change +it or regenerate `configure' using a newer version of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes a while. While running, it prints some + messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Type `make install' to install the programs and any data files and + documentation. + + 4. You can remove the program binaries and object files from the + source code directory by typing `make clean'. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. You can give `configure' +initial values for variables by setting them in the environment. Using +a Bourne-compatible shell, you can do that on the command line like +this: + CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure + +Or on systems that have the `env' program, you can do it like this: + env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you must use a version of `make' that +supports the `VPATH' variable, such as GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + If you have to use a `make' that does not supports the `VPATH' +variable, you have to compile the package for one architecture at a time +in the source code directory. After you have installed the package for +one architecture, use `make distclean' before reconfiguring for another +architecture. + +Installation Names +================== + + By default, `make install' will install the package's files in +`/usr/local/bin', `/usr/local/man', etc. You can specify an +installation prefix other than `/usr/local' by giving `configure' the +option `--prefix=PATH'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +give `configure' the option `--exec-prefix=PATH', the package will use +PATH as the prefix for installing programs and libraries. +Documentation and other data files will still use the regular prefix. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +Specifying the System Type +========================== + + There may be some features `configure' can not figure out +automatically, but needs to determine by the type of host the package +will run on. Usually `configure' can figure that out, but if it prints +a message saying it can not guess the host type, give it the +`--host=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name with three fields: + CPU-COMPANY-SYSTEM + +See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the host type. + + If you are building compiler tools for cross-compiling, you can also +use the `--target=TYPE' option to select the type of system they will +produce code for and the `--build=TYPE' option to select the type of +system on which you are compiling the package. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Operation Controls +================== + + `configure' recognizes the following options to control how it +operates. + +`--cache-file=FILE' + Use and save the results of the tests in FILE instead of + `./config.cache'. Set FILE to `/dev/null' to disable caching, for + debugging `configure'. + +`--help' + Print a summary of the options to `configure', and exit. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`--version' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`configure' also accepts some other, not widely useful, options. + diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..1799d25 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,2 @@ +SUBDIRS = src doc + @@ -0,0 +1,5 @@ +libplis is a library for converting Unicode text encoded in UTF-8 +to postscript by using pango. + +plis is a command line program using this library. + @@ -0,0 +1,4 @@ +* Embed character outlines in Type3 fonts in order to make substantially + smaller PDF files after running through ps2pdf. + +* Alternatively create PDF generating backend. diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 0000000..1a38e85 --- /dev/null +++ b/autogen.sh @@ -0,0 +1,37 @@ +#!/bin/sh +# Run this to generate all the initial makefiles, etc. + +DIE=0 + +(libtoolize --force) + +(autoconf --version) < /dev/null > /dev/null 2>&1 || { + echo + echo "You must have autoconf installed to compile libpaps." + echo "Download the appropriate package for your distribution," + echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/" + DIE=1 +} + +(libtool --version) < /dev/null > /dev/null 2>&1 || { + echo + echo "You must have libtool installed to compile libpaps." + echo "Get it from ftp://ftp.gnu.org/pub/gnu/libtool/" + DIE=1 +} +if test "$DIE" -eq 1; then + exit 1 +fi + +if test -z "$*"; then + echo "I am going to run ./configure with no arguments - if you wish " + echo "to pass any to it, please specify them on the $0 command line." +fi + +aclocal $ACLOCAL_FLAGS +automake --add-missing +autoconf +./configure "$@" + +echo +echo "Now type 'make' to compile libpaps" diff --git a/config.h.in b/config.h.in new file mode 100644 index 0000000..5a1898a --- /dev/null +++ b/config.h.in @@ -0,0 +1,55 @@ +/* config.h.in. Generated from configure.in by autoheader. */ + +/* Define to 1 if you have the <dlfcn.h> header file. */ +#undef HAVE_DLFCN_H + +/* Define to 1 if you have the <inttypes.h> header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the <memory.h> header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the <stdint.h> header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the <stdlib.h> header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the <strings.h> header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the <string.h> header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the <sys/stat.h> header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the <sys/types.h> header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the <unistd.h> header file. */ +#undef HAVE_UNISTD_H + +/* Name of package */ +#undef PACKAGE + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Version number of package */ +#undef VERSION diff --git a/configure.in b/configure.in new file mode 100644 index 0000000..e97495e --- /dev/null +++ b/configure.in @@ -0,0 +1,10 @@ +AC_INIT(configure.in) + +AM_CONFIG_HEADER(config.h) +AM_INIT_AUTOMAKE(paps, 0.6.1) + +AC_LANG_C +AC_PROG_CC +AM_PROG_LIBTOOL + +AC_OUTPUT(Makefile src/Makefile doc/Makefile) diff --git a/doc/Doxyfile b/doc/Doxyfile new file mode 100644 index 0000000..f8b5229 --- /dev/null +++ b/doc/Doxyfile @@ -0,0 +1,227 @@ +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- +PROJECT_NAME = libpaps +PROJECT_NUMBER = 0.6 +OUTPUT_DIRECTORY = +CREATE_SUBDIRS = NO +OUTPUT_LANGUAGE = English +USE_WINDOWS_ENCODING = NO +BRIEF_MEMBER_DESC = YES +REPEAT_BRIEF = YES +ABBREVIATE_BRIEF = "The $name class" \ + "The $name widget" \ + "The $name file" \ + is \ + provides \ + specifies \ + contains \ + represents \ + a \ + an \ + the +ALWAYS_DETAILED_SEC = NO +INLINE_INHERITED_MEMB = NO +FULL_PATH_NAMES = YES +STRIP_FROM_INC_PATH = +SHORT_NAMES = NO +JAVADOC_AUTOBRIEF = NO +MULTILINE_CPP_IS_BRIEF = NO +DETAILS_AT_TOP = NO +INHERIT_DOCS = YES +DISTRIBUTE_GROUP_DOC = NO +TAB_SIZE = 8 +ALIASES = +OPTIMIZE_OUTPUT_FOR_C = NO +OPTIMIZE_OUTPUT_JAVA = NO +SUBGROUPING = YES +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- +EXTRACT_ALL = NO +EXTRACT_PRIVATE = NO +EXTRACT_STATIC = NO +EXTRACT_LOCAL_CLASSES = YES +EXTRACT_LOCAL_METHODS = NO +HIDE_UNDOC_MEMBERS = NO +HIDE_UNDOC_CLASSES = NO +HIDE_FRIEND_COMPOUNDS = NO +HIDE_IN_BODY_DOCS = NO +INTERNAL_DOCS = NO +CASE_SENSE_NAMES = YES +HIDE_SCOPE_NAMES = NO +SHOW_INCLUDE_FILES = YES +INLINE_INFO = YES +SORT_MEMBER_DOCS = YES +SORT_BRIEF_DOCS = NO +SORT_BY_SCOPE_NAME = NO +GENERATE_TODOLIST = YES +GENERATE_TESTLIST = YES +GENERATE_BUGLIST = YES +GENERATE_DEPRECATEDLIST= YES +ENABLED_SECTIONS = +MAX_INITIALIZER_LINES = 30 +SHOW_USED_FILES = YES +SHOW_DIRECTORIES = YES +FILE_VERSION_FILTER = +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- +QUIET = NO +WARNINGS = YES +WARN_IF_UNDOCUMENTED = YES +WARN_IF_DOC_ERROR = YES +WARN_NO_PARAMDOC = NO +WARN_FORMAT = "$file:$line: $text" +WARN_LOGFILE = +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- +INPUT = ../src . +FILE_PATTERNS = *.h +RECURSIVE = yes +EXCLUDE = +EXCLUDE_SYMLINKS = NO +EXCLUDE_PATTERNS = +EXAMPLE_PATH = +EXAMPLE_PATTERNS = * +EXAMPLE_RECURSIVE = NO +IMAGE_PATH = . +INPUT_FILTER = +FILTER_PATTERNS = +FILTER_SOURCE_FILES = NO +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- +SOURCE_BROWSER = NO +INLINE_SOURCES = NO +STRIP_CODE_COMMENTS = YES +REFERENCED_BY_RELATION = YES +REFERENCES_RELATION = YES +VERBATIM_HEADERS = YES +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- +ALPHABETICAL_INDEX = NO +COLS_IN_ALPHA_INDEX = 5 +IGNORE_PREFIX = +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- +GENERATE_HTML = YES +HTML_OUTPUT = doxygen-html +HTML_FILE_EXTENSION = .html +HTML_HEADER = +HTML_FOOTER = +HTML_STYLESHEET = +HTML_ALIGN_MEMBERS = YES +GENERATE_HTMLHELP = NO +CHM_FILE = +HHC_LOCATION = +GENERATE_CHI = NO +BINARY_TOC = NO +TOC_EXPAND = NO +DISABLE_INDEX = NO +ENUM_VALUES_PER_LINE = 4 +GENERATE_TREEVIEW = NO +TREEVIEW_WIDTH = 250 +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- +GENERATE_LATEX = NO +LATEX_OUTPUT = latex +LATEX_CMD_NAME = latex +MAKEINDEX_CMD_NAME = makeindex +COMPACT_LATEX = NO +PAPER_TYPE = a4wide +EXTRA_PACKAGES = +LATEX_HEADER = +PDF_HYPERLINKS = NO +USE_PDFLATEX = NO +LATEX_BATCHMODE = NO +LATEX_HIDE_INDICES = NO +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- +GENERATE_RTF = NO +RTF_OUTPUT = rtf +COMPACT_RTF = NO +RTF_HYPERLINKS = NO +RTF_STYLESHEET_FILE = +RTF_EXTENSIONS_FILE = +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- +GENERATE_MAN = NO +MAN_OUTPUT = man +MAN_EXTENSION = .3 +MAN_LINKS = NO +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- +GENERATE_XML = NO +XML_OUTPUT = xml +XML_SCHEMA = +XML_DTD = +XML_PROGRAMLISTING = YES +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- +GENERATE_AUTOGEN_DEF = NO +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- +GENERATE_PERLMOD = NO +PERLMOD_LATEX = NO +PERLMOD_PRETTY = YES +PERLMOD_MAKEVAR_PREFIX = +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- +ENABLE_PREPROCESSING = YES +MACRO_EXPANSION = NO +EXPAND_ONLY_PREDEF = NO +SEARCH_INCLUDES = YES +INCLUDE_PATH = +INCLUDE_FILE_PATTERNS = +PREDEFINED = +EXPAND_AS_DEFINED = +SKIP_FUNCTION_MACROS = YES +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- +TAGFILES = +GENERATE_TAGFILE = libpaps.tag +ALLEXTERNALS = NO +EXTERNAL_GROUPS = YES +PERL_PATH = /usr/bin/perl +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- +CLASS_DIAGRAMS = YES +HIDE_UNDOC_RELATIONS = YES +HAVE_DOT = NO +CLASS_GRAPH = YES +COLLABORATION_GRAPH = YES +GROUP_GRAPHS = YES +UML_LOOK = NO +TEMPLATE_RELATIONS = NO +INCLUDE_GRAPH = YES +INCLUDED_BY_GRAPH = YES +CALL_GRAPH = NO +GRAPHICAL_HIERARCHY = YES +DIRECTORY_GRAPH = YES +DOT_IMAGE_FORMAT = png +DOT_PATH = +DOTFILE_DIRS = +MAX_DOT_GRAPH_WIDTH = 1024 +MAX_DOT_GRAPH_HEIGHT = 1024 +MAX_DOT_GRAPH_DEPTH = 1000 +DOT_TRANSPARENT = NO +DOT_MULTI_TARGETS = NO +GENERATE_LEGEND = YES +DOT_CLEANUP = YES +#--------------------------------------------------------------------------- +# Configuration::additions related to the search engine +#--------------------------------------------------------------------------- +SEARCHENGINE = NO diff --git a/doc/Makefile.am b/doc/Makefile.am new file mode 100644 index 0000000..e0457f8 --- /dev/null +++ b/doc/Makefile.am @@ -0,0 +1,16 @@ +DOXYGEN = doxygen + +all: doxygen-html + +doxygen-html: Doxyfile + $(DOXYGEN) $< + +clean-generic: + rm -rf doxygen-html + +EXTRA_DIST = Doxyfile example-output.png mainpage.h + +htmldir = share/doc/libpaps/html +install-data-hook: + mkdir -p $(prefix)/$(htmldir) + cp -dpR doxygen-html/* $(prefix)/$(htmldir) diff --git a/doc/example-output.png b/doc/example-output.png Binary files differnew file mode 100644 index 0000000..34905fd --- /dev/null +++ b/doc/example-output.png diff --git a/doc/mainpage.h b/doc/mainpage.h new file mode 100644 index 0000000..0ea4746 --- /dev/null +++ b/doc/mainpage.h @@ -0,0 +1,170 @@ +/*! \mainpage + + \section intro Introduction + + paps is a a program that renders UTF8 files in PostScript through + pango. paps also comes with libpaps, a library that + makes it easy to render PostScript output in any pango based programs, + e.g. programs based on gtk. + + \section API API documentation + + - \link libpaps.h libpaps.h \endlink - Libpaps API documentation + + \section Examples Examples + Here are is an example showing the use of libpango. + + \code +/*====================================================================== +// test-paps.c - Testing the paps library. +// +// Dov Grobgeld <dov.weizmann@weizmann.ac.il> +// Tue Nov 8 21:50:31 2005 +//---------------------------------------------------------------------- +*/ + +#include <pango/pango.h> +#include <pango/pangoft2.h> +#include <stdio.h> +#include "libpaps.h" + +int main(int argc, char*argv[]) +{ + paps_t *paps = paps_new(); + gchar *header, *ps_layout; + PangoContext *pango_context; + PangoFontDescription *font_description; + PangoDirection pango_dir = PANGO_DIRECTION_LTR; + PangoLayout *layout; + gchar *font_family = "sans"; + int font_scale = 14; + GString *ps_text = g_string_new(""); + + pango_context = paps_get_pango_context(); + + /* Setup pango */ + pango_context_set_language (pango_context, pango_language_from_string ("en_US")); + pango_context_set_base_dir (pango_context, pango_dir); + + font_description = pango_font_description_new (); + pango_font_description_set_family (font_description, g_strdup (font_family)); + pango_font_description_set_style (font_description, PANGO_STYLE_NORMAL); + pango_font_description_set_variant (font_description, PANGO_VARIANT_NORMAL); + pango_font_description_set_weight (font_description, PANGO_WEIGHT_NORMAL); + pango_font_description_set_stretch (font_description, PANGO_STRETCH_NORMAL); + pango_font_description_set_size (font_description, font_scale * PANGO_SCALE); + + pango_context_set_font_description (pango_context, font_description); + + // Create a layout and set its properties + layout = pango_layout_new (pango_context); + pango_layout_set_justify (layout, TRUE); + pango_layout_set_width (layout, paps_postscript_points_to_pango(5*72)); + + pango_layout_set_text (layout, + "It was the best of times, it was the worst of times, " + "it was the age of wisdom, it was the age of foolishness, " + "it was the epoch of belief, it was the epoch of incredulity, " + "it was the season of Light, it was the season of Darkness, " + "it was the spring of hope, it was the winter of despair, " + "we had everything before us, we had nothing before us, " + "we were all going direct to Heaven, we were all going direct " + "the other way--in short, the period was so far like the present " + "period, that some of its noisiest authorities insisted on its " + "being received, for good or for evil, in the superlative degree " + "of comparison only. " + "\n\n" + "There were a king with a large jaw and a queen with a plain face, " + "on the throne of England; there were a king with a large jaw and " + "a queen with a fair face, on the throne of France. In both " + "countries it was clearer than crystal to the lords of the State " + "preserves of loaves and fishes, that things in general were " + "settled for ever. " + "\n\n" + "It was the year of Our Lord one thousand seven hundred and " + "seventy-five. Spiritual revelations were conceded to England at " + "that favoured period, as at this. Mrs. Southcott had recently " + "attained her five-and-twentieth blessed birthday, of whom a " + "prophetic private in the Life Guards had heralded the sublime " + "appearance by announcing that arrangements were made for the " + "swallowing up of London and Westminster. Even the Cock-lane " + "ghost had been laid only a round dozen of years, after rapping " + "out its messages, as the spirits of this very year last past " + "(supernaturally deficient in originality) rapped out theirs. " + "Mere messages in the earthly order of events had lately come to " + "the English Crown and People, from a congress of British subjects " + "in America: which, strange to relate, have proved more important " + "to the human race than any communications yet received through " + "any of the chickens of the Cock-lane brood. " + , -1); + + ps_layout = paps_layout_to_postscript_strdup(paps, + 0, 0, + layout); + g_string_append_printf(ps_text, + "gsave\n" + "1 0.8 0.8 setrgbcolor\n" + "72 72 10 mul translate\n" + "3 rotate %s\n" + "grestore\n", + ps_layout); + g_free(ps_layout); + + pango_font_description_set_size (font_description, 25 * PANGO_SCALE); + pango_context_set_font_description (pango_context, font_description); + pango_layout_set_width (layout, paps_postscript_points_to_pango(7*72)); + pango_layout_set_text (layout, + "paps by Dov Grobgeld (\327\223\327\221 \327\222\327\250\327\225" + "\327\221\327\222\327\234\327\223\n" + "Printing through \316\240\316\261\316\275\350\252\236 (Pango)\n" + "\n" + "Arabic \330\247\331\204\330\263\331\204\330\247\330\271" + "\331\204\331\212\331\203\331\205\n" + "Hebrew \327\251\327\201\326\270\327\234\327\225\326\271\327\235\n" + "Greek (\316\225\316\273\316\273\316\267\316\275\316\271\316\272" + "\316\254) \316\223\316\265\316\271\316\254 \317\203\316\261\317\202\n" + "Japanese (\346\227\245\346\234\254\350\252\236) \343\201\223\343" + "\202\223\343\201\253\343\201\241\343\201\257, \357\275\272\357\276" + "\235\357\276\206\357\276\201\357\276\212\n" + "Chinese (\344\270\255\346\226\207, \346\231\256\351\200\232\350" + "\257\235,\346\261\211\350\257\255) \344\275\240\345\245\275\n" + "Vietnamese (Ti\341\272\277ng Vi\341\273\207t) Xin Ch" + "\303\240o\n", + -1 + ); + ps_layout = paps_layout_to_postscript_strdup(paps, + 0, 0, + layout); + g_string_append_printf(ps_text, + "gsave\n" + "0.2 0.2 1.0 setrgbcolor\n" + "100 700 translate\n" + "-10 rotate %s\n" + "grestore\n", + ps_layout); + g_string_append_printf(ps_text, + "gsave\n" + "0 0.5 0.1 setrgbcolor\n" + "500 300 translate\n" + "-5 rotate -0.5 1 scale %s\n" + "grestore\n", + ps_layout); + g_free(ps_layout); + + + header = paps_get_postscript_header_strdup(paps); + printf("%s",header); + g_free(header); + + printf("%s", ps_text->str); + + return 0; +} +\endcode + + The result is shown here: + + \image html example-output.png + + +*/ diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..95fd6b1 --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,26 @@ +lib_LIBRARIES = libpaps.a +libpaps_a_SOURCES = libpaps.c +libpaps_a_inc_HEADERS = libpaps.h +libpaps_a_incdir = $(includedir) + +bin_PROGRAMS = paps +paps_CFLAGS = -Wall +paps_SOURCES = paps.c +paps_LDADD = $(lib_LIBRARIES) $(all_libraries) +paps_LDFLAGS = `pkg-config --libs pangoft2` +paps_DEPENDENCIES = $(lib_LIBRARIES) + +EXTRA_DIST = test_libpaps.c + +# set the include path found by configure +INCLUDES= $(all_includes) `pkg-config --cflags pangoft2` + +# Test program +noinst_PROGRAMS = test_libpaps + + +test_libpaps_SOURCES = test_libpaps.c +test_libpaps_LDADD = $(lib_LIBRARIES) $(all_libraries) +test_libpaps_LDFLAGS = `pkg-config --libs pangoft2` +test_libpaps_DEPENDENCIES = $(lib_LIBRARIES) + diff --git a/src/libpaps.c b/src/libpaps.c new file mode 100644 index 0000000..6648057 --- /dev/null +++ b/src/libpaps.c @@ -0,0 +1,640 @@ +/* Pango + * paps.c: A postscript printing program using pango. + * + * Copyright (C) 2002, 2005 Dov Grobgeld <dov.grobgeld@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library 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. + * + * * Turn into a reusable library. + */ + + +#include "libpaps.h" +#include <pango/pango.h> +#include <pango/pangoft2.h> +#include <freetype/ftglyph.h> +#include <freetype/ftoutln.h> +#include <errno.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <math.h> + +// The dpi is not used as dpi but only determines the number of significant +// digits used in the definition of the outlines. In the PostScript all +// distances are scaled and only integer values are given for compactness. +// By decreasing this value the PostScript becomes smaller. But I believe +// there are better ways to compact the postscript... +#define PAPS_DPI 1000 +#define FT2PS (72.0/64.0) + +typedef struct { + GString *header; + GHashTable *glyph_cache; + int last_char_idx; + double last_pos_y; + double last_pos_x; +} paps_private_t; + + +// Forward declarations +static void add_postscript_prologue(GString *ps_string); +static gchar *get_next_char_id_strdup(paps_private_t *paps); +static void add_line_to_postscript(paps_private_t *paps, + GString *line_str, + double x_pos, + double y_pos, + PangoLayoutLine *line); + +paps_t *paps_new() +{ + paps_private_t *paps = g_new0(paps_private_t, 1); + paps->header = g_string_new(""); + paps->glyph_cache = g_hash_table_new_full(g_str_hash, + g_str_equal, + g_free, + g_free); + // Make sure the cache will be invalid... + paps->last_pos_x = -1e67; + paps->last_pos_y = -1e67; + paps->last_char_idx = 0; + + add_postscript_prologue(paps->header); + + return paps; +} + +PangoContext *paps_get_pango_context() +{ + return pango_ft2_get_context (PAPS_DPI, PAPS_DPI); +} + +gchar *paps_get_postscript_header_strdup(paps_t *paps_) +{ + paps_private_t *paps = (paps_private_t*)paps_; + + /* Add end of header string, create a strdup, and then erase the + end of line. */ + int old_len = paps->header->len; + gchar *ret_str; + g_string_append_printf(paps->header, + "end end\n" + "%%%%EndPrologue\n" + ); + ret_str = g_strdup(paps->header->str); + g_string_truncate(paps->header, old_len); + + return ret_str; +} + +typedef struct { + PangoLayoutLine *pango_line; + PangoRectangle logical_rect; + PangoRectangle ink_rect; +} LineLink; + +/* Information passed in user data when drawing outlines */ +typedef struct _OutlineInfo OutlineInfo; +struct _OutlineInfo { + GString *out_string; + FT_Vector glyph_origin; + int dpi; + int is_empty; // Flag for optimization +}; + +static void draw_line_to_page(paps_private_t *paps, + GString *line_str, + double x_pos, + double y_pos, + PangoLayoutLine *line); +static void draw_contour(paps_private_t *paps, + GString *line_str, + PangoLayoutLine *pango_line, + double line_start_pos_x, + double line_start_pos_y + ); +void draw_bezier_outline(paps_private_t *paps, + GString *layout_str, + FT_Face face, + PangoGlyphInfo *glyph_info, + double pos_x, + double pos_y + ); +/* Countour traveling functions */ +static int paps_ps_move_to( FT_Vector* to, + void *user_data); +static int paps_ps_line_to( FT_Vector* to, + void *user_data); +static int paps_ps_conic_to( FT_Vector* control, + FT_Vector* to, + void *user_data); +static int paps_ps_cubic_to( FT_Vector* control1, + FT_Vector* control2, + FT_Vector* to, + void *user_data); +static void get_next_char_id(// output + char *char_id); +static void get_glyph_hash_string(FT_Face face, + PangoGlyphInfo *glyph_info, + // output + gchar *hash_string + ); + +// Fonts are three character symbols in an alphabet composing of +// the following characters: +// +// First character: a-zA-Z@_.,!-~`'" +// Rest of chars: like first + 0-9 +// +// Care is taken that no keywords are overwritten, e.g. def, end. + +#define CASE(s) if (strcmp(S_, s) == 0) + +/* Split a list of paragraphs into a list of lines. + */ +gchar *paps_layout_to_postscript_strdup(paps_t *paps_, + double pos_x, + double pos_y, + PangoLayout *layout) +{ + paps_private_t *paps = (paps_private_t*)paps_; + GString *layout_str = g_string_new(""); + gchar *ret_str; + int para_num_lines, line_idx; + double scale = 72.0 / PANGO_SCALE / PAPS_DPI; + + para_num_lines = pango_layout_get_line_count(layout); + + for (line_idx=0; line_idx<para_num_lines; line_idx++) + { + PangoRectangle logical_rect, ink_rect; + PangoLayoutLine *pango_line = pango_layout_get_line(layout, line_idx); + + pango_layout_line_get_extents(pango_line, + &ink_rect, &logical_rect); + + + add_line_to_postscript(paps, + layout_str, + pos_x, + pos_y, + pango_line); + + pos_y -= logical_rect.height * scale; + } + + ret_str = layout_str->str; + g_string_free(layout_str, FALSE); + + return ret_str; +} + +gchar *paps_layout_line_to_postscript_strdup(paps_t *paps_, + double pos_x, + double pos_y, + PangoLayoutLine *layout_line) +{ + paps_private_t *paps = (paps_private_t*)paps_; + GString *layout_str = g_string_new(""); + gchar *ret_str; + int para_num_lines, line_idx; + double scale = 72.0 / PANGO_SCALE / PAPS_DPI; + + add_line_to_postscript(paps, + layout_str, + pos_x, + pos_y, + layout_line); + + ret_str = layout_str->str; + g_string_free(layout_str, FALSE); + + return ret_str; +} + +void add_postscript_prologue(GString *ps_string) +{ + g_string_append_printf(ps_string, + "%%%%BeginProlog\n" + "/papsdict 1 dict def\n" + "papsdict begin\n" + "\n" + ); + + /* Outline support */ + g_string_append_printf(ps_string, + "/conicto {\n" + " /to_y exch def\n" + " /to_x exch def\n" + " /conic_cntrl_y exch def\n" + " /conic_cntrl_x exch def\n" + " currentpoint\n" + " /p0_y exch def\n" + " /p0_x exch def\n" + " /p1_x p0_x conic_cntrl_x p0_x sub 2 3 div mul add def\n" + " /p1_y p0_y conic_cntrl_y p0_y sub 2 3 div mul add def\n" + " /p2_x p1_x to_x p0_x sub 1 3 div mul add def\n" + " /p2_y p1_y to_y p0_y sub 1 3 div mul add def\n" + " p1_x p1_y p2_x p2_y to_x to_y curveto\n" + "} bind def\n" + "/start_ol { gsave } bind def\n" + "/end_ol { closepath fill grestore } bind def\n" + /* Specify both x and y. */ + "/draw_char { fontdict begin gsave %f dup scale last_x last_y translate load exec end grestore} def\n" + "/goto_xy { fontdict begin /last_y exch def /last_x exch def end } def\n" + "/goto_x { fontdict begin /last_x exch def end } def\n" + "/fwd_x { fontdict begin /last_x exch last_x add def end } def\n" + "/c /curveto load def\n" + "/x /conicto load def\n" + "/l /lineto load def\n" + "/m /moveto load def\n" + "end\n", + // The scaling is a combination of the scaling due + // to the dpi and the difference in the coordinate + // systems of postscript and freetype2. + 1.0 / PAPS_DPI + ); + + // The following is a dispatcher for an encoded string that contains + // a packed version of the pango layout data. Currently it just executes + // the symbols corresponding to the encoded characters, but in the future + // it will also contain some meta data, e.g. the size of the layout. + g_string_append_printf(ps_string, + "/paps_exec {\n" + " 1 dict begin\n" + " /ps exch def\n" + " /len ps length def\n" + " /pos 0 def\n" + "\n" + " %% Loop over all the characters of the string\n" + " {\n" + " pos len eq {exit} if\n" + "\n" + " %% Get character at pos\n" + " /ch ps pos 1 getinterval def\n" + " \n" + " %% check for +\n" + " (+) ch eq {\n" + " /pos 1 pos add def\n" + " /xp ps pos 8 getinterval cvi def\n" + " /yp ps pos 8 add 8 getinterval cvi def\n" + " /pos 16 pos add def\n" + " papsdict begin xp yp goto_xy end\n" + " } {\n" + " (*) ch eq {\n" + " /pos 1 pos add def\n" + " /xp ps pos 8 getinterval cvi def\n" + " /pos 8 pos add def\n" + " papsdict begin xp goto_x end\n" + " } { (>) ch eq {\n" + " /pos 1 pos add def\n" + " /xp ps pos 4 getinterval cvi def\n" + " /pos 4 pos add def\n" + " papsdict begin xp 2 mul fwd_x end\n" + " } { (-) ch eq {\n" + " /pos 1 pos add def\n" + " /xp ps pos 4 getinterval cvi def\n" + " /pos 4 pos add def\n" + " papsdict begin xp neg 2 mul fwd_x end\n" + " } {\n" + " %% Must be a 3 char sym. Load and exec\n" + " /name ps pos 3 getinterval def\n" + " papsdict begin name draw_char end\n" + " /pos 3 pos add def\n" + " } ifelse\n" + " } ifelse\n" + " } ifelse\n" + " } ifelse\n" + " } loop\n" + " end\n" + "} def\n" + ); + + /* Open up dictionaries */ + g_string_append(ps_string, + "/fontdict 1 dict def\n" + "papsdict begin fontdict begin\n"); +} + + +static void +add_line_to_postscript(paps_private_t *paps, + GString *line_str, + double x_pos, + double y_pos, + PangoLayoutLine *line) +{ + PangoRectangle ink_rect, logical_rect; + + pango_layout_line_get_extents(line, + &ink_rect, + &logical_rect); + + + + +#if 0 + // TBD - Handle RTL scripts + if (paps->pango_dir == PANGO_DIRECTION_RTL) { + x_pos += page_layout->column_width - logical_rect.width / (page_layout->pt_to_pixel * PANGO_SCALE); + } +#endif + + draw_contour(paps, line_str, line, x_pos, y_pos); +} + +/* draw_contour() draws all of the contours that make up a line. + to access the ft font information out of the pango font info. + */ +static void draw_contour(paps_private_t *paps, + GString *layout_str, + PangoLayoutLine *pango_line, + double line_start_pos_x, + double line_start_pos_y + ) +{ + GSList *runs_list; + double scale = 72.0 / PANGO_SCALE / PAPS_DPI; + + g_string_append(layout_str, "("); + + /* Loop over the runs and output font info */ + runs_list = pango_line->runs; + double x_pos = line_start_pos_x; + while(runs_list) + { + PangoLayoutRun *run = runs_list->data; + PangoItem *item = run->item; + PangoGlyphString *glyphs = run->glyphs; + PangoAnalysis *analysis = &item->analysis; + PangoFont *font = analysis->font; + FT_Face ft_face = pango_ft2_font_get_face(font); + int num_glyphs = glyphs->num_glyphs; + int glyph_idx; + + for (glyph_idx=0; glyph_idx<num_glyphs; glyph_idx++) + { + PangoGlyphGeometry geometry = glyphs->glyphs[glyph_idx].geometry; + double glyph_pos_x, glyph_pos_y; + + glyph_pos_x = x_pos + 1.0*geometry.x_offset * scale; + glyph_pos_y = line_start_pos_y - 1.0*geometry.y_offset * scale; + + x_pos += geometry.width * scale; + + draw_bezier_outline(paps, + layout_str, + ft_face, + &glyphs->glyphs[glyph_idx], + glyph_pos_x, + glyph_pos_y + ); + } + + runs_list = runs_list->next; + } + + g_string_append(layout_str, ")paps_exec\n"); + +} + +void draw_bezier_outline(paps_private_t *paps, + GString *layout_str, + FT_Face face, + PangoGlyphInfo *glyph_info, + double pos_x, + double pos_y + ) +{ + double scale = 72.0 / PANGO_SCALE / PAPS_DPI; + double epsilon = 1e-2; + double glyph_width = glyph_info->geometry.width * scale; + gchar glyph_hash_string[20]; + gchar *id; + + /* Output outline */ + static FT_Outline_Funcs ps_outlinefunc = + { + paps_ps_move_to, + paps_ps_line_to, + paps_ps_conic_to, + paps_ps_cubic_to + }; + FT_Outline_Funcs *outlinefunc; + OutlineInfo outline_info; + + get_glyph_hash_string(face, + glyph_info, + // output + glyph_hash_string); + + // Look up the key in the hash table + if (!(id = g_hash_table_lookup(paps->glyph_cache, + glyph_hash_string))) + { + FT_Int load_flags = FT_LOAD_DEFAULT; + FT_Glyph glyph; + GString *glyph_def_string = g_string_new(""); + + // The key doesn't exist. Define the outline + id = get_next_char_id_strdup(paps); + + // Create the outline + outlinefunc = &ps_outlinefunc; + outline_info.glyph_origin.x = pos_x; + outline_info.is_empty = 1; + outline_info.glyph_origin.y = pos_y; + outline_info.out_string = glyph_def_string; + + g_string_append(glyph_def_string, + "start_ol\n"); + + FT_Load_Glyph(face, glyph_info->glyph, load_flags); + FT_Get_Glyph (face->glyph, &glyph); + FT_Outline_Decompose (&(((FT_OutlineGlyph)glyph)->outline), + outlinefunc, &outline_info); + + g_string_append_printf(glyph_def_string, + "%.0f fwd_x\n" + "end_ol\n", + glyph_info->geometry.width * scale * PAPS_DPI + ); + + // TBD - Check if the glyph_def_string is empty. If so, set the + // id to the character to "" and don't draw it. + if (outline_info.is_empty) + id[0] = '*'; + else + // Put the font in the font def dictionary + g_string_append_printf(paps->header, + "/%s { %s } def\n", + id, + glyph_def_string->str); + + g_hash_table_insert(paps->glyph_cache, + g_strdup(glyph_hash_string), + id); + + g_string_free(glyph_def_string, TRUE); + FT_Done_Glyph (glyph); + + } + + if (id[0] != '*') + { + glyph_width *= PAPS_DPI; + pos_x *=PAPS_DPI; + pos_y *= PAPS_DPI; + + // Output codes according to the ps_exec string encoding! + if (fabs (pos_y - paps->last_pos_y ) > epsilon) + { + g_string_append_printf(layout_str, + "+%8.0f%8.0f", + pos_x, pos_y + ); + } + else if (fabs(pos_x - paps->last_pos_x) > epsilon) + { + int dx = (int)(pos_x - paps->last_pos_x+0.5); + + // The extra 2 factor makes the small dx encoding trigger + // more often... + if (dx > 0 && dx < 20000) + g_string_append_printf(layout_str, + ">%4d", dx/2 + ); + else if (dx < 0 && dx > -20000) + g_string_append_printf(layout_str, + "-%4d", abs(dx)/2 + ); + else if (dx != 0) + g_string_append_printf(layout_str, + "*%8.0f", pos_x + ); + } + + // Put character on page + g_string_append_printf(layout_str, + "%s", + id + ); + + paps->last_pos_y = pos_y; + paps->last_pos_x = pos_x+glyph_width; // glyph_with is added by the outline def + } +} + +/*====================================================================== +// outline traversing functions. +//----------------------------------------------------------------------*/ +static int paps_ps_move_to( FT_Vector* to, + void *user_data) +{ + OutlineInfo *outline_info = (OutlineInfo*)user_data; + g_string_append_printf(outline_info->out_string, + "%d %d m\n", + (int)(to->x * FT2PS) , + (int)(to->y * FT2PS )); + return 0; +} + +static int paps_ps_line_to( FT_Vector* to, + void *user_data) +{ + OutlineInfo *outline_info = (OutlineInfo*)user_data; + g_string_append_printf(outline_info->out_string, + "%d %d l\n", + (int)(to->x * FT2PS) , + (int)(to->y * FT2PS) ); + outline_info->is_empty = 0; + return 0; +} + +static int paps_ps_conic_to( FT_Vector* control, + FT_Vector* to, + void *user_data) +{ + OutlineInfo *outline_info = (OutlineInfo*)user_data; + g_string_append_printf(outline_info->out_string, + "%d %d %d %d x\n", + (int)(control->x * FT2PS) , + (int)(control->y * FT2PS) , + (int)(to->x * FT2PS), + (int)(to->y * FT2PS)); + outline_info->is_empty = 0; + return 0; +} + +static int paps_ps_cubic_to( FT_Vector* control1, + FT_Vector* control2, + FT_Vector* to, + void *user_data) +{ + OutlineInfo *outline_info = (OutlineInfo*)user_data; + g_string_append_printf(outline_info->out_string, + "%d %d %d %d %d %d c\n", + (int)(control1->x * FT2PS) , + (int)(control1->y * FT2PS) , + (int)(control2->x * FT2PS) , + (int)(control2->y * FT2PS) , + (int)(to->x * FT2PS) , + (int)(to->y * FT2PS) ); + outline_info->is_empty = 0; + return 0; +} + +static gchar *get_next_char_id_strdup(paps_private_t *paps) +{ + int i; + int index = paps->last_char_idx++; + gchar *char_id = g_new0(gchar, 4); + + // Just use a-zA-Z for the three chars + for (i=0; i<3; i++) + { + int p = index % 52; + index /= 52; + + if (p < 26) + p += 'A'; + else + p += 'a'-26; + + char_id[i] = p; + } + char_id[3] = 0; + return char_id; +} + +static void get_glyph_hash_string(FT_Face face, + PangoGlyphInfo *glyph_info, + // output + gchar *hash_string + ) +{ + sprintf(hash_string, "%08x-%d-%d", + (unsigned int)face, + glyph_info->glyph, + glyph_info->geometry.width + ); +} + +double paps_postscript_points_to_pango(double points) +{ + return points * 1.0 / 72 * PAPS_DPI * PANGO_SCALE; +} + diff --git a/src/libpaps.h b/src/libpaps.h new file mode 100644 index 0000000..7c05a33 --- /dev/null +++ b/src/libpaps.h @@ -0,0 +1,110 @@ +/** + * @file libpaps.h + * + * @brief Interface for converting pango layouts into postscript. + * + * The library is used by first creating a paps object through + * paps_new(). The paps object is then used to generate PostScript + * for one or more pango layouts through paps_layout_to_postscript_strdup() + * or paps_layout_line_to_postscript_strdup(). Once all the layouts + * have been processed, the system may generate the PostScript header through + * paps_get_postscript_header_strdup(). It + * is the responsibility of the caller to place the PostScript + * header in front of the renderings of the pango layouts. + * + * The PostScript of the rendered layouts is relocatable in all + * sense so any postscript operators may be used to change their + * colors, transformations etc. + */ +#ifndef LIBPAPS_H +#define LIBPAPS_H + +#include <glib.h> +#include <pango/pango.h> + +typedef void paps_t; + +/** + * Create a new paps object that may subsequently be used for + * generating postscript strings. + * + * @return + */ +paps_t *paps_new(); + +/** + * Delete the paps object and free any allocated memory associated with + * it. + * + * @param paps + */ +void paps_free(paps_t *paps); + +/** + * libpaps may currently be used only with a PangoContext that it + * is creating. The context returned may of course be changed though + * by any routines related to a PangoContext. + * + * @return + */ +PangoContext *paps_get_pango_context(); + +/** + * paps_get_postscript_header_strdup() returns the header and the + * font definitions related to the glyphs being used. This routine + * must only be called after the processing of all the strings is + * over. + * + * @param paps Paps object + * + * @return A newly allocated string containing the postscript prologue + * needed for the postscript strings created by libpaps. + */ +gchar *paps_get_postscript_header_strdup(paps_t *paps); + +/** + * Create postscript related to a PangoLayout at position pos_x, + * pos_y (postscript coordinates). The related font definitions + * are stored internally and will be returned when doing + * paps_get_postscript_header_strdup. + * + * @param paps Paps object + * @param pos_x x-position + * @param pos_y y-position + * @param layout Layout to render + * + * @return + */ +gchar *paps_layout_to_postscript_strdup(paps_t *paps, + double pos_x, + double pos_y, + PangoLayout *layout); +/** + * Create postscript related to a single PangoLayout line at position + * pos_x, pos_y (postscript coordinates). The related font definitions + * are stored internally and will be returned when doing + * paps_get_postscript_header_strdup. + * + * @param paps Paps object + * @param pos_x x-position + * @param pos_y y-position + * @param layout_line Layout line to render + * + * @return + */ +gchar *paps_layout_line_to_postscript_strdup(paps_t *paps_, + double pos_x, + double pos_y, + PangoLayoutLine *layout_line); + +/** + * Utility function that translates from postscript points to pango + * units. + * + * @param points + * + * @return + */ +double paps_postscript_points_to_pango(double points); + +#endif /* LIBPAPS */ diff --git a/src/paps.c b/src/paps.c new file mode 100644 index 0000000..73e6246 --- /dev/null +++ b/src/paps.c @@ -0,0 +1,751 @@ +/* Pango + * paps.c: A postscript printing program using pango. + * + * Copyright (C) 2002, 2005 Dov Grobgeld <dov.grobgeld@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library 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. + * + * * Turn into a reusable library. + */ + + +#include <pango/pango.h> +#include "libpaps.h" +#include <errno.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#define BUFSIZE 1024 + +typedef enum { + PAPER_TYPE_A4 = 0, + PAPER_TYPE_US_LETTER = 1, + PAPER_TYPE_US_LEGAL = 2 +} paper_type_t ; + +typedef struct { + double width; + double height; +} paper_size_t; + +const paper_size_t paper_sizes[] = { + { 595.28, 841.89}, /* A4 */ + { 612, 792}, /* US letter */ + { 612, 1008} /* US legal */ +}; + +typedef struct { + double pt_to_pixel; + double pixel_to_pt; + int column_width; + int column_height; + int num_columns; + int gutter_width; /* These are all in postscript points=1/72 inch... */ + int top_margin; + int bottom_margin; + int left_margin; + int right_margin; + int page_width; + int page_height; + int header_ypos; + int header_sep; + gboolean do_draw_header; + gboolean do_draw_footer; + gboolean do_duplex; + gboolean do_tumble; + gboolean do_landscape; + gboolean do_justify; + gboolean do_separation_line; + gboolean do_draw_contour; + PangoDirection pango_dir; +} page_layout_t; + +typedef struct { + char *text; + int length; +} para_t; + +typedef struct { + PangoLayoutLine *pango_line; + PangoRectangle logical_rect; + PangoRectangle ink_rect; +} LineLink; + +typedef struct _Paragraph Paragraph; + +/* Structure representing a paragraph + */ +struct _Paragraph { + char *text; + int length; + int height; /* Height, in pixels */ + PangoLayout *layout; +}; + +/* Information passed in user data when drawing outlines */ +GList *split_paragraphs_into_lines(GList *paragraphs); +static char *read_file (FILE *file); +static GList * +split_text_into_paragraphs (PangoContext *pango_context, + page_layout_t *page_layout, + int paint_width, + char *text); + +int output_pages(FILE *OUT, + GList *pango_lines, + page_layout_t *page_layout); +void print_postscript_header(FILE *OUT, + const char *title, + page_layout_t *page_layout); +void print_postscript_trailer(FILE *OUT, int num_pages); +void print_svg_trailer(FILE *OUT, int num_pages); +void eject_column(FILE *OUT, + page_layout_t *page_layout, + int column_idx); +void eject_page(FILE *OUT); +void start_page(FILE *OUT, int page_idx); +void draw_line_to_page(FILE *OUT, + int column_idx, + int column_pos, + page_layout_t *page_layout, + PangoLayoutLine *line); +// Fonts are three character symbols in an alphabet composing of +// the following characters: +// +// First character: a-zA-Z@_.,!-~`'" +// Rest of chars: like first + 0-9 +// +// Care is taken that no keywords are overwritten, e.g. def, end. +GString *ps_font_def_string = NULL; +GString *ps_pages_string = NULL; +int last_char_idx = 0; +double last_pos_y = -1; +double last_pos_x = -1; +paps_t *paps; + +#define CASE(s) if (strcmp(S_, s) == 0) + +int main(int argc, char *argv[]) +{ + int argp=1; + char *filename_in; + char *title; + FILE *IN, *OUT = NULL; + page_layout_t page_layout; + char *text; + GList *paragraphs; + GList *pango_lines; + PangoContext *pango_context; + PangoFontDescription *font_description; + PangoDirection pango_dir = PANGO_DIRECTION_LTR; + char *font_family = "sans"; + int font_scale = 12; + int num_pages = 1; + int num_columns = 1; + int gutter_width = 40; + int total_gutter_width; + paper_type_t paper_type = PAPER_TYPE_A4; + int page_width = paper_sizes[0].width; + int page_height = paper_sizes[0].height; + gboolean do_landscape = FALSE; + int do_tumble = -1; /* -1 means not initialized */ + int do_duplex = -1; + gboolean do_draw_header = FALSE; + gboolean do_justify = FALSE; + gchar *paps_header = NULL; + + /* Prerequisite when using glib. */ + g_type_init(); + + /* Parse command line */ + while(argp < argc && argv[argp][0] == '-') + { + char *S_ = argv[argp++]; + CASE("--help") + { + printf("paps - A postscript generating program using pango.\n" + "\n" + "Syntax:\n" + " paps [--landscape] [--columns cl] [--font_scale fs]\n" + " [--family f] [--rtl] [--paper=type]\n" + "\n" + "Description:\n" + " paps reads a UTF-8 encoded file and generates a PostScript\n" + " rendering of the file. The rendering is done by creating\n" + " outline curves through the pango FT2 backend.\n" + "\n" + "Options:\n" + " --landscape Landscape output. Default is portrait.\n" + " --columns cl Number of columns output. Default is 1.\n" + " --font_scale fs Font scaling. Default is 12.\n" + " --family f Pango ft2 font family. Default is sans.\n" + " --rtl Do rtl layout.\n" + " --paper=letter Use US Letter page layout. Default is A4.\n" + " --paper=legal Use US Legal pge layout. Default is A4.\n" + ); + + exit(0); + } + CASE("--landscape") { do_landscape = TRUE; continue; } + CASE("--columns") { num_columns = atoi(argv[argp++]); continue; } + CASE("--font_scale") { font_scale = atoi(argv[argp++]); continue; } + CASE("--family") { font_family = argv[argp++]; continue; } + CASE("--rtl") { pango_dir = PANGO_DIRECTION_RTL; continue; } + CASE("--justify") { do_justify = TRUE; continue; } + CASE("--paper=letter") { paper_type=PAPER_TYPE_US_LETTER; continue; } + CASE("--paper=legal") { paper_type=PAPER_TYPE_US_LEGAL; continue; } + fprintf(stderr, "Unknown option %s!\n", S_); + exit(0); + } + + if (argp < argc) + { + filename_in = argv[argp++]; + IN = fopen(filename_in, "rb"); + if (!IN) + { + fprintf(stderr, "Failed to open %s!\n", filename_in); + } + } + else + { + filename_in = "stdin"; + IN = stdin; + } + title = filename_in; + + paps = paps_new(); + pango_context = paps_get_pango_context (paps); + + /* Setup pango */ + pango_context_set_language (pango_context, pango_language_from_string ("en_US")); + pango_context_set_base_dir (pango_context, pango_dir); + + font_description = pango_font_description_new (); + pango_font_description_set_family (font_description, g_strdup (font_family)); + pango_font_description_set_style (font_description, PANGO_STYLE_NORMAL); + pango_font_description_set_variant (font_description, PANGO_VARIANT_NORMAL); + pango_font_description_set_weight (font_description, PANGO_WEIGHT_NORMAL); + pango_font_description_set_stretch (font_description, PANGO_STRETCH_NORMAL); + pango_font_description_set_size (font_description, font_scale * PANGO_SCALE); + + pango_context_set_font_description (pango_context, font_description); + + /* Page layout */ + page_width = paper_sizes[(int)paper_type].width; + page_height = paper_sizes[(int)paper_type].height; + + if (num_columns == 1) + total_gutter_width = 0; + else + total_gutter_width = gutter_width * (num_columns - 1); + if (do_landscape) + { + int tmp; + tmp = page_width; + page_width = page_height; + page_height = tmp; + if (do_tumble < 0) + do_tumble = TRUE; + if (do_duplex < 0) + do_duplex = TRUE; + } + else + { + if (do_tumble < 0) + do_tumble = TRUE; + if (do_duplex < 0) + do_duplex = TRUE; + } + + page_layout.page_width = page_width; + page_layout.page_height = page_height; + page_layout.num_columns = num_columns; + page_layout.left_margin = 36; + page_layout.right_margin = 36; + page_layout.gutter_width = gutter_width; + page_layout.top_margin = 36; + page_layout.bottom_margin = 18; + page_layout.header_ypos = page_layout.top_margin; + if (do_draw_header) + page_layout.header_sep = font_scale * 2.5; + else + page_layout.header_sep = 0; + + page_layout.column_height = page_height + - page_layout.top_margin + - page_layout.header_sep + - page_layout.bottom_margin; + page_layout.column_width = (page_layout.page_width + - page_layout.left_margin - page_layout.right_margin + - total_gutter_width) / page_layout.num_columns; + page_layout.pt_to_pixel = paps_postscript_points_to_pango(1)/PANGO_SCALE; + page_layout.pixel_to_pt = 1.0/page_layout.pt_to_pixel; + page_layout.do_separation_line = TRUE; + page_layout.do_landscape = do_landscape; + page_layout.do_justify = do_justify; + page_layout.do_tumble = do_tumble; + page_layout.do_duplex = do_duplex; + page_layout.pango_dir = pango_dir; + + text = read_file(IN); + paragraphs = split_text_into_paragraphs(pango_context, + &page_layout, + page_layout.column_width * page_layout.pt_to_pixel, + text); + pango_lines = split_paragraphs_into_lines(paragraphs); + + if (OUT == NULL) + OUT = stdout; + + print_postscript_header(OUT, title, &page_layout); + ps_pages_string = g_string_new(""); + + num_pages = output_pages(OUT, pango_lines, &page_layout); + + paps_header = paps_get_postscript_header_strdup(paps); + fprintf(OUT, "%s", paps_header); + g_free(paps_header); + + fprintf(OUT, "%%%%EndPrologue\n"); + fprintf(OUT, "%s", ps_pages_string->str); + print_postscript_trailer(OUT, num_pages); + + // Cleanup + g_string_free(ps_pages_string, TRUE); + + return 0; +} + + +/* Read an entire file into a string + */ +static char * +read_file (FILE *file) +{ + GString *inbuf; + char *text; + char buffer[BUFSIZE]; + + inbuf = g_string_new (NULL); + while (1) + { + char *bp = fgets (buffer, BUFSIZE-1, file); + if (ferror (file)) + { + fprintf(stderr, "%s: Error reading file.\n", g_get_prgname ()); + g_string_free (inbuf, TRUE); + return NULL; + } + else if (bp == NULL) + break; + + g_string_append (inbuf, buffer); + } + + fclose (file); + + text = inbuf->str; + g_string_free (inbuf, FALSE); + + return text; +} + +/* Take a UTF8 string and break it into paragraphs on \n characters + */ +static GList * +split_text_into_paragraphs (PangoContext *pango_context, + page_layout_t *page_layout, + int paint_width, /* In pixels */ + char *text) +{ + char *p = text; + char *next; + gunichar wc; + GList *result = NULL; + char *last_para = text; + + while (*p) + { + wc = g_utf8_get_char (p); + next = g_utf8_next_char (p); + if (wc == (gunichar)-1) + { + fprintf (stderr, "%s: Invalid character in input\n", g_get_prgname ()); + wc = 0; + } + if (!*p || !wc || wc == '\n') + { + Paragraph *para = g_new (Paragraph, 1); + para->text = last_para; + para->length = p - last_para; + para->layout = pango_layout_new (pango_context); + pango_layout_set_text (para->layout, para->text, para->length); + pango_layout_set_justify (para->layout, page_layout->do_justify); + pango_layout_set_alignment (para->layout, + page_layout->pango_dir == PANGO_DIRECTION_LTR + ? PANGO_ALIGN_LEFT : PANGO_ALIGN_RIGHT); + pango_layout_set_width (para->layout, paint_width * PANGO_SCALE); + para->height = 0; + + last_para = next; + + result = g_list_prepend (result, para); + } + if (!wc) /* incomplete character at end */ + break; + p = next; + } + + return g_list_reverse (result); +} + +/* Split a list of paragraphs into a list of lines. + */ +GList * +split_paragraphs_into_lines(GList *paragraphs) +{ + GList *line_list = NULL; + /* Read the file */ + + /* Now split all the pagraphs into lines */ + GList *par_list; + + par_list = paragraphs; + while(par_list) + { + int para_num_lines, i; + Paragraph *para = par_list->data; + + para_num_lines = pango_layout_get_line_count(para->layout); + + for (i=0; i<para_num_lines; i++) + { + PangoRectangle logical_rect, ink_rect; + LineLink *line_link = g_new(LineLink, 1); + + line_link->pango_line = pango_layout_get_line(para->layout, i); + pango_layout_line_get_extents(line_link->pango_line, + &ink_rect, &logical_rect); + line_link->logical_rect = logical_rect; + line_link->ink_rect = ink_rect; + line_list = g_list_prepend(line_list, line_link); + } + + par_list = par_list->next; + } + + return g_list_reverse(line_list); + +} + +int output_pages(FILE *OUT, + GList *pango_lines, + page_layout_t *page_layout) +{ + int column_idx = 0; + int column_y_pos = 0; + int page_idx = 1; + int pango_column_height = page_layout->column_height * page_layout->pt_to_pixel * PANGO_SCALE; + + start_page(OUT, page_idx); + + while(pango_lines) + { + LineLink *line_link = pango_lines->data; + PangoLayoutLine *line = line_link->pango_line; + + /* Check if we need to move to next column */ + if (column_y_pos + line_link->logical_rect.height + >= pango_column_height) + { + column_idx++; + column_y_pos = 0; + if (column_idx == page_layout->num_columns) + { + column_idx = 0; + eject_page(OUT); + page_idx++; + start_page(OUT, page_idx); + } + else + eject_column(OUT, + page_layout, + column_idx + ); + } + draw_line_to_page(OUT, + column_idx, + column_y_pos+line_link->logical_rect.height, + page_layout, + line); + column_y_pos += line_link->logical_rect.height; + + pango_lines = pango_lines->next; + } + eject_page(OUT); + return page_idx; +} + +void print_postscript_header(FILE *OUT, + const char *title, + page_layout_t *page_layout) +{ + const char *bool_name[2] = { "false", "true" }; + const char *orientation_names[2] = { "Portrait", "Landscape" }; + int bodytop = page_layout->header_ypos + page_layout->header_sep; + int orientation = page_layout->page_width > page_layout->page_height; + + fprintf(OUT, + "%%!PS-Adobe-3.0\n" + "%%%%Title: %s\n" + "%%%%Creator: paps version 0.1 by Dov Grobgeld\n" + "%%%%Pages: (atend)\n" + "%%%%BeginProlog\n" + "%%%%Orientation: %s\n" + "/papsdict 1 dict def\n" + "papsdict begin\n" + "\n" + "/inch {72 mul} bind def\n" + "/mm {1 inch 25.4 div mul} bind def\n" + "\n" + "%% override setpagedevice if it is not defined\n" + "/setpagedevice where {\n" + " pop %% get rid of its dictionary\n" + " /setpagesize { \n" + " 3 dict begin\n" + " /pageheight exch def \n" + " /pagewidth exch def\n" + " /orientation 0 def\n" + " %% Exchange pagewidth and pageheight so that pagewidth is bigger\n" + " pagewidth pageheight gt { \n" + " pagewidth\n" + " /pagewidth pageheight def\n" + " /pageheight exch def\n" + " /orientation 3 def\n" + " } if\n" + " 2 dict\n" + " dup /PageSize [pagewidth pageheight] put\n" + " dup /Orientation orientation put\n" + " setpagedevice \n" + " end\n" + " } def\n" + "}\n" + "{\n" + " /setpagesize { pop pop } def\n" + "} ifelse\n" + "/duplex {\n" + " statusdict /setduplexmode known \n" + " { statusdict begin setduplexmode end } {pop} ifelse\n" + "} def\n" + "/tumble {\n" + " statusdict /settumble known\n" + " { statusdict begin settumble end } {pop} ifelse\n" + "} def\n" + "%% Turn the page around\n" + "/turnpage {\n" + " 90 rotate\n" + " 0 pageheight neg translate\n" + "} def\n", + title, + orientation_names[orientation] + ); + + fprintf(OUT, + "%% User settings\n" + "/pagewidth %d def\n" + "/pageheight %d def\n" + "/column_width %d def\n" + + "/bodyheight %d def\n" + "/lmarg %d def\n" + + "/ytop %d def\n" + "/do_separation_line %s def\n" + "/do_landscape %s def\n" + + "/do_tumble %s def\n" + "/do_duplex %s def\n", + page_layout->page_width, + page_layout->page_height, + page_layout->column_width, + page_layout->column_height, + page_layout->left_margin, + page_layout->page_height - bodytop, + bool_name[page_layout->do_separation_line>0], + bool_name[page_layout->do_landscape>0], + bool_name[page_layout->do_tumble>0], + bool_name[page_layout->do_duplex>0] + ); + + fprintf(OUT, + "%% Procedures to translate position to first and second column\n" + "/lw 20 def %% whatever\n" + "/setnumcolumns {\n" + " /numcolumns exch def\n" + " /firstcolumn { /xpos lmarg def /ypos ytop def} def\n" + " /nextcolumn { \n" + " do_separation_line {\n" + " xpos column_width add gutter_width 2 div add %% x start\n" + " ytop lw add moveto %% y start\n" + " 0 bodyheight lw add neg rlineto 0 setlinewidth stroke\n" + " } if\n" + " /xpos xpos column_width add gutter_width add def \n" + " /ypos ytop def\n" + " } def\n" + "} def\n" + "\n" + ); + + fprintf(OUT, + "pagewidth pageheight setpagesize\n" + "%d setnumcolumns\n", + page_layout->num_columns); + fprintf(OUT, + "/showline {\n" + " /y exch def\n" + " /s exch def\n" + " xpos y moveto \n" + " column_width 0 rlineto stroke\n" + " xpos y moveto /Helvetica findfont 20 scalefont setfont s show\n" + "} def\n" + ); + + // The following definitions polute the global namespace. All such + // definitions should start with paps_ + fprintf(OUT, + "/paps_bop { %% Beginning of page definitions\n" + " papsdict begin\n" + " gsave\n" + " do_landscape {turnpage} if \n" + " firstcolumn\n" + " end\n" + "} def\n" + "\n" + "/paps_eop { %% End of page cleanups\n" + " grestore \n" + "} def\n"); + +} + +void print_postscript_trailer(FILE *OUT, + int num_pages) +{ + fprintf(OUT, + "%%%%Pages: %d\n" + "%%%%Trailer\n" + "%%%%EOF\n", + num_pages + ); +} + +void eject_column(FILE *OUT, + page_layout_t *page_layout, + int column_idx) +{ + double x_pos, y_top, y_bot, total_gutter; + +#if 0 + fprintf(stderr, "do_separation_line column_idx = %d %d\n", page_layout->do_separation_line, column_idx); +#endif + if (!page_layout->do_separation_line) + return; + + if (page_layout->pango_dir == PANGO_DIRECTION_RTL) + column_idx = (page_layout->num_columns - column_idx); + + if (column_idx == 1) + total_gutter = 1.0 * page_layout->gutter_width /2; + else + total_gutter = (column_idx + 1.5) * page_layout->gutter_width; + + x_pos = page_layout->left_margin + + page_layout->column_width * column_idx + + total_gutter; + + y_top = page_layout->page_height - page_layout->top_margin; + y_bot = page_layout->bottom_margin; + + g_string_append_printf(ps_pages_string, + "%f %f moveto %f %f lineto 0 setlinewidth stroke\n", + x_pos, y_top, + x_pos, y_bot); +} + +void eject_page(FILE *OUT) +{ + g_string_append_printf(ps_pages_string, + "paps_eop\n" + "showpage\n"); +} + +void start_page(FILE *OUT, + int page_idx) +{ + g_string_append_printf(ps_pages_string, + "%%%%Page: %d %d\n" + "paps_bop\n", + page_idx, page_idx); +} + +void +draw_line_to_page(FILE *OUT, + int column_idx, + int column_pos, + page_layout_t *page_layout, + PangoLayoutLine *line) +{ + /* Assume square aspect ratio for now */ + double y_pos = page_layout->page_height + - page_layout->top_margin + - page_layout->header_sep + - column_pos / PANGO_SCALE * page_layout->pixel_to_pt; + double x_pos = page_layout->left_margin + + column_idx * (page_layout->column_width + + page_layout->gutter_width); + gchar *ps_layout; + + PangoRectangle ink_rect, logical_rect; + + /* Do RTL column layout for RTL direction */ + if (page_layout->pango_dir == PANGO_DIRECTION_RTL) + { + x_pos = page_layout->left_margin + + (page_layout->num_columns-1-column_idx) + * (page_layout->column_width + page_layout->gutter_width); + } + + pango_layout_line_get_extents(line, + &ink_rect, + &logical_rect); + + + + + if (page_layout->pango_dir == PANGO_DIRECTION_RTL) { + x_pos += page_layout->column_width - logical_rect.width / (page_layout->pt_to_pixel * PANGO_SCALE); + } + + ps_layout = paps_layout_line_to_postscript_strdup(paps, + x_pos, y_pos, + line); + + g_string_append(ps_pages_string, + ps_layout); + g_free(ps_layout); +} + diff --git a/src/test_libpaps.c b/src/test_libpaps.c new file mode 100644 index 0000000..c293d4b --- /dev/null +++ b/src/test_libpaps.c @@ -0,0 +1,138 @@ +/*====================================================================== +// test-paps.c - Testing the paps library. +// +// Dov Grobgeld <dov.weizmann@weizmann.ac.il> +// Tue Nov 8 21:50:31 2005 +//---------------------------------------------------------------------- +*/ + +#include <pango/pango.h> +#include <pango/pangoft2.h> +#include <stdio.h> +#include "libpaps.h" + +int main(int argc, char*argv[]) +{ + paps_t *paps = paps_new(); + gchar *header, *ps_layout; + PangoContext *pango_context; + PangoFontDescription *font_description; + PangoDirection pango_dir = PANGO_DIRECTION_LTR; + PangoLayout *layout; + gchar *font_family = "sans"; + int font_scale = 14; + GString *ps_text = g_string_new(""); + + pango_context = paps_get_pango_context(); + + /* Setup pango */ + pango_context_set_language (pango_context, pango_language_from_string ("en_US")); + pango_context_set_base_dir (pango_context, pango_dir); + + font_description = pango_font_description_new (); + pango_font_description_set_family (font_description, g_strdup (font_family)); + pango_font_description_set_style (font_description, PANGO_STYLE_NORMAL); + pango_font_description_set_variant (font_description, PANGO_VARIANT_NORMAL); + pango_font_description_set_weight (font_description, PANGO_WEIGHT_NORMAL); + pango_font_description_set_stretch (font_description, PANGO_STRETCH_NORMAL); + pango_font_description_set_size (font_description, font_scale * PANGO_SCALE); + + pango_context_set_font_description (pango_context, font_description); + + // Create a layout and set its properties + layout = pango_layout_new (pango_context); + pango_layout_set_justify (layout, TRUE); + pango_layout_set_width (layout, paps_postscript_points_to_pango(5*72)); + + pango_layout_set_text (layout, + "It was the best of times, it was the worst of times, " + "it was the age of wisdom, it was the age of foolishness, " + "it was the epoch of belief, it was the epoch of incredulity, " + "it was the season of Light, it was the season of Darkness, " + "it was the spring of hope, it was the winter of despair, " + "we had everything before us, we had nothing before us, " + "we were all going direct to Heaven, we were all going direct " + "the other way--in short, the period was so far like the present " + "period, that some of its noisiest authorities insisted on its " + "being received, for good or for evil, in the superlative degree " + "of comparison only. " + "\n\n" + "There were a king with a large jaw and a queen with a plain face, " + "on the throne of England; there were a king with a large jaw and " + "a queen with a fair face, on the throne of France. In both " + "countries it was clearer than crystal to the lords of the State " + "preserves of loaves and fishes, that things in general were " + "settled for ever. " + "\n\n" + "It was the year of Our Lord one thousand seven hundred and " + "seventy-five. Spiritual revelations were conceded to England at " + "that favoured period, as at this. Mrs. Southcott had recently " + "attained her five-and-twentieth blessed birthday, of whom a " + "prophetic private in the Life Guards had heralded the sublime " + "appearance by announcing that arrangements were made for the " + "swallowing up of London and Westminster. Even the Cock-lane " + "ghost had been laid only a round dozen of years, after rapping " + "out its messages, as the spirits of this very year last past " + "(supernaturally deficient in originality) rapped out theirs. " + "Mere messages in the earthly order of events had lately come to " + "the English Crown and People, from a congress of British subjects " + "in America: which, strange to relate, have proved more important " + "to the human race than any communications yet received through " + "any of the chickens of the Cock-lane brood. " + , -1); + + ps_layout = paps_layout_to_postscript_strdup(paps, + 0, 0, + layout); + g_string_append_printf(ps_text, + "gsave\n" + "1 0.8 0.8 setrgbcolor\n" + "72 72 10 mul translate\n" + "3 rotate %s\n" + "grestore\n", + ps_layout); + g_free(ps_layout); + + pango_font_description_set_size (font_description, 25 * PANGO_SCALE); + pango_context_set_font_description (pango_context, font_description); + pango_layout_set_width (layout, paps_postscript_points_to_pango(7*72)); + pango_layout_set_text (layout, + "paps by Dov Grobgeld (\327\223\327\221 \327\222\327\250\327\225\327\221\327\222\327\234\327\223\n" + "Printing through \316\240\316\261\316\275\350\252\236 (Pango)\n" + "\n" + "Arabic \330\247\331\204\330\263\331\204\330\247\330\271\331\204\331\212\331\203\331\205\n" + "Hebrew \327\251\327\201\326\270\327\234\327\225\326\271\327\235\n" + "Greek (\316\225\316\273\316\273\316\267\316\275\316\271\316\272\316\254) \316\223\316\265\316\271\316\254 \317\203\316\261\317\202\n" + "Japanese (\346\227\245\346\234\254\350\252\236) \343\201\223\343\202\223\343\201\253\343\201\241\343\201\257, \357\275\272\357\276\235\357\276\206\357\276\201\357\276\212\n" + "Chinese (\344\270\255\346\226\207, \346\231\256\351\200\232\350\257\235,\346\261\211\350\257\255) \344\275\240\345\245\275\n" + "Vietnamese (Ti\341\272\277ng Vi\341\273\207t) Xin Ch\303\240o\n", + -1 + ); + ps_layout = paps_layout_to_postscript_strdup(paps, + 0, 0, + layout); + g_string_append_printf(ps_text, + "gsave\n" + "0.2 0.2 1.0 setrgbcolor\n" + "100 700 translate\n" + "-10 rotate %s\n" + "grestore\n", + ps_layout); + g_string_append_printf(ps_text, + "gsave\n" + "0 0.5 0.1 setrgbcolor\n" + "500 300 translate\n" + "-5 rotate -0.5 1 scale %s\n" + "grestore\n", + ps_layout); + g_free(ps_layout); + + + header = paps_get_postscript_header_strdup(paps); + printf("%s",header); + g_free(header); + + printf("%s", ps_text->str); + + return 0; +} |