filters

oodrawimport.cc

00001 /* This file is part of the KDE project
00002    Copyright (c) 2003 Rob Buis <buis@kde.org>
00003 
00004    This library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Library General Public
00006    License as published by the Free Software Foundation; either
00007    version 2 of the License, or (at your option) any later version.
00008 
00009    This library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Library General Public License for more details.
00013 
00014    You should have received a copy of the GNU Library General Public License
00015    along with this library; see the file COPYING.LIB.  If not, write to
00016    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017  * Boston, MA 02110-1301, USA.
00018 */
00019 
00020 #include "oodrawimport.h"
00021 
00022 #include <math.h>
00023 
00024 #include <qdatetime.h>
00025 #include <qfileinfo.h>
00026 #include <qdir.h>
00027 
00028 #include <kzip.h>
00029 #include <karchive.h>
00030 #include <kdebug.h>
00031 #include <KoUnit.h>
00032 #include <KoPageLayout.h>
00033 #include <KoDocumentInfo.h>
00034 #include <KoDocument.h>
00035 #include <ooutils.h>
00036 #include <KoDom.h>
00037 
00038 #include <kgenericfactory.h>
00039 #include <KoFilterChain.h>
00040 #include <KoGlobal.h>
00041 
00042 #include <shapes/vellipse.h>
00043 #include <shapes/vrectangle.h>
00044 #include <shapes/vpolygon.h>
00045 
00046 #include <core/vfill.h>
00047 #include <core/vgroup.h>
00048 
00049 typedef KGenericFactory<OoDrawImport, KoFilter> OoDrawImportFactory;
00050 K_EXPORT_COMPONENT_FACTORY( liboodrawimport, OoDrawImportFactory( "kofficefilters" ) )
00051 
00052 
00053 OoDrawImport::OoDrawImport( KoFilter *, const char *, const QStringList & )
00054     : KoFilter(),
00055       m_styles( 23, true ),
00056       m_styleStack( ooNS::style, ooNS::fo )
00057 {
00058     m_styles.setAutoDelete( true );
00059 }
00060 
00061 OoDrawImport::~OoDrawImport()
00062 {
00063 }
00064 
00065 KoFilter::ConversionStatus OoDrawImport::convert( QCString const & from, QCString const & to )
00066 {
00067     kdDebug() << "Entering Oodraw Import filter: " << from << " - " << to << endl;
00068 
00069     if( from != "application/vnd.sun.xml.draw" || to != "application/x-karbon" )
00070     {
00071         kdWarning() << "Invalid mimetypes " << from << " " << to << endl;
00072         return KoFilter::NotImplemented;
00073     }
00074 
00075     m_zip = new KZip(  m_chain->inputFile() );
00076 
00077     if ( !m_zip->open( IO_ReadOnly ) )
00078     {
00079         kdError(30518) << "Couldn't open the requested file "<< m_chain->inputFile() << endl;
00080         delete m_zip;
00081         return KoFilter::FileNotFound;
00082     }
00083 
00084     KoFilter::ConversionStatus preStatus = openFile();
00085 
00086     if( preStatus != KoFilter::OK )
00087     {
00088         m_zip->close();
00089         delete m_zip;
00090         return preStatus;
00091     }
00092 /*QDomDocument docinfo;
00093   createDocumentInfo( docinfo );
00094 
00095 // store document info
00096 KoStoreDevice* out = m_chain->storageFile( "documentinfo.xml", KoStore::Write );
00097 if( out )
00098 {
00099 QCString info = docinfo.toCString();
00100 //kdDebug() << " info :" << info << endl;
00101 // WARNING: we cannot use KoStore::write(const QByteArray&) because it gives an extra NULL character at the end.
00102 out->writeBlock( info , info.length() );
00103 }*/
00104     QDomDocument docinfo;
00105     createDocumentInfo( docinfo );
00106     // store document info
00107     KoStoreDevice* out = m_chain->storageFile( "documentinfo.xml", KoStore::Write );
00108     if( out )
00109     {
00110         QCString info = docinfo.toCString();
00111         //kdDebug(30518) << " info :" << info << endl;
00112         // WARNING: we cannot use KoStore::write(const QByteArray&) because it gives an extra NULL character at the end.
00113         out->writeBlock( info , info.length() );
00114     }
00115 
00116     convert();
00117     QDomDocument outdoc = m_document.saveXML();
00118     // add paper info, we always need custom for svg (Rob)
00119     QDomElement paper = outdoc.createElement( "PAPER" );
00120     outdoc.documentElement().appendChild( paper );
00121     paper.setAttribute( "format", PG_CUSTOM );
00122     paper.setAttribute( "width", m_document.width() );
00123     paper.setAttribute( "height", m_document.height() );
00124 
00125     // store document content
00126     out = m_chain->storageFile( "maindoc.xml", KoStore::Write );
00127     if( out )
00128     {
00129         QCString content = outdoc.toCString();
00130         kdDebug() << " content :" << content << endl;
00131         out->writeBlock( content , content.length() );
00132     }
00133     m_zip->close();
00134     delete m_zip;
00135 
00136     kdDebug() << "######################## OoDrawImport::convert done ####################" << endl;
00137 
00138     return KoFilter::OK;
00139 }
00140 
00141 // Very related to OoWriterImport::createDocumentInfo
00142 void OoDrawImport::createDocumentInfo( QDomDocument &docinfo )
00143 {
00144     docinfo = KoDocument::createDomDocument( "document-info" /*DTD name*/, "document-info" /*tag name*/, "1.1" );
00145 
00146     OoUtils::createDocumentInfo(m_meta, docinfo);
00147     //kdDebug(30518) << " meta-info :" << m_meta.toCString() << endl;
00148 }
00149 
00150 
00151 // Very related to OoWriterImport::openFile()
00152 KoFilter::ConversionStatus OoDrawImport::openFile()
00153 {
00154     KoFilter::ConversionStatus status = loadAndParse( "content.xml", m_content );
00155     if ( status != KoFilter::OK )
00156     {
00157         kdError(30518) << "Content.xml could not be parsed correctly! Aborting!" << endl;
00158         return status;
00159     }
00160 
00161     // We do not stop if the following calls fail.
00162     QDomDocument styles;
00163     loadAndParse( "styles.xml", styles );
00164     loadAndParse( "meta.xml", m_meta );
00165     loadAndParse( "settings.xml", m_settings );
00166 
00167     emit sigProgress( 10 );
00168     createStyleMap( styles );
00169 
00170     return KoFilter::OK;
00171 }
00172 
00173 void OoDrawImport::convert()
00174 {
00175     m_document.saveAsPath( false );
00176 
00177     QDomElement content = m_content.documentElement();
00178 
00179     // content.xml contains some automatic-styles that we need to store
00180     QDomNode automaticStyles = KoDom::namedItemNS( content, ooNS::office, "automatic-styles" );
00181     if( !automaticStyles.isNull() )
00182         insertStyles( automaticStyles.toElement() );
00183 
00184     QDomNode body = KoDom::namedItemNS( content, ooNS::office, "body" );
00185     if( body.isNull() )
00186         return;
00187 
00188     // we take the settings of the first slide for the whole document.
00189     QDomElement drawPage = KoDom::namedItemNS( body, ooNS::draw, "page" );
00190     if( drawPage.isNull() ) // no pages? give up.
00191         return;
00192 
00193     QDomElement *master = m_styles[drawPage.attributeNS( ooNS::draw, "master-page-name", QString::null )];
00194     QDomElement *style = m_styles[master->attributeNS( ooNS::style, "page-master-name", QString::null )];
00195     QDomElement properties = KoDom::namedItemNS( *style, ooNS::style, "properties" ).toElement();
00196 
00197     if( properties.isNull() )
00198     {
00199         m_document.setWidth( 550.0 );
00200         m_document.setHeight( 841.0 );
00201     }
00202     else
00203     {
00204         m_document.setWidth( KoUnit::parseValue(properties.attributeNS( ooNS::fo, "page-width", QString::null ) ) );
00205         m_document.setHeight( KoUnit::parseValue(properties.attributeNS( ooNS::fo, "page-height", QString::null ) ) );
00206     }
00207 
00208     // parse all pages
00209     for( QDomNode drawPage = body.firstChild(); !drawPage.isNull(); drawPage = drawPage.nextSibling() )
00210     {
00211         QDomElement dp = drawPage.toElement();
00212         m_styleStack.clear(); // remove all styles
00213         fillStyleStack( dp );
00214         //m_styleStack.setPageMark();
00215 
00216         // set the pagetitle
00217         //QDomElement titleElement = doc.createElement( "Title" );
00218         //titleElement.setAttribute( "title", dp.attributeNS( "name" ) );
00219         //pageTitleElement.appendChild( titleElement );
00220 
00221     parseGroup( 0L, dp );
00222     }
00223 }
00224 
00225 
00226 KoFilter::ConversionStatus OoDrawImport::loadAndParse(const QString& filename, QDomDocument& doc)
00227 {
00228      return OoUtils::loadAndParse( filename, doc, m_zip);
00229 }
00230 
00231 void
00232 OoDrawImport::parseGroup( VGroup *parent, const QDomElement& parentobject )
00233 {
00234     // parse all objects
00235     for( QDomNode object = parentobject.firstChild(); !object.isNull(); object = object.nextSibling() )
00236     {
00237         QDomElement o = object.toElement();
00238         if( o.namespaceURI() != ooNS::draw ) continue;
00239         QString name = o.localName();
00240         QString drawID = o.attributeNS( ooNS::draw, "id", QString::null );
00241         VObject *obj = 0L;
00242 
00243         if( name == "g" ) // polyline
00244         {
00245             storeObjectStyles( o );
00246             VGroup *group = new VGroup( parent );
00247             appendPen( *group );
00248             appendBrush( *group );
00249             obj = group;
00250             parseGroup( group, o );
00251         }
00252         else if( name == "rect" ) // rectangle
00253         {
00254             storeObjectStyles( o );
00255             double x = KoUnit::parseValue( o.attributeNS( ooNS::svg, "x", QString::null ) );
00256             double y = ymirror( KoUnit::parseValue( o.attributeNS( ooNS::svg, "y", QString::null ) ) );
00257             double w = KoUnit::parseValue( o.attributeNS( ooNS::svg, "width", QString::null ) );
00258             double h = KoUnit::parseValue( o.attributeNS( ooNS::svg, "height", QString::null ) );
00259             int corner = static_cast<int>( KoUnit::parseValue( o.attributeNS( ooNS::draw, "corner-radius", QString::null ) ) );
00260             VRectangle *rect = new VRectangle( parent, KoPoint( x, y ), w, h, corner );
00261             appendPen( *rect );
00262             appendBrush( *rect );
00263             obj = rect;
00264         }
00265         else if( name == "circle" || name == "ellipse" )
00266         {
00267             storeObjectStyles( o );
00268             double w = KoUnit::parseValue( o.attributeNS( ooNS::svg, "width", QString::null ) );
00269             double h = KoUnit::parseValue( o.attributeNS( ooNS::svg, "height", QString::null ) );
00270             double x = KoUnit::parseValue( o.attributeNS( ooNS::svg, "x", QString::null ) );
00271             double y = ymirror( KoUnit::parseValue( o.attributeNS( ooNS::svg, "y", QString::null ) ) ) - h;
00272             double start = o.attributeNS( ooNS::draw, "start-angle", QString::null ).toDouble();
00273             double end = o.attributeNS( ooNS::draw, "end-angle", QString::null ).toDouble();
00274             QString kind = o.attributeNS( ooNS::draw, "kind", QString::null );
00275             VEllipse::VEllipseType type = VEllipse::full;
00276             if( !kind.isEmpty() )
00277             {
00278                 if( kind == "section" )
00279                     type = VEllipse::cut;
00280                 else if( kind == "cut" )
00281                     type = VEllipse::section;
00282                 else if( kind == "arc" )
00283                     type = VEllipse::arc;
00284             }
00285             VEllipse *ellipse = new VEllipse( parent, KoPoint( x, y ), w, h, type, start, end );
00286             appendPen( *ellipse );
00287             // arc has no brush
00288             if( kind != "arc" )
00289                 appendBrush( *ellipse );
00290             obj = ellipse;
00291         }
00292         else if( name == "line" ) // line
00293         {
00294             storeObjectStyles( o );
00295             VPath *line = new VPath( parent );
00296             double x1 = KoUnit::parseValue( o.attributeNS( ooNS::svg, "x1", QString::null ) );
00297             double y1 = ymirror( KoUnit::parseValue( o.attributeNS( ooNS::svg, "y1", QString::null ) ) );
00298             double x2 = KoUnit::parseValue( o.attributeNS( ooNS::svg, "x2", QString::null ) );
00299             double y2 = ymirror( KoUnit::parseValue( o.attributeNS( ooNS::svg, "y2", QString::null ) ) );
00300             line->moveTo( KoPoint( x1, y1 ) );
00301             line->lineTo( KoPoint( x2, y2 ) );
00302             appendPen( *line );
00303             appendBrush( *line );
00304             obj = line;
00305         }
00306         else if( name == "polyline" ) // polyline
00307         {
00308             storeObjectStyles( o );
00309             VPath *polyline = new VPath( parent );
00310             appendPoints( *polyline, o);
00311             appendPen( *polyline );
00312             appendBrush( *polyline );
00313             obj = polyline;
00314         }
00315         else if( name == "polygon" ) // polygon
00316         {
00317             storeObjectStyles( o );
00318             //VPolygon *polygon = new VPolygon( parent );
00319             //polygon->load( o );
00320             VPath *polygon = new VPath( parent );
00321             appendPoints( *polygon, o );
00322             appendPen( *polygon );
00323             appendBrush( *polygon );
00324             obj = polygon;
00325         }
00326         else if( name == "path" ) // path
00327         {
00328             storeObjectStyles( o );
00329             VPath *path = new VPath( parent );
00330             path->loadSvgPath( o.attributeNS( ooNS::svg, "d", QString::null ) );
00331             KoRect rect = parseViewBox( o );
00332             double x = KoUnit::parseValue( o.attributeNS( ooNS::svg, "x", QString::null ) );
00333             double y = ymirror( KoUnit::parseValue( o.attributeNS( ooNS::svg, "y", QString::null ) ) );
00334             double w = KoUnit::parseValue( o.attributeNS( ooNS::svg, "width", QString::null ) );
00335             double h = KoUnit::parseValue( o.attributeNS( ooNS::svg, "height", QString::null ) );
00336             QWMatrix mat;
00337             mat.translate( x, y );
00338             mat.scale( w / rect.width(), -h / rect.height() );
00339             path->transform( mat );
00340             appendPen( *path );
00341             appendBrush( *path );
00342             obj = path;
00343         }
00344 /*else if( name == "draw:image" ) // image
00345 {
00346 storeObjectStyles( o );
00347 e = doc.createElement( "OBJECT" );
00348 e.setAttribute( "type", 0 );
00349 appendImage( doc, e, pictureElement, o );
00350 }*/
00351         else
00352         {
00353             kdDebug() << "Unsupported object '" << name << "'" << endl;
00354             continue;
00355         }
00356         if( parent && obj )
00357             parent->append( obj );
00358         else if( obj )
00359             m_document.append( obj );
00360     }
00361 }
00362 
00363 void
00364 OoDrawImport::appendPen( VObject &obj )
00365 {
00366     if( m_styleStack.hasAttributeNS( ooNS::draw, "stroke" ) )
00367     {
00368         VStroke stroke;
00369 
00370         if( m_styleStack.attributeNS( ooNS::draw, "stroke" ) == "none" )
00371             stroke.setType( VStroke::none );
00372         else if( m_styleStack.attributeNS( ooNS::draw, "stroke" ) == "solid" )
00373             stroke.setType( VStroke::solid );
00374         else if( m_styleStack.attributeNS( ooNS::draw, "stroke" ) == "dash" )
00375         {
00376             QValueList<float> dashes;
00377             stroke.setType( VStroke::solid );
00378             QString style = m_styleStack.attributeNS( ooNS::draw, "stroke-dash" );
00379             if( style == "Ultrafine Dashed" ||
00380                 style == "Fine Dashed (var)" || style == "Dashed (var)" )
00381                 stroke.dashPattern().setArray( dashes << 2 << 2 );
00382             else if( style == "Fine Dashed" )
00383                 stroke.dashPattern().setArray( dashes << 10 << 10 );
00384             else if( style == "Fine Dotted" || style == "Ultrafine Dotted (var)" ||
00385                 style == "Line with Fine Dots" )
00386                 stroke.dashPattern().setArray( dashes << 2 << 10 );
00387             else if( style == "3 Dashes 3 Dots (var)" || style == "Ultrafine 2 Dots 3 Dashes" )
00388                 stroke.dashPattern().setArray( dashes << 3 << 3 );
00389             else if( style == "2 Dots 1 Dash" )
00390                 stroke.dashPattern().setArray( dashes << 2 << 1 );
00391         }
00392         if( m_styleStack.hasAttributeNS( ooNS::svg, "stroke-width" ) )
00393         {
00394             double lwidth = KoUnit::parseValue( m_styleStack.attributeNS( ooNS::svg, "stroke-width" ) );
00395             if( lwidth == 0 )
00396                 lwidth = 1.0;
00397             stroke.setLineWidth( lwidth );
00398         }
00399         if( m_styleStack.hasAttributeNS( ooNS::svg, "stroke-color" ) )
00400         {
00401             VColor c;
00402             parseColor( c, m_styleStack.attributeNS( ooNS::svg, "stroke-color" ) );
00403             stroke.setColor( c );
00404         }
00405 
00406         obj.setStroke( stroke );
00407     }
00408 }
00409 
00410 void
00411 OoDrawImport::appendBrush( VObject &obj )
00412 {
00413     if( m_styleStack.hasAttributeNS( ooNS::draw, "fill" ) )
00414     {
00415         const QString fill = m_styleStack.attributeNS( ooNS::draw, "fill" );
00416         VFill f;
00417 
00418         if( fill == "solid" )
00419         {
00420             f.setType( VFill::solid );
00421             if( m_styleStack.hasAttributeNS( ooNS::draw, "fill-color" ) )
00422             {
00423                 VColor c;
00424                 parseColor( c, m_styleStack.attributeNS( ooNS::draw, "fill-color" ) );
00425                 f.setColor( c );
00426             }
00427         }
00428         else if( fill == "gradient" )
00429         {
00430             VGradient gradient;
00431             gradient.clearStops();
00432             gradient.setRepeatMethod( VGradient::none );
00433             QString style = m_styleStack.attributeNS( ooNS::draw, "fill-gradient-name" );
00434 
00435             QDomElement* draw = m_draws[style];
00436             if( draw )
00437             {
00438                 double border = 0.0;
00439                 if( draw->hasAttributeNS( ooNS::draw, "border" ) )
00440                     border += draw->attributeNS( ooNS::draw, "border", QString::null ).remove( '%' ).toDouble() / 100.0;
00441                 VColor c;
00442                 parseColor( c, draw->attributeNS( ooNS::draw, "start-color", QString::null ) );
00443                 gradient.addStop( c, border, 0.5 );
00444                 parseColor( c, draw->attributeNS( ooNS::draw, "end-color", QString::null ) );
00445                 gradient.addStop( c, 1.0, 0.5 );
00446 
00447                 QString type = draw->attributeNS( ooNS::draw, "style", QString::null );
00448                 if( type == "linear" || type == "axial" )
00449                 {
00450                     gradient.setType( VGradient::linear );
00451                     int angle = draw->attributeNS( ooNS::draw, "angle", QString::null ).toInt() / 10;
00452 
00453                     // make sure the angle is between 0 and 359
00454                     angle = abs( angle );
00455                     angle -= ( (int) ( angle / 360 ) ) * 360;
00456 
00457                     // What we are trying to do here is to find out if the given
00458                     // angle belongs to a horizontal, vertical or diagonal gradient.
00459                     int lower, upper, nearAngle = 0;
00460                     for ( lower = 0, upper = 45; upper < 360; lower += 45, upper += 45 )
00461                     {
00462                         if( upper >= angle )
00463                         {
00464                             int distanceToUpper = abs( angle - upper );
00465                             int distanceToLower = abs( angle - lower );
00466                             nearAngle = distanceToUpper > distanceToLower ? lower : upper;
00467                             break;
00468                         }
00469                     }
00470                     KoRect rect = obj.boundingBox();
00471                     KoPoint origin, vector;
00472                     // nearAngle should now be one of: 0, 45, 90, 135, 180...
00473                     kdDebug() << "nearAngle: " << nearAngle << endl;
00474                     if( nearAngle == 0 || nearAngle == 180 )
00475                     {
00476                         origin.setX( rect.x() + rect.width() );
00477                         origin.setY( rect.y() + rect.height());
00478                         vector.setX( rect.x() + rect.width() );
00479                         vector.setY( rect.y() );
00480                     }
00481                     else if( nearAngle == 90 || nearAngle == 270 )
00482                     {
00483                         origin.setX( rect.x() );
00484                         origin.setY( rect.y() + rect.height() );
00485                         vector.setX( rect.x() + rect.width() );
00486                         vector.setY( rect.y() + rect.height() );
00487                     }
00488                     else if( nearAngle == 45 || nearAngle == 225 )
00489                     {
00490                         origin.setX( rect.x() );
00491                         origin.setY( rect.y() );
00492                         vector.setX( rect.x() + rect.width() );
00493                         vector.setY( rect.y() + rect.height() );
00494                     }
00495                     else if( nearAngle == 135 || nearAngle == 315 )
00496                     {
00497                         origin.setX( rect.x() + rect.width() );
00498                         origin.setY( rect.y() + rect.height() );
00499                         vector.setX( rect.x() );
00500                         vector.setY( rect.y() );
00501                     }
00502 
00503                     gradient.setOrigin( origin );
00504                     gradient.setVector( vector );
00505                 }
00506                 else if( type == "radial" || type == "ellipsoid" )
00507                 {
00508                     gradient.setType( VGradient::radial );
00509 //else if( type == "square" || type == "rectangular" )
00510 //gradient.setAttribute( "type", 6 ); // rectangle
00511 //else if( type == "axial" )
00512 //gradient.setAttribute( "type", 7 ); // pipecross
00513 
00514                     // Hard to map between x- and y-center settings of oodraw
00515                     // and (un-)balanced settings of kpresenter. Let's try it.
00516                     double x, y;
00517                     if( draw->hasAttributeNS( ooNS::draw, "cx" ) )
00518                         x = draw->attributeNS( ooNS::draw, "cx", QString::null ).remove( '%' ).toDouble() / 100.0;
00519                     else
00520                         x = 0.5;
00521 
00522                     if( draw->hasAttributeNS( ooNS::draw, "cy" ) )
00523                         y = draw->attributeNS( ooNS::draw, "cy", QString::null ).remove( '%' ).toDouble() / 100.0;
00524                     else
00525                         y = 0.5;
00526 
00527                     KoRect rect = obj.boundingBox();
00528                     gradient.setOrigin( KoPoint( rect.x() + x * rect.width(),
00529                                                  rect.y() + y * rect.height() ) );
00530                     gradient.setFocalPoint( KoPoint( rect.x() + x * rect.width(),
00531                                                      rect.y() + y * rect.height() ) );
00532                     gradient.setVector( KoPoint( rect.x() + rect.width(),
00533                                                  rect.y() + y * rect.height() ) );
00534                 }
00535                 f.gradient() = gradient;
00536                 f.setType( VFill::grad );
00537             }
00538         }
00539         obj.setFill( f );
00540     }
00541 /*else if( fill == "hatch" )
00542 {
00543 QDomElement brush = doc.createElement( "BRUSH" );
00544 QString style = m_styleStack.attributeNS( "fill-hatch-name" );
00545 if( style == "Black 0 Degrees" )
00546 brush.setAttribute( "style", 9 );
00547 else if( style == "Black 90 Degrees" )
00548 brush.setAttribute( "style", 10 );
00549 else if( style == "Red Crossed 0 Degrees" || style == "Blue Crossed 0 Degrees" )
00550 brush.setAttribute( "style", 11 );
00551 else if( style == "Black 45 Degrees" || style == "Black 45 Degrees Wide" )
00552 brush.setAttribute( "style", 12 );
00553 else if( style == "Black -45 Degrees" )
00554 brush.setAttribute( "style", 13 );
00555 else if( style == "Red Crossed 45 Degrees" || style == "Blue Crossed 45 Degrees" )
00556 brush.setAttribute( "style", 14 );
00557 
00558 QDomElement* draw = m_draws[style];
00559 if( draw && draw->hasAttributeNS( "color" ) )
00560 brush.setAttribute( "color", draw->attributeNS( "color" ) );
00561 e.appendChild( brush );
00562 }*/
00563 }
00564 
00565 void
00566 OoDrawImport::createStyleMap( QDomDocument &docstyles )
00567 {
00568     QDomElement styles = docstyles.documentElement();
00569     if( styles.isNull() )
00570         return;
00571 
00572     QDomNode fixedStyles = KoDom::namedItemNS( styles, ooNS::office, "styles" );
00573     if( !fixedStyles.isNull() )
00574     {
00575         insertDraws( fixedStyles.toElement() );
00576         insertStyles( fixedStyles.toElement() );
00577     }
00578     QDomNode automaticStyles = KoDom::namedItemNS( styles, ooNS::office, "automatic-styles" );
00579     if( !automaticStyles.isNull() )
00580         insertStyles( automaticStyles.toElement() );
00581 
00582     QDomNode masterStyles = KoDom::namedItemNS( styles, ooNS::office, "master-styles" );
00583     if( !masterStyles.isNull() )
00584         insertStyles( masterStyles.toElement() );
00585 }
00586 
00587 void
00588 OoDrawImport::insertDraws( const QDomElement& styles )
00589 {
00590     for( QDomNode n = styles.firstChild(); !n.isNull(); n = n.nextSibling() )
00591     {
00592         QDomElement e = n.toElement();
00593 
00594         if( !e.hasAttributeNS( ooNS::draw, "name" ) )
00595             continue;
00596 
00597         QString name = e.attributeNS( ooNS::draw, "name", QString::null );
00598         m_draws.insert( name, new QDomElement( e ) );
00599     }
00600 }
00601 
00602 
00603 void
00604 OoDrawImport::insertStyles( const QDomElement& styles )
00605 {
00606     for ( QDomNode n = styles.firstChild(); !n.isNull(); n = n.nextSibling() )
00607     {
00608         QDomElement e = n.toElement();
00609 
00610         if( !e.hasAttributeNS( ooNS::style, "name" ) )
00611             continue;
00612 
00613         QString name = e.attributeNS( ooNS::style, "name", QString::null );
00614         m_styles.insert( name, new QDomElement( e ) );
00615         //kdDebug() << "Style: '" << name << "' loaded " << endl;
00616     }
00617 }
00618 
00619 void
00620 OoDrawImport::fillStyleStack( const QDomElement& object )
00621 {
00622     // find all styles associated with an object and push them on the stack
00623     if( object.hasAttributeNS( ooNS::presentation, "style-name" ) )
00624         addStyles( m_styles[object.attributeNS( ooNS::presentation, "style-name", QString::null )] );
00625 
00626     if( object.hasAttributeNS( ooNS::draw, "style-name" ) )
00627         addStyles( m_styles[object.attributeNS( ooNS::draw, "style-name", QString::null )] );
00628 
00629     if( object.hasAttributeNS( ooNS::draw, "text-style-name" ) )
00630         addStyles( m_styles[object.attributeNS( ooNS::draw, "text-style-name", QString::null )] );
00631 
00632     if( object.hasAttributeNS( ooNS::text, "style-name" ) )
00633         addStyles( m_styles[object.attributeNS( ooNS::text, "style-name", QString::null )] );
00634 }
00635 
00636 void
00637 OoDrawImport::addStyles( const QDomElement* style )
00638 {
00639     // this function is necessary as parent styles can have parents themself
00640     if( style->hasAttributeNS( ooNS::style, "parent-style-name" ) )
00641         addStyles( m_styles[style->attributeNS( ooNS::style, "parent-style-name", QString::null )] );
00642 
00643     m_styleStack.push( *style );
00644 }
00645 
00646 void
00647 OoDrawImport::storeObjectStyles( const QDomElement& object )
00648 {
00649     //m_styleStack.clearPageMark(); // remove styles of previous object
00650     fillStyleStack( object );
00651     //m_styleStack.setObjectMark();
00652 }
00653 
00654 KoRect
00655 OoDrawImport::parseViewBox( const QDomElement& object )
00656 {
00657     KoRect rect;
00658     if( !object.attributeNS( ooNS::svg, "viewBox", QString::null ).isEmpty() )
00659     {
00660         // allow for viewbox def with ',' or whitespace
00661         QString viewbox( object.attributeNS( ooNS::svg, "viewBox", QString::null ) );
00662         QStringList points = QStringList::split( ' ', viewbox.replace( ',', ' ').simplifyWhiteSpace() );
00663 
00664         rect.setX( points[0].toFloat() );
00665         rect.setY( points[1].toFloat() );
00666         rect.setWidth( points[2].toFloat() );
00667         rect.setHeight( points[3].toFloat() );
00668     }
00669     return rect;
00670 }
00671 
00672 void
00673 OoDrawImport::appendPoints(VPath &path, const QDomElement& object)
00674 {
00675     double x = KoUnit::parseValue( object.attributeNS( ooNS::svg, "x", QString::null ) );
00676     double y = KoUnit::parseValue( object.attributeNS( ooNS::svg, "y", QString::null ) );
00677     double w = KoUnit::parseValue( object.attributeNS( ooNS::svg, "width", QString::null ) );
00678     double h = KoUnit::parseValue( object.attributeNS( ooNS::svg, "height", QString::null ) );
00679 
00680     KoRect rect = parseViewBox( object );
00681     rect.setX( rect.x() + x );
00682     rect.setY( rect.y() + y );
00683 
00684     QStringList ptList = QStringList::split( ' ', object.attributeNS( ooNS::draw, "points", QString::null ) );
00685 
00686     QString pt_x, pt_y;
00687     double tmp_x, tmp_y;
00688     KoPoint point;
00689     bool bFirst = true;
00690     for( QStringList::Iterator it = ptList.begin(); it != ptList.end(); ++it )
00691     {
00692         tmp_x = rect.x() + ( (*it).section( ',', 0, 0 ).toInt() * w ) / rect.width();
00693         tmp_y = rect.y() + ( (*it).section( ',', 1, 1 ).toInt() * h ) / rect.height();
00694 
00695         point.setX( tmp_x );
00696         point.setY( ymirror( tmp_y ) );
00697         if( bFirst )
00698         {
00699             path.moveTo( point );
00700             bFirst = false;
00701         }
00702         else
00703             path.lineTo( point );
00704     }
00705 }
00706 
00707 void
00708 OoDrawImport::parseColor( VColor &color, const QString &s )
00709 {
00710     if( s.startsWith( "rgb(" ) )
00711     {
00712         QString parse = s.stripWhiteSpace();
00713         QStringList colors = QStringList::split( ',', parse );
00714         QString r = colors[0].right( ( colors[0].length() - 4 ) );
00715         QString g = colors[1];
00716         QString b = colors[2].left( ( colors[2].length() - 1 ) );
00717 
00718         if( r.contains( "%" ) )
00719         {
00720             r = r.left( r.length() - 1 );
00721             r = QString::number( int( ( double( 255 * r.toDouble() ) / 100.0 ) ) );
00722         }
00723 
00724         if( g.contains( "%" ) )
00725         {
00726             g = g.left( g.length() - 1 );
00727             g = QString::number( int( ( double( 255 * g.toDouble() ) / 100.0 ) ) );
00728         }
00729 
00730         if( b.contains( "%" ) )
00731         {
00732             b = b.left( b.length() - 1 );
00733             b = QString::number( int( ( double( 255 * b.toDouble() ) / 100.0 ) ) );
00734         }
00735 
00736         QColor c( r.toInt(), g.toInt(), b.toInt() );
00737         color.set( c.red() / 255.0, c.green() / 255.0, c.blue() / 255.0 );
00738     }
00739     else
00740     {
00741         QString rgbColor = s.stripWhiteSpace();
00742         QColor c;
00743         if( rgbColor.startsWith( "#" ) )
00744             c.setNamedColor( rgbColor );
00745         //else
00746         //  c = parseColor( rgbColor );
00747         color.set( c.red() / 255.0, c.green() / 255.0, c.blue() / 255.0 );
00748     }
00749 }
00750 
00751 double
00752 OoDrawImport::ymirror( double y )
00753 {
00754     return m_document.height() - y;
00755 }
00756 
00757 #include "oodrawimport.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys