summaryrefslogtreecommitdiffstats
path: root/kpresenter/KPrPieObject.cpp
diff options
context:
space:
mode:
authortpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-01-20 01:29:50 +0000
committertpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-01-20 01:29:50 +0000
commit8362bf63dea22bbf6736609b0f49c152f975eb63 (patch)
tree0eea3928e39e50fae91d4e68b21b1e6cbae25604 /kpresenter/KPrPieObject.cpp
downloadkoffice-8362bf63dea22bbf6736609b0f49c152f975eb63.tar.gz
koffice-8362bf63dea22bbf6736609b0f49c152f975eb63.zip
Added old abandoned KDE3 version of koffice
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/koffice@1077364 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'kpresenter/KPrPieObject.cpp')
-rw-r--r--kpresenter/KPrPieObject.cpp607
1 files changed, 607 insertions, 0 deletions
diff --git a/kpresenter/KPrPieObject.cpp b/kpresenter/KPrPieObject.cpp
new file mode 100644
index 00000000..9ed85109
--- /dev/null
+++ b/kpresenter/KPrPieObject.cpp
@@ -0,0 +1,607 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998, 1999 Reginald Stadlbauer <reggie@kde.org>
+ Copyright (C) 2005-2006 Thorsten Zachmann <zachmann@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include "KPrPieObject.h"
+#include "KPrGradient.h"
+#include "KPrUtils.h"
+#include "KPrPieObjectIface.h"
+
+#include <KoTextZoomHandler.h>
+#include <KoOasisContext.h>
+#include <KoStyleStack.h>
+#include <KoXmlNS.h>
+
+#include <kdebug.h>
+
+#include <qregion.h>
+#include <qpicture.h>
+#include <qdom.h>
+#include <qpainter.h>
+#include <qbitmap.h>
+using namespace std;
+
+KPrPieObject::KPrPieObject()
+: KPr2DObject()
+, KPrStartEndLine( L_NORMAL, L_NORMAL )
+{
+ pieType = PT_PIE;
+ p_angle = 45 * 16;
+ p_len = 270 * 16;
+}
+
+KPrPieObject::KPrPieObject( const KoPen &_pen, const QBrush &_brush, FillType _fillType,
+ const QColor &_gColor1, const QColor &_gColor2, BCType _gType,
+ PieType _pieType, int _p_angle, int _p_len,
+ LineEnd _lineBegin, LineEnd _lineEnd,
+ bool _unbalanced, int _xfactor, int _yfactor )
+: KPr2DObject( _pen, _brush, _fillType, _gColor1, _gColor2, _gType, _unbalanced, _xfactor, _yfactor )
+, KPrStartEndLine( _lineBegin, _lineEnd )
+{
+ pieType = _pieType;
+ p_angle = _p_angle;
+ p_len = _p_len;
+}
+
+DCOPObject* KPrPieObject::dcopObject()
+{
+ if ( !dcop )
+ dcop = new KPrPieObjectIface( this );
+ return dcop;
+}
+
+KPrPieObject &KPrPieObject::operator=( const KPrPieObject & )
+{
+ return *this;
+}
+
+QDomDocumentFragment KPrPieObject::save( QDomDocument& doc, double offset )
+{
+ QDomDocumentFragment fragment=KPr2DObject::save(doc, offset);
+ KPrStartEndLine::save( fragment, doc );
+ if (p_angle!=720)
+ fragment.appendChild(KPrObject::createValueElement("PIEANGLE", p_angle, doc));
+ if (p_len!=1440)
+ fragment.appendChild(KPrObject::createValueElement("PIELENGTH", p_len, doc));
+ if (pieType!=PT_PIE)
+ fragment.appendChild(KPrObject::createValueElement("PIETYPE", static_cast<int>(pieType), doc));
+ return fragment;
+}
+
+bool KPrPieObject::saveOasisObjectAttributes( KPOasisSaveContext &sc ) const
+{
+ switch( pieType )
+ {
+ case PT_PIE:
+ sc.xmlWriter.addAttribute( "draw:kind", "section" );
+ break;
+ case PT_CHORD:
+ sc.xmlWriter.addAttribute( "draw:kind", "cut" );
+ break;
+ case PT_ARC:
+ sc.xmlWriter.addAttribute( "draw:kind", "arc" );
+ break;
+ default:
+ kdDebug() << " type of pie not supported" << endl;
+ }
+
+ int startangle = ( (int)p_angle / 16 );
+ sc.xmlWriter.addAttribute( "draw:start-angle", startangle );
+
+ int endangle = ( (int) p_len / 16 ) + startangle;
+ sc.xmlWriter.addAttribute( "draw:end-angle", endangle );
+
+ return true;
+}
+
+void KPrPieObject::fillStyle( KoGenStyle& styleObjectAuto, KoGenStyles& mainStyles ) const
+{
+ KPrShadowObject::fillStyle( styleObjectAuto, mainStyles );
+ if ( pieType == PT_ARC )
+ {
+ saveOasisMarkerElement( mainStyles, styleObjectAuto );
+ }
+ else
+ {
+ m_brush.saveOasisFillStyle( styleObjectAuto, mainStyles );
+ }
+}
+
+const char * KPrPieObject::getOasisElementName() const
+{
+ return ext.width() == ext.height() ? "draw:circle" : "draw:ellipse";
+}
+
+
+void KPrPieObject::loadOasis(const QDomElement &element, KoOasisContext & context, KPrLoadingInfo *info)
+{
+ kdDebug()<<"void KPrPieObject::loadOasis(const QDomElement &element) ***************\n";
+ KPr2DObject::loadOasis(element, context, info);
+ QString kind = element.attributeNS( KoXmlNS::draw, "kind", QString::null );
+ if ( kind == "section" )
+ pieType = PT_PIE;
+ else if ( kind == "cut" )
+ pieType = PT_CHORD;
+ else if ( kind == "arc" )
+ pieType =PT_ARC;
+ else
+ {
+ kdDebug()<<" KPrPieObject::loadOasis(const QDomElement &element) type indefined :"<<kind<<endl;
+ pieType = PT_PIE;
+ }
+ kdDebug()<<" type of pie object :"<<( ( pieType == PT_PIE ) ? "pie" : ( pieType == PT_CHORD )?"cut" : "arc" )<<endl;
+
+ int start = (int) ( element.attributeNS( KoXmlNS::draw, "start-angle", QString::null ).toDouble() );
+ p_angle=start*16;
+
+ int end = (int) ( element.attributeNS( KoXmlNS::draw, "end-angle", QString::null ).toDouble() );
+ if ( end < start )
+ p_len = ( ( 360 - start + end ) * 16 );
+ else
+ p_len = ( ( end - start ) * 16 );
+
+ kdDebug()<<"KPrPieObject::loadOasis(const QDomElement &element) : p_angle :"<<p_angle<<" p_len :"<<p_len<<endl;
+ if ( pieType == PT_ARC )
+ {
+ loadOasisMarkerElement( context, "marker-start", lineBegin );
+ loadOasisMarkerElement( context, "marker-end", lineEnd );
+ }
+}
+
+double KPrPieObject::load(const QDomElement &element)
+{
+ double offset=KPr2DObject::load(element);
+ KPrStartEndLine::load( element );
+ QDomElement e=element.namedItem("PIEANGLE").toElement();
+ if(!e.isNull()) {
+ int tmp=0;
+ if(e.hasAttribute("value"))
+ tmp=e.attribute("value").toInt();
+ p_angle=tmp;
+ }
+ e=element.namedItem("PIELENGTH").toElement();
+ if(!e.isNull()) {
+ int tmp=0;
+ if(e.hasAttribute("value"))
+ tmp=e.attribute("value").toInt();
+ p_len=tmp;
+ }
+ else
+ p_len=1440; //necessary to reinitialise p_len
+ //I don't know who change default value
+ e=element.namedItem("PIETYPE").toElement();
+ if(!e.isNull()) {
+ int tmp=0;
+ if(e.hasAttribute("value"))
+ tmp=e.attribute("value").toInt();
+ pieType=static_cast<PieType>(tmp);
+ }
+ return offset;
+}
+
+void KPrPieObject::paint( QPainter* _painter, KoTextZoomHandler*_zoomHandler,
+ int /* pageNum */, bool drawingShadow, bool drawContour )
+{
+ double ow = ext.width();
+ double oh = ext.height();
+ double pw = ( ( pen.style() == Qt::NoPen ) ? 1 : pen.pointWidth() ) / 2.0;
+
+ if ( drawContour ) {
+ QPen pen3( Qt::black, 1, Qt::DotLine );
+ _painter->setPen( pen3 );
+ _painter->setRasterOp( Qt::NotXorROP );
+ }
+ else {
+ QPen pen2 = pen.zoomedPen( _zoomHandler );
+ _painter->setPen( pen2 );
+ if ( drawingShadow || getFillType() == FT_BRUSH || !gradient )
+ {
+ _painter->setBrush( getBrush() );
+ }
+ else
+ {
+ if ( pieType != PT_ARC )
+ {
+ QSize size( _zoomHandler->zoomSize( ext ) );
+
+ if ( m_redrawGradientPix || gradient->size() != size )
+ {
+ m_redrawGradientPix = false;
+ gradient->setSize( size );
+
+ m_gradientPix.resize ( size );
+ m_gradientPix.fill( Qt::white );
+ QPainter p;
+ p.begin( &m_gradientPix );
+ p.drawPixmap( 0, 0, gradient->pixmap() );
+ p.end();
+
+ QBitmap mask( size, true );
+ p.begin( &mask );
+ p.setPen( QPen( Qt::color1 ) );
+ p.setBrush( QBrush( Qt::color1 ) );
+ if ( pieType == PT_CHORD )
+ {
+ p.drawChord( _zoomHandler->zoomItX(pw), _zoomHandler->zoomItY(pw),
+ _zoomHandler->zoomItX(ow - 2 * pw),
+ _zoomHandler->zoomItY(oh - 2 * pw), p_angle, p_len );
+ }
+ else
+ {
+ p.drawPie( _zoomHandler->zoomItX(pw), _zoomHandler->zoomItY(pw),
+ _zoomHandler->zoomItX( ow - 2 * pw),
+ _zoomHandler->zoomItY( oh - 2 * pw), p_angle, p_len );
+ }
+ p.end();
+ m_gradientPix.setMask( mask );
+ }
+ _painter->drawPixmap( 0, 0, m_gradientPix, 0, 0, size.width(), size.height() );
+ _painter->setBrush( Qt::NoBrush );
+ }
+ }
+ if ( pieType == PT_ARC )
+ {
+ KoPointArray points( 2 );
+ setEndPoints( points );
+ KoPoint start( points.point( 0 ) );
+ KoPoint end( points.point( 1 ) );
+
+ double ys = ( ( 1 - start.x() / ( ext.width() * ext.width() / 4 ) ) * ext.height() * ext.height() / 4 ) / start.y();
+ double s_angle = 90 + ( atan( ( start.x() - 1 ) / ( start.y() - ys ) ) * 180 / M_PI );
+ if ( p_angle / 16 >= 90 && p_angle / 16 <= 270 )
+ {
+ s_angle += 180.0;
+ }
+ double ye = ( ( 1 - end.x() / ( ext.width() * ext.width() / 4 ) ) * ext.height() * ext.height() / 4 ) / end.y();
+ double e_angle = 270 + ( atan( ( end.x() - 1 ) / ( end.y() - ye ) ) * 180 / M_PI );
+ if ( ( ( p_angle + p_len ) / 16 ) % 360 >= 90 && ( ( p_angle + p_len ) / 16 ) % 360 <= 270 )
+ {
+ e_angle -= 180.0;
+ }
+
+ start = KoPoint( ext.width() / 2.0 + start.x(), ext.height() / 2.0 - start.y() );
+ end = KoPoint( ext.width() / 2.0 + end.x(), ext.height() / 2.0 - end.y() );
+
+
+
+ if ( lineBegin != L_NORMAL )
+ drawFigureWithOffset( lineBegin, _painter, start,
+ pen2.color(), int( pen.pointWidth() ), s_angle, _zoomHandler, true );
+
+ if ( lineEnd != L_NORMAL )
+ drawFigureWithOffset( lineEnd, _painter, end,
+ pen2.color(), int( pen.pointWidth() ), e_angle, _zoomHandler, false );
+ }
+ }
+ switch ( pieType )
+ {
+ case PT_PIE:
+ _painter->drawPie( _zoomHandler->zoomItX(pw), _zoomHandler->zoomItY( pw),
+ _zoomHandler->zoomItX( ow - 2 * pw),
+ _zoomHandler->zoomItY( oh - 2 * pw), p_angle, p_len );
+ break;
+ case PT_ARC:
+ _painter->drawArc( _zoomHandler->zoomItX(pw), _zoomHandler->zoomItY(pw),
+ _zoomHandler->zoomItX(ow - 2 * pw),
+ _zoomHandler->zoomItY(oh - 2 * pw), p_angle, p_len );
+ break;
+ case PT_CHORD:
+ _painter->drawChord( _zoomHandler->zoomItX(pw), _zoomHandler->zoomItY(pw),
+ _zoomHandler->zoomItX(ow - 2 * pw),
+ _zoomHandler->zoomItY(oh - 2 * pw), p_angle, p_len );
+ break;
+ default: break;
+ }
+}
+
+void KPrPieObject::flip( bool horizontal )
+{
+ KPr2DObject::flip( horizontal );
+ if ( ! horizontal )
+ {
+ p_angle = 360*16 - p_angle -p_len;
+ }
+ else
+ {
+ p_angle = 180*16 - p_angle - p_len;
+ }
+ // angle smaller 0
+ while ( p_angle < 0 ) {
+ p_angle += 360*16;
+ }
+
+}
+
+
+void KPrPieObject::setMinMax( double &min_x, double &min_y,
+ double &max_x, double &max_y, KoPoint point ) const
+{
+ double tmp_x = point.x();
+ double tmp_y = point.y();
+
+ if ( tmp_x < min_x ) {
+ min_x = tmp_x;
+ }
+ else if ( tmp_x > max_x ) {
+ max_x = tmp_x;
+ }
+
+ if ( tmp_y < min_y ) {
+ min_y = tmp_y;
+ }
+ else if ( tmp_y > max_y ) {
+ max_y = tmp_y;
+ }
+}
+
+
+/*
+ * The calculation of the real size and origin for a pie object is a little more
+ * complicated. It took me quite a whlie to get it right.
+ * Here is how it works:
+ * 1. calculate the position of the end points
+ * 2. calculate the 4 maximal points, the points with max x or y position, of the
+ * hole ellipse
+ * 3. find minimal and maximal points
+ * 4. check if the maximal points lie on the arc
+ *
+ */
+void KPrPieObject::getRealSizeAndOrig( KoSize &size, KoPoint &realOrig ) const {
+ double radius1 = size.width() / 2.0;
+ double radius2 = size.height() / 2.0;
+
+ // the rotation angle
+ double angInRad = angle * M_PI / 180;
+
+ // 1. calulate position of end points
+ KoPointArray points(2);
+ setEndPoints( points );
+
+ // rotate point
+ for ( int i = 0; i < 2; i++ ) {
+ if ( angle != 0 ) {
+ double sinus = sin( angInRad );
+ double cosinus = cos( angInRad );
+
+ double tmp_x = points.point( i ).x();
+ double tmp_y = points.point( i ).y();
+
+ double x = tmp_x * cosinus + tmp_y * sinus;
+ double y = - tmp_x * sinus + tmp_y * cosinus;
+ points.setPoint( i, x, y );
+ }
+ }
+
+ KoPoint firstPoint( points.point(0) );
+ KoPoint secondPoint( points.point(1) );
+
+ // 2. calulate maximal points
+ KoPointArray maxPoints(4);
+ if ( angle == 0 ) {
+ maxPoints.setPoint( 0, 0, radius2 );
+ maxPoints.setPoint( 1, radius1, 0 );
+ maxPoints.setPoint( 2, 0, -radius2 );
+ maxPoints.setPoint( 3, -radius1, 0 );
+ }
+ else {
+ double sinus = sin( angInRad );
+ double cosinus = cos( angInRad );
+
+ double x = sqrt( pow( radius1 * cosinus , 2 ) + pow(radius2 * sinus, 2));
+ double y = ( pow( radius2, 2 ) - pow( radius1, 2) ) * sinus * cosinus / x;
+ maxPoints.setPoint( 0, x, y );
+ maxPoints.setPoint( 1, -x, -y );
+
+ y = sqrt( pow( radius1 * sinus , 2 ) + pow(radius2 * cosinus, 2));
+ x = ( pow( radius1, 2 ) - pow( radius2, 2) ) * sinus * cosinus / y;
+ maxPoints.setPoint( 2, x, y);
+ maxPoints.setPoint( 3, -x, -y );
+ }
+
+ // 3. find minimal and maximal points
+ double min_x = firstPoint.x();
+ double min_y = firstPoint.y();
+ double max_x = firstPoint.x();
+ double max_y = firstPoint.y();
+
+ if ( pieType == PT_PIE ) {
+ KoPoint zero(0,0);
+ setMinMax( min_x, min_y, max_x, max_y, zero );
+ }
+ setMinMax( min_x, min_y, max_x, max_y, secondPoint );
+
+ /* 4. check if maximal points lie on the arc.
+ * There are three posibilities how many sections have to
+ * been checked.
+ * 1. the arc is only once on one side of the x axis
+ * 2. the arc is on both sides of the x axis
+ * 3. the arc is twice on one one side of the x axis
+ *
+ * 1) 2) 3)
+ * y y y
+ * ex|xx xx|xs s |
+ * | x x | x | e
+ * | s x | x | x
+ * ----+---- x ----+---- x ----+---- x
+ * | x | x | x
+ * | x | x | x
+ * | e | xx|xx
+ *
+ */
+ if ( firstPoint.y() >= 0 ) {
+ if ( secondPoint.y() >= 0 ) {
+ if ( firstPoint.x() > secondPoint.x() || p_len == 0 ) {
+ // 1 section
+ // f.x() <= x <= s.x() && y >= 0
+ KoPointArray::ConstIterator it( maxPoints.begin() );
+ for ( ; it != maxPoints.end(); ++it ) {
+ if ( (*it).y() >= 0 &&
+ (*it).x() <= firstPoint.x() && (*it).x() >= secondPoint.x() )
+ {
+ setMinMax( min_x, min_y, max_x, max_y, *it );
+ }
+ }
+ }
+ else {
+ // 3 sections
+ // x <= f.x() && y >= 0
+ // y < 0
+ // x >= s.x() && y >= 0
+ KoPointArray::ConstIterator it( maxPoints.begin() );
+ for ( ; it != maxPoints.end(); ++it ) {
+ if ( (*it).y() >= 0 ) {
+ if ( (*it).x() <= firstPoint.x() || (*it).x() >= secondPoint.x() ) {
+ setMinMax( min_x, min_y, max_x, max_y, *it );
+ }
+ }
+ else {
+ setMinMax( min_x, min_y, max_x, max_y, *it );
+ }
+ }
+ }
+ }
+ else {
+ // 2 sections
+ // x <= f.x() && y >= 0
+ // x <= s.x() && y < 0
+ KoPointArray::ConstIterator it( maxPoints.begin() );
+ for ( ; it != maxPoints.end(); ++it ) {
+ if ( (*it).y() >= 0 ) {
+ if ( (*it).x() <= firstPoint.x() ) {
+ setMinMax( min_x, min_y, max_x, max_y, *it );
+ }
+ }
+ else {
+ if ( (*it).x() <= secondPoint.x() ) {
+ setMinMax( min_x, min_y, max_x, max_y, *it );
+ }
+ }
+ }
+ }
+ }
+ else {
+ if ( secondPoint.y() >= 0 ) {
+ // 2 sections
+ // x >= f.x() && y < 0
+ // x >= s.x() && y >= 0
+ KoPointArray::ConstIterator it( maxPoints.begin() );
+ for ( ; it != maxPoints.end(); ++it ) {
+ if ( (*it).y() < 0 ) {
+ if ( (*it).x() >= firstPoint.x() ) {
+ setMinMax( min_x, min_y, max_x, max_y, *it );
+ }
+ }
+ else {
+ if ( (*it).x() >= secondPoint.x() ) {
+ setMinMax( min_x, min_y, max_x, max_y, *it );
+ }
+ }
+ }
+ }
+ else {
+ if ( firstPoint.x() < secondPoint.x() || p_len == 0 ) {
+ // 1 section
+ // f.x() <= x <= s.x() && y < 0
+ KoPointArray::ConstIterator it( maxPoints.begin() );
+ for ( ; it != maxPoints.end(); ++it ) {
+ if ( (*it).y() < 0 &&
+ (*it).x() >= firstPoint.x() && (*it).x() <= secondPoint.x() )
+ {
+ setMinMax( min_x, min_y, max_x, max_y, *it );
+ }
+ }
+ }
+ else {
+ // 3 sections
+ // x >= f.x() && y < 0
+ // y >= 0
+ // x <= s.x() && y < 0
+ KoPointArray::ConstIterator it( maxPoints.begin() );
+ for ( ; it != maxPoints.end(); ++it ) {
+ if ( (*it).y() < 0 ) {
+ if ( (*it).x() >= firstPoint.x() || (*it).x() <= secondPoint.x() ) {
+ setMinMax( min_x, min_y, max_x, max_y, *it );
+ }
+ }
+ else {
+ setMinMax( min_x, min_y, max_x, max_y, *it );
+ }
+ }
+ }
+ }
+ }
+
+ double mid_x = size.width() / 2;
+ double mid_y = size.height() / 2;
+
+ size.setWidth( max_x - min_x );
+ size.setHeight( max_y - min_y );
+
+ realOrig.setX( realOrig.x() + mid_x + min_x );
+ realOrig.setY( realOrig.y() + mid_y - max_y );
+}
+
+void KPrPieObject::setEndPoints( KoPointArray &points ) const
+{
+ int angles[] = { p_angle, ( p_angle + p_len ) % ( 16 * 360 ) };
+ double anglesInRad[] = { p_angle / 16.0 * M_PI / 180, ( angles[1] ) / 16.0 * M_PI / 180 };
+
+ double radius1 = ext.width() / 2.0;
+ double radius2 = ext.height() / 2.0;
+
+ double prop = radius2 / radius1;
+
+ for ( int i = 0; i < 2; i++ ) {
+ double x = 0;
+ double y = 0;
+
+ // be carefull
+ if ( angles[i] == 90 * 16 ) {
+ y = radius2;
+ }
+ else if ( angles[i] == 270 * 16 ) {
+ y = -radius2;
+ }
+ else {
+ // The real angle is not what was given. It is only ok if radius1 == radius2,
+ // otherwise it is arctan ( radius2 / radius1 tan ( angle ) )
+ double tanalpha = tan( anglesInRad[i] ) * prop;
+ x = sqrt( 1 / ( pow ( 1 / radius1, 2 ) + pow( tanalpha / radius2, 2 ) ) );
+ if ( angles[i] > 90 * 16 && angles[i] < 270 * 16 )
+ x = -x;
+ y = tanalpha * x;
+ }
+ points.setPoint( i, x, y );
+ }
+}
+
+KoSize KPrPieObject::getRealSize() const {
+ KoSize size( ext );
+ KoPoint realOrig( orig );
+ getRealSizeAndOrig( size, realOrig );
+ return size;
+}
+
+
+KoPoint KPrPieObject::getRealOrig() const {
+ KoSize size( ext );
+ KoPoint realOrig( orig );
+ getRealSizeAndOrig( size, realOrig );
+ return realOrig;
+}