Showing preview only (527K chars total). Download the full file or copy to clipboard to get everything.
Repository: viavansi/mupdf-android
Branch: master
Commit: 9fe7c5277834
Files: 100
Total size: 485.5 KB
Directory structure:
gitextract_jjhp7xc0/
├── .gitignore
├── COPYING
├── LICENSE
├── README.md
├── build.gradle
├── gradle.properties
├── proguard-rules.pro
└── src/
├── androidTest/
│ └── java/
│ └── com/
│ └── artifex/
│ └── viafirma/
│ └── mupdf/
│ └── ApplicationTest.java
└── main/
├── AndroidManifest.xml
├── java/
│ └── com/
│ └── artifex/
│ ├── mupdfdemo/
│ │ ├── Annotation.java
│ │ ├── ArrayDeque.java
│ │ ├── AsyncTask.java
│ │ ├── CancellableAsyncTask.java
│ │ ├── CancellableTaskDefinition.java
│ │ ├── ChoosePDFActivity.java
│ │ ├── ChoosePDFAdapter.java
│ │ ├── ChoosePDFItem.java
│ │ ├── Deque.java
│ │ ├── FilePicker.java
│ │ ├── LinkInfo.java
│ │ ├── LinkInfoExternal.java
│ │ ├── LinkInfoInternal.java
│ │ ├── LinkInfoRemote.java
│ │ ├── LinkInfoVisitor.java
│ │ ├── MuPDFActivity.java
│ │ ├── MuPDFAlert.java
│ │ ├── MuPDFAlertInternal.java
│ │ ├── MuPDFCancellableTaskDefinition.java
│ │ ├── MuPDFCore.java
│ │ ├── MuPDFFragment.java
│ │ ├── MuPDFPageAdapter.java
│ │ ├── MuPDFPageView.java
│ │ ├── MuPDFReaderView.java
│ │ ├── MuPDFReflowAdapter.java
│ │ ├── MuPDFReflowView.java
│ │ ├── MuPDFView.java
│ │ ├── OutlineActivity.java
│ │ ├── OutlineActivityData.java
│ │ ├── OutlineAdapter.java
│ │ ├── OutlineItem.java
│ │ ├── PageView.java
│ │ ├── PrintDialogActivity.java
│ │ ├── ReaderView.java
│ │ ├── SafeAnimatorInflater.java
│ │ ├── SearchTask.java
│ │ ├── SearchTaskResult.java
│ │ ├── Stepper.java
│ │ ├── TextChar.java
│ │ ├── TextWord.java
│ │ └── WidgetType.java
│ └── utils/
│ ├── DigitalizedEventCallback.java
│ └── PdfBitmap.java
└── res/
├── animator/
│ └── info.xml
├── drawable/
│ ├── busy.xml
│ ├── button.xml
│ ├── page_num.xml
│ ├── search.xml
│ ├── seek_progress.xml
│ ├── seek_thumb.xml
│ └── tiled_background.xml
├── layout/
│ ├── buttons.xml
│ ├── main.xml
│ ├── outline_entry.xml
│ ├── picker_entry.xml
│ ├── print_dialog.xml
│ └── textentry.xml
├── values/
│ ├── colors.xml
│ ├── strings.xml
│ └── styles.xml
├── values-ar/
│ └── strings.xml
├── values-ca/
│ └── strings.xml
├── values-cs/
│ └── strings.xml
├── values-da/
│ └── strings.xml
├── values-de/
│ └── strings.xml
├── values-el/
│ └── strings.xml
├── values-es/
│ └── strings.xml
├── values-et/
│ └── strings.xml
├── values-fi/
│ └── strings.xml
├── values-fr/
│ └── strings.xml
├── values-hi/
│ └── strings.xml
├── values-hu/
│ └── strings.xml
├── values-in/
│ └── strings.xml
├── values-it/
│ └── strings.xml
├── values-iw/
│ └── strings.xml
├── values-ja/
│ └── strings.xml
├── values-ko/
│ └── strings.xml
├── values-lt/
│ └── strings.xml
├── values-ms/
│ └── strings.xml
├── values-nl/
│ └── strings.xml
├── values-no/
│ └── strings.xml
├── values-pl/
│ └── strings.xml
├── values-pt/
│ └── strings.xml
├── values-ru/
│ └── strings.xml
├── values-sk/
│ └── strings.xml
├── values-sv/
│ └── strings.xml
├── values-th/
│ └── strings.xml
├── values-tl/
│ └── strings.xml
├── values-tr/
│ └── strings.xml
├── values-zh/
│ └── strings.xml
└── values-zh-rTW/
└── strings.xml
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
.gradle
/local.properties
/.idea/workspace.xml
/.idea/libraries
.DS_Store
/build
/*.iml
*.iml
================================================
FILE: COPYING
================================================
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/>.
================================================
FILE: LICENSE
================================================
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/>.
================================================
FILE: README.md
================================================
# MuPDF for Android
## Introduction
This project is intended to offer an easy integration of MuPDF library (http://www.mupdf.com) on Android, avoiding the building process and adapted to the last version of Android Studio and Gradle as of February 2015 (commit 262a4717a9997c89cac275d24ce6d605ca06284f from http://git.ghostscript.com/mupdf.git)
We also added some features:
* You can add custom Bitmaps to each page.
* You can use the MuPDFActivity as a Fragment (MuPDFFragment), that allows you to include it in your own activity as any other layout.
* You can add an interface listener to the page of the pdf, so you can listen when the user taps, double taps or long press any coordinate of the pdf.
This version is still on development.
## Installation guide
1. Make sure you have installed the newest NDK from https://developer.android.com/tools/sdk/ndk/index.html#Installing (version 9+ required)
================================================
FILE: build.gradle
================================================
repositories {
google()
mavenCentral()
jcenter()
maven { url "https://repositorio.viavansi.com/repo/" }
}
buildscript {
repositories {
google()
mavenCentral()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.4.2'
}
}
apply plugin: 'com.android.library'
apply plugin: 'maven-publish'
def muPdfversionCode = 22
def muPdfversionName = '1.2.24.1'
android {
compileSdkVersion 28
lintOptions {
abortOnError false
}
defaultConfig {
minSdkVersion 19
targetSdkVersion 31
versionCode muPdfversionCode
versionName muPdfversionName
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
configurations {
deployerJars
}
dependencies {
deployerJars 'org.apache.maven.wagon:wagon-http:2.2'
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.0.0'
}
// For Maven Repository submitting : Execute task: UploadArchives. Ex: > gradle uploadArchives
// Define repoUsername, repoPassword and repoUrl on "gradle.properties" file in order to use this task.
//uploadArchives {
// repositories.mavenDeployer {
// configuration = configurations.deployerJars
// repository(url: repoUrl) {
// authentication(userName: repoUsername, password: repoPassword)
// }
// pom.version = muPdfversionName
// pom.artifactId = "mupdf-android"
// pom.groupId = "com.viafirma"
// }
//}
================================================
FILE: gradle.properties
================================================
# Project-wide Gradle settings.
# IDE (e.g. Android Studio) users:
# Settings specified in this file will override any Gradle settings
# configured through the IDE.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
# Default value: -Xmx10248m -XX:MaxPermSize=256m
# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
repoUrl=http://repositorio.viavansi.com/artifactory/libs-releases-local
repoUsername=<username>
repoPassword=<password>
android.useDeprecatedNdk=true
================================================
FILE: proguard-rules.pro
================================================
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in /Applications/android-sdk-macosx/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
================================================
FILE: src/androidTest/java/com/artifex/viafirma/mupdf/ApplicationTest.java
================================================
package com.artifex.viafirma.mupdf;
import android.app.Application;
import android.test.ApplicationTestCase;
/**
* <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a>
*/
public class ApplicationTest extends ApplicationTestCase<Application> {
public ApplicationTest() {
super(Application.class);
}
}
================================================
FILE: src/main/AndroidManifest.xml
================================================
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.artifex.mupdfdemo"
android:installLocation="auto">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET" />
<supports-screens
android:smallScreens="true"
android:normalScreens="true"
android:largeScreens="true"
android:anyDensity="true" />
<application
android:label="@string/mupdf_title"
android:hardwareAccelerated="true">
</application>
</manifest>
================================================
FILE: src/main/java/com/artifex/mupdfdemo/Annotation.java
================================================
package com.artifex.mupdfdemo;
import android.graphics.RectF;
public class Annotation extends RectF {
enum Type {
TEXT, LINK, FREETEXT, LINE, SQUARE, CIRCLE, POLYGON, POLYLINE, HIGHLIGHT,
UNDERLINE, SQUIGGLY, STRIKEOUT, STAMP, CARET, INK, POPUP, FILEATTACHMENT,
SOUND, MOVIE, WIDGET, SCREEN, PRINTERMARK, TRAPNET, WATERMARK, A3D, UNKNOWN
}
public final Type type;
public Annotation(float x0, float y0, float x1, float y1, int _type) {
super(x0, y0, x1, y1);
type = _type == -1 ? Type.UNKNOWN : Type.values()[_type];
}
}
================================================
FILE: src/main/java/com/artifex/mupdfdemo/ArrayDeque.java
================================================
/*
* Written by Josh Bloch of Google Inc. and released to the public domain,
* as explained at http://creativecommons.org/publicdomain/zero/1.0/.
*/
package com.artifex.mupdfdemo;
import java.util.AbstractCollection;
import java.util.Arrays;
import java.util.Collection;
import java.util.ConcurrentModificationException;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Queue;
import java.util.Stack;
// BEGIN android-note
// removed link to collections framework docs
// END android-note
/**
* Resizable-array implementation of the {@link Deque} interface. Array
* deques have no capacity restrictions; they grow as necessary to support
* usage. They are not thread-safe; in the absence of external
* synchronization, they do not support concurrent access by multiple threads.
* Null elements are prohibited. This class is likely to be faster than
* {@link java.util.Stack} when used as a stack, and faster than {@link java.util.LinkedList}
* when used as a queue.
*
* <p>Most <tt>ArrayDeque</tt> operations run in amortized constant time.
* Exceptions include {@link #remove(Object) remove}, {@link
* #removeFirstOccurrence removeFirstOccurrence}, {@link #removeLastOccurrence
* removeLastOccurrence}, {@link #contains contains}, {@link #iterator
* iterator.remove()}, and the bulk operations, all of which run in linear
* time.
*
* <p>The iterators returned by this class's <tt>iterator</tt> method are
* <i>fail-fast</i>: If the deque is modified at any time after the iterator
* is created, in any way except through the iterator's own <tt>remove</tt>
* method, the iterator will generally throw a {@link
* java.util.ConcurrentModificationException}. Thus, in the face of concurrent
* modification, the iterator fails quickly and cleanly, rather than risking
* arbitrary, non-deterministic behavior at an undetermined time in the
* future.
*
* <p>Note that the fail-fast behavior of an iterator cannot be guaranteed
* as it is, generally speaking, impossible to make any hard guarantees in the
* presence of unsynchronized concurrent modification. Fail-fast iterators
* throw <tt>ConcurrentModificationException</tt> on a best-effort basis.
* Therefore, it would be wrong to write a program that depended on this
* exception for its correctness: <i>the fail-fast behavior of iterators
* should be used only to detect bugs.</i>
*
* <p>This class and its iterator implement all of the
* <em>optional</em> methods of the {@link java.util.Collection} and {@link
* java.util.Iterator} interfaces.
*
* @author Josh Bloch and Doug Lea
* @since 1.6
* @param <E> the type of elements held in this collection
*/
public class ArrayDeque<E> extends AbstractCollection<E>
implements Deque<E>, Cloneable, java.io.Serializable
{
/**
* The array in which the elements of the deque are stored.
* The capacity of the deque is the length of this array, which is
* always a power of two. The array is never allowed to become
* full, except transiently within an addX method where it is
* resized (see doubleCapacity) immediately upon becoming full,
* thus avoiding head and tail wrapping around to equal each
* other. We also guarantee that all array cells not holding
* deque elements are always null.
*/
private transient Object[] elements;
/**
* The index of the element at the head of the deque (which is the
* element that would be removed by remove() or pop()); or an
* arbitrary number equal to tail if the deque is empty.
*/
private transient int head;
/**
* The index at which the next element would be added to the tail
* of the deque (via addLast(E), add(E), or push(E)).
*/
private transient int tail;
/**
* The minimum capacity that we'll use for a newly created deque.
* Must be a power of 2.
*/
private static final int MIN_INITIAL_CAPACITY = 8;
// ****** Array allocation and resizing utilities ******
/**
* Allocate empty array to hold the given number of elements.
*
* @param numElements the number of elements to hold
*/
private void allocateElements(int numElements) {
int initialCapacity = MIN_INITIAL_CAPACITY;
// Find the best power of two to hold elements.
// Tests "<=" because arrays aren't kept full.
if (numElements >= initialCapacity) {
initialCapacity = numElements;
initialCapacity |= (initialCapacity >>> 1);
initialCapacity |= (initialCapacity >>> 2);
initialCapacity |= (initialCapacity >>> 4);
initialCapacity |= (initialCapacity >>> 8);
initialCapacity |= (initialCapacity >>> 16);
initialCapacity++;
if (initialCapacity < 0) // Too many elements, must back off
initialCapacity >>>= 1;// Good luck allocating 2 ^ 30 elements
}
elements = new Object[initialCapacity];
}
/**
* Double the capacity of this deque. Call only when full, i.e.,
* when head and tail have wrapped around to become equal.
*/
private void doubleCapacity() {
// assert head == tail;
int p = head;
int n = elements.length;
int r = n - p; // number of elements to the right of p
int newCapacity = n << 1;
if (newCapacity < 0)
throw new IllegalStateException("Sorry, deque too big");
Object[] a = new Object[newCapacity];
System.arraycopy(elements, p, a, 0, r);
System.arraycopy(elements, 0, a, r, p);
elements = a;
head = 0;
tail = n;
}
/**
* Copies the elements from our element array into the specified array,
* in order (from first to last element in the deque). It is assumed
* that the array is large enough to hold all elements in the deque.
*
* @return its argument
*/
private <T> T[] copyElements(T[] a) {
if (head < tail) {
System.arraycopy(elements, head, a, 0, size());
} else if (head > tail) {
int headPortionLen = elements.length - head;
System.arraycopy(elements, head, a, 0, headPortionLen);
System.arraycopy(elements, 0, a, headPortionLen, tail);
}
return a;
}
/**
* Constructs an empty array deque with an initial capacity
* sufficient to hold 16 elements.
*/
public ArrayDeque() {
elements = new Object[16];
}
/**
* Constructs an empty array deque with an initial capacity
* sufficient to hold the specified number of elements.
*
* @param numElements lower bound on initial capacity of the deque
*/
public ArrayDeque(int numElements) {
allocateElements(numElements);
}
/**
* Constructs a deque containing the elements of the specified
* collection, in the order they are returned by the collection's
* iterator. (The first element returned by the collection's
* iterator becomes the first element, or <i>front</i> of the
* deque.)
*
* @param c the collection whose elements are to be placed into the deque
* @throws NullPointerException if the specified collection is null
*/
public ArrayDeque(Collection<? extends E> c) {
allocateElements(c.size());
addAll(c);
}
// The main insertion and extraction methods are addFirst,
// addLast, pollFirst, pollLast. The other methods are defined in
// terms of these.
/**
* Inserts the specified element at the front of this deque.
*
* @param e the element to add
* @throws NullPointerException if the specified element is null
*/
public void addFirst(E e) {
if (e == null)
throw new NullPointerException("e == null");
elements[head = (head - 1) & (elements.length - 1)] = e;
if (head == tail)
doubleCapacity();
}
/**
* Inserts the specified element at the end of this deque.
*
* <p>This method is equivalent to {@link #add}.
*
* @param e the element to add
* @throws NullPointerException if the specified element is null
*/
public void addLast(E e) {
if (e == null)
throw new NullPointerException("e == null");
elements[tail] = e;
if ( (tail = (tail + 1) & (elements.length - 1)) == head)
doubleCapacity();
}
/**
* Inserts the specified element at the front of this deque.
*
* @param e the element to add
* @return <tt>true</tt> (as specified by {@link Deque#offerFirst})
* @throws NullPointerException if the specified element is null
*/
public boolean offerFirst(E e) {
addFirst(e);
return true;
}
/**
* Inserts the specified element at the end of this deque.
*
* @param e the element to add
* @return <tt>true</tt> (as specified by {@link Deque#offerLast})
* @throws NullPointerException if the specified element is null
*/
public boolean offerLast(E e) {
addLast(e);
return true;
}
/**
* @throws java.util.NoSuchElementException {@inheritDoc}
*/
public E removeFirst() {
E x = pollFirst();
if (x == null)
throw new NoSuchElementException();
return x;
}
/**
* @throws java.util.NoSuchElementException {@inheritDoc}
*/
public E removeLast() {
E x = pollLast();
if (x == null)
throw new NoSuchElementException();
return x;
}
public E pollFirst() {
int h = head;
@SuppressWarnings("unchecked") E result = (E) elements[h];
// Element is null if deque empty
if (result == null)
return null;
elements[h] = null; // Must null out slot
head = (h + 1) & (elements.length - 1);
return result;
}
public E pollLast() {
int t = (tail - 1) & (elements.length - 1);
@SuppressWarnings("unchecked") E result = (E) elements[t];
if (result == null)
return null;
elements[t] = null;
tail = t;
return result;
}
/**
* @throws java.util.NoSuchElementException {@inheritDoc}
*/
public E getFirst() {
@SuppressWarnings("unchecked") E result = (E) elements[head];
if (result == null)
throw new NoSuchElementException();
return result;
}
/**
* @throws java.util.NoSuchElementException {@inheritDoc}
*/
public E getLast() {
@SuppressWarnings("unchecked")
E result = (E) elements[(tail - 1) & (elements.length - 1)];
if (result == null)
throw new NoSuchElementException();
return result;
}
public E peekFirst() {
@SuppressWarnings("unchecked") E result = (E) elements[head];
// elements[head] is null if deque empty
return result;
}
public E peekLast() {
@SuppressWarnings("unchecked")
E result = (E) elements[(tail - 1) & (elements.length - 1)];
return result;
}
/**
* Removes the first occurrence of the specified element in this
* deque (when traversing the deque from head to tail).
* If the deque does not contain the element, it is unchanged.
* More formally, removes the first element <tt>e</tt> such that
* <tt>o.equals(e)</tt> (if such an element exists).
* Returns <tt>true</tt> if this deque contained the specified element
* (or equivalently, if this deque changed as a result of the call).
*
* @param o element to be removed from this deque, if present
* @return <tt>true</tt> if the deque contained the specified element
*/
public boolean removeFirstOccurrence(Object o) {
if (o == null)
return false;
int mask = elements.length - 1;
int i = head;
Object x;
while ( (x = elements[i]) != null) {
if (o.equals(x)) {
delete(i);
return true;
}
i = (i + 1) & mask;
}
return false;
}
/**
* Removes the last occurrence of the specified element in this
* deque (when traversing the deque from head to tail).
* If the deque does not contain the element, it is unchanged.
* More formally, removes the last element <tt>e</tt> such that
* <tt>o.equals(e)</tt> (if such an element exists).
* Returns <tt>true</tt> if this deque contained the specified element
* (or equivalently, if this deque changed as a result of the call).
*
* @param o element to be removed from this deque, if present
* @return <tt>true</tt> if the deque contained the specified element
*/
public boolean removeLastOccurrence(Object o) {
if (o == null)
return false;
int mask = elements.length - 1;
int i = (tail - 1) & mask;
Object x;
while ( (x = elements[i]) != null) {
if (o.equals(x)) {
delete(i);
return true;
}
i = (i - 1) & mask;
}
return false;
}
// *** Queue methods ***
/**
* Inserts the specified element at the end of this deque.
*
* <p>This method is equivalent to {@link #addLast}.
*
* @param e the element to add
* @return <tt>true</tt> (as specified by {@link java.util.Collection#add})
* @throws NullPointerException if the specified element is null
*/
public boolean add(E e) {
addLast(e);
return true;
}
/**
* Inserts the specified element at the end of this deque.
*
* <p>This method is equivalent to {@link #offerLast}.
*
* @param e the element to add
* @return <tt>true</tt> (as specified by {@link java.util.Queue#offer})
* @throws NullPointerException if the specified element is null
*/
public boolean offer(E e) {
return offerLast(e);
}
/**
* Retrieves and removes the head of the queue represented by this deque.
*
* This method differs from {@link #poll poll} only in that it throws an
* exception if this deque is empty.
*
* <p>This method is equivalent to {@link #removeFirst}.
*
* @return the head of the queue represented by this deque
* @throws java.util.NoSuchElementException {@inheritDoc}
*/
public E remove() {
return removeFirst();
}
/**
* Retrieves and removes the head of the queue represented by this deque
* (in other words, the first element of this deque), or returns
* <tt>null</tt> if this deque is empty.
*
* <p>This method is equivalent to {@link #pollFirst}.
*
* @return the head of the queue represented by this deque, or
* <tt>null</tt> if this deque is empty
*/
public E poll() {
return pollFirst();
}
/**
* Retrieves, but does not remove, the head of the queue represented by
* this deque. This method differs from {@link #peek peek} only in
* that it throws an exception if this deque is empty.
*
* <p>This method is equivalent to {@link #getFirst}.
*
* @return the head of the queue represented by this deque
* @throws java.util.NoSuchElementException {@inheritDoc}
*/
public E element() {
return getFirst();
}
/**
* Retrieves, but does not remove, the head of the queue represented by
* this deque, or returns <tt>null</tt> if this deque is empty.
*
* <p>This method is equivalent to {@link #peekFirst}.
*
* @return the head of the queue represented by this deque, or
* <tt>null</tt> if this deque is empty
*/
public E peek() {
return peekFirst();
}
// *** Stack methods ***
/**
* Pushes an element onto the stack represented by this deque. In other
* words, inserts the element at the front of this deque.
*
* <p>This method is equivalent to {@link #addFirst}.
*
* @param e the element to push
* @throws NullPointerException if the specified element is null
*/
public void push(E e) {
addFirst(e);
}
/**
* Pops an element from the stack represented by this deque. In other
* words, removes and returns the first element of this deque.
*
* <p>This method is equivalent to {@link #removeFirst()}.
*
* @return the element at the front of this deque (which is the top
* of the stack represented by this deque)
* @throws java.util.NoSuchElementException {@inheritDoc}
*/
public E pop() {
return removeFirst();
}
private void checkInvariants() {
// assert elements[tail] == null;
// assert head == tail ? elements[head] == null :
// (elements[head] != null &&
// elements[(tail - 1) & (elements.length - 1)] != null);
// assert elements[(head - 1) & (elements.length - 1)] == null;
}
/**
* Removes the element at the specified position in the elements array,
* adjusting head and tail as necessary. This can result in motion of
* elements backwards or forwards in the array.
*
* <p>This method is called delete rather than remove to emphasize
* that its semantics differ from those of {@link java.util.List#remove(int)}.
*
* @return true if elements moved backwards
*/
private boolean delete(int i) {
//checkInvariants();
final Object[] elements = this.elements;
final int mask = elements.length - 1;
final int h = head;
final int t = tail;
final int front = (i - h) & mask;
final int back = (t - i) & mask;
// Invariant: head <= i < tail mod circularity
if (front >= ((t - h) & mask))
throw new ConcurrentModificationException();
// Optimize for least element motion
if (front < back) {
if (h <= i) {
System.arraycopy(elements, h, elements, h + 1, front);
} else { // Wrap around
System.arraycopy(elements, 0, elements, 1, i);
elements[0] = elements[mask];
System.arraycopy(elements, h, elements, h + 1, mask - h);
}
elements[h] = null;
head = (h + 1) & mask;
return false;
} else {
if (i < t) { // Copy the null tail as well
System.arraycopy(elements, i + 1, elements, i, back);
tail = t - 1;
} else { // Wrap around
System.arraycopy(elements, i + 1, elements, i, mask - i);
elements[mask] = elements[0];
System.arraycopy(elements, 1, elements, 0, t);
tail = (t - 1) & mask;
}
return true;
}
}
// *** Collection Methods ***
/**
* Returns the number of elements in this deque.
*
* @return the number of elements in this deque
*/
public int size() {
return (tail - head) & (elements.length - 1);
}
/**
* Returns <tt>true</tt> if this deque contains no elements.
*
* @return <tt>true</tt> if this deque contains no elements
*/
public boolean isEmpty() {
return head == tail;
}
/**
* Returns an iterator over the elements in this deque. The elements
* will be ordered from first (head) to last (tail). This is the same
* order that elements would be dequeued (via successive calls to
* {@link #remove} or popped (via successive calls to {@link #pop}).
*
* @return an iterator over the elements in this deque
*/
public Iterator<E> iterator() {
return new DeqIterator();
}
public Iterator<E> descendingIterator() {
return new DescendingIterator();
}
private class DeqIterator implements Iterator<E> {
/**
* Index of element to be returned by subsequent call to next.
*/
private int cursor = head;
/**
* Tail recorded at construction (also in remove), to stop
* iterator and also to check for comodification.
*/
private int fence = tail;
/**
* Index of element returned by most recent call to next.
* Reset to -1 if element is deleted by a call to remove.
*/
private int lastRet = -1;
public boolean hasNext() {
return cursor != fence;
}
public E next() {
if (cursor == fence)
throw new NoSuchElementException();
@SuppressWarnings("unchecked") E result = (E) elements[cursor];
// This check doesn't catch all possible comodifications,
// but does catch the ones that corrupt traversal
if (tail != fence || result == null)
throw new ConcurrentModificationException();
lastRet = cursor;
cursor = (cursor + 1) & (elements.length - 1);
return result;
}
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
if (delete(lastRet)) { // if left-shifted, undo increment in next()
cursor = (cursor - 1) & (elements.length - 1);
fence = tail;
}
lastRet = -1;
}
}
private class DescendingIterator implements Iterator<E> {
/*
* This class is nearly a mirror-image of DeqIterator, using
* tail instead of head for initial cursor, and head instead of
* tail for fence.
*/
private int cursor = tail;
private int fence = head;
private int lastRet = -1;
public boolean hasNext() {
return cursor != fence;
}
public E next() {
if (cursor == fence)
throw new NoSuchElementException();
cursor = (cursor - 1) & (elements.length - 1);
@SuppressWarnings("unchecked") E result = (E) elements[cursor];
if (head != fence || result == null)
throw new ConcurrentModificationException();
lastRet = cursor;
return result;
}
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
if (!delete(lastRet)) {
cursor = (cursor + 1) & (elements.length - 1);
fence = head;
}
lastRet = -1;
}
}
/**
* Returns <tt>true</tt> if this deque contains the specified element.
* More formally, returns <tt>true</tt> if and only if this deque contains
* at least one element <tt>e</tt> such that <tt>o.equals(e)</tt>.
*
* @param o object to be checked for containment in this deque
* @return <tt>true</tt> if this deque contains the specified element
*/
public boolean contains(Object o) {
if (o == null)
return false;
int mask = elements.length - 1;
int i = head;
Object x;
while ( (x = elements[i]) != null) {
if (o.equals(x))
return true;
i = (i + 1) & mask;
}
return false;
}
/**
* Removes a single instance of the specified element from this deque.
* If the deque does not contain the element, it is unchanged.
* More formally, removes the first element <tt>e</tt> such that
* <tt>o.equals(e)</tt> (if such an element exists).
* Returns <tt>true</tt> if this deque contained the specified element
* (or equivalently, if this deque changed as a result of the call).
*
* <p>This method is equivalent to {@link #removeFirstOccurrence}.
*
* @param o element to be removed from this deque, if present
* @return <tt>true</tt> if this deque contained the specified element
*/
public boolean remove(Object o) {
return removeFirstOccurrence(o);
}
/**
* Removes all of the elements from this deque.
* The deque will be empty after this call returns.
*/
public void clear() {
int h = head;
int t = tail;
if (h != t) { // clear all cells
head = tail = 0;
int i = h;
int mask = elements.length - 1;
do {
elements[i] = null;
i = (i + 1) & mask;
} while (i != t);
}
}
/**
* Returns an array containing all of the elements in this deque
* in proper sequence (from first to last element).
*
* <p>The returned array will be "safe" in that no references to it are
* maintained by this deque. (In other words, this method must allocate
* a new array). The caller is thus free to modify the returned array.
*
* <p>This method acts as bridge between array-based and collection-based
* APIs.
*
* @return an array containing all of the elements in this deque
*/
public Object[] toArray() {
return copyElements(new Object[size()]);
}
/**
* Returns an array containing all of the elements in this deque in
* proper sequence (from first to last element); the runtime type of the
* returned array is that of the specified array. If the deque fits in
* the specified array, it is returned therein. Otherwise, a new array
* is allocated with the runtime type of the specified array and the
* size of this deque.
*
* <p>If this deque fits in the specified array with room to spare
* (i.e., the array has more elements than this deque), the element in
* the array immediately following the end of the deque is set to
* <tt>null</tt>.
*
* <p>Like the {@link #toArray()} method, this method acts as bridge between
* array-based and collection-based APIs. Further, this method allows
* precise control over the runtime type of the output array, and may,
* under certain circumstances, be used to save allocation costs.
*
* <p>Suppose <tt>x</tt> is a deque known to contain only strings.
* The following code can be used to dump the deque into a newly
* allocated array of <tt>String</tt>:
*
* <pre> {@code String[] y = x.toArray(new String[0]);}</pre>
*
* Note that <tt>toArray(new Object[0])</tt> is identical in function to
* <tt>toArray()</tt>.
*
* @param a the array into which the elements of the deque are to
* be stored, if it is big enough; otherwise, a new array of the
* same runtime type is allocated for this purpose
* @return an array containing all of the elements in this deque
* @throws ArrayStoreException if the runtime type of the specified array
* is not a supertype of the runtime type of every element in
* this deque
* @throws NullPointerException if the specified array is null
*/
@SuppressWarnings("unchecked")
public <T> T[] toArray(T[] a) {
int size = size();
if (a.length < size)
a = (T[])java.lang.reflect.Array.newInstance(
a.getClass().getComponentType(), size);
copyElements(a);
if (a.length > size)
a[size] = null;
return a;
}
// *** Object methods ***
/**
* Returns a copy of this deque.
*
* @return a copy of this deque
*/
public ArrayDeque<E> clone() {
try {
@SuppressWarnings("unchecked")
ArrayDeque<E> result = (ArrayDeque<E>) super.clone();
result.elements = Arrays.copyOf(elements, elements.length);
return result;
} catch (CloneNotSupportedException e) {
throw new AssertionError();
}
}
/**
* Appease the serialization gods.
*/
private static final long serialVersionUID = 2340985798034038923L;
/**
* Serialize this deque.
*
* @serialData The current size (<tt>int</tt>) of the deque,
* followed by all of its elements (each an object reference) in
* first-to-last order.
*/
private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException {
s.defaultWriteObject();
// Write out size
s.writeInt(size());
// Write out elements in order.
int mask = elements.length - 1;
for (int i = head; i != tail; i = (i + 1) & mask)
s.writeObject(elements[i]);
}
/**
* Deserialize this deque.
*/
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
s.defaultReadObject();
// Read in size and allocate array
int size = s.readInt();
allocateElements(size);
head = 0;
tail = size;
// Read in all elements in the proper order.
for (int i = 0; i < size; i++)
elements[i] = s.readObject();
}
}
================================================
FILE: src/main/java/com/artifex/mupdfdemo/AsyncTask.java
================================================
/*
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.artifex.mupdfdemo;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.FutureTask;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import android.os.Process;
import android.os.Handler;
import android.os.Message;
/**
* <p>AsyncTask enables proper and easy use of the UI thread. This class allows to
* perform background operations and publish results on the UI thread without
* having to manipulate threads and/or handlers.</p>
*
* <p>AsyncTask is designed to be a helper class around {@link Thread} and {@link android.os.Handler}
* and does not constitute a generic threading framework. AsyncTasks should ideally be
* used for short operations (a few seconds at the most.) If you need to keep threads
* running for long periods of time, it is highly recommended you use the various APIs
* provided by the <code>java.util.concurrent</code> pacakge such as {@link java.util.concurrent.Executor},
* {@link java.util.concurrent.ThreadPoolExecutor} and {@link java.util.concurrent.FutureTask}.</p>
*
* <p>An asynchronous task is defined by a computation that runs on a background thread and
* whose result is published on the UI thread. An asynchronous task is defined by 3 generic
* types, called <code>Params</code>, <code>Progress</code> and <code>Result</code>,
* and 4 steps, called <code>onPreExecute</code>, <code>doInBackground</code>,
* <code>onProgressUpdate</code> and <code>onPostExecute</code>.</p>
*
* <div class="special reference">
* <h3>Developer Guides</h3>
* <p>For more information about using tasks and threads, read the
* <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html">Processes and
* Threads</a> developer guide.</p>
* </div>
*
* <h2>Usage</h2>
* <p>AsyncTask must be subclassed to be used. The subclass will override at least
* one method ({@link #doInBackground}), and most often will override a
* second one ({@link #onPostExecute}.)</p>
*
* <p>Here is an example of subclassing:</p>
* <pre class="prettyprint">
* private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
* protected Long doInBackground(URL... urls) {
* int count = urls.length;
* long totalSize = 0;
* for (int i = 0; i < count; i++) {
* totalSize += Downloader.downloadFile(urls[i]);
* publishProgress((int) ((i / (float) count) * 100));
* // Escape early if cancel() is called
* if (isCancelled()) break;
* }
* return totalSize;
* }
*
* protected void onProgressUpdate(Integer... progress) {
* setProgressPercent(progress[0]);
* }
*
* protected void onPostExecute(Long result) {
* showDialog("Downloaded " + result + " bytes");
* }
* }
* </pre>
*
* <p>Once created, a task is executed very simply:</p>
* <pre class="prettyprint">
* new DownloadFilesTask().execute(url1, url2, url3);
* </pre>
*
* <h2>AsyncTask's generic types</h2>
* <p>The three types used by an asynchronous task are the following:</p>
* <ol>
* <li><code>Params</code>, the type of the parameters sent to the task upon
* execution.</li>
* <li><code>Progress</code>, the type of the progress units published during
* the background computation.</li>
* <li><code>Result</code>, the type of the result of the background
* computation.</li>
* </ol>
* <p>Not all types are always used by an asynchronous task. To mark a type as unused,
* simply use the type {@link Void}:</p>
* <pre>
* private class MyTask extends AsyncTask<Void, Void, Void> { ... }
* </pre>
*
* <h2>The 4 steps</h2>
* <p>When an asynchronous task is executed, the task goes through 4 steps:</p>
* <ol>
* <li>{@link #onPreExecute()}, invoked on the UI thread before the task
* is executed. This step is normally used to setup the task, for instance by
* showing a progress bar in the user interface.</li>
* <li>{@link #doInBackground}, invoked on the background thread
* immediately after {@link #onPreExecute()} finishes executing. This step is used
* to perform background computation that can take a long time. The parameters
* of the asynchronous task are passed to this step. The result of the computation must
* be returned by this step and will be passed back to the last step. This step
* can also use {@link #publishProgress} to publish one or more units
* of progress. These values are published on the UI thread, in the
* {@link #onProgressUpdate} step.</li>
* <li>{@link #onProgressUpdate}, invoked on the UI thread after a
* call to {@link #publishProgress}. The timing of the execution is
* undefined. This method is used to display any form of progress in the user
* interface while the background computation is still executing. For instance,
* it can be used to animate a progress bar or show logs in a text field.</li>
* <li>{@link #onPostExecute}, invoked on the UI thread after the background
* computation finishes. The result of the background computation is passed to
* this step as a parameter.</li>
* </ol>
*
* <h2>Cancelling a task</h2>
* <p>A task can be cancelled at any time by invoking {@link #cancel(boolean)}. Invoking
* this method will cause subsequent calls to {@link #isCancelled()} to return true.
* After invoking this method, {@link #onCancelled(Object)}, instead of
* {@link #onPostExecute(Object)} will be invoked after {@link #doInBackground(Object[])}
* returns. To ensure that a task is cancelled as quickly as possible, you should always
* check the return value of {@link #isCancelled()} periodically from
* {@link #doInBackground(Object[])}, if possible (inside a loop for instance.)</p>
*
* <h2>Threading rules</h2>
* <p>There are a few threading rules that must be followed for this class to
* work properly:</p>
* <ul>
* <li>The AsyncTask class must be loaded on the UI thread. This is done
* automatically as of {@link android.os.Build.VERSION_CODES#JELLY_BEAN}.</li>
* <li>The task instance must be created on the UI thread.</li>
* <li>{@link #execute} must be invoked on the UI thread.</li>
* <li>Do not call {@link #onPreExecute()}, {@link #onPostExecute},
* {@link #doInBackground}, {@link #onProgressUpdate} manually.</li>
* <li>The task can be executed only once (an exception will be thrown if
* a second execution is attempted.)</li>
* </ul>
*
* <h2>Memory observability</h2>
* <p>AsyncTask guarantees that all callback calls are synchronized in such a way that the following
* operations are safe without explicit synchronizations.</p>
* <ul>
* <li>Set member fields in the constructor or {@link #onPreExecute}, and refer to them
* in {@link #doInBackground}.
* <li>Set member fields in {@link #doInBackground}, and refer to them in
* {@link #onProgressUpdate} and {@link #onPostExecute}.
* </ul>
*
* <h2>Order of execution</h2>
* <p>When first introduced, AsyncTasks were executed serially on a single background
* thread. Starting with {@link android.os.Build.VERSION_CODES#DONUT}, this was changed
* to a pool of threads allowing multiple tasks to operate in parallel. Starting with
* {@link android.os.Build.VERSION_CODES#HONEYCOMB}, tasks are executed on a single
* thread to avoid common application errors caused by parallel execution.</p>
* <p>If you truly want parallel execution, you can invoke
* {@link #executeOnExecutor(java.util.concurrent.Executor, Object[])} with
* {@link #THREAD_POOL_EXECUTOR}.</p>
*/
public abstract class AsyncTask<Params, Progress, Result> {
private static final String LOG_TAG = "AsyncTask";
private static final int CORE_POOL_SIZE = 5;
private static final int MAXIMUM_POOL_SIZE = 128;
private static final int KEEP_ALIVE = 1;
private static final ThreadFactory sThreadFactory = new ThreadFactory() {
private final AtomicInteger mCount = new AtomicInteger(1);
public Thread newThread(Runnable r) {
return new Thread(r, "AsyncTask #" + mCount.getAndIncrement());
}
};
private static final BlockingQueue<Runnable> sPoolWorkQueue =
new LinkedBlockingQueue<Runnable>(10);
/**
* An {@link java.util.concurrent.Executor} that can be used to execute tasks in parallel.
*/
public static final Executor THREAD_POOL_EXECUTOR
= new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE,
TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);
/**
* An {@link java.util.concurrent.Executor} that executes tasks one at a time in serial
* order. This serialization is global to a particular process.
*/
public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
private static final int MESSAGE_POST_RESULT = 0x1;
private static final int MESSAGE_POST_PROGRESS = 0x2;
private static final InternalHandler sHandler = new InternalHandler();
private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
private final WorkerRunnable<Params, Result> mWorker;
private final FutureTask<Result> mFuture;
private volatile Status mStatus = Status.PENDING;
private final AtomicBoolean mCancelled = new AtomicBoolean();
private final AtomicBoolean mTaskInvoked = new AtomicBoolean();
private static class SerialExecutor implements Executor {
final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
Runnable mActive;
public synchronized void execute(final Runnable r) {
mTasks.offer(new Runnable() {
public void run() {
try {
r.run();
} finally {
scheduleNext();
}
}
});
if (mActive == null) {
scheduleNext();
}
}
protected synchronized void scheduleNext() {
if ((mActive = mTasks.poll()) != null) {
THREAD_POOL_EXECUTOR.execute(mActive);
}
}
}
/**
* Indicates the current status of the task. Each status will be set only once
* during the lifetime of a task.
*/
public enum Status {
/**
* Indicates that the task has not been executed yet.
*/
PENDING,
/**
* Indicates that the task is running.
*/
RUNNING,
/**
* Indicates that {@link com.artifex.mupdfdemo.AsyncTask#onPostExecute} has finished.
*/
FINISHED,
}
/** @hide Used to force static handler to be created. */
public static void init() {
sHandler.getLooper();
}
/** @hide */
public static void setDefaultExecutor(Executor exec) {
sDefaultExecutor = exec;
}
/**
* Creates a new asynchronous task. This constructor must be invoked on the UI thread.
*/
public AsyncTask() {
mWorker = new WorkerRunnable<Params, Result>() {
public Result call() throws Exception {
mTaskInvoked.set(true);
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
//noinspection unchecked
return postResult(doInBackground(mParams));
}
};
mFuture = new FutureTask<Result>(mWorker) {
@Override
protected void done() {
try {
postResultIfNotInvoked(get());
} catch (InterruptedException e) {
android.util.Log.w(LOG_TAG, e);
} catch (ExecutionException e) {
throw new RuntimeException("An error occured while executing doInBackground()",
e.getCause());
} catch (CancellationException e) {
postResultIfNotInvoked(null);
}
}
};
}
private void postResultIfNotInvoked(Result result) {
final boolean wasTaskInvoked = mTaskInvoked.get();
if (!wasTaskInvoked) {
postResult(result);
}
}
private Result postResult(Result result) {
@SuppressWarnings("unchecked")
Message message = sHandler.obtainMessage(MESSAGE_POST_RESULT,
new AsyncTaskResult<Result>(this, result));
message.sendToTarget();
return result;
}
/**
* Returns the current status of this task.
*
* @return The current status.
*/
public final Status getStatus() {
return mStatus;
}
/**
* Override this method to perform a computation on a background thread. The
* specified parameters are the parameters passed to {@link #execute}
* by the caller of this task.
*
* This method can call {@link #publishProgress} to publish updates
* on the UI thread.
*
* @param params The parameters of the task.
*
* @return A result, defined by the subclass of this task.
*
* @see #onPreExecute()
* @see #onPostExecute
* @see #publishProgress
*/
protected abstract Result doInBackground(Params... params);
/**
* Runs on the UI thread before {@link #doInBackground}.
*
* @see #onPostExecute
* @see #doInBackground
*/
protected void onPreExecute() {
}
/**
* <p>Runs on the UI thread after {@link #doInBackground}. The
* specified result is the value returned by {@link #doInBackground}.</p>
*
* <p>This method won't be invoked if the task was cancelled.</p>
*
* @param result The result of the operation computed by {@link #doInBackground}.
*
* @see #onPreExecute
* @see #doInBackground
* @see #onCancelled(Object)
*/
@SuppressWarnings({"UnusedDeclaration"})
protected void onPostExecute(Result result) {
}
/**
* Runs on the UI thread after {@link #publishProgress} is invoked.
* The specified values are the values passed to {@link #publishProgress}.
*
* @param values The values indicating progress.
*
* @see #publishProgress
* @see #doInBackground
*/
@SuppressWarnings({"UnusedDeclaration"})
protected void onProgressUpdate(Progress... values) {
}
/**
* <p>Runs on the UI thread after {@link #cancel(boolean)} is invoked and
* {@link #doInBackground(Object[])} has finished.</p>
*
* <p>The default implementation simply invokes {@link #onCancelled()} and
* ignores the result. If you write your own implementation, do not call
* <code>super.onCancelled(result)</code>.</p>
*
* @param result The result, if any, computed in
* {@link #doInBackground(Object[])}, can be null
*
* @see #cancel(boolean)
* @see #isCancelled()
*/
@SuppressWarnings({"UnusedParameters"})
protected void onCancelled(Result result) {
onCancelled();
}
/**
* <p>Applications should preferably override {@link #onCancelled(Object)}.
* This method is invoked by the default implementation of
* {@link #onCancelled(Object)}.</p>
*
* <p>Runs on the UI thread after {@link #cancel(boolean)} is invoked and
* {@link #doInBackground(Object[])} has finished.</p>
*
* @see #onCancelled(Object)
* @see #cancel(boolean)
* @see #isCancelled()
*/
protected void onCancelled() {
}
/**
* Returns <tt>true</tt> if this task was cancelled before it completed
* normally. If you are calling {@link #cancel(boolean)} on the task,
* the value returned by this method should be checked periodically from
* {@link #doInBackground(Object[])} to end the task as soon as possible.
*
* @return <tt>true</tt> if task was cancelled before it completed
*
* @see #cancel(boolean)
*/
public final boolean isCancelled() {
return mCancelled.get();
}
/**
* <p>Attempts to cancel execution of this task. This attempt will
* fail if the task has already completed, already been cancelled,
* or could not be cancelled for some other reason. If successful,
* and this task has not started when <tt>cancel</tt> is called,
* this task should never run. If the task has already started,
* then the <tt>mayInterruptIfRunning</tt> parameter determines
* whether the thread executing this task should be interrupted in
* an attempt to stop the task.</p>
*
* <p>Calling this method will result in {@link #onCancelled(Object)} being
* invoked on the UI thread after {@link #doInBackground(Object[])}
* returns. Calling this method guarantees that {@link #onPostExecute(Object)}
* is never invoked. After invoking this method, you should check the
* value returned by {@link #isCancelled()} periodically from
* {@link #doInBackground(Object[])} to finish the task as early as
* possible.</p>
*
* @param mayInterruptIfRunning <tt>true</tt> if the thread executing this
* task should be interrupted; otherwise, in-progress tasks are allowed
* to complete.
*
* @return <tt>false</tt> if the task could not be cancelled,
* typically because it has already completed normally;
* <tt>true</tt> otherwise
*
* @see #isCancelled()
* @see #onCancelled(Object)
*/
public final boolean cancel(boolean mayInterruptIfRunning) {
mCancelled.set(true);
return mFuture.cancel(mayInterruptIfRunning);
}
/**
* Waits if necessary for the computation to complete, and then
* retrieves its result.
*
* @return The computed result.
*
* @throws java.util.concurrent.CancellationException If the computation was cancelled.
* @throws java.util.concurrent.ExecutionException If the computation threw an exception.
* @throws InterruptedException If the current thread was interrupted
* while waiting.
*/
public final Result get() throws InterruptedException, ExecutionException {
return mFuture.get();
}
/**
* Waits if necessary for at most the given time for the computation
* to complete, and then retrieves its result.
*
* @param timeout Time to wait before cancelling the operation.
* @param unit The time unit for the timeout.
*
* @return The computed result.
*
* @throws java.util.concurrent.CancellationException If the computation was cancelled.
* @throws java.util.concurrent.ExecutionException If the computation threw an exception.
* @throws InterruptedException If the current thread was interrupted
* while waiting.
* @throws java.util.concurrent.TimeoutException If the wait timed out.
*/
public final Result get(long timeout, TimeUnit unit) throws InterruptedException,
ExecutionException, TimeoutException {
return mFuture.get(timeout, unit);
}
/**
* Executes the task with the specified parameters. The task returns
* itself (this) so that the caller can keep a reference to it.
*
* <p>Note: this function schedules the task on a queue for a single background
* thread or pool of threads depending on the platform version. When first
* introduced, AsyncTasks were executed serially on a single background thread.
* Starting with {@link android.os.Build.VERSION_CODES#DONUT}, this was changed
* to a pool of threads allowing multiple tasks to operate in parallel. Starting
* {@link android.os.Build.VERSION_CODES#HONEYCOMB}, tasks are back to being
* executed on a single thread to avoid common application errors caused
* by parallel execution. If you truly want parallel execution, you can use
* the {@link #executeOnExecutor} version of this method
* with {@link #THREAD_POOL_EXECUTOR}; however, see commentary there for warnings
* on its use.
*
* <p>This method must be invoked on the UI thread.
*
* @param params The parameters of the task.
*
* @return This instance of AsyncTask.
*
* @throws IllegalStateException If {@link #getStatus()} returns either
* {@link com.artifex.mupdfdemo.AsyncTask.Status#RUNNING} or {@link com.artifex.mupdfdemo.AsyncTask.Status#FINISHED}.
*
* @see #executeOnExecutor(java.util.concurrent.Executor, Object[])
* @see #execute(Runnable)
*/
public final AsyncTask<Params, Progress, Result> execute(Params... params) {
return executeOnExecutor(sDefaultExecutor, params);
}
/**
* Executes the task with the specified parameters. The task returns
* itself (this) so that the caller can keep a reference to it.
*
* <p>This method is typically used with {@link #THREAD_POOL_EXECUTOR} to
* allow multiple tasks to run in parallel on a pool of threads managed by
* AsyncTask, however you can also use your own {@link java.util.concurrent.Executor} for custom
* behavior.
*
* <p><em>Warning:</em> Allowing multiple tasks to run in parallel from
* a thread pool is generally <em>not</em> what one wants, because the order
* of their operation is not defined. For example, if these tasks are used
* to modify any state in common (such as writing a file due to a button click),
* there are no guarantees on the order of the modifications.
* Without careful work it is possible in rare cases for the newer version
* of the data to be over-written by an older one, leading to obscure data
* loss and stability issues. Such changes are best
* executed in serial; to guarantee such work is serialized regardless of
* platform version you can use this function with {@link #SERIAL_EXECUTOR}.
*
* <p>This method must be invoked on the UI thread.
*
* @param exec The executor to use. {@link #THREAD_POOL_EXECUTOR} is available as a
* convenient process-wide thread pool for tasks that are loosely coupled.
* @param params The parameters of the task.
*
* @return This instance of AsyncTask.
*
* @throws IllegalStateException If {@link #getStatus()} returns either
* {@link com.artifex.mupdfdemo.AsyncTask.Status#RUNNING} or {@link com.artifex.mupdfdemo.AsyncTask.Status#FINISHED}.
*
* @see #execute(Object[])
*/
public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,
Params... params) {
if (mStatus != Status.PENDING) {
switch (mStatus) {
case RUNNING:
throw new IllegalStateException("Cannot execute task:"
+ " the task is already running.");
case FINISHED:
throw new IllegalStateException("Cannot execute task:"
+ " the task has already been executed "
+ "(a task can be executed only once)");
}
}
mStatus = Status.RUNNING;
onPreExecute();
mWorker.mParams = params;
exec.execute(mFuture);
return this;
}
/**
* Convenience version of {@link #execute(Object...)} for use with
* a simple Runnable object. See {@link #execute(Object[])} for more
* information on the order of execution.
*
* @see #execute(Object[])
* @see #executeOnExecutor(java.util.concurrent.Executor, Object[])
*/
public static void execute(Runnable runnable) {
sDefaultExecutor.execute(runnable);
}
/**
* This method can be invoked from {@link #doInBackground} to
* publish updates on the UI thread while the background computation is
* still running. Each call to this method will trigger the execution of
* {@link #onProgressUpdate} on the UI thread.
*
* {@link #onProgressUpdate} will note be called if the task has been
* canceled.
*
* @param values The progress values to update the UI with.
*
* @see #onProgressUpdate
* @see #doInBackground
*/
protected final void publishProgress(Progress... values) {
if (!isCancelled()) {
sHandler.obtainMessage(MESSAGE_POST_PROGRESS,
new AsyncTaskResult<Progress>(this, values)).sendToTarget();
}
}
private void finish(Result result) {
if (isCancelled()) {
onCancelled(result);
} else {
onPostExecute(result);
}
mStatus = Status.FINISHED;
}
private static class InternalHandler extends Handler {
@SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})
@Override
public void handleMessage(Message msg) {
AsyncTaskResult result = (AsyncTaskResult) msg.obj;
switch (msg.what) {
case MESSAGE_POST_RESULT:
// There is only one result
result.mTask.finish(result.mData[0]);
break;
case MESSAGE_POST_PROGRESS:
result.mTask.onProgressUpdate(result.mData);
break;
}
}
}
private static abstract class WorkerRunnable<Params, Result> implements Callable<Result> {
Params[] mParams;
}
@SuppressWarnings({"RawUseOfParameterizedType"})
private static class AsyncTaskResult<Data> {
final AsyncTask mTask;
final Data[] mData;
AsyncTaskResult(AsyncTask task, Data... data) {
mTask = task;
mData = data;
}
}
}
================================================
FILE: src/main/java/com/artifex/mupdfdemo/CancellableAsyncTask.java
================================================
package com.artifex.mupdfdemo;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
// Ideally this would be a subclass of AsyncTask, however the cancel() method is final, and cannot
// be overridden. I felt that having two different, but similar cancel methods was a bad idea.
public class CancellableAsyncTask<Params, Result>
{
private final AsyncTask<Params, Void, Result> asyncTask;
private final CancellableTaskDefinition<Params, Result> ourTask;
public void onPreExecute()
{
}
public void onPostExecute(Result result)
{
}
public CancellableAsyncTask(final CancellableTaskDefinition<Params, Result> task)
{
if (task == null)
throw new IllegalArgumentException();
this.ourTask = task;
asyncTask = new AsyncTask<Params, Void, Result>()
{
@Override
protected Result doInBackground(Params... params)
{
return task.doInBackground(params);
}
@Override
protected void onPreExecute()
{
CancellableAsyncTask.this.onPreExecute();
}
@Override
protected void onPostExecute(Result result)
{
CancellableAsyncTask.this.onPostExecute(result);
task.doCleanup();
}
};
}
public void cancelAndWait()
{
this.asyncTask.cancel(true);
ourTask.doCancel();
try
{
this.asyncTask.get();
}
catch (InterruptedException e)
{
}
catch (ExecutionException e)
{
}
catch (CancellationException e)
{
}
ourTask.doCleanup();
}
public void execute(Params ... params)
{
asyncTask.execute(params);
}
}
================================================
FILE: src/main/java/com/artifex/mupdfdemo/CancellableTaskDefinition.java
================================================
package com.artifex.mupdfdemo;
public interface CancellableTaskDefinition <Params, Result>
{
public Result doInBackground(Params... params);
public void doCancel();
public void doCleanup();
}
================================================
FILE: src/main/java/com/artifex/mupdfdemo/ChoosePDFActivity.java
================================================
package com.artifex.mupdfdemo;
import java.io.File;
import java.io.FileFilter;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import android.app.AlertDialog;
import android.app.ListActivity;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.content.res.Resources;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.FileObserver;
import android.os.Handler;
import android.view.View;
import android.widget.ListView;
enum Purpose {
PickPDF,
PickKeyFile
}
public class ChoosePDFActivity extends ListActivity {
static public final String PICK_KEY_FILE = "com.artifex.mupdfdemo.PICK_KEY_FILE";
static private File mDirectory;
static private Map<String, Integer> mPositions = new HashMap<String, Integer>();
private File mParent;
private File [] mDirs;
private File [] mFiles;
private Handler mHandler;
private Runnable mUpdateFiles;
private ChoosePDFAdapter adapter;
private Purpose mPurpose;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mPurpose = PICK_KEY_FILE.equals(getIntent().getAction()) ? Purpose.PickKeyFile : Purpose.PickPDF;
String storageState = Environment.getExternalStorageState();
if (!Environment.MEDIA_MOUNTED.equals(storageState)
&& !Environment.MEDIA_MOUNTED_READ_ONLY.equals(storageState))
{
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(R.string.no_media_warning);
builder.setMessage(R.string.no_media_hint);
AlertDialog alert = builder.create();
alert.setButton(AlertDialog.BUTTON_POSITIVE,getString(R.string.dismiss),
new OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
finish();
}
});
alert.show();
return;
}
if (mDirectory == null)
mDirectory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
// Create a list adapter...
adapter = new ChoosePDFAdapter(getLayoutInflater());
setListAdapter(adapter);
// ...that is updated dynamically when files are scanned
mHandler = new Handler();
mUpdateFiles = new Runnable() {
public void run() {
Resources res = getResources();
String appName = res.getString(R.string.mupdf_title);
String version = res.getString(R.string.version);
String title = res.getString(R.string.picker_title_App_Ver_Dir);
setTitle(String.format(title, appName, version, mDirectory));
mParent = mDirectory.getParentFile();
mDirs = mDirectory.listFiles(new FileFilter() {
public boolean accept(File file) {
return file.isDirectory();
}
});
if (mDirs == null)
mDirs = new File[0];
mFiles = mDirectory.listFiles(new FileFilter() {
public boolean accept(File file) {
if (file.isDirectory())
return false;
String fname = file.getName().toLowerCase();
switch (mPurpose) {
case PickPDF:
if (fname.endsWith(".pdf"))
return true;
if (fname.endsWith(".xps"))
return true;
if (fname.endsWith(".cbz"))
return true;
if (fname.endsWith(".png"))
return true;
if (fname.endsWith(".jpe"))
return true;
if (fname.endsWith(".jpeg"))
return true;
if (fname.endsWith(".jpg"))
return true;
if (fname.endsWith(".jfif"))
return true;
if (fname.endsWith(".jfif-tbnl"))
return true;
if (fname.endsWith(".tif"))
return true;
if (fname.endsWith(".tiff"))
return true;
return false;
case PickKeyFile:
if (fname.endsWith(".pfx"))
return true;
return false;
default:
return false;
}
}
});
if (mFiles == null)
mFiles = new File[0];
Arrays.sort(mFiles, new Comparator<File>() {
public int compare(File arg0, File arg1) {
return arg0.getName().compareToIgnoreCase(arg1.getName());
}
});
Arrays.sort(mDirs, new Comparator<File>() {
public int compare(File arg0, File arg1) {
return arg0.getName().compareToIgnoreCase(arg1.getName());
}
});
adapter.clear();
if (mParent != null)
adapter.add(new ChoosePDFItem(ChoosePDFItem.Type.PARENT, getString(R.string.parent_directory)));
for (File f : mDirs)
adapter.add(new ChoosePDFItem(ChoosePDFItem.Type.DIR, f.getName()));
for (File f : mFiles)
adapter.add(new ChoosePDFItem(ChoosePDFItem.Type.DOC, f.getName()));
lastPosition();
}
};
// Start initial file scan...
mHandler.post(mUpdateFiles);
// ...and observe the directory and scan files upon changes.
FileObserver observer = new FileObserver(mDirectory.getPath(), FileObserver.CREATE | FileObserver.DELETE) {
public void onEvent(int event, String path) {
mHandler.post(mUpdateFiles);
}
};
observer.startWatching();
}
private void lastPosition() {
String p = mDirectory.getAbsolutePath();
if (mPositions.containsKey(p))
getListView().setSelection(mPositions.get(p));
}
@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
mPositions.put(mDirectory.getAbsolutePath(), getListView().getFirstVisiblePosition());
if (position < (mParent == null ? 0 : 1)) {
mDirectory = mParent;
mHandler.post(mUpdateFiles);
return;
}
position -= (mParent == null ? 0 : 1);
if (position < mDirs.length) {
mDirectory = mDirs[position];
mHandler.post(mUpdateFiles);
return;
}
position -= mDirs.length;
Uri uri = Uri.parse(mFiles[position].getAbsolutePath());
Intent intent = new Intent(this,MuPDFActivity.class);
intent.setAction(Intent.ACTION_VIEW);
intent.setData(uri);
switch (mPurpose) {
case PickPDF:
// Start an activity to display the PDF file
startActivity(intent);
break;
case PickKeyFile:
// Return the uri to the caller
setResult(RESULT_OK, intent);
finish();
break;
}
}
@Override
protected void onPause() {
super.onPause();
if (mDirectory != null)
mPositions.put(mDirectory.getAbsolutePath(), getListView().getFirstVisiblePosition());
}
}
================================================
FILE: src/main/java/com/artifex/mupdfdemo/ChoosePDFAdapter.java
================================================
package com.artifex.mupdfdemo;
import java.util.LinkedList;
import android.graphics.Color;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
public class ChoosePDFAdapter extends BaseAdapter {
private final LinkedList<ChoosePDFItem> mItems;
private final LayoutInflater mInflater;
public ChoosePDFAdapter(LayoutInflater inflater) {
mInflater = inflater;
mItems = new LinkedList<ChoosePDFItem>();
}
public void clear() {
mItems.clear();
}
public void add(ChoosePDFItem item) {
mItems.add(item);
notifyDataSetChanged();
}
public int getCount() {
return mItems.size();
}
public Object getItem(int i) {
return null;
}
public long getItemId(int arg0) {
return 0;
}
private int iconForType(ChoosePDFItem.Type type) {
switch (type) {
case PARENT: return R.drawable.ic_arrow_up;
case DIR: return R.drawable.ic_dir;
case DOC: return R.drawable.ic_doc;
default: return 0;
}
}
public View getView(int position, View convertView, ViewGroup parent) {
View v;
if (convertView == null) {
v = mInflater.inflate(R.layout.picker_entry, null);
} else {
v = convertView;
}
ChoosePDFItem item = mItems.get(position);
((TextView)v.findViewById(R.id.name)).setText(item.name);
((ImageView)v.findViewById(R.id.icon)).setImageResource(iconForType(item.type));
((ImageView)v.findViewById(R.id.icon)).setColorFilter(Color.argb(255, 0, 0, 0));
return v;
}
}
================================================
FILE: src/main/java/com/artifex/mupdfdemo/ChoosePDFItem.java
================================================
package com.artifex.mupdfdemo;
public class ChoosePDFItem {
enum Type {
PARENT, DIR, DOC
}
final public Type type;
final public String name;
public ChoosePDFItem (Type t, String n) {
type = t;
name = n;
}
}
================================================
FILE: src/main/java/com/artifex/mupdfdemo/Deque.java
================================================
/*
* Written by Doug Lea and Josh Bloch with assistance from members of
* JCP JSR-166 Expert Group and released to the public domain, as explained
* at http://creativecommons.org/publicdomain/zero/1.0/
*/
package com.artifex.mupdfdemo;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Queue;
import java.util.Stack;
// BEGIN android-note
// removed link to collections framework docs
// END android-note
/**
* A linear collection that supports element insertion and removal at
* both ends. The name <i>deque</i> is short for "double ended queue"
* and is usually pronounced "deck". Most <tt>Deque</tt>
* implementations place no fixed limits on the number of elements
* they may contain, but this interface supports capacity-restricted
* deques as well as those with no fixed size limit.
*
* <p>This interface defines methods to access the elements at both
* ends of the deque. Methods are provided to insert, remove, and
* examine the element. Each of these methods exists in two forms:
* one throws an exception if the operation fails, the other returns a
* special value (either <tt>null</tt> or <tt>false</tt>, depending on
* the operation). The latter form of the insert operation is
* designed specifically for use with capacity-restricted
* <tt>Deque</tt> implementations; in most implementations, insert
* operations cannot fail.
*
* <p>The twelve methods described above are summarized in the
* following table:
*
* <p>
* <table BORDER CELLPADDING=3 CELLSPACING=1>
* <tr>
* <td></td>
* <td ALIGN=CENTER COLSPAN = 2> <b>First Element (Head)</b></td>
* <td ALIGN=CENTER COLSPAN = 2> <b>Last Element (Tail)</b></td>
* </tr>
* <tr>
* <td></td>
* <td ALIGN=CENTER><em>Throws exception</em></td>
* <td ALIGN=CENTER><em>Special value</em></td>
* <td ALIGN=CENTER><em>Throws exception</em></td>
* <td ALIGN=CENTER><em>Special value</em></td>
* </tr>
* <tr>
* <td><b>Insert</b></td>
* <td>{@link #addFirst addFirst(e)}</td>
* <td>{@link #offerFirst offerFirst(e)}</td>
* <td>{@link #addLast addLast(e)}</td>
* <td>{@link #offerLast offerLast(e)}</td>
* </tr>
* <tr>
* <td><b>Remove</b></td>
* <td>{@link #removeFirst removeFirst()}</td>
* <td>{@link #pollFirst pollFirst()}</td>
* <td>{@link #removeLast removeLast()}</td>
* <td>{@link #pollLast pollLast()}</td>
* </tr>
* <tr>
* <td><b>Examine</b></td>
* <td>{@link #getFirst getFirst()}</td>
* <td>{@link #peekFirst peekFirst()}</td>
* <td>{@link #getLast getLast()}</td>
* <td>{@link #peekLast peekLast()}</td>
* </tr>
* </table>
*
* <p>This interface extends the {@link java.util.Queue} interface. When a deque is
* used as a queue, FIFO (First-In-First-Out) behavior results. Elements are
* added at the end of the deque and removed from the beginning. The methods
* inherited from the <tt>Queue</tt> interface are precisely equivalent to
* <tt>Deque</tt> methods as indicated in the following table:
*
* <p>
* <table BORDER CELLPADDING=3 CELLSPACING=1>
* <tr>
* <td ALIGN=CENTER> <b><tt>Queue</tt> Method</b></td>
* <td ALIGN=CENTER> <b>Equivalent <tt>Deque</tt> Method</b></td>
* </tr>
* <tr>
* <td>{@link java.util.Queue#add add(e)}</td>
* <td>{@link #addLast addLast(e)}</td>
* </tr>
* <tr>
* <td>{@link java.util.Queue#offer offer(e)}</td>
* <td>{@link #offerLast offerLast(e)}</td>
* </tr>
* <tr>
* <td>{@link java.util.Queue#remove remove()}</td>
* <td>{@link #removeFirst removeFirst()}</td>
* </tr>
* <tr>
* <td>{@link java.util.Queue#poll poll()}</td>
* <td>{@link #pollFirst pollFirst()}</td>
* </tr>
* <tr>
* <td>{@link java.util.Queue#element element()}</td>
* <td>{@link #getFirst getFirst()}</td>
* </tr>
* <tr>
* <td>{@link java.util.Queue#peek peek()}</td>
* <td>{@link #peek peekFirst()}</td>
* </tr>
* </table>
*
* <p>Deques can also be used as LIFO (Last-In-First-Out) stacks. This
* interface should be used in preference to the legacy {@link java.util.Stack} class.
* When a deque is used as a stack, elements are pushed and popped from the
* beginning of the deque. Stack methods are precisely equivalent to
* <tt>Deque</tt> methods as indicated in the table below:
*
* <p>
* <table BORDER CELLPADDING=3 CELLSPACING=1>
* <tr>
* <td ALIGN=CENTER> <b>Stack Method</b></td>
* <td ALIGN=CENTER> <b>Equivalent <tt>Deque</tt> Method</b></td>
* </tr>
* <tr>
* <td>{@link #push push(e)}</td>
* <td>{@link #addFirst addFirst(e)}</td>
* </tr>
* <tr>
* <td>{@link #pop pop()}</td>
* <td>{@link #removeFirst removeFirst()}</td>
* </tr>
* <tr>
* <td>{@link #peek peek()}</td>
* <td>{@link #peekFirst peekFirst()}</td>
* </tr>
* </table>
*
* <p>Note that the {@link #peek peek} method works equally well when
* a deque is used as a queue or a stack; in either case, elements are
* drawn from the beginning of the deque.
*
* <p>This interface provides two methods to remove interior
* elements, {@link #removeFirstOccurrence removeFirstOccurrence} and
* {@link #removeLastOccurrence removeLastOccurrence}.
*
* <p>Unlike the {@link java.util.List} interface, this interface does not
* provide support for indexed access to elements.
*
* <p>While <tt>Deque</tt> implementations are not strictly required
* to prohibit the insertion of null elements, they are strongly
* encouraged to do so. Users of any <tt>Deque</tt> implementations
* that do allow null elements are strongly encouraged <i>not</i> to
* take advantage of the ability to insert nulls. This is so because
* <tt>null</tt> is used as a special return value by various methods
* to indicated that the deque is empty.
*
* <p><tt>Deque</tt> implementations generally do not define
* element-based versions of the <tt>equals</tt> and <tt>hashCode</tt>
* methods, but instead inherit the identity-based versions from class
* <tt>Object</tt>.
*
* @author Doug Lea
* @author Josh Bloch
* @since 1.6
* @param <E> the type of elements held in this collection
*/
public interface Deque<E> extends Queue<E> {
/**
* Inserts the specified element at the front of this deque if it is
* possible to do so immediately without violating capacity restrictions.
* When using a capacity-restricted deque, it is generally preferable to
* use method {@link #offerFirst}.
*
* @param e the element to add
* @throws IllegalStateException if the element cannot be added at this
* time due to capacity restrictions
* @throws ClassCastException if the class of the specified element
* prevents it from being added to this deque
* @throws NullPointerException if the specified element is null and this
* deque does not permit null elements
* @throws IllegalArgumentException if some property of the specified
* element prevents it from being added to this deque
*/
void addFirst(E e);
/**
* Inserts the specified element at the end of this deque if it is
* possible to do so immediately without violating capacity restrictions.
* When using a capacity-restricted deque, it is generally preferable to
* use method {@link #offerLast}.
*
* <p>This method is equivalent to {@link #add}.
*
* @param e the element to add
* @throws IllegalStateException if the element cannot be added at this
* time due to capacity restrictions
* @throws ClassCastException if the class of the specified element
* prevents it from being added to this deque
* @throws NullPointerException if the specified element is null and this
* deque does not permit null elements
* @throws IllegalArgumentException if some property of the specified
* element prevents it from being added to this deque
*/
void addLast(E e);
/**
* Inserts the specified element at the front of this deque unless it would
* violate capacity restrictions. When using a capacity-restricted deque,
* this method is generally preferable to the {@link #addFirst} method,
* which can fail to insert an element only by throwing an exception.
*
* @param e the element to add
* @return <tt>true</tt> if the element was added to this deque, else
* <tt>false</tt>
* @throws ClassCastException if the class of the specified element
* prevents it from being added to this deque
* @throws NullPointerException if the specified element is null and this
* deque does not permit null elements
* @throws IllegalArgumentException if some property of the specified
* element prevents it from being added to this deque
*/
boolean offerFirst(E e);
/**
* Inserts the specified element at the end of this deque unless it would
* violate capacity restrictions. When using a capacity-restricted deque,
* this method is generally preferable to the {@link #addLast} method,
* which can fail to insert an element only by throwing an exception.
*
* @param e the element to add
* @return <tt>true</tt> if the element was added to this deque, else
* <tt>false</tt>
* @throws ClassCastException if the class of the specified element
* prevents it from being added to this deque
* @throws NullPointerException if the specified element is null and this
* deque does not permit null elements
* @throws IllegalArgumentException if some property of the specified
* element prevents it from being added to this deque
*/
boolean offerLast(E e);
/**
* Retrieves and removes the first element of this deque. This method
* differs from {@link #pollFirst pollFirst} only in that it throws an
* exception if this deque is empty.
*
* @return the head of this deque
* @throws java.util.NoSuchElementException if this deque is empty
*/
E removeFirst();
/**
* Retrieves and removes the last element of this deque. This method
* differs from {@link #pollLast pollLast} only in that it throws an
* exception if this deque is empty.
*
* @return the tail of this deque
* @throws java.util.NoSuchElementException if this deque is empty
*/
E removeLast();
/**
* Retrieves and removes the first element of this deque,
* or returns <tt>null</tt> if this deque is empty.
*
* @return the head of this deque, or <tt>null</tt> if this deque is empty
*/
E pollFirst();
/**
* Retrieves and removes the last element of this deque,
* or returns <tt>null</tt> if this deque is empty.
*
* @return the tail of this deque, or <tt>null</tt> if this deque is empty
*/
E pollLast();
/**
* Retrieves, but does not remove, the first element of this deque.
*
* This method differs from {@link #peekFirst peekFirst} only in that it
* throws an exception if this deque is empty.
*
* @return the head of this deque
* @throws java.util.NoSuchElementException if this deque is empty
*/
E getFirst();
/**
* Retrieves, but does not remove, the last element of this deque.
* This method differs from {@link #peekLast peekLast} only in that it
* throws an exception if this deque is empty.
*
* @return the tail of this deque
* @throws java.util.NoSuchElementException if this deque is empty
*/
E getLast();
/**
* Retrieves, but does not remove, the first element of this deque,
* or returns <tt>null</tt> if this deque is empty.
*
* @return the head of this deque, or <tt>null</tt> if this deque is empty
*/
E peekFirst();
/**
* Retrieves, but does not remove, the last element of this deque,
* or returns <tt>null</tt> if this deque is empty.
*
* @return the tail of this deque, or <tt>null</tt> if this deque is empty
*/
E peekLast();
/**
* Removes the first occurrence of the specified element from this deque.
* If the deque does not contain the element, it is unchanged.
* More formally, removes the first element <tt>e</tt> such that
* <tt>(o==null ? e==null : o.equals(e))</tt>
* (if such an element exists).
* Returns <tt>true</tt> if this deque contained the specified element
* (or equivalently, if this deque changed as a result of the call).
*
* @param o element to be removed from this deque, if present
* @return <tt>true</tt> if an element was removed as a result of this call
* @throws ClassCastException if the class of the specified element
* is incompatible with this deque (optional)
* @throws NullPointerException if the specified element is null and this
* deque does not permit null elements (optional)
*/
boolean removeFirstOccurrence(Object o);
/**
* Removes the last occurrence of the specified element from this deque.
* If the deque does not contain the element, it is unchanged.
* More formally, removes the last element <tt>e</tt> such that
* <tt>(o==null ? e==null : o.equals(e))</tt>
* (if such an element exists).
* Returns <tt>true</tt> if this deque contained the specified element
* (or equivalently, if this deque changed as a result of the call).
*
* @param o element to be removed from this deque, if present
* @return <tt>true</tt> if an element was removed as a result of this call
* @throws ClassCastException if the class of the specified element
* is incompatible with this deque (optional)
* @throws NullPointerException if the specified element is null and this
* deque does not permit null elements (optional)
*/
boolean removeLastOccurrence(Object o);
// *** Queue methods ***
/**
* Inserts the specified element into the queue represented by this deque
* (in other words, at the tail of this deque) if it is possible to do so
* immediately without violating capacity restrictions, returning
* <tt>true</tt> upon success and throwing an
* <tt>IllegalStateException</tt> if no space is currently available.
* When using a capacity-restricted deque, it is generally preferable to
* use {@link #offer(Object) offer}.
*
* <p>This method is equivalent to {@link #addLast}.
*
* @param e the element to add
* @return <tt>true</tt> (as specified by {@link java.util.Collection#add})
* @throws IllegalStateException if the element cannot be added at this
* time due to capacity restrictions
* @throws ClassCastException if the class of the specified element
* prevents it from being added to this deque
* @throws NullPointerException if the specified element is null and this
* deque does not permit null elements
* @throws IllegalArgumentException if some property of the specified
* element prevents it from being added to this deque
*/
boolean add(E e);
/**
* Inserts the specified element into the queue represented by this deque
* (in other words, at the tail of this deque) if it is possible to do so
* immediately without violating capacity restrictions, returning
* <tt>true</tt> upon success and <tt>false</tt> if no space is currently
* available. When using a capacity-restricted deque, this method is
* generally preferable to the {@link #add} method, which can fail to
* insert an element only by throwing an exception.
*
* <p>This method is equivalent to {@link #offerLast}.
*
* @param e the element to add
* @return <tt>true</tt> if the element was added to this deque, else
* <tt>false</tt>
* @throws ClassCastException if the class of the specified element
* prevents it from being added to this deque
* @throws NullPointerException if the specified element is null and this
* deque does not permit null elements
* @throws IllegalArgumentException if some property of the specified
* element prevents it from being added to this deque
*/
boolean offer(E e);
/**
* Retrieves and removes the head of the queue represented by this deque
* (in other words, the first element of this deque).
* This method differs from {@link #poll poll} only in that it throws an
* exception if this deque is empty.
*
* <p>This method is equivalent to {@link #removeFirst()}.
*
* @return the head of the queue represented by this deque
* @throws java.util.NoSuchElementException if this deque is empty
*/
E remove();
/**
* Retrieves and removes the head of the queue represented by this deque
* (in other words, the first element of this deque), or returns
* <tt>null</tt> if this deque is empty.
*
* <p>This method is equivalent to {@link #pollFirst()}.
*
* @return the first element of this deque, or <tt>null</tt> if
* this deque is empty
*/
E poll();
/**
* Retrieves, but does not remove, the head of the queue represented by
* this deque (in other words, the first element of this deque).
* This method differs from {@link #peek peek} only in that it throws an
* exception if this deque is empty.
*
* <p>This method is equivalent to {@link #getFirst()}.
*
* @return the head of the queue represented by this deque
* @throws java.util.NoSuchElementException if this deque is empty
*/
E element();
/**
* Retrieves, but does not remove, the head of the queue represented by
* this deque (in other words, the first element of this deque), or
* returns <tt>null</tt> if this deque is empty.
*
* <p>This method is equivalent to {@link #peekFirst()}.
*
* @return the head of the queue represented by this deque, or
* <tt>null</tt> if this deque is empty
*/
E peek();
// *** Stack methods ***
/**
* Pushes an element onto the stack represented by this deque (in other
* words, at the head of this deque) if it is possible to do so
* immediately without violating capacity restrictions, returning
* <tt>true</tt> upon success and throwing an
* <tt>IllegalStateException</tt> if no space is currently available.
*
* <p>This method is equivalent to {@link #addFirst}.
*
* @param e the element to push
* @throws IllegalStateException if the element cannot be added at this
* time due to capacity restrictions
* @throws ClassCastException if the class of the specified element
* prevents it from being added to this deque
* @throws NullPointerException if the specified element is null and this
* deque does not permit null elements
* @throws IllegalArgumentException if some property of the specified
* element prevents it from being added to this deque
*/
void push(E e);
/**
* Pops an element from the stack represented by this deque. In other
* words, removes and returns the first element of this deque.
*
* <p>This method is equivalent to {@link #removeFirst()}.
*
* @return the element at the front of this deque (which is the top
* of the stack represented by this deque)
* @throws java.util.NoSuchElementException if this deque is empty
*/
E pop();
// *** Collection methods ***
/**
* Removes the first occurrence of the specified element from this deque.
* If the deque does not contain the element, it is unchanged.
* More formally, removes the first element <tt>e</tt> such that
* <tt>(o==null ? e==null : o.equals(e))</tt>
* (if such an element exists).
* Returns <tt>true</tt> if this deque contained the specified element
* (or equivalently, if this deque changed as a result of the call).
*
* <p>This method is equivalent to {@link #removeFirstOccurrence}.
*
* @param o element to be removed from this deque, if present
* @return <tt>true</tt> if an element was removed as a result of this call
* @throws ClassCastException if the class of the specified element
* is incompatible with this deque (optional)
* @throws NullPointerException if the specified element is null and this
* deque does not permit null elements (optional)
*/
boolean remove(Object o);
/**
* Returns <tt>true</tt> if this deque contains the specified element.
* More formally, returns <tt>true</tt> if and only if this deque contains
* at least one element <tt>e</tt> such that
* <tt>(o==null ? e==null : o.equals(e))</tt>.
*
* @param o element whose presence in this deque is to be tested
* @return <tt>true</tt> if this deque contains the specified element
* @throws ClassCastException if the type of the specified element
* is incompatible with this deque (optional)
* @throws NullPointerException if the specified element is null and this
* deque does not permit null elements (optional)
*/
boolean contains(Object o);
/**
* Returns the number of elements in this deque.
*
* @return the number of elements in this deque
*/
public int size();
/**
* Returns an iterator over the elements in this deque in proper sequence.
* The elements will be returned in order from first (head) to last (tail).
*
* @return an iterator over the elements in this deque in proper sequence
*/
Iterator<E> iterator();
/**
* Returns an iterator over the elements in this deque in reverse
* sequential order. The elements will be returned in order from
* last (tail) to first (head).
*
* @return an iterator over the elements in this deque in reverse
* sequence
*/
Iterator<E> descendingIterator();
}
================================================
FILE: src/main/java/com/artifex/mupdfdemo/FilePicker.java
================================================
package com.artifex.mupdfdemo;
import android.net.Uri;
public abstract class FilePicker {
public interface FilePickerSupport {
void performPickFor(FilePicker picker);
}
private final FilePickerSupport support;
FilePicker(FilePickerSupport _support) {
support = _support;
}
void pick() {
support.performPickFor(this);
}
abstract void onPick(Uri uri);
}
================================================
FILE: src/main/java/com/artifex/mupdfdemo/LinkInfo.java
================================================
package com.artifex.mupdfdemo;
import android.graphics.RectF;
public class LinkInfo {
final public RectF rect;
public LinkInfo(float l, float t, float r, float b) {
rect = new RectF(l, t, r, b);
}
public void acceptVisitor(LinkInfoVisitor visitor) {
}
}
================================================
FILE: src/main/java/com/artifex/mupdfdemo/LinkInfoExternal.java
================================================
package com.artifex.mupdfdemo;
public class LinkInfoExternal extends LinkInfo {
final public String url;
public LinkInfoExternal(float l, float t, float r, float b, String u) {
super(l, t, r, b);
url = u;
}
public void acceptVisitor(LinkInfoVisitor visitor) {
visitor.visitExternal(this);
}
}
================================================
FILE: src/main/java/com/artifex/mupdfdemo/LinkInfoInternal.java
================================================
package com.artifex.mupdfdemo;
public class LinkInfoInternal extends LinkInfo {
final public int pageNumber;
public LinkInfoInternal(float l, float t, float r, float b, int p) {
super(l, t, r, b);
pageNumber = p;
}
public void acceptVisitor(LinkInfoVisitor visitor) {
visitor.visitInternal(this);
}
}
================================================
FILE: src/main/java/com/artifex/mupdfdemo/LinkInfoRemote.java
================================================
package com.artifex.mupdfdemo;
public class LinkInfoRemote extends LinkInfo {
final public String fileSpec;
final public int pageNumber;
final public boolean newWindow;
public LinkInfoRemote(float l, float t, float r, float b, String f, int p, boolean n) {
super(l, t, r, b);
fileSpec = f;
pageNumber = p;
newWindow = n;
}
public void acceptVisitor(LinkInfoVisitor visitor) {
visitor.visitRemote(this);
}
}
================================================
FILE: src/main/java/com/artifex/mupdfdemo/LinkInfoVisitor.java
================================================
package com.artifex.mupdfdemo;
abstract public class LinkInfoVisitor {
public abstract void visitInternal(LinkInfoInternal li);
public abstract void visitExternal(LinkInfoExternal li);
public abstract void visitRemote(LinkInfoRemote li);
}
================================================
FILE: src/main/java/com/artifex/mupdfdemo/MuPDFActivity.java
================================================
package com.artifex.mupdfdemo;
import java.io.InputStream;
import java.util.concurrent.Executor;
import com.artifex.mupdfdemo.ReaderView.ViewMapper;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnCancelListener;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.database.Cursor;
import android.graphics.Color;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.text.Editable;
import android.text.TextWatcher;
import android.text.method.PasswordTransformationMethod;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.TranslateAnimation;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.RelativeLayout;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.ViewAnimator;
class ThreadPerTaskExecutor implements Executor {
public void execute(Runnable r) {
new Thread(r).start();
}
}
public class MuPDFActivity extends Activity implements FilePicker.FilePickerSupport
{
/* The core rendering instance */
enum TopBarMode {Main, Search, Annot, Delete, More, Accept};
enum AcceptMode {Highlight, Underline, StrikeOut, Ink, CopyText};
private final int OUTLINE_REQUEST=0;
private final int PRINT_REQUEST=1;
private final int FILEPICK_REQUEST=2;
private MuPDFCore core;
private String mFileName;
private MuPDFReaderView mDocView;
private View mButtonsView;
private boolean mButtonsVisible;
private EditText mPasswordView;
private TextView mFilenameView;
private SeekBar mPageSlider;
private int mPageSliderRes;
private TextView mPageNumberView;
private TextView mInfoView;
private ImageButton mSearchButton;
private ImageButton mReflowButton;
private ImageButton mOutlineButton;
private ImageButton mMoreButton;
private TextView mAnnotTypeText;
private ImageButton mAnnotButton;
private ViewAnimator mTopBarSwitcher;
private ImageButton mLinkButton;
private TopBarMode mTopBarMode = TopBarMode.Main;
private AcceptMode mAcceptMode;
private ImageButton mSearchBack;
private ImageButton mSearchFwd;
private EditText mSearchText;
private SearchTask mSearchTask;
private AlertDialog.Builder mAlertBuilder;
private boolean mLinkHighlight = false;
private final Handler mHandler = new Handler();
private boolean mAlertsActive= false;
private boolean mReflow = false;
private AsyncTask<Void,Void,MuPDFAlert> mAlertTask;
private AlertDialog mAlertDialog;
private FilePicker mFilePicker;
public void createAlertWaiter() {
mAlertsActive = true;
// All mupdf library calls are performed on asynchronous tasks to avoid stalling
// the UI. Some calls can lead to javascript-invoked requests to display an
// alert dialog and collect a reply from the user. The task has to be blocked
// until the user's reply is received. This method creates an asynchronous task,
// the purpose of which is to wait of these requests and produce the dialog
// in response, while leaving the core blocked. When the dialog receives the
// user's response, it is sent to the core via replyToAlert, unblocking it.
// Another alert-waiting task is then created to pick up the next alert.
if (mAlertTask != null) {
mAlertTask.cancel(true);
mAlertTask = null;
}
if (mAlertDialog != null) {
mAlertDialog.cancel();
mAlertDialog = null;
}
mAlertTask = new AsyncTask<Void,Void,MuPDFAlert>() {
@Override
protected MuPDFAlert doInBackground(Void... arg0) {
if (!mAlertsActive)
return null;
return core.waitForAlert();
}
@Override
protected void onPostExecute(final MuPDFAlert result) {
// core.waitForAlert may return null when shutting down
if (result == null)
return;
final MuPDFAlert.ButtonPressed pressed[] = new MuPDFAlert.ButtonPressed[3];
for(int i = 0; i < 3; i++)
pressed[i] = MuPDFAlert.ButtonPressed.None;
DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
mAlertDialog = null;
if (mAlertsActive) {
int index = 0;
switch (which) {
case AlertDialog.BUTTON1: index=0; break;
case AlertDialog.BUTTON2: index=1; break;
case AlertDialog.BUTTON3: index=2; break;
}
result.buttonPressed = pressed[index];
// Send the user's response to the core, so that it can
// continue processing.
core.replyToAlert(result);
// Create another alert-waiter to pick up the next alert.
createAlertWaiter();
}
}
};
mAlertDialog = mAlertBuilder.create();
mAlertDialog.setTitle(result.title);
mAlertDialog.setMessage(result.message);
switch (result.iconType)
{
case Error:
break;
case Warning:
break;
case Question:
break;
case Status:
break;
}
switch (result.buttonGroupType)
{
case OkCancel:
mAlertDialog.setButton(AlertDialog.BUTTON2, getString(R.string.cancel), listener);
pressed[1] = MuPDFAlert.ButtonPressed.Cancel;
case Ok:
mAlertDialog.setButton(AlertDialog.BUTTON1, getString(R.string.okay), listener);
pressed[0] = MuPDFAlert.ButtonPressed.Ok;
break;
case YesNoCancel:
mAlertDialog.setButton(AlertDialog.BUTTON3, getString(R.string.cancel), listener);
pressed[2] = MuPDFAlert.ButtonPressed.Cancel;
case YesNo:
mAlertDialog.setButton(AlertDialog.BUTTON1, getString(R.string.yes), listener);
pressed[0] = MuPDFAlert.ButtonPressed.Yes;
mAlertDialog.setButton(AlertDialog.BUTTON2, getString(R.string.no), listener);
pressed[1] = MuPDFAlert.ButtonPressed.No;
break;
}
mAlertDialog.setOnCancelListener(new OnCancelListener() {
public void onCancel(DialogInterface dialog) {
mAlertDialog = null;
if (mAlertsActive) {
result.buttonPressed = MuPDFAlert.ButtonPressed.None;
core.replyToAlert(result);
createAlertWaiter();
}
}
});
mAlertDialog.show();
}
};
mAlertTask.executeOnExecutor(new ThreadPerTaskExecutor());
}
public void destroyAlertWaiter() {
mAlertsActive = false;
if (mAlertDialog != null) {
mAlertDialog.cancel();
mAlertDialog = null;
}
if (mAlertTask != null) {
mAlertTask.cancel(true);
mAlertTask = null;
}
}
private MuPDFCore openFile(String path)
{
int lastSlashPos = path.lastIndexOf('/');
mFileName = new String(lastSlashPos == -1
? path
: path.substring(lastSlashPos+1));
System.out.println("Trying to open "+path);
try
{
core = new MuPDFCore(this, path);
// New file: drop the old outline data
OutlineActivityData.set(null);
}
catch (Exception e)
{
System.out.println(e);
return null;
}
return core;
}
private MuPDFCore openBuffer(byte buffer[], String magic)
{
System.out.println("Trying to open byte buffer");
try
{
core = new MuPDFCore(this, buffer, magic);
// New file: drop the old outline data
OutlineActivityData.set(null);
}
catch (Exception e)
{
System.out.println(e);
return null;
}
return core;
}
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
mAlertBuilder = new AlertDialog.Builder(this);
if (core == null) {
core = (MuPDFCore)getLastNonConfigurationInstance();
if (savedInstanceState != null && savedInstanceState.containsKey("FileName")) {
mFileName = savedInstanceState.getString("FileName");
}
}
if (core == null) {
Intent intent = getIntent();
byte buffer[] = null;
if (Intent.ACTION_VIEW.equals(intent.getAction())) {
Uri uri = intent.getData();
System.out.println("URI to open is: " + uri);
if (uri.toString().startsWith("content://")) {
String reason = null;
try {
InputStream is = getContentResolver().openInputStream(uri);
int len = is.available();
buffer = new byte[len];
is.read(buffer, 0, len);
is.close();
}
catch (OutOfMemoryError e) {
System.out.println("Out of memory during buffer reading");
reason = e.toString();
}
catch (Exception e) {
System.out.println("Exception reading from stream: " + e);
// Handle view requests from the Transformer Prime's file manager
// Hopefully other file managers will use this same scheme, if not
// using explicit paths.
// I'm hoping that this case below is no longer needed...but it's
// hard to test as the file manager seems to have changed in 4.x.
try {
Cursor cursor = getContentResolver().query(uri, new String[]{"_data"}, null, null, null);
if (cursor.moveToFirst()) {
String str = cursor.getString(0);
if (str == null) {
reason = "Couldn't parse data in intent";
}
else {
uri = Uri.parse(str);
}
}
}
catch (Exception e2) {
System.out.println("Exception in Transformer Prime file manager code: " + e2);
reason = e2.toString();
}
}
if (reason != null) {
buffer = null;
Resources res = getResources();
AlertDialog alert = mAlertBuilder.create();
setTitle(String.format(res.getString(R.string.cannot_open_document_Reason), reason));
alert.setButton(AlertDialog.BUTTON_POSITIVE, getString(R.string.dismiss),
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
finish();
}
});
alert.show();
return;
}
}
if (buffer != null) {
core = openBuffer(buffer, intent.getType());
} else {
core = openFile(Uri.decode(uri.getEncodedPath()));
}
SearchTaskResult.set(null);
}
if (core != null && core.needsPassword()) {
requestPassword(savedInstanceState);
return;
}
if (core != null && core.countPages() == 0)
{
core = null;
}
}
if (core == null)
{
AlertDialog alert = mAlertBuilder.create();
alert.setTitle(R.string.cannot_open_document);
alert.setButton(AlertDialog.BUTTON_POSITIVE, getString(R.string.dismiss),
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
finish();
}
});
alert.setOnCancelListener(new OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
finish();
}
});
alert.show();
return;
}
createUI(savedInstanceState);
}
public void requestPassword(final Bundle savedInstanceState) {
mPasswordView = new EditText(this);
mPasswordView.setInputType(EditorInfo.TYPE_TEXT_VARIATION_PASSWORD);
mPasswordView.setTransformationMethod(new PasswordTransformationMethod());
AlertDialog alert = mAlertBuilder.create();
alert.setTitle(R.string.enter_password);
alert.setView(mPasswordView);
alert.setButton(AlertDialog.BUTTON_POSITIVE, getString(R.string.okay),
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
if (core.authenticatePassword(mPasswordView.getText().toString())) {
createUI(savedInstanceState);
} else {
requestPassword(savedInstanceState);
}
}
});
alert.setButton(AlertDialog.BUTTON_NEGATIVE, getString(R.string.cancel),
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
finish();
}
});
alert.show();
}
public void createUI(Bundle savedInstanceState) {
if (core == null)
return;
// Now create the UI.
// First create the document view
mDocView = new MuPDFReaderView(this) {
@Override
protected void onMoveToChild(int i) {
if (core == null)
return;
mPageNumberView.setText(String.format("%d / %d", i + 1,
core.countPages()));
mPageSlider.setMax((core.countPages() - 1) * mPageSliderRes);
mPageSlider.setProgress(i * mPageSliderRes);
super.onMoveToChild(i);
}
@Override
protected void onTapMainDocArea() {
if (!mButtonsVisible) {
showButtons();
} else {
if (mTopBarMode == TopBarMode.Main)
hideButtons();
}
}
@Override
protected void onDocMotion() {
hideButtons();
}
@Override
protected void onHit(Hit item) {
switch (mTopBarMode) {
case Annot:
if (item == Hit.Annotation) {
showButtons();
mTopBarMode = TopBarMode.Delete;
mTopBarSwitcher.setDisplayedChild(mTopBarMode.ordinal());
}
break;
case Delete:
mTopBarMode = TopBarMode.Annot;
mTopBarSwitcher.setDisplayedChild(mTopBarMode.ordinal());
// fall through
default:
// Not in annotation editing mode, but the pageview will
// still select and highlight hit annotations, so
// deselect just in case.
MuPDFView pageView = (MuPDFView) mDocView.getDisplayedView();
if (pageView != null)
pageView.deselectAnnotation();
break;
}
}
};
mDocView.setAdapter(new MuPDFPageAdapter(this, this, core));
mSearchTask = new SearchTask(this, core) {
@Override
protected void onTextFound(SearchTaskResult result) {
SearchTaskResult.set(result);
// Ask the ReaderView to move to the resulting page
mDocView.setDisplayedViewIndex(result.pageNumber);
// Make the ReaderView act on the change to SearchTaskResult
// via overridden onChildSetup method.
mDocView.resetupChildren();
}
};
// Make the buttons overlay, and store all its
// controls in variables
makeButtonsView();
// Set up the page slider
int smax = Math.max(core.countPages()-1,1);
mPageSliderRes = ((10 + smax - 1)/smax) * 2;
// Set the file-name text
mFilenameView.setText(mFileName);
// Activate the seekbar
mPageSlider.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
public void onStopTrackingTouch(SeekBar seekBar) {
mDocView.setDisplayedViewIndex((seekBar.getProgress()+mPageSliderRes/2)/mPageSliderRes);
}
public void onStartTrackingTouch(SeekBar seekBar) {}
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
updatePageNumView((progress+mPageSliderRes/2)/mPageSliderRes);
}
});
// Activate the search-preparing button
mSearchButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
searchModeOn();
}
});
// Activate the reflow button
mReflowButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
toggleReflow();
}
});
if (core.fileFormat().startsWith("PDF") && core.isUnencryptedPDF() && !core.wasOpenedFromBuffer())
{
mAnnotButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
mTopBarMode = TopBarMode.Annot;
mTopBarSwitcher.setDisplayedChild(mTopBarMode.ordinal());
}
});
}
else
{
mAnnotButton.setVisibility(View.GONE);
}
// Search invoking buttons are disabled while there is no text specified
mSearchBack.setEnabled(false);
mSearchFwd.setEnabled(false);
mSearchBack.setColorFilter(Color.argb(255, 128, 128, 128));
mSearchFwd.setColorFilter(Color.argb(255, 128, 128, 128));
// React to interaction with the text widget
mSearchText.addTextChangedListener(new TextWatcher() {
public void afterTextChanged(Editable s) {
boolean haveText = s.toString().length() > 0;
setButtonEnabled(mSearchBack, haveText);
setButtonEnabled(mSearchFwd, haveText);
// Remove any previous search results
if (SearchTaskResult.get() != null && !mSearchText.getText().toString().equals(SearchTaskResult.get().txt)) {
SearchTaskResult.set(null);
mDocView.resetupChildren();
}
}
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {}
public void onTextChanged(CharSequence s, int start, int before,
int count) {}
});
//React to Done button on keyboard
mSearchText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_DONE)
search(1);
return false;
}
});
mSearchText.setOnKeyListener(new View.OnKeyListener() {
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_DOWN && keyCode == KeyEvent.KEYCODE_ENTER)
search(1);
return false;
}
});
// Activate search invoking buttons
mSearchBack.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
search(-1);
}
});
mSearchFwd.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
search(1);
}
});
mLinkButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
setLinkHighlight(!mLinkHighlight);
}
});
if (core.hasOutline()) {
mOutlineButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
OutlineItem outline[] = core.getOutline();
if (outline != null) {
OutlineActivityData.get().items = outline;
Intent intent = new Intent(MuPDFActivity.this, OutlineActivity.class);
startActivityForResult(intent, OUTLINE_REQUEST);
}
}
});
} else {
mOutlineButton.setVisibility(View.GONE);
}
// Reenstate last state if it was recorded
SharedPreferences prefs = getPreferences(Context.MODE_PRIVATE);
mDocView.setDisplayedViewIndex(prefs.getInt("page"+mFileName, 0));
if (savedInstanceState == null || !savedInstanceState.getBoolean("ButtonsHidden", false))
showButtons();
if(savedInstanceState != null && savedInstanceState.getBoolean("SearchMode", false))
searchModeOn();
if(savedInstanceState != null && savedInstanceState.getBoolean("ReflowMode", false))
reflowModeSet(true);
// Stick the document view and the buttons overlay into a parent view
RelativeLayout layout = new RelativeLayout(this);
layout.addView(mDocView);
layout.addView(mButtonsView);
setContentView(layout);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case OUTLINE_REQUEST:
if (resultCode >= 0)
mDocView.setDisplayedViewIndex(resultCode);
break;
case PRINT_REQUEST:
if (resultCode == RESULT_CANCELED)
showInfo(getString(R.string.print_failed));
break;
case FILEPICK_REQUEST:
if (mFilePicker != null && resultCode == RESULT_OK)
mFilePicker.onPick(data.getData());
}
super.onActivityResult(requestCode, resultCode, data);
}
public Object onRetainNonConfigurationInstance()
{
MuPDFCore mycore = core;
core = null;
return mycore;
}
private void reflowModeSet(boolean reflow)
{
mReflow = reflow;
mDocView.setAdapter(mReflow ? new MuPDFReflowAdapter(this, core) : new MuPDFPageAdapter(this, this, core));
mReflowButton.setColorFilter(mReflow ? Color.argb(0xFF, 172, 114, 37) : Color.argb(0xFF, 255, 255, 255));
setButtonEnabled(mAnnotButton, !reflow);
setButtonEnabled(mSearchButton, !reflow);
if (reflow) setLinkHighlight(false);
setButtonEnabled(mLinkButton, !reflow);
setButtonEnabled(mMoreButton, !reflow);
mDocView.refresh(mReflow);
}
private void toggleReflow() {
reflowModeSet(!mReflow);
showInfo(mReflow ? getString(R.string.entering_reflow_mode) : getString(R.string.leaving_reflow_mode));
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if (mFileName != null && mDocView != null) {
outState.putString("FileName", mFileName);
// Store current page in the prefs against the file name,
// so that we can pick it up each time the file is loaded
// Other info is needed only for screen-orientation change,
// so it can go in the bundle
SharedPreferences prefs = getPreferences(Context.MODE_PRIVATE);
SharedPreferences.Editor edit = prefs.edit();
edit.putInt("page"+mFileName, mDocView.getDisplayedViewIndex());
edit.commit();
}
if (!mButtonsVisible)
outState.putBoolean("ButtonsHidden", true);
if (mTopBarMode == TopBarMode.Search)
outState.putBoolean("SearchMode", true);
if (mReflow)
outState.putBoolean("ReflowMode", true);
}
@Override
protected void onPause() {
super.onPause();
if (mSearchTask != null)
mSearchTask.stop();
if (mFileName != null && mDocView != null) {
SharedPreferences prefs = getPreferences(Context.MODE_PRIVATE);
SharedPreferences.Editor edit = prefs.edit();
edit.putInt("page"+mFileName, mDocView.getDisplayedViewIndex());
edit.commit();
}
}
public void onDestroy()
{
if (mDocView != null) {
mDocView.applyToChildren(new ViewMapper() {
void applyToView(View view) {
((MuPDFView)view).releaseBitmaps();
}
});
}
if (core != null)
core.onDestroy();
if (mAlertTask != null) {
mAlertTask.cancel(true);
mAlertTask = null;
}
core = null;
super.onDestroy();
}
private void setButtonEnabled(ImageButton button, boolean enabled) {
button.setEnabled(enabled);
button.setColorFilter(enabled ? Color.argb(255, 255, 255, 255):Color.argb(255, 128, 128, 128));
}
private void setLinkHighlight(boolean highlight) {
mLinkHighlight = highlight;
// LINK_COLOR tint
mLinkButton.setColorFilter(highlight ? Color.argb(0xFF, 172, 114, 37) : Color.argb(0xFF, 255, 255, 255));
// Inform pages of the change.
mDocView.setLinksEnabled(highlight);
}
private void showButtons() {
if (core == null)
return;
if (!mButtonsVisible) {
mButtonsVisible = true;
// Update page number text and slider
int index = mDocView.getDisplayedViewIndex();
updatePageNumView(index);
mPageSlider.setMax((core.countPages()-1)*mPageSliderRes);
mPageSlider.setProgress(index*mPageSliderRes);
if (mTopBarMode == TopBarMode.Search) {
mSearchText.requestFocus();
showKeyboard();
}
Animation anim = new TranslateAnimation(0, 0, -mTopBarSwitcher.getHeight(), 0);
anim.setDuration(200);
anim.setAnimationListener(new Animation.AnimationListener() {
public void onAnimationStart(Animation animation) {
mTopBarSwitcher.setVisibility(View.VISIBLE);
}
public void onAnimationRepeat(Animation animation) {}
public void onAnimationEnd(Animation animation) {}
});
mTopBarSwitcher.startAnimation(anim);
anim = new TranslateAnimation(0, 0, mPageSlider.getHeight(), 0);
anim.setDuration(200);
anim.setAnimationListener(new Animation.AnimationListener() {
public void onAnimationStart(Animation animation) {
mPageSlider.setVisibility(View.VISIBLE);
}
public void onAnimationRepeat(Animation animation) {}
public void onAnimationEnd(Animation animation) {
mPageNumberView.setVisibility(View.VISIBLE);
}
});
mPageSlider.startAnimation(anim);
}
}
private void hideButtons() {
if (mButtonsVisible) {
mButtonsVisible = false;
hideKeyboard();
Animation anim = new TranslateAnimation(0, 0, 0, -mTopBarSwitcher.getHeight());
anim.setDuration(200);
anim.setAnimationListener(new Animation.AnimationListener() {
public void onAnimationStart(Animation animation) {}
public void onAnimationRepeat(Animation animation) {}
public void onAnimationEnd(Animation animation) {
mTopBarSwitcher.setVisibility(View.INVISIBLE);
}
});
mTopBarSwitcher.startAnimation(anim);
anim = new TranslateAnimation(0, 0, 0, mPageSlider.getHeight());
anim.setDuration(200);
anim.setAnimationListener(new Animation.AnimationListener() {
public void onAnimationStart(Animation animation) {
mPageNumberView.setVisibility(View.INVISIBLE);
}
public void onAnimationRepeat(Animation animation) {}
public void onAnimationEnd(Animation animation) {
mPageSlider.setVisibility(View.INVISIBLE);
}
});
mPageSlider.startAnimation(anim);
}
}
private void searchModeOn() {
if (mTopBarMode != TopBarMode.Search) {
mTopBarMode = TopBarMode.Search;
//Focus on EditTextWidget
mSearchText.requestFocus();
showKeyboard();
mTopBarSwitcher.setDisplayedChild(mTopBarMode.ordinal());
}
}
private void searchModeOff() {
if (mTopBarMode == TopBarMode.Search) {
mTopBarMode = TopBarMode.Main;
hideKeyboard();
mTopBarSwitcher.setDisplayedChild(mTopBarMode.ordinal());
SearchTaskResult.set(null);
// Make the ReaderView act on the change to mSearchTaskResult
// via overridden onChildSetup method.
mDocView.resetupChildren();
}
}
private void updatePageNumView(int index) {
if (core == null)
return;
mPageNumberView.setText(String.format("%d / %d", index+1, core.countPages()));
}
private void printDoc() {
if (!core.fileFormat().startsWith("PDF")) {
showInfo(getString(R.string.format_currently_not_supported));
return;
}
Intent myIntent = getIntent();
Uri docUri = myIntent != null ? myIntent.getData() : null;
if (docUri == null) {
showInfo(getString(R.string.print_failed));
}
if (docUri.getScheme() == null)
docUri = Uri.parse("file://"+docUri.toString());
Intent printIntent = new Intent(this, PrintDialogActivity.class);
printIntent.setDataAndType(docUri, "aplication/pdf");
printIntent.putExtra("title", mFileName);
startActivityForResult(printIntent, PRINT_REQUEST);
}
private void showInfo(String message) {
mInfoView.setText(message);
int currentApiVersion = android.os.Build.VERSION.SDK_INT;
if (currentApiVersion >= android.os.Build.VERSION_CODES.HONEYCOMB) {
SafeAnimatorInflater safe = new SafeAnimatorInflater((Activity)this, R.animator.info, (View)mInfoView);
} else {
mInfoView.setVisibility(View.VISIBLE);
mHandler.postDelayed(new Runnable() {
public void run() {
mInfoView.setVisibility(View.INVISIBLE);
}
}, 500);
}
}
private void makeButtonsView() {
mButtonsView = getLayoutInflater().inflate(R.layout.buttons,null);
mFilenameView = (TextView)mButtonsView.findViewById(R.id.docNameText);
mPageSlider = (SeekBar)mButtonsView.findViewById(R.id.pageSlider);
mPageNumberView = (TextView)mButtonsView.findViewById(R.id.pageNumber);
mInfoView = (TextView)mButtonsView.findViewById(R.id.info);
mSearchButton = (ImageButton)mButtonsView.findViewById(R.id.searchButton);
mReflowButton = (ImageButton)mButtonsView.findViewById(R.id.reflowButton);
mOutlineButton = (ImageButton)mButtonsView.findViewById(R.id.outlineButton);
mAnnotButton = (ImageButton)mButtonsView.findViewById(R.id.editAnnotButton);
mAnnotTypeText = (TextView)mButtonsView.findViewById(R.id.annotType);
mTopBarSwitcher = (ViewAnimator)mButtonsView.findViewById(R.id.switcher);
mSearchBack = (ImageButton)mButtonsView.findViewById(R.id.searchBack);
mSearchFwd = (ImageButton)mButtonsView.findViewById(R.id.searchForward);
mSearchText = (EditText)mButtonsView.findViewById(R.id.searchText);
mLinkButton = (ImageButton)mButtonsView.findViewById(R.id.linkButton);
mMoreButton = (ImageButton)mButtonsView.findViewById(R.id.moreButton);
mTopBarSwitcher.setVisibility(View.INVISIBLE);
mPageNumberView.setVisibility(View.INVISIBLE);
mInfoView.setVisibility(View.INVISIBLE);
mPageSlider.setVisibility(View.INVISIBLE);
}
public void OnMoreButtonClick(View v) {
mTopBarMode = TopBarMode.More;
mTopBarSwitcher.setDisplayedChild(mTopBarMode.ordinal());
}
public void OnCancelMoreButtonClick(View v) {
mTopBarMode = TopBarMode.Main;
mTopBarSwitcher.setDisplayedChild(mTopBarMode.ordinal());
}
public void OnPrintButtonClick(View v) {
printDoc();
}
public void OnCopyTextButtonClick(View v) {
mTopBarMode = TopBarMode.Accept;
mTopBarSwitcher.setDisplayedChild(mTopBarMode.ordinal());
mAcceptMode = AcceptMode.CopyText;
mDocView.setMode(MuPDFReaderView.Mode.Selecting);
mAnnotTypeText.setText(getString(R.string.copy_text));
showInfo(getString(R.string.select_text));
}
public void OnEditAnnotButtonClick(View v) {
mTopBarMode = TopBarMode.Annot;
mTopBarSwitcher.setDisplayedChild(mTopBarMode.ordinal());
}
public void OnCancelAnnotButtonClick(View v) {
mTopBarMode = TopBarMode.More;
mTopBarSwitcher.setDisplayedChild(mTopBarMode.ordinal());
}
public void OnHighlightButtonClick(View v) {
mTopBarMode = TopBarMode.Accept;
mTopBarSwitcher.setDisplayedChild(mTopBarMode.ordinal());
mAcceptMode = AcceptMode.Highlight;
mDocView.setMode(MuPDFReaderView.Mode.Selecting);
mAnnotTypeText.setText(R.string.highlight);
showInfo(getString(R.string.select_text));
}
public void OnUnderlineButtonClick(View v) {
mTopBarMode = TopBarMode.Accept;
mTopBarSwitcher.setDisplayedChild(mTopBarMode.ordinal());
mAcceptMode = AcceptMode.Underline;
mDocView.setMode(MuPDFReaderView.Mode.Selecting);
mAnnotTypeText.setText(R.string.underline);
showInfo(getString(R.string.select_text));
}
public void OnStrikeOutButtonClick(View v) {
mTopBarMode = TopBarMode.Accept;
mTopBarSwitcher.setDisplayedChild(mTopBarMode.ordinal());
mAcceptMode = AcceptMode.StrikeOut;
mDocView.setMode(MuPDFReaderView.Mode.Selecting);
mAnnotTypeText.setText(R.string.strike_out);
showInfo(getString(R.string.select_text));
}
public void OnInkButtonClick(View v) {
mTopBarMode = TopBarMode.Accept;
mTopBarSwitcher.setDisplayedChild(mTopBarMode.ordinal());
mAcceptMode = AcceptMode.Ink;
mDocView.setMode(MuPDFReaderView.Mode.Drawing);
mAnnotTypeText.setText(R.string.ink);
showInfo(getString(R.string.draw_annotation));
}
public void OnCancelAcceptButtonClick(View v) {
MuPDFView pageView = (MuPDFView) mDocView.getDisplayedView();
if (pageView != null) {
pageView.deselectText();
pageView.cancelDraw();
}
mDocView.setMode(MuPDFReaderView.Mode.Viewing);
switch (mAcceptMode) {
case CopyText:
mTopBarMode = TopBarMode.More;
break;
default:
mTopBarMode = TopBarMode.Annot;
break;
}
mTopBarSwitcher.setDisplayedChild(mTopBarMode.ordinal());
}
public void OnAcceptButtonClick(View v) {
MuPDFView pageView = (MuPDFView) mDocView.getDisplayedView();
boolean success = false;
switch (mAcceptMode) {
case CopyText:
if (pageView != null)
success = pageView.copySelection();
mTopBarMode = TopBarMode.More;
showInfo(success?getString(R.string.copied_to_clipboard):getString(R.string.no_text_selected));
break;
case Highlight:
if (pageView != null)
success = pageView.markupSelection(Annotation.Type.HIGHLIGHT);
mTopBarMode = TopBarMode.Annot;
if (!success)
showInfo(getString(R.string.no_text_selected));
break;
case Underline:
if (pageView != null)
success
gitextract_jjhp7xc0/
├── .gitignore
├── COPYING
├── LICENSE
├── README.md
├── build.gradle
├── gradle.properties
├── proguard-rules.pro
└── src/
├── androidTest/
│ └── java/
│ └── com/
│ └── artifex/
│ └── viafirma/
│ └── mupdf/
│ └── ApplicationTest.java
└── main/
├── AndroidManifest.xml
├── java/
│ └── com/
│ └── artifex/
│ ├── mupdfdemo/
│ │ ├── Annotation.java
│ │ ├── ArrayDeque.java
│ │ ├── AsyncTask.java
│ │ ├── CancellableAsyncTask.java
│ │ ├── CancellableTaskDefinition.java
│ │ ├── ChoosePDFActivity.java
│ │ ├── ChoosePDFAdapter.java
│ │ ├── ChoosePDFItem.java
│ │ ├── Deque.java
│ │ ├── FilePicker.java
│ │ ├── LinkInfo.java
│ │ ├── LinkInfoExternal.java
│ │ ├── LinkInfoInternal.java
│ │ ├── LinkInfoRemote.java
│ │ ├── LinkInfoVisitor.java
│ │ ├── MuPDFActivity.java
│ │ ├── MuPDFAlert.java
│ │ ├── MuPDFAlertInternal.java
│ │ ├── MuPDFCancellableTaskDefinition.java
│ │ ├── MuPDFCore.java
│ │ ├── MuPDFFragment.java
│ │ ├── MuPDFPageAdapter.java
│ │ ├── MuPDFPageView.java
│ │ ├── MuPDFReaderView.java
│ │ ├── MuPDFReflowAdapter.java
│ │ ├── MuPDFReflowView.java
│ │ ├── MuPDFView.java
│ │ ├── OutlineActivity.java
│ │ ├── OutlineActivityData.java
│ │ ├── OutlineAdapter.java
│ │ ├── OutlineItem.java
│ │ ├── PageView.java
│ │ ├── PrintDialogActivity.java
│ │ ├── ReaderView.java
│ │ ├── SafeAnimatorInflater.java
│ │ ├── SearchTask.java
│ │ ├── SearchTaskResult.java
│ │ ├── Stepper.java
│ │ ├── TextChar.java
│ │ ├── TextWord.java
│ │ └── WidgetType.java
│ └── utils/
│ ├── DigitalizedEventCallback.java
│ └── PdfBitmap.java
└── res/
├── animator/
│ └── info.xml
├── drawable/
│ ├── busy.xml
│ ├── button.xml
│ ├── page_num.xml
│ ├── search.xml
│ ├── seek_progress.xml
│ ├── seek_thumb.xml
│ └── tiled_background.xml
├── layout/
│ ├── buttons.xml
│ ├── main.xml
│ ├── outline_entry.xml
│ ├── picker_entry.xml
│ ├── print_dialog.xml
│ └── textentry.xml
├── values/
│ ├── colors.xml
│ ├── strings.xml
│ └── styles.xml
├── values-ar/
│ └── strings.xml
├── values-ca/
│ └── strings.xml
├── values-cs/
│ └── strings.xml
├── values-da/
│ └── strings.xml
├── values-de/
│ └── strings.xml
├── values-el/
│ └── strings.xml
├── values-es/
│ └── strings.xml
├── values-et/
│ └── strings.xml
├── values-fi/
│ └── strings.xml
├── values-fr/
│ └── strings.xml
├── values-hi/
│ └── strings.xml
├── values-hu/
│ └── strings.xml
├── values-in/
│ └── strings.xml
├── values-it/
│ └── strings.xml
├── values-iw/
│ └── strings.xml
├── values-ja/
│ └── strings.xml
├── values-ko/
│ └── strings.xml
├── values-lt/
│ └── strings.xml
├── values-ms/
│ └── strings.xml
├── values-nl/
│ └── strings.xml
├── values-no/
│ └── strings.xml
├── values-pl/
│ └── strings.xml
├── values-pt/
│ └── strings.xml
├── values-ru/
│ └── strings.xml
├── values-sk/
│ └── strings.xml
├── values-sv/
│ └── strings.xml
├── values-th/
│ └── strings.xml
├── values-tl/
│ └── strings.xml
├── values-tr/
│ └── strings.xml
├── values-zh/
│ └── strings.xml
└── values-zh-rTW/
└── strings.xml
SYMBOL INDEX (737 symbols across 44 files)
FILE: src/androidTest/java/com/artifex/viafirma/mupdf/ApplicationTest.java
class ApplicationTest (line 9) | public class ApplicationTest extends ApplicationTestCase<Application> {
method ApplicationTest (line 10) | public ApplicationTest() {
FILE: src/main/java/com/artifex/mupdfdemo/Annotation.java
class Annotation (line 5) | public class Annotation extends RectF {
type Type (line 6) | enum Type {
method Annotation (line 14) | public Annotation(float x0, float y0, float x1, float y1, int _type) {
FILE: src/main/java/com/artifex/mupdfdemo/ArrayDeque.java
class ArrayDeque (line 64) | public class ArrayDeque<E> extends AbstractCollection<E>
method allocateElements (line 105) | private void allocateElements(int numElements) {
method doubleCapacity (line 128) | private void doubleCapacity() {
method copyElements (line 151) | private <T> T[] copyElements(T[] a) {
method ArrayDeque (line 166) | public ArrayDeque() {
method ArrayDeque (line 176) | public ArrayDeque(int numElements) {
method ArrayDeque (line 190) | public ArrayDeque(Collection<? extends E> c) {
method addFirst (line 205) | public void addFirst(E e) {
method addLast (line 221) | public void addLast(E e) {
method offerFirst (line 236) | public boolean offerFirst(E e) {
method offerLast (line 248) | public boolean offerLast(E e) {
method removeFirst (line 256) | public E removeFirst() {
method removeLast (line 266) | public E removeLast() {
method pollFirst (line 273) | public E pollFirst() {
method pollLast (line 284) | public E pollLast() {
method getFirst (line 297) | public E getFirst() {
method getLast (line 307) | public E getLast() {
method peekFirst (line 315) | public E peekFirst() {
method peekLast (line 321) | public E peekLast() {
method removeFirstOccurrence (line 339) | public boolean removeFirstOccurrence(Object o) {
method removeLastOccurrence (line 367) | public boolean removeLastOccurrence(Object o) {
method add (line 394) | public boolean add(E e) {
method offer (line 408) | public boolean offer(E e) {
method remove (line 423) | public E remove() {
method poll (line 437) | public E poll() {
method element (line 451) | public E element() {
method peek (line 464) | public E peek() {
method push (line 479) | public void push(E e) {
method pop (line 493) | public E pop() {
method checkInvariants (line 497) | private void checkInvariants() {
method delete (line 515) | private boolean delete(int i) {
method size (line 561) | public int size() {
method isEmpty (line 570) | public boolean isEmpty() {
method iterator (line 582) | public Iterator<E> iterator() {
method descendingIterator (line 586) | public Iterator<E> descendingIterator() {
class DeqIterator (line 590) | private class DeqIterator implements Iterator<E> {
method hasNext (line 608) | public boolean hasNext() {
method next (line 612) | public E next() {
method remove (line 625) | public void remove() {
class DescendingIterator (line 636) | private class DescendingIterator implements Iterator<E> {
method hasNext (line 646) | public boolean hasNext() {
method next (line 650) | public E next() {
method remove (line 661) | public void remove() {
method contains (line 680) | public boolean contains(Object o) {
method remove (line 707) | public boolean remove(Object o) {
method clear (line 715) | public void clear() {
method toArray (line 742) | public Object[] toArray() {
method toArray (line 782) | @SuppressWarnings("unchecked")
method clone (line 801) | public ArrayDeque<E> clone() {
method writeObject (line 825) | private void writeObject(java.io.ObjectOutputStream s)
method readObject (line 841) | private void readObject(java.io.ObjectInputStream s)
FILE: src/main/java/com/artifex/mupdfdemo/AsyncTask.java
class AsyncTask (line 180) | public abstract class AsyncTask<Params, Progress, Result> {
method newThread (line 190) | public Thread newThread(Runnable r) {
class SerialExecutor (line 225) | private static class SerialExecutor implements Executor {
method execute (line 229) | public synchronized void execute(final Runnable r) {
method scheduleNext (line 244) | protected synchronized void scheduleNext() {
type Status (line 255) | public enum Status {
method init (line 271) | public static void init() {
method setDefaultExecutor (line 276) | public static void setDefaultExecutor(Executor exec) {
method AsyncTask (line 283) | public AsyncTask() {
method postResultIfNotInvoked (line 311) | private void postResultIfNotInvoked(Result result) {
method postResult (line 318) | private Result postResult(Result result) {
method getStatus (line 331) | public final Status getStatus() {
method doInBackground (line 351) | protected abstract Result doInBackground(Params... params);
method onPreExecute (line 359) | protected void onPreExecute() {
method onPostExecute (line 374) | @SuppressWarnings({"UnusedDeclaration"})
method onProgressUpdate (line 387) | @SuppressWarnings({"UnusedDeclaration"})
method onCancelled (line 405) | @SuppressWarnings({"UnusedParameters"})
method onCancelled (line 422) | protected void onCancelled() {
method isCancelled (line 435) | public final boolean isCancelled() {
method cancel (line 468) | public final boolean cancel(boolean mayInterruptIfRunning) {
method get (line 484) | public final Result get() throws InterruptedException, ExecutionExcept...
method get (line 503) | public final Result get(long timeout, TimeUnit unit) throws Interrupte...
method execute (line 536) | public final AsyncTask<Params, Progress, Result> execute(Params... par...
method executeOnExecutor (line 573) | public final AsyncTask<Params, Progress, Result> executeOnExecutor(Exe...
method execute (line 605) | public static void execute(Runnable runnable) {
method publishProgress (line 623) | protected final void publishProgress(Progress... values) {
method finish (line 630) | private void finish(Result result) {
class InternalHandler (line 639) | private static class InternalHandler extends Handler {
method handleMessage (line 640) | @SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})
class WorkerRunnable (line 656) | private static abstract class WorkerRunnable<Params, Result> implement...
class AsyncTaskResult (line 660) | @SuppressWarnings({"RawUseOfParameterizedType"})
method AsyncTaskResult (line 665) | AsyncTaskResult(AsyncTask task, Data... data) {
FILE: src/main/java/com/artifex/mupdfdemo/CancellableAsyncTask.java
class CancellableAsyncTask (line 8) | public class CancellableAsyncTask<Params, Result>
method onPreExecute (line 13) | public void onPreExecute()
method onPostExecute (line 18) | public void onPostExecute(Result result)
method CancellableAsyncTask (line 23) | public CancellableAsyncTask(final CancellableTaskDefinition<Params, Re...
method cancelAndWait (line 52) | public void cancelAndWait()
method execute (line 74) | public void execute(Params ... params)
FILE: src/main/java/com/artifex/mupdfdemo/CancellableTaskDefinition.java
type CancellableTaskDefinition (line 3) | public interface CancellableTaskDefinition <Params, Result>
method doInBackground (line 5) | public Result doInBackground(Params... params);
method doCancel (line 6) | public void doCancel();
method doCleanup (line 7) | public void doCleanup();
FILE: src/main/java/com/artifex/mupdfdemo/ChoosePDFActivity.java
type Purpose (line 24) | enum Purpose {
class ChoosePDFActivity (line 29) | public class ChoosePDFActivity extends ListActivity {
method onCreate (line 41) | @Override
method lastPosition (line 174) | private void lastPosition() {
method onListItemClick (line 180) | @Override
method onPause (line 219) | @Override
FILE: src/main/java/com/artifex/mupdfdemo/ChoosePDFAdapter.java
class ChoosePDFAdapter (line 13) | public class ChoosePDFAdapter extends BaseAdapter {
method ChoosePDFAdapter (line 17) | public ChoosePDFAdapter(LayoutInflater inflater) {
method clear (line 22) | public void clear() {
method add (line 26) | public void add(ChoosePDFItem item) {
method getCount (line 31) | public int getCount() {
method getItem (line 35) | public Object getItem(int i) {
method getItemId (line 39) | public long getItemId(int arg0) {
method iconForType (line 43) | private int iconForType(ChoosePDFItem.Type type) {
method getView (line 52) | public View getView(int position, View convertView, ViewGroup parent) {
FILE: src/main/java/com/artifex/mupdfdemo/ChoosePDFItem.java
class ChoosePDFItem (line 3) | public class ChoosePDFItem {
type Type (line 4) | enum Type {
method ChoosePDFItem (line 11) | public ChoosePDFItem (Type t, String n) {
FILE: src/main/java/com/artifex/mupdfdemo/Deque.java
type Deque (line 172) | public interface Deque<E> extends Queue<E> {
method addFirst (line 189) | void addFirst(E e);
method addLast (line 209) | void addLast(E e);
method offerFirst (line 227) | boolean offerFirst(E e);
method offerLast (line 245) | boolean offerLast(E e);
method removeFirst (line 255) | E removeFirst();
method removeLast (line 265) | E removeLast();
method pollFirst (line 273) | E pollFirst();
method pollLast (line 281) | E pollLast();
method getFirst (line 292) | E getFirst();
method getLast (line 302) | E getLast();
method peekFirst (line 310) | E peekFirst();
method peekLast (line 318) | E peekLast();
method removeFirstOccurrence (line 336) | boolean removeFirstOccurrence(Object o);
method removeLastOccurrence (line 354) | boolean removeLastOccurrence(Object o);
method add (line 380) | boolean add(E e);
method offer (line 403) | boolean offer(E e);
method remove (line 416) | E remove();
method poll (line 428) | E poll();
method element (line 441) | E element();
method peek (line 453) | E peek();
method push (line 477) | void push(E e);
method pop (line 489) | E pop();
method remove (line 512) | boolean remove(Object o);
method contains (line 527) | boolean contains(Object o);
method size (line 534) | public int size();
method iterator (line 542) | Iterator<E> iterator();
method descendingIterator (line 552) | Iterator<E> descendingIterator();
FILE: src/main/java/com/artifex/mupdfdemo/FilePicker.java
class FilePicker (line 5) | public abstract class FilePicker {
type FilePickerSupport (line 6) | public interface FilePickerSupport {
method performPickFor (line 7) | void performPickFor(FilePicker picker);
method FilePicker (line 12) | FilePicker(FilePickerSupport _support) {
method pick (line 16) | void pick() {
method onPick (line 20) | abstract void onPick(Uri uri);
FILE: src/main/java/com/artifex/mupdfdemo/LinkInfo.java
class LinkInfo (line 5) | public class LinkInfo {
method LinkInfo (line 8) | public LinkInfo(float l, float t, float r, float b) {
method acceptVisitor (line 12) | public void acceptVisitor(LinkInfoVisitor visitor) {
FILE: src/main/java/com/artifex/mupdfdemo/LinkInfoExternal.java
class LinkInfoExternal (line 3) | public class LinkInfoExternal extends LinkInfo {
method LinkInfoExternal (line 6) | public LinkInfoExternal(float l, float t, float r, float b, String u) {
method acceptVisitor (line 11) | public void acceptVisitor(LinkInfoVisitor visitor) {
FILE: src/main/java/com/artifex/mupdfdemo/LinkInfoInternal.java
class LinkInfoInternal (line 3) | public class LinkInfoInternal extends LinkInfo {
method LinkInfoInternal (line 6) | public LinkInfoInternal(float l, float t, float r, float b, int p) {
method acceptVisitor (line 11) | public void acceptVisitor(LinkInfoVisitor visitor) {
FILE: src/main/java/com/artifex/mupdfdemo/LinkInfoRemote.java
class LinkInfoRemote (line 3) | public class LinkInfoRemote extends LinkInfo {
method LinkInfoRemote (line 8) | public LinkInfoRemote(float l, float t, float r, float b, String f, in...
method acceptVisitor (line 15) | public void acceptVisitor(LinkInfoVisitor visitor) {
FILE: src/main/java/com/artifex/mupdfdemo/LinkInfoVisitor.java
class LinkInfoVisitor (line 3) | abstract public class LinkInfoVisitor {
method visitInternal (line 4) | public abstract void visitInternal(LinkInfoInternal li);
method visitExternal (line 5) | public abstract void visitExternal(LinkInfoExternal li);
method visitRemote (line 6) | public abstract void visitRemote(LinkInfoRemote li);
FILE: src/main/java/com/artifex/mupdfdemo/MuPDFActivity.java
class ThreadPerTaskExecutor (line 38) | class ThreadPerTaskExecutor implements Executor {
method execute (line 39) | public void execute(Runnable r) {
class MuPDFActivity (line 44) | public class MuPDFActivity extends Activity implements FilePicker.FilePi...
type TopBarMode (line 47) | enum TopBarMode {Main, Search, Annot, Delete, More, Accept}
type AcceptMode (line 48) | enum AcceptMode {Highlight, Underline, StrikeOut, Ink, CopyText}
method createAlertWaiter (line 87) | public void createAlertWaiter() {
method destroyAlertWaiter (line 193) | public void destroyAlertWaiter() {
method openFile (line 205) | private MuPDFCore openFile(String path)
method openBuffer (line 226) | private MuPDFCore openBuffer(byte buffer[], String magic)
method onCreate (line 244) | @Override
method requestPassword (line 357) | public void requestPassword(final Bundle savedInstanceState) {
method createUI (line 385) | public void createUI(Bundle savedInstanceState) {
method onActivityResult (line 606) | @Override
method onRetainNonConfigurationInstance (line 624) | public Object onRetainNonConfigurationInstance()
method reflowModeSet (line 631) | private void reflowModeSet(boolean reflow)
method toggleReflow (line 644) | private void toggleReflow() {
method onSaveInstanceState (line 649) | @Override
method onPause (line 676) | @Override
method onDestroy (line 691) | public void onDestroy()
method setButtonEnabled (line 710) | private void setButtonEnabled(ImageButton button, boolean enabled) {
method setLinkHighlight (line 715) | private void setLinkHighlight(boolean highlight) {
method showButtons (line 723) | private void showButtons() {
method hideButtons (line 764) | private void hideButtons() {
method searchModeOn (line 795) | private void searchModeOn() {
method searchModeOff (line 805) | private void searchModeOff() {
method updatePageNumView (line 817) | private void updatePageNumView(int index) {
method printDoc (line 823) | private void printDoc() {
method showInfo (line 845) | private void showInfo(String message) {
method makeButtonsView (line 861) | private void makeButtonsView() {
method OnMoreButtonClick (line 884) | public void OnMoreButtonClick(View v) {
method OnCancelMoreButtonClick (line 889) | public void OnCancelMoreButtonClick(View v) {
method OnPrintButtonClick (line 894) | public void OnPrintButtonClick(View v) {
method OnCopyTextButtonClick (line 898) | public void OnCopyTextButtonClick(View v) {
method OnEditAnnotButtonClick (line 907) | public void OnEditAnnotButtonClick(View v) {
method OnCancelAnnotButtonClick (line 912) | public void OnCancelAnnotButtonClick(View v) {
method OnHighlightButtonClick (line 917) | public void OnHighlightButtonClick(View v) {
method OnUnderlineButtonClick (line 926) | public void OnUnderlineButtonClick(View v) {
method OnStrikeOutButtonClick (line 935) | public void OnStrikeOutButtonClick(View v) {
method OnInkButtonClick (line 944) | public void OnInkButtonClick(View v) {
method OnCancelAcceptButtonClick (line 953) | public void OnCancelAcceptButtonClick(View v) {
method OnAcceptButtonClick (line 971) | public void OnAcceptButtonClick(View v) {
method OnCancelSearchButtonClick (line 1018) | public void OnCancelSearchButtonClick(View v) {
method OnDeleteButtonClick (line 1022) | public void OnDeleteButtonClick(View v) {
method OnCancelDeleteButtonClick (line 1030) | public void OnCancelDeleteButtonClick(View v) {
method showKeyboard (line 1038) | private void showKeyboard() {
method hideKeyboard (line 1044) | private void hideKeyboard() {
method search (line 1050) | private void search(int direction) {
method onSearchRequested (line 1058) | @Override
method onPrepareOptionsMenu (line 1069) | @Override
method onStart (line 1080) | @Override
method onStop (line 1091) | @Override
method onBackPressed (line 1102) | @Override
method performPickFor (line 1124) | @Override
FILE: src/main/java/com/artifex/mupdfdemo/MuPDFAlert.java
class MuPDFAlert (line 3) | public class MuPDFAlert {
type IconType (line 4) | public enum IconType {Error,Warning,Question,Status}
type ButtonPressed (line 5) | public enum ButtonPressed {None,Ok,Cancel,No,Yes}
type ButtonGroupType (line 6) | public enum ButtonGroupType {Ok,OkCancel,YesNo,YesNoCancel}
method MuPDFAlert (line 14) | MuPDFAlert(String aMessage, IconType aIconType, ButtonGroupType aButto...
FILE: src/main/java/com/artifex/mupdfdemo/MuPDFAlertInternal.java
class MuPDFAlertInternal (line 4) | public class MuPDFAlertInternal {
method MuPDFAlertInternal (line 11) | MuPDFAlertInternal(String aMessage, int aIconType, int aButtonGroupTyp...
method MuPDFAlertInternal (line 19) | MuPDFAlertInternal(MuPDFAlert alert) {
method toAlert (line 27) | MuPDFAlert toAlert() {
FILE: src/main/java/com/artifex/mupdfdemo/MuPDFCancellableTaskDefinition.java
class MuPDFCancellableTaskDefinition (line 3) | public abstract class MuPDFCancellableTaskDefinition<Params, Result> imp...
method MuPDFCancellableTaskDefinition (line 7) | public MuPDFCancellableTaskDefinition(MuPDFCore core)
method doCancel (line 12) | @Override
method doCleanup (line 21) | @Override
method doInBackground (line 31) | @Override
method doInBackground (line 37) | public abstract Result doInBackground(MuPDFCore.Cookie cookie, Params ...
FILE: src/main/java/com/artifex/mupdfdemo/MuPDFCore.java
class MuPDFCore (line 10) | public class MuPDFCore
method openFile (line 28) | private native long openFile(String filename);
method openBuffer (line 29) | private native long openBuffer(String magic);
method fileFormatInternal (line 30) | private native String fileFormatInternal();
method isUnencryptedPDFInternal (line 31) | private native boolean isUnencryptedPDFInternal();
method countPagesInternal (line 32) | private native int countPagesInternal();
method gotoPageInternal (line 33) | private native void gotoPageInternal(int localActionPageNum);
method getPageWidth (line 34) | private native float getPageWidth();
method getPageHeight (line 35) | private native float getPageHeight();
method drawPage (line 36) | private native void drawPage(Bitmap bitmap,
method updatePageInternal (line 41) | private native void updatePageInternal(Bitmap bitmap,
method searchPage (line 47) | private native RectF[] searchPage(String text);
method text (line 48) | private native TextChar[][][][] text();
method textAsHtml (line 49) | private native byte[] textAsHtml();
method addMarkupAnnotationInternal (line 50) | private native void addMarkupAnnotationInternal(PointF[] quadPoints, i...
method addInkAnnotationInternal (line 51) | private native void addInkAnnotationInternal(PointF[][] arcs);
method deleteAnnotationInternal (line 52) | private native void deleteAnnotationInternal(int annot_index);
method passClickEventInternal (line 53) | private native int passClickEventInternal(int page, float x, float y);
method setFocusedWidgetChoiceSelectedInternal (line 54) | private native void setFocusedWidgetChoiceSelectedInternal(String [] s...
method getFocusedWidgetChoiceSelected (line 55) | private native String [] getFocusedWidgetChoiceSelected();
method getFocusedWidgetChoiceOptions (line 56) | private native String [] getFocusedWidgetChoiceOptions();
method getFocusedWidgetSignatureState (line 57) | private native int getFocusedWidgetSignatureState();
method checkFocusedSignatureInternal (line 58) | private native String checkFocusedSignatureInternal();
method signFocusedSignatureInternal (line 59) | private native boolean signFocusedSignatureInternal(String keyFile, St...
method setFocusedWidgetTextInternal (line 60) | private native int setFocusedWidgetTextInternal(String text);
method getFocusedWidgetTextInternal (line 61) | private native String getFocusedWidgetTextInternal();
method getFocusedWidgetTypeInternal (line 62) | private native int getFocusedWidgetTypeInternal();
method getPageLinksInternal (line 63) | private native LinkInfo [] getPageLinksInternal(int page);
method getWidgetAreasInternal (line 64) | private native RectF[] getWidgetAreasInternal(int page);
method getAnnotationsInternal (line 65) | private native Annotation[] getAnnotationsInternal(int page);
method getOutlineInternal (line 66) | private native OutlineItem [] getOutlineInternal();
method hasOutlineInternal (line 67) | private native boolean hasOutlineInternal();
method needsPasswordInternal (line 68) | private native boolean needsPasswordInternal();
method authenticatePasswordInternal (line 69) | private native boolean authenticatePasswordInternal(String password);
method waitForAlertInternal (line 70) | private native MuPDFAlertInternal waitForAlertInternal();
method replyToAlertInternal (line 71) | private native void replyToAlertInternal(MuPDFAlertInternal alert);
method startAlertsInternal (line 72) | private native void startAlertsInternal();
method stopAlertsInternal (line 73) | private native void stopAlertsInternal();
method destroying (line 74) | private native void destroying();
method hasChangesInternal (line 75) | private native boolean hasChangesInternal();
method saveInternal (line 76) | private native void saveInternal();
method createCookie (line 77) | private native long createCookie();
method destroyCookie (line 78) | private native void destroyCookie(long cookie);
method abortCookie (line 79) | private native void abortCookie(long cookie);
method javascriptSupported (line 81) | public native boolean javascriptSupported();
class Cookie (line 83) | public class Cookie
method Cookie (line 87) | public Cookie()
method abort (line 94) | public void abort()
method destroy (line 99) | public void destroy()
method MuPDFCore (line 107) | public MuPDFCore(Context context, String filename) throws Exception
method MuPDFCore (line 119) | public MuPDFCore(Context context, byte buffer[], String magic) throws ...
method countPages (line 131) | public int countPages()
method fileFormat (line 139) | public String fileFormat()
method isUnencryptedPDF (line 144) | public boolean isUnencryptedPDF()
method wasOpenedFromBuffer (line 149) | public boolean wasOpenedFromBuffer()
method countPagesSynchronized (line 154) | private synchronized int countPagesSynchronized() {
method gotoPage (line 159) | private void gotoPage(int page)
method getPageSize (line 170) | public synchronized PointF getPageSize(int page) {
method waitForAlert (line 175) | public MuPDFAlert waitForAlert() {
method replyToAlert (line 180) | public void replyToAlert(MuPDFAlert alert) {
method stopAlerts (line 184) | public void stopAlerts() {
method startAlerts (line 188) | public void startAlerts() {
method onDestroy (line 192) | public synchronized void onDestroy() {
method drawPage (line 197) | public synchronized void drawPage(Bitmap bm, int page,
method updatePage (line 206) | public synchronized void updatePage(Bitmap bm, int page,
method passClickEvent (line 214) | public synchronized PassClickResult passClickEvent(int page, float x, ...
method setFocusedWidgetText (line 232) | public synchronized boolean setFocusedWidgetText(int page, String text) {
method setFocusedWidgetChoiceSelected (line 240) | public synchronized void setFocusedWidgetChoiceSelected(String [] sele...
method checkFocusedSignature (line 244) | public synchronized String checkFocusedSignature() {
method signFocusedSignature (line 248) | public synchronized boolean signFocusedSignature(String keyFile, Strin...
method getPageLinks (line 252) | public synchronized LinkInfo [] getPageLinks(int page) {
method getWidgetAreas (line 256) | public synchronized RectF [] getWidgetAreas(int page) {
method getAnnoations (line 260) | public synchronized Annotation [] getAnnoations(int page) {
method searchPage (line 264) | public synchronized RectF [] searchPage(int page, String text) {
method html (line 269) | public synchronized byte[] html(int page) {
method textLines (line 274) | public synchronized TextWord [][] textLines(int page) {
method addMarkupAnnotation (line 312) | public synchronized void addMarkupAnnotation(int page, PointF[] quadPo...
method addInkAnnotation (line 317) | public synchronized void addInkAnnotation(int page, PointF[][] arcs) {
method deleteAnnotation (line 322) | public synchronized void deleteAnnotation(int page, int annot_index) {
method hasOutline (line 327) | public synchronized boolean hasOutline() {
method getOutline (line 331) | public synchronized OutlineItem [] getOutline() {
method needsPassword (line 335) | public synchronized boolean needsPassword() {
method authenticatePassword (line 339) | public synchronized boolean authenticatePassword(String password) {
method hasChanges (line 343) | public synchronized boolean hasChanges() {
method save (line 347) | public synchronized void save() {
FILE: src/main/java/com/artifex/mupdfdemo/MuPDFFragment.java
class MuPDFFragment (line 47) | public class MuPDFFragment extends Fragment implements FilePicker.FilePi...
type TopBarMode (line 62) | enum TopBarMode {Main, Search, Annot, Delete, More, Accept}
type AcceptMode (line 63) | enum AcceptMode {Highlight, Underline, StrikeOut, Ink, CopyText}
method createAlertWaiter (line 108) | public void createAlertWaiter() {
method destroyAlertWaiter (line 214) | public void destroyAlertWaiter() {
method openFile (line 226) | private MuPDFCore openFile(String path)
method openBuffer (line 249) | private MuPDFCore openBuffer(byte buffer[], String magic)
method onCreateView (line 267) | @Override
method requestPassword (line 401) | public void requestPassword(final Bundle savedInstanceState) {
method createUI (line 429) | public View createUI(Bundle savedInstanceState, final Context context) {
method onRetainNonConfigurationInstance (line 675) | public Object onRetainNonConfigurationInstance()
method reflowModeSet (line 682) | private void reflowModeSet(boolean reflow)
method toggleReflow (line 695) | private void toggleReflow() {
method onSaveInstanceState (line 700) | @Override
method onPause (line 727) | @Override
method onDestroy (line 742) | public void onDestroy()
method setButtonEnabled (line 769) | private void setButtonEnabled(ImageButton button, boolean enabled) {
method setLinkHighlight (line 774) | private void setLinkHighlight(boolean highlight) {
method showButtons (line 782) | private void showButtons() {
method hideButtons (line 826) | private void hideButtons() {
method searchModeOn (line 860) | private void searchModeOn() {
method searchModeOff (line 870) | private void searchModeOff() {
method updatePageNumView (line 882) | private void updatePageNumView(int index) {
method printDoc (line 888) | private void printDoc() {
method showInfo (line 910) | private void showInfo(String message) {
method makeButtonsView (line 926) | private void makeButtonsView() {
method OnMoreButtonClick (line 949) | public void OnMoreButtonClick(View v) {
method OnCancelMoreButtonClick (line 954) | public void OnCancelMoreButtonClick(View v) {
method OnPrintButtonClick (line 959) | public void OnPrintButtonClick(View v) {
method OnCopyTextButtonClick (line 963) | public void OnCopyTextButtonClick(View v) {
method OnEditAnnotButtonClick (line 972) | public void OnEditAnnotButtonClick(View v) {
method OnCancelAnnotButtonClick (line 977) | public void OnCancelAnnotButtonClick(View v) {
method OnHighlightButtonClick (line 982) | public void OnHighlightButtonClick(View v) {
method OnUnderlineButtonClick (line 991) | public void OnUnderlineButtonClick(View v) {
method OnStrikeOutButtonClick (line 1000) | public void OnStrikeOutButtonClick(View v) {
method OnInkButtonClick (line 1009) | public void OnInkButtonClick(View v) {
method OnCancelAcceptButtonClick (line 1018) | public void OnCancelAcceptButtonClick(View v) {
method OnAcceptButtonClick (line 1036) | public void OnAcceptButtonClick(View v) {
method OnCancelSearchButtonClick (line 1083) | public void OnCancelSearchButtonClick(View v) {
method OnDeleteButtonClick (line 1087) | public void OnDeleteButtonClick(View v) {
method OnCancelDeleteButtonClick (line 1095) | public void OnCancelDeleteButtonClick(View v) {
method showKeyboard (line 1103) | private void showKeyboard() {
method hideKeyboard (line 1109) | private void hideKeyboard() {
method search (line 1115) | public void search(int direction) {
method onStart (line 1123) | @Override
method onStop (line 1134) | @Override
method performPickFor (line 1145) | @Override
method newInstance (line 1156) | public static MuPDFFragment newInstance (String signBitmapPath, List<P...
method setPageNumber (line 1160) | public void setPageNumber(int pageNumber) {
method getCurrentPage (line 1169) | public int getCurrentPage() {
method newInstance (line 1177) | public static MuPDFFragment newInstance (String signBitmapPath, List<P...
method newInstance (line 1182) | public static MuPDFFragment newInstance (String signBitmapPath, List<P...
method newInstance (line 1207) | public static MuPDFFragment newInstance (byte[] bufferedPdf) {
method newInstance (line 1213) | public static MuPDFFragment newInstance (String pathPdf) {
method newInstance (line 1218) | public static MuPDFFragment newInstance (String pathPdf, String passwo...
method newInstance (line 1223) | public static MuPDFFragment newInstance (byte[] bufferedPdf, boolean s...
method newInstance (line 1229) | public static MuPDFFragment newInstance (String pathPdf, boolean showC...
method addBitmap (line 1234) | public void addBitmap(PdfBitmap pdfBitmap) {
method setPdfBitmapList (line 1242) | public void setPdfBitmapList(Collection<PdfBitmap> pdfBitmaps) {
method getBitmapList (line 1249) | public Collection<PdfBitmap> getBitmapList() {
method removeBitmapOnPosition (line 1258) | public boolean removeBitmapOnPosition(float x, float y) {
method setByteArrayPdf (line 1269) | public void setByteArrayPdf(byte[] byteArrayPdf) {
method onAttach (line 1273) | @Override
method checkSign (line 1279) | public boolean checkSign(){
method getEventCallback (line 1294) | public DigitalizedEventCallback getEventCallback() {
method setEventCallback (line 1298) | public void setEventCallback(DigitalizedEventCallback eventCallback) {
method onConfigurationChanged (line 1305) | @Override
method updateCurrentPage (line 1313) | public void updateCurrentPage() {
method redrawAll (line 1319) | public void redrawAll() {
method run (line 1327) | @Override
method redrawTouch (line 1335) | private void redrawTouch(){
FILE: src/main/java/com/artifex/mupdfdemo/MuPDFPageAdapter.java
class MuPDFPageAdapter (line 17) | public class MuPDFPageAdapter extends BaseAdapter {
method MuPDFPageAdapter (line 26) | public MuPDFPageAdapter(Context c, FilePicker.FilePickerSupport filePi...
method getCount (line 32) | public int getCount() {
method getItem (line 36) | public Object getItem(int position) {
method getItemId (line 40) | public long getItemId(int position) {
method getView (line 44) | public View getView(final int position, View convertView, ViewGroup pa...
method getPdfBitmapList (line 102) | public Collection<PdfBitmap> getPdfBitmapList() {
method setPdfBitmapList (line 109) | public void setPdfBitmapList(Collection<PdfBitmap> pdfBitmapList) {
method getNumSignature (line 113) | public int getNumSignature() {
method setNumSignature (line 117) | public void setNumSignature(int numSignature) {
method addBitmaps (line 121) | public void addBitmaps(Set<PdfBitmap> pdfBitmaps) {
method addBitmap (line 129) | public void addBitmap(PdfBitmap pdfBitmap) {
FILE: src/main/java/com/artifex/mupdfdemo/MuPDFPageView.java
type SignatureState (line 25) | enum SignatureState {
class PassClickResultVisitor (line 31) | abstract class PassClickResultVisitor {
method visitText (line 32) | public abstract void visitText(PassClickResultText result);
method visitChoice (line 33) | public abstract void visitChoice(PassClickResultChoice result);
method visitSignature (line 34) | public abstract void visitSignature(PassClickResultSignature result);
class PassClickResult (line 37) | class PassClickResult {
method PassClickResult (line 40) | public PassClickResult(boolean _changed) {
method acceptVisitor (line 44) | public void acceptVisitor(PassClickResultVisitor visitor) {
class PassClickResultText (line 48) | class PassClickResultText extends PassClickResult {
method PassClickResultText (line 51) | public PassClickResultText(boolean _changed, String _text) {
method acceptVisitor (line 56) | public void acceptVisitor(PassClickResultVisitor visitor) {
class PassClickResultChoice (line 61) | class PassClickResultChoice extends PassClickResult {
method PassClickResultChoice (line 65) | public PassClickResultChoice(boolean _changed, String [] _options, Str...
method acceptVisitor (line 71) | public void acceptVisitor(PassClickResultVisitor visitor) {
class PassClickResultSignature (line 76) | class PassClickResultSignature extends PassClickResult {
method PassClickResultSignature (line 79) | public PassClickResultSignature(boolean _changed, int _state) {
method acceptVisitor (line 84) | public void acceptVisitor(PassClickResultVisitor visitor) {
class MuPDFPageView (line 89) | public class MuPDFPageView extends PageView implements MuPDFView {
method MuPDFPageView (line 116) | public MuPDFPageView(Context c, FilePicker.FilePickerSupport filePicke...
method signWithKeyFile (line 201) | private void signWithKeyFile(final Uri uri) {
method signWithKeyFileAndPassword (line 214) | private void signWithKeyFileAndPassword(final Uri uri, final String pa...
method hitLink (line 238) | public LinkInfo hitLink(float x, float y) {
method invokeTextDialog (line 254) | private void invokeTextDialog(String text) {
method invokeChoiceDialog (line 260) | private void invokeChoiceDialog(final String [] options) {
method invokeSignatureCheckingDialog (line 284) | private void invokeSignatureCheckingDialog() {
method invokeSigningDialog (line 301) | private void invokeSigningDialog() {
method warnNoSignatureSupport (line 306) | private void warnNoSignatureSupport() {
method setChangeReporter (line 312) | public void setChangeReporter(Runnable reporter) {
method passClickEvent (line 316) | public Hit passClickEvent(float x, float y) {
method copySelection (line 405) | @TargetApi(11)
method markupSelection (line 447) | public boolean markupSelection(final Annotation.Type type) {
method deleteSelectedAnnotation (line 494) | public void deleteSelectedAnnotation() {
method deselectAnnotation (line 520) | public void deselectAnnotation() {
method saveDraw (line 525) | public boolean saveDraw() {
method getDrawPageTask (line 557) | @Override
method getUpdatePageTask (line 575) | protected CancellableTaskDefinition<Void, Void> getUpdatePageTask(fina...
method getLinkInfo (line 593) | @Override
method getText (line 598) | @Override
method addMarkup (line 603) | @Override
method loadAnnotations (line 608) | private void loadAnnotations() {
method setPage (line 627) | @Override
method setScale (line 648) | public void setScale(float scale) {
method releaseResources (line 653) | @Override
FILE: src/main/java/com/artifex/mupdfdemo/MuPDFReaderView.java
class MuPDFReaderView (line 14) | public class MuPDFReaderView extends ReaderView {
type Mode (line 15) | enum Mode {Viewing, Selecting, Drawing}
method onTapMainDocArea (line 24) | protected void onTapMainDocArea() {}
method onDocMotion (line 25) | protected void onDocMotion() {}
method onHit (line 26) | protected void onHit(Hit item) {}
method setLinksEnabled (line 28) | public void setLinksEnabled(boolean b) {
method setMode (line 33) | public void setMode(Mode m) {
method setup (line 37) | private void setup()
method MuPDFReaderView (line 56) | public MuPDFReaderView(Context context) {
method MuPDFReaderView (line 62) | public MuPDFReaderView(Context context, AttributeSet attrs)
method onSingleTapUp (line 69) | public boolean onSingleTapUp(MotionEvent e) {
method onDown (line 114) | @Override
method onScroll (line 120) | public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
method onFling (line 138) | @Override
method onScaleBegin (line 149) | public boolean onScaleBegin(ScaleGestureDetector d) {
method onTouchEvent (line 157) | public boolean onTouchEvent(MotionEvent event) {
method touch_start (line 189) | private void touch_start(float x, float y) {
method touch_move (line 200) | private void touch_move(float x, float y) {
method touch_up (line 216) | private void touch_up() {
method onChildSetup (line 221) | protected void onChildSetup(int i, View v) {
method onMoveToChild (line 242) | protected void onMoveToChild(int i) {
method onMoveOffChild (line 250) | @Override
method onSettle (line 257) | protected void onSettle(View v) {
method onUnsettle (line 263) | protected void onUnsettle(View v) {
method onNotInUse (line 269) | @Override
method onScaleChild (line 274) | @Override
FILE: src/main/java/com/artifex/mupdfdemo/MuPDFReflowAdapter.java
class MuPDFReflowAdapter (line 10) | public class MuPDFReflowAdapter extends BaseAdapter {
method MuPDFReflowAdapter (line 14) | public MuPDFReflowAdapter(Context c, MuPDFCore core) {
method getCount (line 19) | public int getCount() {
method getItem (line 23) | public Object getItem(int arg0) {
method getItemId (line 27) | public long getItemId(int arg0) {
method getView (line 31) | public View getView(int position, View convertView, ViewGroup parent) {
FILE: src/main/java/com/artifex/mupdfdemo/MuPDFReflowView.java
class MuPDFReflowView (line 14) | public class MuPDFReflowView extends WebView implements MuPDFView {
method MuPDFReflowView (line 23) | public MuPDFReflowView(Context c, MuPDFCore core, Point parentSize) {
method requestHeight (line 49) | private void requestHeight() {
method setPage (line 55) | public void setPage(int page, PointF size) {
method getPage (line 74) | public int getPage() {
method setScale (line 78) | public void setScale(float scale) {
method blank (line 84) | public void blank(int page) {
method passClickEvent (line 87) | public Hit passClickEvent(float x, float y) {
method hitLink (line 91) | public LinkInfo hitLink(float x, float y) {
method selectText (line 95) | public void selectText(float x0, float y0, float x1, float y1) {
method deselectText (line 98) | public void deselectText() {
method copySelection (line 101) | public boolean copySelection() {
method markupSelection (line 105) | public boolean markupSelection(Annotation.Type type) {
method startDraw (line 109) | public void startDraw(float x, float y) {
method continueDraw (line 112) | public void continueDraw(float x, float y) {
method cancelDraw (line 115) | public void cancelDraw() {
method saveDraw (line 118) | public boolean saveDraw() {
method setSearchBoxes (line 122) | public void setSearchBoxes(RectF[] searchBoxes) {
method setLinkHighlighting (line 125) | public void setLinkHighlighting(boolean f) {
method deleteSelectedAnnotation (line 128) | public void deleteSelectedAnnotation() {
method deselectAnnotation (line 131) | public void deselectAnnotation() {
method setChangeReporter (line 134) | public void setChangeReporter(Runnable reporter) {
method update (line 137) | public void update() {
method updateHq (line 140) | public void updateHq(boolean update) {
method removeHq (line 143) | public void removeHq() {
method releaseResources (line 146) | public void releaseResources() {
method releaseBitmaps (line 153) | public void releaseBitmaps() {
method onMeasure (line 156) | @Override
method onTouchEvent (line 177) | @Override
FILE: src/main/java/com/artifex/mupdfdemo/MuPDFView.java
type Hit (line 6) | enum Hit {Nothing, Widget, Annotation}
type MuPDFView (line 8) | public interface MuPDFView {
method setPage (line 9) | public void setPage(int page, PointF size);
method setScale (line 10) | public void setScale(float scale);
method getPage (line 11) | public int getPage();
method blank (line 12) | public void blank(int page);
method passClickEvent (line 13) | public Hit passClickEvent(float x, float y);
method hitLink (line 14) | public LinkInfo hitLink(float x, float y);
method selectText (line 15) | public void selectText(float x0, float y0, float x1, float y1);
method deselectText (line 16) | public void deselectText();
method copySelection (line 17) | public boolean copySelection();
method markupSelection (line 18) | public boolean markupSelection(Annotation.Type type);
method deleteSelectedAnnotation (line 19) | public void deleteSelectedAnnotation();
method setSearchBoxes (line 20) | public void setSearchBoxes(RectF searchBoxes[]);
method setLinkHighlighting (line 21) | public void setLinkHighlighting(boolean f);
method deselectAnnotation (line 22) | public void deselectAnnotation();
method startDraw (line 23) | public void startDraw(float x, float y);
method continueDraw (line 24) | public void continueDraw(float x, float y);
method cancelDraw (line 25) | public void cancelDraw();
method saveDraw (line 26) | public boolean saveDraw();
method setChangeReporter (line 27) | public void setChangeReporter(Runnable reporter);
method update (line 28) | public void update();
method updateHq (line 29) | public void updateHq(boolean update);
method removeHq (line 30) | public void removeHq();
method releaseResources (line 31) | public void releaseResources();
method releaseBitmaps (line 32) | public void releaseBitmaps();
FILE: src/main/java/com/artifex/mupdfdemo/OutlineActivity.java
class OutlineActivity (line 8) | public class OutlineActivity extends ListActivity {
method onCreate (line 12) | @Override
method onListItemClick (line 24) | @Override
FILE: src/main/java/com/artifex/mupdfdemo/OutlineActivityData.java
class OutlineActivityData (line 3) | public class OutlineActivityData {
method set (line 8) | static public void set(OutlineActivityData d) {
method get (line 12) | static public OutlineActivityData get() {
FILE: src/main/java/com/artifex/mupdfdemo/OutlineAdapter.java
class OutlineAdapter (line 9) | public class OutlineAdapter extends BaseAdapter {
method OutlineAdapter (line 12) | public OutlineAdapter(LayoutInflater inflater, OutlineItem items[]) {
method getCount (line 17) | public int getCount() {
method getItem (line 21) | public Object getItem(int arg0) {
method getItemId (line 25) | public long getItemId(int arg0) {
method getView (line 29) | public View getView(int position, View convertView, ViewGroup parent) {
FILE: src/main/java/com/artifex/mupdfdemo/OutlineItem.java
class OutlineItem (line 3) | public class OutlineItem {
method OutlineItem (line 8) | OutlineItem(int _level, String _title, int _page) {
FILE: src/main/java/com/artifex/mupdfdemo/PageView.java
class OpaqueImageView (line 30) | class OpaqueImageView extends ImageView {
method OpaqueImageView (line 32) | public OpaqueImageView(Context context) {
method isOpaque (line 36) | @Override
type TextProcessor (line 42) | interface TextProcessor {
method onStartLine (line 43) | void onStartLine();
method onWord (line 45) | void onWord(TextWord word);
method onEndLine (line 47) | void onEndLine();
class TextSelector (line 50) | class TextSelector {
method TextSelector (line 54) | public TextSelector(TextWord[][] text, RectF selectBox) {
method select (line 59) | public void select(TextProcessor tp) {
class PageView (line 96) | public abstract class PageView extends ViewGroup {
method PageView (line 153) | public PageView(Context c, Point parentSize, MuPDFPageAdapter adapter) {
method getDrawPageTask (line 163) | protected abstract CancellableTaskDefinition<Void, Void> getDrawPageTa...
method getUpdatePageTask (line 165) | protected abstract CancellableTaskDefinition<Void, Void> getUpdatePage...
method getLinkInfo (line 167) | protected abstract LinkInfo[] getLinkInfo();
method getText (line 169) | protected abstract TextWord[][] getText();
method addMarkup (line 171) | protected abstract void addMarkup(PointF[] quadPoints, Annotation.Type...
method reinit (line 173) | private void reinit() {
method releaseResources (line 221) | public void releaseResources() {
method releaseBitmaps (line 232) | public void releaseBitmaps() {
method blank (line 251) | public void blank(int page) {
method setPage (line 265) | public void setPage(int page, PointF size) {
method updateEntireCanvas (line 420) | public void updateEntireCanvas(final boolean updateZoomed) {
method setSearchBoxes (line 478) | public void setSearchBoxes(RectF searchBoxes[]) {
method setLinkHighlighting (line 484) | public void setLinkHighlighting(boolean f) {
method deselectText (line 490) | public void deselectText() {
method selectText (line 495) | public void selectText(float x0, float y0, float x1, float y1) {
method startDraw (line 529) | public void startDraw(float x, float y) {
method continueDraw (line 543) | public void continueDraw(float x, float y) {
method cancelDraw (line 556) | public void cancelDraw() {
method getDraw (line 562) | protected PointF[][] getDraw() {
method processSelectedText (line 576) | protected void processSelectedText(TextProcessor tp) {
method setItemSelectBox (line 580) | public void setItemSelectBox(RectF rect) {
method onMeasure (line 586) | @Override
method onLayout (line 612) | @Override
method updateHq (line 653) | public void updateHq(boolean update) {
method update (line 762) | public void update() {
method removeHq (line 798) | public void removeHq() {
method getPage (line 815) | public int getPage() {
method isOpaque (line 819) | @Override
method redrawEntireBitmaps (line 824) | protected void redrawEntireBitmaps() {
method redrawZoomedBitmaps (line 833) | private void redrawZoomedBitmaps() {
method removeBitmapOnPosition (line 843) | public boolean removeBitmapOnPosition(Point point) {
method onLongPress (line 862) | public void onLongPress(MotionEvent e, float mScale) {
method onSingleTap (line 883) | public void onSingleTap(MotionEvent e, float mScale) {
method translateCoords (line 904) | private float[] translateCoords(float mScale, float x, float y) {
method pdfCoordsToScreen (line 930) | private float[] pdfCoordsToScreen(float pdfX, float pdfY) {
method onDoubleTap (line 936) | public boolean onDoubleTap(MotionEvent e, float mScale) {
method removeIfExistSign (line 994) | private int removeIfExistSign(Point screenPoint) {
method onDraw (line 1038) | @Override
method correctBugMuPdf (line 1049) | private PointF correctBugMuPdf(PointF size) {
method getEventCallback (line 1053) | public DigitalizedEventCallback getEventCallback() {
method setEventCallback (line 1057) | public void setEventCallback(DigitalizedEventCallback eventCallback) {
method drawBitmaps (line 1061) | private void drawBitmaps(Canvas canvas, Point patchViewSize, Rect patc...
method scaledSize (line 1120) | private float[] scaledSize(int width, int height) {
method setParentSize (line 1129) | public void setParentSize(Point parentSize) {
method isBitmapRecycled (line 1133) | public boolean isBitmapRecycled(Bitmap bitmap) {
method recycleBitmap (line 1141) | public void recycleBitmap(Bitmap bitmap) {
FILE: src/main/java/com/artifex/mupdfdemo/PrintDialogActivity.java
class PrintDialogActivity (line 16) | public class PrintDialogActivity extends Activity {
method onCreate (line 42) | @Override
method onActivityResult (line 61) | @Override
class PrintDialogJavaScriptInterface (line 68) | final class PrintDialogJavaScriptInterface {
method getType (line 69) | public String getType() {
method getTitle (line 73) | public String getTitle() {
method getContent (line 77) | public String getContent() {
method getEncoding (line 102) | public String getEncoding() {
method onPostMessage (line 106) | public void onPostMessage(String message) {
class PrintDialogWebClient (line 114) | private final class PrintDialogWebClient extends WebViewClient {
method shouldOverrideUrlLoading (line 115) | @Override
method onPageFinished (line 131) | @Override
FILE: src/main/java/com/artifex/mupdfdemo/ReaderView.java
class ReaderView (line 26) | public class ReaderView
class ViewMapper (line 76) | static abstract class ViewMapper {
method applyToView (line 77) | abstract void applyToView(View view);
method ReaderView (line 80) | public ReaderView(Context context) {
method ReaderView (line 88) | public ReaderView(Context context, AttributeSet attrs) {
method ReaderView (line 109) | public ReaderView(Context context, AttributeSet attrs, int defStyle) {
method getDisplayedViewIndex (line 117) | public int getDisplayedViewIndex() {
method setDisplayedViewIndex (line 121) | public void setDisplayedViewIndex(int i) {
method moveToNext (line 131) | public void moveToNext() {
method moveToPrevious (line 137) | public void moveToPrevious() {
method smartAdvanceAmount (line 147) | private int smartAdvanceAmount(int screenHeight, int max) {
method smartMoveForwards (line 168) | public void smartMoveForwards() {
method smartMoveBackwards (line 241) | public void smartMoveBackwards() {
method resetupChildren (line 313) | public void resetupChildren() {
method applyToChildren (line 318) | public void applyToChildren(ViewMapper mapper) {
method refresh (line 323) | public void refresh(boolean reflow) {
method onChildSetup (line 334) | protected void onChildSetup(int i, View v) {}
method onMoveToChild (line 336) | protected void onMoveToChild(int i) {}
method onMoveOffChild (line 338) | protected void onMoveOffChild(int i) {}
method onSettle (line 340) | protected void onSettle(View v) {}
method onUnsettle (line 342) | protected void onUnsettle(View v) {}
method onNotInUse (line 344) | protected void onNotInUse(View v) {
method onScaleChild (line 348) | protected void onScaleChild(View v, Float scale) {}
method getView (line 350) | public View getView(int i) {
method getDisplayedView (line 354) | public View getDisplayedView() {
method run (line 358) | public void run() {
method onDown (line 379) | public boolean onDown(MotionEvent arg0) {
method onFling (line 384) | public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
method onScroll (line 461) | public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
method onShowPress (line 471) | public void onShowPress(MotionEvent e) {
method onSingleTapUp (line 474) | public boolean onSingleTapUp(MotionEvent e) {
method onScale (line 478) | public boolean onScale(ScaleGestureDetector detector) {
method onScaleBegin (line 506) | public boolean onScaleBegin(ScaleGestureDetector detector) {
method onScaleEnd (line 515) | public void onScaleEnd(ScaleGestureDetector detector) {
method onTouchEvent (line 527) | @Override
method processTouchEvent (line 552) | private void processTouchEvent(MotionEvent event, boolean withRefresh) {
method onMeasure (line 582) | @Override
method onLayout (line 591) | @Override
method getAdapter (line 771) | @Override
method getSelectedView (line 776) | @Override
method setAdapter (line 781) | @Override
method setSelection (line 788) | @Override
method getCached (line 793) | private View getCached() {
method getOrCreateChild (line 800) | private View getOrCreateChild(int i) {
method addAndMeasureChild (line 812) | private void addAndMeasureChild(int i, View v) {
method measureView (line 822) | private void measureView(View v) {
method getScrollBounds (line 840) | private Rect getScrollBounds(int left, int top, int right, int bottom) {
method getScrollBounds (line 854) | private Rect getScrollBounds(View v) {
method getCorrection (line 864) | private Point getCorrection(Rect bounds) {
method postSettle (line 869) | private void postSettle(final View v) {
method postUnsettle (line 880) | private void postUnsettle(final View v) {
method slideViewOntoScreen (line 888) | private void slideViewOntoScreen(View v) {
method subScreenSizeOffset (line 897) | private Point subScreenSizeOffset(View v) {
method directionOfTravel (line 902) | private static int directionOfTravel(float vx, float vy) {
method withinBoundsInDirectionOfTravel (line 911) | private static boolean withinBoundsInDirectionOfTravel(Rect bounds, fl...
method addBitmap (line 924) | public void addBitmap(PdfBitmap pdfBitmap) {
method setPdfBitmapList (line 933) | public void setPdfBitmapList(Collection<PdfBitmap> pdfBitmaps) {
method getBitmapList (line 940) | public Collection<PdfBitmap> getBitmapList() {
method removeBitmapOnPosition (line 948) | public boolean removeBitmapOnPosition(Point point) {
method refreshView (line 956) | public void refreshView(){
method updateCurrentPage (line 975) | public void updateCurrentPage() {
method redrawAll (line 983) | public void redrawAll() {
method redrawPage (line 995) | private void redrawPage(PageView pageView) {
method onDoubleTap (line 1002) | @Override
method onLongPress (line 1011) | @Override
method onDoubleTapEvent (line 1018) | @Override
method onSingleTapConfirmed (line 1023) | @Override
method getEventCallback (line 1031) | public DigitalizedEventCallback getEventCallback() {
method setEventCallback (line 1039) | public void setEventCallback(DigitalizedEventCallback eventCallback) {
FILE: src/main/java/com/artifex/mupdfdemo/SafeAnimatorInflater.java
class SafeAnimatorInflater (line 9) | public class SafeAnimatorInflater
method SafeAnimatorInflater (line 13) | public SafeAnimatorInflater(Activity activity, int animation, View view)
FILE: src/main/java/com/artifex/mupdfdemo/SearchTask.java
class ProgressDialogX (line 10) | class ProgressDialogX extends ProgressDialog {
method ProgressDialogX (line 11) | public ProgressDialogX(Context context) {
method isCancelled (line 17) | public boolean isCancelled() {
method cancel (line 21) | @Override
class SearchTask (line 28) | public abstract class SearchTask {
method SearchTask (line 36) | public SearchTask(Context context, MuPDFCore core) {
method onTextFound (line 43) | protected abstract void onTextFound(SearchTaskResult result);
method stop (line 45) | public void stop() {
method go (line 52) | public void go(final String text, int direction, int displayPage, int ...
FILE: src/main/java/com/artifex/mupdfdemo/SearchTaskResult.java
class SearchTaskResult (line 5) | public class SearchTaskResult {
method SearchTaskResult (line 11) | SearchTaskResult(String _txt, int _pageNumber, RectF _searchBoxes[]) {
method get (line 17) | static public SearchTaskResult get() {
method set (line 21) | static public void set(SearchTaskResult r) {
FILE: src/main/java/com/artifex/mupdfdemo/Stepper.java
class Stepper (line 7) | public class Stepper {
method Stepper (line 12) | public Stepper(View v, Runnable r) {
method prod (line 18) | @SuppressLint("NewApi")
FILE: src/main/java/com/artifex/mupdfdemo/TextChar.java
class TextChar (line 5) | public class TextChar extends RectF {
method TextChar (line 8) | public TextChar(float x0, float y0, float x1, float y1, char _c) {
FILE: src/main/java/com/artifex/mupdfdemo/TextWord.java
class TextWord (line 5) | public class TextWord extends RectF {
method TextWord (line 8) | public TextWord() {
method Add (line 13) | public void Add(TextChar tc) {
FILE: src/main/java/com/artifex/mupdfdemo/WidgetType.java
type WidgetType (line 3) | public enum WidgetType {
FILE: src/main/java/com/artifex/utils/DigitalizedEventCallback.java
type DigitalizedEventCallback (line 6) | public interface DigitalizedEventCallback {
method longPressOnPdfPosition (line 11) | public void longPressOnPdfPosition(int page, float viewX, float viewY,...
method doubleTapOnPdfPosition (line 12) | public void doubleTapOnPdfPosition(int page, float viewX, float viewY,...
method singleTapOnPdfPosition (line 13) | public void singleTapOnPdfPosition(int page, float viewX, float viewY,...
method pageChanged (line 14) | public void pageChanged(int page);
method error (line 15) | public void error(String message);
FILE: src/main/java/com/artifex/utils/PdfBitmap.java
class PdfBitmap (line 11) | public class PdfBitmap implements Parcelable {
type Type (line 13) | public enum Type {
method PdfBitmap (line 38) | public PdfBitmap(Bitmap image, int width, int height, int pdfX, int pd...
method PdfBitmap (line 50) | public PdfBitmap(Parcel in) {
method getBitmapImage (line 67) | public Bitmap getBitmapImage() {
method getWidth (line 71) | public int getWidth() {
method getHeight (line 75) | public int getHeight() {
method getPageNumber (line 79) | public int getPageNumber() {
method describeContents (line 83) | @Override
method writeToParcel (line 88) | @Override
method createFromParcel (line 102) | public PdfBitmap createFromParcel(Parcel in) {
method newArray (line 105) | public PdfBitmap[] newArray(int size) {
method getPdfX (line 110) | public int getPdfX() {
method getPdfY (line 114) | public int getPdfY() {
method getType (line 118) | public Type getType() {
method setType (line 122) | public void setType(Type type) {
method isRemovable (line 126) | public boolean isRemovable() {
method setIsRemovable (line 130) | public void setIsRemovable(boolean isRemovable) {
method getMetadata (line 134) | public HashMap<String, String> getMetadata() {
method setMetadata (line 138) | public void setMetadata(HashMap<String, String> metadata) {
method toString (line 142) | @Override
method equals (line 148) | @Override
Condensed preview — 100 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (548K chars).
[
{
"path": ".gitignore",
"chars": 93,
"preview": ".gradle\n/local.properties\n/.idea/workspace.xml\n/.idea/libraries\n.DS_Store\n/build\n/*.iml\n*.iml"
},
{
"path": "COPYING",
"chars": 34502,
"preview": " GNU AFFERO GENERAL PUBLIC LICENSE\n Version 3, 19 November 2007\n\n Copyright (C) 2007 Free Softwar"
},
{
"path": "LICENSE",
"chars": 34501,
"preview": "GNU AFFERO GENERAL PUBLIC LICENSE\n Version 3, 19 November 2007\n\n Copyright (C) 2007 Free Software "
},
{
"path": "README.md",
"chars": 910,
"preview": "# MuPDF for Android \n\n## Introduction\nThis project is intended to offer an easy integration of MuPDF library (http://www"
},
{
"path": "build.gradle",
"chars": 1651,
"preview": "repositories {\n google()\n mavenCentral()\n jcenter()\n maven { url \"https://repositorio.viavansi.com/repo/\" }\n"
},
{
"path": "gradle.properties",
"chars": 1003,
"preview": "# Project-wide Gradle settings.\n\n# IDE (e.g. Android Studio) users:\n# Settings specified in this file will override any "
},
{
"path": "proguard-rules.pro",
"chars": 663,
"preview": "# Add project specific ProGuard rules here.\n# By default, the flags in this file are appended to flags specified\n# in /A"
},
{
"path": "src/androidTest/java/com/artifex/viafirma/mupdf/ApplicationTest.java",
"chars": 357,
"preview": "package com.artifex.viafirma.mupdf;\n\nimport android.app.Application;\nimport android.test.ApplicationTestCase;\n\n/**\n * <a"
},
{
"path": "src/main/AndroidManifest.xml",
"chars": 597,
"preview": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n package=\"com.artifex.mupdfdemo\"\n android:ins"
},
{
"path": "src/main/java/com/artifex/mupdfdemo/Annotation.java",
"chars": 539,
"preview": "package com.artifex.mupdfdemo;\n\nimport android.graphics.RectF;\n\npublic class Annotation extends RectF {\n\tenum Type {\n\t\tT"
},
{
"path": "src/main/java/com/artifex/mupdfdemo/ArrayDeque.java",
"chars": 29348,
"preview": "/*\n * Written by Josh Bloch of Google Inc. and released to the public domain,\n * as explained at http://creativecommons."
},
{
"path": "src/main/java/com/artifex/mupdfdemo/AsyncTask.java",
"chars": 26858,
"preview": "/*\n * Copyright (C) 2008 The Android Open Source Project\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lice"
},
{
"path": "src/main/java/com/artifex/mupdfdemo/CancellableAsyncTask.java",
"chars": 1588,
"preview": "package com.artifex.mupdfdemo;\n\nimport java.util.concurrent.CancellationException;\nimport java.util.concurrent.Execution"
},
{
"path": "src/main/java/com/artifex/mupdfdemo/CancellableTaskDefinition.java",
"chars": 196,
"preview": "package com.artifex.mupdfdemo;\n\npublic interface CancellableTaskDefinition <Params, Result>\n{\n\tpublic Result doInBackgro"
},
{
"path": "src/main/java/com/artifex/mupdfdemo/ChoosePDFActivity.java",
"chars": 6341,
"preview": "package com.artifex.mupdfdemo;\n\nimport java.io.File;\nimport java.io.FileFilter;\nimport java.util.Arrays;\nimport java.uti"
},
{
"path": "src/main/java/com/artifex/mupdfdemo/ChoosePDFAdapter.java",
"chars": 1555,
"preview": "package com.artifex.mupdfdemo;\n\nimport java.util.LinkedList;\n\nimport android.graphics.Color;\nimport android.view.LayoutI"
},
{
"path": "src/main/java/com/artifex/mupdfdemo/ChoosePDFItem.java",
"chars": 222,
"preview": "package com.artifex.mupdfdemo;\n\npublic class ChoosePDFItem {\n\tenum Type {\n\t\tPARENT, DIR, DOC\n\t}\n\n\tfinal public Type type"
},
{
"path": "src/main/java/com/artifex/mupdfdemo/Deque.java",
"chars": 22401,
"preview": "/*\n * Written by Doug Lea and Josh Bloch with assistance from members of\n * JCP JSR-166 Expert Group and released to the"
},
{
"path": "src/main/java/com/artifex/mupdfdemo/FilePicker.java",
"chars": 372,
"preview": "package com.artifex.mupdfdemo;\n\nimport android.net.Uri;\n\npublic abstract class FilePicker {\n\tpublic interface FilePicker"
},
{
"path": "src/main/java/com/artifex/mupdfdemo/LinkInfo.java",
"chars": 265,
"preview": "package com.artifex.mupdfdemo;\n\nimport android.graphics.RectF;\n\npublic class LinkInfo {\n\tfinal public RectF rect;\n\n\tpubl"
},
{
"path": "src/main/java/com/artifex/mupdfdemo/LinkInfoExternal.java",
"chars": 307,
"preview": "package com.artifex.mupdfdemo;\n\npublic class LinkInfoExternal extends LinkInfo {\n\tfinal public String url;\n\n\tpublic Link"
},
{
"path": "src/main/java/com/artifex/mupdfdemo/LinkInfoInternal.java",
"chars": 315,
"preview": "package com.artifex.mupdfdemo;\n\npublic class LinkInfoInternal extends LinkInfo {\n\tfinal public int pageNumber;\n\n\tpublic "
},
{
"path": "src/main/java/com/artifex/mupdfdemo/LinkInfoRemote.java",
"chars": 427,
"preview": "package com.artifex.mupdfdemo;\n\npublic class LinkInfoRemote extends LinkInfo {\n\tfinal public String fileSpec;\n\tfinal pub"
},
{
"path": "src/main/java/com/artifex/mupdfdemo/LinkInfoVisitor.java",
"chars": 244,
"preview": "package com.artifex.mupdfdemo;\n\nabstract public class LinkInfoVisitor {\n\tpublic abstract void visitInternal(LinkInfoInte"
},
{
"path": "src/main/java/com/artifex/mupdfdemo/MuPDFActivity.java",
"chars": 34724,
"preview": "package com.artifex.mupdfdemo;\n\nimport java.io.InputStream;\nimport java.util.concurrent.Executor;\n\nimport com.artifex.mu"
},
{
"path": "src/main/java/com/artifex/mupdfdemo/MuPDFAlert.java",
"chars": 675,
"preview": "package com.artifex.mupdfdemo;\n\npublic class MuPDFAlert {\n\tpublic enum IconType {Error,Warning,Question,Status};\n\tpublic"
},
{
"path": "src/main/java/com/artifex/mupdfdemo/MuPDFAlertInternal.java",
"chars": 972,
"preview": "package com.artifex.mupdfdemo;\n\n// Version of MuPDFAlert without enums to simplify JNI\npublic class MuPDFAlertInternal {"
},
{
"path": "src/main/java/com/artifex/mupdfdemo/MuPDFCancellableTaskDefinition.java",
"chars": 696,
"preview": "package com.artifex.mupdfdemo;\n\npublic abstract class MuPDFCancellableTaskDefinition<Params, Result> implements Cancella"
},
{
"path": "src/main/java/com/artifex/mupdfdemo/MuPDFCore.java",
"chars": 9668,
"preview": "package com.artifex.mupdfdemo;\nimport java.util.ArrayList;\n\nimport android.content.Context;\nimport android.graphics.Bitm"
},
{
"path": "src/main/java/com/artifex/mupdfdemo/MuPDFFragment.java",
"chars": 41828,
"preview": "package com.artifex.mupdfdemo;\n\nimport java.io.InputStream;\nimport java.util.Collection;\nimport java.util.HashSet;\nimpor"
},
{
"path": "src/main/java/com/artifex/mupdfdemo/MuPDFPageAdapter.java",
"chars": 3771,
"preview": "package com.artifex.mupdfdemo;\n\nimport android.content.Context;\nimport android.graphics.Point;\nimport android.graphics.P"
},
{
"path": "src/main/java/com/artifex/mupdfdemo/MuPDFPageView.java",
"chars": 18804,
"preview": "package com.artifex.mupdfdemo;\n\nimport java.util.ArrayList;\n\nimport com.artifex.mupdfdemo.MuPDFCore.Cookie;\n\nimport andr"
},
{
"path": "src/main/java/com/artifex/mupdfdemo/MuPDFReaderView.java",
"chars": 6958,
"preview": "package com.artifex.mupdfdemo;\n\nimport android.app.Activity;\nimport android.content.Context;\nimport android.content.Inte"
},
{
"path": "src/main/java/com/artifex/mupdfdemo/MuPDFReflowAdapter.java",
"chars": 973,
"preview": "package com.artifex.mupdfdemo;\n\nimport android.content.Context;\nimport android.graphics.Point;\nimport android.graphics.P"
},
{
"path": "src/main/java/com/artifex/mupdfdemo/MuPDFReflowView.java",
"chars": 3997,
"preview": "package com.artifex.mupdfdemo;\n\nimport android.content.Context;\nimport android.graphics.Point;\nimport android.graphics.P"
},
{
"path": "src/main/java/com/artifex/mupdfdemo/MuPDFView.java",
"chars": 1089,
"preview": "package com.artifex.mupdfdemo;\n\nimport android.graphics.PointF;\nimport android.graphics.RectF;\n\nenum Hit {Nothing, Widge"
},
{
"path": "src/main/java/com/artifex/mupdfdemo/OutlineActivity.java",
"chars": 938,
"preview": "package com.artifex.mupdfdemo;\n\nimport android.app.ListActivity;\nimport android.os.Bundle;\nimport android.view.View;\nimp"
},
{
"path": "src/main/java/com/artifex/mupdfdemo/OutlineActivityData.java",
"chars": 379,
"preview": "package com.artifex.mupdfdemo;\n\npublic class OutlineActivityData {\n\tpublic OutlineItem items[];\n\tpublic int posi"
},
{
"path": "src/main/java/com/artifex/mupdfdemo/OutlineAdapter.java",
"chars": 1128,
"preview": "package com.artifex.mupdfdemo;\n\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.view.ViewGr"
},
{
"path": "src/main/java/com/artifex/mupdfdemo/OutlineItem.java",
"chars": 255,
"preview": "package com.artifex.mupdfdemo;\n\npublic class OutlineItem {\n\tpublic final int level;\n\tpublic final String title;\n\tpubl"
},
{
"path": "src/main/java/com/artifex/mupdfdemo/PageView.java",
"chars": 42239,
"preview": "package com.artifex.mupdfdemo;\n\nimport android.content.Context;\nimport android.graphics.Bitmap;\nimport android.graphics."
},
{
"path": "src/main/java/com/artifex/mupdfdemo/PrintDialogActivity.java",
"chars": 4202,
"preview": "package com.artifex.mupdfdemo;\n\nimport java.io.ByteArrayOutputStream;\nimport java.io.InputStream;\n\nimport android.app.Ac"
},
{
"path": "src/main/java/com/artifex/mupdfdemo/ReaderView.java",
"chars": 32938,
"preview": "package com.artifex.mupdfdemo;\n\nimport android.content.Context;\nimport android.graphics.Point;\nimport android.graphics.R"
},
{
"path": "src/main/java/com/artifex/mupdfdemo/SafeAnimatorInflater.java",
"chars": 867,
"preview": "package com.artifex.mupdfdemo;\n\nimport android.animation.Animator;\nimport android.animation.AnimatorInflater;\nimport and"
},
{
"path": "src/main/java/com/artifex/mupdfdemo/SearchTask.java",
"chars": 3396,
"preview": "package com.artifex.mupdfdemo;\n\nimport android.app.AlertDialog;\nimport android.app.ProgressDialog;\nimport android.conten"
},
{
"path": "src/main/java/com/artifex/mupdfdemo/SearchTaskResult.java",
"chars": 514,
"preview": "package com.artifex.mupdfdemo;\n\nimport android.graphics.RectF;\n\npublic class SearchTaskResult {\n\tpublic final String txt"
},
{
"path": "src/main/java/com/artifex/mupdfdemo/Stepper.java",
"chars": 785,
"preview": "package com.artifex.mupdfdemo;\n\nimport android.annotation.SuppressLint;\nimport android.os.Build;\nimport android.view.Vie"
},
{
"path": "src/main/java/com/artifex/mupdfdemo/TextChar.java",
"chars": 227,
"preview": "package com.artifex.mupdfdemo;\n\nimport android.graphics.RectF;\n\npublic class TextChar extends RectF {\n\tpublic char c;\n\n\t"
},
{
"path": "src/main/java/com/artifex/mupdfdemo/TextWord.java",
"chars": 279,
"preview": "package com.artifex.mupdfdemo;\n\nimport android.graphics.RectF;\n\npublic class TextWord extends RectF {\n\tpublic String w;\n"
},
{
"path": "src/main/java/com/artifex/mupdfdemo/WidgetType.java",
"chars": 105,
"preview": "package com.artifex.mupdfdemo;\n\npublic enum WidgetType {\n\tNONE,\n\tTEXT,\n\tLISTBOX,\n\tCOMBOBOX,\n\tSIGNATURE\n}\n"
},
{
"path": "src/main/java/com/artifex/utils/DigitalizedEventCallback.java",
"chars": 662,
"preview": "package com.artifex.utils;\n\n/**\n * Created by @elage on 6/2/15.\n */\npublic interface DigitalizedEventCallback {\n\n pub"
},
{
"path": "src/main/java/com/artifex/utils/PdfBitmap.java",
"chars": 4221,
"preview": "package com.artifex.utils;\n\nimport android.graphics.Bitmap;\nimport android.os.Parcel;\nimport android.os.Parcelable;\nimpo"
},
{
"path": "src/main/res/animator/info.xml",
"chars": 474,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<set xmlns:android=\"http://schemas.android.com/apk/res/android\"\n\tandroid:ordering"
},
{
"path": "src/main/res/drawable/busy.xml",
"chars": 327,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<shape xmlns:android=\"http://schemas.android.com/apk/res/android\"\n\tandroid:shape="
},
{
"path": "src/main/res/drawable/button.xml",
"chars": 796,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\n<selector xmlns:android=\"http://schemas.android.com/apk/res/android\">\n\t<item and"
},
{
"path": "src/main/res/drawable/page_num.xml",
"chars": 288,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<shape xmlns:android=\"http://schemas.android.com/apk/res/android\"\n\tandroid:shape="
},
{
"path": "src/main/res/drawable/search.xml",
"chars": 1028,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\n<selector xmlns:android=\"http://schemas.android.com/apk/res/android\">\n\t<item and"
},
{
"path": "src/main/res/drawable/seek_progress.xml",
"chars": 208,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\n<shape xmlns:android=\"http://schemas.android.com/apk/res/android\"\n\tandroid:shape"
},
{
"path": "src/main/res/drawable/seek_thumb.xml",
"chars": 237,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\n<shape xmlns:android=\"http://schemas.android.com/apk/res/android\"\n\tandroid:shape"
},
{
"path": "src/main/res/drawable/tiled_background.xml",
"chars": 172,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<bitmap xmlns:android=\"http://schemas.android.com/apk/res/android\"\n\tandroid:src=\""
},
{
"path": "src/main/res/layout/buttons.xml",
"chars": 13097,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\n<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n\tandr"
},
{
"path": "src/main/res/layout/main.xml",
"chars": 220,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n\tandroid"
},
{
"path": "src/main/res/layout/outline_entry.xml",
"chars": 898,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n\tandro"
},
{
"path": "src/main/res/layout/picker_entry.xml",
"chars": 767,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n\tandro"
},
{
"path": "src/main/res/layout/print_dialog.xml",
"chars": 320,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\n<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n\tandr"
},
{
"path": "src/main/res/layout/textentry.xml",
"chars": 282,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<EditText xmlns:android=\"http://schemas.android.com/apk/res/android\"\n\tandroid:sin"
},
{
"path": "src/main/res/values/colors.xml",
"chars": 660,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n\t<color name=\"canvas\">#404040</color>\n\t<color name=\"toolbar\">#C000000"
},
{
"path": "src/main/res/values/strings.xml",
"chars": 3358,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n\t<string name=\"mupdf_title\">MuPDF</string>\n\t<string name=\"version\">1."
},
{
"path": "src/main/res/values/styles.xml",
"chars": 201,
"preview": "<resources>\n <style name=\"AppBaseTheme\" parent=\"@android:style/Theme.NoTitleBar.Fullscreen\">\n <item name=\"andr"
},
{
"path": "src/main/res/values-ar/strings.xml",
"chars": 2841,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n\t<string name=\"accept\">قبول</string>\n\t<string name=\"mupdf_title\">MuPD"
},
{
"path": "src/main/res/values-ca/strings.xml",
"chars": 2991,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n\t<string name=\"accept\">Acceptar</string>\n\t<string name=\"mupdf_title\">"
},
{
"path": "src/main/res/values-cs/strings.xml",
"chars": 2917,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n\t<string name=\"accept\">Přijmout</string>\n\t<string name=\"mupdf_title\">"
},
{
"path": "src/main/res/values-da/strings.xml",
"chars": 2936,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n\t<string name=\"accept\">Accepter</string>\n\t<string name=\"mupdf_title\">"
},
{
"path": "src/main/res/values-de/strings.xml",
"chars": 3137,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n\t<string name=\"accept\">Akzeptieren</string>\n\t<string name=\"mupdf_titl"
},
{
"path": "src/main/res/values-el/strings.xml",
"chars": 3201,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n\t<string name=\"accept\">Αποδοχή</string>\n\t<string name=\"mupdf_title\">M"
},
{
"path": "src/main/res/values-es/strings.xml",
"chars": 3395,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n\t<string name=\"accept\">Aceptar</string>\n\t<string name=\"mupdf_title\">M"
},
{
"path": "src/main/res/values-et/strings.xml",
"chars": 2961,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n\t<string name=\"accept\">Nõustu</string>\n\t<string name=\"mupdf_title\">Mu"
},
{
"path": "src/main/res/values-fi/strings.xml",
"chars": 2992,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n\t<string name=\"accept\">Hyväksy</string>\n\t<string name=\"mupdf_title\">M"
},
{
"path": "src/main/res/values-fr/strings.xml",
"chars": 3113,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n\t<string name=\"accept\">Accepter</string>\n\t<string name=\"mupdf_title\">"
},
{
"path": "src/main/res/values-hi/strings.xml",
"chars": 3006,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n\t<string name=\"accept\">स्वीकार करें</string>\n\t<string name=\"mupdf_tit"
},
{
"path": "src/main/res/values-hu/strings.xml",
"chars": 3060,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n\t<string name=\"accept\">Elfogadás</string>\n\t<string name=\"mupdf_title\""
},
{
"path": "src/main/res/values-in/strings.xml",
"chars": 2930,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n\t<string name=\"accept\">Terima</string>\n\t<string name=\"mupdf_title\">Mu"
},
{
"path": "src/main/res/values-it/strings.xml",
"chars": 3069,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n\t<string name=\"accept\">Accetta</string>\n\t<string name=\"mupdf_title\">M"
},
{
"path": "src/main/res/values-iw/strings.xml",
"chars": 2717,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n\t<string name=\"accept\">קבל</string>\n\t<string name=\"mupdf_title\">MuPDF"
},
{
"path": "src/main/res/values-ja/strings.xml",
"chars": 2596,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n\t<string name=\"accept\">承諾する</string>\n\t<string name=\"mupdf_title\">MuPD"
},
{
"path": "src/main/res/values-ko/strings.xml",
"chars": 2497,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n\t<string name=\"accept\">수락</string>\n\t<string name=\"mupdf_title\">MuPDF<"
},
{
"path": "src/main/res/values-lt/strings.xml",
"chars": 2994,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n\t<string name=\"accept\">Priimti</string>\n\t<string name=\"mupdf_title\">„"
},
{
"path": "src/main/res/values-ms/strings.xml",
"chars": 2983,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n\t<string name=\"accept\">Terima</string>\n\t<string name=\"mupdf_title\">Mu"
},
{
"path": "src/main/res/values-nl/strings.xml",
"chars": 3068,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n\t<string name=\"accept\">Accepteren</string>\n\t<string name=\"mupdf_title"
},
{
"path": "src/main/res/values-no/strings.xml",
"chars": 2951,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n\t<string name=\"accept\">Aksepter</string>\n\t<string name=\"mupdf_title\">"
},
{
"path": "src/main/res/values-pl/strings.xml",
"chars": 3027,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n\t<string name=\"accept\">Zaakceptuj</string>\n\t<string name=\"mupdf_title"
},
{
"path": "src/main/res/values-pt/strings.xml",
"chars": 3148,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n\t<string name=\"accept\">Aceitar</string>\n\t<string name=\"mupdf_title\">M"
},
{
"path": "src/main/res/values-ru/strings.xml",
"chars": 3045,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n\t<string name=\"accept\">Принять</string>\n\t<string name=\"mupdf_title\">M"
},
{
"path": "src/main/res/values-sk/strings.xml",
"chars": 2976,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n\t<string name=\"accept\">Prijať</string>\n\t<string name=\"mupdf_title\">Mu"
},
{
"path": "src/main/res/values-sv/strings.xml",
"chars": 2888,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n\t<string name=\"accept\">Acceptera</string>\n\t<string name=\"mupdf_title\""
},
{
"path": "src/main/res/values-th/strings.xml",
"chars": 2912,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n\t<string name=\"accept\">ยอมรับ</string>\n\t<string name=\"mupdf_title\">Mu"
},
{
"path": "src/main/res/values-tl/strings.xml",
"chars": 3143,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n\t<string name=\"accept\">Tanggapin</string>\n\t<string name=\"mupdf_title\""
},
{
"path": "src/main/res/values-tr/strings.xml",
"chars": 2966,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n\t<string name=\"accept\">Kabul et</string>\n\t<string name=\"mupdf_title\">"
},
{
"path": "src/main/res/values-zh/strings.xml",
"chars": 2394,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n\t<string name=\"accept\">接受</string>\n\t<string name=\"mupdf_title\">MuPDF<"
},
{
"path": "src/main/res/values-zh-rTW/strings.xml",
"chars": 2380,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n\t<string name=\"accept\">同意</string>\n\t<string name=\"mupdf_title\">MuPDF<"
}
]
About this extraction
This page contains the full source code of the viavansi/mupdf-android GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 100 files (485.5 KB), approximately 126.6k tokens, and a symbol index with 737 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.