00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <qdom.h>
00021 #include <qbuffer.h>
00022
00023 #include "vdocument.h"
00024 #include "vglobal.h"
00025 #include "vgradient.h"
00026
00027 #include <KoGenStyles.h>
00028 #include <KoXmlWriter.h>
00029 #include <KoXmlNS.h>
00030
00031 int VGradient::VColorStopList::compareItems( QPtrCollection::Item item1, QPtrCollection::Item item2 )
00032 {
00033 float r1 = ( (VColorStop*)item1 )->rampPoint;
00034 float r2 = ( (VColorStop*)item2 )->rampPoint;
00035
00036 return ( r1 == r2 ? 0 : r1 < r2 ? -1 : 1 );
00037 }
00038
00039 VGradient::VGradient( VGradientType type )
00040 : m_type( type )
00041 {
00042 m_colorStops.setAutoDelete( true );
00043
00044
00045 VColor color;
00046
00047 color.set( 1.0, 0.0, 0.0 );
00048 addStop( color, 0.0, 0.5 );
00049
00050 color.set( 1.0, 1.0, 0.0 );
00051 addStop( color, 1.0, 0.5 );
00052
00053 setOrigin( KoPoint( 0, 0 ) );
00054 setVector( KoPoint( 0, 50 ) );
00055 setRepeatMethod( VGradient::reflect );
00056 }
00057
00058 VGradient::VGradient( const VGradient& gradient )
00059 {
00060 m_colorStops.setAutoDelete( true );
00061
00062 m_origin = gradient.m_origin;
00063 m_focalPoint = gradient.m_focalPoint;
00064 m_vector = gradient.m_vector;
00065 m_type = gradient.m_type;
00066 m_repeatMethod = gradient.m_repeatMethod;
00067
00068 m_colorStops.clear();
00069 QPtrVector<VColorStop> cs = gradient.colorStops();
00070 for( uint i = 0; i < cs.count(); i++ )
00071 m_colorStops.append( new VColorStop( *cs[i] ) );
00072 m_colorStops.sort();
00073 }
00074
00075 VGradient& VGradient::operator=( const VGradient& gradient )
00076 {
00077 m_colorStops.setAutoDelete( true );
00078
00079 if ( this == &gradient )
00080 return *this;
00081
00082 m_origin = gradient.m_origin;
00083 m_focalPoint = gradient.m_focalPoint;
00084 m_vector = gradient.m_vector;
00085 m_type = gradient.m_type;
00086 m_repeatMethod = gradient.m_repeatMethod;
00087
00088 m_colorStops.clear();
00089 QPtrVector<VColorStop> cs = gradient.colorStops();
00090 for( uint i = 0; i < cs.count(); i++ )
00091 m_colorStops.append( new VColorStop( *cs[i] ) );
00092 m_colorStops.sort();
00093
00094 return *this;
00095 }
00096
00097 const QPtrVector<VColorStop> VGradient::colorStops() const
00098 {
00099 QPtrVector<VColorStop> v;
00100 m_colorStops.toVector( &v );
00101 v.setAutoDelete( false );
00102 return v;
00103 }
00104
00105 void
00106 VGradient::clearStops()
00107 {
00108 m_colorStops.clear();
00109 }
00110
00111 void
00112 VGradient::addStop( const VColorStop& colorStop )
00113 {
00114 m_colorStops.inSort( new VColorStop( colorStop ) );
00115 }
00116
00117 void
00118 VGradient::addStop( const VColor &color, float rampPoint, float midPoint )
00119 {
00120
00121 rampPoint = kMax( 0.0f, rampPoint );
00122 rampPoint = kMin( 1.0f, rampPoint );
00123
00124 midPoint = kMax( 0.0f, midPoint );
00125 midPoint = kMin( 1.0f, midPoint );
00126
00127
00128 VColorStop *v;
00129 for(v = m_colorStops.first(); v; v = m_colorStops.next())
00130 {
00131 if(rampPoint == v->rampPoint)
00132 rampPoint += 0.001f;
00133 }
00134 m_colorStops.inSort( new VColorStop( rampPoint, midPoint, color ) );
00135 }
00136
00137 void VGradient::removeStop( const VColorStop& colorstop )
00138 {
00139 m_colorStops.remove( &colorstop );
00140 }
00141
00142 void
00143 VGradient::save( QDomElement& element ) const
00144 {
00145 QDomElement me = element.ownerDocument().createElement( "GRADIENT" );
00146
00147 me.setAttribute( "originX", m_origin.x() );
00148 me.setAttribute( "originY", m_origin.y() );
00149 me.setAttribute( "focalX", m_focalPoint.x() );
00150 me.setAttribute( "focalY", m_focalPoint.y() );
00151 me.setAttribute( "vectorX", m_vector.x() );
00152 me.setAttribute( "vectorY", m_vector.y() );
00153 me.setAttribute( "type", m_type );
00154 me.setAttribute( "repeatMethod", m_repeatMethod );
00155
00156
00157 VColorStop* colorstop;
00158 QPtrList<VColorStop>& colorStops = const_cast<VColorStopList&>( m_colorStops );
00159 for( colorstop = colorStops.first(); colorstop; colorstop = colorStops.next() )
00160 {
00161 QDomElement stop = element.ownerDocument().createElement( "COLORSTOP" );
00162 colorstop->color.save( stop );
00163 stop.setAttribute( "ramppoint", colorstop->rampPoint );
00164 stop.setAttribute( "midpoint", colorstop->midPoint );
00165 me.appendChild( stop );
00166 }
00167
00168 element.appendChild( me );
00169 }
00170
00171 QString
00172 VGradient::saveOasis( KoGenStyles &mainStyles ) const
00173 {
00174 bool radial = m_type == VGradient::radial;
00175 KoGenStyle gradientStyle( radial ? VDocument::STYLE_RADIAL_GRADIENT : VDocument::STYLE_LINEAR_GRADIENT );
00176 if( radial )
00177 {
00178 gradientStyle.addAttribute( "draw:style", "radial" );
00179 gradientStyle.addAttributePt( "svg:cx", m_origin.x() );
00180 gradientStyle.addAttributePt( "svg:cy", m_origin.y() );
00181 double dx = m_vector.x() - m_origin.x();
00182 double dy = m_vector.y() - m_origin.y();
00183 gradientStyle.addAttributePt( "svg:r", sqrt( dx * dx + dy * dy ) );
00184 gradientStyle.addAttributePt( "svg:fx", m_focalPoint.x() );
00185 gradientStyle.addAttributePt( "svg:fy", m_focalPoint.y() );
00186 }
00187 else
00188 {
00189 gradientStyle.addAttribute( "draw:style", "linear" );
00190 gradientStyle.addAttributePt( "svg:x1", m_origin.x() );
00191 gradientStyle.addAttributePt( "svg:y1", m_origin.y() );
00192 gradientStyle.addAttributePt( "svg:x2", m_vector.x() );
00193 gradientStyle.addAttributePt( "svg:y2", m_vector.y() );
00194 }
00195 if( m_repeatMethod == VGradient::repeat )
00196 gradientStyle.addAttribute( "svg:spreadMethod", "repeat" );
00197 else if( m_repeatMethod == VGradient::reflect )
00198 gradientStyle.addAttribute( "svg:spreadMethod", "reflect" );
00199 else
00200 gradientStyle.addAttribute( "svg:spreadMethod", "pad" );
00201 QBuffer buffer;
00202 buffer.open( IO_WriteOnly );
00203 KoXmlWriter elementWriter( &buffer );
00204
00205
00206 VColorStop* colorstop;
00207 QPtrList<VColorStop>& colorStops = const_cast<VColorStopList&>( m_colorStops );
00208 for( colorstop = colorStops.first(); colorstop; colorstop = colorStops.next() )
00209 {
00210 elementWriter.startElement( "svg:stop" );
00211 elementWriter.addAttribute( "svg:offset", QString( "%1" ).arg( colorstop->rampPoint ) );
00212 elementWriter.addAttribute( "svg:color", QColor( colorstop->color ).name() );
00213 if( colorstop->color.opacity() < 1 )
00214 elementWriter.addAttribute( "svg:stop-opacity", QString( "%1" ).arg( colorstop->color.opacity() ) );
00215 elementWriter.endElement();
00216 }
00217
00218 QString elementContents = QString::fromUtf8( buffer.buffer(), buffer.buffer().size() );
00219 gradientStyle.addChildElement( "svg:stop", elementContents );
00220 return mainStyles.lookup( gradientStyle, "gradient" );
00221 }
00222
00223 void
00224 VGradient::loadOasis( const QDomElement &object, KoStyleStack &, VObject* parent )
00225 {
00226 kdDebug(38000) << "namespaceURI: " << object.namespaceURI() << endl;
00227 kdDebug(38000) << "localName: " << object.localName() << endl;
00228
00229 KoRect bb;
00230
00231 if( parent )
00232 bb = parent->boundingBox();
00233
00234 if( object.namespaceURI() == KoXmlNS::draw && object.localName() == "gradient" )
00235 {
00236 m_repeatMethod = VGradient::reflect;
00237 QString strType = object.attributeNS( KoXmlNS::draw, "style", QString::null );
00238 if( strType == "radial" )
00239 {
00240 m_type = VGradient::radial;
00241
00242 double cx = KoUnit::parseValue( object.attributeNS( KoXmlNS::draw, "cx", QString::null ).remove("%") );
00243 m_origin.setX( bb.bottomLeft().x() + bb.width() * 0.01 * cx );
00244 double cy = KoUnit::parseValue( object.attributeNS( KoXmlNS::draw, "cy", QString::null ).remove("%") );
00245 m_origin.setY( bb.bottomLeft().y() - bb.height() * 0.01 * cy );
00246 m_focalPoint = m_origin;
00247 m_vector = bb.topRight();
00248 }
00249 else if( strType == "linear" )
00250 {
00251 m_type = VGradient::linear;
00252 double angle = 90 + object.attributeNS( KoXmlNS::draw, "angle", "0" ).toDouble();
00253 double radius = 0.5 * sqrt( bb.width()*bb.width() + bb.height()*bb.height() );
00254 double sx = cos( angle * VGlobal::pi / 180 ) * radius;
00255 double sy = sin( angle * VGlobal::pi / 180 ) * radius;
00256 m_origin.setX( bb.center().x() + sx );
00257 m_origin.setY( bb.center().y() + sy );
00258 m_vector.setX( bb.center().x() - sx );
00259 m_vector.setY( bb.center().y() - sy );
00260 m_focalPoint = m_origin;
00261 }
00262 else return;
00263
00264 VColor startColor( QColor( object.attributeNS( KoXmlNS::draw, "start-color", QString::null ) ) );
00265 VColor endColor( QColor( object.attributeNS( KoXmlNS::draw, "end-color", QString::null ) ) );
00266
00267 double startOpacity = 0.01 * object.attributeNS( KoXmlNS::draw, "start-intensity", "100" ).remove("%").toDouble();
00268 double endOpacity = 0.01 * object.attributeNS( KoXmlNS::draw, "end-intensity", "100" ).remove("%").toDouble();
00269
00270 startColor.setOpacity( startOpacity );
00271 endColor.setOpacity( endOpacity );
00272 m_colorStops.clear();
00273 addStop( startColor, 0.0, 0.5 );
00274 addStop( endColor, 1.0, 0.0 );
00275 m_colorStops.sort();
00276
00277 }
00278 else if( object.namespaceURI() == KoXmlNS::svg )
00279 {
00280 if( object.localName() == "linearGradient" )
00281 {
00282 m_type = VGradient::linear;
00283 m_origin.setX( KoUnit::parseValue( object.attributeNS( KoXmlNS::svg, "x1", QString::null ) ) );
00284 m_origin.setY( KoUnit::parseValue( object.attributeNS( KoXmlNS::svg, "y1", QString::null ) ) );
00285 m_vector.setX( KoUnit::parseValue( object.attributeNS( KoXmlNS::svg, "x2", QString::null ) ) );
00286 m_vector.setY( KoUnit::parseValue( object.attributeNS( KoXmlNS::svg, "y2", QString::null ) ) );
00287 m_focalPoint = m_origin;
00288 }
00289 else if( object.localName() == "radialGradient" )
00290 {
00291 m_type = VGradient::radial;
00292 m_origin.setX( KoUnit::parseValue( object.attributeNS( KoXmlNS::svg, "cx", QString::null ) ) );
00293 m_origin.setY( KoUnit::parseValue( object.attributeNS( KoXmlNS::svg, "cy", QString::null ) ) );
00294 double r = KoUnit::parseValue( object.attributeNS( KoXmlNS::svg, "r", QString::null ) );
00295 m_vector.setX( m_origin.x() + r );
00296 m_vector.setY( m_origin.y() );
00297 m_focalPoint.setX( KoUnit::parseValue( object.attributeNS( KoXmlNS::svg, "fx", QString::null ) ) );
00298 m_focalPoint.setY( KoUnit::parseValue( object.attributeNS( KoXmlNS::svg, "fy", QString::null ) ) );
00299 }
00300
00301 QString strSpread( object.attributeNS( KoXmlNS::svg, "spreadMethod", "pad" ) );
00302 if( strSpread == "repeat" )
00303 m_repeatMethod = VGradient::repeat;
00304 else if( strSpread == "reflect" )
00305 m_repeatMethod = VGradient::reflect;
00306 else
00307 m_repeatMethod = VGradient::none;
00308
00309 m_colorStops.clear();
00310
00311
00312 QDomNodeList list = object.childNodes();
00313 for( uint i = 0; i < list.count(); ++i )
00314 {
00315 if( list.item( i ).isElement() )
00316 {
00317 QDomElement colorstop = list.item( i ).toElement();
00318
00319 if( colorstop.namespaceURI() == KoXmlNS::svg && colorstop.localName() == "stop" )
00320 {
00321 VColor color( QColor( colorstop.attributeNS( KoXmlNS::svg, "color", QString::null ) ) );
00322 color.setOpacity( colorstop.attributeNS( KoXmlNS::svg, "stop-opacity", "1.0" ).toDouble() );
00323 addStop( color, colorstop.attributeNS( KoXmlNS::svg, "offset", "0.0" ).toDouble(), 0.5 );
00324 }
00325 }
00326 }
00327 m_colorStops.sort();
00328 }
00329 }
00330
00331 void
00332 VGradient::load( const QDomElement& element )
00333 {
00334 m_origin.setX( element.attribute( "originX", "0.0" ).toDouble() );
00335 m_origin.setY( element.attribute( "originY", "0.0" ).toDouble() );
00336 m_focalPoint.setX( element.attribute( "focalX", "0.0" ).toDouble() );
00337 m_focalPoint.setY( element.attribute( "focalY", "0.0" ).toDouble() );
00338 m_vector.setX( element.attribute( "vectorX", "0.0" ).toDouble() );
00339 m_vector.setY( element.attribute( "vectorY", "0.0" ).toDouble() );
00340 m_type = (VGradientType)element.attribute( "type", 0 ).toInt();
00341 m_repeatMethod = (VGradientRepeatMethod)element.attribute( "repeatMethod", 0 ).toInt();
00342
00343 m_colorStops.clear();
00344
00345
00346 QDomNodeList list = element.childNodes();
00347 for( uint i = 0; i < list.count(); ++i )
00348 {
00349 if( list.item( i ).isElement() )
00350 {
00351 QDomElement colorstop = list.item( i ).toElement();
00352
00353 if( colorstop.tagName() == "COLORSTOP" )
00354 {
00355 VColor color;
00356 color.load( colorstop.firstChild().toElement() );
00357 addStop( color, colorstop.attribute( "ramppoint", "0.0" ).toDouble(), colorstop.attribute( "midpoint", "0.5" ).toDouble() );
00358 }
00359 }
00360 }
00361 m_colorStops.sort();
00362 }
00363
00364 void
00365 VGradient::transform( const QWMatrix &m )
00366 {
00367 m_origin = m_origin.transform( m );
00368 m_focalPoint = m_focalPoint.transform( m );
00369 m_vector = m_vector.transform( m );
00370 }