summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordov-g <dov-g>2005-12-20 19:35:22 +0000
committerdov-g <dov-g>2005-12-20 19:35:22 +0000
commit3cd9710852f772065b83eccdc9669b3409d7702f (patch)
tree017b7abaf4e35cf1a3844054a4db098f35b9ff3e
downloadpaps-3cd9710852f772065b83eccdc9669b3409d7702f.tar.gz
paps-3cd9710852f772065b83eccdc9669b3409d7702f.tar.xz
paps-3cd9710852f772065b83eccdc9669b3409d7702f.zip
Initial revision
-rw-r--r--AUTHORS1
-rw-r--r--COPYING.LIB481
-rw-r--r--ChangeLog22
-rw-r--r--Doxyfile275
-rw-r--r--INSTALL167
-rw-r--r--Makefile.am2
-rw-r--r--NEWS0
-rw-r--r--README5
-rw-r--r--TODO4
-rwxr-xr-xautogen.sh37
-rw-r--r--config.h.in55
-rw-r--r--configure.in10
-rw-r--r--doc/Doxyfile227
-rw-r--r--doc/Makefile.am16
-rw-r--r--doc/example-output.pngbin0 -> 95289 bytes
-rw-r--r--doc/mainpage.h170
-rw-r--r--src/Makefile.am26
-rw-r--r--src/libpaps.c640
-rw-r--r--src/libpaps.h110
-rw-r--r--src/paps.c751
-rw-r--r--src/test_libpaps.c138
21 files changed, 3137 insertions, 0 deletions
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..aef3878
--- /dev/null
+++ b/AUTHORS
@@ -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
diff --git a/INSTALL b/INSTALL
new file mode 100644
index 0000000..02a4a07
--- /dev/null
+++ b/INSTALL
@@ -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
+
diff --git a/NEWS b/NEWS
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/NEWS
diff --git a/README b/README
new file mode 100644
index 0000000..7afa54d
--- /dev/null
+++ b/README
@@ -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.
+
diff --git a/TODO b/TODO
new file mode 100644
index 0000000..750296f
--- /dev/null
+++ b/TODO
@@ -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
new file mode 100644
index 0000000..34905fd
--- /dev/null
+++ b/doc/example-output.png
Binary files differ
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;
+}