00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "annotations.h"
00011 #include "annotations_p.h"
00012
00013
00014 #include <QtGui/QApplication>
00015 #include <QtGui/QColor>
00016
00017
00018 #include "page_p.h"
00019
00020 using namespace Okular;
00021
00022
00023 Annotation * AnnotationUtils::createAnnotation( const QDomElement & annElement )
00024 {
00025
00026 if ( !annElement.hasAttribute( "type" ) )
00027 return 0;
00028
00029
00030 Annotation * annotation = 0;
00031 int typeNumber = annElement.attribute( "type" ).toInt();
00032 switch ( typeNumber )
00033 {
00034 case Annotation::AText:
00035 annotation = new TextAnnotation( annElement );
00036 break;
00037 case Annotation::ALine:
00038 annotation = new LineAnnotation( annElement );
00039 break;
00040 case Annotation::AGeom:
00041 annotation = new GeomAnnotation( annElement );
00042 break;
00043 case Annotation::AHighlight:
00044 annotation = new HighlightAnnotation( annElement );
00045 break;
00046 case Annotation::AStamp:
00047 annotation = new StampAnnotation( annElement );
00048 break;
00049 case Annotation::AInk:
00050 annotation = new InkAnnotation( annElement );
00051 break;
00052 }
00053
00054
00055 return annotation;
00056 }
00057
00058 void AnnotationUtils::storeAnnotation( const Annotation * ann, QDomElement & annElement,
00059 QDomDocument & document )
00060 {
00061
00062 annElement.setAttribute( "type", (uint)ann->subType() );
00063
00064
00065 ann->store( annElement, document );
00066 }
00067
00068 QDomElement AnnotationUtils::findChildElement( const QDomNode & parentNode,
00069 const QString & name )
00070 {
00071
00072 QDomNode subNode = parentNode.firstChild();
00073 while( subNode.isElement() )
00074 {
00075 QDomElement element = subNode.toElement();
00076 if ( element.tagName() == name )
00077 return element;
00078 subNode = subNode.nextSibling();
00079 }
00080
00081 return QDomElement();
00082 }
00083
00084 QRect AnnotationUtils::annotationGeometry( const Annotation * ann,
00085 double scaledWidth, double scaledHeight )
00086 {
00087 if ( ann->subType() == Annotation::AText && ( ( (TextAnnotation*)ann )->textType() == TextAnnotation::Linked ) )
00088 {
00089 return QRect( (int)( ann->transformedBoundingRectangle().left * scaledWidth ),
00090 (int)( ann->transformedBoundingRectangle().top * scaledHeight ), 24, 24 );
00091 }
00092
00093 return ann->transformedBoundingRectangle().geometry( (int)scaledWidth, (int)scaledHeight );
00094 }
00095
00096
00097
00098
00099
00100 class Annotation::Style::Private
00101 {
00102 public:
00103 Private()
00104 : m_opacity( 1.0 ), m_width( 1.0 ), m_style( Solid ), m_xCorners( 0.0 ),
00105 m_yCorners( 0.0 ), m_marks( 3 ), m_spaces( 0 ), m_effect( NoEffect ),
00106 m_effectIntensity( 1.0 )
00107 {
00108 }
00109
00110 QColor m_color;
00111 double m_opacity;
00112 double m_width;
00113 LineStyle m_style;
00114 double m_xCorners;
00115 double m_yCorners;
00116 int m_marks;
00117 int m_spaces;
00118 LineEffect m_effect;
00119 double m_effectIntensity;
00120 };
00121
00122 Annotation::Style::Style()
00123 : d( new Private )
00124 {
00125 }
00126
00127 Annotation::Style::~Style()
00128 {
00129 delete d;
00130 }
00131
00132 Annotation::Style::Style( const Style &other )
00133 : d( new Private )
00134 {
00135 *d = *other.d;
00136 }
00137
00138 Annotation::Style& Annotation::Style::operator=( const Style &other )
00139 {
00140 if ( this != &other )
00141 *d = *other.d;
00142
00143 return *this;
00144 }
00145
00146 void Annotation::Style::setColor( const QColor &color )
00147 {
00148 d->m_color = color;
00149 }
00150
00151 QColor Annotation::Style::color() const
00152 {
00153 return d->m_color;
00154 }
00155
00156 void Annotation::Style::setOpacity( double opacity )
00157 {
00158 d->m_opacity = opacity;
00159 }
00160
00161 double Annotation::Style::opacity() const
00162 {
00163 return d->m_opacity;
00164 }
00165
00166 void Annotation::Style::setWidth( double width )
00167 {
00168 d->m_width = width;
00169 }
00170
00171 double Annotation::Style::width() const
00172 {
00173 return d->m_width;
00174 }
00175
00176 void Annotation::Style::setLineStyle( LineStyle style )
00177 {
00178 d->m_style = style;
00179 }
00180
00181 Annotation::LineStyle Annotation::Style::lineStyle() const
00182 {
00183 return d->m_style;
00184 }
00185
00186 void Annotation::Style::setXCorners( double xCorners )
00187 {
00188 d->m_xCorners = xCorners;
00189 }
00190
00191 double Annotation::Style::xCorners() const
00192 {
00193 return d->m_xCorners;
00194 }
00195
00196 void Annotation::Style::setYCorners( double yCorners )
00197 {
00198 d->m_yCorners = yCorners;
00199 }
00200
00201 double Annotation::Style::yCorners() const
00202 {
00203 return d->m_yCorners;
00204 }
00205
00206 void Annotation::Style::setMarks( int marks )
00207 {
00208 d->m_marks = marks;
00209 }
00210
00211 int Annotation::Style::marks() const
00212 {
00213 return d->m_marks;
00214 }
00215
00216 void Annotation::Style::setSpaces( int spaces )
00217 {
00218 d->m_spaces = spaces;
00219 }
00220
00221 int Annotation::Style::spaces() const
00222 {
00223 return d->m_spaces;
00224 }
00225
00226 void Annotation::Style::setLineEffect( LineEffect effect )
00227 {
00228 d->m_effect = effect;
00229 }
00230
00231 Annotation::LineEffect Annotation::Style::lineEffect() const
00232 {
00233 return d->m_effect;
00234 }
00235
00236 void Annotation::Style::setEffectIntensity( double intensity )
00237 {
00238 d->m_effectIntensity = intensity;
00239 }
00240
00241 double Annotation::Style::effectIntensity() const
00242 {
00243 return d->m_effectIntensity;
00244 }
00245
00246
00247 class Annotation::Window::Private
00248 {
00249 public:
00250 Private()
00251 : m_flags( -1 ), m_width( 0 ), m_height( 0 )
00252 {
00253 }
00254
00255 int m_flags;
00256 NormalizedPoint m_topLeft;
00257 int m_width;
00258 int m_height;
00259 QString m_title;
00260 QString m_summary;
00261 QString m_text;
00262 };
00263
00264 Annotation::Window::Window()
00265 : d( new Private )
00266 {
00267 }
00268
00269 Annotation::Window::~Window()
00270 {
00271 delete d;
00272 }
00273
00274 Annotation::Window::Window( const Window &other )
00275 : d( new Private )
00276 {
00277 *d = *other.d;
00278 }
00279
00280 Annotation::Window& Annotation::Window::operator=( const Window &other )
00281 {
00282 if ( this != &other )
00283 *d = *other.d;
00284
00285 return *this;
00286 }
00287
00288 void Annotation::Window::setFlags( int flags )
00289 {
00290 d->m_flags = flags;
00291 }
00292
00293 int Annotation::Window::flags() const
00294 {
00295 return d->m_flags;
00296 }
00297
00298 void Annotation::Window::setTopLeft( const NormalizedPoint &point )
00299 {
00300 d->m_topLeft = point;
00301 }
00302
00303 NormalizedPoint Annotation::Window::topLeft() const
00304 {
00305 return d->m_topLeft;
00306 }
00307
00308 void Annotation::Window::setWidth( int width )
00309 {
00310 d->m_width = width;
00311 }
00312
00313 int Annotation::Window::width() const
00314 {
00315 return d->m_width;
00316 }
00317
00318 void Annotation::Window::setHeight( int height )
00319 {
00320 d->m_height = height;
00321 }
00322
00323 int Annotation::Window::height() const
00324 {
00325 return d->m_height;
00326 }
00327
00328 void Annotation::Window::setTitle( const QString &title )
00329 {
00330 d->m_title = title;
00331 }
00332
00333 QString Annotation::Window::title() const
00334 {
00335 return d->m_title;
00336 }
00337
00338 void Annotation::Window::setSummary( const QString &summary )
00339 {
00340 d->m_summary = summary;
00341 }
00342
00343 QString Annotation::Window::summary() const
00344 {
00345 return d->m_summary;
00346 }
00347
00348 void Annotation::Window::setText( const QString &text )
00349 {
00350 d->m_text = text;
00351 }
00352
00353 QString Annotation::Window::text() const
00354 {
00355 return d->m_text;
00356 }
00357
00358
00359 class Annotation::Revision::Private
00360 {
00361 public:
00362 Private()
00363 : m_annotation( 0 ), m_scope( Reply ), m_type( None )
00364 {
00365 }
00366
00367 Annotation *m_annotation;
00368 RevisionScope m_scope;
00369 RevisionType m_type;
00370 };
00371
00372 Annotation::Revision::Revision()
00373 : d( new Private )
00374 {
00375 }
00376
00377 Annotation::Revision::~Revision()
00378 {
00379 delete d;
00380 }
00381
00382 Annotation::Revision::Revision( const Revision &other )
00383 : d( new Private )
00384 {
00385 *d = *other.d;
00386 }
00387
00388 Annotation::Revision& Annotation::Revision::operator=( const Revision &other )
00389 {
00390 if ( this != &other )
00391 *d = *other.d;
00392
00393 return *this;
00394 }
00395
00396 void Annotation::Revision::setAnnotation( Annotation *annotation )
00397 {
00398 d->m_annotation = annotation;
00399 }
00400
00401 Annotation *Annotation::Revision::annotation() const
00402 {
00403 return d->m_annotation;
00404 }
00405
00406 void Annotation::Revision::setScope( RevisionScope scope )
00407 {
00408 d->m_scope = scope;
00409 }
00410
00411 Annotation::RevisionScope Annotation::Revision::scope() const
00412 {
00413 return d->m_scope;
00414 }
00415
00416 void Annotation::Revision::setType( RevisionType type )
00417 {
00418 d->m_type = type;
00419 }
00420
00421 Annotation::RevisionType Annotation::Revision::type() const
00422 {
00423 return d->m_type;
00424 }
00425
00426
00427 AnnotationPrivate::AnnotationPrivate()
00428 : m_page( 0 ), m_flags( 0 )
00429 {
00430 }
00431
00432 AnnotationPrivate::~AnnotationPrivate()
00433 {
00434
00435 if ( m_revisions.isEmpty() )
00436 return;
00437
00438 QLinkedList< Annotation::Revision >::iterator it = m_revisions.begin(), end = m_revisions.end();
00439 for ( ; it != end; ++it )
00440 delete (*it).annotation();
00441 }
00442
00443 Annotation::Annotation( AnnotationPrivate &dd )
00444 : d_ptr( &dd )
00445 {
00446 }
00447
00448 Annotation::Annotation( AnnotationPrivate &dd, const QDomNode & annNode )
00449 : d_ptr( &dd )
00450 {
00451 Q_D( Annotation );
00452
00453 QDomElement e = AnnotationUtils::findChildElement( annNode, "base" );
00454 if ( e.isNull() )
00455 return;
00456
00457
00458 if ( e.hasAttribute( "author" ) )
00459 d->m_author = e.attribute( "author" );
00460 if ( e.hasAttribute( "contents" ) )
00461 d->m_contents = e.attribute( "contents" );
00462 if ( e.hasAttribute( "uniqueName" ) )
00463 d->m_uniqueName = e.attribute( "uniqueName" );
00464 if ( e.hasAttribute( "modifyDate" ) )
00465 d->m_modifyDate = QDateTime::fromString( e.attribute("modifyDate"), Qt::ISODate );
00466 if ( e.hasAttribute( "creationDate" ) )
00467 d->m_creationDate = QDateTime::fromString( e.attribute("creationDate"), Qt::ISODate );
00468
00469
00470 if ( e.hasAttribute( "flags" ) )
00471 d->m_flags = e.attribute( "flags" ).toInt();
00472 if ( e.hasAttribute( "color" ) )
00473 d->m_style.setColor( QColor( e.attribute( "color" ) ) );
00474 if ( e.hasAttribute( "opacity" ) )
00475 d->m_style.setOpacity( e.attribute( "opacity" ).toDouble() );
00476
00477
00478
00479 QDomNode eSubNode = e.firstChild();
00480 while ( eSubNode.isElement() )
00481 {
00482 QDomElement ee = eSubNode.toElement();
00483 eSubNode = eSubNode.nextSibling();
00484
00485
00486 if ( ee.tagName() == "boundary" )
00487 {
00488 d->m_boundary=NormalizedRect(ee.attribute( "l" ).toDouble(),
00489 ee.attribute( "t" ).toDouble(),
00490 ee.attribute( "r" ).toDouble(),
00491 ee.attribute( "b" ).toDouble());
00492 }
00493
00494 else if ( ee.tagName() == "penStyle" )
00495 {
00496 d->m_style.setWidth( ee.attribute( "width" ).toDouble() );
00497 d->m_style.setLineStyle( (LineStyle)ee.attribute( "style" ).toInt() );
00498 d->m_style.setXCorners( ee.attribute( "xcr" ).toDouble() );
00499 d->m_style.setYCorners( ee.attribute( "ycr" ).toDouble() );
00500 d->m_style.setMarks( ee.attribute( "marks" ).toInt() );
00501 d->m_style.setSpaces( ee.attribute( "spaces" ).toInt() );
00502 }
00503
00504 else if ( ee.tagName() == "penEffect" )
00505 {
00506 d->m_style.setLineEffect( (LineEffect)ee.attribute( "effect" ).toInt() );
00507 d->m_style.setEffectIntensity( ee.attribute( "intensity" ).toDouble() );
00508 }
00509
00510 else if ( ee.tagName() == "window" )
00511 {
00512 d->m_window.setFlags( ee.attribute( "flags" ).toInt() );
00513 d->m_window.setTopLeft( NormalizedPoint( ee.attribute( "top" ).toDouble(),
00514 ee.attribute( "left" ).toDouble() ) );
00515 d->m_window.setWidth( ee.attribute( "width" ).toInt() );
00516 d->m_window.setHeight( ee.attribute( "height" ).toInt() );
00517 d->m_window.setTitle( ee.attribute( "title" ) );
00518 d->m_window.setSummary( ee.attribute( "summary" ) );
00519
00520 QDomNode winNode = ee.firstChild();
00521 for ( ; winNode.isElement(); winNode = winNode.nextSibling() )
00522 {
00523 QDomElement winElement = winNode.toElement();
00524 if ( winElement.tagName() == "text" )
00525 d->m_window.setText( winElement.firstChild().toCDATASection().data() );
00526 }
00527 }
00528 }
00529
00530
00531 QDomNode revNode = annNode.firstChild();
00532 for ( ; revNode.isElement(); revNode = revNode.nextSibling() )
00533 {
00534 QDomElement revElement = revNode.toElement();
00535 if ( revElement.tagName() != "revision" )
00536 continue;
00537
00538
00539 Revision revision;
00540 revision.setScope( (RevisionScope)revElement.attribute( "revScope" ).toInt() );
00541 revision.setType( (RevisionType)revElement.attribute( "revType" ).toInt() );
00542 revision.setAnnotation( AnnotationUtils::createAnnotation( revElement ) );
00543
00544
00545 if ( revision.annotation() )
00546 d->m_revisions.append( revision );
00547 }
00548
00549 d->m_transformedBoundary = d->m_boundary;
00550 }
00551
00552 Annotation::~Annotation()
00553 {
00554 delete d_ptr;
00555 }
00556
00557 void Annotation::setAuthor( const QString &author )
00558 {
00559 Q_D( Annotation );
00560 d->m_author = author;
00561 }
00562
00563 QString Annotation::author() const
00564 {
00565 Q_D( const Annotation );
00566 return d->m_author;
00567 }
00568
00569 void Annotation::setContents( const QString &contents )
00570 {
00571 Q_D( Annotation );
00572 d->m_contents = contents;
00573 }
00574
00575 QString Annotation::contents() const
00576 {
00577 Q_D( const Annotation );
00578 return d->m_contents;
00579 }
00580
00581 void Annotation::setUniqueName( const QString &name )
00582 {
00583 Q_D( Annotation );
00584 d->m_uniqueName = name;
00585 }
00586
00587 QString Annotation::uniqueName() const
00588 {
00589 Q_D( const Annotation );
00590 return d->m_uniqueName;
00591 }
00592
00593 void Annotation::setModificationDate( const QDateTime &date )
00594 {
00595 Q_D( Annotation );
00596 d->m_modifyDate = date;
00597 }
00598
00599 QDateTime Annotation::modificationDate() const
00600 {
00601 Q_D( const Annotation );
00602 return d->m_modifyDate;
00603 }
00604
00605 void Annotation::setCreationDate( const QDateTime &date )
00606 {
00607 Q_D( Annotation );
00608 d->m_creationDate = date;
00609 }
00610
00611 QDateTime Annotation::creationDate() const
00612 {
00613 Q_D( const Annotation );
00614 return d->m_creationDate;
00615 }
00616
00617 void Annotation::setFlags( int flags )
00618 {
00619 Q_D( Annotation );
00620 d->m_flags = flags;
00621 }
00622
00623 int Annotation::flags() const
00624 {
00625 Q_D( const Annotation );
00626 return d->m_flags;
00627 }
00628
00629 void Annotation::setBoundingRectangle( const NormalizedRect &rectangle )
00630 {
00631 Q_D( Annotation );
00632 d->m_boundary = rectangle;
00633 d->resetTransformation();
00634 if ( d->m_page )
00635 {
00636 d->transform( d->m_page->rotationMatrix() );
00637 }
00638 }
00639
00640 NormalizedRect Annotation::boundingRectangle() const
00641 {
00642 Q_D( const Annotation );
00643 return d->m_boundary;
00644 }
00645
00646 NormalizedRect Annotation::transformedBoundingRectangle() const
00647 {
00648 Q_D( const Annotation );
00649 return d->m_transformedBoundary;
00650 }
00651
00652 void Annotation::translate( const NormalizedPoint &coord )
00653 {
00654 Q_D( Annotation );
00655 d->translate( coord );
00656 d->resetTransformation();
00657 if ( d->m_page )
00658 {
00659 d->transform( d->m_page->rotationMatrix() );
00660 }
00661 }
00662
00663 Annotation::Style & Annotation::style()
00664 {
00665 Q_D( Annotation );
00666 return d->m_style;
00667 }
00668
00669 const Annotation::Style & Annotation::style() const
00670 {
00671 Q_D( const Annotation );
00672 return d->m_style;
00673 }
00674
00675 Annotation::Window & Annotation::window()
00676 {
00677 Q_D( Annotation );
00678 return d->m_window;
00679 }
00680
00681 const Annotation::Window & Annotation::window() const
00682 {
00683 Q_D( const Annotation );
00684 return d->m_window;
00685 }
00686
00687 QLinkedList< Annotation::Revision > & Annotation::revisions()
00688 {
00689 Q_D( Annotation );
00690 return d->m_revisions;
00691 }
00692
00693 const QLinkedList< Annotation::Revision > & Annotation::revisions() const
00694 {
00695 Q_D( const Annotation );
00696 return d->m_revisions;
00697 }
00698
00699 void Annotation::store( QDomNode & annNode, QDomDocument & document ) const
00700 {
00701 Q_D( const Annotation );
00702
00703 QDomElement e = document.createElement( "base" );
00704 annNode.appendChild( e );
00705
00706
00707 if ( !d->m_author.isEmpty() )
00708 e.setAttribute( "author", d->m_author );
00709 if ( !d->m_contents.isEmpty() )
00710 e.setAttribute( "contents", d->m_contents );
00711 if ( !d->m_uniqueName.isEmpty() )
00712 e.setAttribute( "uniqueName", d->m_uniqueName );
00713 if ( d->m_modifyDate.isValid() )
00714 e.setAttribute( "modifyDate", d->m_modifyDate.toString(Qt::ISODate) );
00715 if ( d->m_creationDate.isValid() )
00716 e.setAttribute( "creationDate", d->m_creationDate.toString(Qt::ISODate) );
00717
00718
00719 if ( d->m_flags )
00720 e.setAttribute( "flags", d->m_flags );
00721 if ( d->m_style.color().isValid() )
00722 e.setAttribute( "color", d->m_style.color().name() );
00723 if ( d->m_style.opacity() != 1.0 )
00724 e.setAttribute( "opacity", d->m_style.opacity() );
00725
00726
00727 QDomElement bE = document.createElement( "boundary" );
00728 e.appendChild( bE );
00729 bE.setAttribute( "l", (double)d->m_boundary.left );
00730 bE.setAttribute( "t", (double)d->m_boundary.top );
00731 bE.setAttribute( "r", (double)d->m_boundary.right );
00732 bE.setAttribute( "b", (double)d->m_boundary.bottom );
00733
00734
00735 if ( d->m_style.width() != 1 || d->m_style.lineStyle() != Solid || d->m_style.xCorners() != 0 ||
00736 d->m_style.yCorners() != 0.0 || d->m_style.marks() != 3 || d->m_style.spaces() != 0 )
00737 {
00738 QDomElement psE = document.createElement( "penStyle" );
00739 e.appendChild( psE );
00740 psE.setAttribute( "width", d->m_style.width() );
00741 psE.setAttribute( "style", (int)d->m_style.lineStyle() );
00742 psE.setAttribute( "xcr", d->m_style.xCorners() );
00743 psE.setAttribute( "ycr", d->m_style.yCorners() );
00744 psE.setAttribute( "marks", d->m_style.marks() );
00745 psE.setAttribute( "spaces", d->m_style.spaces() );
00746 }
00747
00748
00749 if ( d->m_style.lineEffect() != NoEffect || d->m_style.effectIntensity() != 1.0 )
00750 {
00751 QDomElement peE = document.createElement( "penEffect" );
00752 e.appendChild( peE );
00753 peE.setAttribute( "effect", (int)d->m_style.lineEffect() );
00754 peE.setAttribute( "intensity", d->m_style.effectIntensity() );
00755 }
00756
00757
00758 if ( d->m_window.flags() != -1 || !d->m_window.title().isEmpty() ||
00759 !d->m_window.summary().isEmpty() || !d->m_window.text().isEmpty() )
00760 {
00761 QDomElement wE = document.createElement( "window" );
00762 e.appendChild( wE );
00763 wE.setAttribute( "flags", d->m_window.flags() );
00764 wE.setAttribute( "top", d->m_window.topLeft().x );
00765 wE.setAttribute( "left", d->m_window.topLeft().y );
00766 wE.setAttribute( "width", d->m_window.width() );
00767 wE.setAttribute( "height", d->m_window.height() );
00768 wE.setAttribute( "title", d->m_window.title() );
00769 wE.setAttribute( "summary", d->m_window.summary() );
00770
00771 if ( !d->m_window.text().isEmpty() )
00772 {
00773 QDomElement escapedText = document.createElement( "text" );
00774 wE.appendChild( escapedText );
00775 QDomCDATASection textCData = document.createCDATASection( d->m_window.text() );
00776 escapedText.appendChild( textCData );
00777 }
00778 }
00779
00780
00781 if ( d->m_revisions.isEmpty() )
00782 return;
00783
00784
00785 QLinkedList< Revision >::const_iterator it = d->m_revisions.begin(), end = d->m_revisions.end();
00786 for ( ; it != end; ++it )
00787 {
00788
00789 const Revision & revision = *it;
00790 QDomElement r = document.createElement( "revision" );
00791 annNode.appendChild( r );
00792
00793 r.setAttribute( "revScope", (int)revision.scope() );
00794 r.setAttribute( "revType", (int)revision.type() );
00795
00796 AnnotationUtils::storeAnnotation( revision.annotation(), r, document );
00797 }
00798 }
00799
00800 void AnnotationPrivate::annotationTransform( const QMatrix &matrix )
00801 {
00802 resetTransformation();
00803 transform( matrix );
00804 }
00805
00806 void AnnotationPrivate::transform( const QMatrix &matrix )
00807 {
00808 m_transformedBoundary.transform( matrix );
00809 }
00810
00811 void AnnotationPrivate::baseTransform( const QMatrix &matrix )
00812 {
00813 m_boundary.transform( matrix );
00814 }
00815
00816 void AnnotationPrivate::resetTransformation()
00817 {
00818 m_transformedBoundary = m_boundary;
00819 }
00820
00821 void AnnotationPrivate::translate( const NormalizedPoint &coord )
00822 {
00823 m_boundary.left = m_boundary.left + coord.x;
00824 m_boundary.right = m_boundary.right + coord.x;
00825 m_boundary.top = m_boundary.top + coord.y;
00826 m_boundary.bottom = m_boundary.bottom + coord.y;
00827 }
00828
00829
00830
00831
00834 class Okular::TextAnnotationPrivate : public Okular::AnnotationPrivate
00835 {
00836 public:
00837 TextAnnotationPrivate()
00838 : AnnotationPrivate(), m_textType( TextAnnotation::Linked ),
00839 m_textIcon( "Note" ), m_inplaceAlign( 0 ),
00840 m_inplaceIntent( TextAnnotation::Unknown )
00841 {
00842 }
00843
00844 virtual void transform( const QMatrix &matrix );
00845 virtual void baseTransform( const QMatrix &matrix );
00846 virtual void resetTransformation();
00847 virtual void translate( const NormalizedPoint &coord );
00848
00849 TextAnnotation::TextType m_textType;
00850 QString m_textIcon;
00851 QFont m_textFont;
00852 int m_inplaceAlign;
00853 QString m_inplaceText;
00854 NormalizedPoint m_inplaceCallout[3];
00855 NormalizedPoint m_transformedInplaceCallout[3];
00856 TextAnnotation::InplaceIntent m_inplaceIntent;
00857 };
00858
00859
00860
00861
00862 TextAnnotation::TextAnnotation()
00863 : Annotation( *new TextAnnotationPrivate() )
00864 {
00865 }
00866
00867 TextAnnotation::TextAnnotation( const QDomNode & node )
00868 : Annotation( *new TextAnnotationPrivate(), node )
00869 {
00870 Q_D( TextAnnotation );
00871
00872 QDomNode subNode = node.firstChild();
00873 while( subNode.isElement() )
00874 {
00875 QDomElement e = subNode.toElement();
00876 subNode = subNode.nextSibling();
00877 if ( e.tagName() != "text" )
00878 continue;
00879
00880
00881 if ( e.hasAttribute( "type" ) )
00882 d->m_textType = (TextAnnotation::TextType)e.attribute( "type" ).toInt();
00883 if ( e.hasAttribute( "icon" ) )
00884 d->m_textIcon = e.attribute( "icon" );
00885 if ( e.hasAttribute( "font" ) )
00886 d->m_textFont.fromString( e.attribute( "font" ) );
00887 if ( e.hasAttribute( "align" ) )
00888 d->m_inplaceAlign = e.attribute( "align" ).toInt();
00889 if ( e.hasAttribute( "intent" ) )
00890 d->m_inplaceIntent = (TextAnnotation::InplaceIntent)e.attribute( "intent" ).toInt();
00891
00892
00893 QDomNode eSubNode = e.firstChild();
00894 while ( eSubNode.isElement() )
00895 {
00896 QDomElement ee = eSubNode.toElement();
00897 eSubNode = eSubNode.nextSibling();
00898
00899 if ( ee.tagName() == "escapedText" )
00900 {
00901 d->m_inplaceText = ee.firstChild().toCDATASection().data();
00902 }
00903 else if ( ee.tagName() == "callout" )
00904 {
00905 d->m_inplaceCallout[0].x = ee.attribute( "ax" ).toDouble();
00906 d->m_inplaceCallout[0].y = ee.attribute( "ay" ).toDouble();
00907 d->m_inplaceCallout[1].x = ee.attribute( "bx" ).toDouble();
00908 d->m_inplaceCallout[1].y = ee.attribute( "by" ).toDouble();
00909 d->m_inplaceCallout[2].x = ee.attribute( "cx" ).toDouble();
00910 d->m_inplaceCallout[2].y = ee.attribute( "cy" ).toDouble();
00911 }
00912 }
00913
00914
00915 break;
00916 }
00917
00918 for ( int i = 0; i < 3; ++i )
00919 d->m_transformedInplaceCallout[i] = d->m_inplaceCallout[i];
00920 }
00921
00922 TextAnnotation::~TextAnnotation()
00923 {
00924 }
00925
00926 void TextAnnotation::setTextType( TextType textType )
00927 {
00928 Q_D( TextAnnotation );
00929 d->m_textType = textType;
00930 }
00931
00932 TextAnnotation::TextType TextAnnotation::textType() const
00933 {
00934 Q_D( const TextAnnotation );
00935 return d->m_textType;
00936 }
00937
00938 void TextAnnotation::setTextIcon( const QString &icon )
00939 {
00940 Q_D( TextAnnotation );
00941 d->m_textIcon = icon;
00942 }
00943
00944 QString TextAnnotation::textIcon() const
00945 {
00946 Q_D( const TextAnnotation );
00947 return d->m_textIcon;
00948 }
00949
00950 void TextAnnotation::setTextFont( const QFont &font )
00951 {
00952 Q_D( TextAnnotation );
00953 d->m_textFont = font;
00954 }
00955
00956 QFont TextAnnotation::textFont() const
00957 {
00958 Q_D( const TextAnnotation );
00959 return d->m_textFont;
00960 }
00961
00962 void TextAnnotation::setInplaceAlignment( int alignment )
00963 {
00964 Q_D( TextAnnotation );
00965 d->m_inplaceAlign = alignment;
00966 }
00967
00968 int TextAnnotation::inplaceAlignment() const
00969 {
00970 Q_D( const TextAnnotation );
00971 return d->m_inplaceAlign;
00972 }
00973
00974 void TextAnnotation::setInplaceText( const QString &text )
00975 {
00976 Q_D( TextAnnotation );
00977 d->m_inplaceText = text;
00978 }
00979
00980 QString TextAnnotation::inplaceText() const
00981 {
00982 Q_D( const TextAnnotation );
00983 return d->m_inplaceText;
00984 }
00985
00986 void TextAnnotation::setInplaceCallout( const NormalizedPoint &point, int index )
00987 {
00988 if ( index < 0 || index > 2 )
00989 return;
00990
00991 Q_D( TextAnnotation );
00992 d->m_inplaceCallout[ index ] = point;
00993 }
00994
00995 NormalizedPoint TextAnnotation::inplaceCallout( int index ) const
00996 {
00997 if ( index < 0 || index > 2 )
00998 return NormalizedPoint();
00999
01000 Q_D( const TextAnnotation );
01001 return d->m_inplaceCallout[ index ];
01002 }
01003
01004 NormalizedPoint TextAnnotation::transformedInplaceCallout( int index ) const
01005 {
01006 if ( index < 0 || index > 2 )
01007 return NormalizedPoint();
01008
01009 Q_D( const TextAnnotation );
01010 return d->m_transformedInplaceCallout[ index ];
01011 }
01012
01013 void TextAnnotation::setInplaceIntent( InplaceIntent intent )
01014 {
01015 Q_D( TextAnnotation );
01016 d->m_inplaceIntent = intent;
01017 }
01018
01019 TextAnnotation::InplaceIntent TextAnnotation::inplaceIntent() const
01020 {
01021 Q_D( const TextAnnotation );
01022 return d->m_inplaceIntent;
01023 }
01024
01025 Annotation::SubType TextAnnotation::subType() const
01026 {
01027 return AText;
01028 }
01029
01030 void TextAnnotation::store( QDomNode & node, QDomDocument & document ) const
01031 {
01032 Q_D( const TextAnnotation );
01033
01034 Annotation::store( node, document );
01035
01036
01037 QDomElement textElement = document.createElement( "text" );
01038 node.appendChild( textElement );
01039
01040
01041 if ( d->m_textType != Linked )
01042 textElement.setAttribute( "type", (int)d->m_textType );
01043 if ( d->m_textIcon != "Comment" )
01044 textElement.setAttribute( "icon", d->m_textIcon );
01045 if ( d->m_textFont != QApplication::font() )
01046 textElement.setAttribute( "font", d->m_textFont.toString() );
01047 if ( d->m_inplaceAlign )
01048 textElement.setAttribute( "align", d->m_inplaceAlign );
01049 if ( d->m_inplaceIntent != Unknown )
01050 textElement.setAttribute( "intent", (int)d->m_inplaceIntent );
01051
01052
01053 if ( !d->m_inplaceText.isEmpty() )
01054 {
01055 QDomElement escapedText = document.createElement( "escapedText" );
01056 textElement.appendChild( escapedText );
01057 QDomCDATASection textCData = document.createCDATASection( d->m_inplaceText );
01058 escapedText.appendChild( textCData );
01059 }
01060
01061
01062 if ( d->m_inplaceCallout[0].x != 0.0 )
01063 {
01064 QDomElement calloutElement = document.createElement( "callout" );
01065 textElement.appendChild( calloutElement );
01066 calloutElement.setAttribute( "ax", d->m_inplaceCallout[0].x );
01067 calloutElement.setAttribute( "ay", d->m_inplaceCallout[0].y );
01068 calloutElement.setAttribute( "bx", d->m_inplaceCallout[1].x );
01069 calloutElement.setAttribute( "by", d->m_inplaceCallout[1].y );
01070 calloutElement.setAttribute( "cx", d->m_inplaceCallout[2].x );
01071 calloutElement.setAttribute( "cy", d->m_inplaceCallout[2].y );
01072 }
01073 }
01074
01075 void TextAnnotationPrivate::transform( const QMatrix &matrix )
01076 {
01077 AnnotationPrivate::transform( matrix );
01078
01079 for ( int i = 0; i < 3; ++i ) {
01080 m_transformedInplaceCallout[i].transform( matrix );
01081 }
01082 }
01083
01084 void TextAnnotationPrivate::baseTransform( const QMatrix &matrix )
01085 {
01086 AnnotationPrivate::baseTransform( matrix );
01087
01088 for ( int i = 0; i < 3; ++i ) {
01089 m_inplaceCallout[i].transform( matrix );
01090 }
01091 }
01092
01093 void TextAnnotationPrivate::resetTransformation()
01094 {
01095 AnnotationPrivate::resetTransformation();
01096
01097 for ( int i = 0; i < 3; ++i ) {
01098 m_transformedInplaceCallout[i] = m_inplaceCallout[i];
01099 }
01100 }
01101
01102 void TextAnnotationPrivate::translate( const NormalizedPoint &coord )
01103 {
01104 AnnotationPrivate::translate( coord );
01105
01106 #define ADD_COORD( c1, c2 ) \
01107 { \
01108 c1.x = c1.x + c2.x; \
01109 c1.y = c1.y + c2.y; \
01110 }
01111 ADD_COORD( m_inplaceCallout[0], coord )
01112 ADD_COORD( m_inplaceCallout[1], coord )
01113 ADD_COORD( m_inplaceCallout[2], coord )
01114 #undef ADD_COORD
01115 }
01116
01119 class Okular::LineAnnotationPrivate : public Okular::AnnotationPrivate
01120 {
01121 public:
01122 LineAnnotationPrivate()
01123 : AnnotationPrivate(),
01124 m_lineStartStyle( LineAnnotation::None ), m_lineEndStyle( LineAnnotation::None ),
01125 m_lineClosed( false ), m_lineShowCaption( false ), m_lineLeadingFwdPt( 0 ),
01126 m_lineLeadingBackPt( 0 ), m_lineIntent( LineAnnotation::Unknown )
01127 {
01128 }
01129
01130 virtual void transform( const QMatrix &matrix );
01131 virtual void baseTransform( const QMatrix &matrix );
01132 virtual void resetTransformation();
01133 virtual void translate( const NormalizedPoint &coord );
01134
01135 QLinkedList<NormalizedPoint> m_linePoints;
01136 QLinkedList<NormalizedPoint> m_transformedLinePoints;
01137 LineAnnotation::TermStyle m_lineStartStyle;
01138 LineAnnotation::TermStyle m_lineEndStyle;
01139 bool m_lineClosed : 1;
01140 bool m_lineShowCaption : 1;
01141 QColor m_lineInnerColor;
01142 double m_lineLeadingFwdPt;
01143 double m_lineLeadingBackPt;
01144 LineAnnotation::LineIntent m_lineIntent;
01145 };
01146
01147 LineAnnotation::LineAnnotation()
01148 : Annotation( *new LineAnnotationPrivate() )
01149 {
01150 }
01151
01152 LineAnnotation::LineAnnotation( const QDomNode & node )
01153 : Annotation( *new LineAnnotationPrivate(), node )
01154 {
01155 Q_D( LineAnnotation );
01156
01157 QDomNode subNode = node.firstChild();
01158 while( subNode.isElement() )
01159 {
01160 QDomElement e = subNode.toElement();
01161 subNode = subNode.nextSibling();
01162 if ( e.tagName() != "line" )
01163 continue;
01164
01165
01166 if ( e.hasAttribute( "startStyle" ) )
01167 d->m_lineStartStyle = (LineAnnotation::TermStyle)e.attribute( "startStyle" ).toInt();
01168 if ( e.hasAttribute( "endStyle" ) )
01169 d->m_lineEndStyle = (LineAnnotation::TermStyle)e.attribute( "endStyle" ).toInt();
01170 if ( e.hasAttribute( "closed" ) )
01171 d->m_lineClosed = e.attribute( "closed" ).toInt();
01172 if ( e.hasAttribute( "innerColor" ) )
01173 d->m_lineInnerColor = QColor( e.attribute( "innerColor" ) );
01174 if ( e.hasAttribute( "leadFwd" ) )
01175 d->m_lineLeadingFwdPt = e.attribute( "leadFwd" ).toDouble();
01176 if ( e.hasAttribute( "leadBack" ) )
01177 d->m_lineLeadingBackPt = e.attribute( "leadBack" ).toDouble();
01178 if ( e.hasAttribute( "showCaption" ) )
01179 d->m_lineShowCaption = e.attribute( "showCaption" ).toInt();
01180 if ( e.hasAttribute( "intent" ) )
01181 d->m_lineIntent = (LineAnnotation::LineIntent)e.attribute( "intent" ).toInt();
01182
01183
01184 QDomNode pointNode = e.firstChild();
01185 while ( pointNode.isElement() )
01186 {
01187 QDomElement pe = pointNode.toElement();
01188 pointNode = pointNode.nextSibling();
01189
01190 if ( pe.tagName() != "point" )
01191 continue;
01192
01193 NormalizedPoint p;
01194 p.x = pe.attribute( "x", "0.0" ).toDouble();
01195 p.y = pe.attribute( "y", "0.0" ).toDouble();
01196 d->m_linePoints.append( p );
01197 }
01198
01199
01200 break;
01201 }
01202
01203 d->m_transformedLinePoints = d->m_linePoints;
01204 }
01205
01206 LineAnnotation::~LineAnnotation()
01207 {
01208 }
01209
01210 void LineAnnotation::setLinePoints( const QLinkedList<NormalizedPoint> &points )
01211 {
01212 Q_D( LineAnnotation );
01213 d->m_linePoints = points;
01214 }
01215
01216 QLinkedList<NormalizedPoint> LineAnnotation::linePoints() const
01217 {
01218 Q_D( const LineAnnotation );
01219 return d->m_linePoints;
01220 }
01221
01222 QLinkedList<NormalizedPoint> LineAnnotation::transformedLinePoints() const
01223 {
01224 Q_D( const LineAnnotation );
01225 return d->m_transformedLinePoints;
01226 }
01227
01228 void LineAnnotation::setLineStartStyle( TermStyle style )
01229 {
01230 Q_D( LineAnnotation );
01231 d->m_lineStartStyle = style;
01232 }
01233
01234 LineAnnotation::TermStyle LineAnnotation::lineStartStyle() const
01235 {
01236 Q_D( const LineAnnotation );
01237 return d->m_lineStartStyle;
01238 }
01239
01240 void LineAnnotation::setLineEndStyle( TermStyle style )
01241 {
01242 Q_D( LineAnnotation );
01243 d->m_lineEndStyle = style;
01244 }
01245
01246 LineAnnotation::TermStyle LineAnnotation::lineEndStyle() const
01247 {
01248 Q_D( const LineAnnotation );
01249 return d->m_lineEndStyle;
01250 }
01251
01252 void LineAnnotation::setLineClosed( bool closed )
01253 {
01254 Q_D( LineAnnotation );
01255 d->m_lineClosed = closed;
01256 }
01257
01258 bool LineAnnotation::lineClosed() const
01259 {
01260 Q_D( const LineAnnotation );
01261 return d->m_lineClosed;
01262 }
01263
01264 void LineAnnotation::setLineInnerColor( const QColor &color )
01265 {
01266 Q_D( LineAnnotation );
01267 d->m_lineInnerColor = color;
01268 }
01269
01270 QColor LineAnnotation::lineInnerColor() const
01271 {
01272 Q_D( const LineAnnotation );
01273 return d->m_lineInnerColor;
01274 }
01275
01276 void LineAnnotation::setLineLeadingForwardPoint( double point )
01277 {
01278 Q_D( LineAnnotation );
01279 d->m_lineLeadingFwdPt = point;
01280 }
01281
01282 double LineAnnotation::lineLeadingForwardPoint() const
01283 {
01284 Q_D( const LineAnnotation );
01285 return d->m_lineLeadingFwdPt;
01286 }
01287
01288 void LineAnnotation::setLineLeadingBackwardPoint( double point )
01289 {
01290 Q_D( LineAnnotation );
01291 d->m_lineLeadingBackPt = point;
01292 }
01293
01294 double LineAnnotation::lineLeadingBackwardPoint() const
01295 {
01296 Q_D( const LineAnnotation );
01297 return d->m_lineLeadingBackPt;
01298 }
01299
01300 void LineAnnotation::setShowCaption( bool show )
01301 {
01302 Q_D( LineAnnotation );
01303 d->m_lineShowCaption = show;
01304 }
01305
01306 bool LineAnnotation::showCaption() const
01307 {
01308 Q_D( const LineAnnotation );
01309 return d->m_lineShowCaption;
01310 }
01311
01312 void LineAnnotation::setLineIntent( LineIntent intent )
01313 {
01314 Q_D( LineAnnotation );
01315 d->m_lineIntent = intent;
01316 }
01317
01318 LineAnnotation::LineIntent LineAnnotation::lineIntent() const
01319 {
01320 Q_D( const LineAnnotation );
01321 return d->m_lineIntent;
01322 }
01323
01324 Annotation::SubType LineAnnotation::subType() const
01325 {
01326 return ALine;
01327 }
01328
01329 void LineAnnotation::store( QDomNode & node, QDomDocument & document ) const
01330 {
01331 Q_D( const LineAnnotation );
01332
01333 Annotation::store( node, document );
01334
01335
01336 QDomElement lineElement = document.createElement( "line" );
01337 node.appendChild( lineElement );
01338
01339
01340 if ( d->m_lineStartStyle != None )
01341 lineElement.setAttribute( "startStyle", (int)d->m_lineStartStyle );
01342 if ( d->m_lineEndStyle != None )
01343 lineElement.setAttribute( "endStyle", (int)d->m_lineEndStyle );
01344 if ( d->m_lineClosed )
01345 lineElement.setAttribute( "closed", d->m_lineClosed );
01346 if ( d->m_lineInnerColor.isValid() )
01347 lineElement.setAttribute( "innerColor", d->m_lineInnerColor.name() );
01348 if ( d->m_lineLeadingFwdPt != 0.0 )
01349 lineElement.setAttribute( "leadFwd", d->m_lineLeadingFwdPt );
01350 if ( d->m_lineLeadingBackPt != 0.0 )
01351 lineElement.setAttribute( "leadBack", d->m_lineLeadingBackPt );
01352 if ( d->m_lineShowCaption )
01353 lineElement.setAttribute( "showCaption", d->m_lineShowCaption );
01354 if ( d->m_lineIntent != Unknown )
01355 lineElement.setAttribute( "intent", d->m_lineIntent );
01356
01357
01358 int points = d->m_linePoints.count();
01359 if ( points > 1 )
01360 {
01361 QLinkedList<NormalizedPoint>::const_iterator it = d->m_linePoints.begin(), end = d->m_linePoints.end();
01362 while ( it != end )
01363 {
01364 const NormalizedPoint & p = *it;
01365 QDomElement pElement = document.createElement( "point" );
01366 lineElement.appendChild( pElement );
01367 pElement.setAttribute( "x", p.x );
01368 pElement.setAttribute( "y", p.y );
01369 it++;
01370 }
01371 }
01372 }
01373
01374 void LineAnnotationPrivate::transform( const QMatrix &matrix )
01375 {
01376 AnnotationPrivate::transform( matrix );
01377
01378 QMutableLinkedListIterator<NormalizedPoint> it( m_transformedLinePoints );
01379 while ( it.hasNext() )
01380 it.next().transform( matrix );
01381 }
01382
01383 void LineAnnotationPrivate::baseTransform( const QMatrix &matrix )
01384 {
01385 AnnotationPrivate::baseTransform( matrix );
01386
01387 QMutableLinkedListIterator<NormalizedPoint> it( m_linePoints );
01388 while ( it.hasNext() )
01389 it.next().transform( matrix );
01390 }
01391
01392 void LineAnnotationPrivate::resetTransformation()
01393 {
01394 AnnotationPrivate::resetTransformation();
01395
01396 m_transformedLinePoints = m_linePoints;
01397 }
01398
01399 void LineAnnotationPrivate::translate( const NormalizedPoint &coord )
01400 {
01401 AnnotationPrivate::translate( coord );
01402
01403 QMutableLinkedListIterator<NormalizedPoint> it( m_linePoints );
01404 while ( it.hasNext() )
01405 {
01406 NormalizedPoint& p = it.next();
01407 p.x = p.x + coord.x;
01408 p.y = p.y + coord.y;
01409 }
01410 }
01411
01414 class Okular::GeomAnnotationPrivate : public Okular::AnnotationPrivate
01415 {
01416 public:
01417 GeomAnnotationPrivate()
01418 : AnnotationPrivate(), m_geomType( GeomAnnotation::InscribedSquare ),
01419 m_geomWidthPt( 18 )
01420 {
01421 }
01422
01423 GeomAnnotation::GeomType m_geomType;
01424 QColor m_geomInnerColor;
01425 int m_geomWidthPt;
01426 };
01427
01428 GeomAnnotation::GeomAnnotation()
01429 : Annotation( *new GeomAnnotationPrivate() )
01430 {
01431 }
01432
01433 GeomAnnotation::GeomAnnotation( const QDomNode & node )
01434 : Annotation( *new GeomAnnotationPrivate(), node )
01435 {
01436 Q_D( GeomAnnotation );
01437
01438 QDomNode subNode = node.firstChild();
01439 while( subNode.isElement() )
01440 {
01441 QDomElement e = subNode.toElement();
01442 subNode = subNode.nextSibling();
01443 if ( e.tagName() != "geom" )
01444 continue;
01445
01446
01447 if ( e.hasAttribute( "type" ) )
01448 d->m_geomType = (GeomAnnotation::GeomType)e.attribute( "type" ).toInt();
01449 if ( e.hasAttribute( "color" ) )
01450 d->m_geomInnerColor = QColor( e.attribute( "color" ) );
01451 if ( e.hasAttribute( "width" ) )
01452 d->m_geomWidthPt = e.attribute( "width" ).toInt();
01453
01454
01455 break;
01456 }
01457 }
01458
01459 GeomAnnotation::~GeomAnnotation()
01460 {
01461 }
01462
01463 void GeomAnnotation::setGeometricalType( GeomType type )
01464 {
01465 Q_D( GeomAnnotation );
01466 d->m_geomType = type;
01467 }
01468
01469 GeomAnnotation::GeomType GeomAnnotation::geometricalType() const
01470 {
01471 Q_D( const GeomAnnotation );
01472 return d->m_geomType;
01473 }
01474
01475 void GeomAnnotation::setGeometricalInnerColor( const QColor &color )
01476 {
01477 Q_D( GeomAnnotation );
01478 d->m_geomInnerColor = color;
01479 }
01480
01481 QColor GeomAnnotation::geometricalInnerColor() const
01482 {
01483 Q_D( const GeomAnnotation );
01484 return d->m_geomInnerColor;
01485 }
01486
01487 void GeomAnnotation::setGeometricalPointWidth( int width )
01488 {
01489 Q_D( GeomAnnotation );
01490 d->m_geomWidthPt = width;
01491 }
01492
01493 int GeomAnnotation::geometricalPointWidth() const
01494 {
01495 Q_D( const GeomAnnotation );
01496 return d->m_geomWidthPt;
01497 }
01498
01499 Annotation::SubType GeomAnnotation::subType() const
01500 {
01501 return AGeom;
01502 }
01503
01504 void GeomAnnotation::store( QDomNode & node, QDomDocument & document ) const
01505 {
01506 Q_D( const GeomAnnotation );
01507
01508 Annotation::store( node, document );
01509
01510
01511 QDomElement geomElement = document.createElement( "geom" );
01512 node.appendChild( geomElement );
01513
01514
01515 if ( d->m_geomType != InscribedSquare )
01516 geomElement.setAttribute( "type", (int)d->m_geomType );
01517 if ( d->m_geomInnerColor.isValid() )
01518 geomElement.setAttribute( "color", d->m_geomInnerColor.name() );
01519 if ( d->m_geomWidthPt != 18 )
01520 geomElement.setAttribute( "width", d->m_geomWidthPt );
01521 }
01522
01525 class HighlightAnnotation::Quad::Private
01526 {
01527 public:
01528 Private()
01529 {
01530 }
01531
01532 NormalizedPoint m_points[4];
01533 NormalizedPoint m_transformedPoints[4];
01534 bool m_capStart : 1;
01535 bool m_capEnd : 1;
01536 double m_feather;
01537 };
01538
01539 HighlightAnnotation::Quad::Quad()
01540 : d( new Private )
01541 {
01542 }
01543
01544 HighlightAnnotation::Quad::~Quad()
01545 {
01546 delete d;
01547 }
01548
01549 HighlightAnnotation::Quad::Quad( const Quad &other )
01550 : d( new Private )
01551 {
01552 *d = *other.d;
01553 }
01554
01555 HighlightAnnotation::Quad& HighlightAnnotation::Quad::operator=( const Quad &other )
01556 {
01557 if ( this != &other )
01558 *d = *other.d;
01559
01560 return *this;
01561 }
01562
01563 void HighlightAnnotation::Quad::setPoint( const NormalizedPoint &point, int index )
01564 {
01565 if ( index < 0 || index > 3 )
01566 return;
01567
01568 d->m_points[ index ] = point;
01569 }
01570
01571 NormalizedPoint HighlightAnnotation::Quad::point( int index ) const
01572 {
01573 if ( index < 0 || index > 3 )
01574 return NormalizedPoint();
01575
01576 return d->m_points[ index ];
01577 }
01578
01579 NormalizedPoint HighlightAnnotation::Quad::transformedPoint( int index ) const
01580 {
01581 if ( index < 0 || index > 3 )
01582 return NormalizedPoint();
01583
01584 return d->m_transformedPoints[ index ];
01585 }
01586
01587 void HighlightAnnotation::Quad::setCapStart( bool value )
01588 {
01589 d->m_capStart = value;
01590 }
01591
01592 bool HighlightAnnotation::Quad::capStart() const
01593 {
01594 return d->m_capStart;
01595 }
01596
01597 void HighlightAnnotation::Quad::setCapEnd( bool value )
01598 {
01599 d->m_capEnd = value;
01600 }
01601
01602 bool HighlightAnnotation::Quad::capEnd() const
01603 {
01604 return d->m_capEnd;
01605 }
01606
01607 void HighlightAnnotation::Quad::setFeather( double width )
01608 {
01609 d->m_feather = width;
01610 }
01611
01612 double HighlightAnnotation::Quad::feather() const
01613 {
01614 return d->m_feather;
01615 }
01616
01617 void HighlightAnnotation::Quad::transform( const QMatrix &matrix )
01618 {
01619 for ( int i = 0; i < 4; ++i ) {
01620 d->m_transformedPoints[ i ] = d->m_points[ i ];
01621 d->m_transformedPoints[ i ].transform( matrix );
01622 }
01623 }
01624
01625
01626 class Okular::HighlightAnnotationPrivate : public Okular::AnnotationPrivate
01627 {
01628 public:
01629 HighlightAnnotationPrivate()
01630 : AnnotationPrivate(), m_highlightType( HighlightAnnotation::Highlight )
01631 {
01632 }
01633
01634 virtual void transform( const QMatrix &matrix );
01635 virtual void baseTransform( const QMatrix &matrix );
01636
01637 HighlightAnnotation::HighlightType m_highlightType;
01638 QList< HighlightAnnotation::Quad > m_highlightQuads;
01639 };
01640
01641 HighlightAnnotation::HighlightAnnotation()
01642 : Annotation( *new HighlightAnnotationPrivate() )
01643 {
01644 }
01645
01646 HighlightAnnotation::HighlightAnnotation( const QDomNode & node )
01647 : Annotation( *new HighlightAnnotationPrivate(), node )
01648 {
01649 Q_D( HighlightAnnotation );
01650
01651 QDomNode subNode = node.firstChild();
01652 while( subNode.isElement() )
01653 {
01654 QDomElement e = subNode.toElement();
01655 subNode = subNode.nextSibling();
01656 if ( e.tagName() != "hl" )
01657 continue;
01658
01659
01660 if ( e.hasAttribute( "type" ) )
01661 d->m_highlightType = (HighlightAnnotation::HighlightType)e.attribute( "type" ).toInt();
01662
01663
01664 QDomNode quadNode = e.firstChild();
01665 for ( ; quadNode.isElement(); quadNode = quadNode.nextSibling() )
01666 {
01667 QDomElement qe = quadNode.toElement();
01668 if ( qe.tagName() != "quad" )
01669 continue;
01670
01671 HighlightAnnotation::Quad q;
01672 q.setPoint( NormalizedPoint( qe.attribute( "ax", "0.0" ).toDouble(), qe.attribute( "ay", "0.0" ).toDouble() ), 0 );
01673 q.setPoint( NormalizedPoint( qe.attribute( "bx", "0.0" ).toDouble(), qe.attribute( "by", "0.0" ).toDouble() ), 1 );
01674 q.setPoint( NormalizedPoint( qe.attribute( "cx", "0.0" ).toDouble(), qe.attribute( "cy", "0.0" ).toDouble() ), 2 );
01675 q.setPoint( NormalizedPoint( qe.attribute( "dx", "0.0" ).toDouble(), qe.attribute( "dy", "0.0" ).toDouble() ), 3 );
01676 q.setCapStart( qe.hasAttribute( "start" ) );
01677 q.setCapEnd( qe.hasAttribute( "end" ) );
01678 q.setFeather( qe.attribute( "feather", "0.1" ).toDouble() );
01679
01680 q.transform( QMatrix() );
01681
01682 d->m_highlightQuads.append( q );
01683 }
01684
01685
01686 break;
01687 }
01688 }
01689
01690 HighlightAnnotation::~HighlightAnnotation()
01691 {
01692 }
01693
01694 void HighlightAnnotation::setHighlightType( HighlightType type )
01695 {
01696 Q_D( HighlightAnnotation );
01697 d->m_highlightType = type;
01698 }
01699
01700 HighlightAnnotation::HighlightType HighlightAnnotation::highlightType() const
01701 {
01702 Q_D( const HighlightAnnotation );
01703 return d->m_highlightType;
01704 }
01705
01706 QList< HighlightAnnotation::Quad > & HighlightAnnotation::highlightQuads()
01707 {
01708 Q_D( HighlightAnnotation );
01709 return d->m_highlightQuads;
01710 }
01711
01712 void HighlightAnnotation::store( QDomNode & node, QDomDocument & document ) const
01713 {
01714 Q_D( const HighlightAnnotation );
01715
01716 Annotation::store( node, document );
01717
01718
01719 QDomElement hlElement = document.createElement( "hl" );
01720 node.appendChild( hlElement );
01721
01722
01723 if ( d->m_highlightType != Highlight )
01724 hlElement.setAttribute( "type", (int)d->m_highlightType );
01725 if ( d->m_highlightQuads.count() < 1 )
01726 return;
01727
01728 QList< Quad >::const_iterator it = d->m_highlightQuads.begin(), end = d->m_highlightQuads.end();
01729 for ( ; it != end; ++it )
01730 {
01731 QDomElement quadElement = document.createElement( "quad" );
01732 hlElement.appendChild( quadElement );
01733 const Quad & q = *it;
01734 quadElement.setAttribute( "ax", q.point( 0 ).x );
01735 quadElement.setAttribute( "ay", q.point( 0 ).y );
01736 quadElement.setAttribute( "bx", q.point( 1 ).x );
01737 quadElement.setAttribute( "by", q.point( 1 ).y );
01738 quadElement.setAttribute( "cx", q.point( 2 ).x );
01739 quadElement.setAttribute( "cy", q.point( 2 ).y );
01740 quadElement.setAttribute( "dx", q.point( 3 ).x );
01741 quadElement.setAttribute( "dy", q.point( 3 ).y );
01742 if ( q.capStart() )
01743 quadElement.setAttribute( "start", 1 );
01744 if ( q.capEnd() )
01745 quadElement.setAttribute( "end", 1 );
01746 quadElement.setAttribute( "feather", q.feather() );
01747 }
01748 }
01749
01750 Annotation::SubType HighlightAnnotation::subType() const
01751 {
01752 return AHighlight;
01753 }
01754
01755 void HighlightAnnotationPrivate::transform( const QMatrix &matrix )
01756 {
01757 AnnotationPrivate::transform( matrix );
01758
01759 QMutableListIterator<HighlightAnnotation::Quad> it( m_highlightQuads );
01760 while ( it.hasNext() )
01761 it.next().transform( matrix );
01762 }
01763
01764 void HighlightAnnotationPrivate::baseTransform( const QMatrix &matrix )
01765 {
01766 AnnotationPrivate::baseTransform( matrix );
01767
01768 QMutableListIterator<HighlightAnnotation::Quad> it( m_highlightQuads );
01769 while ( it.hasNext() )
01770 it.next().transform( matrix );
01771 }
01772
01775 class Okular::StampAnnotationPrivate : public Okular::AnnotationPrivate
01776 {
01777 public:
01778 StampAnnotationPrivate()
01779 : AnnotationPrivate(), m_stampIconName( "Draft" )
01780 {
01781 }
01782
01783 QString m_stampIconName;
01784 };
01785
01786 StampAnnotation::StampAnnotation()
01787 : Annotation( *new StampAnnotationPrivate() )
01788 {
01789 }
01790
01791 StampAnnotation::StampAnnotation( const QDomNode & node )
01792 : Annotation( *new StampAnnotationPrivate(), node )
01793 {
01794 Q_D( StampAnnotation );
01795
01796 QDomNode subNode = node.firstChild();
01797 while( subNode.isElement() )
01798 {
01799 QDomElement e = subNode.toElement();
01800 subNode = subNode.nextSibling();
01801 if ( e.tagName() != "stamp" )
01802 continue;
01803
01804
01805 if ( e.hasAttribute( "icon" ) )
01806 d->m_stampIconName = e.attribute( "icon" );
01807
01808
01809 break;
01810 }
01811 }
01812
01813 StampAnnotation::~StampAnnotation()
01814 {
01815 }
01816
01817 void StampAnnotation::setStampIconName( const QString &name )
01818 {
01819 Q_D( StampAnnotation );
01820 d->m_stampIconName = name;
01821 }
01822
01823 QString StampAnnotation::stampIconName() const
01824 {
01825 Q_D( const StampAnnotation );
01826 return d->m_stampIconName;
01827 }
01828
01829 Annotation::SubType StampAnnotation::subType() const
01830 {
01831 return AStamp;
01832 }
01833
01834 void StampAnnotation::store( QDomNode & node, QDomDocument & document ) const
01835 {
01836 Q_D( const StampAnnotation );
01837
01838 Annotation::store( node, document );
01839
01840
01841 QDomElement stampElement = document.createElement( "stamp" );
01842 node.appendChild( stampElement );
01843
01844
01845 if ( d->m_stampIconName != "Draft" )
01846 stampElement.setAttribute( "icon", d->m_stampIconName );
01847 }
01848
01851 class Okular::InkAnnotationPrivate : public Okular::AnnotationPrivate
01852 {
01853 public:
01854 InkAnnotationPrivate()
01855 : AnnotationPrivate()
01856 {
01857 }
01858
01859 virtual void transform( const QMatrix &matrix );
01860 virtual void baseTransform( const QMatrix &matrix );
01861 virtual void resetTransformation();
01862 virtual void translate( const NormalizedPoint &coord );
01863
01864 QList< QLinkedList<NormalizedPoint> > m_inkPaths;
01865 QList< QLinkedList<NormalizedPoint> > m_transformedInkPaths;
01866 };
01867
01868 InkAnnotation::InkAnnotation()
01869 : Annotation( *new InkAnnotationPrivate() )
01870 {
01871 }
01872
01873 InkAnnotation::InkAnnotation( const QDomNode & node )
01874 : Annotation( *new InkAnnotationPrivate(), node )
01875 {
01876 Q_D( InkAnnotation );
01877
01878 QDomNode subNode = node.firstChild();
01879 while( subNode.isElement() )
01880 {
01881 QDomElement e = subNode.toElement();
01882 subNode = subNode.nextSibling();
01883 if ( e.tagName() != "ink" )
01884 continue;
01885
01886
01887 QDomNode pathNode = e.firstChild();
01888 while ( pathNode.isElement() )
01889 {
01890 QDomElement pathElement = pathNode.toElement();
01891 pathNode = pathNode.nextSibling();
01892
01893 if ( pathElement.tagName() != "path" )
01894 continue;
01895
01896
01897 QLinkedList<NormalizedPoint> path;
01898 QDomNode pointNode = pathElement.firstChild();
01899 while ( pointNode.isElement() )
01900 {
01901 QDomElement pointElement = pointNode.toElement();
01902 pointNode = pointNode.nextSibling();
01903
01904 if ( pointElement.tagName() != "point" )
01905 continue;
01906
01907 NormalizedPoint p;
01908 p.x = pointElement.attribute( "x", "0.0" ).toDouble();
01909 p.y = pointElement.attribute( "y", "0.0" ).toDouble();
01910 path.append( p );
01911 }
01912
01913
01914 if ( path.count() >= 2 )
01915 d->m_inkPaths.append( path );
01916 }
01917
01918
01919 break;
01920 }
01921
01922 d->m_transformedInkPaths = d->m_inkPaths;
01923 }
01924
01925 InkAnnotation::~InkAnnotation()
01926 {
01927 }
01928
01929 void InkAnnotation::setInkPaths( const QList< QLinkedList<NormalizedPoint> > &paths )
01930 {
01931 Q_D( InkAnnotation );
01932 d->m_inkPaths = paths;
01933 }
01934
01935 QList< QLinkedList<NormalizedPoint> > InkAnnotation::inkPaths() const
01936 {
01937 Q_D( const InkAnnotation );
01938 return d->m_inkPaths;
01939 }
01940
01941 QList< QLinkedList<NormalizedPoint> > InkAnnotation::transformedInkPaths() const
01942 {
01943 Q_D( const InkAnnotation );
01944 return d->m_transformedInkPaths;
01945 }
01946
01947 Annotation::SubType InkAnnotation::subType() const
01948 {
01949 return AInk;
01950 }
01951
01952 void InkAnnotation::store( QDomNode & node, QDomDocument & document ) const
01953 {
01954 Q_D( const InkAnnotation );
01955
01956 Annotation::store( node, document );
01957
01958
01959 QDomElement inkElement = document.createElement( "ink" );
01960 node.appendChild( inkElement );
01961
01962
01963 if ( d->m_inkPaths.count() < 1 )
01964 return;
01965
01966 QList< QLinkedList<NormalizedPoint> >::const_iterator pIt = d->m_inkPaths.begin(), pEnd = d->m_inkPaths.end();
01967 for ( ; pIt != pEnd; ++pIt )
01968 {
01969 QDomElement pathElement = document.createElement( "path" );
01970 inkElement.appendChild( pathElement );
01971 const QLinkedList<NormalizedPoint> & path = *pIt;
01972 QLinkedList<NormalizedPoint>::const_iterator iIt = path.begin(), iEnd = path.end();
01973 for ( ; iIt != iEnd; ++iIt )
01974 {
01975 const NormalizedPoint & point = *iIt;
01976 QDomElement pointElement = document.createElement( "point" );
01977 pathElement.appendChild( pointElement );
01978 pointElement.setAttribute( "x", point.x );
01979 pointElement.setAttribute( "y", point.y );
01980 }
01981 }
01982 }
01983
01984 void InkAnnotationPrivate::transform( const QMatrix &matrix )
01985 {
01986 AnnotationPrivate::transform( matrix );
01987
01988 for ( int i = 0; i < m_transformedInkPaths.count(); ++i )
01989 {
01990 QMutableLinkedListIterator<NormalizedPoint> it( m_transformedInkPaths[ i ] );
01991 while ( it.hasNext() )
01992 it.next().transform( matrix );
01993 }
01994 }
01995
01996 void InkAnnotationPrivate::baseTransform( const QMatrix &matrix )
01997 {
01998 AnnotationPrivate::baseTransform( matrix );
01999
02000 for ( int i = 0; i < m_inkPaths.count(); ++i )
02001 {
02002 QMutableLinkedListIterator<NormalizedPoint> it( m_inkPaths[ i ] );
02003 while ( it.hasNext() )
02004 it.next().transform( matrix );
02005 }
02006 }
02007
02008 void InkAnnotationPrivate::resetTransformation()
02009 {
02010 AnnotationPrivate::resetTransformation();
02011
02012 m_transformedInkPaths = m_inkPaths;
02013 }
02014
02015 void InkAnnotationPrivate::translate( const NormalizedPoint &coord )
02016 {
02017 AnnotationPrivate::translate( coord );
02018
02019 for ( int i = 0; i < m_inkPaths.count(); ++i )
02020 {
02021 QMutableLinkedListIterator<NormalizedPoint> it( m_inkPaths[ i ] );
02022 while ( it.hasNext() )
02023 {
02024 NormalizedPoint& p = it.next();
02025 p.x = p.x + coord.x;
02026 p.y = p.y + coord.y;
02027 }
02028 }
02029 }