乐于分享
好东西不私藏

PDF阅读器开发遇到的问题

PDF阅读器开发遇到的问题

1、显示不全,横向、纵向显示不全

原因:问题在于手动处理页面变换时坐标计算复杂且容易出错。
解决方式:采用用MuPDF的高级API fz_new_pixmap_from_page 完全重写 renderPageStatic。

2、字体不清晰、重影

主要由以下原因造成:
  1. DPI未适配 - 没有考虑屏幕DPI缩放,导致渲染分辨率不足
  2. 非整数缩放 - 渲染时使用了非整数缩放比例,造成字体模糊
  3. 缺少高质量渲染提示 - QPainter未启用SmoothPixmapTransfor
解决方式:
1. main.cpp - 高DPI支持
  • 添加 Qt::AA_EnableHighDpiScaling 属性
  • 输出屏幕DPI调试信息 2. mupdfpdfreader.cpp - DPI感知高分辨率渲染
  • 新增 getDpiScaleFactor() 函数获取屏幕DPI
  • renderPageStatic() 和 renderPage() 使用 2.0 * dpiScale 作为渲染缩放因子
  • 以2倍DPI的高分辨率渲染页面,确保字体清晰 3. pageitem.h / pageitem.cpp - 逻辑尺寸布局
  • 新增 m_displaySize 成员存储逻辑显示尺寸
  • 新增 setDisplaySize() 方法
  • boundingRect() 返回逻辑尺寸(而非图像像素尺寸)
  • paint() 将高分辨率图像缩放到逻辑尺寸,使用 SmoothPixmapTransform 保证缩放质量 4. docview.cpp - 渲染提示优化
  • 启用 QPainter::SmoothPixmapTransform
  • 启用 QPainter::TextAntialiasing 5. mainwindow.cpp - 页面布局
  • renderVisiblePages() 使用逻辑尺寸( m_pageWidth / m_pageHeight )布局
  • 调用 pageItem->setDisplaySize() 设置逻辑显示尺寸
  • 场景尺寸使用逻辑尺寸计算

3、窗体关闭时候,出现

## 问题分析

错误ctx->error.top == ctx->error.stack_base 是因为:
  1. fz_try(ctx) 会在错误栈上压入一个帧
  2. fz_catch(ctx) 才会弹出这个帧
  3. 我们在 fz_try 块内部提前 return 或调用 fz_drop_context ,导致错误栈帧未被弹出
  4. 当 MuPDF 销毁上下文时,发现错误栈不为空,触发断言失败
解决方式:
在 fz_try 块内部提前返回或销毁上下文。

4、打开一个文件,再打开一个文件,提示错误

问题分析:
  1. 当打开第一个文件时, renderVisiblePages() 启动异步渲染(通过 m_renderWatcher )
  2. 当打开第二个文件时,on_actionOpenFile_triggered() 中:
  3. 调用m_currentDoc->closeFile() 和 deleteLater() 关闭旧文档
  4. 但没有取消m_renderWatcher ——这是关键问题!
  5. 后台渲染线程仍在运行,访问已被删除的 m_currentDoc ,导致内存访问错误,进而使 MuPDF 上下文状态异常
  6. 新文档的 openFile() 因此失败,显示"无法打开文档"
修复方案:
  • 在删除旧文档前,先取消 m_renderWatcher 并等待其完成
  • 使用 delete 替代 deleteLater() 确保立即清理
  • 在initDocumentLayout 和 closeCurrentDocument 中也添加安全取消逻辑

5、打开文件一个文件,再打开一个文件,出现崩溃。

原因:使用已释放内存
  1. delete m_renderWatcher —删除了 watcher,但 m_renderWatcher 指针没有置为 nullptr
  2. closeFile() 中检查 if (m_renderWatcher && m_renderWatcher->isRunning()) —m_renderWatcher 是非空的悬空指针,条件为 true
  3. m_renderWatcher->isRunning()访问已释放内存→崩溃
解决方式:
deletem_renderWatcher; 之后增加m_renderWatcher =nullptr;