diff --git a/pdf_annotate/annotations/text.py b/pdf_annotate/annotations/text.py index d19b37a..0a17fa0 100644 --- a/pdf_annotate/annotations/text.py +++ b/pdf_annotate/annotations/text.py @@ -14,6 +14,7 @@ from pdfrw import PdfDict from pdfrw import PdfName from pdfrw import PdfString +from pdfrw import PdfObject from pdf_annotate.annotations.base import _make_border_dict from pdf_annotate.annotations.base import Annotation @@ -42,6 +43,31 @@ 'Helvetica.ttf', ) +class NoteText(Annotation): + subtype = 'Text' + + def make_rect(self): + L = self._location + return [L.x1, L.y1, L.x2, L.y2] + + def add_additional_pdf_object_data(self, obj): + obj.Contents = self._appearance.content + obj.C = self._appearance.fill + # NOTE: See PDF "Text" Annot section in Ref Document for valid values. + obj.Name = PdfName(self._appearance.text_name) + obj.F = 0 + # NOTE: We currently need to override what gets inserted by default. + obj.AP = ContentStream([]).resolve() + obj.Open = PdfObject('true') + + def make_default_appearance(self): + obj.C = [0.5, 0.5, 0.5] + return ContentStream([]) + + def make_appearance_stream(self): + # Not needed. Necessary to satisfy Annotation interface + return ContentStream([]) + class FreeText(Annotation): """FreeText annotation. Right now, we only support writing text in the diff --git a/pdf_annotate/annotator.py b/pdf_annotate/annotator.py index efb1936..5b5dae8 100644 --- a/pdf_annotate/annotator.py +++ b/pdf_annotate/annotator.py @@ -20,6 +20,7 @@ from pdf_annotate.annotations.rect import Circle from pdf_annotate.annotations.rect import Square from pdf_annotate.annotations.text import FreeText +from pdf_annotate.annotations.text import NoteText from pdf_annotate.config.metadata import Metadata from pdf_annotate.config.metadata import UNSET from pdf_annotate.graphics import ContentStream @@ -40,6 +41,7 @@ 'polyline': Polyline, 'ink': Ink, 'text': FreeText, + 'note': NoteText, 'image': Image, } diff --git a/pdf_annotate/config/appearance.py b/pdf_annotate/config/appearance.py index a9ac440..86e2290 100644 --- a/pdf_annotate/config/appearance.py +++ b/pdf_annotate/config/appearance.py @@ -16,6 +16,7 @@ from pdf_annotate.config.constants import BLACK from pdf_annotate.config.constants import DEFAULT_BORDER_STYLE from pdf_annotate.config.constants import DEFAULT_CONTENT +from pdf_annotate.config.constants import DEFAULT_TEXT_ANNOT_NAME from pdf_annotate.config.constants import DEFAULT_FONT_SIZE from pdf_annotate.config.constants import DEFAULT_LINE_SPACING from pdf_annotate.config.constants import DEFAULT_STROKE_WIDTH @@ -71,6 +72,7 @@ class Appearance(object): text_baseline = Enum(ALLOWED_BASELINES, default=TEXT_BASELINE_MIDDLE) line_spacing = Number(default=DEFAULT_LINE_SPACING, validator=positive) wrap_text = Boolean(default=True) + text_name = String(default=DEFAULT_TEXT_ANNOT_NAME) # Image attributes image = String(default=None) diff --git a/pdf_annotate/config/constants.py b/pdf_annotate/config/constants.py index ab61a36..6dd8667 100644 --- a/pdf_annotate/config/constants.py +++ b/pdf_annotate/config/constants.py @@ -27,6 +27,7 @@ DEFAULT_CONTENT = '' DEFAULT_FONT_SIZE = 12 DEFAULT_LINE_SPACING = 1.2 +DEFAULT_TEXT_ANNOT_NAME = 'Note' DEFAULT_STROKE_WIDTH = 1 DEFAULT_BORDER_STYLE = 'S' diff --git a/tests/annotations/test_text.py b/tests/annotations/test_text.py index 18d2764..5ceaca1 100644 --- a/tests/annotations/test_text.py +++ b/tests/annotations/test_text.py @@ -1,6 +1,6 @@ from unittest import TestCase -from pdf_annotate.annotations.text import FreeText, HELVETICA_PATH +from pdf_annotate.annotations.text import FreeText, NoteText, HELVETICA_PATH from pdf_annotate.config.appearance import Appearance from pdf_annotate.config.constants import PDF_ANNOTATOR_FONT from pdf_annotate.config.location import Location @@ -31,6 +31,24 @@ def test_pdf_object(self): assert obj.AP.N.BBox == [x1, y1, x2, y2] assert obj.AP.N.Matrix == translate(-x1, -y1) + + def test_text_note_pdf_object(self): + x1, y1, x2, y2 = 10, 20, 100, 200 + annotation = NoteText( + Location(x1=x1, y1=y1, x2=x2, y2=y2, page=0), + Appearance( + fill=[0.4, 0, 0], + content='Hi', + text_name='Comment', + ), + ) + obj = annotation.as_pdf_object(identity(), page=None) + assert obj.Rect == [x1, y1, x2, y2] + assert obj.C == [0.4, 0, 0] + assert obj.Name == '/Comment' + assert obj.Contents == 'Hi' + + def test_make_composite_font(self): font = FreeText.make_composite_font_object(HELVETICA_PATH) keys = font.keys() diff --git a/tests/end_to_end/test_annotate_pdf.py b/tests/end_to_end/test_annotate_pdf.py index 347c022..f7b719d 100644 --- a/tests/end_to_end/test_annotate_pdf.py +++ b/tests/end_to_end/test_annotate_pdf.py @@ -249,6 +249,13 @@ def _add_text_annotations(self, a, y1=220, y2=300): Location(x1=x, y1=y1, x2=(x + 40), y2=y2, page=0), appearance, ) + # TODO: Proper way to enable? + # a.add_annotation( + # 'note', + # Location(x1=(x + 10), y1=y1, x2=(x + 40), y2=y2, page=0), + # appearance, + # ) + def _add_rounded_rectangles(self, a): """Add a few rounded rectangles with different border radii."""