%%========================================================================== %% Copyright (C) 2003 Mikael Karlsson %% %% Permission is hereby granted, free of charge, to any person obtaining a %% copy of this software and associated documentation files (the %% "Software"), to deal in the Software without restriction, including %% without limitation the rights to use, copy, modify, merge, publish, %% distribute, sublicense, and/or sell copies of the Software, and to permit %% persons to whom the Software is furnished to do so, subject to the %% following conditions: %% %% The above copyright notice and this permission notice shall be included %% in all copies or substantial portions of the Software. %% %% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS %% OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF %% MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN %% NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, %% DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR %% OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE %% USE OR OTHER DEALINGS IN THE SOFTWARE. %% %% Author: Mikael Karlsson %% Purpose: PDF Annotations %%========================================================================== %% @doc Annotations. %% %%

Purpose: Create and serialise PDF Annotations

%%

Ref. Chapter 8.4 Annotations in PDF reference v1.4

%% %%

%%

%%
/Type
/Annot
%%
/Subtype
name, Required
%%
/Contents
%%
text string. Required or optional depending on subtype
%%
/P
%%
dictionary. Optional indirect ref. to the page object
%%
/Rect
rectangle. Required
%%
/NM
text string. Optional, annotation name
%%
/M
%%
Date or string. Optional, last modified date and time
%%
/F
%%
Integer. optional, Flags specifying various characteristics
%%
/BS
Dictionary. Optional, Border style
%%
/Border
%%
Array. Optional, annotation border characteristics. %% Use bs inst.
%%
/AP
Dictionary. Appearance
%%
/AS
%%
Name. Required if ap contains one or more subdirectories. %% Appearance state, selects applicable appearance stream.
%%
/C
%%
Array of 3 numbers range 0-1. Optional. RGB color, for icon etc.
%%
/CA
%%
Number 0-1, Optional. Constant opacity value 0=no contr. 1=full
%%
/T
Text string. Optional. Text label in title bar.
%%
/Popup
%%
Dictionary. Optional. Indirect reference to popup annot for edit.
%%
/A
%%
Dictionary. Optional. Action to be performed when activated.
%%
/AA
Dictionary. Optional. Additional actions
%%
/StructParent
%%
Integer. Required if annotation is a structural content item.
%%
%%

%% @end -module(eg_pdf_annot). -include("../include/eg.hrl"). -export([new/3, new_text/2, new_text/3, new_open_text/2, new_open_text/3, new_link/2, new_link/3, new_action/2, new_line/3, set_flags/2, andflags/2, orflags/2, contents/1, flag/1, isflagset/2, rect/1, set_borderstyle/3, style/1, serialise/2]). %% ============================================================================ %% Subtypes subtype(text) -> {name, "Text"}; subtype(link) -> {name, "Link"}; subtype(freetext) -> {name, "FreeText"}; subtype(line) -> {name, "Line"}; subtype(square) -> {name, "Square"}; subtype(circle) -> {name, "Circle"}; subtype(highlight) -> {name, "Highlight"}; subtype(underline) -> {name, "Underline"}; subtype(squiggly) -> {name, "Squiggly"}; subtype(strikeout) -> {name, "StrikeOut"}; subtype(stamp) -> {name, "Stamp"}; subtype(ink) -> {name, "Ink"}; subtype(popup) -> {name, "Popup"}; subtype(fileattachement) -> {name, "FileAttacheMent"}; subtype(sound) -> {name, "Sound"}; subtype(movie) -> {name, "Movie"}; subtype(widget) -> {name, "Widget"}; subtype(printermark) -> {name, "PrinterMark"}; subtype(trapnet) -> {name, "TrapNet"}. contents(Contents) -> {string, Contents}. %% @type rect() = {X, Y, Width, Height} rect({A,B,C,D}) -> {array, [A,B,C,D]}. %% Flags flag(invisible) -> 1; flag(hidden) -> 2; flag(print) -> 4; flag(nozoom) -> 8; flag(norotate) -> 16; flag(noview) -> 32; flag(readonly) -> 64. %% @spec new(Subtype, Rect) -> dict() %% Rect = {rect, {X,Y, Width, Height}} new(SubType, {rect,{_X, _Y, _W, _H}} = Rect)-> {dict,[{"Type",{name,"Annot"}}, {"Subtype", subtype(SubType)}, {"Rect", Rect }]}. new(SubType, Rect, Contents)-> A = new(SubType, Rect), set_contents(Contents,A). %% @spec new_text(Rect::rect(), Contents::string()) -> %% text_annotation() %% @doc Text annotations represents a sticky note new_text(Rect, Contents)-> new(text,Rect,Contents). %% Default when Name is not given is Note %% @spec new_text(Rect::rect(), Contents::string(), name()) -> %% text_annotation() new_text(Rect, Contents, Name)-> A = new_text(Rect, Contents), store("Name", name(Name), A). %% @spec new_open_text(Rect::rect(), Contents::string()) -> %% text_annotation() %% @doc Text annotation that is open new_open_text(Rect, Contents)-> A = new_text(Rect, Contents), store( "Open", true, A ). %% @spec new_open_text(Rect::rect(), Contents::string(), name()) -> %% text_annotation() new_open_text(Rect, Contents, Name)-> A = new_text(Rect, Contents), B = store("Name", name(Name), A), store( "Open", true, B ). %% @type name() = comment|help|insert|key|note|paragraph name(comment) -> {name, "Comment"}; name(help) -> {name, "Help"}; name(insert) -> {name, "Insert"}; name(key) -> {name, "Key"}; name(newparagraph)-> {name, "NewParagraph"}; name(note) -> {name, "Note"}; name(paragraph) -> {name, "Paragraph"}. %% ------ Link annotations are either hyper text links %% or actions to performed %% @spec new_link(Rect::rect(), Dest::destination()) -> dict() new_link(Rect, Dest)-> A = new(link,Rect), %% [ PageNo | T ] = Dest, store("Border",{array,[16,16,1]}, store("Dest", Dest, A )). %% @spec new_link(Rect::rect(), Dest::destination(), Highlight) -> dict() %% Highlight = none | invert | outline | push new_link(Rect, Dest, Highlight)-> A = new_link(Rect, Dest), store( "H", highlight(Highlight), A ). highlight(none) -> {name, "N"}; highlight(invert) -> {name, "I"}; %% Default highlight(outline) -> {name, "O"}; highlight(push) -> {name, "P"}. %% Action is a predefined action dictionary new_action(Rect, {action, Action})-> A = new(link, Rect), store("A", {action, Action}, A). %% ------ Line annotations new_line(Rect, Contents, {Point1, Point2})-> A = new(line,Rect, Contents), {X1, Y1} = Point1, {X2, Y2} = Point2, store("L", {array,[X1, Y1, X2, Y2]}, A ). set_contents(Contents, Annot)-> store("Contents", {string,Contents}, Annot). store(Key, Value, Dict)-> eg_pdf_lib:store_in_dict({Key, Value}, Dict). set_borderstyle(Width, Style, Annot)-> S = style(Style), A = {dict,[{"Type",{name,"Border"}}, {"W", Width}, {"S", S}]}, store("BS", A, Annot). style(solid) -> {name, "S"}; style(dashed) -> {name, "D"}; style(beveled) -> {name, "B"}; style(inset) -> {name, "I"}; style(underline) -> {name, "U"}. %% Annotation flags orflags(Flag, Flags)-> flag(Flag) bor Flags. andflags(Flag, Flags)-> flag(Flag) band Flags. isflagset(Flag, Flags)-> case andflags(Flag, Flags) of 0 -> false; _ -> true end. set_flags(Flags, Annot)-> store("F", Flags, Annot). serialise(Annots, I)-> serialise(Annots, I, [], []). serialise([], I, Is, Os) -> A = {{obj,I,0},{array,lists:map(fun(J) -> {ptr,J,0} end, lists:reverse(Is))}}, {I+1, {ptr,I,0}, lists:reverse([A|Os])}; serialise([H|T], I, Fs, E) -> O = mk_annot(I, H), serialise(T, I+1, [I|Fs], [O|E]). mk_annot(I, {annot,A}) -> {{obj,I,0}, {dict,dict:to_list(A)} }.