"""pdf_add_text — escribe un bloque de texto en el documento PDF.""" import sys import os _types_dir = os.path.join(os.path.dirname(__file__), "..", "..", "..", "python", "types", "infra") sys.path.insert(0, _types_dir) from pdf_doc import PDFDoc from pdf_style import PDFStyle def _parse_hex_color(hex_color: str) -> tuple[int, int, int]: """Convierte color hex (#RRGGBB) a tupla (r, g, b).""" h = hex_color.lstrip("#") if len(h) == 3: h = "".join(c * 2 for c in h) r = int(h[0:2], 16) g = int(h[2:4], 16) b = int(h[4:6], 16) return r, g, b def _align_char(alignment: str) -> str: """Convierte nombre de alineacion al caracter fpdf2.""" mapping = { "left": "L", "center": "C", "right": "R", "justify": "J", } return mapping.get(alignment, "L") def pdf_add_text( doc: PDFDoc, text: str, style: PDFStyle | None = None, x: float | None = None, y: float | None = None, width: float | None = None, ) -> PDFDoc: """Escribe un bloque de texto en el documento PDF con el estilo dado. Posiciona el cursor en (x, y) si se especifican, o continua desde la posicion actual. Aplica fuente, tamaño, color y alineacion del estilo. Respeta saltos de linea en el texto. Args: doc: PDFDoc con una pagina activa. text: texto a escribir. Soporta saltos de linea con '\\n'. style: PDFStyle con fuente, tamaño, color, alineacion. None usa defaults. x: posicion X en mm. None mantiene la posicion actual (margen izquierdo). y: posicion Y en mm. None mantiene la posicion actual (posicion del cursor). width: ancho del bloque de texto en mm. None usa el ancho disponible. Returns: PDFDoc con el texto añadido (mismo objeto modificado). """ if style is None: style = PDFStyle() fpdf = doc.fpdf # Aplicar margen superior if style.margin_top > 0: fpdf.ln(style.margin_top) # Posicion if x is not None or y is not None: cur_x = x if x is not None else fpdf.get_x() cur_y = y if y is not None else fpdf.get_y() fpdf.set_xy(cur_x, cur_y) # Fuente family = style.font_family # Detectar bold/italic del nombre bold = "-Bold" in family or "-BoldOblique" in family italic = "-Oblique" in family or "-BoldOblique" in family base_family = family.split("-")[0] style_str = "" if bold: style_str += "B" if italic: style_str += "I" fpdf.set_font(base_family, style=style_str, size=style.font_size) # Color r, g, b = _parse_hex_color(style.color) fpdf.set_text_color(r, g, b) # Alineacion align = _align_char(style.alignment) # Ancho disponible cell_width = width if width is not None else (fpdf.epw) # Altura de linea line_h = style.font_size * style.line_height * 0.352778 # pt a mm aprox # Escribir texto con multi_cell para soportar saltos de linea y wrap fpdf.multi_cell(w=cell_width, h=line_h, text=text, align=align) # Margen inferior if style.margin_bottom > 0: fpdf.ln(style.margin_bottom) return doc