first commit

This commit is contained in:
2023-10-17 17:51:53 +02:00
commit 9c7f9cfea0
107 changed files with 22995 additions and 0 deletions
+6
View File
@@ -0,0 +1,6 @@
# Enforce LF for Netpbm formats on Windows
testdata/test.pam text eol=lf
testdata/test.pbm text eol=lf
testdata/test.pfm text eol=lf
testdata/test.pgm text eol=lf
testdata/test.ppm text eol=lf
+1
View File
@@ -0,0 +1 @@
Milan Nikolic <gen2brain@gmail.com>
+661
View File
@@ -0,0 +1,661 @@
GNU AFFERO GENERAL PUBLIC LICENSE
Version 3, 19 November 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU Affero General Public License is a free, copyleft license for
software and other kinds of works, specifically designed to ensure
cooperation with the community in the case of network server software.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
our General Public Licenses are intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users.
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
them 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.
Developers that use our General Public Licenses protect your rights
with two steps: (1) assert copyright on the software, and (2) offer
you this License which gives you legal permission to copy, distribute
and/or modify the software.
A secondary benefit of defending all users' freedom is that
improvements made in alternate versions of the program, if they
receive widespread use, become available for other developers to
incorporate. Many developers of free software are heartened and
encouraged by the resulting cooperation. However, in the case of
software used on network servers, this result may fail to come about.
The GNU General Public License permits making a modified version and
letting the public access it on a server without ever releasing its
source code to the public.
The GNU Affero General Public License is designed specifically to
ensure that, in such cases, the modified source code becomes available
to the community. It requires the operator of a network server to
provide the source code of the modified version running there to the
users of that server. Therefore, public use of a modified version, on
a publicly accessible server, gives the public access to the source
code of the modified version.
An older license, called the Affero General Public License and
published by Affero, was designed to accomplish similar goals. This is
a different license, not a version of the Affero GPL, but Affero has
released a new version of the Affero GPL which permits relicensing under
this license.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU Affero General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If 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 convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Remote Network Interaction; Use with the GNU General Public License.
Notwithstanding any other provision of this License, if you modify the
Program, your modified version must prominently offer all users
interacting with it remotely through a computer network (if your version
supports such interaction) an opportunity to receive the Corresponding
Source of your version by providing access to the Corresponding Source
from a network server at no charge, through some standard or customary
means of facilitating copying of software. This Corresponding Source
shall include the Corresponding Source for any work covered by version 3
of the GNU General Public License that is incorporated pursuant to the
following paragraph.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the work with which it is combined will remain governed by version
3 of the GNU General Public License.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU Affero 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
Program specifies that a certain numbered version of the GNU Affero General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU Affero General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU Affero General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "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 PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state 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 program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If your software can interact with users remotely through a computer
network, you should also make sure that it provides a way for users to
get its source. For example, if your program is a web application, its
interface could display a "Source" link that leads users to an archive
of the code. There are many ways you could offer source, and different
solutions will be better for different programs; see section 13 for the
specific requirements.
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU AGPL, see
<http://www.gnu.org/licenses/>.
+71
View File
@@ -0,0 +1,71 @@
## go-fitz
### Maal Disclaimer
This is just fork from github repository. Forked in order to recompile with new glibc version.
Whenever you have problem with compability you can download source package from [Mupdf source](https://mupdf.com/downloads/archive/mupdf-1.23.0-source.tar.gz) after simply run ``` make``` to compile on your platform. When this is completed just simply copy following files:
```libmupdf.a``` ==> ```libs/libmupdfthird_linux_amd64.a```
```libmupdf-third.a``` ==> ```libs/libmupdf_linux_amd64.a```
Part of file name 'linux_amd64' maens OS and platform.
##### Notice that you need to compile MuPdf source for OS and platform you want to use
### ---------------------------------------------------------------------------------------
Go wrapper for [MuPDF](http://mupdf.com/) fitz library that can extract pages from PDF and EPUB documents as images, text, html or svg.
### Build tags
* `extlib` - use external MuPDF library
* `static` - build with static external MuPDF library (used with `extlib`)
* `pkgconfig` - enable pkg-config (used with `extlib`)
* `musl` - use musl compiled library
### Example
```go
package main
import (
"fmt"
"image/jpeg"
"os"
"path/filepath"
"github.com/gen2brain/go-fitz"
)
func main() {
doc, err := fitz.New("test.pdf")
if err != nil {
panic(err)
}
defer doc.Close()
tmpDir, err := os.MkdirTemp(os.TempDir(), "fitz")
if err != nil {
panic(err)
}
// Extract pages as images
for n := 0; n < doc.NumPage(); n++ {
img, err := doc.Image(n)
if err != nil {
panic(err)
}
f, err := os.Create(filepath.Join(tmpDir, fmt.Sprintf("test%03d.jpg", n)))
if err != nil {
panic(err)
}
err = jpeg.Encode(f, img, &jpeg.Options{jpeg.DefaultQuality})
if err != nil {
panic(err)
}
f.Close()
}
}
```
+104
View File
@@ -0,0 +1,104 @@
package fitz_test
import (
"fmt"
"image/jpeg"
"os"
"path/filepath"
"git.ma-al.com/go-fitz"
)
func ExampleNew() {
doc, err := fitz.New("test.pdf")
if err != nil {
panic(err)
}
defer doc.Close()
tmpDir, err := os.MkdirTemp(os.TempDir(), "fitz")
if err != nil {
panic(err)
}
// Extract pages as images
for n := 0; n < doc.NumPage(); n++ {
img, err := doc.Image(n)
if err != nil {
panic(err)
}
f, err := os.Create(filepath.Join(tmpDir, fmt.Sprintf("test%03d.jpg", n)))
if err != nil {
panic(err)
}
err = jpeg.Encode(f, img, &jpeg.Options{Quality: jpeg.DefaultQuality})
if err != nil {
panic(err)
}
f.Close()
}
// Extract pages as text
for n := 0; n < doc.NumPage(); n++ {
text, err := doc.Text(n)
if err != nil {
panic(err)
}
f, err := os.Create(filepath.Join(tmpDir, fmt.Sprintf("test%03d.txt", n)))
if err != nil {
panic(err)
}
_, err = f.WriteString(text)
if err != nil {
panic(err)
}
f.Close()
}
// Extract pages as html
for n := 0; n < doc.NumPage(); n++ {
html, err := doc.HTML(n, true)
if err != nil {
panic(err)
}
f, err := os.Create(filepath.Join(tmpDir, fmt.Sprintf("test%03d.html", n)))
if err != nil {
panic(err)
}
_, err = f.WriteString(html)
if err != nil {
panic(err)
}
f.Close()
}
// Extract pages as svg
for n := 0; n < doc.NumPage(); n++ {
svg, err := doc.SVG(n)
if err != nil {
panic(err)
}
f, err := os.Create(filepath.Join(tmpDir, fmt.Sprintf("test%03d.svg", n)))
if err != nil {
panic(err)
}
_, err = f.WriteString(svg)
if err != nil {
panic(err)
}
f.Close()
}
}
+559
View File
@@ -0,0 +1,559 @@
// Package fitz provides wrapper for the [MuPDF](http://mupdf.com/) fitz library
// that can extract pages from PDF and EPUB documents as images, text, html or svg.
package fitz
/*
#include <mupdf/fitz.h>
#include <stdlib.h>
const char *fz_version = FZ_VERSION;
fz_document *open_document(fz_context *ctx, const char *filename) {
fz_document *doc;
fz_try(ctx) {
doc = fz_open_document(ctx, filename);
}
fz_catch(ctx) {
return NULL;
}
return doc;
}
fz_document *open_document_with_stream(fz_context *ctx, const char *magic, fz_stream *stream) {
fz_document *doc;
fz_try(ctx) {
doc = fz_open_document_with_stream(ctx, magic, stream);
}
fz_catch(ctx) {
return NULL;
}
return doc;
}
*/
import "C"
import (
"errors"
"image"
"io"
"os"
"path/filepath"
"sync"
"unsafe"
)
// Errors.
var (
ErrNoSuchFile = errors.New("fitz: no such file")
ErrCreateContext = errors.New("fitz: cannot create context")
ErrOpenDocument = errors.New("fitz: cannot open document")
ErrOpenMemory = errors.New("fitz: cannot open memory")
ErrPageMissing = errors.New("fitz: page missing")
ErrCreatePixmap = errors.New("fitz: cannot create pixmap")
ErrPixmapSamples = errors.New("fitz: cannot get pixmap samples")
ErrNeedsPassword = errors.New("fitz: document needs password")
ErrLoadOutline = errors.New("fitz: cannot load outline")
)
// Document represents fitz document.
type Document struct {
ctx *C.struct_fz_context
data []byte // binds data to the Document lifecycle avoiding premature GC
doc *C.struct_fz_document
mtx sync.Mutex
stream *C.fz_stream
}
// Outline type.
type Outline struct {
// Hierarchy level of the entry (starting from 1).
Level int
// Title of outline item.
Title string
// Destination in the document to be displayed when this outline item is activated.
URI string
// The page number of an internal link.
Page int
// Top.
Top float64
}
// Link type.
type Link struct {
URI string
}
// New returns new fitz document.
func New(filename string) (f *Document, err error) {
f = &Document{}
filename, err = filepath.Abs(filename)
if err != nil {
return
}
if _, e := os.Stat(filename); e != nil {
err = ErrNoSuchFile
return
}
f.ctx = (*C.struct_fz_context)(unsafe.Pointer(C.fz_new_context_imp(nil, nil, C.FZ_STORE_UNLIMITED, C.fz_version)))
if f.ctx == nil {
err = ErrCreateContext
return
}
C.fz_register_document_handlers(f.ctx)
cfilename := C.CString(filename)
defer C.free(unsafe.Pointer(cfilename))
f.doc = C.open_document(f.ctx, cfilename)
if f.doc == nil {
err = ErrOpenDocument
return
}
ret := C.fz_needs_password(f.ctx, f.doc)
v := int(ret) != 0
if v {
err = ErrNeedsPassword
}
return
}
// NewFromMemory returns new fitz document from byte slice.
func NewFromMemory(b []byte) (f *Document, err error) {
f = &Document{}
f.ctx = (*C.struct_fz_context)(unsafe.Pointer(C.fz_new_context_imp(nil, nil, C.FZ_STORE_UNLIMITED, C.fz_version)))
if f.ctx == nil {
err = ErrCreateContext
return
}
C.fz_register_document_handlers(f.ctx)
stream := C.fz_open_memory(f.ctx, (*C.uchar)(&b[0]), C.size_t(len(b)))
f.stream = C.fz_keep_stream(f.ctx, stream)
if f.stream == nil {
err = ErrOpenMemory
return
}
magic := contentType(b)
if magic == "" {
err = ErrOpenMemory
return
}
f.data = b
cmagic := C.CString(magic)
defer C.free(unsafe.Pointer(cmagic))
f.doc = C.open_document_with_stream(f.ctx, cmagic, f.stream)
if f.doc == nil {
err = ErrOpenDocument
}
ret := C.fz_needs_password(f.ctx, f.doc)
v := int(ret) != 0
if v {
err = ErrNeedsPassword
}
return
}
// NewFromReader returns new fitz document from io.Reader.
func NewFromReader(r io.Reader) (f *Document, err error) {
b, e := io.ReadAll(r)
if e != nil {
err = e
return
}
f, err = NewFromMemory(b)
return
}
// NumPage returns total number of pages in document.
func (f *Document) NumPage() int {
return int(C.fz_count_pages(f.ctx, f.doc))
}
// Image returns image for given page number.
func (f *Document) Image(pageNumber int) (image.Image, error) {
return f.ImageDPI(pageNumber, 300.0)
}
// ImageDPI returns image for given page number and DPI.
func (f *Document) ImageDPI(pageNumber int, dpi float64) (image.Image, error) {
f.mtx.Lock()
defer f.mtx.Unlock()
img := image.RGBA{}
if pageNumber >= f.NumPage() {
return nil, ErrPageMissing
}
page := C.fz_load_page(f.ctx, f.doc, C.int(pageNumber))
defer C.fz_drop_page(f.ctx, page)
var bounds C.fz_rect
bounds = C.fz_bound_page(f.ctx, page)
var ctm C.fz_matrix
ctm = C.fz_scale(C.float(dpi/72), C.float(dpi/72))
var bbox C.fz_irect
bounds = C.fz_transform_rect(bounds, ctm)
bbox = C.fz_round_rect(bounds)
pixmap := C.fz_new_pixmap_with_bbox(f.ctx, C.fz_device_rgb(f.ctx), bbox, nil, 1)
if pixmap == nil {
return nil, ErrCreatePixmap
}
C.fz_clear_pixmap_with_value(f.ctx, pixmap, C.int(0xff))
//defer C.fz_drop_pixmap(f.ctx, pixmap)
device := C.fz_new_draw_device(f.ctx, ctm, pixmap)
C.fz_enable_device_hints(f.ctx, device, C.FZ_NO_CACHE)
defer C.fz_drop_device(f.ctx, device)
drawMatrix := C.fz_identity
C.fz_run_page(f.ctx, page, device, drawMatrix, nil)
C.fz_close_device(f.ctx, device)
pixels := C.fz_pixmap_samples(f.ctx, pixmap)
if pixels == nil {
return nil, ErrPixmapSamples
}
defer C.free(unsafe.Pointer(pixels))
img.Pix = C.GoBytes(unsafe.Pointer(pixels), C.int(4*bbox.x1*bbox.y1))
img.Rect = image.Rect(int(bbox.x0), int(bbox.y0), int(bbox.x1), int(bbox.y1))
img.Stride = 4 * img.Rect.Max.X
return &img, nil
}
// ImagePNG returns image for given page number as PNG bytes.
func (f *Document) ImagePNG(pageNumber int, dpi float64) ([]byte, error) {
f.mtx.Lock()
defer f.mtx.Unlock()
if pageNumber >= f.NumPage() {
return nil, ErrPageMissing
}
page := C.fz_load_page(f.ctx, f.doc, C.int(pageNumber))
defer C.fz_drop_page(f.ctx, page)
var bounds C.fz_rect
bounds = C.fz_bound_page(f.ctx, page)
var ctm C.fz_matrix
ctm = C.fz_scale(C.float(dpi/72), C.float(dpi/72))
var bbox C.fz_irect
bounds = C.fz_transform_rect(bounds, ctm)
bbox = C.fz_round_rect(bounds)
pixmap := C.fz_new_pixmap_with_bbox(f.ctx, C.fz_device_rgb(f.ctx), bbox, nil, 1)
if pixmap == nil {
return nil, ErrCreatePixmap
}
C.fz_clear_pixmap_with_value(f.ctx, pixmap, C.int(0xff))
//defer C.fz_drop_pixmap(f.ctx, pixmap)
device := C.fz_new_draw_device(f.ctx, ctm, pixmap)
C.fz_enable_device_hints(f.ctx, device, C.FZ_NO_CACHE)
defer C.fz_drop_device(f.ctx, device)
drawMatrix := C.fz_identity
C.fz_run_page(f.ctx, page, device, drawMatrix, nil)
C.fz_close_device(f.ctx, device)
buf := C.fz_new_buffer_from_pixmap_as_png(f.ctx, pixmap, C.fz_default_color_params)
defer C.fz_drop_buffer(f.ctx, buf)
size := C.fz_buffer_storage(f.ctx, buf, nil)
str := C.GoStringN(C.fz_string_from_buffer(f.ctx, buf), C.int(size))
return []byte(str), nil
}
// Links returns slice of links for given page number.
func (f *Document) Links(pageNumber int) ([]Link, error) {
f.mtx.Lock()
defer f.mtx.Unlock()
if pageNumber >= f.NumPage() {
return nil, ErrPageMissing
}
page := C.fz_load_page(f.ctx, f.doc, C.int(pageNumber))
defer C.fz_drop_page(f.ctx, page)
links := C.fz_load_links(f.ctx, page)
defer C.fz_drop_link(f.ctx, links)
linkCount := 0
for currLink := links; currLink != nil; currLink = currLink.next {
linkCount++
}
if linkCount == 0 {
return nil, nil
}
gLinks := make([]Link, linkCount)
currLink := links
for i := 0; i < linkCount; i++ {
gLinks[i] = Link{
URI: C.GoString(currLink.uri),
}
currLink = currLink.next
}
return gLinks, nil
}
// Text returns text for given page number.
func (f *Document) Text(pageNumber int) (string, error) {
f.mtx.Lock()
defer f.mtx.Unlock()
if pageNumber >= f.NumPage() {
return "", ErrPageMissing
}
page := C.fz_load_page(f.ctx, f.doc, C.int(pageNumber))
defer C.fz_drop_page(f.ctx, page)
var bounds C.fz_rect
bounds = C.fz_bound_page(f.ctx, page)
var ctm C.fz_matrix
ctm = C.fz_scale(C.float(72.0/72), C.float(72.0/72))
text := C.fz_new_stext_page(f.ctx, bounds)
defer C.fz_drop_stext_page(f.ctx, text)
var opts C.fz_stext_options
opts.flags = 0
device := C.fz_new_stext_device(f.ctx, text, &opts)
C.fz_enable_device_hints(f.ctx, device, C.FZ_NO_CACHE)
defer C.fz_drop_device(f.ctx, device)
var cookie C.fz_cookie
C.fz_run_page(f.ctx, page, device, ctm, &cookie)
C.fz_close_device(f.ctx, device)
buf := C.fz_new_buffer_from_stext_page(f.ctx, text)
defer C.fz_drop_buffer(f.ctx, buf)
str := C.GoString(C.fz_string_from_buffer(f.ctx, buf))
return str, nil
}
// HTML returns html for given page number.
func (f *Document) HTML(pageNumber int, header bool) (string, error) {
f.mtx.Lock()
defer f.mtx.Unlock()
if pageNumber >= f.NumPage() {
return "", ErrPageMissing
}
page := C.fz_load_page(f.ctx, f.doc, C.int(pageNumber))
defer C.fz_drop_page(f.ctx, page)
var bounds C.fz_rect
bounds = C.fz_bound_page(f.ctx, page)
var ctm C.fz_matrix
ctm = C.fz_scale(C.float(72.0/72), C.float(72.0/72))
text := C.fz_new_stext_page(f.ctx, bounds)
defer C.fz_drop_stext_page(f.ctx, text)
var opts C.fz_stext_options
opts.flags = C.FZ_STEXT_PRESERVE_IMAGES
device := C.fz_new_stext_device(f.ctx, text, &opts)
C.fz_enable_device_hints(f.ctx, device, C.FZ_NO_CACHE)
defer C.fz_drop_device(f.ctx, device)
var cookie C.fz_cookie
C.fz_run_page(f.ctx, page, device, ctm, &cookie)
C.fz_close_device(f.ctx, device)
buf := C.fz_new_buffer(f.ctx, 1024)
defer C.fz_drop_buffer(f.ctx, buf)
out := C.fz_new_output_with_buffer(f.ctx, buf)
defer C.fz_drop_output(f.ctx, out)
if header {
C.fz_print_stext_header_as_html(f.ctx, out)
}
C.fz_print_stext_page_as_html(f.ctx, out, text, C.int(pageNumber))
if header {
C.fz_print_stext_trailer_as_html(f.ctx, out)
}
str := C.GoString(C.fz_string_from_buffer(f.ctx, buf))
return str, nil
}
// SVG returns svg document for given page number.
func (f *Document) SVG(pageNumber int) (string, error) {
f.mtx.Lock()
defer f.mtx.Unlock()
if pageNumber >= f.NumPage() {
return "", ErrPageMissing
}
page := C.fz_load_page(f.ctx, f.doc, C.int(pageNumber))
defer C.fz_drop_page(f.ctx, page)
var bounds C.fz_rect
bounds = C.fz_bound_page(f.ctx, page)
var ctm C.fz_matrix
ctm = C.fz_scale(C.float(72.0/72), C.float(72.0/72))
bounds = C.fz_transform_rect(bounds, ctm)
buf := C.fz_new_buffer(f.ctx, 1024)
defer C.fz_drop_buffer(f.ctx, buf)
out := C.fz_new_output_with_buffer(f.ctx, buf)
defer C.fz_drop_output(f.ctx, out)
device := C.fz_new_svg_device(f.ctx, out, bounds.x1-bounds.x0, bounds.y1-bounds.y0, C.FZ_SVG_TEXT_AS_PATH, 1)
C.fz_enable_device_hints(f.ctx, device, C.FZ_NO_CACHE)
defer C.fz_drop_device(f.ctx, device)
var cookie C.fz_cookie
C.fz_run_page(f.ctx, page, device, ctm, &cookie)
C.fz_close_device(f.ctx, device)
str := C.GoString(C.fz_string_from_buffer(f.ctx, buf))
return str, nil
}
// ToC returns the table of contents (also known as outline).
func (f *Document) ToC() ([]Outline, error) {
data := make([]Outline, 0)
outline := C.fz_load_outline(f.ctx, f.doc)
if outline == nil {
return nil, ErrLoadOutline
}
defer C.fz_drop_outline(f.ctx, outline)
var walk func(outline *C.fz_outline, level int)
walk = func(outline *C.fz_outline, level int) {
for outline != nil {
res := Outline{}
res.Level = level
res.Title = C.GoString(outline.title)
res.URI = C.GoString(outline.uri)
res.Page = int(outline.page.page)
res.Top = float64(outline.y)
data = append(data, res)
if outline.down != nil {
walk(outline.down, level+1)
}
outline = outline.next
}
}
walk(outline, 1)
return data, nil
}
// Metadata returns the map with standard metadata.
func (f *Document) Metadata() map[string]string {
data := make(map[string]string)
lookup := func(key string) string {
ckey := C.CString(key)
defer C.free(unsafe.Pointer(ckey))
buf := make([]byte, 256)
C.fz_lookup_metadata(f.ctx, f.doc, ckey, (*C.char)(unsafe.Pointer(&buf[0])), C.int(len(buf)))
return string(buf)
}
data["format"] = lookup("format")
data["encryption"] = lookup("encryption")
data["title"] = lookup("info:Title")
data["author"] = lookup("info:Author")
data["subject"] = lookup("info:Subject")
data["keywords"] = lookup("info:Keywords")
data["creator"] = lookup("info:Creator")
data["producer"] = lookup("info:Producer")
data["creationDate"] = lookup("info:CreationDate")
data["modDate"] = lookup("info:modDate")
return data
}
// Bound gives the Bounds of a given Page in the document.
func (f *Document) Bound(pageNumber int) (image.Rectangle, error) {
f.mtx.Lock()
defer f.mtx.Unlock()
if pageNumber >= f.NumPage() {
return image.Rectangle{}, ErrPageMissing
}
page := C.fz_load_page(f.ctx, f.doc, C.int(pageNumber))
defer C.fz_drop_page(f.ctx, page)
var bounds C.fz_rect
bounds = C.fz_bound_page(f.ctx, page)
return image.Rect(int(bounds.x0), int(bounds.y0), int(bounds.x1), int(bounds.y1)), nil
}
// Close closes the underlying fitz document.
func (f *Document) Close() error {
if f.stream != nil {
C.fz_drop_stream(f.ctx, f.stream)
}
C.fz_drop_document(f.ctx, f.doc)
C.fz_drop_context(f.ctx)
f.data = nil
return nil
}
+21
View File
@@ -0,0 +1,21 @@
//go:build !extlib
package fitz
/*
#cgo CFLAGS: -Iinclude
#cgo linux,386 LDFLAGS: -L${SRCDIR}/libs -lmupdf_linux_386 -lmupdfthird_linux_386 -lm
#cgo linux,amd64,!musl LDFLAGS: -L${SRCDIR}/libs -lmupdf_linux_amd64 -lmupdfthird_linux_amd64 -lm
#cgo linux,amd64,musl LDFLAGS: -L${SRCDIR}/libs -lmupdf_linux_amd64_musl -lmupdfthird_linux_amd64_musl -lm
#cgo linux,!android,arm LDFLAGS: -L${SRCDIR}/libs -lmupdf_linux_arm -lmupdfthird_linux_arm -lm
#cgo linux,!android,arm64,!musl LDFLAGS: -L${SRCDIR}/libs -lmupdf_linux_arm64 -lmupdfthird_linux_arm64 -lm
#cgo linux,!android,arm64,musl LDFLAGS: -L${SRCDIR}/libs -lmupdf_linux_arm64_musl -lmupdfthird_linux_arm64_musl -lm
#cgo android,arm LDFLAGS: -L${SRCDIR}/libs -lmupdf_android_arm -lmupdfthird_android_arm -lm -llog
#cgo android,arm64 LDFLAGS: -L${SRCDIR}/libs -lmupdf_android_arm64 -lmupdfthird_android_arm64 -lm -llog
#cgo windows,386 LDFLAGS: -L${SRCDIR}/libs -lmupdf_windows_386 -lmupdfthird_windows_386 -lm -lcomdlg32 -lgdi32 -lmsvcr90 -Wl,--allow-multiple-definition
#cgo windows,amd64 LDFLAGS: -L${SRCDIR}/libs -lmupdf_windows_amd64 -lmupdfthird_windows_amd64 -lm -lcomdlg32 -lgdi32 -Wl,--allow-multiple-definition
#cgo darwin,amd64 LDFLAGS: -L${SRCDIR}/libs -lmupdf_darwin_amd64 -lmupdfthird_darwin_amd64 -lm
#cgo darwin,arm64 LDFLAGS: -L${SRCDIR}/libs -lmupdf_darwin_arm64 -lmupdfthird_darwin_arm64 -lm
*/
import "C"
+11
View File
@@ -0,0 +1,11 @@
//go:build extlib && !pkgconfig
package fitz
/*
#cgo !static LDFLAGS: -lmupdf -lm
#cgo static LDFLAGS: -lmupdf -lm -lmupdf-third
#cgo android LDFLAGS: -llog
#cgo windows LDFLAGS: -lcomdlg32 -lgdi32
*/
import "C"
+8
View File
@@ -0,0 +1,8 @@
//go:build extlib && pkgconfig
package fitz
/*
#cgo pkg-config: mupdf
*/
import "C"
+171
View File
@@ -0,0 +1,171 @@
package fitz
// contentType returns document MIME type.
func contentType(b []byte) string {
l := len(b)
// for file length shortcuts see https://github.com/mathiasbynens/small
switch {
case l < 8:
return ""
case isPAM(b):
return "image/x-portable-arbitrarymap"
case isPBM(b):
return "image/x-portable-bitmap"
case isPFM(b):
return "image/x-portable-floatmap"
case isPGM(b):
return "image/x-portable-greymap"
case isPPM(b):
return "image/x-portable-pixmap"
case isGIF(b):
return "image/gif"
case l < 16:
return ""
case isBMP(b):
return "image/bmp"
case isJBIG2(b):
// file header + segment header = 24 bytes
return "image/x-jb2"
case l < 32:
return ""
case isTIFF(b):
return "image/tiff"
case l < 64:
return ""
case isJPEG(b):
return "image/jpeg"
case isPNG(b):
return "image/png"
case isJPEG2000(b):
return "image/jp2"
case isJPEGXR(b):
return "image/vnd.ms-photo"
case isPDF(b):
return "application/pdf"
case isZIP(b):
switch {
case isEPUB(b):
return "application/epub+zip"
case isXPS(b):
return "application/oxps"
default:
// fitz will consider it a Comic Book Archive
// must contain at least one image, i.e. >64 bytes
return "application/zip"
}
case isXML(b):
// fitz will consider it an FB2
// minimal valid FB2 w/o content is >64 bytes
return "text/xml"
default:
return ""
}
}
func isBMP(b []byte) bool {
return b[0] == 0x42 && b[1] == 0x4D
}
func isGIF(b []byte) bool {
return b[0] == 0x47 && b[1] == 0x49 && b[2] == 0x46 && b[3] == 0x38
}
func isJBIG2(b []byte) bool {
return b[0] == 0x97 && b[1] == 0x4A && b[2] == 0x42 && b[3] == 0x32 &&
b[4] == 0x0D && b[5] == 0x0A && b[6] == 0x1A && b[7] == 0x0A
}
func isJPEG(b []byte) bool {
return b[0] == 0xFF && b[1] == 0xD8 && b[2] == 0xFF
}
func isJPEG2000(b []byte) bool {
switch {
case b[0] == 0xFF && b[1] == 0x4F && b[2] == 0xFF && b[3] == 0x51:
return true
default:
return b[0] == 0x00 && b[1] == 0x00 && b[2] == 0x00 && b[3] == 0x0C &&
b[4] == 0x6A && b[5] == 0x50 && b[6] == 0x20 && b[7] == 0x20 &&
b[8] == 0x0D && b[9] == 0x0A && b[10] == 0x87 && b[11] == 0x0A
}
}
func isJPEGXR(b []byte) bool {
return b[0] == 0x49 && b[1] == 0x49 && b[2] == 0xBC
}
func isPAM(b []byte) bool {
return b[0] == 0x50 && b[1] == 0x37 && b[2] == 0x0A
}
func isPBM(b []byte) bool {
return b[0] == 0x50 && (b[1] == 0x31 || b[1] == 0x34) && b[2] == 0x0A
}
func isPFM(b []byte) bool {
return b[0] == 0x50 && (b[1] == 0x46 || b[1] == 0x66) && b[2] == 0x0A
}
func isPGM(b []byte) bool {
return b[0] == 0x50 && (b[1] == 0x32 || b[1] == 0x35) && b[2] == 0x0A
}
func isPPM(b []byte) bool {
return b[0] == 0x50 && (b[1] == 0x33 || b[1] == 0x36) && b[2] == 0x0A
}
func isPNG(b []byte) bool {
return b[0] == 0x89 && b[1] == 0x50 && b[2] == 0x4E && b[3] == 0x47 &&
b[4] == 0x0D && b[5] == 0x0A && b[6] == 0x1A && b[7] == 0x0A
}
func isTIFF(b []byte) bool {
return b[0] == 0x49 && b[1] == 0x49 && b[2] == 0x2A && b[3] == 0x00 ||
b[0] == 0x4D && b[1] == 0x4D && b[2] == 0x00 && b[3] == 0x2A
}
// PDF magic number 25 50 44 46 = "%PDF".
func isPDF(b []byte) bool {
return b[0] == 0x25 && b[1] == 0x50 && b[2] == 0x44 && b[3] == 0x46
}
// Non-empty ZIP archive magic number 50 4B 03 04.
func isZIP(b []byte) bool {
return b[0] == 0x50 && b[1] == 0x4B && b[2] == 0x03 && b[3] == 0x04
}
// Looks for a file named "mimetype" containing the ASCII string "application/epub+zip".
// The file must be uncompressed and be the first file within the archive.
func isEPUB(b []byte) bool {
return b[30] == 0x6D && b[31] == 0x69 && b[32] == 0x6D && b[33] == 0x65 &&
b[34] == 0x74 && b[35] == 0x79 && b[36] == 0x70 && b[37] == 0x65 &&
b[38] == 0x61 && b[39] == 0x70 && b[40] == 0x70 && b[41] == 0x6C &&
b[42] == 0x69 && b[43] == 0x63 && b[44] == 0x61 && b[45] == 0x74 &&
b[46] == 0x69 && b[47] == 0x6F && b[48] == 0x6E && b[49] == 0x2F &&
b[50] == 0x65 && b[51] == 0x70 && b[52] == 0x75 && b[53] == 0x62 &&
b[54] == 0x2B && b[55] == 0x7A && b[56] == 0x69 && b[57] == 0x70
}
// Looks for a file named "[Content_Types].xml" at the root of a ZIP archive.
// MS Office apps put this file first within the archive enabling for fast detection.
func isXPS(b []byte) bool {
return b[30] == 0x5B && b[31] == 0x43 && b[32] == 0x6F && b[33] == 0x6E &&
b[34] == 0x74 && b[35] == 0x65 && b[36] == 0x6E && b[37] == 0x74 &&
b[38] == 0x5F && b[39] == 0x54 && b[40] == 0x79 && b[41] == 0x70 &&
b[42] == 0x65 && b[43] == 0x73 && b[44] == 0x5D && b[45] == 0x2E &&
b[46] == 0x78 && b[47] == 0x6D && b[48] == 0x6C
}
// Checks for "<?xml" string at the beginning of the file.
// Possible occurrences of a UTF-8 BOM are also considered.
func isXML(b []byte) bool {
switch {
// w/o UTF-8 BOM:
case b[0] == 0x3C && b[1] == 0x3F && b[2] == 0x78 && b[3] == 0x6D && b[4] == 0x6C:
return true
// w/ UTF-8 BOM:
default:
return b[0] == 0xEF && b[1] == 0xBB && b[2] == 0xBF && b[3] == 0x3C &&
b[4] == 0x3F && b[5] == 0x78 && b[6] == 0x6D && b[7] == 0x6C
}
}
+131
View File
@@ -0,0 +1,131 @@
package fitz
import (
_ "embed"
"testing"
)
func testContentType(want string, b []byte, t *testing.T) {
if got := contentType(b); got != want {
t.Errorf("contentType([]byte) = '%v'; want '%v'", got, want)
}
}
//go:embed testdata/test.bmp
var bmp []byte
func TestContentTypeBMP(t *testing.T) {
testContentType("image/bmp", bmp, t)
}
//go:embed testdata/test.epub
var epub []byte
func TestContentTypeEPUB(t *testing.T) {
testContentType("application/epub+zip", epub, t)
}
//go:embed testdata/test.cbz
var cbz []byte
func TestContentTypeCBZ(t *testing.T) {
testContentType("application/zip", cbz, t)
}
//go:embed testdata/test.fb2
var fb2 []byte
func TestContentTypeFB2(t *testing.T) {
testContentType("text/xml", fb2, t)
}
//go:embed testdata/test.gif
var gif []byte
func TestContentTypeGIF(t *testing.T) {
testContentType("image/gif", gif, t)
}
//go:embed testdata/test.jb2
var jb2 []byte
func TestContentTypeJBIG2(t *testing.T) {
testContentType("image/x-jb2", jb2, t)
}
//go:embed testdata/test.jpg
var jpg []byte
func TestContentTypeJPEG(t *testing.T) {
testContentType("image/jpeg", jpg, t)
}
//go:embed testdata/test.jp2
var jp2 []byte
func TestContentTypeJPEG2000(t *testing.T) {
testContentType("image/jp2", jp2, t)
}
//go:embed testdata/test.jxr
var jxr []byte
func TestContentTypeJPEGXR(t *testing.T) {
testContentType("image/vnd.ms-photo", jxr, t)
}
//go:embed testdata/test.pam
var pam []byte
func TestContentTypePAM(t *testing.T) {
testContentType("image/x-portable-arbitrarymap", pam, t)
}
//go:embed testdata/test.pbm
var pbm []byte
func TestContentTypePBM(t *testing.T) {
testContentType("image/x-portable-bitmap", pbm, t)
}
//go:embed testdata/test.pdf
var pdf []byte
func TestContentTypePDF(t *testing.T) {
testContentType("application/pdf", pdf, t)
}
//go:embed testdata/test.pfm
var pfm []byte
func TestContentTypePFM(t *testing.T) {
testContentType("image/x-portable-floatmap", pfm, t)
}
//go:embed testdata/test.pgm
var pgm []byte
func TestContentTypePGM(t *testing.T) {
testContentType("image/x-portable-greymap", pgm, t)
}
//go:embed testdata/test.ppm
var ppm []byte
func TestContentTypePPM(t *testing.T) {
testContentType("image/x-portable-pixmap", ppm, t)
}
//go:embed testdata/test.tif
var tif []byte
func TestContentTypeTIFF(t *testing.T) {
testContentType("image/tiff", tif, t)
}
//go:embed testdata/test.xps
var xps []byte
func TestContentTypeXPS(t *testing.T) {
testContentType("application/oxps", xps, t)
}
+260
View File
@@ -0,0 +1,260 @@
package fitz_test
import (
"fmt"
"image"
"image/jpeg"
"io/ioutil"
"os"
"path/filepath"
"testing"
"git.ma-al.com/go-fitz"
)
func TestImage(t *testing.T) {
doc, err := fitz.New(filepath.Join("testdata", "test.pdf"))
if err != nil {
t.Error(err)
}
defer doc.Close()
tmpDir, err := os.MkdirTemp(os.TempDir(), "fitz")
if err != nil {
t.Error(err)
}
for n := 0; n < doc.NumPage(); n++ {
img, err := doc.Image(n)
if err != nil {
t.Error(err)
}
f, err := os.Create(filepath.Join(tmpDir, fmt.Sprintf("test%03d.jpg", n)))
if err != nil {
t.Error(err)
}
err = jpeg.Encode(f, img, &jpeg.Options{Quality: jpeg.DefaultQuality})
if err != nil {
t.Error(err)
}
f.Close()
}
}
func TestImageFromMemory(t *testing.T) {
b, err := os.ReadFile(filepath.Join("testdata", "test.pdf"))
if err != nil {
t.Error(err)
}
doc, err := fitz.NewFromMemory(b)
if err != nil {
t.Error(err)
}
defer doc.Close()
tmpDir, err := os.MkdirTemp(os.TempDir(), "fitz")
if err != nil {
t.Error(err)
}
defer os.RemoveAll(tmpDir)
for n := 0; n < doc.NumPage(); n++ {
img, err := doc.Image(n)
if err != nil {
t.Error(err)
}
f, err := os.Create(filepath.Join(tmpDir, fmt.Sprintf("test%03d.jpg", n)))
if err != nil {
t.Error(err)
}
err = jpeg.Encode(f, img, &jpeg.Options{Quality: jpeg.DefaultQuality})
if err != nil {
t.Error(err)
}
f.Close()
}
}
func TestLinks(t *testing.T) {
doc, err := fitz.New(filepath.Join("testdata", "test.pdf"))
if err != nil {
t.Error(err)
}
defer doc.Close()
links, err := doc.Links(2)
if err != nil {
t.Error(err)
}
if len(links) != 1 {
t.Error("expected 1 link, got", len(links))
}
if links[0].URI != "https://creativecommons.org/licenses/by-nc-sa/4.0/" {
t.Error("expected empty URI, got", links[0].URI)
}
}
func TestText(t *testing.T) {
doc, err := fitz.New(filepath.Join("testdata", "test.pdf"))
if err != nil {
t.Error(err)
}
defer doc.Close()
tmpDir, err := os.MkdirTemp(os.TempDir(), "fitz")
if err != nil {
t.Error(err)
}
for n := 0; n < doc.NumPage(); n++ {
text, err := doc.Text(n)
if err != nil {
t.Error(err)
}
f, err := os.Create(filepath.Join(tmpDir, fmt.Sprintf("test%03d.txt", n)))
if err != nil {
t.Error(err)
}
_, err = f.WriteString(text)
if err != nil {
t.Error(err)
}
f.Close()
}
}
func TestHTML(t *testing.T) {
doc, err := fitz.New(filepath.Join("testdata", "test.pdf"))
if err != nil {
t.Error(err)
}
defer doc.Close()
tmpDir, err := ioutil.TempDir(os.TempDir(), "fitz")
if err != nil {
t.Error(err)
}
for n := 0; n < doc.NumPage(); n++ {
html, err := doc.HTML(n, true)
if err != nil {
t.Error(err)
}
f, err := os.Create(filepath.Join(tmpDir, fmt.Sprintf("test%03d.html", n)))
if err != nil {
t.Error(err)
}
_, err = f.WriteString(html)
if err != nil {
t.Error(err)
}
f.Close()
}
}
func TestSVG(t *testing.T) {
doc, err := fitz.New(filepath.Join("testdata", "test.pdf"))
if err != nil {
t.Error(err)
}
defer doc.Close()
tmpDir, err := ioutil.TempDir(os.TempDir(), "fitz")
if err != nil {
t.Error(err)
}
for n := 0; n < doc.NumPage(); n++ {
svg, err := doc.SVG(n)
if err != nil {
t.Error(err)
}
f, err := os.Create(filepath.Join(tmpDir, fmt.Sprintf("test%03d.svg", n)))
if err != nil {
t.Error(err)
}
_, err = f.WriteString(svg)
if err != nil {
t.Error(err)
}
f.Close()
}
}
func TestToC(t *testing.T) {
doc, err := fitz.New(filepath.Join("testdata", "test.pdf"))
if err != nil {
t.Error(err)
}
defer doc.Close()
_, err = doc.ToC()
if err != nil {
t.Error(err)
}
}
func TestMetadata(t *testing.T) {
doc, err := fitz.New(filepath.Join("testdata", "test.pdf"))
if err != nil {
t.Error(err)
}
defer doc.Close()
meta := doc.Metadata()
if len(meta) == 0 {
t.Error(fmt.Errorf("metadata is empty"))
}
}
func TestBound(t *testing.T) {
doc, err := fitz.New(filepath.Join("testdata", "test.pdf"))
if err != nil {
t.Error(err)
}
defer doc.Close()
expected := image.Rect(0, 0, 612, 792)
for i := 0; i < doc.NumPage(); i++ {
bound, err := doc.Bound(i)
if err != nil {
t.Error(err)
}
if bound != expected {
t.Error(fmt.Errorf("bounds didn't match go %v when expedient %v", bound, expected))
}
}
_, err = doc.Bound(doc.NumPage())
if err != fitz.ErrPageMissing {
t.Error(fmt.Errorf("ErrPageMissing not returned got %v", err))
}
}
+3
View File
@@ -0,0 +1,3 @@
module git.ma-al.com/go-fitz
go 1.20
View File
+95
View File
@@ -0,0 +1,95 @@
// Copyright (C) 2004-2021 Artifex Software, Inc.
//
// This file is part of MuPDF.
//
// MuPDF is free software: you can redistribute it and/or modify it under the
// terms of the GNU Affero General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option)
// any later version.
//
// MuPDF 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 Affero General Public License for more
// details.
//
// You should have received a copy of the GNU Affero General Public License
// along with MuPDF. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html>
//
// Alternative licensing terms are available from the licensor.
// For commercial licensing, see <https://www.artifex.com/> or contact
// Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,
// CA 94129, USA, for further information.
#ifndef MUDPF_FITZ_H
#define MUDPF_FITZ_H
#ifdef __cplusplus
extern "C" {
#endif
#include "mupdf/fitz/version.h"
#include "mupdf/fitz/config.h"
#include "mupdf/fitz/system.h"
#include "mupdf/fitz/context.h"
#include "mupdf/fitz/output.h"
#include "mupdf/fitz/log.h"
#include "mupdf/fitz/crypt.h"
#include "mupdf/fitz/getopt.h"
#include "mupdf/fitz/geometry.h"
#include "mupdf/fitz/hash.h"
#include "mupdf/fitz/pool.h"
#include "mupdf/fitz/string-util.h"
#include "mupdf/fitz/tree.h"
#include "mupdf/fitz/bidi.h"
#include "mupdf/fitz/xml.h"
/* I/O */
#include "mupdf/fitz/buffer.h"
#include "mupdf/fitz/stream.h"
#include "mupdf/fitz/compress.h"
#include "mupdf/fitz/compressed-buffer.h"
#include "mupdf/fitz/filter.h"
#include "mupdf/fitz/archive.h"
/* Resources */
#include "mupdf/fitz/store.h"
#include "mupdf/fitz/color.h"
#include "mupdf/fitz/pixmap.h"
#include "mupdf/fitz/bitmap.h"
#include "mupdf/fitz/image.h"
#include "mupdf/fitz/shade.h"
#include "mupdf/fitz/font.h"
#include "mupdf/fitz/path.h"
#include "mupdf/fitz/text.h"
#include "mupdf/fitz/separation.h"
#include "mupdf/fitz/glyph.h"
#include "mupdf/fitz/device.h"
#include "mupdf/fitz/display-list.h"
#include "mupdf/fitz/structured-text.h"
#include "mupdf/fitz/transition.h"
#include "mupdf/fitz/glyph-cache.h"
/* Document */
#include "mupdf/fitz/link.h"
#include "mupdf/fitz/outline.h"
#include "mupdf/fitz/document.h"
#include "mupdf/fitz/util.h"
/* Output formats */
#include "mupdf/fitz/writer.h"
#include "mupdf/fitz/band-writer.h"
#include "mupdf/fitz/write-pixmap.h"
#include "mupdf/fitz/output-svg.h"
#include "mupdf/fitz/story.h"
#include "mupdf/fitz/story-writer.h"
#ifdef __cplusplus
}
#endif
#endif
+373
View File
@@ -0,0 +1,373 @@
// Copyright (C) 2004-2022 Artifex Software, Inc.
//
// This file is part of MuPDF.
//
// MuPDF is free software: you can redistribute it and/or modify it under the
// terms of the GNU Affero General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option)
// any later version.
//
// MuPDF 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 Affero General Public License for more
// details.
//
// You should have received a copy of the GNU Affero General Public License
// along with MuPDF. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html>
//
// Alternative licensing terms are available from the licensor.
// For commercial licensing, see <https://www.artifex.com/> or contact
// Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,
// CA 94129, USA, for further information.
#ifndef MUPDF_FITZ_ARCHIVE_H
#define MUPDF_FITZ_ARCHIVE_H
#include "mupdf/fitz/system.h"
#include "mupdf/fitz/context.h"
#include "mupdf/fitz/buffer.h"
#include "mupdf/fitz/stream.h"
#include "mupdf/fitz/tree.h"
/* PUBLIC API */
/**
fz_archive:
fz_archive provides methods for accessing "archive" files.
An archive file is a conceptual entity that contains multiple
files, which can be counted, enumerated, and read.
Implementations of fz_archive based upon directories, zip
and tar files are included.
*/
typedef struct fz_archive fz_archive;
/**
Open a zip or tar archive
Open a file and identify its archive type based on the archive
signature contained inside.
filename: a path to a file as it would be given to open(2).
*/
fz_archive *fz_open_archive(fz_context *ctx, const char *filename);
/**
Open zip or tar archive stream.
Open an archive using a seekable stream object rather than
opening a file or directory on disk.
*/
fz_archive *fz_open_archive_with_stream(fz_context *ctx, fz_stream *file);
/**
Open zip or tar archive stream.
Does the same as fz_open_archive_with_stream, but will not throw
an error in the event of failing to recognise the format. Will
still throw errors in other cases though!
*/
fz_archive *fz_try_open_archive_with_stream(fz_context *ctx, fz_stream *file);
/**
Open a directory as if it was an archive.
A special case where a directory is opened as if it was an
archive.
Note that for directories it is not possible to retrieve the
number of entries or list the entries. It is however possible
to check if the archive has a particular entry.
path: a path to a directory as it would be given to opendir(3).
*/
fz_archive *fz_open_directory(fz_context *ctx, const char *path);
/**
Determine if a given path is a directory.
*/
int fz_is_directory(fz_context *ctx, const char *path);
/**
Drop a reference to an archive.
When the last reference is dropped, this closes and releases
any memory or filehandles associated with the archive.
*/
void fz_drop_archive(fz_context *ctx, fz_archive *arch);
/**
Keep a reference to an archive.
*/
fz_archive *
fz_keep_archive(fz_context *ctx, fz_archive *arch);
/**
Return a pointer to a string describing the format of the
archive.
The lifetime of the string is unspecified (in current
implementations the string will persist until the archive
is closed, but this is not guaranteed).
*/
const char *fz_archive_format(fz_context *ctx, fz_archive *arch);
/**
Number of entries in archive.
Will always return a value >= 0.
May throw an exception if this type of archive cannot count the
entries (such as a directory).
*/
int fz_count_archive_entries(fz_context *ctx, fz_archive *arch);
/**
Get listed name of entry position idx.
idx: Must be a value >= 0 < return value from
fz_count_archive_entries. If not in range NULL will be
returned.
May throw an exception if this type of archive cannot list the
entries (such as a directory).
*/
const char *fz_list_archive_entry(fz_context *ctx, fz_archive *arch, int idx);
/**
Check if entry by given name exists.
If named entry does not exist 0 will be returned, if it does
exist 1 is returned.
name: Entry name to look for, this must be an exact match to
the entry name in the archive.
*/
int fz_has_archive_entry(fz_context *ctx, fz_archive *arch, const char *name);
/**
Opens an archive entry as a stream.
name: Entry name to look for, this must be an exact match to
the entry name in the archive.
Throws an exception if a matching entry cannot be found.
*/
fz_stream *fz_open_archive_entry(fz_context *ctx, fz_archive *arch, const char *name);
/**
Opens an archive entry as a stream.
Returns NULL if a matching entry cannot be found, otherwise
behaves exactly as fz_open_archive_entry.
*/
fz_stream *fz_try_open_archive_entry(fz_context *ctx, fz_archive *arch, const char *name);
/**
Reads all bytes in an archive entry
into a buffer.
name: Entry name to look for, this must be an exact match to
the entry name in the archive.
Throws an exception if a matching entry cannot be found.
*/
fz_buffer *fz_read_archive_entry(fz_context *ctx, fz_archive *arch, const char *name);
/**
Reads all bytes in an archive entry
into a buffer.
name: Entry name to look for, this must be an exact match to
the entry name in the archive.
Returns NULL if a matching entry cannot be found. Otherwise behaves
the same as fz_read_archive_entry. Exceptions may be thrown.
*/
fz_buffer *fz_try_read_archive_entry(fz_context *ctx, fz_archive *arch, const char *name);
/**
fz_archive: tar implementation
*/
/**
Detect if stream object is a tar achieve.
Assumes that the stream object is seekable.
*/
int fz_is_tar_archive(fz_context *ctx, fz_stream *file);
/**
Open a tar archive file.
An exception is throw if the file is not a tar archive as
indicated by the presence of a tar signature.
filename: a path to a tar archive file as it would be given to
open(2).
*/
fz_archive *fz_open_tar_archive(fz_context *ctx, const char *filename);
/**
Open a tar archive stream.
Open an archive using a seekable stream object rather than
opening a file or directory on disk.
An exception is throw if the stream is not a tar archive as
indicated by the presence of a tar signature.
*/
fz_archive *fz_open_tar_archive_with_stream(fz_context *ctx, fz_stream *file);
/**
fz_archive: zip implementation
*/
/**
Detect if stream object is a zip archive.
Assumes that the stream object is seekable.
*/
int fz_is_zip_archive(fz_context *ctx, fz_stream *file);
/**
Open a zip archive file.
An exception is throw if the file is not a zip archive as
indicated by the presence of a zip signature.
filename: a path to a zip archive file as it would be given to
open(2).
*/
fz_archive *fz_open_zip_archive(fz_context *ctx, const char *path);
/**
Open a zip archive stream.
Open an archive using a seekable stream object rather than
opening a file or directory on disk.
An exception is throw if the stream is not a zip archive as
indicated by the presence of a zip signature.
*/
fz_archive *fz_open_zip_archive_with_stream(fz_context *ctx, fz_stream *file);
/**
fz_zip_writer offers methods for creating and writing zip files.
It can be seen as the reverse of the fz_archive zip
implementation.
*/
typedef struct fz_zip_writer fz_zip_writer;
/**
Create a new zip writer that writes to a given file.
Open an archive using a seekable stream object rather than
opening a file or directory on disk.
*/
fz_zip_writer *fz_new_zip_writer(fz_context *ctx, const char *filename);
/**
Create a new zip writer that writes to a given output stream.
Ownership of out passes in immediately upon calling this function.
The caller should never drop the fz_output, even if this function throws
an exception.
*/
fz_zip_writer *fz_new_zip_writer_with_output(fz_context *ctx, fz_output *out);
/**
Given a buffer of data, (optionally) compress it, and add it to
the zip file with the given name.
*/
void fz_write_zip_entry(fz_context *ctx, fz_zip_writer *zip, const char *name, fz_buffer *buf, int compress);
/**
Close the zip file for writing.
This flushes any pending data to the file. This can throw
exceptions.
*/
void fz_close_zip_writer(fz_context *ctx, fz_zip_writer *zip);
/**
Drop the reference to the zipfile.
In common with other 'drop' methods, this will never throw an
exception.
*/
void fz_drop_zip_writer(fz_context *ctx, fz_zip_writer *zip);
/**
Create an archive that holds named buffers.
tree can either be a preformed tree with fz_buffers as values,
or it can be NULL for an empty tree.
*/
fz_archive *fz_new_tree_archive(fz_context *ctx, fz_tree *tree);
/**
Add a named buffer to an existing tree archive.
The tree will take a new reference to the buffer. Ownership
is not transferred.
*/
void fz_tree_archive_add_buffer(fz_context *ctx, fz_archive *arch_, const char *name, fz_buffer *buf);
/**
Add a named block of data to an existing tree archive.
The data will be copied into a buffer, and so the caller
may free it as soon as this returns.
*/
void fz_tree_archive_add_data(fz_context *ctx, fz_archive *arch_, const char *name, const void *data, size_t size);
/**
Create a new multi archive (initially empty).
*/
fz_archive *fz_new_multi_archive(fz_context *ctx);
/**
Add an archive to the set of archives handled by a multi
archive.
If path is NULL, then the archive contents will appear at the
top level, otherwise, the archives contents will appear prefixed
by path.
*/
void fz_mount_multi_archive(fz_context *ctx, fz_archive *arch_, fz_archive *sub, const char *path);
/**
Implementation details: Subject to change.
*/
struct fz_archive
{
int refs;
fz_stream *file;
const char *format;
void (*drop_archive)(fz_context *ctx, fz_archive *arch);
int (*count_entries)(fz_context *ctx, fz_archive *arch);
const char *(*list_entry)(fz_context *ctx, fz_archive *arch, int idx);
int (*has_entry)(fz_context *ctx, fz_archive *arch, const char *name);
fz_buffer *(*read_entry)(fz_context *ctx, fz_archive *arch, const char *name);
fz_stream *(*open_entry)(fz_context *ctx, fz_archive *arch, const char *name);
};
fz_archive *fz_new_archive_of_size(fz_context *ctx, fz_stream *file, int size);
#define fz_new_derived_archive(C,F,M) \
((M*)Memento_label(fz_new_archive_of_size(C, F, sizeof(M)), #M))
#endif
+117
View File
@@ -0,0 +1,117 @@
// Copyright (C) 2004-2021 Artifex Software, Inc.
//
// This file is part of MuPDF.
//
// MuPDF is free software: you can redistribute it and/or modify it under the
// terms of the GNU Affero General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option)
// any later version.
//
// MuPDF 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 Affero General Public License for more
// details.
//
// You should have received a copy of the GNU Affero General Public License
// along with MuPDF. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html>
//
// Alternative licensing terms are available from the licensor.
// For commercial licensing, see <https://www.artifex.com/> or contact
// Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,
// CA 94129, USA, for further information.
#ifndef MUPDF_FITZ_BAND_WRITER_H
#define MUPDF_FITZ_BAND_WRITER_H
#include "mupdf/fitz/system.h"
#include "mupdf/fitz/context.h"
#include "mupdf/fitz/output.h"
#include "mupdf/fitz/color.h"
#include "mupdf/fitz/separation.h"
/**
fz_band_writer
*/
typedef struct fz_band_writer fz_band_writer;
/**
Cause a band writer to write the header for
a banded image with the given properties/dimensions etc. This
also configures the bandwriter for the format of the data to be
passed in future calls.
w, h: Width and Height of the entire page.
n: Number of components (including spots and alphas).
alpha: Number of alpha components.
xres, yres: X and Y resolutions in dpi.
cs: Colorspace (NULL for bitmaps)
seps: Separation details (or NULL).
*/
void fz_write_header(fz_context *ctx, fz_band_writer *writer, int w, int h, int n, int alpha, int xres, int yres, int pagenum, fz_colorspace *cs, fz_separations *seps);
/**
Cause a band writer to write the next band
of data for an image.
stride: The byte offset from the first byte of the data
for a pixel to the first byte of the data for the same pixel
on the row below.
band_height: The number of lines in this band.
samples: Pointer to first byte of the data.
*/
void fz_write_band(fz_context *ctx, fz_band_writer *writer, int stride, int band_height, const unsigned char *samples);
/**
Finishes up the output and closes the band writer. After this
call no more headers or bands may be written.
*/
void fz_close_band_writer(fz_context *ctx, fz_band_writer *writer);
/**
Drop the reference to the band writer, causing it to be
destroyed.
Never throws an exception.
*/
void fz_drop_band_writer(fz_context *ctx, fz_band_writer *writer);
/* Implementation details: subject to change. */
typedef void (fz_write_header_fn)(fz_context *ctx, fz_band_writer *writer, fz_colorspace *cs);
typedef void (fz_write_band_fn)(fz_context *ctx, fz_band_writer *writer, int stride, int band_start, int band_height, const unsigned char *samples);
typedef void (fz_write_trailer_fn)(fz_context *ctx, fz_band_writer *writer);
typedef void (fz_close_band_writer_fn)(fz_context *ctx, fz_band_writer *writer);
typedef void (fz_drop_band_writer_fn)(fz_context *ctx, fz_band_writer *writer);
struct fz_band_writer
{
fz_drop_band_writer_fn *drop;
fz_close_band_writer_fn *close;
fz_write_header_fn *header;
fz_write_band_fn *band;
fz_write_trailer_fn *trailer;
fz_output *out;
int w;
int h;
int n;
int s;
int alpha;
int xres;
int yres;
int pagenum;
int line;
fz_separations *seps;
};
fz_band_writer *fz_new_band_writer_of_size(fz_context *ctx, size_t size, fz_output *out);
#define fz_new_band_writer(C,M,O) ((M *)Memento_label(fz_new_band_writer_of_size(ctx, sizeof(M), O), #M))
#endif
+90
View File
@@ -0,0 +1,90 @@
/**
Bidirectional text processing.
Derived from the SmartOffice code, which is itself derived
from the example unicode standard code. Original copyright
messages follow:
Copyright (C) Picsel, 2004-2008. All Rights Reserved.
Processes Unicode text by arranging the characters into an order
suitable for display. E.g. Hebrew text will be arranged from
right-to-left and any English within the text will remain in the
left-to-right order.
This is an implementation of the Unicode Bidirectional Algorithm
which can be found here: http://www.unicode.org/reports/tr9/ and
is based on the reference implementation found on Unicode.org.
*/
#ifndef FITZ_BIDI_H
#define FITZ_BIDI_H
#include "mupdf/fitz/system.h"
#include "mupdf/fitz/context.h"
/* Implementation details: subject to change. */
typedef enum
{
FZ_BIDI_LTR = 0,
FZ_BIDI_RTL = 1,
FZ_BIDI_NEUTRAL = 2
}
fz_bidi_direction;
typedef enum
{
FZ_BIDI_CLASSIFY_WHITE_SPACE = 1,
FZ_BIDI_REPLACE_TAB = 2
}
fz_bidi_flags;
/**
Prototype for callback function supplied to fz_bidi_fragment_text.
@param fragment first character in fragment
@param fragmentLen number of characters in fragment
@param bidiLevel The bidirectional level for this text.
The bottom bit will be set iff block
should concatenate with other blocks as
right-to-left
@param script the script in use for this fragment (other
than common or inherited)
@param arg data from caller of Bidi_fragmentText
*/
typedef void (fz_bidi_fragment_fn)(const uint32_t *fragment,
size_t fragmentLen,
int bidiLevel,
int script,
void *arg);
/**
Partitions the given Unicode sequence into one or more
unidirectional fragments and invokes the given callback
function for each fragment.
For example, if directionality of text is:
0123456789
rrlllrrrrr,
we'll invoke callback with:
&text[0], length == 2
&text[2], length == 3
&text[5], length == 5
@param[in] text start of Unicode sequence
@param[in] textlen number of Unicodes to analyse
@param[in] baseDir direction of paragraph (specify FZ_BIDI_NEUTRAL to force auto-detection)
@param[in] callback function to be called for each fragment
@param[in] arg data to be passed to the callback function
@param[in] flags flags to control operation (see fz_bidi_flags above)
*/
void fz_bidi_fragment_text(fz_context *ctx,
const uint32_t *text,
size_t textlen,
fz_bidi_direction *baseDir,
fz_bidi_fragment_fn *callback,
void *arg,
int flags);
#endif
+168
View File
@@ -0,0 +1,168 @@
// Copyright (C) 2004-2021 Artifex Software, Inc.
//
// This file is part of MuPDF.
//
// MuPDF is free software: you can redistribute it and/or modify it under the
// terms of the GNU Affero General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option)
// any later version.
//
// MuPDF 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 Affero General Public License for more
// details.
//
// You should have received a copy of the GNU Affero General Public License
// along with MuPDF. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html>
//
// Alternative licensing terms are available from the licensor.
// For commercial licensing, see <https://www.artifex.com/> or contact
// Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,
// CA 94129, USA, for further information.
#ifndef MUPDF_FITZ_BITMAP_H
#define MUPDF_FITZ_BITMAP_H
#include "mupdf/fitz/system.h"
#include "mupdf/fitz/context.h"
#include "mupdf/fitz/pixmap.h"
/**
Bitmaps have 1 bit per component. Only used for creating
halftoned versions of contone buffers, and saving out. Samples
are stored msb first, akin to pbms.
The internals of this struct are considered implementation
details and subject to change. Where possible, accessor
functions should be used in preference.
*/
typedef struct
{
int refs;
int w, h, stride, n;
int xres, yres;
unsigned char *samples;
} fz_bitmap;
/**
Take an additional reference to the bitmap. The same pointer
is returned.
Never throws exceptions.
*/
fz_bitmap *fz_keep_bitmap(fz_context *ctx, fz_bitmap *bit);
/**
Drop a reference to the bitmap. When the reference count reaches
zero, the bitmap will be destroyed.
Never throws exceptions.
*/
void fz_drop_bitmap(fz_context *ctx, fz_bitmap *bit);
/**
A halftone is a set of threshold tiles, one per component. Each
threshold tile is a pixmap, possibly of varying sizes and
phases. Currently, we only provide one 'default' halftone tile
for operating on 1 component plus alpha pixmaps (where the alpha
is ignored). This is signified by a fz_halftone pointer to NULL.
*/
typedef struct fz_halftone fz_halftone;
/**
Make a bitmap from a pixmap and a halftone.
pix: The pixmap to generate from. Currently must be a single
color component with no alpha.
ht: The halftone to use. NULL implies the default halftone.
Returns the resultant bitmap. Throws exceptions in the case of
failure to allocate.
*/
fz_bitmap *fz_new_bitmap_from_pixmap(fz_context *ctx, fz_pixmap *pix, fz_halftone *ht);
/**
Make a bitmap from a pixmap and a
halftone, allowing for the position of the pixmap within an
overall banded rendering.
pix: The pixmap to generate from. Currently must be a single
color component with no alpha.
ht: The halftone to use. NULL implies the default halftone.
band_start: Vertical offset within the overall banded rendering
(in pixels)
Returns the resultant bitmap. Throws exceptions in the case of
failure to allocate.
*/
fz_bitmap *fz_new_bitmap_from_pixmap_band(fz_context *ctx, fz_pixmap *pix, fz_halftone *ht, int band_start);
/**
Create a new bitmap.
w, h: Width and Height for the bitmap
n: Number of color components (assumed to be a divisor of 8)
xres, yres: X and Y resolutions (in pixels per inch).
Returns pointer to created bitmap structure. The bitmap
data is uninitialised.
*/
fz_bitmap *fz_new_bitmap(fz_context *ctx, int w, int h, int n, int xres, int yres);
/**
Retrieve details of a given bitmap.
bitmap: The bitmap to query.
w: Pointer to storage to retrieve width (or NULL).
h: Pointer to storage to retrieve height (or NULL).
n: Pointer to storage to retrieve number of color components (or
NULL).
stride: Pointer to storage to retrieve bitmap stride (or NULL).
*/
void fz_bitmap_details(fz_bitmap *bitmap, int *w, int *h, int *n, int *stride);
/**
Set the entire bitmap to 0.
Never throws exceptions.
*/
void fz_clear_bitmap(fz_context *ctx, fz_bitmap *bit);
/**
Create a 'default' halftone structure
for the given number of components.
num_comps: The number of components to use.
Returns a simple default halftone. The default halftone uses
the same halftone tile for each plane, which may not be ideal
for all purposes.
*/
fz_halftone *fz_default_halftone(fz_context *ctx, int num_comps);
/**
Take an additional reference to the halftone. The same pointer
is returned.
Never throws exceptions.
*/
fz_halftone *fz_keep_halftone(fz_context *ctx, fz_halftone *half);
/**
Drop a reference to the halftone. When the reference count
reaches zero, the halftone is destroyed.
Never throws exceptions.
*/
void fz_drop_halftone(fz_context *ctx, fz_halftone *ht);
#endif
+250
View File
@@ -0,0 +1,250 @@
// Copyright (C) 2004-2023 Artifex Software, Inc.
//
// This file is part of MuPDF.
//
// MuPDF is free software: you can redistribute it and/or modify it under the
// terms of the GNU Affero General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option)
// any later version.
//
// MuPDF 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 Affero General Public License for more
// details.
//
// You should have received a copy of the GNU Affero General Public License
// along with MuPDF. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html>
//
// Alternative licensing terms are available from the licensor.
// For commercial licensing, see <https://www.artifex.com/> or contact
// Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,
// CA 94129, USA, for further information.
#ifndef MUPDF_FITZ_BUFFER_H
#define MUPDF_FITZ_BUFFER_H
#include "mupdf/fitz/system.h"
#include "mupdf/fitz/context.h"
/**
fz_buffer is a wrapper around a dynamically allocated array of
bytes.
Buffers have a capacity (the number of bytes storage immediately
available) and a current size.
The contents of the structure are considered implementation
details and are subject to change. Users should use the accessor
functions in preference.
*/
typedef struct
{
int refs;
unsigned char *data;
size_t cap, len;
int unused_bits;
int shared;
} fz_buffer;
/**
Take an additional reference to the buffer. The same pointer
is returned.
Never throws exceptions.
*/
fz_buffer *fz_keep_buffer(fz_context *ctx, fz_buffer *buf);
/**
Drop a reference to the buffer. When the reference count reaches
zero, the buffer is destroyed.
Never throws exceptions.
*/
void fz_drop_buffer(fz_context *ctx, fz_buffer *buf);
/**
Retrieve internal memory of buffer.
datap: Output parameter that will be pointed to the data.
Returns the current size of the data in bytes.
*/
size_t fz_buffer_storage(fz_context *ctx, fz_buffer *buf, unsigned char **datap);
/**
Ensure that a buffer's data ends in a
0 byte, and return a pointer to it.
*/
const char *fz_string_from_buffer(fz_context *ctx, fz_buffer *buf);
fz_buffer *fz_new_buffer(fz_context *ctx, size_t capacity);
/**
Create a new buffer with existing data.
data: Pointer to existing data.
size: Size of existing data.
Takes ownership of data. Does not make a copy. Calls fz_free on
the data when the buffer is deallocated. Do not use 'data' after
passing to this function.
Returns pointer to new buffer. Throws exception on allocation
failure.
*/
fz_buffer *fz_new_buffer_from_data(fz_context *ctx, unsigned char *data, size_t size);
/**
Like fz_new_buffer, but does not take ownership.
*/
fz_buffer *fz_new_buffer_from_shared_data(fz_context *ctx, const unsigned char *data, size_t size);
/**
Create a new buffer containing a copy of the passed data.
*/
fz_buffer *fz_new_buffer_from_copied_data(fz_context *ctx, const unsigned char *data, size_t size);
/**
Make a new buffer, containing a copy of the data used in
the original.
*/
fz_buffer *fz_clone_buffer(fz_context *ctx, fz_buffer *buf);
/**
Create a new buffer with data decoded from a base64 input string.
*/
fz_buffer *fz_new_buffer_from_base64(fz_context *ctx, const char *data, size_t size);
/**
Ensure that a buffer has a given capacity,
truncating data if required.
capacity: The desired capacity for the buffer. If the current
size of the buffer contents is smaller than capacity, it is
truncated.
*/
void fz_resize_buffer(fz_context *ctx, fz_buffer *buf, size_t capacity);
/**
Make some space within a buffer (i.e. ensure that
capacity > size).
*/
void fz_grow_buffer(fz_context *ctx, fz_buffer *buf);
/**
Trim wasted capacity from a buffer by resizing internal memory.
*/
void fz_trim_buffer(fz_context *ctx, fz_buffer *buf);
/**
Empties the buffer. Storage is not freed, but is held ready
to be reused as the buffer is refilled.
Never throws exceptions.
*/
void fz_clear_buffer(fz_context *ctx, fz_buffer *buf);
/**
Create a new buffer with a (subset of) the data from the buffer.
start: if >= 0, offset from start of buffer, if < 0 offset from end of buffer.
end: if >= 0, offset from start of buffer, if < 0 offset from end of buffer.
*/
fz_buffer *fz_slice_buffer(fz_context *ctx, fz_buffer *buf, int64_t start, int64_t end);
/**
Append the contents of the source buffer onto the end of the
destination buffer, extending automatically as required.
Ownership of buffers does not change.
*/
void fz_append_buffer(fz_context *ctx, fz_buffer *destination, fz_buffer *source);
/**
Write a base64 encoded data block, optionally with periodic newlines.
*/
void fz_append_base64(fz_context *ctx, fz_buffer *out, const unsigned char *data, size_t size, int newline);
/**
Append a base64 encoded fz_buffer, optionally with periodic newlines.
*/
void fz_append_base64_buffer(fz_context *ctx, fz_buffer *out, fz_buffer *data, int newline);
/**
fz_append_*: Append data to a buffer.
The buffer will automatically grow as required.
*/
void fz_append_data(fz_context *ctx, fz_buffer *buf, const void *data, size_t len);
void fz_append_string(fz_context *ctx, fz_buffer *buf, const char *data);
void fz_append_byte(fz_context *ctx, fz_buffer *buf, int c);
void fz_append_rune(fz_context *ctx, fz_buffer *buf, int c);
void fz_append_int32_le(fz_context *ctx, fz_buffer *buf, int x);
void fz_append_int16_le(fz_context *ctx, fz_buffer *buf, int x);
void fz_append_int32_be(fz_context *ctx, fz_buffer *buf, int x);
void fz_append_int16_be(fz_context *ctx, fz_buffer *buf, int x);
void fz_append_bits(fz_context *ctx, fz_buffer *buf, int value, int count);
void fz_append_bits_pad(fz_context *ctx, fz_buffer *buf);
/**
fz_append_pdf_string: Append a string with PDF syntax quotes and
escapes.
The buffer will automatically grow as required.
*/
void fz_append_pdf_string(fz_context *ctx, fz_buffer *buffer, const char *text);
/**
fz_append_printf: Format and append data to buffer using
printf-like formatting (see fz_vsnprintf).
The buffer will automatically grow as required.
*/
void fz_append_printf(fz_context *ctx, fz_buffer *buffer, const char *fmt, ...);
/**
fz_append_vprintf: Format and append data to buffer using
printf-like formatting with varargs (see fz_vsnprintf).
*/
void fz_append_vprintf(fz_context *ctx, fz_buffer *buffer, const char *fmt, va_list args);
/**
Zero-terminate buffer in order to use as a C string.
This byte is invisible and does not affect the length of the
buffer as returned by fz_buffer_storage. The zero byte is
written *after* the data, and subsequent writes will overwrite
the terminating byte.
Subsequent changes to the size of the buffer (such as by
fz_buffer_trim, fz_buffer_grow, fz_resize_buffer, etc) may
invalidate this.
*/
void fz_terminate_buffer(fz_context *ctx, fz_buffer *buf);
/**
Create an MD5 digest from buffer contents.
Never throws exceptions.
*/
void fz_md5_buffer(fz_context *ctx, fz_buffer *buffer, unsigned char digest[16]);
/**
Take ownership of buffer contents.
Performs the same task as fz_buffer_storage, but ownership of
the data buffer returns with this call. The buffer is left
empty.
Note: Bad things may happen if this is called on a buffer with
multiple references that is being used from multiple threads.
data: Pointer to place to retrieve data pointer.
Returns length of stream.
*/
size_t fz_buffer_extract(fz_context *ctx, fz_buffer *buf, unsigned char **data);
#endif
+427
View File
@@ -0,0 +1,427 @@
// Copyright (C) 2004-2021 Artifex Software, Inc.
//
// This file is part of MuPDF.
//
// MuPDF is free software: you can redistribute it and/or modify it under the
// terms of the GNU Affero General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option)
// any later version.
//
// MuPDF 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 Affero General Public License for more
// details.
//
// You should have received a copy of the GNU Affero General Public License
// along with MuPDF. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html>
//
// Alternative licensing terms are available from the licensor.
// For commercial licensing, see <https://www.artifex.com/> or contact
// Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,
// CA 94129, USA, for further information.
#ifndef MUPDF_FITZ_COLOR_H
#define MUPDF_FITZ_COLOR_H
#include "mupdf/fitz/system.h"
#include "mupdf/fitz/context.h"
#include "mupdf/fitz/store.h"
#if FZ_ENABLE_ICC
/**
Opaque type for an ICC Profile.
*/
typedef struct fz_icc_profile fz_icc_profile;
#endif
/**
Describes a given colorspace.
*/
typedef struct fz_colorspace fz_colorspace;
/**
Pixmaps represent a set of pixels for a 2 dimensional region of
a plane. Each pixel has n components per pixel. The components
are in the order process-components, spot-colors, alpha, where
there can be 0 of any of those types. The data is in
premultiplied alpha when rendering, but non-premultiplied for
colorspace conversions and rescaling.
*/
typedef struct fz_pixmap fz_pixmap;
/* Color handling parameters: rendering intent, overprint, etc. */
enum
{
/* Same order as needed by lcms */
FZ_RI_PERCEPTUAL,
FZ_RI_RELATIVE_COLORIMETRIC,
FZ_RI_SATURATION,
FZ_RI_ABSOLUTE_COLORIMETRIC,
};
typedef struct
{
uint8_t ri; /* rendering intent */
uint8_t bp; /* black point compensation */
uint8_t op; /* overprinting */
uint8_t opm; /* overprint mode */
} fz_color_params;
FZ_DATA extern const fz_color_params fz_default_color_params;
/**
Map from (case sensitive) rendering intent string to enumeration
value.
*/
int fz_lookup_rendering_intent(const char *name);
/**
Map from enumerated rendering intent to string.
The returned string is static and therefore must not be freed.
*/
const char *fz_rendering_intent_name(int ri);
/**
The maximum number of colorants available in any given
color/colorspace (not including alpha).
Changing this value will alter the amount of memory being used
(both stack and heap space), but not hugely. Speed should
(largely) be determined by the number of colors actually used.
*/
enum { FZ_MAX_COLORS = 32 };
enum fz_colorspace_type
{
FZ_COLORSPACE_NONE,
FZ_COLORSPACE_GRAY,
FZ_COLORSPACE_RGB,
FZ_COLORSPACE_BGR,
FZ_COLORSPACE_CMYK,
FZ_COLORSPACE_LAB,
FZ_COLORSPACE_INDEXED,
FZ_COLORSPACE_SEPARATION,
};
enum
{
FZ_COLORSPACE_IS_DEVICE = 1,
FZ_COLORSPACE_IS_ICC = 2,
FZ_COLORSPACE_HAS_CMYK = 4,
FZ_COLORSPACE_HAS_SPOTS = 8,
FZ_COLORSPACE_HAS_CMYK_AND_SPOTS = 4|8,
};
/**
Creates a new colorspace instance and returns a reference.
No internal checking is done that the colorspace type (e.g.
CMYK) matches with the flags (e.g. FZ_COLORSPACE_HAS_CMYK) or
colorant count (n) or name.
The reference should be dropped when it is finished with.
Colorspaces are immutable once created (with the exception of
setting up colorant names for separation spaces).
*/
fz_colorspace *fz_new_colorspace(fz_context *ctx, enum fz_colorspace_type type, int flags, int n, const char *name);
/**
Increment the reference count for the colorspace.
Returns the same pointer. Never throws an exception.
*/
fz_colorspace *fz_keep_colorspace(fz_context *ctx, fz_colorspace *colorspace);
/**
Drops a reference to the colorspace.
When the reference count reaches zero, the colorspace is
destroyed.
*/
void fz_drop_colorspace(fz_context *ctx, fz_colorspace *colorspace);
/**
Create an indexed colorspace.
The supplied lookup table is high palette entries long. Each
entry is n bytes long, where n is given by the number of
colorants in the base colorspace, one byte per colorant.
Ownership of lookup is passed it; it will be freed on
destruction, so must be heap allocated.
The colorspace will keep an additional reference to the base
colorspace that will be dropped on destruction.
The returned reference should be dropped when it is finished
with.
Colorspaces are immutable once created.
*/
fz_colorspace *fz_new_indexed_colorspace(fz_context *ctx, fz_colorspace *base, int high, unsigned char *lookup);
/**
Create a colorspace from an ICC profile supplied in buf.
Limited checking is done to ensure that the colorspace type is
appropriate for the supplied ICC profile.
An additional reference is taken to buf, which will be dropped
on destruction. Ownership is NOT passed in.
The returned reference should be dropped when it is finished
with.
Colorspaces are immutable once created.
*/
fz_colorspace *fz_new_icc_colorspace(fz_context *ctx, enum fz_colorspace_type type, int flags, const char *name, fz_buffer *buf);
/**
Create a calibrated gray colorspace.
The returned reference should be dropped when it is finished
with.
Colorspaces are immutable once created.
*/
fz_colorspace *fz_new_cal_gray_colorspace(fz_context *ctx, float wp[3], float bp[3], float gamma);
/**
Create a calibrated rgb colorspace.
The returned reference should be dropped when it is finished
with.
Colorspaces are immutable once created.
*/
fz_colorspace *fz_new_cal_rgb_colorspace(fz_context *ctx, float wp[3], float bp[3], float gamma[3], float matrix[9]);
/**
Query the type of colorspace.
*/
enum fz_colorspace_type fz_colorspace_type(fz_context *ctx, fz_colorspace *cs);
/**
Query the name of a colorspace.
The returned string has the same lifespan as the colorspace
does. Caller should not free it.
*/
const char *fz_colorspace_name(fz_context *ctx, fz_colorspace *cs);
/**
Query the number of colorants in a colorspace.
*/
int fz_colorspace_n(fz_context *ctx, fz_colorspace *cs);
/**
True for CMYK, Separation and DeviceN colorspaces.
*/
int fz_colorspace_is_subtractive(fz_context *ctx, fz_colorspace *cs);
/**
True if DeviceN color space has only colorants from the CMYK set.
*/
int fz_colorspace_device_n_has_only_cmyk(fz_context *ctx, fz_colorspace *cs);
/**
True if DeviceN color space has cyan magenta yellow or black as
one of its colorants.
*/
int fz_colorspace_device_n_has_cmyk(fz_context *ctx, fz_colorspace *cs);
/**
Tests for particular types of colorspaces
*/
int fz_colorspace_is_gray(fz_context *ctx, fz_colorspace *cs);
int fz_colorspace_is_rgb(fz_context *ctx, fz_colorspace *cs);
int fz_colorspace_is_cmyk(fz_context *ctx, fz_colorspace *cs);
int fz_colorspace_is_lab(fz_context *ctx, fz_colorspace *cs);
int fz_colorspace_is_indexed(fz_context *ctx, fz_colorspace *cs);
int fz_colorspace_is_device_n(fz_context *ctx, fz_colorspace *cs);
int fz_colorspace_is_device(fz_context *ctx, fz_colorspace *cs);
int fz_colorspace_is_device_gray(fz_context *ctx, fz_colorspace *cs);
int fz_colorspace_is_device_cmyk(fz_context *ctx, fz_colorspace *cs);
int fz_colorspace_is_lab_icc(fz_context *ctx, fz_colorspace *cs);
/**
Check to see that a colorspace is appropriate to be used as
a blending space (i.e. only grey, rgb or cmyk).
*/
int fz_is_valid_blend_colorspace(fz_context *ctx, fz_colorspace *cs);
/**
Get the 'base' colorspace for a colorspace.
For indexed colorspaces, this is the colorspace the index
decodes into. For all other colorspaces, it is the colorspace
itself.
The returned colorspace is 'borrowed' (i.e. no additional
references are taken or dropped).
*/
fz_colorspace *fz_base_colorspace(fz_context *ctx, fz_colorspace *cs);
/**
Retrieve global default colorspaces.
These return borrowed references that should not be dropped,
unless they are kept first.
*/
fz_colorspace *fz_device_gray(fz_context *ctx);
fz_colorspace *fz_device_rgb(fz_context *ctx);
fz_colorspace *fz_device_bgr(fz_context *ctx);
fz_colorspace *fz_device_cmyk(fz_context *ctx);
fz_colorspace *fz_device_lab(fz_context *ctx);
/**
Assign a name for a given colorant in a colorspace.
Used while initially setting up a colorspace. The string is
copied into local storage, so need not be retained by the
caller.
*/
void fz_colorspace_name_colorant(fz_context *ctx, fz_colorspace *cs, int n, const char *name);
/**
Retrieve a the name for a colorant.
Returns a pointer with the same lifespan as the colorspace.
*/
const char *fz_colorspace_colorant(fz_context *ctx, fz_colorspace *cs, int n);
/* Color conversion */
/**
Clamp the samples in a color to the correct ranges for a
given colorspace.
*/
void fz_clamp_color(fz_context *ctx, fz_colorspace *cs, const float *in, float *out);
/**
Convert color values sv from colorspace ss into colorvalues dv
for colorspace ds, via an optional intervening space is,
respecting the given color_params.
*/
void fz_convert_color(fz_context *ctx, fz_colorspace *ss, const float *sv, fz_colorspace *ds, float *dv, fz_colorspace *is, fz_color_params params);
/* Default (fallback) colorspace handling */
/**
Structure to hold default colorspaces.
*/
typedef struct
{
int refs;
fz_colorspace *gray;
fz_colorspace *rgb;
fz_colorspace *cmyk;
fz_colorspace *oi;
} fz_default_colorspaces;
/**
Create a new default colorspace structure with values inherited
from the context, and return a reference to it.
These can be overridden using fz_set_default_xxxx.
These should not be overridden while more than one caller has
the reference for fear of race conditions.
The caller should drop this reference once finished with it.
*/
fz_default_colorspaces *fz_new_default_colorspaces(fz_context *ctx);
/**
Keep an additional reference to the default colorspaces
structure.
Never throws exceptions.
*/
fz_default_colorspaces* fz_keep_default_colorspaces(fz_context *ctx, fz_default_colorspaces *default_cs);
/**
Drop a reference to the default colorspaces structure. When the
reference count reaches 0, the references it holds internally
to the underlying colorspaces will be dropped, and the structure
will be destroyed.
Never throws exceptions.
*/
void fz_drop_default_colorspaces(fz_context *ctx, fz_default_colorspaces *default_cs);
/**
Returns a reference to a newly cloned default colorspaces
structure.
The new clone may safely be altered without fear of race
conditions as the caller is the only reference holder.
*/
fz_default_colorspaces *fz_clone_default_colorspaces(fz_context *ctx, fz_default_colorspaces *base);
/**
Retrieve default colorspaces (typically page local).
If default_cs is non NULL, the default is retrieved from there,
otherwise the global default is retrieved.
These return borrowed references that should not be dropped,
unless they are kept first.
*/
fz_colorspace *fz_default_gray(fz_context *ctx, const fz_default_colorspaces *default_cs);
fz_colorspace *fz_default_rgb(fz_context *ctx, const fz_default_colorspaces *default_cs);
fz_colorspace *fz_default_cmyk(fz_context *ctx, const fz_default_colorspaces *default_cs);
fz_colorspace *fz_default_output_intent(fz_context *ctx, const fz_default_colorspaces *default_cs);
/**
Set new defaults within the default colorspace structure.
New references are taken to the new default, and references to
the old defaults dropped.
Never throws exceptions.
*/
void fz_set_default_gray(fz_context *ctx, fz_default_colorspaces *default_cs, fz_colorspace *cs);
void fz_set_default_rgb(fz_context *ctx, fz_default_colorspaces *default_cs, fz_colorspace *cs);
void fz_set_default_cmyk(fz_context *ctx, fz_default_colorspaces *default_cs, fz_colorspace *cs);
void fz_set_default_output_intent(fz_context *ctx, fz_default_colorspaces *default_cs, fz_colorspace *cs);
/* Implementation details: subject to change. */
struct fz_colorspace
{
fz_key_storable key_storable;
enum fz_colorspace_type type;
int flags;
int n;
char *name;
union {
#if FZ_ENABLE_ICC
struct {
fz_buffer *buffer;
unsigned char md5[16];
fz_icc_profile *profile;
} icc;
#endif
struct {
fz_colorspace *base;
int high;
unsigned char *lookup;
} indexed;
struct {
fz_colorspace *base;
void (*eval)(fz_context *ctx, void *tint, const float *s, int sn, float *d, int dn);
void (*drop)(fz_context *ctx, void *tint);
void *tint;
char *colorant[FZ_MAX_COLORS];
} separation;
} u;
};
void fz_drop_colorspace_imp(fz_context *ctx, fz_storable *cs_);
#endif
+87
View File
@@ -0,0 +1,87 @@
// Copyright (C) 2004-2021 Artifex Software, Inc.
//
// This file is part of MuPDF.
//
// MuPDF is free software: you can redistribute it and/or modify it under the
// terms of the GNU Affero General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option)
// any later version.
//
// MuPDF 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 Affero General Public License for more
// details.
//
// You should have received a copy of the GNU Affero General Public License
// along with MuPDF. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html>
//
// Alternative licensing terms are available from the licensor.
// For commercial licensing, see <https://www.artifex.com/> or contact
// Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,
// CA 94129, USA, for further information.
#ifndef MUPDF_FITZ_COMPRESS_H
#define MUPDF_FITZ_COMPRESS_H
#include "mupdf/fitz/system.h"
#include "mupdf/fitz/buffer.h"
typedef enum
{
FZ_DEFLATE_NONE = 0,
FZ_DEFLATE_BEST_SPEED = 1,
FZ_DEFLATE_BEST = 9,
FZ_DEFLATE_DEFAULT = -1
} fz_deflate_level;
/**
Returns the upper bound on the
size of flated data of length size.
*/
size_t fz_deflate_bound(fz_context *ctx, size_t size);
/**
Compress source_length bytes of data starting
at source, into a buffer of length *destLen, starting at dest.
*compressed_length will be updated on exit to contain the size
actually used.
*/
void fz_deflate(fz_context *ctx, unsigned char *dest, size_t *compressed_length, const unsigned char *source, size_t source_length, fz_deflate_level level);
/**
Compress source_length bytes of data starting
at source, into a new memory block malloced for that purpose.
*compressed_length is updated on exit to contain the size used.
Ownership of the block is returned from this function, and the
caller is therefore responsible for freeing it. The block may be
considerably larger than is actually required. The caller is
free to fz_realloc it down if it wants to.
*/
unsigned char *fz_new_deflated_data(fz_context *ctx, size_t *compressed_length, const unsigned char *source, size_t source_length, fz_deflate_level level);
/**
Compress the contents of a fz_buffer into a
new block malloced for that purpose. *compressed_length is
updated on exit to contain the size used. Ownership of the block
is returned from this function, and the caller is therefore
responsible for freeing it. The block may be considerably larger
than is actually required. The caller is free to fz_realloc it
down if it wants to.
*/
unsigned char *fz_new_deflated_data_from_buffer(fz_context *ctx, size_t *compressed_length, fz_buffer *buffer, fz_deflate_level level);
/**
Compress bitmap data as CCITT Group 3 1D fax image.
Creates a stream assuming the default PDF parameters,
except the number of columns.
*/
fz_buffer *fz_compress_ccitt_fax_g3(fz_context *ctx, const unsigned char *data, int columns, int rows);
/**
Compress bitmap data as CCITT Group 4 2D fax image.
Creates a stream assuming the default PDF parameters, except
K=-1 and the number of columns.
*/
fz_buffer *fz_compress_ccitt_fax_g4(fz_context *ctx, const unsigned char *data, int columns, int rows);
#endif
+173
View File
@@ -0,0 +1,173 @@
// Copyright (C) 2004-2023 Artifex Software, Inc.
//
// This file is part of MuPDF.
//
// MuPDF is free software: you can redistribute it and/or modify it under the
// terms of the GNU Affero General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option)
// any later version.
//
// MuPDF 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 Affero General Public License for more
// details.
//
// You should have received a copy of the GNU Affero General Public License
// along with MuPDF. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html>
//
// Alternative licensing terms are available from the licensor.
// For commercial licensing, see <https://www.artifex.com/> or contact
// Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,
// CA 94129, USA, for further information.
#ifndef MUPDF_FITZ_COMPRESSED_BUFFER_H
#define MUPDF_FITZ_COMPRESSED_BUFFER_H
#include "mupdf/fitz/system.h"
#include "mupdf/fitz/context.h"
#include "mupdf/fitz/buffer.h"
#include "mupdf/fitz/stream.h"
#include "mupdf/fitz/filter.h"
/**
Compression parameters used for buffers of compressed data;
typically for the source data for images.
*/
typedef struct
{
int type;
union {
struct {
int color_transform; /* Use -1 for unset */
} jpeg;
struct {
int smask_in_data;
} jpx;
struct {
fz_jbig2_globals *globals;
int embedded;
} jbig2;
struct {
int columns;
int rows;
int k;
int end_of_line;
int encoded_byte_align;
int end_of_block;
int black_is_1;
int damaged_rows_before_error;
} fax;
struct
{
int columns;
int colors;
int predictor;
int bpc;
}
flate;
struct
{
int columns;
int colors;
int predictor;
int bpc;
int early_change;
} lzw;
} u;
} fz_compression_params;
/**
Buffers of compressed data; typically for the source data
for images.
*/
typedef struct
{
fz_compression_params params;
fz_buffer *buffer;
} fz_compressed_buffer;
/**
Return the storage size used for a buffer and its data.
Used in implementing store handling.
Never throws exceptions.
*/
size_t fz_compressed_buffer_size(fz_compressed_buffer *buffer);
/**
Open a stream to read the decompressed version of a buffer.
*/
fz_stream *fz_open_compressed_buffer(fz_context *ctx, fz_compressed_buffer *);
/**
Open a stream to read the decompressed version of a buffer,
with optional log2 subsampling.
l2factor = NULL for no subsampling, or a pointer to an integer
containing the maximum log2 subsample factor acceptable (0 =
none, 1 = halve dimensions, 2 = quarter dimensions etc). If
non-NULL, then *l2factor will be updated on exit with the actual
log2 subsample factor achieved.
*/
fz_stream *fz_open_image_decomp_stream_from_buffer(fz_context *ctx, fz_compressed_buffer *, int *l2factor);
/**
Open a stream to read the decompressed version of another stream
with optional log2 subsampling.
*/
fz_stream *fz_open_image_decomp_stream(fz_context *ctx, fz_stream *, fz_compression_params *, int *l2factor);
/**
Recognise image format strings in the first 8 bytes from image
data.
*/
int fz_recognize_image_format(fz_context *ctx, unsigned char p[8]);
/**
Map from FZ_IMAGE_* value to string.
The returned string is static and therefore must not be freed.
*/
const char *fz_image_type_name(int type);
/**
Map from (case sensitive) image type string to FZ_IMAGE_*
type value.
*/
int fz_lookup_image_type(const char *type);
enum
{
FZ_IMAGE_UNKNOWN = 0,
/* Uncompressed samples */
FZ_IMAGE_RAW,
/* Compressed samples */
FZ_IMAGE_FAX,
FZ_IMAGE_FLATE,
FZ_IMAGE_LZW,
FZ_IMAGE_RLD,
/* Full image formats */
FZ_IMAGE_BMP,
FZ_IMAGE_GIF,
FZ_IMAGE_JBIG2,
FZ_IMAGE_JPEG,
FZ_IMAGE_JPX,
FZ_IMAGE_JXR,
FZ_IMAGE_PNG,
FZ_IMAGE_PNM,
FZ_IMAGE_TIFF,
FZ_IMAGE_PSD,
};
/**
Drop a reference to a compressed buffer. Destroys the buffer
and frees any storage/other references held by it.
Never throws exceptions.
*/
void fz_drop_compressed_buffer(fz_context *ctx, fz_compressed_buffer *buf);
#endif
+222
View File
@@ -0,0 +1,222 @@
// Copyright (C) 2004-2021 Artifex Software, Inc.
//
// This file is part of MuPDF.
//
// MuPDF is free software: you can redistribute it and/or modify it under the
// terms of the GNU Affero General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option)
// any later version.
//
// MuPDF 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 Affero General Public License for more
// details.
//
// You should have received a copy of the GNU Affero General Public License
// along with MuPDF. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html>
//
// Alternative licensing terms are available from the licensor.
// For commercial licensing, see <https://www.artifex.com/> or contact
// Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,
// CA 94129, USA, for further information.
#ifndef FZ_CONFIG_H
#define FZ_CONFIG_H
/**
Enable the following for spot (and hence overprint/overprint
simulation) capable rendering. This forces FZ_PLOTTERS_N on.
*/
/* #define FZ_ENABLE_SPOT_RENDERING 1 */
/**
Choose which plotters we need.
By default we build all the plotters in. To avoid building
plotters in that aren't needed, define the unwanted
FZ_PLOTTERS_... define to 0.
*/
/* #define FZ_PLOTTERS_G 1 */
/* #define FZ_PLOTTERS_RGB 1 */
/* #define FZ_PLOTTERS_CMYK 1 */
/* #define FZ_PLOTTERS_N 1 */
/**
Choose which document agents to include.
By default all are enabled. To avoid building unwanted
ones, define FZ_ENABLE_... to 0.
*/
/* #define FZ_ENABLE_PDF 1 */
/* #define FZ_ENABLE_XPS 1 */
/* #define FZ_ENABLE_SVG 1 */
/* #define FZ_ENABLE_CBZ 1 */
/* #define FZ_ENABLE_IMG 1 */
/* #define FZ_ENABLE_HTML 1 */
/* #define FZ_ENABLE_EPUB 1 */
/**
Choose which document writers to include.
By default all are enabled. To avoid building unwanted
ones, define FZ_ENABLE_..._OUTPUT to 0.
*/
/* #define FZ_ENABLE_OCR_OUTPUT 1 */
/* #define FZ_ENABLE_DOCX_OUTPUT 1 */
/* #define FZ_ENABLE_ODT_OUTPUT 1 */
/**
Choose whether to enable ICC color profiles.
*/
/* #define FZ_ENABLE_ICC 1 */
/**
Choose whether to enable JPEG2000 decoding.
By default, it is enabled, but due to frequent security
issues with the third party libraries we support disabling
it with this flag.
*/
/* #define FZ_ENABLE_JPX 1 */
/**
Choose whether to enable JavaScript.
By default JavaScript is enabled both for mutool and PDF
interactivity.
*/
/* #define FZ_ENABLE_JS 1 */
/**
Choose which fonts to include.
By default we include the base 14 PDF fonts,
DroidSansFallback from Android for CJK, and
Charis SIL from SIL for epub/html.
Enable the following defines to AVOID including
unwanted fonts.
*/
/* To avoid all noto fonts except CJK, enable: */
#define TOFU 1
/* To skip the CJK font, enable: (this implicitly enables TOFU_CJK_EXT
* and TOFU_CJK_LANG) */
#define TOFU_CJK 1
/* To skip CJK Extension A, enable: (this implicitly enables
* TOFU_CJK_LANG) */
/* #define TOFU_CJK_EXT */
/* To skip CJK language specific fonts, enable: */
/* #define TOFU_CJK_LANG */
/* To skip the Emoji font, enable: */
/* #define TOFU_EMOJI */
/* To skip the ancient/historic scripts, enable: */
/* #define TOFU_HISTORIC */
/* To skip the symbol font, enable: */
/* #define TOFU_SYMBOL */
/* To skip the SIL fonts, enable: */
/* #define TOFU_SIL */
/* To skip the Base14 fonts, enable: */
/* #define TOFU_BASE14 */
/* (You probably really don't want to do that except for measurement
* purposes!) */
/* ---------- DO NOT EDIT ANYTHING UNDER THIS LINE ---------- */
#ifndef FZ_ENABLE_SPOT_RENDERING
#define FZ_ENABLE_SPOT_RENDERING 1
#endif
#if FZ_ENABLE_SPOT_RENDERING
#undef FZ_PLOTTERS_N
#define FZ_PLOTTERS_N 1
#endif /* FZ_ENABLE_SPOT_RENDERING */
#ifndef FZ_PLOTTERS_G
#define FZ_PLOTTERS_G 1
#endif /* FZ_PLOTTERS_G */
#ifndef FZ_PLOTTERS_RGB
#define FZ_PLOTTERS_RGB 1
#endif /* FZ_PLOTTERS_RGB */
#ifndef FZ_PLOTTERS_CMYK
#define FZ_PLOTTERS_CMYK 1
#endif /* FZ_PLOTTERS_CMYK */
#ifndef FZ_PLOTTERS_N
#define FZ_PLOTTERS_N 1
#endif /* FZ_PLOTTERS_N */
/* We need at least 1 plotter defined */
#if FZ_PLOTTERS_G == 0 && FZ_PLOTTERS_RGB == 0 && FZ_PLOTTERS_CMYK == 0
#undef FZ_PLOTTERS_N
#define FZ_PLOTTERS_N 1
#endif
#ifndef FZ_ENABLE_PDF
#define FZ_ENABLE_PDF 1
#endif /* FZ_ENABLE_PDF */
#ifndef FZ_ENABLE_XPS
#define FZ_ENABLE_XPS 1
#endif /* FZ_ENABLE_XPS */
#ifndef FZ_ENABLE_SVG
#define FZ_ENABLE_SVG 1
#endif /* FZ_ENABLE_SVG */
#ifndef FZ_ENABLE_CBZ
#define FZ_ENABLE_CBZ 1
#endif /* FZ_ENABLE_CBZ */
#ifndef FZ_ENABLE_IMG
#define FZ_ENABLE_IMG 1
#endif /* FZ_ENABLE_IMG */
#ifndef FZ_ENABLE_HTML
#define FZ_ENABLE_HTML 1
#endif /* FZ_ENABLE_HTML */
#ifndef FZ_ENABLE_EPUB
#define FZ_ENABLE_EPUB 1
#endif /* FZ_ENABLE_EPUB */
#ifndef FZ_ENABLE_OCR_OUTPUT
#define FZ_ENABLE_OCR_OUTPUT 1
#endif /* FZ_ENABLE_OCR_OUTPUT */
#ifndef FZ_ENABLE_ODT_OUTPUT
#define FZ_ENABLE_ODT_OUTPUT 1
#endif /* FZ_ENABLE_ODT_OUTPUT */
#ifndef FZ_ENABLE_DOCX_OUTPUT
#define FZ_ENABLE_DOCX_OUTPUT 1
#endif /* FZ_ENABLE_DOCX_OUTPUT */
#ifndef FZ_ENABLE_JPX
#define FZ_ENABLE_JPX 1
#endif /* FZ_ENABLE_JPX */
#ifndef FZ_ENABLE_JS
#define FZ_ENABLE_JS 1
#endif /* FZ_ENABLE_JS */
#ifndef FZ_ENABLE_ICC
#define FZ_ENABLE_ICC 1
#endif /* FZ_ENABLE_ICC */
/* If Epub and HTML are both disabled, disable SIL fonts */
#if FZ_ENABLE_HTML == 0 && FZ_ENABLE_EPUB == 0
#undef TOFU_SIL
#define TOFU_SIL
#endif
#if !defined(HAVE_LEPTONICA) || !defined(HAVE_TESSERACT)
#ifndef OCR_DISABLED
#define OCR_DISABLED
#endif
#endif
#endif /* FZ_CONFIG_H */
+942
View File
@@ -0,0 +1,942 @@
// Copyright (C) 2004-2022 Artifex Software, Inc.
//
// This file is part of MuPDF.
//
// MuPDF is free software: you can redistribute it and/or modify it under the
// terms of the GNU Affero General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option)
// any later version.
//
// MuPDF 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 Affero General Public License for more
// details.
//
// You should have received a copy of the GNU Affero General Public License
// along with MuPDF. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html>
//
// Alternative licensing terms are available from the licensor.
// For commercial licensing, see <https://www.artifex.com/> or contact
// Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,
// CA 94129, USA, for further information.
#ifndef MUPDF_FITZ_CONTEXT_H
#define MUPDF_FITZ_CONTEXT_H
#include "mupdf/fitz/version.h"
#include "mupdf/fitz/system.h"
#include "mupdf/fitz/geometry.h"
#ifndef FZ_VERBOSE_EXCEPTIONS
#define FZ_VERBOSE_EXCEPTIONS 0
#endif
typedef struct fz_font_context fz_font_context;
typedef struct fz_colorspace_context fz_colorspace_context;
typedef struct fz_style_context fz_style_context;
typedef struct fz_tuning_context fz_tuning_context;
typedef struct fz_store fz_store;
typedef struct fz_glyph_cache fz_glyph_cache;
typedef struct fz_document_handler_context fz_document_handler_context;
typedef struct fz_output fz_output;
typedef struct fz_context fz_context;
/**
Allocator structure; holds callbacks and private data pointer.
*/
typedef struct
{
void *user;
void *(*malloc)(void *, size_t);
void *(*realloc)(void *, void *, size_t);
void (*free)(void *, void *);
} fz_alloc_context;
/**
Exception macro definitions. Just treat these as a black box -
pay no attention to the man behind the curtain.
*/
#define fz_var(var) fz_var_imp((void *)&(var))
#define fz_try(ctx) if (!fz_setjmp(*fz_push_try(ctx))) if (fz_do_try(ctx)) do
#define fz_always(ctx) while (0); if (fz_do_always(ctx)) do
#define fz_catch(ctx) while (0); if (fz_do_catch(ctx))
/**
These macros provide a simple exception handling system. Use them as
follows:
fz_try(ctx)
...
fz_catch(ctx)
...
or as:
fz_try(ctx)
...
fz_always(ctx)
...
fz_catch(ctx)
...
Code within the fz_try() section can then throw exceptions using fz_throw()
(or fz_vthrow()).
They are implemented with setjmp/longjmp, which can have unfortunate
consequences for 'losing' local variable values on a throw. To avoid this
we recommend calling 'fz_var(variable)' before the fz_try() for any
local variable whose value may change within the fz_try() block and whose
value will be required afterwards.
Do not call anything in the fz_always() section that can throw.
Any exception can be rethrown from the fz_catch() section using fz_rethrow()
as long as there has been no intervening use of fz_try/fz_catch.
*/
/**
Throw an exception.
This assumes an enclosing fz_try() block within the callstack.
*/
FZ_NORETURN void fz_vthrow(fz_context *ctx, int errcode, const char *, va_list ap);
FZ_NORETURN void fz_throw(fz_context *ctx, int errcode, const char *, ...) FZ_PRINTFLIKE(3,4);
FZ_NORETURN void fz_rethrow(fz_context *ctx);
/**
Called within a catch block this modifies the current
exception's code. If it's of type 'fromcode' it is
modified to 'tocode'. Typically used for 'downgrading'
exception severity.
*/
void fz_morph_error(fz_context *ctx, int fromcode, int tocode);
/**
Log a warning.
This goes to the registered warning stream (stderr by
default).
*/
void fz_vwarn(fz_context *ctx, const char *fmt, va_list ap);
void fz_warn(fz_context *ctx, const char *fmt, ...) FZ_PRINTFLIKE(2,3);
/**
Within an fz_catch() block, retrieve the formatted message
string for the current exception.
This assumes no intervening use of fz_try/fz_catch.
*/
const char *fz_caught_message(fz_context *ctx);
/**
Within an fz_catch() block, retrieve the error code for
the current exception.
This assumes no intervening use of fz_try/fz_catch.
*/
int fz_caught(fz_context *ctx);
/**
Within an fz_catch() block, rethrow the current exception
if the errcode of the current exception matches.
This assumes no intervening use of fz_try/fz_catch.
*/
void fz_rethrow_if(fz_context *ctx, int errcode);
/**
Format an error message, and log it to the registered
error stream (stderr by default).
*/
void fz_log_error_printf(fz_context *ctx, const char *fmt, ...) FZ_PRINTFLIKE(2,3);
void fz_vlog_error_printf(fz_context *ctx, const char *fmt, va_list ap);
/**
Log a (preformatted) string to the registered
error stream (stderr by default).
*/
void fz_log_error(fz_context *ctx, const char *str);
void fz_start_throw_on_repair(fz_context *ctx);
void fz_end_throw_on_repair(fz_context *ctx);
/**
Now, a debugging feature. If FZ_VERBOSE_EXCEPTIONS is 1 then
some of the above functions are replaced by versions that print
FILE and LINE information.
*/
#if FZ_VERBOSE_EXCEPTIONS
#define fz_vthrow(CTX, ERRCODE, FMT, VA) fz_vthrowFL(CTX, __FILE__, __LINE__, ERRCODE, FMT, VA)
#define fz_throw(CTX, ERRCODE, ...) fz_throwFL(CTX, __FILE__, __LINE__, ERRCODE, __VA_ARGS__)
#define fz_rethrow(CTX) fz_rethrowFL(CTX, __FILE__, __LINE__)
#define fz_morph_error(CTX, FROM, TO) fz_morph_errorFL(CTX, __FILE__, __LINE__, FROM, TO)
#define fz_vwarn(CTX, FMT, VA) fz_vwarnFL(CTX, __FILE__, __LINE__, FMT, VA)
#define fz_warn(CTX, ...) fz_warnFL(CTX, __FILE__, __LINE__, __VA_ARGS__)
#define fz_rethrow_if(CTX, ERRCODE) fz_rethrow_ifFL(CTX, __FILE__, __LINE__, ERRCODE)
#define fz_log_error_printf(CTX, ...) fz_log_error_printfFL(CTX, __FILE__, __LINE__, __VA_ARGS__)
#define fz_vlog_error_printf(CTX, FMT, VA) fz_log_error_printfFL(CTX, __FILE__, __LINE__, FMT, VA)
#define fz_log_error(CTX, STR) fz_log_error_printfFL(CTX, __FILE__, __LINE__, STR)
FZ_NORETURN void fz_vthrowFL(fz_context *ctx, const char *file, int line, int errcode, const char *fmt, va_list ap);
FZ_NORETURN void fz_throwFL(fz_context *ctx, const char *file, int line, int errcode, const char *fmt, ...) FZ_PRINTFLIKE(5,6);
FZ_NORETURN void fz_rethrowFL(fz_context *ctx, const char *file, int line);
void fz_morph_errorFL(fz_context *ctx, const char *file, int line, int fromcode, int tocode);
void fz_vwarnFL(fz_context *ctx, const char *file, int line, const char *fmt, va_list ap);
void fz_warnFL(fz_context *ctx, const char *file, int line, const char *fmt, ...) FZ_PRINTFLIKE(4,5);
void fz_rethrow_ifFL(fz_context *ctx, const char *file, int line, int errcode);
void fz_log_error_printfFL(fz_context *ctx, const char *file, int line, const char *fmt, ...) FZ_PRINTFLIKE(4,5);
void fz_vlog_error_printfFL(fz_context *ctx, const char *file, int line, const char *fmt, va_list ap);
void fz_log_errorFL(fz_context *ctx, const char *file, int line, const char *str);
#endif
enum
{
FZ_ERROR_NONE = 0,
FZ_ERROR_MEMORY = 1,
FZ_ERROR_GENERIC = 2,
FZ_ERROR_SYNTAX = 3,
FZ_ERROR_MINOR = 4,
FZ_ERROR_TRYLATER = 5,
FZ_ERROR_ABORT = 6,
FZ_ERROR_REPAIRED = 7,
FZ_ERROR_COUNT
};
/**
Flush any repeated warnings.
Repeated warnings are buffered, counted and eventually printed
along with the number of repetitions. Call fz_flush_warnings
to force printing of the latest buffered warning and the
number of repetitions, for example to make sure that all
warnings are printed before exiting an application.
*/
void fz_flush_warnings(fz_context *ctx);
/**
Locking functions
MuPDF is kept deliberately free of any knowledge of particular
threading systems. As such, in order for safe multi-threaded
operation, we rely on callbacks to client provided functions.
A client is expected to provide FZ_LOCK_MAX number of mutexes,
and a function to lock/unlock each of them. These may be
recursive mutexes, but do not have to be.
If a client does not intend to use multiple threads, then it
may pass NULL instead of a lock structure.
In order to avoid deadlocks, we have one simple rule
internally as to how we use locks: We can never take lock n
when we already hold any lock i, where 0 <= i <= n. In order
to verify this, we have some debugging code, that can be
enabled by defining FITZ_DEBUG_LOCKING.
*/
typedef struct
{
void *user;
void (*lock)(void *user, int lock);
void (*unlock)(void *user, int lock);
} fz_locks_context;
enum {
FZ_LOCK_ALLOC = 0,
FZ_LOCK_FREETYPE,
FZ_LOCK_GLYPHCACHE,
FZ_LOCK_MAX
};
#if defined(MEMENTO) || !defined(NDEBUG)
#define FITZ_DEBUG_LOCKING
#endif
#ifdef FITZ_DEBUG_LOCKING
void fz_assert_lock_held(fz_context *ctx, int lock);
void fz_assert_lock_not_held(fz_context *ctx, int lock);
void fz_lock_debug_lock(fz_context *ctx, int lock);
void fz_lock_debug_unlock(fz_context *ctx, int lock);
#else
#define fz_assert_lock_held(A,B) do { } while (0)
#define fz_assert_lock_not_held(A,B) do { } while (0)
#define fz_lock_debug_lock(A,B) do { } while (0)
#define fz_lock_debug_unlock(A,B) do { } while (0)
#endif /* !FITZ_DEBUG_LOCKING */
/**
Specifies the maximum size in bytes of the resource store in
fz_context. Given as argument to fz_new_context.
FZ_STORE_UNLIMITED: Let resource store grow unbounded.
FZ_STORE_DEFAULT: A reasonable upper bound on the size, for
devices that are not memory constrained.
*/
enum {
FZ_STORE_UNLIMITED = 0,
FZ_STORE_DEFAULT = 256 << 20,
};
/**
Allocate context containing global state.
The global state contains an exception stack, resource store,
etc. Most functions in MuPDF take a context argument to be
able to reference the global state. See fz_drop_context for
freeing an allocated context.
alloc: Supply a custom memory allocator through a set of
function pointers. Set to NULL for the standard library
allocator. The context will keep the allocator pointer, so the
data it points to must not be modified or freed during the
lifetime of the context.
locks: Supply a set of locks and functions to lock/unlock
them, intended for multi-threaded applications. Set to NULL
when using MuPDF in a single-threaded applications. The
context will keep the locks pointer, so the data it points to
must not be modified or freed during the lifetime of the
context.
max_store: Maximum size in bytes of the resource store, before
it will start evicting cached resources such as fonts and
images. FZ_STORE_UNLIMITED can be used if a hard limit is not
desired. Use FZ_STORE_DEFAULT to get a reasonable size.
May return NULL.
*/
#define fz_new_context(alloc, locks, max_store) fz_new_context_imp(alloc, locks, max_store, FZ_VERSION)
/**
Make a clone of an existing context.
This function is meant to be used in multi-threaded
applications where each thread requires its own context, yet
parts of the global state, for example caching, are shared.
ctx: Context obtained from fz_new_context to make a copy of.
ctx must have had locks and lock/functions setup when created.
The two contexts will share the memory allocator, resource
store, locks and lock/unlock functions. They will each have
their own exception stacks though.
May return NULL.
*/
fz_context *fz_clone_context(fz_context *ctx);
/**
Free a context and its global state.
The context and all of its global state is freed, and any
buffered warnings are flushed (see fz_flush_warnings). If NULL
is passed in nothing will happen.
Must not be called for a context that is being used in an active
fz_try(), fz_always() or fz_catch() block.
*/
void fz_drop_context(fz_context *ctx);
/**
Set the user field in the context.
NULL initially, this field can be set to any opaque value
required by the user. It is copied on clones.
*/
void fz_set_user_context(fz_context *ctx, void *user);
/**
Read the user field from the context.
*/
void *fz_user_context(fz_context *ctx);
/**
FIXME: Better not to expose fz_default_error_callback, and
fz_default_warning callback and to allow 'NULL' to be used
int fz_set_xxxx_callback to mean "defaults".
FIXME: Do we need/want functions like
fz_error_callback(ctx, message) to allow callers to inject
stuff into the error/warning streams?
*/
/**
The default error callback. Declared publicly just so that the
error callback can be set back to this after it has been
overridden.
*/
void fz_default_error_callback(void *user, const char *message);
/**
The default warning callback. Declared publicly just so that
the warning callback can be set back to this after it has been
overridden.
*/
void fz_default_warning_callback(void *user, const char *message);
/**
A callback called whenever an error message is generated.
The user pointer passed to fz_set_error_callback() is passed
along with the error message.
*/
typedef void (fz_error_cb)(void *user, const char *message);
/**
A callback called whenever a warning message is generated.
The user pointer passed to fz_set_warning_callback() is
passed along with the warning message.
*/
typedef void (fz_warning_cb)(void *user, const char *message);
/**
Set the error callback. This will be called as part of the
exception handling.
The callback must not throw exceptions!
*/
void fz_set_error_callback(fz_context *ctx, fz_error_cb *error_cb, void *user);
/**
Retrieve the currently set error callback, or NULL if none
has been set. Optionally, if user is non-NULL, the user pointer
given when the warning callback was set is also passed back to
the caller.
*/
fz_error_cb *fz_error_callback(fz_context *ctx, void **user);
/**
Set the warning callback. This will be called as part of the
exception handling.
The callback must not throw exceptions!
*/
void fz_set_warning_callback(fz_context *ctx, fz_warning_cb *warning_cb, void *user);
/**
Retrieve the currently set warning callback, or NULL if none
has been set. Optionally, if user is non-NULL, the user pointer
given when the warning callback was set is also passed back to
the caller.
*/
fz_warning_cb *fz_warning_callback(fz_context *ctx, void **user);
/**
In order to tune MuPDF's behaviour, certain functions can
(optionally) be provided by callers.
*/
/**
Given the width and height of an image,
the subsample factor, and the subarea of the image actually
required, the caller can decide whether to decode the whole
image or just a subarea.
arg: The caller supplied opaque argument.
w, h: The width/height of the complete image.
l2factor: The log2 factor for subsampling (i.e. image will be
decoded to (w>>l2factor, h>>l2factor)).
subarea: The actual subarea required for the current operation.
The tuning function is allowed to increase this in size if
required.
*/
typedef void (fz_tune_image_decode_fn)(void *arg, int w, int h, int l2factor, fz_irect *subarea);
/**
Given the source width and height of
image, together with the actual required width and height,
decide whether we should use mitchell scaling.
arg: The caller supplied opaque argument.
dst_w, dst_h: The actual width/height required on the target
device.
src_w, src_h: The source width/height of the image.
Return 0 not to use the Mitchell scaler, 1 to use the Mitchell
scaler. All other values reserved.
*/
typedef int (fz_tune_image_scale_fn)(void *arg, int dst_w, int dst_h, int src_w, int src_h);
/**
Set the tuning function to use for
image decode.
image_decode: Function to use.
arg: Opaque argument to be passed to tuning function.
*/
void fz_tune_image_decode(fz_context *ctx, fz_tune_image_decode_fn *image_decode, void *arg);
/**
Set the tuning function to use for
image scaling.
image_scale: Function to use.
arg: Opaque argument to be passed to tuning function.
*/
void fz_tune_image_scale(fz_context *ctx, fz_tune_image_scale_fn *image_scale, void *arg);
/**
Get the number of bits of antialiasing we are
using (for graphics). Between 0 and 8.
*/
int fz_aa_level(fz_context *ctx);
/**
Set the number of bits of antialiasing we should
use (for both text and graphics).
bits: The number of bits of antialiasing to use (values are
clamped to within the 0 to 8 range).
*/
void fz_set_aa_level(fz_context *ctx, int bits);
/**
Get the number of bits of antialiasing we are
using for text. Between 0 and 8.
*/
int fz_text_aa_level(fz_context *ctx);
/**
Set the number of bits of antialiasing we
should use for text.
bits: The number of bits of antialiasing to use (values are
clamped to within the 0 to 8 range).
*/
void fz_set_text_aa_level(fz_context *ctx, int bits);
/**
Get the number of bits of antialiasing we are
using for graphics. Between 0 and 8.
*/
int fz_graphics_aa_level(fz_context *ctx);
/**
Set the number of bits of antialiasing we
should use for graphics.
bits: The number of bits of antialiasing to use (values are
clamped to within the 0 to 8 range).
*/
void fz_set_graphics_aa_level(fz_context *ctx, int bits);
/**
Get the minimum line width to be
used for stroked lines.
min_line_width: The minimum line width to use (in pixels).
*/
float fz_graphics_min_line_width(fz_context *ctx);
/**
Set the minimum line width to be
used for stroked lines.
min_line_width: The minimum line width to use (in pixels).
*/
void fz_set_graphics_min_line_width(fz_context *ctx, float min_line_width);
/**
Get the user stylesheet source text.
*/
const char *fz_user_css(fz_context *ctx);
/**
Set the user stylesheet source text for use with HTML and EPUB.
*/
void fz_set_user_css(fz_context *ctx, const char *text);
/**
Return whether to respect document styles in HTML and EPUB.
*/
int fz_use_document_css(fz_context *ctx);
/**
Toggle whether to respect document styles in HTML and EPUB.
*/
void fz_set_use_document_css(fz_context *ctx, int use);
/**
Enable icc profile based operation.
*/
void fz_enable_icc(fz_context *ctx);
/**
Disable icc profile based operation.
*/
void fz_disable_icc(fz_context *ctx);
/**
Memory Allocation and Scavenging:
All calls to MuPDF's allocator functions pass through to the
underlying allocators passed in when the initial context is
created, after locks are taken (using the supplied locking
function) to ensure that only one thread at a time calls
through.
If the underlying allocator fails, MuPDF attempts to make room
for the allocation by evicting elements from the store, then
retrying.
Any call to allocate may then result in several calls to the
underlying allocator, and result in elements that are only
referred to by the store being freed.
*/
/**
Allocate memory for a structure, clear it, and tag the pointer
for Memento.
Throws exception in the event of failure to allocate.
*/
#define fz_malloc_struct(CTX, TYPE) \
((TYPE*)Memento_label(fz_calloc(CTX, 1, sizeof(TYPE)), #TYPE))
/**
Allocate memory for an array of structures, clear it, and tag
the pointer for Memento.
Throws exception in the event of failure to allocate.
*/
#define fz_malloc_struct_array(CTX, N, TYPE) \
((TYPE*)Memento_label(fz_calloc(CTX, N, sizeof(TYPE)), #TYPE "[]"))
/**
Allocate uninitialized memory for an array of structures, and
tag the pointer for Memento. Does NOT clear the memory!
Throws exception in the event of failure to allocate.
*/
#define fz_malloc_array(CTX, COUNT, TYPE) \
((TYPE*)Memento_label(fz_malloc(CTX, (COUNT) * sizeof(TYPE)), #TYPE "[]"))
#define fz_realloc_array(CTX, OLD, COUNT, TYPE) \
((TYPE*)Memento_label(fz_realloc(CTX, OLD, (COUNT) * sizeof(TYPE)), #TYPE "[]"))
/**
Allocate uninitialized memory of a given size.
Does NOT clear the memory!
May return NULL for size = 0.
Throws exception in the event of failure to allocate.
*/
void *fz_malloc(fz_context *ctx, size_t size);
/**
Allocate array of memory of count entries of size bytes.
Clears the memory to zero.
Throws exception in the event of failure to allocate.
*/
void *fz_calloc(fz_context *ctx, size_t count, size_t size);
/**
Reallocates a block of memory to given size. Existing contents
up to min(old_size,new_size) are maintained. The rest of the
block is uninitialised.
fz_realloc(ctx, NULL, size) behaves like fz_malloc(ctx, size).
fz_realloc(ctx, p, 0); behaves like fz_free(ctx, p).
Throws exception in the event of failure to allocate.
*/
void *fz_realloc(fz_context *ctx, void *p, size_t size);
/**
Free a previously allocated block of memory.
fz_free(ctx, NULL) does nothing.
Never throws exceptions.
*/
void fz_free(fz_context *ctx, void *p);
/**
fz_malloc equivalent that returns NULL rather than throwing
exceptions.
*/
void *fz_malloc_no_throw(fz_context *ctx, size_t size);
/**
fz_calloc equivalent that returns NULL rather than throwing
exceptions.
*/
void *fz_calloc_no_throw(fz_context *ctx, size_t count, size_t size);
/**
fz_realloc equivalent that returns NULL rather than throwing
exceptions.
*/
void *fz_realloc_no_throw(fz_context *ctx, void *p, size_t size);
/**
Portable strdup implementation, using fz allocators.
*/
char *fz_strdup(fz_context *ctx, const char *s);
/**
Fill block with len bytes of pseudo-randomness.
*/
void fz_memrnd(fz_context *ctx, uint8_t *block, int len);
/* Implementation details: subject to change. */
/* Implementations exposed for speed, but considered private. */
void fz_var_imp(void *);
fz_jmp_buf *fz_push_try(fz_context *ctx);
int fz_do_try(fz_context *ctx);
int fz_do_always(fz_context *ctx);
int fz_do_catch(fz_context *ctx);
#ifndef FZ_JMPBUF_ALIGN
#define FZ_JMPBUF_ALIGN 32
#endif
typedef struct
{
fz_jmp_buf buffer;
int state, code;
char padding[FZ_JMPBUF_ALIGN-sizeof(int)*2];
} fz_error_stack_slot;
typedef struct
{
fz_error_stack_slot *top;
fz_error_stack_slot stack[256];
fz_error_stack_slot padding;
fz_error_stack_slot *stack_base;
int errcode;
void *print_user;
void (*print)(void *user, const char *message);
char message[256];
} fz_error_context;
typedef struct
{
void *print_user;
void (*print)(void *user, const char *message);
int count;
char message[256];
} fz_warn_context;
typedef struct
{
int hscale;
int vscale;
int scale;
int bits;
int text_bits;
float min_line_width;
} fz_aa_context;
struct fz_context
{
void *user;
fz_alloc_context alloc;
fz_locks_context locks;
fz_error_context error;
fz_warn_context warn;
/* unshared contexts */
fz_aa_context aa;
uint16_t seed48[7];
#if FZ_ENABLE_ICC
int icc_enabled;
#endif
int throw_on_repair;
/* TODO: should these be unshared? */
fz_document_handler_context *handler;
fz_style_context *style;
fz_tuning_context *tuning;
/* shared contexts */
fz_output *stddbg;
fz_font_context *font;
fz_colorspace_context *colorspace;
fz_store *store;
fz_glyph_cache *glyph_cache;
};
fz_context *fz_new_context_imp(const fz_alloc_context *alloc, const fz_locks_context *locks, size_t max_store, const char *version);
/**
Lock one of the user supplied mutexes.
*/
static inline void
fz_lock(fz_context *ctx, int lock)
{
fz_lock_debug_lock(ctx, lock);
ctx->locks.lock(ctx->locks.user, lock);
}
/**
Unlock one of the user supplied mutexes.
*/
static inline void
fz_unlock(fz_context *ctx, int lock)
{
fz_lock_debug_unlock(ctx, lock);
ctx->locks.unlock(ctx->locks.user, lock);
}
/* Lock-safe reference counting functions */
static inline void *
fz_keep_imp(fz_context *ctx, void *p, int *refs)
{
if (p)
{
(void)Memento_checkIntPointerOrNull(refs);
fz_lock(ctx, FZ_LOCK_ALLOC);
if (*refs > 0)
{
(void)Memento_takeRef(p);
++*refs;
}
fz_unlock(ctx, FZ_LOCK_ALLOC);
}
return p;
}
static inline void *
fz_keep_imp_locked(fz_context *ctx FZ_UNUSED, void *p, int *refs)
{
if (p)
{
(void)Memento_checkIntPointerOrNull(refs);
if (*refs > 0)
{
(void)Memento_takeRef(p);
++*refs;
}
}
return p;
}
static inline void *
fz_keep_imp8_locked(fz_context *ctx FZ_UNUSED, void *p, int8_t *refs)
{
if (p)
{
(void)Memento_checkIntPointerOrNull(refs);
if (*refs > 0)
{
(void)Memento_takeRef(p);
++*refs;
}
}
return p;
}
static inline void *
fz_keep_imp8(fz_context *ctx, void *p, int8_t *refs)
{
if (p)
{
(void)Memento_checkBytePointerOrNull(refs);
fz_lock(ctx, FZ_LOCK_ALLOC);
if (*refs > 0)
{
(void)Memento_takeRef(p);
++*refs;
}
fz_unlock(ctx, FZ_LOCK_ALLOC);
}
return p;
}
static inline void *
fz_keep_imp16(fz_context *ctx, void *p, int16_t *refs)
{
if (p)
{
(void)Memento_checkShortPointerOrNull(refs);
fz_lock(ctx, FZ_LOCK_ALLOC);
if (*refs > 0)
{
(void)Memento_takeRef(p);
++*refs;
}
fz_unlock(ctx, FZ_LOCK_ALLOC);
}
return p;
}
static inline int
fz_drop_imp(fz_context *ctx, void *p, int *refs)
{
if (p)
{
int drop;
(void)Memento_checkIntPointerOrNull(refs);
fz_lock(ctx, FZ_LOCK_ALLOC);
if (*refs > 0)
{
(void)Memento_dropIntRef(p);
drop = --*refs == 0;
}
else
drop = 0;
fz_unlock(ctx, FZ_LOCK_ALLOC);
return drop;
}
return 0;
}
static inline int
fz_drop_imp8(fz_context *ctx, void *p, int8_t *refs)
{
if (p)
{
int drop;
(void)Memento_checkBytePointerOrNull(refs);
fz_lock(ctx, FZ_LOCK_ALLOC);
if (*refs > 0)
{
(void)Memento_dropByteRef(p);
drop = --*refs == 0;
}
else
drop = 0;
fz_unlock(ctx, FZ_LOCK_ALLOC);
return drop;
}
return 0;
}
static inline int
fz_drop_imp16(fz_context *ctx, void *p, int16_t *refs)
{
if (p)
{
int drop;
(void)Memento_checkShortPointerOrNull(refs);
fz_lock(ctx, FZ_LOCK_ALLOC);
if (*refs > 0)
{
(void)Memento_dropShortRef(p);
drop = --*refs == 0;
}
else
drop = 0;
fz_unlock(ctx, FZ_LOCK_ALLOC);
return drop;
}
return 0;
}
#endif
+270
View File
@@ -0,0 +1,270 @@
// Copyright (C) 2004-2021 Artifex Software, Inc.
//
// This file is part of MuPDF.
//
// MuPDF is free software: you can redistribute it and/or modify it under the
// terms of the GNU Affero General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option)
// any later version.
//
// MuPDF 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 Affero General Public License for more
// details.
//
// You should have received a copy of the GNU Affero General Public License
// along with MuPDF. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html>
//
// Alternative licensing terms are available from the licensor.
// For commercial licensing, see <https://www.artifex.com/> or contact
// Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,
// CA 94129, USA, for further information.
#ifndef MUPDF_FITZ_CRYPT_H
#define MUPDF_FITZ_CRYPT_H
#include "mupdf/fitz/system.h"
/* md5 digests */
/**
Structure definition is public to enable stack
based allocation. Do not access the members directly.
*/
typedef struct
{
uint32_t lo, hi;
uint32_t a, b, c, d;
unsigned char buffer[64];
} fz_md5;
/**
MD5 initialization. Begins an MD5 operation, writing a new
context.
Never throws an exception.
*/
void fz_md5_init(fz_md5 *state);
/**
MD5 block update operation. Continues an MD5 message-digest
operation, processing another message block, and updating the
context.
Never throws an exception.
*/
void fz_md5_update(fz_md5 *state, const unsigned char *input, size_t inlen);
/**
MD5 block update operation. Continues an MD5 message-digest
operation, processing an int64, and updating the context.
Never throws an exception.
*/
void fz_md5_update_int64(fz_md5 *state, int64_t i);
/**
MD5 finalization. Ends an MD5 message-digest operation, writing
the message digest and zeroizing the context.
Never throws an exception.
*/
void fz_md5_final(fz_md5 *state, unsigned char digest[16]);
/* sha-256 digests */
/**
Structure definition is public to enable stack
based allocation. Do not access the members directly.
*/
typedef struct
{
unsigned int state[8];
unsigned int count[2];
union {
unsigned char u8[64];
unsigned int u32[16];
} buffer;
} fz_sha256;
/**
SHA256 initialization. Begins an SHA256 operation, initialising
the supplied context.
Never throws an exception.
*/
void fz_sha256_init(fz_sha256 *state);
/**
SHA256 block update operation. Continues an SHA256 message-
digest operation, processing another message block, and updating
the context.
Never throws an exception.
*/
void fz_sha256_update(fz_sha256 *state, const unsigned char *input, size_t inlen);
/**
MD5 finalization. Ends an MD5 message-digest operation, writing
the message digest and zeroizing the context.
Never throws an exception.
*/
void fz_sha256_final(fz_sha256 *state, unsigned char digest[32]);
/* sha-512 digests */
/**
Structure definition is public to enable stack
based allocation. Do not access the members directly.
*/
typedef struct
{
uint64_t state[8];
unsigned int count[2];
union {
unsigned char u8[128];
uint64_t u64[16];
} buffer;
} fz_sha512;
/**
SHA512 initialization. Begins an SHA512 operation, initialising
the supplied context.
Never throws an exception.
*/
void fz_sha512_init(fz_sha512 *state);
/**
SHA512 block update operation. Continues an SHA512 message-
digest operation, processing another message block, and updating
the context.
Never throws an exception.
*/
void fz_sha512_update(fz_sha512 *state, const unsigned char *input, size_t inlen);
/**
SHA512 finalization. Ends an SHA512 message-digest operation,
writing the message digest and zeroizing the context.
Never throws an exception.
*/
void fz_sha512_final(fz_sha512 *state, unsigned char digest[64]);
/* sha-384 digests */
typedef fz_sha512 fz_sha384;
/**
SHA384 initialization. Begins an SHA384 operation, initialising
the supplied context.
Never throws an exception.
*/
void fz_sha384_init(fz_sha384 *state);
/**
SHA384 block update operation. Continues an SHA384 message-
digest operation, processing another message block, and updating
the context.
Never throws an exception.
*/
void fz_sha384_update(fz_sha384 *state, const unsigned char *input, size_t inlen);
/**
SHA384 finalization. Ends an SHA384 message-digest operation,
writing the message digest and zeroizing the context.
Never throws an exception.
*/
void fz_sha384_final(fz_sha384 *state, unsigned char digest[64]);
/* arc4 crypto */
/**
Structure definition is public to enable stack
based allocation. Do not access the members directly.
*/
typedef struct
{
unsigned x;
unsigned y;
unsigned char state[256];
} fz_arc4;
/**
RC4 initialization. Begins an RC4 operation, writing a new
context.
Never throws an exception.
*/
void fz_arc4_init(fz_arc4 *state, const unsigned char *key, size_t len);
/**
RC4 block encrypt operation; encrypt src into dst (both of
length len) updating the RC4 state as we go.
Never throws an exception.
*/
void fz_arc4_encrypt(fz_arc4 *state, unsigned char *dest, const unsigned char *src, size_t len);
/**
RC4 finalization. Zero the context.
Never throws an exception.
*/
void fz_arc4_final(fz_arc4 *state);
/* AES block cipher implementation from XYSSL */
/**
Structure definitions are public to enable stack
based allocation. Do not access the members directly.
*/
typedef struct
{
int nr; /* number of rounds */
uint32_t *rk; /* AES round keys */
uint32_t buf[68]; /* unaligned data */
} fz_aes;
#define FZ_AES_DECRYPT 0
#define FZ_AES_ENCRYPT 1
/**
AES encryption intialisation. Fills in the supplied context
and prepares for encryption using the given key.
Returns non-zero for error (key size other than 128/192/256).
Never throws an exception.
*/
int fz_aes_setkey_enc(fz_aes *ctx, const unsigned char *key, int keysize);
/**
AES decryption intialisation. Fills in the supplied context
and prepares for decryption using the given key.
Returns non-zero for error (key size other than 128/192/256).
Never throws an exception.
*/
int fz_aes_setkey_dec(fz_aes *ctx, const unsigned char *key, int keysize);
/**
AES block processing. Encrypts or Decrypts (according to mode,
which must match what was initially set up) length bytes (which
must be a multiple of 16), using (and modifying) the insertion
vector iv, reading from input, and writing to output.
Never throws an exception.
*/
void fz_aes_crypt_cbc(fz_aes *ctx, int mode, size_t length,
unsigned char iv[16],
const unsigned char *input,
unsigned char *output );
#endif
+595
View File
@@ -0,0 +1,595 @@
// Copyright (C) 2004-2023 Artifex Software, Inc.
//
// This file is part of MuPDF.
//
// MuPDF is free software: you can redistribute it and/or modify it under the
// terms of the GNU Affero General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option)
// any later version.
//
// MuPDF 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 Affero General Public License for more
// details.
//
// You should have received a copy of the GNU Affero General Public License
// along with MuPDF. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html>
//
// Alternative licensing terms are available from the licensor.
// For commercial licensing, see <https://www.artifex.com/> or contact
// Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,
// CA 94129, USA, for further information.
#ifndef MUPDF_FITZ_DEVICE_H
#define MUPDF_FITZ_DEVICE_H
#include "mupdf/fitz/system.h"
#include "mupdf/fitz/context.h"
#include "mupdf/fitz/geometry.h"
#include "mupdf/fitz/image.h"
#include "mupdf/fitz/shade.h"
#include "mupdf/fitz/path.h"
#include "mupdf/fitz/text.h"
/**
The different format handlers (pdf, xps etc) interpret pages to
a device. These devices can then process the stream of calls
they receive in various ways:
The trace device outputs debugging information for the calls.
The draw device will render them.
The list device stores them in a list to play back later.
The text device performs text extraction and searching.
The bbox device calculates the bounding box for the page.
Other devices can (and will) be written in the future.
*/
typedef struct fz_device fz_device;
enum
{
/* Flags */
FZ_DEVFLAG_MASK = 1,
FZ_DEVFLAG_COLOR = 2,
FZ_DEVFLAG_UNCACHEABLE = 4,
FZ_DEVFLAG_FILLCOLOR_UNDEFINED = 8,
FZ_DEVFLAG_STROKECOLOR_UNDEFINED = 16,
FZ_DEVFLAG_STARTCAP_UNDEFINED = 32,
FZ_DEVFLAG_DASHCAP_UNDEFINED = 64,
FZ_DEVFLAG_ENDCAP_UNDEFINED = 128,
FZ_DEVFLAG_LINEJOIN_UNDEFINED = 256,
FZ_DEVFLAG_MITERLIMIT_UNDEFINED = 512,
FZ_DEVFLAG_LINEWIDTH_UNDEFINED = 1024,
/* Arguably we should have a bit for the dash pattern itself
* being undefined, but that causes problems; do we assume that
* it should always be set to non-dashing at the start of every
* glyph? */
FZ_DEVFLAG_BBOX_DEFINED = 2048,
FZ_DEVFLAG_GRIDFIT_AS_TILED = 4096,
};
enum
{
/* PDF 1.4 -- standard separable */
FZ_BLEND_NORMAL,
FZ_BLEND_MULTIPLY,
FZ_BLEND_SCREEN,
FZ_BLEND_OVERLAY,
FZ_BLEND_DARKEN,
FZ_BLEND_LIGHTEN,
FZ_BLEND_COLOR_DODGE,
FZ_BLEND_COLOR_BURN,
FZ_BLEND_HARD_LIGHT,
FZ_BLEND_SOFT_LIGHT,
FZ_BLEND_DIFFERENCE,
FZ_BLEND_EXCLUSION,
/* PDF 1.4 -- standard non-separable */
FZ_BLEND_HUE,
FZ_BLEND_SATURATION,
FZ_BLEND_COLOR,
FZ_BLEND_LUMINOSITY,
/* For packing purposes */
FZ_BLEND_MODEMASK = 15,
FZ_BLEND_ISOLATED = 16,
FZ_BLEND_KNOCKOUT = 32
};
/**
Map from (case sensitive) blend mode string to enumeration.
*/
int fz_lookup_blendmode(const char *name);
/**
Map from enumeration to blend mode string.
The string is static, with arbitrary lifespan.
*/
const char *fz_blendmode_name(int blendmode);
/**
The device structure is public to allow devices to be
implemented outside of fitz.
Device methods should always be called using e.g.
fz_fill_path(ctx, dev, ...) rather than
dev->fill_path(ctx, dev, ...)
*/
/**
Devices can keep track of containers (clips/masks/groups/tiles)
as they go to save callers having to do it.
*/
typedef struct
{
fz_rect scissor;
int type;
int user;
} fz_device_container_stack;
enum
{
fz_device_container_stack_is_clip,
fz_device_container_stack_is_mask,
fz_device_container_stack_is_group,
fz_device_container_stack_is_tile,
};
/* Structure types */
typedef enum
{
FZ_STRUCTURE_INVALID = -1,
/* Grouping elements (PDF 1.7 - Table 10.20) */
FZ_STRUCTURE_DOCUMENT,
FZ_STRUCTURE_PART,
FZ_STRUCTURE_ART,
FZ_STRUCTURE_SECT,
FZ_STRUCTURE_DIV,
FZ_STRUCTURE_BLOCKQUOTE,
FZ_STRUCTURE_CAPTION,
FZ_STRUCTURE_TOC,
FZ_STRUCTURE_TOCI,
FZ_STRUCTURE_INDEX,
FZ_STRUCTURE_NONSTRUCT,
FZ_STRUCTURE_PRIVATE,
/* Grouping elements (PDF 2.0 - Table 364) */
FZ_STRUCTURE_DOCUMENTFRAGMENT,
/* Grouping elements (PDF 2.0 - Table 365) */
FZ_STRUCTURE_ASIDE,
/* Grouping elements (PDF 2.0 - Table 366) */
FZ_STRUCTURE_TITLE,
FZ_STRUCTURE_FENOTE,
/* Grouping elements (PDF 2.0 - Table 367) */
FZ_STRUCTURE_SUB,
/* Paragraphlike elements (PDF 1.7 - Table 10.21) */
FZ_STRUCTURE_P,
FZ_STRUCTURE_H,
FZ_STRUCTURE_H1,
FZ_STRUCTURE_H2,
FZ_STRUCTURE_H3,
FZ_STRUCTURE_H4,
FZ_STRUCTURE_H5,
FZ_STRUCTURE_H6,
/* List elements (PDF 1.7 - Table 10.23) */
FZ_STRUCTURE_LIST,
FZ_STRUCTURE_LISTITEM,
FZ_STRUCTURE_LABEL,
FZ_STRUCTURE_LISTBODY,
/* Table elements (PDF 1.7 - Table 10.24) */
FZ_STRUCTURE_TABLE,
FZ_STRUCTURE_TR,
FZ_STRUCTURE_TH,
FZ_STRUCTURE_TD,
FZ_STRUCTURE_THEAD,
FZ_STRUCTURE_TBODY,
FZ_STRUCTURE_TFOOT,
/* Inline elements (PDF 1.7 - Table 10.25) */
FZ_STRUCTURE_SPAN,
FZ_STRUCTURE_QUOTE,
FZ_STRUCTURE_NOTE,
FZ_STRUCTURE_REFERENCE,
FZ_STRUCTURE_BIBENTRY,
FZ_STRUCTURE_CODE,
FZ_STRUCTURE_LINK,
FZ_STRUCTURE_ANNOT,
/* Inline elements (PDF 2.0 - Table 368) */
FZ_STRUCTURE_EM,
FZ_STRUCTURE_STRONG,
/* Ruby inline element (PDF 1.7 - Table 10.26) */
FZ_STRUCTURE_RUBY,
FZ_STRUCTURE_RB,
FZ_STRUCTURE_RT,
FZ_STRUCTURE_RP,
/* Warichu inline element (PDF 1.7 - Table 10.26) */
FZ_STRUCTURE_WARICHU,
FZ_STRUCTURE_WT,
FZ_STRUCTURE_WP,
/* Illustration elements (PDF 1.7 - Table 10.27) */
FZ_STRUCTURE_FIGURE,
FZ_STRUCTURE_FORMULA,
FZ_STRUCTURE_FORM,
/* Artifact structure type (PDF 2.0 - Table 375) */
FZ_STRUCTURE_ARTIFACT
} fz_structure;
const char *fz_structure_to_string(fz_structure type);
fz_structure fz_structure_from_string(const char *str);
typedef enum
{
FZ_METATEXT_ACTUALTEXT,
FZ_METATEXT_ALT,
FZ_METATEXT_ABBREVIATION,
FZ_METATEXT_TITLE
} fz_metatext;
struct fz_device
{
int refs;
int hints;
int flags;
void (*close_device)(fz_context *, fz_device *);
void (*drop_device)(fz_context *, fz_device *);
void (*fill_path)(fz_context *, fz_device *, const fz_path *, int even_odd, fz_matrix, fz_colorspace *, const float *color, float alpha, fz_color_params );
void (*stroke_path)(fz_context *, fz_device *, const fz_path *, const fz_stroke_state *, fz_matrix, fz_colorspace *, const float *color, float alpha, fz_color_params );
void (*clip_path)(fz_context *, fz_device *, const fz_path *, int even_odd, fz_matrix, fz_rect scissor);
void (*clip_stroke_path)(fz_context *, fz_device *, const fz_path *, const fz_stroke_state *, fz_matrix, fz_rect scissor);
void (*fill_text)(fz_context *, fz_device *, const fz_text *, fz_matrix, fz_colorspace *, const float *color, float alpha, fz_color_params );
void (*stroke_text)(fz_context *, fz_device *, const fz_text *, const fz_stroke_state *, fz_matrix, fz_colorspace *, const float *color, float alpha, fz_color_params );
void (*clip_text)(fz_context *, fz_device *, const fz_text *, fz_matrix, fz_rect scissor);
void (*clip_stroke_text)(fz_context *, fz_device *, const fz_text *, const fz_stroke_state *, fz_matrix, fz_rect scissor);
void (*ignore_text)(fz_context *, fz_device *, const fz_text *, fz_matrix );
void (*fill_shade)(fz_context *, fz_device *, fz_shade *shd, fz_matrix ctm, float alpha, fz_color_params color_params);
void (*fill_image)(fz_context *, fz_device *, fz_image *img, fz_matrix ctm, float alpha, fz_color_params color_params);
void (*fill_image_mask)(fz_context *, fz_device *, fz_image *img, fz_matrix ctm, fz_colorspace *, const float *color, float alpha, fz_color_params color_params);
void (*clip_image_mask)(fz_context *, fz_device *, fz_image *img, fz_matrix ctm, fz_rect scissor);
void (*pop_clip)(fz_context *, fz_device *);
void (*begin_mask)(fz_context *, fz_device *, fz_rect area, int luminosity, fz_colorspace *, const float *bc, fz_color_params );
void (*end_mask)(fz_context *, fz_device *);
void (*begin_group)(fz_context *, fz_device *, fz_rect area, fz_colorspace *cs, int isolated, int knockout, int blendmode, float alpha);
void (*end_group)(fz_context *, fz_device *);
int (*begin_tile)(fz_context *, fz_device *, fz_rect area, fz_rect view, float xstep, float ystep, fz_matrix ctm, int id);
void (*end_tile)(fz_context *, fz_device *);
void (*render_flags)(fz_context *, fz_device *, int set, int clear);
void (*set_default_colorspaces)(fz_context *, fz_device *, fz_default_colorspaces *);
void (*begin_layer)(fz_context *, fz_device *, const char *layer_name);
void (*end_layer)(fz_context *, fz_device *);
void (*begin_structure)(fz_context *, fz_device *, fz_structure standard, const char *raw, int uid);
void (*end_structure)(fz_context *, fz_device *);
void (*begin_metatext)(fz_context *, fz_device *, fz_metatext meta, const char *text);
void (*end_metatext)(fz_context *, fz_device *);
fz_rect d1_rect;
int container_len;
int container_cap;
fz_device_container_stack *container;
};
/**
Device calls; graphics primitives and containers.
*/
void fz_fill_path(fz_context *ctx, fz_device *dev, const fz_path *path, int even_odd, fz_matrix ctm, fz_colorspace *colorspace, const float *color, float alpha, fz_color_params color_params);
void fz_stroke_path(fz_context *ctx, fz_device *dev, const fz_path *path, const fz_stroke_state *stroke, fz_matrix ctm, fz_colorspace *colorspace, const float *color, float alpha, fz_color_params color_params);
void fz_clip_path(fz_context *ctx, fz_device *dev, const fz_path *path, int even_odd, fz_matrix ctm, fz_rect scissor);
void fz_clip_stroke_path(fz_context *ctx, fz_device *dev, const fz_path *path, const fz_stroke_state *stroke, fz_matrix ctm, fz_rect scissor);
void fz_fill_text(fz_context *ctx, fz_device *dev, const fz_text *text, fz_matrix ctm, fz_colorspace *colorspace, const float *color, float alpha, fz_color_params color_params);
void fz_stroke_text(fz_context *ctx, fz_device *dev, const fz_text *text, const fz_stroke_state *stroke, fz_matrix ctm, fz_colorspace *colorspace, const float *color, float alpha, fz_color_params color_params);
void fz_clip_text(fz_context *ctx, fz_device *dev, const fz_text *text, fz_matrix ctm, fz_rect scissor);
void fz_clip_stroke_text(fz_context *ctx, fz_device *dev, const fz_text *text, const fz_stroke_state *stroke, fz_matrix ctm, fz_rect scissor);
void fz_ignore_text(fz_context *ctx, fz_device *dev, const fz_text *text, fz_matrix ctm);
void fz_pop_clip(fz_context *ctx, fz_device *dev);
void fz_fill_shade(fz_context *ctx, fz_device *dev, fz_shade *shade, fz_matrix ctm, float alpha, fz_color_params color_params);
void fz_fill_image(fz_context *ctx, fz_device *dev, fz_image *image, fz_matrix ctm, float alpha, fz_color_params color_params);
void fz_fill_image_mask(fz_context *ctx, fz_device *dev, fz_image *image, fz_matrix ctm, fz_colorspace *colorspace, const float *color, float alpha, fz_color_params color_params);
void fz_clip_image_mask(fz_context *ctx, fz_device *dev, fz_image *image, fz_matrix ctm, fz_rect scissor);
void fz_begin_mask(fz_context *ctx, fz_device *dev, fz_rect area, int luminosity, fz_colorspace *colorspace, const float *bc, fz_color_params color_params);
void fz_end_mask(fz_context *ctx, fz_device *dev);
void fz_begin_group(fz_context *ctx, fz_device *dev, fz_rect area, fz_colorspace *cs, int isolated, int knockout, int blendmode, float alpha);
void fz_end_group(fz_context *ctx, fz_device *dev);
void fz_begin_tile(fz_context *ctx, fz_device *dev, fz_rect area, fz_rect view, float xstep, float ystep, fz_matrix ctm);
int fz_begin_tile_id(fz_context *ctx, fz_device *dev, fz_rect area, fz_rect view, float xstep, float ystep, fz_matrix ctm, int id);
void fz_end_tile(fz_context *ctx, fz_device *dev);
void fz_render_flags(fz_context *ctx, fz_device *dev, int set, int clear);
void fz_set_default_colorspaces(fz_context *ctx, fz_device *dev, fz_default_colorspaces *default_cs);
void fz_begin_layer(fz_context *ctx, fz_device *dev, const char *layer_name);
void fz_end_layer(fz_context *ctx, fz_device *dev);
void fz_begin_structure(fz_context *ctx, fz_device *dev, fz_structure standard, const char *raw, int uid);
void fz_end_structure(fz_context *ctx, fz_device *dev);
void fz_begin_metatext(fz_context *ctx, fz_device *dev, fz_metatext meta, const char *text);
void fz_end_metatext(fz_context *ctx, fz_device *dev);
/**
Devices are created by calls to device implementations, for
instance: foo_new_device(). These will be implemented by calling
fz_new_derived_device(ctx, foo_device) where foo_device is a
structure "derived from" fz_device, for instance
typedef struct { fz_device base; ...extras...} foo_device;
*/
fz_device *fz_new_device_of_size(fz_context *ctx, int size);
#define fz_new_derived_device(CTX, TYPE) \
((TYPE *)Memento_label(fz_new_device_of_size(ctx,sizeof(TYPE)),#TYPE))
/**
Signal the end of input, and flush any buffered output.
This is NOT called implicitly on fz_drop_device. This
may throw exceptions.
*/
void fz_close_device(fz_context *ctx, fz_device *dev);
/**
Reduce the reference count on a device. When the reference count
reaches zero, the device and its resources will be freed.
Don't forget to call fz_close_device before dropping the device,
or you may get incomplete output!
Never throws exceptions.
*/
void fz_drop_device(fz_context *ctx, fz_device *dev);
/**
Increment the reference count for a device. Returns the same
pointer.
Never throws exceptions.
*/
fz_device *fz_keep_device(fz_context *ctx, fz_device *dev);
/**
Enable (set) hint bits within the hint bitfield for a device.
*/
void fz_enable_device_hints(fz_context *ctx, fz_device *dev, int hints);
/**
Disable (clear) hint bits within the hint bitfield for a device.
*/
void fz_disable_device_hints(fz_context *ctx, fz_device *dev, int hints);
/**
Find current scissor region as tracked by the device.
*/
fz_rect fz_device_current_scissor(fz_context *ctx, fz_device *dev);
enum
{
/* Hints */
FZ_DONT_INTERPOLATE_IMAGES = 1,
FZ_NO_CACHE = 2,
};
/**
Cookie support - simple communication channel between app/library.
*/
/**
Provide two-way communication between application and library.
Intended for multi-threaded applications where one thread is
rendering pages and another thread wants to read progress
feedback or abort a job that takes a long time to finish. The
communication is unsynchronized without locking.
abort: The application should set this field to 0 before
calling fz_run_page to render a page. At any point when the
page is being rendered the application my set this field to 1
which will cause the rendering to finish soon. This field is
checked periodically when the page is rendered, but exactly
when is not known, therefore there is no upper bound on
exactly when the rendering will abort. If the application
did not provide a set of locks to fz_new_context, it must also
await the completion of fz_run_page before issuing another
call to fz_run_page. Note that once the application has set
this field to 1 after it called fz_run_page it may not change
the value again.
progress: Communicates rendering progress back to the
application and is read only. Increments as a page is being
rendered. The value starts out at 0 and is limited to less
than or equal to progress_max, unless progress_max is -1.
progress_max: Communicates the known upper bound of rendering
back to the application and is read only. The maximum value
that the progress field may take. If there is no known upper
bound on how long the rendering may take this value is -1 and
progress is not limited. Note that the value of progress_max
may change from -1 to a positive value once an upper bound is
known, so take this into consideration when comparing the
value of progress to that of progress_max.
errors: count of errors during current rendering.
incomplete: Initially should be set to 0. Will be set to
non-zero if a TRYLATER error is thrown during rendering.
*/
typedef struct
{
int abort;
int progress;
size_t progress_max; /* (size_t)-1 for unknown */
int errors;
int incomplete;
} fz_cookie;
/**
Create a device to print a debug trace of all device calls.
*/
fz_device *fz_new_trace_device(fz_context *ctx, fz_output *out);
/**
Create a device to output raw information.
*/
fz_device *fz_new_xmltext_device(fz_context *ctx, fz_output *out);
/**
Create a device to compute the bounding
box of all marks on a page.
The returned bounding box will be the union of all bounding
boxes of all objects on a page.
*/
fz_device *fz_new_bbox_device(fz_context *ctx, fz_rect *rectp);
/**
Create a device to test for features.
Currently only tests for the presence of non-grayscale colors.
is_color: Possible values returned:
0: Definitely greyscale
1: Probably color (all colors were grey, but there
were images or shadings in a non grey colorspace).
2: Definitely color
threshold: The difference from grayscale that will be tolerated.
Typical values to use are either 0 (be exact) and 0.02 (allow an
imperceptible amount of slop).
options: A set of bitfield options, from the FZ_TEST_OPT set.
passthrough: A device to pass all calls through to, or NULL.
If set, then the test device can both test and pass through to
an underlying device (like, say, the display list device). This
means that a display list can be created and at the end we'll
know if it's colored or not.
In the absence of a passthrough device, the device will throw
an exception to stop page interpretation when color is found.
*/
fz_device *fz_new_test_device(fz_context *ctx, int *is_color, float threshold, int options, fz_device *passthrough);
enum
{
/* If set, test every pixel of images exhaustively.
* If clear, just look at colorspaces for images. */
FZ_TEST_OPT_IMAGES = 1,
/* If set, test every pixel of shadings. */
/* If clear, just look at colorspaces for shadings. */
FZ_TEST_OPT_SHADINGS = 2
};
/**
Create a device to draw on a pixmap.
dest: Target pixmap for the draw device. See fz_new_pixmap*
for how to obtain a pixmap. The pixmap is not cleared by the
draw device, see fz_clear_pixmap* for how to clear it prior to
calling fz_new_draw_device. Free the device by calling
fz_drop_device.
transform: Transform from user space in points to device space
in pixels.
*/
fz_device *fz_new_draw_device(fz_context *ctx, fz_matrix transform, fz_pixmap *dest);
/**
Create a device to draw on a pixmap.
dest: Target pixmap for the draw device. See fz_new_pixmap*
for how to obtain a pixmap. The pixmap is not cleared by the
draw device, see fz_clear_pixmap* for how to clear it prior to
calling fz_new_draw_device. Free the device by calling
fz_drop_device.
transform: Transform from user space in points to device space
in pixels.
clip: Bounding box to restrict any marking operations of the
draw device.
*/
fz_device *fz_new_draw_device_with_bbox(fz_context *ctx, fz_matrix transform, fz_pixmap *dest, const fz_irect *clip);
/**
Create a device to draw on a pixmap.
dest: Target pixmap for the draw device. See fz_new_pixmap*
for how to obtain a pixmap. The pixmap is not cleared by the
draw device, see fz_clear_pixmap* for how to clear it prior to
calling fz_new_draw_device. Free the device by calling
fz_drop_device.
transform: Transform from user space in points to device space
in pixels.
proof_cs: Intermediate color space to map though when mapping to
color space defined by pixmap.
*/
fz_device *fz_new_draw_device_with_proof(fz_context *ctx, fz_matrix transform, fz_pixmap *dest, fz_colorspace *proof_cs);
/**
Create a device to draw on a pixmap.
dest: Target pixmap for the draw device. See fz_new_pixmap*
for how to obtain a pixmap. The pixmap is not cleared by the
draw device, see fz_clear_pixmap* for how to clear it prior to
calling fz_new_draw_device. Free the device by calling
fz_drop_device.
transform: Transform from user space in points to device space
in pixels.
clip: Bounding box to restrict any marking operations of the
draw device.
proof_cs: Color space to render to prior to mapping to color
space defined by pixmap.
*/
fz_device *fz_new_draw_device_with_bbox_proof(fz_context *ctx, fz_matrix transform, fz_pixmap *dest, const fz_irect *clip, fz_colorspace *cs);
fz_device *fz_new_draw_device_type3(fz_context *ctx, fz_matrix transform, fz_pixmap *dest);
/**
struct fz_draw_options: Options for creating a pixmap and draw
device.
*/
typedef struct
{
int rotate;
int x_resolution;
int y_resolution;
int width;
int height;
fz_colorspace *colorspace;
int alpha;
int graphics;
int text;
} fz_draw_options;
FZ_DATA extern const char *fz_draw_options_usage;
/**
Parse draw device options from a comma separated key-value string.
*/
fz_draw_options *fz_parse_draw_options(fz_context *ctx, fz_draw_options *options, const char *string);
/**
Create a new pixmap and draw device, using the specified options.
options: Options to configure the draw device, and choose the
resolution and colorspace.
mediabox: The bounds of the page in points.
pixmap: An out parameter containing the newly created pixmap.
*/
fz_device *fz_new_draw_device_with_options(fz_context *ctx, const fz_draw_options *options, fz_rect mediabox, fz_pixmap **pixmap);
#endif
+142
View File
@@ -0,0 +1,142 @@
// Copyright (C) 2004-2021 Artifex Software, Inc.
//
// This file is part of MuPDF.
//
// MuPDF is free software: you can redistribute it and/or modify it under the
// terms of the GNU Affero General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option)
// any later version.
//
// MuPDF 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 Affero General Public License for more
// details.
//
// You should have received a copy of the GNU Affero General Public License
// along with MuPDF. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html>
//
// Alternative licensing terms are available from the licensor.
// For commercial licensing, see <https://www.artifex.com/> or contact
// Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,
// CA 94129, USA, for further information.
#ifndef MUPDF_FITZ_DISPLAY_LIST_H
#define MUPDF_FITZ_DISPLAY_LIST_H
#include "mupdf/fitz/system.h"
#include "mupdf/fitz/context.h"
#include "mupdf/fitz/geometry.h"
#include "mupdf/fitz/device.h"
/**
Display list device -- record and play back device commands.
*/
/**
fz_display_list is a list containing drawing commands (text,
images, etc.). The intent is two-fold: as a caching-mechanism
to reduce parsing of a page, and to be used as a data
structure in multi-threading where one thread parses the page
and another renders pages.
Create a display list with fz_new_display_list, hand it over to
fz_new_list_device to have it populated, and later replay the
list (once or many times) by calling fz_run_display_list. When
the list is no longer needed drop it with fz_drop_display_list.
*/
typedef struct fz_display_list fz_display_list;
/**
Create an empty display list.
A display list contains drawing commands (text, images, etc.).
Use fz_new_list_device for populating the list.
mediabox: Bounds of the page (in points) represented by the
display list.
*/
fz_display_list *fz_new_display_list(fz_context *ctx, fz_rect mediabox);
/**
Create a rendering device for a display list.
When the device is rendering a page it will populate the
display list with drawing commands (text, images, etc.). The
display list can later be reused to render a page many times
without having to re-interpret the page from the document file
for each rendering. Once the device is no longer needed, free
it with fz_drop_device.
list: A display list that the list device takes a reference to.
*/
fz_device *fz_new_list_device(fz_context *ctx, fz_display_list *list);
/**
(Re)-run a display list through a device.
list: A display list, created by fz_new_display_list and
populated with objects from a page by running fz_run_page on a
device obtained from fz_new_list_device.
ctm: Transform to apply to display list contents. May include
for example scaling and rotation, see fz_scale, fz_rotate and
fz_concat. Set to fz_identity if no transformation is desired.
scissor: Only the part of the contents of the display list
visible within this area will be considered when the list is
run through the device. This does not imply for tile objects
contained in the display list.
cookie: Communication mechanism between caller and library
running the page. Intended for multi-threaded applications,
while single-threaded applications set cookie to NULL. The
caller may abort an ongoing page run. Cookie also communicates
progress information back to the caller. The fields inside
cookie are continually updated while the page is being run.
*/
void fz_run_display_list(fz_context *ctx, fz_display_list *list, fz_device *dev, fz_matrix ctm, fz_rect scissor, fz_cookie *cookie);
/**
Increment the reference count for a display list. Returns the
same pointer.
Never throws exceptions.
*/
fz_display_list *fz_keep_display_list(fz_context *ctx, fz_display_list *list);
/**
Decrement the reference count for a display list. When the
reference count reaches zero, all the references in the display
list itself are dropped, and the display list is freed.
Never throws exceptions.
*/
void fz_drop_display_list(fz_context *ctx, fz_display_list *list);
/**
Return the bounding box of the page recorded in a display list.
*/
fz_rect fz_bound_display_list(fz_context *ctx, fz_display_list *list);
/**
Create a new image from a display list.
w, h: The conceptual width/height of the image.
transform: The matrix that needs to be applied to the given
list to make it render to the unit square.
list: The display list.
*/
fz_image *fz_new_image_from_display_list(fz_context *ctx, float w, float h, fz_display_list *list);
/**
Check for a display list being empty
list: The list to check.
Returns true if empty, false otherwise.
*/
int fz_display_list_is_empty(fz_context *ctx, const fz_display_list *list);
#endif
File diff suppressed because it is too large Load Diff
+52
View File
@@ -0,0 +1,52 @@
// Copyright (C) 2004-2021 Artifex Software, Inc.
//
// This file is part of MuPDF.
//
// MuPDF is free software: you can redistribute it and/or modify it under the
// terms of the GNU Affero General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option)
// any later version.
//
// MuPDF 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 Affero General Public License for more
// details.
//
// You should have received a copy of the GNU Affero General Public License
// along with MuPDF. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html>
//
// Alternative licensing terms are available from the licensor.
// For commercial licensing, see <https://www.artifex.com/> or contact
// Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,
// CA 94129, USA, for further information.
#ifndef MUPDF_FITZ_EXPORT_H
#define MUPDF_FITZ_EXPORT_H
/*
* Support for building/using MuPDF DLL on Windows.
*
* When compiling code that uses MuPDF DLL, FZ_DLL_CLIENT should be defined.
*
* When compiling MuPDF DLL itself, FZ_DLL should be defined.
*/
#if defined(_WIN32) || defined(_WIN64)
#if defined(FZ_DLL)
/* Building DLL. */
#define FZ_FUNCTION __declspec(dllexport)
#define FZ_DATA __declspec(dllexport)
#elif defined(FZ_DLL_CLIENT)
/* Building DLL client code. */
#define FZ_FUNCTION __declspec(dllexport)
#define FZ_DATA __declspec(dllimport)
#else
#define FZ_FUNCTION
#define FZ_DATA
#endif
#else
#define FZ_FUNCTION
#define FZ_DATA
#endif
#endif
+251
View File
@@ -0,0 +1,251 @@
// Copyright (C) 2004-2023 Artifex Software, Inc.
//
// This file is part of MuPDF.
//
// MuPDF is free software: you can redistribute it and/or modify it under the
// terms of the GNU Affero General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option)
// any later version.
//
// MuPDF 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 Affero General Public License for more
// details.
//
// You should have received a copy of the GNU Affero General Public License
// along with MuPDF. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html>
//
// Alternative licensing terms are available from the licensor.
// For commercial licensing, see <https://www.artifex.com/> or contact
// Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,
// CA 94129, USA, for further information.
#ifndef MUPDF_FITZ_FILTER_H
#define MUPDF_FITZ_FILTER_H
#include "mupdf/fitz/system.h"
#include "mupdf/fitz/context.h"
#include "mupdf/fitz/buffer.h"
#include "mupdf/fitz/store.h"
#include "mupdf/fitz/stream.h"
typedef struct fz_jbig2_globals fz_jbig2_globals;
typedef struct
{
int64_t offset;
uint64_t length;
} fz_range;
/**
The null filter reads a specified amount of data from the
substream.
*/
fz_stream *fz_open_null_filter(fz_context *ctx, fz_stream *chain, uint64_t len, int64_t offset);
/**
The range filter copies data from specified ranges of the
chained stream.
*/
fz_stream *fz_open_range_filter(fz_context *ctx, fz_stream *chain, fz_range *ranges, int nranges);
/**
The endstream filter reads a PDF substream, and starts to look
for an 'endstream' token after the specified length.
*/
fz_stream *fz_open_endstream_filter(fz_context *ctx, fz_stream *chain, uint64_t len, int64_t offset);
/**
Concat filter concatenates several streams into one.
*/
fz_stream *fz_open_concat(fz_context *ctx, int max, int pad);
/**
Add a chained stream to the end of the concatenate filter.
Ownership of chain is passed in.
*/
void fz_concat_push_drop(fz_context *ctx, fz_stream *concat, fz_stream *chain);
/**
arc4 filter performs RC4 decoding of data read from the chained
filter using the supplied key.
*/
fz_stream *fz_open_arc4(fz_context *ctx, fz_stream *chain, unsigned char *key, unsigned keylen);
/**
aesd filter performs AES decoding of data read from the chained
filter using the supplied key.
*/
fz_stream *fz_open_aesd(fz_context *ctx, fz_stream *chain, unsigned char *key, unsigned keylen);
/**
a85d filter performs ASCII 85 Decoding of data read
from the chained filter.
*/
fz_stream *fz_open_a85d(fz_context *ctx, fz_stream *chain);
/**
ahxd filter performs ASCII Hex decoding of data read
from the chained filter.
*/
fz_stream *fz_open_ahxd(fz_context *ctx, fz_stream *chain);
/**
rld filter performs Run Length Decoding of data read
from the chained filter.
*/
fz_stream *fz_open_rld(fz_context *ctx, fz_stream *chain);
/**
dctd filter performs DCT (JPEG) decoding of data read
from the chained filter.
color_transform implements the PDF color_transform option;
use 0 to disable YUV-RGB / YCCK-CMYK transforms
use >0 to enable YUV-RGB / YCCK-CMYK transforms
use -1 (default) if not embedded in PDF
use -2 (default) if embedded in PDF
For subsampling on decode, set l2factor to the log2 of the
reduction required (therefore 0 = full size decode).
jpegtables is an optional stream from which the JPEG tables
can be read. Use NULL if not required.
*/
fz_stream *fz_open_dctd(fz_context *ctx, fz_stream *chain, int color_transform, int l2factor, fz_stream *jpegtables);
/**
faxd filter performs FAX decoding of data read from
the chained filter.
k: see fax specification (fax default is 0).
end_of_line: whether we expect end of line markers (fax default
is 0).
encoded_byte_align: whether we align to bytes after each line
(fax default is 0).
columns: how many columns in the image (fax default is 1728).
rows: 0 for unspecified or the number of rows of data to expect.
end_of_block: whether we expect end of block markers (fax
default is 1).
black_is_1: determines the polarity of the image (fax default is
0).
*/
fz_stream *fz_open_faxd(fz_context *ctx, fz_stream *chain,
int k, int end_of_line, int encoded_byte_align,
int columns, int rows, int end_of_block, int black_is_1);
/**
flated filter performs LZ77 decoding (inflating) of data read
from the chained filter.
window_bits: How large a decompression window to use. Typically
15. A negative number, -n, means to use n bits, but to expect
raw data with no header.
*/
fz_stream *fz_open_flated(fz_context *ctx, fz_stream *chain, int window_bits);
/**
lzwd filter performs LZW decoding of data read from the chained
filter.
early_change: (Default 1) specifies whether to change codes 1
bit early.
min_bits: (Default 9) specifies the minimum number of bits to
use.
reverse_bits: (Default 0) allows for compatibility with gif and
old style tiffs (1).
old_tiff: (Default 0) allows for different handling of the clear
code, as found in old style tiffs.
*/
fz_stream *fz_open_lzwd(fz_context *ctx, fz_stream *chain, int early_change, int min_bits, int reverse_bits, int old_tiff);
/**
predict filter performs pixel prediction on data read from
the chained filter.
predictor: 1 = copy, 2 = tiff, other = inline PNG predictor
columns: width of image in pixels
colors: number of components.
bpc: bits per component (typically 8)
*/
fz_stream *fz_open_predict(fz_context *ctx, fz_stream *chain, int predictor, int columns, int colors, int bpc);
/**
Open a filter that performs jbig2 decompression on the chained
stream, using the optional globals record.
*/
fz_stream *fz_open_jbig2d(fz_context *ctx, fz_stream *chain, fz_jbig2_globals *globals, int embedded);
/**
Create a jbig2 globals record from a buffer.
Immutable once created.
*/
fz_jbig2_globals *fz_load_jbig2_globals(fz_context *ctx, fz_buffer *buf);
/**
Increment the reference count for a jbig2 globals record.
Never throws an exception.
*/
fz_jbig2_globals *fz_keep_jbig2_globals(fz_context *ctx, fz_jbig2_globals *globals);
/**
Decrement the reference count for a jbig2 globals record.
When the reference count hits zero, the record is freed.
Never throws an exception.
*/
void fz_drop_jbig2_globals(fz_context *ctx, fz_jbig2_globals *globals);
/**
Special jbig2 globals drop function for use in implementing
store support.
*/
void fz_drop_jbig2_globals_imp(fz_context *ctx, fz_storable *globals);
/**
Return buffer containing jbig2 globals data stream.
*/
fz_buffer * fz_jbig2_globals_data(fz_context *ctx, fz_jbig2_globals *globals);
/* Extra filters for tiff */
/**
SGI Log 16bit (greyscale) decode from the chained filter.
Decodes lines of w pixels to 8bpp greyscale.
*/
fz_stream *fz_open_sgilog16(fz_context *ctx, fz_stream *chain, int w);
/**
SGI Log 24bit (LUV) decode from the chained filter.
Decodes lines of w pixels to 8bpc rgb.
*/
fz_stream *fz_open_sgilog24(fz_context *ctx, fz_stream *chain, int w);
/**
SGI Log 32bit (LUV) decode from the chained filter.
Decodes lines of w pixels to 8bpc rgb.
*/
fz_stream *fz_open_sgilog32(fz_context *ctx, fz_stream *chain, int w);
/**
4bit greyscale Thunderscan decoding from the chained filter.
Decodes lines of w pixels to 8bpp greyscale.
*/
fz_stream *fz_open_thunder(fz_context *ctx, fz_stream *chain, int w);
#endif
+745
View File
@@ -0,0 +1,745 @@
// Copyright (C) 2004-2021 Artifex Software, Inc.
//
// This file is part of MuPDF.
//
// MuPDF is free software: you can redistribute it and/or modify it under the
// terms of the GNU Affero General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option)
// any later version.
//
// MuPDF 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 Affero General Public License for more
// details.
//
// You should have received a copy of the GNU Affero General Public License
// along with MuPDF. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html>
//
// Alternative licensing terms are available from the licensor.
// For commercial licensing, see <https://www.artifex.com/> or contact
// Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,
// CA 94129, USA, for further information.
#ifndef MUPDF_FITZ_FONT_H
#define MUPDF_FITZ_FONT_H
#include "mupdf/fitz/system.h"
#include "mupdf/fitz/context.h"
#include "mupdf/fitz/geometry.h"
#include "mupdf/fitz/buffer.h"
#include "mupdf/fitz/color.h"
/* forward declaration for circular dependency */
struct fz_device;
/* Various font encoding tables and lookup functions */
FZ_DATA extern const char *fz_glyph_name_from_adobe_standard[256];
FZ_DATA extern const char *fz_glyph_name_from_iso8859_7[256];
FZ_DATA extern const char *fz_glyph_name_from_koi8u[256];
FZ_DATA extern const char *fz_glyph_name_from_mac_expert[256];
FZ_DATA extern const char *fz_glyph_name_from_mac_roman[256];
FZ_DATA extern const char *fz_glyph_name_from_win_ansi[256];
FZ_DATA extern const char *fz_glyph_name_from_windows_1252[256];
FZ_DATA extern const unsigned short fz_unicode_from_iso8859_1[256];
FZ_DATA extern const unsigned short fz_unicode_from_iso8859_7[256];
FZ_DATA extern const unsigned short fz_unicode_from_koi8u[256];
FZ_DATA extern const unsigned short fz_unicode_from_pdf_doc_encoding[256];
FZ_DATA extern const unsigned short fz_unicode_from_windows_1250[256];
FZ_DATA extern const unsigned short fz_unicode_from_windows_1251[256];
FZ_DATA extern const unsigned short fz_unicode_from_windows_1252[256];
int fz_iso8859_1_from_unicode(int u);
int fz_iso8859_7_from_unicode(int u);
int fz_koi8u_from_unicode(int u);
int fz_windows_1250_from_unicode(int u);
int fz_windows_1251_from_unicode(int u);
int fz_windows_1252_from_unicode(int u);
int fz_unicode_from_glyph_name(const char *name);
int fz_unicode_from_glyph_name_strict(const char *name);
const char **fz_duplicate_glyph_names_from_unicode(int unicode);
const char *fz_glyph_name_from_unicode_sc(int unicode);
/**
An abstract font handle.
*/
typedef struct fz_font fz_font;
/**
Fonts come in two variants:
Regular fonts are handled by FreeType.
Type 3 fonts have callbacks to the interpreter.
*/
/**
Retrieve the FT_Face handle
for the font.
font: The font to query
Returns the FT_Face handle for the font, or NULL
if not a freetype handled font. (Cast to void *
to avoid nasty header exposure).
*/
void *fz_font_ft_face(fz_context *ctx, fz_font *font);
/**
Retrieve the Type3 procs
for a font.
font: The font to query
Returns the t3_procs pointer. Will be NULL for a
non type-3 font.
*/
fz_buffer **fz_font_t3_procs(fz_context *ctx, fz_font *font);
/* common CJK font collections */
enum { FZ_ADOBE_CNS, FZ_ADOBE_GB, FZ_ADOBE_JAPAN, FZ_ADOBE_KOREA };
/**
Every fz_font carries a set of flags
within it, in a fz_font_flags_t structure.
*/
typedef struct
{
unsigned int is_mono : 1;
unsigned int is_serif : 1;
unsigned int is_bold : 1;
unsigned int is_italic : 1;
unsigned int ft_substitute : 1; /* use substitute metrics */
unsigned int ft_stretch : 1; /* stretch to match PDF metrics */
unsigned int fake_bold : 1; /* synthesize bold */
unsigned int fake_italic : 1; /* synthesize italic */
unsigned int has_opentype : 1; /* has opentype shaping tables */
unsigned int invalid_bbox : 1;
unsigned int cjk : 1;
unsigned int cjk_lang : 2; /* CNS, GB, JAPAN, or KOREA */
unsigned int embed : 1;
unsigned int never_embed : 1;
} fz_font_flags_t;
/**
Retrieve a pointer to the font flags
for a given font. These can then be updated as required.
font: The font to query
Returns a pointer to the flags structure (or NULL, if
the font is NULL).
*/
fz_font_flags_t *fz_font_flags(fz_font *font);
/**
In order to shape a given font, we need to
declare it to a shaper library (harfbuzz, by default, but others
are possible). To avoid redeclaring it every time we need to
shape, we hold a shaper handle and the destructor for it within
the font itself. The handle is initialised by the caller when
first required and the destructor is called when the fz_font is
destroyed.
*/
typedef struct
{
void *shaper_handle;
void (*destroy)(fz_context *ctx, void *); /* Destructor for shape_handle */
} fz_shaper_data_t;
/**
Retrieve a pointer to the shaper data
structure for the given font.
font: The font to query.
Returns a pointer to the shaper data structure (or NULL if
font is NULL).
*/
fz_shaper_data_t *fz_font_shaper_data(fz_context *ctx, fz_font *font);
/**
Retrieve a pointer to the name of the font.
font: The font to query.
Returns a pointer to an internal copy of the font name.
Will never be NULL, but may be the empty string.
*/
const char *fz_font_name(fz_context *ctx, fz_font *font);
/**
Query whether the font flags say that this font is bold.
*/
int fz_font_is_bold(fz_context *ctx, fz_font *font);
/**
Query whether the font flags say that this font is italic.
*/
int fz_font_is_italic(fz_context *ctx, fz_font *font);
/**
Query whether the font flags say that this font is serif.
*/
int fz_font_is_serif(fz_context *ctx, fz_font *font);
/**
Query whether the font flags say that this font is monospaced.
*/
int fz_font_is_monospaced(fz_context *ctx, fz_font *font);
/**
Retrieve the font bbox.
font: The font to query.
Returns the font bbox by value; it is valid only if
fz_font_flags(font)->invalid_bbox is zero.
*/
fz_rect fz_font_bbox(fz_context *ctx, fz_font *font);
/**
Type for user supplied system font loading hook.
name: The name of the font to load.
bold: 1 if a bold font desired, 0 otherwise.
italic: 1 if an italic font desired, 0 otherwise.
needs_exact_metrics: 1 if an exact metric match is required for
the font requested.
Returns a new font handle, or NULL if no font found (or on error).
*/
typedef fz_font *(fz_load_system_font_fn)(fz_context *ctx, const char *name, int bold, int italic, int needs_exact_metrics);
/**
Type for user supplied cjk font loading hook.
name: The name of the font to load.
ordering: The ordering for which to load the font (e.g.
FZ_ADOBE_KOREA)
serif: 1 if a serif font is desired, 0 otherwise.
Returns a new font handle, or NULL if no font found (or on error).
*/
typedef fz_font *(fz_load_system_cjk_font_fn)(fz_context *ctx, const char *name, int ordering, int serif);
/**
Type for user supplied fallback font loading hook.
name: The name of the font to load.
script: UCDN script enum.
language: FZ_LANG enum.
serif, bold, italic: boolean style flags.
Returns a new font handle, or NULL if no font found (or on error).
*/
typedef fz_font *(fz_load_system_fallback_font_fn)(fz_context *ctx, int script, int language, int serif, int bold, int italic);
/**
Install functions to allow MuPDF to request fonts from the
system.
Only one set of hooks can be in use at a time.
*/
void fz_install_load_system_font_funcs(fz_context *ctx,
fz_load_system_font_fn *f,
fz_load_system_cjk_font_fn *f_cjk,
fz_load_system_fallback_font_fn *f_fallback);
/**
Attempt to load a given font from the system.
name: The name of the desired font.
bold: 1 if bold desired, 0 otherwise.
italic: 1 if italic desired, 0 otherwise.
needs_exact_metrics: 1 if an exact metrical match is required,
0 otherwise.
Returns a new font handle, or NULL if no matching font was found
(or on error).
*/
fz_font *fz_load_system_font(fz_context *ctx, const char *name, int bold, int italic, int needs_exact_metrics);
/**
Attempt to load a given font from
the system.
name: The name of the desired font.
ordering: The ordering to load the font from (e.g. FZ_ADOBE_KOREA)
serif: 1 if serif desired, 0 otherwise.
Returns a new font handle, or NULL if no matching font was found
(or on error).
*/
fz_font *fz_load_system_cjk_font(fz_context *ctx, const char *name, int ordering, int serif);
/**
Search the builtin fonts for a match.
Whether a given font is present or not will depend on the
configuration in which MuPDF is built.
name: The name of the font desired.
bold: 1 if bold desired, 0 otherwise.
italic: 1 if italic desired, 0 otherwise.
len: Pointer to a place to receive the length of the discovered
font buffer.
Returns a pointer to the font file data, or NULL if not present.
*/
const unsigned char *fz_lookup_builtin_font(fz_context *ctx, const char *name, int bold, int italic, int *len);
/**
Search the builtin base14 fonts for a match.
Whether a given font is present or not will depend on the
configuration in which MuPDF is built.
name: The name of the font desired.
len: Pointer to a place to receive the length of the discovered
font buffer.
Returns a pointer to the font file data, or NULL if not present.
*/
const unsigned char *fz_lookup_base14_font(fz_context *ctx, const char *name, int *len);
/**
Search the builtin cjk fonts for a match.
Whether a font is present or not will depend on the
configuration in which MuPDF is built.
ordering: The desired ordering of the font (e.g. FZ_ADOBE_KOREA).
len: Pointer to a place to receive the length of the discovered
font buffer.
Returns a pointer to the font file data, or NULL if not present.
*/
const unsigned char *fz_lookup_cjk_font(fz_context *ctx, int ordering, int *len, int *index);
/**
Search the builtin cjk fonts for a match for a given language.
Whether a font is present or not will depend on the
configuration in which MuPDF is built.
lang: Pointer to a (case sensitive) language string (e.g.
"ja", "ko", "zh-Hant" etc).
len: Pointer to a place to receive the length of the discovered
font buffer.
subfont: Pointer to a place to store the subfont index of the
discovered font.
Returns a pointer to the font file data, or NULL if not present.
*/
const unsigned char *fz_lookup_cjk_font_by_language(fz_context *ctx, const char *lang, int *len, int *subfont);
/**
Return the matching FZ_ADOBE_* ordering
for the given language tag, such as "zh-Hant", "zh-Hans", "ja", or "ko".
*/
int fz_lookup_cjk_ordering_by_language(const char *name);
/**
Search the builtin noto fonts for a match.
Whether a font is present or not will depend on the
configuration in which MuPDF is built.
script: The script desired (e.g. UCDN_SCRIPT_KATAKANA).
lang: The language desired (e.g. FZ_LANG_ja).
len: Pointer to a place to receive the length of the discovered
font buffer.
Returns a pointer to the font file data, or NULL if not present.
*/
const unsigned char *fz_lookup_noto_font(fz_context *ctx, int script, int lang, int *len, int *subfont);
/**
Search the builtin noto fonts specific symbol fonts.
Whether a font is present or not will depend on the
configuration in which MuPDF is built.
*/
const unsigned char *fz_lookup_noto_math_font(fz_context *ctx, int *len);
const unsigned char *fz_lookup_noto_music_font(fz_context *ctx, int *len);
const unsigned char *fz_lookup_noto_symbol1_font(fz_context *ctx, int *len);
const unsigned char *fz_lookup_noto_symbol2_font(fz_context *ctx, int *len);
const unsigned char *fz_lookup_noto_emoji_font(fz_context *ctx, int *len);
/**
Try to load a fallback font for the
given combination of font attributes. Whether a font is
present or not will depend on the configuration in which
MuPDF is built.
script: The script desired (e.g. UCDN_SCRIPT_KATAKANA).
language: The language desired (e.g. FZ_LANG_ja).
serif: 1 if serif desired, 0 otherwise.
bold: 1 if bold desired, 0 otherwise.
italic: 1 if italic desired, 0 otherwise.
Returns a new font handle, or NULL if not available.
*/
fz_font *fz_load_fallback_font(fz_context *ctx, int script, int language, int serif, int bold, int italic);
/**
Create a new (empty) type3 font.
name: Name of font (or NULL).
matrix: Font matrix.
Returns a new font handle, or throws exception on
allocation failure.
*/
fz_font *fz_new_type3_font(fz_context *ctx, const char *name, fz_matrix matrix);
/**
Create a new font from a font file in memory.
Fonts created in this way, will be eligible for embedding by default.
name: Name of font (leave NULL to use name from font).
data: Pointer to the font file data.
len: Length of the font file data.
index: Which font from the file to load (0 for default).
use_glyph_box: 1 if we should use the glyph bbox, 0 otherwise.
Returns new font handle, or throws exception on error.
*/
fz_font *fz_new_font_from_memory(fz_context *ctx, const char *name, const unsigned char *data, int len, int index, int use_glyph_bbox);
/**
Create a new font from a font file in a fz_buffer.
Fonts created in this way, will be eligible for embedding by default.
name: Name of font (leave NULL to use name from font).
buffer: Buffer to load from.
index: Which font from the file to load (0 for default).
use_glyph_box: 1 if we should use the glyph bbox, 0 otherwise.
Returns new font handle, or throws exception on error.
*/
fz_font *fz_new_font_from_buffer(fz_context *ctx, const char *name, fz_buffer *buffer, int index, int use_glyph_bbox);
/**
Create a new font from a font file.
Fonts created in this way, will be eligible for embedding by default.
name: Name of font (leave NULL to use name from font).
path: File path to load from.
index: Which font from the file to load (0 for default).
use_glyph_box: 1 if we should use the glyph bbox, 0 otherwise.
Returns new font handle, or throws exception on error.
*/
fz_font *fz_new_font_from_file(fz_context *ctx, const char *name, const char *path, int index, int use_glyph_bbox);
/**
Create a new font from one of the built-in fonts.
*/
fz_font *fz_new_base14_font(fz_context *ctx, const char *name);
fz_font *fz_new_cjk_font(fz_context *ctx, int ordering);
fz_font *fz_new_builtin_font(fz_context *ctx, const char *name, int is_bold, int is_italic);
/**
Control whether a given font should be embedded or not when writing.
*/
void fz_set_font_embedding(fz_context *ctx, fz_font *font, int embed);
/**
Add a reference to an existing fz_font.
font: The font to add a reference to.
Returns the same font.
*/
fz_font *fz_keep_font(fz_context *ctx, fz_font *font);
/**
Drop a reference to a fz_font, destroying the
font when the last reference is dropped.
font: The font to drop a reference to.
*/
void fz_drop_font(fz_context *ctx, fz_font *font);
/**
Set the font bbox.
font: The font to set the bbox for.
xmin, ymin, xmax, ymax: The bounding box.
*/
void fz_set_font_bbox(fz_context *ctx, fz_font *font, float xmin, float ymin, float xmax, float ymax);
/**
Return a bbox for a given glyph in a font.
font: The font to look for the glyph in.
gid: The glyph to bound.
trm: The matrix to apply to the glyph before bounding.
Returns rectangle by value containing the bounds of the given
glyph.
*/
fz_rect fz_bound_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix trm);
/**
Determine if a given glyph in a font
is cacheable. Certain glyphs in a type 3 font cannot safely
be cached, as their appearance depends on the enclosing
graphic state.
font: The font to look for the glyph in.
gif: The glyph to query.
Returns non-zero if cacheable, 0 if not.
*/
int fz_glyph_cacheable(fz_context *ctx, fz_font *font, int gid);
/**
Run a glyph from a Type3 font to
a given device.
font: The font to find the glyph in.
gid: The glyph to run.
trm: The transform to apply.
dev: The device to render onto.
*/
void fz_run_t3_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix trm, struct fz_device *dev);
/**
Return the advance for a given glyph.
font: The font to look for the glyph in.
glyph: The glyph to find the advance for.
wmode: 1 for vertical mode, 0 for horizontal.
Returns the advance for the glyph.
*/
float fz_advance_glyph(fz_context *ctx, fz_font *font, int glyph, int wmode);
/**
Find the glyph id for a given unicode
character within a font.
font: The font to look for the unicode character in.
unicode: The unicode character to encode.
Returns the glyph id for the given unicode value, or 0 if
unknown.
*/
int fz_encode_character(fz_context *ctx, fz_font *font, int unicode);
/**
Encode character, preferring small-caps variant if available.
font: The font to look for the unicode character in.
unicode: The unicode character to encode.
Returns the glyph id for the given unicode value, or 0 if
unknown.
*/
int fz_encode_character_sc(fz_context *ctx, fz_font *font, int unicode);
/**
Encode character.
Either by direct lookup of glyphname within a font, or, failing
that, by mapping glyphname to unicode and thence to the glyph
index within the given font.
Returns zero for type3 fonts.
*/
int fz_encode_character_by_glyph_name(fz_context *ctx, fz_font *font, const char *glyphname);
/**
Find the glyph id for
a given unicode character within a font, falling back to
an alternative if not found.
font: The font to look for the unicode character in.
unicode: The unicode character to encode.
script: The script in use.
language: The language in use.
out_font: The font handle in which the given glyph represents
the requested unicode character. The caller does not own the
reference it is passed, so should call fz_keep_font if it is
not simply to be used immediately.
Returns the glyph id for the given unicode value in the supplied
font (and sets *out_font to font) if it is present. Otherwise
an alternative fallback font (based on script/language) is
searched for. If the glyph is found therein, *out_font is set
to this reference, and the glyph reference is returned. If it
cannot be found anywhere, the function returns 0.
*/
int fz_encode_character_with_fallback(fz_context *ctx, fz_font *font, int unicode, int script, int language, fz_font **out_font);
/**
Find the name of a glyph
font: The font to look for the glyph in.
glyph: The glyph id to look for.
buf: Pointer to a buffer for the name to be inserted into.
size: The size of the buffer.
If a font contains a name table, then the name of the glyph
will be returned in the supplied buffer. Otherwise a name
is synthesised. The name will be truncated to fit in
the buffer.
*/
void fz_get_glyph_name(fz_context *ctx, fz_font *font, int glyph, char *buf, int size);
/**
Retrieve font ascender in ems.
*/
float fz_font_ascender(fz_context *ctx, fz_font *font);
/**
Retrieve font descender in ems.
*/
float fz_font_descender(fz_context *ctx, fz_font *font);
/**
Retrieve the MD5 digest for the font's data.
*/
void fz_font_digest(fz_context *ctx, fz_font *font, unsigned char digest[16]);
/* Implementation details: subject to change. */
void fz_decouple_type3_font(fz_context *ctx, fz_font *font, void *t3doc);
/**
map an FT error number to a
static string.
err: The error number to lookup.
Returns a pointer to a static textual representation
of a freetype error.
*/
const char *ft_error_string(int err);
int ft_char_index(void *face, int cid);
int ft_name_index(void *face, const char *name);
/**
Internal functions for our Harfbuzz integration
to work around the lack of thread safety.
*/
/**
Lock against Harfbuzz being called
simultaneously in several threads. This reuses
FZ_LOCK_FREETYPE.
*/
void fz_hb_lock(fz_context *ctx);
/**
Unlock after a Harfbuzz call. This reuses
FZ_LOCK_FREETYPE.
*/
void fz_hb_unlock(fz_context *ctx);
struct fz_font
{
int refs;
char name[32];
fz_buffer *buffer;
fz_font_flags_t flags;
void *ft_face; /* has an FT_Face if used */
fz_shaper_data_t shaper_data;
fz_matrix t3matrix;
void *t3resources;
fz_buffer **t3procs; /* has 256 entries if used */
struct fz_display_list **t3lists; /* has 256 entries if used */
float *t3widths; /* has 256 entries if used */
unsigned short *t3flags; /* has 256 entries if used */
void *t3doc; /* a pdf_document for the callback */
void (*t3run)(fz_context *ctx, void *doc, void *resources, fz_buffer *contents, struct fz_device *dev, fz_matrix ctm, void *gstate, fz_default_colorspaces *default_cs);
void (*t3freeres)(fz_context *ctx, void *doc, void *resources);
fz_rect bbox; /* font bbox is used only for t3 fonts */
int glyph_count;
/* per glyph bounding box cache. */
fz_rect **bbox_table;
int use_glyph_bbox;
/* substitute metrics */
int width_count;
short width_default; /* in 1000 units */
short *width_table; /* in 1000 units */
/* cached glyph metrics */
float **advance_cache;
/* cached encoding lookup */
uint16_t *encoding_cache[256];
/* cached md5sum for caching */
int has_digest;
unsigned char digest[16];
/* Which font to use in a collection. */
int subfont;
};
#endif
+818
View File
@@ -0,0 +1,818 @@
// Copyright (C) 2004-2022 Artifex Software, Inc.
//
// This file is part of MuPDF.
//
// MuPDF is free software: you can redistribute it and/or modify it under the
// terms of the GNU Affero General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option)
// any later version.
//
// MuPDF 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 Affero General Public License for more
// details.
//
// You should have received a copy of the GNU Affero General Public License
// along with MuPDF. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html>
//
// Alternative licensing terms are available from the licensor.
// For commercial licensing, see <https://www.artifex.com/> or contact
// Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,
// CA 94129, USA, for further information.
#ifndef MUPDF_FITZ_MATH_H
#define MUPDF_FITZ_MATH_H
#include "mupdf/fitz/system.h"
#include <assert.h>
/**
Multiply scaled two integers in the 0..255 range
*/
static inline int fz_mul255(int a, int b)
{
/* see Jim Blinn's book "Dirty Pixels" for how this works */
int x = a * b + 128;
x += x >> 8;
return x >> 8;
}
/**
Undo alpha premultiplication.
*/
static inline int fz_div255(int c, int a)
{
return a ? c * (255 * 256 / a) >> 8 : 0;
}
/**
Expand a value A from the 0...255 range to the 0..256 range
*/
#define FZ_EXPAND(A) ((A)+((A)>>7))
/**
Combine values A (in any range) and B (in the 0..256 range),
to give a single value in the same range as A was.
*/
#define FZ_COMBINE(A,B) (((A)*(B))>>8)
/**
Combine values A and C (in the same (any) range) and B and D (in
the 0..256 range), to give a single value in the same range as A
and C were.
*/
#define FZ_COMBINE2(A,B,C,D) (((A) * (B) + (C) * (D))>>8)
/**
Blend SRC and DST (in the same range) together according to
AMOUNT (in the 0...256 range).
*/
#define FZ_BLEND(SRC, DST, AMOUNT) ((((SRC)-(DST))*(AMOUNT) + ((DST)<<8))>>8)
/**
Range checking atof
*/
float fz_atof(const char *s);
/**
atoi that copes with NULL
*/
int fz_atoi(const char *s);
/**
64bit atoi that copes with NULL
*/
int64_t fz_atoi64(const char *s);
/**
Some standard math functions, done as static inlines for speed.
People with compilers that do not adequately implement inline
may like to reimplement these using macros.
*/
static inline float fz_abs(float f)
{
return (f < 0 ? -f : f);
}
static inline int fz_absi(int i)
{
return (i < 0 ? -i : i);
}
static inline float fz_min(float a, float b)
{
return (a < b ? a : b);
}
static inline int fz_mini(int a, int b)
{
return (a < b ? a : b);
}
static inline size_t fz_minz(size_t a, size_t b)
{
return (a < b ? a : b);
}
static inline int64_t fz_mini64(int64_t a, int64_t b)
{
return (a < b ? a : b);
}
static inline float fz_max(float a, float b)
{
return (a > b ? a : b);
}
static inline int fz_maxi(int a, int b)
{
return (a > b ? a : b);
}
static inline size_t fz_maxz(size_t a, size_t b)
{
return (a > b ? a : b);
}
static inline int64_t fz_maxi64(int64_t a, int64_t b)
{
return (a > b ? a : b);
}
static inline float fz_clamp(float x, float min, float max)
{
return x < min ? min : x > max ? max : x;
}
static inline int fz_clampi(int x, int min, int max)
{
return x < min ? min : x > max ? max : x;
}
static inline int64_t fz_clamp64(int64_t x, int64_t min, int64_t max)
{
return x < min ? min : x > max ? max : x;
}
static inline double fz_clampd(double x, double min, double max)
{
return x < min ? min : x > max ? max : x;
}
static inline void *fz_clampp(void *x, void *min, void *max)
{
return x < min ? min : x > max ? max : x;
}
#define DIV_BY_ZERO(a, b, min, max) (((a) < 0) ^ ((b) < 0) ? (min) : (max))
/**
fz_point is a point in a two-dimensional space.
*/
typedef struct
{
float x, y;
} fz_point;
static inline fz_point fz_make_point(float x, float y)
{
fz_point p = { x, y };
return p;
}
/**
fz_rect is a rectangle represented by two diagonally opposite
corners at arbitrary coordinates.
Rectangles are always axis-aligned with the X- and Y- axes. We
wish to distinguish rectangles in 3 categories; infinite, finite,
and invalid. Zero area rectangles are a sub-category of finite
ones.
For all valid rectangles, x0 <= x1 and y0 <= y1 in all cases.
Infinite rectangles have x0 = y0 = FZ_MIN_INF_RECT,
x1 = y1 = FZ_MAX_INF_RECT. For any non infinite valid rectangle,
the area is defined as (x1 - x0) * (y1 - y0).
To check for empty or infinite rectangles use fz_is_empty_rect
and fz_is_infinite_rect. To check for valid rectangles use
fz_is_valid_rect.
We choose this representation, so that we can easily distinguish
the difference between intersecting 2 valid rectangles and
getting an invalid one, as opposed to getting a zero area one
(which nonetheless has valid bounds within the plane).
x0, y0: The top left corner.
x1, y1: The bottom right corner.
We choose FZ_{MIN,MAX}_INF_RECT to be the largest 32bit signed
integer values that survive roundtripping to floats.
*/
#define FZ_MIN_INF_RECT ((int)0x80000000)
#define FZ_MAX_INF_RECT ((int)0x7fffff80)
typedef struct
{
float x0, y0;
float x1, y1;
} fz_rect;
static inline fz_rect fz_make_rect(float x0, float y0, float x1, float y1)
{
fz_rect r = { x0, y0, x1, y1 };
return r;
}
/**
fz_irect is a rectangle using integers instead of floats.
It's used in the draw device and for pixmap dimensions.
*/
typedef struct
{
int x0, y0;
int x1, y1;
} fz_irect;
static inline fz_irect fz_make_irect(int x0, int y0, int x1, int y1)
{
fz_irect r = { x0, y0, x1, y1 };
return r;
}
/**
A rectangle with sides of length one.
The bottom left corner is at (0, 0) and the top right corner
is at (1, 1).
*/
FZ_DATA extern const fz_rect fz_unit_rect;
/**
An empty rectangle with an area equal to zero.
*/
FZ_DATA extern const fz_rect fz_empty_rect;
FZ_DATA extern const fz_irect fz_empty_irect;
/**
An infinite rectangle.
*/
FZ_DATA extern const fz_rect fz_infinite_rect;
FZ_DATA extern const fz_irect fz_infinite_irect;
/**
Check if rectangle is empty.
An empty rectangle is defined as one whose area is zero.
All invalid rectangles are empty.
*/
static inline int fz_is_empty_rect(fz_rect r)
{
return (r.x0 >= r.x1 || r.y0 >= r.y1);
}
static inline int fz_is_empty_irect(fz_irect r)
{
return (r.x0 >= r.x1 || r.y0 >= r.y1);
}
/**
Check if rectangle is infinite.
*/
static inline int fz_is_infinite_rect(fz_rect r)
{
return (r.x0 == FZ_MIN_INF_RECT && r.x1 == FZ_MAX_INF_RECT &&
r.y0 == FZ_MIN_INF_RECT && r.y1 == FZ_MAX_INF_RECT);
}
/**
Check if an integer rectangle
is infinite.
*/
static inline int fz_is_infinite_irect(fz_irect r)
{
return (r.x0 == FZ_MIN_INF_RECT && r.x1 == FZ_MAX_INF_RECT &&
r.y0 == FZ_MIN_INF_RECT && r.y1 == FZ_MAX_INF_RECT);
}
/**
Check if rectangle is valid.
*/
static inline int fz_is_valid_rect(fz_rect r)
{
return (r.x0 <= r.x1 && r.y0 <= r.y1);
}
/**
Check if an integer rectangle is valid.
*/
static inline int fz_is_valid_irect(fz_irect r)
{
return (r.x0 <= r.x1 && r.y0 <= r.y1);
}
/**
Return the width of an irect. Invalid irects return 0.
*/
static inline unsigned int
fz_irect_width(fz_irect r)
{
unsigned int w;
if (r.x0 >= r.x1)
return 0;
/* Check for w overflowing. This should never happen, but
* if it does, it's pretty likely an indication of a severe
* problem. */
w = (unsigned int)r.x1 - r.x0;
assert((int)w >= 0);
if ((int)w < 0)
return 0;
return (int)w;
}
/**
Return the height of an irect. Invalid irects return 0.
*/
static inline int
fz_irect_height(fz_irect r)
{
unsigned int h;
if (r.y0 >= r.y1)
return 0;
/* Check for h overflowing. This should never happen, but
* if it does, it's pretty likely an indication of a severe
* problem. */
h = (unsigned int)(r.y1 - r.y0);
assert((int)h >= 0);
if ((int)h < 0)
return 0;
return (int)h;
}
/**
fz_matrix is a row-major 3x3 matrix used for representing
transformations of coordinates throughout MuPDF.
Since all points reside in a two-dimensional space, one vector
is always a constant unit vector; hence only some elements may
vary in a matrix. Below is how the elements map between
different representations.
/ a b 0 \
| c d 0 | normally represented as [ a b c d e f ].
\ e f 1 /
*/
typedef struct
{
float a, b, c, d, e, f;
} fz_matrix;
/**
Identity transform matrix.
*/
FZ_DATA extern const fz_matrix fz_identity;
static inline fz_matrix fz_make_matrix(float a, float b, float c, float d, float e, float f)
{
fz_matrix m = { a, b, c, d, e, f };
return m;
}
static inline int fz_is_identity(fz_matrix m)
{
return m.a == 1 && m.b == 0 && m.c == 0 && m.d == 1 && m.e == 0 && m.f == 0;
}
/**
Multiply two matrices.
The order of the two matrices are important since matrix
multiplication is not commutative.
Returns result.
*/
fz_matrix fz_concat(fz_matrix left, fz_matrix right);
/**
Create a scaling matrix.
The returned matrix is of the form [ sx 0 0 sy 0 0 ].
m: Pointer to the matrix to populate
sx, sy: Scaling factors along the X- and Y-axes. A scaling
factor of 1.0 will not cause any scaling along the relevant
axis.
Returns m.
*/
fz_matrix fz_scale(float sx, float sy);
/**
Scale a matrix by premultiplication.
m: Pointer to the matrix to scale
sx, sy: Scaling factors along the X- and Y-axes. A scaling
factor of 1.0 will not cause any scaling along the relevant
axis.
Returns m (updated).
*/
fz_matrix fz_pre_scale(fz_matrix m, float sx, float sy);
/**
Scale a matrix by postmultiplication.
m: Pointer to the matrix to scale
sx, sy: Scaling factors along the X- and Y-axes. A scaling
factor of 1.0 will not cause any scaling along the relevant
axis.
Returns m (updated).
*/
fz_matrix fz_post_scale(fz_matrix m, float sx, float sy);
/**
Create a shearing matrix.
The returned matrix is of the form [ 1 sy sx 1 0 0 ].
m: pointer to place to store returned matrix
sx, sy: Shearing factors. A shearing factor of 0.0 will not
cause any shearing along the relevant axis.
Returns m.
*/
fz_matrix fz_shear(float sx, float sy);
/**
Premultiply a matrix with a shearing matrix.
The shearing matrix is of the form [ 1 sy sx 1 0 0 ].
m: pointer to matrix to premultiply
sx, sy: Shearing factors. A shearing factor of 0.0 will not
cause any shearing along the relevant axis.
Returns m (updated).
*/
fz_matrix fz_pre_shear(fz_matrix m, float sx, float sy);
/**
Create a rotation matrix.
The returned matrix is of the form
[ cos(deg) sin(deg) -sin(deg) cos(deg) 0 0 ].
m: Pointer to place to store matrix
degrees: Degrees of counter clockwise rotation. Values less
than zero and greater than 360 are handled as expected.
Returns m.
*/
fz_matrix fz_rotate(float degrees);
/**
Rotate a transformation by premultiplying.
The premultiplied matrix is of the form
[ cos(deg) sin(deg) -sin(deg) cos(deg) 0 0 ].
m: Pointer to matrix to premultiply.
degrees: Degrees of counter clockwise rotation. Values less
than zero and greater than 360 are handled as expected.
Returns m (updated).
*/
fz_matrix fz_pre_rotate(fz_matrix m, float degrees);
/**
Create a translation matrix.
The returned matrix is of the form [ 1 0 0 1 tx ty ].
m: A place to store the created matrix.
tx, ty: Translation distances along the X- and Y-axes. A
translation of 0 will not cause any translation along the
relevant axis.
Returns m.
*/
fz_matrix fz_translate(float tx, float ty);
/**
Translate a matrix by premultiplication.
m: The matrix to translate
tx, ty: Translation distances along the X- and Y-axes. A
translation of 0 will not cause any translation along the
relevant axis.
Returns m.
*/
fz_matrix fz_pre_translate(fz_matrix m, float tx, float ty);
/**
Create transform matrix to draw page
at a given resolution and rotation. Adjusts the scaling
factors so that the page covers whole number of
pixels and adjust the page origin to be at 0,0.
*/
fz_matrix fz_transform_page(fz_rect mediabox, float resolution, float rotate);
/**
Create an inverse matrix.
inverse: Place to store inverse matrix.
matrix: Matrix to invert. A degenerate matrix, where the
determinant is equal to zero, can not be inverted and the
original matrix is returned instead.
Returns inverse.
*/
fz_matrix fz_invert_matrix(fz_matrix matrix);
/**
Attempt to create an inverse matrix.
inverse: Place to store inverse matrix.
matrix: Matrix to invert. A degenerate matrix, where the
determinant is equal to zero, can not be inverted.
Returns 1 if matrix is degenerate (singular), or 0 otherwise.
*/
int fz_try_invert_matrix(fz_matrix *inv, fz_matrix src);
/**
Check if a transformation is rectilinear.
Rectilinear means that no shearing is present and that any
rotations present are a multiple of 90 degrees. Usually this
is used to make sure that axis-aligned rectangles before the
transformation are still axis-aligned rectangles afterwards.
*/
int fz_is_rectilinear(fz_matrix m);
/**
Calculate average scaling factor of matrix.
*/
float fz_matrix_expansion(fz_matrix m);
/**
Compute intersection of two rectangles.
Given two rectangles, update the first to be the smallest
axis-aligned rectangle that covers the area covered by both
given rectangles. If either rectangle is empty then the
intersection is also empty. If either rectangle is infinite
then the intersection is simply the non-infinite rectangle.
Should both rectangles be infinite, then the intersection is
also infinite.
*/
fz_rect fz_intersect_rect(fz_rect a, fz_rect b);
/**
Compute intersection of two bounding boxes.
Similar to fz_intersect_rect but operates on two bounding
boxes instead of two rectangles.
*/
fz_irect fz_intersect_irect(fz_irect a, fz_irect b);
/**
Compute union of two rectangles.
Given two rectangles, update the first to be the smallest
axis-aligned rectangle that encompasses both given rectangles.
If either rectangle is infinite then the union is also infinite.
If either rectangle is empty then the union is simply the
non-empty rectangle. Should both rectangles be empty, then the
union is also empty.
*/
fz_rect fz_union_rect(fz_rect a, fz_rect b);
/**
Convert a rect into the minimal bounding box
that covers the rectangle.
Coordinates in a bounding box are integers, so rounding of the
rects coordinates takes place. The top left corner is rounded
upwards and left while the bottom right corner is rounded
downwards and to the right.
*/
fz_irect fz_irect_from_rect(fz_rect rect);
/**
Round rectangle coordinates.
Coordinates in a bounding box are integers, so rounding of the
rects coordinates takes place. The top left corner is rounded
upwards and left while the bottom right corner is rounded
downwards and to the right.
This differs from fz_irect_from_rect, in that fz_irect_from_rect
slavishly follows the numbers (i.e any slight over/under
calculations can cause whole extra pixels to be added).
fz_round_rect allows for a small amount of rounding error when
calculating the bbox.
*/
fz_irect fz_round_rect(fz_rect rect);
/**
Convert a bbox into a rect.
For our purposes, a rect can represent all the values we meet in
a bbox, so nothing can go wrong.
rect: A place to store the generated rectangle.
bbox: The bbox to convert.
Returns rect (updated).
*/
fz_rect fz_rect_from_irect(fz_irect bbox);
/**
Expand a bbox by a given amount in all directions.
*/
fz_rect fz_expand_rect(fz_rect b, float expand);
fz_irect fz_expand_irect(fz_irect a, int expand);
/**
Expand a bbox to include a given point.
To create a rectangle that encompasses a sequence of points, the
rectangle must first be set to be the empty rectangle at one of
the points before including the others.
*/
fz_rect fz_include_point_in_rect(fz_rect r, fz_point p);
/**
Translate bounding box.
Translate a bbox by a given x and y offset. Allows for overflow.
*/
fz_rect fz_translate_rect(fz_rect a, float xoff, float yoff);
fz_irect fz_translate_irect(fz_irect a, int xoff, int yoff);
/**
Test rectangle inclusion.
Return true if a entirely contains b.
*/
int fz_contains_rect(fz_rect a, fz_rect b);
/**
Apply a transformation to a point.
transform: Transformation matrix to apply. See fz_concat,
fz_scale, fz_rotate and fz_translate for how to create a
matrix.
point: Pointer to point to update.
Returns transform (unchanged).
*/
fz_point fz_transform_point(fz_point point, fz_matrix m);
fz_point fz_transform_point_xy(float x, float y, fz_matrix m);
/**
Apply a transformation to a vector.
transform: Transformation matrix to apply. See fz_concat,
fz_scale and fz_rotate for how to create a matrix. Any
translation will be ignored.
vector: Pointer to vector to update.
*/
fz_point fz_transform_vector(fz_point vector, fz_matrix m);
/**
Apply a transform to a rectangle.
After the four corner points of the axis-aligned rectangle
have been transformed it may not longer be axis-aligned. So a
new axis-aligned rectangle is created covering at least the
area of the transformed rectangle.
transform: Transformation matrix to apply. See fz_concat,
fz_scale and fz_rotate for how to create a matrix.
rect: Rectangle to be transformed. The two special cases
fz_empty_rect and fz_infinite_rect, may be used but are
returned unchanged as expected.
*/
fz_rect fz_transform_rect(fz_rect rect, fz_matrix m);
/**
Normalize a vector to length one.
*/
fz_point fz_normalize_vector(fz_point p);
/**
Grid fit a matrix.
as_tiled = 0 => adjust the matrix so that the image of the unit
square completely covers any pixel that was touched by the
image of the unit square under the original matrix.
as_tiled = 1 => adjust the matrix so that the corners of the
image of the unit square align with the closest integer corner
of the image of the unit square under the original matrix.
*/
fz_matrix fz_gridfit_matrix(int as_tiled, fz_matrix m);
/**
Find the largest expansion performed by this matrix.
(i.e. max(abs(m.a),abs(m.b),abs(m.c),abs(m.d))
*/
float fz_matrix_max_expansion(fz_matrix m);
/**
A representation for a region defined by 4 points.
The significant difference between quads and rects is that
the edges of quads are not axis aligned.
*/
typedef struct
{
fz_point ul, ur, ll, lr;
} fz_quad;
/**
Inline convenience construction function.
*/
static inline fz_quad fz_make_quad(
float ul_x, float ul_y,
float ur_x, float ur_y,
float ll_x, float ll_y,
float lr_x, float lr_y)
{
fz_quad q = {
{ ul_x, ul_y },
{ ur_x, ur_y },
{ ll_x, ll_y },
{ lr_x, lr_y },
};
return q;
}
/**
Convert a rect to a quad (losslessly).
*/
fz_quad fz_quad_from_rect(fz_rect r);
/**
Convert a quad to the smallest rect that covers it.
*/
fz_rect fz_rect_from_quad(fz_quad q);
/**
Transform a quad by a matrix.
*/
fz_quad fz_transform_quad(fz_quad q, fz_matrix m);
/**
Inclusion test for quads.
*/
int fz_is_point_inside_quad(fz_point p, fz_quad q);
/**
Inclusion test for rects. (Rect is assumed to be open, i.e.
top right corner is not included).
*/
int fz_is_point_inside_rect(fz_point p, fz_rect r);
/**
Inclusion test for irects. (Rect is assumed to be open, i.e.
top right corner is not included).
*/
int fz_is_point_inside_irect(int x, int y, fz_irect r);
/**
Inclusion test for quad in quad.
This may break down if quads are not 'well formed'.
*/
int fz_is_quad_inside_quad(fz_quad needle, fz_quad haystack);
/**
Intersection test for quads.
This may break down if quads are not 'well formed'.
*/
int fz_is_quad_intersecting_quad(fz_quad a, fz_quad b);
#endif
+35
View File
@@ -0,0 +1,35 @@
// Copyright (C) 2004-2021 Artifex Software, Inc.
//
// This file is part of MuPDF.
//
// MuPDF is free software: you can redistribute it and/or modify it under the
// terms of the GNU Affero General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option)
// any later version.
//
// MuPDF 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 Affero General Public License for more
// details.
//
// You should have received a copy of the GNU Affero General Public License
// along with MuPDF. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html>
//
// Alternative licensing terms are available from the licensor.
// For commercial licensing, see <https://www.artifex.com/> or contact
// Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,
// CA 94129, USA, for further information.
#ifndef MUPDF_FITZ_GETOPT_H
#define MUPDF_FITZ_GETOPT_H
#include "export.h"
/**
Simple functions/variables for use in tools.
*/
extern int fz_getopt(int nargc, char * const *nargv, const char *ostr);
FZ_DATA extern int fz_optind;
FZ_DATA extern char *fz_optarg;
#endif
+96
View File
@@ -0,0 +1,96 @@
// Copyright (C) 2004-2021 Artifex Software, Inc.
//
// This file is part of MuPDF.
//
// MuPDF is free software: you can redistribute it and/or modify it under the
// terms of the GNU Affero General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option)
// any later version.
//
// MuPDF 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 Affero General Public License for more
// details.
//
// You should have received a copy of the GNU Affero General Public License
// along with MuPDF. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html>
//
// Alternative licensing terms are available from the licensor.
// For commercial licensing, see <https://www.artifex.com/> or contact
// Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,
// CA 94129, USA, for further information.
#ifndef MUPDF_FITZ_GLYPH_CACHE_H
#define MUPDF_FITZ_GLYPH_CACHE_H
#include "mupdf/fitz/context.h"
#include "mupdf/fitz/geometry.h"
#include "mupdf/fitz/font.h"
#include "mupdf/fitz/pixmap.h"
#include "mupdf/fitz/device.h"
/**
Purge all the glyphs from the cache.
*/
void fz_purge_glyph_cache(fz_context *ctx);
/**
Create a pixmap containing a rendered glyph.
Lookup gid from font, clip it with scissor, and rendering it
with aa bits of antialiasing into a new pixmap.
The caller takes ownership of the pixmap and so must free it.
Note: This function is no longer used for normal rendering
operations, and is kept around just because we use it in the
app. It should be considered "at risk" of removal from the API.
*/
fz_pixmap *fz_render_glyph_pixmap(fz_context *ctx, fz_font *font, int gid, fz_matrix *ctm, const fz_irect *scissor, int aa);
/**
Nasty PDF interpreter specific hernia, required to allow the
interpreter to replay glyphs from a type3 font directly into
the target device.
This is only used in exceptional circumstances (such as type3
glyphs that inherit current graphics state, or nested type3
glyphs).
*/
void fz_render_t3_glyph_direct(fz_context *ctx, fz_device *dev, fz_font *font, int gid, fz_matrix trm, void *gstate, fz_default_colorspaces *def_cs);
/**
Force a type3 font to cache the displaylist for a given glyph
id.
This caching can involve reading the underlying file, so must
happen ahead of time, so we aren't suddenly forced to read the
file while playing a displaylist back.
*/
void fz_prepare_t3_glyph(fz_context *ctx, fz_font *font, int gid);
/**
Dump debug statistics for the glyph cache.
*/
void fz_dump_glyph_cache_stats(fz_context *ctx, fz_output *out);
/**
Perform subpixel quantisation and adjustment on a glyph matrix.
ctm: On entry, the desired 'ideal' transformation for a glyph.
On exit, adjusted to a (very similar) transformation quantised
for subpixel caching.
subpix_ctm: Initialised by the routine to the transform that
should be used to render the glyph.
qe, qf: which subpixel position we quantised to.
Returns: the size of the glyph.
Note: This is currently only exposed for use in our app. It
should be considered "at risk" of removal from the API.
*/
float fz_subpixel_adjust(fz_context *ctx, fz_matrix *ctm, fz_matrix *subpix_ctm, unsigned char *qe, unsigned char *qf);
#endif
+81
View File
@@ -0,0 +1,81 @@
// Copyright (C) 2004-2021 Artifex Software, Inc.
//
// This file is part of MuPDF.
//
// MuPDF is free software: you can redistribute it and/or modify it under the
// terms of the GNU Affero General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option)
// any later version.
//
// MuPDF 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 Affero General Public License for more
// details.
//
// You should have received a copy of the GNU Affero General Public License
// along with MuPDF. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html>
//
// Alternative licensing terms are available from the licensor.
// For commercial licensing, see <https://www.artifex.com/> or contact
// Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,