Anotaciones PDF
Anotaciones PDF
Page.annotations expone un AnnotationCollection — una vista mutable, similar a una secuencia, sobre cada anotación en una página. Cada entrada es un Annotation (o las subclases MarkupAnnotation / LinkAnnotation), y los datos específicos del subtipo, como puntos cuádruples, listas de tinta o colores, se leen y escriben a través de get_property() / set_property() en lugar de atributos dedicados.
Añadiendo anotaciones
AnnotationCollection.add(subtype, rect, contents, title, appearance_normal, properties) crea una nueva anotación y la agrega a la página. subtype acepta ya sea una cadena simple ("Text", "Square", "Highlight") o un miembro del enumerado AnnotationType.
import aspose_pdf
from aspose_pdf import Document, AnnotationType
doc = Document()
doc.pages.add()
page = doc.pages[0]
# Plain string subtype
page.annotations.add("Text", (100, 100, 200, 200), "Hello")
# AnnotationType enum, with subtype-specific properties
page.annotations.add(
AnnotationType.POLYGON,
(0, 0, 10, 10),
"",
properties={"Vertices": [0, 0, 10, 0, 5, 10]},
)Lectura y actualización de propiedades
get_property(name, default) lee un valor específico del subtipo; set_property(name, value) escribe uno, y establecer una propiedad a None lo elimina del diccionario properties de la anotación.
doc = Document()
doc.pages.add()
page = doc.pages[0]
ann = page.annotations.add(
"Square", (0, 0, 50, 50), "x", properties={"C": [1, 0, 0]},
)
ann.set_property("IC", [0, 0, 1])
print(page.annotations[0].get_property("IC")) # [0, 0, 1]
ann.set_property("C", None) # removes the "C" entry entirely
print("C" in page.annotations[0].properties) # FalseNombrar anotaciones con AnnotationName
Los nombres PDF (p.ej., la entrada Name de una anotación Stamp) se marcan distintamente de las cadenas simples usando AnnotationName, una subclase str de aspose_pdf.engine.cos. Un valor almacenado de esta manera sigue siendo igual a una cadena ordinaria.
from aspose_pdf.engine.cos import AnnotationName
doc = Document()
doc.pages.add()
page = doc.pages[0]
page.annotations.add(
"Stamp", (10, 10, 110, 60), "",
properties={"Name": AnnotationName("Approved")},
)Insertar, eliminar y limpiar
insert(index, subtype, rect, contents, title, appearance_normal, properties) coloca una nueva anotación en una posición específica; delete(index) elimina una por índice (generando IndexError para un índice fuera de rango); clear() elimina todas las anotaciones de la página.
doc = Document()
doc.pages.add()
page = doc.pages[0]
page.annotations.add("Text", (0, 0, 100, 100), "A")
page.annotations.add("Text", (200, 200, 300, 300), "C")
page.annotations.insert(1, "Text", (100, 100, 200, 200), "B")
# order is now: A, B, C
page.annotations.delete(1) # removes "B"
page.annotations.clear() # removes everything remainingGenerar apariencias de anotaciones
Annotation.generate_appearance(force) construye el flujo de apariencia /AP /N para una anotación y devuelve True cuando existe un renderizador para ese subtipo; AnnotationCollection.generate_appearances(force) hace lo mismo para cada anotación en la página en una sola llamada y devuelve el recuento de anotaciones que realmente se generaron (los subtipos no compatibles se omiten).
doc = Document()
doc.pages.add()
page = doc.pages[0]
page.annotations.add("Square", (0, 0, 50, 50), "")
page.annotations.add("Circle", (60, 0, 110, 50), "")
page.annotations.add("Text", (0, 60, 20, 80), "") # unsupported subtype -> skipped
generated = page.annotations.generate_appearances()
print(generated) # 2Subtipos de anotaciones y banderas
AnnotationType enumera los nombres de subtipo estándar del PDF 32000-1:2008 (Tabla 169): TEXT, LINK, FREE_TEXT, LINE, SQUARE, CIRCLE, POLYGON, POLY_LINE, HIGHLIGHT, UNDERLINE, SQUIGGLY, STRIKE_OUT, STAMP, CARET, INK, POPUP, FILE_ATTACHMENT, SOUND, MOVIE, WIDGET, SCREEN, PRINTER_MARK, TRAP_NET, WATERMARK, y REDACT.
AnnotationFlags es un IntFlag que cubre el comportamiento de visualización/interacción de anotaciones: DEFAULT, INVISIBLE, HIDDEN, PRINT, NO_ZOOM, NO_ROTATE, NO_VIEW, READ_ONLY, LOCKED y TOGGLE_NO_VIEW.
Prelanzamiento: 3D Annotations
PDF3DAnnotation, PDF3DArtwork, PDF3DContent y PDF3DView modelan arte 3D adjunto a una página — un PDF3DAnnotation tiene un rect: Rectangle, un artwork: PDF3DArtwork y un background_color: Color opcional. PDF3DArtwork.add_view() registra un PDF3DView, cada uno lleva un render_mode (PDF3DRenderMode: SOLID, WIREFRAME, TRANSPARENT) y un lighting_scheme (PDF3DLightingScheme: HEADLAMP, WHITE, GRAY, DARK, CUSTOM). La docstring propia de la biblioteca marca PDF3DAnnotation como un “envoltorio de anotación mínima para importaciones de prelanzamiento” — trate esta superficie como una etapa temprana más que como una API de autoría 3D totalmente desarrollada.
Consejos y Mejores Prácticas
- Prefiera los miembros del enum
AnnotationTypesobre cadenas de subtipo crudas cuando el valor también necesite ser comparado o ramificado en otra parte de su código. - Llame a
set_property(name, None)para eliminar una propiedad por completo en lugar de dejar un valor obsoleto en su lugar — la entrada desaparece depropertiescompletamente. - Genere apariencias por lotes con
AnnotationCollection.generate_appearancesen lugar de iterargenerate_appearance()por anotación; devuelve el número real generado para que pueda detectar subtipos omitidos/no compatibles. delete()y el indexado enpage.annotationsson ambos basados en 0; valide un índice antes de llamar adelete()si proviene de la entrada del usuario, ya que un índice fuera de rango lanzaIndexError.- Envuelva los valores de nombres PDF (como el
Namede unStamp) enAnnotationNamepara que circulen como nombres PDF en lugar de cadenas de texto simples.
Problemas comunes
| Problema | Causa | Corrección |
|---|---|---|
generate_appearances() devuelve menos que el número de anotaciones añadidas | Uno o más subtipos no tienen un renderizador de apariencia incorporado | Verifique el recuento de retorno contra len(page.annotations); los subtipos no compatibles se omiten silenciosamente, sin generar error |
delete(index) lanza IndexError | El índice es negativo o está más allá del recuento actual de anotaciones | Verifique len(page.annotations) antes de llamar a delete() |
Una propiedad establecida con set_property() no aparece después de recargar | La propiedad se estableció en None, lo que la elimina en lugar de almacenarla | Use un valor real, no None, cuando la propiedad debe persistir |
| La anotación insertada termina en la posición incorrecta | Índice insert(index, ...) contado desde el estado de la colección antes de la inserción | Vuelva a comprobar los índices después de cada llamada a insert() en un bucle |
FAQ
¿Cómo añado una anotación de comentario de texto plano?
Llame a page.annotations.add("Text", (x0, y0, x1, y1), "comment text"). La tupla de cuatro números es el rectángulo de la anotación en la página.
¿Cuál es la diferencia entre Annotation, MarkupAnnotation y LinkAnnotation?
Annotation es la vista en vivo devuelta para cualquier anotación en una página. MarkupAnnotation es la base para los subtipos de estilo marcado (highlights, text notes, shapes) y LinkAnnotation se conserva para anotaciones de estilo enlace; ambos actualmente exponen la misma superficie de métodos/propiedades que Annotation.
¿Puedo eliminar una sola propiedad sin borrar toda la anotación?
Sí — llame a annotation.set_property(name, None); la propia anotación permanece intacta, solo se elimina esa entrada de properties.
¿Falla AnnotationCollection.generate_appearances si un subtipo no es compatible?
No. Omite los subtipos sin un renderizador de apariencia incorporado y devuelve el recuento de anotaciones para las que realmente generó una apariencia.
¿Están las clases de anotación 3D listas para producción?
PDF3DAnnotation y los tipos relacionados están documentados como un contenedor mínimo para importaciones prerelease — verifique el comportamiento en su visor de PDF objetivo antes de confiar en ellos para contenido 3D de producción.
Resumen de API Reference
| Clase/Método | Descripción |
|---|---|
AnnotationCollection.add | Crear y añadir una nueva anotación a una página |
AnnotationCollection.insert | Crear e insertar una nueva anotación en un índice específico |
AnnotationCollection.delete | Eliminar una anotación por índice (lanza IndexError si está fuera de rango) |
AnnotationCollection.clear | Eliminar todas las anotaciones de la página |
AnnotationCollection.generate_appearances | Generar flujos de apariencia /AP /N para cada anotación compatible en la página |
Annotation.get_property / set_property | Leer o escribir un valor de propiedad específico del subtipo |
Annotation.update_properties | Recalcular el estado derivado después de ediciones directas de propiedades |
Annotation.generate_appearance | Generar el flujo de apariencia /AP /N para una única anotación |
AnnotationType | Enumeración de nombres de subtipos de anotación PDF estándar |
AnnotationFlags | IntFlag del comportamiento de visualización/interacción de la anotación |
AnnotationName | str subclase que marca un valor para serializarlo como un nombre PDF |
PDF3DAnnotation / PDF3DArtwork / PDF3DContent / PDF3DView | Modelo de anotación y obra de arte 3D en pre-lanzamiento |
PDF3DRenderMode / PDF3DLightingScheme | Enums para el modo de renderizado de vista 3D y el esquema de iluminación |