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);拓展可以拓展其它功能:笔记/修改,新建笔记;    功能:选择字体大小         选择背景



0 0
原创粉丝点击