Skip to content

fix(reader): clamp OFD render slices to page canvas - #382

Closed
add-uos wants to merge 2 commits into
linuxdeepin:ofd_supportfrom
add-uos:fix-ofd-render-slice-out-of-canvas
Closed

add-uos wants to merge 2 commits into
linuxdeepin:ofd_supportfrom
add-uos:fix-ofd-render-slice-out-of-canvas

Conversation

@add-uos

@add-uos add-uos commented Sep 14, 2026

Copy link
Copy Markdown
Contributor

问题

打开 OFD 文档时出现两类渲染异常(样例:发票监制章-数科.ofd):

  1. <deepin_reader::OfdDocument::renderPage:493> OFD render region outside canvas: QRect(1000,0 1000x1542) QRect(0,0 1090x1542)

    • 大图任务按 1000px 宽度分片时,末尾分片未截断到页面实际宽度:页宽 1090px 时生成 QRect(1000,0,1000,1542)(右边界到 2000),越界请求被 OfdDocument::renderPage 的保护检查拒绝,页面右侧留白
    • PDF 未暴露此问题是因为 pdfium 自动裁剪越界区域,rofd C ABI 则严格拒绝
  2. 放大镜 BrowserPage::getImagePoint 在悬停点靠近页边时同样产生越界请求矩形

修复

均为调用方按契约收敛请求,保持 OfdDocument::renderPage 的严格越界检查不变:

  • reader/browser/PageRenderThread.cpp:分片循环改为步进累加 + qMin(1000, width - i),末尾分片自动截断
  • reader/browser/BrowserPage.cppgetImagePoint 先将请求矩形与整页画布求交集(取整方式与 getImage 参数一致),空矩形直接返回空图

验证

  • 实际打开发票监制章-数科.ofd:日志中 0 次 "render region outside canvas"、0 次 "page render failed",页面完整渲染
  • 单测:OFD 模型 31 项、浏览器相关 87 项全部通过(含 renderSmallRegionOnHugeCanvasrejectInvalidRegions 等既有越界契约用例)

Summary by Sourcery

Clamp browser rendering requests to page boundaries so OFD documents render completely without rejected out-of-bounds regions.

Bug Fixes:

  • Prevent OFD page rendering failures and blank areas by clamping tiled render regions to the page canvas.
  • Prevent magnifier requests near page edges from issuing invalid out-of-bounds render regions.

Enhancements:

  • Preserve strict document-model bounds validation while ensuring callers submit valid render rectangles.

Chores:

  • Add the applicable REUSE dependency licensing metadata.

The big-image task split pages into 1000px-wide tiles without
clamping the last tile to the actual page width. Pages whose width
was not a multiple of 1000 produced out-of-canvas requests that the
OFD document model rejects, leaving the right edge unpainted. The
magnifier (getImagePoint) could also request rects beyond the canvas
near page edges; intersect the rect with the canvas first.

大图任务按1000px分片时末尾未截断到页面实际宽度,页宽非1000整数倍
时越界请求被OFD文档模型拒绝,页面右侧无法绘制;放大镜在页边悬停
时同样可能越界,先与整页画布求交集。

Log: 修复OFD分片越界导致页面右侧渲染缺失
Influence: OFD文档大图分片与放大镜渲染不再产生越界请求,页面右侧不再缺失。
@sourcery-ai

sourcery-ai Bot commented Sep 14, 2026

Copy link
Copy Markdown
Reviewer's guide (collapsed on small PRs)

Reviewer's Guide

Fix OFD rendering gaps and magnifier failures by constraining caller-generated regions to the page canvas: tiled rendering now truncates the final slice, and point-based magnifier requests are intersected with the scaled canvas while the renderer’s strict validation remains unchanged.

Sequence diagram for clamped OFD page rendering

sequenceDiagram
    participant PageRenderThread
    participant OfdDocument
    PageRenderThread->>PageRenderThread: run()
    loop Each 1000px slice
        PageRenderThread->>OfdDocument: renderPage(clamped QRect)
        OfdDocument-->>PageRenderThread: rendered slice
    end
    Note over PageRenderThread,OfdDocument: Final slice width is qMin(1000, task.rect.width() - i)
Loading

File-Level Changes

Change Details Files
Clamp tiled page-render requests so the final horizontal slice stays within the page canvas.
  • Replace fixed-width slice counting with width-stepped iteration.
  • Use the remaining width to size the final slice via qMin(1000, remaining width).
reader/browser/PageRenderThread.cpp
Clamp magnifier image requests to the scaled page canvas before rendering.
  • Intersect the computed hover rectangle with the canvas using the existing rounding conventions.
  • Return an empty image when the intersection is empty.
  • Preserve strict out-of-bounds rejection in the document renderer by fixing requests at the call site.
reader/browser/BrowserPage.cpp

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@deepin-ci-robot

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: add-uos

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've reviewed your changes and they look great!


Sourcery is free for open source - if you like our reviews please consider sharing them ✨

The ofd_support branch added four OFD design docs under docs/
without copyright or licensing declarations, which made the
license-check workflow fail on every PR touching this branch. Add
a dep5 entry covering docs/ with GPL-3.0-or-later, consistent with
the source tree.

ofd_support 分支在 docs/ 下新增了四个 OFD 设计文档,缺少版权与
许可声明,导致 license-check 流水线对所有 PR 都会失败。在 dep5
中补充 docs/ 条目,与源码目录一致使用 GPL-3.0-or-later。

Log: 补充docs目录REUSE声明修复流水线license-check失败
Influence: 仓库通过REUSE 3.3合规检查,docs目录许可与源码一致。
@deepin-ci-robot

Copy link
Copy Markdown

deepin pr auto review

🤖 AI 代码审查报告

总体评分: 99 分 (通过阈值: 70分)

Pass


📊 总体评价

项目 结果
审查结论 代码审查通过
评分详情 总体评分 99 分,大于 70 分通过阈值。本次提交修复了 OFD 文档渲染分片越界问题,代码逻辑正确,注释清晰,无安全漏洞。

🔍 详细分析

1. 语法逻辑 ✅

评价: 优秀 ✅ 通过

潜在问题:
✅ 未发现明显问题

建议: 语法正确,逻辑清晰,边界处理完善。BrowserPage.cpp 中 getImagePoint 函数新增画布交集与空矩形检查,逻辑严谨;PageRenderThread.cpp 中分片循环重构为步进式遍历并使用 qMin 截断末尾分片宽度,逻辑正确。


2. 代码质量 ✅

评价: 优秀 ✅ 通过

潜在问题:
✅ 未发现明显问题

建议: 代码结构清晰,注释完整。建议将分片宽度 1000 提取为命名常量(如 kSliceWidth)以增强可维护性。新增的中文注释清晰解释了修复原因和背景。


3. 代码性能 ✅

评价: 优秀 ✅ 通过

潜在问题:
✅ 未发现明显问题

建议: 性能良好,资源使用合理。QRect::intersected() 为 O(1) 操作开销极低;重构后的分片循环移除了取模和条件运算,性能略有提升;新增的 rect.isEmpty() 检查避免了无效渲染器调用。


4. 代码安全 🔒

评价: 优秀 ✅ 通过

🔐 发现 0 个安全漏洞

安全漏洞详情:
✅ 未发现安全漏洞

建议: 存在0个安全漏洞。本次修复实际上增强了代码健壮性,通过画布交集和分片宽度截断防止了越界渲染请求。无用户输入处理风险,无硬编码密钥,无注入风险。


💡 改进建议代码示例

// 建议将魔法数字提取为命名常量
static constexpr int kSliceWidth = 1000;

// PageRenderThread.cpp 改进示例
for (int i = 0; i < task.rect.width(); i += kSliceWidth) {
    renderRects.append(QRect(i, 0, qMin(kSliceWidth, task.rect.width() - i), task.rect.height()));
}

本报告由 AI 代码审查工具自动生成

@add-uos

add-uos commented Sep 14, 2026

Copy link
Copy Markdown
Contributor Author

此修复已并入整体功能 PR #383(OFD 文档支持直接进入 master),包含本 PR 的渲染分片修复提交 fix(reader): clamp OFD render slices to page canvas,请移步 #383 评审。

@add-uos add-uos closed this Sep 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants