/contrib/media/updf/android/AndroidManifest.xml |
---|
0,0 → 1,23 |
<?xml version="1.0" encoding="utf-8"?> |
<manifest xmlns:android="http://schemas.android.com/apk/res/android" |
package="com.artifex.mupdf" |
android:versionCode="1" |
android:versionName="1.0"> |
<supports-screens android:smallScreens="true" |
android:normalScreens="true" |
android:largeScreens="true" |
android:anyDensity="true" /> |
<uses-sdk android:minSdkVersion="8" /> |
<application android:label="@string/app_name" |
android:icon="@drawable/icon" |
android:debuggable="true"> |
<activity android:name="MuPDFActivity" |
android:label="@string/app_name" |
android:theme="@style/Theme.NoBackground.NoTitle"> |
<intent-filter> |
<action android:name="android.intent.action.MAIN" /> |
<category android:name="android.intent.category.LAUNCHER" /> |
</intent-filter> |
</activity> |
</application> |
</manifest> |
/contrib/media/updf/android/ReadMe.txt |
---|
0,0 → 1,111 |
To build/debug android build. |
1) Download the android sdk, and install it. On windows I unpacked it as: |
C:\Program Files\android-sdk-windows |
on Macos as: |
/Library/android-sdk-mac_x86 |
On windows add: C:/Progra~1/android-sdk-windows/tools to your path. |
On linux/macos add the equivalent. |
2) Download the android ndk, and install in. On windows I unpacked it as: |
C:\Program Files\android-ndk-r5 |
on Macos as: |
/Library/android-ndk-r5 |
On windows add: C:/Progra~1/android-ndk-r5 to your path. On linux/macos |
add the equivalent. |
3) On windows, to use the ndk, you *must* be running under cygwin. This means |
you need to install Cygwin 1.7 or greater now. |
In the current release of the ndk (r5), when running under cygwin, there are |
bugs to do with the automatic conversion of dependencies from DOS format |
paths to cygwin format paths. The 2 fixes can be found in: |
<http://groups.google.com/group/android-ndk/msg/b385e47e1484c2d4> |
4) Bring up a shell, and run 'android'. This will bring up a graphical |
gui for the sdk. From here you can install the different SDK components |
for the different flavours of android. Download them all - bandwidth and disk |
space are cheap, right? |
5) Now go to the Virtual Devices entry on the right hand side. You need to |
create yourself an emulator image to use. Click 'New...' on the right hand |
side and a window will appear. Fill in the entries as follows: |
Name: FroyoEm |
Target: Android 2.2 - API Level 8 |
SD card: Size: 1024MiB |
Skin: Resolution: 480x756 (756 just fits my macbook screen, but 800 may |
be 'more standard') |
Click 'Create AVD' and wait for a minute or so while it is prepared. Now |
you can exit the GUI. |
6) Now we are ready to build mupdf for Android. Check out a copy of MuPDF |
(but you've done that already, cos you're reading this, right?). |
7) You will also need a copy of mupdf-thirdparty.zip (see the source code |
link on http://mupdf.com/). Unpack the contents of this into a 'thirdparty' |
directory created within the mupdf directory (i.e. at the same level as |
fitz, pdf, android etc). |
8) Finally, you will need a copy of a 'generated' directory. This is not |
currently available to download. The easiest way to obtain this is to do |
a standard windows or linux build of mupdf, which generates the required |
files as part of the build process. |
9) Change into the android directory, and edit local.properties into your |
favourite editor. Change the sdk path there as appropriate. This should be |
the only bit of localisation you need to do. |
10) Change into the android directory (note, the android directory, NOT |
the android/jni directory!), and execute (in a Cygwin window on Windows!): |
ndk-build |
This should build the native code portion. Then execute: |
ant debug |
or on windows under cygwin: |
ant.bat debug |
This should build the java wrapper. |
11) Now start the emulator by executing: |
emulator -avd FroyoEm |
This will take a while to full start up (be patient). |
12) We now need to give the demo file something to chew on, so let's copy |
a file into the SD card image of the emulator (this should only need to be |
done once). With the emulator running type: |
adb push ../../MyTests/pdf_reference17.pdf /mnt/sdcard/Download/test.pdf |
(where obviously ../../MyTests/pdf_reference17.pdf is altered for your |
machine). (adb lives in <sdk>/platform-tools if it's not on your path). |
13) With the emulator running (see step 11), execute |
ant install |
('ant.bat install' on Windows) and that will copy MuPDF into the emulator |
where you can run it from the launchpad screen. |
14) To see debug messages from the emulator (including stdout/stderr from |
our app), execute: |
adb logcat |
Good luck! |
/contrib/media/updf/android/build.properties |
---|
0,0 → 1,17 |
# This file is used to override default values used by the Ant build system. |
# |
# This file must be checked in Version Control Systems, as it is |
# integral to the build system of your project. |
# This file is only used by the Ant script. |
# You can use this to override default values such as |
# 'source.dir' for the location of your java source folder and |
# 'out.dir' for the location of your output folder. |
# You can also use it define how the release builds are signed by declaring |
# the following properties: |
# 'key.store' for the location of your keystore and |
# 'key.alias' for the name of the key to use. |
# The password will be asked during the build when you use the 'release' target. |
/contrib/media/updf/android/build.sh |
---|
0,0 → 1,0 |
ndk-build && ant.bat install |
/contrib/media/updf/android/build.xml |
---|
0,0 → 1,84 |
<?xml version="1.0" encoding="UTF-8"?> |
<project name="MuPDF" default="help"> |
<!-- The local.properties file is created and updated by the 'android' |
tool. |
It contains the path to the SDK. It should *NOT* be checked into |
Version Control Systems. --> |
<property file="local.properties" /> |
<!-- The build.properties file can be created by you and is never touched |
by the 'android' tool. This is the place to change some of the |
default property values used by the Ant rules. |
Here are some properties you may want to change/update: |
source.dir |
The name of the source directory. Default is 'src'. |
out.dir |
The name of the output directory. Default is 'bin'. |
Properties related to the SDK location or the project target should |
be updated using the 'android' tool with the 'update' action. |
This file is an integral part of the build system for your |
application and should be checked into Version Control Systems. |
--> |
<property file="build.properties" /> |
<!-- The default.properties file is created and updated by the 'android' |
tool, as well as ADT. |
This file is an integral part of the build system for your |
application and should be checked into Version Control Systems. --> |
<property file="default.properties" /> |
<!-- Custom Android task to deal with the project target, and import the |
proper rules. |
This requires ant 1.6.0 or above. --> |
<path id="android.antlibs"> |
<pathelement path="${sdk.dir}/tools/lib/anttasks.jar" /> |
<pathelement path="${sdk.dir}/tools/lib/sdklib.jar" /> |
<pathelement path="${sdk.dir}/tools/lib/androidprefs.jar" /> |
</path> |
<taskdef name="setup" |
classname="com.android.ant.SetupTask" |
classpathref="android.antlibs" /> |
<!-- extension targets. Uncomment the ones where you want to do custom work |
in between standard targets --> |
<!-- |
<target name="-pre-build"> |
</target> |
<target name="-pre-compile"> |
</target> |
[This is typically used for code obfuscation. |
Compiled code location: ${out.classes.absolute.dir} |
If this is not done in place, override ${out.dex.input.absolute.dir}] |
<target name="-post-compile"> |
</target> |
--> |
<!-- Execute the Android Setup task that will setup some properties |
specific to the target, and import the build rules files. |
The rules file is imported from |
<SDK>/platforms/<target_platform>/ant/ant_rules_r#.xml |
To customize existing targets, there are two options: |
- Customize only one target: |
- copy/paste the target into this file, *before* the |
<setup> task. |
- customize it to your needs. |
- Customize the whole script. |
- copy/paste the content of the rules files (minus the top node) |
into this file, *after* the <setup> task |
- disable the import of the rules by changing the setup task |
below to <setup import="false" />. |
- customize to your needs. |
--> |
<setup /> |
</project> |
/contrib/media/updf/android/default.properties |
---|
0,0 → 1,11 |
# This file is automatically generated by Android Tools. |
# Do not modify this file -- YOUR CHANGES WILL BE ERASED! |
# |
# This file must be checked in Version Control Systems. |
# |
# To customize properties used by the Ant build system use, |
# "build.properties", and override values to adapt the script to your |
# project structure. |
# Project target. |
target=android-8 |
/contrib/media/updf/android/jni/Android.mk |
---|
0,0 → 1,22 |
LOCAL_PATH := $(call my-dir) |
TOP_LOCAL_PATH := $(LOCAL_PATH) |
MUPDF_ROOT := .. |
include $(TOP_LOCAL_PATH)/Core.mk |
include $(TOP_LOCAL_PATH)/ThirdParty.mk |
include $(CLEAR_VARS) |
LOCAL_C_INCLUDES := \ |
$(MUPDF_ROOT)/draw \ |
$(MUPDF_ROOT)/fitz \ |
$(MUPDF_ROOT)/pdf |
LOCAL_CFLAGS := |
LOCAL_MODULE := mupdf |
LOCAL_SRC_FILES := mupdf.c |
LOCAL_STATIC_LIBRARIES := mupdfcore mupdfthirdparty |
LOCAL_LDLIBS := -lm -llog -ljnigraphics |
include $(BUILD_SHARED_LIBRARY) |
/contrib/media/updf/android/jni/Application.mk |
---|
0,0 → 1,3 |
# The ARMv7 is significanly faster due to the use of the hardware FPU |
APP_ABI := armeabi armeabi-v7a |
APP_OPTIM := debug |
/contrib/media/updf/android/jni/Core.mk |
---|
0,0 → 1,99 |
LOCAL_PATH := $(call my-dir) |
include $(CLEAR_VARS) |
MY_ROOT := ../.. |
LOCAL_C_INCLUDES := \ |
../thirdparty/jbig2dec \ |
../thirdparty/openjpeg-1.4/libopenjpeg \ |
../thirdparty/jpeg-8c \ |
../thirdparty/zlib-1.2.5 \ |
../thirdparty/freetype-2.4.4/include \ |
../draw \ |
../fitz \ |
../pdf \ |
../scripts \ |
.. |
LOCAL_MODULE := mupdfcore |
LOCAL_SRC_FILES := \ |
$(MY_ROOT)/fitz/base_error.c \ |
$(MY_ROOT)/fitz/base_geometry.c \ |
$(MY_ROOT)/fitz/base_getopt.c \ |
$(MY_ROOT)/fitz/base_hash.c \ |
$(MY_ROOT)/fitz/base_memory.c \ |
$(MY_ROOT)/fitz/base_object.c \ |
$(MY_ROOT)/fitz/base_string.c \ |
$(MY_ROOT)/fitz/base_time.c \ |
$(MY_ROOT)/fitz/crypt_aes.c \ |
$(MY_ROOT)/fitz/crypt_arc4.c \ |
$(MY_ROOT)/fitz/crypt_md5.c \ |
$(MY_ROOT)/fitz/crypt_sha2.c \ |
$(MY_ROOT)/fitz/dev_bbox.c \ |
$(MY_ROOT)/fitz/dev_list.c \ |
$(MY_ROOT)/fitz/dev_null.c \ |
$(MY_ROOT)/fitz/dev_text.c \ |
$(MY_ROOT)/fitz/dev_trace.c \ |
$(MY_ROOT)/fitz/filt_basic.c \ |
$(MY_ROOT)/fitz/filt_dctd.c \ |
$(MY_ROOT)/fitz/filt_faxd.c \ |
$(MY_ROOT)/fitz/filt_flate.c \ |
$(MY_ROOT)/fitz/filt_jbig2d.c \ |
$(MY_ROOT)/fitz/filt_jpxd.c \ |
$(MY_ROOT)/fitz/filt_lzwd.c \ |
$(MY_ROOT)/fitz/filt_predict.c \ |
$(MY_ROOT)/fitz/obj_print.c \ |
$(MY_ROOT)/fitz/res_colorspace.c \ |
$(MY_ROOT)/fitz/res_font.c \ |
$(MY_ROOT)/fitz/res_path.c \ |
$(MY_ROOT)/fitz/res_pixmap.c \ |
$(MY_ROOT)/fitz/res_shade.c \ |
$(MY_ROOT)/fitz/res_text.c \ |
$(MY_ROOT)/fitz/stm_buffer.c \ |
$(MY_ROOT)/fitz/stm_open.c \ |
$(MY_ROOT)/fitz/stm_read.c \ |
$(MY_ROOT)/draw/arch_arm.c \ |
$(MY_ROOT)/draw/arch_port.c \ |
$(MY_ROOT)/draw/draw_affine.c \ |
$(MY_ROOT)/draw/draw_blend.c \ |
$(MY_ROOT)/draw/draw_device.c \ |
$(MY_ROOT)/draw/draw_edge.c \ |
$(MY_ROOT)/draw/draw_glyph.c \ |
$(MY_ROOT)/draw/draw_mesh.c \ |
$(MY_ROOT)/draw/draw_paint.c \ |
$(MY_ROOT)/draw/draw_path.c \ |
$(MY_ROOT)/draw/draw_scale.c \ |
$(MY_ROOT)/draw/draw_unpack.c \ |
$(MY_ROOT)/pdf/pdf_annot.c \ |
$(MY_ROOT)/pdf/pdf_cmap.c \ |
$(MY_ROOT)/pdf/pdf_cmap_load.c \ |
$(MY_ROOT)/pdf/pdf_cmap_parse.c \ |
$(MY_ROOT)/pdf/pdf_cmap_table.c \ |
$(MY_ROOT)/pdf/pdf_colorspace.c \ |
$(MY_ROOT)/pdf/pdf_crypt.c \ |
$(MY_ROOT)/pdf/pdf_encoding.c \ |
$(MY_ROOT)/pdf/pdf_font.c \ |
$(MY_ROOT)/pdf/pdf_fontfile.c \ |
$(MY_ROOT)/pdf/pdf_function.c \ |
$(MY_ROOT)/pdf/pdf_image.c \ |
$(MY_ROOT)/pdf/pdf_interpret.c \ |
$(MY_ROOT)/pdf/pdf_lex.c \ |
$(MY_ROOT)/pdf/pdf_metrics.c \ |
$(MY_ROOT)/pdf/pdf_nametree.c \ |
$(MY_ROOT)/pdf/pdf_outline.c \ |
$(MY_ROOT)/pdf/pdf_page.c \ |
$(MY_ROOT)/pdf/pdf_parse.c \ |
$(MY_ROOT)/pdf/pdf_pattern.c \ |
$(MY_ROOT)/pdf/pdf_repair.c \ |
$(MY_ROOT)/pdf/pdf_shade.c \ |
$(MY_ROOT)/pdf/pdf_store.c \ |
$(MY_ROOT)/pdf/pdf_stream.c \ |
$(MY_ROOT)/pdf/pdf_type3.c \ |
$(MY_ROOT)/pdf/pdf_unicode.c \ |
$(MY_ROOT)/pdf/pdf_xobject.c \ |
$(MY_ROOT)/pdf/pdf_xref.c |
LOCAL_LDLIBS := -lm -llog -ljnigraphics |
include $(BUILD_STATIC_LIBRARY) |
/contrib/media/updf/android/jni/ThirdParty.mk |
---|
0,0 → 1,153 |
LOCAL_PATH := $(call my-dir) |
include $(CLEAR_VARS) |
MY_ROOT := ../.. |
LOCAL_C_INCLUDES := \ |
../thirdparty/jbig2dec \ |
../thirdparty/openjpeg-1.4/libopenjpeg \ |
../thirdparty/jpeg-8c \ |
../thirdparty/zlib-1.2.5 \ |
../thirdparty/freetype-2.4.4/include \ |
../scripts |
LOCAL_CFLAGS := \ |
-DFT2_BUILD_LIBRARY -DDARWIN_NO_CARBON -DHAVE_STDINT_H |
LOCAL_MODULE := mupdfthirdparty |
LOCAL_SRC_FILES := \ |
$(MY_ROOT)/thirdparty/jbig2dec/jbig2.c \ |
$(MY_ROOT)/thirdparty/jbig2dec/jbig2_arith.c \ |
$(MY_ROOT)/thirdparty/jbig2dec/jbig2_arith_int.c \ |
$(MY_ROOT)/thirdparty/jbig2dec/jbig2_arith_iaid.c \ |
$(MY_ROOT)/thirdparty/jbig2dec/jbig2_huffman.c \ |
$(MY_ROOT)/thirdparty/jbig2dec/jbig2_segment.c \ |
$(MY_ROOT)/thirdparty/jbig2dec/jbig2_page.c \ |
$(MY_ROOT)/thirdparty/jbig2dec/jbig2_symbol_dict.c \ |
$(MY_ROOT)/thirdparty/jbig2dec/jbig2_text.c \ |
$(MY_ROOT)/thirdparty/jbig2dec/jbig2_generic.c \ |
$(MY_ROOT)/thirdparty/jbig2dec/jbig2_refinement.c \ |
$(MY_ROOT)/thirdparty/jbig2dec/jbig2_mmr.c \ |
$(MY_ROOT)/thirdparty/jbig2dec/jbig2_image.c \ |
$(MY_ROOT)/thirdparty/jbig2dec/jbig2_metadata.c \ |
$(MY_ROOT)/thirdparty/openjpeg-1.4/libopenjpeg/bio.c \ |
$(MY_ROOT)/thirdparty/openjpeg-1.4/libopenjpeg/cio.c \ |
$(MY_ROOT)/thirdparty/openjpeg-1.4/libopenjpeg/dwt.c \ |
$(MY_ROOT)/thirdparty/openjpeg-1.4/libopenjpeg/event.c \ |
$(MY_ROOT)/thirdparty/openjpeg-1.4/libopenjpeg/image.c \ |
$(MY_ROOT)/thirdparty/openjpeg-1.4/libopenjpeg/j2k.c \ |
$(MY_ROOT)/thirdparty/openjpeg-1.4/libopenjpeg/j2k_lib.c \ |
$(MY_ROOT)/thirdparty/openjpeg-1.4/libopenjpeg/jp2.c \ |
$(MY_ROOT)/thirdparty/openjpeg-1.4/libopenjpeg/jpt.c \ |
$(MY_ROOT)/thirdparty/openjpeg-1.4/libopenjpeg/mct.c \ |
$(MY_ROOT)/thirdparty/openjpeg-1.4/libopenjpeg/mqc.c \ |
$(MY_ROOT)/thirdparty/openjpeg-1.4/libopenjpeg/openjpeg.c \ |
$(MY_ROOT)/thirdparty/openjpeg-1.4/libopenjpeg/pi.c \ |
$(MY_ROOT)/thirdparty/openjpeg-1.4/libopenjpeg/raw.c \ |
$(MY_ROOT)/thirdparty/openjpeg-1.4/libopenjpeg/t1.c \ |
$(MY_ROOT)/thirdparty/openjpeg-1.4/libopenjpeg/t2.c \ |
$(MY_ROOT)/thirdparty/openjpeg-1.4/libopenjpeg/tcd.c \ |
$(MY_ROOT)/thirdparty/openjpeg-1.4/libopenjpeg/tgt.c \ |
$(MY_ROOT)/thirdparty/jpeg-8c/jaricom.c \ |
$(MY_ROOT)/thirdparty/jpeg-8c/jcapimin.c \ |
$(MY_ROOT)/thirdparty/jpeg-8c/jcapistd.c \ |
$(MY_ROOT)/thirdparty/jpeg-8c/jcarith.c \ |
$(MY_ROOT)/thirdparty/jpeg-8c/jccoefct.c \ |
$(MY_ROOT)/thirdparty/jpeg-8c/jccolor.c \ |
$(MY_ROOT)/thirdparty/jpeg-8c/jcdctmgr.c \ |
$(MY_ROOT)/thirdparty/jpeg-8c/jchuff.c \ |
$(MY_ROOT)/thirdparty/jpeg-8c/jcinit.c \ |
$(MY_ROOT)/thirdparty/jpeg-8c/jcmainct.c \ |
$(MY_ROOT)/thirdparty/jpeg-8c/jcmarker.c \ |
$(MY_ROOT)/thirdparty/jpeg-8c/jcmaster.c \ |
$(MY_ROOT)/thirdparty/jpeg-8c/jcomapi.c \ |
$(MY_ROOT)/thirdparty/jpeg-8c/jcparam.c \ |
$(MY_ROOT)/thirdparty/jpeg-8c/jcprepct.c \ |
$(MY_ROOT)/thirdparty/jpeg-8c/jcsample.c \ |
$(MY_ROOT)/thirdparty/jpeg-8c/jctrans.c \ |
$(MY_ROOT)/thirdparty/jpeg-8c/jdapimin.c \ |
$(MY_ROOT)/thirdparty/jpeg-8c/jdapistd.c \ |
$(MY_ROOT)/thirdparty/jpeg-8c/jdarith.c \ |
$(MY_ROOT)/thirdparty/jpeg-8c/jdatadst.c \ |
$(MY_ROOT)/thirdparty/jpeg-8c/jdatasrc.c \ |
$(MY_ROOT)/thirdparty/jpeg-8c/jdcoefct.c \ |
$(MY_ROOT)/thirdparty/jpeg-8c/jdcolor.c \ |
$(MY_ROOT)/thirdparty/jpeg-8c/jddctmgr.c \ |
$(MY_ROOT)/thirdparty/jpeg-8c/jdhuff.c \ |
$(MY_ROOT)/thirdparty/jpeg-8c/jdinput.c \ |
$(MY_ROOT)/thirdparty/jpeg-8c/jdmainct.c \ |
$(MY_ROOT)/thirdparty/jpeg-8c/jdmarker.c \ |
$(MY_ROOT)/thirdparty/jpeg-8c/jdmaster.c \ |
$(MY_ROOT)/thirdparty/jpeg-8c/jdmerge.c \ |
$(MY_ROOT)/thirdparty/jpeg-8c/jdpostct.c \ |
$(MY_ROOT)/thirdparty/jpeg-8c/jdsample.c \ |
$(MY_ROOT)/thirdparty/jpeg-8c/jdtrans.c \ |
$(MY_ROOT)/thirdparty/jpeg-8c/jerror.c \ |
$(MY_ROOT)/thirdparty/jpeg-8c/jfdctflt.c \ |
$(MY_ROOT)/thirdparty/jpeg-8c/jfdctfst.c \ |
$(MY_ROOT)/thirdparty/jpeg-8c/jfdctint.c \ |
$(MY_ROOT)/thirdparty/jpeg-8c/jidctflt.c \ |
$(MY_ROOT)/thirdparty/jpeg-8c/jidctfst.c \ |
$(MY_ROOT)/thirdparty/jpeg-8c/jidctint.c \ |
$(MY_ROOT)/thirdparty/jpeg-8c/jquant1.c \ |
$(MY_ROOT)/thirdparty/jpeg-8c/jquant2.c \ |
$(MY_ROOT)/thirdparty/jpeg-8c/jutils.c \ |
$(MY_ROOT)/thirdparty/jpeg-8c/jmemmgr.c \ |
$(MY_ROOT)/thirdparty/jpeg-8c/jmemansi.c \ |
$(MY_ROOT)/thirdparty/zlib-1.2.5/adler32.c \ |
$(MY_ROOT)/thirdparty/zlib-1.2.5/compress.c \ |
$(MY_ROOT)/thirdparty/zlib-1.2.5/crc32.c \ |
$(MY_ROOT)/thirdparty/zlib-1.2.5/deflate.c \ |
$(MY_ROOT)/thirdparty/zlib-1.2.5/gzclose.c \ |
$(MY_ROOT)/thirdparty/zlib-1.2.5/gzlib.c \ |
$(MY_ROOT)/thirdparty/zlib-1.2.5/gzread.c \ |
$(MY_ROOT)/thirdparty/zlib-1.2.5/gzwrite.c \ |
$(MY_ROOT)/thirdparty/zlib-1.2.5/infback.c \ |
$(MY_ROOT)/thirdparty/zlib-1.2.5/inffast.c \ |
$(MY_ROOT)/thirdparty/zlib-1.2.5/inflate.c \ |
$(MY_ROOT)/thirdparty/zlib-1.2.5/inftrees.c \ |
$(MY_ROOT)/thirdparty/zlib-1.2.5/trees.c \ |
$(MY_ROOT)/thirdparty/zlib-1.2.5/uncompr.c \ |
$(MY_ROOT)/thirdparty/zlib-1.2.5/zutil.c \ |
$(MY_ROOT)/thirdparty/freetype-2.4.4/src/autofit/autofit.c \ |
$(MY_ROOT)/thirdparty/freetype-2.4.4/src/base/ftbase.c \ |
$(MY_ROOT)/thirdparty/freetype-2.4.4/src/base/ftbbox.c \ |
$(MY_ROOT)/thirdparty/freetype-2.4.4/src/base/ftbdf.c \ |
$(MY_ROOT)/thirdparty/freetype-2.4.4/src/base/ftbitmap.c \ |
$(MY_ROOT)/thirdparty/freetype-2.4.4/src/base/ftdebug.c \ |
$(MY_ROOT)/thirdparty/freetype-2.4.4/src/base/ftgasp.c \ |
$(MY_ROOT)/thirdparty/freetype-2.4.4/src/base/ftglyph.c \ |
$(MY_ROOT)/thirdparty/freetype-2.4.4/src/base/ftgxval.c \ |
$(MY_ROOT)/thirdparty/freetype-2.4.4/src/base/ftinit.c \ |
$(MY_ROOT)/thirdparty/freetype-2.4.4/src/base/ftlcdfil.c \ |
$(MY_ROOT)/thirdparty/freetype-2.4.4/src/base/ftmm.c \ |
$(MY_ROOT)/thirdparty/freetype-2.4.4/src/base/ftotval.c \ |
$(MY_ROOT)/thirdparty/freetype-2.4.4/src/base/ftpfr.c \ |
$(MY_ROOT)/thirdparty/freetype-2.4.4/src/base/ftstroke.c \ |
$(MY_ROOT)/thirdparty/freetype-2.4.4/src/base/ftsynth.c \ |
$(MY_ROOT)/thirdparty/freetype-2.4.4/src/base/ftsystem.c \ |
$(MY_ROOT)/thirdparty/freetype-2.4.4/src/base/fttype1.c \ |
$(MY_ROOT)/thirdparty/freetype-2.4.4/src/base/ftwinfnt.c \ |
$(MY_ROOT)/thirdparty/freetype-2.4.4/src/base/ftxf86.c \ |
$(MY_ROOT)/thirdparty/freetype-2.4.4/src/base/ftpatent.c \ |
$(MY_ROOT)/thirdparty/freetype-2.4.4/src/bdf/bdf.c \ |
$(MY_ROOT)/thirdparty/freetype-2.4.4/src/cache/ftcache.c \ |
$(MY_ROOT)/thirdparty/freetype-2.4.4/src/cff/cff.c \ |
$(MY_ROOT)/thirdparty/freetype-2.4.4/src/cid/type1cid.c \ |
$(MY_ROOT)/thirdparty/freetype-2.4.4/src/gzip/ftgzip.c \ |
$(MY_ROOT)/thirdparty/freetype-2.4.4/src/lzw/ftlzw.c \ |
$(MY_ROOT)/thirdparty/freetype-2.4.4/src/pcf/pcf.c \ |
$(MY_ROOT)/thirdparty/freetype-2.4.4/src/pfr/pfr.c \ |
$(MY_ROOT)/thirdparty/freetype-2.4.4/src/psaux/psaux.c \ |
$(MY_ROOT)/thirdparty/freetype-2.4.4/src/pshinter/pshinter.c \ |
$(MY_ROOT)/thirdparty/freetype-2.4.4/src/psnames/psnames.c \ |
$(MY_ROOT)/thirdparty/freetype-2.4.4/src/raster/raster.c \ |
$(MY_ROOT)/thirdparty/freetype-2.4.4/src/smooth/smooth.c \ |
$(MY_ROOT)/thirdparty/freetype-2.4.4/src/sfnt/sfnt.c \ |
$(MY_ROOT)/thirdparty/freetype-2.4.4/src/truetype/truetype.c \ |
$(MY_ROOT)/thirdparty/freetype-2.4.4/src/type1/type1.c \ |
$(MY_ROOT)/thirdparty/freetype-2.4.4/src/type42/type42.c \ |
$(MY_ROOT)/thirdparty/freetype-2.4.4/src/winfonts/winfnt.c |
include $(BUILD_STATIC_LIBRARY) |
/contrib/media/updf/android/jni/mupdf.c |
---|
0,0 → 1,212 |
#include <jni.h> |
#include <time.h> |
#include <android/log.h> |
#include <android/bitmap.h> |
#include <stdio.h> |
#include <stdlib.h> |
#include <math.h> |
#include "fitz.h" |
#include "mupdf.h" |
#define LOG_TAG "libmupdf" |
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__) |
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__) |
/* Set to 1 to enable debug log traces. */ |
#define DEBUG 0 |
/* Globals */ |
fz_colorspace *colorspace; |
fz_glyph_cache *glyphcache; |
pdf_xref *xref; |
int pagenum = 1; |
int resolution = 160; |
float pageWidth = 100; |
float pageHeight = 100; |
fz_display_list *currentPageList; |
fz_rect currentMediabox; |
int currentRotate; |
JNIEXPORT int JNICALL |
Java_com_artifex_mupdf_MuPDFCore_openFile(JNIEnv * env, jobject thiz, jstring jfilename) |
{ |
const char *filename; |
char *password = ""; |
int accelerate = 1; |
fz_error error; |
int pages; |
filename = (*env)->GetStringUTFChars(env, jfilename, NULL); |
if (filename == NULL) |
{ |
LOGE("Failed to get filename"); |
return 0; |
} |
if (accelerate) |
fz_accelerate(); |
glyphcache = fz_new_glyph_cache(); |
colorspace = fz_device_rgb; |
LOGE("Opening document..."); |
error = pdf_open_xref(&xref, filename, password); |
if (error) |
{ |
LOGE("Cannot open document: '%s'\n", filename); |
return 0; |
} |
LOGE("Loading page tree..."); |
error = pdf_load_page_tree(xref); |
if (error) |
{ |
LOGE("Cannot load page tree: '%s'\n", filename); |
return 0; |
} |
pages = pdf_count_pages(xref); |
LOGE("Done! %d pages", pages); |
return pages; |
} |
JNIEXPORT void JNICALL |
Java_com_artifex_mupdf_MuPDFCore_gotoPageInternal(JNIEnv *env, jobject thiz, int page) |
{ |
float zoom; |
fz_matrix ctm; |
fz_bbox bbox; |
fz_error error; |
fz_device *dev; |
pdf_page *currentPage; |
/* In the event of an error, ensure we give a non-empty page */ |
pageWidth = 100; |
pageHeight = 100; |
LOGE("Goto page %d...", page); |
if (currentPageList != NULL) |
{ |
fz_free_display_list(currentPageList); |
currentPageList = NULL; |
} |
pagenum = page; |
error = pdf_load_page(¤tPage, xref, pagenum); |
if (error) |
return; |
zoom = resolution / 72; |
currentMediabox = currentPage->mediabox; |
currentRotate = currentPage->rotate; |
ctm = fz_translate(0, -currentMediabox.y1); |
ctm = fz_concat(ctm, fz_scale(zoom, -zoom)); |
ctm = fz_concat(ctm, fz_rotate(currentRotate)); |
bbox = fz_round_rect(fz_transform_rect(ctm, currentMediabox)); |
pageWidth = bbox.x1-bbox.x0; |
pageHeight = bbox.y1-bbox.y0; |
/* Render to list */ |
currentPageList = fz_new_display_list(); |
dev = fz_new_list_device(currentPageList); |
error = pdf_run_page(xref, currentPage, dev, fz_identity); |
pdf_free_page(currentPage); |
if (error) |
LOGE("cannot make displaylist from page %d", pagenum); |
fz_free_device(dev); |
} |
JNIEXPORT float JNICALL |
Java_com_artifex_mupdf_MuPDFCore_getPageWidth(JNIEnv *env, jobject thiz) |
{ |
LOGE("PageWidth=%g", pageWidth); |
return pageWidth; |
} |
JNIEXPORT float JNICALL |
Java_com_artifex_mupdf_MuPDFCore_getPageHeight(JNIEnv *env, jobject thiz) |
{ |
LOGE("PageHeight=%g", pageHeight); |
return pageHeight; |
} |
JNIEXPORT jboolean JNICALL |
Java_com_artifex_mupdf_MuPDFCore_drawPage(JNIEnv *env, jobject thiz, jobject bitmap, |
int pageW, int pageH, int patchX, int patchY, int patchW, int patchH) |
{ |
AndroidBitmapInfo info; |
void *pixels; |
int ret; |
fz_error error; |
fz_device *dev; |
float zoom; |
fz_matrix ctm; |
fz_bbox bbox; |
fz_pixmap *pix; |
float xscale, yscale; |
fz_bbox rect; |
LOGI("In native method\n"); |
if ((ret = AndroidBitmap_getInfo(env, bitmap, &info)) < 0) { |
LOGE("AndroidBitmap_getInfo() failed ! error=%d", ret); |
return 0; |
} |
LOGI("Checking format\n"); |
if (info.format != ANDROID_BITMAP_FORMAT_RGBA_8888) { |
LOGE("Bitmap format is not RGBA_8888 !"); |
return 0; |
} |
LOGI("locking pixels\n"); |
if ((ret = AndroidBitmap_lockPixels(env, bitmap, &pixels)) < 0) { |
LOGE("AndroidBitmap_lockPixels() failed ! error=%d", ret); |
return 0; |
} |
/* Call mupdf to render display list to screen */ |
LOGE("Rendering page=%dx%d patch=[%d,%d,%d,%d]", |
pageW, pageH, patchX, patchY, patchW, patchH); |
rect.x0 = patchX; |
rect.y0 = patchY; |
rect.x1 = patchX + patchW; |
rect.y1 = patchY + patchH; |
pix = fz_new_pixmap_with_rect_and_data(colorspace, rect, pixels); |
if (currentPageList == NULL) |
{ |
fz_clear_pixmap_with_color(pix, 0xd0); |
return 0; |
} |
fz_clear_pixmap_with_color(pix, 0xff); |
zoom = resolution / 72; |
ctm = fz_translate(-currentMediabox.x0, -currentMediabox.y1); |
ctm = fz_concat(ctm, fz_scale(zoom, -zoom)); |
ctm = fz_concat(ctm, fz_rotate(currentRotate)); |
bbox = fz_round_rect(fz_transform_rect(ctm,currentMediabox)); |
/* Now, adjust ctm so that it would give the correct page width |
* heights. */ |
xscale = (float)pageW/(float)(bbox.x1-bbox.x0); |
yscale = (float)pageH/(float)(bbox.y1-bbox.y0); |
ctm = fz_concat(ctm, fz_scale(xscale, yscale)); |
bbox = fz_round_rect(fz_transform_rect(ctm,currentMediabox)); |
dev = fz_new_draw_device(glyphcache, pix); |
fz_execute_display_list(currentPageList, dev, ctm, bbox); |
fz_free_device(dev); |
fz_drop_pixmap(pix); |
LOGE("Rendered"); |
AndroidBitmap_unlockPixels(env, bitmap); |
return 1; |
} |
JNIEXPORT void JNICALL |
Java_com_artifex_mupdf_MuPDFCore_destroying(JNIEnv * env, jobject thiz) |
{ |
fz_free_display_list(currentPageList); |
currentPageList = NULL; |
pdf_free_xref(xref); |
xref = NULL; |
fz_free_glyph_cache(glyphcache); |
glyphcache = NULL; |
} |
/contrib/media/updf/android/local.properties |
---|
0,0 → 1,2 |
#sdk.dir=/Library/android-sdk-mac_x86 |
sdk.dir=C:\\Program Files\\android-sdk-windows |
/contrib/media/updf/android/res/drawable-hdpi/icon.png |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/contrib/media/updf/android/res/drawable-ldpi/icon.png |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/contrib/media/updf/android/res/drawable-mdpi/icon.png |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/contrib/media/updf/android/res/layout/main.xml |
---|
0,0 → 1,8 |
<?xml version="1.0" encoding="utf-8"?> |
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" |
android:orientation="vertical" |
android:layout_width="fill_parent" |
android:layout_height="fill_parent" |
> |
</LinearLayout> |
/contrib/media/updf/android/res/values/strings.xml |
---|
0,0 → 1,4 |
<?xml version="1.0" encoding="utf-8"?> |
<resources> |
<string name="app_name">MuPDF</string> |
</resources> |
/contrib/media/updf/android/res/values/theme.xml |
---|
0,0 → 1,7 |
<?xml version="1.0" encoding="utf-8"?> |
<resources> |
<style name="Theme.NoBackground.NoTitle" parent="android:Theme"> |
<item name="android:windowBackground">@null</item> |
<item name="android:windowNoTitle">true</item> |
</style> |
</resources> |
/contrib/media/updf/android/src/com/artifex/mupdf/MuPDFActivity.java |
---|
0,0 → 1,162 |
package com.artifex.mupdf; |
import android.app.Activity; |
import android.os.Bundle; |
import android.os.Environment; |
import android.view.*; |
import android.view.View.OnClickListener; |
import android.widget.*; |
import android.widget.LinearLayout.*; |
import java.io.File; |
import com.artifex.mupdf.PixmapView; |
public class MuPDFActivity extends Activity |
{ |
/* The core rendering instance */ |
private MuPDFCore core; |
private MuPDFCore openFile() |
{ |
String storageState = Environment.getExternalStorageState(); |
File path, file; |
MuPDFCore core; |
if (Environment.MEDIA_MOUNTED.equals(storageState)) |
{ |
System.out.println("Media mounted read/write"); |
} |
else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(storageState)) |
{ |
System.out.println("Media mounted read only"); |
} |
else |
{ |
System.out.println("No media at all! Bale!\n"); |
return null; |
} |
path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS); |
file = new File(path, "test.pdf"); |
System.out.println("Trying to open "+file.toString()); |
try |
{ |
core = new MuPDFCore(file.toString()); |
} |
catch (Exception e) |
{ |
System.out.println(e); |
return null; |
} |
return core; |
} |
/** Called when the activity is first created. */ |
@Override |
public void onCreate(Bundle savedInstanceState) |
{ |
PixmapView pixmapView; |
if (core == null) { |
core = (MuPDFCore)getLastNonConfigurationInstance(); |
} |
if (core == null) { |
core = openFile(); |
} |
if (core == null) |
{ |
/* FIXME: Error handling here! */ |
return; |
} |
pixmapView = new PixmapView(this, core); |
super.onCreate(savedInstanceState); |
/* Now create the UI */ |
RelativeLayout layout; |
LinearLayout bar; |
MyButtonHandler bh = new MyButtonHandler(pixmapView); |
bar = new LinearLayout(this); |
bar.setOrientation(LinearLayout.HORIZONTAL); |
bh.buttonStart = new Button(this); |
bh.buttonStart.setText("<<"); |
bh.buttonStart.setOnClickListener(bh); |
bar.addView(bh.buttonStart); |
bh.buttonPrev = new Button(this); |
bh.buttonPrev.setText("<"); |
bh.buttonPrev.setOnClickListener(bh); |
bar.addView(bh.buttonPrev); |
bh.buttonNext = new Button(this); |
bh.buttonNext.setText(">"); |
bh.buttonNext.setOnClickListener(bh); |
bar.addView(bh.buttonNext); |
bh.buttonEnd = new Button(this); |
bh.buttonEnd.setText(">>"); |
bh.buttonEnd.setOnClickListener(bh); |
bar.addView(bh.buttonEnd); |
layout = new RelativeLayout(this); |
layout.setLayoutParams(new RelativeLayout.LayoutParams( |
RelativeLayout.LayoutParams.FILL_PARENT, |
RelativeLayout.LayoutParams.FILL_PARENT)); |
layout.setGravity(Gravity.FILL); |
RelativeLayout.LayoutParams barParams = |
new RelativeLayout.LayoutParams( |
RelativeLayout.LayoutParams.FILL_PARENT, |
RelativeLayout.LayoutParams.WRAP_CONTENT); |
barParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM); |
bar.setId(100); |
layout.addView(bar, barParams); |
RelativeLayout.LayoutParams pixmapParams = |
new RelativeLayout.LayoutParams( |
RelativeLayout.LayoutParams.FILL_PARENT, |
RelativeLayout.LayoutParams.FILL_PARENT); |
pixmapParams.addRule(RelativeLayout.ABOVE,100); |
layout.addView(pixmapView, pixmapParams); |
setContentView(layout); |
} |
public Object onRetainNonConfigurationInstance() |
{ |
MuPDFCore mycore = core; |
core = null; |
return mycore; |
} |
public void onDestroy() |
{ |
if (core != null) |
core.onDestroy(); |
core = null; |
super.onDestroy(); |
} |
private class MyButtonHandler implements OnClickListener |
{ |
Button buttonStart; |
Button buttonPrev; |
Button buttonNext; |
Button buttonEnd; |
PixmapView pixmapView; |
public MyButtonHandler(PixmapView pixmapView) |
{ |
this.pixmapView = pixmapView; |
} |
public void onClick(View v) |
{ |
if (v == buttonStart) |
pixmapView.changePage(Integer.MIN_VALUE); |
else if (v == buttonPrev) |
pixmapView.changePage(-1); |
else if (v == buttonNext) |
pixmapView.changePage(+1); |
else if (v == buttonEnd) |
pixmapView.changePage(Integer.MAX_VALUE); |
} |
} |
} |
/contrib/media/updf/android/src/com/artifex/mupdf/MuPDFCore.java |
---|
0,0 → 1,54 |
package com.artifex.mupdf; |
import android.graphics.*; |
public class MuPDFCore |
{ |
/* load our native library */ |
static { |
System.loadLibrary("mupdf"); |
} |
/* Readable members */ |
public int pageNum; |
public int numPages; |
public float pageWidth; |
public float pageHeight; |
/* The native functions */ |
private static native int openFile(String filename); |
private static native void gotoPageInternal(int localActionPageNum); |
private static native float getPageWidth(); |
private static native float getPageHeight(); |
public static native void drawPage(Bitmap bitmap, |
int pageW, int pageH, |
int patchX, int patchY, |
int patchW, int patchH); |
public static native void destroying(); |
public MuPDFCore(String filename) throws Exception |
{ |
numPages = openFile(filename); |
if (numPages <= 0) |
{ |
throw new Exception("Failed to open "+filename); |
} |
pageNum = 0; |
} |
/* Shim function */ |
public void gotoPage(int page) |
{ |
if (page > numPages-1) |
page = numPages-1; |
else if (page < 0) |
page = 0; |
gotoPageInternal(page); |
this.pageNum = page; |
this.pageWidth = getPageWidth(); |
this.pageHeight = getPageHeight(); |
} |
public void onDestroy() { |
destroying(); |
} |
} |
/contrib/media/updf/android/src/com/artifex/mupdf/PixmapView.java |
---|
0,0 → 1,579 |
package com.artifex.mupdf; |
import android.app.*; |
import android.os.*; |
import android.content.*; |
import android.content.res.*; |
import android.graphics.*; |
import android.util.*; |
import android.view.*; |
import android.widget.*; |
import java.net.*; |
import java.io.*; |
public class PixmapView extends SurfaceView implements SurfaceHolder.Callback |
{ |
private SurfaceHolder holder; |
private MuPDFThread thread = null; |
private boolean threadStarted = false; |
private MuPDFCore core; |
/* Constructor */ |
public PixmapView(Context context, MuPDFCore core) |
{ |
super(context); |
System.out.println("PixmapView construct"); |
this.core = core; |
holder = getHolder(); |
holder.addCallback(this); |
thread = new MuPDFThread(holder, core); |
setFocusable(true); // need to get the key events |
} |
/* load our native library */ |
static { |
System.loadLibrary("mupdf"); |
} |
/* Handlers for keys - so we can actually do stuff */ |
@Override |
public boolean onKeyDown(int keyCode, KeyEvent event) |
{ |
if (thread.onKeyDown(keyCode, event)) |
return true; |
return super.onKeyDown(keyCode, event); |
} |
@Override |
public boolean onKeyUp(int keyCode, KeyEvent event) |
{ |
if (thread.onKeyUp(keyCode, event)) |
return true; |
return super.onKeyUp(keyCode, event); |
} |
@Override |
public boolean onTouchEvent(MotionEvent event) |
{ |
if (thread.onTouchEvent(event)) |
return true; |
return super.onTouchEvent(event); |
} |
public void changePage(int delta) |
{ |
thread.changePage(delta); |
} |
/* Handlers for SurfaceHolder callbacks; these are called when the |
* surface is created/destroyed/changed. We need to ensure that we only |
* draw into the surface between the created and destroyed calls. |
* Therefore, we start/stop the thread that actually runs MuPDF on |
* creation/destruction. */ |
public void surfaceCreated(SurfaceHolder holder) |
{ |
} |
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) |
{ |
thread.newScreenSize(width, height); |
if (!threadStarted) |
{ |
threadStarted = true; |
thread.setRunning(true); |
thread.start(); |
} |
} |
public void surfaceDestroyed(SurfaceHolder holder) |
{ |
boolean retry = true; |
System.out.println("Surface destroyed 1 this="+this); |
thread.setRunning(false); |
System.out.println("Surface destroyed 2"); |
while (retry) |
{ |
try |
{ |
thread.join(); |
retry = false; |
} |
catch (InterruptedException e) |
{ |
} |
} |
threadStarted = false; |
System.out.println("Surface destroyed 3"); |
} |
class MuPDFThread extends Thread |
{ |
private SurfaceHolder holder; |
private boolean running = false; |
private int keycode = -1; |
private int screenWidth; |
private int screenHeight; |
private int screenGeneration; |
private Bitmap bitmap; |
private MuPDFCore core; |
/* The following variables deal with the size of the current page; |
* specifically, its position on the screen, its raw size, its |
* current scale, and its current scaled size (in terms of whole |
* pixels). |
*/ |
private int pageOriginX; |
private int pageOriginY; |
private float pageScale; |
private int pageWidth; |
private int pageHeight; |
/* The following variables deal with the multitouch handling */ |
private final int NONE = 0; |
private final int DRAG = 1; |
private final int ZOOM = 2; |
private int touchMode = NONE; |
private float touchInitialSpacing; |
private float touchDragStartX; |
private float touchDragStartY; |
private float touchInitialOriginX; |
private float touchInitialOriginY; |
private float touchInitialScale; |
private PointF touchZoomMidpoint; |
/* The following control the inner loop; other events etc cause |
* action to be set. The inner loop runs around a tight loop |
* performing the action requested of it. |
*/ |
private boolean wakeMe = false; |
private int action; |
private final int SLEEP = 0; |
private final int REDRAW = 1; |
private final int DIE = 2; |
private final int GOTOPAGE = 3; |
private int actionPageNum; |
/* Members for blitting, declared here to avoid causing gcs */ |
private Rect srcRect; |
private RectF dstRect; |
public MuPDFThread(SurfaceHolder holder, MuPDFCore core) |
{ |
this.holder = holder; |
this.core = core; |
touchZoomMidpoint = new PointF(0,0); |
srcRect = new Rect(0,0,0,0); |
dstRect = new RectF(0,0,0,0); |
} |
public void setRunning(boolean running) |
{ |
this.running = running; |
if (!running) |
{ |
System.out.println("killing 1"); |
synchronized(this) |
{ |
System.out.println("killing 2"); |
action = DIE; |
if (wakeMe) |
{ |
wakeMe = false; |
System.out.println("killing 3"); |
this.notify(); |
System.out.println("killing 4"); |
} |
} |
} |
} |
public void newScreenSize(int width, int height) |
{ |
this.screenWidth = width; |
this.screenHeight = height; |
this.screenGeneration++; |
} |
public boolean onKeyDown(int keyCode, KeyEvent msg) |
{ |
keycode = keyCode; |
return false; |
} |
public boolean onKeyUp(int keyCode, KeyEvent msg) |
{ |
return false; |
} |
public synchronized void changePage(int delta) |
{ |
action = GOTOPAGE; |
if (delta == Integer.MIN_VALUE) |
actionPageNum = 0; |
else if (delta == Integer.MAX_VALUE) |
actionPageNum = core.numPages-1; |
else |
{ |
actionPageNum += delta; |
if (actionPageNum < 0) |
actionPageNum = 0; |
if (actionPageNum > core.numPages-1) |
actionPageNum = core.numPages-1; |
} |
if (wakeMe) |
{ |
wakeMe = false; |
this.notify(); |
} |
} |
private float spacing(MotionEvent event) |
{ |
float x = event.getX(0) - event.getX(1); |
float y = event.getY(0) - event.getY(1); |
return FloatMath.sqrt(x*x+y*y); |
} |
private void midpoint(PointF point, MotionEvent event) |
{ |
float x = event.getX(0) + event.getX(1); |
float y = event.getY(0) + event.getY(1); |
point.set(x/2, y/2); |
} |
private synchronized void forceRedraw() |
{ |
if (wakeMe) |
{ |
wakeMe = false; |
this.notify(); |
} |
action = REDRAW; |
} |
public synchronized void setPageOriginTo(int x, int y) |
{ |
/* Adjust the coordinates so that the page always covers the |
* centre of the screen. */ |
if (x + pageWidth < screenWidth/2) |
{ |
x = screenWidth/2 - pageWidth; |
} |
else if (x > screenWidth/2) |
{ |
x = screenWidth/2; |
} |
if (y + pageHeight < screenHeight/2) |
{ |
y = screenHeight/2 - pageHeight; |
} |
else if (y > screenHeight/2) |
{ |
y = screenHeight/2; |
} |
if ((x != pageOriginX) || (y != pageOriginY)) |
{ |
pageOriginX = x; |
pageOriginY = y; |
} |
forceRedraw(); |
} |
public void setPageScaleTo(float scale, PointF midpoint) |
{ |
float x, y; |
/* Convert midpoint (in screen coords) to page coords */ |
x = (midpoint.x - pageOriginX)/pageScale; |
y = (midpoint.y - pageOriginY)/pageScale; |
/* Find new scaled page sizes */ |
synchronized(this) |
{ |
pageWidth = (int)(core.pageWidth*scale+0.5); |
if (pageWidth < screenWidth/2) |
{ |
scale = screenWidth/2/core.pageWidth; |
pageWidth = (int)(core.pageWidth*scale+0.5); |
} |
pageHeight = (int)(core.pageHeight*scale+0.5); |
if (pageHeight < screenHeight/2) |
{ |
scale = screenHeight/2/core.pageHeight; |
pageWidth = (int)(core.pageWidth *scale+0.5); |
pageHeight = (int)(core.pageHeight*scale+0.5); |
} |
pageScale = scale; |
/* Now given this new scale, calculate page origins so that |
* x and y are at midpoint */ |
float xscale = (float)pageWidth /core.pageWidth; |
float yscale = (float)pageHeight/core.pageHeight; |
setPageOriginTo((int)(midpoint.x - x*xscale + 0.5), |
(int)(midpoint.y - y*yscale + 0.5)); |
} |
} |
public void scalePageToScreen() |
{ |
float scaleX, scaleY; |
scaleX = (float)screenWidth /core.pageWidth; |
scaleY = (float)screenHeight/core.pageHeight; |
synchronized(this) |
{ |
if (scaleX < scaleY) |
pageScale = scaleX; |
else |
pageScale = scaleY; |
pageWidth = (int)(core.pageWidth * pageScale + 0.5); |
pageHeight = (int)(core.pageHeight * pageScale + 0.5); |
pageOriginX = (screenWidth - pageWidth)/2; |
pageOriginY = (screenHeight - pageHeight)/2; |
forceRedraw(); |
} |
System.out.println("scalePageToScreen: Raw="+ |
core.pageWidth+"x"+core.pageHeight+" scaled="+ |
pageWidth+","+pageHeight+" pageScale="+ |
pageScale); |
} |
public boolean onTouchEvent(MotionEvent event) |
{ |
int action = event.getAction(); |
boolean done = false; |
switch (action & MotionEvent.ACTION_MASK) |
{ |
case MotionEvent.ACTION_DOWN: |
touchMode = DRAG; |
touchDragStartX = event.getX(); |
touchDragStartY = event.getY(); |
touchInitialOriginX = pageOriginX; |
touchInitialOriginY = pageOriginY; |
System.out.println("Starting dragging from: "+touchDragStartX+","+touchDragStartY+" ("+pageOriginX+","+pageOriginY+")"); |
done = true; |
break; |
case MotionEvent.ACTION_POINTER_DOWN: |
touchInitialSpacing = spacing(event); |
if (touchInitialSpacing > 10f) |
{ |
System.out.println("Started zooming: spacing="+touchInitialSpacing); |
touchInitialScale = pageScale; |
touchMode = ZOOM; |
done = true; |
} |
break; |
case MotionEvent.ACTION_UP: |
case MotionEvent.ACTION_POINTER_UP: |
if (touchMode != NONE) |
{ |
System.out.println("Released!"); |
touchMode = NONE; |
done = true; |
} |
break; |
case MotionEvent.ACTION_MOVE: |
if (touchMode == DRAG) |
{ |
float x = touchInitialOriginX+event.getX()-touchDragStartX; |
float y = touchInitialOriginY+event.getY()-touchDragStartY; |
System.out.println("Dragged to "+x+","+y); |
setPageOriginTo((int)(x+0.5),(int)(y+0.5)); |
done = true; |
} |
else if (touchMode == ZOOM) |
{ |
float newSpacing = spacing(event); |
if (newSpacing > 10f) |
{ |
float newScale = touchInitialScale*newSpacing/touchInitialSpacing; |
System.out.println("Zoomed to "+newSpacing); |
midpoint(touchZoomMidpoint,event); |
setPageScaleTo(newScale,touchZoomMidpoint); |
done = true; |
} |
} |
} |
return done; |
} |
public void run() |
{ |
boolean redraw = false; |
int patchW = 0; |
int patchH = 0; |
int patchX = 0; |
int patchY = 0; |
int localPageW = 0; |
int localPageH = 0; |
int localScreenGeneration = screenGeneration; |
int localAction; |
int localActionPageNum = core.pageNum; |
/* Set up our default action */ |
action = GOTOPAGE; |
actionPageNum = core.pageNum; |
while (action != DIE) |
{ |
synchronized(this) |
{ |
while (action == SLEEP) |
{ |
wakeMe = true; |
try |
{ |
System.out.println("Render thread sleeping"); |
this.wait(); |
System.out.println("Render thread woken"); |
} |
catch (java.lang.InterruptedException e) |
{ |
System.out.println("Render thread exception:"+e); |
} |
} |
/* Now we do as little as we can get away with while |
* synchronised. In general this means copying any action |
* or global variables into local ones so that when we |
* unsynchronoise, other people can alter them again. |
*/ |
switch (action) |
{ |
case DIE: |
System.out.println("Woken to die!"); |
break; |
case GOTOPAGE: |
localActionPageNum = actionPageNum; |
break; |
case REDRAW: |
/* Figure out what area of the page we want to |
* redraw (in local variables, in docspace). |
* We'll always draw a screensized lump, unless |
* that's too big. */ |
System.out.println("page="+pageWidth+","+pageHeight+" ("+core.pageWidth+","+core.pageHeight+"@"+pageScale+") @ "+pageOriginX+","+pageOriginY); |
localPageW = pageWidth; |
localPageH = pageHeight; |
patchW = pageWidth; |
patchH = pageHeight; |
patchX = -pageOriginX; |
patchY = -pageOriginY; |
if (patchX < 0) |
patchX = 0; |
if (patchW > screenWidth) |
patchW = screenWidth; |
srcRect.left = 0; |
if (patchX+patchW > pageWidth) |
{ |
srcRect.left += patchX+patchW-pageWidth; |
patchX = pageWidth-patchW; |
} |
if (patchY < 0) |
patchY = 0; |
if (patchH > screenHeight) |
patchH = screenHeight; |
srcRect.top = 0; |
if (patchY+patchH > pageHeight) |
{ |
srcRect.top += patchY+patchH-pageHeight; |
patchY = pageHeight-patchH; |
} |
dstRect.left = pageOriginX; |
if (dstRect.left < 0) |
dstRect.left = 0; |
dstRect.top = pageOriginY; |
if (dstRect.top < 0) |
dstRect.top = 0; |
dstRect.right = dstRect.left + patchW; |
srcRect.right = srcRect.left + patchW; |
if (srcRect.right > screenWidth) |
{ |
dstRect.right -= srcRect.right-screenWidth; |
srcRect.right = screenWidth; |
} |
if (dstRect.right > screenWidth) |
{ |
srcRect.right -= dstRect.right-screenWidth; |
dstRect.right = screenWidth; |
} |
dstRect.bottom = dstRect.top + patchH; |
srcRect.bottom = srcRect.top + patchH; |
if (srcRect.bottom > screenHeight) |
{ |
dstRect.bottom -=srcRect.bottom-screenHeight; |
srcRect.bottom = screenHeight; |
} |
if (dstRect.bottom > screenHeight) |
{ |
srcRect.bottom -=dstRect.bottom-screenHeight; |
dstRect.bottom = screenHeight; |
} |
System.out.println("patch=["+patchX+","+patchY+","+patchW+","+patchH+"]"); |
break; |
} |
localAction = action; |
if (action != DIE) |
action = SLEEP; |
} |
/* In the redraw case: |
* pW, pH, pX, pY, localPageW, localPageH are now all set |
* in local variables, and we are safe from the global vars |
* being altered in calls from other threads. This is all |
* the information we need to actually do our render. |
*/ |
switch (localAction) |
{ |
case GOTOPAGE: |
core.gotoPage(localActionPageNum); |
scalePageToScreen(); |
action = REDRAW; |
break; |
case REDRAW: |
if ((bitmap == null) || |
(bitmap.getWidth() != patchW) || |
(bitmap.getHeight() != patchH)) |
{ |
/* make bitmap of required size */ |
bitmap = Bitmap.createBitmap(patchW, patchH, Bitmap.Config.ARGB_8888); |
} |
System.out.println("Calling redraw native method"); |
core.drawPage(bitmap, localPageW, localPageH, patchX, patchY, patchW, patchH); |
System.out.println("Called native method"); |
{ |
Canvas c = null; |
try |
{ |
c = holder.lockCanvas(null); |
synchronized(holder) |
{ |
if (localScreenGeneration == screenGeneration) |
{ |
doDraw(c); |
} |
else |
{ |
/* Someone has changed the screen |
* under us! Better redraw again... |
*/ |
action = REDRAW; |
} |
} |
} |
finally |
{ |
if (c != null) |
holder.unlockCanvasAndPost(c); |
} |
} |
} |
} |
} |
protected void doDraw(Canvas canvas) |
{ |
if ((canvas == null) || (bitmap == null)) |
return; |
/* Clear the screen */ |
canvas.drawRGB(128,128,128); |
/* Draw our bitmap on top */ |
System.out.println("Blitting bitmap from "+srcRect.left+","+srcRect.top+","+srcRect.right+","+srcRect.bottom+" to "+dstRect.left+","+dstRect.top+","+dstRect.right+","+dstRect.bottom); |
canvas.drawBitmap(bitmap, srcRect, dstRect, (Paint)null); |
} |
} |
} |