| 192 | |
| 193 | |
| 194 | class RichTextGenerator(Generator): |
| 195 | @staticmethod |
| 196 | def generate(segment: TextSegment) -> Image.Image: |
| 197 | font = load_font(segment.font_path) |
| 198 | |
| 199 | # 获取文本尺寸 |
| 200 | metrics = font.getmetrics() |
| 201 | text = ' ' if not segment.text or segment.text == '' else segment.text |
| 202 | bbox = font.getbbox(text) |
| 203 | # 创建透明画布 |
| 204 | image = Image.new('RGBA', (int(bbox[2] - bbox[0]), metrics[0] + abs(metrics[1])), (0, 0, 0, 0)) |
| 205 | draw = ImageDraw.Draw(image) |
| 206 | # 直接绘制文本 |
| 207 | draw.text((0, 0), text, font=font, fill=_parse_color(segment.color)) |
| 208 | |
| 209 | # 使用 start_process 处理图片,解耦对 Filter 的直接依赖 |
| 210 | pipeline = [ |
| 211 | { |
| 212 | "processor_name": "trim", |
| 213 | "trim_top": segment.trim, |
| 214 | "trim_bottom": segment.trim, |
| 215 | "save_buffer": False, |
| 216 | }, |
| 217 | { |
| 218 | "processor_name": "resize", |
| 219 | "height": segment.height * 1.13 if segment.is_bold else segment.height, |
| 220 | "save_buffer": False, |
| 221 | } |
| 222 | ] |
| 223 | # 使用临时 buffer 路径(实际上是 image 对象) |
| 224 | from processor.core import start_process |
| 225 | return start_process(pipeline, input_path=None, output_path=None, initial_buffer=[image]) |
| 226 | |
| 227 | def process(self, ctx: PipelineContext): |
| 228 | img = RichTextGenerator.generate(TextSegment.from_dict(ctx)) |
| 229 | ctx.update_buffer([img]).save_buffer(self.name()).success() |
| 230 | |
| 231 | def name(self) -> str: |
| 232 | return "rich_text" |
| 233 | |
| 234 | |
| 235 | class MultiRichTextGenerator(Generator): |