@@ -514,10 +514,13 @@ def put_text_vertical(font_size: int, text: str, h: int, alignment: str, fg: Tup
514514 bg_size = int (max (font_size * 0.07 , 1 )) if bg is not None else 0
515515 spacing_x = int (font_size * (line_spacing or 0.2 ))
516516
517- # Conditional wrapping logic based on the new region_count parameter
517+ # Conditional wrapping logic based on disable_auto_wrap and region_count
518518 effective_max_height = h
519- if config and config .render .layout_mode == 'smart_scaling' :
520- if config .render .disable_auto_wrap or region_count <= 1 :
519+ if config and config .render .disable_auto_wrap :
520+ # 当AI断句开启时,使用无限高度,让文本按AI断句标记换行
521+ effective_max_height = 99999
522+ elif config and config .render .layout_mode == 'smart_scaling' :
523+ if region_count <= 1 :
521524 effective_max_height = 99999
522525
523526 # Use original font size for line breaking calculation
@@ -714,7 +717,26 @@ def calc_horizontal(font_size: int, text: str, max_width: int, max_height: int,
714717 whitespace_offset_x = get_char_offset_x (font_size , ' ' )
715718 hyphen_offset_x = get_char_offset_x (font_size , '-' )
716719
717- words = re .split (r'\s+' , text )
720+ # 先按换行符分割段落,然后对每段分割单词
721+ # 使用特殊标记来保留换行位置
722+ paragraphs = text .split ('\n ' )
723+ words = []
724+ newline_positions = set () # 记录哪些位置是段落结束(需要强制换行)
725+
726+ for para_idx , paragraph in enumerate (paragraphs ):
727+ if paragraph .strip (): # 非空段落
728+ para_words = re .split (r'[ \t]+' , paragraph ) # 只按空格和制表符分割,不包括 \n
729+ words .extend (para_words )
730+ if para_idx < len (paragraphs ) - 1 : # 不是最后一段
731+ newline_positions .add (len (words ) - 1 ) # 标记这个单词后面需要换行
732+ elif para_idx < len (paragraphs ) - 1 : # 空段落但不是最后一个
733+ # 空行也需要保留
734+ words .append ('' )
735+ newline_positions .add (len (words ) - 1 )
736+
737+ # 如果没有单词,返回空结果
738+ if not words :
739+ return [], []
718740
719741 word_widths = []
720742 for i , word in enumerate (words ):
@@ -804,6 +826,9 @@ def get_present_syllables(line_idx, word_pos):
804826 line_words .append (i )
805827 line_width += current_width + word_widths [i ]
806828 i += 1
829+ # 检查是否需要强制换行(AI 断句)
830+ if (i - 1 ) in newline_positions :
831+ break_line ()
807832 elif word_widths [i ] > max_width :
808833 j = 0
809834 hyphenation_idx = 0
@@ -824,8 +849,18 @@ def get_present_syllables(line_idx, word_pos):
824849 line_words .append (i )
825850 line_width += current_width
826851 i += 1
852+ # 检查是否需要强制换行(AI 断句)
853+ if (i - 1 ) in newline_positions :
854+ break_line ()
827855 else :
828- break_line ()
856+ if hyphenate :
857+ break_line ()
858+ else :
859+ line_words .append (i )
860+ line_width += current_width + word_widths [i ]
861+ i += 1
862+ if (i - 1 ) in newline_positions :
863+ break_line ()
829864
830865
831866 # 连字符优化阶段
@@ -1050,16 +1085,23 @@ def put_text_horizontal(font_size: int, text: str, width: int, height: int, alig
10501085 layout_mode = 'default'
10511086 if config :
10521087 layout_mode = config .render .layout_mode
1053- # Check for no-wrap condition and handle AI line breaks
1054- if layout_mode == 'smart_scaling' :
1055- # In smart_scaling mode, wrapping is conditional.
1056- # It wraps only if manual line breaks ([BR] or \n) are present.
1057- # Otherwise, it expands without wrapping.
1058- text = re .sub (r'\s*\[BR\]\s*' , '\n ' , text , flags = re .IGNORECASE )
1059- if '\n ' not in text :
1060- # No manual breaks found, so disable wrapping by setting a large width.
1061- if config .render .disable_auto_wrap or region_count <= 1 :
1062- width = 99999
1088+
1089+ # 当AI断句开启时,统一处理换行符并使用无限宽度
1090+ if config and config .render .disable_auto_wrap :
1091+ # 统一处理所有类型的AI换行符
1092+ text = re .sub (r'\s*(\[BR\]|<br>|【BR】)\s*' , '\n ' , text , flags = re .IGNORECASE )
1093+ # 使用无限宽度,让文本完全按照AI断句标记换行
1094+ width = 99999
1095+ elif layout_mode == 'smart_scaling' :
1096+ # In smart_scaling mode, wrapping is conditional.
1097+ # It wraps only if manual line breaks ([BR] or \n) are present.
1098+ # Otherwise, it expands without wrapping.
1099+ # 统一处理所有类型的AI换行符
1100+ text = re .sub (r'\s*(\[BR\]|<br>|【BR】)\s*' , '\n ' , text , flags = re .IGNORECASE )
1101+ if '\n ' not in text :
1102+ # No manual breaks found, so disable wrapping by setting a large width.
1103+ if region_count <= 1 :
1104+ width = 99999
10631105
10641106 bg_size = int (max (font_size * 0.07 , 1 )) if bg is not None else 0
10651107 spacing_y = int (font_size * (line_spacing or 0.01 ))
0 commit comments