PDF阅读器系列之--MuPDF源码分析过程(二)
来源:互联网 发布:贵阳网络广播电视台 编辑:程序博客网 时间:2024/05/18 09:20
分析
初看项目工程目录结构,不是很多,直接看类的字面意思均可以得出一些浅显易懂的知识点
1.看清单文件得出来有4个activity
在ChooseActivity中,添加了多个intent-filter意图过滤器,其作用就是规定一些格式文件,一些支持的类型
2.进入src中
tip :项目代码中大量运用枚举
ChoosePDFActivity是程序的主界面,分类型,是文件夹是就进行打开,pdf就跳转等待结果
ChoosePDFAdapter是加载sd卡文件信息,3中type:上一层,文件夹,文件
MuPDFReflowView继承WebView
MuPDFCore 是声明本地方法并加载so的类:功能用c实现
/* The core rendering instance */
enumTopBarMode {Main, Search, Annot, Delete, More, Accept};
enumAcceptMode {Highlight, Underline, StrikeOut, Ink, CopyText};
3.再看xml
布局文件在 buttons.xml下,采用的是ViewAnimator(视图切换)
draw的逻辑分析
draw相关的类MuPDFActivity MuPDFReaderView ReaderView PageView MuPDFPageView
充分利用 ctrl+shift +F 查找你想要的信息
//墨迹Ink 绘制按钮
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));
}
在源PDF文件上绘制图层,找到触发绘制的事件,追踪绘制的逻辑
MuPDFActivity MuPDFReaderView ReaderView PageView MuPDFPageView
Point类: Point holds two integer coordinates
MuPDFPageView继承PageView
在MuPDFReaderView中
touch事件
touch_start touch_move
在方法中都使用MuPDFView,实现MuPDFView接口,中startDraw continueDraw方法
有个问题:当状态为 Drawing时,双手可以进行缩放
Annot 是Annotation的缩写:代表注释状态
总结如下:
1.mupdfdemo他核心代码是用本地C写的,java调用在MuPDFCore类中
2.几个重要的类分别是
MuPDFActivity控制相关按钮事件
PageView中绘制相关
MuPDFView 继承PageView
reflow 跟重排版文档相关
print 跟打印相关
ordinary 回到TopBarMode.main类型
重点分析MuPDFActivity.java
//注释 点击已绘制区域,可删除//注释 点击已绘制区域,可删除
publicvoidOnDeleteButtonClick(View v) {
MuPDFView pageView = (MuPDFView) mDocView.getDisplayedView();
if (pageView != null)
pageView.deleteSelectedAnnotation();
LogUtils.d(TAG,"OnDeleteButtonClick: ");
mTopBarMode = TopBarMode.Annot;
mTopBarSwitcher.setDisplayedChild(mTopBarMode.ordinal());
}
//注释 点击已绘制区域,可返回
publicvoidOnCancelDeleteButtonClick(View v) {
MuPDFView pageView = (MuPDFView) mDocView.getDisplayedView();
if (pageView != null)
pageView.deselectAnnotation();
LogUtils.d(TAG,"OnCancelDeleteButtonClick: ");
mTopBarMode = TopBarMode.Annot;
mTopBarSwitcher.setDisplayedChild(mTopBarMode.ordinal());
}
思路
触摸PDF view 执行的一些事件
ReaderView.java
1。点击屏幕中央:
2.点击屏幕左边或者右边:
2016年2月29日16:05:53
先实现 绘制页面,添加几个按钮:前进,撤销,颜色选择;
实现结果就是在相应模式下面点击新增按钮实现不同的效果
一、实现绘制回退功能
需求:点击画笔之后绘制一笔后,点击此按钮,能够撤销操作
1.
二、实现绘制前进功能(待议)
需求:在撤销操作后,点击此按钮,能够前进操作
三、实现画笔颜色选择功能
需求:选择你想要的画笔颜色,能够绘制不同颜色的笔迹
1.popuwindow
难点:目前mupdf的 绘制功能在pageview中
代码:
//注释 绘制墨迹if (mDrawing != null) { LogUtils.d(TAG,"paint的绘制"); Path path = new Path(); PointF p; paint.setAntiAlias(true); paint.setDither(true); paint.setStrokeJoin(Paint.Join.ROUND); paint.setStrokeCap(Paint.Cap.ROUND); paint.setStyle(Paint.Style.FILL); paint.setStrokeWidth(INK_THICKNESS * scale); paint.setColor(INK_COLOR); Iterator<ArrayList<PointF>> it = mDrawing.iterator(); while (it.hasNext()) { ArrayList<PointF> arc = it.next(); if (arc.size() >= 2) { Iterator<PointF> iit = arc.iterator(); p = iit.next(); float mX = p.x * scale; float mY = p.y * scale; path.moveTo(mX, mY); while (iit.hasNext()) { p = iit.next(); float x = p.x * scale; float y = p.y * scale; path.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2); mX = x; mY = y; } path.lineTo(mX, mY); } else { p = arc.get(0); canvas.drawCircle(p.x * scale, p.y * scale, INK_THICKNESS * scale / 2, paint); } } paint.setStyle(Paint.Style.STROKE); canvas.drawPath(path, paint);}
分析
想拿到当前绘制的paint对象,以及绘制的路径path,存入集合中,
问:对paint熟悉吗,撤销和恢复怎么实现
如何保证在绘制过程中不丢帧,即在绘制过程中控制笔迹很流畅
源码分析 找不到 接收保存绘制后的红色笔迹,再议 2016年3月1日17:58:50
头好晕….
2016年3月2日09:28:37 星期三
再次使用AS进行debug调试,定位在接受按钮点击事件方法中 头 尾 2个断点
当进行到最后一句代码时
mDocView.setMode(MuPDFReaderView.Mode.Viewing);
force step into 强制进入内部 观察代码执行过程
最后跟踪到View类中的几个方法
setForegroundTintMode 、getForegroundTintMode、applyForegroundTint
/** * Applies a tint to the foreground drawable. Does not modify the current tint * mode, which is {@link PorterDuff.Mode#SRC_IN} by default. * <p> * Subsequent calls to {@link #setForeground(Drawable)} will automatically * mutate the drawable and apply the specified tint and tint mode using * {@link Drawable#setTintList(ColorStateList)}. * * @param tint the tint to apply, may be {@code null} to clear tint * * @attr ref android.R.styleable#View_foregroundTint * @see #getForegroundTintList() * @see Drawable#setTintList(ColorStateList) */public void setForegroundTintList(@Nullable ColorStateList tint) { if (mForegroundInfo == null) { mForegroundInfo = new ForegroundInfo(); } if (mForegroundInfo.mTintInfo == null) { mForegroundInfo.mTintInfo = new TintInfo(); } mForegroundInfo.mTintInfo.mTintList = tint; mForegroundInfo.mTintInfo.mHasTintList = true; applyForegroundTint();}/** * Return the tint applied to the foreground drawable, if specified. * * @return the tint applied to the foreground drawable * @attr ref android.R.styleable#View_foregroundTint * @see #setForegroundTintList(ColorStateList) */@Nullablepublic ColorStateList getForegroundTintList() { return mForegroundInfo != null && mForegroundInfo.mTintInfo != null ? mForegroundInfo.mTintInfo.mTintList : null;}/** * Specifies the blending mode used to apply the tint specified by * {@link #setForegroundTintList(ColorStateList)}} to the background * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}. * * @param tintMode the blending mode used to apply the tint, may be * {@code null} to clear tint * @attr ref android.R.styleable#View_foregroundTintMode * @see #getForegroundTintMode() * @see Drawable#setTintMode(PorterDuff.Mode) */public void setForegroundTintMode(@Nullable PorterDuff.Mode tintMode) { if (mForegroundInfo == null) { mForegroundInfo = new ForegroundInfo(); } if (mForegroundInfo.mTintInfo == null) { mForegroundInfo.mTintInfo = new TintInfo(); } mForegroundInfo.mTintInfo.mTintMode = tintMode; mForegroundInfo.mTintInfo.mHasTintMode = true; applyForegroundTint();}/** * Return the blending mode used to apply the tint to the foreground * drawable, if specified. * * @return the blending mode used to apply the tint to the foreground * drawable * @attr ref android.R.styleable#View_foregroundTintMode * @see #setForegroundTintMode(PorterDuff.Mode) */@Nullablepublic PorterDuff.Mode getForegroundTintMode() { return mForegroundInfo != null && mForegroundInfo.mTintInfo != null ? mForegroundInfo.mTintInfo.mTintMode : null;}private void applyForegroundTint() { if (mForegroundInfo != null && mForegroundInfo.mDrawable != null && mForegroundInfo.mTintInfo != null) { final TintInfo tintInfo = mForegroundInfo.mTintInfo; if (tintInfo.mHasTintList || tintInfo.mHasTintMode) { mForegroundInfo.mDrawable = mForegroundInfo.mDrawable.mutate(); if (tintInfo.mHasTintList) { mForegroundInfo.mDrawable.setTintList(tintInfo.mTintList); } if (tintInfo.mHasTintMode) { mForegroundInfo.mDrawable.setTintMode(tintInfo.mTintMode); } // The drawable (or one of its children) may not have been // stateful before applying the tint, so let's try again. if (mForegroundInfo.mDrawable.isStateful()) { mForegroundInfo.mDrawable.setState(getDrawableState()); } } }}发现这几个方法都有传入ColorStateList引用,点进去一看,找到了原来默认的颜色是红色;再次回到 OnAcceptButtonClick点击方法中来/*################### 添加注释 #################*///注释 这个方法是当用户完成相应操作后,点击保存时的事件// Edited by Oayiel on ${DATE}.public void OnAcceptButtonClick(View v) { LogUtils.d(TAG, "OnAcceptButtonClick: "); 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 = pageView.markupSelection(Annotation.Type.UNDERLINE); mTopBarMode = TopBarMode.Annot; if (!success) showInfo(getString(R.string.no_text_selected)); break; case StrikeOut: //删除线 if (pageView != null) success = pageView.markupSelection(Annotation.Type.STRIKEOUT); mTopBarMode = TopBarMode.Annot; if (!success) showInfo(getString(R.string.no_text_selected)); break; case Ink: //墨迹 //注释 添加va TODO 动画效果 mViewAnimator.setVisibility(View.INVISIBLE); if (pageView != null) LogUtils.d(TAG,"保存已经绘制好的墨迹"); success = pageView.saveDraw(); mTopBarMode = TopBarMode.Annot; if (!success) showInfo(getString(R.string.nothing_to_save)); break; } mTopBarSwitcher.setDisplayedChild(mTopBarMode.ordinal()); mDocView.setMode(MuPDFReaderView.Mode.Viewing); //绘制 回到观察模式 //注释 绘制后的笔迹是走的View--getForegroundTintList--ColorStateList默认的红色}经过测试 发现Underline:是蓝色,StrikeOut和Ink默认走的系统红色不知道从哪改这种颜色 TODO:修改后保存的文件也能被打开?
@Override
public void onBackPressed() {
//注释 发生绘制事件时,提示用户是否保存
if (core != null && core.hasChanges()) {
DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
if (which == AlertDialog.BUTTON_POSITIVE)
core.save();
finish(); } }; AlertDialog alert = mAlertBuilder.create(); alert.setTitle("MuPDF"); alert.setMessage(getString(R.string.document_has_changes_save_them_)); alert.setButton(AlertDialog.BUTTON_POSITIVE, getString(R.string.yes), listener); alert.setButton(AlertDialog.BUTTON_NEGATIVE, getString(R.string.no), listener); alert.show();} else { super.onBackPressed(); } }
绘制的 撤销,恢复,画笔颜色,画笔粗细
自定义一个PaintView 实现撤销恢复操作2016年3月2日18:11:22
绘制的功能全是在MuPDFView接口中定义好了
在PageView中与接口中方法同名,如撤销&恢复&保存等,利用子类继承父类并且实现该接口的方式,在activity中click事件中先拿到当前的view对象,强制转换为MuPDFView接口类型
MuPDFView :
public void cancelDraw(int i); //撤销
public class MuPDFPageView extends PageView implements MuPDFView {
MuPDFView pageView = (MuPDFView) mDocView.getDisplayedView();
if (v == mInkBack) {
pageView.cancelDraw(0);
PageView:
MuPDFView:
MuPDFActivity:
Buttons.xml:
txt功能以另一种引擎方式进行打开
之前的想法:方向对了,但是无法与开源项目联系起来 public static ArrayList<View> mViews = new ArrayList<View>(); public static DrawViewListener mDrawViewListener; public static void setDrawViewListener(DrawViewListener drawViewListener) { mDrawViewListener = drawViewListener; } public interface DrawViewListener { void onDrawView(View view, ArrayList<ArrayList<PointF>> drawing); } //注释 添加事件 /** * 撤销的核心思想就是将画布清空, * 将保存下来的Path路径最后一个移除掉, * 重新将路径画在画布上面。 */ public void undo() { LogUtils.d(TAG, "PageView's -- undo"); if (savePath != null && savePath.size() > 0) { //调用初始化画布函数以清空画布 // initCanvas(); //将路径保存列表中的最后一个元素删除 ,并将其保存在路径删除列表中 DrawPath drawPath = savePath.get(savePath.size() - 1); deletePath.add(drawPath); savePath.remove(savePath.size() - 1); //将路径保存列表中的路径重绘在画布上 Iterator<DrawPath> iter = savePath.iterator(); //重复保存 while (iter.hasNext()) { DrawPath dp = iter.next(); mCanvas.drawPath(dp.path, dp.paint); } invalidate();// 刷新 } } /** * 恢复的核心思想就是将撤销的路径保存到另外一个列表里面(栈), * 然后从redo的列表里面取出最顶端对象, * 画在画布上面即可 */ public void redo() { LogUtils.d(TAG, "PageView's -- redo"); if (deletePath.size() > 0) { //将删除的路径列表中的最后一个,也就是最顶端路径取出(栈),并加入路径保存列表中 DrawPath dp = deletePath.get(deletePath.size() - 1); savePath.add(dp); //将取出的路径重绘在画布上 mCanvas.drawPath(dp.path, dp.paint); //将该路径从删除的路径列表中去除 deletePath.remove(deletePath.size() - 1); invalidate(); } } private Canvas mCanvas; private ArrayList<DrawPath> savePath = new ArrayList<>(); private ArrayList<DrawPath> deletePath = new ArrayList<>(); //路径对象 class DrawPath { Path path; Paint paint; }
试了一下,还是git提交到github保存吧橡皮擦功能:触摸笔迹消失选择绘笔粗细 setStrokeWidth选择绘笔颜色 setColor复制文本到粘贴板跳转页面:结合 seekbar(可自定义)txt文件:给个跳转到另一个解码库 String path = mFiles[position].getAbsolutePath(); if(path.endsWith("txt")){ Toast.makeText(ChoosePDFActivity.this, "PickTXT", Toast.LENGTH_SHORT).show(); //如果点击了txt格式文件,跳转至txt解码器 TODO txt解码// startActivity(new Intent(this,TXTActivity.class)); }else {可以新建txt文件,操作Rss:网络阅读器jsonsettings:TODO浏览最近的文件:VudroidUI:ChoosePDFItem:Type(PARENT,DIR,DOC),显示对应icon搜索功能 TODOTXT文件解码相关//打开txt文本格式的逻辑private void open(Bookmark bookmark) { Intent intent = new Intent(BookmarkListActivity.this, ReadActivity.class); intent.setData(Uri.parse("file://" + bookmark.getPath())); startActivity(intent);} ReadActivity ReadView BookmarkManager复制到系统粘贴板ClipboardManager cbm = (ClipboardManager) getContext().getSystemService(Context.CLIPBOARD_SERVICE);cbm.setPrimaryClip(ClipData.newPlainText(null, content.toString()));
Typeface typeface = Typeface.createFromAsset(context.getAssets(),"fonts/FZBYSK.TTF");11https://github.com/lfkdsk/JustWeTools#readview%E5%B0%8F%E8%AF%B4%E9%98%85%E8%AF%BB 不是打广告啊,是这个博主写的真的好<activity android:name="com.cinread.ebook.TXTActivity" android:theme="@android:style/Theme.Light.NoTitleBar.Fullscreen"> <intent-filter> <action android:name="android.intent.action.VIEW"/> <category android:name="android.intent.category.DEFAULT"/> <category android:name="android.intent.category.BROWSABLE"/> <data android:scheme="file"/> <data android:mimeType="*/*"/> <data android:pathPattern=".*\\.txt"/> <data android:host="*"/> </intent-filter> </activity>1234567891011121312345678910111213public class TXTActivity extends Activity { private ReadView readView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); File dir = null; Uri fileUri = getIntent().getData(); if (fileUri != null) { dir = new File(fileUri.getPath()); } readView = null; if (dir != null) { readView = new ReadView(this,dir.getPath()); } else finish(); setContentView(readView); }}String path = mFiles[position].getAbsolutePath(); if(path.endsWith("txt")){ //如果点击了txt格式文件,跳转至txt解码器 TODO txt解码 Intent intent = new Intent(this, TXTActivity.class); intent.setAction(Intent.ACTION_VIEW); intent.setData(Uri.parse("file://"+path)); startActivity(intent);拓展可以拓展其它功能:笔记/修改,新建笔记; 功能:选择字体大小 选择背景
- PDF阅读器系列之--MuPDF源码分析过程(二)
- PDF阅读器系列之--MuPDF源码分析过程(二)
- PDF阅读器系列之--MuPDF源码分析过程(一)
- PDF阅读器系列之--MuPDF源码分析过程(一)
- 我的PDF阅读器之muPDF的编译
- Mupdf源码分析之MuPDFActivity类分析(一)
- iOS 中使用Mupdf教程 pdf阅读器
- mupdf源码分析
- MuPDF 开源PDF库编译过程记录
- Android使用MuPDF查看pdf文件之源码的下载与编译
- elasticsearch源码分析之启动过程(二)
- elasticsearch源码分析之启动过程(二)
- Elasticsearch源码分析之二------索引过程源码概要分析
- ElasticSearch源码分析之二:索引过程源码概要分析
- mupdf 篇二,修改渲染过程
- android WifiDisplay 源码分析系列 (二)
- DbUtils源码分析系列(二)
- 车道检测源码分析系列(二)
- spring 加载xml
- redis数据库--操作对象
- UITextView改变选中字的颜色
- 应用JNI进行差分更新
- unity 关于Rotation和Quaternion的一些问题(欧拉角与四元数,lerp与slerp)
- PDF阅读器系列之--MuPDF源码分析过程(二)
- (java)根据map中value进行排序
- C++实验4—输出星号图
- 学习新语言
- PHP实现冒泡排序
- imageNamed和imageWithContentsOfFile-无法加载图片的问题
- A Knight's Journey(搜索题)
- Eclipse配置PyDev插件安装方法
- Bestcoder Pro.ID 2006 求奇数的乘积