Skip to content

fix: wrap local t2i headers and inline code#6079

Open
stablegenius49 wants to merge 1 commit intoAstrBotDevs:masterfrom
stablegenius49:pr-factory/issue-5998-local-t2i-wrap
Open

fix: wrap local t2i headers and inline code#6079
stablegenius49 wants to merge 1 commit intoAstrBotDevs:masterfrom
stablegenius49:pr-factory/issue-5998-local-t2i-wrap

Conversation

@stablegenius49
Copy link
Contributor

@stablegenius49 stablegenius49 commented Mar 11, 2026

Summary

  • wrap local T2I headers with the same width-splitting logic already used by calculate_height()
  • wrap long inline-code spans into multiple rendered lines so their background/text stay inside the image bounds
  • add focused unit tests for both wrapped render paths

Testing

  • PYTHONPATH=. pytest -q tests/unit/test_local_t2i_strategy.py
  • python3 -m py_compile astrbot/core/utils/t2i/local_strategy.py tests/unit/test_local_t2i_strategy.py

Closes #5998.

Summary by Sourcery

包装本地 T2I 标题和行内代码,以适配图片宽度并改进渲染文本的布局。

Bug Fixes:

  • 确保本地 T2I 渲染中的标题文本被拆分为多行,从而保持在图片边界之内。
  • 将较长的行内代码片段换行为多行,使其背景和文本始终保持在图片区域内。

Tests:

  • 为本地 T2I 策略中标题换行和多行行内代码渲染行为添加单元测试。
Original summary in English

Summary by Sourcery

Wrap local T2I headers and inline code to respect image width and improve layout of rendered text.

Bug Fixes:

  • Ensure header text in local T2I rendering is split into multiple lines to stay within image bounds.
  • Wrap long inline code spans across multiple lines so their background and text remain inside the image area.

Tests:

  • Add unit tests covering header wrapping and inline code multi-line rendering behavior in the local T2I strategy.

@auto-assign auto-assign bot requested review from Raven95676 and anka-afk March 11, 2026 22:49
@dosubot dosubot bot added the size:L This PR changes 100-499 lines, ignoring generated files. label Mar 11, 2026
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request enhances the text-to-image rendering capabilities by addressing text overflow issues for headers and inline code. By applying intelligent text wrapping, the visual presentation of generated images is significantly improved, preventing content from extending beyond the defined image width. This ensures a more polished and readable output for text-based elements.

Highlights

  • Header Wrapping: Implemented width-splitting logic for local T2I headers, ensuring they wrap correctly within the image boundaries, similar to existing calculate_height() functionality.
  • Inline Code Wrapping: Introduced functionality to wrap long inline-code spans into multiple rendered lines, ensuring their background and text remain within the image bounds.
  • Unit Tests: Added dedicated unit tests to verify the correct behavior of both header and inline code wrapping render paths.
Changelog
  • astrbot/core/utils/t2i/local_strategy.py
    • Modified HeaderElement.render to utilize TextMeasurer.split_text_to_fit_width for wrapping header content across multiple lines.
    • Updated InlineCodeElement to include _PADDING and _LINE_HEIGHT_EXTRA constants for better control over spacing.
    • Refactored InlineCodeElement.calculate_height to account for wrapped lines when determining the total height.
    • Adjusted InlineCodeElement.render to iterate through wrapped lines, drawing a separate rounded background and text for each line.
  • tests/unit/test_local_t2i_strategy.py
    • Added a new test file to cover the new text wrapping functionalities.
    • Included test_header_element_render_wraps_long_headers to verify that header elements correctly wrap long text.
    • Added test_inline_code_element_wraps_and_draws_each_line to ensure inline code elements wrap and render each line with its own background.
Activity
  • No human activity has been recorded for this pull request yet.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@dosubot dosubot bot added the area:core The bug / feature is about astrbot's core, backend label Mar 11, 2026
Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey - 我在这里给出了一些高层次的反馈:

  • InlineCodeElement 的垂直间距和内边距值(例如 _PADDING_LINE_HEIGHT_EXTRA,以及那些硬编码的 + 4 偏移)有点随意;可以考虑把它们集中到一些命名清晰的常量或辅助方法中,这样布局计算会更容易理解,也更容易保持一致。
  • InlineCodeElement.calculate_heightInlineCodeElement.render 都在手动重新计算 line_height 和行数;可以提取一个共享的辅助方法(例如 _line_height(font_size)_layout_lines(...)),以减少重复代码,也降低这两条逻辑路径出现偏差的风险。
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The vertical spacing and padding values for `InlineCodeElement` (e.g., `_PADDING`, `_LINE_HEIGHT_EXTRA`, and the hardcoded `+ 4` offsets) are a bit ad hoc; consider centralizing them into clearly named constants or helper methods so the layout math is easier to understand and keep consistent.
- Both `InlineCodeElement.calculate_height` and `InlineCodeElement.render` manually recompute `line_height` and line counts; extracting a shared helper (e.g., `_line_height(font_size)` or `_layout_lines(...)`) would reduce duplication and the risk of these two paths drifting apart.

Sourcery 对开源项目是免费的——如果你觉得我们的 Review 有帮助,欢迎分享 ✨
帮我变得更有用!请在每条评论上点 👍 或 👎,我会根据你的反馈改进之后的 Review。
Original comment in English

Hey - I've left some high level feedback:

  • The vertical spacing and padding values for InlineCodeElement (e.g., _PADDING, _LINE_HEIGHT_EXTRA, and the hardcoded + 4 offsets) are a bit ad hoc; consider centralizing them into clearly named constants or helper methods so the layout math is easier to understand and keep consistent.
  • Both InlineCodeElement.calculate_height and InlineCodeElement.render manually recompute line_height and line counts; extracting a shared helper (e.g., _line_height(font_size) or _layout_lines(...)) would reduce duplication and the risk of these two paths drifting apart.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The vertical spacing and padding values for `InlineCodeElement` (e.g., `_PADDING`, `_LINE_HEIGHT_EXTRA`, and the hardcoded `+ 4` offsets) are a bit ad hoc; consider centralizing them into clearly named constants or helper methods so the layout math is easier to understand and keep consistent.
- Both `InlineCodeElement.calculate_height` and `InlineCodeElement.render` manually recompute `line_height` and line counts; extracting a shared helper (e.g., `_line_height(font_size)` or `_layout_lines(...)`) would reduce duplication and the risk of these two paths drifting apart.

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request effectively addresses the issue of long headers and inline code overflowing the image boundaries by implementing text wrapping. The changes are well-implemented, particularly in InlineCodeElement where a helper method and constants improve clarity. The addition of focused unit tests for the new wrapping logic is a great practice. I've identified a minor issue regarding the handling of empty inline code elements, which could result in incorrect height calculation and rendering. My specific comments provide suggestions to address this.

return font_size + 16 # 包含内边距和上下间距
font = FontManager.get_font(font_size)
lines = self._wrapped_lines(image_width, font)
return max(len(lines), 1) * (font_size + self._LINE_HEIGHT_EXTRA)
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

When self.content is empty, _wrapped_lines returns an empty list, making len(lines) zero. However, max(len(lines), 1) forces the result to be 1, causing the method to calculate the height for a single line of an empty element. This allocates unnecessary space. Removing max(..., 1) will correctly calculate a height of 0 for empty inline code. If self.content is not empty, _wrapped_lines will return a list with at least one element, so len(lines) will be sufficient.

Suggested change
return max(len(lines), 1) * (font_size + self._LINE_HEIGHT_EXTRA)
return len(lines) * (font_size + self._LINE_HEIGHT_EXTRA)

)

return y + text_height + 16 # 返回新的y坐标
return y + max(len(lines), 1) * line_height # 返回新的y坐标
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

Similar to the issue in calculate_height, using max(len(lines), 1) will cause the y coordinate to advance even for an empty inline code element, which is inconsistent since nothing is rendered. By using len(lines) directly, the y coordinate will not change if there are no lines to render, which is the correct behavior.

Suggested change
return y + max(len(lines), 1) * line_height # 返回新的y坐标
return y + len(lines) * line_height # 返回新的y坐标

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:core The bug / feature is about astrbot's core, backend size:L This PR changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] 文本转图像local模式下文本超出图片边界

2 participants