Commit c6191c48 authored by Enrico Ros's avatar Enrico Ros

Annotations -Part2- PDF1.6 DSs are summarized and ready4impl in ann*.h

Annotation: the class has been passivized. It's only a data container now,
  no more active manipulation of events/paints.
PageViewAnnotator: this class has been created to handle creating annots.
  PageView creates its 'Annotator on demand. The annotator parses tool
  definition from the 'tool.xml' file.
  The Annotator internally uses AnnotatorEngine(s) to react to mouse events
  and the annotation is created when the job is really finished.
Page: added a (maybe temporary) NormalizedPoint to complement Norm..Rect.
PageViewUtils: removed PageViewEditTools and cleaned up header.
conf/: added a debug option for showing annotation boundary while creating
  one and added a temporary 'debug' toolbox in the config dialogs.

svn path=/branches/kpdf_annotations/kdegraphics/kpdf/; revision=394959
parent 8d960f1e
......@@ -9,7 +9,7 @@
<x>0</x>
<y>0</y>
<width>320</width>
<height>169</height>
<height>253</height>
</rect>
</property>
<vbox>
......@@ -158,6 +158,35 @@
</widget>
</hbox>
</widget>
<widget class="QGroupBox">
<property name="name">
<cstring>groupBox2_2</cstring>
</property>
<property name="title">
<string>Temporary DEBUG Options</string>
</property>
<vbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<widget class="QCheckBox">
<property name="name">
<cstring>kcfg_DebugDrawBoundaries</cstring>
</property>
<property name="text">
<string>DebugDrawBoundaries</string>
</property>
</widget>
<widget class="QCheckBox">
<property name="name">
<cstring>kcfg_DebugDrawAnnotationRect</cstring>
</property>
<property name="text">
<string>DebugDrawAnnotationRect</string>
</property>
</widget>
</vbox>
</widget>
<spacer>
<property name="name">
<cstring>spacer3</cstring>
......
......@@ -164,5 +164,8 @@
<entry key="DebugDrawBoundaries" type="Bool" >
<default>false</default>
</entry>
<entry key="DebugDrawAnnotationRect" type="Bool" >
<default>false</default>
</entry>
</group>
</kcfg>
......@@ -7,264 +7,60 @@
* (at your option) any later version. *
***************************************************************************/
// qt / kde includes
#include <qrect.h>
#include <qpainter.h>
#include <qpixmap.h>
#include <qimage.h>
#include <klocale.h>
// system includes
#include <math.h>
// qt/kde includes
#include <qcolor.h>
// local includes
#include "annotations.h"
/** Annotation **/
Annotation::Annotation()
: NormalizedRect(), m_state( NewBorn )
{
state = Opened;
flags = 0;
}
Annotation::~Annotation()
{
}
/*
bool mouseEvent( MouseEvent e, double x, double y, Qt::ButtonState b );
void overlayPaint( QPainter * painter );
void finalPaint( QPixmap * pixmap, MouseState mouseState );
void overlayPaint( QPainter * )
void finalPaint( QPixmap *, MouseState )
*/
/** Text **/
/** TextAnnotation **/
TextAnnotation::TextAnnotation( Type type )
: Annotation(), m_type( type )
{
}
TextAnnotation::TextAnnotation()
: subType( InPlace ) {}
QString TextAnnotation::usageTip() const
{
if ( m_type == InPlace )
return i18n( "A..." );
//else m_type == Popup
return i18n( "B..." );
}
bool TextAnnotation::mouseEvent( MouseEvent, double, double, Qt::ButtonState )
{
return false;
}
/** LineAnnotation **/
void TextAnnotation::paintOverlay( QPainter *, int, int, const QRect & )
{
}
LineAnnotation::LineAnnotation()
: srcArrow( false ), dstArrow( false ), width( 2 ) {}
void TextAnnotation::paintFinal( QImage &, int, int, const QRect & )
{
}
/** GeomAnnotation **/
/** Line **/
LineAnnotation::LineAnnotation( Type type )
: Annotation(), m_type( type )
{
}
GeomAnnotation::GeomAnnotation()
: subType( Square ) {}
QString LineAnnotation::usageTip() const
{
return i18n( "Draw a line between A and Br" );
}
bool LineAnnotation::mouseEvent( MouseEvent, double, double, Qt::ButtonState )
{
return false;
}
/** PathAnnotation **/
void LineAnnotation::paintOverlay( QPainter *, int, int, const QRect & )
{
}
PathAnnotation::PathAnnotation()
: subType( Ink ) {}
void LineAnnotation::paintFinal( QImage &, int, int, const QRect & )
{
}
/** HighlightAnnotation **/
/** Path **/
HighlightAnnotation::HighlightAnnotation()
: subType( Highlight ) {}
PathAnnotation::PathAnnotation( Type type )
: Annotation(), m_type( type )
{
}
QString PathAnnotation::usageTip() const
{
if ( m_type == Ink )
return i18n( "Use the mouse as an ink pen." );
//else if m_type == Poly
return i18n( "Press --describe me--." );
}
/** StampAnnotation **/
bool PathAnnotation::mouseEvent( MouseEvent e, double x, double y, Qt::ButtonState b )
{
// only process events if left button pressed
if ( b != Qt::LeftButton )
return false;
StampAnnotation::StampAnnotation() {}
// start operation
if ( e == MousePress && m_state == NewBorn )
{
FloatPoint newPoint;
left = right = newPoint.x = x;
top = bottom = newPoint.y = y;
m_points.append( newPoint );
m_state = Creating;
return false;
}
// add a point to the path, TODO inline redundancy suppression
else if ( e == MouseMove && m_state == Creating )
{
double dist = hypot( x - m_points.last().x, y - m_points.last().y );
if ( dist < 0.02 )
return false;
left = QMIN( left, x );
top = QMIN( y, top );
right = QMAX( x, right );
bottom = QMAX( y, bottom );
FloatPoint newPoint;
newPoint.x = x;
newPoint.y = y;
m_points.append( newPoint );
return true;
}
// terminate precess
else if ( e == MouseRelease && m_state == Creating )
{
if ( m_points.count() > 2 )
m_state = Opened;
else
m_state = NewBorn;
return false;
}
// nothing change -> don't update gfx
return false;
}
/** MediaAnnotation **/
void PathAnnotation::paintOverlay( QPainter * painter, int xScale, int yScale, const QRect & limits )
{
// draw annotations whith at least 2 points
if ( m_points.count() < 2 )
return;
// use basecolor
painter->setPen( QPen(m_baseColor, 3) );
// perform a rought paint drawing meanline only
//const QRect myRect = geometry( xScale, yScale );
QValueList<FloatPoint>::iterator pIt = m_points.begin(), pEnd = m_points.end();
FloatPoint pA = *pIt;
++pIt;
for ( ; pIt != pEnd; ++pIt )
{
FloatPoint pB = *pIt;
painter->drawLine( (int)(pA.x * (double)xScale), (int)(pA.y * (double)yScale),
(int)(pB.x * (double)xScale), (int)(pB.y * (double)yScale) );
pA = pB;
}
}
void PathAnnotation::paintFinal( QImage & /*backImage*/, int /*xScale*/, int /*yScale*/, const QRect & /*limits*/ )
{
// use m_type for painting
}
/** Highlight **/
HighlightAnnotation::HighlightAnnotation( Type type )
: Annotation(), m_type( type )
{
}
QString HighlightAnnotation::usageTip() const
{
return i18n( "Press and drag the mouse to highlight words." );
}
bool HighlightAnnotation::mouseEvent( MouseEvent e, double x, double y, Qt::ButtonState b )
{
// only process events if left button pressed
if ( b != Qt::LeftButton )
return false;
// start operation
if ( e == MousePress && m_state == NewBorn )
{
FloatPoint newPoint;
left = right = newPoint.x = x;
top = bottom = newPoint.y = y;
m_points.append( newPoint );
m_state = Creating;
return false;
}
// add a point to the path, TODO inline redundancy suppression
else if ( e == MouseMove && m_state == Creating )
{
double dist = hypot( x - m_points.last().x, y - m_points.last().y );
if ( dist < 0.02 )
return false;
left = QMIN( left, x );
top = QMIN( y, top );
right = QMAX( x, right );
bottom = QMAX( y, bottom );
FloatPoint newPoint;
newPoint.x = x;
newPoint.y = y;
m_points.append( newPoint );
return true;
}
// terminate precess
else if ( e == MouseRelease && m_state == Creating )
{
if ( m_points.count() > 2 )
m_state = Opened;
else
m_state = NewBorn;
return false;
}
// nothing change -> don't update gfx
return false;
}
void HighlightAnnotation::paintOverlay( QPainter * painter, int xScale, int yScale, const QRect & limits )
{
// draw annotations whith at least 2 points
if ( m_points.count() < 2 )
return;
// use basecolor
painter->setPen( QPen(m_baseColor, 3) );
// perform a rought paint drawing meanline only
//const QRect myRect = geometry( xScale, yScale );
QValueList<FloatPoint>::iterator pIt = m_points.begin(), pEnd = m_points.end();
FloatPoint pA = *pIt;
++pIt;
for ( ; pIt != pEnd; ++pIt )
{
FloatPoint pB = *pIt;
painter->drawLine( (int)(pA.x * (double)xScale), (int)(pA.y * (double)yScale),
(int)(pB.x * (double)xScale), (int)(pB.y * (double)yScale) );
pA = pB;
}
}
void HighlightAnnotation::paintFinal( QImage & /*backImage*/, int /*xScale*/, int /*yScale*/, const QRect & /*limits*/ )
{
// use m_type for painting
}
MediaAnnotation::MediaAnnotation()
: subType( URL ) {}
......@@ -17,7 +17,7 @@
#include "page.h"
/**
* @short Base options for an annotation (highlight, stamp, boxes, ..).
* @short Base options for an annotation (highlights, stamps, boxes, ..).
*
* From PDFreferece v.1.6:
* An annotation associates an object such as a note, sound, or movie with a
......@@ -27,135 +27,253 @@
* Other fields in pdf reference we dropped here:
* -subtype, rectangle(we are a rect), border stuff
*/
class Annotation : public NormalizedRect
struct Annotation : public NormalizedRect
{
public:
Annotation();
virtual ~Annotation();
enum State { NewBorn, Creating, Modifying, Closed, Opened };
enum MouseEvent { MousePress, MouseMove, MouseRelease };
//enum MouseState { Normal, Hovered, Pressed };
enum Flags { Hidden, NoOpenable, Print, Locked, ReadOnly };
// provide some i18n strings
virtual QString usageTip() const = 0;
// event handlers (must update state)
virtual bool mouseEvent( MouseEvent e, double x, double y, Qt::ButtonState b ) = 0;
// paint roughtly over a cleared area
virtual void paintOverlay( QPainter * painter, int xScale, int yScale, const QRect & limits ) = 0;
// cool-paint over a pixmap
virtual void paintFinal( QImage & backImage, int xScale, int yScale, const QRect & limits ) = 0;
State state() const { return m_state; }
const QString & text() const { return m_text; }
const QString & uniqueName() const { return m_uniqueName; }
const QDateTime & creationDate() const { return m_creationDate; }
const QDateTime & modifyDate() const { return m_modifyDate; }
const QColor & baseColor() const { return m_baseColor; }
void setBaseColor( const QColor & color ) { m_baseColor = color; }
protected:
State m_state;
//MouseState m_mouseState;
QString m_text;
QString m_uniqueName;
QDateTime m_modifyDate;
QColor m_baseColor;
private:
QDateTime m_creationDate;
};
// enum definitions
enum Flags { Hidden, NoOpenable, Print, Locked, ReadOnly };
enum State { Closed, Opened };
// common annotation fields
int pageNumber;
State state;
int flags;
QString text;
QString uniqueName;
QDateTime creationDate;
QDateTime modifyDate;
QColor baseColor;
// virtual function to identify annotation subclasses
enum AType { AText, ALine, AGeom, APath, AHighlight, AStamp, AMedia };
virtual AType aType() const = 0;
struct FloatPoint {
double x, y;
// initialize default values
Annotation();
virtual ~Annotation();
};
class TextAnnotation : public Annotation
/** Annotations in PDF 1.6 specification **
KDPF will try to support ALL annotations and ALL parameters for each one. If
this can't be done, we must support at least the most common ones and the
most common parameters. */
/*
COMMON FIELDS (note: '*' is required)
Type name 'Annot'
*Subtype name [Text...3D]
\ see second table (below)
*Rect rectangle norma rect
Contents text string alternate text / description
P dictionary page reference (mandatory for Screen)
NM text string unique name
M date or string last modify date
F integer flags (default:0)
\ OR-ed flags: Invisible(0), Hidden(1), Print(2), NoZoom(3), NoRotate(4),
\NoView(5), ReadOnly(6), Locked(7), ToggleNoView(8)
BS dictionary border styles (also style for: Line,Square,Circle,Ink)
\ Type (name), W (number), S (name), D (array)
(BE dictionary border effect (only for square, circle, and polygon))
( \ S (name (effect[S:no effect,C: cloudy])), I (number (intensity(0..2)))
AP dictionary visual representation (handler should provide own impl)
\ renderable data to be used with composition algorithm 8.1 (in pdf spec)
AS name visual state (indexes an AP representation)
Border array pre-BS: x-corner-rad, y-corner-rad, border width
C array color (3 components in range [0..1])
A dictionary action (NA on link, specialized on Movie)
AA dictionary additional actions for events (used by Widget only)
StructPar. integer annotation?s key in the structural tree(not used)
OC dictionary optional content properties (custom visi-check)
MARKUP Annotations additional fields (see X entries in the Subtype table)
T text string titlebar text (creator name by convention)
Popup dictionary refrence to pupup annot for editing text
CA number opacity (def: 1.0)
RC text string rich text displayed if opened (overrides Contents)
CreationD. date creation date
IRT dictionary reference to the ann this is 'in reply to' (if RT)
Subj text string short subject addressed
RT name 'R':in reply 'Group':grouped (if IRT)
IT name annotation intent (specialized for certail types)
[annotation states? pg 585]
Most other markup annotations have an associated pop-up window that may
contain text. The annotation?s Contents entry specifies the text to be displayed
when the pop-up window is opened. These include text, line, square, circle,
polygon, polyline, highlight, underline, squiggly-underline, strikeout, rubber
stamp, caret, ink, and file attachment annotations.
CUSTOM FIELDS (for each subType):
X: uses markup for
Text X a 'sticky note' attached to a point in document
\Open boolean default:false
Name name icon[Comment,Key,Note,Help,NewParagraph,Paragraph,Insert]
[M]State text if RT,IRT,StateModel are set
[M]StateM. text if RT,IRT,State are set
Link . hypertext link to a location in document or action
\Dest linkDest if A not present
H name N(none) I(invert) O(outline) P(sunken)
PA dictionary URI action
QuadPoints array array of quadrilaterals (8 x n numbers)
FreeText X like Text but the text is always visible
\*DA string appearance string (AP takes precedence)
Q integer 0(Left-justified) 1(Centered) 2(Right-justified)
RC text rich text string (overrides Contents)
DS text default text string
CL array 2 or 3 {x,y} couples for callout line
[M]IT name not present,FreeTextCallout,FreeTextTypeWriter
Line X a single straight line on the page (has popup note)
\*L array 4 numbers (2 x,y couples)
BS dictionary width and dash pattern to be used in drawing the line
LE array 2 names (start and end styles) (def:None,None)
\ values [Square,Circle,Diamond,OpenArrow,ClosedArrow,None,
Butt,ROpenArrow,RClosedArrow,Slash]
IC array interior color (3 components in range [0..1])
LL number leader line fwd (if LLE) in points
LLE number leader line bk (if LL) in points
Cap boolean has caption (RC or Contents) (def:false)
[M]IT name not present,LineArrow,LineDimension
Square X rect or ellipse on the page (has popup note) the square
Circle X or circle have 18pt border are inscribed into rect
\BS dictionary line width and dash pattern
IC array interior color (3 components in range [0..1])
BE dictionary border effect
RD rectangle negative border offsets (4 positive coords)
Polygon X closed polygon on the page
PolyLine X polygon without first and last vtx closed
\*Vertices array n*{x,y} pairs of all line vertices
LE array 2 names (start and end styles) (def:None,None)
BS dictionary width and dash pattern
IC array interior color (3 components in range [0..1])
BE dictionary border effect
IT name not present,PolygonCloud
Highlight X
Underline X appears as highlights, underlines, strikeouts. has
Squiggly X popup text of associated note)
StrikeOut X
\*QuadPo. array array of ccw quadrilats (8 x n numbers) (AP takes prec)
Caret X visual symbol that indicates the presence of text
\RD rectangle rect displacement from effective rect to annotation one
Sy name 'P':paragraph symbol, 'None':no symbol(defaulr)
Stamp X displays text or graphics intended to look as rubber stamps
\Name name [Approved,Experimental,NotApproved,AsIs,Expired,
NotForPublicRelease,Confidential,Final,Sold,Departmental,
ForComment,TopSecret,Draft,ForPublicRelease]
Ink X freehand ?scribble? composed of one or more disjoint paths
\InkList array array or arrays of {x,y} userspace couples
BS dictionary line width and dash pattern
Popup . no gfx only a parent (inherits Contents,M,C,T)
\Parent dictionary indirect reference to parent (from wich Mark. are inh)
Open boolean initially displayed opened (def:false)
FileAttachment X reference to file (typically embedded)
\*FS file file associated
Name name icon [Graph,PushPin,Paperclip,Tag]
Sound X like Text but contains sound
\*Sound stream sound to be played when annot is activated
Name name icon [Speaker,Mic,_more_]
Movie . contains animated graphics and sound
\Movie dictionary the movie to be played when annot is actived
A boolean whether and how to play the movie (def:true)
NOT USED BY KPDF:
Screen . specifies a region of a page on which play media clips
\MK dictionary appearance characteristics dictionary
(AP is the screen appearance, AA (addit actions)controls, P mandatory for rend)
Widget . appearance of the fields for user interaction
\H name highlighting N:none,I:invert,O:outline,T|P:sunken
MK dictionary appearance characteristics dictionary (see table 8.36)
PrinterMark . a graphic symbol used to assist production personnel
TrapNet . add color marks along colour boundaries to avoid artifacts
Watermark . graphics to be printed at a fixed size and position on a page
3D . the mean by which 3D artwork is represented in a document
*/
struct TextAnnotation : public Annotation
{
public:
enum Type { InPlace, Popup };
TextAnnotation( Type type );
// [Annotation] inherited methods
QString usageTip() const;
bool mouseEvent( MouseEvent e, double x, double y, Qt::ButtonState b );
void paintOverlay( QPainter * painter, int xScale, int yScale, const QRect & limits );
void paintFinal( QImage & backImage, int xScale, int yScale, const QRect & limits );
private:
Type m_type;
// enum definitions
enum TextType { InPlace, Popup };
TextType subType; // InPlace
TextAnnotation();
AType aType() const { return AText; }
};
class LineAnnotation : public Annotation
struct LineAnnotation : public Annotation
{
public:
enum Type { Line, DestArrow, SrcArrow, BiArrow };
LineAnnotation( Type type );
// [Annotation] inherited methods
QString usageTip() const;
bool mouseEvent( MouseEvent e, double x, double y, Qt::ButtonState b );
void paintOverlay( QPainter * painter, int xScale, int yScale, const QRect & limits );
void paintFinal( QImage & backImage, int xScale, int yScale, const QRect & limits );
private:
Type m_type;
NormalizedPoint point[2];
bool srcArrow; // false
bool dstArrow; // false
int width; // 2
LineAnnotation();
AType aType() const { return ALine; }
};