diff options
author | Armin Le Grand <alg@apache.org> | 2011-12-19 15:41:21 +0000 |
---|---|---|
committer | Armin Le Grand <alg@apache.org> | 2011-12-19 15:41:21 +0000 |
commit | e2e16715893229b5d0ad2da6c8e84464e0c43a2e (patch) | |
tree | 79d1c632784b3de16fc82c1dfc27c1796a9ef451 | |
parent | ea4f454ed956e08be47783b3bddd7789f905e350 (diff) |
Svg: Reintegrated Svg replacement from /branches/alg/svgreplavement to trunk, first version of Svg stable and done
228 files changed, 20325 insertions, 2744 deletions
diff --git a/Module_ooo.mk b/Module_ooo.mk index 2913794a827f..da1306da015f 100644 --- a/Module_ooo.mk +++ b/Module_ooo.mk @@ -30,7 +30,8 @@ $(eval $(call gb_Module_Module,ooo)) $(eval $(call gb_Module_add_moduledirs,ooo,\ comphelper \ drawinglayer \ - editeng \ + svgio \ + editeng \ framework \ padmin \ sfx2 \ diff --git a/Repository.mk b/Repository.mk index 656d457d0dc7..e3971a050424 100755 --- a/Repository.mk +++ b/Repository.mk @@ -52,6 +52,7 @@ $(eval $(call gb_Helper_register_libraries,OOOLIBS, \ cui \ desktop_detector \ drawinglayer \ + svgio \ editeng \ fwe \ fwi \ diff --git a/basegfx/inc/basegfx/color/bcolor.hxx b/basegfx/inc/basegfx/color/bcolor.hxx index 76596bdb4d5f..724fe057afab 100644 --- a/basegfx/inc/basegfx/color/bcolor.hxx +++ b/basegfx/inc/basegfx/color/bcolor.hxx @@ -151,9 +151,9 @@ namespace basegfx // luminance double luminance() const { - const double fRedWeight(77.0 / 256.0); - const double fGreenWeight(151.0 / 256.0); - const double fBlueWeight(28.0 / 256.0); + const double fRedWeight(77.0 / 256.0); // 0.30 + const double fGreenWeight(151.0 / 256.0); // 0.59 + const double fBlueWeight(28.0 / 256.0); // 0.11 return (mfX * fRedWeight + mfY * fGreenWeight + mfZ * fBlueWeight); } diff --git a/basegfx/inc/basegfx/color/bcolormodifier.hxx b/basegfx/inc/basegfx/color/bcolormodifier.hxx index 55ed936985e2..afdc38c8b9a7 100644 --- a/basegfx/inc/basegfx/color/bcolormodifier.hxx +++ b/basegfx/inc/basegfx/color/bcolormodifier.hxx @@ -35,10 +35,12 @@ namespace basegfx */ enum BColorModifyMode { - BCOLORMODIFYMODE_REPLACE, // replace all color with local color - BCOLORMODIFYMODE_INTERPOLATE, // interpolate color between given and local with local value - BCOLORMODIFYMODE_GRAY, // convert color to gray - BCOLORMODIFYMODE_BLACKANDWHITE // convert color to B&W, local value is treshhold + BCOLORMODIFYMODE_REPLACE, // replace all color with local color + BCOLORMODIFYMODE_INTERPOLATE, // interpolate color between given and local with local value + BCOLORMODIFYMODE_GRAY, // convert color to gray + BCOLORMODIFYMODE_BLACKANDWHITE, // convert color to B&W, local value is treshhold + BCOLORMODIFYMODE_INVERT, // invert color + BCOLORMODIFYMODE_LUMINANCE_TO_ALPHA // convert color to alpha value (used for Svg Mask) }; /** Class to hold a color, value and mode for a color modification. Color modification is diff --git a/basegfx/inc/basegfx/matrix/b2dhommatrixtools.hxx b/basegfx/inc/basegfx/matrix/b2dhommatrixtools.hxx index 51b955eb2dfe..267cf570b7ce 100644 --- a/basegfx/inc/basegfx/matrix/b2dhommatrixtools.hxx +++ b/basegfx/inc/basegfx/matrix/b2dhommatrixtools.hxx @@ -149,7 +149,7 @@ namespace basegfx double mfShearX; public: - B2DHomMatrixBufferedDecompose(const B2DHomMatrix& rB2DHomMatrix) + B2DHomMatrixBufferedDecompose(const B2DHomMatrix& rB2DHomMatrix = B2DHomMatrix()) : maScale(), maTranslate(), mfRotate(0.0), @@ -201,7 +201,7 @@ namespace basegfx } public: - B2DHomMatrixBufferedOnDemandDecompose(const B2DHomMatrix& rB2DHomMatrix) + B2DHomMatrixBufferedOnDemandDecompose(const B2DHomMatrix& rB2DHomMatrix = B2DHomMatrix()) : maB2DHomMatrix(rB2DHomMatrix), maScale(), maTranslate(), diff --git a/basegfx/inc/basegfx/polygon/b2dpolygon.hxx b/basegfx/inc/basegfx/polygon/b2dpolygon.hxx index 12b8b8d34ee6..fd988a382f86 100644 --- a/basegfx/inc/basegfx/polygon/b2dpolygon.hxx +++ b/basegfx/inc/basegfx/polygon/b2dpolygon.hxx @@ -263,6 +263,10 @@ namespace basegfx B2DPoint* begin(); B2DPoint* end(); }; + + // typedef for a vector of B2DPolygons + typedef ::std::vector< B2DPolygon > B2DPolygonVector; + } // end of namespace basegfx ////////////////////////////////////////////////////////////////////////////// diff --git a/basegfx/inc/basegfx/polygon/b2dpolypolygon.hxx b/basegfx/inc/basegfx/polygon/b2dpolypolygon.hxx index 75d2685593c9..68b7a5090ead 100644 --- a/basegfx/inc/basegfx/polygon/b2dpolypolygon.hxx +++ b/basegfx/inc/basegfx/polygon/b2dpolypolygon.hxx @@ -128,6 +128,10 @@ namespace basegfx B2DPolygon* begin(); B2DPolygon* end(); }; + + // typedef for a vector of B2DPolyPolygons + typedef ::std::vector< B2DPolyPolygon > B2DPolyPolygonVector; + } // end of namespace basegfx #endif /* _BGFX_POLYGON_B2DPOLYPOLYGON_HXX */ diff --git a/basegfx/inc/basegfx/polygon/b2dpolypolygoncutter.hxx b/basegfx/inc/basegfx/polygon/b2dpolypolygoncutter.hxx index 1be6c1950af9..d43af8c53e7a 100644 --- a/basegfx/inc/basegfx/polygon/b2dpolypolygoncutter.hxx +++ b/basegfx/inc/basegfx/polygon/b2dpolypolygoncutter.hxx @@ -65,6 +65,13 @@ namespace basegfx // can be combined for logical polygon operations or polygon clipping. B2DPolyPolygon stripDispensablePolygons(const B2DPolyPolygon& rCandidate, bool bKeepAboveZero = false); + // geometrically convert PolyPolygons which are proposed to use nonzero fill rule + // to a representation where evenodd paint will give the same result. To do this + // all intersections and self-intersections get solved (the polygons will be rearranged + // if needed). Then all polygons which are inside another one with the same orientation + // get deleted + B2DPolyPolygon createNonzeroConform(const B2DPolyPolygon& rCandidate); + // For convenience: The four basic operations OR, XOR, AND and DIFF for // two PolyPolygons. These are combinations of the above methods. To not be forced // to do evtl. already done preparations twice, You have to do the operations Yourself. @@ -104,7 +111,7 @@ namespace basegfx @return A single PolyPolygon containing the Or-merged result */ - B2DPolyPolygon mergeToSinglePolyPolygon(const std::vector< basegfx::B2DPolyPolygon >& rInput); + B2DPolyPolygon mergeToSinglePolyPolygon(const B2DPolyPolygonVector& rInput); } // end of namespace tools } // end of namespace basegfx diff --git a/basegfx/source/color/bcolormodifier.cxx b/basegfx/source/color/bcolormodifier.cxx index 50215f3f71a2..517fe417cae6 100644 --- a/basegfx/source/color/bcolormodifier.cxx +++ b/basegfx/source/color/bcolormodifier.cxx @@ -56,6 +56,15 @@ namespace basegfx return ::basegfx::BColor(1.0, 1.0, 1.0); } } + case BCOLORMODIFYMODE_INVERT : + { + return ::basegfx::BColor(1.0 - aSourceColor.getRed(), 1.0 - aSourceColor.getGreen(), 1.0 - aSourceColor.getBlue()); + } + case BCOLORMODIFYMODE_LUMINANCE_TO_ALPHA: + { + const double fAlpha(1.0 - ((aSourceColor.getRed() * 0.2125) + (aSourceColor.getGreen() * 0.7154) + (aSourceColor.getBlue() * 0.0721))); + return ::basegfx::BColor(fAlpha, fAlpha, fAlpha); + } default : // BCOLORMODIFYMODE_REPLACE { return maBColor; diff --git a/basegfx/source/polygon/b2dpolypolygon.cxx b/basegfx/source/polygon/b2dpolypolygon.cxx index 94b8745871a5..28f8270ece65 100644 --- a/basegfx/source/polygon/b2dpolypolygon.cxx +++ b/basegfx/source/polygon/b2dpolypolygon.cxx @@ -38,9 +38,7 @@ class ImplB2DPolyPolygon { - typedef ::std::vector< basegfx::B2DPolygon > PolygonVector; - - PolygonVector maPolygons; + basegfx::B2DPolygonVector maPolygons; public: ImplB2DPolyPolygon() : maPolygons() @@ -80,7 +78,7 @@ public: if(nCount) { // add nCount copies of rPolygon - PolygonVector::iterator aIndex(maPolygons.begin()); + basegfx::B2DPolygonVector::iterator aIndex(maPolygons.begin()); aIndex += nIndex; maPolygons.insert(aIndex, nCount, rPolygon); } @@ -94,7 +92,7 @@ public: { // add nCount polygons from rPolyPolygon maPolygons.reserve(maPolygons.size() + nCount); - PolygonVector::iterator aIndex(maPolygons.begin()); + basegfx::B2DPolygonVector::iterator aIndex(maPolygons.begin()); aIndex += nIndex; for(sal_uInt32 a(0L); a < nCount; a++) @@ -110,9 +108,9 @@ public: if(nCount) { // remove polygon data - PolygonVector::iterator aStart(maPolygons.begin()); + basegfx::B2DPolygonVector::iterator aStart(maPolygons.begin()); aStart += nIndex; - const PolygonVector::iterator aEnd(aStart + nCount); + const basegfx::B2DPolygonVector::iterator aEnd(aStart + nCount); maPolygons.erase(aStart, aEnd); } diff --git a/basegfx/source/polygon/b2dpolypolygoncutter.cxx b/basegfx/source/polygon/b2dpolypolygoncutter.cxx index 37a81ff334cb..849fc3811f0d 100644 --- a/basegfx/source/polygon/b2dpolypolygoncutter.cxx +++ b/basegfx/source/polygon/b2dpolypolygoncutter.cxx @@ -701,6 +701,94 @@ namespace basegfx ////////////////////////////////////////////////////////////////////////////// + B2DPolyPolygon createNonzeroConform(const B2DPolyPolygon& rCandidate) + { + B2DPolyPolygon aCandidate; + + // remove all self-intersections and intersections + if(rCandidate.count() == 1) + { + aCandidate = basegfx::tools::solveCrossovers(rCandidate.getB2DPolygon(0)); + } + else + { + aCandidate = basegfx::tools::solveCrossovers(rCandidate); + } + + // cleanup evtl. neutral polygons + aCandidate = basegfx::tools::stripNeutralPolygons(aCandidate); + + // remove all polygons which have the same orientation as the polygon they are directly contained in + const sal_uInt32 nCount(aCandidate.count()); + + if(nCount > 1) + { + sal_uInt32 a, b; + ::std::vector< StripHelper > aHelpers; + aHelpers.resize(nCount); + + for(a = 0; a < nCount; a++) + { + const B2DPolygon aCand(aCandidate.getB2DPolygon(a)); + StripHelper* pNewHelper = &(aHelpers[a]); + pNewHelper->maRange = tools::getRange(aCand); + pNewHelper->meOrinetation = tools::getOrientation(aCand); + + // initialize with own orientation + pNewHelper->mnDepth = (ORIENTATION_NEGATIVE == pNewHelper->meOrinetation ? -1 : 1); + } + + for(a = 0; a < nCount - 1; a++) + { + const B2DPolygon aCandA(aCandidate.getB2DPolygon(a)); + StripHelper& rHelperA = aHelpers[a]; + + for(b = a + 1; b < nCount; b++) + { + const B2DPolygon aCandB(aCandidate.getB2DPolygon(b)); + StripHelper& rHelperB = aHelpers[b]; + const bool bAInB(rHelperB.maRange.isInside(rHelperA.maRange) && tools::isInside(aCandB, aCandA, true)); + + if(bAInB) + { + // A is inside B, add orientation of B to A + rHelperA.mnDepth += (ORIENTATION_NEGATIVE == rHelperB.meOrinetation ? -1 : 1); + } + + const bool bBInA(rHelperA.maRange.isInside(rHelperB.maRange) && tools::isInside(aCandA, aCandB, true)); + + if(bBInA) + { + // B is inside A, add orientation of A to B + rHelperB.mnDepth += (ORIENTATION_NEGATIVE == rHelperA.meOrinetation ? -1 : 1); + } + } + } + + const B2DPolyPolygon aSource(aCandidate); + aCandidate.clear(); + + for(a = 0L; a < nCount; a++) + { + const StripHelper& rHelper = aHelpers[a]; + // for contained unequal oriented polygons sum will be 0 + // for contained equal it will be >=2 or <=-2 + // for free polygons (not contained) it will be 1 or -1 + // -> accept all which are >=-1 && <= 1 + bool bAcceptEntry(rHelper.mnDepth >= -1 && rHelper.mnDepth <= 1); + + if(bAcceptEntry) + { + aCandidate.append(aSource.getB2DPolygon(a)); + } + } + } + + return aCandidate; + } + + ////////////////////////////////////////////////////////////////////////////// + B2DPolyPolygon stripDispensablePolygons(const B2DPolyPolygon& rCandidate, bool bKeepAboveZero) { const sal_uInt32 nCount(rCandidate.count()); @@ -922,15 +1010,15 @@ namespace basegfx } } - B2DPolyPolygon mergeToSinglePolyPolygon(const std::vector< basegfx::B2DPolyPolygon >& rInput) + B2DPolyPolygon mergeToSinglePolyPolygon(const B2DPolyPolygonVector& rInput) { - std::vector< basegfx::B2DPolyPolygon > aInput(rInput); + B2DPolyPolygonVector aInput(rInput); // first step: prepareForPolygonOperation and simple merge of non-overlapping // PolyPolygons for speedup; this is possible for the wanted OR-operation if(aInput.size()) { - std::vector< basegfx::B2DPolyPolygon > aResult; + B2DPolyPolygonVector aResult; aResult.reserve(aInput.size()); for(sal_uInt32 a(0); a < aInput.size(); a++) @@ -972,7 +1060,7 @@ namespace basegfx // second step: melt pairwise to a single PolyPolygon while(aInput.size() > 1) { - std::vector< basegfx::B2DPolyPolygon > aResult; + B2DPolyPolygonVector aResult; aResult.reserve((aInput.size() / 2) + 1); for(sal_uInt32 a(0); a < aInput.size(); a += 2) diff --git a/basegfx/source/polygon/b2dsvgpolypolygon.cxx b/basegfx/source/polygon/b2dsvgpolypolygon.cxx index bfac98f3e5f1..1ac1258d7cdd 100644 --- a/basegfx/source/polygon/b2dsvgpolypolygon.cxx +++ b/basegfx/source/polygon/b2dsvgpolypolygon.cxx @@ -782,9 +782,16 @@ namespace basegfx // (since // createPolygonFromEllipseSegment() // normalizes to e.g. cw arc) - const bool bFlipSegment( (bLargeArcFlag!=0) == - (fmod(fTheta2+2*M_PI-fTheta1, - 2*M_PI)<M_PI) ); + + // ALG: In my opinion flipping the segment only + // depends on the sweep flag. At least, this gives + // correct results forthe SVG example (see SVG doc 8.3.8 ff) + // + //const bool bFlipSegment( (bLargeArcFlag!=0) == + // (fmod(fTheta2+2*M_PI-fTheta1, + // 2*M_PI)<M_PI) ); + const bool bFlipSegment(!bSweepFlag); + if( bFlipSegment ) std::swap(fTheta1,fTheta2); diff --git a/cppcanvas/source/mtfrenderer/implrenderer.cxx b/cppcanvas/source/mtfrenderer/implrenderer.cxx index 96ce84546cb2..a395092f1ad3 100644 --- a/cppcanvas/source/mtfrenderer/implrenderer.cxx +++ b/cppcanvas/source/mtfrenderer/implrenderer.cxx @@ -79,7 +79,6 @@ #include <lineaction.hxx> #include <pointaction.hxx> #include <polypolyaction.hxx> -#include <rendergraphicaction.hxx> #include <textaction.hxx> #include <transparencygroupaction.hxx> #include <vector> @@ -2650,32 +2649,6 @@ namespace cppcanvas } break; - case META_RENDERGRAPHIC_ACTION: - { - MetaRenderGraphicAction* pAct = static_cast<MetaRenderGraphicAction*>(pCurrAct); - - ActionSharedPtr pRenderGraphicAction( - internal::RenderGraphicActionFactory::createRenderGraphicAction( - pAct->GetRenderGraphic(), - getState( rStates ).mapModeTransform * - ::vcl::unotools::b2DPointFromPoint( pAct->GetPoint() ), - getState( rStates ).mapModeTransform * - ::vcl::unotools::b2DSizeFromSize( pAct->GetSize() ), - rCanvas, - getState( rStates ) ) ); - - if( pRenderGraphicAction ) - { - maActions.push_back( - MtfAction( - pRenderGraphicAction, - io_rCurrActionIndex ) ); - - io_rCurrActionIndex += pRenderGraphicAction->getActionCount()-1; - } - } - break; - default: OSL_ENSURE( false, "Unknown meta action type encountered" ); diff --git a/cppcanvas/source/mtfrenderer/makefile.mk b/cppcanvas/source/mtfrenderer/makefile.mk index 92ae7e1200bc..d142731f81af 100644 --- a/cppcanvas/source/mtfrenderer/makefile.mk +++ b/cppcanvas/source/mtfrenderer/makefile.mk @@ -48,7 +48,6 @@ SLOFILES = $(SLO)$/cachedprimitivebase.obj \ $(SLO)$/lineaction.obj \ $(SLO)$/pointaction.obj \ $(SLO)$/polypolyaction.obj \ - $(SLO)$/rendergraphicaction.obj \ $(SLO)$/textaction.obj \ $(SLO)$/transparencygroupaction.obj \ $(SLO)$/mtftools.obj diff --git a/cppcanvas/source/mtfrenderer/rendergraphicaction.cxx b/cppcanvas/source/mtfrenderer/rendergraphicaction.cxx deleted file mode 100644 index 764d3eabc6af..000000000000 --- a/cppcanvas/source/mtfrenderer/rendergraphicaction.cxx +++ /dev/null @@ -1,201 +0,0 @@ -/************************************************************************* - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright 2000, 2010 Oracle and/or its affiliates. - * - * OpenOffice.org - a multi-platform office productivity suite - * - * This file is part of OpenOffice.org. - * - * OpenOffice.org is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 3 - * only, as published by the Free Software Foundation. - * - * OpenOffice.org 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 Lesser General Public License version 3 for more details - * (a copy is included in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU Lesser General Public License - * version 3 along with OpenOffice.org. If not, see - * <http://www.openoffice.org/license.html> - * for a copy of the LGPLv3 License. - * - ************************************************************************/ - -// MARKER(update_precomp.py): autogen include statement, do not remove -#include "precompiled_cppcanvas.hxx" - -#include <rtl/logfile.hxx> -#include <com/sun/star/rendering/XBitmap.hpp> -#include <com/sun/star/rendering/RepaintResult.hpp> -#include <com/sun/star/rendering/XCachedPrimitive.hpp> -#include <vcl/rendergraphicrasterizer.hxx> -#include <tools/gen.hxx> -#include <vcl/canvastools.hxx> -#include <canvas/canvastools.hxx> -#include <basegfx/matrix/b2dhommatrix.hxx> -#include <basegfx/vector/b2dsize.hxx> -#include <basegfx/point/b2dpoint.hxx> -#include <basegfx/range/b2drange.hxx> -#include <basegfx/tools/canvastools.hxx> -#include <boost/utility.hpp> -#include "cachedprimitivebase.hxx" -#include "rendergraphicaction.hxx" -#include "outdevstate.hxx" -#include "mtftools.hxx" -#include <basegfx/matrix/b2dhommatrixtools.hxx> - - -using namespace ::com::sun::star; - -namespace cppcanvas -{ - namespace internal - { - namespace - { - - class RenderGraphicAction : public CachedPrimitiveBase - { - public: - RenderGraphicAction( const ::vcl::RenderGraphic& rRenderGraphic, - const ::basegfx::B2DPoint& rDstPoint, - const ::basegfx::B2DVector& rDstSize, - const CanvasSharedPtr&, - const OutDevState& ); - - virtual bool render( const ::basegfx::B2DHomMatrix& rTransformation, - const Subset& rSubset ) const; - - virtual ::basegfx::B2DRange getBounds( const ::basegfx::B2DHomMatrix& rTransformation ) const; - virtual ::basegfx::B2DRange getBounds( const ::basegfx::B2DHomMatrix& rTransformation, - const Subset& rSubset ) const; - - virtual sal_Int32 getActionCount() const; - - private: - using Action::render; - virtual bool render( uno::Reference< rendering::XCachedPrimitive >& rCachedPrimitive, - const ::basegfx::B2DHomMatrix& rTransformation ) const; - - ::vcl::RenderGraphic maRenderGraphic; - uno::Reference< rendering::XBitmap > mxBitmap; - CanvasSharedPtr mpCanvas; - rendering::RenderState maState; - }; - - RenderGraphicAction::RenderGraphicAction( const ::vcl::RenderGraphic& rRenderGraphic, - const ::basegfx::B2DPoint& rDstPoint, - const ::basegfx::B2DVector& rDstSize, - const CanvasSharedPtr& rCanvas, - const OutDevState& rState ) : - CachedPrimitiveBase( rCanvas, true ), - maRenderGraphic( rRenderGraphic ), - mpCanvas( rCanvas ) - { - tools::initRenderState( maState,rState ); - - const ::vcl::RenderGraphicRasterizer aRasterizer( rRenderGraphic ); - const BitmapEx aBmpEx( aRasterizer.Rasterize( ::vcl::unotools::sizeFromB2DSize( rDstSize ) ) ); - const Size aRasteredSizePixel( aBmpEx.GetSizePixel() ); - - if( aRasteredSizePixel.Width() && aRasteredSizePixel.Height() ) - { - const ::basegfx::B2DVector aScale( rDstSize.getX() / aRasteredSizePixel.Width(), - rDstSize.getY() / aRasteredSizePixel.Height() ); - const basegfx::B2DHomMatrix aLocalTransformation( - basegfx::tools::createScaleTranslateB2DHomMatrix( aScale, rDstPoint)) ; - - ::canvas::tools::appendToRenderState( maState, aLocalTransformation ); - - // correct clip (which is relative to original transform) - tools::modifyClip( maState, rState, rCanvas, rDstPoint, &aScale, NULL ); - - mxBitmap = ::vcl::unotools::xBitmapFromBitmapEx( rCanvas->getUNOCanvas()->getDevice(), aBmpEx ); - } - } - - bool RenderGraphicAction::render( uno::Reference< rendering::XCachedPrimitive >& rCachedPrimitive, - const ::basegfx::B2DHomMatrix& rTransformation ) const - { - RTL_LOGFILE_CONTEXT( aLog, "::cppcanvas::internal::RenderGraphicAction::render()" ); - RTL_LOGFILE_CONTEXT_TRACE1( aLog, "::cppcanvas::internal::RenderGraphicAction: 0x%X", this ); - - if( mxBitmap.is() ) - { - rendering::RenderState aLocalState( maState ); - ::canvas::tools::prependToRenderState(aLocalState, rTransformation); - - rCachedPrimitive = mpCanvas->getUNOCanvas()->drawBitmap( mxBitmap, - mpCanvas->getViewState(), - aLocalState ); - } - - return true; - } - - bool RenderGraphicAction::render( const ::basegfx::B2DHomMatrix& rTransformation, - const Subset& rSubset ) const - { - // rendergraphic only contains a single action, fail if subset - // requests different range - if( rSubset.mnSubsetBegin != 0 || - rSubset.mnSubsetEnd != 1 ) - return false; - - return CachedPrimitiveBase::render( rTransformation ); - } - - ::basegfx::B2DRange RenderGraphicAction::getBounds( const ::basegfx::B2DHomMatrix& rTransformation ) const - { - ::basegfx::B2DRange aRet; - - if( mxBitmap.is() ) - { - rendering::RenderState aLocalState( maState ); - ::canvas::tools::prependToRenderState(aLocalState, rTransformation); - - geometry::IntegerSize2D aSize( mxBitmap->getSize() ); - - aRet = tools::calcDevicePixelBounds( ::basegfx::B2DRange( 0, 0, aSize.Width, aSize.Height ), - mpCanvas->getViewState(), aLocalState ); - } - - return( aRet ); - } - - ::basegfx::B2DRange RenderGraphicAction::getBounds( const ::basegfx::B2DHomMatrix& rTransformation, - const Subset& rSubset ) const - { - // rendergraphic only contains a single action, empty bounds - // if subset requests different range - if( rSubset.mnSubsetBegin != 0 || - rSubset.mnSubsetEnd != 1 ) - return ::basegfx::B2DRange(); - - return getBounds( rTransformation ); - } - - sal_Int32 RenderGraphicAction::getActionCount() const - { - return 1; - } - } - - ActionSharedPtr RenderGraphicActionFactory::createRenderGraphicAction( const ::vcl::RenderGraphic& rRenderGraphic, - const ::basegfx::B2DPoint& rDstPoint, - const ::basegfx::B2DVector& rDstSize, - const CanvasSharedPtr& rCanvas, - const OutDevState& rState ) - { - return ActionSharedPtr( new RenderGraphicAction(rRenderGraphic, - rDstPoint, - rDstSize, - rCanvas, - rState ) ); - } - } -} diff --git a/cppcanvas/source/mtfrenderer/rendergraphicaction.hxx b/cppcanvas/source/mtfrenderer/rendergraphicaction.hxx deleted file mode 100644 index f1e2dccdfe0d..000000000000 --- a/cppcanvas/source/mtfrenderer/rendergraphicaction.hxx +++ /dev/null @@ -1,77 +0,0 @@ -/************************************************************************* - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright 2000, 2010 Oracle and/or its affiliates. - * - * OpenOffice.org - a multi-platform office productivity suite - * - * This file is part of OpenOffice.org. - * - * OpenOffice.org is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 3 - * only, as published by the Free Software Foundation. - * - * OpenOffice.org 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 Lesser General Public License version 3 for more details - * (a copy is included in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU Lesser General Public License - * version 3 along with OpenOffice.org. If not, see - * <http://www.openoffice.org/license.html> - * for a copy of the LGPLv3 License. - * - ************************************************************************/ - -#ifndef _CPPCANVAS_RENDERGRAPHICACTION_HXX -#define _CPPCANVAS_RENDERGRAPHICACTION_HXX - -#include <cppcanvas/canvas.hxx> -#include <action.hxx> - -namespace basegfx { - class B2DPoint; - class B2DVector; -} -namespace vcl { - class RenderGraphic; -} - -/* Definition of internal::RenderGraphicActionFactory class */ - -namespace cppcanvas -{ - namespace internal - { - struct OutDevState; - - /** Creates encapsulated converters between GDIMetaFile and - XCanvas. The Canvas argument is deliberately placed at the - constructor, to force reconstruction of this object for a - new canvas. This considerably eases internal state - handling, since a lot of the internal state (e.g. fonts, - text layout) is Canvas-dependent. - */ - class RenderGraphicActionFactory - { - public: - /// Scaled rendergraphic action, dest point and dest size - static ActionSharedPtr createRenderGraphicAction( const ::vcl::RenderGraphic& rRenderGraphic, - const ::basegfx::B2DPoint& rDstPoint, - const ::basegfx::B2DVector& rDstSize, - const CanvasSharedPtr&, - const OutDevState& ); - - private: - // static factory, disable big four - RenderGraphicActionFactory(); - ~RenderGraphicActionFactory(); - RenderGraphicActionFactory(const RenderGraphicActionFactory&); - RenderGraphicActionFactory& operator=( const RenderGraphicActionFactory& ); - }; - } -} - -#endif /*_CPPCANVAS_RENDERGRAPHICACTION_HXX */ diff --git a/cppcanvas/source/mtfrenderer/transparencygroupaction.cxx b/cppcanvas/source/mtfrenderer/transparencygroupaction.cxx index 3d62fb64fe24..a3229f7e8cf9 100644 --- a/cppcanvas/source/mtfrenderer/transparencygroupaction.cxx +++ b/cppcanvas/source/mtfrenderer/transparencygroupaction.cxx @@ -387,7 +387,6 @@ namespace cppcanvas case META_TEXTLINE_ACTION: case META_TEXTRECT_ACTION: case META_STRETCHTEXT_ACTION: - case META_RENDERGRAPHIC_ACTION: // output-generating action - only // copy, if we're within the // requested subset diff --git a/drawinglayer/Library_drawinglayer.mk b/drawinglayer/Library_drawinglayer.mk index e96d5af8b6e0..3b2041fd5e6f 100755 --- a/drawinglayer/Library_drawinglayer.mk +++ b/drawinglayer/Library_drawinglayer.mk @@ -27,6 +27,8 @@ $(eval $(call gb_Library_Library,drawinglayer)) +$(eval $(call gb_Library_set_componentfile,drawinglayer,drawinglayer/drawinglayer)) + $(eval $(call gb_Library_add_package_headers,drawinglayer,drawinglayer_inc)) $(eval $(call gb_Library_add_precompiled_header,drawinglayer,$(SRCDIR)/drawinglayer/inc/pch/precompiled_drawinglayer)) @@ -94,6 +96,7 @@ $(eval $(call gb_Library_add_exception_objects,drawinglayer,\ drawinglayer/source/primitive2d/borderlineprimitive2d \ drawinglayer/source/primitive2d/chartprimitive2d \ drawinglayer/source/primitive2d/controlprimitive2d \ + drawinglayer/source/primitive2d/cropprimitive2d \ drawinglayer/source/primitive2d/discretebitmapprimitive2d \ drawinglayer/source/primitive2d/discreteshadowprimitive2d \ drawinglayer/source/primitive2d/embedded3dprimitive2d \ @@ -114,14 +117,16 @@ $(eval $(call gb_Library_add_exception_objects,drawinglayer,\ drawinglayer/source/primitive2d/metafileprimitive2d \ drawinglayer/source/primitive2d/modifiedcolorprimitive2d \ drawinglayer/source/primitive2d/pagepreviewprimitive2d \ + drawinglayer/source/primitive2d/patternfillprimitive2d \ drawinglayer/source/primitive2d/polypolygonprimitive2d \ drawinglayer/source/primitive2d/polygonprimitive2d \ drawinglayer/source/primitive2d/primitivetools2d \ - drawinglayer/source/primitive2d/rendergraphicprimitive2d \ drawinglayer/source/primitive2d/sceneprimitive2d \ drawinglayer/source/primitive2d/sdrdecompositiontools2d \ drawinglayer/source/primitive2d/shadowprimitive2d \ drawinglayer/source/primitive2d/structuretagprimitive2d \ + drawinglayer/source/primitive2d/svggradientprimitive2d \ + drawinglayer/source/primitive2d/textbreakuphelper \ drawinglayer/source/primitive2d/texteffectprimitive2d \ drawinglayer/source/primitive2d/textenumsprimitive2d \ drawinglayer/source/primitive2d/textlayoutdevice \ @@ -176,6 +181,9 @@ $(eval $(call gb_Library_add_exception_objects,drawinglayer,\ drawinglayer/source/processor3d/zbufferprocessor3d \ drawinglayer/source/texture/texture \ drawinglayer/source/texture/texture3d \ + drawinglayer/source/tools/converters \ + drawinglayer/source/drawinglayeruno/drawinglayeruno \ + drawinglayer/source/drawinglayeruno/xprimitive2drenderer \ )) # vim: set noet sw=4 ts=4: diff --git a/drawinglayer/Package_inc.mk b/drawinglayer/Package_inc.mk index 77d1e0659d57..3be2c7ff9f00 100755 --- a/drawinglayer/Package_inc.mk +++ b/drawinglayer/Package_inc.mk @@ -36,6 +36,7 @@ $(eval $(call gb_Package_add_file,drawinglayer_inc,inc/drawinglayer/primitive2d/ $(eval $(call gb_Package_add_file,drawinglayer_inc,inc/drawinglayer/primitive2d/borderlineprimitive2d.hxx,drawinglayer/primitive2d/borderlineprimitive2d.hxx)) $(eval $(call gb_Package_add_file,drawinglayer_inc,inc/drawinglayer/primitive2d/chartprimitive2d.hxx,drawinglayer/primitive2d/chartprimitive2d.hxx)) $(eval $(call gb_Package_add_file,drawinglayer_inc,inc/drawinglayer/primitive2d/controlprimitive2d.hxx,drawinglayer/primitive2d/controlprimitive2d.hxx)) +$(eval $(call gb_Package_add_file,drawinglayer_inc,inc/drawinglayer/primitive2d/cropprimitive2d.hxx,drawinglayer/primitive2d/cropprimitive2d.hxx)) $(eval $(call gb_Package_add_file,drawinglayer_inc,inc/drawinglayer/primitive2d/discretebitmapprimitive2d.hxx,drawinglayer/primitive2d/discretebitmapprimitive2d.hxx)) $(eval $(call gb_Package_add_file,drawinglayer_inc,inc/drawinglayer/primitive2d/discreteshadowprimitive2d.hxx,drawinglayer/primitive2d/discreteshadowprimitive2d.hxx)) $(eval $(call gb_Package_add_file,drawinglayer_inc,inc/drawinglayer/primitive2d/embedded3dprimitive2d.hxx,drawinglayer/primitive2d/embedded3dprimitive2d.hxx)) @@ -54,6 +55,7 @@ $(eval $(call gb_Package_add_file,drawinglayer_inc,inc/drawinglayer/primitive2d/ $(eval $(call gb_Package_add_file,drawinglayer_inc,inc/drawinglayer/primitive2d/metafileprimitive2d.hxx,drawinglayer/primitive2d/metafileprimitive2d.hxx)) $(eval $(call gb_Package_add_file,drawinglayer_inc,inc/drawinglayer/primitive2d/modifiedcolorprimitive2d.hxx,drawinglayer/primitive2d/modifiedcolorprimitive2d.hxx)) $(eval $(call gb_Package_add_file,drawinglayer_inc,inc/drawinglayer/primitive2d/pagepreviewprimitive2d.hxx,drawinglayer/primitive2d/pagepreviewprimitive2d.hxx)) +$(eval $(call gb_Package_add_file,drawinglayer_inc,inc/drawinglayer/primitive2d/patternfillprimitive2d.hxx,drawinglayer/primitive2d/patternfillprimitive2d.hxx)) $(eval $(call gb_Package_add_file,drawinglayer_inc,inc/drawinglayer/primitive2d/pointarrayprimitive2d.hxx,drawinglayer/primitive2d/pointarrayprimitive2d.hxx)) $(eval $(call gb_Package_add_file,drawinglayer_inc,inc/drawinglayer/primitive2d/polygonprimitive2d.hxx,drawinglayer/primitive2d/polygonprimitive2d.hxx)) $(eval $(call gb_Package_add_file,drawinglayer_inc,inc/drawinglayer/primitive2d/polypolygonprimitive2d.hxx,drawinglayer/primitive2d/polypolygonprimitive2d.hxx)) @@ -62,10 +64,14 @@ $(eval $(call gb_Package_add_file,drawinglayer_inc,inc/drawinglayer/primitive2d/ $(eval $(call gb_Package_add_file,drawinglayer_inc,inc/drawinglayer/primitive2d/sceneprimitive2d.hxx,drawinglayer/primitive2d/sceneprimitive2d.hxx)) $(eval $(call gb_Package_add_file,drawinglayer_inc,inc/drawinglayer/primitive2d/shadowprimitive2d.hxx,drawinglayer/primitive2d/shadowprimitive2d.hxx)) $(eval $(call gb_Package_add_file,drawinglayer_inc,inc/drawinglayer/primitive2d/structuretagprimitive2d.hxx,drawinglayer/primitive2d/structuretagprimitive2d.hxx)) +$(eval $(call gb_Package_add_file,drawinglayer_inc,inc/drawinglayer/primitive2d/svggradientprimitive2d.hxx,drawinglayer/primitive2d/svggradientprimitive2d.hxx)) +$(eval $(call gb_Package_add_file,drawinglayer_inc,inc/drawinglayer/primitive2d/textbreakuphelper.hxx,drawinglayer/primitive2d/textbreakuphelper.hxx)) $(eval $(call gb_Package_add_file,drawinglayer_inc,inc/drawinglayer/primitive2d/textenumsprimitive2d.hxx,drawinglayer/primitive2d/textenumsprimitive2d.hxx)) $(eval $(call gb_Package_add_file,drawinglayer_inc,inc/drawinglayer/primitive2d/texteffectprimitive2d.hxx,drawinglayer/primitive2d/texteffectprimitive2d.hxx)) $(eval $(call gb_Package_add_file,drawinglayer_inc,inc/drawinglayer/primitive2d/textlayoutdevice.hxx,drawinglayer/primitive2d/textlayoutdevice.hxx)) +$(eval $(call gb_Package_add_file,drawinglayer_inc,inc/drawinglayer/primitive2d/textlineprimitive2d.hxx,drawinglayer/primitive2d/textlineprimitive2d.hxx)) $(eval $(call gb_Package_add_file,drawinglayer_inc,inc/drawinglayer/primitive2d/textprimitive2d.hxx,drawinglayer/primitive2d/textprimitive2d.hxx)) +$(eval $(call gb_Package_add_file,drawinglayer_inc,inc/drawinglayer/primitive2d/textstrikeoutprimitive2d.hxx,drawinglayer/primitive2d/textstrikeoutprimitive2d.hxx)) $(eval $(call gb_Package_add_file,drawinglayer_inc,inc/drawinglayer/primitive2d/textdecoratedprimitive2d.hxx,drawinglayer/primitive2d/textdecoratedprimitive2d.hxx)) $(eval $(call gb_Package_add_file,drawinglayer_inc,inc/drawinglayer/primitive2d/texthierarchyprimitive2d.hxx,drawinglayer/primitive2d/texthierarchyprimitive2d.hxx)) $(eval $(call gb_Package_add_file,drawinglayer_inc,inc/drawinglayer/primitive2d/transformprimitive2d.hxx,drawinglayer/primitive2d/transformprimitive2d.hxx)) @@ -76,6 +82,7 @@ $(eval $(call gb_Package_add_file,drawinglayer_inc,inc/drawinglayer/primitive3d/ $(eval $(call gb_Package_add_file,drawinglayer_inc,inc/drawinglayer/primitive3d/baseprimitive3d.hxx,drawinglayer/primitive3d/baseprimitive3d.hxx)) $(eval $(call gb_Package_add_file,drawinglayer_inc,inc/drawinglayer/primitive3d/groupprimitive3d.hxx,drawinglayer/primitive3d/groupprimitive3d.hxx)) $(eval $(call gb_Package_add_file,drawinglayer_inc,inc/drawinglayer/primitive3d/hatchtextureprimitive3d.hxx,drawinglayer/primitive3d/hatchtextureprimitive3d.hxx)) +$(eval $(call gb_Package_add_file,drawinglayer_inc,inc/drawinglayer/primitive3d/hiddengeometryprimitive3d.hxx,drawinglayer/primitive3d/hiddengeometryprimitive3d.hxx)) $(eval $(call gb_Package_add_file,drawinglayer_inc,inc/drawinglayer/primitive3d/modifiedcolorprimitive3d.hxx,drawinglayer/primitive3d/modifiedcolorprimitive3d.hxx)) $(eval $(call gb_Package_add_file,drawinglayer_inc,inc/drawinglayer/primitive3d/polygonprimitive3d.hxx,drawinglayer/primitive3d/polygonprimitive3d.hxx)) $(eval $(call gb_Package_add_file,drawinglayer_inc,inc/drawinglayer/primitive3d/polygontubeprimitive3d.hxx,drawinglayer/primitive3d/polygontubeprimitive3d.hxx)) @@ -110,6 +117,8 @@ $(eval $(call gb_Package_add_file,drawinglayer_inc,inc/drawinglayer/processor2d/ $(eval $(call gb_Package_add_file,drawinglayer_inc,inc/drawinglayer/processor3d/baseprocessor3d.hxx,drawinglayer/processor3d/baseprocessor3d.hxx)) $(eval $(call gb_Package_add_file,drawinglayer_inc,inc/drawinglayer/processor3d/cutfindprocessor3d.hxx,drawinglayer/processor3d/cutfindprocessor3d.hxx)) $(eval $(call gb_Package_add_file,drawinglayer_inc,inc/drawinglayer/processor3d/defaultprocessor3d.hxx,drawinglayer/processor3d/defaultprocessor3d.hxx)) +$(eval $(call gb_Package_add_file,drawinglayer_inc,inc/drawinglayer/processor3d/geometry2dextractor.hxx,drawinglayer/processor3d/geometry2dextractor.hxx)) +$(eval $(call gb_Package_add_file,drawinglayer_inc,inc/drawinglayer/processor3d/shadow3dextractor.hxx,drawinglayer/processor3d/shadow3dextractor.hxx)) $(eval $(call gb_Package_add_file,drawinglayer_inc,inc/drawinglayer/processor3d/zbufferprocessor3d.hxx,drawinglayer/processor3d/zbufferprocessor3d.hxx)) $(eval $(call gb_Package_add_file,drawinglayer_inc,inc/drawinglayer/attribute/fillgradientattribute.hxx,drawinglayer/attribute/fillgradientattribute.hxx)) @@ -132,3 +141,5 @@ $(eval $(call gb_Package_add_file,drawinglayer_inc,inc/drawinglayer/attribute/li $(eval $(call gb_Package_add_file,drawinglayer_inc,inc/drawinglayer/attribute/linestartendattribute.hxx,drawinglayer/attribute/linestartendattribute.hxx)) $(eval $(call gb_Package_add_file,drawinglayer_inc,inc/drawinglayer/texture/texture.hxx,drawinglayer/texture/texture.hxx)) + +$(eval $(call gb_Package_add_file,drawinglayer_inc,inc/drawinglayer/tools/converters.hxx,drawinglayer/tools/converters.hxx)) diff --git a/drawinglayer/drawinglayer.component b/drawinglayer/drawinglayer.component new file mode 100644 index 000000000000..73630675a849 --- /dev/null +++ b/drawinglayer/drawinglayer.component @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!--****************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http:\\www.apache.org\licenses\LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************--> + +<component loader="com.sun.star.loader.SharedLibrary" + xmlns="http://openoffice.org/2010/uno-components"> + <implementation name="drawinglayer::unorenderer::XPrimitive2DRenderer"> + <service name="com.sun.star.graphic.Primitive2DTools"/> + </implementation> +</component> diff --git a/drawinglayer/inc/drawinglayer/primitive2d/baseprimitive2d.hxx b/drawinglayer/inc/drawinglayer/primitive2d/baseprimitive2d.hxx index 0222c8ed37f0..b907d7536012 100644 --- a/drawinglayer/inc/drawinglayer/primitive2d/baseprimitive2d.hxx +++ b/drawinglayer/inc/drawinglayer/primitive2d/baseprimitive2d.hxx @@ -265,6 +265,10 @@ namespace drawinglayer { namespace primitive2d { + /// support to handle a sequence of primitives as stl vector and convert it during creation + typedef ::std::vector< BasePrimitive2D* > Primitive2DVector; + Primitive2DSequence DRAWINGLAYER_DLLPUBLIC Primitive2DVectorToPrimitive2DSequence(const Primitive2DVector& rSource, bool bInvert = false); + /// get B2DRange from a given Primitive2DReference basegfx::B2DRange DRAWINGLAYER_DLLPUBLIC getB2DRangeFromPrimitive2DReference(const Primitive2DReference& rCandidate, const geometry::ViewInformation2D& aViewInformation); diff --git a/drawinglayer/inc/drawinglayer/primitive2d/cropprimitive2d.hxx b/drawinglayer/inc/drawinglayer/primitive2d/cropprimitive2d.hxx new file mode 100644 index 000000000000..86b218d2665a --- /dev/null +++ b/drawinglayer/inc/drawinglayer/primitive2d/cropprimitive2d.hxx @@ -0,0 +1,105 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +#ifndef INCLUDED_DRAWINGLAYER_PRIMITIVE2D_CROPPRIMITIVE2D_HXX +#define INCLUDED_DRAWINGLAYER_PRIMITIVE2D_CROPPRIMITIVE2D_HXX + +#include <drawinglayer/drawinglayerdllapi.h> +#include <drawinglayer/primitive2d/groupprimitive2d.hxx> +#include <basegfx/matrix/b2dhommatrix.hxx> + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace primitive2d + { + /** CropPrimitive2D class + + Caution: Due to old constraints (old core definitions) the + crop distances describe how the uncropped content is defined + relative to the current object size. This means that maTransformation + describes the rurrent object size (the part of the object visible + with the crop applied). To get the original size and orientation + of the uncropped content it is necessary to calc back from the + current situation (maTransformation) using the crop values + to get to the uncropped original content. + + Thus a transformation has to be calculated which will be applied + to the already exsisting content to get it to the uncropped state + ans then this is masked with the current state (mask polygon + created from unit polygon and maTransformation). + + At least in this primitive the units of the crop values are + already in the local coordinate system; inthe core these distances + are defined relative to the object content size (PrefMapMode + and PrefSize of the content)... + + Of course this is a primitive, so feel free to just ignore all that + stuff and use the automatically generated decomposition. Sigh. + */ + class DRAWINGLAYER_DLLPUBLIC CropPrimitive2D : public GroupPrimitive2D + { + private: + // the transformation already applied to the child geometry + basegfx::B2DHomMatrix maTransformation; + + // the crop offsets relative to the range of the unrotated content + double mfCropLeft; + double mfCropTop; + double mfCropRight; + double mfCropBottom; + + public: + /// constructor + CropPrimitive2D( + const Primitive2DSequence& rChildren, + const basegfx::B2DHomMatrix& rTransformation, + double fCropLeft, + double fCropTop, + double fCropRight, + double fCropBottom); + + /// data read access + const basegfx::B2DHomMatrix& getTransformation() const { return maTransformation; } + double getCropLeft() const { return mfCropLeft; } + double getCropTop() const { return mfCropTop; } + double getCropRight() const { return mfCropRight; } + double getCropBottom() const { return mfCropBottom; } + + /// compare operator + virtual bool operator==(const BasePrimitive2D& rPrimitive) const; + + /// local decomposition + virtual Primitive2DSequence get2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const; + + /// provide unique ID + DeclPrimitrive2DIDBlock() + }; + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// + +#endif //INCLUDED_DRAWINGLAYER_PRIMITIVE2D_CROPPRIMITIVE2D_HXX + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/drawinglayer/inc/drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx b/drawinglayer/inc/drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx index e14751122198..4aacc64fba71 100644 --- a/drawinglayer/inc/drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx +++ b/drawinglayer/inc/drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx @@ -99,7 +99,12 @@ #define PRIMITIVE2D_ID_EPSPRIMITIVE2D (PRIMITIVE2D_ID_RANGE_DRAWINGLAYER| 60) #define PRIMITIVE2D_ID_DISCRETESHADOWPRIMITIVE2D (PRIMITIVE2D_ID_RANGE_DRAWINGLAYER| 61) #define PRIMITIVE2D_ID_HIDDENGEOMETRYPRIMITIVE2D (PRIMITIVE2D_ID_RANGE_DRAWINGLAYER| 62) -#define PRIMITIVE2D_ID_RENDERGRAPHICPRIMITIVE2D (PRIMITIVE2D_ID_RANGE_DRAWINGLAYER| 63) +#define PRIMITIVE2D_ID_SVGLINEARGRADIENTPRIMITIVE2D (PRIMITIVE2D_ID_RANGE_DRAWINGLAYER| 63) +#define PRIMITIVE2D_ID_SVGRADIALGRADIENTPRIMITIVE2D (PRIMITIVE2D_ID_RANGE_DRAWINGLAYER| 64) +#define PRIMITIVE2D_ID_SVGLINEARATOMPRIMITIVE2D (PRIMITIVE2D_ID_RANGE_DRAWINGLAYER| 65) +#define PRIMITIVE2D_ID_SVGRADIALATOMPRIMITIVE2D (PRIMITIVE2D_ID_RANGE_DRAWINGLAYER| 66) +#define PRIMITIVE2D_ID_CROPPRIMITIVE2D (PRIMITIVE2D_ID_RANGE_DRAWINGLAYER| 67) +#define PRIMITIVE2D_ID_PATTERNFILLPRIMITIVE2D (PRIMITIVE2D_ID_RANGE_DRAWINGLAYER| 68) ////////////////////////////////////////////////////////////////////////////// diff --git a/drawinglayer/inc/drawinglayer/primitive2d/patternfillprimitive2d.hxx b/drawinglayer/inc/drawinglayer/primitive2d/patternfillprimitive2d.hxx new file mode 100644 index 000000000000..5d760e2e0d1d --- /dev/null +++ b/drawinglayer/inc/drawinglayer/primitive2d/patternfillprimitive2d.hxx @@ -0,0 +1,84 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +#ifndef INCLUDED_DRAWINGLAYER_PRIMITIVE2D_PATTERNFILLPRIMITIVE2D_HXX +#define INCLUDED_DRAWINGLAYER_PRIMITIVE2D_PATTERNFILLPRIMITIVE2D_HXX + +#include <drawinglayer/drawinglayerdllapi.h> +#include <drawinglayer/primitive2d/baseprimitive2d.hxx> +#include <basegfx/matrix/b2dhommatrix.hxx> +#include <basegfx/polygon/b2dpolypolygon.hxx> + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace primitive2d + { + /** PatternFillPrimitive2D class + + This primitive allows filling a given PolyPolygon with a pattern + defined by a sequence of primitives which are mapped to the unit range. + The pattern is defined using a reference range which defines a rectangular + area relative to the PolyPolygon (in unit coordinates) which is virtually + infinitely repeated. + */ + class DRAWINGLAYER_DLLPUBLIC PatternFillPrimitive2D : public BufferedDecompositionPrimitive2D + { + private: + const basegfx::B2DPolyPolygon maMask; + const Primitive2DSequence maChildren; + const basegfx::B2DRange maReferenceRange; + + protected: + /// create local decomposition + virtual Primitive2DSequence create2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const; + + public: + /// constructor + PatternFillPrimitive2D( + const basegfx::B2DPolyPolygon& rMask, + const Primitive2DSequence& rChildren, + const basegfx::B2DRange& rReferenceRange); + + /// data read access + const basegfx::B2DPolyPolygon& getMask() const { return maMask; } + const Primitive2DSequence& getChildren() const { return maChildren; } + const basegfx::B2DRange& getReferenceRange() const { return maReferenceRange; } + + /// compare operator + virtual bool operator==(const BasePrimitive2D& rPrimitive) const; + + /// get range + virtual basegfx::B2DRange getB2DRange(const geometry::ViewInformation2D& rViewInformation) const; + + /// provide unique ID + DeclPrimitrive2DIDBlock() + }; + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// + +#endif //INCLUDED_DRAWINGLAYER_PRIMITIVE2D_PATTERNFILLPRIMITIVE2D_HXX + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/drawinglayer/inc/drawinglayer/primitive2d/rendergraphicprimitive2d.hxx b/drawinglayer/inc/drawinglayer/primitive2d/rendergraphicprimitive2d.hxx deleted file mode 100644 index 190439442917..000000000000 --- a/drawinglayer/inc/drawinglayer/primitive2d/rendergraphicprimitive2d.hxx +++ /dev/null @@ -1,95 +0,0 @@ -/************************************************************************* - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright 2000, 2010 Oracle and/or its affiliates. - * - * OpenOffice.org - a multi-platform office productivity suite - * - * This file is part of OpenOffice.org. - * - * OpenOffice.org is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 3 - * only, as published by the Free Software Foundation. - * - * OpenOffice.org 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 Lesser General Public License version 3 for more details - * (a copy is included in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU Lesser General Public License - * version 3 along with OpenOffice.org. If not, see - * <http://www.openoffice.org/license.html> - * for a copy of the LGPLv3 License. - * - ************************************************************************/ - -#ifndef INCLUDED_DRAWINGLAYER_PRIMITIVE2D_RENDERGRAPHICPRIMITIVE2D_HXX -#define INCLUDED_DRAWINGLAYER_PRIMITIVE2D_RENDERGRAPHICPRIMITIVE2D_HXX - -#include <drawinglayer/primitive2d/baseprimitive2d.hxx> -#include <basegfx/matrix/b2dhommatrix.hxx> -#include <vcl/rendergraphic.hxx> -#include <memory> - -////////////////////////////////////////////////////////////////////////////// -// RenderGraphicPrimitive2D class - -namespace vcl { class RenderGraphicRasterizer; } - -namespace drawinglayer -{ - namespace primitive2d - { - /** RenderGraphicPrimitive2D class - - This class is the central primitive for RenderGraphic-based primitives. - */ - class RenderGraphicPrimitive2D : public BasePrimitive2D - { - private: - /// the RenderGraphic data - vcl::RenderGraphic maRenderGraphic; - mutable std::auto_ptr< vcl::RenderGraphicRasterizer > mapCurrentRasterizer; - - /** the object transformation from unit coordinates, defining - size, shear, rotate and position - */ - basegfx::B2DHomMatrix maTransform; - - public: - /// constructor - RenderGraphicPrimitive2D( - const vcl::RenderGraphic& rRenderGraphic, - const basegfx::B2DHomMatrix& rTransform); - - /// data read access - inline const vcl::RenderGraphic& getRenderGraphic() const { return maRenderGraphic; } - inline const basegfx::B2DHomMatrix& getTransform() const { return maTransform; } - - // access to latest used vcl::GraphicRasterizer for possibly reusing - // an already rendered vcl::RenderGraphic with the same transform - // properties during the next rendering process - void setCurrentRasterizer() const; - void setCurrentRasterizer( const vcl::RenderGraphicRasterizer& rCurrentGraphicRasterizer ) const; - inline const vcl::RenderGraphicRasterizer* getCurrentRasterizer() const { return( mapCurrentRasterizer.get() ); } - - /// compare operator - virtual bool operator==(const BasePrimitive2D& rPrimitive) const; - - /// get range - virtual basegfx::B2DRange getB2DRange(const geometry::ViewInformation2D& rViewInformation) const; - - /// provide unique ID - DeclPrimitrive2DIDBlock() - }; - } // end of namespace primitive2d -} // end of namespace drawinglayer - -////////////////////////////////////////////////////////////////////////////// - -#endif // INCLUDED_DRAWINGLAYER_PRIMITIVE2D_RENDERGRAPHICPRIMITIVE2D_HXX - -////////////////////////////////////////////////////////////////////////////// -// eof diff --git a/drawinglayer/inc/drawinglayer/primitive2d/svggradientprimitive2d.hxx b/drawinglayer/inc/drawinglayer/primitive2d/svggradientprimitive2d.hxx new file mode 100644 index 000000000000..e2e12cff19ff --- /dev/null +++ b/drawinglayer/inc/drawinglayer/primitive2d/svggradientprimitive2d.hxx @@ -0,0 +1,468 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http:\\www.apache.org\licenses\LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +#ifndef INCLUDED_DRAWINGLAYER_PRIMITIVE2D_SVGGRADIENTPRIMITIVE2D_HXX +#define INCLUDED_DRAWINGLAYER_PRIMITIVE2D_SVGGRADIENTPRIMITIVE2D_HXX + +#include <drawinglayer/drawinglayerdllapi.h> +#include <drawinglayer/primitive2d/baseprimitive2d.hxx> +#include <basegfx/color/bcolor.hxx> +#include <basegfx/polygon/b2dpolypolygon.hxx> +#include <basegfx/matrix/b2dhommatrix.hxx> +#include <drawinglayer/primitive2d/primitivetools2d.hxx> +#include <vector> + +////////////////////////////////////////////////////////////////////////////// +// SvgGradientEntry class + +namespace drawinglayer +{ + namespace primitive2d + { + /// a single GradientStop defining a color and opacity at a distance + class SvgGradientEntry + { + private: + double mfOffset; + basegfx::BColor maColor; + double mfOpacity; + + public: + SvgGradientEntry(double fOffset, const basegfx::BColor& rColor = basegfx::BColor(0.0, 0.0, 0.0), double fOpacity = 1.0) + : mfOffset(fOffset), + maColor(rColor), + mfOpacity(fOpacity) + { + } + + double getOffset() const { return mfOffset; } + const basegfx::BColor& getColor() const { return maColor; } + double getOpacity() const { return mfOpacity; } + + bool operator==(const SvgGradientEntry& rCompare) const + { + return (getOffset() == rCompare.getOffset() + && getColor() == getColor() + && getOpacity() == getOpacity()); + } + + bool operator<(const SvgGradientEntry& rCompare) const + { + return getOffset() < rCompare.getOffset(); + } + }; + + typedef ::std::vector< SvgGradientEntry > SvgGradientEntryVector; + + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// +// SvgGradientHelper class +#define DEFAULT_OVERLAPPING_VALUE (1.0/512.0) + +namespace drawinglayer +{ + namespace primitive2d + { + enum SpreadMethod + { + Spread_pad = 0, + Spread_reflect, + Spread_repeat + }; + + /* helper for linear and radial gradient, both get derived from this + to share common definitions and functionality + **/ + class SvgGradientHelper + { + private: + /// geometric definition, the geometry to be filled + basegfx::B2DPolyPolygon maPolyPolygon; + + /// the gradient definition + SvgGradientEntryVector maGradientEntries; + + /// start and/or center point + basegfx::B2DPoint maStart; + + /// how to spread + SpreadMethod maSpreadMethod; + + /* allows to set an overlapping value to be able to create + slightly overlapping PolyPolygons/Polygons for the decomposition. + This is needed since when creating geometrically correct decompositions + many visualisations will show artefacts at the borders, even when these + borders are absolutely correctly defined. It is possible to define a + useful value for this since the coordinate system we are working in is + in unit coordinates so that the whole gradient is from [0.0 .. 1.0] range. + This explains the default value which is 1/512 by a maximum possible + color count of 255 steps per GradientStop. + Give a 0.0 here to go to geometrically correct gradient decompositions if + needed. + An alternative would be to create no PolyPolygons from outside to inside + (example for radial), but this leads to up to 255 filled polygons per + GradientStop and thus to enormous rendering costs. + **/ + double mfOverlapping; + + /// bitfield + bool mbPreconditionsChecked : 1; + bool mbCreatesContent : 1; + bool mbSingleEntry : 1; + bool mbFullyOpaque : 1; + + protected: + /// local helpers + Primitive2DSequence createSingleGradientEntryFill() const; + virtual void createAtom( + Primitive2DVector& rTargetColor, + Primitive2DVector& rTargetOpacity, + const SvgGradientEntry& rFrom, + const SvgGradientEntry& rTo, + sal_Int32 nOffset) const = 0; + double createRun( + Primitive2DVector& rTargetColor, + Primitive2DVector& rTargetOpacity, + double fPos, + double fMax, + const SvgGradientEntryVector& rEntries, + sal_Int32 nOffset) const; + virtual void checkPreconditions(); + Primitive2DSequence SvgGradientHelper::createResult( + const Primitive2DVector& rTargetColor, + const Primitive2DVector& rTargetOpacity, + const basegfx::B2DHomMatrix& rUnitGradientToObject, + bool bInvert = false) const; + bool getCreatesContent() const { return mbCreatesContent; } + bool getSingleEntry() const { return mbSingleEntry; } + void setSingleEntry() { mbSingleEntry = true; } + bool getPreconditionsChecked() const { return mbPreconditionsChecked; } + bool getFullyOpaque() const { return mbFullyOpaque; } + + public: + /// constructor + SvgGradientHelper( + const basegfx::B2DPolyPolygon& rPolyPolygon, + const SvgGradientEntryVector& rGradientEntries, + const basegfx::B2DPoint& rStart, + SpreadMethod aSpreadMethod = Spread_pad, + double fOverlapping = DEFAULT_OVERLAPPING_VALUE); + + /// data read access + const basegfx::B2DPolyPolygon& getPolyPolygon() const { return maPolyPolygon; } + const SvgGradientEntryVector& getGradientEntries() const { return maGradientEntries; } + const basegfx::B2DPoint& getStart() const { return maStart; } + SpreadMethod getSpreadMethod() const { return maSpreadMethod; } + const double getOverlapping() const { return mfOverlapping; } + + /// compare operator + virtual bool operator==(const SvgGradientHelper& rSvgGradientHelper) const; + }; + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// +// SvgLinearGradientPrimitive2D class + +namespace drawinglayer +{ + namespace primitive2d + { + /// the basic linear gradient primitive + class DRAWINGLAYER_DLLPUBLIC SvgLinearGradientPrimitive2D : public BufferedDecompositionPrimitive2D, public SvgGradientHelper + { + private: + /// the end point for linear gradient + basegfx::B2DPoint maEnd; + + /// local helpers + void ensureGeometry( + basegfx::B2DPolyPolygon& rPolyPolygon, + const SvgGradientEntry& rFrom, + const SvgGradientEntry& rTo, + sal_Int32 nOffset) const; + + protected: + /// local helpers + virtual void createAtom( + Primitive2DVector& rTargetColor, + Primitive2DVector& rTargetOpacity, + const SvgGradientEntry& rFrom, + const SvgGradientEntry& rTo, + sal_Int32 nOffset) const; + virtual void checkPreconditions(); + + /// local decomposition. + virtual Primitive2DSequence create2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const; + + public: + /// constructor + SvgLinearGradientPrimitive2D( + const basegfx::B2DPolyPolygon& rPolyPolygon, + const SvgGradientEntryVector& rGradientEntries, + const basegfx::B2DPoint& rStart, + const basegfx::B2DPoint& rEnd, + SpreadMethod aSpreadMethod = Spread_pad, + double fOverlapping = DEFAULT_OVERLAPPING_VALUE); + + /// data read access + const basegfx::B2DPoint& getEnd() const { return maEnd; } + + /// compare operator + virtual bool operator==(const BasePrimitive2D& rPrimitive) const; + + /// get range + virtual basegfx::B2DRange getB2DRange(const geometry::ViewInformation2D& rViewInformation) const; + + /// provide unique ID + DeclPrimitrive2DIDBlock() + }; + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// +// SvgRadialGradientPrimitive2D class + +namespace drawinglayer +{ + namespace primitive2d + { + /// the basic radial gradient primitive + class DRAWINGLAYER_DLLPUBLIC SvgRadialGradientPrimitive2D : public BufferedDecompositionPrimitive2D, public SvgGradientHelper + { + private: + /// the geometric definition + double mfRadius; + + /// Focal only used when focal is set at all, see constructors + basegfx::B2DPoint maFocal; + basegfx::B2DVector maFocalVector; + double maFocalLength; + + // internal helper for case Spread_reflect + SvgGradientEntryVector maMirroredGradientEntries; + + /// bitfield + bool mbFocalSet : 1; + + /// local helpers + const SvgGradientEntryVector& getMirroredGradientEntries() const; + void createMirroredGradientEntries(); + void ensureGeometry( + basegfx::B2DPolyPolygon& rPolyPolygon, + const SvgGradientEntry& rFrom, + const SvgGradientEntry& rTo, + sal_Int32 nOffset) const; + + protected: + /// local helpers + virtual void createAtom( + Primitive2DVector& rTargetColor, + Primitive2DVector& rTargetOpacity, + const SvgGradientEntry& rFrom, + const SvgGradientEntry& rTo, + sal_Int32 nOffset) const; + virtual void checkPreconditions(); + + /// local decomposition. + virtual Primitive2DSequence create2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const; + + public: + /// constructor + SvgRadialGradientPrimitive2D( + const basegfx::B2DPolyPolygon& rPolyPolygon, + const SvgGradientEntryVector& rGradientEntries, + const basegfx::B2DPoint& rStart, + double fRadius, + SpreadMethod aSpreadMethod = Spread_pad, + const basegfx::B2DPoint* pFocal = 0, + double fOverlapping = DEFAULT_OVERLAPPING_VALUE); + + /// data read access + double getRadius() const { return mfRadius; } + const basegfx::B2DPoint& getFocal() const { return maFocal; } + bool isFocalSet() const { return mbFocalSet; } + + /// compare operator + virtual bool operator==(const BasePrimitive2D& rPrimitive) const; + + /// get range + virtual basegfx::B2DRange getB2DRange(const geometry::ViewInformation2D& rViewInformation) const; + + /// provide unique ID + DeclPrimitrive2DIDBlock() + }; + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// +// SvgLinearAtomPrimitive2D class + +namespace drawinglayer +{ + namespace primitive2d + { + /* basic primitive for a single linear GradientRun in unit coordiantes. + It's derived from DiscreteMetricDependentPrimitive2D to allow view-dependent + decompositions allowing reduced color steps + **/ + class DRAWINGLAYER_DLLPUBLIC SvgLinearAtomPrimitive2D : public DiscreteMetricDependentPrimitive2D + { + private: + /// the geometric definition in unit coordiantes + basegfx::BColor maColorA; + basegfx::BColor maColorB; + double mfOffsetA; + double mfOffsetB; + double mfOverlapping; + + protected: + + /// local decomposition. + virtual Primitive2DSequence create2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const; + + public: + /// constructor + SvgLinearAtomPrimitive2D( + const basegfx::BColor& aColorA, double fOffsetA, + const basegfx::BColor& aColorB, double fOffsetB, + double fOverlapping = DEFAULT_OVERLAPPING_VALUE) + : DiscreteMetricDependentPrimitive2D(), + maColorA(aColorA), + maColorB(aColorB), + mfOffsetA(fOffsetA), + mfOffsetB(fOffsetB), + mfOverlapping(fOverlapping) + { + } + + /// data read access + const basegfx::BColor& getColorA() const { return maColorA; } + const basegfx::BColor& getColorB() const { return maColorB; } + double getOffsetA() const { return mfOffsetA; } + double getOffsetB() const { return mfOffsetB; } + const double getOverlapping() const { return mfOverlapping; } + + /// compare operator + virtual bool operator==(const BasePrimitive2D& rPrimitive) const; + + /// provide unique ID + DeclPrimitrive2DIDBlock() + }; + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// +// SvgRadialAtomPrimitive2D class + +namespace drawinglayer +{ + namespace primitive2d + { + /* basic primitive for a single radial GradientRun in unit coordiantes. + It's derived from DiscreteMetricDependentPrimitive2D to allow view-dependent + decompositions allowing reduced color steps + **/ + class DRAWINGLAYER_DLLPUBLIC SvgRadialAtomPrimitive2D : public DiscreteMetricDependentPrimitive2D + { + private: + /// the geometric definition in unit coordiantes + basegfx::BColor maColorA; + basegfx::BColor maColorB; + double mfScaleA; + double mfScaleB; + + /// Only used when focal is set + basegfx::B2DVector maTranslateA; + basegfx::B2DVector maTranslateB; + + double mfOverlapping; + + /// bitfield + bool mbTranslateSet : 1; + + protected: + + /// local decomposition. + virtual Primitive2DSequence create2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const; + + public: + /// constructor + SvgRadialAtomPrimitive2D( + const basegfx::BColor& aColorA, double fScaleA, const basegfx::B2DVector& rTranslateA, + const basegfx::BColor& aColorB, double fScaleB, const basegfx::B2DVector& rTranslateB, + double fOverlapping = DEFAULT_OVERLAPPING_VALUE) + : DiscreteMetricDependentPrimitive2D(), + maColorA(aColorA), + maColorB(aColorB), + mfScaleA(fScaleA), + mfScaleB(fScaleB), + maTranslateA(rTranslateA), + maTranslateB(rTranslateB), + mfOverlapping(fOverlapping), + mbTranslateSet(true) + { + mbTranslateSet = !maTranslateA.equal(maTranslateB); + } + + SvgRadialAtomPrimitive2D( + const basegfx::BColor& aColorA, double fScaleA, + const basegfx::BColor& aColorB, double fScaleB, + double fOverlapping = DEFAULT_OVERLAPPING_VALUE) + : DiscreteMetricDependentPrimitive2D(), + maColorA(aColorA), + maColorB(aColorB), + mfScaleA(fScaleA), + mfScaleB(fScaleB), + maTranslateA(), + maTranslateB(), + mfOverlapping(fOverlapping), + mbTranslateSet(false) + { + } + + /// data read access + const basegfx::BColor& getColorA() const { return maColorA; } + const basegfx::BColor& getColorB() const { return maColorB; } + double getScaleA() const { return mfScaleA; } + double getScaleB() const { return mfScaleB; } + const basegfx::B2DVector& getTranslateA() const { return maTranslateA; } + const basegfx::B2DVector& getTranslateB() const { return maTranslateB; } + const double getOverlapping() const { return mfOverlapping; } + bool getTranslateSet() const { return mbTranslateSet; } + + /// compare operator + virtual bool operator==(const BasePrimitive2D& rPrimitive) const; + + /// provide unique ID + DeclPrimitrive2DIDBlock() + }; + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// + +#endif //INCLUDED_DRAWINGLAYER_PRIMITIVE2D_SVGGRADIENTPRIMITIVE2D_HXX + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/drawinglayer/inc/drawinglayer/primitive2d/textbreakuphelper.hxx b/drawinglayer/inc/drawinglayer/primitive2d/textbreakuphelper.hxx new file mode 100644 index 000000000000..66560938221c --- /dev/null +++ b/drawinglayer/inc/drawinglayer/primitive2d/textbreakuphelper.hxx @@ -0,0 +1,91 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http:\\www.apache.org\licenses\LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +#ifndef INCLUDED_DRAWINGLAYER_PRIMITIVE2D_TEXTBREAKUPHELPER_HXX +#define INCLUDED_DRAWINGLAYER_PRIMITIVE2D_TEXTBREAKUPHELPER_HXX + +#include <drawinglayer/drawinglayerdllapi.h> +#include <drawinglayer/primitive2d/textprimitive2d.hxx> +#include <drawinglayer/primitive2d/textlayoutdevice.hxx> +#include <basegfx/matrix/b2dhommatrixtools.hxx> + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace primitive2d + { + enum BreakupUnit + { + BreakupUnit_character, + BreakupUnit_word, + BreakupUnit_sentence + }; + + class DRAWINGLAYER_DLLPUBLIC TextBreakupHelper + { + private: + const Primitive2DReference mxSource; + Primitive2DSequence mxResult; + const TextSimplePortionPrimitive2D* mpSource; + TextLayouterDevice maTextLayouter; + basegfx::tools::B2DHomMatrixBufferedOnDemandDecompose maDecTrans; + + /// bitfield + bool mbNoDXArray : 1; + + /// create a portion from nIndex to nLength and append to rTempResult + void breakupPortion(Primitive2DVector& rTempResult, sal_uInt32 nIndex, sal_uInt32 nLength); + + /// breakup complete primitive + void breakup(BreakupUnit aBreakupUnit); + + protected: + /// allow user callback to allow changes to the new TextTransformation. Default + /// does nothing. Retval defines if a primitive gets created, e.g. return false + /// to suppress creation + virtual bool allowChange(sal_uInt32 nCount, basegfx::B2DHomMatrix& rNewTransform, sal_uInt32 nIndex, sal_uInt32 nLength); + + /// allow read access to evtl. useful local parts + const TextSimplePortionPrimitive2D* getCastedSource() const { return mpSource; } + const TextLayouterDevice& getTextLayouter() const { return maTextLayouter; } + const basegfx::tools::B2DHomMatrixBufferedOnDemandDecompose& getDecTrans() const { return maDecTrans; } + + public: + TextBreakupHelper(const Primitive2DReference& rxSource); + virtual ~TextBreakupHelper(); + + /// get result + const Primitive2DSequence& getResult(BreakupUnit aBreakupUnit = BreakupUnit_character) const; + + /// data read access + const Primitive2DReference& getSource() const { return mxSource; } + }; + + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// + +#endif //INCLUDED_DRAWINGLAYER_PRIMITIVE2D_TEXTBREAKUPHELPER_HXX + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/drawinglayer/inc/drawinglayer/primitive2d/textlayoutdevice.hxx b/drawinglayer/inc/drawinglayer/primitive2d/textlayoutdevice.hxx index 9ffb1d3ea527..e87c378c6f50 100644 --- a/drawinglayer/inc/drawinglayer/primitive2d/textlayoutdevice.hxx +++ b/drawinglayer/inc/drawinglayer/primitive2d/textlayoutdevice.hxx @@ -30,6 +30,7 @@ #include <basegfx/range/b2drange.hxx> #include <vector> #include <com/sun/star/lang/Locale.hpp> +#include <basegfx/polygon/b2dpolypolygon.hxx> ////////////////////////////////////////////////////////////////////////////// // predefines @@ -43,11 +44,6 @@ namespace drawinglayer { namespace attribute { class FontAttribute; }} -namespace basegfx { - class B2DPolyPolygon; - typedef ::std::vector< B2DPolyPolygon > B2DPolyPolygonVector; -} - ////////////////////////////////////////////////////////////////////////////// // access to one global impTimedRefDev incarnation in namespace drawinglayer::primitive diff --git a/drawinglayer/inc/drawinglayer/primitive2d/textprimitive2d.hxx b/drawinglayer/inc/drawinglayer/primitive2d/textprimitive2d.hxx index 6abc4ad6458a..a9bbea65f16d 100644 --- a/drawinglayer/inc/drawinglayer/primitive2d/textprimitive2d.hxx +++ b/drawinglayer/inc/drawinglayer/primitive2d/textprimitive2d.hxx @@ -33,15 +33,11 @@ #include <vector> #include <com/sun/star/lang/Locale.hpp> #include <drawinglayer/attribute/fontattribute.hxx> +#include <basegfx/polygon/b2dpolypolygon.hxx> ////////////////////////////////////////////////////////////////////////////// // predefines -namespace basegfx { - class B2DPolyPolygon; - typedef ::std::vector< B2DPolyPolygon > B2DPolyPolygonVector; -} - class OutputDevice; ////////////////////////////////////////////////////////////////////////////// diff --git a/drawinglayer/inc/drawinglayer/processor2d/canvasprocessor.hxx b/drawinglayer/inc/drawinglayer/processor2d/canvasprocessor.hxx index d9f32533b0a4..c3457044bc4a 100644 --- a/drawinglayer/inc/drawinglayer/processor2d/canvasprocessor.hxx +++ b/drawinglayer/inc/drawinglayer/processor2d/canvasprocessor.hxx @@ -53,7 +53,6 @@ namespace drawinglayer { namespace primitive2d { class MetafilePrimitive2D; class TextSimplePortionPrimitive2D; class BitmapPrimitive2D; - class RenderGraphicPrimitive2D; class TransparencePrimitive2D; class PolygonStrokePrimitive2D; class FillBitmapPrimitive2D; @@ -106,7 +105,6 @@ namespace drawinglayer void impRenderMetafilePrimitive2D(const primitive2d::MetafilePrimitive2D& rMetaCandidate); void impRenderTextSimplePortionPrimitive2D(const primitive2d::TextSimplePortionPrimitive2D& rTextCandidate); void impRenderBitmapPrimitive2D(const primitive2d::BitmapPrimitive2D& rBitmapCandidate); - void impRenderRenderGraphicPrimitive2D(const primitive2d::RenderGraphicPrimitive2D& rRenderGraphicCandidate); void impRenderTransparencePrimitive2D(const primitive2d::TransparencePrimitive2D& rTransparenceCandidate); void impRenderPolygonStrokePrimitive2D(const primitive2d::PolygonStrokePrimitive2D& rPolygonStrokePrimitive); void impRenderFillBitmapPrimitive2D(const primitive2d::FillBitmapPrimitive2D& rFillBitmapPrimitive2D); diff --git a/drawinglayer/inc/drawinglayer/processor2d/contourextractor2d.hxx b/drawinglayer/inc/drawinglayer/processor2d/contourextractor2d.hxx index 921eb95eb502..37421fd3b854 100644 --- a/drawinglayer/inc/drawinglayer/processor2d/contourextractor2d.hxx +++ b/drawinglayer/inc/drawinglayer/processor2d/contourextractor2d.hxx @@ -44,7 +44,7 @@ namespace drawinglayer { private: /// the extracted contour - std::vector< basegfx::B2DPolyPolygon > maExtractedContour; + basegfx::B2DPolyPolygonVector maExtractedContour; /// tooling methods void processBasePrimitive2D(const primitive2d::BasePrimitive2D& rCandidate); @@ -53,7 +53,7 @@ namespace drawinglayer ContourExtractor2D(const geometry::ViewInformation2D& rViewInformation); virtual ~ContourExtractor2D(); - const std::vector< basegfx::B2DPolyPolygon >& getExtractedContour() const { return maExtractedContour; } + const basegfx::B2DPolyPolygonVector& getExtractedContour() const { return maExtractedContour; } }; } // end of namespace processor2d } // end of namespace drawinglayer diff --git a/drawinglayer/inc/drawinglayer/processor2d/linegeometryextractor2d.hxx b/drawinglayer/inc/drawinglayer/processor2d/linegeometryextractor2d.hxx index 13402c050ba6..408614c26fe5 100644 --- a/drawinglayer/inc/drawinglayer/processor2d/linegeometryextractor2d.hxx +++ b/drawinglayer/inc/drawinglayer/processor2d/linegeometryextractor2d.hxx @@ -27,6 +27,7 @@ #include <drawinglayer/drawinglayerdllapi.h> #include <drawinglayer/processor2d/baseprocessor2d.hxx> #include <basegfx/polygon/b2dpolypolygon.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> ////////////////////////////////////////////////////////////////////////////// @@ -42,8 +43,8 @@ namespace drawinglayer class DRAWINGLAYER_DLLPUBLIC LineGeometryExtractor2D : public BaseProcessor2D { private: - std::vector< basegfx::B2DPolygon > maExtractedHairlines; - std::vector< basegfx::B2DPolyPolygon > maExtractedLineFills; + basegfx::B2DPolygonVector maExtractedHairlines; + basegfx::B2DPolyPolygonVector maExtractedLineFills; /// bitfield unsigned mbInLineGeometry : 1; @@ -55,8 +56,8 @@ namespace drawinglayer LineGeometryExtractor2D(const geometry::ViewInformation2D& rViewInformation); virtual ~LineGeometryExtractor2D(); - const std::vector< basegfx::B2DPolygon >& getExtractedHairlines() const { return maExtractedHairlines; } - const std::vector< basegfx::B2DPolyPolygon >& getExtractedLineFills() const { return maExtractedLineFills; } + const basegfx::B2DPolygonVector& getExtractedHairlines() const { return maExtractedHairlines; } + const basegfx::B2DPolyPolygonVector& getExtractedLineFills() const { return maExtractedLineFills; } }; } // end of namespace processor2d } // end of namespace drawinglayer diff --git a/drawinglayer/inc/drawinglayer/processor2d/vclprocessor2d.hxx b/drawinglayer/inc/drawinglayer/processor2d/vclprocessor2d.hxx index b3c8fb0b6799..b5db89f98332 100644 --- a/drawinglayer/inc/drawinglayer/processor2d/vclprocessor2d.hxx +++ b/drawinglayer/inc/drawinglayer/processor2d/vclprocessor2d.hxx @@ -38,7 +38,6 @@ namespace drawinglayer { namespace primitive2d { class TextSimplePortionPrimitive2D; class PolygonHairlinePrimitive2D; class BitmapPrimitive2D; - class RenderGraphicPrimitive2D; class FillBitmapPrimitive2D; class PolyPolygonGradientPrimitive2D; class PolyPolygonBitmapPrimitive2D; @@ -95,7 +94,6 @@ namespace drawinglayer void RenderTextSimpleOrDecoratedPortionPrimitive2D(const primitive2d::TextSimplePortionPrimitive2D& rTextCandidate); void RenderPolygonHairlinePrimitive2D(const primitive2d::PolygonHairlinePrimitive2D& rPolygonCandidate, bool bPixelBased); void RenderBitmapPrimitive2D(const primitive2d::BitmapPrimitive2D& rBitmapCandidate); - void RenderRenderGraphicPrimitive2D(const primitive2d::RenderGraphicPrimitive2D& rRenderGraphicCandidate); void RenderFillBitmapPrimitive2D(const primitive2d::FillBitmapPrimitive2D& rFillBitmapCandidate); void RenderPolyPolygonGradientPrimitive2D(const primitive2d::PolyPolygonGradientPrimitive2D& rPolygonCandidate); void RenderPolyPolygonBitmapPrimitive2D(const primitive2d::PolyPolygonBitmapPrimitive2D& rPolygonCandidate); diff --git a/drawinglayer/inc/drawinglayer/processor3d/shadow3dextractor.hxx b/drawinglayer/inc/drawinglayer/processor3d/shadow3dextractor.hxx index 24caa31905b0..d33c89ef0c76 100644 --- a/drawinglayer/inc/drawinglayer/processor3d/shadow3dextractor.hxx +++ b/drawinglayer/inc/drawinglayer/processor3d/shadow3dextractor.hxx @@ -51,12 +51,9 @@ namespace drawinglayer class DRAWINGLAYER_DLLPUBLIC Shadow3DExtractingProcessor : public BaseProcessor3D { private: - /// typedef for data handling - typedef std::vector< primitive2d::BasePrimitive2D* > BasePrimitive2DVector; - /// result holding vector (2D) and target vector for stacking (inited to &maPrimitive2DSequence) - BasePrimitive2DVector maPrimitive2DSequence; - BasePrimitive2DVector* mpPrimitive2DSequence; + primitive2d::Primitive2DVector maPrimitive2DSequence; + primitive2d::Primitive2DVector* mpPrimitive2DSequence; /// object transformation for scene for 2d definition basegfx::B2DHomMatrix maObjectTransformation; @@ -93,10 +90,6 @@ namespace drawinglayer */ virtual void processBasePrimitive3D(const primitive3d::BasePrimitive3D& rCandidate); - /// helper to convert from BasePrimitive2DVector to primitive2d::Primitive2DSequence - const primitive2d::Primitive2DSequence getPrimitive2DSequenceFromBasePrimitive2DVector( - const BasePrimitive2DVector& rVector) const; - public: Shadow3DExtractingProcessor( const geometry::ViewInformation3D& rViewInformation, diff --git a/drawinglayer/inc/drawinglayer/tools/converters.hxx b/drawinglayer/inc/drawinglayer/tools/converters.hxx new file mode 100644 index 000000000000..1233f17717d1 --- /dev/null +++ b/drawinglayer/inc/drawinglayer/tools/converters.hxx @@ -0,0 +1,49 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http:\\www.apache.org\licenses\LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +#ifndef INCLUDED_DRAWINGLAYER_TOOLS_CONVERTERS_HXX +#define INCLUDED_DRAWINGLAYER_TOOLS_CONVERTERS_HXX + +#include <drawinglayer/drawinglayerdllapi.h> +#include <vcl/bitmapex.hxx> +#include <drawinglayer/primitive2d/baseprimitive2d.hxx> + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace tools + { + BitmapEx DRAWINGLAYER_DLLPUBLIC convertToBitmapEx( + const drawinglayer::primitive2d::Primitive2DSequence& rSeq, + const geometry::ViewInformation2D& rViewInformation2D, + sal_uInt32 nDiscreteWidth, + sal_uInt32 nDiscreteHeight, + sal_uInt32 nMaxQuadratPixels); + + } // end of namespace tools +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// + +#endif //INCLUDED_DRAWINGLAYER_TOOLS_CONVERTERS_HXX + +// eof diff --git a/drawinglayer/source/drawinglayeruno/drawinglayeruno.cxx b/drawinglayer/source/drawinglayeruno/drawinglayeruno.cxx new file mode 100644 index 000000000000..8ead3d1023b9 --- /dev/null +++ b/drawinglayer/source/drawinglayeruno/drawinglayeruno.cxx @@ -0,0 +1,95 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http:\\www.apache.org\licenses\LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_drawinglayer.hxx" + +#include <drawinglayer/drawinglayerdllapi.h> +#include <com/sun/star/uno/Reference.h> +#include <com/sun/star/uno/RuntimeException.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/registry/XRegistryKey.hpp> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/XSingleServiceFactory.hpp> +#include <uno/environment.h> +#include <cppuhelper/factory.hxx> + +////////////////////////////////////////////////////////////////////////////// + +using namespace ::com::sun::star; + +////////////////////////////////////////////////////////////////////////////// +// predefines + +namespace drawinglayer +{ + namespace unorenderer + { + extern uno::Sequence< rtl::OUString > SAL_CALL XPrimitive2DRenderer_getSupportedServiceNames(); + extern rtl::OUString SAL_CALL XPrimitive2DRenderer_getImplementationName(); + extern uno::Reference< uno::XInterface > SAL_CALL XPrimitive2DRenderer_createInstance( const uno::Reference< lang::XMultiServiceFactory > & ); + } // end of namespace unorenderer +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// +// component_getImplementationEnvironment + +extern "C" +{ + DRAWINGLAYER_DLLPUBLIC void SAL_CALL component_getImplementationEnvironment( const sal_Char ** ppEnvTypeName, uno_Environment ** /* ppEnv */ ) + { + *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; + } +} + +////////////////////////////////////////////////////////////////////////////// +// component_getFactory + +extern "C" +{ + DRAWINGLAYER_DLLPUBLIC void* SAL_CALL component_getFactory( const sal_Char* pImplName, void* pServiceManager, void* /* pRegistryKey */ ) + { + uno::Reference< lang::XSingleServiceFactory > xFactory; + void* pRet = 0; + + if(drawinglayer::unorenderer::XPrimitive2DRenderer_getImplementationName().equalsAscii(pImplName)) + { + xFactory = ::cppu::createSingleFactory( + reinterpret_cast< lang::XMultiServiceFactory * >(pServiceManager), + drawinglayer::unorenderer::XPrimitive2DRenderer_getImplementationName(), + drawinglayer::unorenderer::XPrimitive2DRenderer_createInstance, + drawinglayer::unorenderer::XPrimitive2DRenderer_getSupportedServiceNames()); + } + + if(xFactory.is()) + { + xFactory->acquire(); + pRet = xFactory.get(); + } + + return pRet; + } +} + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/drawinglayer/source/drawinglayeruno/xprimitive2drenderer.cxx b/drawinglayer/source/drawinglayeruno/xprimitive2drenderer.cxx new file mode 100644 index 000000000000..c6667ad2319f --- /dev/null +++ b/drawinglayer/source/drawinglayeruno/xprimitive2drenderer.cxx @@ -0,0 +1,223 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http:\\www.apache.org\licenses\LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_drawinglayer.hxx" + +#include <com/sun/star/graphic/XPrimitive2DRenderer.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <cppuhelper/implbase2.hxx> +#include <com/sun/star/xml/sax/XParser.hpp> +#include <com/sun/star/xml/sax/InputSource.hpp> +#include <comphelper/processfactory.hxx> +#include <drawinglayer/geometry/viewinformation2d.hxx> +#include <basegfx/numeric/ftools.hxx> +#include <vcl/bitmapex.hxx> +#include <drawinglayer/tools/converters.hxx> +#include <vcl/canvastools.hxx> +#include <com/sun/star/geometry/RealRectangle2D.hpp> +#include <basegfx/matrix/b2dhommatrixtools.hxx> +#include <drawinglayer/primitive2d/transformprimitive2d.hxx> + +////////////////////////////////////////////////////////////////////////////// + +using namespace ::com::sun::star; + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace unorenderer + { + class XPrimitive2DRenderer : public ::cppu::WeakAggImplHelper2< graphic::XPrimitive2DRenderer, lang::XServiceInfo > + { + private: + XPrimitive2DRenderer(const XPrimitive2DRenderer&); + XPrimitive2DRenderer& operator=(const XPrimitive2DRenderer&); + + protected: + public: + XPrimitive2DRenderer(); + virtual ~XPrimitive2DRenderer(); + + // XPrimitive2DRenderer + virtual uno::Reference< rendering::XBitmap > SAL_CALL rasterize( + const uno::Sequence< uno::Reference< graphic::XPrimitive2D > >& Primitive2DSequence, + const uno::Sequence< beans::PropertyValue >& aViewInformationSequence, + ::sal_uInt32 DPI_X, + ::sal_uInt32 DPI_Y, + const ::com::sun::star::geometry::RealRectangle2D& Range, + ::sal_uInt32 MaximumQuadraticPixels) throw (uno::RuntimeException); + + // XServiceInfo + virtual rtl::OUString SAL_CALL getImplementationName() throw(uno::RuntimeException); + virtual ::sal_Bool SAL_CALL supportsService(const rtl::OUString&) throw(uno::RuntimeException); + virtual uno::Sequence< rtl::OUString > SAL_CALL getSupportedServiceNames() throw(uno::RuntimeException); + }; + } // end of namespace unorenderer +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// +// uno functions + +namespace drawinglayer +{ + namespace unorenderer + { + uno::Sequence< rtl::OUString > XPrimitive2DRenderer_getSupportedServiceNames() + { + static rtl::OUString aServiceName(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.graphic.Primitive2DTools" ) ); + static uno::Sequence< rtl::OUString > aServiceNames( &aServiceName, 1 ); + + return( aServiceNames ); + } + + rtl::OUString XPrimitive2DRenderer_getImplementationName() + { + return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "drawinglayer::unorenderer::XPrimitive2DRenderer" ) ); + } + + uno::Reference< uno::XInterface > SAL_CALL XPrimitive2DRenderer_createInstance(const uno::Reference< lang::XMultiServiceFactory >&) + { + return static_cast< ::cppu::OWeakObject* >(new XPrimitive2DRenderer); + } + } // end of namespace unorenderer +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace unorenderer + { + XPrimitive2DRenderer::XPrimitive2DRenderer() + { + } + + XPrimitive2DRenderer::~XPrimitive2DRenderer() + { + } + + uno::Reference< rendering::XBitmap > XPrimitive2DRenderer::rasterize( + const uno::Sequence< uno::Reference< graphic::XPrimitive2D > >& Primitive2DSequence, + const uno::Sequence< beans::PropertyValue >& aViewInformationSequence, + ::sal_uInt32 DPI_X, + ::sal_uInt32 DPI_Y, + const ::com::sun::star::geometry::RealRectangle2D& Range, + ::sal_uInt32 MaximumQuadraticPixels) throw (uno::RuntimeException) + { + uno::Reference< rendering::XBitmap > XBitmap; + + if(Primitive2DSequence.hasElements()) + { + const basegfx::B2DRange aRange(Range.X1, Range.Y1, Range.X2, Range.Y2); + const double fWidth(aRange.getWidth()); + const double fHeight(aRange.getHeight()); + + if(basegfx::fTools::more(fWidth, 0.0) && basegfx::fTools::more(fHeight, 0.0)) + { + if(0 == DPI_X) + { + DPI_X = 75; + } + + if(0 == DPI_Y) + { + DPI_Y = 75; + } + + if(0 == MaximumQuadraticPixels) + { + MaximumQuadraticPixels = 500000; + } + + const geometry::ViewInformation2D aViewInformation2D(aViewInformationSequence); + const double fFactor100th_mmToInch(2.54/1000.0); + const sal_uInt32 nDiscreteWidth(basegfx::fround((fWidth * fFactor100th_mmToInch) * DPI_X)); + const sal_uInt32 nDiscreteHeight(basegfx::fround((fHeight * fFactor100th_mmToInch) * DPI_Y)); + + basegfx::B2DHomMatrix aEmbedding( + basegfx::tools::createTranslateB2DHomMatrix( + -aRange.getMinX(), + -aRange.getMinY())); + + aEmbedding.scale( + nDiscreteWidth / fWidth, + nDiscreteHeight / fHeight); + + const primitive2d::Primitive2DReference xEmbedRef( + new primitive2d::TransformPrimitive2D( + aEmbedding, + Primitive2DSequence)); + const primitive2d::Primitive2DSequence xEmbedSeq(&xEmbedRef, 1); + + BitmapEx aBitmapEx( + tools::convertToBitmapEx( + xEmbedSeq, + aViewInformation2D, + nDiscreteWidth, + nDiscreteHeight, + MaximumQuadraticPixels)); + + if(!aBitmapEx.IsEmpty()) + { + const uno::Reference< rendering::XGraphicDevice > xGraphicDevice; + + aBitmapEx.SetPrefMapMode(MapMode(MAP_100TH_MM)); + aBitmapEx.SetPrefSize(Size(basegfx::fround(fWidth), basegfx::fround(fHeight))); + XBitmap = vcl::unotools::xBitmapFromBitmapEx(xGraphicDevice, aBitmapEx); + } + } + } + + return XBitmap; + } + + rtl::OUString SAL_CALL XPrimitive2DRenderer::getImplementationName() throw(uno::RuntimeException) + { + return(XPrimitive2DRenderer_getImplementationName()); + } + + sal_Bool SAL_CALL XPrimitive2DRenderer::supportsService(const rtl::OUString& rServiceName) throw(uno::RuntimeException) + { + const uno::Sequence< rtl::OUString > aServices(XPrimitive2DRenderer_getSupportedServiceNames()); + + for(sal_Int32 nService(0); nService < aServices.getLength(); nService++) + { + if(rServiceName == aServices[nService]) + { + return sal_True; + } + } + + return sal_False; + } + + uno::Sequence< rtl::OUString > SAL_CALL XPrimitive2DRenderer::getSupportedServiceNames() throw(uno::RuntimeException) + { + return XPrimitive2DRenderer_getSupportedServiceNames(); + } + + } // end of namespace unorenderer +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/drawinglayer/source/primitive2d/baseprimitive2d.cxx b/drawinglayer/source/primitive2d/baseprimitive2d.cxx index 8f5d7b14a157..868305b45208 100644 --- a/drawinglayer/source/primitive2d/baseprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/baseprimitive2d.cxx @@ -115,6 +115,27 @@ namespace drawinglayer { namespace primitive2d { + // convert helper stl vector of primitives to Primitive2DSequence + Primitive2DSequence Primitive2DVectorToPrimitive2DSequence(const Primitive2DVector& rSource, bool bInvert) + { + const sal_uInt32 nSize(rSource.size()); + Primitive2DSequence aRetval; + + aRetval.realloc(nSize); + + for(sal_uInt32 a(0); a < nSize; a++) + { + aRetval[bInvert ? nSize - 1 - a : a] = rSource[a]; + } + + // all entries taken over to Uno References as owners. To avoid + // errors with users of this mechanism to delete pointers to BasePrimitive2D + // itself, clear given vector + const_cast< Primitive2DVector& >(rSource).clear(); + + return aRetval; + } + // get B2DRange from a given Primitive2DReference basegfx::B2DRange getB2DRangeFromPrimitive2DReference(const Primitive2DReference& rCandidate, const geometry::ViewInformation2D& aViewInformation) { diff --git a/drawinglayer/source/primitive2d/cropprimitive2d.cxx b/drawinglayer/source/primitive2d/cropprimitive2d.cxx new file mode 100644 index 000000000000..f4b6e82b9df0 --- /dev/null +++ b/drawinglayer/source/primitive2d/cropprimitive2d.cxx @@ -0,0 +1,202 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_drawinglayer.hxx" + +#include <drawinglayer/primitive2d/cropprimitive2d.hxx> +#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx> +#include <basegfx/matrix/b2dhommatrix.hxx> +#include <basegfx/matrix/b2dhommatrixtools.hxx> +#include <drawinglayer/primitive2d/transformprimitive2d.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> +#include <basegfx/polygon/b2dpolygontools.hxx> +#include <drawinglayer/primitive2d/maskprimitive2d.hxx> + +////////////////////////////////////////////////////////////////////////////// + +using namespace com::sun::star; + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace primitive2d + { + CropPrimitive2D::CropPrimitive2D( + const Primitive2DSequence& rChildren, + const basegfx::B2DHomMatrix& rTransformation, + double fCropLeft, + double fCropTop, + double fCropRight, + double fCropBottom) + : GroupPrimitive2D(rChildren), + maTransformation(rTransformation), + mfCropLeft(fCropLeft), + mfCropTop(fCropTop), + mfCropRight(fCropRight), + mfCropBottom(fCropBottom) + { + } + + bool CropPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const + { + if(GroupPrimitive2D::operator==(rPrimitive)) + { + const CropPrimitive2D& rCompare = static_cast< const CropPrimitive2D& >(rPrimitive); + + return (getTransformation() == rCompare.getTransformation() + && getCropLeft() == rCompare.getCropLeft() + && getCropTop() == rCompare.getCropTop() + && getCropRight() == rCompare.getCropRight() + && getCropBottom() == rCompare.getCropBottom()); + } + + return false; + } + + Primitive2DSequence CropPrimitive2D::get2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const + { + Primitive2DSequence xRetval; + + if(getChildren().hasElements()) + { + // decompose to have current translate and scale + basegfx::B2DVector aScale, aTranslate; + double fRotate, fShearX; + + getTransformation().decompose(aScale, aTranslate, fRotate, fShearX); + + // detect 180 degree rotation, this is the same as mirrored in X and Y, + // thus change to mirroring. Prefer mirroring here. Use the equal call + // with getSmallValue here, the original which uses rtl::math::approxEqual + // is too correct here. Maybe this changes with enhanced precision in aw080 + // to the better so that this can be reduced to the more precise call again + if(basegfx::fTools::equal(fRotate, F_PI, 0.000000001)) + { + aScale.setX(aScale.getX() * -1.0); + aScale.setY(aScale.getY() * -1.0); + fRotate = 0.0; + } + + // create target translate and scale + const bool bMirroredX(aScale.getX() < 0.0); + const bool bMirroredY(aScale.getY() < 0.0); + basegfx::B2DVector aTargetScale(aScale); + basegfx::B2DVector aTargetTranslate(aTranslate); + + if(bMirroredX) + { + aTargetTranslate.setX(aTargetTranslate.getX() + getCropRight()); + aTargetScale.setX(aTargetScale.getX() - getCropLeft() - getCropRight()); + } + else + { + aTargetTranslate.setX(aTargetTranslate.getX() - getCropLeft()); + aTargetScale.setX(aTargetScale.getX() + getCropRight() + getCropLeft()); + } + + if(bMirroredY) + { + aTargetTranslate.setY(aTargetTranslate.getY() + getCropBottom()); + aTargetScale.setY(aTargetScale.getY() - getCropTop() - getCropBottom()); + } + else + { + aTargetTranslate.setY(aTargetTranslate.getY() - getCropTop()); + aTargetScale.setY(aTargetScale.getY() + getCropBottom() + getCropTop()); + } + + // create ranges to make comparisons + const basegfx::B2DRange aCurrent( + aTranslate.getX(), aTranslate.getY(), + aTranslate.getX() + aScale.getX(), aTranslate.getY() + aScale.getY()); + const basegfx::B2DRange aCropped( + aTargetTranslate.getX(), aTargetTranslate.getY(), + aTargetTranslate.getX() + aTargetScale.getX(), aTargetTranslate.getY() + aTargetScale.getY()); + + if(aCropped.isEmpty()) + { + // nothing to return since cropped content is completely empty + } + else if(aCurrent.equal(aCropped)) + { + // no crop, just use content + xRetval = getChildren(); + } + else + { + // build new combined content transformation + basegfx::B2DHomMatrix aNewObjectTransform(getTransformation()); + + // remove content transform by inverting + aNewObjectTransform.invert(); + + // add target values and original shear/rotate + aNewObjectTransform = basegfx::tools::createScaleShearXRotateTranslateB2DHomMatrix( + aTargetScale.getX(), + aTargetScale.getY(), + fShearX, + fRotate, + aTargetTranslate.getX(), + aTargetTranslate.getY()) + * aNewObjectTransform; + + // prepare TransformPrimitive2D with xPrimitive + const Primitive2DReference xTransformPrimitive( + new TransformPrimitive2D( + aNewObjectTransform, + getChildren())); + + if(aCurrent.isInside(aCropped)) + { + // crop just shrunk so that its inside content, + // no need to use a mask since not really cropped. + xRetval = Primitive2DSequence(&xTransformPrimitive, 1); + } + else + { + // mask with original object's bounds + basegfx::B2DPolyPolygon aMaskPolyPolygon(basegfx::tools::createUnitPolygon()); + aMaskPolyPolygon.transform(getTransformation()); + + // create maskPrimitive with aMaskPolyPolygon and aMaskContentVector + const Primitive2DReference xMask( + new MaskPrimitive2D( + aMaskPolyPolygon, + Primitive2DSequence(&xTransformPrimitive, 1))); + + xRetval = Primitive2DSequence(&xMask, 1); + } + } + } + + return xRetval; + } + + // provide unique ID + ImplPrimitrive2DIDBlock(CropPrimitive2D, PRIMITIVE2D_ID_CROPPRIMITIVE2D) + + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/drawinglayer/source/primitive2d/graphicprimitive2d.cxx b/drawinglayer/source/primitive2d/graphicprimitive2d.cxx index f7a3930610d1..0703f9225b45 100644 --- a/drawinglayer/source/primitive2d/graphicprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/graphicprimitive2d.cxx @@ -27,14 +27,14 @@ #include <drawinglayer/primitive2d/graphicprimitive2d.hxx> #include <drawinglayer/animation/animationtiming.hxx> #include <drawinglayer/primitive2d/bitmapprimitive2d.hxx> -#include <drawinglayer/primitive2d/rendergraphicprimitive2d.hxx> #include <drawinglayer/primitive2d/animatedprimitive2d.hxx> #include <drawinglayer/primitive2d/metafileprimitive2d.hxx> #include <drawinglayer/primitive2d/transformprimitive2d.hxx> #include <basegfx/polygon/b2dpolygon.hxx> #include <basegfx/polygon/b2dpolygontools.hxx> -#include <drawinglayer/primitive2d/maskprimitive2d.hxx> +#include <drawinglayer/primitive2d/cropprimitive2d.hxx> #include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx> +#include <drawinglayer/primitive2d/maskprimitive2d.hxx> ////////////////////////////////////////////////////////////////////////////// // helper class for animated graphics @@ -259,8 +259,8 @@ namespace drawinglayer aSuppressGraphicAttr.SetRotation(0); aSuppressGraphicAttr.SetMirrorFlags(0); - const GraphicObject& rGraphicObject = getGraphicObject(); - const Graphic aTransformedGraphic(rGraphicObject.GetTransformedGraphic(&aSuppressGraphicAttr)); + const GraphicObject& rGraphicObject = getGraphicObject(); + const Graphic aTransformedGraphic(rGraphicObject.GetTransformedGraphic(&aSuppressGraphicAttr)); switch(aTransformedGraphic.GetType()) { @@ -293,6 +293,32 @@ namespace drawinglayer xPrimitive = Primitive2DReference(new AnimatedSwitchPrimitive2D(aAnimationList, aBitmapPrimitives, false)); } } + else if(aTransformedGraphic.getSvgData().get()) + { + // embedded Svg fill, create embed transform + const basegfx::B2DRange& rSvgRange(aTransformedGraphic.getSvgData()->getRange()); + + if(basegfx::fTools::more(rSvgRange.getWidth(), 0.0) && basegfx::fTools::more(rSvgRange.getHeight(), 0.0)) + { + // translate back to origin, scale to unit coordinates + basegfx::B2DHomMatrix aEmbedSvg( + basegfx::tools::createTranslateB2DHomMatrix( + -rSvgRange.getMinX(), + -rSvgRange.getMinY())); + + aEmbedSvg.scale( + 1.0 / rSvgRange.getWidth(), + 1.0 / rSvgRange.getHeight()); + + // apply created object transformation + aEmbedSvg = aTransform * aEmbedSvg; + + // add Svg primitives embedded + xPrimitive = new TransformPrimitive2D( + aEmbedSvg, + aTransformedGraphic.getSvgData()->getPrimitive2DSequence()); + } + } else { xPrimitive = Primitive2DReference(new BitmapPrimitive2D(aTransformedGraphic.GetBitmapEx(), aTransform)); @@ -745,41 +771,31 @@ namespace drawinglayer // create MetafilePrimitive2D const GDIMetaFile& rMetafile = aTransformedGraphic.GetGDIMetaFile(); - if( aTransformedGraphic.IsRenderGraphic() ) + xPrimitive = Primitive2DReference( + new MetafilePrimitive2D( + aTransform, + rMetafile)); + + // #i100357# find out if clipping is needed for this primitive. Unfortunately, + // there exist Metafiles who's content is bigger than the proposed PrefSize set + // at them. This is an error, but we need to work around this + const Size aMetaFilePrefSize(rMetafile.GetPrefSize()); + const Size aMetaFileRealSize( + const_cast< GDIMetaFile& >(rMetafile).GetBoundRect( + *Application::GetDefaultDevice()).GetSize()); + + if(aMetaFileRealSize.getWidth() > aMetaFilePrefSize.getWidth() + || aMetaFileRealSize.getHeight() > aMetaFilePrefSize.getHeight()) { + // clipping needed. Embed to MaskPrimitive2D. Create childs and mask polygon + const primitive2d::Primitive2DSequence aChildContent(&xPrimitive, 1); + basegfx::B2DPolygon aMaskPolygon(basegfx::tools::createUnitPolygon()); + aMaskPolygon.transform(aTransform); + xPrimitive = Primitive2DReference( - new RenderGraphicPrimitive2D( - static_cast< MetaRenderGraphicAction* >(rMetafile.GetAction(0))->GetRenderGraphic(), - aTransform)); - } - else - { - xPrimitive = Primitive2DReference( - new MetafilePrimitive2D( - aTransform, - rMetafile)); - - // #i100357# find out if clipping is needed for this primitive. Unfortunately, - // there exist Metafiles who's content is bigger than the proposed PrefSize set - // at them. This is an error, but we need to work around this - const Size aMetaFilePrefSize(rMetafile.GetPrefSize()); - const Size aMetaFileRealSize( - const_cast< GDIMetaFile& >(rMetafile).GetBoundRect( - *Application::GetDefaultDevice()).GetSize()); - - if(aMetaFileRealSize.getWidth() > aMetaFilePrefSize.getWidth() - || aMetaFileRealSize.getHeight() > aMetaFilePrefSize.getHeight()) - { - // clipping needed. Embed to MaskPrimitive2D. Create childs and mask polygon - const primitive2d::Primitive2DSequence aChildContent(&xPrimitive, 1); - basegfx::B2DPolygon aMaskPolygon(basegfx::tools::createUnitPolygon()); - aMaskPolygon.transform(aTransform); - - xPrimitive = Primitive2DReference( - new MaskPrimitive2D( - basegfx::B2DPolyPolygon(aMaskPolygon), - aChildContent)); - } + new MaskPrimitive2D( + basegfx::B2DPolyPolygon(aMaskPolygon), + aChildContent)); } #ifdef USE_DEBUG_CODE_TO_TEST_METAFILE_DECOMPOSE } @@ -800,16 +816,6 @@ namespace drawinglayer // check for cropping if(getGraphicAttr().IsCropped()) { - // decompose to get current pos and size - basegfx::B2DVector aScale, aTranslate; - double fRotate, fShearX; - getTransform().decompose(aScale, aTranslate, fRotate, fShearX); - - // create ranges. The current object range is just scale and translate - const basegfx::B2DRange aCurrent( - aTranslate.getX(), aTranslate.getY(), - aTranslate.getX() + aScale.getX(), aTranslate.getY() + aScale.getY()); - // calculate scalings between real image size and logic object size. This // is necessary since the crop values are relative to original bitmap size double fFactorX(1.0); @@ -831,68 +837,31 @@ namespace drawinglayer const double fDivX(aBitmapSize.Width() - getGraphicAttr().GetLeftCrop() - getGraphicAttr().GetRightCrop()); const double fDivY(aBitmapSize.Height() - getGraphicAttr().GetTopCrop() - getGraphicAttr().GetBottomCrop()); + const basegfx::B2DVector aScale(aTransform * basegfx::B2DVector(1.0, 1.0)); if(!basegfx::fTools::equalZero(fDivX)) { - fFactorX = aScale.getX() / fDivX; + fFactorX = fabs(aScale.getX()) / fDivX; } if(!basegfx::fTools::equalZero(fDivY)) { - fFactorY = aScale.getY() / fDivY; + fFactorY = fabs(aScale.getY()) / fDivY; } } - // Create cropped range, describes the bounds of the original graphic - basegfx::B2DRange aCropped; - aCropped.expand(aCurrent.getMinimum() - basegfx::B2DPoint(getGraphicAttr().GetLeftCrop() * fFactorX, getGraphicAttr().GetTopCrop() * fFactorY)); - aCropped.expand(aCurrent.getMaximum() + basegfx::B2DPoint(getGraphicAttr().GetRightCrop() * fFactorX, getGraphicAttr().GetBottomCrop() * fFactorY)); - - if(aCropped.isEmpty()) - { - // nothing to add since cropped bitmap is completely empty - // xPrimitive will not be used - } - else - { - // build new object transformation for transform primitive which contains xPrimitive - basegfx::B2DHomMatrix aNewObjectTransform(getTransform()); - aNewObjectTransform.invert(); - aNewObjectTransform = basegfx::tools::createScaleTranslateB2DHomMatrix( - aCropped.getWidth(), aCropped.getHeight(), - aCropped.getMinX() - aCurrent.getMinX(), aCropped.getMinY() - aCurrent.getMinY()) - * aNewObjectTransform; - - // add shear, rotate and translate using combined matrix to speedup - const basegfx::B2DHomMatrix aCombinedMatrix(basegfx::tools::createShearXRotateTranslateB2DHomMatrix( - fShearX, fRotate, aTranslate.getX(), aTranslate.getY())); - aNewObjectTransform = aCombinedMatrix * aNewObjectTransform; - - // prepare TransformPrimitive2D with xPrimitive - const Primitive2DReference xTransformPrimitive(new TransformPrimitive2D(aNewObjectTransform, Primitive2DSequence(&xPrimitive, 1L))); - - if(aCurrent.isInside(aCropped)) - { - // cropped just got smaller, no need to really use a mask. Add to destination directly - appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, xTransformPrimitive); - } - else - { - // cropped got bigger, mask it with original object's bounds - basegfx::B2DPolyPolygon aMaskPolyPolygon(basegfx::tools::createUnitPolygon()); - aMaskPolyPolygon.transform(getTransform()); - - // create maskPrimitive with aMaskPolyPolygon and aMaskContentVector - const Primitive2DReference xRefB(new MaskPrimitive2D(aMaskPolyPolygon, Primitive2DSequence(&xTransformPrimitive, 1L))); - appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, xRefB); - } - } - } - else - { - // add to decomposition - appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, xPrimitive); + // embed content in cropPrimitive + xPrimitive = new CropPrimitive2D( + Primitive2DSequence(&xPrimitive, 1), + aTransform, + getGraphicAttr().GetLeftCrop() * fFactorX, + getGraphicAttr().GetTopCrop() * fFactorY, + getGraphicAttr().GetRightCrop() * fFactorX, + getGraphicAttr().GetBottomCrop() * fFactorY); } + + // add to decomposition + appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, xPrimitive); } } diff --git a/drawinglayer/source/primitive2d/metafileprimitive2d.cxx b/drawinglayer/source/primitive2d/metafileprimitive2d.cxx index 4d11fe523754..a3eff771d4da 100644 --- a/drawinglayer/source/primitive2d/metafileprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/metafileprimitive2d.cxx @@ -59,7 +59,6 @@ #include <drawinglayer/primitive2d/textlineprimitive2d.hxx> #include <drawinglayer/primitive2d/textstrikeoutprimitive2d.hxx> #include <drawinglayer/primitive2d/epsprimitive2d.hxx> -#include <drawinglayer/primitive2d/rendergraphicprimitive2d.hxx> #include <numeric> ////////////////////////////////////////////////////////////////////////////// @@ -3065,33 +3064,6 @@ namespace break; } - case META_RENDERGRAPHIC_ACTION : - { - const MetaRenderGraphicAction* pA = (const MetaRenderGraphicAction*)pAction; - const Rectangle aRectangle(pA->GetPoint(), pA->GetSize()); - - if(!aRectangle.IsEmpty()) - { - // create object transform - basegfx::B2DHomMatrix aObjectTransform; - - aObjectTransform.set(0, 0, aRectangle.GetWidth()); - aObjectTransform.set(1, 1, aRectangle.GetHeight()); - aObjectTransform.set(0, 2, aRectangle.Left()); - aObjectTransform.set(1, 2, aRectangle.Top()); - - // add current transformation - aObjectTransform = rPropertyHolders.Current().getTransformation() * aObjectTransform; - - // embed using EpsPrimitive - rTargetHolders.Current().append( - new drawinglayer::primitive2d::RenderGraphicPrimitive2D( - pA->GetRenderGraphic(), - aObjectTransform ) ); - } - - break; - } case META_COMMENT_ACTION : { /** CHECKED, WORKS WELL */ diff --git a/drawinglayer/source/primitive2d/patternfillprimitive2d.cxx b/drawinglayer/source/primitive2d/patternfillprimitive2d.cxx new file mode 100644 index 000000000000..3c334d2770c9 --- /dev/null +++ b/drawinglayer/source/primitive2d/patternfillprimitive2d.cxx @@ -0,0 +1,158 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + + + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_drawinglayer.hxx" + +#include <drawinglayer/primitive2d/patternfillprimitive2d.hxx> +#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx> +#include <drawinglayer/primitive2d/transformprimitive2d.hxx> +#include <drawinglayer/primitive2d/polygonprimitive2d.hxx> +#include <basegfx/polygon/b2dpolygontools.hxx> +#include <basegfx/matrix/b2dhommatrixtools.hxx> +#include <drawinglayer/texture/texture.hxx> +#include <drawinglayer/primitive2d/maskprimitive2d.hxx> + +////////////////////////////////////////////////////////////////////////////// + +using namespace com::sun::star; + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace primitive2d + { + Primitive2DSequence PatternFillPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const + { + Primitive2DSequence aRetval; + + if(getChildren().hasElements()) + { + if(!getReferenceRange().isEmpty() && getReferenceRange().getWidth() > 0.0 && getReferenceRange().getHeight() > 0.0) + { + const basegfx::B2DRange aMaskRange(getMask().getB2DRange()); + + if(!aMaskRange.isEmpty() && aMaskRange.getWidth() > 0.0 && aMaskRange.getHeight() > 0.0) + { + // create tiling matrices + ::std::vector< basegfx::B2DHomMatrix > aMatrices; + texture::GeoTexSvxTiled aTiling(getReferenceRange().getMinimum(), getReferenceRange().getRange()); + aTiling.appendTransformations(aMatrices); + + // check if content needs to be clipped + const basegfx::B2DRange aUnitRange(0.0, 0.0, 1.0, 1.0); + const basegfx::B2DRange aContentRange(getB2DRangeFromPrimitive2DSequence(getChildren(), rViewInformation)); + Primitive2DSequence aContent(getChildren()); + + if(!aUnitRange.isInside(aContentRange)) + { + const Primitive2DReference xRef( + new MaskPrimitive2D( + basegfx::B2DPolyPolygon(basegfx::tools::createPolygonFromRect(aUnitRange)), + aContent)); + + aContent = Primitive2DSequence(&xRef, 1); + } + + // resize result + aRetval.realloc(aMatrices.size()); + + // create one primitive for each matrix + for(sal_uInt32 a(0); a < aMatrices.size(); a++) + { + aRetval[a] = new TransformPrimitive2D( + aMatrices[a], + aContent); + } + + // transform result which is in unit coordinates to mask's object coordiantes + { + const basegfx::B2DHomMatrix aMaskTransform( + basegfx::tools::createScaleTranslateB2DHomMatrix( + aMaskRange.getRange(), + aMaskRange.getMinimum())); + + const Primitive2DReference xRef( + new TransformPrimitive2D( + aMaskTransform, + aRetval)); + + aRetval = Primitive2DSequence(&xRef, 1); + } + + // embed result in mask + { + const Primitive2DReference xRef( + new MaskPrimitive2D( + getMask(), + aRetval)); + + aRetval = Primitive2DSequence(&xRef, 1); + } + + } + } + } + + return aRetval; + } + + PatternFillPrimitive2D::PatternFillPrimitive2D( + const basegfx::B2DPolyPolygon& rMask, + const Primitive2DSequence& rChildren, + const basegfx::B2DRange& rReferenceRange) + : BufferedDecompositionPrimitive2D(), + maMask(rMask), + maChildren(rChildren), + maReferenceRange(rReferenceRange) + { + } + + bool PatternFillPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const + { + if(BufferedDecompositionPrimitive2D::operator==(rPrimitive)) + { + const PatternFillPrimitive2D& rCompare = static_cast< const PatternFillPrimitive2D& >(rPrimitive); + + return (getMask() == rCompare.getMask() + && getChildren() == rCompare.getChildren() + && getReferenceRange() == rCompare.getReferenceRange()); + } + + return false; + } + + basegfx::B2DRange PatternFillPrimitive2D::getB2DRange(const geometry::ViewInformation2D& rViewInformation) const + { + return getMask().getB2DRange(); + } + + // provide unique ID + ImplPrimitrive2DIDBlock(PatternFillPrimitive2D, PRIMITIVE2D_ID_PATTERNFILLPRIMITIVE2D) + + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/drawinglayer/source/primitive2d/rendergraphicprimitive2d.cxx b/drawinglayer/source/primitive2d/rendergraphicprimitive2d.cxx deleted file mode 100644 index 439937f5d0f5..000000000000 --- a/drawinglayer/source/primitive2d/rendergraphicprimitive2d.cxx +++ /dev/null @@ -1,92 +0,0 @@ -/************************************************************************* - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright 2000, 2010 Oracle and/or its affiliates. - * - * OpenOffice.org - a multi-platform office productivity suite - * - * This file is part of OpenOffice.org. - * - * OpenOffice.org is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 3 - * only, as published by the Free Software Foundation. - * - * OpenOffice.org 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 Lesser General Public License version 3 for more details - * (a copy is included in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU Lesser General Public License - * version 3 along with OpenOffice.org. If not, see - * <http://www.openoffice.org/license.html> - * for a copy of the LGPLv3 License. - * - ************************************************************************/ - -// MARKER(update_precomp.py): autogen include statement, do not remove -#include "precompiled_drawinglayer.hxx" - -#include <drawinglayer/primitive2d/rendergraphicprimitive2d.hxx> -#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx> -#include <basegfx/tools/canvastools.hxx> -#include <vcl/rendergraphicrasterizer.hxx> - -////////////////////////////////////////////////////////////////////////////// - -using namespace com::sun::star; - -////////////////////////////////////////////////////////////////////////////// - -namespace drawinglayer -{ - namespace primitive2d - { - RenderGraphicPrimitive2D::RenderGraphicPrimitive2D( - const vcl::RenderGraphic& rRenderGraphic, - const basegfx::B2DHomMatrix& rTransform) - : BasePrimitive2D(), - maRenderGraphic(rRenderGraphic), - maTransform(rTransform) - { - } - - void RenderGraphicPrimitive2D::setCurrentRasterizer() const - { - mapCurrentRasterizer.reset(); - } - - void RenderGraphicPrimitive2D::setCurrentRasterizer( const vcl::RenderGraphicRasterizer& rCurrentRasterizer ) const - { - mapCurrentRasterizer.reset( new vcl::RenderGraphicRasterizer( rCurrentRasterizer ) ); - } - - bool RenderGraphicPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const - { - if(BasePrimitive2D::operator==(rPrimitive)) - { - const RenderGraphicPrimitive2D& rCompare = (RenderGraphicPrimitive2D&)rPrimitive; - - return (getRenderGraphic() == rCompare.getRenderGraphic() - && getTransform() == rCompare.getTransform()); - } - - return false; - } - - basegfx::B2DRange RenderGraphicPrimitive2D::getB2DRange(const geometry::ViewInformation2D& /*rViewInformation*/) const - { - basegfx::B2DRange aRetval(0.0, 0.0, 1.0, 1.0); - aRetval.transform(maTransform); - return aRetval; - } - - // provide unique ID - ImplPrimitrive2DIDBlock(RenderGraphicPrimitive2D, PRIMITIVE2D_ID_RENDERGRAPHICPRIMITIVE2D) - - } // end of namespace primitive2d -} // end of namespace drawinglayer - -////////////////////////////////////////////////////////////////////////////// -// eof diff --git a/drawinglayer/source/primitive2d/svggradientprimitive2d.cxx b/drawinglayer/source/primitive2d/svggradientprimitive2d.cxx new file mode 100644 index 000000000000..199fc3d3fb03 --- /dev/null +++ b/drawinglayer/source/primitive2d/svggradientprimitive2d.cxx @@ -0,0 +1,1249 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http:\\www.apache.org\licenses\LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_drawinglayer.hxx" + +#include <drawinglayer/primitive2d/svggradientprimitive2d.hxx> +#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx> +#include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx> +#include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx> +#include <drawinglayer/primitive2d/polygonprimitive2d.hxx> +#include <basegfx/matrix/b2dhommatrixtools.hxx> +#include <basegfx/polygon/b2dpolygontools.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> +#include <drawinglayer/primitive2d/transparenceprimitive2d.hxx> +#include <drawinglayer/primitive2d/transformprimitive2d.hxx> +#include <drawinglayer/primitive2d/maskprimitive2d.hxx> +#include <drawinglayer/geometry/viewinformation2d.hxx> + +////////////////////////////////////////////////////////////////////////////// + +using namespace com::sun::star; + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace primitive2d + { + Primitive2DSequence SvgGradientHelper::createSingleGradientEntryFill() const + { + const SvgGradientEntryVector& rEntries = getGradientEntries(); + const sal_uInt32 nCount(rEntries.size()); + Primitive2DSequence xRetval; + + if(nCount) + { + const SvgGradientEntry& rSingleEntry = rEntries[nCount - 1]; + const double fOpacity(rSingleEntry.getOpacity()); + + if(fOpacity > 0.0) + { + Primitive2DReference xRef( + new PolyPolygonColorPrimitive2D( + getPolyPolygon(), + rSingleEntry.getColor())); + + if(fOpacity < 1.0) + { + const Primitive2DSequence aContent(&xRef, 1); + + xRef = Primitive2DReference( + new UnifiedTransparencePrimitive2D( + aContent, + 1.0 - fOpacity)); + } + + xRetval = Primitive2DSequence(&xRef, 1); + } + } + else + { + OSL_ENSURE(false, "Single gradient entry construction without entry (!)"); + } + + return xRetval; + } + + void SvgGradientHelper::checkPreconditions() + { + mbPreconditionsChecked = true; + const SvgGradientEntryVector& rEntries = getGradientEntries(); + + if(rEntries.empty()) + { + // no fill at all + } + else + { + const sal_uInt32 nCount(rEntries.size()); + + if(1 == nCount) + { + // fill with single existing color + setSingleEntry(); + } + else + { + // sort maGradientEntries when more than one + std::sort(maGradientEntries.begin(), maGradientEntries.end()); + + // gradient with at least two colors + bool bAllInvisible(true); + + for(sal_uInt32 a(0); a < nCount; a++) + { + const SvgGradientEntry& rCandidate = rEntries[a]; + + if(basegfx::fTools::equalZero(rCandidate.getOpacity())) + { + // invisible + mbFullyOpaque = false; + } + else if(basegfx::fTools::equal(rCandidate.getOpacity(), 1.0)) + { + // completely opaque + bAllInvisible = false; + } + else + { + // opacity + bAllInvisible = false; + mbFullyOpaque = false; + } + } + + if(bAllInvisible) + { + // all invisible, nothing to do + } + else + { + const basegfx::B2DRange aPolyRange(getPolyPolygon().getB2DRange()); + + if(aPolyRange.isEmpty()) + { + // no range to fill, nothing to do + } + else + { + const double fPolyWidth(aPolyRange.getWidth()); + const double fPolyHeight(aPolyRange.getHeight()); + + if(basegfx::fTools::equalZero(fPolyWidth) || basegfx::fTools::equalZero(fPolyHeight)) + { + // no width/height to fill, nothing to do + } + else + { + mbCreatesContent = true; + } + } + } + } + } + } + + double SvgGradientHelper::createRun( + Primitive2DVector& rTargetColor, + Primitive2DVector& rTargetOpacity, + double fPos, + double fMax, + const SvgGradientEntryVector& rEntries, + sal_Int32 nOffset) const + { + const sal_uInt32 nCount(rEntries.size()); + + if(nCount) + { + const SvgGradientEntry& rStart = rEntries[0]; + const bool bCreateStartPad(fPos < 0.0 && Spread_pad == getSpreadMethod()); + const bool bCreateStartFill(rStart.getOffset() > 0.0); + sal_uInt32 nIndex(0); + + if(bCreateStartPad || bCreateStartFill) + { + const SvgGradientEntry aTemp(bCreateStartPad ? fPos : 0.0, rStart.getColor(), rStart.getOpacity()); + + createAtom(rTargetColor, rTargetOpacity, aTemp, rStart, nOffset); + fPos = rStart.getOffset(); + } + + while(fPos < 1.0 && nIndex + 1 < nCount) + { + const SvgGradientEntry& rCandidateA = rEntries[nIndex++]; + const SvgGradientEntry& rCandidateB = rEntries[nIndex]; + + createAtom(rTargetColor, rTargetOpacity, rCandidateA, rCandidateB, nOffset); + fPos = rCandidateB.getOffset(); + } + + const SvgGradientEntry& rEnd = rEntries[nCount - 1]; + const bool bCreateEndPad(fPos < fMax && Spread_pad == getSpreadMethod()); + const bool bCreateEndFill(rEnd.getOffset() < 1.0); + + if(bCreateEndPad || bCreateEndFill) + { + fPos = bCreateEndPad ? fMax : 1.0; + const SvgGradientEntry aTemp(fPos, rEnd.getColor(), rEnd.getOpacity()); + + createAtom(rTargetColor, rTargetOpacity, rEnd, aTemp, nOffset); + } + } + else + { + OSL_ENSURE(false, "GradientAtom creation without ColorStops (!)"); + fPos = fMax; + } + + return fPos; + } + + Primitive2DSequence SvgGradientHelper::createResult( + const Primitive2DVector& rTargetColor, + const Primitive2DVector& rTargetOpacity, + const basegfx::B2DHomMatrix& rUnitGradientToObject, + bool bInvert) const + { + Primitive2DSequence xRetval; + const Primitive2DSequence aTargetColorEntries(Primitive2DVectorToPrimitive2DSequence(rTargetColor, bInvert)); + const Primitive2DSequence aTargetOpacityEntries(Primitive2DVectorToPrimitive2DSequence(rTargetOpacity, bInvert)); + + if(aTargetColorEntries.hasElements()) + { + Primitive2DReference xRefContent; + + if(aTargetOpacityEntries.hasElements()) + { + const Primitive2DReference xRefOpacity = new TransparencePrimitive2D( + aTargetColorEntries, + aTargetOpacityEntries); + + xRefContent = new TransformPrimitive2D( + rUnitGradientToObject, + Primitive2DSequence(&xRefOpacity, 1)); + } + else + { + xRefContent = new TransformPrimitive2D( + rUnitGradientToObject, + aTargetColorEntries); + } + + xRefContent = new MaskPrimitive2D( + getPolyPolygon(), + Primitive2DSequence(&xRefContent, 1)); + + xRetval = Primitive2DSequence(&xRefContent, 1); + } + + return xRetval; + } + + SvgGradientHelper::SvgGradientHelper( + const basegfx::B2DPolyPolygon& rPolyPolygon, + const SvgGradientEntryVector& rGradientEntries, + const basegfx::B2DPoint& rStart, + SpreadMethod aSpreadMethod, + double fOverlapping) + : maPolyPolygon(rPolyPolygon), + maGradientEntries(rGradientEntries), + maStart(rStart), + maSpreadMethod(aSpreadMethod), + mfOverlapping(fOverlapping), + mbPreconditionsChecked(false), + mbCreatesContent(false), + mbSingleEntry(false), + mbFullyOpaque(true) + { + } + + bool SvgGradientHelper::operator==(const SvgGradientHelper& rSvgGradientHelper) const + { + const SvgGradientHelper& rCompare = static_cast< const SvgGradientHelper& >(rSvgGradientHelper); + + return (getPolyPolygon() == rCompare.getPolyPolygon() + && getGradientEntries() == rCompare.getGradientEntries() + && getStart() == rCompare.getStart() + && getSpreadMethod() == rCompare.getSpreadMethod() + && getOverlapping() == rCompare.getOverlapping()); + } + + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace primitive2d + { + void SvgLinearGradientPrimitive2D::checkPreconditions() + { + // call parent + SvgGradientHelper::checkPreconditions(); + + if(getCreatesContent()) + { + // Check Vector + const basegfx::B2DVector aVector(getEnd() - getStart()); + + if(basegfx::fTools::equalZero(aVector.getX()) && basegfx::fTools::equalZero(aVector.getY())) + { + // fill with single color using last stop color + setSingleEntry(); + } + } + } + + void SvgLinearGradientPrimitive2D::ensureGeometry( + basegfx::B2DPolyPolygon& rPolyPolygon, + const SvgGradientEntry& rFrom, + const SvgGradientEntry& rTo, + sal_Int32 nOffset) const + { + if(!rPolyPolygon.count()) + { + rPolyPolygon.append( + basegfx::tools::createPolygonFromRect( + basegfx::B2DRange( + rFrom.getOffset() - getOverlapping() + nOffset, + 0.0, + rTo.getOffset() + getOverlapping() + nOffset, + 1.0))); + } + } + + void SvgLinearGradientPrimitive2D::createAtom( + Primitive2DVector& rTargetColor, + Primitive2DVector& rTargetOpacity, + const SvgGradientEntry& rFrom, + const SvgGradientEntry& rTo, + sal_Int32 nOffset) const + { + // create gradient atom [rFrom.getOffset() .. rTo.getOffset()] with (rFrom.getOffset() > rTo.getOffset()) + if(rFrom.getOffset() == rTo.getOffset()) + { + OSL_ENSURE(false, "SvgGradient Atom creation with no step width (!)"); + } + else + { + const bool bColorChange(rFrom.getColor() != rTo.getColor()); + const bool bOpacityChange(rFrom.getOpacity() != rTo.getOpacity()); + basegfx::B2DPolyPolygon aPolyPolygon; + + if(bColorChange) + { + rTargetColor.push_back( + new SvgLinearAtomPrimitive2D( + rFrom.getColor(), rFrom.getOffset() + nOffset, + rTo.getColor(), rTo.getOffset() + nOffset, + getOverlapping())); + } + else + { + ensureGeometry(aPolyPolygon, rFrom, rTo, nOffset); + rTargetColor.push_back( + new PolyPolygonColorPrimitive2D( + aPolyPolygon, + rFrom.getColor())); + } + + if(bOpacityChange) + { + const double fTransFrom(1.0 - rFrom.getOpacity()); + const double fTransTo(1.0 - rTo.getOpacity()); + + rTargetOpacity.push_back( + new SvgLinearAtomPrimitive2D( + basegfx::BColor(fTransFrom, fTransFrom, fTransFrom), rFrom.getOffset() + nOffset, + basegfx::BColor(fTransTo,fTransTo, fTransTo), rTo.getOffset() + nOffset, + getOverlapping())); + } + else if(!getFullyOpaque()) + { + const double fTransparence(1.0 - rFrom.getOpacity()); + + ensureGeometry(aPolyPolygon, rFrom, rTo, nOffset); + rTargetOpacity.push_back( + new PolyPolygonColorPrimitive2D( + aPolyPolygon, + basegfx::BColor(fTransparence, fTransparence, fTransparence))); + } + } + } + + Primitive2DSequence SvgLinearGradientPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const + { + Primitive2DSequence xRetval; + + if(!getPreconditionsChecked()) + { + const_cast< SvgLinearGradientPrimitive2D* >(this)->checkPreconditions(); + } + + if(getSingleEntry()) + { + // fill with last existing color + xRetval = createSingleGradientEntryFill(); + } + else if(getCreatesContent()) + { + // at least two color stops in range [0.0 .. 1.0], sorted, non-null vector, not completely + // invisible, width and height to fill are not empty + const basegfx::B2DRange aPolyRange(getPolyPolygon().getB2DRange()); + const double fPolyWidth(aPolyRange.getWidth()); + const double fPolyHeight(aPolyRange.getHeight()); + + // create ObjectTransform based on polygon range + const basegfx::B2DHomMatrix aObjectTransform( + basegfx::tools::createScaleTranslateB2DHomMatrix( + fPolyWidth, fPolyHeight, + aPolyRange.getMinX(), aPolyRange.getMinY())); + + // create unit transform from unit vector [0.0 .. 1.0] along the X-Axis to given + // gradient vector defined by Start,End + const basegfx::B2DVector aVector(getEnd() - getStart()); + const double fVectorLength(aVector.getLength()); + basegfx::B2DHomMatrix aUnitGradientToGradient; + + aUnitGradientToGradient.scale(fVectorLength, 1.0); + aUnitGradientToGradient.rotate(atan2(aVector.getY(), aVector.getX())); + aUnitGradientToGradient.translate(getStart().getX(), getStart().getY()); + + // create full transform from unit gradient coordinates to object coordinates + // including the SvgGradient transformation + basegfx::B2DHomMatrix aUnitGradientToObject(aObjectTransform * aUnitGradientToGradient); + + // create inverse from it + basegfx::B2DHomMatrix aObjectToUnitGradient(aUnitGradientToObject); + aObjectToUnitGradient.invert(); + + // back-transform polygon to unit gradient coordinates and get + // UnitRage. This is the range the gradient has to cover + basegfx::B2DPolyPolygon aUnitPoly(getPolyPolygon()); + aUnitPoly.transform(aObjectToUnitGradient); + const basegfx::B2DRange aUnitRange(aUnitPoly.getB2DRange()); + + // prepare result vectors + Primitive2DVector aTargetColor; + Primitive2DVector aTargetOpacity; + + if(basegfx::fTools::more(aUnitRange.getWidth(), 0.0)) + { + // add a pre-multiply to aUnitGradientToObject to allow + // multiplication of the polygon(xl, 0.0, xr, 1.0) + const basegfx::B2DHomMatrix aPreMultiply( + basegfx::tools::createScaleTranslateB2DHomMatrix( + 1.0, aUnitRange.getHeight(), 0.0, aUnitRange.getMinY())); + aUnitGradientToObject = aUnitGradientToObject * aPreMultiply; + + // create central run, may also already do all necessary when + // Spread_pad is set as SpreadMethod and/or the range is smaller + double fPos(createRun(aTargetColor, aTargetOpacity, aUnitRange.getMinX(), aUnitRange.getMaxX(), getGradientEntries(), 0)); + + if(fPos < aUnitRange.getMaxX()) + { + // can only happen when SpreadMethod is Spread_reflect or Spread_repeat, + // else the start and end pads are already created and fPos == aUnitRange.getMaxX(). + // Its possible to express the repeated linear gradient by adding the + // transformed central run. Crete it this way + Primitive2DSequence aTargetColorEntries(Primitive2DVectorToPrimitive2DSequence(aTargetColor)); + Primitive2DSequence aTargetOpacityEntries(Primitive2DVectorToPrimitive2DSequence(aTargetOpacity)); + aTargetColor.clear(); + aTargetOpacity.clear(); + + if(aTargetColorEntries.hasElements()) + { + // add original central run as group primitive + aTargetColor.push_back(new GroupPrimitive2D(aTargetColorEntries)); + + if(aTargetOpacityEntries.hasElements()) + { + aTargetOpacity.push_back(new GroupPrimitive2D(aTargetOpacityEntries)); + } + + // add negative runs + fPos = 0.0; + sal_Int32 nOffset(0); + + while(fPos > aUnitRange.getMinX()) + { + fPos -= 1.0; + nOffset++; + + basegfx::B2DHomMatrix aTransform; + const bool bMirror(Spread_reflect == getSpreadMethod() && (nOffset % 2)); + + if(bMirror) + { + aTransform.scale(-1.0, 1.0); + aTransform.translate(fPos + 1.0, 0.0); + } + else + { + aTransform.translate(fPos, 0.0); + } + + aTargetColor.push_back(new TransformPrimitive2D(aTransform, aTargetColorEntries)); + + if(aTargetOpacityEntries.hasElements()) + { + aTargetOpacity.push_back(new TransformPrimitive2D(aTransform, aTargetOpacityEntries)); + } + } + + // add positive runs + fPos = 1.0; + nOffset = 1; + + while(fPos < aUnitRange.getMaxX()) + { + basegfx::B2DHomMatrix aTransform; + const bool bMirror(Spread_reflect == getSpreadMethod() && (nOffset % 2)); + + if(bMirror) + { + aTransform.scale(-1.0, 1.0); + aTransform.translate(fPos + 1.0, 0.0); + } + else + { + aTransform.translate(fPos, 0.0); + } + + aTargetColor.push_back(new TransformPrimitive2D(aTransform, aTargetColorEntries)); + + if(aTargetOpacityEntries.hasElements()) + { + aTargetOpacity.push_back(new TransformPrimitive2D(aTransform, aTargetOpacityEntries)); + } + + fPos += 1.0; + nOffset++; + } + } + } + } + + xRetval = createResult(aTargetColor, aTargetOpacity, aUnitGradientToObject); + } + + return xRetval; + } + + SvgLinearGradientPrimitive2D::SvgLinearGradientPrimitive2D( + const basegfx::B2DPolyPolygon& rPolyPolygon, + const SvgGradientEntryVector& rGradientEntries, + const basegfx::B2DPoint& rStart, + const basegfx::B2DPoint& rEnd, + SpreadMethod aSpreadMethod, + double fOverlapping) + : BufferedDecompositionPrimitive2D(), + SvgGradientHelper(rPolyPolygon, rGradientEntries, rStart, aSpreadMethod, fOverlapping), + maEnd(rEnd) + { + } + + bool SvgLinearGradientPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const + { + const SvgGradientHelper* pSvgGradientHelper = dynamic_cast< const SvgGradientHelper* >(&rPrimitive); + + if(pSvgGradientHelper && SvgGradientHelper::operator==(*pSvgGradientHelper)) + { + const SvgLinearGradientPrimitive2D& rCompare = static_cast< const SvgLinearGradientPrimitive2D& >(rPrimitive); + + return (getEnd() == rCompare.getEnd()); + } + + return false; + } + + basegfx::B2DRange SvgLinearGradientPrimitive2D::getB2DRange(const geometry::ViewInformation2D& /*rViewInformation*/) const + { + // return ObjectRange + return getPolyPolygon().getB2DRange(); + } + + // provide unique ID + ImplPrimitrive2DIDBlock(SvgLinearGradientPrimitive2D, PRIMITIVE2D_ID_SVGLINEARGRADIENTPRIMITIVE2D) + + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace primitive2d + { + void SvgRadialGradientPrimitive2D::checkPreconditions() + { + // call parent + SvgGradientHelper::checkPreconditions(); + + if(getCreatesContent()) + { + // Check Radius + if(basegfx::fTools::equalZero(getRadius())) + { + // fill with single color using last stop color + setSingleEntry(); + } + } + } + + void SvgRadialGradientPrimitive2D::ensureGeometry( + basegfx::B2DPolyPolygon& rPolyPolygon, + const SvgGradientEntry& rFrom, + const SvgGradientEntry& rTo, + sal_Int32 nOffset) const + { + if(!rPolyPolygon.count()) + { + basegfx::B2DPolygon aPolygonA(basegfx::tools::createPolygonFromUnitCircle()); + basegfx::B2DPolygon aPolygonB(basegfx::tools::createPolygonFromUnitCircle()); + double fScaleFrom(rFrom.getOffset() + nOffset); + const double fScaleTo(rTo.getOffset() + nOffset); + + if(fScaleFrom > getOverlapping()) + { + fScaleFrom -= getOverlapping(); + } + + if(isFocalSet()) + { + const basegfx::B2DVector aTranslateFrom(maFocalVector * (maFocalLength - fScaleFrom)); + const basegfx::B2DVector aTranslateTo(maFocalVector * (maFocalLength - fScaleTo)); + + aPolygonA.transform( + basegfx::tools::createScaleTranslateB2DHomMatrix( + fScaleFrom, + fScaleFrom, + aTranslateFrom.getX(), + aTranslateFrom.getY())); + aPolygonB.transform( + basegfx::tools::createScaleTranslateB2DHomMatrix( + fScaleTo, + fScaleTo, + aTranslateTo.getX(), + aTranslateTo.getY())); + } + else + { + aPolygonA.transform( + basegfx::tools::createScaleB2DHomMatrix( + fScaleFrom, + fScaleFrom)); + aPolygonB.transform( + basegfx::tools::createScaleB2DHomMatrix( + fScaleTo, + fScaleTo)); + } + + // add the outer polygon first + rPolyPolygon.append(aPolygonB); + rPolyPolygon.append(aPolygonA); + } + } + + void SvgRadialGradientPrimitive2D::createAtom( + Primitive2DVector& rTargetColor, + Primitive2DVector& rTargetOpacity, + const SvgGradientEntry& rFrom, + const SvgGradientEntry& rTo, + sal_Int32 nOffset) const + { + // create gradient atom [rFrom.getOffset() .. rTo.getOffset()] with (rFrom.getOffset() > rTo.getOffset()) + if(rFrom.getOffset() == rTo.getOffset()) + { + OSL_ENSURE(false, "SvgGradient Atom creation with no step width (!)"); + } + else + { + const bool bColorChange(rFrom.getColor() != rTo.getColor()); + const bool bOpacityChange(rFrom.getOpacity() != rTo.getOpacity()); + basegfx::B2DPolyPolygon aPolyPolygon; + + if(bColorChange) + { + const double fScaleFrom(rFrom.getOffset() + nOffset); + const double fScaleTo(rTo.getOffset() + nOffset); + + if(isFocalSet()) + { + const basegfx::B2DVector aTranslateFrom(maFocalVector * (maFocalLength - fScaleFrom)); + const basegfx::B2DVector aTranslateTo(maFocalVector * (maFocalLength - fScaleTo)); + + rTargetColor.push_back( + new SvgRadialAtomPrimitive2D( + rFrom.getColor(), fScaleFrom, aTranslateFrom, + rTo.getColor(), fScaleTo, aTranslateTo, + getOverlapping())); + } + else + { + rTargetColor.push_back( + new SvgRadialAtomPrimitive2D( + rFrom.getColor(), fScaleFrom, + rTo.getColor(), fScaleTo, + getOverlapping())); + } + } + else + { + ensureGeometry(aPolyPolygon, rFrom, rTo, nOffset); + rTargetColor.push_back( + new PolyPolygonColorPrimitive2D( + aPolyPolygon, + rFrom.getColor())); + } + + if(bOpacityChange) + { + const double fTransFrom(1.0 - rFrom.getOpacity()); + const double fTransTo(1.0 - rTo.getOpacity()); + const basegfx::BColor aColorFrom(fTransFrom, fTransFrom, fTransFrom); + const basegfx::BColor aColorTo(fTransTo, fTransTo, fTransTo); + const double fScaleFrom(rFrom.getOffset() + nOffset); + const double fScaleTo(rTo.getOffset() + nOffset); + + if(isFocalSet()) + { + const basegfx::B2DVector aTranslateFrom(maFocalVector * (maFocalLength - fScaleFrom)); + const basegfx::B2DVector aTranslateTo(maFocalVector * (maFocalLength - fScaleTo)); + + rTargetOpacity.push_back( + new SvgRadialAtomPrimitive2D( + aColorFrom, fScaleFrom, aTranslateFrom, + aColorTo, fScaleTo, aTranslateTo, + getOverlapping())); + } + else + { + rTargetOpacity.push_back( + new SvgRadialAtomPrimitive2D( + aColorFrom, fScaleFrom, + aColorTo, fScaleTo, + getOverlapping())); + } + } + else if(!getFullyOpaque()) + { + const double fTransparence(1.0 - rFrom.getOpacity()); + + ensureGeometry(aPolyPolygon, rFrom, rTo, nOffset); + rTargetOpacity.push_back( + new PolyPolygonColorPrimitive2D( + aPolyPolygon, + basegfx::BColor(fTransparence, fTransparence, fTransparence))); + } + } + } + + const SvgGradientEntryVector& SvgRadialGradientPrimitive2D::getMirroredGradientEntries() const + { + if(maMirroredGradientEntries.empty() && !getGradientEntries().empty()) + { + const_cast< SvgRadialGradientPrimitive2D* >(this)->createMirroredGradientEntries(); + } + + return maMirroredGradientEntries; + } + + void SvgRadialGradientPrimitive2D::createMirroredGradientEntries() + { + if(maMirroredGradientEntries.empty() && !getGradientEntries().empty()) + { + const sal_uInt32 nCount(getGradientEntries().size()); + maMirroredGradientEntries.clear(); + maMirroredGradientEntries.reserve(nCount); + + for(sal_uInt32 a(0); a < nCount; a++) + { + const SvgGradientEntry& rCandidate = getGradientEntries()[nCount - 1 - a]; + + maMirroredGradientEntries.push_back( + SvgGradientEntry( + 1.0 - rCandidate.getOffset(), + rCandidate.getColor(), + rCandidate.getOpacity())); + } + } + } + + Primitive2DSequence SvgRadialGradientPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const + { + Primitive2DSequence xRetval; + + if(!getPreconditionsChecked()) + { + const_cast< SvgRadialGradientPrimitive2D* >(this)->checkPreconditions(); + } + + if(getSingleEntry()) + { + // fill with last existing color + xRetval = createSingleGradientEntryFill(); + } + else if(getCreatesContent()) + { + // at least two color stops in range [0.0 .. 1.0], sorted, non-null vector, not completely + // invisible, width and height to fill are not empty + const SvgGradientEntryVector& rEntries = getGradientEntries(); + const basegfx::B2DRange aPolyRange(getPolyPolygon().getB2DRange()); + const double fPolyWidth(aPolyRange.getWidth()); + const double fPolyHeight(aPolyRange.getHeight()); + + // create ObjectTransform based on polygon range + const basegfx::B2DHomMatrix aObjectTransform( + basegfx::tools::createScaleTranslateB2DHomMatrix( + fPolyWidth, fPolyHeight, + aPolyRange.getMinX(), aPolyRange.getMinY())); + + // create unit transform from unit vector to given linear gradient vector + basegfx::B2DHomMatrix aUnitGradientToGradient; + + aUnitGradientToGradient.scale(getRadius(), getRadius()); + aUnitGradientToGradient.translate(getStart().getX(), getStart().getY()); + + // create full transform from unit gradient coordinates to object coordinates + // including the SvgGradient transformation + basegfx::B2DHomMatrix aUnitGradientToObject(aObjectTransform * aUnitGradientToGradient); + + // create inverse from it + basegfx::B2DHomMatrix aObjectToUnitGradient(aUnitGradientToObject); + aObjectToUnitGradient.invert(); + + // back-transform polygon to unit gradient coordinates and get + // UnitRage. This is the range the gradient has to cover + basegfx::B2DPolyPolygon aUnitPoly(getPolyPolygon()); + aUnitPoly.transform(aObjectToUnitGradient); + const basegfx::B2DRange aUnitRange(aUnitPoly.getB2DRange()); + + // create range which the gradient has to cover to cover the whole given geometry. + // For circle, go from 0.0 to max radius in all directions (the corners) + double fMax(basegfx::B2DVector(aUnitRange.getMinimum()).getLength()); + fMax = std::max(fMax, basegfx::B2DVector(aUnitRange.getMaximum()).getLength()); + fMax = std::max(fMax, basegfx::B2DVector(aUnitRange.getMinX(), aUnitRange.getMaxY()).getLength()); + fMax = std::max(fMax, basegfx::B2DVector(aUnitRange.getMaxX(), aUnitRange.getMinY()).getLength()); + + // prepare result vectors + Primitive2DVector aTargetColor; + Primitive2DVector aTargetOpacity; + + if(0.0 < fMax) + { + // prepare maFocalVector + if(isFocalSet()) + { + const_cast< SvgRadialGradientPrimitive2D* >(this)->maFocalLength = fMax; + } + + // create central run, may also already do all necessary when + // Spread_pad is set as SpreadMethod and/or the range is smaller + double fPos(createRun(aTargetColor, aTargetOpacity, 0.0, fMax, getGradientEntries(), 0)); + + if(fPos < fMax) + { + // can only happen when SpreadMethod is Spread_reflect or Spread_repeat, + // else the start and end pads are already created and fPos == fMax. + // For radial there is no way to transform the already created + // central run, it needs to be created from 1.0 to fMax + sal_Int32 nOffset(1); + + while(fPos < fMax) + { + const bool bMirror(Spread_reflect == getSpreadMethod() && (nOffset % 2)); + + if(bMirror) + { + createRun(aTargetColor, aTargetOpacity, 0.0, fMax, getMirroredGradientEntries(), nOffset); + } + else + { + createRun(aTargetColor, aTargetOpacity, 0.0, fMax, getGradientEntries(), nOffset); + } + + nOffset++; + fPos += 1.0; + } + } + } + + xRetval = createResult(aTargetColor, aTargetOpacity, aUnitGradientToObject, true); + } + + return xRetval; + } + + SvgRadialGradientPrimitive2D::SvgRadialGradientPrimitive2D( + const basegfx::B2DPolyPolygon& rPolyPolygon, + const SvgGradientEntryVector& rGradientEntries, + const basegfx::B2DPoint& rStart, + double fRadius, + SpreadMethod aSpreadMethod, + const basegfx::B2DPoint* pFocal, + double fOverlapping) + : BufferedDecompositionPrimitive2D(), + SvgGradientHelper(rPolyPolygon, rGradientEntries, rStart, aSpreadMethod, fOverlapping), + mfRadius(fRadius), + maFocal(rStart), + maFocalVector(0.0, 0.0), + maFocalLength(0.0), + maMirroredGradientEntries(), + mbFocalSet(false) + { + if(pFocal) + { + maFocal = *pFocal; + maFocalVector = maFocal - getStart(); + mbFocalSet = true; + } + } + + bool SvgRadialGradientPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const + { + const SvgGradientHelper* pSvgGradientHelper = dynamic_cast< const SvgGradientHelper* >(&rPrimitive); + + if(pSvgGradientHelper && SvgGradientHelper::operator==(*pSvgGradientHelper)) + { + const SvgRadialGradientPrimitive2D& rCompare = static_cast< const SvgRadialGradientPrimitive2D& >(rPrimitive); + + if(getRadius() == rCompare.getRadius()) + { + if(isFocalSet() == rCompare.isFocalSet()) + { + if(isFocalSet()) + { + return getFocal() == rCompare.getFocal(); + } + else + { + return true; + } + } + } + } + + return false; + } + + basegfx::B2DRange SvgRadialGradientPrimitive2D::getB2DRange(const geometry::ViewInformation2D& /*rViewInformation*/) const + { + // return ObjectRange + return getPolyPolygon().getB2DRange(); + } + + // provide unique ID + ImplPrimitrive2DIDBlock(SvgRadialGradientPrimitive2D, PRIMITIVE2D_ID_SVGRADIALGRADIENTPRIMITIVE2D) + + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// +// SvgLinearAtomPrimitive2D class + +namespace drawinglayer +{ + namespace primitive2d + { + Primitive2DSequence SvgLinearAtomPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const + { + Primitive2DSequence xRetval; + const double fDelta(getOffsetB() - getOffsetA()); + + if(!basegfx::fTools::equalZero(fDelta)) + { + if(getColorA() == getColorB()) + { + const basegfx::B2DPolygon aPolygon( + basegfx::tools::createPolygonFromRect( + basegfx::B2DRange( + getOffsetA() - getOverlapping(), + 0.0, + getOffsetB() + getOverlapping(), + 1.0))); + + xRetval.realloc(1); + xRetval[0] = new PolyPolygonColorPrimitive2D( + basegfx::B2DPolyPolygon(aPolygon), + getColorA()); + } + else + { + // calc discrete length to change color all 2.5 pixels + sal_uInt32 nSteps(basegfx::fround(fDelta / (getDiscreteUnit() * 2.5))); + + // use color distance, assume to do every 3rd + const double fColorDistance(getColorA().getDistance(getColorB())); + const sal_uInt32 nColorSteps(basegfx::fround(fColorDistance * (255.0 * 0.3))); + nSteps = std::min(nSteps, nColorSteps); + + // roughly cut when too big + nSteps = std::min(nSteps, sal_uInt32(100)); + nSteps = std::max(nSteps, sal_uInt32(1)); + + // preapare iteration + double fStart(0.0); + double fStep(fDelta / nSteps); + + xRetval.realloc(nSteps); + + for(sal_uInt32 a(0); a < nSteps; a++, fStart += fStep) + { + const double fLeft(getOffsetA() + fStart); + const double fRight(fLeft + fStep); + const basegfx::B2DPolygon aPolygon( + basegfx::tools::createPolygonFromRect( + basegfx::B2DRange( + fLeft - getOverlapping(), + 0.0, + fRight + getOverlapping(), + 1.0))); + + xRetval[a] = new PolyPolygonColorPrimitive2D( + basegfx::B2DPolyPolygon(aPolygon), + basegfx::interpolate(getColorA(), getColorB(), fStart/fDelta)); + } + } + } + + return xRetval; + } + + bool SvgLinearAtomPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const + { + if(DiscreteMetricDependentPrimitive2D::operator==(rPrimitive)) + { + const SvgLinearAtomPrimitive2D& rCompare = static_cast< const SvgLinearAtomPrimitive2D& >(rPrimitive); + + return (getColorA() == rCompare.getColorA() + && getColorB() == rCompare.getColorB() + && getOffsetA() == rCompare.getOffsetA() + && getOffsetB() == rCompare.getOffsetB() + && getOverlapping() == rCompare.getOverlapping()); + } + + return false; + } + + // provide unique ID + ImplPrimitrive2DIDBlock(SvgLinearAtomPrimitive2D, PRIMITIVE2D_ID_SVGLINEARATOMPRIMITIVE2D) + + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// +// SvgRadialAtomPrimitive2D class + +namespace drawinglayer +{ + namespace primitive2d + { + Primitive2DSequence SvgRadialAtomPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const + { + Primitive2DSequence xRetval; + const double fDeltaScale(getScaleB() - getScaleA()); + + if(!basegfx::fTools::equalZero(fDeltaScale)) + { + if(getColorA() == getColorB()) + { + basegfx::B2DPolygon aPolygonA(basegfx::tools::createPolygonFromUnitCircle()); + basegfx::B2DPolygon aPolygonB(basegfx::tools::createPolygonFromUnitCircle()); + double fScaleA(getScaleA()); + const double fScaleB(getScaleB()); + + if(fScaleA > getOverlapping()) + { + fScaleA -= getOverlapping(); + } + + const bool bUseA(basegfx::fTools::equalZero(fScaleA)); + + if(getTranslateSet()) + { + if(bUseA) + { + aPolygonA.transform( + basegfx::tools::createScaleTranslateB2DHomMatrix( + fScaleA, + fScaleA, + getTranslateA().getX(), + getTranslateA().getY())); + } + + aPolygonB.transform( + basegfx::tools::createScaleTranslateB2DHomMatrix( + fScaleB, + fScaleB, + getTranslateB().getX(), + getTranslateB().getY())); + } + else + { + if(bUseA) + { + aPolygonA.transform( + basegfx::tools::createScaleB2DHomMatrix( + fScaleA, + fScaleA)); + } + + aPolygonB.transform( + basegfx::tools::createScaleB2DHomMatrix( + fScaleB, + fScaleB)); + } + + basegfx::B2DPolyPolygon aPolyPolygon(aPolygonB); + + if(bUseA) + { + aPolyPolygon.append(aPolygonA); + } + + xRetval.realloc(1); + + xRetval[0] = new PolyPolygonColorPrimitive2D( + aPolyPolygon, + getColorA()); + } + else + { + // calc discrete length to change color all 2.5 pixels + sal_uInt32 nSteps(basegfx::fround(fDeltaScale / (getDiscreteUnit() * 2.5))); + + // use color distance, assume to do every 3rd + const double fColorDistance(getColorA().getDistance(getColorB())); + const sal_uInt32 nColorSteps(basegfx::fround(fColorDistance * (255.0 * 0.3))); + nSteps = std::min(nSteps, nColorSteps); + + // roughly cut when too big + nSteps = std::min(nSteps, sal_uInt32(100)); + nSteps = std::max(nSteps, sal_uInt32(1)); + + // preapare iteration + double fStartScale(0.0); + double fStepScale(fDeltaScale / nSteps); + + xRetval.realloc(nSteps); + + for(sal_uInt32 a(0); a < nSteps; a++, fStartScale += fStepScale) + { + double fScaleA(getScaleA() + fStartScale); + const double fScaleB(fScaleA + fStepScale); + const double fUnitScale(fStartScale/fDeltaScale); + basegfx::B2DPolygon aPolygonA(basegfx::tools::createPolygonFromUnitCircle()); + basegfx::B2DPolygon aPolygonB(basegfx::tools::createPolygonFromUnitCircle()); + + if(fScaleA > getOverlapping()) + { + fScaleA -= getOverlapping(); + } + + const bool bUseA(basegfx::fTools::equalZero(fScaleA)); + + if(getTranslateSet()) + { + const double fUnitScaleEnd((fStartScale + fStepScale)/fDeltaScale); + const basegfx::B2DVector aTranslateB(basegfx::interpolate(getTranslateA(), getTranslateB(), fUnitScaleEnd)); + + if(bUseA) + { + const basegfx::B2DVector aTranslateA(basegfx::interpolate(getTranslateA(), getTranslateB(), fUnitScale)); + + aPolygonA.transform( + basegfx::tools::createScaleTranslateB2DHomMatrix( + fScaleA, + fScaleA, + aTranslateA.getX(), + aTranslateA.getY())); + } + + aPolygonB.transform( + basegfx::tools::createScaleTranslateB2DHomMatrix( + fScaleB, + fScaleB, + aTranslateB.getX(), + aTranslateB.getY())); + } + else + { + if(bUseA) + { + aPolygonA.transform( + basegfx::tools::createScaleB2DHomMatrix( + fScaleA, + fScaleA)); + } + + aPolygonB.transform( + basegfx::tools::createScaleB2DHomMatrix( + fScaleB, + fScaleB)); + } + + basegfx::B2DPolyPolygon aPolyPolygon(aPolygonB); + + if(bUseA) + { + aPolyPolygon.append(aPolygonA); + } + + xRetval[nSteps - 1 - a] = new PolyPolygonColorPrimitive2D( + aPolyPolygon, + basegfx::interpolate(getColorA(), getColorB(), fUnitScale)); + } + } + } + + return xRetval; + } + + bool SvgRadialAtomPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const + { + if(DiscreteMetricDependentPrimitive2D::operator==(rPrimitive)) + { + const SvgRadialAtomPrimitive2D& rCompare = static_cast< const SvgRadialAtomPrimitive2D& >(rPrimitive); + + return (getColorA() == rCompare.getColorA() + && getColorB() == rCompare.getColorB() + && getScaleA() == rCompare.getScaleA() + && getScaleB() == rCompare.getScaleB() + && getTranslateA() == rCompare.getTranslateA() + && getTranslateB() == rCompare.getTranslateB() + && getOverlapping() == rCompare.getOverlapping()); + } + + return false; + } + + // provide unique ID + ImplPrimitrive2DIDBlock(SvgRadialAtomPrimitive2D, PRIMITIVE2D_ID_SVGRADIALATOMPRIMITIVE2D) + + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/drawinglayer/source/primitive2d/textbreakuphelper.cxx b/drawinglayer/source/primitive2d/textbreakuphelper.cxx new file mode 100644 index 000000000000..4979a9932cc2 --- /dev/null +++ b/drawinglayer/source/primitive2d/textbreakuphelper.cxx @@ -0,0 +1,294 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http:\\www.apache.org\licenses\LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_drawinglayer.hxx" + +#include <drawinglayer/primitive2d/textbreakuphelper.hxx> +#include <drawinglayer/primitive2d/textdecoratedprimitive2d.hxx> +#include <com/sun/star/i18n/XBreakIterator.hpp> +#include <comphelper/processfactory.hxx> +#include <com/sun/star/i18n/CharacterIteratorMode.hdl> +#include <com/sun/star/i18n/WordType.hpp> + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace primitive2d + { + TextBreakupHelper::TextBreakupHelper(const Primitive2DReference& rxSource) + : mxSource(rxSource), + mxResult(), + mpSource(dynamic_cast< const TextSimplePortionPrimitive2D* >(rxSource.get())), + maTextLayouter(), + maDecTrans(), + mbNoDXArray() + { + if(mpSource) + { + maDecTrans = mpSource->getTextTransform(); + mbNoDXArray = mpSource->getDXArray().empty(); + + if(mbNoDXArray) + { + // init TextLayouter when no dxarray + maTextLayouter.setFontAttribute( + mpSource->getFontAttribute(), + maDecTrans.getScale().getX(), + maDecTrans.getScale().getY(), + mpSource->getLocale()); + } + } + } + + TextBreakupHelper::~TextBreakupHelper() + { + } + + void TextBreakupHelper::breakupPortion(Primitive2DVector& rTempResult, sal_uInt32 nIndex, sal_uInt32 nLength) + { + if(mpSource && nLength && !(nIndex == mpSource->getTextPosition() && nLength == mpSource->getTextLength())) + { + // prepare values for new portion + basegfx::B2DHomMatrix aNewTransform; + ::std::vector< double > aNewDXArray; + const bool bNewStartIsNotOldStart(nIndex > mpSource->getTextPosition()); + + if(!mbNoDXArray) + { + // prepare new DXArray for the single word + aNewDXArray = ::std::vector< double >( + mpSource->getDXArray().begin() + (nIndex - mpSource->getTextPosition()), + mpSource->getDXArray().begin() + ((nIndex + nLength) - mpSource->getTextPosition())); + } + + if(bNewStartIsNotOldStart) + { + // needs to be moved to a new start position + double fOffset(0.0); + + if(mbNoDXArray) + { + // evaluate using TextLayouter + fOffset = maTextLayouter.getTextWidth(mpSource->getText(), mpSource->getTextPosition(), nIndex); + } + else + { + // get from DXArray + const sal_uInt32 nIndex(static_cast< sal_uInt32 >(nIndex - mpSource->getTextPosition())); + fOffset = mpSource->getDXArray()[nIndex - 1]; + } + + // need offset without FontScale for building the new transformation. The + // new transformation will be multiplied with the current text transformation + // so FontScale would be double + double fOffsetNoScale(fOffset); + const double fFontScaleX(maDecTrans.getScale().getX()); + + if(!basegfx::fTools::equal(fFontScaleX, 1.0) + && !basegfx::fTools::equalZero(fFontScaleX)) + { + fOffsetNoScale /= fFontScaleX; + } + + // apply needed offset to transformation + aNewTransform.translate(fOffsetNoScale, 0.0); + + if(!mbNoDXArray) + { + // DXArray values need to be corrected with the offset, too. Here, + // take the scaled offset since the DXArray is scaled + const sal_uInt32 nArraySize(aNewDXArray.size()); + + for(sal_uInt32 a(0); a < nArraySize; a++) + { + aNewDXArray[a] -= fOffset; + } + } + } + + // add text transformation to new transformation + aNewTransform = maDecTrans.getB2DHomMatrix() * aNewTransform; + + // callback to allow evtl. changes + const bool bCreate(allowChange(rTempResult.size(), aNewTransform, nIndex, nLength)); + + if(bCreate) + { + // check if we have a decorated primitive as source + const TextDecoratedPortionPrimitive2D* pTextDecoratedPortionPrimitive2D = + dynamic_cast< const TextDecoratedPortionPrimitive2D* >(mpSource); + + if(pTextDecoratedPortionPrimitive2D) + { + // create a TextDecoratedPortionPrimitive2D + rTempResult.push_back( + new TextDecoratedPortionPrimitive2D( + aNewTransform, + mpSource->getText(), + nIndex, + nLength, + aNewDXArray, + mpSource->getFontAttribute(), + mpSource->getLocale(), + mpSource->getFontColor(), + + pTextDecoratedPortionPrimitive2D->getOverlineColor(), + pTextDecoratedPortionPrimitive2D->getTextlineColor(), + pTextDecoratedPortionPrimitive2D->getFontOverline(), + pTextDecoratedPortionPrimitive2D->getFontUnderline(), + pTextDecoratedPortionPrimitive2D->getUnderlineAbove(), + pTextDecoratedPortionPrimitive2D->getTextStrikeout(), + pTextDecoratedPortionPrimitive2D->getWordLineMode(), + pTextDecoratedPortionPrimitive2D->getTextEmphasisMark(), + pTextDecoratedPortionPrimitive2D->getEmphasisMarkAbove(), + pTextDecoratedPortionPrimitive2D->getEmphasisMarkBelow(), + pTextDecoratedPortionPrimitive2D->getTextRelief(), + pTextDecoratedPortionPrimitive2D->getShadow())); + } + else + { + // create a SimpleTextPrimitive + rTempResult.push_back( + new TextSimplePortionPrimitive2D( + aNewTransform, + mpSource->getText(), + nIndex, + nLength, + aNewDXArray, + mpSource->getFontAttribute(), + mpSource->getLocale(), + mpSource->getFontColor())); + } + } + } + } + + bool TextBreakupHelper::allowChange(sal_uInt32 nCount, basegfx::B2DHomMatrix& rNewTransform, sal_uInt32 nIndex, sal_uInt32 nLength) + { + return true; + } + + void TextBreakupHelper::breakup(BreakupUnit aBreakupUnit) + { + if(mpSource && mpSource->getTextLength()) + { + Primitive2DVector aTempResult; + static ::com::sun::star::uno::Reference< ::com::sun::star::i18n::XBreakIterator > xBreakIterator; + + if(!xBreakIterator.is()) + { + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xMSF(::comphelper::getProcessServiceFactory()); + xBreakIterator.set(xMSF->createInstance(rtl::OUString::createFromAscii("com.sun.star.i18n.BreakIterator")), ::com::sun::star::uno::UNO_QUERY); + } + + if(xBreakIterator.is()) + { + const rtl::OUString& rTxt = mpSource->getText(); + const sal_Int32 nTextLength(mpSource->getTextLength()); + const ::com::sun::star::lang::Locale& rLocale = mpSource->getLocale(); + const sal_Int32 nTextPosition(mpSource->getTextPosition()); + sal_Int32 nCurrent(nTextPosition); + + switch(aBreakupUnit) + { + case BreakupUnit_character: + { + sal_Int32 nDone; + sal_Int32 nNextCellBreak(xBreakIterator->nextCharacters(rTxt, nTextPosition, rLocale, ::com::sun::star::i18n::CharacterIteratorMode::SKIPCELL, 0, nDone)); + sal_Int32 a(nTextPosition); + + for(; a < nTextPosition + nTextLength; a++) + { + if(a == nNextCellBreak) + { + breakupPortion(aTempResult, nCurrent, a - nCurrent); + nCurrent = a; + nNextCellBreak = xBreakIterator->nextCharacters(rTxt, a, rLocale, ::com::sun::star::i18n::CharacterIteratorMode::SKIPCELL, 1, nDone); + } + } + + breakupPortion(aTempResult, nCurrent, a - nCurrent); + break; + } + case BreakupUnit_word: + { + ::com::sun::star::i18n::Boundary nNextWordBoundary(xBreakIterator->getWordBoundary(rTxt, nTextPosition, rLocale, ::com::sun::star::i18n::WordType::ANY_WORD, sal_True)); + sal_Int32 a(nTextPosition); + + for(; a < nTextPosition + nTextLength; a++) + { + if(a == nNextWordBoundary.endPos) + { + breakupPortion(aTempResult, nCurrent, a - nCurrent); + nCurrent = a; + nNextWordBoundary = xBreakIterator->getWordBoundary(rTxt, a + 1, rLocale, ::com::sun::star::i18n::WordType::ANY_WORD, sal_True); + } + } + + breakupPortion(aTempResult, nCurrent, a - nCurrent); + break; + } + case BreakupUnit_sentence: + { + sal_Int32 nNextSentenceBreak(xBreakIterator->endOfSentence(rTxt, nTextPosition, rLocale)); + sal_Int32 a(nTextPosition); + + for(; a < nTextPosition + nTextLength; a++) + { + if(a == nNextSentenceBreak) + { + breakupPortion(aTempResult, nCurrent, a - nCurrent); + nCurrent = a; + nNextSentenceBreak = xBreakIterator->endOfSentence(rTxt, a + 1, rLocale); + } + } + + breakupPortion(aTempResult, nCurrent, a - nCurrent); + break; + } + } + } + + mxResult = Primitive2DVectorToPrimitive2DSequence(aTempResult); + } + } + + const Primitive2DSequence& TextBreakupHelper::getResult(BreakupUnit aBreakupUnit) const + { + if(mxResult.hasElements()) + { + return mxResult; + } + else if(mpSource) + { + const_cast< TextBreakupHelper* >(this)->breakup(aBreakupUnit); + } + + return mxResult; + } + + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/drawinglayer/source/processor2d/hittestprocessor2d.cxx b/drawinglayer/source/processor2d/hittestprocessor2d.cxx index 855535eb96e8..3b5e266f3bfd 100644 --- a/drawinglayer/source/processor2d/hittestprocessor2d.cxx +++ b/drawinglayer/source/processor2d/hittestprocessor2d.cxx @@ -525,7 +525,6 @@ namespace drawinglayer case PRIMITIVE2D_ID_FILLHATCHPRIMITIVE2D : case PRIMITIVE2D_ID_PAGEPREVIEWPRIMITIVE2D : case PRIMITIVE2D_ID_MEDIAPRIMITIVE2D: - case PRIMITIVE2D_ID_RENDERGRAPHICPRIMITIVE2D: { if(!getHitTextOnly()) { diff --git a/drawinglayer/source/processor2d/linegeometryextractor2d.cxx b/drawinglayer/source/processor2d/linegeometryextractor2d.cxx index 65a87c83f4a0..97ecf9da6952 100644 --- a/drawinglayer/source/processor2d/linegeometryextractor2d.cxx +++ b/drawinglayer/source/processor2d/linegeometryextractor2d.cxx @@ -119,7 +119,6 @@ namespace drawinglayer case PRIMITIVE2D_ID_MARKERARRAYPRIMITIVE2D : case PRIMITIVE2D_ID_POINTARRAYPRIMITIVE2D : case PRIMITIVE2D_ID_BITMAPPRIMITIVE2D : - case PRIMITIVE2D_ID_RENDERGRAPHICPRIMITIVE2D : case PRIMITIVE2D_ID_METAFILEPRIMITIVE2D : case PRIMITIVE2D_ID_MASKPRIMITIVE2D : { diff --git a/drawinglayer/source/processor2d/textaspolygonextractor2d.cxx b/drawinglayer/source/processor2d/textaspolygonextractor2d.cxx index 13cbfcb3badb..59a47fc790a6 100644 --- a/drawinglayer/source/processor2d/textaspolygonextractor2d.cxx +++ b/drawinglayer/source/processor2d/textaspolygonextractor2d.cxx @@ -210,7 +210,6 @@ namespace drawinglayer case PRIMITIVE2D_ID_MARKERARRAYPRIMITIVE2D : case PRIMITIVE2D_ID_POINTARRAYPRIMITIVE2D : case PRIMITIVE2D_ID_BITMAPPRIMITIVE2D : - case PRIMITIVE2D_ID_RENDERGRAPHICPRIMITIVE2D : case PRIMITIVE2D_ID_METAFILEPRIMITIVE2D : case PRIMITIVE2D_ID_MASKPRIMITIVE2D : { diff --git a/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx b/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx index c56909e9dfde..63dbabf2bce5 100644 --- a/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx +++ b/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx @@ -34,7 +34,6 @@ #include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx> #include <drawinglayer/primitive2d/polygonprimitive2d.hxx> #include <drawinglayer/primitive2d/bitmapprimitive2d.hxx> -#include <drawinglayer/primitive2d/rendergraphicprimitive2d.hxx> #include <drawinglayer/primitive2d/metafileprimitive2d.hxx> #include <drawinglayer/primitive2d/maskprimitive2d.hxx> #include <basegfx/polygon/b2dpolygonclipper.hxx> @@ -1284,12 +1283,6 @@ namespace drawinglayer RenderBitmapPrimitive2D(static_cast< const primitive2d::BitmapPrimitive2D& >(rCandidate)); break; } - case PRIMITIVE2D_ID_RENDERGRAPHICPRIMITIVE2D : - { - // direct draw of transformed RenderGraphic primitive; use default processing - RenderRenderGraphicPrimitive2D(static_cast< const primitive2d::RenderGraphicPrimitive2D& >(rCandidate)); - break; - } case PRIMITIVE2D_ID_POLYPOLYGONBITMAPPRIMITIVE2D : { // need to handle PolyPolygonBitmapPrimitive2D here to support XPATHFILL_SEQ_BEGIN/XPATHFILL_SEQ_END @@ -1657,7 +1650,8 @@ namespace drawinglayer // the ClipRegion is built from the Polygon. A AdaptiveSubdivide on the source polygon was missing there mpOutputDevice->Push(PUSH_CLIPREGION); //mpOutputDevice->SetClipRegion(Region(PolyPolygon(basegfx::tools::adaptiveSubdivideByAngle(maClipPolyPolygon)))); - mpOutputDevice->SetClipRegion(Region(PolyPolygon(maClipPolyPolygon))); + //mpOutputDevice->SetClipRegion(Region(PolyPolygon(maClipPolyPolygon))); + mpOutputDevice->SetClipRegion(Region(maClipPolyPolygon)); } // recursively paint content diff --git a/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx b/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx index f485aa182bd2..d71090ed7d5b 100644 --- a/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx +++ b/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx @@ -31,7 +31,6 @@ #include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx> #include <drawinglayer/primitive2d/polygonprimitive2d.hxx> #include <drawinglayer/primitive2d/bitmapprimitive2d.hxx> -#include <drawinglayer/primitive2d/rendergraphicprimitive2d.hxx> #include <drawinglayer/primitive2d/fillbitmapprimitive2d.hxx> #include <drawinglayer/primitive2d/metafileprimitive2d.hxx> #include <drawinglayer/primitive2d/maskprimitive2d.hxx> @@ -190,12 +189,6 @@ namespace drawinglayer RenderBitmapPrimitive2D(static_cast< const primitive2d::BitmapPrimitive2D& >(rCandidate)); break; } - case PRIMITIVE2D_ID_RENDERGRAPHICPRIMITIVE2D : - { - // direct draw of transformed BitmapEx primitive - RenderRenderGraphicPrimitive2D(static_cast< const primitive2d::RenderGraphicPrimitive2D& >(rCandidate)); - break; - } case PRIMITIVE2D_ID_FILLBITMAPPRIMITIVE2D : { // direct draw of fillBitmapPrimitive diff --git a/drawinglayer/source/processor2d/vclprocessor2d.cxx b/drawinglayer/source/processor2d/vclprocessor2d.cxx index 8027f3284909..dc79dcce648a 100644 --- a/drawinglayer/source/processor2d/vclprocessor2d.cxx +++ b/drawinglayer/source/processor2d/vclprocessor2d.cxx @@ -31,7 +31,6 @@ #include <vcl/outdev.hxx> #include <drawinglayer/primitive2d/polygonprimitive2d.hxx> #include <drawinglayer/primitive2d/bitmapprimitive2d.hxx> -#include <drawinglayer/primitive2d/rendergraphicprimitive2d.hxx> #include <vclhelperbitmaptransform.hxx> #include <basegfx/polygon/b2dpolygontools.hxx> #include <vclhelperbitmaprender.hxx> @@ -57,7 +56,6 @@ #include <vcl/metric.hxx> #include <drawinglayer/primitive2d/textenumsprimitive2d.hxx> #include <drawinglayer/primitive2d/epsprimitive2d.hxx> -#include <vcl/rendergraphicrasterizer.hxx> ////////////////////////////////////////////////////////////////////////////// // control support @@ -419,75 +417,6 @@ namespace drawinglayer } } - void VclProcessor2D::RenderRenderGraphicPrimitive2D(const primitive2d::RenderGraphicPrimitive2D& rRenderGraphicCandidate) - { - // create local transform - basegfx::B2DHomMatrix aLocalTransform(maCurrentTransformation * rRenderGraphicCandidate.getTransform()); - vcl::RenderGraphic aRenderGraphic(rRenderGraphicCandidate.getRenderGraphic()); - bool bPainted(false); - - if(maBColorModifierStack.count()) - { - // !!! TODO - // aRenderGraphic = impModifyRenderGraphic(maBColorModifierStack, aRenderGraphic); - - if(aRenderGraphic.IsEmpty()) - { - // color gets completely replaced, get it - const basegfx::BColor aModifiedColor(maBColorModifierStack.getModifiedColor(basegfx::BColor())); - basegfx::B2DPolygon aPolygon(basegfx::tools::createUnitPolygon()); - aPolygon.transform(aLocalTransform); - - mpOutputDevice->SetFillColor(Color(aModifiedColor)); - mpOutputDevice->SetLineColor(); - mpOutputDevice->DrawPolygon(aPolygon); - - bPainted = true; - } - } - - if(!bPainted) - { - // decompose matrix to check for shear, rotate and mirroring - basegfx::B2DVector aScale, aTranslate; - double fRotate, fShearX; - aLocalTransform.decompose(aScale, aTranslate, fRotate, fShearX); - - basegfx::B2DRange aOutlineRange(0.0, 0.0, 1.0, 1.0); - - if( basegfx::fTools::equalZero( fRotate ) ) - { - aOutlineRange.transform( aLocalTransform ); - } - else - { - // !!! TODO - // if rotated, create the unrotated output rectangle for the GraphicManager paint - /* - const basegfx::B2DHomMatrix aSimpleObjectMatrix(basegfx::tools::createScaleTranslateB2DHomMatrix( - fabs(aScale.getX()), fabs(aScale.getY()), - aTranslate.getX(), aTranslate.getY())); - - aOutlineRange.transform(aSimpleObjectMatrix); - */ - } - - // prepare dest coordinates - const Point aPoint( basegfx::fround(aOutlineRange.getMinX() ), - basegfx::fround(aOutlineRange.getMinY() ) ); - const Size aSize( basegfx::fround(aOutlineRange.getWidth() ), - basegfx::fround(aOutlineRange.getHeight() ) ); - const Size aSizePixel( mpOutputDevice->LogicToPixel( aSize ) ); - const vcl::RenderGraphicRasterizer aRasterizer( aRenderGraphic ); - const BitmapEx aBitmapEx( aRasterizer.Rasterize( aSizePixel, fRotate, fShearX ) ); - - if( !aBitmapEx.IsEmpty() ) - { - mpOutputDevice->DrawBitmapEx( aPoint, aSize, aBitmapEx ); - } - } - } - void VclProcessor2D::RenderFillBitmapPrimitive2D(const primitive2d::FillBitmapPrimitive2D& rFillBitmapCandidate) { const attribute::FillBitmapAttribute& rFillBitmapAttribute(rFillBitmapCandidate.getFillBitmap()); diff --git a/drawinglayer/source/processor3d/shadow3dextractor.cxx b/drawinglayer/source/processor3d/shadow3dextractor.cxx index 572610805e4c..497c020f5894 100644 --- a/drawinglayer/source/processor3d/shadow3dextractor.cxx +++ b/drawinglayer/source/processor3d/shadow3dextractor.cxx @@ -47,25 +47,6 @@ namespace drawinglayer { namespace processor3d { - /// helper to convert from BasePrimitive2DVector to primitive2d::Primitive2DSequence - const primitive2d::Primitive2DSequence Shadow3DExtractingProcessor::getPrimitive2DSequenceFromBasePrimitive2DVector( - const BasePrimitive2DVector& rVector) const - { - const sal_uInt32 nCount(rVector.size()); - primitive2d::Primitive2DSequence aRetval(nCount); - - for(sal_uInt32 a(0); a < nCount; a++) - { - aRetval[a] = rVector[a]; - } - - // all entries taken over; no need to delete entries, just reset to - // mark as empty - const_cast< BasePrimitive2DVector& >(rVector).clear(); - - return aRetval; - } - // as tooling, the process() implementation takes over API handling and calls this // virtual render method when the primitive implementation is BasePrimitive3D-based. void Shadow3DExtractingProcessor::processBasePrimitive3D(const primitive3d::BasePrimitive3D& rCandidate) @@ -79,8 +60,8 @@ namespace drawinglayer const primitive3d::ShadowPrimitive3D& rPrimitive = static_cast< const primitive3d::ShadowPrimitive3D& >(rCandidate); // set new target - BasePrimitive2DVector aNewSubList; - BasePrimitive2DVector* pLastTargetSequence = mpPrimitive2DSequence; + primitive2d::Primitive2DVector aNewSubList; + primitive2d::Primitive2DVector* pLastTargetSequence = mpPrimitive2DSequence; mpPrimitive2DSequence = &aNewSubList; // activate convert @@ -104,7 +85,7 @@ namespace drawinglayer primitive2d::BasePrimitive2D* pNew = new primitive2d::ShadowPrimitive2D( rPrimitive.getShadowTransform(), rPrimitive.getShadowColor(), - getPrimitive2DSequenceFromBasePrimitive2DVector(aNewSubList)); + primitive2d::Primitive2DVectorToPrimitive2DSequence(aNewSubList)); if(basegfx::fTools::more(rPrimitive.getShadowTransparence(), 0.0)) { @@ -328,7 +309,7 @@ namespace drawinglayer const primitive2d::Primitive2DSequence Shadow3DExtractingProcessor::getPrimitive2DSequence() const { - return getPrimitive2DSequenceFromBasePrimitive2DVector(maPrimitive2DSequence); + return Primitive2DVectorToPrimitive2DSequence(maPrimitive2DSequence); } } // end of namespace processor3d diff --git a/drawinglayer/source/tools/converters.cxx b/drawinglayer/source/tools/converters.cxx new file mode 100644 index 000000000000..a7d22a5df698 --- /dev/null +++ b/drawinglayer/source/tools/converters.cxx @@ -0,0 +1,143 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http:\\www.apache.org\licenses\LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_drawinglayer.hxx" + +#include <drawinglayer/tools/converters.hxx> +#include <drawinglayer/geometry/viewinformation2d.hxx> +#include <drawinglayer/processor2d/vclpixelprocessor2d.hxx> +#include <drawinglayer/primitive2d/modifiedcolorprimitive2d.hxx> +#include <basegfx/matrix/b2dhommatrixtools.hxx> +#include <drawinglayer/primitive2d/transformprimitive2d.hxx> +#include <vcl/virdev.hxx> + +#ifdef DBG_UTIL +#include <tools/stream.hxx> +#endif + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace tools + { + BitmapEx DRAWINGLAYER_DLLPUBLIC convertToBitmapEx( + const drawinglayer::primitive2d::Primitive2DSequence& rSeq, + const geometry::ViewInformation2D& rViewInformation2D, + sal_uInt32 nDiscreteWidth, + sal_uInt32 nDiscreteHeight, + sal_uInt32 nMaxQuadratPixels) + { + BitmapEx aRetval; + + if(rSeq.hasElements() && nDiscreteWidth && nDiscreteHeight) + { + // get destination size in pixels + const MapMode aMapModePixel(MAP_PIXEL); + const sal_uInt32 nViewVisibleArea(nDiscreteWidth * nDiscreteHeight); + double fReduceFactor(1.0); + drawinglayer::primitive2d::Primitive2DSequence aSequence(rSeq); + + if(nViewVisibleArea > nMaxQuadratPixels) + { + // reduce render size + fReduceFactor = sqrt((double)nMaxQuadratPixels / (double)nViewVisibleArea); + nDiscreteWidth = basegfx::fround((double)nDiscreteWidth * fReduceFactor); + nDiscreteHeight = basegfx::fround((double)nDiscreteHeight * fReduceFactor); + + const drawinglayer::primitive2d::Primitive2DReference aEmbed( + new drawinglayer::primitive2d::TransformPrimitive2D( + basegfx::tools::createScaleB2DHomMatrix(fReduceFactor, fReduceFactor), + rSeq)); + + aSequence = drawinglayer::primitive2d::Primitive2DSequence(&aEmbed, 1); + } + + const Point aEmptyPoint; + const Size aSizePixel(nDiscreteWidth, nDiscreteHeight); + geometry::ViewInformation2D aViewInformation2D(rViewInformation2D); + VirtualDevice maContent; + + // prepare vdev + maContent.SetOutputSizePixel(aSizePixel, false); + maContent.SetMapMode(aMapModePixel); + maContent.SetAntialiasing(true); + + // set to all white + maContent.SetBackground(Wallpaper(Color(COL_WHITE))); + maContent.Erase(); + + // create processor + processor2d::VclPixelProcessor2D aContentProcessor(aViewInformation2D, maContent); + + // render content + aContentProcessor.process(aSequence); + + // get content + maContent.EnableMapMode(false); + const Bitmap aContent(maContent.GetBitmap(aEmptyPoint, aSizePixel)); + + // prepare for mask creation + maContent.SetMapMode(aMapModePixel); + maContent.SetAntialiasing(true); + + // set alpha to all white (fully transparent) + maContent.Erase(); + + // embed primitives to paint them black + const primitive2d::Primitive2DReference xRef( + new primitive2d::ModifiedColorPrimitive2D( + aSequence, + basegfx::BColorModifier( + basegfx::BColor(0.0, 0.0, 0.0), + 0.5, + basegfx::BCOLORMODIFYMODE_REPLACE))); + const primitive2d::Primitive2DSequence xSeq(&xRef, 1); + + // render + aContentProcessor.process(xSeq); + + // get alpha cahannel from vdev + maContent.EnableMapMode(false); + const AlphaMask aAlphaMask(maContent.GetBitmap(aEmptyPoint, aSizePixel)); + + // create BitmapEx result + aRetval = BitmapEx(aContent, aAlphaMask); + } + +#ifdef DBG_UTIL + static bool bDoSaveForVisualControl(false); + if(bDoSaveForVisualControl) + { + SvFileStream aNew((const String&)String(ByteString( "c:\\test.png" ), RTL_TEXTENCODING_UTF8), STREAM_WRITE|STREAM_TRUNC); + aNew << aRetval; + } +#endif + + return aRetval; + } + + } // end of namespace tools +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/editeng/inc/editeng/unoprnms.hxx b/editeng/inc/editeng/unoprnms.hxx index f03d985537fb..9379e1b0616f 100644 --- a/editeng/inc/editeng/unoprnms.hxx +++ b/editeng/inc/editeng/unoprnms.hxx @@ -176,6 +176,7 @@ #define UNO_NAME_GRAPHOBJ_FILLBITMAP "GraphicObjectFillBitmap" #define UNO_NAME_GRAPHOBJ_GRAFURL "GraphicURL" +#define UNO_NAME_GRAPHOBJ_REPLACEMENTGRAFURL "ReplacementGraphicURL" #define UNO_NAME_GRAPHOBJ_GRAFSTREAMURL "GraphicStreamURL" #define UNO_NAME_GRAPHOBJ_URLPREFIX "vnd.sun.star.GraphicObject:" #define UNO_NAME_GRAPHOBJ_URLPKGPREFIX "vnd.sun.star.Package:" diff --git a/filter/source/flash/swfwriter1.cxx b/filter/source/flash/swfwriter1.cxx index 24e6e0e777fc..018cae8e2b7f 100644 --- a/filter/source/flash/swfwriter1.cxx +++ b/filter/source/flash/swfwriter1.cxx @@ -36,7 +36,6 @@ #include <basegfx/matrix/b2dhommatrixtools.hxx> #include <svtools/filter.hxx> #include <vcl/graphictools.hxx> -#include <vcl/rendergraphicrasterizer.hxx> #ifndef _ZLIB_H #ifdef SYSTEM_ZLIB @@ -1887,19 +1886,6 @@ void Writer::Impl_writeActions( const GDIMetaFile& rMtf ) } break; - case( META_RENDERGRAPHIC_ACTION ): - { - const MetaRenderGraphicAction* pA = (const MetaRenderGraphicAction*) pAction; - const ::vcl::RenderGraphicRasterizer aRasterizer( pA->GetRenderGraphic() ); - const Point aPointPixel; - const Size aSizePixel( mpVDev->LogicToPixel( pA->GetSize() ) ); - const BitmapEx aBmpEx( aRasterizer.Rasterize( aSizePixel ) ); - - Impl_writeImage( aBmpEx, pA->GetPoint(), pA->GetSize(), - aPointPixel, aBmpEx.GetSizePixel(), clipRect, 1 == bMap ); - } - break; - case( META_MAPMODE_ACTION ): { // const MetaMapModeAction *pA = (const MetaMapModeAction*) pAction; diff --git a/filter/source/graphicfilter/eos2met/eos2met.cxx b/filter/source/graphicfilter/eos2met/eos2met.cxx index 93a9ecd78a9a..bd0ee366936d 100644 --- a/filter/source/graphicfilter/eos2met/eos2met.cxx +++ b/filter/source/graphicfilter/eos2met/eos2met.cxx @@ -40,7 +40,6 @@ #include <vcl/virdev.hxx> #include <vcl/svapp.hxx> #include <vcl/msgbox.hxx> -#include <vcl/rendergraphicrasterizer.hxx> #include <svl/solar.hrc> @@ -323,7 +322,6 @@ void METWriter::CountActionsAndBitmaps(const GDIMetaFile * pMTF) case META_BMPEX_ACTION: case META_BMPEXSCALE_ACTION: case META_BMPEXSCALEPART_ACTION: - case META_RENDERGRAPHIC_ACTION: nNumberOfBitmaps++; break; } @@ -797,16 +795,6 @@ void METWriter::WriteImageObjects(const GDIMetaFile * pMTF) } break; - case( META_RENDERGRAPHIC_ACTION ): - { - const MetaRenderGraphicAction* pA = (const MetaRenderGraphicAction*) pMA; - const ::vcl::RenderGraphicRasterizer aRasterizer( pA->GetRenderGraphic() ); - const BitmapEx aBmpEx( aRasterizer.Rasterize( pCompDev->LogicToPixel( pA->GetSize() ) ) ); - - METSetMix( eGDIRasterOp ); - WriteImageObject( Graphic( aBmpEx ).GetBitmap() ); - } - break; } if (bStatus==sal_False) @@ -2355,14 +2343,6 @@ void METWriter::WriteOrders( const GDIMetaFile* pMTF ) } break; - case( META_RENDERGRAPHIC_ACTION ): - { - const MetaRenderGraphicAction* pA = (const MetaRenderGraphicAction*) pMA; - - METSetMix( eGDIRasterOp ); - METBitBlt( pA->GetPoint(), pA->GetSize(), pCompDev->LogicToPixel( pA->GetSize(), pMTF->GetPrefMapMode() ) ); - } - break; } nWrittenActions++; diff --git a/filter/source/graphicfilter/epict/epict.cxx b/filter/source/graphicfilter/epict/epict.cxx index 7c6b1fa8d76f..6a66b2a1ebee 100644 --- a/filter/source/graphicfilter/epict/epict.cxx +++ b/filter/source/graphicfilter/epict/epict.cxx @@ -42,7 +42,6 @@ #include <vcl/svapp.hxx> #include <vcl/msgbox.hxx> #include <vcl/gdimtf.hxx> -#include <vcl/rendergraphicrasterizer.hxx> #include <tools/bigint.hxx> @@ -223,7 +222,6 @@ void PictWriter::CountActionsAndBitmaps(const GDIMetaFile & rMTF) case META_BMPEX_ACTION: case META_BMPEXSCALE_ACTION: case META_BMPEXSCALEPART_ACTION: - case META_RENDERGRAPHIC_ACTION: nNumberOfBitmaps++; break; } @@ -2153,17 +2151,6 @@ void PictWriter::WriteOpcodes( const GDIMetaFile & rMTF ) } break; - case( META_RENDERGRAPHIC_ACTION ): - { - const MetaRenderGraphicAction* pA = (const MetaRenderGraphicAction*) pMA; - const ::vcl::RenderGraphicRasterizer aRasterizer( pA->GetRenderGraphic() ); - VirtualDevice aVirDev; - const Bitmap aBmp( Graphic( aRasterizer.Rasterize( - aVirDev.LogicToPixel( pA->GetSize() ) ) ).GetBitmap() ); - - WriteOpcode_BitsRect( pA->GetPoint(), pA->GetSize(), aBmp ); - } - break; } nWrittenActions++; diff --git a/filter/source/graphicfilter/eps/eps.cxx b/filter/source/graphicfilter/eps/eps.cxx index 4458d5f99790..2f63c27017d7 100644 --- a/filter/source/graphicfilter/eps/eps.cxx +++ b/filter/source/graphicfilter/eps/eps.cxx @@ -43,7 +43,6 @@ #include <svtools/fltcall.hxx> #include <svtools/FilterConfigItem.hxx> #include <vcl/graphictools.hxx> -#include <vcl/rendergraphicrasterizer.hxx> #include "strings.hrc" #include <math.h> @@ -1336,7 +1335,6 @@ void PSWriter::ImplWriteActions( const GDIMetaFile& rMtf, VirtualDevice& rVDev ) case META_BMPSCALEPART_ACTION : case META_BMPEXSCALE_ACTION : case META_BMPEXSCALEPART_ACTION : - case META_RENDERGRAPHIC_ACTION : { nBitmapCount++; nBitmapAction = nCurAction; @@ -1396,22 +1394,6 @@ void PSWriter::ImplWriteActions( const GDIMetaFile& rMtf, VirtualDevice& rVDev ) } break; - case( META_RENDERGRAPHIC_ACTION ): - { - const MetaRenderGraphicAction* pA = (const MetaRenderGraphicAction*) pMA; - const ::vcl::RenderGraphicRasterizer aRasterizer( pA->GetRenderGraphic() ); - const BitmapEx aBmpEx( aRasterizer.Rasterize( rVDev.LogicToPixel( pA->GetSize() ) ) ); - Bitmap aBmp( aBmpEx.GetBitmap() ); - - if ( mbGrayScale ) - aBmp.Convert( BMP_CONVERSION_8BIT_GREYS ); - - Bitmap aMask( aBmpEx.GetMask() ); - Size aSize( pA->GetSize() ); - - ImplBmp( &aBmp, &aMask, pA->GetPoint(), aSize.Width(), aSize.Height() ); - } - break; } } } diff --git a/filter/source/svg/svgwriter.cxx b/filter/source/svg/svgwriter.cxx index 7b78a083ca19..271f52e3e790 100644 --- a/filter/source/svg/svgwriter.cxx +++ b/filter/source/svg/svgwriter.cxx @@ -1658,24 +1658,6 @@ void SVGActionWriter::ImplWriteActions( const GDIMetaFile& rMtf, } break; - case( META_RENDERGRAPHIC_ACTION ): - { - if( nWriteFlags & SVGWRITER_WRITE_FILL ) - { - // TODO KA: try to embed the native data in case the RenderGraphic - // contains valid SVG data (MimeType "image/svg+xml") - // => incorporate 'use' or 'image' element (KA 01/2011) - const MetaRenderGraphicAction* pA = (const MetaRenderGraphicAction*) pAction; - const ::vcl::RenderGraphicRasterizer aRasterizer( pA->GetRenderGraphic() ); - const Point aPointPixel; - const Size aSizePixel( mpVDev->LogicToPixel( pA->GetSize() ) ); - const BitmapEx aBmpEx( aRasterizer.Rasterize( aSizePixel ) ); - - ImplWriteBmp( aBmpEx, pA->GetPoint(), pA->GetSize(), aPointPixel, aBmpEx.GetSizePixel() ); - } - } - break; - case( META_CLIPREGION_ACTION ): case( META_ISECTRECTCLIPREGION_ACTION ): case( META_ISECTREGIONCLIPREGION_ACTION ): diff --git a/filter/source/svg/svgwriter.hxx b/filter/source/svg/svgwriter.hxx index 9b84751417c2..233a244e5cd4 100644 --- a/filter/source/svg/svgwriter.hxx +++ b/filter/source/svg/svgwriter.hxx @@ -50,7 +50,6 @@ #include <vcl/cvtgrf.hxx> #endif #include <vcl/graphictools.hxx> -#include <vcl/rendergraphicrasterizer.hxx> #include <xmloff/xmlexp.hxx> #include <xmloff/nmspmap.hxx> diff --git a/offapi/com/sun/star/graphic/Primitive2DTools.idl b/offapi/com/sun/star/graphic/Primitive2DTools.idl new file mode 100644 index 000000000000..80c8ca121907 --- /dev/null +++ b/offapi/com/sun/star/graphic/Primitive2DTools.idl @@ -0,0 +1,43 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http:\\www.apache.org\licenses\LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +#ifndef com_sun_star_graphic_Primitive2DTools_idl +#define com_sun_star_graphic_Primitive2DTools_idl + +#include <com/sun/star/graphic/XPrimitive2DRenderer.idl> + +module com { module sun { module star { module graphic +{ + +/** Service that describes the necessary interfaces and properties + for tooling involved with XPrimitive2D interfaces + */ + +service Primitive2DTools +{ + /** Interface to render B2DPrimitives to a XBitmap + */ + interface ::com::sun::star::graphic::XPrimitive2DRenderer; +}; + +} ; } ; } ; } ; + +#endif diff --git a/offapi/com/sun/star/graphic/SvgTools.idl b/offapi/com/sun/star/graphic/SvgTools.idl new file mode 100644 index 000000000000..bbb86621ce31 --- /dev/null +++ b/offapi/com/sun/star/graphic/SvgTools.idl @@ -0,0 +1,44 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http:\\www.apache.org\licenses\LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +#ifndef com_sun_star_graphic_SvgTools_idl +#define com_sun_star_graphic_SvgTools_idl + +#include <com/sun/star/graphic/XSvgParser.idl> + +module com { module sun { module star { module graphic +{ + +/** Service that describes the necessary interfaces and properties + to handle svg files + */ + +service SvgTools +{ + /** Interface to parse a svg file to a sequence of + B2DPrimitives for internal usage + */ + interface ::com::sun::star::graphic::XSvgParser; +}; + +} ; } ; } ; } ; + +#endif diff --git a/offapi/com/sun/star/graphic/XPrimitive2DRenderer.idl b/offapi/com/sun/star/graphic/XPrimitive2DRenderer.idl new file mode 100644 index 000000000000..b939d1ea9a73 --- /dev/null +++ b/offapi/com/sun/star/graphic/XPrimitive2DRenderer.idl @@ -0,0 +1,80 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http:\\www.apache.org\licenses\LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ +#ifndef __com_sun_star_graphic_XPrimitive2DRenderer_idl__ +#define __com_sun_star_graphic_XPrimitive2DRenderer_idl__ + +#include <com/sun/star/uno/XInterface.idl> +#include <com/sun/star/rendering/XBitmap.idl> +#include <com/sun/star/beans/PropertyValue.idl> +#include <com/sun/star/geometry/RealRectangle2D.idl> + +module com { module sun { module star { module graphic { + +interface XPrimitive2D; + +/** XPrimitive2DRenderer interface + + This interface allows to convert from a sequence of XPrimitive2Ds + to a XBitmap + */ +interface XPrimitive2DRenderer : ::com::sun::star::uno::XInterface +{ + /** return rasterized version of given XPrimitive2D + + @param Primitive2DSequence + The graphic content description + + @param aViewInformationSequence + The ViewInformation2D + + @param DPI_X + The horizontal resolution of the callers device in pixel per inch. This + value is needed to calculate the correct dimensions of the graphic to be + rasterized. If a value of <value>0</value> is given, a horizontal default + resolution of 72 DPI is used. + + @param DPI_Y + The vertical resolution of the callers device in pixel per inch. This + value is needed to calculate the correct dimensions of the graphic to be + rasterized. If a value of <value>0</value> is given, a vertical default + resolution of 72 DPI is used. + + @param Range + The range in 1/100th mm of the graphic to be rasterized + + @param MaximumQuadraticPixels + The maximum allowed number of pixels to be used to allow limiting the + possible size of used pixels. The AspectRatio is preserved, the result + gets limited to given number. If a value of 0 is given, a default of + 500000 is used. + */ + com::sun::star::rendering::XBitmap rasterize( + [in] sequence< XPrimitive2D > Primitive2DSequence, + [in] sequence< ::com::sun::star::beans::PropertyValue > aViewInformationSequence, + [in] unsigned long DPI_X, + [in] unsigned long DPI_Y, + [in] ::com::sun::star::geometry::RealRectangle2D Range, + [in] unsigned long MaximumQuadraticPixels); +}; + +}; }; }; }; + +#endif diff --git a/offapi/com/sun/star/graphic/XSvgParser.idl b/offapi/com/sun/star/graphic/XSvgParser.idl new file mode 100644 index 000000000000..5adf67897a2c --- /dev/null +++ b/offapi/com/sun/star/graphic/XSvgParser.idl @@ -0,0 +1,50 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http:\\www.apache.org\licenses\LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ +#ifndef __com_sun_star_graphic_XSvgParser_idl__ +#define __com_sun_star_graphic_XSvgParser_idl__ + +#include <com/sun/star/uno/XInterface.idl> +#include <com/sun/star/io/XInputStream.idl> + +module com { module sun { module star { module graphic { + +interface XPrimitive2D; + +/** XSvgParser interface + + This interface allows to parse a SVG stream in form of a sequence of bytes + to be parsed into a sequence of XPrimitive2Ds + */ +interface XSvgParser : ::com::sun::star::uno::XInterface +{ + /** Retrieve decomposed list of simpler primitives + + @param xSvgStream + The file containing the SVG XML data + */ + sequence< XPrimitive2D > getDecomposition( + [in] io::XInputStream xSvgStream, + [in] string aAbsolutePath); +}; + +}; }; }; }; + +#endif diff --git a/offapi/com/sun/star/graphic/makefile.mk b/offapi/com/sun/star/graphic/makefile.mk index 6e4a0187c15c..9a1452dca771 100755 --- a/offapi/com/sun/star/graphic/makefile.mk +++ b/offapi/com/sun/star/graphic/makefile.mk @@ -48,6 +48,8 @@ IDLFILES= \ GraphicRendererVCL.idl \ GraphicType.idl \ MediaProperties.idl \ + Primitive2DTools.idl \ + SvgTools.idl \ XPrimitive2D.idl \ XPrimitive3D.idl \ XPrimitiveFactory2D.idl \ @@ -56,7 +58,9 @@ IDLFILES= \ XGraphicRasterizer.idl \ XGraphicRenderer.idl \ XGraphicObject.idl \ - XGraphicTransformer.idl + XGraphicTransformer.idl \ + XPrimitive2DRenderer.idl \ + XSvgParser.idl # --- Targets ------------------------------------------------------ diff --git a/postprocess/packcomponents/makefile.mk b/postprocess/packcomponents/makefile.mk index e931d838bcdb..4dffeeedbc6b 100644 --- a/postprocess/packcomponents/makefile.mk +++ b/postprocess/packcomponents/makefile.mk @@ -55,12 +55,14 @@ my_components = \ charttools \ chartview \ component/comphelper/util/comphelp \ + component/drawinglayer/drawinglayer \ component/framework/util/fwk \ component/framework/util/fwl \ component/framework/util/fwm \ component/vbahelper/util/msforms \ component/sfx2/util/sfx \ component/sot/util/sot \ + component/svgio/svgio \ component/svl/source/fsstor/fsstorage \ component/svl/source/passwordcontainer/passwordcontainer \ component/svl/util/svl \ diff --git a/postprocess/prj/build.lst b/postprocess/prj/build.lst index dfcb4c893ef7..4503e6806306 100644 --- a/postprocess/prj/build.lst +++ b/postprocess/prj/build.lst @@ -1,4 +1,4 @@ -po postprocess :: accessibility automation basctl bean BINFILTER:binfilter chart2 configmgr CRASHREP:crashrep cui dbaccess desktop dtrans embeddedobj embedserv EPM:epm eventattacher extensions extras fileaccess filter forms fpicker helpcontent2 hwpfilter io JAVAINSTALLER2:javainstaller2 lingucomponent MATHMLDTD:MathMLDTD ODK:odk officecfg package padmin psprint_config remotebridges sc scaddins scp2 scripting sd setup_native slideshow starmath sw sysui testtools ucb UnoControls unoxml ure wizards xmerge xmlsecurity MORE_FONTS:more_fonts OOo:pyuno OOo:readlicense_oo SO:top unodevtools JFREEREPORT:jfreereport REPORTBUILDER:reportbuilder reportdesign SDEXT:sdext SWEXT:swext smoketestdoc uui writerfilter oox MYSQLC:mysqlc LIBXSLT:libxslt NULL +po postprocess :: svgio accessibility automation basctl bean BINFILTER:binfilter chart2 configmgr CRASHREP:crashrep cui dbaccess desktop dtrans embeddedobj embedserv EPM:epm eventattacher extensions extras fileaccess filter forms fpicker helpcontent2 hwpfilter io JAVAINSTALLER2:javainstaller2 lingucomponent MATHMLDTD:MathMLDTD ODK:odk officecfg package padmin psprint_config remotebridges sc scaddins scp2 scripting sd setup_native slideshow starmath sw sysui testtools ucb UnoControls unoxml ure wizards xmerge xmlsecurity MORE_FONTS:more_fonts OOo:pyuno OOo:readlicense_oo SO:top unodevtools JFREEREPORT:jfreereport REPORTBUILDER:reportbuilder reportdesign SDEXT:sdext SWEXT:swext smoketestdoc uui writerfilter oox MYSQLC:mysqlc LIBXSLT:libxslt NULL po postprocess usr1 - all po_mkout NULL po postprocess\checkxml nmake - all po_checkxml NULL po postprocess\checkdeliver nmake - all po_checkdlv NULL diff --git a/scp2/source/ooo/file_library_ooo.scp b/scp2/source/ooo/file_library_ooo.scp index 419ff7c6117d..521718c1532d 100755 --- a/scp2/source/ooo/file_library_ooo.scp +++ b/scp2/source/ooo/file_library_ooo.scp @@ -378,6 +378,7 @@ End #endif STD_LIB_FILE(gid_File_Lib_Drawinglayer,drawinglayer) +STD_LIB_FILE(gid_File_Lib_SvgIo,svgio) SPECIAL_LIB_FILE(gid_File_Lib_Embobj,embobj) diff --git a/scp2/source/ooo/module_hidden_ooo.scp b/scp2/source/ooo/module_hidden_ooo.scp index 01eda12cd10f..c4bff2b139f5 100644 --- a/scp2/source/ooo/module_hidden_ooo.scp +++ b/scp2/source/ooo/module_hidden_ooo.scp @@ -173,6 +173,7 @@ Module gid_Module_Root_Files_4 gid_File_Lib_Dbt, gid_File_Lib_Dbfile, gid_File_Lib_Drawinglayer, + gid_File_Lib_SvgIo, gid_File_Lib_Editeng, gid_File_Lib_Flat, gid_File_Lib_For, diff --git a/sd/source/ui/view/drviews2.cxx b/sd/source/ui/view/drviews2.cxx index 732abf866dec..ba0afc2b0b57 100755 --- a/sd/source/ui/view/drviews2.cxx +++ b/sd/source/ui/view/drviews2.cxx @@ -627,7 +627,9 @@ void DrawViewShell::FuTemporary(SfxRequest& rReq) else { if( mpDrawView->IsVectorizeAllowed() ) + { SetCurrentFunction( FuVectorize::Create( this, GetActiveWindow(), mpDrawView, GetDoc(), rReq ) ); + } else { WaitObject aWait( (Window*)GetActiveWindow() ); @@ -709,8 +711,31 @@ void DrawViewShell::FuTemporary(SfxRequest& rReq) break; case SID_CONVERT_TO_BITMAP: { - Bitmap aBitmap (mpDrawView->GetAllMarkedBitmap ()); - aGraphic = Graphic(aBitmap); + bool bDone(false); + + // I have to get the image here directly since GetAllMarkedBitmap works + // based on Bitmaps, but not on BitmapEx, thus throwing away the alpha + // channel. Argh! GetAllMarkedBitmap itself is too widely used to safely + // change that, e.g. in the exchange formats. For now I can only add this + // exception to get good results for Svgs. This is how the code gets more + // and more crowded, at last I made a remark for myself to change this + // as one of the next tasks. + if(1 == mpDrawView->GetMarkedObjectCount()) + { + const SdrGrafObj* pSdrGrafObj = dynamic_cast< const SdrGrafObj* >(mpDrawView->GetMarkedObjectByIndex(0)); + + if(pSdrGrafObj && pSdrGrafObj->isEmbeddedSvg()) + { + aGraphic = Graphic(pSdrGrafObj->GetGraphic().getSvgData()->getReplacement()); + bDone = true; + } + } + + if(!bDone) + { + Bitmap aBitmap (mpDrawView->GetAllMarkedBitmap ()); + aGraphic = Graphic(aBitmap); + } } break; } diff --git a/sd/source/ui/view/drviews6.cxx b/sd/source/ui/view/drviews6.cxx index 4bedfdb69663..17ec4618c075 100755 --- a/sd/source/ui/view/drviews6.cxx +++ b/sd/source/ui/view/drviews6.cxx @@ -446,7 +446,7 @@ void DrawViewShell::GetBmpMaskState( SfxItemSet& rSet ) // valid graphic object? if( pObj && pObj->ISA( SdrGrafObj ) && - !( ((SdrGrafObj*) pObj)->IsEPS() || ((SdrGrafObj*) pObj)->IsRenderGraphic() ) && + !((SdrGrafObj*) pObj)->IsEPS() && !mpDrawView->IsTextEdit() ) { bEnable = sal_True; diff --git a/sd/source/ui/view/drviews7.cxx b/sd/source/ui/view/drviews7.cxx index cc7ba64df08d..cb1423cc359d 100755 --- a/sd/source/ui/view/drviews7.cxx +++ b/sd/source/ui/view/drviews7.cxx @@ -1426,11 +1426,17 @@ void DrawViewShell::GetMenuState( SfxItemSet &rSet ) bFoundMetafile = true; break; case OBJ_GRAF : + { bSingleGraphicSelected = nMarkCount == 1; - switch ( ((SdrGrafObj*)pObj)->GetGraphicType() ) + const SdrGrafObj* pSdrGrafObj = static_cast< const SdrGrafObj* >(pObj); + switch(pSdrGrafObj->GetGraphicType()) { case GRAPHIC_BITMAP : bFoundBitmap = sal_True; + if(pSdrGrafObj->isEmbeddedSvg()) + { + bFoundMetafile = true; + } break; case GRAPHIC_GDIMETAFILE : bFoundMetafile = sal_True; @@ -1442,6 +1448,7 @@ void DrawViewShell::GetMenuState( SfxItemSet &rSet ) // #i25616# bFoundObjNoLine = sal_True; // #i25616# bFoundObjNoArea = sal_True; break; + } case OBJ_TABLE: bFoundTable = true; break; diff --git a/sd/source/ui/view/drviewsc.cxx b/sd/source/ui/view/drviewsc.cxx index b5dbab402d0d..e325dc721991 100755 --- a/sd/source/ui/view/drviewsc.cxx +++ b/sd/source/ui/view/drviewsc.cxx @@ -363,10 +363,23 @@ void DrawViewShell::FuTemp03(SfxRequest& rReq) SdrObject* pObj=pM->GetMarkedSdrObj(); SdrGrafObj* pGraf=PTR_CAST(SdrGrafObj,pObj); SdrOle2Obj* pOle2=PTR_CAST(SdrOle2Obj,pObj); - if (pGraf!=NULL && pGraf->HasGDIMetaFile()) - nCount += pGraf->GetGraphic().GetGDIMetaFile().GetActionCount(); - if(pOle2!=NULL && pOle2->GetGraphic()) + + if(pGraf) + { + if(pGraf->HasGDIMetaFile()) + { + nCount += pGraf->GetGraphic().GetGDIMetaFile().GetActionCount(); + } + else if(pGraf->isEmbeddedSvg()) + { + nCount += pGraf->getMetafileFromEmbeddedSvg().GetActionCount(); + } + } + + if(pOle2 && pOle2->GetGraphic()) + { nCount += pOle2->GetGraphic()->GetGDIMetaFile().GetActionCount(); + } } // anhand der erm. Summe entscheiden ob mit diff --git a/sd/source/ui/view/drviewsj.cxx b/sd/source/ui/view/drviewsj.cxx index 5992b678d7af..40366a4ee555 100755 --- a/sd/source/ui/view/drviewsj.cxx +++ b/sd/source/ui/view/drviewsj.cxx @@ -127,22 +127,22 @@ void DrawViewShell::GetMenuStateSel( SfxItemSet &rSet ) SFX_ITEM_AVAILABLE == rSet.GetItemState( SID_TEXTATTR_DLG ) ) { const SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj(); + const SdrGrafObj* pSdrGrafObj = dynamic_cast< const SdrGrafObj* >(pObj); + const SdrOle2Obj* pSdrOle2Obj = dynamic_cast< const SdrOle2Obj* >(pObj); sal_uInt32 nInv = pObj->GetObjInventor(); sal_uInt16 nId = pObj->GetObjIdentifier(); SdrObjTransformInfoRec aInfoRec; pObj->TakeObjInfo( aInfoRec ); - // #91929#; don't show original size entry if not possible - if ( pObj->ISA( SdrOle2Obj ) ) + if(pSdrOle2Obj) { - SdrOle2Obj* pOleObj = PTR_CAST(SdrOle2Obj, pObj); - if (pOleObj->GetObjRef().is() && - ((pOleObj->GetObjRef()->getStatus( pOleObj->GetAspect() ) & embed::EmbedMisc::MS_EMBED_RECOMPOSEONRESIZE) ) ) + if (pSdrOle2Obj->GetObjRef().is() && + ((pSdrOle2Obj->GetObjRef()->getStatus( pSdrOle2Obj->GetAspect() ) & embed::EmbedMisc::MS_EMBED_RECOMPOSEONRESIZE) ) ) rSet.DisableItem(SID_ORIGINAL_SIZE); } - if ( !( pObj->ISA( SdrGrafObj ) ) ) + if(!pSdrGrafObj) { rSet.DisableItem(SID_SAVEGRAPHIC); } @@ -167,9 +167,10 @@ void DrawViewShell::GetMenuStateSel( SfxItemSet &rSet ) rSet.DisableItem( SID_NAME_GROUP ); } */ - if (!pObj->ISA(SdrGrafObj) || - ((SdrGrafObj*) pObj)->GetGraphicType() != GRAPHIC_BITMAP || - ((SdrGrafObj*) pObj)->IsLinkedGraphic()) + if(!pSdrGrafObj || + pSdrGrafObj->GetGraphicType() != GRAPHIC_BITMAP || + pSdrGrafObj->IsLinkedGraphic() || + pSdrGrafObj->isEmbeddedSvg()) { rSet.DisableItem(SID_CONVERT_TO_1BIT_THRESHOLD); rSet.DisableItem(SID_CONVERT_TO_1BIT_MATRIX); diff --git a/sd/source/ui/view/sdview.cxx b/sd/source/ui/view/sdview.cxx index ec4b371bf244..cf096a396b27 100755 --- a/sd/source/ui/view/sdview.cxx +++ b/sd/source/ui/view/sdview.cxx @@ -1073,10 +1073,15 @@ sal_Bool View::IsVectorizeAllowed() const if( rMarkList.GetMarkCount() == 1 ) { - const SdrObject* pObj = rMarkList.GetMark( 0 )->GetMarkedSdrObj(); + const SdrGrafObj* pObj = dynamic_cast< const SdrGrafObj* >(rMarkList.GetMark( 0 )->GetMarkedSdrObj()); - if( pObj->ISA( SdrGrafObj ) && ( (SdrGrafObj*) pObj )->GetGraphicType() == GRAPHIC_BITMAP ) - bRet = sal_True; + if(pObj) + { + if(GRAPHIC_BITMAP == pObj->GetGraphicType() && !pObj->isEmbeddedSvg()) + { + bRet = sal_True; + } + } } return bRet; diff --git a/sd/source/ui/view/sdview3.cxx b/sd/source/ui/view/sdview3.cxx index 3ed80ae038ed..7f95b212aabe 100755 --- a/sd/source/ui/view/sdview3.cxx +++ b/sd/source/ui/view/sdview3.cxx @@ -219,7 +219,6 @@ if( aPreviewSizePixel.Width() && aPreviewSizePixel.Height() ) case META_GRADIENTEX_ACTION: case META_BMPSCALEPART_ACTION: case META_BMPEXSCALEPART_ACTION: - case META_RENDERGRAPHIC_ACTION: bVector = true; break; case META_BMP_ACTION: diff --git a/sd/source/ui/view/sdview4.cxx b/sd/source/ui/view/sdview4.cxx index 6a34c5265f59..1f5e0f28f567 100755 --- a/sd/source/ui/view/sdview4.cxx +++ b/sd/source/ui/view/sdview4.cxx @@ -395,8 +395,10 @@ IMPL_LINK( View, DropInsertFileHdl, Timer*, EMPTYARG ) const bool bLink = ( ( nTempAction & DND_ACTION_LINK ) != 0 ); SdrGrafObj* pGrafObj = InsertGraphic( aGraphic, nTempAction, maDropPos, NULL, NULL ); - if( pGrafObj && bLink ) + if(pGrafObj && bLink) + { pGrafObj->SetGraphicLink( aCurrentDropFile, String() ); + } // return action from first inserted graphic if( aIter == maDropFileVector.begin() ) diff --git a/solenv/inc/libs.mk b/solenv/inc/libs.mk index 4bcc55756c2d..030d87a79e03 100644 --- a/solenv/inc/libs.mk +++ b/solenv/inc/libs.mk @@ -139,6 +139,7 @@ VCLLIB=-lvcl$(DLLPOSTFIX) OOXLIB=-loox$(DLLPOSTFIX) BASEGFXLIB=-lbasegfx$(DLLPOSTFIX) DRAWINGLAYERLIB=-ldrawinglayer$(DLLPOSTFIX) +SVGIOLIB=-lsvgio$(DLLPOSTFIX) BASEBMPLIB=-lbasebmp$(DLLPOSTFIX) CANVASTOOLSLIB=-lcanvastools$(DLLPOSTFIX) CPPCANVASLIB=-lcppcanvas$(DLLPOSTFIX) @@ -463,6 +464,7 @@ VCLLIB=ivcl.lib OOXLIB=ioox.lib BASEGFXLIB=ibasegfx.lib DRAWINGLAYERLIB=idrawinglayer.lib +SVGIOLIB=isvgio.lib BASEBMPLIB=ibasebmp.lib CANVASTOOLSLIB=icanvastools.lib CPPCANVASLIB=icppcanvas.lib diff --git a/splitbuild/framework.lst b/splitbuild/framework.lst index 1333e7dc7eec..30a9d55e04a9 100644 --- a/splitbuild/framework.lst +++ b/splitbuild/framework.lst @@ -1 +1 @@ -automation avmedia basic basctl cui desktop drawinglayer extensions forms formula framework idl scripting sfx2 svx xmlsecurity vbahelper +automation avmedia basic basctl cui desktop drawinglayer svgio extensions forms formula framework idl scripting sfx2 svx xmlsecurity vbahelper diff --git a/svgio/Library_svgio.mk b/svgio/Library_svgio.mk new file mode 100644 index 000000000000..0d80f85a63f9 --- /dev/null +++ b/svgio/Library_svgio.mk @@ -0,0 +1,93 @@ +#/************************************************************** +# * +# * Licensed to the Apache Software Foundation (ASF) under one +# * or more contributor license agreements. See the NOTICE file +# * distributed with this work for additional information +# * regarding copyright ownership. The ASF licenses this file +# * to you under the Apache License, Version 2.0 (the +# * "License"); you may not use this file except in compliance +# * with the License. You may obtain a copy of the License at +# * +# * http://www.apache.org/licenses/LICENSE-2.0 +# * +# * Unless required by applicable law or agreed to in writing, +# * software distributed under the License is distributed on an +# * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# * KIND, either express or implied. See the License for the +# * specific language governing permissions and limitations +# * under the License. +# * +# *************************************************************/ + +$(eval $(call gb_Library_Library,svgio)) + +$(eval $(call gb_Library_set_componentfile,svgio,svgio/svgio)) + +$(eval $(call gb_Library_add_package_headers,svgio,svgio_inc)) + +$(eval $(call gb_Library_add_precompiled_header,svgio,$(SRCDIR)/svgio/inc/pch/precompiled_svgio)) + +$(eval $(call gb_Library_set_include,svgio,\ + $$(INCLUDE) \ + -I$(SRCDIR)/svgio/inc \ + -I$(SRCDIR)/svgio/inc/pch \ + -I$(SRCDIR)/solenv/inc \ + -I$(OUTDIR)/inc/offuh \ +)) + +$(eval $(call gb_Library_set_defs,svgio,\ + $$(DEFS) \ + -DSVGIO_DLLIMPLEMENTATION \ +)) + +$(eval $(call gb_Library_add_linked_libs,svgio,\ + basegfx \ + drawinglayer \ + comphelper \ + cppu \ + cppuhelper \ + sal \ + stl \ + tl \ + sax \ + vcl \ + svt \ + $(gb_STDLIBS) \ +)) + +$(eval $(call gb_Library_add_exception_objects,svgio,\ + svgio/source/svgreader/svgcharacternode \ + svgio/source/svgreader/svgcirclenode \ + svgio/source/svgreader/svgclippathnode \ + svgio/source/svgreader/svgdocument \ + svgio/source/svgreader/svgdocumenthandler \ + svgio/source/svgreader/svgellipsenode \ + svgio/source/svgreader/svggnode \ + svgio/source/svgreader/svggradientnode \ + svgio/source/svgreader/svggradientstopnode \ + svgio/source/svgreader/svgimagenode \ + svgio/source/svgreader/svglinenode \ + svgio/source/svgreader/svgmarkernode \ + svgio/source/svgreader/svgmasknode \ + svgio/source/svgreader/svgnode \ + svgio/source/svgreader/svgpaint \ + svgio/source/svgreader/svgpathnode \ + svgio/source/svgreader/svgpatternnode \ + svgio/source/svgreader/svgpolynode \ + svgio/source/svgreader/svgrectnode \ + svgio/source/svgreader/svgstyleattributes \ + svgio/source/svgreader/svgstylenode \ + svgio/source/svgreader/svgsvgnode \ + svgio/source/svgreader/svgsymbolnode \ + svgio/source/svgreader/svgtextnode \ + svgio/source/svgreader/svgtoken \ + svgio/source/svgreader/svgtrefnode \ + svgio/source/svgreader/svgtools \ + svgio/source/svgreader/svgtextpathnode \ + svgio/source/svgreader/svgtspannode \ + svgio/source/svgreader/svgusenode \ + svgio/source/svguno/svguno \ + svgio/source/svguno/xsvgparser \ +)) + +# vim: set noet sw=4 ts=4: diff --git a/svgio/Makefile b/svgio/Makefile new file mode 100644 index 000000000000..631870fb0980 --- /dev/null +++ b/svgio/Makefile @@ -0,0 +1,32 @@ +#/************************************************************** +# * +# * Licensed to the Apache Software Foundation (ASF) under one +# * or more contributor license agreements. See the NOTICE file +# * distributed with this work for additional information +# * regarding copyright ownership. The ASF licenses this file +# * to you under the Apache License, Version 2.0 (the +# * "License"); you may not use this file except in compliance +# * with the License. You may obtain a copy of the License at +# * +# * http://www.apache.org/licenses/LICENSE-2.0 +# * +# * Unless required by applicable law or agreed to in writing, +# * software distributed under the License is distributed on an +# * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# * KIND, either express or implied. See the License for the +# * specific language governing permissions and limitations +# * under the License. +# * +# *************************************************************/ + +ifeq ($(strip $(SOLARENV)),) +$(error No environment set!) +endif + +gb_PARTIALBUILD := T +GBUILDDIR := $(SOLARENV)/gbuild +include $(GBUILDDIR)/gbuild.mk + +$(eval $(call gb_Module_make_global_targets,$(shell ls $(dir $(realpath $(firstword $(MAKEFILE_LIST))))/Module*.mk))) + +# vim: set noet sw=4 ts=4: diff --git a/svgio/Module_svgio.mk b/svgio/Module_svgio.mk new file mode 100644 index 000000000000..4ca9474263e4 --- /dev/null +++ b/svgio/Module_svgio.mk @@ -0,0 +1,29 @@ +#/************************************************************** +# * +# * Licensed to the Apache Software Foundation (ASF) under one +# * or more contributor license agreements. See the NOTICE file +# * distributed with this work for additional information +# * regarding copyright ownership. The ASF licenses this file +# * to you under the Apache License, Version 2.0 (the +# * "License"); you may not use this file except in compliance +# * with the License. You may obtain a copy of the License at +# * +# * http://www.apache.org/licenses/LICENSE-2.0 +# * +# * Unless required by applicable law or agreed to in writing, +# * software distributed under the License is distributed on an +# * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# * KIND, either express or implied. See the License for the +# * specific language governing permissions and limitations +# * under the License. +# * +# *************************************************************/ + +$(eval $(call gb_Module_Module,svgio)) + +$(eval $(call gb_Module_add_targets,svgio,\ + Library_svgio \ + Package_inc \ +)) + +# vim: set noet ts=4 sw=4: diff --git a/svgio/Package_inc.mk b/svgio/Package_inc.mk new file mode 100644 index 000000000000..0bd9ea0ac244 --- /dev/null +++ b/svgio/Package_inc.mk @@ -0,0 +1,53 @@ +#/************************************************************** +# * +# * Licensed to the Apache Software Foundation (ASF) under one +# * or more contributor license agreements. See the NOTICE file +# * distributed with this work for additional information +# * regarding copyright ownership. The ASF licenses this file +# * to you under the Apache License, Version 2.0 (the +# * "License"); you may not use this file except in compliance +# * with the License. You may obtain a copy of the License at +# * +# * http://www.apache.org/licenses/LICENSE-2.0 +# * +# * Unless required by applicable law or agreed to in writing, +# * software distributed under the License is distributed on an +# * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# * KIND, either express or implied. See the License for the +# * specific language governing permissions and limitations +# * under the License. +# * +# *************************************************************/ + +$(eval $(call gb_Package_Package,svgio_inc,$(SRCDIR)/svgio/inc)) +$(eval $(call gb_Package_add_file,svgio_inc,inc/svgio/svgiodllapi.h,svgio/svgiodllapi.h)) +$(eval $(call gb_Package_add_file,svgio_inc,inc/svgio/svgreader/svgcharacternode.hxx,svgio/svgreader/svgcharacternode.hxx)) +$(eval $(call gb_Package_add_file,svgio_inc,inc/svgio/svgreader/svgcirclenode.hxx,svgio/svgreader/svgcirclenode.hxx)) +$(eval $(call gb_Package_add_file,svgio_inc,inc/svgio/svgreader/svgclippathnode.hxx,svgio/svgreader/svgclippathnode.hxx)) +$(eval $(call gb_Package_add_file,svgio_inc,inc/svgio/svgreader/svgdocument.hxx,svgio/svgreader/svgdocument.hxx)) +$(eval $(call gb_Package_add_file,svgio_inc,inc/svgio/svgreader/svgdocumenthandler.hxx,svgio/svgreader/svgdocumenthandler.hxx)) +$(eval $(call gb_Package_add_file,svgio_inc,inc/svgio/svgreader/svgellipsenode.hxx,svgio/svgreader/svgellipsenode.hxx)) +$(eval $(call gb_Package_add_file,svgio_inc,inc/svgio/svgreader/svggnode.hxx,svgio/svgreader/svggnode.hxx)) +$(eval $(call gb_Package_add_file,svgio_inc,inc/svgio/svgreader/svggradientnode.hxx,svgio/svgreader/svggradientnode.hxx)) +$(eval $(call gb_Package_add_file,svgio_inc,inc/svgio/svgreader/svggradientstopnode.hxx,svgio/svgreader/svggradientstopnode.hxx)) +$(eval $(call gb_Package_add_file,svgio_inc,inc/svgio/svgreader/svgimagenode.hxx,svgio/svgreader/svgimagenode.hxx)) +$(eval $(call gb_Package_add_file,svgio_inc,inc/svgio/svgreader/svglinenode.hxx,svgio/svgreader/svglinenode.hxx)) +$(eval $(call gb_Package_add_file,svgio_inc,inc/svgio/svgreader/svgnode.hxx,svgio/svgreader/svgnode.hxx)) +$(eval $(call gb_Package_add_file,svgio_inc,inc/svgio/svgreader/svgmarkernode.hxx,svgio/svgreader/svgmarkernode.hxx)) +$(eval $(call gb_Package_add_file,svgio_inc,inc/svgio/svgreader/svgmasknode.hxx,svgio/svgreader/svgmasknode.hxx)) +$(eval $(call gb_Package_add_file,svgio_inc,inc/svgio/svgreader/svgpaint.hxx,svgio/svgreader/svgpaint.hxx)) +$(eval $(call gb_Package_add_file,svgio_inc,inc/svgio/svgreader/svgpathnode.hxx,svgio/svgreader/svgpathnode.hxx)) +$(eval $(call gb_Package_add_file,svgio_inc,inc/svgio/svgreader/svgpatternnode.hxx,svgio/svgreader/svgpatternnode.hxx)) +$(eval $(call gb_Package_add_file,svgio_inc,inc/svgio/svgreader/svgpolynode.hxx,svgio/svgreader/svgpolynode.hxx)) +$(eval $(call gb_Package_add_file,svgio_inc,inc/svgio/svgreader/svgrectnode.hxx,svgio/svgreader/svgrectnode.hxx)) +$(eval $(call gb_Package_add_file,svgio_inc,inc/svgio/svgreader/svgstyleattributes.hxx,svgio/svgreader/svgstyleattributes.hxx)) +$(eval $(call gb_Package_add_file,svgio_inc,inc/svgio/svgreader/svgstylenode.hxx,svgio/svgreader/svgstylenode.hxx)) +$(eval $(call gb_Package_add_file,svgio_inc,inc/svgio/svgreader/svgsvgnode.hxx,svgio/svgreader/svgsvgnode.hxx)) +$(eval $(call gb_Package_add_file,svgio_inc,inc/svgio/svgreader/svgsymbolnode.hxx,svgio/svgreader/svgsymbolnode.hxx)) +$(eval $(call gb_Package_add_file,svgio_inc,inc/svgio/svgreader/svgtextnode.hxx,svgio/svgreader/svgtextnode.hxx)) +$(eval $(call gb_Package_add_file,svgio_inc,inc/svgio/svgreader/svgtoken.hxx,svgio/svgreader/svgtoken.hxx)) +$(eval $(call gb_Package_add_file,svgio_inc,inc/svgio/svgreader/svgtrefnode.hxx,svgio/svgreader/svgtrefnode.hxx)) +$(eval $(call gb_Package_add_file,svgio_inc,inc/svgio/svgreader/svgtools.hxx,svgio/svgreader/svgtools.hxx)) +$(eval $(call gb_Package_add_file,svgio_inc,inc/svgio/svgreader/svgtextpathnode.hxx,svgio/svgreader/svgtextpathnode.hxx)) +$(eval $(call gb_Package_add_file,svgio_inc,inc/svgio/svgreader/svgtspannode.hxx,svgio/svgreader/svgtspannode.hxx)) +$(eval $(call gb_Package_add_file,svgio_inc,inc/svgio/svgreader/svgusenode.hxx,svgio/svgreader/svgusenode.hxx)) diff --git a/svgio/inc/makefile.mk b/svgio/inc/makefile.mk new file mode 100644 index 000000000000..39e5dee8bbed --- /dev/null +++ b/svgio/inc/makefile.mk @@ -0,0 +1,41 @@ +#/************************************************************** +# * +# * Licensed to the Apache Software Foundation (ASF) under one +# * or more contributor license agreements. See the NOTICE file +# * distributed with this work for additional information +# * regarding copyright ownership. The ASF licenses this file +# * to you under the Apache License, Version 2.0 (the +# * "License"); you may not use this file except in compliance +# * with the License. You may obtain a copy of the License at +# * +# * http://www.apache.org/licenses/LICENSE-2.0 +# * +# * Unless required by applicable law or agreed to in writing, +# * software distributed under the License is distributed on an +# * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# * KIND, either express or implied. See the License for the +# * specific language governing permissions and limitations +# * under the License. +# * +# *************************************************************/ +PRJ=.. + +PRJNAME=svgio +TARGET=inc + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# --- Files -------------------------------------------------------- +# --- Targets ------------------------------------------------------- + +.INCLUDE : target.mk + +.IF "$(ENABLE_PCH)"!="" +ALLTAR : \ + $(SLO)$/precompiled.pch \ + $(SLO)$/precompiled_ex.pch + +.ENDIF # "$(ENABLE_PCH)"!="" + diff --git a/svgio/inc/pch/precompiled_svgio.cxx b/svgio/inc/pch/precompiled_svgio.cxx new file mode 100644 index 000000000000..bb4be3a78fe1 --- /dev/null +++ b/svgio/inc/pch/precompiled_svgio.cxx @@ -0,0 +1,23 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +#include "precompiled_svgio.hxx" + diff --git a/svgio/inc/pch/precompiled_svgio.hxx b/svgio/inc/pch/precompiled_svgio.hxx new file mode 100644 index 000000000000..1f660d13c16d --- /dev/null +++ b/svgio/inc/pch/precompiled_svgio.hxx @@ -0,0 +1,26 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +// MARKER(update_precomp.py): Generated on 2006-09-01 17:49:30.796084 + +#ifdef PRECOMPILED_HEADERS +#endif + diff --git a/svgio/inc/svgio/svgiodllapi.h b/svgio/inc/svgio/svgiodllapi.h new file mode 100644 index 000000000000..2d4265a18a68 --- /dev/null +++ b/svgio/inc/svgio/svgiodllapi.h @@ -0,0 +1,33 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ +#ifndef INCLUDED_SVGIODLLAPI_H +#define INCLUDED_SVGIODLLAPI_H + +#include "sal/types.h" + +#if defined(SVGIO_DLLIMPLEMENTATION) +#define SVGIO_DLLPUBLIC SAL_DLLPUBLIC_EXPORT +#else +#define SVGIO_DLLPUBLIC SAL_DLLPUBLIC_IMPORT +#endif +#define SVGIO_DLLPRIVATE SAL_DLLPRIVATE + +#endif /* INCLUDED_SVGIODLLAPI_H */ diff --git a/svgio/inc/svgio/svgreader/svgcharacternode.hxx b/svgio/inc/svgio/svgreader/svgcharacternode.hxx new file mode 100644 index 000000000000..6b135b8dcb9d --- /dev/null +++ b/svgio/inc/svgio/svgreader/svgcharacternode.hxx @@ -0,0 +1,184 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +#ifndef INCLUDED_SVGIO_SVGREADER_SVGCHARACTERNODE_HXX +#define INCLUDED_SVGIO_SVGREADER_SVGCHARACTERNODE_HXX + +#include <svgio/svgiodllapi.h> +#include <svgio/svgreader/svgnode.hxx> + +////////////////////////////////////////////////////////////////////////////// +// predefines + +namespace drawinglayer { namespace primitive2d { class TextSimplePortionPrimitive2D; }} + +////////////////////////////////////////////////////////////////////////////// + +namespace svgio +{ + namespace svgreader + { + class SvgTextPositions + { + private: + SvgNumberVector maX; + SvgNumberVector maY; + SvgNumberVector maDx; + SvgNumberVector maDy; + SvgNumberVector maRotate; + SvgNumber maTextLength; + + /// bitfield + bool mbLengthAdjust : 1; // true = spacing, false = spacingAndGlyphs + + public: + SvgTextPositions(); + + void parseTextPositionAttributes(const rtl::OUString& rTokenName, SVGToken aSVGToken, const rtl::OUString& aContent); + + /// X content + const SvgNumberVector& getX() const { return maX; } + void setX(const SvgNumberVector& aX) { maX = aX; } + + /// Y content + const SvgNumberVector& getY() const { return maY; } + void setY(const SvgNumberVector& aY) { maY = aY; } + + /// Dx content + const SvgNumberVector& getDx() const { return maDx; } + void setDx(const SvgNumberVector& aDx) { maDx = aDx; } + + /// Dy content + const SvgNumberVector& getDy() const { return maDy; } + void setDy(const SvgNumberVector& aDy) { maDy = aDy; } + + /// Rotate content + const SvgNumberVector& getRotate() const { return maRotate; } + void setRotate(const SvgNumberVector& aRotate) { maRotate = aRotate; } + + /// TextLength content + const SvgNumber& getTextLength() const { return maTextLength; } + void setTextLength(const SvgNumber& rTextLength = SvgNumber()) { maTextLength = rTextLength; } + + /// LengthAdjust content + bool getLengthAdjust() const { return mbLengthAdjust; } + void setLengthAdjust(bool bNew) { mbLengthAdjust = bNew; } + }; + } // end of namespace svgreader +} // end of namespace svgio + +////////////////////////////////////////////////////////////////////////////// + +namespace svgio +{ + namespace svgreader + { + class SvgTextPosition + { + private: + SvgTextPosition* mpParent; + ::std::vector< double > maX; + ::std::vector< double > maY; + ::std::vector< double > maRotate; + double mfTextLength; + + // absolute, current, advancing position + basegfx::B2DPoint maPosition; + + // advancing rotation index + sal_uInt32 mnRotationIndex; + + /// bitfield + bool mbLengthAdjust : 1; // true = spacing, false = spacingAndGlyphs + bool mbAbsoluteX : 1; + bool mbAbsoluteY : 1; + + public: + SvgTextPosition( + SvgTextPosition* pParent, + const InfoProvider& rInfoProvider, + const SvgTextPositions& rSvgTextPositions); + + // data read access + const SvgTextPosition* getParent() const { return mpParent; } + const ::std::vector< double >& getX() const { return maX; } + const ::std::vector< double >& getY() const { return maY; } + double getTextLength() const { return mfTextLength; } + bool getLengthAdjust() const { return mbLengthAdjust; } + bool getAbsoluteX() const { return mbAbsoluteX; } + bool getAbsoluteY() const { return mbAbsoluteY; } + + // get/set absolute, current, advancing position + const basegfx::B2DPoint& getPosition() const { return maPosition; } + void setPosition(const basegfx::B2DPoint& rNew) { maPosition = rNew; } + + // rotation handling + bool isRotated() const; + double consumeRotation(); + }; + } // end of namespace svgreader +} // end of namespace svgio + +////////////////////////////////////////////////////////////////////////////// + +namespace svgio +{ + namespace svgreader + { + class SvgCharacterNode : public SvgNode + { + private: + /// the string data + rtl::OUString maText; + + /// local helpers + drawinglayer::primitive2d::TextSimplePortionPrimitive2D* createSimpleTextPrimitive( + SvgTextPosition& rSvgTextPosition, + const SvgStyleAttributes& rSvgStyleAttributes) const; + void decomposeTextWithStyle( + drawinglayer::primitive2d::Primitive2DSequence& rTarget, + SvgTextPosition& rSvgTextPosition, + const SvgStyleAttributes& rSvgStyleAttributes) const; + + public: + SvgCharacterNode( + SvgDocument& rDocument, + SvgNode* pParent, + const rtl::OUString& rText); + virtual ~SvgCharacterNode(); + + virtual const SvgStyleAttributes* getSvgStyleAttributes() const; + virtual void decomposeText(drawinglayer::primitive2d::Primitive2DSequence& rTarget, SvgTextPosition& rSvgTextPosition) const; + void whiteSpaceHandling(); + void addGap(); + void concatenate(const rtl::OUString& rText); + + /// Text content + const rtl::OUString& getText() const { return maText; } + }; + } // end of namespace svgreader +} // end of namespace svgio + +////////////////////////////////////////////////////////////////////////////// + +#endif //INCLUDED_SVGIO_SVGREADER_SVGCHARACTERNODE_HXX + +// eof diff --git a/svgio/inc/svgio/svgreader/svgcirclenode.hxx b/svgio/inc/svgio/svgreader/svgcirclenode.hxx new file mode 100644 index 000000000000..420cfb93d5ea --- /dev/null +++ b/svgio/inc/svgio/svgreader/svgcirclenode.hxx @@ -0,0 +1,80 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +#ifndef INCLUDED_SVGIO_SVGREADER_SVGCIRCLENODE_HXX +#define INCLUDED_SVGIO_SVGREADER_SVGCIRCLENODE_HXX + +#include <svgio/svgiodllapi.h> +#include <svgio/svgreader/svgnode.hxx> +#include <svgio/svgreader/svgstyleattributes.hxx> + +////////////////////////////////////////////////////////////////////////////// + +namespace svgio +{ + namespace svgreader + { + class SvgCircleNode : public SvgNode + { + private: + /// use styles + SvgStyleAttributes maSvgStyleAttributes; + + /// variable scan values, dependent of given XAttributeList + SvgNumber maCx; + SvgNumber maCy; + SvgNumber maR; + basegfx::B2DHomMatrix* mpaTransform; + + public: + SvgCircleNode( + SvgDocument& rDocument, + SvgNode* pParent); + virtual ~SvgCircleNode(); + + virtual const SvgStyleAttributes* getSvgStyleAttributes() const; + virtual void parseAttribute(const rtl::OUString& rTokenName, SVGToken aSVGToken, const rtl::OUString& aContent); + virtual void decomposeSvgNode(drawinglayer::primitive2d::Primitive2DSequence& rTarget, bool bReferenced) const; + + /// Cx content, set if found in current context + const SvgNumber& getCx() const { return maCx; } + void setCx(const SvgNumber& rCx = SvgNumber()) { maCx = rCx; } + + /// Cy content, set if found in current context + const SvgNumber& getCy() const { return maCy; } + void setCy(const SvgNumber& rCy = SvgNumber()) { maCy = rCy; } + + /// R content, set if found in current context + const SvgNumber& getR() const { return maR; } + void setR(const SvgNumber& rR = SvgNumber()) { maR = rR; } + + /// transform content, set if found in current context + const basegfx::B2DHomMatrix* getTransform() const { return mpaTransform; } + void setTransform(const basegfx::B2DHomMatrix* pMatrix = 0) { if(mpaTransform) delete mpaTransform; mpaTransform = 0; if(pMatrix) mpaTransform = new basegfx::B2DHomMatrix(*pMatrix); } + }; + } // end of namespace svgreader +} // end of namespace svgio + +////////////////////////////////////////////////////////////////////////////// + +#endif //INCLUDED_SVGIO_SVGREADER_SVGCIRCLENODE_HXX + +// eof diff --git a/svgio/inc/svgio/svgreader/svgclippathnode.hxx b/svgio/inc/svgio/svgreader/svgclippathnode.hxx new file mode 100755 index 000000000000..e2fc7cb11f5c --- /dev/null +++ b/svgio/inc/svgio/svgreader/svgclippathnode.hxx @@ -0,0 +1,73 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +#ifndef INCLUDED_SVGIO_SVGREADER_SVGCLIPPATHNODE_HXX +#define INCLUDED_SVGIO_SVGREADER_SVGCLIPPATHNODE_HXX + +#include <svgio/svgiodllapi.h> +#include <svgio/svgreader/svgnode.hxx> +#include <svgio/svgreader/svgstyleattributes.hxx> + +////////////////////////////////////////////////////////////////////////////// + +namespace svgio +{ + namespace svgreader + { + class SvgClipPathNode : public SvgNode + { + private: + /// use styles + SvgStyleAttributes maSvgStyleAttributes; + + /// variable scan values, dependent of given XAttributeList + basegfx::B2DHomMatrix* mpaTransform; + SvgUnits maClipPathUnits; + + public: + SvgClipPathNode( + SvgDocument& rDocument, + SvgNode* pParent); + virtual ~SvgClipPathNode(); + + virtual const SvgStyleAttributes* getSvgStyleAttributes() const; + virtual void parseAttribute(const rtl::OUString& rTokenName, SVGToken aSVGToken, const rtl::OUString& aContent); + virtual void decomposeSvgNode(drawinglayer::primitive2d::Primitive2DSequence& rTarget, bool bReferenced) const; + + /// apply contained clipPath to given geometry + void apply(drawinglayer::primitive2d::Primitive2DSequence& rTarget) const; + + /// clipPathUnits content + SvgUnits getClipPathUnits() const { return maClipPathUnits; } + void setClipPathUnits(const SvgUnits aClipPathUnits) { maClipPathUnits = aClipPathUnits; } + + /// transform content + const basegfx::B2DHomMatrix* getTransform() const { return mpaTransform; } + void setTransform(const basegfx::B2DHomMatrix* pMatrix = 0) { if(mpaTransform) delete mpaTransform; mpaTransform = 0; if(pMatrix) mpaTransform = new basegfx::B2DHomMatrix(*pMatrix); } + }; + } // end of namespace svgreader +} // end of namespace svgio + +////////////////////////////////////////////////////////////////////////////// + +#endif //INCLUDED_SVGIO_SVGREADER_SVGCLIPPATHNODE_HXX + +// eof diff --git a/svgio/inc/svgio/svgreader/svgdocument.hxx b/svgio/inc/svgio/svgreader/svgdocument.hxx new file mode 100644 index 000000000000..ac233784afdf --- /dev/null +++ b/svgio/inc/svgio/svgreader/svgdocument.hxx @@ -0,0 +1,88 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +#ifndef INCLUDED_SVGIO_SVGREADER_SVGDOCUMENT_HXX +#define INCLUDED_SVGIO_SVGREADER_SVGDOCUMENT_HXX + +#include <svgio/svgiodllapi.h> +#include <boost/utility.hpp> +#include <svgio/svgreader/svgnode.hxx> + +////////////////////////////////////////////////////////////////////////////// + +namespace svgio +{ + namespace svgreader + { + class SvgDocument : private boost::noncopyable + { + private: + /// the document hierarchy with all root nodes + SvgNodeVector maNodes; + + /// the absolute path of the Svg file in progress (if available) + const rtl::OUString maAbsolutePath; + + /// hash mapper to find nodes by their id + typedef std::hash_map< const rtl::OUString, const SvgNode*, rtl::OUStringHash > IdTokenMapper; + typedef std::pair< const rtl::OUString, const SvgNode* > IdTokenValueType; + IdTokenMapper maIdTokenMapperList; + + /// hash mapper to find css styles by their id + typedef std::hash_map< const rtl::OUString, const SvgStyleAttributes*, rtl::OUStringHash > IdStyleTokenMapper; + typedef std::pair< const rtl::OUString, const SvgStyleAttributes* > IdStyleTokenValueType; + IdStyleTokenMapper maIdStyleTokenMapperList; + + public: + SvgDocument(const rtl::OUString& rAbsolutePath); + ~SvgDocument(); + + /// append anopther root node, ownership changes + void appendNode(SvgNode* pNode); + + /// add/remove nodes with Id to mapper + void addSvgNodeToMapper(const rtl::OUString& rStr, const SvgNode& rNode); + void removeSvgNodeFromMapper(const rtl::OUString& rStr); + + /// find a node by it's Id + bool hasSvgNodesById() const { return !maIdTokenMapperList.empty(); } + const SvgNode* findSvgNodeById(const rtl::OUString& rStr) const; + + /// add/remove styles to mapper + void addSvgStyleAttributesToMapper(const rtl::OUString& rStr, const SvgStyleAttributes& rSvgStyleAttributes); + void removeSvgStyleAttributesFromMapper(const rtl::OUString& rStr); + + /// find a style by it's Id + bool hasSvgStyleAttributesById() const { return !maIdStyleTokenMapperList.empty(); } + const SvgStyleAttributes* findSvgStyleAttributesById(const rtl::OUString& rStr) const; + + /// data read access + const SvgNodeVector& getSvgNodeVector() const { return maNodes; } + const rtl::OUString& getAbsolutePath() const { return maAbsolutePath; } + }; + } // end of namespace svgreader +} // end of namespace svgio + +////////////////////////////////////////////////////////////////////////////// + +#endif //INCLUDED_SVGIO_SVGREADER_SVGDOCUMENT_HXX + +// eof diff --git a/svgio/inc/svgio/svgreader/svgdocumenthandler.hxx b/svgio/inc/svgio/svgreader/svgdocumenthandler.hxx new file mode 100644 index 000000000000..19b631acb87c --- /dev/null +++ b/svgio/inc/svgio/svgreader/svgdocumenthandler.hxx @@ -0,0 +1,75 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +#ifndef INCLUDED_SVGIO_SVGREADER_SVGDOCUMENTHANDLER_HXX +#define INCLUDED_SVGIO_SVGREADER_SVGDOCUMENTHANDLER_HXX + +#include <svgio/svgiodllapi.h> +#include <com/sun/star/xml/sax/XDocumentHandler.hpp> +#include <svgio/svgreader/svgdocument.hxx> + +////////////////////////////////////////////////////////////////////////////// +// predefines + +namespace svgio { namespace svgreader { class SvgCharacterNode; }} + +////////////////////////////////////////////////////////////////////////////// + +namespace svgio +{ + namespace svgreader + { + class SvgDocHdl : public cppu::WeakImplHelper1< com::sun::star::xml::sax::XDocumentHandler > + { + private: + // the complete SVG Document + SvgDocument maDocument; + + // current node for parsing + SvgNode* mpTarget; + + /// bitfield + bool mbValidToken : 1; + + public: + SvgDocHdl(const rtl::OUString& rAbsolutePath); + ~SvgDocHdl(); + + // Methods XDocumentHandler + virtual void SAL_CALL startDocument( ) throw (com::sun::star::xml::sax::SAXException, com::sun::star::uno::RuntimeException); + virtual void SAL_CALL endDocument( ) throw (com::sun::star::xml::sax::SAXException, com::sun::star::uno::RuntimeException); + virtual void SAL_CALL startElement( const ::rtl::OUString& aName, const com::sun::star::uno::Reference< com::sun::star::xml::sax::XAttributeList >& xAttribs ) throw (com::sun::star::xml::sax::SAXException, com::sun::star::uno::RuntimeException); + virtual void SAL_CALL endElement( const ::rtl::OUString& aName ) throw (com::sun::star::xml::sax::SAXException, com::sun::star::uno::RuntimeException); + virtual void SAL_CALL characters( const ::rtl::OUString& aChars ) throw (com::sun::star::xml::sax::SAXException, com::sun::star::uno::RuntimeException); + virtual void SAL_CALL ignorableWhitespace( const ::rtl::OUString& aWhitespaces ) throw (com::sun::star::xml::sax::SAXException, com::sun::star::uno::RuntimeException); + virtual void SAL_CALL processingInstruction( const ::rtl::OUString& aTarget, const ::rtl::OUString& aData ) throw (com::sun::star::xml::sax::SAXException, com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setDocumentLocator( const com::sun::star::uno::Reference< com::sun::star::xml::sax::XLocator >& xLocator ) throw (com::sun::star::xml::sax::SAXException, com::sun::star::uno::RuntimeException); + + const SvgDocument& getSvgDocument() const { return maDocument; } + }; + } // end of namespace svgreader +} // end of namespace svgio + +////////////////////////////////////////////////////////////////////////////// + +#endif //INCLUDED_SVGIO_SVGREADER_SVGDOCUMENTHANDLER_HXX + +// eof diff --git a/svgio/inc/svgio/svgreader/svgellipsenode.hxx b/svgio/inc/svgio/svgreader/svgellipsenode.hxx new file mode 100644 index 000000000000..108ea288d176 --- /dev/null +++ b/svgio/inc/svgio/svgreader/svgellipsenode.hxx @@ -0,0 +1,85 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +#ifndef INCLUDED_SVGIO_SVGREADER_SVGELLIPSENODE_HXX +#define INCLUDED_SVGIO_SVGREADER_SVGELLIPSENODE_HXX + +#include <svgio/svgiodllapi.h> +#include <svgio/svgreader/svgnode.hxx> +#include <svgio/svgreader/svgstyleattributes.hxx> + +////////////////////////////////////////////////////////////////////////////// + +namespace svgio +{ + namespace svgreader + { + class SvgEllipseNode : public SvgNode + { + private: + /// use styles + SvgStyleAttributes maSvgStyleAttributes; + + /// variable scan values, dependent of given XAttributeList + SvgNumber maCx; + SvgNumber maCy; + SvgNumber maRx; + SvgNumber maRy; + basegfx::B2DHomMatrix* mpaTransform; + + public: + SvgEllipseNode( + SvgDocument& rDocument, + SvgNode* pParent); + virtual ~SvgEllipseNode(); + + virtual const SvgStyleAttributes* getSvgStyleAttributes() const; + virtual void parseAttribute(const rtl::OUString& rTokenName, SVGToken aSVGToken, const rtl::OUString& aContent); + virtual void decomposeSvgNode(drawinglayer::primitive2d::Primitive2DSequence& rTarget, bool bReferenced) const; + + /// Cx content, set if found in current context + const SvgNumber& getCx() const { return maCx; } + void setCx(const SvgNumber& rCx = SvgNumber()) { maCx = rCx; } + + /// Cy content, set if found in current context + const SvgNumber& getCy() const { return maCy; } + void setCy(const SvgNumber& rCy = SvgNumber()) { maCy = rCy; } + + /// Rx content, set if found in current context + const SvgNumber& getRx() const { return maRx; } + void setRx(const SvgNumber& rRx = SvgNumber()) { maRx = rRx; } + + /// Ry content, set if found in current context + const SvgNumber& getRy() const { return maRy; } + void setRy(const SvgNumber& rRy = SvgNumber()) { maRy = rRy; } + + /// transform content, set if found in current context + const basegfx::B2DHomMatrix* getTransform() const { return mpaTransform; } + void setTransform(const basegfx::B2DHomMatrix* pMatrix = 0) { if(mpaTransform) delete mpaTransform; mpaTransform = 0; if(pMatrix) mpaTransform = new basegfx::B2DHomMatrix(*pMatrix); } + }; + } // end of namespace svgreader +} // end of namespace svgio + +////////////////////////////////////////////////////////////////////////////// + +#endif //INCLUDED_SVGIO_SVGREADER_SVGELLIPSENODE_HXX + +// eof diff --git a/svgio/inc/svgio/svgreader/svggnode.hxx b/svgio/inc/svgio/svgreader/svggnode.hxx new file mode 100644 index 000000000000..67929602354d --- /dev/null +++ b/svgio/inc/svgio/svgreader/svggnode.hxx @@ -0,0 +1,66 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +#ifndef INCLUDED_SVGIO_SVGREADER_SVGGNODE_HXX +#define INCLUDED_SVGIO_SVGREADER_SVGGNODE_HXX + +#include <svgio/svgiodllapi.h> +#include <svgio/svgreader/svgnode.hxx> +#include <svgio/svgreader/svgstyleattributes.hxx> + +////////////////////////////////////////////////////////////////////////////// + +namespace svgio +{ + namespace svgreader + { + class SvgGNode : public SvgNode + { + private: + /// use styles + SvgStyleAttributes maSvgStyleAttributes; + + /// variable scan values, dependent of given XAttributeList + basegfx::B2DHomMatrix* mpaTransform; + + public: + SvgGNode( + SVGToken aType, + SvgDocument& rDocument, + SvgNode* pParent); + virtual ~SvgGNode(); + + virtual const SvgStyleAttributes* getSvgStyleAttributes() const; + virtual void parseAttribute(const rtl::OUString& rTokenName, SVGToken aSVGToken, const rtl::OUString& aContent); + virtual void decomposeSvgNode(drawinglayer::primitive2d::Primitive2DSequence& rTarget, bool bReferenced) const; + + /// transform content + const basegfx::B2DHomMatrix* getTransform() const { return mpaTransform; } + void setTransform(const basegfx::B2DHomMatrix* pMatrix = 0) { if(mpaTransform) delete mpaTransform; mpaTransform = 0; if(pMatrix) mpaTransform = new basegfx::B2DHomMatrix(*pMatrix); } + }; + } // end of namespace svgreader +} // end of namespace svgio + +////////////////////////////////////////////////////////////////////////////// + +#endif //INCLUDED_SVGIO_SVGREADER_SVGGNODE_HXX + +// eof diff --git a/svgio/inc/svgio/svgreader/svggradientnode.hxx b/svgio/inc/svgio/svgreader/svggradientnode.hxx new file mode 100644 index 000000000000..b2cf79930365 --- /dev/null +++ b/svgio/inc/svgio/svgreader/svggradientnode.hxx @@ -0,0 +1,137 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +#ifndef INCLUDED_SVGIO_SVGREADER_SVGGRADIENTNODE_HXX +#define INCLUDED_SVGIO_SVGREADER_SVGGRADIENTNODE_HXX + +#include <svgio/svgiodllapi.h> +#include <svgio/svgreader/svgnode.hxx> +#include <svgio/svgreader/svgstyleattributes.hxx> +#include <drawinglayer/primitive2d/svggradientprimitive2d.hxx> + +////////////////////////////////////////////////////////////////////////////// + +namespace svgio +{ + namespace svgreader + { + class SvgGradientNode : public SvgNode + { + private: + /// use styles + SvgStyleAttributes maSvgStyleAttributes; + + /// linear gradient values + SvgNumber maX1; + SvgNumber maY1; + SvgNumber maX2; + SvgNumber maY2; + + /// radial gradient values + SvgNumber maCx; + SvgNumber maCy; + SvgNumber maR; + SvgNumber maFx; + SvgNumber maFy; + + /// variable scan values, dependent of given XAttributeList + SvgUnits maGradientUnits; + drawinglayer::primitive2d::SpreadMethod maSpreadMethod; + basegfx::B2DHomMatrix* mpaGradientTransform; + + /// link to another gradient used as style. If maXLink + /// is set, the node can be fetched on demand by using + // tryToFindLink (buffered) + rtl::OUString maXLink; + const SvgGradientNode* mpXLink; + + /// link on demand + void tryToFindLink(); + + public: + SvgGradientNode( + SVGToken aType, + SvgDocument& rDocument, + SvgNode* pParent); + virtual ~SvgGradientNode(); + + virtual const SvgStyleAttributes* getSvgStyleAttributes() const; + virtual void parseAttribute(const rtl::OUString& rTokenName, SVGToken aSVGToken, const rtl::OUString& aContent); + + /// collect gradient stop entries + void collectGradientEntries(drawinglayer::primitive2d::SvgGradientEntryVector& aVector) const; + + /// x1 content + const SvgNumber getX1() const; + void setX1(const SvgNumber& rX1 = SvgNumber()) { maX1 = rX1; } + + /// y1 content + const SvgNumber getY1() const; + void setY1(const SvgNumber& rY1 = SvgNumber()) { maY1 = rY1; } + + /// x2 content + const SvgNumber getX2() const; + void setX2(const SvgNumber& rX2 = SvgNumber()) { maX2 = rX2; } + + /// y2 content + const SvgNumber getY2() const; + void setY2(const SvgNumber& rY2 = SvgNumber()) { maY2 = rY2; } + + /// Cx content + const SvgNumber getCx() const; + void setCx(const SvgNumber& rCx = SvgNumber()) { maCx = rCx; } + + /// Cy content + const SvgNumber getCy() const; + void setCy(const SvgNumber& rCy = SvgNumber()) { maCy = rCy; } + + /// R content + const SvgNumber getR() const; + void setR(const SvgNumber& rR = SvgNumber()) { maR = rR; } + + /// Fx content + const SvgNumber* getFx() const; + void setFx(const SvgNumber& rFx = SvgNumber()) { maFx = rFx; } + + /// Fy content + const SvgNumber* getFy() const; + void setFy(const SvgNumber& rFy = SvgNumber()) { maFy = rFy; } + + /// gradientUnits content + SvgUnits getGradientUnits() const { return maGradientUnits; } + void setGradientUnits(const SvgUnits aGradientUnits) { maGradientUnits = aGradientUnits; } + + /// SpreadMethod content + drawinglayer::primitive2d::SpreadMethod getSpreadMethod() const { return maSpreadMethod; } + void setSpreadMethod(const drawinglayer::primitive2d::SpreadMethod aSpreadMethod) { maSpreadMethod = aSpreadMethod; } + + /// transform content, set if found in current context + const basegfx::B2DHomMatrix* getGradientTransform() const; + void setGradientTransform(const basegfx::B2DHomMatrix* pMatrix = 0); + }; + } // end of namespace svgreader +} // end of namespace svgio + +////////////////////////////////////////////////////////////////////////////// + +#endif //INCLUDED_SVGIO_SVGREADER_SVGGRADIENTNODE_HXX + +// eof diff --git a/svgio/inc/svgio/svgreader/svggradientstopnode.hxx b/svgio/inc/svgio/svgreader/svggradientstopnode.hxx new file mode 100644 index 000000000000..cc7acbf6cdd7 --- /dev/null +++ b/svgio/inc/svgio/svgreader/svggradientstopnode.hxx @@ -0,0 +1,64 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +#ifndef INCLUDED_SVGIO_SVGREADER_SVGGRADIENTSTOPNODE_HXX +#define INCLUDED_SVGIO_SVGREADER_SVGGRADIENTSTOPNODE_HXX + +#include <svgio/svgiodllapi.h> +#include <svgio/svgreader/svgnode.hxx> +#include <svgio/svgreader/svgstyleattributes.hxx> + +////////////////////////////////////////////////////////////////////////////// + +namespace svgio +{ + namespace svgreader + { + class SvgGradientStopNode : public SvgNode + { + private: + /// use styles + SvgStyleAttributes maSvgStyleAttributes; + + /// local attributes + SvgNumber maOffset; + + public: + SvgGradientStopNode( + SvgDocument& rDocument, + SvgNode* pParent); + virtual ~SvgGradientStopNode(); + + virtual const SvgStyleAttributes* getSvgStyleAttributes() const; + virtual void parseAttribute(const rtl::OUString& rTokenName, SVGToken aSVGToken, const rtl::OUString& aContent); + + /// offset content + const SvgNumber getOffset() const { return maOffset; } + void setOffset(const SvgNumber& rOffset = SvgNumber()) { maOffset = rOffset; } + }; + } // end of namespace svgreader +} // end of namespace svgio + +////////////////////////////////////////////////////////////////////////////// + +#endif //INCLUDED_SVGIO_SVGREADER_SVGGRADIENTSTOPNODE_HXX + +// eof diff --git a/svgio/inc/svgio/svgreader/svgimagenode.hxx b/svgio/inc/svgio/svgreader/svgimagenode.hxx new file mode 100644 index 000000000000..5df5272303cd --- /dev/null +++ b/svgio/inc/svgio/svgreader/svgimagenode.hxx @@ -0,0 +1,99 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +#ifndef INCLUDED_SVGIO_SVGREADER_SVGIMAGENODE_HXX +#define INCLUDED_SVGIO_SVGREADER_SVGIMAGENODE_HXX + +#include <svgio/svgiodllapi.h> +#include <svgio/svgreader/svgnode.hxx> +#include <svgio/svgreader/svgstyleattributes.hxx> + +////////////////////////////////////////////////////////////////////////////// + +namespace svgio +{ + namespace svgreader + { + class SvgImageNode : public SvgNode + { + private: + /// use styles + SvgStyleAttributes maSvgStyleAttributes; + + /// variable scan values, dependent of given XAttributeList + SvgAspectRatio maSvgAspectRatio; + basegfx::B2DHomMatrix* mpaTransform; + SvgNumber maX; + SvgNumber maY; + SvgNumber maWidth; + SvgNumber maHeight; + + rtl::OUString maXLink; // internal link + rtl::OUString maUrl; // external link + + rtl::OUString maMimeType; // mimetype and + rtl::OUString maData; // base64 data + + public: + SvgImageNode( + SvgDocument& rDocument, + SvgNode* pParent); + virtual ~SvgImageNode(); + + virtual const SvgStyleAttributes* getSvgStyleAttributes() const; + virtual void parseAttribute(const rtl::OUString& rTokenName, SVGToken aSVGToken, const rtl::OUString& aContent); + virtual void decomposeSvgNode(drawinglayer::primitive2d::Primitive2DSequence& rTarget, bool bReferenced) const; + + /// SvgAspectRatio content + const SvgAspectRatio& getSvgAspectRatio() const { return maSvgAspectRatio; } + void setSvgAspectRatio(const SvgAspectRatio& rSvgAspectRatio = SvgAspectRatio()) { maSvgAspectRatio = rSvgAspectRatio; } + + /// transform content, set if found in current context + const basegfx::B2DHomMatrix* getTransform() const { return mpaTransform; } + void setTransform(const basegfx::B2DHomMatrix* pMatrix = 0) { if(mpaTransform) delete mpaTransform; mpaTransform = 0; if(pMatrix) mpaTransform = new basegfx::B2DHomMatrix(*pMatrix); } + + /// x content, set if found in current context + const SvgNumber& getX() const { return maX; } + void setX(const SvgNumber& rX = SvgNumber()) { maX = rX; } + + /// y content, set if found in current context + const SvgNumber& getY() const { return maY; } + void setY(const SvgNumber& rY = SvgNumber()) { maY = rY; } + + /// width content, set if found in current context + const SvgNumber& getWidth() const { return maWidth; } + void setWidth(const SvgNumber& rWidth = SvgNumber()) { maWidth = rWidth; } + + /// height content, set if found in current context + const SvgNumber& getHeight() const { return maHeight; } + void setHeight(const SvgNumber& rHeight = SvgNumber()) { maHeight = rHeight; } + + /// XLink access + const rtl::OUString& getXLink() const { return maXLink; } + }; + } // end of namespace svgreader +} // end of namespace svgio + +////////////////////////////////////////////////////////////////////////////// + +#endif //INCLUDED_SVGIO_SVGREADER_SVGIMAGENODE_HXX + +// eof diff --git a/svgio/inc/svgio/svgreader/svglinenode.hxx b/svgio/inc/svgio/svgreader/svglinenode.hxx new file mode 100644 index 000000000000..b897aba28cc2 --- /dev/null +++ b/svgio/inc/svgio/svgreader/svglinenode.hxx @@ -0,0 +1,85 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +#ifndef INCLUDED_SVGIO_SVGREADER_SVGLINENODE_HXX +#define INCLUDED_SVGIO_SVGREADER_SVGLINENODE_HXX + +#include <svgio/svgiodllapi.h> +#include <svgio/svgreader/svgnode.hxx> +#include <svgio/svgreader/svgstyleattributes.hxx> + +////////////////////////////////////////////////////////////////////////////// + +namespace svgio +{ + namespace svgreader + { + class SvgLineNode : public SvgNode + { + private: + /// use styles + SvgStyleAttributes maSvgStyleAttributes; + + /// variable scan values, dependent of given XAttributeList + SvgNumber maX1; + SvgNumber maY1; + SvgNumber maX2; + SvgNumber maY2; + basegfx::B2DHomMatrix* mpaTransform; + + public: + SvgLineNode( + SvgDocument& rDocument, + SvgNode* pParent); + virtual ~SvgLineNode(); + + virtual const SvgStyleAttributes* getSvgStyleAttributes() const; + virtual void parseAttribute(const rtl::OUString& rTokenName, SVGToken aSVGToken, const rtl::OUString& aContent); + virtual void decomposeSvgNode(drawinglayer::primitive2d::Primitive2DSequence& rTarget, bool bReferenced) const; + + /// X1 content, set if found in current context + const SvgNumber& getX1() const { return maX1; } + void setX1(const SvgNumber& rX1 = SvgNumber()) { maX1 = rX1; } + + /// Y1 content, set if found in current context + const SvgNumber& getY1() const { return maY1; } + void setY1(const SvgNumber& rY1 = SvgNumber()) { maY1 = rY1; } + + /// X2 content, set if found in current context + const SvgNumber& getX2() const { return maX2; } + void setX2(const SvgNumber& rX2 = SvgNumber()) { maX2 = rX2; } + + /// Y2 content, set if found in current context + const SvgNumber& getY2() const { return maY2; } + void setY2(const SvgNumber& rY2 = SvgNumber()) { maY2 = rY2; } + + /// transform content, set if found in current context + const basegfx::B2DHomMatrix* getTransform() const { return mpaTransform; } + void setTransform(const basegfx::B2DHomMatrix* pMatrix = 0) { if(mpaTransform) delete mpaTransform; mpaTransform = 0; if(pMatrix) mpaTransform = new basegfx::B2DHomMatrix(*pMatrix); } + }; + } // end of namespace svgreader +} // end of namespace svgio + +////////////////////////////////////////////////////////////////////////////// + +#endif //INCLUDED_SVGIO_SVGREADER_SVGLINENODE_HXX + +// eof diff --git a/svgio/inc/svgio/svgreader/svgmarkernode.hxx b/svgio/inc/svgio/svgreader/svgmarkernode.hxx new file mode 100755 index 000000000000..b5562f70df44 --- /dev/null +++ b/svgio/inc/svgio/svgreader/svgmarkernode.hxx @@ -0,0 +1,123 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +#ifndef INCLUDED_SVGIO_SVGREADER_SVGMARKERNODE_HXX +#define INCLUDED_SVGIO_SVGREADER_SVGMARKERNODE_HXX + +#include <svgio/svgiodllapi.h> +#include <svgio/svgreader/svgnode.hxx> +#include <svgio/svgreader/svgstyleattributes.hxx> + +////////////////////////////////////////////////////////////////////////////// + +namespace svgio +{ + namespace svgreader + { + class SvgMarkerNode : public SvgNode + { + public: + enum MarkerUnits + { + strokeWidth, + userSpaceOnUse + }; + + private: + /// buffered decomposition + drawinglayer::primitive2d::Primitive2DSequence aPrimitives; + + /// use styles + SvgStyleAttributes maSvgStyleAttributes; + + /// variable scan values, dependent of given XAttributeList + basegfx::B2DRange* mpViewBox; + SvgAspectRatio maSvgAspectRatio; + SvgNumber maRefX; + SvgNumber maRefY; + MarkerUnits maMarkerUnits; + SvgNumber maMarkerWidth; + SvgNumber maMarkerHeight; + double mfAngle; + + /// bitfield + bool mbOrientAuto : 1; // true == on, false == fAngle valid + + public: + SvgMarkerNode( + SvgDocument& rDocument, + SvgNode* pParent); + virtual ~SvgMarkerNode(); + + virtual const SvgStyleAttributes* getSvgStyleAttributes() const; + virtual void parseAttribute(const rtl::OUString& rTokenName, SVGToken aSVGToken, const rtl::OUString& aContent); + + /// get marker primitives buffered, uses decomposeSvgNode internally + const drawinglayer::primitive2d::Primitive2DSequence& getMarkerPrimitives() const; + + /// InfoProvider support for % values + virtual const basegfx::B2DRange* getCurrentViewPort() const; + + /// viewBox content + const basegfx::B2DRange* getViewBox() const { return mpViewBox; } + void setViewBox(const basegfx::B2DRange* pViewBox = 0) { if(mpViewBox) delete mpViewBox; mpViewBox = 0; if(pViewBox) mpViewBox = new basegfx::B2DRange(*pViewBox); } + + /// SvgAspectRatio content + const SvgAspectRatio& getSvgAspectRatio() const { return maSvgAspectRatio; } + void setSvgAspectRatio(const SvgAspectRatio& rSvgAspectRatio = SvgAspectRatio()) { maSvgAspectRatio = rSvgAspectRatio; } + + /// RefX content, set if found in current context + const SvgNumber& getRefX() const { return maRefX; } + void setRefX(const SvgNumber& rRefX = SvgNumber()) { maRefX = rRefX; } + + /// RefY content, set if found in current context + const SvgNumber& getRefY() const { return maRefY; } + void setRefY(const SvgNumber& rRefY = SvgNumber()) { maRefY = rRefY; } + + /// MarkerUnits content + MarkerUnits getMarkerUnits() const { return maMarkerUnits; } + void setMarkerUnits(const MarkerUnits aMarkerUnits) { maMarkerUnits = aMarkerUnits; } + + /// MarkerWidth content, set if found in current context + const SvgNumber& getMarkerWidth() const { return maMarkerWidth; } + void setMarkerWidth(const SvgNumber& rMarkerWidth = SvgNumber()) { maMarkerWidth = rMarkerWidth; } + + /// MarkerHeight content, set if found in current context + const SvgNumber& getMarkerHeight() const { return maMarkerHeight; } + void setMarkerHeight(const SvgNumber& rMarkerHeight = SvgNumber()) { maMarkerHeight = rMarkerHeight; } + + /// Angle content, set if found in current context + double getAngle() const { return mfAngle; } + void setAngle(double fAngle = 0.0) { mfAngle = fAngle; mbOrientAuto = false; } + + /// OrientAuto content, set if found in current context + bool getOrientAuto() const { return mbOrientAuto; } + void setOrientAuto(bool bOrientAuto = true) { mbOrientAuto = bOrientAuto; } + + }; + } // end of namespace svgreader +} // end of namespace svgio + +////////////////////////////////////////////////////////////////////////////// + +#endif //INCLUDED_SVGIO_SVGREADER_SVGMARKERNODE_HXX + +// eof diff --git a/svgio/inc/svgio/svgreader/svgmasknode.hxx b/svgio/inc/svgio/svgreader/svgmasknode.hxx new file mode 100755 index 000000000000..6c3089d4a107 --- /dev/null +++ b/svgio/inc/svgio/svgreader/svgmasknode.hxx @@ -0,0 +1,98 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +#ifndef INCLUDED_SVGIO_SVGREADER_SVGMASKNODE_HXX +#define INCLUDED_SVGIO_SVGREADER_SVGMASKNODE_HXX + +#include <svgio/svgiodllapi.h> +#include <svgio/svgreader/svgnode.hxx> +#include <svgio/svgreader/svgstyleattributes.hxx> + +////////////////////////////////////////////////////////////////////////////// + +namespace svgio +{ + namespace svgreader + { + class SvgMaskNode : public SvgNode + { + private: + /// use styles + SvgStyleAttributes maSvgStyleAttributes; + + /// variable scan values, dependent of given XAttributeList + SvgNumber maX; + SvgNumber maY; + SvgNumber maWidth; + SvgNumber maHeight; + basegfx::B2DHomMatrix* mpaTransform; + SvgUnits maMaskUnits; + SvgUnits maMaskContentUnits; + + public: + SvgMaskNode( + SvgDocument& rDocument, + SvgNode* pParent); + virtual ~SvgMaskNode(); + + virtual const SvgStyleAttributes* getSvgStyleAttributes() const; + virtual void parseAttribute(const rtl::OUString& rTokenName, SVGToken aSVGToken, const rtl::OUString& aContent); + virtual void decomposeSvgNode(drawinglayer::primitive2d::Primitive2DSequence& rTarget, bool bReferenced) const; + + /// apply contained clipPath to given geometry + void apply(drawinglayer::primitive2d::Primitive2DSequence& rTarget) const; + + /// x content, set if found in current context + const SvgNumber& getX() const { return maX; } + void setX(const SvgNumber& rX = SvgNumber()) { maX = rX; } + + /// y content, set if found in current context + const SvgNumber& getY() const { return maY; } + void setY(const SvgNumber& rY = SvgNumber()) { maY = rY; } + + /// width content, set if found in current context + const SvgNumber& getWidth() const { return maWidth; } + void setWidth(const SvgNumber& rWidth = SvgNumber()) { maWidth = rWidth; } + + /// height content, set if found in current context + const SvgNumber& getHeight() const { return maHeight; } + void setHeight(const SvgNumber& rHeight = SvgNumber()) { maHeight = rHeight; } + + /// transform content + const basegfx::B2DHomMatrix* getTransform() const { return mpaTransform; } + void setTransform(const basegfx::B2DHomMatrix* pMatrix = 0) { if(mpaTransform) delete mpaTransform; mpaTransform = 0; if(pMatrix) mpaTransform = new basegfx::B2DHomMatrix(*pMatrix); } + + /// MaskUnits content + SvgUnits getMaskUnits() const { return maMaskUnits; } + void setMaskUnits(const SvgUnits aMaskUnits) { maMaskUnits = aMaskUnits; } + + /// MaskContentUnits content + SvgUnits getMaskContentUnits() const { return maMaskContentUnits; } + void setMaskContentUnits(const SvgUnits aMaskContentUnits) { maMaskContentUnits = aMaskContentUnits; } + }; + } // end of namespace svgreader +} // end of namespace svgio + +////////////////////////////////////////////////////////////////////////////// + +#endif //INCLUDED_SVGIO_SVGREADER_SVGMASKNODE_HXX + +// eof diff --git a/svgio/inc/svgio/svgreader/svgnode.hxx b/svgio/inc/svgio/svgreader/svgnode.hxx new file mode 100644 index 000000000000..1a5add60ccc8 --- /dev/null +++ b/svgio/inc/svgio/svgreader/svgnode.hxx @@ -0,0 +1,127 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +#ifndef INCLUDED_SVGIO_SVGREADER_SVGNODE_HXX +#define INCLUDED_SVGIO_SVGREADER_SVGNODE_HXX + +#include <svgio/svgiodllapi.h> +#include <svgio/svgreader/svgtools.hxx> +#include <svgio/svgreader/svgtoken.hxx> +#include <svgio/svgreader/svgpaint.hxx> +#include <basegfx/matrix/b2dhommatrix.hxx> +#include <com/sun/star/xml/sax/XAttributeList.hpp> +#include <vector> +#include <hash_map> + +////////////////////////////////////////////////////////////////////////////// +// predefines +namespace svgio +{ + namespace svgreader + { + class SvgNode; + class SvgDocument; + class SvgStyleAttributes; + } +} + +////////////////////////////////////////////////////////////////////////////// + +namespace svgio +{ + namespace svgreader + { + typedef ::std::vector< SvgNode* > SvgNodeVector; + + enum XmlSpace + { + XmlSpace_notset, + XmlSpace_default, + XmlSpace_preserve + }; + + class SvgNode : private boost::noncopyable, public InfoProvider + { + private: + /// basic data, Type, document we belong to and parent (if not root) + SVGToken maType; + SvgDocument& mrDocument; + const SvgNode* mpParent; + const SvgNode* mpAlternativeParent; + + /// sub hierarchy + SvgNodeVector maChildren; + + /// Id svan value + rtl::OUString* mpId; + + /// Class svan value + rtl::OUString* mpClass; + + /// XmlSpace value + XmlSpace maXmlSpace; + + public: + SvgNode( + SVGToken aType, + SvgDocument& rDocument, + SvgNode* pParent); + virtual ~SvgNode(); + + void parseAttributes(const com::sun::star::uno::Reference< com::sun::star::xml::sax::XAttributeList >& xAttribs); + virtual const SvgStyleAttributes* getSvgStyleAttributes() const; + virtual void parseAttribute(const rtl::OUString& rTokenName, SVGToken aSVGToken, const rtl::OUString& aContent); + virtual void decomposeSvgNode(drawinglayer::primitive2d::Primitive2DSequence& rTarget, bool bReferenced) const; + + /// basic data read access + const SVGToken getType() const { return maType; } + const SvgDocument& getDocument() const { return mrDocument; } + const SvgNode* getParent() const { if(mpAlternativeParent) return mpAlternativeParent; return mpParent; } + const SvgNodeVector& getChildren() const { return maChildren; } + + /// InfoProvider support for %, em and ex values + virtual const basegfx::B2DRange* getCurrentViewPort() const; + virtual double getCurrentFontSize() const; + virtual double getCurrentXHeight() const; + + /// Id access + const rtl::OUString* getId() const { return mpId; } + void setId(const rtl::OUString* pfId = 0); + + /// Class access + const rtl::OUString* getClass() const { return mpClass; } + void setClass(const rtl::OUString* pfClass = 0); + + /// XmlSpace access + XmlSpace getXmlSpace() const; + void setXmlSpace(XmlSpace eXmlSpace = XmlSpace_notset) { maXmlSpace = eXmlSpace; } + + /// alternative parent + void setAlternativeParent(const SvgNode* pAlternativeParent = 0) { mpAlternativeParent = pAlternativeParent; } + }; + } // end of namespace svgreader +} // end of namespace svgio + +////////////////////////////////////////////////////////////////////////////// + +#endif //INCLUDED_SVGIO_SVGREADER_SVGNODE_HXX + +// eof diff --git a/svgio/inc/svgio/svgreader/svgpaint.hxx b/svgio/inc/svgio/svgreader/svgpaint.hxx new file mode 100644 index 000000000000..2a421973581f --- /dev/null +++ b/svgio/inc/svgio/svgreader/svgpaint.hxx @@ -0,0 +1,65 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +#ifndef INCLUDED_SVGIO_SVGREADER_SVGPAINT_HXX +#define INCLUDED_SVGIO_SVGREADER_SVGPAINT_HXX + +#include <svgio/svgiodllapi.h> +#include <basegfx/color/bcolor.hxx> + +////////////////////////////////////////////////////////////////////////////// + +namespace svgio +{ + namespace svgreader + { + class SvgPaint + { + private: + basegfx::BColor maColor; + + /// bitfield + bool mbSet : 1; + bool mbOn : 1; + bool mbCurrent : 1; + + public: + SvgPaint(const basegfx::BColor& rColor = basegfx::BColor(0.0, 0.0, 0.0), bool bSet = false, bool bOn = false, bool bCurrent = false) + : maColor(rColor), + mbSet(bSet), + mbOn(bOn), + mbCurrent(bCurrent) + { + } + + const basegfx::BColor& getBColor() const { return maColor; } + bool isSet() const { return mbSet; } + bool isOn() const { return mbOn; } + bool isCurrent() const { return mbCurrent; } + }; + } // end of namespace svgreader +} // end of namespace svgio + +////////////////////////////////////////////////////////////////////////////// + +#endif //INCLUDED_SVGIO_SVGREADER_SVGPAINT_HXX + +// eof diff --git a/svgio/inc/svgio/svgreader/svgpathnode.hxx b/svgio/inc/svgio/svgreader/svgpathnode.hxx new file mode 100644 index 000000000000..73811b13f880 --- /dev/null +++ b/svgio/inc/svgio/svgreader/svgpathnode.hxx @@ -0,0 +1,75 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +#ifndef INCLUDED_SVGIO_SVGREADER_SVGPATHNODE_HXX +#define INCLUDED_SVGIO_SVGREADER_SVGPATHNODE_HXX + +#include <svgio/svgiodllapi.h> +#include <svgio/svgreader/svgnode.hxx> +#include <svgio/svgreader/svgstyleattributes.hxx> + +////////////////////////////////////////////////////////////////////////////// + +namespace svgio +{ + namespace svgreader + { + class SvgPathNode : public SvgNode + { + private: + /// use styles + SvgStyleAttributes maSvgStyleAttributes; + + /// variable scan values, dependent of given XAttributeList + basegfx::B2DPolyPolygon* mpPolyPolygon; + basegfx::B2DHomMatrix* mpaTransform; + SvgNumber maPathLength; + + public: + SvgPathNode( + SvgDocument& rDocument, + SvgNode* pParent); + virtual ~SvgPathNode(); + + virtual const SvgStyleAttributes* getSvgStyleAttributes() const; + virtual void parseAttribute(const rtl::OUString& rTokenName, SVGToken aSVGToken, const rtl::OUString& aContent); + virtual void decomposeSvgNode(drawinglayer::primitive2d::Primitive2DSequence& rTarget, bool bReferenced) const; + + /// path content, set if found in current context + const basegfx::B2DPolyPolygon* getPath() const { return mpPolyPolygon; } + void setPath(const basegfx::B2DPolyPolygon* pPath = 0) { if(mpPolyPolygon) delete mpPolyPolygon; mpPolyPolygon = 0; if(pPath) mpPolyPolygon = new basegfx::B2DPolyPolygon(*pPath); } + + /// transform content, set if found in current context + const basegfx::B2DHomMatrix* getTransform() const { return mpaTransform; } + void setTransform(const basegfx::B2DHomMatrix* pMatrix = 0) { if(mpaTransform) delete mpaTransform; mpaTransform = 0; if(pMatrix) mpaTransform = new basegfx::B2DHomMatrix(*pMatrix); } + + /// PathLength content + const SvgNumber& getPathLength() const { return maPathLength; } + void setPathLength(const SvgNumber& rPathLength = SvgNumber()) { maPathLength = rPathLength; } + }; + } // end of namespace svgreader +} // end of namespace svgio + +////////////////////////////////////////////////////////////////////////////// + +#endif //INCLUDED_SVGIO_SVGREADER_SVGPATHNODE_HXX + +// eof diff --git a/svgio/inc/svgio/svgreader/svgpatternnode.hxx b/svgio/inc/svgio/svgreader/svgpatternnode.hxx new file mode 100755 index 000000000000..faf0994a81dd --- /dev/null +++ b/svgio/inc/svgio/svgreader/svgpatternnode.hxx @@ -0,0 +1,126 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +#ifndef INCLUDED_SVGIO_SVGREADER_SVGPATTERNNODE_HXX +#define INCLUDED_SVGIO_SVGREADER_SVGPATTERNNODE_HXX + +#include <svgio/svgiodllapi.h> +#include <svgio/svgreader/svgnode.hxx> +#include <svgio/svgreader/svgstyleattributes.hxx> + +////////////////////////////////////////////////////////////////////////////// + +namespace svgio +{ + namespace svgreader + { + class SvgPatternNode : public SvgNode + { + private: + /// buffered decomposition + drawinglayer::primitive2d::Primitive2DSequence aPrimitives; + + /// use styles + SvgStyleAttributes maSvgStyleAttributes; + + /// variable scan values, dependent of given XAttributeList + basegfx::B2DRange* mpViewBox; + SvgAspectRatio maSvgAspectRatio; + SvgNumber maX; + SvgNumber maY; + SvgNumber maWidth; + SvgNumber maHeight; + SvgUnits* mpPatternUnits; + SvgUnits* mpPatternContentUnits; + basegfx::B2DHomMatrix* mpaPatternTransform; + + /// link to another pattern used as style. If maXLink + /// is set, the node can be fetched on demand by using + // tryToFindLink (buffered) + rtl::OUString maXLink; + const SvgPatternNode* mpXLink; + + /// link on demand + void tryToFindLink(); + + public: + SvgPatternNode( + SvgDocument& rDocument, + SvgNode* pParent); + virtual ~SvgPatternNode(); + + virtual const SvgStyleAttributes* getSvgStyleAttributes() const; + virtual void parseAttribute(const rtl::OUString& rTokenName, SVGToken aSVGToken, const rtl::OUString& aContent); + + /// global helpers + void getValuesRelative(double& rfX, double& rfY, double& rfW, double& rfH, const basegfx::B2DRange& rGeoRange, SvgNode& rUser) const; + + /// get pattern primitives buffered, uses decomposeSvgNode internally + const drawinglayer::primitive2d::Primitive2DSequence& getPatternPrimitives() const; + + /// InfoProvider support for % values + virtual const basegfx::B2DRange* getCurrentViewPort() const; + + /// viewBox content + const basegfx::B2DRange* getViewBox() const; + void setViewBox(const basegfx::B2DRange* pViewBox = 0) { if(mpViewBox) delete mpViewBox; mpViewBox = 0; if(pViewBox) mpViewBox = new basegfx::B2DRange(*pViewBox); } + + /// SvgAspectRatio content + const SvgAspectRatio& getSvgAspectRatio() const; + void setSvgAspectRatio(const SvgAspectRatio& rSvgAspectRatio = SvgAspectRatio()) { maSvgAspectRatio = rSvgAspectRatio; } + + /// X content, set if found in current context + const SvgNumber& getX() const; + void setX(const SvgNumber& rX = SvgNumber()) { maX = rX; } + + /// Y content, set if found in current context + const SvgNumber& getY() const; + void setY(const SvgNumber& rY = SvgNumber()) { maY = rY; } + + /// Width content, set if found in current context + const SvgNumber& getWidth() const; + void setWidth(const SvgNumber& rWidth = SvgNumber()) { maWidth = rWidth; } + + /// Height content, set if found in current context + const SvgNumber& getHeight() const; + void setHeight(const SvgNumber& rHeight = SvgNumber()) { maHeight = rHeight; } + + /// PatternUnits content + const SvgUnits* getPatternUnits() const; + void setPatternUnits(const SvgUnits aPatternUnits) { if(mpPatternUnits) delete mpPatternUnits; mpPatternUnits = 0; mpPatternUnits = new SvgUnits(aPatternUnits); } + + /// PatternContentUnits content + const SvgUnits* getPatternContentUnits() const; + void setPatternContentUnits(const SvgUnits aPatternContentUnits) { if(mpPatternContentUnits) delete mpPatternContentUnits; mpPatternContentUnits = 0; mpPatternContentUnits = new SvgUnits(aPatternContentUnits); } + + /// PatternTransform content + const basegfx::B2DHomMatrix* getPatternTransform() const; + void setPatternTransform(const basegfx::B2DHomMatrix* pMatrix = 0) { if(mpaPatternTransform) delete mpaPatternTransform; mpaPatternTransform = 0; if(pMatrix) mpaPatternTransform = new basegfx::B2DHomMatrix(*pMatrix); } + + }; + } // end of namespace svgreader +} // end of namespace svgio + +////////////////////////////////////////////////////////////////////////////// + +#endif //INCLUDED_SVGIO_SVGREADER_SVGPATTERNNODE_HXX + +// eof diff --git a/svgio/inc/svgio/svgreader/svgpolynode.hxx b/svgio/inc/svgio/svgreader/svgpolynode.hxx new file mode 100644 index 000000000000..406d267a1ac8 --- /dev/null +++ b/svgio/inc/svgio/svgreader/svgpolynode.hxx @@ -0,0 +1,78 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +#ifndef INCLUDED_SVGIO_SVGREADER_SVGPOLYNODE_HXX +#define INCLUDED_SVGIO_SVGREADER_SVGPOLYNODE_HXX + +#include <svgio/svgiodllapi.h> +#include <svgio/svgreader/svgnode.hxx> +#include <svgio/svgreader/svgstyleattributes.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> + +////////////////////////////////////////////////////////////////////////////// + +namespace svgio +{ + namespace svgreader + { + class SvgPolyNode : public SvgNode + { + private: + /// use styles + SvgStyleAttributes maSvgStyleAttributes; + + /// variable scan values, dependent of given XAttributeList + basegfx::B2DPolygon* mpPolygon; + basegfx::B2DHomMatrix* mpaTransform; + + /// bitfield + bool mbIsPolyline : 1; // true = polyline, false = polygon + + public: + SvgPolyNode( + SvgDocument& rDocument, + SvgNode* pParent, + bool bIsPolyline); + virtual ~SvgPolyNode(); + + virtual const SvgStyleAttributes* getSvgStyleAttributes() const; + virtual void parseAttribute(const rtl::OUString& rTokenName, SVGToken aSVGToken, const rtl::OUString& aContent); + virtual void decomposeSvgNode(drawinglayer::primitive2d::Primitive2DSequence& rTarget, bool bReferenced) const; + + /// type read access + bool isPolyline() const { return mbIsPolyline; } + + /// Polygon content, set if found in current context + const basegfx::B2DPolygon* getPolygon() const { return mpPolygon; } + void setPolygon(const basegfx::B2DPolygon* pPolygon = 0) { if(mpPolygon) delete mpPolygon; mpPolygon = 0; if(pPolygon) mpPolygon = new basegfx::B2DPolygon(*pPolygon); } + + /// transform content, set if found in current context + const basegfx::B2DHomMatrix* getTransform() const { return mpaTransform; } + void setTransform(const basegfx::B2DHomMatrix* pMatrix = 0) { if(mpaTransform) delete mpaTransform; mpaTransform = 0; if(pMatrix) mpaTransform = new basegfx::B2DHomMatrix(*pMatrix); } + }; + } // end of namespace svgreader +} // end of namespace svgio + +////////////////////////////////////////////////////////////////////////////// + +#endif //INCLUDED_SVGIO_SVGREADER_SVGPOLYNODE_HXX + +// eof diff --git a/svgio/inc/svgio/svgreader/svgrectnode.hxx b/svgio/inc/svgio/svgreader/svgrectnode.hxx new file mode 100644 index 000000000000..b8a42db45d11 --- /dev/null +++ b/svgio/inc/svgio/svgreader/svgrectnode.hxx @@ -0,0 +1,95 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +#ifndef INCLUDED_SVGIO_SVGREADER_SVGRECTNODE_HXX +#define INCLUDED_SVGIO_SVGREADER_SVGRECTNODE_HXX + +#include <svgio/svgiodllapi.h> +#include <svgio/svgreader/svgnode.hxx> +#include <svgio/svgreader/svgstyleattributes.hxx> + +////////////////////////////////////////////////////////////////////////////// + +namespace svgio +{ + namespace svgreader + { + class SvgRectNode : public SvgNode + { + private: + /// use styles + SvgStyleAttributes maSvgStyleAttributes; + + /// variable scan values, dependent of given XAttributeList + SvgNumber maX; + SvgNumber maY; + SvgNumber maWidth; + SvgNumber maHeight; + SvgNumber maRx; + SvgNumber maRy; + basegfx::B2DHomMatrix* mpaTransform; + + public: + SvgRectNode( + SvgDocument& rDocument, + SvgNode* pParent); + virtual ~SvgRectNode(); + + virtual const SvgStyleAttributes* getSvgStyleAttributes() const; + virtual void parseAttribute(const rtl::OUString& rTokenName, SVGToken aSVGToken, const rtl::OUString& aContent); + virtual void decomposeSvgNode(drawinglayer::primitive2d::Primitive2DSequence& rTarget, bool bReferenced) const; + + /// x content, set if found in current context + const SvgNumber& getX() const { return maX; } + void setX(const SvgNumber& rX = SvgNumber()) { maX = rX; } + + /// y content, set if found in current context + const SvgNumber& getY() const { return maY; } + void setY(const SvgNumber& rY = SvgNumber()) { maY = rY; } + + /// width content, set if found in current context + const SvgNumber& getWidth() const { return maWidth; } + void setWidth(const SvgNumber& rWidth = SvgNumber()) { maWidth = rWidth; } + + /// height content, set if found in current context + const SvgNumber& getHeight() const { return maHeight; } + void setHeight(const SvgNumber& rHeight = SvgNumber()) { maHeight = rHeight; } + + /// Rx content, set if found in current context + const SvgNumber& getRx() const { return maRx; } + void setRx(const SvgNumber& rRx = SvgNumber()) { maRx = rRx; } + + /// Ry content, set if found in current context + const SvgNumber& getRy() const { return maRy; } + void setRy(const SvgNumber& rRy = SvgNumber()) { maRy = rRy; } + + /// transform content, set if found in current context + const basegfx::B2DHomMatrix* getTransform() const { return mpaTransform; } + void setTransform(const basegfx::B2DHomMatrix* pMatrix = 0) { if(mpaTransform) delete mpaTransform; mpaTransform = 0; if(pMatrix) mpaTransform = new basegfx::B2DHomMatrix(*pMatrix); } + }; + } // end of namespace svgreader +} // end of namespace svgio + +////////////////////////////////////////////////////////////////////////////// + +#endif //INCLUDED_SVGIO_SVGREADER_SVGRECTNODE_HXX + +// eof diff --git a/svgio/inc/svgio/svgreader/svgstyleattributes.hxx b/svgio/inc/svgio/svgreader/svgstyleattributes.hxx new file mode 100644 index 000000000000..9be162330ad5 --- /dev/null +++ b/svgio/inc/svgio/svgreader/svgstyleattributes.hxx @@ -0,0 +1,411 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +#ifndef INCLUDED_SVGIO_SVGREADER_SVGSTYLEATTRIBUTES_HXX +#define INCLUDED_SVGIO_SVGREADER_SVGSTYLEATTRIBUTES_HXX + +#include <svgio/svgiodllapi.h> +#include <svgio/svgreader/svgpaint.hxx> +#include <svgio/svgreader/svgnode.hxx> +#include <vcl/vclenum.hxx> + +////////////////////////////////////////////////////////////////////////////// +// predefines + +namespace svgio { namespace svgreader { + class SvgGradientNode; + class SvgPatternNode; + class SvgMarkerNode; +}} + +////////////////////////////////////////////////////////////////////////////// + +namespace svgio +{ + namespace svgreader + { + enum StrokeLinecap + { + StrokeLinecap_notset, + StrokeLinecap_butt, + StrokeLinecap_round, + StrokeLinecap_square + }; + + enum StrokeLinejoin + { + StrokeLinejoin_notset, + StrokeLinejoin_miter, + StrokeLinejoin_round, + StrokeLinejoin_bevel + }; + + enum FontStretch + { + FontStretch_notset, + FontStretch_normal, + FontStretch_wider, + FontStretch_narrower, + FontStretch_ultra_condensed, + FontStretch_extra_condensed, + FontStretch_condensed, + FontStretch_semi_condensed, + FontStretch_semi_expanded, + FontStretch_expanded, + FontStretch_extra_expanded, + FontStretch_ultra_expanded + }; + + FontStretch getWider(FontStretch aSource); + FontStretch getNarrower(FontStretch aSource); + + enum FontStyle + { + FontStyle_notset, + FontStyle_normal, + FontStyle_italic, + FontStyle_oblique + }; + + enum FontVariant + { + FontVariant_notset, + FontVariant_normal, + FontVariant_small_caps + }; + + enum FontWeight + { + FontWeight_notset, + FontWeight_100, + FontWeight_200, + FontWeight_300, + FontWeight_400, // same as FontWeight_normal + FontWeight_500, + FontWeight_600, + FontWeight_700, // same as FontWeight_bold + FontWeight_800, + FontWeight_900, + FontWeight_bolder, + FontWeight_lighter, + }; + + FontWeight getBolder(FontWeight aSource); + FontWeight getLighter(FontWeight aSource); + ::FontWeight getVclFontWeight(FontWeight aSource); + + enum TextAlign + { + TextAlign_notset, + TextAlign_left, + TextAlign_right, + TextAlign_center, + TextAlign_justify + }; + + enum TextDecoration + { + TextDecoration_notset, + TextDecoration_none, + TextDecoration_underline, + TextDecoration_overline, + TextDecoration_line_through, + TextDecoration_blink + }; + + enum TextAnchor + { + TextAnchor_notset, + TextAnchor_start, + TextAnchor_middle, + TextAnchor_end + }; + + class SvgStyleAttributes + { + private: + SvgNode& mrOwner; + const SvgStyleAttributes* mpCssStyleParent; + + SvgPaint maFill; + SvgPaint maStroke; + SvgPaint maStopColor; + SvgNumber maStrokeWidth; + SvgNumber maStopOpacity; + const SvgGradientNode* mpSvgGradientNodeFill; + const SvgGradientNode* mpSvgGradientNodeStroke; + const SvgPatternNode* mpSvgPatternNodeFill; + const SvgPatternNode* mpSvgPatternNodeStroke; + SvgNumber maFillOpacity; + SvgNumberVector maStrokeDasharray; + SvgNumber maStrokeDashOffset; + StrokeLinecap maStrokeLinecap; + StrokeLinejoin maStrokeLinejoin; + SvgNumber maStrokeMiterLimit; + SvgNumber maStrokeOpacity; + SvgStringVector maFontFamily; + SvgNumber maFontSize; + FontStretch maFontStretch; + FontStyle maFontStyle; + FontVariant maFontVariant; + FontWeight maFontWeight; + TextAlign maTextAlign; + TextDecoration maTextDecoration; + TextAnchor maTextAnchor; + SvgPaint maColor; + SvgNumber maOpacity; + + /// link to content. If set, the node can be fetched on demand + rtl::OUString maClipPathXLink; + rtl::OUString maMaskXLink; + + /// link to markers. If set, the node can be fetched on demand + rtl::OUString maMarkerStartXLink; + const SvgMarkerNode* mpMarkerStartXLink; + rtl::OUString maMarkerMidXLink; + const SvgMarkerNode* mpMarkerMidXLink; + rtl::OUString maMarkerEndXLink; + const SvgMarkerNode* mpMarkerEndXLink; + + /// bitfield + bool maFillRule : 1; // true: NonZero, false: EvenOdd + bool maFillRuleSet : 1; + + // defines if this attributes are part of a ClipPath. If yes, + // rough geometry will be created on decomposition by patching + // vaules for fill, stroke, strokeWidth and others + bool mbIsClipPathContent : 1; + + // ClipRule setting (only valid wne mbIsClipPathContent == true) + bool mbClipRule : 1; // true == nonzero(default), false == evenodd + + /// internal helpers + void add_fillGradient( + const basegfx::B2DPolyPolygon& rPath, + drawinglayer::primitive2d::Primitive2DSequence& rTarget, + const SvgGradientNode& rFillGradient, + const basegfx::B2DRange& rGeoRange) const; + void add_fillPatternTransform( + const basegfx::B2DPolyPolygon& rPath, + drawinglayer::primitive2d::Primitive2DSequence& rTarget, + const SvgPatternNode& rFillGradient, + const basegfx::B2DRange& rGeoRange) const; + void add_fillPattern( + const basegfx::B2DPolyPolygon& rPath, + drawinglayer::primitive2d::Primitive2DSequence& rTarget, + const SvgPatternNode& rFillGradient, + const basegfx::B2DRange& rGeoRange) const; + void add_fill( + const basegfx::B2DPolyPolygon& rPath, + drawinglayer::primitive2d::Primitive2DSequence& rTarget, + const basegfx::B2DRange& rGeoRange) const; + void add_stroke( + const basegfx::B2DPolyPolygon& rPath, + drawinglayer::primitive2d::Primitive2DSequence& rTarget, + const basegfx::B2DRange& rGeoRange) const; + bool prepare_singleMarker( + drawinglayer::primitive2d::Primitive2DSequence& rMarkerPrimitives, + basegfx::B2DHomMatrix& rMarkerTransform, + basegfx::B2DRange& rClipRange, + const SvgMarkerNode& rMarker) const; + void add_singleMarker( + drawinglayer::primitive2d::Primitive2DSequence& rTarget, + const drawinglayer::primitive2d::Primitive2DSequence& rMarkerPrimitives, + const basegfx::B2DHomMatrix& rMarkerTransform, + const basegfx::B2DRange& rClipRange, + const SvgMarkerNode& rMarker, + const basegfx::B2DPolygon& rCandidate, + const sal_uInt32 nIndex) const; + void add_markers( + const basegfx::B2DPolyPolygon& rPath, + drawinglayer::primitive2d::Primitive2DSequence& rTarget) const; + + public: + /// local attribute scanner + void parseStyleAttribute(const rtl::OUString& rTokenName, SVGToken aSVGToken, const rtl::OUString& aContent); + + /// helper which does the necessary with a given path + void add_text( + drawinglayer::primitive2d::Primitive2DSequence& rTarget, + drawinglayer::primitive2d::Primitive2DSequence& rSource) const; + void add_path( + const basegfx::B2DPolyPolygon& rPath, + drawinglayer::primitive2d::Primitive2DSequence& rTarget) const; + void add_postProcess( + drawinglayer::primitive2d::Primitive2DSequence& rTarget, + const drawinglayer::primitive2d::Primitive2DSequence& rSource, + const basegfx::B2DHomMatrix* pTransform) const; + + /// helper to evtl. link to css style + void checkForCssStyle(const rtl::OUString& rClassStr) const; + + /// scan helpers + void readStyle(const rtl::OUString& rCandidate); + const SvgStyleAttributes* getParentStyle() const; + + SvgStyleAttributes(SvgNode& rOwner); + ~SvgStyleAttributes(); + + /// fill content + const basegfx::BColor* getFill() const; + void setFill(const SvgPaint& rFill) { maFill = rFill; } + + /// stroke content + const basegfx::BColor* getStroke() const; + void setStroke(const SvgPaint& rStroke) { maStroke = rStroke; } + + /// stop color content + const basegfx::BColor& getStopColor() const; + void setStopColor(const SvgPaint& rStopColor) { maStopColor = rStopColor; } + + /// stroke-width content + const SvgNumber getStrokeWidth() const; + void setStrokeWidth(const SvgNumber& rStrokeWidth = SvgNumber()) { maStrokeWidth = rStrokeWidth; } + + /// stop opacity content + const SvgNumber getStopOpacity() const; + void setStopOpacity(const SvgNumber& rStopOpacity = SvgNumber()) { maStopOpacity = rStopOpacity; } + + /// access to evtl. set fill gradient + const SvgGradientNode* getSvgGradientNodeFill() const; + void setSvgGradientNodeFill(const SvgGradientNode* pNew) { mpSvgGradientNodeFill = pNew; } + + /// access to evtl. set fill pattern + const SvgPatternNode* getSvgPatternNodeFill() const; + void setSvgPatternNodeFill(const SvgPatternNode* pNew) { mpSvgPatternNodeFill = pNew; } + + /// access to evtl. set stroke gradient + const SvgGradientNode* getSvgGradientNodeStroke() const; + void setSvgGradientNodeStroke(const SvgGradientNode* pNew) { mpSvgGradientNodeStroke = pNew; } + + /// access to evtl. set stroke pattern + const SvgPatternNode* getSvgPatternNodeStroke() const; + void setSvgPatternNodeStroke(const SvgPatternNode* pNew) { mpSvgPatternNodeStroke = pNew; } + + /// fill opacity content + const SvgNumber getFillOpacity() const; + void setFillOpacity(const SvgNumber& rFillOpacity = SvgNumber()) { maFillOpacity = rFillOpacity; } + + /// fill rule content + bool getFillRule() const; + void setFillRule(const bool* pFillRule = 0); + + /// fill StrokeDasharray content + const SvgNumberVector& getStrokeDasharray() const; + void setStrokeDasharray(const SvgNumberVector& rStrokeDasharray = SvgNumberVector()) { maStrokeDasharray = rStrokeDasharray; } + + /// StrokeDashOffset content + const SvgNumber getStrokeDashOffset() const; + void setStrokeDashOffset(const SvgNumber& rStrokeDashOffset = SvgNumber()) { maStrokeDashOffset = rStrokeDashOffset; } + + /// StrokeLinecap content + const StrokeLinecap getStrokeLinecap() const; + void setStrokeLinecap(const StrokeLinecap aStrokeLinecap = StrokeLinecap_notset) { maStrokeLinecap = aStrokeLinecap; } + + /// StrokeLinejoin content + const StrokeLinejoin getStrokeLinejoin() const; + void setStrokeLinejoin(const StrokeLinejoin aStrokeLinejoin = StrokeLinejoin_notset) { maStrokeLinejoin = aStrokeLinejoin; } + + /// StrokeMiterLimit content + const SvgNumber getStrokeMiterLimit() const; + void setStrokeMiterLimit(const SvgNumber& rStrokeMiterLimit = SvgNumber()) { maStrokeMiterLimit = rStrokeMiterLimit; } + + /// StrokeOpacity content + const SvgNumber getStrokeOpacity() const; + void setStrokeOpacity(const SvgNumber& rStrokeOpacity = SvgNumber()) { maStrokeOpacity = rStrokeOpacity; } + + /// Font content + const SvgStringVector& getFontFamily() const; + void setFontFamily(const SvgStringVector& rSvgStringVector = SvgStringVector()) { maFontFamily = rSvgStringVector; } + + /// FontSize content + const SvgNumber getFontSize() const; + void setFontSize(const SvgNumber& rFontSize = SvgNumber()) { maFontSize = rFontSize; } + + /// FontStretch content + const FontStretch getFontStretch() const; + void setFontStretch(const FontStretch aFontStretch = FontStretch_notset) { maFontStretch = aFontStretch; } + + /// FontStyle content + const FontStyle getFontStyle() const; + void setFontStyle(const FontStyle aFontStyle = FontStyle_notset) { maFontStyle = aFontStyle; } + + /// FontVariant content + const FontVariant getFontVariant() const; + void setFontVariant(const FontVariant aFontVariant = FontVariant_notset) { maFontVariant = aFontVariant; } + + /// FontWeight content + const FontWeight getFontWeight() const; + void setFontWeight(const FontWeight aFontWeight = FontWeight_notset) { maFontWeight = aFontWeight; } + + /// TextAlign content + const TextAlign getTextAlign() const; + void setTextAlign(const TextAlign aTextAlign = TextAlign_notset) { maTextAlign = aTextAlign; } + + /// TextDecoration content + const SvgStyleAttributes* getTextDecorationDefiningSvgStyleAttributes() const; + const TextDecoration getTextDecoration() const; + void setTextDecoration(const TextDecoration aTextDecoration = TextDecoration_notset) { maTextDecoration = aTextDecoration; } + + /// TextAnchor content + const TextAnchor getTextAnchor() const; + void setTextAnchor(const TextAnchor aTextAnchor = TextAnchor_notset) { maTextAnchor = aTextAnchor; } + + /// Color content + const basegfx::BColor* getColor() const; + void setColor(const SvgPaint& rColor) { maColor = rColor; } + + /// Opacity content + const SvgNumber getOpacity() const { return maOpacity; } + void setOpacity(const SvgNumber& rOpacity = SvgNumber()) { maOpacity = rOpacity; } + + // ClipPathXLink content + const rtl::OUString getClipPathXLink() const { return maClipPathXLink; } + void setClipPathXLink(const rtl::OUString& rNew) { maClipPathXLink = rNew; } + + // MaskXLink content + const rtl::OUString getMaskXLink() const { return maMaskXLink; } + void setMaskXLink(const rtl::OUString& rNew) { maMaskXLink = rNew; } + + // MarkerStartXLink content + const rtl::OUString getMarkerStartXLink() const; + const SvgMarkerNode* accessMarkerStartXLink() const; + void setMarkerStartXLink(const rtl::OUString& rNew) { maMarkerStartXLink = rNew; } + + // MarkerMidXLink content + const rtl::OUString getMarkerMidXLink() const; + const SvgMarkerNode* accessMarkerMidXLink() const; + void setMarkerMidXLink(const rtl::OUString& rNew) { maMarkerMidXLink = rNew; } + + // MarkerEndXLink content + const rtl::OUString getMarkerEndXLink() const; + const SvgMarkerNode* accessMarkerEndXLink() const; + void setMarkerEndXLink(const rtl::OUString& rNew) { maMarkerEndXLink = rNew; } + + }; + } // end of namespace svgreader +} // end of namespace svgio + +////////////////////////////////////////////////////////////////////////////// + +#endif //INCLUDED_SVGIO_SVGREADER_SVGSTYLEATTRIBUTES_HXX + +// eof diff --git a/svgio/inc/svgio/svgreader/svgstylenode.hxx b/svgio/inc/svgio/svgreader/svgstylenode.hxx new file mode 100644 index 000000000000..04dc20ab5ade --- /dev/null +++ b/svgio/inc/svgio/svgreader/svgstylenode.hxx @@ -0,0 +1,64 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +#ifndef INCLUDED_SVGIO_SVGREADER_SVGSTYLENODE_HXX +#define INCLUDED_SVGIO_SVGREADER_SVGSTYLENODE_HXX + +#include <svgio/svgiodllapi.h> +#include <svgio/svgreader/svgnode.hxx> +#include <svgio/svgreader/svgstyleattributes.hxx> + +////////////////////////////////////////////////////////////////////////////// + +namespace svgio +{ + namespace svgreader + { + class SvgStyleNode : public SvgNode + { + private: + /// use styles + std::vector< SvgStyleAttributes* > maSvgStyleAttributes; + + /// bitfield + bool mbTextCss : 1; // true == type is 'text/css' + + public: + SvgStyleNode( + SvgDocument& rDocument, + SvgNode* pParent); + virtual ~SvgStyleNode(); + + virtual void parseAttribute(const rtl::OUString& rTokenName, SVGToken aSVGToken, const rtl::OUString& aContent); + void addCssStyleSheet(const rtl::OUString& aContent); + + /// textCss access + bool isTextCss() const { return mbTextCss; } + void setTextCss(bool bNew) { mbTextCss = bNew; } + }; + } // end of namespace svgreader +} // end of namespace svgio + +////////////////////////////////////////////////////////////////////////////// + +#endif //INCLUDED_SVGIO_SVGREADER_SVGSTYLENODE_HXX + +// eof diff --git a/svgio/inc/svgio/svgreader/svgsvgnode.hxx b/svgio/inc/svgio/svgreader/svgsvgnode.hxx new file mode 100644 index 000000000000..a72fcf7ad243 --- /dev/null +++ b/svgio/inc/svgio/svgreader/svgsvgnode.hxx @@ -0,0 +1,97 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +#ifndef INCLUDED_SVGIO_SVGREADER_SVGSVGNODE_HXX +#define INCLUDED_SVGIO_SVGREADER_SVGSVGNODE_HXX + +#include <svgio/svgiodllapi.h> +#include <svgio/svgreader/svgstyleattributes.hxx> + +////////////////////////////////////////////////////////////////////////////// + +namespace svgio +{ + namespace svgreader + { + class SvgSvgNode : public SvgNode + { + private: + /// use styles + SvgStyleAttributes maSvgStyleAttributes; + + /// variable scan values, dependent of given XAttributeList + basegfx::B2DRange* mpViewBox; + SvgAspectRatio maSvgAspectRatio; + SvgNumber maX; + SvgNumber maY; + SvgNumber maWidth; + SvgNumber maHeight; + SvgNumber maVersion; + + public: + SvgSvgNode( + SvgDocument& rDocument, + SvgNode* pParent); + virtual ~SvgSvgNode(); + + virtual const SvgStyleAttributes* getSvgStyleAttributes() const; + virtual void parseAttribute(const rtl::OUString& rTokenName, SVGToken aSVGToken, const rtl::OUString& aContent); + virtual void decomposeSvgNode(drawinglayer::primitive2d::Primitive2DSequence& rTarget, bool bReferenced) const; + + /// InfoProvider support for % values + virtual const basegfx::B2DRange* getCurrentViewPort() const; + + /// viewBox content + const basegfx::B2DRange* getViewBox() const { return mpViewBox; } + void setViewBox(const basegfx::B2DRange* pViewBox = 0) { if(mpViewBox) delete mpViewBox; mpViewBox = 0; if(pViewBox) mpViewBox = new basegfx::B2DRange(*pViewBox); } + + /// SvgAspectRatio content + const SvgAspectRatio& getSvgAspectRatio() const { return maSvgAspectRatio; } + void setSvgAspectRatio(const SvgAspectRatio& rSvgAspectRatio = SvgAspectRatio()) { maSvgAspectRatio = rSvgAspectRatio; } + + /// x content + const SvgNumber& getX() const { return maX; } + void setX(const SvgNumber& rX = SvgNumber()) { maX = rX; } + + /// y content + const SvgNumber& getY() const { return maY; } + void setY(const SvgNumber& rY = SvgNumber()) { maY = rY; } + + /// width content + const SvgNumber& getWidth() const { return maWidth; } + void setWidth(const SvgNumber& rWidth = SvgNumber()) { maWidth = rWidth; } + + /// height content + const SvgNumber& getHeight() const { return maHeight; } + void setHeight(const SvgNumber& rHeight = SvgNumber()) { maHeight = rHeight; } + + /// version content + const SvgNumber& getVersion() const { return maVersion; } + void setVersion(const SvgNumber& rVersion = SvgNumber()) { maVersion = rVersion; } + }; + } // end of namespace svgreader +} // end of namespace svgio + +////////////////////////////////////////////////////////////////////////////// + +#endif //INCLUDED_SVGIO_SVGREADER_SVGSVGNODE_HXX + +// eof diff --git a/svgio/inc/svgio/svgreader/svgsymbolnode.hxx b/svgio/inc/svgio/svgreader/svgsymbolnode.hxx new file mode 100644 index 000000000000..b7b2df125d6e --- /dev/null +++ b/svgio/inc/svgio/svgreader/svgsymbolnode.hxx @@ -0,0 +1,68 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +#ifndef INCLUDED_SVGIO_SVGREADER_SVGSYMBOLNODE_HXX +#define INCLUDED_SVGIO_SVGREADER_SVGSYMBOLNODE_HXX + +#include <svgio/svgiodllapi.h> +#include <svgio/svgreader/svgstyleattributes.hxx> + +////////////////////////////////////////////////////////////////////////////// + +namespace svgio +{ + namespace svgreader + { + class SvgSymbolNode : public SvgNode + { + private: + /// use styles + SvgStyleAttributes maSvgStyleAttributes; + + /// variable scan values, dependent of given XAttributeList + basegfx::B2DRange* mpViewBox; + SvgAspectRatio maSvgAspectRatio; + + public: + SvgSymbolNode( + SvgDocument& rDocument, + SvgNode* pParent); + virtual ~SvgSymbolNode(); + + virtual const SvgStyleAttributes* getSvgStyleAttributes() const; + virtual void parseAttribute(const rtl::OUString& rTokenName, SVGToken aSVGToken, const rtl::OUString& aContent); + + /// viewBox content + const basegfx::B2DRange* getViewBox() const { return mpViewBox; } + void setViewBox(const basegfx::B2DRange* pViewBox = 0) { if(mpViewBox) delete mpViewBox; mpViewBox = 0; if(pViewBox) mpViewBox = new basegfx::B2DRange(*pViewBox); } + + /// SvgAspectRatio content + const SvgAspectRatio& getSvgAspectRatio() const { return maSvgAspectRatio; } + void setSvgAspectRatio(const SvgAspectRatio& rSvgAspectRatio = SvgAspectRatio()) { maSvgAspectRatio = rSvgAspectRatio; } + }; + } // end of namespace svgreader +} // end of namespace svgio + +////////////////////////////////////////////////////////////////////////////// + +#endif //INCLUDED_SVGIO_SVGREADER_SVGSYMBOLNODE_HXX + +// eof diff --git a/svgio/inc/svgio/svgreader/svgtextnode.hxx b/svgio/inc/svgio/svgreader/svgtextnode.hxx new file mode 100644 index 000000000000..9aeed6f91cbc --- /dev/null +++ b/svgio/inc/svgio/svgreader/svgtextnode.hxx @@ -0,0 +1,80 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +#ifndef INCLUDED_SVGIO_SVGREADER_SVGTEXTNODE_HXX +#define INCLUDED_SVGIO_SVGREADER_SVGTEXTNODE_HXX + +#include <svgio/svgiodllapi.h> +#include <svgio/svgreader/svgnode.hxx> +#include <svgio/svgreader/svgstyleattributes.hxx> +#include <svgio/svgreader/svgcharacternode.hxx> + +////////////////////////////////////////////////////////////////////////////// + +namespace svgio +{ + namespace svgreader + { + class SvgTextNode : public SvgNode + { + private: + /// use styles + SvgStyleAttributes maSvgStyleAttributes; + + /// variable scan values, dependent of given XAttributeList + basegfx::B2DHomMatrix* mpaTransform; + SvgTextPositions maSvgTextPositions; + + /// local helpers + void DecomposeChild( + const SvgNode& rCandidate, + drawinglayer::primitive2d::Primitive2DSequence& rTarget, + SvgTextPosition& rSvgTextPosition) const; + void addTextPrimitives( + const SvgNode& rCandidate, + drawinglayer::primitive2d::Primitive2DSequence& rTarget, + drawinglayer::primitive2d::Primitive2DSequence& rSource) const; + + public: + SvgTextNode( + SvgDocument& rDocument, + SvgNode* pParent); + virtual ~SvgTextNode(); + + virtual const SvgStyleAttributes* getSvgStyleAttributes() const; + virtual void parseAttribute(const rtl::OUString& rTokenName, SVGToken aSVGToken, const rtl::OUString& aContent); + virtual void decomposeSvgNode(drawinglayer::primitive2d::Primitive2DSequence& rTarget, bool bReferenced) const; + + /// transform content, set if found in current context + const basegfx::B2DHomMatrix* getTransform() const { return mpaTransform; } + void setTransform(const basegfx::B2DHomMatrix* pMatrix = 0) { if(mpaTransform) delete mpaTransform; mpaTransform = 0; if(pMatrix) mpaTransform = new basegfx::B2DHomMatrix(*pMatrix); } + + /// access to SvgTextPositions + const SvgTextPositions& getSvgTextPositions() const { return maSvgTextPositions; } + }; + } // end of namespace svgreader +} // end of namespace svgio + +////////////////////////////////////////////////////////////////////////////// + +#endif //INCLUDED_SVGIO_SVGREADER_SVGTEXTNODE_HXX + +// eof diff --git a/svgio/inc/svgio/svgreader/svgtextpathnode.hxx b/svgio/inc/svgio/svgreader/svgtextpathnode.hxx new file mode 100644 index 000000000000..fa5c3d84648c --- /dev/null +++ b/svgio/inc/svgio/svgreader/svgtextpathnode.hxx @@ -0,0 +1,86 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +#ifndef INCLUDED_SVGIO_SVGREADER_SVGTEXTPATHNODE_HXX +#define INCLUDED_SVGIO_SVGREADER_SVGTEXTPATHNODE_HXX + +#include <svgio/svgiodllapi.h> +#include <svgio/svgreader/svgnode.hxx> +#include <svgio/svgreader/svgstyleattributes.hxx> +#include <svgio/svgreader/svgpathnode.hxx> + +////////////////////////////////////////////////////////////////////////////// + +namespace svgio +{ + namespace svgreader + { + class SvgTextPathNode : public SvgNode + { + private: + /// use styles + SvgStyleAttributes maSvgStyleAttributes; + + /// link to path content. If maXLink + /// is set, the node can be fetched on demand + rtl::OUString maXLink; + + /// variable scan values, dependent of given XAttributeList + SvgNumber maStartOffset; + + /// bitfield + bool mbMethod : 1; // true = align, false = stretch + bool mbSpacing : 1; // true = auto, false = exact + + public: + SvgTextPathNode( + SvgDocument& rDocument, + SvgNode* pParent); + virtual ~SvgTextPathNode(); + + virtual const SvgStyleAttributes* getSvgStyleAttributes() const; + virtual void parseAttribute(const rtl::OUString& rTokenName, SVGToken aSVGToken, const rtl::OUString& aContent); + void decomposePathNode( + const drawinglayer::primitive2d::Primitive2DSequence& rPathContent, + drawinglayer::primitive2d::Primitive2DSequence& rTarget, + const basegfx::B2DPoint& rTextStart) const; + bool isValid() const; + + /// StartOffset content + const SvgNumber& getStartOffset() const { return maStartOffset; } + void setStartOffset(const SvgNumber& rStartOffset = SvgNumber()) { maStartOffset = rStartOffset; } + + /// Method content + bool getMethod() const { return mbMethod; } + void setMethod(bool bNew) { mbMethod = bNew; } + + /// Spacing content + bool getSpacing() const { return mbSpacing; } + void setSpacing(bool bNew) { mbSpacing = bNew; } + }; + } // end of namespace svgreader +} // end of namespace svgio + +////////////////////////////////////////////////////////////////////////////// + +#endif //INCLUDED_SVGIO_SVGREADER_SVGTEXTPATHNODE_HXX + +// eof diff --git a/svgio/inc/svgio/svgreader/svgtoken.hxx b/svgio/inc/svgio/svgreader/svgtoken.hxx new file mode 100644 index 000000000000..b1d2e8463cc7 --- /dev/null +++ b/svgio/inc/svgio/svgreader/svgtoken.hxx @@ -0,0 +1,194 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +#ifndef INCLUDED_SVGIO_SVGREADER_SVGTOKEN_HXX +#define INCLUDED_SVGIO_SVGREADER_SVGTOKEN_HXX + +#include <svgio/svgiodllapi.h> +#include <rtl/ustring.hxx> +#include <hash_map> + +////////////////////////////////////////////////////////////////////////////// + +namespace svgio +{ + namespace svgreader + { + // SVG token mapper with hashing + enum SVGToken + { + SVGTokenUnknown = 0, + + // diverse attribute tokens + SVGTokenWidth, + SVGTokenHeight, + SVGTokenViewBox, + SVGTokenTransform, + SVGTokenStyle, + SVGTokenD, + SVGTokenX, + SVGTokenY, + SVGTokenXmlns, + SVGTokenVersion, + SVGTokenId, + SVGTokenRx, + SVGTokenRy, + SVGTokenPoints, + SVGTokenDx, + SVGTokenDy, + SVGTokenRotate, + SVGTokenTextLength, + SVGTokenLengthAdjust, + SVGTokenFont, + SVGTokenFontFamily, + SVGTokenFontSize, + SVGTokenFontSizeAdjust, + SVGTokenFontStretch, + SVGTokenFontStyle, + SVGTokenFontVariant, + SVGTokenFontWeight, + SVGTokenDirection, + SVGTokenLetterSpacing, + SVGTokenTextDecoration, + SVGTokenUnicodeBidi, + SVGTokenWordSpacing, + SVGTokenCharacter, // not in the hash, just for simple text handling in SvgCharacterNode + SVGTokenTspan, + SVGTokenTref, + SVGTokenTextPath, + SVGTokenStartOffset, + SVGTokenMethod, + SVGTokenSpacing, + SVGTokenTextAlign, + SVGTokenPathLength, + SVGTokenType, + SVGTokenClass, + SVGTokenTextAnchor, + SVGTokenXmlSpace, + SVGTokenColor, + SVGTokenClipPathNode, + SVGTokenClipPathProperty, + SVGTokenMask, + SVGTokenClipPathUnits, + SVGTokenMaskUnits, + SVGTokenMaskContentUnits, + SVGTokenClipRule, + SVGTokenMarker, + SVGTokenMarkerStart, + SVGTokenMarkerMid, + SVGTokenMarkerEnd, + SVGTokenRefX, + SVGTokenRefY, + SVGTokenMarkerUnits, + SVGTokenMarkerWidth, + SVGTokenMarkerHeight, + SVGTokenOrient, + SVGTokenPattern, + SVGTokenPatternUnits, + SVGTokenPatternContentUnits, + SVGTokenPatternTransform, + SVGTokenOpacity, + + // AspectRatio and params + SVGTokenPreserveAspectRatio, + SVGTokenDefer, + SVGTokenNone, + SVGTokenXMinYMin, + SVGTokenXMidYMin, + SVGTokenXMaxYMin, + SVGTokenXMinYMid, + SVGTokenXMidYMid, + SVGTokenXMaxYMid, + SVGTokenXMinYMax, + SVGTokenXMidYMax, + SVGTokenXMaxYMax, + SVGTokenMeet, + SVGTokenSlice, + + // structural elements + SVGTokenDefs, + SVGTokenG, + SVGTokenSvg, + SVGTokenSymbol, + SVGTokenUse, + + // shape elements + SVGTokenCircle, + SVGTokenEllipse, + SVGTokenLine, + SVGTokenPath, + SVGTokenPolygon, + SVGTokenPolyline, + SVGTokenRect, + SVGTokenImage, + + // gradient elements and tokens + SVGTokenLinearGradient, + SVGTokenRadialGradient, + SVGTokenStop, + SVGTokenOffset, + SVGTokenX1, + SVGTokenY1, + SVGTokenX2, + SVGTokenY2, + SVGTokenCx, + SVGTokenCy, + SVGTokenFx, + SVGTokenFy, + SVGTokenR, + SVGTokenGradientUnits, + SVGTokenGradientTransform, + SVGTokenSpreadMethod, + SVGTokenXlinkHref, + SVGTokenStopColor, + SVGTokenStopOpacity, + + // fill tokens + SVGTokenFill, + SVGTokenFillOpacity, + SVGTokenFillRule, + + // stroke tokens + SVGTokenStroke, + SVGTokenStrokeDasharray, + SVGTokenStrokeDashoffset, + SVGTokenStrokeLinecap, + SVGTokenStrokeLinejoin, + SVGTokenStrokeMiterlimit, + SVGTokenStrokeOpacity, + SVGTokenStrokeWidth, + + // text tokens + SVGTokenText, + + SVGTokenLast + }; + + SVGToken StrToSVGToken(const rtl::OUString& rStr); + + } // end of namespace svgreader +} // end of namespace svgio + +////////////////////////////////////////////////////////////////////////////// + +#endif //INCLUDED_SVGIO_SVGREADER_SVGTOKEN_HXX + +// eof diff --git a/svgio/inc/svgio/svgreader/svgtools.hxx b/svgio/inc/svgio/svgreader/svgtools.hxx new file mode 100644 index 000000000000..3933d3b41335 --- /dev/null +++ b/svgio/inc/svgio/svgreader/svgtools.hxx @@ -0,0 +1,228 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +#ifndef INCLUDED_SVGIO_SVGREADER_SVGTOOLS_HXX +#define INCLUDED_SVGIO_SVGREADER_SVGTOOLS_HXX + +#include <svgio/svgiodllapi.h> +#include <drawinglayer/primitive2d/baseprimitive2d.hxx> +#include <basegfx/color/bcolor.hxx> +#include <basegfx/polygon/b2dpolypolygon.hxx> +#include <svgio/svgreader/svgpaint.hxx> +#include <vector> + +////////////////////////////////////////////////////////////////////////////// + +namespace svgio +{ + namespace svgreader + { +#ifdef DBG_UTIL + // error helper + void myAssert(const rtl::OUString& rMessage); +#endif + + // common non-token strings + struct commonStrings + { + static const rtl::OUString aStrUserSpaceOnUse; + static const rtl::OUString aStrObjectBoundingBox; + static const rtl::OUString aStrNonzero; + static const rtl::OUString aStrEvenOdd; + }; + + enum SvgUnits + { + userSpaceOnUse, + objectBoundingBox + }; + + enum NumberType + { + xcoordinate, + ycoordinate, + length + }; + + class InfoProvider + { + public: + virtual const basegfx::B2DRange* getCurrentViewPort() const = 0; + virtual double getCurrentFontSize() const = 0; + virtual double getCurrentXHeight() const = 0; + }; + + enum SvgUnit + { + Unit_em = 0, // relative to current font size + Unit_ex, // relative to current x-height + + Unit_px, // 'user unit' + Unit_pt, // points, 1.25 px + Unit_pc, // 15.0 px + Unit_cm, // 35.43307 px + Unit_mm, // 3.543307 px + Unit_in, // 90 px + + Unit_percent // relative to range + }; + + class SvgNumber + { + private: + double mfNumber; + SvgUnit meUnit; + + /// bitfield + bool mbSet : 1; + + public: + SvgNumber() + : mfNumber(0.0), + meUnit(Unit_px), + mbSet(false) + { + } + + SvgNumber(double fNum, SvgUnit aSvgUnit = Unit_px, bool bSet = true) + : mfNumber(fNum), + meUnit(aSvgUnit), + mbSet(bSet) + { + } + + double getNumber() const + { + return mfNumber; + } + + SvgUnit getUnit() const + { + return meUnit; + } + + bool isSet() const + { + return mbSet; + } + + bool isPositive() const; + + double solve(const InfoProvider& rInfoProvider, NumberType aNumberType = length) const; + }; + + typedef ::std::vector< SvgNumber > SvgNumberVector; + + enum SvgAlign + { + Align_none, + Align_xMinYMin, + Align_xMidYMin, + Align_xMaxYMin, + Align_xMinYMid, + Align_xMidYMid, // default + Align_xMaxYMid, + Align_xMinYMax, + Align_xMidYMax, + Align_xMaxYMax + }; + + class SvgAspectRatio + { + private: + SvgAlign maSvgAlign; + + /// bitfield + bool mbDefer : 1; // default is false + bool mbMeetOrSlice : 1; // true = meet (default), false = slice + bool mbSet : 1; + + public: + SvgAspectRatio() + : maSvgAlign(Align_xMidYMid), + mbDefer(false), + mbMeetOrSlice(true), + mbSet(false) + { + } + + SvgAspectRatio(SvgAlign aSvgAlign, bool bDefer, bool bMeetOrSlice) + : maSvgAlign(aSvgAlign), + mbDefer(bDefer), + mbMeetOrSlice(bMeetOrSlice), + mbSet(true) + { + } + + /// data read access + SvgAlign getSvgAlign() const { return maSvgAlign; } + bool isDefer() const { return mbDefer; } + bool isMeetOrSlice() const { return mbMeetOrSlice; } + bool isSet() const { return mbSet; } + + /// tooling + static basegfx::B2DHomMatrix createLinearMapping(const basegfx::B2DRange& rTarget, const basegfx::B2DRange& rSource); + basegfx::B2DHomMatrix createMapping(const basegfx::B2DRange& rTarget, const basegfx::B2DRange& rSource) const; + }; + + void skip_char(const rtl::OUString& rCandidate, const sal_Unicode& rChar, sal_Int32& nPos, const sal_Int32 nLen); + void skip_char(const rtl::OUString& rCandidate, const sal_Unicode& rCharA, const sal_Unicode& rCharB, sal_Int32& nPos, const sal_Int32 nLen); + void copySign(const rtl::OUString& rCandidate, sal_Int32& nPos, rtl::OUStringBuffer& rTarget, const sal_Int32 nLen); + void copyNumber(const rtl::OUString& rCandidate, sal_Int32& nPos, rtl::OUStringBuffer& rTarget, const sal_Int32 nLen); + void copyHex(const rtl::OUString& rCandidate, sal_Int32& nPos, rtl::OUStringBuffer& rTarget, const sal_Int32 nLen); + void copyString(const rtl::OUString& rCandidate, sal_Int32& nPos, rtl::OUStringBuffer& rTarget, const sal_Int32 nLen); + void copyToLimiter(const rtl::OUString& rCandidate, const sal_Unicode& rLimiter, sal_Int32& nPos, rtl::OUStringBuffer& rTarget, const sal_Int32 nLen); + bool readNumber(const rtl::OUString& rCandidate, sal_Int32& nPos, double& fNum, const sal_Int32 nLen); + SvgUnit readUnit(const rtl::OUString& rCandidate, sal_Int32& nPos, const sal_Int32 nLen); + bool readNumberAndUnit(const rtl::OUString& rCandidate, sal_Int32& nPos, SvgNumber& aNum, const sal_Int32 nLen); + bool readAngle(const rtl::OUString& rCandidate, sal_Int32& nPos, double& fAngle, const sal_Int32 nLen); + sal_Int32 read_hex(const sal_Unicode& rChar); + bool match_colorKeyword(basegfx::BColor& rColor, const rtl::OUString& rName); + bool read_color(const rtl::OUString& rCandidate, basegfx::BColor& rColor); + basegfx::B2DRange readViewBox(const rtl::OUString& rCandidate, InfoProvider& rInfoProvider); + basegfx::B2DHomMatrix readTransform(const rtl::OUString& rCandidate, InfoProvider& rInfoProvider); + bool readSingleNumber(const rtl::OUString& rCandidate, SvgNumber& aNum); + bool readLocalUrl(const rtl::OUString& rCandidate, rtl::OUString& rURL); + bool readSvgPaint(const rtl::OUString& rCandidate, SvgPaint& rSvgPaint, rtl::OUString& rURL); + + bool readSvgNumberVector(const rtl::OUString& rCandidate, SvgNumberVector& rSvgNumberVector); + ::std::vector< double > solveSvgNumberVector(const SvgNumberVector& rInput, const InfoProvider& rInfoProvider, NumberType aNumberType = length); + + SvgAspectRatio readSvgAspectRatio(const rtl::OUString& rCandidate); + + typedef ::std::vector< rtl::OUString > SvgStringVector; + bool readSvgStringVector(const rtl::OUString& rCandidate, SvgStringVector& rSvgStringVector); + + void readImageLink(const rtl::OUString& rCandidate, rtl::OUString& rXLink, rtl::OUString& rUrl, rtl::OUString& rMimeType, rtl::OUString& rData); + + rtl::OUString convert(const rtl::OUString& rCandidate, const sal_Unicode& rPattern, const sal_Unicode& rNew, bool bRemove); + rtl::OUString consolidateContiguosSpace(const rtl::OUString& rCandidate); + rtl::OUString whiteSpaceHandlingDefault(const rtl::OUString& rCandidate); + rtl::OUString whiteSpaceHandlingPreserve(const rtl::OUString& rCandidate); + + } // end of namespace svgreader +} // end of namespace svgio + +////////////////////////////////////////////////////////////////////////////// + +#endif //INCLUDED_SVGIO_SVGREADER_SVGTOOLS_HXX + +// eof diff --git a/svgio/inc/svgio/svgreader/svgtrefnode.hxx b/svgio/inc/svgio/svgreader/svgtrefnode.hxx new file mode 100644 index 000000000000..798de70c1094 --- /dev/null +++ b/svgio/inc/svgio/svgreader/svgtrefnode.hxx @@ -0,0 +1,65 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +#ifndef INCLUDED_SVGIO_SVGREADER_SVGTREFNODE_HXX +#define INCLUDED_SVGIO_SVGREADER_SVGTREFNODE_HXX + +#include <svgio/svgiodllapi.h> +#include <svgio/svgreader/svgnode.hxx> +#include <svgio/svgreader/svgstyleattributes.hxx> +#include <svgio/svgreader/svgtextnode.hxx> + +////////////////////////////////////////////////////////////////////////////// + +namespace svgio +{ + namespace svgreader + { + class SvgTrefNode : public SvgNode + { + private: + /// use styles + SvgStyleAttributes maSvgStyleAttributes; + + /// link to text content. If maXLink + /// is set, the node can be fetched on demand + rtl::OUString maXLink; + + public: + SvgTrefNode( + SvgDocument& rDocument, + SvgNode* pParent); + virtual ~SvgTrefNode(); + + virtual const SvgStyleAttributes* getSvgStyleAttributes() const; + virtual void parseAttribute(const rtl::OUString& rTokenName, SVGToken aSVGToken, const rtl::OUString& aContent); + + /// access to referenced SvgTextNode + const SvgTextNode* getReferencedSvgTextNode() const; + }; + } // end of namespace svgreader +} // end of namespace svgio + +////////////////////////////////////////////////////////////////////////////// + +#endif //INCLUDED_SVGIO_SVGREADER_SVGTREFNODE_HXX + +// eof diff --git a/svgio/inc/svgio/svgreader/svgtspannode.hxx b/svgio/inc/svgio/svgreader/svgtspannode.hxx new file mode 100644 index 000000000000..45cd1f8d03d9 --- /dev/null +++ b/svgio/inc/svgio/svgreader/svgtspannode.hxx @@ -0,0 +1,64 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +#ifndef INCLUDED_SVGIO_SVGREADER_SVGTSPANNODE_HXX +#define INCLUDED_SVGIO_SVGREADER_SVGTSPANNODE_HXX + +#include <svgio/svgiodllapi.h> +#include <svgio/svgreader/svgcharacternode.hxx> +#include <svgio/svgreader/svgstyleattributes.hxx> +#include <svgio/svgreader/svgtools.hxx> + +////////////////////////////////////////////////////////////////////////////// + +namespace svgio +{ + namespace svgreader + { + class SvgTspanNode : public SvgNode + { + private: + /// use styles + SvgStyleAttributes maSvgStyleAttributes; + + /// variable scan values, dependent of given XAttributeList + SvgTextPositions maSvgTextPositions; + + public: + SvgTspanNode( + SvgDocument& rDocument, + SvgNode* pParent); + virtual ~SvgTspanNode(); + + virtual const SvgStyleAttributes* getSvgStyleAttributes() const; + virtual void parseAttribute(const rtl::OUString& rTokenName, SVGToken aSVGToken, const rtl::OUString& aContent); + + /// access to SvgTextPositions + const SvgTextPositions& getSvgTextPositions() const { return maSvgTextPositions; } + }; + } // end of namespace svgreader +} // end of namespace svgio + +////////////////////////////////////////////////////////////////////////////// + +#endif //INCLUDED_SVGIO_SVGREADER_SVGTSPANNODE_HXX + +// eof diff --git a/svgio/inc/svgio/svgreader/svgusenode.hxx b/svgio/inc/svgio/svgreader/svgusenode.hxx new file mode 100644 index 000000000000..e9fa0ccead17 --- /dev/null +++ b/svgio/inc/svgio/svgreader/svgusenode.hxx @@ -0,0 +1,89 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +#ifndef INCLUDED_SVGIO_SVGREADER_USENODE_HXX +#define INCLUDED_SVGIO_SVGREADER_USENODE_HXX + +#include <svgio/svgiodllapi.h> +#include <svgio/svgreader/svgnode.hxx> +#include <svgio/svgreader/svgstyleattributes.hxx> + +////////////////////////////////////////////////////////////////////////////// + +namespace svgio +{ + namespace svgreader + { + class SvgUseNode : public SvgNode + { + private: + /// use styles + SvgStyleAttributes maSvgStyleAttributes; + + /// variable scan values, dependent of given XAttributeList + basegfx::B2DHomMatrix* mpaTransform; + SvgNumber maX; + SvgNumber maY; + SvgNumber maWidth; + SvgNumber maHeight; + + /// link to content. If maXLink is set, the node can be fetched + // on demand + rtl::OUString maXLink; + + public: + SvgUseNode( + SvgDocument& rDocument, + SvgNode* pParent); + virtual ~SvgUseNode(); + + virtual const SvgStyleAttributes* getSvgStyleAttributes() const; + virtual void parseAttribute(const rtl::OUString& rTokenName, SVGToken aSVGToken, const rtl::OUString& aContent); + virtual void decomposeSvgNode(drawinglayer::primitive2d::Primitive2DSequence& rTarget, bool bReferenced) const; + + /// transform content + const basegfx::B2DHomMatrix* getTransform() const { return mpaTransform; } + void setTransform(const basegfx::B2DHomMatrix* pMatrix = 0) { if(mpaTransform) delete mpaTransform; mpaTransform = 0; if(pMatrix) mpaTransform = new basegfx::B2DHomMatrix(*pMatrix); } + + /// x content + const SvgNumber& getX() const { return maX; } + void setX(const SvgNumber& rX = SvgNumber()) { maX = rX; } + + /// y content + const SvgNumber& getY() const { return maY; } + void setY(const SvgNumber& rY = SvgNumber()) { maY = rY; } + + /// width content + const SvgNumber& getWidth() const { return maWidth; } + void setWidth(const SvgNumber& rWidth = SvgNumber()) { maWidth = rWidth; } + + /// height content + const SvgNumber& getHeight() const { return maHeight; } + void setHeight(const SvgNumber& rHeight = SvgNumber()) { maHeight = rHeight; } + }; + } // end of namespace svgreader +} // end of namespace svgio + +////////////////////////////////////////////////////////////////////////////// + +#endif //INCLUDED_SVGIO_SVGREADER_USENODE_HXX + +// eof diff --git a/svgio/prj/build.lst b/svgio/prj/build.lst new file mode 100644 index 000000000000..ff858ab1ddda --- /dev/null +++ b/svgio/prj/build.lst @@ -0,0 +1,2 @@ +dl svgio : sal basegfx drawinglayer cppuhelper cppu svtools NULL +dl svgio\prj nmake - all svgio_prj NULL diff --git a/svgio/prj/d.lst b/svgio/prj/d.lst new file mode 100755 index 000000000000..e69de29bb2d1 --- /dev/null +++ b/svgio/prj/d.lst diff --git a/svgio/prj/makefile.mk b/svgio/prj/makefile.mk new file mode 100644 index 000000000000..e312a7ccab65 --- /dev/null +++ b/svgio/prj/makefile.mk @@ -0,0 +1,40 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=.. +TARGET=prj + +.INCLUDE : settings.mk + +.IF "$(VERBOSE)"!="" +VERBOSEFLAG := +.ELSE +VERBOSEFLAG := -s +.ENDIF + +all: + cd $(PRJ) && $(GNUMAKE) $(VERBOSEFLAG) -r -j$(MAXPROCESS) $(gb_MAKETARGET) && $(GNUMAKE) $(VERBOSEFLAG) -r deliverlog diff --git a/svgio/source/svgreader/svgcharacternode.cxx b/svgio/source/svgreader/svgcharacternode.cxx new file mode 100644 index 000000000000..bf37cb6e9361 --- /dev/null +++ b/svgio/source/svgreader/svgcharacternode.cxx @@ -0,0 +1,725 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svgio.hxx" + +#include <svgio/svgreader/svgcharacternode.hxx> +#include <svgio/svgreader/svgstyleattributes.hxx> +#include <drawinglayer/attribute/fontattribute.hxx> +#include <drawinglayer/primitive2d/textprimitive2d.hxx> +#include <drawinglayer/primitive2d/textlayoutdevice.hxx> +#include <drawinglayer/primitive2d/textbreakuphelper.hxx> +#include <drawinglayer/primitive2d/groupprimitive2d.hxx> +#include <drawinglayer/primitive2d/textdecoratedprimitive2d.hxx> + +////////////////////////////////////////////////////////////////////////////// + +namespace svgio +{ + namespace svgreader + { + SvgTextPositions::SvgTextPositions() + : maX(), + maY(), + maDx(), + maDy(), + maRotate(), + maTextLength(), + mbLengthAdjust(true) + { + } + + void SvgTextPositions::parseTextPositionAttributes(const rtl::OUString& rTokenName, SVGToken aSVGToken, const rtl::OUString& aContent) + { + // parse own + switch(aSVGToken) + { + case SVGTokenX: + { + if(aContent.getLength()) + { + SvgNumberVector aVector; + + if(readSvgNumberVector(aContent, aVector)) + { + setX(aVector); + } + } + break; + } + case SVGTokenY: + { + if(aContent.getLength()) + { + SvgNumberVector aVector; + + if(readSvgNumberVector(aContent, aVector)) + { + setY(aVector); + } + } + break; + } + case SVGTokenDx: + { + if(aContent.getLength()) + { + SvgNumberVector aVector; + + if(readSvgNumberVector(aContent, aVector)) + { + setDx(aVector); + } + } + break; + } + case SVGTokenDy: + { + if(aContent.getLength()) + { + SvgNumberVector aVector; + + if(readSvgNumberVector(aContent, aVector)) + { + setDy(aVector); + } + } + break; + } + case SVGTokenRotate: + { + if(aContent.getLength()) + { + SvgNumberVector aVector; + + if(readSvgNumberVector(aContent, aVector)) + { + setRotate(aVector); + } + } + break; + } + case SVGTokenTextLength: + { + SvgNumber aNum; + + if(readSingleNumber(aContent, aNum)) + { + if(aNum.isPositive()) + { + setTextLength(aNum); + } + } + break; + } + case SVGTokenLengthAdjust: + { + if(aContent.getLength()) + { + static rtl::OUString aStrSpacing(rtl::OUString::createFromAscii("spacing")); + static rtl::OUString aStrSpacingAndGlyphs(rtl::OUString::createFromAscii("spacingAndGlyphs")); + + if(aContent.match(aStrSpacing)) + { + setLengthAdjust(true); + } + else if(aContent.match(aStrSpacingAndGlyphs)) + { + setLengthAdjust(false); + } + } + break; + } + } + } + + } // end of namespace svgreader +} // end of namespace svgio + +////////////////////////////////////////////////////////////////////////////// + +namespace svgio +{ + namespace svgreader + { + class localTextBreakupHelper : public drawinglayer::primitive2d::TextBreakupHelper + { + private: + SvgTextPosition& mrSvgTextPosition; + + protected: + /// allow user callback to allow changes to the new TextTransformation. Default + /// does nothing. + virtual bool allowChange(sal_uInt32 nCount, basegfx::B2DHomMatrix& rNewTransform, sal_uInt32 nIndex, sal_uInt32 nLength); + + public: + localTextBreakupHelper( + const drawinglayer::primitive2d::Primitive2DReference& rxSource, + SvgTextPosition& rSvgTextPosition) + : drawinglayer::primitive2d::TextBreakupHelper(rxSource), + mrSvgTextPosition(rSvgTextPosition) + { + } + }; + + bool localTextBreakupHelper::allowChange(sal_uInt32 nCount, basegfx::B2DHomMatrix& rNewTransform, sal_uInt32 nIndex, sal_uInt32 nLength) + { + const double fRotation(mrSvgTextPosition.consumeRotation()); + + if(0.0 != fRotation) + { + const basegfx::B2DPoint aBasePoint(rNewTransform * basegfx::B2DPoint(0.0, 0.0)); + + rNewTransform.translate(-aBasePoint.getX(), -aBasePoint.getY()); + rNewTransform.rotate(fRotation); + rNewTransform.translate(aBasePoint.getX(), aBasePoint.getY()); + } + + return true; + } + + } // end of namespace svgreader +} // end of namespace svgio + +////////////////////////////////////////////////////////////////////////////// + +namespace svgio +{ + namespace svgreader + { + SvgCharacterNode::SvgCharacterNode( + SvgDocument& rDocument, + SvgNode* pParent, + const rtl::OUString& rText) + : SvgNode(SVGTokenCharacter, rDocument, pParent), + maText(rText) + { + } + + SvgCharacterNode::~SvgCharacterNode() + { + } + + const SvgStyleAttributes* SvgCharacterNode::getSvgStyleAttributes() const + { + // no own style, use parent's + if(getParent()) + { + return getParent()->getSvgStyleAttributes(); + } + else + { + return 0; + } + } + + drawinglayer::primitive2d::TextSimplePortionPrimitive2D* SvgCharacterNode::createSimpleTextPrimitive( + SvgTextPosition& rSvgTextPosition, + const SvgStyleAttributes& rSvgStyleAttributes) const + { + // prepare retval, index and length + drawinglayer::primitive2d::TextSimplePortionPrimitive2D* pRetval = 0; + sal_uInt32 nIndex(0); + sal_uInt32 nLength(getText().getLength()); + + if(nLength) + { + // prepare FontAttribute + const rtl::OUString aFontFamily = rSvgStyleAttributes.getFontFamily().empty() ? + rtl::OUString(rtl::OUString::createFromAscii("Times New Roman")) : + rSvgStyleAttributes.getFontFamily()[0]; + const ::FontWeight nFontWeight(getVclFontWeight(rSvgStyleAttributes.getFontWeight())); + bool bSymbol(false); + bool bVertical(false); + bool bItalic(FontStyle_italic == rSvgStyleAttributes.getFontStyle() || FontStyle_oblique == rSvgStyleAttributes.getFontStyle()); + bool bMonospaced(false); + bool bOutline(false); + bool bRTL(false); + bool bBiDiStrong(false); + + const drawinglayer::attribute::FontAttribute aFontAttribute( + aFontFamily, + rtl::OUString(), + nFontWeight, + bSymbol, + bVertical, + bItalic, + bMonospaced, + bOutline, + bRTL, + bBiDiStrong); + + // prepare FontSize + double fFontWidth(rSvgStyleAttributes.getFontSize().solve(*this, length)); + double fFontHeight(fFontWidth); + + // prepare locale + ::com::sun::star::lang::Locale aLocale; + + // prepare TextLayouterDevice + drawinglayer::primitive2d::TextLayouterDevice aTextLayouterDevice; + aTextLayouterDevice.setFontAttribute(aFontAttribute, fFontWidth, fFontHeight, aLocale); + + // prepare TextArray + ::std::vector< double > aTextArray(rSvgTextPosition.getX()); + + if(!aTextArray.empty() && aTextArray.size() < nLength) + { + const sal_uInt32 nArray(aTextArray.size()); + + if(nArray < nLength) + { + double fStartX(0.0); + + if(rSvgTextPosition.getParent() && rSvgTextPosition.getParent()->getAbsoluteX()) + { + fStartX = rSvgTextPosition.getParent()->getPosition().getX(); + } + else + { + fStartX = aTextArray[nArray - 1]; + } + + ::std::vector< double > aExtendArray(aTextLayouterDevice.getTextArray(getText(), nArray, nLength - nArray)); + aTextArray.reserve(nLength); + + for(sal_uInt32 a(0); a < aExtendArray.size(); a++) + { + aTextArray.push_back(aExtendArray[a] + fStartX); + } + } + } + + // get current TextPosition and TextWidth in units + basegfx::B2DPoint aPosition(rSvgTextPosition.getPosition()); + double fTextWidth(aTextLayouterDevice.getTextWidth(getText(), nIndex, nLength)); + + // check for user-given TextLength + if(0.0 != rSvgTextPosition.getTextLength() + && !basegfx::fTools::equal(fTextWidth, rSvgTextPosition.getTextLength())) + { + const double fFactor(rSvgTextPosition.getTextLength() / fTextWidth); + + if(rSvgTextPosition.getLengthAdjust()) + { + // spacing, need to create and expand TextArray + if(aTextArray.empty()) + { + aTextArray = aTextLayouterDevice.getTextArray(getText(), nIndex, nLength); + } + + for(sal_uInt32 a(0); a < aTextArray.size(); a++) + { + aTextArray[a] *= fFactor; + } + } + else + { + // spacing and glyphs, just apply to FontWidth + fFontWidth *= fFactor; + } + + fTextWidth = rSvgTextPosition.getTextLength(); + } + + // get TextAlign + TextAlign aTextAlign(rSvgStyleAttributes.getTextAlign()); + + // map TextAnchor to TextAlign, there seems not to be a difference + if(TextAnchor_notset != rSvgStyleAttributes.getTextAnchor()) + { + switch(rSvgStyleAttributes.getTextAnchor()) + { + case TextAnchor_start: + { + aTextAlign = TextAlign_left; + break; + } + case TextAnchor_middle: + { + aTextAlign = TextAlign_center; + break; + } + case TextAnchor_end: + { + aTextAlign = TextAlign_right; + break; + } + } + } + + // apply TextAlign + switch(aTextAlign) + { + case TextAlign_right: + { + aPosition.setX(aPosition.getX() - fTextWidth); + break; + } + case TextAlign_center: + { + aPosition.setX(aPosition.getX() - (fTextWidth * 0.5)); + break; + } + case TextAlign_notset: + case TextAlign_left: + case TextAlign_justify: + { + // TextAlign_notset, TextAlign_left: nothing to do + // TextAlign_justify is not clear currently; handle as TextAlign_left + break; + } + } + + // get fill color + const basegfx::BColor aFill(rSvgStyleAttributes.getFill() + ? *rSvgStyleAttributes.getFill() + : basegfx::BColor(0.0, 0.0, 0.0)); + + // prepare TextTransformation + basegfx::B2DHomMatrix aTextTransform; + + aTextTransform.scale(fFontWidth, fFontHeight); + aTextTransform.translate(aPosition.getX(), aPosition.getY()); + + // check TextDecoration and if TextDecoratedPortionPrimitive2D is needed + const TextDecoration aDeco(rSvgStyleAttributes.getTextDecoration()); + + if(TextDecoration_underline == aDeco + || TextDecoration_overline == aDeco + || TextDecoration_line_through == aDeco) + { + // get the fill for decroation as described by SVG. We cannot + // have different stroke colors/definitions for those, though + const SvgStyleAttributes* pDecoDef = rSvgStyleAttributes.getTextDecorationDefiningSvgStyleAttributes(); + const basegfx::BColor aDecoColor(pDecoDef && pDecoDef->getFill() ? *pDecoDef->getFill() : aFill); + + // create decorated text primitive + pRetval = new drawinglayer::primitive2d::TextDecoratedPortionPrimitive2D( + aTextTransform, + getText(), + nIndex, + nLength, + aTextArray, + aFontAttribute, + aLocale, + aFill, + + // extra props for decorated + aDecoColor, + aDecoColor, + TextDecoration_overline == aDeco ? drawinglayer::primitive2d::TEXT_LINE_SINGLE : drawinglayer::primitive2d::TEXT_LINE_NONE, + TextDecoration_underline == aDeco ? drawinglayer::primitive2d::TEXT_LINE_SINGLE : drawinglayer::primitive2d::TEXT_LINE_NONE, + false, + TextDecoration_line_through == aDeco ? drawinglayer::primitive2d::TEXT_STRIKEOUT_SINGLE : drawinglayer::primitive2d::TEXT_STRIKEOUT_NONE, + false, + drawinglayer::primitive2d::TEXT_EMPHASISMARK_NONE, + true, + false, + drawinglayer::primitive2d::TEXT_RELIEF_NONE, + false); + } + else + { + // create text primitive + pRetval = new drawinglayer::primitive2d::TextSimplePortionPrimitive2D( + aTextTransform, + getText(), + nIndex, + nLength, + aTextArray, + aFontAttribute, + aLocale, + aFill); + } + + // advance current TextPosition + rSvgTextPosition.setPosition(rSvgTextPosition.getPosition() + basegfx::B2DVector(fTextWidth, 0.0)); + } + + return pRetval; + } + + void SvgCharacterNode::decomposeTextWithStyle( + drawinglayer::primitive2d::Primitive2DSequence& rTarget, + SvgTextPosition& rSvgTextPosition, + const SvgStyleAttributes& rSvgStyleAttributes) const + { + const drawinglayer::primitive2d::Primitive2DReference xRef( + createSimpleTextPrimitive( + rSvgTextPosition, + rSvgStyleAttributes)); + + if(xRef.is()) + { + if(!rSvgTextPosition.isRotated()) + { + drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(rTarget, xRef); + } + else + { + // need to apply rotations to each character as given + localTextBreakupHelper alocalTextBreakupHelper(xRef, rSvgTextPosition); + const drawinglayer::primitive2d::Primitive2DSequence aResult( + alocalTextBreakupHelper.getResult(drawinglayer::primitive2d::BreakupUnit_character)); + + if(aResult.hasElements()) + { + drawinglayer::primitive2d::appendPrimitive2DSequenceToPrimitive2DSequence(rTarget, aResult); + } + + // also consume for the implied single space + rSvgTextPosition.consumeRotation(); + } + } + } + + void SvgCharacterNode::whiteSpaceHandling() + { + if(XmlSpace_default == getXmlSpace()) + { + maText = whiteSpaceHandlingDefault(maText); + } + else + { + maText = whiteSpaceHandlingPreserve(maText); + } + } + + void SvgCharacterNode::addGap() + { + maText += rtl::OUString(sal_Unicode(' ')); + } + + void SvgCharacterNode::concatenate(const rtl::OUString& rText) + { + maText += rText; + } + + void SvgCharacterNode::decomposeText(drawinglayer::primitive2d::Primitive2DSequence& rTarget, SvgTextPosition& rSvgTextPosition) const + { + if(getText().getLength()) + { + const SvgStyleAttributes* pSvgStyleAttributes = getSvgStyleAttributes(); + + if(pSvgStyleAttributes) + { + decomposeTextWithStyle(rTarget, rSvgTextPosition, *pSvgStyleAttributes); + } + } + } + + } // end of namespace svgreader +} // end of namespace svgio + +////////////////////////////////////////////////////////////////////////////// + +namespace svgio +{ + namespace svgreader + { + SvgTextPosition::SvgTextPosition( + SvgTextPosition* pParent, + const InfoProvider& rInfoProvider, + const SvgTextPositions& rSvgTextPositions) + : mpParent(pParent), + maX(), // computed below + maY(), // computed below + maRotate(solveSvgNumberVector(rSvgTextPositions.getRotate(), rInfoProvider, length)), + mfTextLength(0.0), + maPosition(), // computed below + mnRotationIndex(0), + mbLengthAdjust(rSvgTextPositions.getLengthAdjust()), + mbAbsoluteX(false), + mbAbsoluteY(false) + { + // get TextLength if provided + if(rSvgTextPositions.getTextLength().isSet()) + { + mfTextLength = rSvgTextPositions.getTextLength().solve(rInfoProvider, length); + } + + // SVG does not really define in which units a rotate for Text/TSpan is given, + // but it seems to be degrees. Convert here to radians + if(!maRotate.empty()) + { + const double fFactor(F_PI / 180.0); + + for(sal_uInt32 a(0); a < maRotate.size(); a++) + { + maRotate[a] *= fFactor; + } + } + + // get text positions X + const sal_uInt32 nSizeX(rSvgTextPositions.getX().size()); + + if(nSizeX) + { + // we have absolute positions, get first one as current text position X + maPosition.setX(rSvgTextPositions.getX()[0].solve(rInfoProvider, xcoordinate)); + mbAbsoluteX = true; + + if(nSizeX > 1) + { + // fill deltas to maX + maX.reserve(nSizeX); + + for(sal_uInt32 a(1); a < nSizeX; a++) + { + maX.push_back(rSvgTextPositions.getX()[a].solve(rInfoProvider, xcoordinate) - maPosition.getX()); + } + } + } + else + { + // no absolute position, get from parent + if(pParent) + { + maPosition.setX(pParent->getPosition().getX()); + } + + const sal_uInt32 nSizeDx(rSvgTextPositions.getDx().size()); + + if(nSizeDx) + { + // relative positions given, translate position derived from parent + maPosition.setX(maPosition.getX() + rSvgTextPositions.getDx()[0].solve(rInfoProvider, xcoordinate)); + + if(nSizeDx > 1) + { + // fill deltas to maX + maX.reserve(nSizeDx); + + for(sal_uInt32 a(1); a < nSizeDx; a++) + { + maX.push_back(rSvgTextPositions.getDx()[a].solve(rInfoProvider, xcoordinate)); + } + } + } + } + + // get text positions Y + const sal_uInt32 nSizeY(rSvgTextPositions.getY().size()); + + if(nSizeY) + { + // we have absolute positions, get first one as current text position Y + maPosition.setY(rSvgTextPositions.getY()[0].solve(rInfoProvider, ycoordinate)); + mbAbsoluteX = true; + + if(nSizeY > 1) + { + // fill deltas to maY + maY.reserve(nSizeY); + + for(sal_uInt32 a(1); a < nSizeY; a++) + { + maY.push_back(rSvgTextPositions.getY()[a].solve(rInfoProvider, ycoordinate) - maPosition.getY()); + } + } + } + else + { + // no absolute position, get from parent + if(pParent) + { + maPosition.setY(pParent->getPosition().getY()); + } + + const sal_uInt32 nSizeDy(rSvgTextPositions.getDy().size()); + + if(nSizeDy) + { + // relative positions given, translate position derived from parent + maPosition.setY(maPosition.getY() + rSvgTextPositions.getDy()[0].solve(rInfoProvider, ycoordinate)); + + if(nSizeDy > 1) + { + // fill deltas to maY + maY.reserve(nSizeDy); + + for(sal_uInt32 a(1); a < nSizeDy; a++) + { + maY.push_back(rSvgTextPositions.getDy()[a].solve(rInfoProvider, ycoordinate)); + } + } + } + } + } + + bool SvgTextPosition::isRotated() const + { + if(maRotate.empty()) + { + if(getParent()) + { + return getParent()->isRotated(); + } + else + { + return false; + } + } + else + { + return true; + } + } + + double SvgTextPosition::consumeRotation() + { + double fRetval(0.0); + + if(maRotate.empty()) + { + if(getParent()) + { + fRetval = mpParent->consumeRotation(); + } + else + { + fRetval = 0.0; + } + } + else + { + const sal_uInt32 nSize(maRotate.size()); + + if(mnRotationIndex < nSize) + { + fRetval = maRotate[mnRotationIndex++]; + } + else + { + fRetval = maRotate[nSize - 1]; + } + } + + return fRetval; + } + + } // end of namespace svgreader +} // end of namespace svgio + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/svgio/source/svgreader/svgcirclenode.cxx b/svgio/source/svgreader/svgcirclenode.cxx new file mode 100644 index 000000000000..95a81ff5611d --- /dev/null +++ b/svgio/source/svgreader/svgcirclenode.cxx @@ -0,0 +1,154 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svgio.hxx" + +#include <svgio/svgreader/svgcirclenode.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> +#include <basegfx/polygon/b2dpolygontools.hxx> + +////////////////////////////////////////////////////////////////////////////// + +namespace svgio +{ + namespace svgreader + { + SvgCircleNode::SvgCircleNode( + SvgDocument& rDocument, + SvgNode* pParent) + : SvgNode(SVGTokenCircle, rDocument, pParent), + maSvgStyleAttributes(*this), + maCx(0), + maCy(0), + maR(0), + mpaTransform(0) + { + } + + SvgCircleNode::~SvgCircleNode() + { + if(mpaTransform) delete mpaTransform; + } + + const SvgStyleAttributes* SvgCircleNode::getSvgStyleAttributes() const + { + static rtl::OUString aClassStr(rtl::OUString::createFromAscii("circle")); + maSvgStyleAttributes.checkForCssStyle(aClassStr); + + return &maSvgStyleAttributes; + } + + void SvgCircleNode::parseAttribute(const rtl::OUString& rTokenName, SVGToken aSVGToken, const rtl::OUString& aContent) + { + // call parent + SvgNode::parseAttribute(rTokenName, aSVGToken, aContent); + + // read style attributes + maSvgStyleAttributes.parseStyleAttribute(rTokenName, aSVGToken, aContent); + + // parse own + switch(aSVGToken) + { + case SVGTokenStyle: + { + maSvgStyleAttributes.readStyle(aContent); + break; + } + case SVGTokenCx: + { + SvgNumber aNum; + + if(readSingleNumber(aContent, aNum)) + { + setCx(aNum); + } + break; + } + case SVGTokenCy: + { + SvgNumber aNum; + + if(readSingleNumber(aContent, aNum)) + { + setCy(aNum); + } + break; + } + case SVGTokenR: + { + SvgNumber aNum; + + if(readSingleNumber(aContent, aNum)) + { + if(aNum.isPositive()) + { + setR(aNum); + } + } + break; + } + case SVGTokenTransform: + { + const basegfx::B2DHomMatrix aMatrix(readTransform(aContent, *this)); + + if(!aMatrix.isIdentity()) + { + setTransform(&aMatrix); + } + break; + } + } + } + + void SvgCircleNode::decomposeSvgNode(drawinglayer::primitive2d::Primitive2DSequence& rTarget, bool bReferenced) const + { + const SvgStyleAttributes* pStyle = getSvgStyleAttributes(); + + if(pStyle && getR().isSet()) + { + const double fR(getR().solve(*this, xcoordinate)); + + if(fR > 0.0) + { + const basegfx::B2DPolygon aPath( + basegfx::tools::createPolygonFromCircle( + basegfx::B2DPoint( + getCx().isSet() ? getCx().solve(*this, xcoordinate) : 0.0, + getCy().isSet() ? getCy().solve(*this, ycoordinate) : 0.0), + fR)); + + drawinglayer::primitive2d::Primitive2DSequence aNewTarget; + + pStyle->add_path(basegfx::B2DPolyPolygon(aPath), aNewTarget); + + if(aNewTarget.hasElements()) + { + pStyle->add_postProcess(rTarget, aNewTarget, getTransform()); + } + } + } + } + } // end of namespace svgreader +} // end of namespace svgio + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/svgio/source/svgreader/svgclippathnode.cxx b/svgio/source/svgreader/svgclippathnode.cxx new file mode 100755 index 000000000000..11889a4437c9 --- /dev/null +++ b/svgio/source/svgreader/svgclippathnode.cxx @@ -0,0 +1,184 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svgio.hxx" + +#include <svgio/svgreader/svgclippathnode.hxx> +#include <drawinglayer/primitive2d/transformprimitive2d.hxx> +#include <drawinglayer/primitive2d/transparenceprimitive2d.hxx> +#include <basegfx/matrix/b2dhommatrixtools.hxx> +#include <drawinglayer/geometry/viewinformation2d.hxx> + +////////////////////////////////////////////////////////////////////////////// + +namespace svgio +{ + namespace svgreader + { + SvgClipPathNode::SvgClipPathNode( + SvgDocument& rDocument, + SvgNode* pParent) + : SvgNode(SVGTokenClipPathNode, rDocument, pParent), + maSvgStyleAttributes(*this), + mpaTransform(0), + maClipPathUnits(userSpaceOnUse) + { + } + + SvgClipPathNode::~SvgClipPathNode() + { + if(mpaTransform) delete mpaTransform; + } + + const SvgStyleAttributes* SvgClipPathNode::getSvgStyleAttributes() const + { + static rtl::OUString aClassStr(rtl::OUString::createFromAscii("clip-path")); + maSvgStyleAttributes.checkForCssStyle(aClassStr); + + return &maSvgStyleAttributes; + } + + void SvgClipPathNode::parseAttribute(const rtl::OUString& rTokenName, SVGToken aSVGToken, const rtl::OUString& aContent) + { + // call parent + SvgNode::parseAttribute(rTokenName, aSVGToken, aContent); + + // read style attributes + maSvgStyleAttributes.parseStyleAttribute(rTokenName, aSVGToken, aContent); + + // parse own + switch(aSVGToken) + { + case SVGTokenStyle: + { + maSvgStyleAttributes.readStyle(aContent); + break; + } + case SVGTokenTransform: + { + const basegfx::B2DHomMatrix aMatrix(readTransform(aContent, *this)); + + if(!aMatrix.isIdentity()) + { + setTransform(&aMatrix); + } + break; + } + case SVGTokenClipPathUnits: + { + if(aContent.getLength()) + { + if(aContent.match(commonStrings::aStrUserSpaceOnUse, 0)) + { + setClipPathUnits(userSpaceOnUse); + } + else if(aContent.match(commonStrings::aStrObjectBoundingBox, 0)) + { + setClipPathUnits(objectBoundingBox); + } + } + break; + } + } + } + + void SvgClipPathNode::decomposeSvgNode(drawinglayer::primitive2d::Primitive2DSequence& rTarget, bool bReferenced) const + { + drawinglayer::primitive2d::Primitive2DSequence aNewTarget; + + // decompose childs + SvgNode::decomposeSvgNode(aNewTarget, bReferenced); + + if(aNewTarget.hasElements()) + { + if(getTransform()) + { + // create embedding group element with transformation + const drawinglayer::primitive2d::Primitive2DReference xRef( + new drawinglayer::primitive2d::TransformPrimitive2D( + *getTransform(), + aNewTarget)); + + drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(rTarget, xRef); + } + else + { + // append to current target + drawinglayer::primitive2d::appendPrimitive2DSequenceToPrimitive2DSequence(rTarget, aNewTarget); + } + } + } + + void SvgClipPathNode::apply(drawinglayer::primitive2d::Primitive2DSequence& rContent) const + { + if(rContent.hasElements()) + { + drawinglayer::primitive2d::Primitive2DSequence aClipTarget; + + // get clipPath definition as primitives + decomposeSvgNode(aClipTarget, true); + + if(aClipTarget.hasElements()) + { + if(objectBoundingBox == getClipPathUnits()) + { + // clip is object-relative, embed in content transformation + const basegfx::B2DRange aContentRange( + drawinglayer::primitive2d::getB2DRangeFromPrimitive2DSequence( + rContent, + drawinglayer::geometry::ViewInformation2D())); + + const drawinglayer::primitive2d::Primitive2DReference xTransform( + new drawinglayer::primitive2d::TransformPrimitive2D( + basegfx::tools::createScaleTranslateB2DHomMatrix( + aContentRange.getRange(), + aContentRange.getMinimum()), + aClipTarget)); + + aClipTarget = drawinglayer::primitive2d::Primitive2DSequence(&xTransform, 1); + } + + // redefine target. Use TransparencePrimitive2D with created clip + // geometry. Using the automatically set mbIsClipPathContent at + // SvgStyleAttributes the clip definition is without fill, stroke, + // and strokeWidth and forced to black, thus being 100% opaque + const drawinglayer::primitive2d::Primitive2DReference xEmbedTransparence( + new drawinglayer::primitive2d::TransparencePrimitive2D( + rContent, + aClipTarget)); + + rContent = drawinglayer::primitive2d::Primitive2DSequence(&xEmbedTransparence, 1); + } + else + { + // An empty clipping path will completely clip away the element that had + // the clip-path property applied. (Svg spec) + rContent.realloc(0); + } + } + } + + } // end of namespace svgreader +} // end of namespace svgio + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/svgio/source/svgreader/svgdocument.cxx b/svgio/source/svgreader/svgdocument.cxx new file mode 100644 index 000000000000..c719dbd6c8ef --- /dev/null +++ b/svgio/source/svgreader/svgdocument.cxx @@ -0,0 +1,121 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svgio.hxx" + +#include <svgio/svgreader/svgdocument.hxx> + +////////////////////////////////////////////////////////////////////////////// + +namespace svgio +{ + namespace svgreader + { + SvgDocument::SvgDocument(const rtl::OUString& rAbsolutePath) + : maNodes(), + maAbsolutePath(rAbsolutePath), + maIdTokenMapperList(), + maIdStyleTokenMapperList() + { + } + + SvgDocument::~SvgDocument() + { + while(!maNodes.empty()) + { + SvgNode* pCandidate = maNodes[maNodes.size() - 1]; + delete pCandidate; + maNodes.pop_back(); + } + } + + void SvgDocument::appendNode(SvgNode* pNode) + { + OSL_ENSURE(pNode, "OOps, empty node added (!)"); + maNodes.push_back(pNode); + } + + void SvgDocument::addSvgNodeToMapper(const rtl::OUString& rStr, const SvgNode& rNode) + { + if(rStr.getLength()) + { + maIdTokenMapperList.insert(IdTokenValueType(rStr, &rNode)); + } + } + + void SvgDocument::removeSvgNodeFromMapper(const rtl::OUString& rStr) + { + if(rStr.getLength()) + { + maIdTokenMapperList.erase(rStr); + } + } + + const SvgNode* SvgDocument::findSvgNodeById(const rtl::OUString& rStr) const + { + const IdTokenMapper::const_iterator aResult(maIdTokenMapperList.find(rStr)); + + if(aResult == maIdTokenMapperList.end()) + { + return 0; + } + else + { + return aResult->second; + } + } + + void SvgDocument::addSvgStyleAttributesToMapper(const rtl::OUString& rStr, const SvgStyleAttributes& rSvgStyleAttributes) + { + if(rStr.getLength()) + { + maIdStyleTokenMapperList.insert(IdStyleTokenValueType(rStr, &rSvgStyleAttributes)); + } + } + + void SvgDocument::removeSvgStyleAttributesFromMapper(const rtl::OUString& rStr) + { + if(rStr.getLength()) + { + maIdStyleTokenMapperList.erase(rStr); + } + } + + const SvgStyleAttributes* SvgDocument::findSvgStyleAttributesById(const rtl::OUString& rStr) const + { + const IdStyleTokenMapper::const_iterator aResult(maIdStyleTokenMapperList.find(rStr)); + + if(aResult == maIdStyleTokenMapperList.end()) + { + return 0; + } + else + { + return aResult->second; + } + } + + } // end of namespace svgreader +} // end of namespace svgio + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/svgio/source/svgreader/svgdocumenthandler.cxx b/svgio/source/svgreader/svgdocumenthandler.cxx new file mode 100644 index 000000000000..1c0fe65d79ef --- /dev/null +++ b/svgio/source/svgreader/svgdocumenthandler.cxx @@ -0,0 +1,518 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svgio.hxx" + +#include <svgio/svgreader/svgdocumenthandler.hxx> +#include <svgio/svgreader/svgtoken.hxx> +#include <svgio/svgreader/svgsvgnode.hxx> +#include <svgio/svgreader/svggnode.hxx> +#include <svgio/svgreader/svgnode.hxx> +#include <svgio/svgreader/svgpathnode.hxx> +#include <svgio/svgreader/svgrectnode.hxx> +#include <svgio/svgreader/svggradientnode.hxx> +#include <svgio/svgreader/svggradientstopnode.hxx> +#include <svgio/svgreader/svgsymbolnode.hxx> +#include <svgio/svgreader/svgusenode.hxx> +#include <svgio/svgreader/svgcirclenode.hxx> +#include <svgio/svgreader/svgellipsenode.hxx> +#include <svgio/svgreader/svglinenode.hxx> +#include <svgio/svgreader/svgpolynode.hxx> +#include <svgio/svgreader/svgsymbolnode.hxx> +#include <svgio/svgreader/svgtextnode.hxx> +#include <svgio/svgreader/svgcharacternode.hxx> +#include <svgio/svgreader/svgtspannode.hxx> +#include <svgio/svgreader/svgtrefnode.hxx> +#include <svgio/svgreader/svgtextpathnode.hxx> +#include <svgio/svgreader/svgstylenode.hxx> +#include <svgio/svgreader/svgimagenode.hxx> +#include <svgio/svgreader/svgclippathnode.hxx> +#include <svgio/svgreader/svgmasknode.hxx> +#include <svgio/svgreader/svgmarkernode.hxx> +#include <svgio/svgreader/svgpatternnode.hxx> + +////////////////////////////////////////////////////////////////////////////// + +using namespace com::sun::star; + +////////////////////////////////////////////////////////////////////////////// + +namespace +{ + svgio::svgreader::SvgCharacterNode* whiteSpaceHandling(svgio::svgreader::SvgNode* pNode, svgio::svgreader::SvgCharacterNode* pLast) + { + if(pNode) + { + const svgio::svgreader::SvgNodeVector& rChilds = pNode->getChildren(); + const sal_uInt32 nCount(rChilds.size()); + + for(sal_uInt32 a(0); a < nCount; a++) + { + svgio::svgreader::SvgNode* pCandidate = rChilds[a]; + + if(pCandidate) + { + switch(pCandidate->getType()) + { + case svgio::svgreader::SVGTokenCharacter: + { + // clean whitespace in text span + svgio::svgreader::SvgCharacterNode* pCharNode = static_cast< svgio::svgreader::SvgCharacterNode* >(pCandidate); + pCharNode->whiteSpaceHandling(); + + // pCharNode may have lost all text. If that's the case, ignore + // as invalid character node + if(pCharNode->getText().getLength()) + { + if(pLast) + { + // add in-between whitespace (single space) to last + // known character node + pLast->addGap(); + } + + // remember new last corected character node + pLast = pCharNode; + } + break; + } + case svgio::svgreader::SVGTokenTspan: + case svgio::svgreader::SVGTokenTextPath: + case svgio::svgreader::SVGTokenTref: + { + // recursively clean whitespaces in subhierarchy + pLast = whiteSpaceHandling(pCandidate, pLast); + break; + } + default: + { + OSL_ENSURE(false, "Unexpected token inside SVGTokenText (!)"); + break; + } + } + } + } + } + + return pLast; + } +} + +////////////////////////////////////////////////////////////////////////////// + +namespace svgio +{ + namespace svgreader + { + SvgDocHdl::SvgDocHdl(const rtl::OUString& aAbsolutePath) + : maDocument(aAbsolutePath), + mpTarget(0) + { + } + + SvgDocHdl::~SvgDocHdl() + { +#ifdef DBG_UTIL + if(mpTarget) + { + OSL_ENSURE(false, "SvgDocHdl destructed with active target (!)"); + delete mpTarget; + } +#endif + } + + void SvgDocHdl::startDocument( ) throw (xml::sax::SAXException, uno::RuntimeException) + { + OSL_ENSURE(!mpTarget, "Already a target at document start (!)"); + } + + void SvgDocHdl::endDocument( ) throw (xml::sax::SAXException, uno::RuntimeException) + { + OSL_ENSURE(!mpTarget, "Still a target at document end (!)"); + } + + void SvgDocHdl::startElement( const ::rtl::OUString& aName, const uno::Reference< xml::sax::XAttributeList >& xAttribs ) throw (xml::sax::SAXException, uno::RuntimeException) + { + if(aName.getLength()) + { + const SVGToken aSVGToken(StrToSVGToken(aName)); + + switch(aSVGToken) + { + /// structural elements + case SVGTokenSymbol: + { + /// new basic node for Symbol. Content gets scanned, but + /// will not be decomposed (see SvgNode::decomposeSvgNode and bReferenced) + mpTarget = new SvgSymbolNode(maDocument, mpTarget); + mpTarget->parseAttributes(xAttribs); + break; + } + case SVGTokenDefs: + case SVGTokenG: + { + /// new node for Defs/G + mpTarget = new SvgGNode(aSVGToken, maDocument, mpTarget); + mpTarget->parseAttributes(xAttribs); + break; + } + case SVGTokenSvg: + { + /// new node for Svg + mpTarget = new SvgSvgNode(maDocument, mpTarget); + mpTarget->parseAttributes(xAttribs); + break; + } + case SVGTokenUse: + { + /// new node for Use + mpTarget = new SvgUseNode(maDocument, mpTarget); + mpTarget->parseAttributes(xAttribs); + break; + } + + /// shape elements + case SVGTokenCircle: + { + /// new node for Circle + mpTarget = new SvgCircleNode(maDocument, mpTarget); + mpTarget->parseAttributes(xAttribs); + break; + } + case SVGTokenEllipse: + { + /// new node for Ellipse + mpTarget = new SvgEllipseNode(maDocument, mpTarget); + mpTarget->parseAttributes(xAttribs); + break; + } + case SVGTokenLine: + { + /// new node for Line + mpTarget = new SvgLineNode(maDocument, mpTarget); + mpTarget->parseAttributes(xAttribs); + break; + } + case SVGTokenPath: + { + /// new node for Path + mpTarget = new SvgPathNode(maDocument, mpTarget); + mpTarget->parseAttributes(xAttribs); + break; + } + case SVGTokenPolygon: + { + /// new node for Polygon + mpTarget = new SvgPolyNode(maDocument, mpTarget, false); + mpTarget->parseAttributes(xAttribs); + break; + } + case SVGTokenPolyline: + { + /// new node for Polyline + mpTarget = new SvgPolyNode(maDocument, mpTarget, true); + mpTarget->parseAttributes(xAttribs); + break; + } + case SVGTokenRect: + { + /// new node for Rect + mpTarget = new SvgRectNode(maDocument, mpTarget); + mpTarget->parseAttributes(xAttribs); + break; + } + case SVGTokenImage: + { + /// new node for Image + mpTarget = new SvgImageNode(maDocument, mpTarget); + mpTarget->parseAttributes(xAttribs); + break; + } + + /// gradients + case SVGTokenLinearGradient: + case SVGTokenRadialGradient: + { + mpTarget = new SvgGradientNode(aSVGToken, maDocument, mpTarget); + mpTarget->parseAttributes(xAttribs); + break; + } + + /// gradient stops + case SVGTokenStop: + { + mpTarget = new SvgGradientStopNode(maDocument, mpTarget); + mpTarget->parseAttributes(xAttribs); + break; + } + + /// text + case SVGTokenText: + { + mpTarget = new SvgTextNode(maDocument, mpTarget); + mpTarget->parseAttributes(xAttribs); + break; + } + case SVGTokenTspan: + { + mpTarget = new SvgTspanNode(maDocument, mpTarget); + mpTarget->parseAttributes(xAttribs); + break; + } + case SVGTokenTref: + { + mpTarget = new SvgTrefNode(maDocument, mpTarget); + mpTarget->parseAttributes(xAttribs); + break; + } + case SVGTokenTextPath: + { + mpTarget = new SvgTextPathNode(maDocument, mpTarget); + mpTarget->parseAttributes(xAttribs); + break; + } + + /// styles (as stylesheets) + case SVGTokenStyle: + { + mpTarget = new SvgStyleNode(maDocument, mpTarget); + mpTarget->parseAttributes(xAttribs); + break; + } + + /// structural elements clip-path and mask. Content gets scanned, but + /// will not be decomposed (see SvgNode::decomposeSvgNode and bReferenced) + case SVGTokenClipPathNode: + { + /// new node for ClipPath + mpTarget = new SvgClipPathNode(maDocument, mpTarget); + mpTarget->parseAttributes(xAttribs); + break; + } + case SVGTokenMask: + { + /// new node for Mask + mpTarget = new SvgMaskNode(maDocument, mpTarget); + mpTarget->parseAttributes(xAttribs); + break; + } + + /// structural element marker + case SVGTokenMarker: + { + /// new node for marker + mpTarget = new SvgMarkerNode(maDocument, mpTarget); + mpTarget->parseAttributes(xAttribs); + break; + } + + /// structural element pattern + case SVGTokenPattern: + { + /// new node for pattern + mpTarget = new SvgPatternNode(maDocument, mpTarget); + mpTarget->parseAttributes(xAttribs); + break; + } + + default: + { + /// invalid token, ignore +#ifdef DBG_UTIL + myAssert( + rtl::OUString::createFromAscii("Unknown Base SvgToken <") + + aName + + rtl::OUString::createFromAscii("> (!)")); +#endif + break; + } + } + } + } + + void SvgDocHdl::endElement( const ::rtl::OUString& aName ) throw (xml::sax::SAXException, uno::RuntimeException) + { + if(aName.getLength()) + { + const SVGToken aSVGToken(StrToSVGToken(aName)); + SvgNode* pWhitespaceCheck(SVGTokenText == aSVGToken ? mpTarget : 0); + + switch(aSVGToken) + { + /// valid tokens for which a new one was created + + /// structural elements + case SVGTokenDefs: + case SVGTokenG: + case SVGTokenSvg: + case SVGTokenSymbol: + case SVGTokenUse: + + /// shape elements + case SVGTokenCircle: + case SVGTokenEllipse: + case SVGTokenLine: + case SVGTokenPath: + case SVGTokenPolygon: + case SVGTokenPolyline: + case SVGTokenRect: + case SVGTokenImage: + + /// gradients + case SVGTokenLinearGradient: + case SVGTokenRadialGradient: + + /// gradient stops + case SVGTokenStop: + + /// text + case SVGTokenText: + case SVGTokenTspan: + case SVGTokenTextPath: + case SVGTokenTref: + + /// styles (as stylesheets) + case SVGTokenStyle: + + /// structural elements clip-path and mask + case SVGTokenClipPathNode: + case SVGTokenMask: + + /// structural element marker + case SVGTokenMarker: + + /// structural element pattern + case SVGTokenPattern: + + /// content handling after parsing + { + if(mpTarget) + { + if(!mpTarget->getParent()) + { + // last element closing, save this tree + maDocument.appendNode(mpTarget); + } + + mpTarget = const_cast< SvgNode* >(mpTarget->getParent()); + } + else + { + OSL_ENSURE(false, "Closing token, but no context (!)"); + } + break; + } + default: + { + /// invalid token, ignore + } + } + + if(pWhitespaceCheck) + { + // cleanup read strings + whiteSpaceHandling(pWhitespaceCheck, 0); + } + } + } + + void SvgDocHdl::characters( const ::rtl::OUString& aChars ) throw (xml::sax::SAXException, uno::RuntimeException) + { + if(mpTarget) + { + const sal_uInt32 nLength(aChars.getLength()); + + if(nLength && + (SVGTokenText == mpTarget->getType() || + SVGTokenTspan == mpTarget->getType() || + SVGTokenTextPath == mpTarget->getType() || + SVGTokenStyle == mpTarget->getType())) + { + switch(mpTarget->getType()) + { + case SVGTokenText: + case SVGTokenTspan: + case SVGTokenTextPath: + { + const SvgNodeVector& rChilds = mpTarget->getChildren(); + SvgCharacterNode* pTarget = 0; + + if(rChilds.size()) + { + pTarget = dynamic_cast< SvgCharacterNode* >(rChilds[rChilds.size() - 1]); + } + + if(pTarget) + { + // concatenate to current character span + pTarget->concatenate(aChars); + } + else + { + // add character span as simplified tspan (no arguments) + // as direct child of SvgTextNode/SvgTspanNode/SvgTextPathNode + new SvgCharacterNode(maDocument, mpTarget, aChars); + } + break; + } + case SVGTokenStyle: + { + SvgStyleNode& rSvgStyleNode = static_cast< SvgStyleNode& >(*mpTarget); + + if(rSvgStyleNode.isTextCss()) + { + // need to interpret css styles and remember them as StyleSheets + const ::rtl::OUString aTrimmedChars(aChars.trim()); + + if(aTrimmedChars.getLength()) + { + rSvgStyleNode.addCssStyleSheet(aTrimmedChars); + } + } + break; + } + default: + { + // characters not used by a known node + break; + } + } + } + } + } + + void SvgDocHdl::ignorableWhitespace( const ::rtl::OUString& aWhitespaces ) throw (xml::sax::SAXException, uno::RuntimeException) + { + } + + void SvgDocHdl::processingInstruction( const ::rtl::OUString& aTarget, const ::rtl::OUString& aData ) throw (xml::sax::SAXException, uno::RuntimeException) + { + } + + void SvgDocHdl::setDocumentLocator( const uno::Reference< xml::sax::XLocator >& xLocator ) throw (xml::sax::SAXException, uno::RuntimeException) + { + } + } // end of namespace svgreader +} // end of namespace svgio + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/svgio/source/svgreader/svgellipsenode.cxx b/svgio/source/svgreader/svgellipsenode.cxx new file mode 100644 index 000000000000..7eee1b9cedb2 --- /dev/null +++ b/svgio/source/svgreader/svgellipsenode.cxx @@ -0,0 +1,169 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svgio.hxx" + +#include <svgio/svgreader/svgellipsenode.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> +#include <basegfx/polygon/b2dpolygontools.hxx> + +////////////////////////////////////////////////////////////////////////////// + +namespace svgio +{ + namespace svgreader + { + SvgEllipseNode::SvgEllipseNode( + SvgDocument& rDocument, + SvgNode* pParent) + : SvgNode(SVGTokenEllipse, rDocument, pParent), + maSvgStyleAttributes(*this), + maCx(0), + maCy(0), + maRx(0), + maRy(0), + mpaTransform(0) + { + } + + SvgEllipseNode::~SvgEllipseNode() + { + if(mpaTransform) delete mpaTransform; + } + + const SvgStyleAttributes* SvgEllipseNode::getSvgStyleAttributes() const + { + static rtl::OUString aClassStr(rtl::OUString::createFromAscii("ellipse")); + maSvgStyleAttributes.checkForCssStyle(aClassStr); + + return &maSvgStyleAttributes; + } + + void SvgEllipseNode::parseAttribute(const rtl::OUString& rTokenName, SVGToken aSVGToken, const rtl::OUString& aContent) + { + // call parent + SvgNode::parseAttribute(rTokenName, aSVGToken, aContent); + + // read style attributes + maSvgStyleAttributes.parseStyleAttribute(rTokenName, aSVGToken, aContent); + + // parse own + switch(aSVGToken) + { + case SVGTokenStyle: + { + maSvgStyleAttributes.readStyle(aContent); + break; + } + case SVGTokenCx: + { + SvgNumber aNum; + + if(readSingleNumber(aContent, aNum)) + { + setCx(aNum); + } + break; + } + case SVGTokenCy: + { + SvgNumber aNum; + + if(readSingleNumber(aContent, aNum)) + { + setCy(aNum); + } + break; + } + case SVGTokenRx: + { + SvgNumber aNum; + + if(readSingleNumber(aContent, aNum)) + { + if(aNum.isPositive()) + { + setRx(aNum); + } + } + break; + } + case SVGTokenRy: + { + SvgNumber aNum; + + if(readSingleNumber(aContent, aNum)) + { + if(aNum.isPositive()) + { + setRy(aNum); + } + } + break; + } + case SVGTokenTransform: + { + const basegfx::B2DHomMatrix aMatrix(readTransform(aContent, *this)); + + if(!aMatrix.isIdentity()) + { + setTransform(&aMatrix); + } + break; + } + } + } + + void SvgEllipseNode::decomposeSvgNode(drawinglayer::primitive2d::Primitive2DSequence& rTarget, bool bReferenced) const + { + const SvgStyleAttributes* pStyle = getSvgStyleAttributes(); + + if(pStyle && getRx().isSet() && getRy().isSet()) + { + const double fRx(getRx().solve(*this, xcoordinate)); + const double fRy(getRy().solve(*this, ycoordinate)); + + if(fRx > 0.0 && fRy > 0.0) + { + const basegfx::B2DPolygon aPath( + basegfx::tools::createPolygonFromEllipse( + basegfx::B2DPoint( + getCx().isSet() ? getCx().solve(*this, xcoordinate) : 0.0, + getCy().isSet() ? getCy().solve(*this, ycoordinate) : 0.0), + fRx, fRy)); + + drawinglayer::primitive2d::Primitive2DSequence aNewTarget; + + pStyle->add_path(basegfx::B2DPolyPolygon(aPath), aNewTarget); + + if(aNewTarget.hasElements()) + { + pStyle->add_postProcess(rTarget, aNewTarget, getTransform()); + } + } + } + } + } // end of namespace svgreader +} // end of namespace svgio + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/svgio/source/svgreader/svggnode.cxx b/svgio/source/svgreader/svggnode.cxx new file mode 100644 index 000000000000..03b49c837e5a --- /dev/null +++ b/svgio/source/svgreader/svggnode.cxx @@ -0,0 +1,114 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svgio.hxx" + +#include <svgio/svgreader/svggnode.hxx> +#include <drawinglayer/primitive2d/transformprimitive2d.hxx> +#include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx> + +////////////////////////////////////////////////////////////////////////////// + +namespace svgio +{ + namespace svgreader + { + SvgGNode::SvgGNode( + SVGToken aType, + SvgDocument& rDocument, + SvgNode* pParent) + : SvgNode(aType, rDocument, pParent), + maSvgStyleAttributes(*this), + mpaTransform(0) + { + OSL_ENSURE(aType == SVGTokenDefs || aType == SVGTokenG, "SvgGNode should ony be used for Group and Defs (!)"); + } + + SvgGNode::~SvgGNode() + { + if(mpaTransform) delete mpaTransform; + } + + const SvgStyleAttributes* SvgGNode::getSvgStyleAttributes() const + { + static rtl::OUString aClassStr(rtl::OUString::createFromAscii("g")); + maSvgStyleAttributes.checkForCssStyle(aClassStr); + + return &maSvgStyleAttributes; + } + + void SvgGNode::parseAttribute(const rtl::OUString& rTokenName, SVGToken aSVGToken, const rtl::OUString& aContent) + { + // call parent + SvgNode::parseAttribute(rTokenName, aSVGToken, aContent); + + // read style attributes + maSvgStyleAttributes.parseStyleAttribute(rTokenName, aSVGToken, aContent); + + // parse own + switch(aSVGToken) + { + case SVGTokenStyle: + { + maSvgStyleAttributes.readStyle(aContent); + break; + } + case SVGTokenTransform: + { + const basegfx::B2DHomMatrix aMatrix(readTransform(aContent, *this)); + + if(!aMatrix.isIdentity()) + { + setTransform(&aMatrix); + } + break; + } + } + } + + void SvgGNode::decomposeSvgNode(drawinglayer::primitive2d::Primitive2DSequence& rTarget, bool bReferenced) const + { + const SvgStyleAttributes* pStyle = getSvgStyleAttributes(); + + if(pStyle) + { + const double fOpacity(pStyle->getOpacity().getNumber()); + + if(fOpacity > 0.0) + { + drawinglayer::primitive2d::Primitive2DSequence aContent; + + // decompose childs + SvgNode::decomposeSvgNode(aContent, bReferenced); + + if(aContent.hasElements()) + { + pStyle->add_postProcess(rTarget, aContent, getTransform()); + } + } + } + } + } // end of namespace svgreader +} // end of namespace svgio + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/svgio/source/svgreader/svggradientnode.cxx b/svgio/source/svgreader/svggradientnode.cxx new file mode 100644 index 000000000000..c5a535250b74 --- /dev/null +++ b/svgio/source/svgreader/svggradientnode.cxx @@ -0,0 +1,507 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svgio.hxx" + +#include <svgio/svgreader/svggradientnode.hxx> +#include <svgio/svgreader/svgdocument.hxx> +#include <svgio/svgreader/svggradientstopnode.hxx> + +////////////////////////////////////////////////////////////////////////////// + +namespace svgio +{ + namespace svgreader + { + void SvgGradientNode::tryToFindLink() + { + if(!mpXLink && maXLink.getLength()) + { + mpXLink = dynamic_cast< const SvgGradientNode* >(getDocument().findSvgNodeById(maXLink)); + } + } + + SvgGradientNode::SvgGradientNode( + SVGToken aType, + SvgDocument& rDocument, + SvgNode* pParent) + : SvgNode(aType, rDocument, pParent), + maSvgStyleAttributes(*this), + maX1(), + maY1(), + maX2(), + maY2(), + maCx(), + maCy(), + maR(), + maFx(), + maFy(), + maGradientUnits(objectBoundingBox), + maSpreadMethod(drawinglayer::primitive2d::Spread_pad), + mpaGradientTransform(0), + maXLink(), + mpXLink(0) + { + } + + SvgGradientNode::~SvgGradientNode() + { + if(mpaGradientTransform) delete mpaGradientTransform; + // do NOT delete mpXLink, it's only referenced, not owned + } + + const SvgStyleAttributes* SvgGradientNode::getSvgStyleAttributes() const + { + return &maSvgStyleAttributes; + } + + void SvgGradientNode::parseAttribute(const rtl::OUString& rTokenName, SVGToken aSVGToken, const rtl::OUString& aContent) + { + // call parent + SvgNode::parseAttribute(rTokenName, aSVGToken, aContent); + + // read style attributes + maSvgStyleAttributes.parseStyleAttribute(rTokenName, aSVGToken, aContent); + + // parse own + switch(aSVGToken) + { + case SVGTokenStyle: + { + maSvgStyleAttributes.readStyle(aContent); + break; + } + case SVGTokenX1: + { + SvgNumber aNum; + + if(readSingleNumber(aContent, aNum)) + { + setX1(aNum); + } + break; + } + case SVGTokenY1: + { + SvgNumber aNum; + + if(readSingleNumber(aContent, aNum)) + { + setY1(aNum); + } + break; + } + case SVGTokenX2: + { + SvgNumber aNum; + + if(readSingleNumber(aContent, aNum)) + { + setX2(aNum); + } + break; + } + case SVGTokenY2: + { + SvgNumber aNum; + + if(readSingleNumber(aContent, aNum)) + { + setY2(aNum); + } + break; + } + case SVGTokenCx: + { + SvgNumber aNum; + + if(readSingleNumber(aContent, aNum)) + { + setCx(aNum); + } + break; + } + case SVGTokenCy: + { + SvgNumber aNum; + + if(readSingleNumber(aContent, aNum)) + { + setCy(aNum); + } + break; + } + case SVGTokenFx: + { + SvgNumber aNum; + + if(readSingleNumber(aContent, aNum)) + { + setFx(aNum); + } + break; + } + case SVGTokenFy: + { + SvgNumber aNum; + + if(readSingleNumber(aContent, aNum)) + { + setFy(aNum); + } + break; + } + case SVGTokenR: + { + SvgNumber aNum; + + if(readSingleNumber(aContent, aNum)) + { + if(aNum.isPositive()) + { + setR(aNum); + } + } + break; + } + case SVGTokenGradientUnits: + { + if(aContent.getLength()) + { + if(aContent.match(commonStrings::aStrUserSpaceOnUse, 0)) + { + setGradientUnits(userSpaceOnUse); + } + else if(aContent.match(commonStrings::aStrObjectBoundingBox, 0)) + { + setGradientUnits(objectBoundingBox); + } + } + break; + } + case SVGTokenSpreadMethod: + { + if(aContent.getLength()) + { + static rtl::OUString aStrPad(rtl::OUString::createFromAscii("pad")); + static rtl::OUString aStrReflect(rtl::OUString::createFromAscii("reflect")); + static rtl::OUString aStrRepeat(rtl::OUString::createFromAscii("repeat")); + + if(aContent.match(aStrPad, 0)) + { + setSpreadMethod(drawinglayer::primitive2d::Spread_pad); + } + else if(aContent.match(aStrReflect, 0)) + { + setSpreadMethod(drawinglayer::primitive2d::Spread_reflect); + } + else if(aContent.match(aStrRepeat, 0)) + { + setSpreadMethod(drawinglayer::primitive2d::Spread_repeat); + } + } + break; + } + case SVGTokenGradientTransform: + { + const basegfx::B2DHomMatrix aMatrix(readTransform(aContent, *this)); + + if(!aMatrix.isIdentity()) + { + setGradientTransform(&aMatrix); + } + break; + } + case SVGTokenXlinkHref: + { + const sal_Int32 nLen(aContent.getLength()); + + if(nLen && sal_Unicode('#') == aContent[0]) + { + maXLink = aContent.copy(1); + tryToFindLink(); + } + break; + } + } + } + + void SvgGradientNode::collectGradientEntries(drawinglayer::primitive2d::SvgGradientEntryVector& aVector) const + { + if(getChildren().empty()) + { + const_cast< SvgGradientNode* >(this)->tryToFindLink(); + + if(mpXLink) + { + mpXLink->collectGradientEntries(aVector); + } + } + else + { + const sal_uInt32 nCount(getChildren().size()); + + for(sal_uInt32 a(0); a < nCount; a++) + { + const SvgGradientStopNode* pCandidate = dynamic_cast< const SvgGradientStopNode* >(getChildren()[a]); + + if(pCandidate) + { + const SvgStyleAttributes* pStyle = pCandidate->getSvgStyleAttributes(); + + if(pStyle) + { + const SvgNumber aOffset(pCandidate->getOffset()); + double fOffset(0.0); + + if(Unit_percent == aOffset.getUnit()) + { + // percent is not relative to distances in ColorStop context, solve locally + fOffset = aOffset.getNumber() * 0.01; + } + else + { + fOffset = aOffset.solve(*this); + } + + if(fOffset < 0.0) + { + OSL_ENSURE(false, "OOps, SvgGradientStopNode with offset out of range (!)"); + fOffset = 0.0; + } + else if(fOffset > 1.0) + { + OSL_ENSURE(false, "OOps, SvgGradientStopNode with offset out of range (!)"); + fOffset = 1.0; + } + + aVector.push_back( + drawinglayer::primitive2d::SvgGradientEntry( + fOffset, + pStyle->getStopColor(), + pStyle->getStopOpacity().solve(*this))); + } + else + { + OSL_ENSURE(false, "OOps, SvgGradientStopNode without Style (!)"); + } + } + } + } + } + + const SvgNumber SvgGradientNode::getX1() const + { + if(maX1.isSet()) + { + return maX1; + } + + const_cast< SvgGradientNode* >(this)->tryToFindLink(); + + if(mpXLink) + { + return mpXLink->getX1(); + } + + // default is 0% + return SvgNumber(0.0, Unit_percent); + } + + const SvgNumber SvgGradientNode::getY1() const + { + if(maY1.isSet()) + { + return maY1; + } + + const_cast< SvgGradientNode* >(this)->tryToFindLink(); + + if(mpXLink) + { + return mpXLink->getY1(); + } + + // default is 0% + return SvgNumber(0.0, Unit_percent); + } + + const SvgNumber SvgGradientNode::getX2() const + { + if(maX2.isSet()) + { + return maX2; + } + + const_cast< SvgGradientNode* >(this)->tryToFindLink(); + + if(mpXLink) + { + return mpXLink->getX2(); + } + + // default is 100% + return SvgNumber(100.0, Unit_percent); + } + + const SvgNumber SvgGradientNode::getY2() const + { + if(maY2.isSet()) + { + return maY2; + } + + const_cast< SvgGradientNode* >(this)->tryToFindLink(); + + if(mpXLink) + { + return mpXLink->getY2(); + } + + // default is 0% + return SvgNumber(0.0, Unit_percent); + } + + const SvgNumber SvgGradientNode::getCx() const + { + if(maCx.isSet()) + { + return maCx; + } + + const_cast< SvgGradientNode* >(this)->tryToFindLink(); + + if(mpXLink) + { + return mpXLink->getCx(); + } + + // default is 50% + return SvgNumber(50.0, Unit_percent); + } + + const SvgNumber SvgGradientNode::getCy() const + { + if(maCy.isSet()) + { + return maCy; + } + + const_cast< SvgGradientNode* >(this)->tryToFindLink(); + + if(mpXLink) + { + return mpXLink->getCy(); + } + + // default is 50% + return SvgNumber(50.0, Unit_percent); + } + + const SvgNumber SvgGradientNode::getR() const + { + if(maR.isSet()) + { + return maR; + } + + const_cast< SvgGradientNode* >(this)->tryToFindLink(); + + if(mpXLink) + { + return mpXLink->getR(); + } + + // default is 50% + return SvgNumber(50.0, Unit_percent); + } + + const SvgNumber* SvgGradientNode::getFx() const + { + if(maFx.isSet()) + { + return &maFx; + } + + const_cast< SvgGradientNode* >(this)->tryToFindLink(); + + if(mpXLink) + { + return mpXLink->getFx(); + } + + return 0; + } + + const SvgNumber* SvgGradientNode::getFy() const + { + if(maFy.isSet()) + { + return &maFy; + } + + const_cast< SvgGradientNode* >(this)->tryToFindLink(); + + if(mpXLink) + { + return mpXLink->getFy(); + } + + return 0; + } + + const basegfx::B2DHomMatrix* SvgGradientNode::getGradientTransform() const + { + if(mpaGradientTransform) + { + return mpaGradientTransform; + } + + const_cast< SvgGradientNode* >(this)->tryToFindLink(); + + if(mpXLink) + { + return mpXLink->getGradientTransform(); + } + + return 0; + } + + void SvgGradientNode::setGradientTransform(const basegfx::B2DHomMatrix* pMatrix) + { + if(mpaGradientTransform) + { + delete mpaGradientTransform; + mpaGradientTransform = 0; + } + + if(pMatrix) + { + mpaGradientTransform = new basegfx::B2DHomMatrix(*pMatrix); + } + } + + } // end of namespace svgreader +} // end of namespace svgio + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/svgio/source/svgreader/svggradientstopnode.cxx b/svgio/source/svgreader/svggradientstopnode.cxx new file mode 100644 index 000000000000..b6da00e584bb --- /dev/null +++ b/svgio/source/svgreader/svggradientstopnode.cxx @@ -0,0 +1,87 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svgio.hxx" + +#include <svgio/svgreader/svggradientstopnode.hxx> + +////////////////////////////////////////////////////////////////////////////// + +namespace svgio +{ + namespace svgreader + { + SvgGradientStopNode::SvgGradientStopNode( + SvgDocument& rDocument, + SvgNode* pParent) + : SvgNode(SVGTokenStop, rDocument, pParent), + maSvgStyleAttributes(*this), + maOffset() + { + } + + SvgGradientStopNode::~SvgGradientStopNode() + { + } + + const SvgStyleAttributes* SvgGradientStopNode::getSvgStyleAttributes() const + { + return &maSvgStyleAttributes; + } + + void SvgGradientStopNode::parseAttribute(const rtl::OUString& rTokenName, SVGToken aSVGToken, const rtl::OUString& aContent) + { + // call parent + SvgNode::parseAttribute(rTokenName, aSVGToken, aContent); + + // read style attributes + maSvgStyleAttributes.parseStyleAttribute(rTokenName, aSVGToken, aContent); + + // parse own + switch(aSVGToken) + { + case SVGTokenStyle: + { + maSvgStyleAttributes.readStyle(aContent); + break; + } + case SVGTokenOffset: + { + SvgNumber aNum; + + if(readSingleNumber(aContent, aNum)) + { + if(aNum.isPositive()) + { + setOffset(aNum); + } + } + break; + } + } + } + + } // end of namespace svgreader +} // end of namespace svgio + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/svgio/source/svgreader/svgimagenode.cxx b/svgio/source/svgreader/svgimagenode.cxx new file mode 100644 index 000000000000..5ee2e0d58e9e --- /dev/null +++ b/svgio/source/svgreader/svgimagenode.cxx @@ -0,0 +1,353 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svgio.hxx" + +#include <svgio/svgreader/svgimagenode.hxx> +#include <svgio/svgreader/svgdocument.hxx> +#include <sax/tools/converter.hxx> +#include <tools/stream.hxx> +#include <vcl/bitmapex.hxx> +#include <svtools/filter.hxx> +#include <basegfx/matrix/b2dhommatrixtools.hxx> +#include <drawinglayer/primitive2d/bitmapprimitive2d.hxx> +#include <drawinglayer/primitive2d/groupprimitive2d.hxx> +#include <drawinglayer/primitive2d/transformprimitive2d.hxx> +#include <drawinglayer/primitive2d/maskprimitive2d.hxx> +#include <basegfx/polygon/b2dpolygontools.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> +#include <rtl/uri.hxx> +#include <drawinglayer/geometry/viewinformation2d.hxx> + +////////////////////////////////////////////////////////////////////////////// + +namespace svgio +{ + namespace svgreader + { + SvgImageNode::SvgImageNode( + SvgDocument& rDocument, + SvgNode* pParent) + : SvgNode(SVGTokenRect, rDocument, pParent), + maSvgStyleAttributes(*this), + maSvgAspectRatio(), + mpaTransform(0), + maX(0), + maY(0), + maWidth(0), + maHeight(0), + maXLink(), + maUrl(), + maMimeType(), + maData() + { + } + + SvgImageNode::~SvgImageNode() + { + if(mpaTransform) delete mpaTransform; + } + + const SvgStyleAttributes* SvgImageNode::getSvgStyleAttributes() const + { + static rtl::OUString aClassStr(rtl::OUString::createFromAscii("image")); + maSvgStyleAttributes.checkForCssStyle(aClassStr); + + return &maSvgStyleAttributes; + } + + void SvgImageNode::parseAttribute(const rtl::OUString& rTokenName, SVGToken aSVGToken, const rtl::OUString& aContent) + { + // call parent + SvgNode::parseAttribute(rTokenName, aSVGToken, aContent); + + // read style attributes + maSvgStyleAttributes.parseStyleAttribute(rTokenName, aSVGToken, aContent); + + // parse own + switch(aSVGToken) + { + case SVGTokenStyle: + { + maSvgStyleAttributes.readStyle(aContent); + break; + } + case SVGTokenPreserveAspectRatio: + { + setSvgAspectRatio(readSvgAspectRatio(aContent)); + break; + } + case SVGTokenTransform: + { + const basegfx::B2DHomMatrix aMatrix(readTransform(aContent, *this)); + + if(!aMatrix.isIdentity()) + { + setTransform(&aMatrix); + } + break; + } + case SVGTokenX: + { + SvgNumber aNum; + + if(readSingleNumber(aContent, aNum)) + { + setX(aNum); + } + break; + } + case SVGTokenY: + { + SvgNumber aNum; + + if(readSingleNumber(aContent, aNum)) + { + setY(aNum); + } + break; + } + case SVGTokenWidth: + { + SvgNumber aNum; + + if(readSingleNumber(aContent, aNum)) + { + if(aNum.isPositive()) + { + setWidth(aNum); + } + } + break; + } + case SVGTokenHeight: + { + SvgNumber aNum; + + if(readSingleNumber(aContent, aNum)) + { + if(aNum.isPositive()) + { + setHeight(aNum); + } + } + break; + } + case SVGTokenXlinkHref: + { + const sal_Int32 nLen(aContent.getLength()); + + if(nLen) + { + readImageLink(aContent, maXLink, maUrl, maMimeType, maData); + } + break; + } + } + } + + void extractFromGraphic( + const Graphic& rGraphic, + drawinglayer::primitive2d::Primitive2DSequence& rEmbedded, + basegfx::B2DRange& rViewBox, + BitmapEx& rBitmapEx) + { + if(GRAPHIC_BITMAP == rGraphic.GetType()) + { + if(rGraphic.getSvgData().get()) + { + // embedded Svg + rEmbedded = rGraphic.getSvgData()->getPrimitive2DSequence(); + + // fill aViewBox + rViewBox = rGraphic.getSvgData()->getRange(); + } + else + { + // get bitmap + rBitmapEx = rGraphic.GetBitmapEx(); + } + } + else + { + // evtl. convert to bitmap + rBitmapEx = rGraphic.GetBitmapEx(); + } + } + + void SvgImageNode::decomposeSvgNode(drawinglayer::primitive2d::Primitive2DSequence& rTarget, bool bReferenced) const + { + // get size range and create path + const SvgStyleAttributes* pStyle = getSvgStyleAttributes(); + + if(pStyle && getWidth().isSet() && getHeight().isSet()) + { + const double fWidth(getWidth().solve(*this, xcoordinate)); + const double fHeight(getHeight().solve(*this, ycoordinate)); + + if(fWidth > 0.0 && fHeight > 0.0) + { + BitmapEx aBitmapEx; + drawinglayer::primitive2d::Primitive2DSequence aNewTarget; + + // prepare Target and ViewBox for evtl. AspectRatio mappings + const double fX(getX().isSet() ? getX().solve(*this, xcoordinate) : 0.0); + const double fY(getY().isSet() ? getY().solve(*this, ycoordinate) : 0.0); + const basegfx::B2DRange aTarget(fX, fY, fX + fWidth, fY + fHeight); + basegfx::B2DRange aViewBox(aTarget); + + if(maMimeType.getLength() && maData.getLength()) + { + // use embedded base64 encoded data + ::com::sun::star::uno::Sequence< sal_Int8 > aPass; + ::sax::Converter::decodeBase64(aPass, maData); + + if(aPass.hasElements()) + { + SvMemoryStream aStream(aPass.getArray(), aPass.getLength(), STREAM_READ); + Graphic aGraphic; + + if(GRFILTER_OK == GraphicFilter::GetGraphicFilter()->ImportGraphic( + aGraphic, + String(), + aStream)) + { + extractFromGraphic(aGraphic, aNewTarget, aViewBox, aBitmapEx); + } + } + } + else if(maUrl.getLength()) + { + const rtl::OUString& rPath = getDocument().getAbsolutePath(); + const rtl::OUString aAbsUrl(rtl::Uri::convertRelToAbs(rPath, maUrl)); + + if(aAbsUrl.getLength()) + { + SvFileStream aStream(aAbsUrl, STREAM_STD_READ); + Graphic aGraphic; + + if(GRFILTER_OK == GraphicFilter::GetGraphicFilter()->ImportGraphic( + aGraphic, + aAbsUrl, + aStream)) + { + extractFromGraphic(aGraphic, aNewTarget, aViewBox, aBitmapEx); + } + } + } + else if(maXLink.getLength()) + { + const SvgNode* mpXLink = getDocument().findSvgNodeById(maXLink); + + if(mpXLink) + { + mpXLink->decomposeSvgNode(aNewTarget, true); + + if(aNewTarget.hasElements()) + { + aViewBox = drawinglayer::primitive2d::getB2DRangeFromPrimitive2DSequence( + aNewTarget, + drawinglayer::geometry::ViewInformation2D()); + } + } + } + + if(!aBitmapEx.IsEmpty()) + { + // create content from created bitmap + aNewTarget.realloc(1); + aNewTarget[0] = new drawinglayer::primitive2d::BitmapPrimitive2D( + aBitmapEx, + basegfx::B2DHomMatrix()); + + // fill aViewBox. No size set yet, use unit size + aViewBox = basegfx::B2DRange(0.0, 0.0, 1.0, 1.0); + } + + if(aNewTarget.hasElements()) + { + if(aTarget.equal(aViewBox)) + { + // just add to rTarget + drawinglayer::primitive2d::appendPrimitive2DSequenceToPrimitive2DSequence(rTarget, aNewTarget); + } + else + { + // create mapping + const SvgAspectRatio& rRatio = getSvgAspectRatio(); + + if(rRatio.isSet()) + { + // let mapping be created from SvgAspectRatio + const basegfx::B2DHomMatrix aEmbeddingTransform(rRatio.createMapping(aTarget, aViewBox)); + + if(!aEmbeddingTransform.isIdentity()) + { + const drawinglayer::primitive2d::Primitive2DReference xRef( + new drawinglayer::primitive2d::TransformPrimitive2D( + aEmbeddingTransform, + aNewTarget)); + + aNewTarget = drawinglayer::primitive2d::Primitive2DSequence(&xRef, 1); + } + + if(!rRatio.isMeetOrSlice()) + { + // need to embed in MaskPrimitive2D to ensure clipping + const drawinglayer::primitive2d::Primitive2DReference xMask( + new drawinglayer::primitive2d::MaskPrimitive2D( + basegfx::B2DPolyPolygon( + basegfx::tools::createPolygonFromRect(aTarget)), + aNewTarget)); + + aNewTarget = drawinglayer::primitive2d::Primitive2DSequence(&xMask, 1); + } + } + else + { + // choose default mapping + const basegfx::B2DHomMatrix aEmbeddingTransform(rRatio.createLinearMapping(aTarget, aViewBox)); + + if(!aEmbeddingTransform.isIdentity()) + { + const drawinglayer::primitive2d::Primitive2DReference xRef( + new drawinglayer::primitive2d::TransformPrimitive2D( + aEmbeddingTransform, + aNewTarget)); + + aNewTarget = drawinglayer::primitive2d::Primitive2DSequence(&xRef, 1); + } + } + + // embed and add to rTarget, take local extra-transform into account + pStyle->add_postProcess(rTarget, aNewTarget, getTransform()); + } + } + } + } + } + + } // end of namespace svgreader +} // end of namespace svgio + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/svgio/source/svgreader/svglinenode.cxx b/svgio/source/svgreader/svglinenode.cxx new file mode 100644 index 000000000000..12f52061f919 --- /dev/null +++ b/svgio/source/svgreader/svglinenode.cxx @@ -0,0 +1,165 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svgio.hxx" + +#include <svgio/svgreader/svglinenode.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> +#include <basegfx/polygon/b2dpolygontools.hxx> + +////////////////////////////////////////////////////////////////////////////// + +namespace svgio +{ + namespace svgreader + { + SvgLineNode::SvgLineNode( + SvgDocument& rDocument, + SvgNode* pParent) + : SvgNode(SVGTokenLine, rDocument, pParent), + maSvgStyleAttributes(*this), + maX1(0), + maY1(0), + maX2(0), + maY2(0), + mpaTransform(0) + { + } + + SvgLineNode::~SvgLineNode() + { + if(mpaTransform) delete mpaTransform; + } + + const SvgStyleAttributes* SvgLineNode::getSvgStyleAttributes() const + { + static rtl::OUString aClassStr(rtl::OUString::createFromAscii("line")); + maSvgStyleAttributes.checkForCssStyle(aClassStr); + + return &maSvgStyleAttributes; + } + + void SvgLineNode::parseAttribute(const rtl::OUString& rTokenName, SVGToken aSVGToken, const rtl::OUString& aContent) + { + // call parent + SvgNode::parseAttribute(rTokenName, aSVGToken, aContent); + + // read style attributes + maSvgStyleAttributes.parseStyleAttribute(rTokenName, aSVGToken, aContent); + + // parse own + switch(aSVGToken) + { + case SVGTokenStyle: + { + maSvgStyleAttributes.readStyle(aContent); + break; + } + case SVGTokenX1: + { + SvgNumber aNum; + + if(readSingleNumber(aContent, aNum)) + { + setX1(aNum); + } + break; + } + case SVGTokenY1: + { + SvgNumber aNum; + + if(readSingleNumber(aContent, aNum)) + { + setY1(aNum); + } + break; + } + case SVGTokenX2: + { + SvgNumber aNum; + + if(readSingleNumber(aContent, aNum)) + { + setX2(aNum); + } + break; + } + case SVGTokenY2: + { + SvgNumber aNum; + + if(readSingleNumber(aContent, aNum)) + { + setY2(aNum); + } + break; + } + case SVGTokenTransform: + { + const basegfx::B2DHomMatrix aMatrix(readTransform(aContent, *this)); + + if(!aMatrix.isIdentity()) + { + setTransform(&aMatrix); + } + break; + } + } + } + + void SvgLineNode::decomposeSvgNode(drawinglayer::primitive2d::Primitive2DSequence& rTarget, bool bReferenced) const + { + const SvgStyleAttributes* pStyle = getSvgStyleAttributes(); + + if(pStyle) + { + const basegfx::B2DPoint X( + getX1().isSet() ? getX1().solve(*this, xcoordinate) : 0.0, + getY1().isSet() ? getY1().solve(*this, ycoordinate) : 0.0); + const basegfx::B2DPoint Y( + getX2().isSet() ? getX2().solve(*this, xcoordinate) : 0.0, + getY2().isSet() ? getY2().solve(*this, ycoordinate) : 0.0); + + if(!X.equal(Y)) + { + basegfx::B2DPolygon aPath; + + aPath.append(X); + aPath.append(Y); + + drawinglayer::primitive2d::Primitive2DSequence aNewTarget; + + pStyle->add_path(basegfx::B2DPolyPolygon(aPath), aNewTarget); + + if(aNewTarget.hasElements()) + { + pStyle->add_postProcess(rTarget, aNewTarget, getTransform()); + } + } + } + } + } // end of namespace svgreader +} // end of namespace svgio + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/svgio/source/svgreader/svgmarkernode.cxx b/svgio/source/svgreader/svgmarkernode.cxx new file mode 100755 index 000000000000..1e0342b44e15 --- /dev/null +++ b/svgio/source/svgreader/svgmarkernode.cxx @@ -0,0 +1,212 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svgio.hxx" + +#include <svgio/svgreader/svgmarkernode.hxx> + +////////////////////////////////////////////////////////////////////////////// + +namespace svgio +{ + namespace svgreader + { + SvgMarkerNode::SvgMarkerNode( + SvgDocument& rDocument, + SvgNode* pParent) + : SvgNode(SVGTokenMarker, rDocument, pParent), + aPrimitives(), + maSvgStyleAttributes(*this), + mpViewBox(0), + maSvgAspectRatio(), + maRefX(0), + maRefY(0), + maMarkerUnits(strokeWidth), + maMarkerWidth(3), + maMarkerHeight(3), + mfAngle(0.0), + mbOrientAuto(false) + { + } + + SvgMarkerNode::~SvgMarkerNode() + { + if(mpViewBox) delete mpViewBox; + } + + const SvgStyleAttributes* SvgMarkerNode::getSvgStyleAttributes() const + { + static rtl::OUString aClassStr(rtl::OUString::createFromAscii("marker")); + maSvgStyleAttributes.checkForCssStyle(aClassStr); + + return &maSvgStyleAttributes; + } + + void SvgMarkerNode::parseAttribute(const rtl::OUString& rTokenName, SVGToken aSVGToken, const rtl::OUString& aContent) + { + // call parent + SvgNode::parseAttribute(rTokenName, aSVGToken, aContent); + + // read style attributes + maSvgStyleAttributes.parseStyleAttribute(rTokenName, aSVGToken, aContent); + + // parse own + switch(aSVGToken) + { + case SVGTokenStyle: + { + maSvgStyleAttributes.readStyle(aContent); + break; + } + case SVGTokenViewBox: + { + const basegfx::B2DRange aRange(readViewBox(aContent, *this)); + + if(!aRange.isEmpty()) + { + setViewBox(&aRange); + } + break; + } + case SVGTokenPreserveAspectRatio: + { + setSvgAspectRatio(readSvgAspectRatio(aContent)); + break; + } + case SVGTokenRefX: + { + SvgNumber aNum; + + if(readSingleNumber(aContent, aNum)) + { + setRefX(aNum); + } + break; + } + case SVGTokenRefY: + { + SvgNumber aNum; + + if(readSingleNumber(aContent, aNum)) + { + setRefY(aNum); + } + break; + } + case SVGTokenMarkerUnits: + { + if(aContent.getLength()) + { + static rtl::OUString aStrStrokeWidth(rtl::OUString::createFromAscii("strokeWidth")); + + if(aContent.match(aStrStrokeWidth, 0)) + { + setMarkerUnits(strokeWidth); + } + else if(aContent.match(commonStrings::aStrUserSpaceOnUse, 0)) + { + setMarkerUnits(userSpaceOnUse); + } + } + break; + } + case SVGTokenMarkerWidth: + { + SvgNumber aNum; + + if(readSingleNumber(aContent, aNum)) + { + if(aNum.isPositive()) + { + setMarkerWidth(aNum); + } + } + break; + } + case SVGTokenMarkerHeight: + { + SvgNumber aNum; + + if(readSingleNumber(aContent, aNum)) + { + if(aNum.isPositive()) + { + setMarkerHeight(aNum); + } + } + break; + } + case SVGTokenOrient: + { + const sal_Int32 nLen(aContent.getLength()); + + if(nLen) + { + static rtl::OUString aStrAuto(rtl::OUString::createFromAscii("auto")); + + if(aContent.match(aStrAuto, 0)) + { + setOrientAuto(true); + } + else + { + sal_Int32 nPos(0); + double fAngle(0.0); + + if(readAngle(aContent, nPos, fAngle, nLen)) + { + setAngle(fAngle); + } + } + } + break; + } + } + } + + const drawinglayer::primitive2d::Primitive2DSequence& SvgMarkerNode::getMarkerPrimitives() const + { + if(!aPrimitives.hasElements()) + { + decomposeSvgNode(const_cast< SvgMarkerNode* >(this)->aPrimitives, true); + } + + return aPrimitives; + } + + const basegfx::B2DRange* SvgMarkerNode::getCurrentViewPort() const + { + if(getViewBox()) + { + return getViewBox(); + } + else + { + return SvgNode::getCurrentViewPort(); + } + } + + } // end of namespace svgreader +} // end of namespace svgio + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/svgio/source/svgreader/svgmasknode.cxx b/svgio/source/svgreader/svgmasknode.cxx new file mode 100755 index 000000000000..45eeebab92e3 --- /dev/null +++ b/svgio/source/svgreader/svgmasknode.cxx @@ -0,0 +1,317 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svgio.hxx" + +#include <svgio/svgreader/svgmasknode.hxx> +#include <drawinglayer/primitive2d/transformprimitive2d.hxx> +#include <drawinglayer/primitive2d/transparenceprimitive2d.hxx> +#include <basegfx/matrix/b2dhommatrixtools.hxx> +#include <drawinglayer/geometry/viewinformation2d.hxx> +#include <drawinglayer/primitive2d/modifiedcolorprimitive2d.hxx> +#include <drawinglayer/primitive2d/maskprimitive2d.hxx> +#include <basegfx/polygon/b2dpolygontools.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> + +////////////////////////////////////////////////////////////////////////////// + +namespace svgio +{ + namespace svgreader + { + SvgMaskNode::SvgMaskNode( + SvgDocument& rDocument, + SvgNode* pParent) + : SvgNode(SVGTokenMask, rDocument, pParent), + maSvgStyleAttributes(*this), + maX(SvgNumber(-10.0, Unit_percent, true)), + maY(SvgNumber(-10.0, Unit_percent, true)), + maWidth(SvgNumber(120.0, Unit_percent, true)), + maHeight(SvgNumber(120.0, Unit_percent, true)), + mpaTransform(0), + maMaskUnits(objectBoundingBox), + maMaskContentUnits(userSpaceOnUse) + { + } + + SvgMaskNode::~SvgMaskNode() + { + if(mpaTransform) delete mpaTransform; + } + + const SvgStyleAttributes* SvgMaskNode::getSvgStyleAttributes() const + { + static rtl::OUString aClassStr(rtl::OUString::createFromAscii("mask")); + maSvgStyleAttributes.checkForCssStyle(aClassStr); + + return &maSvgStyleAttributes; + } + + void SvgMaskNode::parseAttribute(const rtl::OUString& rTokenName, SVGToken aSVGToken, const rtl::OUString& aContent) + { + // call parent + SvgNode::parseAttribute(rTokenName, aSVGToken, aContent); + + // read style attributes + maSvgStyleAttributes.parseStyleAttribute(rTokenName, aSVGToken, aContent); + + // parse own + switch(aSVGToken) + { + case SVGTokenStyle: + { + maSvgStyleAttributes.readStyle(aContent); + break; + } + case SVGTokenX: + { + SvgNumber aNum; + + if(readSingleNumber(aContent, aNum)) + { + setX(aNum); + } + break; + } + case SVGTokenY: + { + SvgNumber aNum; + + if(readSingleNumber(aContent, aNum)) + { + setY(aNum); + } + break; + } + case SVGTokenWidth: + { + SvgNumber aNum; + + if(readSingleNumber(aContent, aNum)) + { + if(aNum.isPositive()) + { + setWidth(aNum); + } + } + break; + } + case SVGTokenHeight: + { + SvgNumber aNum; + + if(readSingleNumber(aContent, aNum)) + { + if(aNum.isPositive()) + { + setHeight(aNum); + } + } + break; + } + case SVGTokenTransform: + { + const basegfx::B2DHomMatrix aMatrix(readTransform(aContent, *this)); + + if(!aMatrix.isIdentity()) + { + setTransform(&aMatrix); + } + break; + } + case SVGTokenMaskUnits: + { + if(aContent.getLength()) + { + if(aContent.match(commonStrings::aStrUserSpaceOnUse, 0)) + { + setMaskUnits(userSpaceOnUse); + } + else if(aContent.match(commonStrings::aStrObjectBoundingBox, 0)) + { + setMaskUnits(objectBoundingBox); + } + } + break; + } + case SVGTokenMaskContentUnits: + { + if(aContent.getLength()) + { + if(aContent.match(commonStrings::aStrUserSpaceOnUse, 0)) + { + setMaskContentUnits(userSpaceOnUse); + } + else if(aContent.match(commonStrings::aStrObjectBoundingBox, 0)) + { + setMaskContentUnits(objectBoundingBox); + } + } + break; + } + } + } + + void SvgMaskNode::decomposeSvgNode(drawinglayer::primitive2d::Primitive2DSequence& rTarget, bool bReferenced) const + { + drawinglayer::primitive2d::Primitive2DSequence aNewTarget; + + // decompose childs + SvgNode::decomposeSvgNode(aNewTarget, bReferenced); + + if(aNewTarget.hasElements()) + { + if(getTransform()) + { + // create embedding group element with transformation + const drawinglayer::primitive2d::Primitive2DReference xRef( + new drawinglayer::primitive2d::TransformPrimitive2D( + *getTransform(), + aNewTarget)); + + aNewTarget = drawinglayer::primitive2d::Primitive2DSequence(&xRef, 1); + } + + // append to current target + drawinglayer::primitive2d::appendPrimitive2DSequenceToPrimitive2DSequence(rTarget, aNewTarget); + } + } + + void SvgMaskNode::apply(drawinglayer::primitive2d::Primitive2DSequence& rTarget) const + { + if(rTarget.hasElements()) + { + drawinglayer::primitive2d::Primitive2DSequence aMaskTarget; + + // get mask definition as primitives + decomposeSvgNode(aMaskTarget, true); + + if(aMaskTarget.hasElements()) + { + // get range of content to be masked + const basegfx::B2DRange aContentRange( + drawinglayer::primitive2d::getB2DRangeFromPrimitive2DSequence( + rTarget, + drawinglayer::geometry::ViewInformation2D())); + const double fContentWidth(aContentRange.getWidth()); + const double fContentHeight(aContentRange.getHeight()); + + if(fContentWidth > 0.0 && fContentHeight > 0.0) + { + // create OffscreenBufferRange + basegfx::B2DRange aOffscreenBufferRange; + + if(objectBoundingBox == getMaskUnits()) + { + // fractions or percentages of the bounding box of the element to which the mask is applied + const double fX(Unit_percent == getX().getUnit() ? getX().getNumber() * 0.01 : getX().getNumber()); + const double fY(Unit_percent == getY().getUnit() ? getY().getNumber() * 0.01 : getY().getNumber()); + const double fW(Unit_percent == getWidth().getUnit() ? getWidth().getNumber() * 0.01 : getWidth().getNumber()); + const double fH(Unit_percent == getHeight().getUnit() ? getHeight().getNumber() * 0.01 : getHeight().getNumber()); + + aOffscreenBufferRange = basegfx::B2DRange( + aContentRange.getMinX() + (fX * fContentWidth), + aContentRange.getMinY() + (fY * fContentHeight), + aContentRange.getMinX() + ((fX + fW) * fContentWidth), + aContentRange.getMinY() + ((fY + fH) * fContentHeight)); + } + else + { + const double fX(getX().isSet() ? getX().solve(*this, xcoordinate) : 0.0); + const double fY(getY().isSet() ? getY().solve(*this, ycoordinate) : 0.0); + + aOffscreenBufferRange = basegfx::B2DRange( + fX, + fY, + fX + (getWidth().isSet() ? getWidth().solve(*this, xcoordinate) : 0.0), + fY + (getHeight().isSet() ? getHeight().solve(*this, ycoordinate) : 0.0)); + } + + if(objectBoundingBox == getMaskContentUnits()) + { + // mask is object-relative, embed in content transformation + const drawinglayer::primitive2d::Primitive2DReference xTransform( + new drawinglayer::primitive2d::TransformPrimitive2D( + basegfx::tools::createScaleTranslateB2DHomMatrix( + aContentRange.getRange(), + aContentRange.getMinimum()), + aMaskTarget)); + + aMaskTarget = drawinglayer::primitive2d::Primitive2DSequence(&xTransform, 1); + } + + // embed content to a ModifiedColorPrimitive2D since the definitions + // how content is used as alpha is special for Svg + { + const drawinglayer::primitive2d::Primitive2DReference xInverseMask( + new drawinglayer::primitive2d::ModifiedColorPrimitive2D( + aMaskTarget, + basegfx::BColorModifier( + basegfx::BColor(0.0, 0.0, 0.0), + 0.5, + basegfx::BCOLORMODIFYMODE_LUMINANCE_TO_ALPHA))); + + aMaskTarget = drawinglayer::primitive2d::Primitive2DSequence(&xInverseMask, 1); + } + + // prepare new content + drawinglayer::primitive2d::Primitive2DReference xNewContent( + new drawinglayer::primitive2d::TransparencePrimitive2D( + rTarget, + aMaskTarget)); + + // output up to now is defined by aContentRange and mask is oriented + // relative to it. It is possible that aOffscreenBufferRange defines + // a smaller area. In that case, embed to a mask primitive + if(!aOffscreenBufferRange.isInside(aContentRange)) + { + xNewContent = new drawinglayer::primitive2d::MaskPrimitive2D( + basegfx::B2DPolyPolygon( + basegfx::tools::createPolygonFromRect( + aOffscreenBufferRange)), + drawinglayer::primitive2d::Primitive2DSequence(&xNewContent, 1)); + } + + // redefine target. Use TransparencePrimitive2D with created mask + // geometry + rTarget = drawinglayer::primitive2d::Primitive2DSequence(&xNewContent, 1); + } + else + { + // content is geometrically empty + rTarget.realloc(0); + } + } + else + { + // An empty clipping path will completely clip away the element that had + // the clip-path property applied. (Svg spec) + rTarget.realloc(0); + } + } + } + + } // end of namespace svgreader +} // end of namespace svgio + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/svgio/source/svgreader/svgnode.cxx b/svgio/source/svgreader/svgnode.cxx new file mode 100644 index 000000000000..bcd802be6640 --- /dev/null +++ b/svgio/source/svgreader/svgnode.cxx @@ -0,0 +1,288 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svgio.hxx" + +#include <svgio/svgreader/svgnode.hxx> +#include <basegfx/polygon/b2dpolypolygontools.hxx> +#include <svgio/svgreader/svgdocument.hxx> +#include <svgio/svgreader/svgnode.hxx> +#include <svgio/svgreader/svgstyleattributes.hxx> + +////////////////////////////////////////////////////////////////////////////// + +namespace svgio +{ + namespace svgreader + { + const SvgStyleAttributes* SvgNode::getSvgStyleAttributes() const + { + return 0; + } + + SvgNode::SvgNode( + SVGToken aType, + SvgDocument& rDocument, + SvgNode* pParent) + : maType(aType), + mrDocument(rDocument), + mpParent(pParent), + mpAlternativeParent(0), + maChildren(), + mpId(0), + mpClass(0), + maXmlSpace(XmlSpace_notset) + { + OSL_ENSURE(SVGTokenUnknown != maType, "SvgNode with unknown type created (!)"); + + if(pParent) + { + pParent->maChildren.push_back(this); + } + else + { +#ifdef DBG_UTIL + if(SVGTokenSvg != getType()) + { + OSL_ENSURE(false, "No parent for this node (!)"); + } +#endif + } + } + + SvgNode::~SvgNode() + { + while(maChildren.size()) + { + delete maChildren[maChildren.size() - 1]; + maChildren.pop_back(); + } + + if(mpId) delete mpId; + if(mpClass) delete mpClass; + } + + void SvgNode::parseAttributes(const com::sun::star::uno::Reference< com::sun::star::xml::sax::XAttributeList >& xAttribs) + { + const sal_uInt32 nAttributes(xAttribs->getLength()); + + for(sal_uInt32 a(0); a < nAttributes; a++) + { + const ::rtl::OUString aTokenName(xAttribs->getNameByIndex(a)); + + parseAttribute(aTokenName, StrToSVGToken(aTokenName), xAttribs->getValueByIndex(a)); + } + } + + void SvgNode::parseAttribute(const rtl::OUString& rTokenName, SVGToken aSVGToken, const rtl::OUString& aContent) + { + switch(aSVGToken) + { + case SVGTokenId: + { + if(aContent.getLength()) + { + setId(&aContent); + } + break; + } + case SVGTokenClass: + { + if(aContent.getLength()) + { + setClass(&aContent); + } + break; + } + case SVGTokenXmlSpace: + { + if(aContent.getLength()) + { + static rtl::OUString aStrDefault(rtl::OUString::createFromAscii("default")); + static rtl::OUString aStrPreserve(rtl::OUString::createFromAscii("preserve")); + + if(aContent.match(aStrDefault)) + { + setXmlSpace(XmlSpace_default); + } + else if(aContent.match(aStrPreserve)) + { + setXmlSpace(XmlSpace_preserve); + } + } + break; + } + } + } + + void SvgNode::decomposeSvgNode(drawinglayer::primitive2d::Primitive2DSequence& rTarget, bool bReferenced) const + { + if(!bReferenced) + { + if(SVGTokenDefs == getType() || + SVGTokenSymbol == getType() || + SVGTokenClipPathNode == getType() || + SVGTokenMask == getType() || + SVGTokenMarker == getType() || + SVGTokenPattern == getType()) + { + // do not decompose defs or symbol nodes (these hold only style-like + // objects which may be used by referencing them) except when doing + // so controlled referenced + + // also do not decompose ClipPaths and Masks. These should be embedded + // in a defs node (which gets not decomposed by itself), but you never + // know + + // also not directly used are Markers and Patterns, only indirecty used + // by reference + return; + } + } + + const SvgNodeVector& rChildren = getChildren(); + + if(!rChildren.empty()) + { + const sal_uInt32 nCount(rChildren.size()); + + for(sal_uInt32 a(0); a < nCount; a++) + { + SvgNode* pCandidate = rChildren[a]; + + if(pCandidate) + { + drawinglayer::primitive2d::Primitive2DSequence aNewTarget; + + pCandidate->decomposeSvgNode(aNewTarget, bReferenced); + + if(aNewTarget.hasElements()) + { + drawinglayer::primitive2d::appendPrimitive2DSequenceToPrimitive2DSequence(rTarget, aNewTarget); + } + } + else + { + OSL_ENSURE(false, "Null-Pointer in child node list (!)"); + } + } + } + } + + const basegfx::B2DRange* SvgNode::getCurrentViewPort() const + { + if(getParent()) + { + return getParent()->getCurrentViewPort(); + } + else + { + return 0; + } + } + + double SvgNode::getCurrentFontSize() const + { + if(getSvgStyleAttributes()) + { + return getSvgStyleAttributes()->getFontSize().solve(*this, xcoordinate); + } + else if(getParent()) + { + return getParent()->getCurrentFontSize(); + } + else + { + return 0.0; + } + } + + double SvgNode::getCurrentXHeight() const + { + if(getSvgStyleAttributes()) + { + // for XHeight, use FontSize currently + return getSvgStyleAttributes()->getFontSize().solve(*this, ycoordinate); + } + else if(getParent()) + { + return getParent()->getCurrentXHeight(); + } + else + { + return 0.0; + } + } + + void SvgNode::setId(const rtl::OUString* pfId) + { + if(mpId) + { + mrDocument.removeSvgNodeFromMapper(*mpId); + delete mpId; + mpId = 0; + } + + if(pfId) + { + mpId = new rtl::OUString(*pfId); + mrDocument.addSvgNodeToMapper(*mpId, *this); + } + } + + void SvgNode::setClass(const rtl::OUString* pfClass) + { + if(mpClass) + { + mrDocument.removeSvgNodeFromMapper(*mpClass); + delete mpClass; + mpClass = 0; + } + + if(pfClass) + { + mpClass = new rtl::OUString(*pfClass); + mrDocument.addSvgNodeToMapper(*mpClass, *this); + } + } + + XmlSpace SvgNode::getXmlSpace() const + { + if(maXmlSpace != XmlSpace_notset) + { + return maXmlSpace; + } + + if(getParent()) + { + return getParent()->getXmlSpace(); + } + + // default is XmlSpace_default + return XmlSpace_default; + } + + } // end of namespace svgreader +} // end of namespace svgio + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/svgio/source/svgreader/svgpaint.cxx b/svgio/source/svgreader/svgpaint.cxx new file mode 100644 index 000000000000..18ef1343716a --- /dev/null +++ b/svgio/source/svgreader/svgpaint.cxx @@ -0,0 +1,37 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svgio.hxx" + +#include <svgio/svgreader/svgpaint.hxx> + +////////////////////////////////////////////////////////////////////////////// + +namespace svgio +{ + namespace svgreader + { + } // end of namespace svgreader +} // end of namespace svgio + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/svgio/source/svgreader/svgpathnode.cxx b/svgio/source/svgreader/svgpathnode.cxx new file mode 100644 index 000000000000..7027f29f1a79 --- /dev/null +++ b/svgio/source/svgreader/svgpathnode.cxx @@ -0,0 +1,132 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svgio.hxx" + +#include <svgio/svgreader/svgpathnode.hxx> +#include <basegfx/polygon/b2dpolypolygontools.hxx> + +////////////////////////////////////////////////////////////////////////////// + +namespace svgio +{ + namespace svgreader + { + SvgPathNode::SvgPathNode( + SvgDocument& rDocument, + SvgNode* pParent) + : SvgNode(SVGTokenPath, rDocument, pParent), + maSvgStyleAttributes(*this), + mpPolyPolygon(0), + mpaTransform(0), + maPathLength() + { + } + + SvgPathNode::~SvgPathNode() + { + if(mpPolyPolygon) delete mpPolyPolygon; + if(mpaTransform) delete mpaTransform; + } + + const SvgStyleAttributes* SvgPathNode::getSvgStyleAttributes() const + { + static rtl::OUString aClassStr(rtl::OUString::createFromAscii("path")); + maSvgStyleAttributes.checkForCssStyle(aClassStr); + + return &maSvgStyleAttributes; + } + + void SvgPathNode::parseAttribute(const rtl::OUString& rTokenName, SVGToken aSVGToken, const rtl::OUString& aContent) + { + // call parent + SvgNode::parseAttribute(rTokenName, aSVGToken, aContent); + + // read style attributes + maSvgStyleAttributes.parseStyleAttribute(rTokenName, aSVGToken, aContent); + + // parse own + switch(aSVGToken) + { + case SVGTokenStyle: + { + maSvgStyleAttributes.readStyle(aContent); + break; + } + case SVGTokenD: + { + basegfx::B2DPolyPolygon aPath; + + if(basegfx::tools::importFromSvgD(aPath, aContent)) + { + if(aPath.count()) + { + setPath(&aPath); + } + } + break; + } + case SVGTokenTransform: + { + const basegfx::B2DHomMatrix aMatrix(readTransform(aContent, *this)); + + if(!aMatrix.isIdentity()) + { + setTransform(&aMatrix); + } + break; + } + case SVGTokenPathLength: + { + SvgNumber aNum; + + if(readSingleNumber(aContent, aNum)) + { + setPathLength(aNum); + } + break; + } + } + } + + void SvgPathNode::decomposeSvgNode(drawinglayer::primitive2d::Primitive2DSequence& rTarget, bool bReferenced) const + { + // fill and/or stroke needed, also a path + const SvgStyleAttributes* pStyle = getSvgStyleAttributes(); + + if(pStyle && getPath()) + { + drawinglayer::primitive2d::Primitive2DSequence aNewTarget; + + pStyle->add_path(*getPath(), aNewTarget); + + if(aNewTarget.hasElements()) + { + pStyle->add_postProcess(rTarget, aNewTarget, getTransform()); + } + } + } + } // end of namespace svgreader +} // end of namespace svgio + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/svgio/source/svgreader/svgpatternnode.cxx b/svgio/source/svgreader/svgpatternnode.cxx new file mode 100755 index 000000000000..e7df8b62344f --- /dev/null +++ b/svgio/source/svgreader/svgpatternnode.cxx @@ -0,0 +1,462 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svgio.hxx" + +#include <svgio/svgreader/svgpatternnode.hxx> +#include <svgio/svgreader/svgdocument.hxx> + +////////////////////////////////////////////////////////////////////////////// + +namespace svgio +{ + namespace svgreader + { + void SvgPatternNode::tryToFindLink() + { + if(!mpXLink && maXLink.getLength()) + { + mpXLink = dynamic_cast< const SvgPatternNode* >(getDocument().findSvgNodeById(maXLink)); + } + } + + SvgPatternNode::SvgPatternNode( + SvgDocument& rDocument, + SvgNode* pParent) + : SvgNode(SVGTokenPattern, rDocument, pParent), + aPrimitives(), + maSvgStyleAttributes(*this), + mpViewBox(0), + maSvgAspectRatio(), + maX(), + maY(), + maWidth(), + maHeight(), + mpPatternUnits(0), + mpPatternContentUnits(0), + mpaPatternTransform(0), + maXLink(), + mpXLink(0) + { + } + + SvgPatternNode::~SvgPatternNode() + { + if(mpViewBox) delete mpViewBox; + if(mpaPatternTransform) delete mpaPatternTransform; + if(mpPatternUnits) delete mpPatternUnits; + if(mpPatternContentUnits) delete mpPatternContentUnits; + } + + const SvgStyleAttributes* SvgPatternNode::getSvgStyleAttributes() const + { + static rtl::OUString aClassStr(rtl::OUString::createFromAscii("pattern")); + maSvgStyleAttributes.checkForCssStyle(aClassStr); + + return &maSvgStyleAttributes; + } + + void SvgPatternNode::parseAttribute(const rtl::OUString& rTokenName, SVGToken aSVGToken, const rtl::OUString& aContent) + { + // call parent + SvgNode::parseAttribute(rTokenName, aSVGToken, aContent); + + // read style attributes + maSvgStyleAttributes.parseStyleAttribute(rTokenName, aSVGToken, aContent); + + // parse own + switch(aSVGToken) + { + case SVGTokenStyle: + { + maSvgStyleAttributes.readStyle(aContent); + break; + } + case SVGTokenViewBox: + { + const basegfx::B2DRange aRange(readViewBox(aContent, *this)); + + if(!aRange.isEmpty()) + { + setViewBox(&aRange); + } + break; + } + case SVGTokenPreserveAspectRatio: + { + setSvgAspectRatio(readSvgAspectRatio(aContent)); + break; + } + case SVGTokenX: + { + SvgNumber aNum; + + if(readSingleNumber(aContent, aNum)) + { + setX(aNum); + } + break; + } + case SVGTokenY: + { + SvgNumber aNum; + + if(readSingleNumber(aContent, aNum)) + { + setY(aNum); + } + break; + } + case SVGTokenWidth: + { + SvgNumber aNum; + + if(readSingleNumber(aContent, aNum)) + { + if(aNum.isPositive()) + { + setWidth(aNum); + } + } + break; + } + case SVGTokenHeight: + { + SvgNumber aNum; + + if(readSingleNumber(aContent, aNum)) + { + if(aNum.isPositive()) + { + setHeight(aNum); + } + } + break; + } + case SVGTokenPatternUnits: + { + if(aContent.getLength()) + { + if(aContent.match(commonStrings::aStrUserSpaceOnUse, 0)) + { + setPatternUnits(userSpaceOnUse); + } + else if(aContent.match(commonStrings::aStrObjectBoundingBox, 0)) + { + setPatternUnits(objectBoundingBox); + } + } + break; + } + case SVGTokenPatternContentUnits: + { + if(aContent.getLength()) + { + if(aContent.match(commonStrings::aStrUserSpaceOnUse, 0)) + { + setPatternContentUnits(userSpaceOnUse); + } + else if(aContent.match(commonStrings::aStrObjectBoundingBox, 0)) + { + setPatternContentUnits(objectBoundingBox); + } + } + break; + } + case SVGTokenPatternTransform: + { + const basegfx::B2DHomMatrix aMatrix(readTransform(aContent, *this)); + + if(!aMatrix.isIdentity()) + { + setPatternTransform(&aMatrix); + } + break; + } + case SVGTokenXlinkHref: + { + const sal_Int32 nLen(aContent.getLength()); + + if(nLen && sal_Unicode('#') == aContent[0]) + { + maXLink = aContent.copy(1); + tryToFindLink(); + } + break; + } + } + } + + void SvgPatternNode::getValuesRelative(double& rfX, double& rfY, double& rfW, double& rfH, const basegfx::B2DRange& rGeoRange, SvgNode& rUser) const + { + double fTargetWidth(rGeoRange.getWidth()); + double fTargetHeight(rGeoRange.getHeight()); + + if(fTargetWidth > 0.0 && fTargetHeight > 0.0) + { + const SvgUnits aPatternUnits(getPatternUnits() ? *getPatternUnits() : objectBoundingBox); + + if(objectBoundingBox == aPatternUnits) + { + rfW = (getWidth().isSet()) ? getWidth().getNumber() : 0.0; + rfH = (getHeight().isSet()) ? getHeight().getNumber() : 0.0; + + if(Unit_percent == getWidth().getUnit()) + { + rfW *= 0.01; + } + + if(Unit_percent == getHeight().getUnit()) + { + rfH *= 0.01; + } + } + else + { + rfW = (getWidth().isSet()) ? getWidth().solve(rUser, xcoordinate) : 0.0; + rfH = (getHeight().isSet()) ? getHeight().solve(rUser, ycoordinate) : 0.0; + + // make relative to rGeoRange + rfW /= fTargetWidth; + rfH /= fTargetHeight; + } + + if(rfW > 0.0 && rfH > 0.0) + { + if(objectBoundingBox == aPatternUnits) + { + rfX = (getX().isSet()) ? getX().getNumber() : 0.0; + rfY = (getY().isSet()) ? getY().getNumber() : 0.0; + + if(Unit_percent == getX().getUnit()) + { + rfX *= 0.01; + } + + if(Unit_percent == getY().getUnit()) + { + rfY *= 0.01; + } + } + else + { + rfX = (getX().isSet()) ? getX().solve(rUser, xcoordinate) : 0.0; + rfY = (getY().isSet()) ? getY().solve(rUser, ycoordinate) : 0.0; + + // make relative to rGeoRange + rfX = (rfX - rGeoRange.getMinX()) / fTargetWidth; + rfY = (rfY - rGeoRange.getMinY()) / fTargetHeight; + } + } + } + } + + const drawinglayer::primitive2d::Primitive2DSequence& SvgPatternNode::getPatternPrimitives() const + { + if(!aPrimitives.hasElements()) + { + decomposeSvgNode(const_cast< SvgPatternNode* >(this)->aPrimitives, true); + } + + if(!aPrimitives.hasElements() && maXLink.getLength()) + { + const_cast< SvgPatternNode* >(this)->tryToFindLink(); + + if(mpXLink) + { + return mpXLink->getPatternPrimitives(); + } + } + + return aPrimitives; + } + + const basegfx::B2DRange* SvgPatternNode::getCurrentViewPort() const + { + if(getViewBox()) + { + return getViewBox(); + } + else + { + return SvgNode::getCurrentViewPort(); + } + } + + const basegfx::B2DRange* SvgPatternNode::getViewBox() const + { + if(mpViewBox) + { + return mpViewBox; + } + + const_cast< SvgPatternNode* >(this)->tryToFindLink(); + + if(mpXLink) + { + return mpXLink->getViewBox(); + } + + return 0; + } + + const SvgAspectRatio& SvgPatternNode::getSvgAspectRatio() const + { + if(maSvgAspectRatio.isSet()) + { + return maSvgAspectRatio; + } + + const_cast< SvgPatternNode* >(this)->tryToFindLink(); + + if(mpXLink) + { + return mpXLink->getSvgAspectRatio(); + } + + return maSvgAspectRatio; + } + + const SvgNumber& SvgPatternNode::getX() const + { + if(maX.isSet()) + { + return maX; + } + + const_cast< SvgPatternNode* >(this)->tryToFindLink(); + + if(mpXLink) + { + return mpXLink->getX(); + } + + return maX; + } + + const SvgNumber& SvgPatternNode::getY() const + { + if(maY.isSet()) + { + return maY; + } + + const_cast< SvgPatternNode* >(this)->tryToFindLink(); + + if(mpXLink) + { + return mpXLink->getY(); + } + + return maY; + } + + const SvgNumber& SvgPatternNode::getWidth() const + { + if(maWidth.isSet()) + { + return maWidth; + } + + const_cast< SvgPatternNode* >(this)->tryToFindLink(); + + if(mpXLink) + { + return mpXLink->getWidth(); + } + + return maWidth; + } + + const SvgNumber& SvgPatternNode::getHeight() const + { + if(maHeight.isSet()) + { + return maHeight; + } + + const_cast< SvgPatternNode* >(this)->tryToFindLink(); + + if(mpXLink) + { + return mpXLink->getHeight(); + } + + return maHeight; + } + + const SvgUnits* SvgPatternNode::getPatternUnits() const + { + if(mpPatternUnits) + { + return mpPatternUnits; + } + + const_cast< SvgPatternNode* >(this)->tryToFindLink(); + + if(mpXLink) + { + return mpXLink->getPatternUnits(); + } + + return 0; + } + + const SvgUnits* SvgPatternNode::getPatternContentUnits() const + { + if(mpPatternContentUnits) + { + return mpPatternContentUnits; + } + + const_cast< SvgPatternNode* >(this)->tryToFindLink(); + + if(mpXLink) + { + return mpXLink->getPatternContentUnits(); + } + + return 0; + } + + const basegfx::B2DHomMatrix* SvgPatternNode::getPatternTransform() const + { + if(mpaPatternTransform) + { + return mpaPatternTransform; + } + + const_cast< SvgPatternNode* >(this)->tryToFindLink(); + + if(mpXLink) + { + return mpXLink->getPatternTransform(); + } + + return 0; + } + + } // end of namespace svgreader +} // end of namespace svgio + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/svgio/source/svgreader/svgpolynode.cxx b/svgio/source/svgreader/svgpolynode.cxx new file mode 100644 index 000000000000..2b3c991a8593 --- /dev/null +++ b/svgio/source/svgreader/svgpolynode.cxx @@ -0,0 +1,128 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svgio.hxx" + +#include <svgio/svgreader/svgpolynode.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> +#include <basegfx/polygon/b2dpolypolygontools.hxx> + +////////////////////////////////////////////////////////////////////////////// + +namespace svgio +{ + namespace svgreader + { + SvgPolyNode::SvgPolyNode( + SvgDocument& rDocument, + SvgNode* pParent, + bool bIsPolyline) + : SvgNode(SVGTokenPolygon, rDocument, pParent), + maSvgStyleAttributes(*this), + mpPolygon(0), + mpaTransform(0), + mbIsPolyline(bIsPolyline) + { + } + + SvgPolyNode::~SvgPolyNode() + { + if(mpaTransform) delete mpaTransform; + if(mpPolygon) delete mpPolygon; + } + + const SvgStyleAttributes* SvgPolyNode::getSvgStyleAttributes() const + { + static rtl::OUString aClassStr(rtl::OUString::createFromAscii("poly")); + maSvgStyleAttributes.checkForCssStyle(aClassStr); + + return &maSvgStyleAttributes; + } + + void SvgPolyNode::parseAttribute(const rtl::OUString& rTokenName, SVGToken aSVGToken, const rtl::OUString& aContent) + { + // call parent + SvgNode::parseAttribute(rTokenName, aSVGToken, aContent); + + // read style attributes + maSvgStyleAttributes.parseStyleAttribute(rTokenName, aSVGToken, aContent); + + // parse own + switch(aSVGToken) + { + case SVGTokenStyle: + { + maSvgStyleAttributes.readStyle(aContent); + break; + } + case SVGTokenPoints: + { + basegfx::B2DPolygon aPath; + + if(basegfx::tools::importFromSvgPoints(aPath, aContent)) + { + if(aPath.count()) + { + if(!isPolyline()) + { + aPath.setClosed(true); + } + + setPolygon(&aPath); + } + } + break; + } + case SVGTokenTransform: + { + const basegfx::B2DHomMatrix aMatrix(readTransform(aContent, *this)); + + if(!aMatrix.isIdentity()) + { + setTransform(&aMatrix); + } + break; + } + } + } + + void SvgPolyNode::decomposeSvgNode(drawinglayer::primitive2d::Primitive2DSequence& rTarget, bool bReferenced) const + { + const SvgStyleAttributes* pStyle = getSvgStyleAttributes(); + + if(pStyle && getPolygon()) + { + drawinglayer::primitive2d::Primitive2DSequence aNewTarget; + + pStyle->add_path(basegfx::B2DPolyPolygon(*getPolygon()), aNewTarget); + + if(aNewTarget.hasElements()) + { + pStyle->add_postProcess(rTarget, aNewTarget, getTransform()); + } + } + } + } // end of namespace svgreader +} // end of namespace svgio + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/svgio/source/svgreader/svgrectnode.cxx b/svgio/source/svgreader/svgrectnode.cxx new file mode 100644 index 000000000000..8ad8eadf8300 --- /dev/null +++ b/svgio/source/svgreader/svgrectnode.cxx @@ -0,0 +1,226 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svgio.hxx" + +#include <svgio/svgreader/svgrectnode.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> +#include <basegfx/polygon/b2dpolygontools.hxx> + +////////////////////////////////////////////////////////////////////////////// + +namespace svgio +{ + namespace svgreader + { + SvgRectNode::SvgRectNode( + SvgDocument& rDocument, + SvgNode* pParent) + : SvgNode(SVGTokenRect, rDocument, pParent), + maSvgStyleAttributes(*this), + maX(0), + maY(0), + maWidth(0), + maHeight(0), + maRx(0), + maRy(0), + mpaTransform(0) + { + } + + SvgRectNode::~SvgRectNode() + { + if(mpaTransform) delete mpaTransform; + } + + const SvgStyleAttributes* SvgRectNode::getSvgStyleAttributes() const + { + static rtl::OUString aClassStr(rtl::OUString::createFromAscii("rect")); + maSvgStyleAttributes.checkForCssStyle(aClassStr); + + return &maSvgStyleAttributes; + } + + void SvgRectNode::parseAttribute(const rtl::OUString& rTokenName, SVGToken aSVGToken, const rtl::OUString& aContent) + { + // call parent + SvgNode::parseAttribute(rTokenName, aSVGToken, aContent); + + // read style attributes + maSvgStyleAttributes.parseStyleAttribute(rTokenName, aSVGToken, aContent); + + // parse own + switch(aSVGToken) + { + case SVGTokenStyle: + { + maSvgStyleAttributes.readStyle(aContent); + break; + } + case SVGTokenX: + { + SvgNumber aNum; + + if(readSingleNumber(aContent, aNum)) + { + setX(aNum); + } + break; + } + case SVGTokenY: + { + SvgNumber aNum; + + if(readSingleNumber(aContent, aNum)) + { + setY(aNum); + } + break; + } + case SVGTokenWidth: + { + SvgNumber aNum; + + if(readSingleNumber(aContent, aNum)) + { + if(aNum.isPositive()) + { + setWidth(aNum); + } + } + break; + } + case SVGTokenHeight: + { + SvgNumber aNum; + + if(readSingleNumber(aContent, aNum)) + { + if(aNum.isPositive()) + { + setHeight(aNum); + } + } + break; + } + case SVGTokenRx: + { + SvgNumber aNum; + + if(readSingleNumber(aContent, aNum)) + { + if(aNum.isPositive()) + { + setRx(aNum); + } + } + break; + } + case SVGTokenRy: + { + SvgNumber aNum; + + if(readSingleNumber(aContent, aNum)) + { + if(aNum.isPositive()) + { + setRy(aNum); + } + } + break; + } + case SVGTokenTransform: + { + const basegfx::B2DHomMatrix aMatrix(readTransform(aContent, *this)); + + if(!aMatrix.isIdentity()) + { + setTransform(&aMatrix); + } + break; + } + } + } + + void SvgRectNode::decomposeSvgNode(drawinglayer::primitive2d::Primitive2DSequence& rTarget, bool bReferenced) const + { + // get size range and create path + const SvgStyleAttributes* pStyle = getSvgStyleAttributes(); + + if(pStyle && getWidth().isSet() && getHeight().isSet()) + { + const double fWidth(getWidth().solve(*this, xcoordinate)); + const double fHeight(getHeight().solve(*this, ycoordinate)); + + if(fWidth > 0.0 && fHeight > 0.0) + { + const double fX(getX().isSet() ? getX().solve(*this, xcoordinate) : 0.0); + const double fY(getY().isSet() ? getY().solve(*this, ycoordinate) : 0.0); + const basegfx::B2DRange aRange(fX, fY, fX + fWidth, fY + fHeight); + basegfx::B2DPolygon aPath; + + if(getRx().isSet() || getRy().isSet()) + { + double frX(getRx().isSet() ? getRx().solve(*this, xcoordinate) : 0.0); + double frY(getRy().isSet() ? getRy().solve(*this, ycoordinate) : 0.0); + + frX = std::max(0.0, frX); + frY = std::max(0.0, frY); + + if(0.0 == frY && frX > 0.0) + { + frY = frX; + } + else if(0.0 == frX && frY > 0.0) + { + frX = frY; + } + + frX /= fWidth; + frY /= fHeight; + + frX = std::min(0.5, frX); + frY = std::min(0.5, frY); + + aPath = basegfx::tools::createPolygonFromRect(aRange, frX * 2.0, frY * 2.0); + } + else + { + aPath = basegfx::tools::createPolygonFromRect(aRange); + } + + drawinglayer::primitive2d::Primitive2DSequence aNewTarget; + + pStyle->add_path(basegfx::B2DPolyPolygon(aPath), aNewTarget); + + if(aNewTarget.hasElements()) + { + pStyle->add_postProcess(rTarget, aNewTarget, getTransform()); + } + } + } + } + } // end of namespace svgreader +} // end of namespace svgio + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/svgio/source/svgreader/svgstyleattributes.cxx b/svgio/source/svgreader/svgstyleattributes.cxx new file mode 100644 index 000000000000..35204aa3ce86 --- /dev/null +++ b/svgio/source/svgreader/svgstyleattributes.cxx @@ -0,0 +1,2435 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svgio.hxx" + +#include <svgio/svgreader/svgstyleattributes.hxx> +#include <drawinglayer/primitive2d/transformprimitive2d.hxx> +#include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx> +#include <svgio/svgreader/svgnode.hxx> +#include <svgio/svgreader/svgdocument.hxx> +#include <drawinglayer/primitive2d/svggradientprimitive2d.hxx> +#include <svgio/svgreader/svggradientnode.hxx> +#include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx> +#include <basegfx/vector/b2enums.hxx> +#include <drawinglayer/processor2d/linegeometryextractor2d.hxx> +#include <drawinglayer/processor2d/textaspolygonextractor2d.hxx> +#include <basegfx/polygon/b2dpolypolygoncutter.hxx> +#include <svgio/svgreader/svgclippathnode.hxx> +#include <svgio/svgreader/svgmasknode.hxx> +#include <basegfx/polygon/b2dpolypolygoncutter.hxx> +#include <basegfx/polygon/b2dpolypolygontools.hxx> +#include <svgio/svgreader/svgmarkernode.hxx> +#include <basegfx/curve/b2dcubicbezier.hxx> +#include <svgio/svgreader/svgpatternnode.hxx> +#include <drawinglayer/primitive2d/patternfillprimitive2d.hxx> + +////////////////////////////////////////////////////////////////////////////// + +namespace svgio +{ + namespace svgreader + { + basegfx::B2DLineJoin StrokeLinejoinToB2DLineJoin(StrokeLinejoin aStrokeLinejoin) + { + if(StrokeLinejoin_round == aStrokeLinejoin) + { + return basegfx::B2DLINEJOIN_ROUND; + } + else if(StrokeLinejoin_bevel == aStrokeLinejoin) + { + return basegfx::B2DLINEJOIN_BEVEL; + } + + return basegfx::B2DLINEJOIN_MITER; + } + + FontStretch getWider(FontStretch aSource) + { + switch(aSource) + { + case FontStretch_ultra_condensed: aSource = FontStretch_extra_condensed; break; + case FontStretch_extra_condensed: aSource = FontStretch_condensed; break; + case FontStretch_condensed: aSource = FontStretch_semi_condensed; break; + case FontStretch_semi_condensed: aSource = FontStretch_normal; break; + case FontStretch_normal: aSource = FontStretch_semi_expanded; break; + case FontStretch_semi_expanded: aSource = FontStretch_expanded; break; + case FontStretch_expanded: aSource = FontStretch_extra_expanded; break; + case FontStretch_extra_expanded: aSource = FontStretch_ultra_expanded; break; + } + + return aSource; + } + + FontStretch getNarrower(FontStretch aSource) + { + switch(aSource) + { + case FontStretch_extra_condensed: aSource = FontStretch_ultra_condensed; break; + case FontStretch_condensed: aSource = FontStretch_extra_condensed; break; + case FontStretch_semi_condensed: aSource = FontStretch_condensed; break; + case FontStretch_normal: aSource = FontStretch_semi_condensed; break; + case FontStretch_semi_expanded: aSource = FontStretch_normal; break; + case FontStretch_expanded: aSource = FontStretch_semi_expanded; break; + case FontStretch_extra_expanded: aSource = FontStretch_expanded; break; + case FontStretch_ultra_expanded: aSource = FontStretch_extra_expanded; break; + } + + return aSource; + } + + FontWeight getBolder(FontWeight aSource) + { + switch(aSource) + { + case FontWeight_100: aSource = FontWeight_200; break; + case FontWeight_200: aSource = FontWeight_300; break; + case FontWeight_300: aSource = FontWeight_400; break; + case FontWeight_400: aSource = FontWeight_500; break; + case FontWeight_500: aSource = FontWeight_600; break; + case FontWeight_600: aSource = FontWeight_700; break; + case FontWeight_700: aSource = FontWeight_800; break; + case FontWeight_800: aSource = FontWeight_900; break; + } + + return aSource; + } + + FontWeight getLighter(FontWeight aSource) + { + switch(aSource) + { + case FontWeight_200: aSource = FontWeight_100; break; + case FontWeight_300: aSource = FontWeight_200; break; + case FontWeight_400: aSource = FontWeight_300; break; + case FontWeight_500: aSource = FontWeight_400; break; + case FontWeight_600: aSource = FontWeight_500; break; + case FontWeight_700: aSource = FontWeight_600; break; + case FontWeight_800: aSource = FontWeight_700; break; + case FontWeight_900: aSource = FontWeight_800; break; + } + + return aSource; + } + + ::FontWeight getVclFontWeight(FontWeight aSource) + { + ::FontWeight nRetval(WEIGHT_NORMAL); + + switch(aSource) + { + case FontWeight_100: nRetval = WEIGHT_ULTRALIGHT; break; + case FontWeight_200: nRetval = WEIGHT_LIGHT; break; + case FontWeight_300: nRetval = WEIGHT_SEMILIGHT; break; + case FontWeight_400: nRetval = WEIGHT_NORMAL; break; + case FontWeight_500: nRetval = WEIGHT_MEDIUM; break; + case FontWeight_600: nRetval = WEIGHT_SEMIBOLD; break; + case FontWeight_700: nRetval = WEIGHT_BOLD; break; + case FontWeight_800: nRetval = WEIGHT_ULTRABOLD; break; + case FontWeight_900: nRetval = WEIGHT_BLACK; break; + } + + return nRetval; + } + + void SvgStyleAttributes::readStyle(const rtl::OUString& rCandidate) + { + const sal_Int32 nLen(rCandidate.getLength()); + sal_Int32 nPos(0); + + while(nPos < nLen) + { + const sal_Int32 nInitPos(nPos); + skip_char(rCandidate, sal_Unicode(' '), nPos, nLen); + rtl::OUStringBuffer aTokenName; + copyString(rCandidate, nPos, aTokenName, nLen); + + if(aTokenName.getLength()) + { + skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(':'), nPos, nLen); + rtl::OUStringBuffer aTokenValue; + copyToLimiter(rCandidate, sal_Unicode(';'), nPos, aTokenValue, nLen); + skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(';'), nPos, nLen); + const rtl::OUString aOUTokenName(aTokenName.makeStringAndClear()); + const rtl::OUString aOUTokenValue(aTokenValue.makeStringAndClear()); + + parseStyleAttribute(aOUTokenName, StrToSVGToken(aOUTokenName), aOUTokenValue); + } + + if(nInitPos == nPos) + { + OSL_ENSURE(false, "Could not interpret on current position (!)"); + nPos++; + } + } + } + + void SvgStyleAttributes::checkForCssStyle(const rtl::OUString& rClassStr) const + { + if(!mpCssStyleParent) + { + const SvgDocument& rDocument = mrOwner.getDocument(); + const SvgStyleAttributes* pNew = 0; + + if(rDocument.hasSvgStyleAttributesById()) + { + if(mrOwner.getClass()) + { + rtl::OUString aId(rtl::OUString::createFromAscii(".")); + aId = aId + *mrOwner.getClass(); + pNew = rDocument.findSvgStyleAttributesById(aId); + + if(!pNew) + { + aId = rClassStr + aId; + + pNew = rDocument.findSvgStyleAttributesById(aId); + } + } + else if(mrOwner.getId()) + { + pNew = rDocument.findSvgStyleAttributesById(*mrOwner.getId()); + } + + if(pNew) + { + // found css style, set as parent + const_cast< SvgStyleAttributes* >(this)->mpCssStyleParent = pNew; + } + } + } + } + + const SvgStyleAttributes* SvgStyleAttributes::getParentStyle() const + { + if(mpCssStyleParent) + { + return mpCssStyleParent; + } + + if(mrOwner.getParent()) + { + return mrOwner.getParent()->getSvgStyleAttributes(); + } + + return 0; + } + + void SvgStyleAttributes::add_text( + drawinglayer::primitive2d::Primitive2DSequence& rTarget, + drawinglayer::primitive2d::Primitive2DSequence& rSource) const + { + if(rSource.hasElements()) + { + // at this point the primitives in rSource are of type TextSimplePortionPrimitive2D + // or TextDecoratedPortionPrimitive2D and have the Fill Color (pAttributes->getFill()) + // set. When another fill is used and also evtl. stroke is set it gets necessary to + // dismantle to geometry and add needed primitives + const basegfx::BColor* pFill = getFill(); + const SvgGradientNode* pFillGradient = getSvgGradientNodeFill(); + const SvgPatternNode* pFillPattern = getSvgPatternNodeFill(); + const basegfx::BColor* pStroke = getStroke(); + const SvgGradientNode* pStrokeGradient = getSvgGradientNodeStroke(); + const SvgPatternNode* pStrokePattern = getSvgPatternNodeStroke(); + basegfx::B2DPolyPolygon aMergedArea; + + if(pFillGradient || pFillPattern || pStroke || pStrokeGradient || pStrokePattern) + { + // text geometry is needed, create + // use neutral ViewInformation and create LineGeometryExtractor2D + const drawinglayer::geometry::ViewInformation2D aViewInformation2D; + drawinglayer::processor2d::TextAsPolygonExtractor2D aExtractor(aViewInformation2D); + + // proccess + aExtractor.process(rSource); + + // get results + const drawinglayer::processor2d::TextAsPolygonDataNodeVector& rResult = aExtractor.getTarget(); + const sal_uInt32 nResultCount(rResult.size()); + basegfx::B2DPolyPolygonVector aTextFillVector; + aTextFillVector.reserve(nResultCount); + + for(sal_uInt32 a(0); a < nResultCount; a++) + { + const drawinglayer::processor2d::TextAsPolygonDataNode& rCandidate = rResult[a]; + + if(rCandidate.getIsFilled()) + { + aTextFillVector.push_back(rCandidate.getB2DPolyPolygon()); + } + } + + if(!aTextFillVector.empty()) + { + aMergedArea = basegfx::tools::mergeToSinglePolyPolygon(aTextFillVector); + } + } + + const bool bStrokeUsed(pStroke || pStrokeGradient || pStrokePattern); + + // add fill. Use geometry even for simple color fill when stroke + // is used, else text rendering and the geometry-based stroke will + // normally not really match optically due to divrese system text + // renderers + if(aMergedArea.count() && (pFillGradient || pFillPattern || bStrokeUsed)) + { + // create text fill content based on geometry + add_fill(aMergedArea, rTarget, aMergedArea.getB2DRange()); + } + else if(pFill) + { + // add the already prepared primitives for single color fill + drawinglayer::primitive2d::appendPrimitive2DSequenceToPrimitive2DSequence(rTarget, rSource); + } + + // add stroke + if(aMergedArea.count() && bStrokeUsed) + { + // create text stroke content + add_stroke(aMergedArea, rTarget, aMergedArea.getB2DRange()); + } + } + } + + void SvgStyleAttributes::add_fillGradient( + const basegfx::B2DPolyPolygon& rPath, + drawinglayer::primitive2d::Primitive2DSequence& rTarget, + const SvgGradientNode& rFillGradient, + const basegfx::B2DRange& rGeoRange) const + { + // create fill content + drawinglayer::primitive2d::SvgGradientEntryVector aSvgGradientEntryVector; + + // get the color stops + rFillGradient.collectGradientEntries(aSvgGradientEntryVector); + + if(!aSvgGradientEntryVector.empty()) + { + basegfx::B2DHomMatrix aGeoToUnit; + + if(rFillGradient.getGradientTransform()) + { + aGeoToUnit = *rFillGradient.getGradientTransform(); + } + + if(userSpaceOnUse == rFillGradient.getGradientUnits()) + { + aGeoToUnit.translate(-rGeoRange.getMinX(), -rGeoRange.getMinY()); + aGeoToUnit.scale(1.0 / rGeoRange.getWidth(), 1.0 / rGeoRange.getHeight()); + } + + if(SVGTokenLinearGradient == rFillGradient.getType()) + { + basegfx::B2DPoint aStart(0.0, 0.0); + basegfx::B2DPoint aEnd(1.0, 0.0); + + if(userSpaceOnUse == rFillGradient.getGradientUnits()) + { + // all possible units + aStart.setX(rFillGradient.getX1().solve(mrOwner, xcoordinate)); + aStart.setY(rFillGradient.getY1().solve(mrOwner, ycoordinate)); + aEnd.setX(rFillGradient.getX2().solve(mrOwner, xcoordinate)); + aEnd.setY(rFillGradient.getY2().solve(mrOwner, ycoordinate)); + } + else + { + // fractions or percent relative to object bounds + const SvgNumber X1(rFillGradient.getX1()); + const SvgNumber Y1(rFillGradient.getY1()); + const SvgNumber X2(rFillGradient.getX2()); + const SvgNumber Y2(rFillGradient.getY2()); + + aStart.setX(Unit_percent == X1.getUnit() ? X1.getNumber() * 0.01 : X1.getNumber()); + aStart.setY(Unit_percent == Y1.getUnit() ? Y1.getNumber() * 0.01 : Y1.getNumber()); + aEnd.setX(Unit_percent == X2.getUnit() ? X2.getNumber() * 0.01 : X2.getNumber()); + aEnd.setY(Unit_percent == Y2.getUnit() ? Y2.getNumber() * 0.01 : Y2.getNumber()); + } + + if(!aGeoToUnit.isIdentity()) + { + aStart *= aGeoToUnit; + aEnd *= aGeoToUnit; + } + + drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence( + rTarget, + new drawinglayer::primitive2d::SvgLinearGradientPrimitive2D( + rPath, + aSvgGradientEntryVector, + aStart, + aEnd, + rFillGradient.getSpreadMethod())); + } + else + { + basegfx::B2DPoint aStart(0.5, 0.5); + basegfx::B2DPoint aFocal; + double fRadius(0.5); + const SvgNumber* pFx = rFillGradient.getFx(); + const SvgNumber* pFy = rFillGradient.getFy(); + const bool bFocal(pFx || pFy); + + if(userSpaceOnUse == rFillGradient.getGradientUnits()) + { + // all possible units + aStart.setX(rFillGradient.getCx().solve(mrOwner, xcoordinate)); + aStart.setY(rFillGradient.getCy().solve(mrOwner, ycoordinate)); + fRadius = rFillGradient.getR().solve(mrOwner, length); + + if(bFocal) + { + aFocal.setX(pFx ? pFx->solve(mrOwner, xcoordinate) : aStart.getX()); + aFocal.setY(pFy ? pFy->solve(mrOwner, ycoordinate) : aStart.getY()); + } + } + else + { + // fractions or percent relative to object bounds + const SvgNumber Cx(rFillGradient.getCx()); + const SvgNumber Cy(rFillGradient.getCy()); + const SvgNumber R(rFillGradient.getR()); + + aStart.setX(Unit_percent == Cx.getUnit() ? Cx.getNumber() * 0.01 : Cx.getNumber()); + aStart.setY(Unit_percent == Cy.getUnit() ? Cy.getNumber() * 0.01 : Cy.getNumber()); + fRadius = (Unit_percent == R.getUnit()) ? R.getNumber() * 0.01 : R.getNumber(); + + if(bFocal) + { + aFocal.setX(pFx ? (Unit_percent == pFx->getUnit() ? pFx->getNumber() * 0.01 : pFx->getNumber()) : aStart.getX()); + aFocal.setY(pFy ? (Unit_percent == pFy->getUnit() ? pFy->getNumber() * 0.01 : pFy->getNumber()) : aStart.getY()); + } + } + + if(!aGeoToUnit.isIdentity()) + { + aStart *= aGeoToUnit; + fRadius = (aGeoToUnit * basegfx::B2DVector(fRadius, 0.0)).getLength(); + + if(bFocal) + { + aFocal *= aGeoToUnit; + } + } + + drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence( + rTarget, + new drawinglayer::primitive2d::SvgRadialGradientPrimitive2D( + rPath, + aSvgGradientEntryVector, + aStart, + fRadius, + rFillGradient.getSpreadMethod(), + bFocal ? &aFocal : 0)); + } + } + } + + void SvgStyleAttributes::add_fillPatternTransform( + const basegfx::B2DPolyPolygon& rPath, + drawinglayer::primitive2d::Primitive2DSequence& rTarget, + const SvgPatternNode& rFillPattern, + const basegfx::B2DRange& rGeoRange) const + { + // prepare fill polyPolygon with given pattern, check for patternTransform + if(rFillPattern.getPatternTransform() && !rFillPattern.getPatternTransform()->isIdentity()) + { + // PatternTransform is active; Handle by filling the inverse transformed + // path and back-transforming the result + basegfx::B2DPolyPolygon aPath(rPath); + basegfx::B2DHomMatrix aInv(*rFillPattern.getPatternTransform()); + drawinglayer::primitive2d::Primitive2DSequence aNewTarget; + + aInv.invert(); + aPath.transform(aInv); + add_fillPattern(aPath, aNewTarget, rFillPattern, aPath.getB2DRange()); + + if(aNewTarget.hasElements()) + { + drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence( + rTarget, + new drawinglayer::primitive2d::TransformPrimitive2D( + *rFillPattern.getPatternTransform(), + aNewTarget)); + } + } + else + { + // no patternTransform, create fillPattern directly + add_fillPattern(rPath, rTarget, rFillPattern, rGeoRange); + } + } + + void SvgStyleAttributes::add_fillPattern( + const basegfx::B2DPolyPolygon& rPath, + drawinglayer::primitive2d::Primitive2DSequence& rTarget, + const SvgPatternNode& rFillPattern, + const basegfx::B2DRange& rGeoRange) const + { + // fill polyPolygon with given pattern + const drawinglayer::primitive2d::Primitive2DSequence& rPrimitives = rFillPattern.getPatternPrimitives(); + + if(rPrimitives.hasElements()) + { + double fTargetWidth(rGeoRange.getWidth()); + double fTargetHeight(rGeoRange.getHeight()); + + if(fTargetWidth > 0.0 && fTargetHeight > 0.0) + { + // get relative values from pattern + double fX(0.0); + double fY(0.0); + double fW(0.0); + double fH(0.0); + + rFillPattern.getValuesRelative(fX, fY, fW, fH, rGeoRange, mrOwner); + + if(fW > 0.0 && fH > 0.0) + { + // build the reference range relative to the rGeoRange + const basegfx::B2DRange aReferenceRange(fX, fY, fX + fW, fY + fH); + + // find out how the content is mapped to the reference range + basegfx::B2DHomMatrix aMapPrimitivesToUnitRange; + const basegfx::B2DRange* pViewBox = rFillPattern.getViewBox(); + + if(pViewBox) + { + // use viewBox/preserveAspectRatio + const SvgAspectRatio& rRatio = rFillPattern.getSvgAspectRatio(); + const basegfx::B2DRange aUnitRange(0.0, 0.0, 1.0, 1.0); + + if(rRatio.isSet()) + { + // let mapping be created from SvgAspectRatio + aMapPrimitivesToUnitRange = rRatio.createMapping(aUnitRange, *pViewBox); + } + else + { + // choose default mapping + aMapPrimitivesToUnitRange = rRatio.createLinearMapping(aUnitRange, *pViewBox); + } + } + else + { + // use patternContentUnits + const SvgUnits aPatternContentUnits(rFillPattern.getPatternContentUnits() ? *rFillPattern.getPatternContentUnits() : userSpaceOnUse); + + if(userSpaceOnUse == aPatternContentUnits) + { + // create relative mapping to unit coordinates + aMapPrimitivesToUnitRange.scale(1.0 / (fW * fTargetWidth), 1.0 / (fH * fTargetHeight)); + } + else + { + aMapPrimitivesToUnitRange.scale(1.0 / fW, 1.0 / fH); + } + } + + // apply aMapPrimitivesToUnitRange to content when used + drawinglayer::primitive2d::Primitive2DSequence aPrimitives(rPrimitives); + + if(!aMapPrimitivesToUnitRange.isIdentity()) + { + const drawinglayer::primitive2d::Primitive2DReference xRef( + new drawinglayer::primitive2d::TransformPrimitive2D( + aMapPrimitivesToUnitRange, + aPrimitives)); + + aPrimitives = drawinglayer::primitive2d::Primitive2DSequence(&xRef, 1); + } + + // embed in PatternFillPrimitive2D + drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence( + rTarget, + new drawinglayer::primitive2d::PatternFillPrimitive2D( + rPath, + aPrimitives, + aReferenceRange)); + } + } + } + } + + void SvgStyleAttributes::add_fill( + const basegfx::B2DPolyPolygon& rPath, + drawinglayer::primitive2d::Primitive2DSequence& rTarget, + const basegfx::B2DRange& rGeoRange) const + { + const basegfx::BColor* pFill = getFill(); + const SvgGradientNode* pFillGradient = getSvgGradientNodeFill(); + const SvgPatternNode* pFillPattern = getSvgPatternNodeFill(); + + if(pFill || pFillGradient || pFillPattern) + { + const double fFillOpacity(getFillOpacity().solve(mrOwner, length)); + + if(basegfx::fTools::more(fFillOpacity, 0.0)) + { + drawinglayer::primitive2d::Primitive2DSequence aNewFill; + + if(pFillGradient) + { + // create fill content with SVG gradient primitive + add_fillGradient(rPath, aNewFill, *pFillGradient, rGeoRange); + } + else if(pFillPattern) + { + // create fill content with SVG pattern primitive + add_fillPatternTransform(rPath, aNewFill, *pFillPattern, rGeoRange); + } + else // if(pFill) + { + // create fill content + aNewFill.realloc(1); + aNewFill[0] = new drawinglayer::primitive2d::PolyPolygonColorPrimitive2D( + rPath, + *pFill); + } + + if(aNewFill.hasElements()) + { + if(basegfx::fTools::less(fFillOpacity, 1.0)) + { + // embed in UnifiedTransparencePrimitive2D + drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence( + rTarget, + new drawinglayer::primitive2d::UnifiedTransparencePrimitive2D( + aNewFill, + 1.0 - fFillOpacity)); + } + else + { + // append + drawinglayer::primitive2d::appendPrimitive2DSequenceToPrimitive2DSequence(rTarget, aNewFill); + } + } + } + } + } + + void SvgStyleAttributes::add_stroke( + const basegfx::B2DPolyPolygon& rPath, + drawinglayer::primitive2d::Primitive2DSequence& rTarget, + const basegfx::B2DRange& rGeoRange) const + { + const basegfx::BColor* pStroke = getStroke(); + const SvgGradientNode* pStrokeGradient = getSvgGradientNodeStroke(); + const SvgPatternNode* pStrokePattern = getSvgPatternNodeStroke(); + + if(pStroke || pStrokeGradient || pStrokePattern) + { + drawinglayer::primitive2d::Primitive2DSequence aNewStroke; + const double fStrokeOpacity(getStrokeOpacity().solve(mrOwner, length)); + + if(basegfx::fTools::more(fStrokeOpacity, 0.0)) + { + // get stroke width; SVG does not use 0.0 == hairline, so 0.0 is no line at all + const double fStrokeWidth(getStrokeWidth().isSet() ? getStrokeWidth().solve(mrOwner, length) : 1.0); + + if(basegfx::fTools::more(fStrokeWidth, 0.0)) + { + // get LineJoin and stroke array + const basegfx::B2DLineJoin aB2DLineJoin(StrokeLinejoinToB2DLineJoin(getStrokeLinejoin())); + ::std::vector< double > aDashArray; + + if(!getStrokeDasharray().empty()) + { + aDashArray = solveSvgNumberVector(getStrokeDasharray(), mrOwner, length); + } + + // todo: Handle getStrokeDashOffset() + // todo: Handle getStrokeLinecap() + + // prepare line attribute + drawinglayer::primitive2d::Primitive2DReference aNewLinePrimitive; + const drawinglayer::attribute::LineAttribute aLineAttribute( + pStroke ? *pStroke : basegfx::BColor(0.0, 0.0, 0.0), + fStrokeWidth, + aB2DLineJoin); + + if(aDashArray.empty()) + { + aNewLinePrimitive = new drawinglayer::primitive2d::PolyPolygonStrokePrimitive2D( + rPath, + aLineAttribute); + } + else + { + const drawinglayer::attribute::StrokeAttribute aStrokeAttribute(aDashArray); + + aNewLinePrimitive = new drawinglayer::primitive2d::PolyPolygonStrokePrimitive2D( + rPath, + aLineAttribute, + aDashArray); + } + + if(pStrokeGradient || pStrokePattern) + { + // put primitive into Primitive2DReference and Primitive2DSequence + const drawinglayer::primitive2d::Primitive2DSequence aSeq(&aNewLinePrimitive, 1); + + // use neutral ViewInformation and create LineGeometryExtractor2D + const drawinglayer::geometry::ViewInformation2D aViewInformation2D; + drawinglayer::processor2d::LineGeometryExtractor2D aExtractor(aViewInformation2D); + + // proccess + aExtractor.process(aSeq); + + // check for fill rsults + const basegfx::B2DPolyPolygonVector& rLineFillVector(aExtractor.getExtractedLineFills()); + + if(!aExtractor.getExtractedLineFills().empty()) + { + const basegfx::B2DPolyPolygon aMergedArea( + basegfx::tools::mergeToSinglePolyPolygon( + aExtractor.getExtractedLineFills())); + + if(aMergedArea.count()) + { + if(pStrokeGradient) + { + // create fill content with SVG gradient primitive. Use original GeoRange, + // e.g. from circle without LineWidth + add_fillGradient(aMergedArea, aNewStroke, *pStrokeGradient, rGeoRange); + } + else // if(pStrokePattern) + { + // create fill content with SVG pattern primitive. Use GeoRange + // from the expanded data, e.g. circle with extended geo by half linewidth + add_fillPatternTransform(aMergedArea, aNewStroke, *pStrokePattern, aMergedArea.getB2DRange()); + } + } + } + } + else // if(pStroke) + { + drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(aNewStroke, aNewLinePrimitive); + } + + if(aNewStroke.hasElements()) + { + if(basegfx::fTools::less(fStrokeOpacity, 1.0)) + { + // embed in UnifiedTransparencePrimitive2D + drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence( + rTarget, + new drawinglayer::primitive2d::UnifiedTransparencePrimitive2D( + aNewStroke, + 1.0 - fStrokeOpacity)); + } + else + { + // append + drawinglayer::primitive2d::appendPrimitive2DSequenceToPrimitive2DSequence(rTarget, aNewStroke); + } + } + } + } + } + } + + double get_markerRotation( + const SvgMarkerNode& rMarker, + const basegfx::B2DPolygon& rPolygon, + const sal_uInt32 nIndex) + { + double fAngle(0.0); + const sal_uInt32 nPointCount(rPolygon.count()); + + if(nPointCount) + { + if(rMarker.getOrientAuto()) + { + const bool bPrev(rPolygon.isClosed() || nIndex > 0); + basegfx::B2DCubicBezier aSegment; + basegfx::B2DVector aPrev; + basegfx::B2DVector aNext; + + if(bPrev) + { + rPolygon.getBezierSegment((nIndex - 1) % nPointCount, aSegment); + aPrev = aSegment.getTangent(1.0); + } + + const bool bNext(rPolygon.isClosed() || nIndex + 1 < nPointCount); + + if(bNext) + { + rPolygon.getBezierSegment(nIndex % nPointCount, aSegment); + aNext = aSegment.getTangent(0.0); + } + + if(bPrev && bNext) + { + fAngle = atan2(aPrev.getY() + aNext.getY(), aPrev.getX() + aNext.getX()); + } + else if(bPrev) + { + fAngle = atan2(aPrev.getY(), aPrev.getX()); + } + else if(bNext) + { + fAngle = atan2(aNext.getY(), aNext.getX()); + } + } + else + { + fAngle = rMarker.getAngle(); + } + } + + return fAngle; + } + + bool SvgStyleAttributes::prepare_singleMarker( + drawinglayer::primitive2d::Primitive2DSequence& rMarkerPrimitives, + basegfx::B2DHomMatrix& rMarkerTransform, + basegfx::B2DRange& rClipRange, + const SvgMarkerNode& rMarker) const + { + // reset return values + rMarkerTransform.identity(); + rClipRange.reset(); + + // get marker primitive representation + rMarkerPrimitives = rMarker.getMarkerPrimitives(); + + if(rMarkerPrimitives.hasElements()) + { + basegfx::B2DRange aPrimitiveRange; + + if(rMarker.getViewBox()) + { + aPrimitiveRange = *rMarker.getViewBox(); + } + else + { + aPrimitiveRange = drawinglayer::primitive2d::getB2DRangeFromPrimitive2DSequence( + rMarkerPrimitives, + drawinglayer::geometry::ViewInformation2D()); + } + + if(aPrimitiveRange.getWidth() > 0.0 && aPrimitiveRange.getHeight() > 0.0) + { + double fTargetWidth(rMarker.getMarkerWidth().isSet() ? rMarker.getMarkerWidth().solve(mrOwner, xcoordinate) : 0.0); + double fTargetHeight(rMarker.getMarkerHeight().isSet() ? rMarker.getMarkerHeight().solve(mrOwner, xcoordinate) : 0.0); + + if(SvgMarkerNode::strokeWidth == rMarker.getMarkerUnits()) + { + // relative to strokeWidth + const double fStrokeWidth(getStrokeWidth().isSet() ? getStrokeWidth().solve(mrOwner, length) : 1.0); + + fTargetWidth *= fStrokeWidth; + fTargetHeight *= fStrokeWidth; + } + + if(fTargetWidth > 0.0 && fTargetHeight > 0.0) + { + const basegfx::B2DRange aTargetRange(0.0, 0.0, fTargetWidth, fTargetHeight); + + // subbstract refX, refY first, it's in marker local coordinates + rMarkerTransform.translate( + rMarker.getRefX().isSet() ? -rMarker.getRefX().solve(mrOwner, xcoordinate) : 0.0, + rMarker.getRefY().isSet() ? -rMarker.getRefY().solve(mrOwner, ycoordinate) : 0.0); + + // create mapping + const SvgAspectRatio& rRatio = rMarker.getSvgAspectRatio(); + + if(rRatio.isSet()) + { + // let mapping be created from SvgAspectRatio + rMarkerTransform = rRatio.createMapping(aTargetRange, aPrimitiveRange) * rMarkerTransform; + + if(rRatio.isMeetOrSlice()) + { + // need to clip + rClipRange = basegfx::B2DRange(0.0, 0.0, 1.0, 1.0); + } + } + else + { + // choose default mapping + rMarkerTransform = rRatio.createLinearMapping(aTargetRange, aPrimitiveRange) * rMarkerTransform; + } + + return true; + } + } + } + + return false; + } + + void SvgStyleAttributes::add_singleMarker( + drawinglayer::primitive2d::Primitive2DSequence& rTarget, + const drawinglayer::primitive2d::Primitive2DSequence& rMarkerPrimitives, + const basegfx::B2DHomMatrix& rMarkerTransform, + const basegfx::B2DRange& rClipRange, + const SvgMarkerNode& rMarker, + const basegfx::B2DPolygon& rCandidate, + const sal_uInt32 nIndex) const + { + const sal_uInt32 nPointCount(rCandidate.count()); + + if(nPointCount) + { + // get and apply rotation + basegfx::B2DHomMatrix aCombinedTransform(rMarkerTransform); + aCombinedTransform.rotate(get_markerRotation(rMarker, rCandidate, nIndex)); + + // get and apply target position + const basegfx::B2DPoint aPoint(rCandidate.getB2DPoint(nIndex % nPointCount)); + aCombinedTransform.translate(aPoint.getX(), aPoint.getY()); + + // add marker + drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence( + rTarget, + new drawinglayer::primitive2d::TransformPrimitive2D( + aCombinedTransform, + rMarkerPrimitives)); + } + } + + void SvgStyleAttributes::add_markers( + const basegfx::B2DPolyPolygon& rPath, + drawinglayer::primitive2d::Primitive2DSequence& rTarget) const + { + // try to access linked markers + const SvgMarkerNode* pStart = accessMarkerStartXLink(); + const SvgMarkerNode* pMid = accessMarkerMidXLink(); + const SvgMarkerNode* pEnd = accessMarkerEndXLink(); + + if(pStart || pMid || pEnd) + { + const sal_uInt32 nCount(rPath.count()); + + for (sal_uInt32 a(0); a < nCount; a++) + { + const basegfx::B2DPolygon aCandidate(rPath.getB2DPolygon(a)); + const sal_uInt32 nPointCount(aCandidate.count()); + + if(nPointCount) + { + const sal_uInt32 nMarkerCount(aCandidate.isClosed() ? nPointCount + 1 : nPointCount); + drawinglayer::primitive2d::Primitive2DSequence aMarkerPrimitives; + basegfx::B2DHomMatrix aMarkerTransform; + basegfx::B2DRange aClipRange; + const SvgMarkerNode* pPrepared = 0; + + if(pStart) + { + if(prepare_singleMarker(aMarkerPrimitives, aMarkerTransform, aClipRange, *pStart)) + { + pPrepared = pStart; + add_singleMarker(rTarget, aMarkerPrimitives, aMarkerTransform, aClipRange, *pPrepared, aCandidate, 0); + } + } + + if(pMid && nMarkerCount > 2) + { + if(pMid == pPrepared || prepare_singleMarker(aMarkerPrimitives, aMarkerTransform, aClipRange, *pMid)) + { + pPrepared = pMid; + + for(sal_uInt32 a(1); a < nMarkerCount - 1; a++) + { + add_singleMarker(rTarget, aMarkerPrimitives, aMarkerTransform, aClipRange, *pPrepared, aCandidate, a); + } + } + } + + if(pEnd) + { + if(pEnd == pPrepared || prepare_singleMarker(aMarkerPrimitives, aMarkerTransform, aClipRange, *pEnd)) + { + pPrepared = pEnd; + add_singleMarker(rTarget, aMarkerPrimitives, aMarkerTransform, aClipRange, *pPrepared, aCandidate, nMarkerCount - 1); + } + } + } + } + } + } + + void SvgStyleAttributes::add_path( + const basegfx::B2DPolyPolygon& rPath, + drawinglayer::primitive2d::Primitive2DSequence& rTarget) const + { + const bool bIsLine(1 == rPath.count() + && !rPath.areControlPointsUsed() + && 2 == rPath.getB2DPolygon(0).count()); + + if(!rPath.count()) + { + return; + } + + const basegfx::B2DRange aGeoRange(rPath.getB2DRange()); + + if(aGeoRange.isEmpty()) + { + return; + } + + if(!bIsLine && // not for lines + (basegfx::fTools::equalZero(aGeoRange.getWidth()) + || basegfx::fTools::equalZero(aGeoRange.getHeight()))) + { + return; + } + + const double fOpacity(getOpacity().getNumber()); + + if(basegfx::fTools::equalZero(fOpacity)) + { + return; + } + + if(!bIsLine) + { + basegfx::B2DPolyPolygon aPath(rPath); + const bool bNeedToCheckClipRule(SVGTokenPath == mrOwner.getType() || SVGTokenPolygon == mrOwner.getType()); + const bool bClipPathIsNonzero(!bIsLine && bNeedToCheckClipRule && mbIsClipPathContent && mbClipRule); + const bool bFillRuleIsNonzero(!bIsLine && bNeedToCheckClipRule && !mbIsClipPathContent && getFillRule()); + + if(bClipPathIsNonzero || bFillRuleIsNonzero) + { + // nonzero is wanted, solve geometrically (see description on basegfx) + aPath = basegfx::tools::createNonzeroConform(aPath); + } + + add_fill(aPath, rTarget, aGeoRange); + } + + add_stroke(rPath, rTarget, aGeoRange); + + // Svg supports markers for path, polygon, polyline and line + if(SVGTokenPath == mrOwner.getType() || // path + SVGTokenPolygon == mrOwner.getType() || // polygon, polyline + SVGTokenLine == mrOwner.getType()) // line + { + // try to add markers + add_markers(rPath, rTarget); + } + } + + void SvgStyleAttributes::add_postProcess( + drawinglayer::primitive2d::Primitive2DSequence& rTarget, + const drawinglayer::primitive2d::Primitive2DSequence& rSource, + const basegfx::B2DHomMatrix* pTransform) const + { + if(rSource.hasElements()) + { + const double fOpacity(getOpacity().getNumber()); + + if(basegfx::fTools::equalZero(fOpacity)) + { + return; + } + + drawinglayer::primitive2d::Primitive2DSequence aSource(rSource); + + if(basegfx::fTools::less(fOpacity, 1.0)) + { + // embed in UnifiedTransparencePrimitive2D + const drawinglayer::primitive2d::Primitive2DReference xRef( + new drawinglayer::primitive2d::UnifiedTransparencePrimitive2D( + aSource, + 1.0 - fOpacity)); + + aSource = drawinglayer::primitive2d::Primitive2DSequence(&xRef, 1); + } + + if(getClipPathXLink().getLength()) + { + // try to access linked ClipPath + const SvgClipPathNode* mpClip = dynamic_cast< const SvgClipPathNode* >(mrOwner.getDocument().findSvgNodeById(getClipPathXLink())); + + if(mpClip) + { + mpClip->apply(aSource); + } + } + + if(aSource.hasElements()) // test again, applied clipPath may have lead to empty geometry + { + if(getMaskXLink().getLength()) + { + // try to access linked Mask + const SvgMaskNode* mpMask = dynamic_cast< const SvgMaskNode* >(mrOwner.getDocument().findSvgNodeById(getMaskXLink())); + + if(mpMask) + { + mpMask->apply(aSource); + } + } + + if(aSource.hasElements()) // test again, applied mask may have lead to empty geometry + { + if(pTransform) + { + // create embedding group element with transformation + const drawinglayer::primitive2d::Primitive2DReference xRef( + new drawinglayer::primitive2d::TransformPrimitive2D( + *pTransform, + aSource)); + + aSource = drawinglayer::primitive2d::Primitive2DSequence(&xRef, 1); + } + + // append to current target + drawinglayer::primitive2d::appendPrimitive2DSequenceToPrimitive2DSequence(rTarget, aSource); + } + } + } + } + + SvgStyleAttributes::SvgStyleAttributes(SvgNode& rOwner) + : mrOwner(rOwner), + mpCssStyleParent(0), + maFill(), + maStroke(), + maStopColor(basegfx::BColor(0.0, 0.0, 0.0), true), + maStrokeWidth(), + maStopOpacity(), + mpSvgGradientNodeFill(0), + mpSvgGradientNodeStroke(0), + mpSvgPatternNodeFill(0), + mpSvgPatternNodeStroke(0), + maFillOpacity(), + maStrokeDasharray(), + maStrokeDashOffset(), + maStrokeLinecap(StrokeLinecap_notset), + maStrokeLinejoin(StrokeLinejoin_notset), + maStrokeMiterLimit(), + maStrokeOpacity(), + maFontFamily(), + maFontSize(), + maFontStretch(FontStretch_notset), + maFontStyle(FontStyle_notset), + maFontVariant(FontVariant_notset), + maFontWeight(FontWeight_notset), + maTextAlign(TextAlign_notset), + maTextDecoration(TextDecoration_notset), + maTextAnchor(TextAnchor_notset), + maColor(), + maOpacity(1.0), + maClipPathXLink(), + maMaskXLink(), + maMarkerStartXLink(), + mpMarkerStartXLink(0), + maMarkerMidXLink(), + mpMarkerMidXLink(0), + maMarkerEndXLink(), + mpMarkerEndXLink(0), + maFillRule(true), + maFillRuleSet(false), + mbIsClipPathContent(SVGTokenClipPathNode == mrOwner.getType()), + mbClipRule(true) + { + if(!mbIsClipPathContent) + { + const SvgStyleAttributes* pParentStyle = getParentStyle(); + + if(pParentStyle) + { + mbIsClipPathContent = pParentStyle->mbIsClipPathContent; + } + } + } + + SvgStyleAttributes::~SvgStyleAttributes() + { + } + + void SvgStyleAttributes::parseStyleAttribute(const rtl::OUString& rTokenName, SVGToken aSVGToken, const rtl::OUString& aContent) + { + switch(aSVGToken) + { + case SVGTokenFill: + { + SvgPaint aSvgPaint; + rtl::OUString aURL; + bool bUseCurrent(false); + + if(readSvgPaint(aContent, aSvgPaint, aURL)) + { + setFill(aSvgPaint); + } + else if(aURL.getLength()) + { + const SvgNode* pNode = mrOwner.getDocument().findSvgNodeById(aURL); + + if(pNode) + { + if(SVGTokenLinearGradient == pNode->getType() || SVGTokenRadialGradient == pNode->getType()) + { + setSvgGradientNodeFill(static_cast< const SvgGradientNode* >(pNode)); + } + else if(SVGTokenPattern == pNode->getType()) + { + setSvgPatternNodeFill(static_cast< const SvgPatternNode* >(pNode)); + } + } + } + break; + } + case SVGTokenFillOpacity: + { + SvgNumber aNum; + + if(readSingleNumber(aContent, aNum)) + { + if(aNum.isPositive()) + { + setFillOpacity(aNum); + } + } + break; + } + case SVGTokenFillRule: + { + if(aContent.getLength()) + { + if(aContent.match(commonStrings::aStrNonzero)) + { + maFillRule = true; + maFillRuleSet = true; + } + else if(aContent.match(commonStrings::aStrEvenOdd)) + { + maFillRule = false; + maFillRuleSet = true; + } + } + break; + } + case SVGTokenStroke: + { + SvgPaint aSvgPaint; + rtl::OUString aURL; + + if(readSvgPaint(aContent, aSvgPaint, aURL)) + { + setStroke(aSvgPaint); + } + else if(aURL.getLength()) + { + const SvgNode* pNode = mrOwner.getDocument().findSvgNodeById(aURL); + + if(pNode) + { + if(SVGTokenLinearGradient == pNode->getType() || SVGTokenRadialGradient == pNode->getType()) + { + setSvgGradientNodeStroke(static_cast< const SvgGradientNode* >(pNode)); + } + else if(SVGTokenPattern == pNode->getType()) + { + setSvgPatternNodeStroke(static_cast< const SvgPatternNode* >(pNode)); + } + } + } + break; + } + case SVGTokenStrokeDasharray: + { + if(aContent.getLength()) + { + SvgNumberVector aVector; + + if(readSvgNumberVector(aContent, aVector)) + { + setStrokeDasharray(aVector); + } + } + break; + } + case SVGTokenStrokeDashoffset: + { + SvgNumber aNum; + + if(readSingleNumber(aContent, aNum)) + { + if(aNum.isPositive()) + { + setStrokeDashOffset(aNum); + } + } + break; + } + case SVGTokenStrokeLinecap: + { + if(aContent.getLength()) + { + static rtl::OUString aStrButt(rtl::OUString::createFromAscii("butt")); + static rtl::OUString aStrRound(rtl::OUString::createFromAscii("round")); + static rtl::OUString aStrSquare(rtl::OUString::createFromAscii("square")); + + if(aContent.match(aStrButt)) + { + setStrokeLinecap(StrokeLinecap_butt); + } + else if(aContent.match(aStrRound)) + { + setStrokeLinecap(StrokeLinecap_round); + } + else if(aContent.match(aStrSquare)) + { + setStrokeLinecap(StrokeLinecap_square); + } + } + break; + } + case SVGTokenStrokeLinejoin: + { + if(aContent.getLength()) + { + static rtl::OUString aStrMiter(rtl::OUString::createFromAscii("miter")); + static rtl::OUString aStrRound(rtl::OUString::createFromAscii("round")); + static rtl::OUString aStrBevel(rtl::OUString::createFromAscii("bevel")); + + if(aContent.match(aStrMiter)) + { + setStrokeLinejoin(StrokeLinejoin_miter); + } + else if(aContent.match(aStrRound)) + { + setStrokeLinejoin(StrokeLinejoin_round); + } + else if(aContent.match(aStrBevel)) + { + setStrokeLinejoin(StrokeLinejoin_bevel); + } + } + break; + } + case SVGTokenStrokeMiterlimit: + { + SvgNumber aNum; + + if(readSingleNumber(aContent, aNum)) + { + if(aNum.isPositive()) + { + setStrokeMiterLimit(aNum); + } + } + break; + } + case SVGTokenStrokeOpacity: + { + SvgNumber aNum; + + if(readSingleNumber(aContent, aNum)) + { + if(aNum.isPositive()) + { + setStrokeOpacity(aNum); + } + } + break; + } + case SVGTokenStrokeWidth: + { + SvgNumber aNum; + + if(readSingleNumber(aContent, aNum)) + { + if(aNum.isPositive()) + { + setStrokeWidth(aNum); + } + } + break; + } + case SVGTokenStopColor: + { + SvgPaint aSvgPaint; + rtl::OUString aURL; + + if(readSvgPaint(aContent, aSvgPaint, aURL)) + { + setStopColor(aSvgPaint); + } + break; + } + case SVGTokenStopOpacity: + { + SvgNumber aNum; + + if(readSingleNumber(aContent, aNum)) + { + if(aNum.isPositive()) + { + setStopOpacity(aNum); + } + } + break; + } + case SVGTokenFont: + { + bool bBla = true; + break; + } + case SVGTokenFontFamily: + { + SvgStringVector aSvgStringVector; + + if(readSvgStringVector(aContent, aSvgStringVector)) + { + setFontFamily(aSvgStringVector); + } + break; + } + case SVGTokenFontSize: + { + SvgNumber aNum; + + if(readSingleNumber(aContent, aNum)) + { + setFontSize(aNum); + } + break; + } + case SVGTokenFontSizeAdjust: + { + bool bBla = true; + break; + } + case SVGTokenFontStretch: + { + if(aContent.getLength()) + { + static rtl::OUString aStrNormal(rtl::OUString::createFromAscii("normal")); + static rtl::OUString aStrWider(rtl::OUString::createFromAscii("wider")); + static rtl::OUString aStrNarrower(rtl::OUString::createFromAscii("narrower")); + static rtl::OUString aStrUltra_condensed(rtl::OUString::createFromAscii("ultra-condensed")); + static rtl::OUString aStrExtra_condensed(rtl::OUString::createFromAscii("extra-condensed")); + static rtl::OUString aStrCondensed(rtl::OUString::createFromAscii("condensed")); + static rtl::OUString aStrSemi_condensed(rtl::OUString::createFromAscii("semi-condensed")); + static rtl::OUString aStrSemi_expanded(rtl::OUString::createFromAscii("semi-expanded")); + static rtl::OUString aStrExpanded(rtl::OUString::createFromAscii("expanded")); + static rtl::OUString aStrExtra_expanded(rtl::OUString::createFromAscii("extra-expanded")); + static rtl::OUString aStrUltra_expanded(rtl::OUString::createFromAscii("ultra-expanded")); + + if(aContent.match(aStrNormal)) + { + setFontStretch(FontStretch_normal); + } + else if(aContent.match(aStrWider)) + { + setFontStretch(FontStretch_wider); + } + else if(aContent.match(aStrNarrower)) + { + setFontStretch(FontStretch_narrower); + } + else if(aContent.match(aStrUltra_condensed)) + { + setFontStretch(FontStretch_ultra_condensed); + } + else if(aContent.match(aStrExtra_condensed)) + { + setFontStretch(FontStretch_extra_condensed); + } + else if(aContent.match(aStrCondensed)) + { + setFontStretch(FontStretch_condensed); + } + else if(aContent.match(aStrSemi_condensed)) + { + setFontStretch(FontStretch_semi_condensed); + } + else if(aContent.match(aStrSemi_expanded)) + { + setFontStretch(FontStretch_semi_expanded); + } + else if(aContent.match(aStrExpanded)) + { + setFontStretch(FontStretch_expanded); + } + else if(aContent.match(aStrExtra_expanded)) + { + setFontStretch(FontStretch_extra_expanded); + } + else if(aContent.match(aStrUltra_expanded)) + { + setFontStretch(FontStretch_ultra_expanded); + } + } + break; + } + case SVGTokenFontStyle: + { + if(aContent.getLength()) + { + static rtl::OUString aStrNormal(rtl::OUString::createFromAscii("normal")); + static rtl::OUString aStrItalic(rtl::OUString::createFromAscii("italic")); + static rtl::OUString aStrOblique(rtl::OUString::createFromAscii("oblique")); + + if(aContent.match(aStrNormal)) + { + setFontStyle(FontStyle_normal); + } + else if(aContent.match(aStrItalic)) + { + setFontStyle(FontStyle_italic); + } + else if(aContent.match(aStrOblique)) + { + setFontStyle(FontStyle_oblique); + } + } + break; + } + case SVGTokenFontVariant: + { + if(aContent.getLength()) + { + static rtl::OUString aStrNormal(rtl::OUString::createFromAscii("normal")); + static rtl::OUString aStrSmallCaps(rtl::OUString::createFromAscii("small-caps")); + + if(aContent.match(aStrNormal)) + { + setFontVariant(FontVariant_normal); + } + else if(aContent.match(aStrSmallCaps)) + { + setFontVariant(FontVariant_small_caps); + } + } + break; + } + case SVGTokenFontWeight: + { + if(aContent.getLength()) + { + static rtl::OUString aStrNormal(rtl::OUString::createFromAscii("normal")); + static rtl::OUString aStrBold(rtl::OUString::createFromAscii("bold")); + static rtl::OUString aStrBolder(rtl::OUString::createFromAscii("bolder")); + static rtl::OUString aStrLighter(rtl::OUString::createFromAscii("lighter")); + static rtl::OUString aStr100(rtl::OUString::createFromAscii("100")); + static rtl::OUString aStr200(rtl::OUString::createFromAscii("200")); + static rtl::OUString aStr300(rtl::OUString::createFromAscii("300")); + static rtl::OUString aStr400(rtl::OUString::createFromAscii("400")); + static rtl::OUString aStr500(rtl::OUString::createFromAscii("500")); + static rtl::OUString aStr600(rtl::OUString::createFromAscii("600")); + static rtl::OUString aStr700(rtl::OUString::createFromAscii("700")); + static rtl::OUString aStr800(rtl::OUString::createFromAscii("800")); + static rtl::OUString aStr900(rtl::OUString::createFromAscii("900")); + + if(aContent.match(aStr100)) + { + setFontWeight(FontWeight_100); + } + else if(aContent.match(aStr200)) + { + setFontWeight(FontWeight_200); + } + else if(aContent.match(aStr300)) + { + setFontWeight(FontWeight_300); + } + else if(aContent.match(aStr400) || aContent.match(aStrNormal)) + { + setFontWeight(FontWeight_400); + } + else if(aContent.match(aStr500)) + { + setFontWeight(FontWeight_500); + } + else if(aContent.match(aStr600)) + { + setFontWeight(FontWeight_600); + } + else if(aContent.match(aStr700) || aContent.match(aStrBold)) + { + setFontWeight(FontWeight_700); + } + else if(aContent.match(aStr800)) + { + setFontWeight(FontWeight_800); + } + else if(aContent.match(aStr900)) + { + setFontWeight(FontWeight_900); + } + else if(aContent.match(aStrBolder)) + { + setFontWeight(FontWeight_bolder); + } + else if(aContent.match(aStrLighter)) + { + setFontWeight(FontWeight_lighter); + } + } + break; + } + case SVGTokenDirection: + { + bool bBla = true; + break; + } + case SVGTokenLetterSpacing: + { + bool bBla = true; + break; + } + case SVGTokenTextDecoration: + { + if(aContent.getLength()) + { + static rtl::OUString aStrNone(rtl::OUString::createFromAscii("none")); + static rtl::OUString aStrUnderline(rtl::OUString::createFromAscii("underline")); + static rtl::OUString aStrOverline(rtl::OUString::createFromAscii("overline")); + static rtl::OUString aStrLineThrough(rtl::OUString::createFromAscii("line-through")); + static rtl::OUString aStrBlink(rtl::OUString::createFromAscii("blink")); + + if(aContent.match(aStrNone)) + { + setTextDecoration(TextDecoration_none); + } + else if(aContent.match(aStrUnderline)) + { + setTextDecoration(TextDecoration_underline); + } + else if(aContent.match(aStrOverline)) + { + setTextDecoration(TextDecoration_overline); + } + else if(aContent.match(aStrLineThrough)) + { + setTextDecoration(TextDecoration_line_through); + } + else if(aContent.match(aStrBlink)) + { + setTextDecoration(TextDecoration_blink); + } + } + break; + } + case SVGTokenUnicodeBidi: + { + bool bBla = true; + break; + } + case SVGTokenWordSpacing: + { + bool bBla = true; + break; + } + case SVGTokenTextAnchor: + { + if(aContent.getLength()) + { + static rtl::OUString aStrStart(rtl::OUString::createFromAscii("start")); + static rtl::OUString aStrMiddle(rtl::OUString::createFromAscii("middle")); + static rtl::OUString aStrEnd(rtl::OUString::createFromAscii("end")); + + if(aContent.match(aStrStart)) + { + setTextAnchor(TextAnchor_start); + } + else if(aContent.match(aStrMiddle)) + { + setTextAnchor(TextAnchor_middle); + } + else if(aContent.match(aStrEnd)) + { + setTextAnchor(TextAnchor_end); + } + } + break; + } + case SVGTokenTextAlign: + { + if(aContent.getLength()) + { + static rtl::OUString aStrLeft(rtl::OUString::createFromAscii("left")); + static rtl::OUString aStrRight(rtl::OUString::createFromAscii("right")); + static rtl::OUString aStrCenter(rtl::OUString::createFromAscii("center")); + static rtl::OUString aStrJustify(rtl::OUString::createFromAscii("justify")); + + if(aContent.match(aStrLeft)) + { + setTextAlign(TextAlign_left); + } + else if(aContent.match(aStrRight)) + { + setTextAlign(TextAlign_right); + } + else if(aContent.match(aStrCenter)) + { + setTextAlign(TextAlign_center); + } + else if(aContent.match(aStrJustify)) + { + setTextAlign(TextAlign_justify); + } + } + break; + } + case SVGTokenColor: + { + SvgPaint aSvgPaint; + rtl::OUString aURL; + + if(readSvgPaint(aContent, aSvgPaint, aURL)) + { + setColor(aSvgPaint); + } + break; + } + case SVGTokenOpacity: + { + SvgNumber aNum; + + if(readSingleNumber(aContent, aNum)) + { + setOpacity(SvgNumber(basegfx::clamp(aNum.getNumber(), 0.0, 1.0), aNum.getUnit(), aNum.isSet())); + } + break; + } + case SVGTokenClipPathProperty: + { + readLocalUrl(aContent, maClipPathXLink); + break; + } + case SVGTokenMask: + { + readLocalUrl(aContent, maMaskXLink); + break; + } + case SVGTokenClipRule: + { + if(aContent.getLength()) + { + if(aContent.match(commonStrings::aStrNonzero)) + { + mbClipRule = true; + } + else if(aContent.match(commonStrings::aStrEvenOdd)) + { + mbClipRule = false; + } + } + break; + } + case SVGTokenMarker: + { + readLocalUrl(aContent, maMarkerEndXLink); + maMarkerStartXLink = maMarkerMidXLink = maMarkerEndXLink; + break; + } + case SVGTokenMarkerStart: + { + readLocalUrl(aContent, maMarkerStartXLink); + break; + } + case SVGTokenMarkerMid: + { + readLocalUrl(aContent, maMarkerMidXLink); + break; + } + case SVGTokenMarkerEnd: + { + readLocalUrl(aContent, maMarkerEndXLink); + break; + } + } + } + + const basegfx::BColor* SvgStyleAttributes::getFill() const + { + if(mbIsClipPathContent) + { + static basegfx::BColor aBlack(0.0, 0.0, 0.0); + + return &aBlack; + } + else if(maFill.isSet()) + { + if(maFill.isCurrent()) + { + return getColor(); + } + else if(maFill.isOn()) + { + return &maFill.getBColor(); + } + } + else + { + const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle(); + + if(pSvgStyleAttributes) + { + return pSvgStyleAttributes->getFill(); + } + } + + return 0; + } + + const basegfx::BColor* SvgStyleAttributes::getStroke() const + { + if(mbIsClipPathContent) + { + return 0; + } + else if(maStroke.isSet()) + { + if(maStroke.isCurrent()) + { + return getColor(); + } + else if(maStroke.isOn()) + { + return &maStroke.getBColor(); + } + } + else + { + const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle(); + + if(pSvgStyleAttributes) + { + return pSvgStyleAttributes->getStroke(); + } + } + + return 0; + } + + const basegfx::BColor& SvgStyleAttributes::getStopColor() const + { + if(maStopColor.isCurrent()) + { + return *getColor(); + } + else + { + return maStopColor.getBColor(); + } + } + + const SvgGradientNode* SvgStyleAttributes::getSvgGradientNodeFill() const + { + if(mbIsClipPathContent) + { + return 0; + } + else if(mpSvgGradientNodeFill) + { + return mpSvgGradientNodeFill; + } + else + { + const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle(); + + if(pSvgStyleAttributes) + { + return pSvgStyleAttributes->getSvgGradientNodeFill(); + } + } + + return 0; + } + + const SvgGradientNode* SvgStyleAttributes::getSvgGradientNodeStroke() const + { + if(mbIsClipPathContent) + { + return 0; + } + else if(mpSvgGradientNodeStroke) + { + return mpSvgGradientNodeStroke; + } + else + { + const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle(); + + if(pSvgStyleAttributes) + { + return pSvgStyleAttributes->getSvgGradientNodeStroke(); + } + } + + return 0; + } + + const SvgPatternNode* SvgStyleAttributes::getSvgPatternNodeFill() const + { + if(mbIsClipPathContent) + { + return 0; + } + else if(mpSvgPatternNodeFill) + { + return mpSvgPatternNodeFill; + } + else + { + const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle(); + + if(pSvgStyleAttributes) + { + return pSvgStyleAttributes->getSvgPatternNodeFill(); + } + } + + return 0; + } + + const SvgPatternNode* SvgStyleAttributes::getSvgPatternNodeStroke() const + { + if(mbIsClipPathContent) + { + return 0; + } + else if(mpSvgPatternNodeStroke) + { + return mpSvgPatternNodeStroke; + } + else + { + const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle(); + + if(pSvgStyleAttributes) + { + return pSvgStyleAttributes->getSvgPatternNodeStroke(); + } + } + + return 0; + } + + const SvgNumber SvgStyleAttributes::getStrokeWidth() const + { + if(mbIsClipPathContent) + { + return SvgNumber(0.0); + } + else if(maStrokeWidth.isSet()) + { + return maStrokeWidth; + } + + const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle(); + + if(pSvgStyleAttributes) + { + return pSvgStyleAttributes->getStrokeWidth(); + } + + // default is 1 + return SvgNumber(1.0); + } + + const SvgNumber SvgStyleAttributes::getStopOpacity() const + { + if(maStopOpacity.isSet()) + { + return maStopOpacity; + } + + // default is 1 + return SvgNumber(1.0); + } + + const SvgNumber SvgStyleAttributes::getFillOpacity() const + { + if(mbIsClipPathContent) + { + return SvgNumber(1.0); + } + else if(maFillOpacity.isSet()) + { + return maFillOpacity; + } + + const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle(); + + if(pSvgStyleAttributes) + { + return pSvgStyleAttributes->getFillOpacity(); + } + + // default is 1 + return SvgNumber(1.0); + } + + bool SvgStyleAttributes::getFillRule() const + { + if(maFillRuleSet) + { + return maFillRule; + } + + const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle(); + + if(pSvgStyleAttributes) + { + return pSvgStyleAttributes->getFillRule(); + } + + // default is NonZero + return true; + } + + void SvgStyleAttributes::setFillRule(const bool* pFillRule) + { + if(pFillRule) + { + maFillRuleSet = true; + maFillRule = *pFillRule; + } + else + { + maFillRuleSet = false; + } + } + + const SvgNumberVector& SvgStyleAttributes::getStrokeDasharray() const + { + if(!maStrokeDasharray.empty()) + { + return maStrokeDasharray; + } + + const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle(); + + if(pSvgStyleAttributes) + { + return pSvgStyleAttributes->getStrokeDasharray(); + } + + // default empty + return maStrokeDasharray; + } + + const SvgNumber SvgStyleAttributes::getStrokeDashOffset() const + { + if(maStrokeDashOffset.isSet()) + { + return maStrokeDashOffset; + } + + const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle(); + + if(pSvgStyleAttributes) + { + return pSvgStyleAttributes->getStrokeDashOffset(); + } + + // default is 0 + return SvgNumber(0.0); + } + + const StrokeLinecap SvgStyleAttributes::getStrokeLinecap() const + { + if(maStrokeLinecap != StrokeLinecap_notset) + { + return maStrokeLinecap; + } + + const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle(); + + if(pSvgStyleAttributes) + { + return pSvgStyleAttributes->getStrokeLinecap(); + } + + // default is StrokeLinecap_butt + return StrokeLinecap_butt; + } + + const StrokeLinejoin SvgStyleAttributes::getStrokeLinejoin() const + { + if(maStrokeLinejoin != StrokeLinejoin_notset) + { + return maStrokeLinejoin; + } + + const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle(); + + if(pSvgStyleAttributes) + { + return pSvgStyleAttributes->getStrokeLinejoin(); + } + + // default is StrokeLinejoin_butt + return StrokeLinejoin_miter; + } + + const SvgNumber SvgStyleAttributes::getStrokeMiterLimit() const + { + if(maStrokeMiterLimit.isSet()) + { + return maStrokeMiterLimit; + } + + const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle(); + + if(pSvgStyleAttributes) + { + return pSvgStyleAttributes->getStrokeMiterLimit(); + } + + // default is 4 + return SvgNumber(4.0); + } + + const SvgNumber SvgStyleAttributes::getStrokeOpacity() const + { + if(maStrokeOpacity.isSet()) + { + return maStrokeOpacity; + } + + const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle(); + + if(pSvgStyleAttributes) + { + return pSvgStyleAttributes->getStrokeOpacity(); + } + + // default is 1 + return SvgNumber(1.0); + } + + const SvgStringVector& SvgStyleAttributes::getFontFamily() const + { + if(!maFontFamily.empty()) + { + return maFontFamily; + } + + const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle(); + + if(pSvgStyleAttributes) + { + return pSvgStyleAttributes->getFontFamily(); + } + + // default is empty + return maFontFamily; + } + + const SvgNumber SvgStyleAttributes::getFontSize() const + { + if(maFontSize.isSet()) + { + return maFontSize; + } + + const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle(); + + if(pSvgStyleAttributes) + { + return pSvgStyleAttributes->getFontSize(); + } + + // default is 'medium' + return SvgNumber(12.0); + } + + const FontStretch SvgStyleAttributes::getFontStretch() const + { + if(maFontStretch != FontStretch_notset) + { + if(FontStretch_wider != maFontStretch && FontStretch_narrower != maFontStretch) + { + return maFontStretch; + } + } + + const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle(); + + if(pSvgStyleAttributes) + { + FontStretch aInherited = pSvgStyleAttributes->getFontStretch(); + + if(FontStretch_wider == maFontStretch) + { + aInherited = getWider(aInherited); + } + else if(FontStretch_narrower == maFontStretch) + { + aInherited = getNarrower(aInherited); + } + + return aInherited; + } + + // default is FontStretch_normal + return FontStretch_normal; + } + + const FontStyle SvgStyleAttributes::getFontStyle() const + { + if(maFontStyle != FontStyle_notset) + { + return maFontStyle; + } + + const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle(); + + if(pSvgStyleAttributes) + { + return pSvgStyleAttributes->getFontStyle(); + } + + // default is FontStyle_normal + return FontStyle_normal; + } + + const FontWeight SvgStyleAttributes::getFontWeight() const + { + if(maFontWeight != FontWeight_notset) + { + if(FontWeight_bolder != maFontWeight && FontWeight_lighter != maFontWeight) + { + return maFontWeight; + } + } + + const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle(); + + if(pSvgStyleAttributes) + { + FontWeight aInherited = pSvgStyleAttributes->getFontWeight(); + + if(FontWeight_bolder == maFontWeight) + { + aInherited = getBolder(aInherited); + } + else if(FontWeight_lighter == maFontWeight) + { + aInherited = getLighter(aInherited); + } + + return aInherited; + } + + // default is FontWeight_400 (FontWeight_normal) + return FontWeight_400; + } + + const TextAlign SvgStyleAttributes::getTextAlign() const + { + if(maTextAlign != TextAlign_notset) + { + return maTextAlign; + } + + const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle(); + + if(pSvgStyleAttributes) + { + return pSvgStyleAttributes->getTextAlign(); + } + + // default is TextAlign_left + return TextAlign_left; + } + + const SvgStyleAttributes* SvgStyleAttributes::getTextDecorationDefiningSvgStyleAttributes() const + { + if(maTextDecoration != TextDecoration_notset) + { + return this; + } + + const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle(); + + if(pSvgStyleAttributes) + { + return pSvgStyleAttributes->getTextDecorationDefiningSvgStyleAttributes(); + } + + // default is 0 + return 0; + } + + const TextDecoration SvgStyleAttributes::getTextDecoration() const + { + const SvgStyleAttributes* pDefining = getTextDecorationDefiningSvgStyleAttributes(); + + if(pDefining) + { + return pDefining->maTextDecoration; + } + else + { + // default is TextDecoration_none + return TextDecoration_none; + } + } + + const TextAnchor SvgStyleAttributes::getTextAnchor() const + { + if(maTextAnchor != TextAnchor_notset) + { + return maTextAnchor; + } + + const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle(); + + if(pSvgStyleAttributes) + { + return pSvgStyleAttributes->getTextAnchor(); + } + + // default is TextAnchor_start + return TextAnchor_start; + } + + const basegfx::BColor* SvgStyleAttributes::getColor() const + { + if(maColor.isSet()) + { + if(maColor.isCurrent()) + { + OSL_ENSURE(false, "Svg error: current color uses current color (!)"); + return 0; + } + else if(maColor.isOn()) + { + return &maColor.getBColor(); + } + } + else + { + const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle(); + + if(pSvgStyleAttributes) + { + return pSvgStyleAttributes->getColor(); + } + } + + return 0; + } + + const rtl::OUString SvgStyleAttributes::getMarkerStartXLink() const + { + if(maMarkerStartXLink.getLength()) + { + return maMarkerStartXLink; + } + + const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle(); + + if(pSvgStyleAttributes) + { + return pSvgStyleAttributes->getMarkerStartXLink(); + } + + return rtl::OUString(); + } + + const SvgMarkerNode* SvgStyleAttributes::accessMarkerStartXLink() const + { + if(!mpMarkerStartXLink) + { + const rtl::OUString aMarker(getMarkerStartXLink()); + + if(aMarker.getLength()) + { + const_cast< SvgStyleAttributes* >(this)->mpMarkerStartXLink = dynamic_cast< const SvgMarkerNode* >(mrOwner.getDocument().findSvgNodeById(getMarkerStartXLink())); + } + } + + return mpMarkerStartXLink; + } + + const rtl::OUString SvgStyleAttributes::getMarkerMidXLink() const + { + if(maMarkerMidXLink.getLength()) + { + return maMarkerMidXLink; + } + + const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle(); + + if(pSvgStyleAttributes) + { + return pSvgStyleAttributes->getMarkerMidXLink(); + } + + return rtl::OUString(); + } + + const SvgMarkerNode* SvgStyleAttributes::accessMarkerMidXLink() const + { + if(!mpMarkerMidXLink) + { + const rtl::OUString aMarker(getMarkerMidXLink()); + + if(aMarker.getLength()) + { + const_cast< SvgStyleAttributes* >(this)->mpMarkerMidXLink = dynamic_cast< const SvgMarkerNode* >(mrOwner.getDocument().findSvgNodeById(getMarkerMidXLink())); + } + } + + return mpMarkerMidXLink; + } + + const rtl::OUString SvgStyleAttributes::getMarkerEndXLink() const + { + if(maMarkerEndXLink.getLength()) + { + return maMarkerEndXLink; + } + + const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle(); + + if(pSvgStyleAttributes) + { + return pSvgStyleAttributes->getMarkerEndXLink(); + } + + return rtl::OUString(); + } + + const SvgMarkerNode* SvgStyleAttributes::accessMarkerEndXLink() const + { + if(!mpMarkerEndXLink) + { + const rtl::OUString aMarker(getMarkerEndXLink()); + + if(aMarker.getLength()) + { + const_cast< SvgStyleAttributes* >(this)->mpMarkerEndXLink = dynamic_cast< const SvgMarkerNode* >(mrOwner.getDocument().findSvgNodeById(getMarkerEndXLink())); + } + } + + return mpMarkerEndXLink; + } + + } // end of namespace svgreader +} // end of namespace svgio + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/svgio/source/svgreader/svgstylenode.cxx b/svgio/source/svgreader/svgstylenode.cxx new file mode 100644 index 000000000000..e670f4137a8f --- /dev/null +++ b/svgio/source/svgreader/svgstylenode.cxx @@ -0,0 +1,115 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svgio.hxx" + +#include <svgio/svgreader/svgstylenode.hxx> +#include <svgio/svgreader/svgdocument.hxx> + +////////////////////////////////////////////////////////////////////////////// + +namespace svgio +{ + namespace svgreader + { + SvgStyleNode::SvgStyleNode( + SvgDocument& rDocument, + SvgNode* pParent) + : SvgNode(SVGTokenStyle, rDocument, pParent), + maSvgStyleAttributes(), + mbTextCss(false) + { + } + + SvgStyleNode::~SvgStyleNode() + { + while(!maSvgStyleAttributes.empty()) + { + delete *(maSvgStyleAttributes.end() - 1); + maSvgStyleAttributes.pop_back(); + } + } + + void SvgStyleNode::parseAttribute(const rtl::OUString& rTokenName, SVGToken aSVGToken, const rtl::OUString& aContent) + { + // call parent + SvgNode::parseAttribute(rTokenName, aSVGToken, aContent); + + // parse own + switch(aSVGToken) + { + case SVGTokenType: + { + if(aContent.getLength()) + { + static rtl::OUString aStrTextCss(rtl::OUString::createFromAscii("text/css")); + + if(aContent.match(aStrTextCss)) + { + setTextCss(true); + } + } + break; + } + } + } + + void SvgStyleNode::addCssStyleSheet(const rtl::OUString& aContent) + { + const sal_Int32 nLen(aContent.getLength()); + + if(nLen) + { + sal_Int32 nPos(0); + rtl::OUStringBuffer aTokenValue; + + skip_char(aContent, sal_Unicode(' '), sal_Unicode('#'), nPos, nLen); + copyToLimiter(aContent, sal_Unicode('{'), nPos, aTokenValue, nLen); + const rtl::OUString aStyleName = aTokenValue.makeStringAndClear().trim(); + + if(aStyleName.getLength()) + { + skip_char(aContent, sal_Unicode(' '), sal_Unicode('{'), nPos, nLen); + copyToLimiter(aContent, sal_Unicode('}'), nPos, aTokenValue, nLen); + const rtl::OUString aStyleContent = aTokenValue.makeStringAndClear().trim(); + + if(aStyleContent.getLength()) + { + // create new style + SvgStyleAttributes* pNewStyle = new SvgStyleAttributes(*this); + maSvgStyleAttributes.push_back(pNewStyle); + + // fill with content + pNewStyle->readStyle(aStyleContent); + + // register new style at document + const_cast< SvgDocument& >(getDocument()).addSvgStyleAttributesToMapper(aStyleName, *pNewStyle); + } + } + } + } + + } // end of namespace svgreader +} // end of namespace svgio + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/svgio/source/svgreader/svgsvgnode.cxx b/svgio/source/svgreader/svgsvgnode.cxx new file mode 100644 index 000000000000..eadbe7705772 --- /dev/null +++ b/svgio/source/svgreader/svgsvgnode.cxx @@ -0,0 +1,395 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svgio.hxx" + +#include <svgio/svgreader/svgsvgnode.hxx> +#include <drawinglayer/geometry/viewinformation2d.hxx> +#include <drawinglayer/primitive2d/transformprimitive2d.hxx> +#include <drawinglayer/primitive2d/maskprimitive2d.hxx> +#include <basegfx/polygon/b2dpolygontools.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> +#include <basegfx/matrix/b2dhommatrixtools.hxx> + +////////////////////////////////////////////////////////////////////////////// + +namespace svgio +{ + namespace svgreader + { + SvgSvgNode::SvgSvgNode( + SvgDocument& rDocument, + SvgNode* pParent) + : SvgNode(SVGTokenSvg, rDocument, pParent), + maSvgStyleAttributes(*this), + mpViewBox(0), + maSvgAspectRatio(), + maX(), + maY(), + maWidth(), + maHeight(), + maVersion() + { + if(!getParent()) + { + // initial fill is black + maSvgStyleAttributes.setFill(SvgPaint(basegfx::BColor(0.0, 0.0, 0.0), true, true)); + } + } + + SvgSvgNode::~SvgSvgNode() + { + if(mpViewBox) delete mpViewBox; + } + + const SvgStyleAttributes* SvgSvgNode::getSvgStyleAttributes() const + { + return &maSvgStyleAttributes; + } + + void SvgSvgNode::parseAttribute(const rtl::OUString& rTokenName, SVGToken aSVGToken, const rtl::OUString& aContent) + { + // call parent + SvgNode::parseAttribute(rTokenName, aSVGToken, aContent); + + // read style attributes + maSvgStyleAttributes.parseStyleAttribute(rTokenName, aSVGToken, aContent); + + // parse own + switch(aSVGToken) + { + case SVGTokenStyle: + { + maSvgStyleAttributes.readStyle(aContent); + break; + } + case SVGTokenViewBox: + { + const basegfx::B2DRange aRange(readViewBox(aContent, *this)); + + if(!aRange.isEmpty()) + { + setViewBox(&aRange); + } + break; + } + case SVGTokenPreserveAspectRatio: + { + setSvgAspectRatio(readSvgAspectRatio(aContent)); + break; + } + case SVGTokenX: + { + SvgNumber aNum; + + if(readSingleNumber(aContent, aNum)) + { + setX(aNum); + } + break; + } + case SVGTokenY: + { + SvgNumber aNum; + + if(readSingleNumber(aContent, aNum)) + { + setY(aNum); + } + break; + } + case SVGTokenWidth: + { + SvgNumber aNum; + + if(readSingleNumber(aContent, aNum)) + { + if(aNum.isPositive()) + { + setWidth(aNum); + } + } + break; + } + case SVGTokenHeight: + { + SvgNumber aNum; + + if(readSingleNumber(aContent, aNum)) + { + if(aNum.isPositive()) + { + setHeight(aNum); + } + } + break; + } + case SVGTokenVersion: + { + SvgNumber aNum; + + if(readSingleNumber(aContent, aNum)) + { + setVersion(aNum); + } + break; + } + } + } + + void SvgSvgNode::decomposeSvgNode(drawinglayer::primitive2d::Primitive2DSequence& rTarget, bool bReferenced) const + { + drawinglayer::primitive2d::Primitive2DSequence aSequence; + + // decompose childs + SvgNode::decomposeSvgNode(aSequence, bReferenced); + + if(aSequence.hasElements()) + { + if(getParent()) + { + if(getViewBox()) + { + // Svg defines that with no width or no height the viewBox content is empty, + // so both need to exist + if(!basegfx::fTools::equalZero(getViewBox()->getWidth()) && !basegfx::fTools::equalZero(getViewBox()->getHeight())) + { + // create target range homing x,y, width and height as given + const double fX(getX().isSet() ? getX().solve(*this, xcoordinate) : 0.0); + const double fY(getY().isSet() ? getY().solve(*this, ycoordinate) : 0.0); + const double fW(getWidth().isSet() ? getWidth().solve(*this, xcoordinate) : getViewBox()->getWidth()); + const double fH(getHeight().isSet() ? getHeight().solve(*this, ycoordinate) : getViewBox()->getHeight()); + const basegfx::B2DRange aTarget(fX, fY, fX + fW, fY + fH); + + if(aTarget.equal(*getViewBox())) + { + // no mapping needed, append + drawinglayer::primitive2d::appendPrimitive2DSequenceToPrimitive2DSequence(rTarget, aSequence); + } + else + { + // create mapping + const SvgAspectRatio& rRatio = getSvgAspectRatio(); + + if(rRatio.isSet()) + { + // let mapping be created from SvgAspectRatio + const basegfx::B2DHomMatrix aEmbeddingTransform( + rRatio.createMapping(aTarget, *getViewBox())); + + // prepare embedding in transformation + const drawinglayer::primitive2d::Primitive2DReference xRef( + new drawinglayer::primitive2d::TransformPrimitive2D( + aEmbeddingTransform, + aSequence)); + + if(rRatio.isMeetOrSlice()) + { + // embed in transformation + drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(rTarget, xRef); + } + else + { + // need to embed in MaskPrimitive2D, too + const drawinglayer::primitive2d::Primitive2DReference xMask( + new drawinglayer::primitive2d::MaskPrimitive2D( + basegfx::B2DPolyPolygon(basegfx::tools::createPolygonFromRect(aTarget)), + drawinglayer::primitive2d::Primitive2DSequence(&xRef, 1))); + + drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(rTarget, xMask); + } + } + else + { + // choose default mapping + const basegfx::B2DHomMatrix aEmbeddingTransform( + rRatio.createLinearMapping( + aTarget, *getViewBox())); + + // embed in transformation + const drawinglayer::primitive2d::Primitive2DReference xTransform( + new drawinglayer::primitive2d::TransformPrimitive2D( + aEmbeddingTransform, + aSequence)); + + drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(rTarget, xTransform); + } + } + } + } + else + { + // check if we have a size + const double fW(getWidth().isSet() ? getWidth().solve(*this, xcoordinate) : 0.0); + const double fH(getHeight().isSet() ? getHeight().solve(*this, ycoordinate) : 0.0); + + // Svg defines that a negative value is an error and that 0.0 disables rendering + if(basegfx::fTools::more(fW, 0.0) && basegfx::fTools::more(fH, 0.0)) + { + // check if we have a x,y position + const double fX(getX().isSet() ? getX().solve(*this, xcoordinate) : 0.0); + const double fY(getY().isSet() ? getY().solve(*this, ycoordinate) : 0.0); + + if(!basegfx::fTools::equalZero(fX) || !basegfx::fTools::equalZero(fY)) + { + // embed in transform + const drawinglayer::primitive2d::Primitive2DReference xRef( + new drawinglayer::primitive2d::TransformPrimitive2D( + basegfx::tools::createTranslateB2DHomMatrix(fX, fY), + aSequence)); + + aSequence = drawinglayer::primitive2d::Primitive2DSequence(&xRef, 1); + } + + // embed in MaskPrimitive2D to clip + const drawinglayer::primitive2d::Primitive2DReference xMask( + new drawinglayer::primitive2d::MaskPrimitive2D( + basegfx::B2DPolyPolygon( + basegfx::tools::createPolygonFromRect( + basegfx::B2DRange(fX, fY, fX + fW, fY + fH))), + aSequence)); + + // append + drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(rTarget, xMask); + } + } + } + else + { + // Outermost SVG element; create target range homing width and height as given. + // SVG defines that x,y has no meanig for the outermost SVG element. Use a fallback + // width and height of din A 4 (21 x 29,7 cm) + double fW(getWidth().isSet() ? getWidth().solve(*this, xcoordinate) : (210.0 * 3.543307)); + double fH(getHeight().isSet() ? getHeight().solve(*this, ycoordinate) : (297.0 * 3.543307)); + + // Svg defines that a negative value is an error and that 0.0 disables rendering + if(basegfx::fTools::more(fW, 0.0) && basegfx::fTools::more(fH, 0.0)) + { + const basegfx::B2DRange aSvgCanvasRange(0.0, 0.0, fW, fH); + + if(getViewBox()) + { + if(!basegfx::fTools::equalZero(getViewBox()->getWidth()) && !basegfx::fTools::equalZero(getViewBox()->getHeight())) + { + // create mapping + const SvgAspectRatio& rRatio = getSvgAspectRatio(); + basegfx::B2DHomMatrix aViewBoxMapping; + + if(rRatio.isSet()) + { + // let mapping be created from SvgAspectRatio + aViewBoxMapping = rRatio.createMapping(aSvgCanvasRange, *getViewBox()); + + // no need to check ratio here for slice, the outermost Svg will + // be clipped anyways (see below) + } + else + { + // choose default mapping + aViewBoxMapping = rRatio.createLinearMapping(aSvgCanvasRange, *getViewBox()); + } + + // scale content to viewBox definitions + const drawinglayer::primitive2d::Primitive2DReference xTransform( + new drawinglayer::primitive2d::TransformPrimitive2D( + aViewBoxMapping, + aSequence)); + + aSequence = drawinglayer::primitive2d::Primitive2DSequence(&xTransform, 1); + } + } + + // to be completely correct in Svg sense it is necessary to clip + // the whole content to the given canvas. I choose here to do this + // initially despite I found various examples of Svg files out there + // which have no correct values for this clipping. It's correct + // due to the Svg spec. + bool bDoCorrectCanvasClipping(true); + + if(bDoCorrectCanvasClipping) + { + // different from Svg we have the possibility with primitives to get + // a correct bounding box for the geometry, thhus I will allow to + // only clip if necessary. This will make Svg images evtl. smaller + // than wanted from Svg (the free space which may be around it is + // conform to the Svg spec), but avoids an expensive and unneccessary + // clip. + const basegfx::B2DRange aContentRange( + drawinglayer::primitive2d::getB2DRangeFromPrimitive2DSequence( + aSequence, + drawinglayer::geometry::ViewInformation2D())); + + if(!aSvgCanvasRange.isInside(aContentRange)) + { + const drawinglayer::primitive2d::Primitive2DReference xMask( + new drawinglayer::primitive2d::MaskPrimitive2D( + basegfx::B2DPolyPolygon( + basegfx::tools::createPolygonFromRect( + aSvgCanvasRange)), + aSequence)); + + aSequence = drawinglayer::primitive2d::Primitive2DSequence(&xMask, 1); + } + } + + { + // embed in transform primitive to scale to 1/100th mm + // where 1 mm == 3.543307 px to get from Svg coordinates to + // drawinglayer ones + const double fScaleTo100thmm(100.0 / 3.543307); + const basegfx::B2DHomMatrix aTransform( + basegfx::tools::createScaleB2DHomMatrix( + fScaleTo100thmm, + fScaleTo100thmm)); + + const drawinglayer::primitive2d::Primitive2DReference xTransform( + new drawinglayer::primitive2d::TransformPrimitive2D( + aTransform, + aSequence)); + + aSequence = drawinglayer::primitive2d::Primitive2DSequence(&xTransform, 1); + } + + // append + drawinglayer::primitive2d::appendPrimitive2DSequenceToPrimitive2DSequence(rTarget, aSequence); + } + } + } + } + + const basegfx::B2DRange* SvgSvgNode::getCurrentViewPort() const + { + if(getViewBox()) + { + return getViewBox(); + } + else + { + return SvgNode::getCurrentViewPort(); + } + } + + } // end of namespace svgreader +} // end of namespace svgio + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/svgio/source/svgreader/svgsymbolnode.cxx b/svgio/source/svgreader/svgsymbolnode.cxx new file mode 100644 index 000000000000..39da059285f4 --- /dev/null +++ b/svgio/source/svgreader/svgsymbolnode.cxx @@ -0,0 +1,93 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svgio.hxx" + +#include <svgio/svgreader/svgsymbolnode.hxx> +#include <drawinglayer/geometry/viewinformation2d.hxx> +#include <drawinglayer/primitive2d/transformprimitive2d.hxx> + +////////////////////////////////////////////////////////////////////////////// + +namespace svgio +{ + namespace svgreader + { + SvgSymbolNode::SvgSymbolNode( + SvgDocument& rDocument, + SvgNode* pParent) + : SvgNode(SVGTokenSvg, rDocument, pParent), + maSvgStyleAttributes(*this), + mpViewBox(0), + maSvgAspectRatio() + { + } + + SvgSymbolNode::~SvgSymbolNode() + { + if(mpViewBox) delete mpViewBox; + } + + const SvgStyleAttributes* SvgSymbolNode::getSvgStyleAttributes() const + { + return &maSvgStyleAttributes; + } + + void SvgSymbolNode::parseAttribute(const rtl::OUString& rTokenName, SVGToken aSVGToken, const rtl::OUString& aContent) + { + // call parent + SvgNode::parseAttribute(rTokenName, aSVGToken, aContent); + + // read style attributes + maSvgStyleAttributes.parseStyleAttribute(rTokenName, aSVGToken, aContent); + + // parse own + switch(aSVGToken) + { + case SVGTokenStyle: + { + maSvgStyleAttributes.readStyle(aContent); + break; + } + case SVGTokenViewBox: + { + const basegfx::B2DRange aRange(readViewBox(aContent, *this)); + + if(!aRange.isEmpty()) + { + setViewBox(&aRange); + } + break; + } + case SVGTokenPreserveAspectRatio: + { + setSvgAspectRatio(readSvgAspectRatio(aContent)); + break; + } + } + } + + } // end of namespace svgreader +} // end of namespace svgio + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/svgio/source/svgreader/svgtextnode.cxx b/svgio/source/svgreader/svgtextnode.cxx new file mode 100644 index 000000000000..903a485016f5 --- /dev/null +++ b/svgio/source/svgreader/svgtextnode.cxx @@ -0,0 +1,273 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svgio.hxx" + +#include <svgio/svgreader/svgtextnode.hxx> +#include <svgio/svgreader/svgcharacternode.hxx> +#include <svgio/svgreader/svgstyleattributes.hxx> +#include <svgio/svgreader/svgtrefnode.hxx> +#include <svgio/svgreader/svgtextpathnode.hxx> +#include <svgio/svgreader/svgtspannode.hxx> +#include <drawinglayer/primitive2d/transformprimitive2d.hxx> +#include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx> + +////////////////////////////////////////////////////////////////////////////// + +namespace svgio +{ + namespace svgreader + { + SvgTextNode::SvgTextNode( + SvgDocument& rDocument, + SvgNode* pParent) + : SvgNode(SVGTokenText, rDocument, pParent), + maSvgStyleAttributes(*this), + mpaTransform(0), + maSvgTextPositions() + { + } + + SvgTextNode::~SvgTextNode() + { + if(mpaTransform) delete mpaTransform; + } + + const SvgStyleAttributes* SvgTextNode::getSvgStyleAttributes() const + { + static rtl::OUString aClassStr(rtl::OUString::createFromAscii("text")); + maSvgStyleAttributes.checkForCssStyle(aClassStr); + + return &maSvgStyleAttributes; + } + + void SvgTextNode::parseAttribute(const rtl::OUString& rTokenName, SVGToken aSVGToken, const rtl::OUString& aContent) + { + // call parent + SvgNode::parseAttribute(rTokenName, aSVGToken, aContent); + + // read style attributes + maSvgStyleAttributes.parseStyleAttribute(rTokenName, aSVGToken, aContent); + + // read text position attributes + maSvgTextPositions.parseTextPositionAttributes(rTokenName, aSVGToken, aContent); + + // parse own + switch(aSVGToken) + { + case SVGTokenStyle: + { + maSvgStyleAttributes.readStyle(aContent); + break; + } + case SVGTokenTransform: + { + const basegfx::B2DHomMatrix aMatrix(readTransform(aContent, *this)); + + if(!aMatrix.isIdentity()) + { + setTransform(&aMatrix); + } + break; + } + } + } + + void SvgTextNode::addTextPrimitives( + const SvgNode& rCandidate, + drawinglayer::primitive2d::Primitive2DSequence& rTarget, + drawinglayer::primitive2d::Primitive2DSequence& rSource) const + { + if(rSource.hasElements()) + { + const SvgStyleAttributes* pAttributes = rCandidate.getSvgStyleAttributes(); + + if(pAttributes) + { + // add text with taking all Fill/Stroke attributes into account + pAttributes->add_text(rTarget, rSource); + } + else + { + // should not happen, every subnode from SvgTextNode will at least + // return the attributes from SvgTextNode. Nonetheless, add text + drawinglayer::primitive2d::appendPrimitive2DSequenceToPrimitive2DSequence(rTarget, rSource); + } + } + } + + void SvgTextNode::DecomposeChild(const SvgNode& rCandidate, drawinglayer::primitive2d::Primitive2DSequence& rTarget, SvgTextPosition& rSvgTextPosition) const + { + switch(rCandidate.getType()) + { + case SVGTokenCharacter: + { + // direct SvgTextPathNode derivates, decompose them + const SvgCharacterNode& rSvgCharacterNode = static_cast< const SvgCharacterNode& >(rCandidate); + rSvgCharacterNode.decomposeText(rTarget, rSvgTextPosition); + break; + } + case SVGTokenTextPath: + { + // direct TextPath decompose + const SvgTextPathNode& rSvgTextPathNode = static_cast< const SvgTextPathNode& >(rCandidate); + const SvgNodeVector& rChildren = rSvgTextPathNode.getChildren(); + const sal_uInt32 nCount(rChildren.size()); + + if(nCount && rSvgTextPathNode.isValid()) + { + // remember original TextStart to later detect hor/ver offsets + const basegfx::B2DPoint aTextStart(rSvgTextPosition.getPosition()); + drawinglayer::primitive2d::Primitive2DSequence aNewTarget; + + // decompose to regular TextPrimitives + for(sal_uInt32 a(0); a < nCount; a++) + { + DecomposeChild(*rChildren[a], aNewTarget, rSvgTextPosition); + } + + if(aNewTarget.hasElements()) + { + const drawinglayer::primitive2d::Primitive2DSequence aPathContent(aNewTarget); + aNewTarget.realloc(0); + + // dismantle TextPrimitives and map them on curve/path + rSvgTextPathNode.decomposePathNode(aPathContent, aNewTarget, aTextStart); + } + + if(aNewTarget.hasElements()) + { + addTextPrimitives(rCandidate, rTarget, aNewTarget); + } + } + + break; + } + case SVGTokenTspan: + { + // Tspan may have children, call recursively + const SvgTspanNode& rSvgTspanNode = static_cast< const SvgTspanNode& >(rCandidate); + const SvgNodeVector& rChildren = rSvgTspanNode.getChildren(); + const sal_uInt32 nCount(rChildren.size()); + + if(nCount) + { + SvgTextPosition aSvgTextPosition(&rSvgTextPosition, rSvgTspanNode, rSvgTspanNode.getSvgTextPositions()); + drawinglayer::primitive2d::Primitive2DSequence aNewTarget; + + for(sal_uInt32 a(0); a < nCount; a++) + { + DecomposeChild(*rChildren[a], aNewTarget, aSvgTextPosition); + } + + rSvgTextPosition.setPosition(aSvgTextPosition.getPosition()); + + if(aNewTarget.hasElements()) + { + addTextPrimitives(rCandidate, rTarget, aNewTarget); + } + } + break; + } + case SVGTokenTref: + { + const SvgTrefNode& rSvgTrefNode = static_cast< const SvgTrefNode& >(rCandidate); + const SvgTextNode* pRefText = rSvgTrefNode.getReferencedSvgTextNode(); + + if(pRefText) + { + const SvgNodeVector& rChildren = pRefText->getChildren(); + const sal_uInt32 nCount(rChildren.size()); + drawinglayer::primitive2d::Primitive2DSequence aNewTarget; + + if(nCount) + { + for(sal_uInt32 a(0); a < nCount; a++) + { + const SvgNode& rChildCandidate = *rChildren[a]; + const_cast< SvgNode& >(rChildCandidate).setAlternativeParent(this); + + DecomposeChild(rChildCandidate, aNewTarget, rSvgTextPosition); + const_cast< SvgNode& >(rChildCandidate).setAlternativeParent(0); + } + + if(aNewTarget.hasElements()) + { + addTextPrimitives(rCandidate, rTarget, aNewTarget); + } + } + } + + break; + } + default: + { + OSL_ENSURE(false, "Unexpected node in text token (!)"); + break; + } + } + } + + void SvgTextNode::decomposeSvgNode(drawinglayer::primitive2d::Primitive2DSequence& rTarget, bool bReferenced) const + { + // text has a group of child nodes, allowed are SVGTokenCharacter, SVGTokenTspan, + // SVGTokenTref and SVGTokenTextPath. These increase a given current text position + const SvgStyleAttributes* pStyle = getSvgStyleAttributes(); + + if(pStyle && !getChildren().empty()) + { + const double fOpacity(pStyle->getOpacity().getNumber()); + + if(fOpacity > 0.0) + { + SvgTextPosition aSvgTextPosition(0, *this, getSvgTextPositions()); + drawinglayer::primitive2d::Primitive2DSequence aNewTarget; + const SvgNodeVector& rChildren = getChildren(); + const sal_uInt32 nCount(rChildren.size()); + + for(sal_uInt32 a(0); a < nCount; a++) + { + const SvgNode& rCandidate = *rChildren[a]; + + DecomposeChild(rCandidate, aNewTarget, aSvgTextPosition); + } + + if(aNewTarget.hasElements()) + { + drawinglayer::primitive2d::Primitive2DSequence aNewTarget2; + + addTextPrimitives(*this, aNewTarget2, aNewTarget); + aNewTarget = aNewTarget2; + } + + if(aNewTarget.hasElements()) + { + pStyle->add_postProcess(rTarget, aNewTarget, getTransform()); + } + } + } + } + } // end of namespace svgreader +} // end of namespace svgio + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/svgio/source/svgreader/svgtextpathnode.cxx b/svgio/source/svgreader/svgtextpathnode.cxx new file mode 100644 index 000000000000..b84ba940236e --- /dev/null +++ b/svgio/source/svgreader/svgtextpathnode.cxx @@ -0,0 +1,510 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svgio.hxx" + +#include <svgio/svgreader/svgtextpathnode.hxx> +#include <svgio/svgreader/svgstyleattributes.hxx> +#include <svgio/svgreader/svgpathnode.hxx> +#include <svgio/svgreader/svgdocument.hxx> +#include <svgio/svgreader/svgtrefnode.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> +#include <basegfx/polygon/b2dpolygontools.hxx> +#include <drawinglayer/primitive2d/textbreakuphelper.hxx> +#include <drawinglayer/primitive2d/groupprimitive2d.hxx> +#include <basegfx/curve/b2dcubicbezier.hxx> +#include <basegfx/curve/b2dbeziertools.hxx> + +////////////////////////////////////////////////////////////////////////////// + +namespace svgio +{ + namespace svgreader + { + class pathTextBreakupHelper : public drawinglayer::primitive2d::TextBreakupHelper + { + private: + const basegfx::B2DPolygon& mrPolygon; + const double mfBasegfxPathLength; + const double mfUserToBasegfx; + double mfPosition; + const basegfx::B2DPoint& mrTextStart; + + const sal_uInt32 mnMaxIndex; + sal_uInt32 mnIndex; + basegfx::B2DCubicBezier maCurrentSegment; + basegfx::B2DCubicBezierHelper* mpB2DCubicBezierHelper; + double mfCurrentSegmentLength; + double mfSegmentStartPosition; + + protected: + /// allow user callback to allow changes to the new TextTransformation. Default + /// does nothing. + virtual bool allowChange(sal_uInt32 nCount, basegfx::B2DHomMatrix& rNewTransform, sal_uInt32 nIndex, sal_uInt32 nLength); + + void freeB2DCubicBezierHelper(); + basegfx::B2DCubicBezierHelper* getB2DCubicBezierHelper(); + void advanceToPosition(double fNewPosition); + + public: + pathTextBreakupHelper( + const drawinglayer::primitive2d::Primitive2DReference& rxSource, + const basegfx::B2DPolygon& rPolygon, + const double fBasegfxPathLength, + const double fUserToBasegfx, + double fPosition, + const basegfx::B2DPoint& rTextStart); + virtual ~pathTextBreakupHelper(); + + // read access to evtl. advanced position + double getPosition() const { return mfPosition; } + + // get length of given text + double getLength(const rtl::OUString& rText) const; + }; + + double pathTextBreakupHelper::getLength(const rtl::OUString& rText) const + { + const sal_uInt32 nLength(rText.getLength()); + + if(nLength) + { + return getTextLayouter().getTextWidth(rText, 0, nLength); + } + + return 0.0; + } + + void pathTextBreakupHelper::freeB2DCubicBezierHelper() + { + if(mpB2DCubicBezierHelper) + { + delete mpB2DCubicBezierHelper; + mpB2DCubicBezierHelper = 0; + } + } + + basegfx::B2DCubicBezierHelper* pathTextBreakupHelper::getB2DCubicBezierHelper() + { + if(!mpB2DCubicBezierHelper && maCurrentSegment.isBezier()) + { + mpB2DCubicBezierHelper = new basegfx::B2DCubicBezierHelper(maCurrentSegment); + } + + return mpB2DCubicBezierHelper; + } + + void pathTextBreakupHelper::advanceToPosition(double fNewPosition) + { + while(mfSegmentStartPosition + mfCurrentSegmentLength < fNewPosition && mnIndex < mnMaxIndex) + { + mfSegmentStartPosition += mfCurrentSegmentLength; + mnIndex++; + + if(mnIndex < mnMaxIndex) + { + freeB2DCubicBezierHelper(); + mrPolygon.getBezierSegment(mnIndex % mrPolygon.count(), maCurrentSegment); + maCurrentSegment.testAndSolveTrivialBezier(); + mfCurrentSegmentLength = getB2DCubicBezierHelper() + ? getB2DCubicBezierHelper()->getLength() + : maCurrentSegment.getLength(); + } + } + + mfPosition = fNewPosition; + } + + pathTextBreakupHelper::pathTextBreakupHelper( + const drawinglayer::primitive2d::Primitive2DReference& rxSource, + const basegfx::B2DPolygon& rPolygon, + const double fBasegfxPathLength, + const double fUserToBasegfx, + double fPosition, + const basegfx::B2DPoint& rTextStart) + : drawinglayer::primitive2d::TextBreakupHelper(rxSource), + mrPolygon(rPolygon), + mfBasegfxPathLength(fBasegfxPathLength), + mfUserToBasegfx(fUserToBasegfx), + mfPosition(0.0), + mrTextStart(rTextStart), + mnMaxIndex(rPolygon.isClosed() ? rPolygon.count() : rPolygon.count() - 1), + mnIndex(0), + maCurrentSegment(), + mpB2DCubicBezierHelper(0), + mfCurrentSegmentLength(0.0), + mfSegmentStartPosition(0.0) + { + mrPolygon.getBezierSegment(mnIndex % mrPolygon.count(), maCurrentSegment); + mfCurrentSegmentLength = maCurrentSegment.getLength(); + + advanceToPosition(fPosition); + } + + pathTextBreakupHelper::~pathTextBreakupHelper() + { + freeB2DCubicBezierHelper(); + } + + bool pathTextBreakupHelper::allowChange(sal_uInt32 nCount, basegfx::B2DHomMatrix& rNewTransform, sal_uInt32 nIndex, sal_uInt32 nLength) + { + bool bRetval(false); + + if(mfPosition < mfBasegfxPathLength && nLength && getCastedSource() && mnIndex < mnMaxIndex) + { + const double fSnippetWidth( + getTextLayouter().getTextWidth( + getCastedSource()->getText(), + nIndex, + nLength)); + + if(basegfx::fTools::more(fSnippetWidth, 0.0)) + { + const ::rtl::OUString aText(getCastedSource()->getText()); + const ::rtl::OUString aTrimmedChars(aText.copy(nIndex, nLength).trim()); + const double fEndPos(mfPosition + fSnippetWidth); + + if(aTrimmedChars.getLength() && (mfPosition < mfBasegfxPathLength || fEndPos > 0.0)) + { + const double fHalfSnippetWidth(fSnippetWidth * 0.5); + + advanceToPosition(mfPosition + fHalfSnippetWidth); + + // create representation for this snippet + bRetval = true; + + // get target position and tangent in that pint + basegfx::B2DPoint aPosition(0.0, 0.0); + basegfx::B2DVector aTangent(0.0, 1.0); + + if(mfPosition < 0.0) + { + // snippet center is left of first segment, but right edge is on it (SVG allows that) + aTangent = maCurrentSegment.getTangent(0.0); + aTangent.normalize(); + aPosition = maCurrentSegment.getStartPoint() + (aTangent * (mfPosition - mfSegmentStartPosition)); + } + else if(mfPosition > mfBasegfxPathLength) + { + // snippet center is right of last segment, but left edge is on it (SVG allows that) + aTangent = maCurrentSegment.getTangent(1.0); + aTangent.normalize(); + aPosition = maCurrentSegment.getEndPoint() + (aTangent * (mfPosition - mfSegmentStartPosition)); + } + else + { + // snippet center inside segment, interpolate + double fBezierDistance(mfPosition - mfSegmentStartPosition); + + if(getB2DCubicBezierHelper()) + { + // use B2DCubicBezierHelper to bridge the non-linear gap between + // length and bezier distances (if it's a bezier segment) + fBezierDistance = getB2DCubicBezierHelper()->distanceToRelative(fBezierDistance); + } + else + { + // linear relationship, make relative to segment length + fBezierDistance = fBezierDistance / mfCurrentSegmentLength; + } + + aPosition = maCurrentSegment.interpolatePoint(fBezierDistance); + aTangent = maCurrentSegment.getTangent(fBezierDistance); + aTangent.normalize(); + } + + // detect evtl. hor/ver translations (depends on text direction) + const basegfx::B2DPoint aBasePoint(rNewTransform * basegfx::B2DPoint(0.0, 0.0)); + const basegfx::B2DVector aOffset(aBasePoint - mrTextStart); + + if(!basegfx::fTools::equalZero(aOffset.getY())) + { + // ...and apply + aPosition.setY(aPosition.getY() + aOffset.getY()); + } + + // move target position from snippet center to left text start + aPosition -= fHalfSnippetWidth * aTangent; + + // remove current translation + rNewTransform.translate(-aBasePoint.getX(), -aBasePoint.getY()); + + // rotate due to tangent + rNewTransform.rotate(atan2(aTangent.getY(), aTangent.getX())); + + // add new translation + rNewTransform.translate(aPosition.getX(), aPosition.getY()); + } + + // advance to end + advanceToPosition(fEndPos); + } + } + + return bRetval; + } + + } // end of namespace svgreader +} // end of namespace svgio + +////////////////////////////////////////////////////////////////////////////// + +namespace svgio +{ + namespace svgreader + { + SvgTextPathNode::SvgTextPathNode( + SvgDocument& rDocument, + SvgNode* pParent) + : SvgNode(SVGTokenTextPath, rDocument, pParent), + maSvgStyleAttributes(*this), + maXLink(), + maStartOffset(), + mbMethod(true), + mbSpacing(false) + { + } + + SvgTextPathNode::~SvgTextPathNode() + { + } + + const SvgStyleAttributes* SvgTextPathNode::getSvgStyleAttributes() const + { + return &maSvgStyleAttributes; + } + + void SvgTextPathNode::parseAttribute(const rtl::OUString& rTokenName, SVGToken aSVGToken, const rtl::OUString& aContent) + { + // call parent + SvgNode::parseAttribute(rTokenName, aSVGToken, aContent); + + // read style attributes + maSvgStyleAttributes.parseStyleAttribute(rTokenName, aSVGToken, aContent); + + // parse own + switch(aSVGToken) + { + case SVGTokenStyle: + { + maSvgStyleAttributes.readStyle(aContent); + break; + } + case SVGTokenStartOffset: + { + SvgNumber aNum; + + if(readSingleNumber(aContent, aNum)) + { + if(aNum.isPositive()) + { + setStartOffset(aNum); + } + } + break; + } + case SVGTokenMethod: + { + if(aContent.getLength()) + { + static rtl::OUString aStrAlign(rtl::OUString::createFromAscii("align")); + static rtl::OUString aStrStretch(rtl::OUString::createFromAscii("stretch")); + + if(aContent.match(aStrAlign)) + { + setMethod(true); + } + else if(aContent.match(aStrStretch)) + { + setMethod(false); + } + } + break; + } + case SVGTokenSpacing: + { + if(aContent.getLength()) + { + static rtl::OUString aStrAuto(rtl::OUString::createFromAscii("auto")); + static rtl::OUString aStrExact(rtl::OUString::createFromAscii("exact")); + + if(aContent.match(aStrAuto)) + { + setSpacing(true); + } + else if(aContent.match(aStrExact)) + { + setSpacing(false); + } + } + break; + } + case SVGTokenXlinkHref: + { + const sal_Int32 nLen(aContent.getLength()); + + if(nLen && sal_Unicode('#') == aContent[0]) + { + maXLink = aContent.copy(1); + } + break; + } + } + } + + bool SvgTextPathNode::isValid() const + { + const SvgPathNode* pSvgPathNode = dynamic_cast< const SvgPathNode* >(getDocument().findSvgNodeById(maXLink)); + + if(!pSvgPathNode) + { + return false; + } + + const basegfx::B2DPolyPolygon* pPolyPolyPath = pSvgPathNode->getPath(); + + if(!pPolyPolyPath || !pPolyPolyPath->count()) + { + return false; + } + + const basegfx::B2DPolygon aPolygon(pPolyPolyPath->getB2DPolygon(0)); + + if(!aPolygon.count()) + { + return false; + } + + const double fBasegfxPathLength(basegfx::tools::getLength(aPolygon)); + + if(basegfx::fTools::equalZero(fBasegfxPathLength)) + { + return false; + } + + return true; + } + + void SvgTextPathNode::decomposePathNode( + const drawinglayer::primitive2d::Primitive2DSequence& rPathContent, + drawinglayer::primitive2d::Primitive2DSequence& rTarget, + const basegfx::B2DPoint& rTextStart) const + { + if(rPathContent.hasElements()) + { + const SvgPathNode* pSvgPathNode = dynamic_cast< const SvgPathNode* >(getDocument().findSvgNodeById(maXLink)); + + if(pSvgPathNode) + { + const basegfx::B2DPolyPolygon* pPolyPolyPath = pSvgPathNode->getPath(); + + if(pPolyPolyPath && pPolyPolyPath->count()) + { + basegfx::B2DPolygon aPolygon(pPolyPolyPath->getB2DPolygon(0)); + + if(pSvgPathNode->getTransform()) + { + aPolygon.transform(*pSvgPathNode->getTransform()); + } + + const double fBasegfxPathLength(basegfx::tools::getLength(aPolygon)); + + if(!basegfx::fTools::equalZero(fBasegfxPathLength)) + { + double fUserToBasegfx(1.0); // multiply: user->basegfx, divide: basegfx->user + + if(pSvgPathNode->getPathLength().isSet()) + { + const double fUserLength(pSvgPathNode->getPathLength().solve(*this, length)); + + if(fUserLength > 0.0 && !basegfx::fTools::equal(fUserLength, fBasegfxPathLength)) + { + fUserToBasegfx = fUserLength / fBasegfxPathLength; + } + } + + double fPosition(0.0); + + if(getStartOffset().isSet()) + { + if(Unit_percent == getStartOffset().getUnit()) + { + // percent are relative to path length + fPosition = getStartOffset().getNumber() * 0.01 * fBasegfxPathLength; + } + else + { + fPosition = getStartOffset().solve(*this, length) * fUserToBasegfx; + } + } + + if(fPosition >= 0.0) + { + const sal_Int32 nLength(rPathContent.getLength()); + sal_Int32 nCurrent(0); + + while(fPosition < fBasegfxPathLength && nCurrent < nLength) + { + const drawinglayer::primitive2d::TextSimplePortionPrimitive2D* pCandidate = 0; + const drawinglayer::primitive2d::Primitive2DReference xReference(rPathContent[nCurrent]); + + if(xReference.is()) + { + pCandidate = dynamic_cast< const drawinglayer::primitive2d::TextSimplePortionPrimitive2D* >(xReference.get()); + } + + if(pCandidate) + { + pathTextBreakupHelper aPathTextBreakupHelper( + xReference, + aPolygon, + fBasegfxPathLength, + fUserToBasegfx, + fPosition, + rTextStart); + + const drawinglayer::primitive2d::Primitive2DSequence aResult( + aPathTextBreakupHelper.getResult(drawinglayer::primitive2d::BreakupUnit_character)); + + if(aResult.hasElements()) + { + drawinglayer::primitive2d::appendPrimitive2DSequenceToPrimitive2DSequence(rTarget, aResult); + } + + // advance position to consumed + fPosition = aPathTextBreakupHelper.getPosition(); + } + + nCurrent++; + } + } + } + } + } + } + } + + } // end of namespace svgreader +} // end of namespace svgio + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/svgio/source/svgreader/svgtoken.cxx b/svgio/source/svgreader/svgtoken.cxx new file mode 100644 index 000000000000..5e16ec1829b2 --- /dev/null +++ b/svgio/source/svgreader/svgtoken.cxx @@ -0,0 +1,321 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svgio.hxx" + +#include <svgio/svgreader/svgtoken.hxx> + +////////////////////////////////////////////////////////////////////////////// + +namespace svgio +{ + namespace svgreader + { + static rtl::OUString aSVGStrWidth(rtl::OUString::createFromAscii("width")); + static rtl::OUString aSVGStrHeight(rtl::OUString::createFromAscii("height")); + static rtl::OUString aSVGStrViewBox(rtl::OUString::createFromAscii("viewBox")); + static rtl::OUString aSVGStrTransform(rtl::OUString::createFromAscii("transform")); + static rtl::OUString aSVGStrStyle(rtl::OUString::createFromAscii("style")); + static rtl::OUString aSVGStrD(rtl::OUString::createFromAscii("d")); + static rtl::OUString aSVGStrX(rtl::OUString::createFromAscii("x")); + static rtl::OUString aSVGStrY(rtl::OUString::createFromAscii("y")); + static rtl::OUString aSVGStrXmlns(rtl::OUString::createFromAscii("xmlns")); + static rtl::OUString aSVGStrVersion(rtl::OUString::createFromAscii("version")); + static rtl::OUString aSVGStrId(rtl::OUString::createFromAscii("id")); + static rtl::OUString aSVGStrRx(rtl::OUString::createFromAscii("rx")); + static rtl::OUString aSVGStrRy(rtl::OUString::createFromAscii("ry")); + static rtl::OUString aSVGStrPoints(rtl::OUString::createFromAscii("points")); + static rtl::OUString aSVGStrDx(rtl::OUString::createFromAscii("dx")); + static rtl::OUString aSVGStrDy(rtl::OUString::createFromAscii("dy")); + static rtl::OUString aSVGStrRotate(rtl::OUString::createFromAscii("rotate")); + static rtl::OUString aSVGStrTextLength(rtl::OUString::createFromAscii("textLength")); + static rtl::OUString aSVGStrLengthAdjust(rtl::OUString::createFromAscii("lengthAdjust")); + static rtl::OUString aSVGStrFont(rtl::OUString::createFromAscii("font")); + static rtl::OUString aSVGStrFontFamily(rtl::OUString::createFromAscii("font-family")); + static rtl::OUString aSVGStrFontSize(rtl::OUString::createFromAscii("font-size")); + static rtl::OUString aSVGStrFontSizeAdjust(rtl::OUString::createFromAscii("font-size-adjust")); + static rtl::OUString aSVGStrFontStretch(rtl::OUString::createFromAscii("font-stretch")); + static rtl::OUString aSVGStrFontStyle(rtl::OUString::createFromAscii("font-style")); + static rtl::OUString aSVGStrFontVariant(rtl::OUString::createFromAscii("font-variant")); + static rtl::OUString aSVGStrFontWeight(rtl::OUString::createFromAscii("font-weight")); + static rtl::OUString aSVGStrDirection(rtl::OUString::createFromAscii("direction")); + static rtl::OUString aSVGStrLetterSpacing(rtl::OUString::createFromAscii("letter-spacing")); + static rtl::OUString aSVGStrTextDecoration(rtl::OUString::createFromAscii("text-decoration")); + static rtl::OUString aSVGStrUnicodeBidi(rtl::OUString::createFromAscii("unicode-bidi")); + static rtl::OUString aSVGStrWordSpacing(rtl::OUString::createFromAscii("word-spacing")); + static rtl::OUString aSVGStrTspan(rtl::OUString::createFromAscii("tspan")); + static rtl::OUString aSVGStrTref(rtl::OUString::createFromAscii("tref")); + static rtl::OUString aSVGStrTextPath(rtl::OUString::createFromAscii("textPath")); + static rtl::OUString aSVGStrStartOffset(rtl::OUString::createFromAscii("startOffset")); + static rtl::OUString aSVGStrMethod(rtl::OUString::createFromAscii("method")); + static rtl::OUString aSVGStrSpacing(rtl::OUString::createFromAscii("spacing")); + static rtl::OUString aSVGStrTextAlign(rtl::OUString::createFromAscii("text-align")); + static rtl::OUString aSVGStrPathLength(rtl::OUString::createFromAscii("pathLength")); + static rtl::OUString aSVGStrType(rtl::OUString::createFromAscii("type")); + static rtl::OUString aSVGStrClass(rtl::OUString::createFromAscii("class")); + static rtl::OUString aSVGStrTextAnchor(rtl::OUString::createFromAscii("text-anchor")); + static rtl::OUString aSVGStrXmlSpace(rtl::OUString::createFromAscii("xml:space")); + static rtl::OUString aSVGStrColor(rtl::OUString::createFromAscii("color")); + static rtl::OUString aSVGStrClipPathNode(rtl::OUString::createFromAscii("clipPath")); + static rtl::OUString aSVGStrClipPathProperty(rtl::OUString::createFromAscii("clip-path")); + static rtl::OUString aSVGStrMask(rtl::OUString::createFromAscii("mask")); + static rtl::OUString aSVGStrClipPathUnits(rtl::OUString::createFromAscii("clipPathUnits")); + static rtl::OUString aSVGStrMaskUnits(rtl::OUString::createFromAscii("maskUnits")); + static rtl::OUString aSVGStrMaskContentUnits(rtl::OUString::createFromAscii("maskContentUnits")); + static rtl::OUString aSVGStrClipRule(rtl::OUString::createFromAscii("clip-rule")); + static rtl::OUString aSVGStrMarker(rtl::OUString::createFromAscii("marker")); + static rtl::OUString aSVGStrMarkerStart(rtl::OUString::createFromAscii("marker-start")); + static rtl::OUString aSVGStrMarkerMid(rtl::OUString::createFromAscii("marker-mid")); + static rtl::OUString aSVGStrMarkerEnd(rtl::OUString::createFromAscii("marker-end")); + static rtl::OUString aSVGStrRefX(rtl::OUString::createFromAscii("refX")); + static rtl::OUString aSVGStrRefY(rtl::OUString::createFromAscii("refY")); + static rtl::OUString aSVGStrMarkerUnits(rtl::OUString::createFromAscii("markerUnits")); + static rtl::OUString aSVGStrMarkerWidth(rtl::OUString::createFromAscii("markerWidth")); + static rtl::OUString aSVGStrMarkerHeight(rtl::OUString::createFromAscii("markerHeight")); + static rtl::OUString aSVGStrOrient(rtl::OUString::createFromAscii("orient")); + static rtl::OUString aSVGStrPattern(rtl::OUString::createFromAscii("pattern")); + static rtl::OUString aSVGStrPatternUnits(rtl::OUString::createFromAscii("patternUnits")); + static rtl::OUString aSVGStrPatternContentUnits(rtl::OUString::createFromAscii("patternContentUnits")); + static rtl::OUString aSVGStrPatternTransform(rtl::OUString::createFromAscii("patternTransform")); + static rtl::OUString aSVGStrOpacity(rtl::OUString::createFromAscii("opacity")); + + static rtl::OUString aSVGStrPreserveAspectRatio(rtl::OUString::createFromAscii("preserveAspectRatio")); + static rtl::OUString aSVGStrDefer(rtl::OUString::createFromAscii("defer")); + static rtl::OUString aSVGStrNone(rtl::OUString::createFromAscii("none")); + static rtl::OUString aSVGStrXMinYMin(rtl::OUString::createFromAscii("xMinYMin")); + static rtl::OUString aSVGStrXMidYMin(rtl::OUString::createFromAscii("xMidYMin")); + static rtl::OUString aSVGStrXMaxYMin(rtl::OUString::createFromAscii("xMaxYMin")); + static rtl::OUString aSVGStrXMinYMid(rtl::OUString::createFromAscii("xMinYMid")); + static rtl::OUString aSVGStrXMidYMid(rtl::OUString::createFromAscii("xMidYMid")); + static rtl::OUString aSVGStrXMaxYMid(rtl::OUString::createFromAscii("xMaxYMid")); + static rtl::OUString aSVGStrXMinYMax(rtl::OUString::createFromAscii("xMinYMax")); + static rtl::OUString aSVGStrXMidYMax(rtl::OUString::createFromAscii("xMidYMax")); + static rtl::OUString aSVGStrXMaxYMax(rtl::OUString::createFromAscii("xMaxYMax")); + static rtl::OUString aSVGStrMeet(rtl::OUString::createFromAscii("meet")); + static rtl::OUString aSVGStrSlice(rtl::OUString::createFromAscii("slice")); + + static rtl::OUString aSVGStrDefs(rtl::OUString::createFromAscii("defs")); + static rtl::OUString aSVGStrG(rtl::OUString::createFromAscii("g")); + static rtl::OUString aSVGStrSvg(rtl::OUString::createFromAscii("svg")); + static rtl::OUString aSVGStrSymbol(rtl::OUString::createFromAscii("symbol")); + static rtl::OUString aSVGStrUse(rtl::OUString::createFromAscii("use")); + + static rtl::OUString aSVGStrCircle(rtl::OUString::createFromAscii("circle")); + static rtl::OUString aSVGStrEllipse(rtl::OUString::createFromAscii("ellipse")); + static rtl::OUString aSVGStrLine(rtl::OUString::createFromAscii("line")); + static rtl::OUString aSVGStrPath(rtl::OUString::createFromAscii("path")); + static rtl::OUString aSVGStrPolygon(rtl::OUString::createFromAscii("polygon")); + static rtl::OUString aSVGStrPolyline(rtl::OUString::createFromAscii("polyline")); + static rtl::OUString aSVGStrRect(rtl::OUString::createFromAscii("rect")); + static rtl::OUString aSVGStrImage(rtl::OUString::createFromAscii("image")); + + static rtl::OUString aSVGStrLinearGradient(rtl::OUString::createFromAscii("linearGradient")); + static rtl::OUString aSVGStrRadialGradient(rtl::OUString::createFromAscii("radialGradient")); + static rtl::OUString aSVGStrStop(rtl::OUString::createFromAscii("stop")); + static rtl::OUString aSVGStrOffset(rtl::OUString::createFromAscii("offset")); + static rtl::OUString aSVGStrX1(rtl::OUString::createFromAscii("x1")); + static rtl::OUString aSVGStrY1(rtl::OUString::createFromAscii("y1")); + static rtl::OUString aSVGStrX2(rtl::OUString::createFromAscii("x2")); + static rtl::OUString aSVGStrY2(rtl::OUString::createFromAscii("y2")); + static rtl::OUString aSVGStrCx(rtl::OUString::createFromAscii("cx")); + static rtl::OUString aSVGStrCy(rtl::OUString::createFromAscii("cy")); + static rtl::OUString aSVGStrFx(rtl::OUString::createFromAscii("fx")); + static rtl::OUString aSVGStrFy(rtl::OUString::createFromAscii("fy")); + static rtl::OUString aSVGStrR(rtl::OUString::createFromAscii("r")); + static rtl::OUString aSVGStrGradientUnits(rtl::OUString::createFromAscii("gradientUnits")); + static rtl::OUString aSVGStrGradientTransform(rtl::OUString::createFromAscii("gradientTransform")); + static rtl::OUString aSVGStrSpreadMethod(rtl::OUString::createFromAscii("spreadMethod")); + static rtl::OUString aSVGStrXlinkHref(rtl::OUString::createFromAscii("xlink:href")); + static rtl::OUString aSVGStrStopColor(rtl::OUString::createFromAscii("stop-color")); + static rtl::OUString aSVGStrStopOpacity(rtl::OUString::createFromAscii("stop-opacity")); + + static rtl::OUString aSVGStrFill(rtl::OUString::createFromAscii("fill")); + static rtl::OUString aSVGStrFillOpacity(rtl::OUString::createFromAscii("fill-opacity")); + static rtl::OUString aSVGStrFillRule(rtl::OUString::createFromAscii("fill-rule")); + + static rtl::OUString aSVGStrStroke(rtl::OUString::createFromAscii("stroke")); + static rtl::OUString aSVGStrStrokeDasharray(rtl::OUString::createFromAscii("stroke-dasharray")); + static rtl::OUString aSVGStrStrokeDashoffset(rtl::OUString::createFromAscii("stroke-dashoffset")); + static rtl::OUString aSVGStrStrokeLinecap(rtl::OUString::createFromAscii("stroke-linecap")); + static rtl::OUString aSVGStrStrokeLinejoin(rtl::OUString::createFromAscii("stroke-linejoin")); + static rtl::OUString aSVGStrStrokeMiterlimit(rtl::OUString::createFromAscii("stroke-miterlimit")); + static rtl::OUString aSVGStrStrokeOpacity(rtl::OUString::createFromAscii("stroke-opacity")); + static rtl::OUString aSVGStrStrokeWidth(rtl::OUString::createFromAscii("stroke-width")); + + static rtl::OUString aSVGStrText(rtl::OUString::createFromAscii("text")); + + SVGToken StrToSVGToken(const rtl::OUString& rStr) + { + typedef std::hash_map< rtl::OUString, SVGToken, rtl::OUStringHash > SVGTokenMapper; + typedef std::pair< rtl::OUString, SVGToken > SVGTokenValueType; + static SVGTokenMapper aSVGTokenMapperList; + + if(aSVGTokenMapperList.empty()) + { + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrWidth, SVGTokenWidth)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrHeight, SVGTokenHeight)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrViewBox, SVGTokenViewBox)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrTransform, SVGTokenTransform)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrStyle, SVGTokenStyle)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrD, SVGTokenD)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrX, SVGTokenX)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrY, SVGTokenY)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrXmlns, SVGTokenXmlns)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrVersion, SVGTokenVersion)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrId, SVGTokenId)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrRx, SVGTokenRx)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrRy, SVGTokenRy)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrPoints, SVGTokenPoints)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrDx, SVGTokenDx)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrDy, SVGTokenDy)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrRotate, SVGTokenRotate)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrFont, SVGTokenFont)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrFontFamily, SVGTokenFontFamily)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrFontSize, SVGTokenFontSize)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrFontSizeAdjust, SVGTokenFontSizeAdjust)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrFontStretch, SVGTokenFontStretch)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrFontStyle, SVGTokenFontStyle)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrFontVariant, SVGTokenFontVariant)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrFontWeight, SVGTokenFontWeight)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrDirection, SVGTokenDirection)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrLetterSpacing, SVGTokenLetterSpacing)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrTextDecoration, SVGTokenTextDecoration)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrUnicodeBidi, SVGTokenUnicodeBidi)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrWordSpacing, SVGTokenWordSpacing)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrTspan, SVGTokenTspan)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrTref, SVGTokenTref)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrTextPath, SVGTokenTextPath)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrStartOffset, SVGTokenStartOffset)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrMethod, SVGTokenMethod)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrSpacing, SVGTokenSpacing)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrTextAlign, SVGTokenTextAlign)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrPathLength, SVGTokenPathLength)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrType, SVGTokenType)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrClass, SVGTokenClass)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrTextAnchor, SVGTokenTextAnchor)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrXmlSpace, SVGTokenXmlSpace)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrColor, SVGTokenColor)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrClipPathNode, SVGTokenClipPathNode)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrClipPathProperty, SVGTokenClipPathProperty)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrMask, SVGTokenMask)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrClipPathUnits, SVGTokenClipPathUnits)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrMaskUnits, SVGTokenMaskUnits)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrMaskContentUnits, SVGTokenMaskContentUnits)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrClipRule, SVGTokenClipRule)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrMarker, SVGTokenMarker)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrMarkerStart, SVGTokenMarkerStart)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrMarkerMid, SVGTokenMarkerMid)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrMarkerEnd, SVGTokenMarkerEnd)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrRefX, SVGTokenRefX)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrRefY, SVGTokenRefY)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrMarkerUnits, SVGTokenMarkerUnits)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrMarkerWidth, SVGTokenMarkerWidth)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrMarkerHeight, SVGTokenMarkerHeight)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrOrient, SVGTokenOrient)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrPattern, SVGTokenPattern)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrPatternUnits, SVGTokenPatternUnits)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrPatternContentUnits, SVGTokenPatternContentUnits)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrPatternTransform, SVGTokenPatternTransform)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrOpacity, SVGTokenOpacity)); + + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrPreserveAspectRatio, SVGTokenPreserveAspectRatio)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrDefer, SVGTokenDefer)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrNone, SVGTokenNone)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrXMinYMin, SVGTokenXMinYMin)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrXMidYMin, SVGTokenXMidYMin)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrXMaxYMin, SVGTokenXMaxYMin)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrXMinYMid, SVGTokenXMinYMid)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrXMidYMid, SVGTokenXMidYMid)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrXMaxYMid, SVGTokenXMaxYMid)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrXMinYMax, SVGTokenXMinYMax)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrXMidYMax, SVGTokenXMidYMax)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrXMaxYMax, SVGTokenXMaxYMax)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrMeet, SVGTokenMeet)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrSlice, SVGTokenSlice)); + + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrDefs, SVGTokenDefs)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrG, SVGTokenG)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrSvg, SVGTokenSvg)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrSymbol, SVGTokenSymbol)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrUse, SVGTokenUse)); + + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrCircle, SVGTokenCircle)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrEllipse, SVGTokenEllipse)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrLine, SVGTokenLine)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrPath, SVGTokenPath)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrPolygon, SVGTokenPolygon)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrPolyline, SVGTokenPolyline)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrRect, SVGTokenRect)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrImage, SVGTokenImage)); + + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrLinearGradient, SVGTokenLinearGradient)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrRadialGradient, SVGTokenRadialGradient)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrStop, SVGTokenStop)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrOffset, SVGTokenOffset)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrX1, SVGTokenX1)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrY1, SVGTokenY1)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrX2, SVGTokenX2)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrY2, SVGTokenY2)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrCx, SVGTokenCx)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrCy, SVGTokenCy)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrFx, SVGTokenFx)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrFy, SVGTokenFy)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrR, SVGTokenR)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrGradientUnits, SVGTokenGradientUnits)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrGradientTransform, SVGTokenGradientTransform)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrSpreadMethod, SVGTokenSpreadMethod)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrXlinkHref, SVGTokenXlinkHref)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrStopColor, SVGTokenStopColor)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrStopOpacity, SVGTokenStopOpacity)); + + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrFill, SVGTokenFill)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrFillOpacity, SVGTokenFillOpacity)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrFillRule, SVGTokenFillRule)); + + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrStroke, SVGTokenStroke)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrStrokeDasharray, SVGTokenStrokeDasharray)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrStrokeDashoffset, SVGTokenStrokeDashoffset)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrStrokeLinecap, SVGTokenStrokeLinecap)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrStrokeLinejoin, SVGTokenStrokeLinejoin)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrStrokeMiterlimit, SVGTokenStrokeMiterlimit)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrStrokeOpacity, SVGTokenStrokeOpacity)); + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrStrokeWidth, SVGTokenStrokeWidth)); + + aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrText, SVGTokenText)); + } + + const SVGTokenMapper::const_iterator aResult(aSVGTokenMapperList.find(rStr)); + + if(aResult == aSVGTokenMapperList.end()) + { + return SVGTokenUnknown; + } + else + { + return aResult->second; + } + } + } // end of namespace svgreader +} // end of namespace svgio + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/svgio/source/svgreader/svgtools.cxx b/svgio/source/svgreader/svgtools.cxx new file mode 100644 index 000000000000..597decfdee08 --- /dev/null +++ b/svgio/source/svgreader/svgtools.cxx @@ -0,0 +1,1581 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svgio.hxx" + +#include <svgio/svgreader/svgtools.hxx> +#include <osl/thread.h> +#include <tools/color.hxx> +#include <basegfx/matrix/b2dhommatrix.hxx> +#include <basegfx/matrix/b2dhommatrixtools.hxx> +#include <svgio/svgreader/svgtoken.hxx> +#include <hash_map> + +////////////////////////////////////////////////////////////////////////////// + +namespace svgio +{ + namespace svgreader + { +#ifdef DBG_UTIL + void myAssert(const rtl::OUString& rMessage) + { + rtl::OString aMessage2; + + rMessage.convertToString(&aMessage2, osl_getThreadTextEncoding(), RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR|RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR); + OSL_ENSURE(false, aMessage2.getStr()); + } +#endif + + // common non-token strings + const rtl::OUString commonStrings::aStrUserSpaceOnUse(rtl::OUString::createFromAscii("userSpaceOnUse")); + const rtl::OUString commonStrings::aStrObjectBoundingBox(rtl::OUString::createFromAscii("objectBoundingBox")); + const rtl::OUString commonStrings::aStrNonzero(rtl::OUString::createFromAscii("nonzero")); + const rtl::OUString commonStrings::aStrEvenOdd(rtl::OUString::createFromAscii("evenodd")); + + basegfx::B2DHomMatrix SvgAspectRatio::createLinearMapping(const basegfx::B2DRange& rTarget, const basegfx::B2DRange& rSource) + { + basegfx::B2DHomMatrix aRetval; + const double fSWidth(rSource.getWidth()); + const double fSHeight(rSource.getHeight()); + const bool bNoSWidth(basegfx::fTools::equalZero(fSWidth)); + const bool bNoSHeight(basegfx::fTools::equalZero(fSHeight)); + + // transform from source state to unit range + aRetval.translate(-rSource.getMinX(), -rSource.getMinY()); + aRetval.scale( + (bNoSWidth ? 1.0 : 1.0 / fSWidth) * rTarget.getWidth(), + (bNoSHeight ? 1.0 : 1.0 / fSHeight) * rTarget.getHeight()); + + // transform from unit rage to target range + aRetval.translate(rTarget.getMinX(), rTarget.getMinY()); + + return aRetval; + } + + basegfx::B2DHomMatrix SvgAspectRatio::createMapping(const basegfx::B2DRange& rTarget, const basegfx::B2DRange& rSource) const + { + if(!isSet() || Align_none == getSvgAlign()) + { + // create linear mapping (default) + return createLinearMapping(rTarget, rSource); + } + + basegfx::B2DHomMatrix aRetval; + + const double fSWidth(rSource.getWidth()); + const double fSHeight(rSource.getHeight()); + const bool bNoSWidth(basegfx::fTools::equalZero(fSWidth)); + const bool bNoSHeight(basegfx::fTools::equalZero(fSHeight)); + const double fScaleX((bNoSWidth ? 1.0 : 1.0 / fSWidth) * rTarget.getWidth()); + const double fScaleY((bNoSHeight ? 1.0 : 1.0 / fSHeight) * rTarget.getHeight()); + const double fScale(isMeetOrSlice() ? std::min(fScaleX, fScaleY) : std::max(fScaleX, fScaleY)); + + // remove source translation, apply scale + aRetval.translate(-rSource.getMinX(), -rSource.getMinY()); + aRetval.scale(fScale, fScale); + + // evaluate horizontal alignment + const double fNewWidth(fSWidth * fScale); + double fTransX(0.0); + + switch(getSvgAlign()) + { + case Align_xMidYMin: + case Align_xMidYMid: + case Align_xMidYMax: + { + // centerX + const double fFreeSpace(rTarget.getWidth() - fNewWidth); + fTransX = fFreeSpace * 0.5; + break; + } + case Align_xMaxYMin: + case Align_xMaxYMid: + case Align_xMaxYMax: + { + // Right align + const double fFreeSpace(rTarget.getWidth() - fNewWidth); + fTransX = fFreeSpace; + break; + } + } + + // evaluate vertical alignment + const double fNewHeight(fSHeight * fScale); + double fTransY(0.0); + + switch(getSvgAlign()) + { + case Align_xMinYMid: + case Align_xMidYMid: + case Align_xMaxYMid: + { + // centerY + const double fFreeSpace(rTarget.getHeight() - fNewHeight); + fTransY = fFreeSpace * 0.5; + break; + } + case Align_xMinYMax: + case Align_xMidYMax: + case Align_xMaxYMax: + { + // Bottom align + const double fFreeSpace(rTarget.getHeight() - fNewHeight); + fTransY = fFreeSpace; + break; + } + } + + // add target translation + aRetval.translate( + rTarget.getMinX() + fTransX, + rTarget.getMinY() + fTransY); + + return aRetval; + } + + double SvgNumber::solve(const InfoProvider& rInfoProvider, NumberType aNumberType) const + { + if(isSet()) + { + switch(meUnit) + { + case Unit_em: + { + return mfNumber * rInfoProvider.getCurrentFontSize(); + break; + } + case Unit_ex: + { + return mfNumber * rInfoProvider.getCurrentXHeight() * 0.5; + break; + } + case Unit_px: + { + return mfNumber; + break; + } + case Unit_pt: + case Unit_pc: + case Unit_cm: + case Unit_mm: + case Unit_in: + { + double fRetval(mfNumber); + + switch(meUnit) + { + case Unit_pt: fRetval *= 1.25; break; + case Unit_pc: fRetval *= 15.0; break; + case Unit_cm: fRetval *= 35.43307; break; + case Unit_mm: fRetval *= 3.543307; break; + case Unit_in: fRetval *= 90.0; break; + } + + return fRetval; + break; + } + case Unit_percent: + { + double fRetval(mfNumber * 0.01); + const basegfx::B2DRange* pViewPort = rInfoProvider.getCurrentViewPort(); + + if(!pViewPort) + { + // no viewPort, assume a normal page size (A4) + static basegfx::B2DRange aDinA4Range( + 0.0, + 0.0, + 210.0 * 3.543307, + 297.0 * 3.543307); + + pViewPort = &aDinA4Range; + } + + if(pViewPort) + { + if(xcoordinate == aNumberType) + { + // it's a x-coordinate, relative to current width (w) + fRetval *= pViewPort->getWidth(); + } + else if(ycoordinate == aNumberType) + { + // it's a y-coordinate, relative to current height (h) + fRetval *= pViewPort->getHeight(); + } + else // length + { + // it's a length, relative to sqrt(w*w + h*h)/sqrt(2) + const double fCurrentWidth(pViewPort->getWidth()); + const double fCurrentHeight(pViewPort->getHeight()); + const double fCurrentLength( + sqrt(fCurrentWidth * fCurrentWidth + fCurrentHeight * fCurrentHeight)/sqrt(2.0)); + + fRetval *= fCurrentLength; + } + } + + return fRetval; + break; + } + } + } + + /// not set + OSL_ENSURE(false, "SvgNumber not set (!)"); + return 0.0; + } + + bool SvgNumber::isPositive() const + { + return basegfx::fTools::moreOrEqual(mfNumber, 0.0); + } + + void skip_char(const rtl::OUString& rCandidate, const sal_Unicode& rChar, sal_Int32& nPos, const sal_Int32 nLen) + { + while(nPos < nLen && rChar == rCandidate[nPos]) + { + nPos++; + } + } + + void skip_char(const rtl::OUString& rCandidate, const sal_Unicode& rCharA, const sal_Unicode& rCharB, sal_Int32& nPos, const sal_Int32 nLen) + { + while(nPos < nLen && (rCharA == rCandidate[nPos] || rCharB == rCandidate[nPos])) + { + nPos++; + } + } + + void copySign(const rtl::OUString& rCandidate, sal_Int32& nPos, rtl::OUStringBuffer& rTarget, const sal_Int32 nLen) + { + if(nPos < nLen) + { + const sal_Unicode aChar(rCandidate[nPos]); + + if(sal_Unicode('+') == aChar || sal_Unicode('-') == aChar) + { + rTarget.append(aChar); + nPos++; + } + } + } + + void copyNumber(const rtl::OUString& rCandidate, sal_Int32& nPos, rtl::OUStringBuffer& rTarget, const sal_Int32 nLen) + { + bool bOnNumber(true); + + while(bOnNumber && nPos < nLen) + { + const sal_Unicode aChar(rCandidate[nPos]); + + bOnNumber = (sal_Unicode('0') <= aChar && sal_Unicode('9') >= aChar) || sal_Unicode('.') == aChar; + + if(bOnNumber) + { + rTarget.append(aChar); + nPos++; + } + } + } + + void copyHex(const rtl::OUString& rCandidate, sal_Int32& nPos, rtl::OUStringBuffer& rTarget, const sal_Int32 nLen) + { + bool bOnHex(true); + + while(bOnHex && nPos < nLen) + { + const sal_Unicode aChar(rCandidate[nPos]); + + bOnHex = (sal_Unicode('0') <= aChar && sal_Unicode('9') >= aChar) + || (sal_Unicode('A') <= aChar && sal_Unicode('F') >= aChar) + || (sal_Unicode('a') <= aChar && sal_Unicode('f') >= aChar); + + if(bOnHex) + { + rTarget.append(aChar); + nPos++; + } + } + } + + void copyString(const rtl::OUString& rCandidate, sal_Int32& nPos, rtl::OUStringBuffer& rTarget, const sal_Int32 nLen) + { + bool bOnChar(true); + + while(bOnChar && nPos < nLen) + { + const sal_Unicode aChar(rCandidate[nPos]); + + bOnChar = (sal_Unicode('a') <= aChar && sal_Unicode('z') >= aChar) + || (sal_Unicode('A') <= aChar && sal_Unicode('Z') >= aChar) + || sal_Unicode('-') == aChar; + + if(bOnChar) + { + rTarget.append(aChar); + nPos++; + } + } + } + + void copyToLimiter(const rtl::OUString& rCandidate, const sal_Unicode& rLimiter, sal_Int32& nPos, rtl::OUStringBuffer& rTarget, const sal_Int32 nLen) + { + while(nPos < nLen && rLimiter != rCandidate[nPos]) + { + rTarget.append(rCandidate[nPos]); + nPos++; + } + } + + bool readNumber(const rtl::OUString& rCandidate, sal_Int32& nPos, double& fNum, const sal_Int32 nLen) + { + if(nPos < nLen) + { + rtl::OUStringBuffer aNum; + + copySign(rCandidate, nPos, aNum, nLen); + copyNumber(rCandidate, nPos, aNum, nLen); + + if(nPos < nLen) + { + const sal_Unicode aChar(rCandidate[nPos]); + + if(sal_Unicode('e') == aChar || sal_Unicode('E') == aChar) + { + // try to read exponential number, but be careful. I had + // a case where dx="2em" was used, thus the 'e' was consumed + // by error. First try if there are numbers after the 'e', + // safe current state + nPos++; + const rtl::OUStringBuffer aNum2(aNum); + const sal_Int32 nPosAfterE(nPos); + + aNum.append(aChar); + copySign(rCandidate, nPos, aNum, nLen); + copyNumber(rCandidate, nPos, aNum, nLen); + + if(nPosAfterE == nPos) + { + // no number after 'e', go back. Do not + // return false, it's still a valid integer number + aNum = aNum2; + nPos--; + } + } + } + + if(aNum.getLength()) + { + rtl_math_ConversionStatus eStatus; + + fNum = rtl::math::stringToDouble( + aNum.makeStringAndClear(), (sal_Unicode)('.'), (sal_Unicode)(','), + &eStatus, 0); + + return eStatus == rtl_math_ConversionStatus_Ok; + } + } + + return false; + } + + SvgUnit readUnit(const rtl::OUString& rCandidate, sal_Int32& nPos, const sal_Int32 nLen) + { + SvgUnit aRetval(Unit_px); + + if(nPos < nLen) + { + const sal_Unicode aCharA(rCandidate[nPos]); + + if(nPos + 1 < nLen) + { + const sal_Unicode aCharB(rCandidate[nPos + 1]); + bool bTwoCharValid(false); + + switch(aCharA) + { + case sal_Unicode('e') : + { + if(sal_Unicode('m') == aCharB) + { + // 'em' Relative to current font size + aRetval = Unit_em; + bTwoCharValid = true; + } + else if(sal_Unicode('x') == aCharB) + { + // 'ex' Relative to current font x-height + aRetval = Unit_ex; + bTwoCharValid = true; + } + break; + } + case sal_Unicode('p') : + { + if(sal_Unicode('x') == aCharB) + { + // 'px' UserUnit (default) + bTwoCharValid = true; + } + else if(sal_Unicode('t') == aCharB) + { + // 'pt' == 1.25 px + aRetval = Unit_pt; + bTwoCharValid = true; + } + else if(sal_Unicode('c') == aCharB) + { + // 'pc' == 15 px + aRetval = Unit_pc; + bTwoCharValid = true; + } + break; + } + case sal_Unicode('i') : + { + if(sal_Unicode('n') == aCharB) + { + // 'in' == 90 px + aRetval = Unit_in; + bTwoCharValid = true; + } + break; + } + case sal_Unicode('c') : + { + if(sal_Unicode('m') == aCharB) + { + // 'cm' == 35.43307 px + aRetval = Unit_cm; + bTwoCharValid = true; + } + break; + } + case sal_Unicode('m') : + { + if(sal_Unicode('m') == aCharB) + { + // 'mm' == 3.543307 px + aRetval = Unit_mm; + bTwoCharValid = true; + } + break; + } + } + + if(bTwoCharValid) + { + nPos += 2; + } + } + else + { + if(sal_Unicode('%') == aCharA) + { + // percent used, relative to current + nPos++; + aRetval = Unit_percent; + } + } + } + + return aRetval; + } + + bool readNumberAndUnit(const rtl::OUString& rCandidate, sal_Int32& nPos, SvgNumber& aNum, const sal_Int32 nLen) + { + double fNum(0.0); + + if(readNumber(rCandidate, nPos, fNum, nLen)) + { + skip_char(rCandidate, sal_Unicode(' '), nPos, nLen); + aNum = SvgNumber(fNum, readUnit(rCandidate, nPos, nLen)); + + return true; + } + + return false; + } + + bool readAngle(const rtl::OUString& rCandidate, sal_Int32& nPos, double& fAngle, const sal_Int32 nLen) + { + if(readNumber(rCandidate, nPos, fAngle, nLen)) + { + skip_char(rCandidate, sal_Unicode(' '), nPos, nLen); + + enum DegreeType + { + deg, + grad, + rad + } aType(deg); // degrees is default + + if(nPos < nLen) + { + const sal_Unicode aChar(rCandidate[nPos]); + static rtl::OUString aStrGrad(rtl::OUString::createFromAscii("grad")); + static rtl::OUString aStrRad(rtl::OUString::createFromAscii("rad")); + + switch(aChar) + { + case sal_Unicode('g') : + case sal_Unicode('G') : + { + if(rCandidate.matchIgnoreAsciiCase(aStrGrad, nPos)) + { + // angle in grad + nPos += aStrGrad.getLength(); + } + break; + } + case sal_Unicode('r') : + case sal_Unicode('R') : + { + if(rCandidate.matchIgnoreAsciiCase(aStrRad, nPos)) + { + // angle in radians + nPos += aStrRad.getLength(); + } + break; + } + } + } + + // convert to radians + if(deg == aType) + { + fAngle *= F_PI / 180.0; + } + else if(grad == aType) + { + // looks like 100 grad is 90 degrees + fAngle *= F_PI / 200.0; + } + + return true; + } + + return false; + } + + sal_Int32 read_hex(const sal_Unicode& rChar) + { + if(rChar >= sal_Unicode('0') && rChar <=sal_Unicode('9')) + { + return sal_Int32(rChar - sal_Unicode('0')); + } + else if(rChar >= sal_Unicode('A') && rChar <=sal_Unicode('F')) + { + return 10 + sal_Int32(rChar - sal_Unicode('A')); + } + else if(rChar >= sal_Unicode('a') && rChar <=sal_Unicode('f')) + { + return 10 + sal_Int32(rChar - sal_Unicode('a')); + } + else + { + // error + return 0; + } + } + + bool match_colorKeyword(basegfx::BColor& rColor, const rtl::OUString& rName) + { + typedef std::hash_map< rtl::OUString, Color, rtl::OUStringHash > ColorTokenMapper; + typedef std::pair< rtl::OUString, Color > ColorTokenValueType; + ColorTokenMapper aColorTokenMapperList; + + if(aColorTokenMapperList.empty()) + { + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("aliceblue"), Color(240, 248, 255))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("antiquewhite"), Color(250, 235, 215))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("aqua"), Color( 0, 255, 255))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("aquamarine"), Color(127, 255, 212))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("azure"), Color(240, 255, 255))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("beige"), Color(245, 245, 220))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("bisque"), Color(255, 228, 196))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("black"), Color( 0, 0, 0))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("blanchedalmond"), Color(255, 235, 205))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("blue"), Color( 0, 0, 255))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("blueviolet"), Color(138, 43, 226))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("brown"), Color(165, 42, 42))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("burlywood"), Color(222, 184, 135))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("cadetblue"), Color( 95, 158, 160))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("chartreuse"), Color(127, 255, 0))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("chocolate"), Color(210, 105, 30))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("coral"), Color(255, 127, 80))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("cornflowerblue"), Color(100, 149, 237))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("cornsilk"), Color(255, 248, 220))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("crimson"), Color(220, 20, 60))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("cyan"), Color( 0, 255, 255))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("darkblue"), Color( 0, 0, 139))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("darkcyan"), Color( 0, 139, 139))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("darkgoldenrod"), Color(184, 134, 11))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("darkgray"), Color(169, 169, 169))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("darkgreen"), Color( 0, 100, 0))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("darkgrey"), Color(169, 169, 169))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("darkkhaki"), Color(189, 183, 107))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("darkmagenta"), Color(139, 0, 139))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("darkolivegreen"), Color( 85, 107, 47))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("darkorange"), Color(255, 140, 0))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("darkorchid"), Color(153, 50, 204))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("darkred"), Color(139, 0, 0))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("darksalmon"), Color(233, 150, 122))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("darkseagreen"), Color(143, 188, 143))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("darkslateblue"), Color( 72, 61, 139))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("darkslategray"), Color( 47, 79, 79))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("darkslategrey"), Color( 47, 79, 79))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("darkturquoise"), Color( 0, 206, 209))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("darkviolet"), Color(148, 0, 211))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("deeppink"), Color(255, 20, 147))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("deepskyblue"), Color( 0, 191, 255))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("dimgray"), Color(105, 105, 105))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("dimgrey"), Color(105, 105, 105))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("dodgerblue"), Color( 30, 144, 255))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("firebrick"), Color(178, 34, 34))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("floralwhite"), Color(255, 250, 240))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("forestgreen"), Color( 34, 139, 34))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("fuchsia"), Color(255, 0, 255))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("gainsboro"), Color(220, 220, 220))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("ghostwhite"), Color(248, 248, 255))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("gold"), Color(255, 215, 0))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("goldenrod"), Color(218, 165, 32))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("gray"), Color(128, 128, 128))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("grey"), Color(128, 128, 128))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("green"), Color(0, 128, 0))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("greenyellow"), Color(173, 255, 47))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("honeydew"), Color(240, 255, 240))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("hotpink"), Color(255, 105, 180))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("indianred"), Color(205, 92, 92))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("indigo"), Color( 75, 0, 130))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("ivory"), Color(255, 255, 240))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("khaki"), Color(240, 230, 140))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("lavender"), Color(230, 230, 250))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("lavenderblush"), Color(255, 240, 245))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("lawngreen"), Color(124, 252, 0))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("lemonchiffon"), Color(255, 250, 205))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("lightblue"), Color(173, 216, 230))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("lightcoral"), Color(240, 128, 128))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("lightcyan"), Color(224, 255, 255))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("lightgoldenrodyellow"), Color(250, 250, 210))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("lightgray"), Color(211, 211, 211))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("lightgreen"), Color(144, 238, 144))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("lightgrey"), Color(211, 211, 211))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("lightpink"), Color(255, 182, 193))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("lightsalmon"), Color(255, 160, 122))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("lightseagreen"), Color( 32, 178, 170))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("lightskyblue"), Color(135, 206, 250))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("lightslategray"), Color(119, 136, 153))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("lightslategrey"), Color(119, 136, 153))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("lightsteelblue"), Color(176, 196, 222))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("lightyellow"), Color(255, 255, 224))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("lime"), Color( 0, 255, 0))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("limegreen"), Color( 50, 205, 50))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("linen"), Color(250, 240, 230))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("magenta"), Color(255, 0, 255))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("maroon"), Color(128, 0, 0))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("mediumaquamarine"), Color(102, 205, 170))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("mediumblue"), Color( 0, 0, 205))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("mediumorchid"), Color(186, 85, 211))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("mediumpurple"), Color(147, 112, 219))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("mediumseagreen"), Color( 60, 179, 113))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("mediumslateblue"), Color(123, 104, 238))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("mediumspringgreen"), Color( 0, 250, 154))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("mediumturquoise"), Color( 72, 209, 204))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("mediumvioletred"), Color(199, 21, 133))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("midnightblue"), Color( 25, 25, 112))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("mintcream"), Color(245, 255, 250))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("mistyrose"), Color(255, 228, 225))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("moccasin"), Color(255, 228, 181))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("navajowhite"), Color(255, 222, 173))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("navy"), Color( 0, 0, 128))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("oldlace"), Color(253, 245, 230))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("olive"), Color(128, 128, 0))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("olivedrab"), Color(107, 142, 35))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("orange"), Color(255, 165, 0))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("orangered"), Color(255, 69, 0))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("orchid"), Color(218, 112, 214))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("palegoldenrod"), Color(238, 232, 170))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("palegreen"), Color(152, 251, 152))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("paleturquoise"), Color(175, 238, 238))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("palevioletred"), Color(219, 112, 147))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("papayawhip"), Color(255, 239, 213))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("peachpuff"), Color(255, 218, 185))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("peru"), Color(205, 133, 63))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("pink"), Color(255, 192, 203))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("plum"), Color(221, 160, 221))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("powderblue"), Color(176, 224, 230))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("purple"), Color(128, 0, 128))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("red"), Color(255, 0, 0))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("rosybrown"), Color(188, 143, 143))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("royalblue"), Color( 65, 105, 225))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("saddlebrown"), Color(139, 69, 19))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("salmon"), Color(250, 128, 114))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("sandybrown"), Color(244, 164, 96))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("seagreen"), Color( 46, 139, 87))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("seashell"), Color(255, 245, 238))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("sienna"), Color(160, 82, 45))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("silver"), Color(192, 192, 192))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("skyblue"), Color(135, 206, 235))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("slateblue"), Color(106, 90, 205))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("slategray"), Color(112, 128, 144))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("slategrey"), Color(112, 128, 144))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("snow"), Color(255, 250, 250))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("springgreen"), Color( 0, 255, 127))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("steelblue"), Color( 70, 130, 180))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("tan"), Color(210, 180, 140))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("teal"), Color( 0, 128, 128))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("thistle"), Color(216, 191, 216))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("tomato"), Color(255, 99, 71))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("turquoise"), Color( 64, 224, 208))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("violet"), Color(238, 130, 238))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("wheat"), Color(245, 222, 179))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("white"), Color(255, 255, 255))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("whitesmoke"), Color(245, 245, 245))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("yellow"), Color(255, 255, 0))); + aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("yellowgreen"), Color(154, 205, 50))); + } + + const ColorTokenMapper::const_iterator aResult(aColorTokenMapperList.find(rName)); + + if(aResult == aColorTokenMapperList.end()) + { + return false; + } + else + { + rColor = aResult->second.getBColor(); + return true; + } + } + + bool read_color(const rtl::OUString& rCandidate, basegfx::BColor& rColor) + { + const sal_Int32 nLen(rCandidate.getLength()); + + if(nLen) + { + const sal_Unicode aChar(rCandidate[0]); + const double fFactor(1.0 / 255.0); + + if(aChar == sal_Unicode('#')) + { + // hex definition + rtl::OUStringBuffer aNum; + sal_Int32 nPos(1); + + copyHex(rCandidate, nPos, aNum, nLen); + const sal_Int32 nLength(aNum.getLength()); + + if(3 == nLength) + { + const sal_Int32 nR(read_hex(aNum.charAt(0))); + const sal_Int32 nG(read_hex(aNum.charAt(1))); + const sal_Int32 nB(read_hex(aNum.charAt(2))); + + rColor.setRed((nR | (nR << 4)) * fFactor); + rColor.setGreen((nG | (nG << 4)) * fFactor); + rColor.setBlue((nB | (nB << 4)) * fFactor); + + return true; + } + else if(6 == nLength) + { + const sal_Int32 nR1(read_hex(aNum.charAt(0))); + const sal_Int32 nR2(read_hex(aNum.charAt(1))); + const sal_Int32 nG1(read_hex(aNum.charAt(2))); + const sal_Int32 nG2(read_hex(aNum.charAt(3))); + const sal_Int32 nB1(read_hex(aNum.charAt(4))); + const sal_Int32 nB2(read_hex(aNum.charAt(5))); + + rColor.setRed((nR2 | (nR1 << 4)) * fFactor); + rColor.setGreen((nG2 | (nG1 << 4)) * fFactor); + rColor.setBlue((nB2 | (nB1 << 4)) * fFactor); + + return true; + } + } + else + { + static rtl::OUString aStrRgb(rtl::OUString::createFromAscii("rgb")); + + if(rCandidate.matchIgnoreAsciiCase(aStrRgb, 0)) + { + // rgb definition + sal_Int32 nPos(aStrRgb.getLength()); + skip_char(rCandidate, sal_Unicode(' '), sal_Unicode('('), nPos, nLen); + double fR(0.0); + + if(readNumber(rCandidate, nPos, fR, nLen)) + { + skip_char(rCandidate, sal_Unicode(' '), nPos, nLen); + + if(nPos < nLen) + { + const sal_Unicode aChar(rCandidate[nPos]); + const bool bIsPercent(sal_Unicode('%') == aChar); + double fG(0.0); + + if(bIsPercent) + { + skip_char(rCandidate, sal_Unicode('%'), nPos, nLen); + } + + skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen); + + if(readNumber(rCandidate, nPos, fG, nLen)) + { + double fB(0.0); + + if(bIsPercent) + { + skip_char(rCandidate, sal_Unicode('%'), nPos, nLen); + } + + skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen); + + if(readNumber(rCandidate, nPos, fB, nLen)) + { + const double fFac(bIsPercent ? 0.01 : fFactor); + + rColor.setRed(fR * fFac); + rColor.setGreen(fG * fFac); + rColor.setBlue(fB * fFac); + + if(bIsPercent) + { + skip_char(rCandidate, sal_Unicode('%'), nPos, nLen); + } + + skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(')'), nPos, nLen); + return true; + } + } + } + } + } + else + { + // color keyword + if(match_colorKeyword(rColor, rCandidate)) + { + return true; + } + } + } + } + + return false; + } + + basegfx::B2DRange readViewBox(const rtl::OUString& rCandidate, InfoProvider& rInfoProvider) + { + const sal_Int32 nLen(rCandidate.getLength()); + + if(nLen) + { + sal_Int32 nPos(0); + SvgNumber aMinX; + skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen); + + if(readNumberAndUnit(rCandidate, nPos, aMinX, nLen)) + { + SvgNumber aMinY; + skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen); + + if(readNumberAndUnit(rCandidate, nPos, aMinY, nLen)) + { + SvgNumber aWidth; + skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen); + + if(readNumberAndUnit(rCandidate, nPos, aWidth, nLen)) + { + SvgNumber aHeight; + skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen); + + if(readNumberAndUnit(rCandidate, nPos, aHeight, nLen)) + { + return basegfx::B2DRange( + aMinX.solve(rInfoProvider, xcoordinate), + aMinY.solve(rInfoProvider, ycoordinate), + aWidth.solve(rInfoProvider, xcoordinate), + aHeight.solve(rInfoProvider, ycoordinate)); + } + } + } + } + } + + return basegfx::B2DRange(); + } + + basegfx::B2DHomMatrix readTransform(const rtl::OUString& rCandidate, InfoProvider& rInfoProvider) + { + basegfx::B2DHomMatrix aMatrix; + const sal_Int32 nLen(rCandidate.getLength()); + + if(nLen) + { + sal_Int32 nPos(0); + skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen); + + while(nPos < nLen) + { + const sal_Unicode aChar(rCandidate[nPos]); + const sal_Int32 nInitPos(nPos); + static rtl::OUString aStrMatrix(rtl::OUString::createFromAscii("matrix")); + static rtl::OUString aStrTranslate(rtl::OUString::createFromAscii("translate")); + static rtl::OUString aStrScale(rtl::OUString::createFromAscii("scale")); + static rtl::OUString aStrRotate(rtl::OUString::createFromAscii("rotate")); + static rtl::OUString aStrSkewX(rtl::OUString::createFromAscii("skewX")); + static rtl::OUString aStrSkewY(rtl::OUString::createFromAscii("skewY")); + + switch(aChar) + { + case sal_Unicode('m') : + { + if(rCandidate.match(aStrMatrix, nPos)) + { + // matrix element + nPos += aStrMatrix.getLength(); + skip_char(rCandidate, sal_Unicode(' '), sal_Unicode('('), nPos, nLen); + SvgNumber aVal; + basegfx::B2DHomMatrix aNew; + + if(readNumberAndUnit(rCandidate, nPos, aVal, nLen)) + { + aNew.set(0, 0, aVal.solve(rInfoProvider)); // Element A + skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen); + + if(readNumberAndUnit(rCandidate, nPos, aVal, nLen)) + { + aNew.set(1, 0, aVal.solve(rInfoProvider)); // Element B + skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen); + + if(readNumberAndUnit(rCandidate, nPos, aVal, nLen)) + { + aNew.set(0, 1, aVal.solve(rInfoProvider)); // Element C + skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen); + + if(readNumberAndUnit(rCandidate, nPos, aVal, nLen)) + { + aNew.set(1, 1, aVal.solve(rInfoProvider)); // Element D + skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen); + + if(readNumberAndUnit(rCandidate, nPos, aVal, nLen)) + { + aNew.set(0, 2, aVal.solve(rInfoProvider, xcoordinate)); // Element E + skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen); + + if(readNumberAndUnit(rCandidate, nPos, aVal, nLen)) + { + aNew.set(1, 2, aVal.solve(rInfoProvider, ycoordinate)); // Element F + skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(')'), nPos, nLen); + skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen); + + // caution: String is evaluated from left to right, but matrix multiplication + // in SVG is right to left, so put the new transformation before the current + // one by multiplicating from the right side + aMatrix = aMatrix * aNew; + } + } + } + } + } + } + } + break; + } + case sal_Unicode('t') : + { + if(rCandidate.match(aStrTranslate, nPos)) + { + // translate element + nPos += aStrTranslate.getLength(); + skip_char(rCandidate, sal_Unicode(' '), sal_Unicode('('), nPos, nLen); + SvgNumber aTransX; + + if(readNumberAndUnit(rCandidate, nPos, aTransX, nLen)) + { + skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen); + SvgNumber aTransY; + readNumberAndUnit(rCandidate, nPos, aTransY, nLen); + skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(')'), nPos, nLen); + skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen); + + aMatrix = aMatrix * basegfx::tools::createTranslateB2DHomMatrix( + aTransX.solve(rInfoProvider, xcoordinate), + aTransY.solve(rInfoProvider, ycoordinate)); + } + } + break; + } + case sal_Unicode('s') : + { + if(rCandidate.match(aStrScale, nPos)) + { + // scale element + nPos += aStrScale.getLength(); + skip_char(rCandidate, sal_Unicode(' '), sal_Unicode('('), nPos, nLen); + SvgNumber aScaleX; + + if(readNumberAndUnit(rCandidate, nPos, aScaleX, nLen)) + { + skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen); + SvgNumber aScaleY(aScaleX); + readNumberAndUnit(rCandidate, nPos, aScaleY, nLen); + skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(')'), nPos, nLen); + skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen); + + aMatrix = aMatrix * basegfx::tools::createScaleB2DHomMatrix( + aScaleX.solve(rInfoProvider), + aScaleY.solve(rInfoProvider)); + } + } + else if(rCandidate.match(aStrSkewX, nPos)) + { + // skewx element + nPos += aStrSkewX.getLength(); + skip_char(rCandidate, sal_Unicode(' '), sal_Unicode('('), nPos, nLen); + double fSkewX(0.0); + + if(readAngle(rCandidate, nPos, fSkewX, nLen)) + { + skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(')'), nPos, nLen); + skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen); + + aMatrix = aMatrix * basegfx::tools::createShearXB2DHomMatrix(tan(fSkewX)); + } + } + else if(rCandidate.match(aStrSkewY, nPos)) + { + // skewy element + nPos += aStrSkewY.getLength(); + skip_char(rCandidate, sal_Unicode(' '), sal_Unicode('('), nPos, nLen); + double fSkewY(0.0); + + if(readAngle(rCandidate, nPos, fSkewY, nLen)) + { + skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(')'), nPos, nLen); + skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen); + + aMatrix = aMatrix * basegfx::tools::createShearYB2DHomMatrix(tan(fSkewY)); + } + } + break; + } + case sal_Unicode('r') : + { + if(rCandidate.match(aStrRotate, nPos)) + { + // rotate element + nPos += aStrRotate.getLength(); + skip_char(rCandidate, sal_Unicode(' '), sal_Unicode('('), nPos, nLen); + double fAngle(0.0); + + if(readAngle(rCandidate, nPos, fAngle, nLen)) + { + skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen); + SvgNumber aX; + readNumberAndUnit(rCandidate, nPos, aX, nLen); + skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen); + SvgNumber aY; + readNumberAndUnit(rCandidate, nPos, aY, nLen); + skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(')'), nPos, nLen); + skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen); + + const double fX(aX.isSet() ? aX.solve(rInfoProvider, xcoordinate) : 0.0); + const double fY(aY.isSet() ? aY.solve(rInfoProvider, ycoordinate) : 0.0); + + if(!basegfx::fTools::equalZero(fX) || !basegfx::fTools::equalZero(fY)) + { + // rotate around point + aMatrix = aMatrix * basegfx::tools::createRotateAroundPoint(fX, fY, fAngle); + } + else + { + // rotate + aMatrix = aMatrix * basegfx::tools::createRotateB2DHomMatrix(fAngle); + } + } + } + break; + } + } + + if(nInitPos == nPos) + { + OSL_ENSURE(false, "Could not interpret on current position (!)"); + nPos++; + } + } + } + + return aMatrix; + } + + bool readSingleNumber(const rtl::OUString& rCandidate, SvgNumber& aNum) + { + const sal_Int32 nLen(rCandidate.getLength()); + sal_Int32 nPos(0); + + return readNumberAndUnit(rCandidate, nPos, aNum, nLen); + } + + bool readLocalUrl(const rtl::OUString& rCandidate, rtl::OUString& rURL) + { + static rtl::OUString aStrUrl(rtl::OUString::createFromAscii("url")); + + if(rCandidate.match(aStrUrl, 0)) + { + const sal_Int32 nLen(rCandidate.getLength()); + sal_Int32 nPos(aStrUrl.getLength()); + + skip_char(rCandidate, sal_Unicode('('), sal_Unicode('#'), nPos, nLen); + rtl::OUStringBuffer aTokenValue; + copyToLimiter(rCandidate, sal_Unicode(')'), nPos, aTokenValue, nLen); + rURL = aTokenValue.makeStringAndClear(); + + return true; + } + + return false; + } + + bool readSvgPaint(const rtl::OUString& rCandidate, SvgPaint& rSvgPaint, rtl::OUString& rURL) + { + const sal_Int32 nLen(rCandidate.getLength()); + + if(nLen) + { + basegfx::BColor aColor; + + if(read_color(rCandidate, aColor)) + { + rSvgPaint = SvgPaint(aColor, true, true); + return true; + } + else + { + static rtl::OUString aStrNone(rtl::OUString::createFromAscii("none")); + static rtl::OUString aStrCurrentColor(rtl::OUString::createFromAscii("currentColor")); + + if(rCandidate.match(aStrNone, 0)) + { + rSvgPaint = SvgPaint(aColor, true, false, false); + return true; + } + else if(readLocalUrl(rCandidate, rURL)) + { + /// Url is copied to rURL, but needs to be solved outside this helper + return false; + } + else if(rCandidate.match(aStrCurrentColor, 0)) + { + rSvgPaint = SvgPaint(aColor, true, true, true); + return true; + } + } + } + + return false; + } + + bool readSvgNumberVector(const rtl::OUString& rCandidate, SvgNumberVector& rSvgNumberVector) + { + const sal_Int32 nLen(rCandidate.getLength()); + rSvgNumberVector.clear(); + + if(nLen) + { + sal_Int32 nPos(0); + SvgNumber aNum; + skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen); + + while(readNumberAndUnit(rCandidate, nPos, aNum, nLen)) + { + rSvgNumberVector.push_back(aNum); + skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen); + } + + return !rSvgNumberVector.empty(); + } + + return false; + } + + SvgAspectRatio readSvgAspectRatio(const rtl::OUString& rCandidate) + { + const sal_Int32 nLen(rCandidate.getLength()); + + if(nLen) + { + sal_Int32 nPos(0); + SvgAlign aSvgAlign(Align_xMidYMid); + bool bDefer(false); + bool bMeetOrSlice(true); + bool bChanged(false); + + while(nPos < nLen) + { + const sal_Int32 nInitPos(nPos); + skip_char(rCandidate, sal_Unicode(' '), nPos, nLen); + rtl::OUStringBuffer aTokenName; + copyString(rCandidate, nPos, aTokenName, nLen); + + if(aTokenName.getLength()) + { + switch(StrToSVGToken(aTokenName.makeStringAndClear())) + { + case SVGTokenDefer: + { + bDefer = true; + bChanged = true; + break; + } + case SVGTokenNone: + { + aSvgAlign = Align_none; + bChanged = true; + break; + } + case SVGTokenXMinYMin: + { + aSvgAlign = Align_xMinYMin; + bChanged = true; + break; + } + case SVGTokenXMidYMin: + { + aSvgAlign = Align_xMidYMin; + bChanged = true; + break; + } + case SVGTokenXMaxYMin: + { + aSvgAlign = Align_xMaxYMin; + bChanged = true; + break; + } + case SVGTokenXMinYMid: + { + aSvgAlign = Align_xMinYMid; + bChanged = true; + break; + } + case SVGTokenXMidYMid: + { + aSvgAlign = Align_xMidYMid; + bChanged = true; + break; + } + case SVGTokenXMaxYMid: + { + aSvgAlign = Align_xMaxYMid; + bChanged = true; + break; + } + case SVGTokenXMinYMax: + { + aSvgAlign = Align_xMinYMax; + bChanged = true; + break; + } + case SVGTokenXMidYMax: + { + aSvgAlign = Align_xMidYMax; + bChanged = true; + break; + } + case SVGTokenXMaxYMax: + { + aSvgAlign = Align_xMaxYMax; + bChanged = true; + break; + } + case SVGTokenMeet: + { + bMeetOrSlice = true; + bChanged = true; + break; + } + case SVGTokenSlice: + { + bMeetOrSlice = false; + bChanged = true; + break; + } + } + } + + if(nInitPos == nPos) + { + OSL_ENSURE(false, "Could not interpret on current position (!)"); + nPos++; + } + } + + if(bChanged) + { + return SvgAspectRatio(aSvgAlign, bDefer, bMeetOrSlice); + } + } + + return SvgAspectRatio(); + } + + bool readSvgStringVector(const rtl::OUString& rCandidate, SvgStringVector& rSvgStringVector) + { + rSvgStringVector.clear(); + const sal_Int32 nLen(rCandidate.getLength()); + + if(nLen) + { + sal_Int32 nPos(0); + rtl::OUStringBuffer aTokenValue; + skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen); + + while(nPos < nLen) + { + copyToLimiter(rCandidate, sal_Unicode(','), nPos, aTokenValue, nLen); + skip_char(rCandidate, sal_Unicode(','), sal_Unicode(' '), nPos, nLen); + const rtl::OUString aString = aTokenValue.makeStringAndClear(); + + if(aString.getLength()) + { + rSvgStringVector.push_back(aString); + } + } + } + + return !rSvgStringVector.empty(); + } + + void readImageLink(const rtl::OUString& rCandidate, rtl::OUString& rXLink, rtl::OUString& rUrl, rtl::OUString& rMimeType, rtl::OUString& rData) + { + rXLink = rUrl = rMimeType = rData = rtl::OUString(); + + if(sal_Unicode('#') == rCandidate[0]) + { + // local link + rXLink = rCandidate.copy(1); + } + else + { + static rtl::OUString aStrData(rtl::OUString::createFromAscii("data:")); + + if(rCandidate.match(aStrData, 0)) + { + // embedded data + sal_Int32 nPos(aStrData.getLength()); + sal_Int32 nLen(rCandidate.getLength()); + rtl::OUStringBuffer aBuffer; + + // read mime type + skip_char(rCandidate, sal_Unicode(' '), nPos, nLen); + copyToLimiter(rCandidate, sal_Unicode(';'), nPos, aBuffer, nLen); + skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(';'), nPos, nLen); + rMimeType = aBuffer.makeStringAndClear(); + + if(rMimeType.getLength() && nPos < nLen) + { + static rtl::OUString aStrImage(rtl::OUString::createFromAscii("image")); + + if(rMimeType.match(aStrImage, 0)) + { + // image data + rtl::OUString aData(rCandidate.copy(nPos)); + static rtl::OUString aStrBase64(rtl::OUString::createFromAscii("base64")); + + if(aData.match(aStrBase64, 0)) + { + // base64 encoded + nPos = aStrBase64.getLength(); + nLen = aData.getLength(); + + skip_char(aData, sal_Unicode(' '), sal_Unicode(','), nPos, nLen); + + if(nPos < nLen) + { + rData = aData.copy(nPos); + } + } + } + } + } + else + { + // Url (path and filename) + rUrl = rCandidate; + } + } + } + + rtl::OUString convert(const rtl::OUString& rCandidate, const sal_Unicode& rPattern, const sal_Unicode& rNew, bool bRemove) + { + const sal_Int32 nLen(rCandidate.getLength()); + + if(nLen) + { + sal_Int32 nPos(0); + rtl::OUStringBuffer aBuffer; + bool bChanged(false); + + while(nPos < nLen) + { + const sal_Unicode aChar(rCandidate[nPos]); + + if(rPattern == aChar) + { + bChanged = true; + + if(!bRemove) + { + aBuffer.append(rNew); + } + } + else + { + aBuffer.append(aChar); + } + + nPos++; + } + + if(bChanged) + { + return aBuffer.makeStringAndClear(); + } + } + + return rCandidate; + } + + rtl::OUString consolidateContiguosSpace(const rtl::OUString& rCandidate) + { + const sal_Int32 nLen(rCandidate.getLength()); + + if(nLen) + { + sal_Int32 nPos(0); + rtl::OUStringBuffer aBuffer; + bool bInsideSpace(false); + const sal_Unicode aSpace(' '); + + while(nPos < nLen) + { + const sal_Unicode aChar(rCandidate[nPos]); + + if(aSpace == aChar) + { + bInsideSpace = true; + } + else + { + if(bInsideSpace) + { + bInsideSpace = false; + aBuffer.append(aSpace); + } + + aBuffer.append(aChar); + } + + nPos++; + } + + if(bInsideSpace) + { + aBuffer.append(aSpace); + } + + if(aBuffer.getLength() != nLen) + { + return aBuffer.makeStringAndClear(); + } + } + + return rCandidate; + } + + rtl::OUString whiteSpaceHandlingDefault(const rtl::OUString& rCandidate) + { + const sal_Unicode aNewline('\n'); + const sal_Unicode aTab('\t'); + const sal_Unicode aSpace(' '); + + // remove all newline characters + rtl::OUString aRetval(convert(rCandidate, aNewline, aNewline, true)); + + // convert tab to space + aRetval = convert(aRetval, aTab, aSpace, false); + + // strip of all leading and trailing spaces + aRetval = aRetval.trim(); + + // consolidate contiguos space + aRetval = consolidateContiguosSpace(aRetval); + + return aRetval; + } + + rtl::OUString whiteSpaceHandlingPreserve(const rtl::OUString& rCandidate) + { + const sal_Unicode aNewline('\n'); + const sal_Unicode aTab('\t'); + const sal_Unicode aSpace(' '); + + // convert newline to space + rtl::OUString aRetval(convert(rCandidate, aNewline, aSpace, false)); + + // convert tab to space + aRetval = convert(rCandidate, aTab, aSpace, false); + + return rCandidate; + } + + ::std::vector< double > solveSvgNumberVector(const SvgNumberVector& rInput, const InfoProvider& rInfoProvider, NumberType aNumberType) + { + ::std::vector< double > aRetval; + + if(!rInput.empty()) + { + const double nCount(rInput.size()); + aRetval.reserve(nCount); + + for(sal_uInt32 a(0); a < nCount; a++) + { + aRetval.push_back(rInput[a].solve(rInfoProvider, aNumberType)); + } + } + + return aRetval; + } + + } // end of namespace svgreader +} // end of namespace svgio + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/svgio/source/svgreader/svgtrefnode.cxx b/svgio/source/svgreader/svgtrefnode.cxx new file mode 100644 index 000000000000..fb0d04143e8f --- /dev/null +++ b/svgio/source/svgreader/svgtrefnode.cxx @@ -0,0 +1,90 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svgio.hxx" + +#include <svgio/svgreader/svgtrefnode.hxx> +#include <svgio/svgreader/svgdocument.hxx> + +////////////////////////////////////////////////////////////////////////////// + +namespace svgio +{ + namespace svgreader + { + SvgTrefNode::SvgTrefNode( + SvgDocument& rDocument, + SvgNode* pParent) + : SvgNode(SVGTokenTref, rDocument, pParent), + maSvgStyleAttributes(*this), + maXLink() + { + } + + SvgTrefNode::~SvgTrefNode() + { + } + + const SvgStyleAttributes* SvgTrefNode::getSvgStyleAttributes() const + { + return &maSvgStyleAttributes; + } + + void SvgTrefNode::parseAttribute(const rtl::OUString& rTokenName, SVGToken aSVGToken, const rtl::OUString& aContent) + { + // call parent + SvgNode::parseAttribute(rTokenName, aSVGToken, aContent); + + // read style attributes + maSvgStyleAttributes.parseStyleAttribute(rTokenName, aSVGToken, aContent); + + // parse own + switch(aSVGToken) + { + case SVGTokenStyle: + { + maSvgStyleAttributes.readStyle(aContent); + break; + } + case SVGTokenXlinkHref: + { + const sal_Int32 nLen(aContent.getLength()); + + if(nLen && sal_Unicode('#') == aContent[0]) + { + maXLink = aContent.copy(1); + } + break; + } + } + } + + const SvgTextNode* SvgTrefNode::getReferencedSvgTextNode() const + { + return dynamic_cast< const SvgTextNode* >(getDocument().findSvgNodeById(maXLink)); + } + + } // end of namespace svgreader +} // end of namespace svgio + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/svgio/source/svgreader/svgtspannode.cxx b/svgio/source/svgreader/svgtspannode.cxx new file mode 100644 index 000000000000..8c66a9eecd99 --- /dev/null +++ b/svgio/source/svgreader/svgtspannode.cxx @@ -0,0 +1,77 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svgio.hxx" + +#include <svgio/svgreader/svgtspannode.hxx> + +////////////////////////////////////////////////////////////////////////////// + +namespace svgio +{ + namespace svgreader + { + SvgTspanNode::SvgTspanNode( + SvgDocument& rDocument, + SvgNode* pParent) + : SvgNode(SVGTokenTspan, rDocument, pParent), + maSvgStyleAttributes(*this), + maSvgTextPositions() + { + } + + SvgTspanNode::~SvgTspanNode() + { + } + + const SvgStyleAttributes* SvgTspanNode::getSvgStyleAttributes() const + { + return &maSvgStyleAttributes; + } + + void SvgTspanNode::parseAttribute(const rtl::OUString& rTokenName, SVGToken aSVGToken, const rtl::OUString& aContent) + { + // call parent + SvgNode::parseAttribute(rTokenName, aSVGToken, aContent); + + // read style attributes + maSvgStyleAttributes.parseStyleAttribute(rTokenName, aSVGToken, aContent); + + // read text position attributes + maSvgTextPositions.parseTextPositionAttributes(rTokenName, aSVGToken, aContent); + + // parse own + switch(aSVGToken) + { + case SVGTokenStyle: + { + maSvgStyleAttributes.readStyle(aContent); + break; + } + } + } + + } // end of namespace svgreader +} // end of namespace svgio + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/svgio/source/svgreader/svgusenode.cxx b/svgio/source/svgreader/svgusenode.cxx new file mode 100644 index 000000000000..c697f93b3b5e --- /dev/null +++ b/svgio/source/svgreader/svgusenode.cxx @@ -0,0 +1,197 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svgio.hxx" + +#include <svgio/svgreader/svgusenode.hxx> +#include <drawinglayer/primitive2d/transformprimitive2d.hxx> +#include <svgio/svgreader/svgdocument.hxx> + +////////////////////////////////////////////////////////////////////////////// + +namespace svgio +{ + namespace svgreader + { + SvgUseNode::SvgUseNode( + SvgDocument& rDocument, + SvgNode* pParent) + : SvgNode(SVGTokenG, rDocument, pParent), + maSvgStyleAttributes(*this), + mpaTransform(0), + maX(), + maY(), + maWidth(), + maHeight(), + maXLink() + { + } + + SvgUseNode::~SvgUseNode() + { + if(mpaTransform) delete mpaTransform; + } + + const SvgStyleAttributes* SvgUseNode::getSvgStyleAttributes() const + { + return &maSvgStyleAttributes; + } + + void SvgUseNode::parseAttribute(const rtl::OUString& rTokenName, SVGToken aSVGToken, const rtl::OUString& aContent) + { + // call parent + SvgNode::parseAttribute(rTokenName, aSVGToken, aContent); + + // read style attributes + maSvgStyleAttributes.parseStyleAttribute(rTokenName, aSVGToken, aContent); + + // parse own + switch(aSVGToken) + { + case SVGTokenStyle: + { + maSvgStyleAttributes.readStyle(aContent); + break; + } + case SVGTokenTransform: + { + const basegfx::B2DHomMatrix aMatrix(readTransform(aContent, *this)); + + if(!aMatrix.isIdentity()) + { + setTransform(&aMatrix); + } + break; + } + case SVGTokenX: + { + SvgNumber aNum; + + if(readSingleNumber(aContent, aNum)) + { + setX(aNum); + } + break; + } + case SVGTokenY: + { + SvgNumber aNum; + + if(readSingleNumber(aContent, aNum)) + { + setY(aNum); + } + break; + } + case SVGTokenWidth: + { + SvgNumber aNum; + + if(readSingleNumber(aContent, aNum)) + { + if(aNum.isPositive()) + { + setWidth(aNum); + } + } + break; + } + case SVGTokenHeight: + { + SvgNumber aNum; + + if(readSingleNumber(aContent, aNum)) + { + if(aNum.isPositive()) + { + setHeight(aNum); + } + } + } + case SVGTokenXlinkHref: + { + const sal_Int32 nLen(aContent.getLength()); + + if(nLen && sal_Unicode('#') == aContent[0]) + { + maXLink = aContent.copy(1); + } + break; + } + } + } + + void SvgUseNode::decomposeSvgNode(drawinglayer::primitive2d::Primitive2DSequence& rTarget, bool bReferenced) const + { + // try to access link to content + const SvgNode* mpXLink = getDocument().findSvgNodeById(maXLink); + + if(mpXLink) + { + // decompose childs + drawinglayer::primitive2d::Primitive2DSequence aNewTarget; + + // todo: in case mpXLink is a SVGTokenSvg or SVGTokenSymbol the + // SVG docs want the getWidth() and getHeight() from this node + // to be valid for the subtree. + const_cast< SvgNode* >(mpXLink)->setAlternativeParent(this); + mpXLink->decomposeSvgNode(aNewTarget, true); + const_cast< SvgNode* >(mpXLink)->setAlternativeParent(0); + + if(aNewTarget.hasElements()) + { + basegfx::B2DHomMatrix aTransform; + + if(getX().isSet() || getY().isSet()) + { + aTransform.translate( + getX().solve(*this, xcoordinate), + getY().solve(*this, ycoordinate)); + } + + if(getTransform()) + { + aTransform = *getTransform() * aTransform; + } + + if(!aTransform.isIdentity()) + { + const drawinglayer::primitive2d::Primitive2DReference xRef( + new drawinglayer::primitive2d::TransformPrimitive2D( + aTransform, + aNewTarget)); + + drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(rTarget, xRef); + } + else + { + drawinglayer::primitive2d::appendPrimitive2DSequenceToPrimitive2DSequence(rTarget, aNewTarget); + } + } + } + } + + } // end of namespace svgreader +} // end of namespace svgio + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/svgio/source/svguno/svguno.cxx b/svgio/source/svguno/svguno.cxx new file mode 100644 index 000000000000..eec9c86e3796 --- /dev/null +++ b/svgio/source/svguno/svguno.cxx @@ -0,0 +1,95 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svgio.hxx" + +#include <svgio/svgiodllapi.h> +#include <com/sun/star/uno/Reference.h> +#include <com/sun/star/uno/RuntimeException.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/registry/XRegistryKey.hpp> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/XSingleServiceFactory.hpp> +#include <uno/environment.h> +#include <cppuhelper/factory.hxx> + +////////////////////////////////////////////////////////////////////////////// + +using namespace ::com::sun::star; + +////////////////////////////////////////////////////////////////////////////// +// predefines + +namespace svgio +{ + namespace svgreader + { + extern uno::Sequence< rtl::OUString > SAL_CALL XSvgParser_getSupportedServiceNames(); + extern rtl::OUString SAL_CALL XSvgParser_getImplementationName(); + extern uno::Reference< uno::XInterface > SAL_CALL XSvgParser_createInstance( const uno::Reference< lang::XMultiServiceFactory > & ); + } // end of namespace svgreader +} // end of namespace svgio + +////////////////////////////////////////////////////////////////////////////// +// component_getImplementationEnvironment + +extern "C" +{ + SVGIO_DLLPUBLIC void SAL_CALL component_getImplementationEnvironment( const sal_Char ** ppEnvTypeName, uno_Environment ** /* ppEnv */ ) + { + *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; + } +} + +////////////////////////////////////////////////////////////////////////////// +// component_getFactory + +extern "C" +{ + SVGIO_DLLPUBLIC void* SAL_CALL component_getFactory( const sal_Char* pImplName, void* pServiceManager, void* /* pRegistryKey */ ) + { + uno::Reference< lang::XSingleServiceFactory > xFactory; + void* pRet = 0; + + if(svgio::svgreader::XSvgParser_getImplementationName().equalsAscii(pImplName)) + { + xFactory = ::cppu::createSingleFactory( + reinterpret_cast< lang::XMultiServiceFactory * >(pServiceManager), + svgio::svgreader::XSvgParser_getImplementationName(), + svgio::svgreader::XSvgParser_createInstance, + svgio::svgreader::XSvgParser_getSupportedServiceNames()); + } + + if(xFactory.is()) + { + xFactory->acquire(); + pRet = xFactory.get(); + } + + return pRet; + } +} + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/svgio/source/svguno/xsvgparser.cxx b/svgio/source/svguno/xsvgparser.cxx new file mode 100644 index 000000000000..92459a6a7632 --- /dev/null +++ b/svgio/source/svguno/xsvgparser.cxx @@ -0,0 +1,194 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svgio.hxx" + +#include <com/sun/star/graphic/XSvgParser.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <cppuhelper/implbase2.hxx> +#include <svgio/svgreader/svgdocumenthandler.hxx> +#include <com/sun/star/xml/sax/XParser.hpp> +#include <com/sun/star/xml/sax/InputSource.hpp> +#include <comphelper/processfactory.hxx> +#include <drawinglayer/geometry/viewinformation2d.hxx> + +////////////////////////////////////////////////////////////////////////////// + +using namespace ::com::sun::star; + +////////////////////////////////////////////////////////////////////////////// + +namespace svgio +{ + namespace svgreader + { + class XSvgParser : public ::cppu::WeakAggImplHelper2< graphic::XSvgParser, lang::XServiceInfo > + { + private: + XSvgParser(const XSvgParser&); + XSvgParser& operator=(const XSvgParser&); + + protected: + public: + XSvgParser(); + virtual ~XSvgParser(); + + // XSvgParser + virtual uno::Sequence< uno::Reference< ::graphic::XPrimitive2D > > SAL_CALL getDecomposition( + const uno::Reference< ::io::XInputStream >& xSVGStream, + const ::rtl::OUString& aAbsolutePath) throw (uno::RuntimeException); + + // XServiceInfo + virtual rtl::OUString SAL_CALL getImplementationName() throw(uno::RuntimeException); + virtual ::sal_Bool SAL_CALL supportsService(const rtl::OUString&) throw(uno::RuntimeException); + virtual uno::Sequence< rtl::OUString > SAL_CALL getSupportedServiceNames() throw(uno::RuntimeException); + }; + } // end of namespace svgreader +} // end of namespace svgio + +////////////////////////////////////////////////////////////////////////////// +// uno functions + +namespace svgio +{ + namespace svgreader + { + uno::Sequence< rtl::OUString > XSvgParser_getSupportedServiceNames() + { + static rtl::OUString aServiceName(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.graphic.SvgTools" ) ); + static uno::Sequence< rtl::OUString > aServiceNames( &aServiceName, 1 ); + + return( aServiceNames ); + } + + rtl::OUString XSvgParser_getImplementationName() + { + return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "svgio::svgreader::XSvgParser" ) ); + } + + uno::Reference< uno::XInterface > SAL_CALL XSvgParser_createInstance(const uno::Reference< lang::XMultiServiceFactory >&) + { + return static_cast< ::cppu::OWeakObject* >(new XSvgParser); + } + } // end of namespace svgreader +} // end of namespace svgio + +////////////////////////////////////////////////////////////////////////////// + +namespace svgio +{ + namespace svgreader + { + XSvgParser::XSvgParser() + { + } + + XSvgParser::~XSvgParser() + { + } + + uno::Sequence< uno::Reference< ::graphic::XPrimitive2D > > XSvgParser::getDecomposition( + const uno::Reference< ::io::XInputStream >& xSVGStream, + const ::rtl::OUString& aAbsolutePath ) throw (uno::RuntimeException) + { + drawinglayer::primitive2d::Primitive2DSequence aRetval; + + if(xSVGStream.is()) + { + // local document handler + SvgDocHdl* pSvgDocHdl = new SvgDocHdl(aAbsolutePath); + uno::Reference< xml::sax::XDocumentHandler > xSvgDocHdl(pSvgDocHdl); + + try + { + // prepare ParserInputSrouce + xml::sax::InputSource myInputSource; + myInputSource.aInputStream = xSVGStream; + + // get parser + uno::Reference< xml::sax::XParser > xParser( + comphelper::getProcessServiceFactory()->createInstance( + rtl::OUString::createFromAscii("com.sun.star.xml.sax.Parser") ), + uno::UNO_QUERY_THROW ); + + // connect parser and filter + xParser->setDocumentHandler(xSvgDocHdl); + + // finally, parse the stream to a hierarchy of + // SVGGraphicPrimitive2D which will be embedded to the + // primitive sequence. Their decompositions will in the + // end create local low-level primitives, thus SVG will + // be processable from all our processors + xParser->parseStream(myInputSource); + } + catch(uno::Exception&) + { + OSL_ENSURE(false, "Parse error (!)"); + } + + // decompose to primitives + const SvgNodeVector& rResults = pSvgDocHdl->getSvgDocument().getSvgNodeVector(); + const sal_uInt32 nCount(rResults.size()); + + for(sal_uInt32 a(0); a < nCount; a++) + { + rResults[a]->decomposeSvgNode(aRetval, false); + } + } + else + { + OSL_ENSURE(false, "Invalid stream (!)"); + } + + return aRetval; + } + + rtl::OUString SAL_CALL XSvgParser::getImplementationName() throw(uno::RuntimeException) + { + return(XSvgParser_getImplementationName()); + } + + sal_Bool SAL_CALL XSvgParser::supportsService(const rtl::OUString& rServiceName) throw(uno::RuntimeException) + { + const uno::Sequence< rtl::OUString > aServices(XSvgParser_getSupportedServiceNames()); + + for(sal_Int32 nService(0); nService < aServices.getLength(); nService++) + { + if(rServiceName == aServices[nService]) + { + return sal_True; + } + } + + return sal_False; + } + + uno::Sequence< rtl::OUString > SAL_CALL XSvgParser::getSupportedServiceNames() throw(uno::RuntimeException) + { + return XSvgParser_getSupportedServiceNames(); + } + + } // end of namespace svgreader +} // end of namespace svgio + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/svgio/svgio.component b/svgio/svgio.component new file mode 100644 index 000000000000..24ff62613029 --- /dev/null +++ b/svgio/svgio.component @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!--************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************--> + +<component loader="com.sun.star.loader.SharedLibrary" + xmlns="http://openoffice.org/2010/uno-components"> + <implementation name="svgio::svgreader::XSvgParser"> + <service name="com.sun.star.graphic.SvgTools"/> + </implementation> +</component> diff --git a/svtools/inc/svtools/grfmgr.hxx b/svtools/inc/svtools/grfmgr.hxx index 4dde3c57494b..1155820e85a8 100644 --- a/svtools/inc/svtools/grfmgr.hxx +++ b/svtools/inc/svtools/grfmgr.hxx @@ -217,8 +217,6 @@ private: sal_Bool mbIsInSwapOut : 1; sal_Bool mbAlpha : 1; sal_Bool mbDummyFlag8 : 1; - sal_Bool mbIsRenderGraphic : 1; - sal_Bool mbHasRenderGraphic : 1; void SVT_DLLPRIVATE ImplConstruct(); void SVT_DLLPRIVATE ImplAssignGraphicData(); @@ -400,8 +398,6 @@ public: sal_Bool IsAlpha() const { return mbAlpha; } sal_Bool IsAnimated() const { return mbAnimated; } sal_Bool IsEPS() const { return mbEPS; } - sal_Bool IsRenderGraphic() const { return mbIsRenderGraphic; } - sal_Bool HasRenderGraphic() const { return mbHasRenderGraphic; } void ResetAnimationLoopCount(); List* GetAnimationInfoList() const; diff --git a/svtools/source/filter/filter.cxx b/svtools/source/filter/filter.cxx index 4e5cc6a72451..2942ef925f19 100644 --- a/svtools/source/filter/filter.cxx +++ b/svtools/source/filter/filter.cxx @@ -35,7 +35,7 @@ #include <vcl/salctype.hxx> #include <vcl/pngread.hxx> #include <vcl/pngwrite.hxx> -#include <vcl/svgread.hxx> +#include <vcl/svgdata.hxx> #include <vcl/virdev.hxx> #include <vcl/svapp.hxx> #include <osl/file.hxx> @@ -71,6 +71,7 @@ #include <comphelper/processfactory.hxx> #include <rtl/bootstrap.hxx> #include <rtl/instance.hxx> +#include <vcl/metaact.hxx> #include "SvFilterOptionsDialog.hxx" @@ -675,13 +676,19 @@ static sal_Bool ImpPeekGraphicFormat( SvStream& rStream, String& rFormatExtensio } //--------------------------- SVG ------------------------------------ - if( !bTest || ( rFormatExtension.CompareToAscii( "SVG", 3 ) == COMPARE_EQUAL ) ) + if( !bTest ) { - bSomethingTested=sal_True; - - // just a simple test for the extension - if( rFormatExtension.CompareToAscii( "SVG", 3 ) == COMPARE_EQUAL ) + if( ImplSearchEntry( sFirstBytes, (sal_uInt8*)"DOCTYPE", 256, 7 ) + && ImplSearchEntry( sFirstBytes, (sal_uInt8*)"svg", 256, 3 ) ) + { + rFormatExtension = UniString::CreateFromAscii( "SVG", 3 ); return sal_True; + } + } + else if( rFormatExtension.CompareToAscii( "SVG", 3 ) == COMPARE_EQUAL ) + { + bSomethingTested = sal_True; + return sal_True; } //--------------------------- TGA ------------------------------------ @@ -1500,21 +1507,38 @@ sal_uInt16 GraphicFilter::ImportGraphic( Graphic& rGraphic, const String& rPath, if( rGraphic.GetContext() == (GraphicReader*) 1 ) rGraphic.SetContext( NULL ); - vcl::SVGReader aSVGReader( rIStream ); - GDIMetaFile aSVGMtf; + const sal_uInt32 nStmPos(rIStream.Tell()); + const sal_uInt32 nStmLen(rIStream.Seek(STREAM_SEEK_TO_END) - nStmPos); + bool bOkay(false); - if( 0 == aSVGReader.Read( aSVGMtf ).GetActionCount() ) - nStatus = GRFILTER_FILTERERROR; + if(nStmLen) + { + SvgDataArray aNewData(new sal_uInt8[nStmLen]); + + rIStream.Seek(nStmPos); + rIStream.Read(aNewData.get(), nStmLen); + + if(!rIStream.GetError()) + { + SvgDataPtr aSvgDataPtr( + new SvgData( + aNewData, + nStmLen, + rPath)); + + rGraphic = Graphic(aSvgDataPtr); + bOkay = true; + } + } + + if(bOkay) + { + eLinkType = GFX_LINK_TYPE_NATIVE_SVG; + } else - rGraphic = Graphic( aSVGMtf ); - - // Dont set any GfxLink here, since the MetaRenderGraphicAction - // inside the just read MetaFile contains excatly this native data; - // setting a ǴfxLink would also affect other program parts, since - // GfxLinks are preferably written to the file format in general, - // which would be a bad idea in case of SVG files, since earlier - // implementations are not able to handle native SVG data in any - // case. (KA 01/19/2011) + { + nStatus = GRFILTER_FILTERERROR; + } } else if( aFilterName.EqualsIgnoreCaseAscii( IMP_XBM ) ) { @@ -1856,7 +1880,7 @@ sal_uInt16 GraphicFilter::ExportGraphic( const Graphic& rGraphic, const String& aMTF.SetPrefSize( aGraphic.GetPrefSize() ); aMTF.SetPrefMapMode( aGraphic.GetPrefMapMode() ); } - aMTF.Write( rOStm, GDIMETAFILE_WRITE_REPLACEMENT_RENDERGRAPHIC ); + aMTF.Write( rOStm ); if( rOStm.GetError() ) nStatus = GRFILTER_IOERROR; } @@ -1973,24 +1997,22 @@ sal_uInt16 GraphicFilter::ExportGraphic( const Graphic& rGraphic, const String& } else if( aFilterName.EqualsIgnoreCaseAscii( EXP_SVG ) ) { - sal_Bool bDone = sal_False; + bool bDone(false); // do we have a native SVG RenderGraphic, whose data can be written directly? - if( ( GRAPHIC_GDIMETAFILE == eType ) && aGraphic.IsRenderGraphic() ) + const SvgDataPtr aSvgDataPtr(rGraphic.getSvgData()); + + if(aSvgDataPtr.get() && aSvgDataPtr->getSvgDataArrayLength()) { - const ::vcl::RenderGraphic aRenderGraphic( aGraphic.GetRenderGraphic() ); + rOStm.Write(aSvgDataPtr->getSvgDataArray().get(), aSvgDataPtr->getSvgDataArrayLength()); - if( aRenderGraphic.GetGraphicDataLength() && - aRenderGraphic.GetGraphicDataMimeType().equalsIgnoreAsciiCase( - ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "image/svg+xml" ) ) ) ) + if( rOStm.GetError() ) { - rOStm.Write( aRenderGraphic.GetGraphicData().get(), - aRenderGraphic.GetGraphicDataLength() ); - - if( rOStm.GetError() ) - { - nStatus = GRFILTER_IOERROR; - } + nStatus = GRFILTER_IOERROR; + } + else + { + bDone = true; } } diff --git a/svtools/source/filter/wmf/emfwr.cxx b/svtools/source/filter/wmf/emfwr.cxx index 99ca92c76abb..2d5e5c4170ad 100644 --- a/svtools/source/filter/wmf/emfwr.cxx +++ b/svtools/source/filter/wmf/emfwr.cxx @@ -33,7 +33,6 @@ #include <basegfx/polygon/b2dpolygon.hxx> #include <basegfx/polygon/b2dpolypolygon.hxx> #include <vcl/lineinfo.hxx> -#include <vcl/rendergraphicrasterizer.hxx> // ----------- // - Defines - @@ -1408,26 +1407,6 @@ void EMFWriter::ImplWrite( const GDIMetaFile& rMtf ) } break; - case( META_RENDERGRAPHIC_ACTION ): - { - const MetaRenderGraphicAction* pA = (const MetaRenderGraphicAction*) pAction; - const ::vcl::RenderGraphicRasterizer aRasterizer( pA->GetRenderGraphic() ); - const BitmapEx aBmpEx( aRasterizer.Rasterize( maVDev.LogicToPixel( pA->GetSize() ) ) ); - Bitmap aBmp( aBmpEx.GetBitmap() ); - Bitmap aMsk( aBmpEx.GetMask() ); - - if( !!aMsk ) - { - aBmp.Replace( aMsk, COL_WHITE ); - aMsk.Invert(); - ImplWriteBmpRecord( aMsk, pA->GetPoint(), pA->GetSize(), WIN_SRCPAINT ); - ImplWriteBmpRecord( aBmp, pA->GetPoint(), pA->GetSize(), WIN_SRCAND ); - } - else - ImplWriteBmpRecord( aBmp, pA->GetPoint(), pA->GetSize(), WIN_SRCCOPY ); - } - break; - default: DBG_ERROR( ( ByteString( "EMFWriter::ImplWriteActions: unsupported MetaAction #" ) += ByteString::CreateFromInt32( nType ) ).GetBuffer() ); break; diff --git a/svtools/source/filter/wmf/wmfwr.cxx b/svtools/source/filter/wmf/wmfwr.cxx index 26bda76a11d9..8067c0966ac5 100644 --- a/svtools/source/filter/wmf/wmfwr.cxx +++ b/svtools/source/filter/wmf/wmfwr.cxx @@ -29,7 +29,6 @@ #include "precompiled_svtools.hxx" #include <vcl/salbtype.hxx> -#include <vcl/rendergraphicrasterizer.hxx> #include "wmfwr.hxx" #include <unotools/fontcvt.hxx> #include "emfwr.hxx" @@ -319,7 +318,6 @@ void WMFWriter::CountActionsAndBitmaps( const GDIMetaFile & rMTF ) case META_BMPEX_ACTION: case META_BMPEXSCALE_ACTION: case META_BMPEXSCALEPART_ACTION: - case META_RENDERGRAPHIC_ACTION: nNumberOfBitmaps++; break; } @@ -1799,26 +1797,6 @@ void WMFWriter::WriteRecords( const GDIMetaFile & rMTF ) } break; - case( META_RENDERGRAPHIC_ACTION ): - { - const MetaRenderGraphicAction* pA = (const MetaRenderGraphicAction*) pMA; - const ::vcl::RenderGraphicRasterizer aRasterizer( pA->GetRenderGraphic() ); - const BitmapEx aBmpEx( aRasterizer.Rasterize( pVirDev->LogicToPixel( pA->GetSize(), aSrcMapMode ) ) ); - Bitmap aBmp( aBmpEx.GetBitmap() ); - Bitmap aMsk( aBmpEx.GetMask() ); - - if( !!aMsk ) - { - aBmp.Replace( aMsk, COL_WHITE ); - aMsk.Invert(); - WMFRecord_StretchDIB( pA->GetPoint(), pA->GetSize(), aMsk, W_SRCPAINT ); - WMFRecord_StretchDIB( pA->GetPoint(), pA->GetSize(), aBmp, W_SRCAND ); - } - else - WMFRecord_StretchDIB( pA->GetPoint(), pA->GetSize(), aBmp ); - } - break; - default: { DBG_ERROR( "Unsupported meta action!" ); diff --git a/svtools/source/graphic/descriptor.cxx b/svtools/source/graphic/descriptor.cxx index 2c1053857593..7ad32926d155 100644 --- a/svtools/source/graphic/descriptor.cxx +++ b/svtools/source/graphic/descriptor.cxx @@ -393,7 +393,10 @@ void GraphicDescriptor::_getPropertyValues( const comphelper::PropertyMapEntry** case( GFX_LINK_TYPE_NATIVE_PNG ): pMimeType = MIMETYPE_PNG; break; case( GFX_LINK_TYPE_NATIVE_WMF ): pMimeType = MIMETYPE_WMF; break; case( GFX_LINK_TYPE_NATIVE_MET ): pMimeType = MIMETYPE_MET; break; - case( GFX_LINK_TYPE_NATIVE_PCT ): pMimeType = MIMETYPE_PCT ; break; + case( GFX_LINK_TYPE_NATIVE_PCT ): pMimeType = MIMETYPE_PCT; break; + + // added Svg mimetype support + case( GFX_LINK_TYPE_NATIVE_SVG ): pMimeType = MIMETYPE_SVG; break; default: pMimeType = NULL; diff --git a/svtools/source/graphic/grfcache.cxx b/svtools/source/graphic/grfcache.cxx index 39ff71280b5a..4f5c85762c14 100644 --- a/svtools/source/graphic/grfcache.cxx +++ b/svtools/source/graphic/grfcache.cxx @@ -29,7 +29,7 @@ #include <vcl/outdev.hxx> #include <tools/poly.hxx> #include "grfcache.hxx" - +#include <rtl/crc.h> #include <memory> // ----------- @@ -88,7 +88,17 @@ GraphicID::GraphicID( const GraphicObject& rObj ) { case( GRAPHIC_BITMAP ): { - if( rGraphic.IsAnimated() ) + if(rGraphic.getSvgData().get()) + { + const SvgDataPtr& rSvgDataPtr = rGraphic.getSvgData(); + const basegfx::B2DRange& rRange = rSvgDataPtr->getRange(); + + mnID1 |= rSvgDataPtr->getSvgDataArrayLength(); + mnID2 = basegfx::fround(rRange.getWidth()); + mnID3 = basegfx::fround(rRange.getHeight()); + mnID4 = rtl_crc32(0, rSvgDataPtr->getSvgDataArray().get(), rSvgDataPtr->getSvgDataArrayLength()); + } + else if( rGraphic.IsAnimated() ) { const Animation aAnimation( rGraphic.GetAnimation() ); @@ -163,10 +173,13 @@ private: BitmapEx* mpBmpEx; GDIMetaFile* mpMtf; Animation* mpAnimation; - sal_Bool mbSwappedAll; + sal_Bool mbSwappedAll; - sal_Bool ImplInit( const GraphicObject& rObj ); - sal_Bool ImplMatches( const GraphicObject& rObj ) const { return( GraphicID( rObj ) == maID ); } + // SvgData support + SvgDataPtr maSvgData; + + sal_Bool ImplInit( const GraphicObject& rObj ); + sal_Bool ImplMatches( const GraphicObject& rObj ) const { return( GraphicID( rObj ) == maID ); } void ImplFillSubstitute( Graphic& rSubstitute ); public: @@ -194,8 +207,9 @@ GraphicCacheEntry::GraphicCacheEntry( const GraphicObject& rObj ) : mpBmpEx ( NULL ), mpMtf ( NULL ), mpAnimation ( NULL ), - mbSwappedAll ( !ImplInit( rObj ) ) + mbSwappedAll ( true ) { + mbSwappedAll = !ImplInit(rObj); maGraphicObjectList.Insert( (void*) &rObj, LIST_APPEND ); } @@ -233,10 +247,18 @@ sal_Bool GraphicCacheEntry::ImplInit( const GraphicObject& rObj ) { case( GRAPHIC_BITMAP ): { - if( rGraphic.IsAnimated() ) + if(rGraphic.getSvgData().get()) + { + maSvgData = rGraphic.getSvgData(); + } + else if( rGraphic.IsAnimated() ) + { mpAnimation = new Animation( rGraphic.GetAnimation() ); + } else + { mpBmpEx = new BitmapEx( rGraphic.GetBitmapEx() ); + } } break; @@ -280,14 +302,26 @@ void GraphicCacheEntry::ImplFillSubstitute( Graphic& rSubstitute ) if( rSubstitute.IsLink() && ( GFX_LINK_TYPE_NONE == maGfxLink.GetType() ) ) maGfxLink = rSubstitute.GetLink(); - if( mpBmpEx ) + if(maSvgData.get()) + { + rSubstitute = maSvgData; + } + else if( mpBmpEx ) + { rSubstitute = *mpBmpEx; + } else if( mpAnimation ) + { rSubstitute = *mpAnimation; + } else if( mpMtf ) + { rSubstitute = *mpMtf; + } else + { rSubstitute.Clear(); + } if( eOldType != GRAPHIC_NONE ) { @@ -298,10 +332,14 @@ void GraphicCacheEntry::ImplFillSubstitute( Graphic& rSubstitute ) } if( GFX_LINK_TYPE_NONE != maGfxLink.GetType() ) + { rSubstitute.SetLink( maGfxLink ); + } if( bDefaultType ) + { rSubstitute.SetDefaultType(); + } } // ----------------------------------------------------------------------------- diff --git a/svtools/source/graphic/grfmgr.cxx b/svtools/source/graphic/grfmgr.cxx index 3ae232ac2b7e..795afab7c0b6 100644 --- a/svtools/source/graphic/grfmgr.cxx +++ b/svtools/source/graphic/grfmgr.cxx @@ -187,8 +187,6 @@ void GraphicObject::ImplAssignGraphicData() mbAlpha = maGraphic.IsAlpha(); mbAnimated = maGraphic.IsAnimated(); mbEPS = maGraphic.IsEPS(); - mbIsRenderGraphic = maGraphic.IsRenderGraphic(); - mbHasRenderGraphic = maGraphic.HasRenderGraphic(); mnAnimationLoopCount = ( mbAnimated ? maGraphic.GetAnimationLoopCount() : 0 ); } @@ -438,7 +436,7 @@ void GraphicObject::Assign( const SvDataCopyStream& rCopyStream ) ByteString GraphicObject::GetUniqueID() const { - if ( !IsInSwapIn() && ( IsEPS() || IsRenderGraphic() ) ) + if ( !IsInSwapIn() && IsEPS() ) const_cast<GraphicObject*>(this)->FireSwapInRequest(); ByteString aRet; diff --git a/svtools/source/graphic/grfmgr2.cxx b/svtools/source/graphic/grfmgr2.cxx index 57b09f5a90e7..61bc4b310038 100644 --- a/svtools/source/graphic/grfmgr2.cxx +++ b/svtools/source/graphic/grfmgr2.cxx @@ -865,8 +865,6 @@ sal_Bool GraphicManager::ImplCreateOutput( OutputDevice* pOut, // FALLTHROUGH intended case META_GRADIENTEX_ACTION: // FALLTHROUGH intended - case META_RENDERGRAPHIC_ACTION: - // FALLTHROUGH intended // OutDev state changes that _do_ affect bitmap // output diff --git a/svtools/source/graphic/provider.cxx b/svtools/source/graphic/provider.cxx index 06e19c7fc26f..9ea46f5e2f29 100644 --- a/svtools/source/graphic/provider.cxx +++ b/svtools/source/graphic/provider.cxx @@ -628,17 +628,24 @@ void ImplApplyFilterData( ::Graphic& rGraphic, uno::Sequence< beans::PropertyVal } if ( rGraphic.GetType() == GRAPHIC_BITMAP ) { - Rectangle aCropPixel( Point( 0, 0 ), rGraphic.GetSizePixel() ); - ImplCalculateCropRect( rGraphic, aCropLogic, aCropPixel ); - if ( bRemoveCropArea ) + if(rGraphic.getSvgData().get()) { - BitmapEx aBmpEx( rGraphic.GetBitmapEx() ); - aBmpEx.Crop( aCropPixel ); - rGraphic = aBmpEx; + // embedded Svg, no need to scale. Also no method to apply crop data currently + } + else + { + Rectangle aCropPixel( Point( 0, 0 ), rGraphic.GetSizePixel() ); + ImplCalculateCropRect( rGraphic, aCropLogic, aCropPixel ); + if ( bRemoveCropArea ) + { + BitmapEx aBmpEx( rGraphic.GetBitmapEx() ); + aBmpEx.Crop( aCropPixel ); + rGraphic = aBmpEx; + } + Size aVisiblePixelSize( bRemoveCropArea ? rGraphic.GetSizePixel() : aCropPixel.GetSize() ); + ImplApplyBitmapResolution( rGraphic, nImageResolution, aVisiblePixelSize, aLogicalSize ); + ImplApplyBitmapScaling( rGraphic, nPixelWidth, nPixelHeight ); } - Size aVisiblePixelSize( bRemoveCropArea ? rGraphic.GetSizePixel() : aCropPixel.GetSize() ); - ImplApplyBitmapResolution( rGraphic, nImageResolution, aVisiblePixelSize, aLogicalSize ); - ImplApplyBitmapScaling( rGraphic, nPixelWidth, nPixelHeight ); } else if ( ( rGraphic.GetType() == GRAPHIC_GDIMETAFILE ) && nImageResolution ) { diff --git a/svx/inc/svx/sdr/contact/objectcontacttools.hxx b/svx/inc/svx/sdr/contact/objectcontacttools.hxx index bbae70cf9b6e..bdd919d5b8f0 100644 --- a/svx/inc/svx/sdr/contact/objectcontacttools.hxx +++ b/svx/inc/svx/sdr/contact/objectcontacttools.hxx @@ -25,6 +25,7 @@ #define _SDR_CONTACT_OBJECTCONTACTTOOLS_HXX #include <drawinglayer/geometry/viewinformation2d.hxx> +#include <svx/svxdllapi.h> ////////////////////////////////////////////////////////////////////////////// // predeclarations @@ -44,7 +45,7 @@ namespace sdr // create a mating VCL-Provessor for given OutputDevice. This includes // looking for MetaFile-recording. The returned renderer changes owner, // deletion is duty of the caller - drawinglayer::processor2d::BaseProcessor2D* createBaseProcessor2DFromOutputDevice( + SVX_DLLPUBLIC drawinglayer::processor2d::BaseProcessor2D* createBaseProcessor2DFromOutputDevice( OutputDevice& rTargetOutDev, const drawinglayer::geometry::ViewInformation2D& rViewInformation2D); diff --git a/svx/inc/svx/svdograf.hxx b/svx/inc/svx/svdograf.hxx index 0607ee235225..b8437b7320c0 100644 --- a/svx/inc/svx/svdograf.hxx +++ b/svx/inc/svx/svdograf.hxx @@ -101,6 +101,7 @@ protected: String aFileName; // Wenn es sich um einen Link handelt, steht hier der Dateiname drin. String aFilterName; GraphicObject* pGraphic; // Zur Beschleunigung von Bitmapausgaben, besonders von gedrehten. + GraphicObject* mpReplacementGraphic; SdrGraphicLink* pGraphicLink; // Und hier noch ein Pointer fuer gelinkte Grafiken bool bMirrored; // True bedeutet, die Grafik ist horizontal, d.h. ueber die Y-Achse gespiegelt auszugeben. @@ -131,6 +132,7 @@ public: void SetGraphicObject( const GraphicObject& rGrfObj ); const GraphicObject& GetGraphicObject( bool bForceSwapIn = false) const; + const GraphicObject* GetReplacementGraphicObject() const; void NbcSetGraphic(const Graphic& rGrf); void SetGraphic(const Graphic& rGrf); @@ -144,8 +146,6 @@ public: // Keep ATM for SD. sal_Bool IsAnimated() const; sal_Bool IsEPS() const; - sal_Bool IsRenderGraphic() const; - sal_Bool HasRenderGraphic() const; sal_Bool IsSwappedOut() const; const MapMode& GetGrafPrefMapMode() const; @@ -199,6 +199,9 @@ public: virtual void SetPage(SdrPage* pNewPage); virtual void SetModel(SdrModel* pNewModel); + bool isEmbeddedSvg() const; + GDIMetaFile getMetafileFromEmbeddedSvg() const; + virtual SdrObject* DoConvertToPolyObj(sal_Bool bBezier, bool bAddText) const; virtual void AdjustToMaxRect( const Rectangle& rMaxRect, bool bShrinkOnly = false ); diff --git a/svx/inc/svx/svdstr.hrc b/svx/inc/svx/svdstr.hrc index c21a564f54a0..1c9a34901a33 100644 --- a/svx/inc/svx/svdstr.hrc +++ b/svx/inc/svx/svdstr.hrc @@ -181,11 +181,16 @@ #define STR_ObjNameSingulMEDIA (STR_ObjNameBegin + 143) #define STR_ObjNamePluralMEDIA (STR_ObjNameBegin + 144) -//#define STR_ObjNameEnd (STR_ObjNamePluralMEDIA) //IAccessibility2 Implementation 2009----- #define STR_ObjNameSingulFONTWORK (STR_ObjNameBegin+145) #define STR_ObjNamePluralFONTWORK (STR_ObjNameBegin+146) -#define STR_ObjNameEnd (STR_ObjNamePluralFONTWORK) + +// Svg support +#define STR_ObjNameSingulGRAFSVG (STR_ObjNameBegin + 147) +#define STR_ObjNamePluralGRAFSVG (STR_ObjNameBegin + 148) + +#define STR_ObjNameEnd (STR_ObjNamePluralGRAFSVG) + //-----IAccessibility2 Implementation 2009 #define STR_EditBegin (STR_ObjNameEnd+1) #define STR_EditWithCopy (STR_EditBegin + 0) diff --git a/svx/inc/svx/svdxcgv.hxx b/svx/inc/svx/svdxcgv.hxx index 0942016b860a..8c08174f21f9 100644 --- a/svx/inc/svx/svdxcgv.hxx +++ b/svx/inc/svx/svdxcgv.hxx @@ -75,7 +75,7 @@ public: // Alle markierten Objekte auf eine Bitmap malen. Diese hat die Farbtiefe // und Aufloesung des Bildschirms. - virtual Bitmap GetMarkedObjBitmap(sal_Bool bNoVDevIfOneBmpMarked=sal_False) const; + BitmapEx GetMarkedObjBitmap(bool bNoVDevIfOneBmpMarked = false) const; // Alle markierten Objekte in ein neues Model kopieren. Dieses neue Model // hat dann genau eine Page. Das Flag PageNotValid an diesem Model ist @@ -90,7 +90,7 @@ public: virtual SdrModel* GetMarkedObjModel() const; GDIMetaFile GetAllMarkedMetaFile(sal_Bool bNoVDevIfOneMtfMarked=sal_False) const { return GetMarkedObjMetaFile(bNoVDevIfOneMtfMarked); } - Bitmap GetAllMarkedBitmap(sal_Bool bNoVDevIfOneBmpMarked=sal_False) const { return GetMarkedObjBitmap(bNoVDevIfOneBmpMarked); } + Bitmap GetAllMarkedBitmap(sal_Bool bNoVDevIfOneBmpMarked=sal_False) const { return GetMarkedObjBitmap(bNoVDevIfOneBmpMarked).GetBitmap(); } Graphic GetAllMarkedGraphic() const; SdrModel* GetAllMarkedModel() const { return GetMarkedObjModel(); } diff --git a/svx/inc/svx/unoshprp.hxx b/svx/inc/svx/unoshprp.hxx index 2e6ac3c1106c..13c265a29365 100644 --- a/svx/inc/svx/unoshprp.hxx +++ b/svx/inc/svx/unoshprp.hxx @@ -125,6 +125,9 @@ #define OWN_ATTR_TRANSFORMATION (OWN_ATTR_VALUE_START+46) #define OWN_ATTR_BASE_GEOMETRY (OWN_ATTR_VALUE_START+47) +/// reuse attr slots for GraphicObject which will never be used together with graphic object +#define OWN_ATTR_REPLACEMENTGRAFURL (OWN_ATTR_VALUE_START+14) + #define OWN_ATTR_APPLET_DOCBASE (OWN_ATTR_VALUE_START+48) #define OWN_ATTR_APPLET_CODEBASE (OWN_ATTR_VALUE_START+49) #define OWN_ATTR_APPLET_NAME (OWN_ATTR_VALUE_START+50) @@ -415,11 +418,12 @@ #define SPECIAL_GRAPHOBJ_PROPERTIES \ SPECIAL_GRAPHOBJ_PROPERTIES_DEFAULTS \ - { MAP_CHAR_LEN(UNO_NAME_GRAPHIC_GRAPHICCROP), SDRATTR_GRAFCROP , &::getCppuType((const ::com::sun::star::text::GraphicCrop*)0), 0, 0 }, \ - { MAP_CHAR_LEN(UNO_NAME_GRAPHOBJ_GRAFURL), OWN_ATTR_GRAFURL , &::getCppuType((const ::rtl::OUString*)0), 0, 0 }, \ - { MAP_CHAR_LEN(UNO_NAME_GRAPHOBJ_GRAFSTREAMURL),OWN_ATTR_GRAFSTREAMURL , &::getCppuType((const ::rtl::OUString*)0), ::com::sun::star::beans::PropertyAttribute::MAYBEVOID, 0 }, \ - { MAP_CHAR_LEN(UNO_NAME_GRAPHOBJ_FILLBITMAP), OWN_ATTR_VALUE_FILLBITMAP , &::getCppuType((const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XBitmap>*)0) , 0, 0}, \ - { MAP_CHAR_LEN(UNO_NAME_GRAPHOBJ_GRAPHIC), OWN_ATTR_VALUE_GRAPHIC , &::getCppuType((const ::com::sun::star::uno::Reference< ::com::sun::star::graphic::XGraphic>*)0) , 0, 0}, + { MAP_CHAR_LEN(UNO_NAME_GRAPHIC_GRAPHICCROP), SDRATTR_GRAFCROP , &::getCppuType((const ::com::sun::star::text::GraphicCrop*)0), 0, 0 }, \ + { MAP_CHAR_LEN(UNO_NAME_GRAPHOBJ_GRAFURL), OWN_ATTR_GRAFURL , &::getCppuType((const ::rtl::OUString*)0), 0, 0 }, \ + { MAP_CHAR_LEN(UNO_NAME_GRAPHOBJ_REPLACEMENTGRAFURL), OWN_ATTR_REPLACEMENTGRAFURL , &::getCppuType((const ::rtl::OUString*)0), 0, 0 }, \ + { MAP_CHAR_LEN(UNO_NAME_GRAPHOBJ_GRAFSTREAMURL), OWN_ATTR_GRAFSTREAMURL , &::getCppuType((const ::rtl::OUString*)0), ::com::sun::star::beans::PropertyAttribute::MAYBEVOID, 0 }, \ + { MAP_CHAR_LEN(UNO_NAME_GRAPHOBJ_FILLBITMAP), OWN_ATTR_VALUE_FILLBITMAP , &::getCppuType((const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XBitmap>*)0) , 0, 0}, \ + { MAP_CHAR_LEN(UNO_NAME_GRAPHOBJ_GRAPHIC), OWN_ATTR_VALUE_GRAPHIC , &::getCppuType((const ::com::sun::star::uno::Reference< ::com::sun::star::graphic::XGraphic>*)0) , 0, 0}, #define SPECIAL_3DSCENEOBJECT_PROPERTIES_DEFAULTS \ diff --git a/svx/source/dialog/_bmpmask.cxx b/svx/source/dialog/_bmpmask.cxx index 91438ee278ad..73484ed512d6 100644 --- a/svx/source/dialog/_bmpmask.cxx +++ b/svx/source/dialog/_bmpmask.cxx @@ -1034,9 +1034,6 @@ GDIMetaFile SvxBmpMask::ImpMask( const GDIMetaFile& rMtf ) default: { - OSL_ENSURE( pAction->GetType() != META_RENDERGRAPHIC_ACTION, - "META_RENDERGRAPHIC_ACTION currently not supported at masking" ); - pAction->Duplicate(); aMtf.AddAction( pAction ); } diff --git a/svx/source/sdr/contact/viewcontactofgraphic.cxx b/svx/source/sdr/contact/viewcontactofgraphic.cxx index f8941f09b57b..f6c50e1a52df 100644 --- a/svx/source/sdr/contact/viewcontactofgraphic.cxx +++ b/svx/source/sdr/contact/viewcontactofgraphic.cxx @@ -410,11 +410,12 @@ namespace sdr { // create primitive. Info: Calling the copy-constructor of GraphicObject in this // SdrGrafPrimitive2D constructor will force a full swap-in of the graphic - const drawinglayer::primitive2d::Primitive2DReference xReference(new drawinglayer::primitive2d::SdrGrafPrimitive2D( - aObjectMatrix, - aAttribute, - rGraphicObject, - aLocalGrafInfo)); + const drawinglayer::primitive2d::Primitive2DReference xReference( + new drawinglayer::primitive2d::SdrGrafPrimitive2D( + aObjectMatrix, + aAttribute, + rGraphicObject, + aLocalGrafInfo)); xRetval = drawinglayer::primitive2d::Primitive2DSequence(&xReference, 1); } diff --git a/svx/source/sdr/primitive2d/sdrgrafprimitive2d.cxx b/svx/source/sdr/primitive2d/sdrgrafprimitive2d.cxx index 8178a6c88054..2630ddab7e48 100644 --- a/svx/source/sdr/primitive2d/sdrgrafprimitive2d.cxx +++ b/svx/source/sdr/primitive2d/sdrgrafprimitive2d.cxx @@ -19,8 +19,6 @@ * *************************************************************/ - - #include "precompiled_svx.hxx" #include <svx/sdr/primitive2d/sdrgrafprimitive2d.hxx> #include <drawinglayer/primitive2d/graphicprimitive2d.hxx> @@ -30,6 +28,8 @@ #include <svx/sdr/primitive2d/svx_primitivetypes2d.hxx> #include <drawinglayer/primitive2d/sdrdecompositiontools2d.hxx> #include <basegfx/polygon/b2dpolygon.hxx> +#include <basegfx/matrix/b2dhommatrixtools.hxx> +#include <drawinglayer/primitive2d/transformprimitive2d.hxx> ////////////////////////////////////////////////////////////////////////////// @@ -94,6 +94,7 @@ namespace drawinglayer // add graphic content if(255L != getGraphicAttr().GetTransparency()) { + // standard graphic fill const Primitive2DReference xGraphicContentPrimitive( new GraphicPrimitive2D( getTransform(), @@ -160,7 +161,8 @@ namespace drawinglayer bool SdrGrafPrimitive2D::isTransparent() const { - return ((0L != getGraphicAttr().GetTransparency()) || (getGraphicObject().IsTransparent())); + return ((0L != getGraphicAttr().GetTransparency()) + || (getGraphicObject().IsTransparent())); } // provide unique ID diff --git a/svx/source/svdraw/svddrgmt.cxx b/svx/source/svdraw/svddrgmt.cxx index 668ef6fc7877..7047117c1a75 100644 --- a/svx/source/svdraw/svddrgmt.cxx +++ b/svx/source/svdraw/svddrgmt.cxx @@ -3628,6 +3628,19 @@ bool SdrDragCrop::EndSdrDrag(bool bCopy) double fScaleX = ( aGraphicSize.Width() - rOldCrop.GetLeft() - rOldCrop.GetRight() ) / (double)aOldRect.GetWidth(); double fScaleY = ( aGraphicSize.Height() - rOldCrop.GetTop() - rOldCrop.GetBottom() ) / (double)aOldRect.GetHeight(); + // to correct the never working combination of cropped images and mirroring + // I have to correct the rectangles the calculation is based on here. In the current + // core geometry stuff a vertical mirror is expressed as 180 degree rotation. All + // this can be removed again when aw080 will have cleaned up the old + // (non-)transformation mess in the core. + if(18000 == pObj->GetGeoStat().nDrehWink) + { + // old notation of vertical mirror, need to correct diffs since both rects + // are rotated by 180 degrees + aOldRect = Rectangle(aOldRect.TopLeft() - (aOldRect.BottomRight() - aOldRect.TopLeft()), aOldRect.TopLeft()); + aNewRect = Rectangle(aNewRect.TopLeft() - (aNewRect.BottomRight() - aNewRect.TopLeft()), aNewRect.TopLeft()); + } + sal_Int32 nDiffLeft = aNewRect.nLeft - aOldRect.nLeft; sal_Int32 nDiffTop = aNewRect.nTop - aOldRect.nTop; sal_Int32 nDiffRight = aNewRect.nRight - aOldRect.nRight; diff --git a/svx/source/svdraw/svdedtv.cxx b/svx/source/svdraw/svdedtv.cxx index d8921e50da18..5656cf02b34e 100644 --- a/svx/source/svdraw/svdedtv.cxx +++ b/svx/source/svdraw/svdedtv.cxx @@ -636,19 +636,20 @@ void SdrEditView::CheckPossibilities() if (!bOrthoDesiredOnMarked && !aInfo.bNoOrthoDesired) bOrthoDesiredOnMarked=sal_True; // ImportMtf checken - if (!bImportMtfPossible) { - sal_Bool bGraf=HAS_BASE(SdrGrafObj,pObj); - sal_Bool bOle2=HAS_BASE(SdrOle2Obj,pObj); + if (!bImportMtfPossible) + { + const SdrGrafObj* pSdrGrafObj = dynamic_cast< const SdrGrafObj* >(pObj); + const SdrOle2Obj* pSdrOle2Obj = dynamic_cast< const SdrOle2Obj* >(pObj); - if( bGraf && - ((SdrGrafObj*)pObj)->HasGDIMetaFile() && - !( ((SdrGrafObj*)pObj)->IsEPS() || ((SdrGrafObj*)pObj)->IsRenderGraphic() ) ) + if(pSdrGrafObj && ((pSdrGrafObj->HasGDIMetaFile() && !pSdrGrafObj->IsEPS()) || pSdrGrafObj->isEmbeddedSvg())) { bImportMtfPossible = sal_True; } - if (bOle2) - bImportMtfPossible=((SdrOle2Obj*)pObj)->GetObjRef().is(); + if(pSdrOle2Obj) + { + bImportMtfPossible = pSdrOle2Obj->GetObjRef().is(); + } } } diff --git a/svx/source/svdraw/svdedtv2.cxx b/svx/source/svdraw/svdedtv2.cxx index 3b003c8c54c4..d9e97abc54a2 100644 --- a/svx/source/svdraw/svdedtv2.cxx +++ b/svx/source/svdraw/svdedtv2.cxx @@ -2073,17 +2073,30 @@ void SdrEditView::DoImportMarkedMtf(SvdProgressInfo *pProgrInfo) sal_uIntPtr nInsAnz=0; Rectangle aLogicRect; - if (pGraf!=NULL && pGraf->HasGDIMetaFile()) + if(pGraf && (pGraf->HasGDIMetaFile() || pGraf->isEmbeddedSvg())) { - ImpSdrGDIMetaFileImport aFilter(*pMod); + GDIMetaFile aMetaFile; - aLogicRect = pGraf->GetLogicRect(); - aFilter.SetScaleRect(aLogicRect); - aFilter.SetLayer(pObj->GetLayer()); + if(pGraf->HasGDIMetaFile()) + { + aMetaFile = pGraf->GetTransformedGraphic( + SDRGRAFOBJ_TRANSFORMATTR_COLOR|SDRGRAFOBJ_TRANSFORMATTR_MIRROR).GetGDIMetaFile(); + } + else if(pGraf->isEmbeddedSvg()) + { + aMetaFile = pGraf->getMetafileFromEmbeddedSvg(); + } + + if(aMetaFile.GetActionCount()) + { + ImpSdrGDIMetaFileImport aFilter(*pMod); - nInsAnz=aFilter.DoImport(pGraf->GetTransformedGraphic( - SDRGRAFOBJ_TRANSFORMATTR_COLOR|SDRGRAFOBJ_TRANSFORMATTR_MIRROR).GetGDIMetaFile(), - *pOL,nInsPos,pProgrInfo); + aLogicRect = pGraf->GetLogicRect(); + aFilter.SetScaleRect(aLogicRect); + aFilter.SetLayer(pObj->GetLayer()); + + nInsAnz = aFilter.DoImport(aMetaFile, *pOL, nInsPos, pProgrInfo); + } } if ( pOle2!=NULL && pOle2->GetGraphic() ) { diff --git a/svx/source/svdraw/svdfmtf.cxx b/svx/source/svdraw/svdfmtf.cxx index de8d53e31c20..5519973e0c88 100644 --- a/svx/source/svdraw/svdfmtf.cxx +++ b/svx/source/svdraw/svdfmtf.cxx @@ -191,7 +191,6 @@ sal_uIntPtr ImpSdrGDIMetaFileImport::DoImport(const GDIMetaFile& rMtf, case META_POP_ACTION : DoAction((MetaPopAction &)*pAct); break; case META_HATCH_ACTION : DoAction((MetaHatchAction &)*pAct); break; case META_COMMENT_ACTION : DoAction((MetaCommentAction &)*pAct, pMtf); break; - case META_RENDERGRAPHIC_ACTION : DoAction((MetaRenderGraphicAction &)*pAct); break; } if(pProgrInfo != NULL) @@ -1025,24 +1024,4 @@ void ImpSdrGDIMetaFileImport::DoAction( MetaCommentAction& rAct, GDIMetaFile* pM } //////////////////////////////////////////////////////////////////////////////////////////////////// - -void ImpSdrGDIMetaFileImport::DoAction(MetaRenderGraphicAction& rAct) -{ - GDIMetaFile aMtf; - const ::vcl::RenderGraphic& rRenderGraphic = rAct.GetRenderGraphic(); - Rectangle aRect( rAct.GetPoint(), rAct.GetSize() ); - const Point aPos; - const Size aPrefSize( rRenderGraphic.GetPrefSize() ); - - aRect.Right()++; aRect.Bottom()++; - - aMtf.SetPrefMapMode( rRenderGraphic.GetPrefMapMode() ); - aMtf.SetPrefSize( aPrefSize ); - aMtf.AddAction( new MetaRenderGraphicAction( aPos, aPrefSize, rRenderGraphic ) ); - aMtf.WindStart(); - - SdrGrafObj* pGraf=new SdrGrafObj( aMtf, aRect ); - InsertObj( pGraf ); -} - // eof diff --git a/svx/source/svdraw/svdfmtf.hxx b/svx/source/svdraw/svdfmtf.hxx index 23ac97524210..c311a8d5dc2f 100644 --- a/svx/source/svdraw/svdfmtf.hxx +++ b/svx/source/svdraw/svdfmtf.hxx @@ -136,7 +136,6 @@ protected: void DoAction(MetaISectRectClipRegionAction& rAct) { rAct.Execute(&aVD); } void DoAction(MetaISectRegionClipRegionAction& rAct) { rAct.Execute(&aVD); } void DoAction(MetaCommentAction& rAct, GDIMetaFile* pMtf); - void DoAction(MetaRenderGraphicAction& rAct); void ImportText( const Point& rPos, const XubString& rStr, const MetaAction& rAct ); void SetAttributes(SdrObject* pObj, FASTBOOL bForceTextAttr=sal_False); diff --git a/svx/source/svdraw/svdobj.cxx b/svx/source/svdraw/svdobj.cxx index 0639220da7b1..15ea175155fa 100644 --- a/svx/source/svdraw/svdobj.cxx +++ b/svx/source/svdraw/svdobj.cxx @@ -1203,7 +1203,7 @@ basegfx::B2DPolyPolygon SdrObject::TakeContour() const // create extractor, process and get result drawinglayer::processor2d::ContourExtractor2D aExtractor(aViewInformation2D); aExtractor.process(xSequence); - const std::vector< basegfx::B2DPolyPolygon >& rResult(aExtractor.getExtractedContour()); + const basegfx::B2DPolyPolygonVector& rResult(aExtractor.getExtractedContour()); const sal_uInt32 nSize(rResult.size()); // when count is one, it is implied that the object has only it's normal @@ -2434,7 +2434,7 @@ SdrObject* SdrObject::ImpConvertToContourObj(SdrObject* pRet, sal_Bool bForceLin aExtractor.process(xSequence); // #i102241# check for line results - const std::vector< basegfx::B2DPolygon >& rHairlineVector = aExtractor.getExtractedHairlines(); + const basegfx::B2DPolygonVector& rHairlineVector = aExtractor.getExtractedHairlines(); if(!rHairlineVector.empty()) { @@ -2446,7 +2446,7 @@ SdrObject* SdrObject::ImpConvertToContourObj(SdrObject* pRet, sal_Bool bForceLin } // #i102241# check for fill rsults - const std::vector< basegfx::B2DPolyPolygon >& rLineFillVector(aExtractor.getExtractedLineFills()); + const basegfx::B2DPolyPolygonVector& rLineFillVector(aExtractor.getExtractedLineFills()); if(!rLineFillVector.empty()) { diff --git a/svx/source/svdraw/svdograf.cxx b/svx/source/svdraw/svdograf.cxx index 5b710281f672..df03d56f06e9 100644 --- a/svx/source/svdraw/svdograf.cxx +++ b/svx/source/svdraw/svdograf.cxx @@ -321,6 +321,7 @@ SdrGrafObj::SdrGrafObj() bMirrored ( sal_False ) { pGraphic = new GraphicObject; + mpReplacementGraphic = 0; pGraphic->SetSwapStreamHdl( LINK( this, SdrGrafObj, ImpSwapHdl ), SWAPGRAPHIC_TIMEOUT ); // #i118485# Shear allowed and possible now @@ -346,6 +347,7 @@ SdrGrafObj::SdrGrafObj(const Graphic& rGrf, const Rectangle& rRect) bMirrored ( sal_False ) { pGraphic = new GraphicObject( rGrf ); + mpReplacementGraphic = 0; pGraphic->SetSwapStreamHdl( LINK( this, SdrGrafObj, ImpSwapHdl ), SWAPGRAPHIC_TIMEOUT ); // #i118485# Shear allowed and possible now @@ -371,6 +373,7 @@ SdrGrafObj::SdrGrafObj( const Graphic& rGrf ) bMirrored ( sal_False ) { pGraphic = new GraphicObject( rGrf ); + mpReplacementGraphic = 0; pGraphic->SetSwapStreamHdl( LINK( this, SdrGrafObj, ImpSwapHdl ), SWAPGRAPHIC_TIMEOUT ); // #i118485# Shear allowed and possible now @@ -393,6 +396,7 @@ SdrGrafObj::SdrGrafObj( const Graphic& rGrf ) SdrGrafObj::~SdrGrafObj() { delete pGraphic; + delete mpReplacementGraphic; ImpLinkAbmeldung(); } @@ -401,6 +405,8 @@ SdrGrafObj::~SdrGrafObj() void SdrGrafObj::SetGraphicObject( const GraphicObject& rGrfObj ) { *pGraphic = rGrfObj; + delete mpReplacementGraphic; + mpReplacementGraphic = 0; pGraphic->SetSwapStreamHdl( LINK( this, SdrGrafObj, ImpSwapHdl ), SWAPGRAPHIC_TIMEOUT ); pGraphic->SetUserData(); mbIsPreview = sal_False; @@ -420,11 +426,28 @@ const GraphicObject& SdrGrafObj::GetGraphicObject(bool bForceSwapIn) const return *pGraphic; } +const GraphicObject* SdrGrafObj::GetReplacementGraphicObject() const +{ + if(!mpReplacementGraphic && pGraphic) + { + const SvgDataPtr& rSvgDataPtr = pGraphic->GetGraphic().getSvgData(); + + if(rSvgDataPtr.get()) + { + const_cast< SdrGrafObj* >(this)->mpReplacementGraphic = new GraphicObject(rSvgDataPtr->getReplacement()); + } + } + + return mpReplacementGraphic; +} + // ----------------------------------------------------------------------------- void SdrGrafObj::NbcSetGraphic( const Graphic& rGrf ) { pGraphic->SetGraphic( rGrf ); + delete mpReplacementGraphic; + mpReplacementGraphic = 0; pGraphic->SetUserData(); mbIsPreview = sal_False; } @@ -503,16 +526,6 @@ sal_Bool SdrGrafObj::IsEPS() const return pGraphic->IsEPS(); } -sal_Bool SdrGrafObj::IsRenderGraphic() const -{ - return pGraphic->IsRenderGraphic(); -} - -sal_Bool SdrGrafObj::HasRenderGraphic() const -{ - return pGraphic->HasRenderGraphic(); -} - sal_Bool SdrGrafObj::IsSwappedOut() const { return mbIsPreview ? sal_True : pGraphic->IsSwappedOut(); @@ -667,7 +680,6 @@ void SdrGrafObj::ReleaseGraphicLink() void SdrGrafObj::TakeObjInfo(SdrObjTransformInfoRec& rInfo) const { FASTBOOL bAnim = pGraphic->IsAnimated(); - FASTBOOL bRenderGraphic = pGraphic->HasRenderGraphic(); FASTBOOL bNoPresGrf = ( pGraphic->GetType() != GRAPHIC_NONE ) && !bEmptyPresObj; rInfo.bResizeFreeAllowed = aGeo.nDrehWink % 9000 == 0 || @@ -675,11 +687,11 @@ void SdrGrafObj::TakeObjInfo(SdrObjTransformInfoRec& rInfo) const aGeo.nDrehWink % 27000 == 0; rInfo.bResizePropAllowed = sal_True; - rInfo.bRotateFreeAllowed = bNoPresGrf && !bAnim && !bRenderGraphic; - rInfo.bRotate90Allowed = bNoPresGrf && !bAnim && !bRenderGraphic; - rInfo.bMirrorFreeAllowed = bNoPresGrf && !bAnim && !bRenderGraphic; - rInfo.bMirror45Allowed = bNoPresGrf && !bAnim && !bRenderGraphic; - rInfo.bMirror90Allowed = !bEmptyPresObj && !bRenderGraphic; + rInfo.bRotateFreeAllowed = bNoPresGrf && !bAnim; + rInfo.bRotate90Allowed = bNoPresGrf && !bAnim; + rInfo.bMirrorFreeAllowed = bNoPresGrf && !bAnim; + rInfo.bMirror45Allowed = bNoPresGrf && !bAnim; + rInfo.bMirror90Allowed = !bEmptyPresObj; rInfo.bTransparenceAllowed = sal_False; rInfo.bGradientAllowed = sal_False; @@ -687,10 +699,10 @@ void SdrGrafObj::TakeObjInfo(SdrObjTransformInfoRec& rInfo) const rInfo.bShearAllowed = true; rInfo.bEdgeRadiusAllowed=sal_False; - rInfo.bCanConvToPath = !IsEPS() && !bRenderGraphic; + rInfo.bCanConvToPath = !IsEPS(); rInfo.bCanConvToPathLineToArea = sal_False; rInfo.bCanConvToPolyLineToArea = sal_False; - rInfo.bCanConvToPoly = !IsEPS() && !bRenderGraphic; + rInfo.bCanConvToPoly = !IsEPS(); rInfo.bCanConvToContour = (rInfo.bCanConvToPoly || LineGeometryUsageIsNecessary()); } @@ -735,38 +747,50 @@ void SdrGrafObj::ImpSetLinkedGraphic( const Graphic& rGraphic ) void SdrGrafObj::TakeObjNameSingul(XubString& rName) const { - switch( pGraphic->GetType() ) + if(pGraphic) { - case GRAPHIC_BITMAP: - { - const sal_uInt16 nId = ( ( pGraphic->IsTransparent() || ( (const SdrGrafTransparenceItem&) GetObjectItem( SDRATTR_GRAFTRANSPARENCE ) ).GetValue() ) ? - ( IsLinkedGraphic() ? STR_ObjNameSingulGRAFBMPTRANSLNK : STR_ObjNameSingulGRAFBMPTRANS ) : - ( IsLinkedGraphic() ? STR_ObjNameSingulGRAFBMPLNK : STR_ObjNameSingulGRAFBMP ) ); + const SvgDataPtr& rSvgDataPtr = pGraphic->GetGraphic().getSvgData(); - rName=ImpGetResStr( nId ); + if(rSvgDataPtr.get()) + { + rName = ImpGetResStr(STR_ObjNameSingulGRAFSVG); } - break; + else + { + switch( pGraphic->GetType() ) + { + case GRAPHIC_BITMAP: + { + const sal_uInt16 nId = ( ( pGraphic->IsTransparent() || ( (const SdrGrafTransparenceItem&) GetObjectItem( SDRATTR_GRAFTRANSPARENCE ) ).GetValue() ) ? + ( IsLinkedGraphic() ? STR_ObjNameSingulGRAFBMPTRANSLNK : STR_ObjNameSingulGRAFBMPTRANS ) : + ( IsLinkedGraphic() ? STR_ObjNameSingulGRAFBMPLNK : STR_ObjNameSingulGRAFBMP ) ); - case GRAPHIC_GDIMETAFILE: - rName=ImpGetResStr( IsLinkedGraphic() ? STR_ObjNameSingulGRAFMTFLNK : STR_ObjNameSingulGRAFMTF ); - break; + rName=ImpGetResStr( nId ); + } + break; - case GRAPHIC_NONE: - rName=ImpGetResStr( IsLinkedGraphic() ? STR_ObjNameSingulGRAFNONELNK : STR_ObjNameSingulGRAFNONE ); - break; + case GRAPHIC_GDIMETAFILE: + rName=ImpGetResStr( IsLinkedGraphic() ? STR_ObjNameSingulGRAFMTFLNK : STR_ObjNameSingulGRAFMTF ); + break; - default: - rName=ImpGetResStr( IsLinkedGraphic() ? STR_ObjNameSingulGRAFLNK : STR_ObjNameSingulGRAF ); - break; - } + case GRAPHIC_NONE: + rName=ImpGetResStr( IsLinkedGraphic() ? STR_ObjNameSingulGRAFNONELNK : STR_ObjNameSingulGRAFNONE ); + break; - const String aName(GetName()); + default: + rName=ImpGetResStr( IsLinkedGraphic() ? STR_ObjNameSingulGRAFLNK : STR_ObjNameSingulGRAF ); + break; + } + } - if( aName.Len() ) - { - rName.AppendAscii( " '" ); - rName += aName; - rName += sal_Unicode( '\'' ); + const String aName(GetName()); + + if( aName.Len() ) + { + rName.AppendAscii( " '" ); + rName += aName; + rName += sal_Unicode( '\'' ); + } } } @@ -774,38 +798,50 @@ void SdrGrafObj::TakeObjNameSingul(XubString& rName) const void SdrGrafObj::TakeObjNamePlural( XubString& rName ) const { - switch( pGraphic->GetType() ) + if(pGraphic) { - case GRAPHIC_BITMAP: - { - const sal_uInt16 nId = ( ( pGraphic->IsTransparent() || ( (const SdrGrafTransparenceItem&) GetObjectItem( SDRATTR_GRAFTRANSPARENCE ) ).GetValue() ) ? - ( IsLinkedGraphic() ? STR_ObjNamePluralGRAFBMPTRANSLNK : STR_ObjNamePluralGRAFBMPTRANS ) : - ( IsLinkedGraphic() ? STR_ObjNamePluralGRAFBMPLNK : STR_ObjNamePluralGRAFBMP ) ); + const SvgDataPtr& rSvgDataPtr = pGraphic->GetGraphic().getSvgData(); - rName=ImpGetResStr( nId ); + if(rSvgDataPtr.get()) + { + rName = ImpGetResStr(STR_ObjNamePluralGRAFSVG); } - break; + else + { + switch( pGraphic->GetType() ) + { + case GRAPHIC_BITMAP: + { + const sal_uInt16 nId = ( ( pGraphic->IsTransparent() || ( (const SdrGrafTransparenceItem&) GetObjectItem( SDRATTR_GRAFTRANSPARENCE ) ).GetValue() ) ? + ( IsLinkedGraphic() ? STR_ObjNamePluralGRAFBMPTRANSLNK : STR_ObjNamePluralGRAFBMPTRANS ) : + ( IsLinkedGraphic() ? STR_ObjNamePluralGRAFBMPLNK : STR_ObjNamePluralGRAFBMP ) ); - case GRAPHIC_GDIMETAFILE: - rName=ImpGetResStr( IsLinkedGraphic() ? STR_ObjNamePluralGRAFMTFLNK : STR_ObjNamePluralGRAFMTF ); - break; + rName=ImpGetResStr( nId ); + } + break; - case GRAPHIC_NONE: - rName=ImpGetResStr( IsLinkedGraphic() ? STR_ObjNamePluralGRAFNONELNK : STR_ObjNamePluralGRAFNONE ); - break; + case GRAPHIC_GDIMETAFILE: + rName=ImpGetResStr( IsLinkedGraphic() ? STR_ObjNamePluralGRAFMTFLNK : STR_ObjNamePluralGRAFMTF ); + break; - default: - rName=ImpGetResStr( IsLinkedGraphic() ? STR_ObjNamePluralGRAFLNK : STR_ObjNamePluralGRAF ); - break; - } + case GRAPHIC_NONE: + rName=ImpGetResStr( IsLinkedGraphic() ? STR_ObjNamePluralGRAFNONELNK : STR_ObjNamePluralGRAFNONE ); + break; + + default: + rName=ImpGetResStr( IsLinkedGraphic() ? STR_ObjNamePluralGRAFLNK : STR_ObjNamePluralGRAF ); + break; + } + } - const String aName(GetName()); + const String aName(GetName()); - if( aName.Len() ) - { - rName.AppendAscii( " '" ); - rName += aName; - rName += sal_Unicode( '\'' ); + if( aName.Len() ) + { + rName.AppendAscii( " '" ); + rName += aName; + rName += sal_Unicode( '\'' ); + } } } @@ -1055,11 +1091,57 @@ const GDIMetaFile* SdrGrafObj::GetGDIMetaFile() const // ----------------------------------------------------------------------------- +bool SdrGrafObj::isEmbeddedSvg() const +{ + return GRAPHIC_BITMAP == GetGraphicType() && GetGraphic().getSvgData().get(); +} + +GDIMetaFile SdrGrafObj::getMetafileFromEmbeddedSvg() const +{ + GDIMetaFile aRetval; + + if(isEmbeddedSvg() && GetModel()) + { + VirtualDevice aOut; + const Rectangle aBoundRect(GetCurrentBoundRect()); + const MapMode aMap(GetModel()->GetScaleUnit(), Point(), GetModel()->GetScaleFraction(), GetModel()->GetScaleFraction()); + + aOut.EnableOutput(false); + aOut.SetMapMode(aMap); + aRetval.Record(&aOut); + SingleObjectPainter(aOut); + aRetval.Stop(); + aRetval.WindStart(); + aRetval.Move(-aBoundRect.Left(), -aBoundRect.Top()); + aRetval.SetPrefMapMode(aMap); + aRetval.SetPrefSize(aBoundRect.GetSize()); + } + + return aRetval; +} + SdrObject* SdrGrafObj::DoConvertToPolyObj(sal_Bool bBezier, bool bAddText) const { SdrObject* pRetval = NULL; + GraphicType aGraphicType(GetGraphicType()); + GDIMetaFile aMtf; + + if(isEmbeddedSvg()) + { + // Embedded Svg + // There is currently no helper to create SdrObjects from primitives (even if I'm thinking + // about writing one for some time). To get the roundtrip to SdrObjects it is necessary to + // use the old converter path over the MetaFile mechanism. Create Metafile from Svg + // primitives here pretty directly + aMtf = getMetafileFromEmbeddedSvg(); + aGraphicType = GRAPHIC_GDIMETAFILE; + } + else if(GRAPHIC_GDIMETAFILE == aGraphicType) + { + aMtf = GetTransformedGraphic(SDRGRAFOBJ_TRANSFORMATTR_COLOR|SDRGRAFOBJ_TRANSFORMATTR_MIRROR).GetGDIMetaFile(); + } - switch( GetGraphicType() ) + switch(aGraphicType) { case GRAPHIC_GDIMETAFILE: { @@ -1069,14 +1151,12 @@ SdrObject* SdrGrafObj::DoConvertToPolyObj(sal_Bool bBezier, bool bAddText) const aFilter.SetLayer(GetLayer()); SdrObjGroup* pGrp = new SdrObjGroup(); - sal_uInt32 nInsAnz = aFilter.DoImport(GetTransformedGraphic( - SDRGRAFOBJ_TRANSFORMATTR_COLOR|SDRGRAFOBJ_TRANSFORMATTR_MIRROR).GetGDIMetaFile(), - *pGrp->GetSubList(), 0); + sal_uInt32 nInsAnz = aFilter.DoImport(aMtf, *pGrp->GetSubList(), 0); if(nInsAnz) { { - // copy transformation + // copy transformation GeoStat aGeoStat(GetGeoStat()); if(aGeoStat.nShearWink) @@ -1343,9 +1423,6 @@ IMPL_LINK( SdrGrafObj, ImpSwapHdl, GraphicObject*, pO ) if(mbInsidePaint && !GetViewContact().HasViewObjectContacts(true)) { -// Rectangle aSnapRect(GetSnapRect()); -// const Rectangle aSnapRectPixel(pOutDev->LogicToPixel(aSnapRect)); - pFilterData = new com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValue >( 3 ); com::sun::star::awt::Size aPreviewSizeHint( 64, 64 ); @@ -1361,8 +1438,9 @@ IMPL_LINK( SdrGrafObj, ImpSwapHdl, GraphicObject*, pO ) mbIsPreview = sal_True; } - if( !GraphicFilter::GetGraphicFilter()->ImportGraphic( aGraphic, String(), *pStream, - GRFILTER_FORMAT_DONTKNOW, NULL, 0, pFilterData ) ) + if(!GraphicFilter::GetGraphicFilter()->ImportGraphic( + aGraphic, aStreamInfo.maUserData, *pStream, + GRFILTER_FORMAT_DONTKNOW, NULL, 0, pFilterData)) { const String aUserData( pGraphic->GetUserData() ); diff --git a/svx/source/svdraw/svdorect.cxx b/svx/source/svdraw/svdorect.cxx index a987ce22cf13..8d21289d593c 100644 --- a/svx/source/svdraw/svdorect.cxx +++ b/svx/source/svdraw/svdorect.cxx @@ -591,7 +591,10 @@ SdrObject* SdrRectObj::DoConvertToPolyObj(sal_Bool bBezier, bool bAddText) const aPolyPolygon.removeDoublePoints(); SdrObject* pRet = 0L; - if(!IsTextFrame() || HasFill() || HasLine()) + // small correction: Do not create something when no fill and no line. To + // be sure to not damage something with non-text frames, do this only + // when used with bAddText==false from other converters + if((bAddText && !IsTextFrame()) || HasFill() || HasLine()) { pRet = ImpConvertMakeObj(aPolyPolygon, sal_True, bBezier); } diff --git a/svx/source/svdraw/svdstr.src b/svx/source/svdraw/svdstr.src index a39e8f7b686d..368fa4082520 100644 --- a/svx/source/svdraw/svdstr.src +++ b/svx/source/svdraw/svdstr.src @@ -474,7 +474,21 @@ String STR_ObjNamePluralGRAFMACLNK { Text [ en-US ] = "Linked Mac graphics" ; }; - //////////////////////////////////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// Svg support + +String STR_ObjNameSingulGRAFSVG +{ + Text [ en-US ] = "SVG" ; +}; +String STR_ObjNamePluralGRAFSVG +{ + Text [ en-US ] = "SVGs" ; +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + String STR_ObjNameSingulOLE2 { Text [ en-US ] = "embedded object (OLE)" ; diff --git a/svx/source/svdraw/svdxcgv.cxx b/svx/source/svdraw/svdxcgv.cxx index a43a9dc870e9..e9d4297d0104 100644 --- a/svx/source/svdraw/svdxcgv.cxx +++ b/svx/source/svdraw/svdxcgv.cxx @@ -529,19 +529,33 @@ void SdrExchangeView::ImpPasteObject(SdrObject* pObj, SdrObjList& rLst, const Po //////////////////////////////////////////////////////////////////////////////////////////////////// -Bitmap SdrExchangeView::GetMarkedObjBitmap( sal_Bool bNoVDevIfOneBmpMarked ) const +BitmapEx SdrExchangeView::GetMarkedObjBitmap( bool bNoVDevIfOneBmpMarked ) const { - Bitmap aBmp; + BitmapEx aBmp; if( AreObjectsMarked() ) { - if( bNoVDevIfOneBmpMarked ) + if(1 == GetMarkedObjectCount()) { - SdrObject* pGrafObjTmp = GetMarkedObjectByIndex( 0 ); - SdrGrafObj* pGrafObj = ( GetMarkedObjectCount() == 1 ) ? PTR_CAST( SdrGrafObj, pGrafObjTmp ) : NULL; + if(bNoVDevIfOneBmpMarked) + { + SdrObject* pGrafObjTmp = GetMarkedObjectByIndex( 0 ); + SdrGrafObj* pGrafObj = ( GetMarkedObjectCount() == 1 ) ? PTR_CAST( SdrGrafObj, pGrafObjTmp ) : NULL; + + if( pGrafObj && ( pGrafObj->GetGraphicType() == GRAPHIC_BITMAP ) ) + { + aBmp = pGrafObj->GetTransformedGraphic().GetBitmapEx(); + } + } + else + { + const SdrGrafObj* pSdrGrafObj = dynamic_cast< const SdrGrafObj* >(GetMarkedObjectByIndex(0)); - if( pGrafObj && ( pGrafObj->GetGraphicType() == GRAPHIC_BITMAP ) ) - aBmp = pGrafObj->GetTransformedGraphic().GetBitmap(); + if(pSdrGrafObj && pSdrGrafObj->isEmbeddedSvg()) + { + aBmp = pSdrGrafObj->GetGraphic().getSvgData()->getReplacement(); + } + } } if( !aBmp ) @@ -557,7 +571,7 @@ Bitmap SdrExchangeView::GetMarkedObjBitmap( sal_Bool bNoVDevIfOneBmpMarked ) con aDrawinglayerOpt.IsAntiAliasing(), aDrawinglayerOpt.IsSnapHorVerLinesToDiscrete()); - aBmp = aGraphic.GetBitmap(aParameters); + aBmp = aGraphic.GetBitmapEx(aParameters); } } @@ -665,10 +679,18 @@ Graphic SdrExchangeView::GetObjGraphic( const SdrModel* pModel, const SdrObject* if(pSdrGrafObj) { - // #110981# Make behaviour coherent with metafile - // recording below (which of course also takes - // view-transformed objects) - aRet = pSdrGrafObj->GetTransformedGraphic(); + if(pSdrGrafObj->isEmbeddedSvg()) + { + // get Metafile for Svg content + aRet = pSdrGrafObj->getMetafileFromEmbeddedSvg(); + } + else + { + // #110981# Make behaviour coherent with metafile + // recording below (which of course also takes + // view-transformed objects) + aRet = pSdrGrafObj->GetTransformedGraphic(); + } } else if(pSdrOle2Obj) { diff --git a/svx/source/tbxctrls/grafctrl.cxx b/svx/source/tbxctrls/grafctrl.cxx index 5077d3e8f830..af026ef86bb6 100644 --- a/svx/source/tbxctrls/grafctrl.cxx +++ b/svx/source/tbxctrls/grafctrl.cxx @@ -1145,8 +1145,7 @@ void SvxGrafAttrHelper::GetGrafAttrState( SfxItemSet& rSet, SdrView& rView ) if( !pGrafObj || ( pGrafObj->GetGraphicType() == GRAPHIC_NONE ) || - ( pGrafObj->GetGraphicType() == GRAPHIC_DEFAULT ) || - pGrafObj->HasRenderGraphic() ) + ( pGrafObj->GetGraphicType() == GRAPHIC_DEFAULT )) { bEnableColors = bEnableTransparency = bEnableCrop = false; break; diff --git a/svx/source/unodraw/unoshap2.cxx b/svx/source/unodraw/unoshap2.cxx index c6ab5315a32d..5e9794570475 100644 --- a/svx/source/unodraw/unoshap2.cxx +++ b/svx/source/unodraw/unoshap2.cxx @@ -1843,6 +1843,20 @@ bool SvxGraphicObject::getPropertyValueImpl( const ::rtl::OUString& rName, const break; } + case OWN_ATTR_REPLACEMENTGRAFURL: + { + const GraphicObject* pGrafObj = static_cast< SdrGrafObj* >(mpObj.get())->GetReplacementGraphicObject(); + + if(pGrafObj) + { + OUString aURL(RTL_CONSTASCII_USTRINGPARAM(UNO_NAME_GRAPHOBJ_URLPREFIX)); + aURL += OUString::createFromAscii(pGrafObj->GetUniqueID().GetBuffer()); + rValue <<= aURL; + } + + break; + } + case OWN_ATTR_GRAFSTREAMURL: { const OUString aStreamURL( ( (SdrGrafObj*) mpObj.get() )->GetGrafStreamURL() ); diff --git a/svx/source/xml/xmlgrhlp.cxx b/svx/source/xml/xmlgrhlp.cxx index de941670b624..5ff20b338559 100644 --- a/svx/source/xml/xmlgrhlp.cxx +++ b/svx/source/xml/xmlgrhlp.cxx @@ -149,7 +149,7 @@ SvXMLGraphicInputStream::SvXMLGraphicInputStream( const ::rtl::OUString& rGraphi { pStm->SetVersion( SOFFICE_FILEFORMAT_8 ); pStm->SetCompressMode( COMPRESSMODE_ZBITMAP ); - ( (GDIMetaFile&) aGraphic.GetGDIMetaFile() ).Write( *pStm, GDIMETAFILE_WRITE_REPLACEMENT_RENDERGRAPHIC ); + ( (GDIMetaFile&) aGraphic.GetGDIMetaFile() ).Write( *pStm ); bRet = ( pStm->GetError() == 0 ); } } @@ -645,7 +645,7 @@ sal_Bool SvXMLGraphicHelper::ImplWriteGraphic( const ::rtl::OUString& rPictureSt pStream->Write( rLink.GetData(), rLink.GetDataSize() ); } else - rMtf.Write( *pStream, GDIMETAFILE_WRITE_REPLACEMENT_RENDERGRAPHIC ); + rMtf.Write( *pStream ); bRet = ( pStream->GetError() == 0 ); } diff --git a/sw/inc/cmdid.h b/sw/inc/cmdid.h index 9ec153757f35..f11f2116bc48 100644 --- a/sw/inc/cmdid.h +++ b/sw/inc/cmdid.h @@ -910,6 +910,8 @@ Achtung: Ab sofort sind in diesem File keine C++-Kommentare (//) mehr #define FN_EMBEDDED_OBJECT (FN_EXTRA2 + 116) +#define FN_UNO_REPLACEMENT_GRAPHIC_U_R_L (FN_EXTRA2 + 117) + /*-------------------------------------------------------------------- Bereich: Hilfe --------------------------------------------------------------------*/ diff --git a/sw/inc/ndgrf.hxx b/sw/inc/ndgrf.hxx index 0211ea79848a..e6a0cd5d544f 100644 --- a/sw/inc/ndgrf.hxx +++ b/sw/inc/ndgrf.hxx @@ -46,6 +46,7 @@ class SW_DLLPUBLIC SwGrfNode: public SwNoTxtNode friend class SwNodes; GraphicObject aGrfObj; + GraphicObject* mpReplacementGraphic; ::sfx2::SvBaseLinkRef refLink; // falls Grafik nur als Link, dann Pointer gesetzt Size nGrfSize; // String aStrmName; // SW3: Name des Storage-Streams fuer Embedded @@ -146,6 +147,7 @@ public: const Graphic& GetGrf() const { return aGrfObj.GetGraphic(); } const GraphicObject& GetGrfObj() const { return aGrfObj; } GraphicObject& GetGrfObj() { return aGrfObj; } + const GraphicObject* GetReplacementGrfObj() const; virtual SwCntntNode *SplitCntntNode( const SwPosition & ); diff --git a/sw/inc/unoprnms.hxx b/sw/inc/unoprnms.hxx index 802635083104..12a2eb930bb1 100644 --- a/sw/inc/unoprnms.hxx +++ b/sw/inc/unoprnms.hxx @@ -803,7 +803,10 @@ enum SwPropNameIds /* 0738 */ UNO_NAME_META, // #i91565# /* 0739 */ UNO_NAME_NESTED_TEXT_CONTENT, // #i109601# /* 0740 */ UNO_NAME_EMBEDDED_OBJECT, -/* 0741 */ SW_PROPNAME_END + +/* 0741 */ UNO_NAME_REPLACEMENT_GRAPHIC_URL, + +/* 0742 */ SW_PROPNAME_END }; diff --git a/sw/source/core/doc/notxtfrm.cxx b/sw/source/core/doc/notxtfrm.cxx index 7a9d733f9592..01bdd1a04cfa 100644 --- a/sw/source/core/doc/notxtfrm.cxx +++ b/sw/source/core/doc/notxtfrm.cxx @@ -78,6 +78,11 @@ #include <dview.hxx> // <-- +#include <basegfx/matrix/b2dhommatrix.hxx> +#include <svx/sdr/contact/objectcontacttools.hxx> +#include <drawinglayer/processor2d/baseprocessor2d.hxx> +#include <basegfx/matrix/b2dhommatrixtools.hxx> + using namespace com::sun::star; #define DEFTEXTSIZE 12 @@ -941,9 +946,101 @@ void SwNoTxtFrm::PaintPicture( OutputDevice* pOut, const SwRect &rGrfArea ) cons 0, GRFMGR_DRAW_STANDARD, pVout ); } else - rGrfObj.DrawWithPDFHandling( *pOut, - aAlignedGrfArea.Pos(), aAlignedGrfArea.SSize(), - &aGrfAttr ); + { + const SvgDataPtr& rSvgDataPtr = rGrfObj.GetGraphic().getSvgData(); + bool bDone(false); + + if(rSvgDataPtr.get()) + { + // Graphic is Svg and can be painted as primitives (vector graphic) + const basegfx::B2DRange& rRange = rSvgDataPtr->getRange(); + const double fWidth(rRange.getWidth()); + const double fHeight(rRange.getHeight()); + const drawinglayer::primitive2d::Primitive2DSequence& rSequence = rSvgDataPtr->getPrimitive2DSequence(); + + if(rSequence.hasElements() && !basegfx::fTools::equalZero(fWidth) && !basegfx::fTools::equalZero(fHeight)) + { + // get target range + const basegfx::B2DRange aTargetRange( + aAlignedGrfArea.Left(), aAlignedGrfArea.Top(), + aAlignedGrfArea.Right(), aAlignedGrfArea.Bottom()); + + // prepare evtl. cropped range + basegfx::B2DRange aCroppedTargetRange(aTargetRange); + + if(aGrfAttr.IsCropped()) + { + // calculate original TargetRange + const double fFactor100thmmToTwips(72.0 / 127.0); + + aCroppedTargetRange = basegfx::B2DRange( + aTargetRange.getMinX() - (aGrfAttr.GetLeftCrop() * fFactor100thmmToTwips), + aTargetRange.getMinY() - (aGrfAttr.GetTopCrop() * fFactor100thmmToTwips), + aTargetRange.getMaxX() + (aGrfAttr.GetRightCrop() * fFactor100thmmToTwips), + aTargetRange.getMaxY() + (aGrfAttr.GetBottomCrop() * fFactor100thmmToTwips)); + } + + const double fTargetWidth(aCroppedTargetRange.getWidth()); + const double fTargetHeight(aCroppedTargetRange.getHeight()); + + if(!basegfx::fTools::equalZero(fTargetWidth) && !basegfx::fTools::equalZero(fTargetHeight)) + { + // map graphic range to target range. This will automatically include + // tme mapping from Svg 1/100th mm content to twips since the target + // range is twips already + basegfx::B2DHomMatrix aMappingTransform( + basegfx::tools::createTranslateB2DHomMatrix( + -rRange.getMinX(), + -rRange.getMinY())); + + aMappingTransform.scale(fTargetWidth / fWidth, fTargetHeight / fHeight); + aMappingTransform.translate(aCroppedTargetRange.getMinX(), aCroppedTargetRange.getMinY()); + + // check for and apply mirrorings + const bool bMirrorHor(aGrfAttr.GetMirrorFlags() & BMP_MIRROR_HORZ); + const bool bMirrorVer(aGrfAttr.GetMirrorFlags() & BMP_MIRROR_VERT); + + if(bMirrorHor || bMirrorVer) + { + aMappingTransform.translate(-aCroppedTargetRange.getCenterX(), -aCroppedTargetRange.getCenterY()); + aMappingTransform.scale(bMirrorHor ? -1.0 : 1.0, bMirrorVer ? -1.0 : 1.0); + aMappingTransform.translate(aCroppedTargetRange.getCenterX(), aCroppedTargetRange.getCenterY()); + } + + // Fill ViewInformation. Use MappingTransform here, so there is no need to + // embed the primitives to it. Use original TargetRange here so there is also + // no need to embed the primitives to a MaskPrimitive for cropping. This works + // only in this case where the graphic object cannot be rotated, though. + const drawinglayer::geometry::ViewInformation2D aViewInformation2D( + aMappingTransform, + pOut->GetViewTransformation(), + aTargetRange, + 0, + 0.0, + com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValue >()); + + // get a primitive processor for rendering + drawinglayer::processor2d::BaseProcessor2D* pProcessor2D = sdr::contact::createBaseProcessor2DFromOutputDevice( + *pOut, + aViewInformation2D); + + if(pProcessor2D) + { + // render and cleanup + pProcessor2D->process(rSequence); + delete pProcessor2D; + bDone = true; + } + } + } + } + + if(!bDone) + { + // fallback paint, uses replacement image + rGrfObj.DrawWithPDFHandling(*pOut, aAlignedGrfArea.Pos(), aAlignedGrfArea.SSize(), &aGrfAttr); + } + } } else { diff --git a/sw/source/core/graphic/ndgrf.cxx b/sw/source/core/graphic/ndgrf.cxx index c6d792690413..cd68a0df3e3e 100755 --- a/sw/source/core/graphic/ndgrf.cxx +++ b/sw/source/core/graphic/ndgrf.cxx @@ -73,6 +73,8 @@ SwGrfNode::SwGrfNode( SwGrfFmtColl *pGrfColl, SwAttrSet* pAutoAttr ) : SwNoTxtNode( rWhere, ND_GRFNODE, pGrfColl, pAutoAttr ), + aGrfObj(), + mpReplacementGraphic(0), // --> OD 2007-01-23 #i73788# mbLinkedInputStreamReady( false ), mbIsStreamReadOnly( sal_False ) @@ -90,6 +92,8 @@ SwGrfNode::SwGrfNode( const SwNodeIndex & rWhere, const GraphicObject& rGrfObj, SwGrfFmtColl *pGrfColl, SwAttrSet* pAutoAttr ) : SwNoTxtNode( rWhere, ND_GRFNODE, pGrfColl, pAutoAttr ), + aGrfObj(rGrfObj), + mpReplacementGraphic(0), // --> OD 2007-01-23 #i73788# mbLinkedInputStreamReady( false ), mbIsStreamReadOnly( sal_False ) @@ -113,6 +117,8 @@ SwGrfNode::SwGrfNode( const SwNodeIndex & rWhere, SwGrfFmtColl *pGrfColl, SwAttrSet* pAutoAttr ) : SwNoTxtNode( rWhere, ND_GRFNODE, pGrfColl, pAutoAttr ), + aGrfObj(), + mpReplacementGraphic(0), // --> OD 2007-01-23 #i73788# mbLinkedInputStreamReady( false ), mbIsStreamReadOnly( sal_False ) @@ -146,6 +152,8 @@ sal_Bool SwGrfNode::ReRead( sal_Bool bNewGrf ) { sal_Bool bReadGrf = sal_False, bSetTwipSize = sal_True; + delete mpReplacementGraphic; + mpReplacementGraphic = 0; ASSERT( pGraphic || pGrfObj || rGrfName.Len(), "GraphicNode without a name, Graphic or GraphicObject" ); @@ -315,6 +323,9 @@ sal_Bool SwGrfNode::ReRead( SwGrfNode::~SwGrfNode() { + delete mpReplacementGraphic; + mpReplacementGraphic = 0; + // --> OD 2007-03-30 #i73788# mpThreadConsumer.reset(); // <-- @@ -348,6 +359,21 @@ SwGrfNode::~SwGrfNode() } +const GraphicObject* SwGrfNode::GetReplacementGrfObj() const +{ + if(!mpReplacementGraphic) + { + const SvgDataPtr& rSvgDataPtr = GetGrfObj().GetGraphic().getSvgData(); + + if(rSvgDataPtr.get()) + { + const_cast< SwGrfNode* >(this)->mpReplacementGraphic = new GraphicObject(rSvgDataPtr->getReplacement()); + } + } + + return mpReplacementGraphic; +} + SwCntntNode *SwGrfNode::SplitCntntNode( const SwPosition & ) { return this; @@ -394,12 +420,15 @@ Size SwGrfNode::GetTwipSize() const sal_Bool SwGrfNode::ImportGraphic( SvStream& rStrm ) { Graphic aGraphic; - if( !GraphicFilter::GetGraphicFilter()->ImportGraphic( aGraphic, String(), rStrm ) ) + const String aURL(aGrfObj.GetUserData()); + + if(!GraphicFilter::GetGraphicFilter()->ImportGraphic(aGraphic, aURL, rStrm)) { - const String aUserData( aGrfObj.GetUserData() ); + delete mpReplacementGraphic; + mpReplacementGraphic = 0; aGrfObj.SetGraphic( aGraphic ); - aGrfObj.SetUserData( aUserData ); + aGrfObj.SetUserData( aURL ); return sal_True; } @@ -432,6 +461,9 @@ short SwGrfNode::SwapIn( sal_Bool bWaitForData ) else if( GRAPHIC_DEFAULT == aGrfObj.GetType() ) { // keine default Bitmap mehr, also neu Painten! + delete mpReplacementGraphic; + mpReplacementGraphic = 0; + aGrfObj.SetGraphic( Graphic() ); SwMsgPoolItem aMsgHint( RES_GRAPHIC_PIECE_ARRIVED ); ModifyNotification( &aMsgHint, &aMsgHint ); @@ -904,7 +936,8 @@ SwCntntNode* SwGrfNode::MakeCopy( SwDoc* pDoc, const SwNodeIndex& rIdx ) const SvStream* pStrm = _GetStreamForEmbedGrf( refPics, aStrmName ); if ( pStrm ) { - GraphicFilter::GetGraphicFilter()->ImportGraphic( aTmpGrf, String(), *pStrm ); + const String aURL(aGrfObj.GetUserData()); + GraphicFilter::GetGraphicFilter()->ImportGraphic(aTmpGrf, aURL, *pStrm); delete pStrm; } // <-- diff --git a/sw/source/core/unocore/unoframe.cxx b/sw/source/core/unocore/unoframe.cxx index 629e8454fff5..69320b30f7ee 100755 --- a/sw/source/core/unocore/unoframe.cxx +++ b/sw/source/core/unocore/unoframe.cxx @@ -1499,6 +1499,30 @@ uno::Any SwXFrame::getPropertyValue(const OUString& rPropertyName) } aAny <<= OUString(sGrfName); } + else if( FN_UNO_REPLACEMENT_GRAPHIC_U_R_L == pEntry->nWID) + { + String sGrfName; + const SwNodeIndex* pIdx = pFmt->GetCntnt().GetCntntIdx(); + + if(pIdx) + { + SwNodeIndex aIdx(*pIdx, 1); + SwGrfNode* pGrfNode = aIdx.GetNode().GetGrfNode(); + if(!pGrfNode) + throw uno::RuntimeException(); + + const GraphicObject* pGraphicObject = pGrfNode->GetReplacementGrfObj(); + + if(pGraphicObject) + { + String sPrefix( RTL_CONSTASCII_STRINGPARAM(sGraphicObjectProtocol) ); + String sId( pGraphicObject->GetUniqueID(), RTL_TEXTENCODING_ASCII_US ); + (sGrfName = sPrefix) += sId; + } + } + + aAny <<= OUString(sGrfName); + } else if( FN_UNO_GRAPHIC_FILTER == pEntry->nWID ) { String sFltName; diff --git a/sw/source/core/unocore/unomap.cxx b/sw/source/core/unocore/unomap.cxx index ca5def979e25..81ac8375c19a 100644 --- a/sw/source/core/unocore/unomap.cxx +++ b/sw/source/core/unocore/unomap.cxx @@ -1108,6 +1108,7 @@ const SfxItemPropertyMapEntry* SwUnoPropertyMapProvider::GetPropertyMapEntries(s { SW_PROP_NMID(UNO_NAME_HORI_MIRRORED_ON_ODD_PAGES), RES_GRFATR_MIRRORGRF, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, MID_MIRROR_HORZ_ODD_PAGES }, { SW_PROP_NMID(UNO_NAME_VERT_MIRRORED), RES_GRFATR_MIRRORGRF, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, MID_MIRROR_VERT }, { SW_PROP_NMID(UNO_NAME_GRAPHIC_URL), FN_UNO_GRAPHIC_U_R_L, CPPU_E2T(CPPUTYPE_OUSTRING), 0, 0 }, + { SW_PROP_NMID(UNO_NAME_REPLACEMENT_GRAPHIC_URL), FN_UNO_REPLACEMENT_GRAPHIC_U_R_L, CPPU_E2T(CPPUTYPE_OUSTRING), 0, 0 }, { SW_PROP_NMID(UNO_NAME_GRAPHIC_FILTER), FN_UNO_GRAPHIC_FILTER, CPPU_E2T(CPPUTYPE_OUSTRING), 0, 0 }, { SW_PROP_NMID(UNO_NAME_GRAPHIC), FN_UNO_GRAPHIC, CPPU_E2T(CPPUTYPE_REFXGRAPHIC), 0, 0 }, { SW_PROP_NMID(UNO_NAME_ACTUAL_SIZE), FN_UNO_ACTUAL_SIZE, CPPU_E2T(CPPUTYPE_AWTSIZE), PropertyAttribute::READONLY, CONVERT_TWIPS}, diff --git a/sw/source/core/unocore/unoprnms.cxx b/sw/source/core/unocore/unoprnms.cxx index 12330e831c3e..de157ad95dd0 100644 --- a/sw/source/core/unocore/unoprnms.cxx +++ b/sw/source/core/unocore/unoprnms.cxx @@ -776,6 +776,7 @@ const SwPropNameTab aPropNameTab = { /* 0738 UNO_NAME_META */ {MAP_CHAR_LEN("InContentMetadata")}, /* 0739 UNO_NAME_NESTED_TEXT_CONTENT */ {MAP_CHAR_LEN("NestedTextContent")}, /* 0740 UNO_NAME_EMBEDDED_OBJECT */ {MAP_CHAR_LEN("EmbeddedObject")}, +/* 0741 UNO_NAME_REPLACEMENT_GRAPHIC_URL */ {MAP_CHAR_LEN("ReplacementGraphicURL")}, }; const SwPropNameLen& SwGetPropName( sal_uInt16 nId ) diff --git a/sw/source/ui/shells/grfsh.cxx b/sw/source/ui/shells/grfsh.cxx index 23e4799c52e6..7c869c6f3024 100644 --- a/sw/source/ui/shells/grfsh.cxx +++ b/sw/source/ui/shells/grfsh.cxx @@ -515,13 +515,6 @@ void SwGrfShell::GetAttrState(SfxItemSet &rSet) rSh.GetCurAttr( aCoreSet ); sal_Bool bParentCntProt = 0 != rSh.IsSelObjProtected( FLYPROTECT_CONTENT|FLYPROTECT_PARENT ); sal_Bool bIsGrfCntnt = CNT_GRF == GetShell().GetCntType(); -// const GraphicObject* pGrfObj = ( bIsGrfCntnt ? rSh.GetGraphicObj() : NULL ); -// sal_Bool bIsRenderGraphicGrfCntnt = ( pGrfObj && pGrfObj->IsRenderGraphic() ); - - // --> OD 2006-11-03 #i59688# -// sal_Bool bSwappedOut = rSh.IsGrfSwapOut( sal_True ); -// sal_Bool bBitmapType = !bSwappedOut && GRAPHIC_BITMAP == rSh.GetGraphicType(); - // <-- SetGetStateSet( &rSet ); diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk index 02f3b1d3d6c7..8df615880ea8 100755 --- a/vcl/Library_vcl.mk +++ b/vcl/Library_vcl.mk @@ -379,13 +379,11 @@ $(eval $(call gb_Library_add_exception_objects,vcl,\ vcl/source/gdi/print \ vcl/source/gdi/regband \ vcl/source/gdi/region \ - vcl/source/gdi/rendergraphic \ - vcl/source/gdi/rendergraphicrasterizer \ vcl/source/gdi/salgdilayout \ vcl/source/gdi/sallayout \ vcl/source/gdi/salmisc \ vcl/source/gdi/salnativewidgets-none \ - vcl/source/gdi/svgread \ + vcl/source/gdi/svgdata \ vcl/source/gdi/textlayout \ vcl/source/gdi/virdev \ vcl/source/gdi/wall \ diff --git a/vcl/Package_inc.mk b/vcl/Package_inc.mk index f45f2b9c3917..15c322381ddf 100644 --- a/vcl/Package_inc.mk +++ b/vcl/Package_inc.mk @@ -119,8 +119,6 @@ $(eval $(call gb_Package_add_file,vcl_inc,inc/vcl/ptrstyle.hxx,vcl/ptrstyle.hxx) $(eval $(call gb_Package_add_file,vcl_inc,inc/vcl/quickselectionengine.hxx,vcl/quickselectionengine.hxx)) $(eval $(call gb_Package_add_file,vcl_inc,inc/vcl/regband.hxx,vcl/regband.hxx)) $(eval $(call gb_Package_add_file,vcl_inc,inc/vcl/region.hxx,vcl/region.hxx)) -$(eval $(call gb_Package_add_file,vcl_inc,inc/vcl/rendergraphicrasterizer.hxx,vcl/rendergraphicrasterizer.hxx)) -$(eval $(call gb_Package_add_file,vcl_inc,inc/vcl/rendergraphic.hxx,vcl/rendergraphic.hxx)) $(eval $(call gb_Package_add_file,vcl_inc,inc/vcl/salbtype.hxx,vcl/salbtype.hxx)) $(eval $(call gb_Package_add_file,vcl_inc,inc/vcl/salctype.hxx,vcl/salctype.hxx)) $(eval $(call gb_Package_add_file,vcl_inc,inc/vcl/salgtype.hxx,vcl/salgtype.hxx)) @@ -141,7 +139,7 @@ $(eval $(call gb_Package_add_file,vcl_inc,inc/vcl/stdtext.hxx,vcl/stdtext.hxx)) $(eval $(call gb_Package_add_file,vcl_inc,inc/vcl/strhelper.hxx,vcl/strhelper.hxx)) $(eval $(call gb_Package_add_file,vcl_inc,inc/vcl/svapp.hxx,vcl/svapp.hxx)) $(eval $(call gb_Package_add_file,vcl_inc,inc/vcl/sv.h,vcl/sv.h)) -$(eval $(call gb_Package_add_file,vcl_inc,inc/vcl/svgread.hxx,vcl/svgread.hxx)) +$(eval $(call gb_Package_add_file,vcl_inc,inc/vcl/svgdata.hxx,vcl/svgdata.hxx)) $(eval $(call gb_Package_add_file,vcl_inc,inc/vcl/symbol.hxx,vcl/symbol.hxx)) $(eval $(call gb_Package_add_file,vcl_inc,inc/vcl/syschild.hxx,vcl/syschild.hxx)) $(eval $(call gb_Package_add_file,vcl_inc,inc/vcl/sysdata.hxx,vcl/sysdata.hxx)) diff --git a/vcl/inc/impgraph.hxx b/vcl/inc/impgraph.hxx index e136fcc06ade..d432b347ce75 100644 --- a/vcl/inc/impgraph.hxx +++ b/vcl/inc/impgraph.hxx @@ -33,8 +33,8 @@ #include <vcl/bitmapex.hxx> #include <vcl/animate.hxx> #include <vcl/gdimtf.hxx> -#include <vcl/rendergraphic.hxx> #include <vcl/graph.h> +#include <vcl/svgdata.hxx> // --------------- // - ImpSwapInfo - @@ -70,11 +70,14 @@ private: GfxLink* mpGfxLink; GraphicType meType; String maDocFileURLStr; - sal_uLong mnDocFilePos; - mutable sal_uLong mnSizeBytes; - sal_uLong mnRefCount; - sal_Bool mbSwapOut; - sal_Bool mbSwapUnderway; + sal_uLong mnDocFilePos; + mutable sal_uLong mnSizeBytes; + sal_uLong mnRefCount; + sal_Bool mbSwapOut; + sal_Bool mbSwapUnderway; + + // SvgData support + SvgDataPtr maSvgData; private: @@ -82,6 +85,7 @@ private: ImpGraphic( const ImpGraphic& rImpGraphic ); ImpGraphic( const Bitmap& rBmp ); ImpGraphic( const BitmapEx& rBmpEx ); + ImpGraphic(const SvgDataPtr& rSvgDataPtr); ImpGraphic( const Animation& rAnimation ); ImpGraphic( const GDIMetaFile& rMtf ); virtual ~ImpGraphic(); @@ -101,14 +105,11 @@ private: sal_Bool ImplIsAlpha() const; sal_Bool ImplIsAnimated() const; sal_Bool ImplIsEPS() const; - sal_Bool ImplIsRenderGraphic() const; - sal_Bool ImplHasRenderGraphic() const; Bitmap ImplGetBitmap(const GraphicConversionParameters& rParameters) const; BitmapEx ImplGetBitmapEx(const GraphicConversionParameters& rParameters) const; Animation ImplGetAnimation() const; const GDIMetaFile& ImplGetGDIMetaFile() const; - ::vcl::RenderGraphic ImplGetRenderGraphic() const; Size ImplGetPrefSize() const; @@ -177,6 +178,9 @@ private: friend SvStream& operator<<( SvStream& rOStm, const ImpGraphic& rImpGraphic ); friend SvStream& operator>>( SvStream& rIStm, ImpGraphic& rImpGraphic ); + + // SvgData support + const SvgDataPtr& getSvgData() const; }; #endif // _SV_IMPGRAPH_HXX diff --git a/vcl/inc/sallayout.hxx b/vcl/inc/sallayout.hxx index bb5c6e829a70..6e3719b60694 100755 --- a/vcl/inc/sallayout.hxx +++ b/vcl/inc/sallayout.hxx @@ -29,12 +29,8 @@ #define _SV_SALLAYOUT_HXX #include <tools/gen.hxx> - #include <vector> -namespace basegfx { - class B2DPolyPolygon; - typedef std::vector<B2DPolyPolygon> B2DPolyPolygonVector; -} +#include <basegfx/polygon/b2dpolypolygon.hxx> #ifndef _TOOLS_LANG_HXX typedef unsigned short LanguageType; diff --git a/vcl/inc/vcl/gdimtf.hxx b/vcl/inc/vcl/gdimtf.hxx index 9a0a16246130..790c410fe12b 100644 --- a/vcl/inc/vcl/gdimtf.hxx +++ b/vcl/inc/vcl/gdimtf.hxx @@ -64,15 +64,6 @@ class Gradient; #define MTF_MIRROR_HORZ 0x00000001UL #define MTF_MIRROR_VERT 0x00000002UL -// ----------------------------- -// - Write flags for streaming - -// ----------------------------- - -#define GDIMETAFILE_WRITE_DEFAULT 0x00000000 -#define GDIMETAFILE_WRITE_REPLACEMENT_RENDERGRAPHIC 0x00000001 - -typedef sal_uInt32 GDIMetaFileWriteFlags; - // --------- // - Enums - // --------- @@ -242,7 +233,7 @@ public: // Methoden zum Lesen und Schreiben des neuen Formats; // die Read-Methode kann auch das alte Format lesen SvStream& Read( SvStream& rIStm ); - SvStream& Write( SvStream& rOStm, GDIMetaFileWriteFlags = GDIMETAFILE_WRITE_DEFAULT ); + SvStream& Write( SvStream& rOStm ); // Stream-Operatoren schreiben das alte Format (noch) // und lesen sowohl das alte wie auch das neue Format diff --git a/vcl/inc/vcl/graph.hxx b/vcl/inc/vcl/graph.hxx index 4d70970008a7..cd30c305a7ae 100644 --- a/vcl/inc/vcl/graph.hxx +++ b/vcl/inc/vcl/graph.hxx @@ -31,10 +31,10 @@ #include <vcl/bitmapex.hxx> #include <vcl/animate.hxx> #include <vcl/gdimtf.hxx> -#include <vcl/rendergraphic.hxx> #include <vcl/graph.h> #include <vcl/gfxlink.hxx> #include <com/sun/star/uno/Reference.hxx> +#include <vcl/svgdata.hxx> namespace com { namespace sun { namespace star { namespace graphic { class XGraphic;} } } } @@ -100,6 +100,7 @@ public: Graphic( const Graphic& rGraphic ); Graphic( const Bitmap& rBmp ); Graphic( const BitmapEx& rBmpEx ); + Graphic(const SvgDataPtr& rSvgDataPtr); Graphic( const Animation& rAnimation ); Graphic( const GDIMetaFile& rMtf ); Graphic( const ::com::sun::star::uno::Reference< ::com::sun::star::graphic::XGraphic >& rxGraphic ); @@ -120,8 +121,6 @@ public: sal_Bool IsAlpha() const; sal_Bool IsAnimated() const; sal_Bool IsEPS() const; - sal_Bool IsRenderGraphic() const; - sal_Bool HasRenderGraphic() const; // #i102089# Access of Bitmap potentially will have to rasterconvert the Graphic // if it is a MetaFile. To be able to control this conversion it is necessary to @@ -133,7 +132,6 @@ public: Animation GetAnimation() const; const GDIMetaFile& GetGDIMetaFile() const; - ::vcl::RenderGraphic GetRenderGraphic() const; ::com::sun::star::uno::Reference< ::com::sun::star::graphic::XGraphic > GetXGraphic() const; @@ -217,6 +215,9 @@ public: virtual void Load( SvStream& ); virtual void Save( SvStream& ); virtual void Assign( const SvDataCopyStream& ); + + // SvgData support + const SvgDataPtr& getSvgData() const; }; #endif // _SV_GRAPH_HXX diff --git a/vcl/inc/vcl/metaact.hxx b/vcl/inc/vcl/metaact.hxx index d50e097ca50e..af1a55a3f519 100644 --- a/vcl/inc/vcl/metaact.hxx +++ b/vcl/inc/vcl/metaact.hxx @@ -38,7 +38,6 @@ #include <vcl/gdimtf.hxx> #include <vcl/gfxlink.hxx> #include <vcl/lineinfo.hxx> -#include <vcl/rendergraphic.hxx> class SvStream; @@ -99,7 +98,6 @@ class SvStream; #define META_LAYOUTMODE_ACTION (149) #define META_TEXTLANGUAGE_ACTION (150) #define META_OVERLINECOLOR_ACTION (151) -#define META_RENDERGRAPHIC_ACTION (152) #define META_COMMENT_ACTION (512) @@ -120,11 +118,9 @@ struct ImplMetaReadData struct ImplMetaWriteData { rtl_TextEncoding meActualCharSet; - GDIMetaFileWriteFlags mnWriteFlags; ImplMetaWriteData() : - meActualCharSet( RTL_TEXTENCODING_ASCII_US ), - mnWriteFlags( GDIMETAFILE_WRITE_DEFAULT ) + meActualCharSet( RTL_TEXTENCODING_ASCII_US ) { } }; @@ -1553,41 +1549,4 @@ public: LanguageType GetTextLanguage() const { return meTextLanguage; } }; -// --------------------------- -// - MetaRenderGraphicAction - -// --------------------------- - -class VCL_DLLPUBLIC MetaRenderGraphicAction : public MetaAction -{ -private: - - ::vcl::RenderGraphic maRenderGraphic; - Point maPoint; - Size maSize; - double mfRotateAngle; - double mfShearAngleX; - double mfShearAngleY; - - virtual sal_Bool Compare( const MetaAction& ) const; - -public: - DECL_META_ACTION( RenderGraphic, META_RENDERGRAPHIC_ACTION ) - - MetaRenderGraphicAction( const Point& rPoint, const Size& rSize, - const vcl::RenderGraphic& rRenderData, - double fRotateAngle = 0.0, - double fShearAngleX = 0.0, - double fShearAngleY = 0.0 ); - - virtual void Move( long nHorzMove, long nVertMove ); - virtual void Scale( double fScaleX, double fScaleY ); - - const ::vcl::RenderGraphic& GetRenderGraphic() const { return maRenderGraphic; } - const Point& GetPoint() const { return maPoint; } - const Size& GetSize() const { return maSize; } - double GetRotateAngle() const { return mfRotateAngle; } - double GetShearAngleX() const { return mfShearAngleX; } - double GetShearAngleY() const { return mfShearAngleY; } -}; - #endif // _SV_METAACT_HXX diff --git a/vcl/inc/vcl/outdev.hxx b/vcl/inc/vcl/outdev.hxx index 08a07b1238f7..30d8c0f3eaa0 100644 --- a/vcl/inc/vcl/outdev.hxx +++ b/vcl/inc/vcl/outdev.hxx @@ -40,6 +40,7 @@ #include <basegfx/vector/b2enums.hxx> #include <com/sun/star/uno/Reference.h> #include <unotools/fontdefs.hxx> +#include <basegfx/polygon/b2dpolypolygon.hxx> #include <vector> @@ -87,7 +88,6 @@ namespace basegfx { class B2DHomMatrix; class B2DPolygon; class B2DPolyPolygon; - typedef ::std::vector< B2DPolyPolygon > B2DPolyPolygonVector; } namespace com { @@ -104,7 +104,6 @@ namespace vcl class PDFWriterImpl; class ExtOutDevData; class ITextLayout; - class RenderGraphic; } #define OUTDEV_BUFFER_SIZE 128 @@ -813,9 +812,6 @@ public: bool DrawEPS( const Point& rPt, const Size& rSz, const GfxLink& rGfxLink, GDIMetaFile* pSubst = NULL ); - void DrawRenderGraphic( const Point& rPt, const Size& rSz, - const ::vcl::RenderGraphic& rRenderGraphic ); - Color GetPixel( const Point& rPt ) const; Color* GetPixel( const Polygon& rPts ) const; diff --git a/vcl/inc/vcl/rendergraphic.hxx b/vcl/inc/vcl/rendergraphic.hxx deleted file mode 100644 index 0a0f475decd6..000000000000 --- a/vcl/inc/vcl/rendergraphic.hxx +++ /dev/null @@ -1,124 +0,0 @@ -/************************************************************************* - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright 2000, 2010 Oracle and/or its affiliates. - * - * OpenOffice.org - a multi-platform office productivity suite - * - * This file is part of OpenOffice.org. - * - * OpenOffice.org is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 3 - * only, as published by the Free Software Foundation. - * - * OpenOffice.org 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 Lesser General Public License version 3 for more details - * (a copy is included in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU Lesser General Public License - * version 3 along with OpenOffice.org. If not, see - * <http://www.openoffice.org/license.html> - * for a copy of the LGPLv3 License. - * - ************************************************************************/ - -#ifndef _SV_RENDERGRAPHIC_HXX -#define _SV_RENDERGRAPHIC_HXX - -#include <vcl/dllapi.h> -#include <rtl/ustring.hxx> -#include <boost/shared_array.hpp> -#include <memory> - -class SvStream; -class MapMode; -class Size; -class BitmapEx; - -namespace vcl -{ - // ----------------- - // - RenderGraphic - - // ----------------- - class VCL_DLLPUBLIC RenderGraphic - { - public: - - typedef boost::shared_array< sal_uInt8 > GraphicData; - - friend VCL_DLLPUBLIC ::SvStream& operator>>( ::SvStream& rIStm, RenderGraphic& rRenderGraphic ); - friend VCL_DLLPUBLIC ::SvStream& operator<<( ::SvStream& rOStm, const RenderGraphic& rRenderGraphic ); - - public: - - RenderGraphic( ); - - RenderGraphic( const RenderGraphic& rRenderGraphic ); - - RenderGraphic( const GraphicData& rGraphicData, - sal_uInt32 nGraphicDataLength, - const rtl::OUString& rGraphicDataMimeType ); - - RenderGraphic( const rtl::OUString& rGraphicDataMimeType, - sal_uInt32 nGraphicDataLength, - const sal_uInt8* pGraphicData = NULL ); - - virtual ~RenderGraphic(); - - RenderGraphic& operator=(const RenderGraphic& rRenderGraphic ); - - bool operator==(const RenderGraphic& rRenderGraphic ) const; - - inline bool operator!=(const RenderGraphic& rRenderGraphic ) const - { - return( !( rRenderGraphic == *this ) ); - } - - bool IsEqual( const RenderGraphic& rRenderGraphic ) const; - - bool operator!() const; - - inline bool IsEmpty( ) const - { - return( !( *this ) ); - } - - inline const GraphicData& GetGraphicData( ) const - { - return( maGraphicData ); - } - - inline sal_uInt32 GetGraphicDataLength( ) const - { - return( mnGraphicDataLength ); - } - - inline const rtl::OUString& GetGraphicDataMimeType( ) const - { - return( maGraphicDataMimeType ); - } - - const MapMode& GetPrefMapMode() const; - const Size& GetPrefSize() const; - - BitmapEx GetReplacement() const; - - private: - - void ImplCheckData(); - void ImplGetDefaults() const; - - private: - - GraphicData maGraphicData; - sal_uInt32 mnGraphicDataLength; - rtl::OUString maGraphicDataMimeType; - mutable ::std::auto_ptr< MapMode > mapPrefMapMode; - mutable ::std::auto_ptr< Size > mapPrefSize; - }; -} - -#endif // _SV_RENDERHRAPHIC_HXX diff --git a/vcl/inc/vcl/rendergraphicrasterizer.hxx b/vcl/inc/vcl/rendergraphicrasterizer.hxx deleted file mode 100644 index f2166b03ffb3..000000000000 --- a/vcl/inc/vcl/rendergraphicrasterizer.hxx +++ /dev/null @@ -1,111 +0,0 @@ -/************************************************************************* - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright 2000, 2010 Oracle and/or its affiliates. - * - * OpenOffice.org - a multi-platform office productivity suite - * - * This file is part of OpenOffice.org. - * - * OpenOffice.org is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 3 - * only, as published by the Free Software Foundation. - * - * OpenOffice.org 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 Lesser General Public License version 3 for more details - * (a copy is included in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU Lesser General Public License - * version 3 along with OpenOffice.org. If not, see - * <http://www.openoffice.org/license.html> - * for a copy of the LGPLv3 License. - * - ************************************************************************/ - -#ifndef _SV_RENDERGRAPHICRASTERIZER_HXX -#define _SV_RENDERGRAPHICRASTERIZER_HXX - -#include <vcl/rendergraphic.hxx> -#include <vcl/bitmapex.hxx> - -#include <com/sun/star/graphic/XGraphicRasterizer.hpp> - -#include <memory> -#include <deque> - -#define VCL_RASTERIZER_UNLIMITED_EXTENT 0x00000000 -#define VCL_RASTERIZER_DEFAULT_EXTENT 0xffffffff - -namespace vcl -{ - // --------------------------- - // - RenderGraphicRasterizer - - // --------------------------- - - class VCL_DLLPUBLIC RenderGraphicRasterizer - { - public: - - RenderGraphicRasterizer( const RenderGraphic& rData ); - - - RenderGraphicRasterizer( const RenderGraphicRasterizer& rRenderGraphicRasterizer ); - - virtual ~RenderGraphicRasterizer(); - - RenderGraphicRasterizer& operator=( const RenderGraphicRasterizer& rRenderGraphicRasterizer ); - - inline const RenderGraphic& GetRenderGraphic() const - { - return( maRenderGraphic ); - } - - const Size& GetDefaultSizePixel() const; - - BitmapEx GetReplacement() const; - - virtual Size GetPrefSize() const; - - virtual MapMode GetPrefMapMode() const; - - virtual const BitmapEx& Rasterize( const Size& rSizePixel_UnrotatedUnsheared, - double fRotateAngle = 0.0, - double fShearAngleX = 0.0, - double fShearAngleY = 0.0, - sal_uInt32 nMaxExtent = VCL_RASTERIZER_DEFAULT_EXTENT ) const; - - protected: - - RenderGraphic maRenderGraphic; - mutable com::sun::star::uno::Reference< com::sun::star::graphic::XGraphicRasterizer > mxRasterizer; - - virtual void InitializeRasterizer(); - - private: - - RenderGraphicRasterizer(); - - mutable BitmapEx maBitmapEx; - mutable Size maDefaultSizePixel; - mutable double mfRotateAngle; - mutable double mfShearAngleX; - mutable double mfShearAngleY; - - private: - - typedef ::std::deque< RenderGraphicRasterizer > RenderGraphicRasterizerCache; - - static RenderGraphicRasterizerCache& ImplGetCache(); - - static bool ImplInitializeFromCache( RenderGraphicRasterizer& rRasterizer ); - static bool ImplRasterizeFromCache( RenderGraphicRasterizer& rRasterizer, - const Size& rSizePixel, double fRotateAngle, - double fShearAngleX, double fShearAngleY ); - static void ImplUpdateCache( const RenderGraphicRasterizer& rRasterizer ); -}; -} - -#endif // _SV_RENDERGRAPHICRASTERIZER_HXX diff --git a/vcl/inc/vcl/svgdata.hxx b/vcl/inc/vcl/svgdata.hxx new file mode 100644 index 000000000000..e7b208e8b739 --- /dev/null +++ b/vcl/inc/vcl/svgdata.hxx @@ -0,0 +1,82 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ +#ifndef _SV_SVGDATA_HXX +#define _SV_SVGDATA_HXX + +#include <basegfx/range/b2drange.hxx> +#include <boost/shared_array.hpp> +#include <boost/shared_ptr.hpp> +#include <boost/utility.hpp> +#include <com/sun/star/graphic/XPrimitive2D.hpp> +#include <vcl/bitmapex.hxx> +#include <rtl/ustring.hxx> + +////////////////////////////////////////////////////////////////////////////// + +typedef boost::shared_array< sal_uInt8 > SvgDataArray; +typedef ::com::sun::star::uno::Reference< ::com::sun::star::graphic::XPrimitive2D > Primitive2DReference; +typedef ::com::sun::star::uno::Sequence< Primitive2DReference > Primitive2DSequence; + +////////////////////////////////////////////////////////////////////////////// + +class VCL_DLLPUBLIC SvgData : private boost::noncopyable +{ +private: + // the file and length + SvgDataArray maSvgDataArray; + sal_uInt32 mnSvgDataArrayLength; + + // The absolute Path if available + rtl::OUString maPath; + + // on demand created content + basegfx::B2DRange maRange; + Primitive2DSequence maSequence; + BitmapEx maReplacement; + + // on demand creators + void ensureReplacement(); + void ensureSequenceAndRange(); + +public: + SvgData(const SvgDataArray& rSvgDataArray, sal_uInt32 nSvgDataArrayLength, const rtl::OUString& rPath); + + /// data read + const SvgDataArray& getSvgDataArray() const { return maSvgDataArray; } + sal_uInt32 getSvgDataArrayLength() const { return mnSvgDataArrayLength; } + const rtl::OUString& getPath() const { return maPath; } + + /// data read and evtl. on demand creation + const basegfx::B2DRange& getRange() const; + const Primitive2DSequence& getPrimitive2DSequence() const; + const BitmapEx& getReplacement() const; +}; + +////////////////////////////////////////////////////////////////////////////// + +typedef boost::shared_ptr< SvgData > SvgDataPtr; + +////////////////////////////////////////////////////////////////////////////// + +#endif // _SV_SVGDATA_HXX + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/vcl/inc/vcl/svgread.hxx b/vcl/inc/vcl/svgread.hxx deleted file mode 100644 index ea4388767d02..000000000000 --- a/vcl/inc/vcl/svgread.hxx +++ /dev/null @@ -1,80 +0,0 @@ -/************************************************************************* - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright 2000, 2010 Oracle and/or its affiliates. - * - * OpenOffice.org - a multi-platform office productivity suite - * - * This file is part of OpenOffice.org. - * - * OpenOffice.org is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 3 - * only, as published by the Free Software Foundation. - * - * OpenOffice.org 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 Lesser General Public License version 3 for more details - * (a copy is included in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU Lesser General Public License - * version 3 along with OpenOffice.org. If not, see - * <http://www.openoffice.org/license.html> - * for a copy of the LGPLv3 License. - * - ************************************************************************/ - -#ifndef _SV_SVGREAD_HXX -#define _SV_SVGREAD_HXX - -#include <vcl/dllapi.h> -#include <memory> - -// ------------- -// - SVGReader - -// ------------- - -class SvStream; -class GDIMetaFile; - -namespace vcl -{ - class SVGReaderImpl; - - class VCL_DLLPUBLIC SVGReader - { - public: - - SVGReader( SvStream& rStm ); - ~SVGReader(); - - /* rSVGMtf is an output parameter, that is also returned - by the method as well. - - In case of a failure, the GDIMetaFile will not contain - any actions at all and thus GDIMetaFile::GetActionCount - will return 0. - - In case of success, the GDIMetaFile will contain a - META_RENDERGRAPHIC_ACTION, containing the SVG raw data. The - data can be rendered by using the standard ways to output a - GDIMetaFile, e.g. calling GDIMetaFile::Play - - */ - GDIMetaFile& Read( GDIMetaFile& rSVGMtf ); - - private: - - SVGReader(); - SVGReader( const SVGReader& rReader ); - - inline SVGReader& operator=( const SVGReader& /* rReader */ ) { return( *this ); } - - private: - - std::auto_ptr< SVGReaderImpl > mapImpl; - }; -} - -#endif // _SV_SVGREAD_HXX diff --git a/vcl/source/gdi/gdimtf.cxx b/vcl/source/gdi/gdimtf.cxx index c02adbee322c..54a4edfc3c9c 100644 --- a/vcl/source/gdi/gdimtf.cxx +++ b/vcl/source/gdi/gdimtf.cxx @@ -37,6 +37,7 @@ #include <vcl/virdev.hxx> #include <vcl/gdimtf.hxx> #include <vcl/graphictools.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> // ----------- // - Defines - @@ -1445,15 +1446,6 @@ void GDIMetaFile::Rotate( long nAngle10 ) } break; - case( META_RENDERGRAPHIC_ACTION ): - { - OSL_TRACE( "Rotate not supported for RenderGraphic MetaActions yet" ); - - pAction->Duplicate(); - aMtf.AddAction( pAction ); - } - break; - default: { pAction->Execute( &aMapVDev ); @@ -1876,14 +1868,6 @@ Rectangle GDIMetaFile::GetBoundRect( OutputDevice& i_rReference ) } break; - case( META_RENDERGRAPHIC_ACTION ): - { - MetaRenderGraphicAction* pAct = (MetaRenderGraphicAction*) pAction; - Rectangle aRect( pAct->GetPoint(), pAct->GetSize() ); - ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack ); - } - break; - default: { pAction->Execute( &aMapVDev ); @@ -2282,15 +2266,6 @@ void GDIMetaFile::ImplExchangeColors( ColorExchangeFnc pFncCol, const void* pCol } break; - case( META_RENDERGRAPHIC_ACTION ): - { - OSL_TRACE( "ExchangeColors not supported for RenderGraphic MetaActions yet" ); - - pAction->Duplicate(); - aMtf.Insert( pAction, LIST_APPEND ); - } - break; - default: { pAction->Duplicate(); @@ -2739,27 +2714,70 @@ sal_uLong GDIMetaFile::GetChecksum() const } break; - case( META_RENDERGRAPHIC_ACTION ): + case META_CLIPREGION_ACTION : { - MetaRenderGraphicAction* pAct = (MetaRenderGraphicAction*) pAction; - const ::vcl::RenderGraphic& rRenderGraphic = pAct->GetRenderGraphic(); + MetaClipRegionAction* pAct = dynamic_cast< MetaClipRegionAction* >(pAction); + const Region& rRegion = pAct->GetRegion(); - ShortToSVBT16( pAct->GetType(), aBT16 ); - nCrc = rtl_crc32( nCrc, aBT16, 2 ); + if(rRegion.HasPolyPolygon()) + { + // It has shown that this is a possible bottleneck for checksum calculation. + // In worst case a very expensive RegionHandle representation gets created. + // In this case it's cheaper to use the PolyPolygon + const basegfx::B2DPolyPolygon aPolyPolygon(rRegion.GetB2DPolyPolygon()); + const sal_uInt32 nPolyCount(aPolyPolygon.count()); + SVBT64 aSVBT64; + + for(sal_uInt32 a(0); a < nPolyCount; a++) + { + const basegfx::B2DPolygon aPolygon(aPolyPolygon.getB2DPolygon(a)); + const sal_uInt32 nPointCount(aPolygon.count()); + const bool bControl(aPolygon.areControlPointsUsed()); - nCrc = rtl_crc32( nCrc, rRenderGraphic.GetGraphicData().get(), rRenderGraphic.GetGraphicDataLength() ); + for(sal_uInt32 b(0); b < nPointCount; b++) + { + const basegfx::B2DPoint aPoint(aPolygon.getB2DPoint(b)); - UInt32ToSVBT32( pAct->GetPoint().X(), aBT32 ); - nCrc = rtl_crc32( nCrc, aBT32, 4 ); + DoubleToSVBT64(aPoint.getX(), aSVBT64); + nCrc = rtl_crc32(nCrc, aSVBT64, 8); + DoubleToSVBT64(aPoint.getY(), aSVBT64); + nCrc = rtl_crc32(nCrc, aSVBT64, 8); - UInt32ToSVBT32( pAct->GetPoint().Y(), aBT32 ); - nCrc = rtl_crc32( nCrc, aBT32, 4 ); + if(bControl) + { + if(aPolygon.isPrevControlPointUsed(b)) + { + const basegfx::B2DPoint aCtrl(aPolygon.getPrevControlPoint(b)); - UInt32ToSVBT32( pAct->GetSize().Width(), aBT32 ); - nCrc = rtl_crc32( nCrc, aBT32, 4 ); + DoubleToSVBT64(aCtrl.getX(), aSVBT64); + nCrc = rtl_crc32(nCrc, aSVBT64, 8); + DoubleToSVBT64(aCtrl.getY(), aSVBT64); + nCrc = rtl_crc32(nCrc, aSVBT64, 8); + } - UInt32ToSVBT32( pAct->GetSize().Height(), aBT32 ); - nCrc = rtl_crc32( nCrc, aBT32, 4 ); + if(aPolygon.isNextControlPointUsed(b)) + { + const basegfx::B2DPoint aCtrl(aPolygon.getNextControlPoint(b)); + + DoubleToSVBT64(aCtrl.getX(), aSVBT64); + nCrc = rtl_crc32(nCrc, aSVBT64, 8); + DoubleToSVBT64(aCtrl.getY(), aSVBT64); + nCrc = rtl_crc32(nCrc, aSVBT64, 8); + } + } + } + } + + SVBT8 aSVBT8; + ByteToSVBT8((sal_uInt8)pAct->IsClipping(), aSVBT8); + nCrc = rtl_crc32(nCrc, aSVBT8, 1); + } + else + { + pAction->Write( aMemStm, &aWriteData ); + nCrc = rtl_crc32( nCrc, aMemStm.GetData(), aMemStm.Tell() ); + aMemStm.Seek( 0 ); + } } break; @@ -2828,8 +2846,6 @@ sal_uLong GDIMetaFile::GetSizeBytes() const nSizeBytes += ( pTextArrayAction->GetLen() << 2 ); } break; - - case( META_RENDERGRAPHIC_ACTION ): nSizeBytes += ( ( (MetaRenderGraphicAction*) pAction )->GetRenderGraphic() ).GetGraphicDataLength(); break; } } @@ -2857,63 +2873,27 @@ SvStream& operator>>( SvStream& rIStm, GDIMetaFile& rGDIMetaFile ) // new format VersionCompat* pCompat; MetaAction* pAction; - sal_uInt32 nStmCompressMode = 0; - sal_uInt32 nCount = 0; - sal_uInt8 bRenderGraphicReplacements = 0; + sal_uInt32 nStmCompressMode = 0; + sal_uInt32 nCount = 0; pCompat = new VersionCompat( rIStm, STREAM_READ ); - { - // version 1 - rIStm >> nStmCompressMode; - rIStm >> rGDIMetaFile.aPrefMapMode; - rIStm >> rGDIMetaFile.aPrefSize; - rIStm >> nCount; - if( pCompat->GetVersion() >= 2 ) - { - // version 2 - // ========= - // contains an additional flag to indicate that RenderGraphic - // actions are immediately followed by a replacement image, that - // needs to be skipped in case the flag is set (KA 01/2011) + rIStm >> nStmCompressMode; + rIStm >> rGDIMetaFile.aPrefMapMode; + rIStm >> rGDIMetaFile.aPrefSize; + rIStm >> nCount; - rIStm >> bRenderGraphicReplacements; - } - } delete pCompat; ImplMetaReadData aReadData; aReadData.meActualCharSet = rIStm.GetStreamCharSet(); - for( sal_uInt32 nAction = 0UL; ( nAction < nCount ) && !rIStm.IsEof(); ++nAction ) + for( sal_uInt32 nAction = 0UL; ( nAction < nCount ) && !rIStm.IsEof(); nAction++ ) { pAction = MetaAction::ReadMetaAction( rIStm, &aReadData ); if( pAction ) - { rGDIMetaFile.AddAction( pAction ); - - // if the MetaFile was written in RenderGraphics replacement mode - // and we just read a RenderGraphic action, skip the following - // META_BMPEXSCALE_ACTION, since this is the replacement image, - // just needed for old implementations; don't forget to increment - // the action read counter! (KA 01/2011) - if( bRenderGraphicReplacements && - ( META_RENDERGRAPHIC_ACTION == pAction->GetType() ) && - ( ++nAction < nCount ) && !rIStm.IsEof() ) - { - sal_uInt16 nFollowingType; - - // dummy read of the next following META_BMPEXSCALE_ACTION - // RenderGraphic replacement action (KA 01/2011) - rIStm >> nFollowingType; - delete ( new VersionCompat( rIStm, STREAM_READ ) ); - - OSL_ENSURE( META_BMPEXSCALE_ACTION == nFollowingType, \ -"META_RENDERGRAPHIC_ACTION read in RenderGraphic replacement mode \ -without following META_BMPEXSCALE_ACTION replacement" ); - } - } } } else @@ -2980,90 +2960,32 @@ SvStream& GDIMetaFile::Read( SvStream& rIStm ) // ------------------------------------------------------------------------ -SvStream& GDIMetaFile::Write( SvStream& rOStm, GDIMetaFileWriteFlags nWriteFlags ) +SvStream& GDIMetaFile::Write( SvStream& rOStm ) { VersionCompat* pCompat; const sal_uInt32 nStmCompressMode = rOStm.GetCompressMode(); sal_uInt16 nOldFormat = rOStm.GetNumberFormatInt(); - const sal_uInt8 bRenderGraphicReplacements = - ( ( ( GDIMETAFILE_WRITE_REPLACEMENT_RENDERGRAPHIC & nWriteFlags ) != 0 ) ? 1 : 0 ); - - // With the introduction of the META_RENDERGRAPHIC_ACTION, it is neccessary - // to provide some kind of document backward compatibility: - // - // If the flag GDIMETAFILE_WRITE_REPLACEMENT_RENDERGRAPHIC is set in - // parameter nWriteFlags, each META_RENDERGRAPHIC_ACTION is followed by - // an additional META_BMPEXSCALE_ACTION, that contains a replacement - // image for the new RenderGraphic action. - // - // Old implementations, not knowing anything about META_RENDERGRAPHIC_ACTION, - // will skip this new action and read the META_BMPEXSCALE_ACTION instead - // - // Since the current implementation is able to handle the new action, the - // then following image replacement action needs to be skipped by this - // implementation, if the metafile was written in the RenderGraphic - // replacement mode. - // - // To be able to detect this compatibility mode, the header needs to - // be extended by a corresponding flag, resulting in version 2 of - // the header. The surrounding VersionCompat of the header - // allows to add such new data without any problems (KA 01/2011) rOStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN ); rOStm.Write( "VCLMTF", 6 ); - pCompat = new VersionCompat( rOStm, STREAM_WRITE, 2 ); - - { - // version 1 - sal_uInt32 nActionCount = 0; - - // calculate correct action count and watch for - // additional RenderGraphic replacement actions, if the - // GDIMETAFILE_WRITE_REPLACEMENT_RENDERGRAPHIC is set - // and META_RENDERGRAPHIC_ACTION are encountered (KA 01/2011) - for( MetaAction* pAct = static_cast< MetaAction* >( First() ); pAct; pAct = static_cast< MetaAction* >( Next() ) ) - { - nActionCount += ( bRenderGraphicReplacements && ( META_RENDERGRAPHIC_ACTION == pAct->GetType() ) ? 2 : 1 ); - } - - rOStm << nStmCompressMode << aPrefMapMode << aPrefSize << nActionCount; + pCompat = new VersionCompat( rOStm, STREAM_WRITE, 1 ); - { - // version 2 - // ========= - // since version 2, a GDIMETAFILE_WRITE_REPLACEMENT_RENDERGRAPHIC flag - // is written, to indicate that each META_BMPEXSCALE_ACTION following - // a META_RENDERGRAPHIC_ACTION needs to be skipped, in case the flag is - // set (KA 01/2011) - rOStm << bRenderGraphicReplacements; - } - } + rOStm << nStmCompressMode; + rOStm << aPrefMapMode; + rOStm << aPrefSize; + rOStm << (sal_uInt32) GetActionCount(); delete pCompat; ImplMetaWriteData aWriteData; - aWriteData.meActualCharSet = rOStm.GetStreamCharSet(); - aWriteData.mnWriteFlags = nWriteFlags; - for( MetaAction* pAct = static_cast< MetaAction* >( First() ); pAct; pAct = static_cast< MetaAction* >( Next() ) ) + MetaAction* pAct = (MetaAction*)First(); + while ( pAct ) { pAct->Write( rOStm, &aWriteData ); - - // write the RenderGraphic replacement image, if the - // GDIMETAFILE_WRITE_REPLACEMENT_RENDERGRAPHIC flag is set - // and if a META_RENDERGRAPHIC_ACTION is encountered (KA 01/2011) - if( bRenderGraphicReplacements && ( META_RENDERGRAPHIC_ACTION == pAct->GetType() ) ) - { - MetaRenderGraphicAction* pRenderAction = static_cast< MetaRenderGraphicAction* >( pAct ); - MetaBmpExScaleAction* pBmpExScaleAction = new MetaBmpExScaleAction( - pRenderAction->GetPoint(), pRenderAction->GetSize(), - pRenderAction->GetRenderGraphic().GetReplacement() ); - - pBmpExScaleAction->Write( rOStm, &aWriteData ); - pBmpExScaleAction->Delete(); - } + pAct = (MetaAction*)Next(); } rOStm.SetNumberFormatInt( nOldFormat ); diff --git a/vcl/source/gdi/graph.cxx b/vcl/source/gdi/graph.cxx index 9b4154740d0b..55477d3b4b89 100644 --- a/vcl/source/gdi/graph.cxx +++ b/vcl/source/gdi/graph.cxx @@ -27,11 +27,9 @@ #include <vcl/outdev.hxx> #include <vcl/svapp.hxx> #include <vcl/graph.hxx> - +#include <vcl/metaact.hxx> #include <impgraph.hxx> - #include <comphelper/processfactory.hxx> - #include <com/sun/star/lang/XMultiServiceFactory.hpp> #include <com/sun/star/graphic/XGraphicProvider.hpp> #include <com/sun/star/lang/XUnoTunnel.hpp> @@ -244,6 +242,13 @@ Graphic::Graphic( const BitmapEx& rBmpEx ) // ------------------------------------------------------------------------ +Graphic::Graphic(const SvgDataPtr& rSvgDataPtr) +{ + mpImpGraphic = new ImpGraphic(rSvgDataPtr); +} + +// ------------------------------------------------------------------------ + Graphic::Graphic( const Animation& rAnimation ) { mpImpGraphic = new ImpGraphic( rAnimation ); @@ -434,20 +439,6 @@ sal_Bool Graphic::IsEPS() const // ------------------------------------------------------------------------ -sal_Bool Graphic::IsRenderGraphic() const -{ - return mpImpGraphic->ImplIsRenderGraphic(); -} - -// ------------------------------------------------------------------------ - -sal_Bool Graphic::HasRenderGraphic() const -{ - return mpImpGraphic->ImplHasRenderGraphic(); -} - -// ------------------------------------------------------------------------ - Bitmap Graphic::GetBitmap(const GraphicConversionParameters& rParameters) const { return mpImpGraphic->ImplGetBitmap(rParameters); @@ -476,13 +467,6 @@ const GDIMetaFile& Graphic::GetGDIMetaFile() const // ------------------------------------------------------------------------ -::vcl::RenderGraphic Graphic::GetRenderGraphic() const -{ - return mpImpGraphic->ImplGetRenderGraphic(); -} - -// ------------------------------------------------------------------------ - uno::Reference< graphic::XGraphic > Graphic::GetXGraphic() const { uno::Reference< graphic::XGraphic > xRet; @@ -840,3 +824,8 @@ SvStream& operator<<( SvStream& rOStream, const Graphic& rGraphic ) { return rOStream << *rGraphic.mpImpGraphic; } + +const SvgDataPtr& Graphic::getSvgData() const +{ + return mpImpGraphic->getSvgData(); +} diff --git a/vcl/source/gdi/impgraph.cxx b/vcl/source/gdi/impgraph.cxx index 5f4c310747fc..140f62c841c0 100644 --- a/vcl/source/gdi/impgraph.cxx +++ b/vcl/source/gdi/impgraph.cxx @@ -175,6 +175,8 @@ ImpGraphic::ImpGraphic( const ImpGraphic& rImpGraphic ) : } else mpAnimation = NULL; + + maSvgData = rImpGraphic.maSvgData; } // ------------------------------------------------------------------------ @@ -213,6 +215,23 @@ ImpGraphic::ImpGraphic( const BitmapEx& rBitmapEx ) : // ------------------------------------------------------------------------ +ImpGraphic::ImpGraphic(const SvgDataPtr& rSvgDataPtr) +: mpAnimation( NULL ), + mpContext( NULL ), + mpSwapFile( NULL ), + mpGfxLink( NULL ), + meType( rSvgDataPtr.get() ? GRAPHIC_BITMAP : GRAPHIC_NONE ), + mnDocFilePos( 0UL ), + mnSizeBytes( 0UL ), + mnRefCount( 1UL ), + mbSwapOut( sal_False ), + mbSwapUnderway( sal_False ), + maSvgData(rSvgDataPtr) +{ +} + +// ------------------------------------------------------------------------ + ImpGraphic::ImpGraphic( const Animation& rAnimation ) : maEx ( rAnimation.GetBitmapEx() ), mpAnimation ( new Animation( rAnimation ) ), @@ -298,6 +317,8 @@ ImpGraphic& ImpGraphic::operator=( const ImpGraphic& rImpGraphic ) mpGfxLink = new GfxLink( *rImpGraphic.mpGfxLink ); else mpGfxLink = NULL; + + maSvgData = rImpGraphic.maSvgData; } return *this; @@ -328,13 +349,35 @@ sal_Bool ImpGraphic::operator==( const ImpGraphic& rImpGraphic ) const case( GRAPHIC_BITMAP ): { - if( mpAnimation ) + if(maSvgData.get()) + { + if(maSvgData == rImpGraphic.maSvgData) + { + bRet = sal_True; + } + else if(rImpGraphic.maSvgData) + { + if(maSvgData->getSvgDataArrayLength() == rImpGraphic.maSvgData->getSvgDataArrayLength()) + { + if(0 == memcmp( + maSvgData->getSvgDataArray().get(), + rImpGraphic.maSvgData->getSvgDataArray().get(), + maSvgData->getSvgDataArrayLength())) + { + bRet = sal_True; + } + } + } + } + else if( mpAnimation ) { if( rImpGraphic.mpAnimation && ( *rImpGraphic.mpAnimation == *mpAnimation ) ) bRet = sal_True; } else if( !rImpGraphic.mpAnimation && ( rImpGraphic.maEx == maEx ) ) + { bRet = sal_True; + } } break; @@ -371,6 +414,8 @@ void ImpGraphic::ImplClearGraphics( sal_Bool bCreateSwapInfo ) delete mpGfxLink; mpGfxLink = NULL; } + + maSvgData.reset(); } // ------------------------------------------------------------------------ @@ -446,12 +491,12 @@ sal_Bool ImpGraphic::ImplIsSupportedGraphic() const sal_Bool ImpGraphic::ImplIsTransparent() const { - sal_Bool bRet; + sal_Bool bRet(sal_True); - if( meType == GRAPHIC_BITMAP ) + if( meType == GRAPHIC_BITMAP && !maSvgData.get()) + { bRet = ( mpAnimation ? mpAnimation->IsTransparent() : maEx.IsTransparent() ); - else - bRet = sal_True; + } return bRet; } @@ -460,12 +505,16 @@ sal_Bool ImpGraphic::ImplIsTransparent() const sal_Bool ImpGraphic::ImplIsAlpha() const { - sal_Bool bRet; + sal_Bool bRet(sal_False); - if( meType == GRAPHIC_BITMAP ) + if(maSvgData.get()) + { + bRet = sal_True; + } + else if( meType == GRAPHIC_BITMAP ) + { bRet = ( NULL == mpAnimation ) && maEx.IsAlpha(); - else - bRet = sal_False; + } return bRet; } @@ -488,45 +537,18 @@ sal_Bool ImpGraphic::ImplIsEPS() const // ------------------------------------------------------------------------ -sal_Bool ImpGraphic::ImplIsRenderGraphic() const -{ - return( ( GRAPHIC_GDIMETAFILE == meType ) && - ( 1 == maMetaFile.GetActionCount() ) && - ( META_RENDERGRAPHIC_ACTION == maMetaFile.GetAction( 0 )->GetType() ) ); -} - -// ------------------------------------------------------------------------ - -sal_Bool ImpGraphic::ImplHasRenderGraphic() const -{ - sal_Bool bRet = sal_False; - - if( GRAPHIC_GDIMETAFILE == meType ) - { - GDIMetaFile& rMtf = const_cast< ImpGraphic* >( this )->maMetaFile; - - for( MetaAction* pAct = rMtf.FirstAction(); pAct && !bRet; pAct = rMtf.NextAction() ) - { - if( META_RENDERGRAPHIC_ACTION == pAct->GetType() ) - { - bRet = sal_True; - } - } - - rMtf.WindStart(); - } - - return( bRet ); -} - -// ------------------------------------------------------------------------ - Bitmap ImpGraphic::ImplGetBitmap(const GraphicConversionParameters& rParameters) const { Bitmap aRetBmp; if( meType == GRAPHIC_BITMAP ) { + if(maSvgData.get() && maEx.IsEmpty()) + { + // use maEx as local buffer for rendered svg + const_cast< ImpGraphic* >(this)->maEx = maSvgData->getReplacement(); + } + const BitmapEx& rRetBmpEx = ( mpAnimation ? mpAnimation->GetBitmapEx() : maEx ); const Color aReplaceColor( COL_WHITE ); @@ -605,6 +627,12 @@ BitmapEx ImpGraphic::ImplGetBitmapEx(const GraphicConversionParameters& rParamet if( meType == GRAPHIC_BITMAP ) { + if(maSvgData.get() && maEx.IsEmpty()) + { + // use maEx as local buffer for rendered svg + const_cast< ImpGraphic* >(this)->maEx = maSvgData->getReplacement(); + } + aRetBmpEx = ( mpAnimation ? mpAnimation->GetBitmapEx() : maEx ); if(rParameters.getSizePixel().Width() || rParameters.getSizePixel().Height()) @@ -633,18 +661,6 @@ Animation ImpGraphic::ImplGetAnimation() const // ------------------------------------------------------------------------ -::vcl::RenderGraphic ImpGraphic::ImplGetRenderGraphic() const -{ - ::vcl::RenderGraphic aRet; - - if( ImplIsRenderGraphic() ) - aRet = static_cast< MetaRenderGraphicAction* >( maMetaFile.GetAction( 0 ) )->GetRenderGraphic(); - - return( aRet ); -} - -// ------------------------------------------------------------------------ - const GDIMetaFile& ImpGraphic::ImplGetGDIMetaFile() const { return maMetaFile; @@ -668,10 +684,22 @@ Size ImpGraphic::ImplGetPrefSize() const case( GRAPHIC_BITMAP ): { - aSize = maEx.GetPrefSize(); + if(maSvgData.get() && maEx.IsEmpty()) + { + // svg not yet buffered in maEx, return size derived from range + const basegfx::B2DRange& rRange = maSvgData->getRange(); - if( !aSize.Width() || !aSize.Height() ) - aSize = maEx.GetSizePixel(); + aSize = Size(basegfx::fround(rRange.getWidth()), basegfx::fround(rRange.getHeight())); + } + else + { + aSize = maEx.GetPrefSize(); + + if( !aSize.Width() || !aSize.Height() ) + { + aSize = maEx.GetSizePixel(); + } + } } break; @@ -698,12 +726,24 @@ void ImpGraphic::ImplSetPrefSize( const Size& rPrefSize ) break; case( GRAPHIC_BITMAP ): + { // #108077# Push through pref size to animation object, // will be lost on copy otherwise - if( ImplIsAnimated() ) - const_cast< BitmapEx& >(mpAnimation->GetBitmapEx()).SetPrefSize( rPrefSize ); + if(maSvgData.get()) + { + // ignore for Svg. If this is really used (except the grfcache) + // it can be extended by using maEx as buffer for maSvgData->getReplacement() + } + else + { + if( ImplIsAnimated() ) + { + const_cast< BitmapEx& >(mpAnimation->GetBitmapEx()).SetPrefSize( rPrefSize ); + } - maEx.SetPrefSize( rPrefSize ); + maEx.SetPrefSize( rPrefSize ); + } + } break; default: @@ -733,10 +773,18 @@ MapMode ImpGraphic::ImplGetPrefMapMode() const case( GRAPHIC_BITMAP ): { - const Size aSize( maEx.GetPrefSize() ); + if(maSvgData.get() && maEx.IsEmpty()) + { + // svg not yet buffered in maEx, return default PrefMapMode + aMapMode = MapMode(MAP_100TH_MM); + } + else + { + const Size aSize( maEx.GetPrefSize() ); - if ( aSize.Width() && aSize.Height() ) - aMapMode = maEx.GetPrefMapMode(); + if ( aSize.Width() && aSize.Height() ) + aMapMode = maEx.GetPrefMapMode(); + } } break; @@ -763,12 +811,24 @@ void ImpGraphic::ImplSetPrefMapMode( const MapMode& rPrefMapMode ) break; case( GRAPHIC_BITMAP ): - // #108077# Push through pref mapmode to animation object, - // will be lost on copy otherwise - if( ImplIsAnimated() ) - const_cast< BitmapEx& >(mpAnimation->GetBitmapEx()).SetPrefMapMode( rPrefMapMode ); + { + if(maSvgData.get()) + { + // ignore for Svg. If this is really used (except the grfcache) + // it can be extended by using maEx as buffer for maSvgData->getReplacement() + } + else + { + // #108077# Push through pref mapmode to animation object, + // will be lost on copy otherwise + if( ImplIsAnimated() ) + { + const_cast< BitmapEx& >(mpAnimation->GetBitmapEx()).SetPrefMapMode( rPrefMapMode ); + } - maEx.SetPrefMapMode( rPrefMapMode ); + maEx.SetPrefMapMode( rPrefMapMode ); + } + } break; default: @@ -788,7 +848,14 @@ sal_uLong ImpGraphic::ImplGetSizeBytes() const { if( meType == GRAPHIC_BITMAP ) { - mnSizeBytes = mpAnimation ? mpAnimation->GetSizeBytes() : maEx.GetSizeBytes(); + if(maSvgData.get()) + { + mnSizeBytes = maSvgData->getSvgDataArrayLength(); + } + else + { + mnSizeBytes = mpAnimation ? mpAnimation->GetSizeBytes() : maEx.GetSizeBytes(); + } } else if( meType == GRAPHIC_GDIMETAFILE ) { @@ -812,10 +879,20 @@ void ImpGraphic::ImplDraw( OutputDevice* pOutDev, const Point& rDestPt ) const case( GRAPHIC_BITMAP ): { + if(maSvgData.get() && !maEx) + { + // use maEx as local buffer for rendered svg + const_cast< ImpGraphic* >(this)->maEx = maSvgData->getReplacement(); + } + if ( mpAnimation ) + { mpAnimation->Draw( pOutDev, rDestPt ); + } else + { maEx.Draw( pOutDev, rDestPt ); + } } break; @@ -840,10 +917,20 @@ void ImpGraphic::ImplDraw( OutputDevice* pOutDev, case( GRAPHIC_BITMAP ): { + if(maSvgData.get() && maEx.IsEmpty()) + { + // use maEx as local buffer for rendered svg + const_cast< ImpGraphic* >(this)->maEx = maSvgData->getReplacement(); + } + if( mpAnimation ) + { mpAnimation->Draw( pOutDev, rDestPt, rDestSize ); + } else + { maEx.Draw( pOutDev, rDestPt, rDestSize ); + } } break; @@ -1052,6 +1139,12 @@ sal_Bool ImpGraphic::ImplReadEmbedded( SvStream& rIStm, sal_Bool bSwap ) { if( meType == GRAPHIC_BITMAP ) { + if(maSvgData.get() && maEx.IsEmpty()) + { + // use maEx as local buffer for rendered svg + maEx = maSvgData->getReplacement(); + } + maEx.aBitmapSize = aSize; if( aMapMode != MapMode() ) @@ -1510,10 +1603,20 @@ sal_uLong ImpGraphic::ImplGetChecksum() const case( GRAPHIC_BITMAP ): { + if(maSvgData.get() && maEx.IsEmpty()) + { + // use maEx as local buffer for rendered svg + const_cast< ImpGraphic* >(this)->maEx = maSvgData->getReplacement(); + } + if( mpAnimation ) + { nRet = mpAnimation->GetChecksum(); + } else + { nRet = maEx.GetChecksum(); + } } break; @@ -1553,6 +1656,13 @@ sal_Bool ImpGraphic::ImplExportNative( SvStream& rOStm ) const // ------------------------------------------------------------------------ +const SvgDataPtr& ImpGraphic::getSvgData() const +{ + return maSvgData; +} + +// ------------------------------------------------------------------------ + SvStream& operator>>( SvStream& rIStm, ImpGraphic& rImpGraphic ) { if( !rIStm.GetError() ) @@ -1704,10 +1814,18 @@ SvStream& operator<<( SvStream& rOStm, const ImpGraphic& rImpGraphic ) case GRAPHIC_BITMAP: { - if ( rImpGraphic.ImplIsAnimated() ) + if(rImpGraphic.getSvgData().get()) + { + rOStm << rImpGraphic.getSvgData()->getReplacement(); + } + else if( rImpGraphic.ImplIsAnimated()) + { rOStm << *rImpGraphic.mpAnimation; + } else + { rOStm << rImpGraphic.maEx; + } } break; diff --git a/vcl/source/gdi/makefile.mk b/vcl/source/gdi/makefile.mk index ec664cf648a6..f3f5ebd87680 100755 --- a/vcl/source/gdi/makefile.mk +++ b/vcl/source/gdi/makefile.mk @@ -76,9 +76,7 @@ EXCEPTIONSFILES= $(SLO)$/salmisc.obj \ $(SLO)$/graphictools.obj \ $(SLO)$/textlayout.obj \ $(SLO)$/lineinfo.obj \ - $(SLO)$/svgread.obj \ - $(SLO)$/rendergraphic.obj \ - $(SLO)$/rendergraphicrasterizer.obj + $(SLO)$/svgdata.obj SLOFILES= $(EXCEPTIONSFILES) \ $(SLO)$/animate.obj \ diff --git a/vcl/source/gdi/metaact.cxx b/vcl/source/gdi/metaact.cxx index f15527feaf2a..df8967fd683d 100644 --- a/vcl/source/gdi/metaact.cxx +++ b/vcl/source/gdi/metaact.cxx @@ -34,7 +34,8 @@ #include <vcl/salbtype.hxx> #include <vcl/metaact.hxx> #include <vcl/graphictools.hxx> -#include <vcl/rendergraphicrasterizer.hxx> +//#include <svgio/svgreader/svgreader.hxx> +#include <basegfx/matrix/b2dhommatrixtools.hxx> // ======================================================================== @@ -232,7 +233,6 @@ MetaAction* MetaAction::ReadMetaAction( SvStream& rIStm, ImplMetaReadData* pData case( META_COMMENT_ACTION ): pAction = new MetaCommentAction; break; case( META_LAYOUTMODE_ACTION ): pAction = new MetaLayoutModeAction; break; case( META_TEXTLANGUAGE_ACTION ): pAction = new MetaTextLanguageAction; break; - case( META_RENDERGRAPHIC_ACTION ): pAction = new MetaRenderGraphicAction; break; default: { @@ -2025,7 +2025,7 @@ void MetaBmpExAction::Execute( OutputDevice* pOut ) MetaAction* MetaBmpExAction::Clone() { - MetaAction* pClone = (MetaAction*) new MetaBmpExAction( *this ); + MetaBmpExAction* pClone = new MetaBmpExAction( *this ); pClone->ResetRefCount(); return pClone; } @@ -4297,82 +4297,4 @@ void MetaTextLanguageAction::Read( SvStream& rIStm, ImplMetaReadData* ) rIStm >> meTextLanguage; } -// ======================================================================== - -IMPL_META_ACTION( RenderGraphic, META_RENDERGRAPHIC_ACTION ) - -// ------------------------------------------------------------------------ - -MetaRenderGraphicAction::MetaRenderGraphicAction( const Point& rPoint, const Size& rSize, - const vcl::RenderGraphic& rRenderGraphic, - double fRotateAngle, double fShearAngleX, double fShearAngleY ) : - MetaAction( META_RENDERGRAPHIC_ACTION ), - maRenderGraphic( rRenderGraphic ), - maPoint( rPoint ), - maSize( rSize ), - mfRotateAngle( fRotateAngle ), - mfShearAngleX( fShearAngleX ), - mfShearAngleY( fShearAngleY ) -{ -} - -// ------------------------------------------------------------------------ - -void MetaRenderGraphicAction::Execute( OutputDevice* pOut ) -{ - pOut->DrawRenderGraphic( maPoint, maSize, maRenderGraphic ); -} - -// ------------------------------------------------------------------------ - -MetaAction* MetaRenderGraphicAction::Clone() -{ - MetaAction* pClone = (MetaAction*) new MetaRenderGraphicAction( *this ); - pClone->ResetRefCount(); - return pClone; -} - -// ------------------------------------------------------------------------ - -void MetaRenderGraphicAction::Move( long nHorzMove, long nVertMove ) -{ - maPoint.Move( nHorzMove, nVertMove ); -} - -// ------------------------------------------------------------------------ - -void MetaRenderGraphicAction::Scale( double fScaleX, double fScaleY ) -{ - Rectangle aRectangle( maPoint, maSize ); - ImplScaleRect( aRectangle, fScaleX, fScaleY ); - maPoint = aRectangle.TopLeft(); - maSize = aRectangle.GetSize(); -} - -// ------------------------------------------------------------------------ - -sal_Bool MetaRenderGraphicAction::Compare( const MetaAction& rMetaAction ) const -{ - return ( maRenderGraphic.IsEqual( ( (MetaRenderGraphicAction&) rMetaAction).maRenderGraphic ) && - ( maPoint == ( (MetaRenderGraphicAction&) rMetaAction).maPoint ) && - ( maSize == ( (MetaRenderGraphicAction&) rMetaAction).maSize ) && - ( mfRotateAngle == ( (MetaRenderGraphicAction&) rMetaAction).mfRotateAngle ) && - ( mfShearAngleX == ( (MetaRenderGraphicAction&) rMetaAction).mfShearAngleX ) && - ( mfShearAngleY == ( (MetaRenderGraphicAction&) rMetaAction).mfShearAngleY ) ); -} - -// ------------------------------------------------------------------------ - -void MetaRenderGraphicAction::Write( SvStream& rOStm, ImplMetaWriteData* pData ) -{ - WRITE_BASE_COMPAT( rOStm, 1, pData ); - rOStm << maRenderGraphic << maPoint << maSize << mfRotateAngle << mfShearAngleX << mfShearAngleY; -} - -// ------------------------------------------------------------------------ - -void MetaRenderGraphicAction::Read( SvStream& rIStm, ImplMetaReadData* ) -{ - COMPAT( rIStm ); - rIStm >> maRenderGraphic >> maPoint >> maSize >> mfRotateAngle >> mfShearAngleX >> mfShearAngleY; -} +// eof diff --git a/vcl/source/gdi/outdev6.cxx b/vcl/source/gdi/outdev6.cxx index 96d7d3793c5c..f4b4dee908c6 100644 --- a/vcl/source/gdi/outdev6.cxx +++ b/vcl/source/gdi/outdev6.cxx @@ -33,7 +33,6 @@ #include <vcl/svapp.hxx> #include <vcl/wrkwin.hxx> #include <vcl/graph.hxx> -#include <vcl/rendergraphicrasterizer.hxx> #include <wall2.hxx> #include <salgdi.hxx> @@ -1246,25 +1245,3 @@ bool OutputDevice::DrawEPS( const Point& rPoint, const Size& rSize, return bDrawn; } -// ------------------------------------------------------------------ - -void OutputDevice::DrawRenderGraphic( const Point& rPoint, const Size& rSize, - const ::vcl::RenderGraphic& rRenderGraphic ) -{ - DBG_TRACE( "OutputDevice::DrawRenderGraphic()" ); - - if( mpMetaFile ) - mpMetaFile->AddAction( new MetaRenderGraphicAction( rPoint, rSize, rRenderGraphic ) ); - - if( !rRenderGraphic.IsEmpty() ) - { - ::vcl::RenderGraphicRasterizer aRasterizer( rRenderGraphic ); - BitmapEx aBmpEx; - const Size aSizePixel( LogicToPixel( rSize ) ); - GDIMetaFile* pOldMetaFile = mpMetaFile; - - mpMetaFile = NULL; - DrawBitmapEx( rPoint, rSize, aRasterizer.Rasterize( aSizePixel ) ); - mpMetaFile = pOldMetaFile; - } -} diff --git a/vcl/source/gdi/pdfwriter_impl2.cxx b/vcl/source/gdi/pdfwriter_impl2.cxx index fe91a07e8ad4..488460ac873d 100644 --- a/vcl/source/gdi/pdfwriter_impl2.cxx +++ b/vcl/source/gdi/pdfwriter_impl2.cxx @@ -31,7 +31,6 @@ #include "vcl/metaact.hxx" #include "vcl/bmpacc.hxx" #include "vcl/graph.hxx" -#include "vcl/rendergraphicrasterizer.hxx" #include "svdata.hxx" @@ -1044,17 +1043,6 @@ void PDFWriterImpl::playMetafile( const GDIMetaFile& i_rMtf, vcl::PDFExtOutDevDa } break; - case( META_RENDERGRAPHIC_ACTION ): - { - const MetaRenderGraphicAction* pA = static_cast< const MetaRenderGraphicAction* >( pAction ); - const ::vcl::RenderGraphicRasterizer aRasterizer( pA->GetRenderGraphic() ); - - implWriteBitmapEx( pA->GetPoint(), pA->GetSize(), - aRasterizer.Rasterize( pDummyVDev->LogicToPixel( pA->GetSize() ) ), - pDummyVDev, i_rContext ); - } - break; - default: // #i24604# Made assertion fire only once per // metafile. The asserted actions here are all diff --git a/vcl/source/gdi/print2.cxx b/vcl/source/gdi/print2.cxx index daced96c9778..5b3b04102577 100644 --- a/vcl/source/gdi/print2.cxx +++ b/vcl/source/gdi/print2.cxx @@ -42,7 +42,6 @@ #include <vcl/print.hxx> #include <vcl/svapp.hxx> #include <vcl/bmpacc.hxx> -#include <vcl/rendergraphicrasterizer.hxx> #include <print.h> @@ -111,9 +110,6 @@ static bool ImplIsActionSpecial( const MetaAction& rAct ) case META_BMPEXSCALEPART_ACTION: return static_cast<const MetaBmpExScalePartAction&>(rAct).GetBitmapEx().IsTransparent(); - case META_RENDERGRAPHIC_ACTION: - return true; - default: return false; } @@ -201,16 +197,6 @@ static void ImplConvertTransparentAction( GDIMetaFile& o_rMtf, aBmpEx = static_cast<const MetaBmpExScaleAction&>(rAct).GetBitmapEx(); break; - case META_RENDERGRAPHIC_ACTION: - { - const ::vcl::RenderGraphicRasterizer aRasterizer( static_cast<const MetaRenderGraphicAction&>(rAct). - GetRenderGraphic() ); - - aBmpEx = aRasterizer.Rasterize( rStateOutDev.LogicToPixel( - static_cast<const MetaRenderGraphicAction&>(rAct).GetSize() ) ); - break; - } - case META_TRANSPARENT_ACTION: default: @@ -278,11 +264,6 @@ static void ImplConvertTransparentAction( GDIMetaFile& o_rMtf, static_cast<const MetaBmpExScalePartAction&>(rAct).GetSrcSize(), aBmp )); break; - case META_RENDERGRAPHIC_ACTION: - o_rMtf.AddAction( new MetaBmpScaleAction( - static_cast<const MetaRenderGraphicAction&>(rAct).GetPoint(), - static_cast<const MetaRenderGraphicAction&>(rAct).GetSize(), - aBmp )); default: DBG_ERROR("Unexpected case"); break; @@ -395,7 +376,6 @@ static bool ImplIsNotTransparent( const MetaAction& rAct, const OutputDevice& rO case META_TEXTRECT_ACTION: case META_STRETCHTEXT_ACTION: case META_TEXTLINE_ACTION: - case META_RENDERGRAPHIC_ACTION: // all other actions: generate non-transparent output bRet = true; break; @@ -650,13 +630,6 @@ static Rectangle ImplCalcActionBounds( const MetaAction& rAct, const OutputDevic DBG_ERROR("META_TEXTLINE_ACTION not supported"); break; - case( META_RENDERGRAPHIC_ACTION ): - { - const MetaRenderGraphicAction& rRenderAct = static_cast<const MetaRenderGraphicAction&>(rAct); - aActionBounds = Rectangle( rRenderAct.GetPoint(), rRenderAct.GetSize() ); - } - break; - default: break; } @@ -682,7 +655,6 @@ static bool ImplIsActionHandlingTransparency( const MetaAction& rAct ) case META_BMPEX_ACTION: case META_BMPEXSCALE_ACTION: case META_BMPEXSCALEPART_ACTION: - case META_RENDERGRAPHIC_ACTION: return true; default: diff --git a/vcl/source/gdi/rendergraphic.cxx b/vcl/source/gdi/rendergraphic.cxx deleted file mode 100644 index 10b6064cc57c..000000000000 --- a/vcl/source/gdi/rendergraphic.cxx +++ /dev/null @@ -1,240 +0,0 @@ -/************************************************************************* - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright 2000, 2010 Oracle and/or its affiliates. - * - * OpenOffice.org - a multi-platform office productivity suite - * - * This file is part of OpenOffice.org. - * - * OpenOffice.org is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 3 - * only, as published by the Free Software Foundation. - * - * OpenOffice.org 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 Lesser General Public License version 3 for more details - * (a copy is included in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU Lesser General Public License - * version 3 along with OpenOffice.org. If not, see - * <http://www.openoffice.org/license.html> - * for a copy of the LGPLv3 License. - * - ************************************************************************/ - -#include <vcl/rendergraphic.hxx> -#include <vcl/rendergraphicrasterizer.hxx> -#include <vcl/mapmod.hxx> -#include <tools/stream.hxx> -#include <tools/vcompat.hxx> - -#include <cstring> -#include <cstdio> - -namespace vcl -{ - -// ----------------- -// - RenderGraphic - -// ----------------- -RenderGraphic::RenderGraphic( ) : - mnGraphicDataLength( 0 ) -{ -} - -// ------------------------------------------------------------------------- - -RenderGraphic::RenderGraphic( const RenderGraphic& rRenderGraphic ) : - maGraphicData( rRenderGraphic.maGraphicData ), - mnGraphicDataLength( rRenderGraphic.mnGraphicDataLength ), - maGraphicDataMimeType( rRenderGraphic.maGraphicDataMimeType ), - mapPrefMapMode( rRenderGraphic.mapPrefMapMode.get() ? new MapMode( *rRenderGraphic.mapPrefMapMode ) : NULL ), - mapPrefSize( rRenderGraphic.mapPrefSize.get() ? new Size( *rRenderGraphic.mapPrefSize ) : NULL ) -{ -} - -// ------------------------------------------------------------------------- - -RenderGraphic::RenderGraphic( const GraphicData& rGraphicData, - sal_uInt32 nGraphicDataLength, - const rtl::OUString& rGraphicDataMimeType ) : - maGraphicData( rGraphicData ), - mnGraphicDataLength( nGraphicDataLength ), - maGraphicDataMimeType( rGraphicDataMimeType ) -{ - ImplCheckData( ); -} - -// ------------------------------------------------------------------------- - -RenderGraphic::RenderGraphic( const rtl::OUString& rGraphicDataMimeType, - sal_uInt32 nGraphicDataLength, - const sal_uInt8* pGraphicData ) : - maGraphicData(), - mnGraphicDataLength( nGraphicDataLength ), - maGraphicDataMimeType( rGraphicDataMimeType ) -{ - if( rGraphicDataMimeType.getLength( ) && nGraphicDataLength ) - { - maGraphicData.reset( new sal_uInt8[ nGraphicDataLength ] ); - - if( pGraphicData ) - { - memcpy( maGraphicData.get(), pGraphicData, nGraphicDataLength ); - } - } - else - { - ImplCheckData( ); - } -} - -// ------------------------------------------------------------------------- - -RenderGraphic::~RenderGraphic( ) -{ -} - -// ------------------------------------------------------------------------- - -RenderGraphic& RenderGraphic::operator=(const RenderGraphic& rRenderGraphic ) -{ - maGraphicData = rRenderGraphic.maGraphicData; - mnGraphicDataLength = rRenderGraphic.mnGraphicDataLength; - maGraphicDataMimeType = rRenderGraphic.maGraphicDataMimeType; - mapPrefMapMode.reset( rRenderGraphic.mapPrefMapMode.get() ? new MapMode( *rRenderGraphic.mapPrefMapMode ) : NULL ); - mapPrefSize.reset( rRenderGraphic.mapPrefSize.get() ? new Size( *rRenderGraphic.mapPrefSize ) : NULL ); - - return( *this ); -} - -// ------------------------------------------------------------------------- - -bool RenderGraphic::operator==(const RenderGraphic& rRenderGraphic ) const -{ - return( ( rRenderGraphic.mnGraphicDataLength == mnGraphicDataLength ) && - ( rRenderGraphic.maGraphicData == maGraphicData ) && - ( rRenderGraphic.maGraphicDataMimeType.equalsIgnoreAsciiCase( maGraphicDataMimeType ) ) ); -} - -// ------------------------------------------------------------------------- - -bool RenderGraphic::operator!() const -{ - return( ( 0 == maGraphicDataMimeType.getLength( ) ) || - ( 0 == mnGraphicDataLength ) || - !maGraphicData.get( ) ); -} - -// ------------------------------------------------------------------------- - -bool RenderGraphic::IsEqual( const RenderGraphic& rRenderGraphic ) const -{ - bool bRet = ( rRenderGraphic.mnGraphicDataLength == mnGraphicDataLength ) && - ( rRenderGraphic.maGraphicDataMimeType.equalsIgnoreAsciiCase( maGraphicDataMimeType ) ); - - if( bRet && mnGraphicDataLength && ( rRenderGraphic.maGraphicData != maGraphicData ) ) - { - bRet = ( 0 == memcmp( rRenderGraphic.maGraphicData.get( ), - maGraphicData.get( ), - mnGraphicDataLength ) ); - } - - return( bRet ); -} - -// ------------------------------------------------------------------------- - -const MapMode& RenderGraphic::GetPrefMapMode() const -{ - ImplGetDefaults(); - return( *mapPrefMapMode ); -} - -// ------------------------------------------------------------------------- - -const Size& RenderGraphic::GetPrefSize() const -{ - ImplGetDefaults(); - return( *mapPrefSize ); -} - -// ------------------------------------------------------------------------- - -BitmapEx RenderGraphic::GetReplacement() const -{ - const RenderGraphicRasterizer aRasterizer( *this ); - - return( aRasterizer.GetReplacement() ); -} - -// ------------------------------------------------------------------------- - -void RenderGraphic::ImplCheckData( ) -{ - if( !( *this ) ) - { - maGraphicData.reset( ); - mnGraphicDataLength = 0; - maGraphicDataMimeType = ::rtl::OUString(); - mapPrefMapMode.reset(); - mapPrefSize.reset(); - } -} - -// ------------------------------------------------------------------------- - -void RenderGraphic::ImplGetDefaults() const -{ - if( !mapPrefMapMode.get() || !mapPrefSize.get() ) - { - const RenderGraphicRasterizer aRasterizer( *this ); - - mapPrefMapMode.reset( new MapMode( aRasterizer.GetPrefMapMode() ) ); - mapPrefSize.reset( new Size( aRasterizer.GetPrefSize() ) ); - } -} - -// ------------------------------------------------------------------------- - -::SvStream& operator>>( ::SvStream& rIStm, RenderGraphic& rRenderGraphic ) -{ - ::VersionCompat aVCompat( rIStm, STREAM_READ ); - String aGraphicDataMimeType; - sal_uInt32 nGraphicDataLength = 0; - - rIStm.ReadByteString( aGraphicDataMimeType, RTL_TEXTENCODING_ASCII_US ); - rIStm >> nGraphicDataLength; - - rRenderGraphic = RenderGraphic( aGraphicDataMimeType, nGraphicDataLength ); - - if( !rRenderGraphic.IsEmpty() ) - { - rIStm.Read( rRenderGraphic.GetGraphicData().get(), nGraphicDataLength ); - } - - return rIStm; -} - -// ------------------------------------------------------------------ - -::SvStream& operator<<( ::SvStream& rOStm, const RenderGraphic& rRenderGraphic ) -{ - ::VersionCompat aVCompat( rOStm, STREAM_WRITE, 1 ); - const sal_uInt32 nGraphicDataLength = rRenderGraphic.GetGraphicDataLength(); - - rOStm.WriteByteString( rRenderGraphic.GetGraphicDataMimeType(), RTL_TEXTENCODING_ASCII_US ); - rOStm << nGraphicDataLength; - - if( nGraphicDataLength ) - { - rOStm.Write( rRenderGraphic.GetGraphicData().get(), nGraphicDataLength ); - } - - return rOStm; -} - -} // VCL diff --git a/vcl/source/gdi/rendergraphicrasterizer.cxx b/vcl/source/gdi/rendergraphicrasterizer.cxx deleted file mode 100644 index dd1704cf02c2..000000000000 --- a/vcl/source/gdi/rendergraphicrasterizer.cxx +++ /dev/null @@ -1,401 +0,0 @@ -/************************************************************************* - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright 2000, 2010 Oracle and/or its affiliates. - * - * OpenOffice.org - a multi-platform office productivity suite - * - * This file is part of OpenOffice.org. - * - * OpenOffice.org is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 3 - * only, as published by the Free Software Foundation. - * - * OpenOffice.org 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 Lesser General Public License version 3 for more details - * (a copy is included in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU Lesser General Public License - * version 3 along with OpenOffice.org. If not, see - * <http://www.openoffice.org/license.html> - * for a copy of the LGPLv3 License. - * - ************************************************************************/ - -#include <vcl/rendergraphicrasterizer.hxx> -#include <vcl/svapp.hxx> -#include <vcl/wrkwin.hxx> -#include <vcl/virdev.hxx> -#include <vcl/unohelp.hxx> -#include <vcl/bmpacc.hxx> -#include <vcl/graph.hxx> -#include <tools/diagnose_ex.h> -#include <tools/stream.hxx> -#include <comphelper/processfactory.hxx> -#include <unotools/streamwrap.hxx> - -#include <com/sun/star/lang/XMultiServiceFactory.hpp> - -#define VCL_SERVICENAME_RASTERIZER_SVG "com.sun.star.graphic.GraphicRasterizer_RSVG" - -using namespace com::sun::star; - -namespace vcl -{ -// --------------------------------------------------------- -// - maximum extent in pixel for graphics to be rasterized - -// --------------------------------------------------------- - -static const sal_uInt32 nRasterizerDefaultExtent = 4096; - -// --------------------------- -// - RenderGraphicRasterizer - -// --------------------------- - -RenderGraphicRasterizer::RenderGraphicRasterizer( const RenderGraphic& rRenderGraphic ) : - maRenderGraphic( rRenderGraphic ), - mfRotateAngle( 0.0 ), - mfShearAngleX( 0.0 ), - mfShearAngleY( 0.0 ) -{ -} - -// ------------------------------------------------------------------------- - -RenderGraphicRasterizer::RenderGraphicRasterizer( const RenderGraphicRasterizer& rRenderGraphicRasterizer ) : - maRenderGraphic( rRenderGraphicRasterizer.maRenderGraphic ), - mxRasterizer( rRenderGraphicRasterizer.mxRasterizer ), - maBitmapEx( rRenderGraphicRasterizer.maBitmapEx ), - maDefaultSizePixel( rRenderGraphicRasterizer.maDefaultSizePixel ), - mfRotateAngle( rRenderGraphicRasterizer.mfRotateAngle ), - mfShearAngleX( rRenderGraphicRasterizer.mfShearAngleX ), - mfShearAngleY( rRenderGraphicRasterizer.mfShearAngleY ) -{ -} - -// ------------------------------------------------------------------------- - -RenderGraphicRasterizer::~RenderGraphicRasterizer() -{ -} - -// ------------------------------------------------------------------------- - -RenderGraphicRasterizer& RenderGraphicRasterizer::operator=( - const RenderGraphicRasterizer& rRenderGraphicRasterizer ) -{ - maRenderGraphic = rRenderGraphicRasterizer.maRenderGraphic; - maBitmapEx = rRenderGraphicRasterizer.maBitmapEx; - maDefaultSizePixel = rRenderGraphicRasterizer.maDefaultSizePixel; - mfRotateAngle = rRenderGraphicRasterizer.mfRotateAngle; - mfShearAngleX = rRenderGraphicRasterizer.mfShearAngleX; - mfShearAngleY = rRenderGraphicRasterizer.mfShearAngleY; - mxRasterizer = rRenderGraphicRasterizer.mxRasterizer; - - return( *this ); -} - -// ------------------------------------------------------------------------- - -const Size& RenderGraphicRasterizer::GetDefaultSizePixel() const -{ - const_cast< RenderGraphicRasterizer* >( this )->InitializeRasterizer(); - - return( maDefaultSizePixel ); -} - -// ------------------------------------------------------------------------- - -BitmapEx RenderGraphicRasterizer::GetReplacement() const -{ - BitmapEx aRet( Rasterize( GetDefaultSizePixel() ) ); - - aRet.SetPrefSize( GetPrefSize() ); - aRet.SetPrefMapMode( GetPrefMapMode() ); - - return( aRet ); -} - -// ------------------------------------------------------------------------- - -Size RenderGraphicRasterizer::GetPrefSize() const -{ - const Size aSizePixel( GetDefaultSizePixel() ); - std::auto_ptr< VirtualDevice > apCompVDev; - OutputDevice* pCompDev = NULL; - -#ifndef NO_GETAPPWINDOW - pCompDev = Application::GetAppWindow(); -#endif - - if( !pCompDev ) - { - apCompVDev.reset( new VirtualDevice ); - pCompDev = apCompVDev.get(); - } - - return( pCompDev->PixelToLogic( aSizePixel, GetPrefMapMode() ) ); -} - -// ------------------------------------------------------------------------- - -MapMode RenderGraphicRasterizer::GetPrefMapMode() const -{ - return( MapMode( MAP_100TH_MM ) ); -} - -// ------------------------------------------------------------------------- - -const BitmapEx& RenderGraphicRasterizer::Rasterize( const Size& rSizePixel, - double fRotateAngle, - double fShearAngleX, - double fShearAngleY, - sal_uInt32 nMaxExtent ) const -{ - const bool bRasterize = !maRenderGraphic.IsEmpty() && - rSizePixel.Width() && rSizePixel.Height() && - ( maBitmapEx.IsEmpty() || - ( rSizePixel != maBitmapEx.GetSizePixel() ) || - ( fRotateAngle != mfRotateAngle ) || - ( fShearAngleX != mfShearAngleX ) || - ( fShearAngleY != mfShearAngleY ) ); - - if( bRasterize ) - { - const_cast< RenderGraphicRasterizer* >( this )->InitializeRasterizer(); - - if( mxRasterizer.is() ) - { - sal_uInt32 nWidth = labs( rSizePixel.Width() ); - sal_uInt32 nHeight = labs( rSizePixel.Height() ); - - // limiting the extent of the rastered bitmap - if( VCL_RASTERIZER_UNLIMITED_EXTENT != nMaxExtent ) - { - if( VCL_RASTERIZER_DEFAULT_EXTENT == nMaxExtent ) - { - nMaxExtent = nRasterizerDefaultExtent; - } - - if( ( nWidth > nMaxExtent ) || ( nHeight > nMaxExtent ) ) - { - const double fScale = static_cast< double >( nMaxExtent ) / ::std::max( nWidth, nHeight ); - - nWidth = FRound( nWidth * fScale ); - nHeight = FRound( nHeight * fScale ); - } - } - - if( !ImplRasterizeFromCache( const_cast< RenderGraphicRasterizer& >( *this ), - Size( nWidth, nHeight ), fRotateAngle, fShearAngleX, fShearAngleY ) ) - { - try - { - const uno::Sequence< beans::PropertyValue > aPropertySeq; - const Graphic aRasteredGraphic( mxRasterizer->rasterize( nWidth, - nHeight, - fRotateAngle, - fShearAngleX, - fShearAngleY, - aPropertySeq ) ); - - maBitmapEx = aRasteredGraphic.GetBitmapEx(); - mfRotateAngle = fRotateAngle; - mfShearAngleX = fShearAngleX; - mfShearAngleY = fShearAngleY; - - ImplUpdateCache( *this ); - -// OSL_TRACE( "Wanted: %d x %d / Got: %d x %d", rSizePixel.Width(), rSizePixel.Height(), maBitmapEx.GetSizePixel().Width(), maBitmapEx.GetSizePixel().Height() ); - } - catch( ... ) - { - OSL_TRACE( "caught exception during rasterization" ); - } - } - } - } - - return( maBitmapEx ); -} - -// ------------------------------------------------------------------------- - -void RenderGraphicRasterizer::InitializeRasterizer() -{ - if( !mxRasterizer.is() && !ImplInitializeFromCache( *this ) ) - { - uno::Reference< lang::XMultiServiceFactory > xFactory( ::comphelper::getProcessServiceFactory() ); - - maDefaultSizePixel.Width() = maDefaultSizePixel.Height() = 0; - - if ( !maRenderGraphic.IsEmpty() ) - { - rtl::OUString aServiceName; - - if ( 0 == maRenderGraphic.GetGraphicDataMimeType().compareToAscii( RTL_CONSTASCII_STRINGPARAM( "image/svg+xml" ) ) ) - { - aServiceName = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( VCL_SERVICENAME_RASTERIZER_SVG ) ); - } - - if( aServiceName.getLength() ) - { - try - { - mxRasterizer.set( xFactory->createInstance( aServiceName ), uno::UNO_QUERY ); - - if( mxRasterizer.is() ) - { - std::auto_ptr< VirtualDevice > apCompVDev; - OutputDevice* pCompDev = NULL; - -#ifndef NO_GETAPPWINDOW - pCompDev = Application::GetAppWindow(); -#endif - - if( !pCompDev ) - { - apCompVDev.reset( new VirtualDevice ); - pCompDev = apCompVDev.get(); - } - - const Size aDPI( pCompDev->LogicToPixel( Size( 1, 1 ), MAP_INCH ) ); - awt::Size aSizePixel; - SvMemoryStream aMemStm( maRenderGraphic.GetGraphicData().get(), - maRenderGraphic.GetGraphicDataLength(), - STREAM_READ ); - - uno::Reference< io::XInputStream > xIStm( new utl::OSeekableInputStreamWrapper( aMemStm ) ); - - if( !xIStm.is() || !mxRasterizer->initializeData( xIStm, aDPI.Width(), aDPI.Height(), aSizePixel ) ) - { - mxRasterizer.clear(); - } - else - { - maDefaultSizePixel.Width() = aSizePixel.Width; - maDefaultSizePixel.Height() = aSizePixel.Height; - } - } - } - catch( ... ) - { - DBG_UNHANDLED_EXCEPTION(); - mxRasterizer.clear(); - } - } - } - } -} - -// ------------------------------------------------------------------------------ - -RenderGraphicRasterizer::RenderGraphicRasterizerCache& RenderGraphicRasterizer::ImplGetCache() -{ - static RenderGraphicRasterizerCache* pCache = NULL; - - if( !pCache ) - { - pCache = new RenderGraphicRasterizerCache; - } - - return( *pCache ); -} - -// ------------------------------------------------------------------------------ - -bool RenderGraphicRasterizer::ImplInitializeFromCache( RenderGraphicRasterizer& rRasterizer ) -{ - RenderGraphicRasterizerCache& rCache = ImplGetCache(); - bool bRet = false; - - for( sal_uInt32 i = 0; i < rCache.size(); ++i ) - { - const RenderGraphicRasterizer* pCheck = &rCache[ i ]; - - if( pCheck && pCheck->mxRasterizer.is() && ( pCheck->maRenderGraphic == rRasterizer.maRenderGraphic ) ) - { -// OSL_TRACE( "Hit RenderGraphicRasterizer cache for initialization" ); - - rRasterizer.mxRasterizer = pCheck->mxRasterizer; - rRasterizer.maDefaultSizePixel = pCheck->maDefaultSizePixel; - - // put found Rasterizer at begin of deque - const RenderGraphicRasterizer aFound( rCache[ i ] ); - - rCache.erase( rCache.begin() + i ); - rCache.push_front( aFound ); - - - bRet = true; - } - } - - return( bRet ); -} - -// ------------------------------------------------------------------------------ - -bool RenderGraphicRasterizer::ImplRasterizeFromCache( RenderGraphicRasterizer& rRasterizer, - const Size& rSizePixel, - double fRotateAngle, - double fShearAngleX, - double fShearAngleY ) -{ - RenderGraphicRasterizerCache& rCache = ImplGetCache(); - bool bRet = false; - - for( sal_uInt32 i = 0; i < rCache.size(); ++i ) - { - const RenderGraphicRasterizer& rCheck = rCache[ i ]; - - if( rCheck.mxRasterizer.is() && rRasterizer.mxRasterizer.is() && - ( ( rCheck.mxRasterizer == rRasterizer.mxRasterizer ) || - ( rRasterizer.maRenderGraphic == rCheck.maRenderGraphic ) ) && - ( rCheck.maBitmapEx.GetSizePixel() == rSizePixel ) && - ( rCheck.mfRotateAngle == fRotateAngle ) && - ( rCheck.mfShearAngleX == fShearAngleX ) && - ( rCheck.mfShearAngleY == fShearAngleY ) ) - { -// OSL_TRACE( "Hit RenderGraphicRasterizer cache for rasterizing" ); - - rRasterizer.maBitmapEx = rCheck.maBitmapEx; - rRasterizer.mfRotateAngle = fRotateAngle; - rRasterizer.mfShearAngleX = fShearAngleX; - rRasterizer.mfShearAngleY = fShearAngleY; - - // put found Rasterizer at begin of deque - const RenderGraphicRasterizer aFound( rCache[ i ] ); - - rCache.erase( rCache.begin() + i ); - rCache.push_front( aFound ); - - bRet = true; - } - } - - return( bRet ); -} - -// ------------------------------------------------------------------------------ - -void RenderGraphicRasterizer::ImplUpdateCache( const RenderGraphicRasterizer& rRasterizer ) -{ - RenderGraphicRasterizerCache& rCache = ImplGetCache(); - const sal_uInt32 nMaxCacheSize = 8; - - if( rCache.size() < nMaxCacheSize ) - { - rCache.push_front( rRasterizer ); - } - else - { - rCache.pop_back(); - rCache.push_front( rRasterizer ); - } -} - -} // VCL diff --git a/vcl/source/gdi/svgdata.cxx b/vcl/source/gdi/svgdata.cxx new file mode 100644 index 000000000000..884d3fd1cbee --- /dev/null +++ b/vcl/source/gdi/svgdata.cxx @@ -0,0 +1,194 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http:\\www.apache.org\licenses\LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_vcl.hxx" + +#include <vcl/svgdata.hxx> +#include <comphelper/processfactory.hxx> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/graphic/XSvgParser.hpp> +#include <com/sun/star/graphic/XPrimitive2DRenderer.hpp> +#include <com/sun/star/rendering/XIntegerReadOnlyBitmap.hpp> +#include <vcl/canvastools.hxx> +#include <comphelper/seqstream.hxx> + +////////////////////////////////////////////////////////////////////////////// + +using namespace ::com::sun::star; + +////////////////////////////////////////////////////////////////////////////// + +void SvgData::ensureReplacement() +{ + ensureSequenceAndRange(); + + if(maReplacement.IsEmpty() && maSequence.hasElements()) + { + // create replacement graphic from maSequence + // create XPrimitive2DRenderer + uno::Reference< lang::XMultiServiceFactory > xFactory(::comphelper::getProcessServiceFactory()); + const rtl::OUString aServiceName(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.graphic.Primitive2DTools")); + + try + { + const uno::Reference< graphic::XPrimitive2DRenderer > xPrimitive2DRenderer(xFactory->createInstance(aServiceName), uno::UNO_QUERY_THROW); + + if(xPrimitive2DRenderer.is()) + { + uno::Sequence< beans::PropertyValue > aViewParameters; + const basegfx::B2DRange& rRange(getRange()); + geometry::RealRectangle2D aRealRect; + + aRealRect.X1 = rRange.getMinX(); + aRealRect.Y1 = rRange.getMinY(); + aRealRect.X2 = rRange.getMaxX(); + aRealRect.Y2 = rRange.getMaxY(); + + const uno::Reference< rendering::XBitmap > xBitmap( + xPrimitive2DRenderer->rasterize( + maSequence, + aViewParameters, + 72, + 72, + aRealRect, + 500000)); + + if(xBitmap.is()) + { + const uno::Reference< rendering::XIntegerReadOnlyBitmap> xIntBmp(xBitmap, uno::UNO_QUERY_THROW); + + if(xIntBmp.is()) + { + maReplacement = vcl::unotools::bitmapExFromXBitmap(xIntBmp); + } + } + } + } + catch(const uno::Exception&) + { + OSL_ENSURE(sal_False, "Got no graphic::XPrimitive2DRenderer (!)" ); + } + } +} + +////////////////////////////////////////////////////////////////////////////// + +void SvgData::ensureSequenceAndRange() +{ + if(!maSequence.hasElements() && mnSvgDataArrayLength) + { + // import SVG to maSequence, also set maRange + maRange.reset(); + + // create stream + const uno::Sequence< sal_Int8 > aPostData((sal_Int8*)maSvgDataArray.get(), mnSvgDataArrayLength); + const uno::Reference< io::XInputStream > myInputStream(new comphelper::SequenceInputStream(aPostData)); + + if(myInputStream.is()) + { + // create SVG interpreter + uno::Reference< lang::XMultiServiceFactory > xFactory(::comphelper::getProcessServiceFactory()); + const rtl::OUString aServiceName(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.graphic.SvgTools")); + + try + { + const uno::Reference< graphic::XSvgParser > xSvgParser(xFactory->createInstance(aServiceName), uno::UNO_QUERY_THROW); + + if(xSvgParser.is()) + { + maSequence = xSvgParser->getDecomposition(myInputStream, maPath); + } + } + catch(const uno::Exception&) + { + OSL_ENSURE(sal_False, "Got no graphic::XSvgParser (!)" ); + } + } + + if(maSequence.hasElements()) + { + const sal_Int32 nCount(maSequence.getLength()); + geometry::RealRectangle2D aRealRect; + uno::Sequence< beans::PropertyValue > aViewParameters; + + for(sal_Int32 a(0L); a < nCount; a++) + { + // get reference + const Primitive2DReference xReference(maSequence[a]); + + if(xReference.is()) + { + aRealRect = xReference->getRange(aViewParameters); + + maRange.expand( + basegfx::B2DRange( + aRealRect.X1, + aRealRect.Y1, + aRealRect.X2, + aRealRect.Y2)); + } + } + } + } +} + +////////////////////////////////////////////////////////////////////////////// + +SvgData::SvgData(const SvgDataArray& rSvgDataArray, sal_uInt32 nSvgDataArrayLength, const rtl::OUString& rPath) +: maSvgDataArray(rSvgDataArray), + mnSvgDataArrayLength(nSvgDataArrayLength), + maPath(rPath), + maRange(), + maSequence(), + maReplacement() +{ +} + +////////////////////////////////////////////////////////////////////////////// + +const basegfx::B2DRange& SvgData::getRange() const +{ + const_cast< SvgData* >(this)->ensureSequenceAndRange(); + + return maRange; +} + +////////////////////////////////////////////////////////////////////////////// + +const Primitive2DSequence& SvgData::getPrimitive2DSequence() const +{ + const_cast< SvgData* >(this)->ensureSequenceAndRange(); + + return maSequence; +} + +////////////////////////////////////////////////////////////////////////////// + +const BitmapEx& SvgData::getReplacement() const +{ + const_cast< SvgData* >(this)->ensureReplacement(); + + return maReplacement; +} + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/vcl/source/gdi/svgread.cxx b/vcl/source/gdi/svgread.cxx deleted file mode 100644 index 2c4855de0a8c..000000000000 --- a/vcl/source/gdi/svgread.cxx +++ /dev/null @@ -1,127 +0,0 @@ -/************************************************************** - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - *************************************************************/ - - - -// MARKER(update_precomp.py): autogen include statement, do not remove -#include <tools/stream.hxx> -#include <vcl/svgread.hxx> -#include <vcl/gdimtf.hxx> -#include <vcl/metaact.hxx> -#include <vcl/rendergraphicrasterizer.hxx> - -// ----------- -// - Defines - -// ----------- - -namespace vcl -{ - // ----------------- - // - SVGReaderImpl - - // ----------------- - - class SVGReaderImpl - { - public: - - SVGReaderImpl( SvStream& rStm ); - ~SVGReaderImpl(); - - GDIMetaFile& ImplRead( GDIMetaFile& rSVGMtf ); - - private: - - SvStream& mrStm; - }; - - // ------------------------------------------------------------------------------ - - SVGReaderImpl::SVGReaderImpl( SvStream& rStm ) : - mrStm( rStm ) - { - } - - // ------------------------------------------------------------------------ - - SVGReaderImpl::~SVGReaderImpl() - { - } - - // ------------------------------------------------------------------------ - - GDIMetaFile& SVGReaderImpl::ImplRead( GDIMetaFile& rSVGMtf ) - { - const sal_uInt32 nStmPos = mrStm.Tell(); - const sal_uInt32 nStmLen = mrStm.Seek( STREAM_SEEK_TO_END ) - nStmPos; - - if( nStmLen ) - { - const vcl::RenderGraphic aSVGGraphic( ::rtl::OUString::createFromAscii( "image/svg+xml" ), nStmLen ); - - mrStm.Seek( nStmPos ); - mrStm.Read( aSVGGraphic.GetGraphicData().get(), nStmLen ); - - if( !mrStm.GetError() ) - { - const vcl::RenderGraphicRasterizer aRasterizer( aSVGGraphic ); - const Size aDefaultSizePixel( aRasterizer.GetDefaultSizePixel() ); - - if( aDefaultSizePixel.Width() && aDefaultSizePixel.Height() ) - { - const Point aPos; - const Size aPrefSize( aRasterizer.GetPrefSize() ); - - rSVGMtf.SetPrefMapMode( aRasterizer.GetPrefMapMode() ); - rSVGMtf.SetPrefSize( aPrefSize ); - rSVGMtf.AddAction( new MetaRenderGraphicAction( aPos, aPrefSize, aSVGGraphic ) ); - rSVGMtf.WindStart(); - } - } - } - - return( rSVGMtf ); - } - - // ------------- - // - SVGReader - - // ------------- - - SVGReader::SVGReader( SvStream& rIStm ) : - mapImpl( new ::vcl::SVGReaderImpl( rIStm ) ) - { - } - - // ------------------------------------------------------------------------ - - SVGReader::~SVGReader() - { - } - - // ------------------------------------------------------------------------ - - GDIMetaFile& SVGReader::Read( GDIMetaFile& rSVGMtf ) - { - rSVGMtf = GDIMetaFile(); - - return( mapImpl.get() ? mapImpl->ImplRead( rSVGMtf ) : rSVGMtf ); - } - -} // namespace vcl diff --git a/vcl/util/makefile.mk b/vcl/util/makefile.mk index 75b3f9f527c1..8d1de2ed30f0 100644 --- a/vcl/util/makefile.mk +++ b/vcl/util/makefile.mk @@ -99,8 +99,6 @@ HXXDEPNLST= $(INC)$/vcl$/accel.hxx \ $(INC)$/vcl$/print.hxx \ $(INC)$/vcl$/prndlg.hxx \ $(INC)$/vcl$/region.hxx \ - $(INC)$/vcl$/rendergraphic.hxx \ - $(INC)$/vcl$/rendergraphicrasterizer.hxx \ $(INC)$/vcl$/salbtype.hxx \ $(INC)$/vcl$/scrbar.hxx \ $(INC)$/vcl$/slider.hxx \ diff --git a/xmloff/Library_xo.mk b/xmloff/Library_xo.mk index 0544171dbfbd..0e23b7dea241 100644 --- a/xmloff/Library_xo.mk +++ b/xmloff/Library_xo.mk @@ -119,6 +119,7 @@ $(eval $(call gb_Library_add_exception_objects,xo,\ xmloff/source/core/xmltkmap \ xmloff/source/core/xmltoken \ xmloff/source/core/xmluconv \ + xmloff/source/core/xmlmultiimagehelper \ xmloff/source/draw/EnhancedCustomShapeToken \ xmloff/source/draw/XMLGraphicsDefaultStyle \ xmloff/source/draw/XMLImageMapContext \ diff --git a/xmloff/Package_inc.mk b/xmloff/Package_inc.mk index 4e11c2b4b5d9..a71da5fe617e 100644 --- a/xmloff/Package_inc.mk +++ b/xmloff/Package_inc.mk @@ -129,3 +129,4 @@ $(eval $(call gb_Package_add_file,xmloff_inc,inc/xmloff/xmltkmap.hxx,xmloff/xmlt $(eval $(call gb_Package_add_file,xmloff_inc,inc/xmloff/xmltoken.hxx,xmloff/xmltoken.hxx)) $(eval $(call gb_Package_add_file,xmloff_inc,inc/xmloff/xmltypes.hxx,xmloff/xmltypes.hxx)) $(eval $(call gb_Package_add_file,xmloff_inc,inc/xmloff/xmluconv.hxx,xmloff/xmluconv.hxx)) +$(eval $(call gb_Package_add_file,xmloff_inc,inc/xmloff/xmlmultiimagehelper.hxx,xmloff/xmlmultiimagehelper.hxx)) diff --git a/xmloff/inc/xmloff/txtparae.hxx b/xmloff/inc/xmloff/txtparae.hxx index a83d24d15d0c..01e1ba9cbff9 100644 --- a/xmloff/inc/xmloff/txtparae.hxx +++ b/xmloff/inc/xmloff/txtparae.hxx @@ -146,6 +146,7 @@ protected: const ::rtl::OUString sGraphicFilter; const ::rtl::OUString sGraphicRotation; const ::rtl::OUString sGraphicURL; + const ::rtl::OUString sReplacementGraphicURL; const ::rtl::OUString sHeight; const ::rtl::OUString sHoriOrient; const ::rtl::OUString sHoriOrientPosition; diff --git a/xmloff/inc/xmloff/xmlmultiimagehelper.hxx b/xmloff/inc/xmloff/xmlmultiimagehelper.hxx new file mode 100644 index 000000000000..c7ce4bae7570 --- /dev/null +++ b/xmloff/inc/xmloff/xmlmultiimagehelper.hxx @@ -0,0 +1,62 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +#ifndef _XMLOFF_XMLMULTIIMAGEHELPER_HXX +#define _XMLOFF_XMLMULTIIMAGEHELPER_HXX + +#include <sal/types.h> +#include <xmloff/xmlimp.hxx> + +////////////////////////////////////////////////////////////////////////////// + +class multiImageImportHelper +{ +private: + std::vector< SvXMLImportContextRef* > maImplContextVector; + bool mbSupportsMultipleContents; + +protected: + /// helper to get the created xShape instance, needs to be overloaded + virtual rtl::OUString getGraphicURLFromImportContext(const SvXMLImportContext& rContext) const = 0; + virtual void removeGraphicFromImportContext(const SvXMLImportContext& rContext) const = 0; + +public: + multiImageImportHelper(); + ~multiImageImportHelper(); + + /// solve multiple imported images. The most valuable one is choosen, + /// see imlementation for evtl. changing weights and/or adding filetypes + void solveMultipleImages(); + + /// add a content to the remembered image import contexts + void addContent(const SvXMLImportContext& rSvXMLImportContext); + + /// read/write access to boolean switch + bool getSupportsMultipleContents() const { return mbSupportsMultipleContents; } + void setSupportsMultipleContents(bool bNew) { mbSupportsMultipleContents = bNew; } +}; + +////////////////////////////////////////////////////////////////////////////// + +#endif // _XMLOFF_XMLMULTIIMAGEHELPER_HXX + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/xmloff/source/core/xmlmultiimagehelper.cxx b/xmloff/source/core/xmlmultiimagehelper.cxx new file mode 100644 index 000000000000..9047ac9d125c --- /dev/null +++ b/xmloff/source/core/xmlmultiimagehelper.cxx @@ -0,0 +1,146 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_xmloff.hxx" + +#include <xmloff/xmlmultiimagehelper.hxx> +#include <rtl/ustring.hxx> + +////////////////////////////////////////////////////////////////////////////// + +using namespace ::com::sun::star; + +////////////////////////////////////////////////////////////////////////////// + +namespace +{ + sal_uInt32 getQualityIndex(const rtl::OUString& rString) + { + sal_uInt32 nRetval(0); + + // pixel formats first + if(rString.endsWithAsciiL(RTL_CONSTASCII_STRINGPARAM(".bmp"))) + { + return 10; + } + if(rString.endsWithAsciiL(RTL_CONSTASCII_STRINGPARAM(".gif"))) + { + return 20; + } + if(rString.endsWithAsciiL(RTL_CONSTASCII_STRINGPARAM(".jpg"))) + { + return 30; + } + if(rString.endsWithAsciiL(RTL_CONSTASCII_STRINGPARAM(".png"))) + { + return 40; + } + + // vector formats, prefer always + if(rString.endsWithAsciiL(RTL_CONSTASCII_STRINGPARAM(".svm"))) + { + return 1000; + } + if(rString.endsWithAsciiL(RTL_CONSTASCII_STRINGPARAM(".wmf"))) + { + return 1010; + } + if(rString.endsWithAsciiL(RTL_CONSTASCII_STRINGPARAM(".emf"))) + { + return 1020; + } + else if(rString.endsWithAsciiL(RTL_CONSTASCII_STRINGPARAM(".svg"))) + { + return 1030; + } + + return nRetval; + } +} + +////////////////////////////////////////////////////////////////////////////// + +multiImageImportHelper::multiImageImportHelper() +: maImplContextVector(), + mbSupportsMultipleContents(false) +{ +} + +multiImageImportHelper::~multiImageImportHelper() +{ + while(!maImplContextVector.empty()) + { + delete *(maImplContextVector.end() - 1); + maImplContextVector.pop_back(); + } +} + +void multiImageImportHelper::solveMultipleImages() +{ + if(maImplContextVector.size() > 1) + { + // multiple child contexts were imported, decide which is the most valuable one + // and remove the rest + sal_uInt32 nIndexOfPreferred(maImplContextVector.size()); + sal_uInt32 nBestQuality(0), a(0); + + for(a = 0; a < maImplContextVector.size(); a++) + { + const rtl::OUString aStreamURL(getGraphicURLFromImportContext(**maImplContextVector[a])); + const sal_uInt32 nNewQuality(getQualityIndex(aStreamURL)); + + if(nNewQuality > nBestQuality) + { + nBestQuality = nNewQuality; + nIndexOfPreferred = a; + } + } + + // correct if needed, default is to use the last entry + if(nIndexOfPreferred >= maImplContextVector.size()) + { + nIndexOfPreferred = maImplContextVector.size() - 1; + } + + // Take out the most valuable one + const std::vector< SvXMLImportContextRef* >::iterator aRemove(maImplContextVector.begin() + nIndexOfPreferred); + delete *aRemove; + maImplContextVector.erase(aRemove); + + // remove the rest from parent + for(a = 0; a < maImplContextVector.size(); a++) + { + removeGraphicFromImportContext(**maImplContextVector[a]); + } + } +} + +void multiImageImportHelper::addContent(const SvXMLImportContext& rSvXMLImportContext) +{ + if(dynamic_cast< const SvXMLImportContext* >(&rSvXMLImportContext)) + { + maImplContextVector.push_back(new SvXMLImportContextRef(const_cast< SvXMLImportContext* >(&rSvXMLImportContext))); + } +} + +////////////////////////////////////////////////////////////////////////////// +//eof diff --git a/xmloff/source/draw/shapeexport2.cxx b/xmloff/source/draw/shapeexport2.cxx index f9b0989825fa..ded603f7801c 100644 --- a/xmloff/source/draw/shapeexport2.cxx +++ b/xmloff/source/draw/shapeexport2.cxx @@ -1156,6 +1156,29 @@ void XMLShapeExport::ImpExportGraphicObjectShape( { if( !bIsEmptyPresObj ) { + OUString aReplacementUrl; + xPropSet->getPropertyValue( OUString(RTL_CONSTASCII_USTRINGPARAM("ReplacementGraphicURL"))) >>= aReplacementUrl; + + // If there is no url, then then graphic is empty + if(aReplacementUrl.getLength()) + { + const OUString aStr = mrExport.AddEmbeddedGraphicObject(aReplacementUrl); + + if(aStr.getLength()) + { + mrExport.AddAttribute(XML_NAMESPACE_XLINK, XML_HREF, aStr); + mrExport.AddAttribute(XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE ); + mrExport.AddAttribute(XML_NAMESPACE_XLINK, XML_SHOW, XML_EMBED ); + mrExport.AddAttribute(XML_NAMESPACE_XLINK, XML_ACTUATE, XML_ONLOAD ); + + // xlink:href for replacement, only written for Svg content + SvXMLElementExport aOBJ(mrExport, XML_NAMESPACE_DRAW, XML_IMAGE, sal_True, sal_True); + + // optional office:binary-data + mrExport.AddEmbeddedGraphicObjectAsBase64(aReplacementUrl); + } + } + OUString aStreamURL; OUString aStr; @@ -1189,7 +1212,7 @@ void XMLShapeExport::ImpExportGraphicObjectShape( { if( aStr[ 0 ] == '#' ) { - aStreamURL = OUString::createFromAscii( "vnd.sun.star.Package:" ); + aStreamURL = sPackageURL; aStreamURL = aStreamURL.concat( aStr.copy( 1, aStr.getLength() - 1 ) ); } diff --git a/xmloff/source/draw/ximpshap.cxx b/xmloff/source/draw/ximpshap.cxx index 11c399ff3ec6..79bcbe026c51 100644 --- a/xmloff/source/draw/ximpshap.cxx +++ b/xmloff/source/draw/ximpshap.cxx @@ -82,6 +82,7 @@ #include <basegfx/matrix/b2dhommatrix.hxx> #include <tools/string.hxx> #include <com/sun/star/drawing/XEnhancedCustomShapeDefaulter.hpp> +#include <com/sun/star/container/XChild.hpp> // --> OD 2006-02-22 #b6382898# #include <com/sun/star/text/XTextDocument.hpp> @@ -3328,7 +3329,10 @@ SdXMLFrameShapeContext::SdXMLFrameShapeContext( SvXMLImport& rImport, sal_uInt16 com::sun::star::uno::Reference< com::sun::star::drawing::XShapes >& rShapes, sal_Bool bTemporaryShape) : SdXMLShapeContext( rImport, nPrfx, rLocalName, xAttrList, rShapes, bTemporaryShape ), - mbSupportsReplacement( sal_False ) + multiImageImportHelper(), + mbSupportsReplacement( sal_False ), + mxImplContext(), + mxReplImplContext() { uno::Reference < util::XCloneable > xClone( xAttrList, uno::UNO_QUERY ); if( xClone.is() ) @@ -3342,6 +3346,67 @@ SdXMLFrameShapeContext::~SdXMLFrameShapeContext() { } +void SdXMLFrameShapeContext::removeGraphicFromImportContext(const SvXMLImportContext& rContext) const +{ + const SdXMLGraphicObjectShapeContext* pSdXMLGraphicObjectShapeContext = dynamic_cast< const SdXMLGraphicObjectShapeContext* >(&rContext); + + if(pSdXMLGraphicObjectShapeContext) + { + try + { + uno::Reference< container::XChild > xChild(pSdXMLGraphicObjectShapeContext->getShape(), uno::UNO_QUERY_THROW); + + if(xChild.is()) + { + uno::Reference< drawing::XShapes > xParent(xChild->getParent(), uno::UNO_QUERY_THROW); + + if(xParent.is()) + { + // remove from parent + xParent->remove(pSdXMLGraphicObjectShapeContext->getShape()); + + // dispose + uno::Reference< lang::XComponent > xComp(pSdXMLGraphicObjectShapeContext->getShape(), UNO_QUERY); + + if(xComp.is()) + { + xComp->dispose(); + } + } + } + } + catch( uno::Exception& ) + { + DBG_ERROR( "Error in cleanup of multiple graphic object import (!)" ); + } + } +} + +rtl::OUString SdXMLFrameShapeContext::getGraphicURLFromImportContext(const SvXMLImportContext& rContext) const +{ + rtl::OUString aRetval; + const SdXMLGraphicObjectShapeContext* pSdXMLGraphicObjectShapeContext = dynamic_cast< const SdXMLGraphicObjectShapeContext* >(&rContext); + + if(pSdXMLGraphicObjectShapeContext) + { + try + { + const uno::Reference< beans::XPropertySet > xPropSet(pSdXMLGraphicObjectShapeContext->getShape(), uno::UNO_QUERY_THROW); + + if(xPropSet.is()) + { + xPropSet->getPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("GraphicStreamURL"))) >>= aRetval; + } + } + catch( uno::Exception& ) + { + DBG_ERROR( "Error in cleanup of multiple graphic object import (!)" ); + } + } + + return aRetval; +} + SvXMLImportContext *SdXMLFrameShapeContext::CreateChildContext( sal_uInt16 nPrefix, const OUString& rLocalName, const uno::Reference< xml::sax::XAttributeList>& xAttrList ) @@ -3351,11 +3416,28 @@ SvXMLImportContext *SdXMLFrameShapeContext::CreateChildContext( sal_uInt16 nPref if( !mxImplContext.Is() ) { pContext = GetImport().GetShapeImport()->CreateFrameChildContext( - GetImport(), nPrefix, rLocalName, xAttrList, mxShapes, mxAttrList ); + GetImport(), nPrefix, rLocalName, xAttrList, mxShapes, mxAttrList); + + mxImplContext = pContext; + mbSupportsReplacement = IsXMLToken(rLocalName, XML_OBJECT ) || IsXMLToken(rLocalName, XML_OBJECT_OLE); + setSupportsMultipleContents(IsXMLToken(rLocalName, XML_IMAGE)); + if(getSupportsMultipleContents() && dynamic_cast< SdXMLGraphicObjectShapeContext* >(pContext)) + { + addContent(*mxImplContext); + } + } + else if(getSupportsMultipleContents() && XML_NAMESPACE_DRAW == nPrefix && IsXMLToken(rLocalName, XML_IMAGE)) + { + // read another image + pContext = GetImport().GetShapeImport()->CreateFrameChildContext( + GetImport(), nPrefix, rLocalName, xAttrList, mxShapes, mxAttrList); mxImplContext = pContext; - mbSupportsReplacement = IsXMLToken( rLocalName, XML_OBJECT ) || - IsXMLToken( rLocalName, XML_OBJECT_OLE ); + + if(dynamic_cast< SdXMLGraphicObjectShapeContext* >(pContext)) + { + addContent(*mxImplContext); + } } else if( mbSupportsReplacement && !mxReplImplContext && XML_NAMESPACE_DRAW == nPrefix && @@ -3415,6 +3497,9 @@ void SdXMLFrameShapeContext::StartElement(const uno::Reference< xml::sax::XAttri void SdXMLFrameShapeContext::EndElement() { + /// solve if multiple image child contexts were imported + solveMultipleImages(); + if( !mxImplContext.Is() ) { // now check if this is an empty presentation object diff --git a/xmloff/source/draw/ximpshap.hxx b/xmloff/source/draw/ximpshap.hxx index 1423f7a4b5d7..e8fe3725312f 100644 --- a/xmloff/source/draw/ximpshap.hxx +++ b/xmloff/source/draw/ximpshap.hxx @@ -38,6 +38,7 @@ #include <vector> #include <xmloff/shapeimport.hxx> +#include <xmloff/xmlmultiimagehelper.hxx> ////////////////////////////////////////////////////////////////////////////// // common shape context @@ -573,13 +574,18 @@ public: ////////////////////////////////////////////////////////////////////////////// // draw:-frame -class SdXMLFrameShapeContext : public SdXMLShapeContext +class SdXMLFrameShapeContext : public SdXMLShapeContext, public multiImageImportHelper { private: sal_Bool mbSupportsReplacement; SvXMLImportContextRef mxImplContext; SvXMLImportContextRef mxReplImplContext; +protected: + /// helper to get the created xShape instance, needs to be overloaded + virtual rtl::OUString getGraphicURLFromImportContext(const SvXMLImportContext& rContext) const; + virtual void removeGraphicFromImportContext(const SvXMLImportContext& rContext) const; + public: TYPEINFO(); diff --git a/xmloff/source/text/XMLTextFrameContext.cxx b/xmloff/source/text/XMLTextFrameContext.cxx index 1548387ffc04..3e741e2f65f9 100644 --- a/xmloff/source/text/XMLTextFrameContext.cxx +++ b/xmloff/source/text/XMLTextFrameContext.cxx @@ -433,6 +433,7 @@ public: TYPEINFO(); sal_Bool CreateIfNotThere(); + const OUString& GetHRef() const { return sHRef; } XMLTextFrameContext_Impl( SvXMLImport& rImport, sal_uInt16 nPrfx, @@ -466,7 +467,7 @@ public: ::com::sun::star::text::TextContentAnchorType GetAnchorType() const { return eAnchorType; } const ::com::sun::star::uno::Reference < - ::com::sun::star::beans::XPropertySet >& GetPropSet() { return xPropSet; } + ::com::sun::star::beans::XPropertySet >& GetPropSet() const { return xPropSet; } }; TYPEINIT1( XMLTextFrameContext_Impl, SvXMLImportContext ); @@ -759,8 +760,6 @@ void XMLTextFrameContext_Impl::Create( sal_Bool /*bHRefOrBase64*/ ) xTextImportHelper->InsertTextContent( xTxtCntnt ); } - Reference < XShape > xShape( xPropSet, UNO_QUERY ); - // #107848# // Make adding the shepe to Z-Ordering dependent from if we are // inside a inside_deleted_section (redlining). That is necessary @@ -770,6 +769,8 @@ void XMLTextFrameContext_Impl::Create( sal_Bool /*bHRefOrBase64*/ ) if(!GetImport().HasTextImport() || !GetImport().GetTextImport()->IsInsideDeleteContext()) { + Reference < XShape > xShape( xPropSet, UNO_QUERY ); + GetImport().GetShapeImport()->shapeWithZIndexAdded( xShape, nZIndex ); } @@ -1308,6 +1309,42 @@ void XMLTextFrameContext_Impl::SetDesc( const OUString& rDesc ) TYPEINIT1( XMLTextFrameContext, SvXMLImportContext ); +void XMLTextFrameContext::removeGraphicFromImportContext(const SvXMLImportContext& rContext) const +{ + const XMLTextFrameContext_Impl* pXMLTextFrameContext_Impl = dynamic_cast< const XMLTextFrameContext_Impl* >(&rContext); + + if(pXMLTextFrameContext_Impl) + { + try + { + // just dispose to delete + uno::Reference< lang::XComponent > xComp(pXMLTextFrameContext_Impl->GetPropSet(), UNO_QUERY); + + if(xComp.is()) + { + xComp->dispose(); + } + } + catch( uno::Exception& ) + { + DBG_ERROR( "Error in cleanup of multiple graphic object import (!)" ); + } + } +} + +rtl::OUString XMLTextFrameContext::getGraphicURLFromImportContext(const SvXMLImportContext& rContext) const +{ + rtl::OUString aRetval; + const XMLTextFrameContext_Impl* pXMLTextFrameContext_Impl = dynamic_cast< const XMLTextFrameContext_Impl* >(&rContext); + + if(pXMLTextFrameContext_Impl) + { + return pXMLTextFrameContext_Impl->GetHRef(); + } + + return aRetval; +} + sal_Bool XMLTextFrameContext::CreateIfNotThere() { sal_Bool bRet = sal_False; @@ -1339,6 +1376,7 @@ XMLTextFrameContext::XMLTextFrameContext( const Reference< XAttributeList > & xAttrList, TextContentAnchorType eATyp ) : SvXMLImportContext( rImport, nPrfx, rLName ) +, multiImageImportHelper() , m_xAttrList( new SvXMLAttributeList( xAttrList ) ) , m_pHyperlink( 0 ) // --> OD 2009-07-22 #i73249# @@ -1401,6 +1439,9 @@ XMLTextFrameContext::~XMLTextFrameContext() void XMLTextFrameContext::EndElement() { + /// solve if multiple image child contexts were imported + solveMultipleImages(); + SvXMLImportContext *pContext = &m_xImplContext; XMLTextFrameContext_Impl *pImpl = PTR_CAST( XMLTextFrameContext_Impl, pContext ); if( pImpl ) @@ -1505,6 +1546,10 @@ SvXMLImportContext *XMLTextFrameContext::CreateChildContext( { m_bSupportsReplacement = sal_True; } + else if(XML_TEXT_FRAME_GRAPHIC == nFrameType) + { + setSupportsMultipleContents(IsXMLToken(rLocalName, XML_IMAGE)); + } if( !pContext ) { @@ -1517,9 +1562,24 @@ SvXMLImportContext *XMLTextFrameContext::CreateChildContext( } m_xImplContext = pContext; + + if(getSupportsMultipleContents() && XML_TEXT_FRAME_GRAPHIC == nFrameType) + { + addContent(*m_xImplContext); + } } } } + else if(getSupportsMultipleContents() && XML_NAMESPACE_DRAW == p_nPrefix && IsXMLToken(rLocalName, XML_IMAGE)) + { + // read another image + pContext = new XMLTextFrameContext_Impl( + GetImport(), p_nPrefix, rLocalName, xAttrList, + m_eDefaultAnchorType, XML_TEXT_FRAME_GRAPHIC, m_xAttrList); + + m_xImplContext = pContext; + addContent(*m_xImplContext); + } else if( m_bSupportsReplacement && !m_xReplImplContext && XML_NAMESPACE_DRAW == p_nPrefix && IsXMLToken( rLocalName, XML_IMAGE ) ) diff --git a/xmloff/source/text/XMLTextFrameContext.hxx b/xmloff/source/text/XMLTextFrameContext.hxx index e8d660ced4a8..0cac2a59e23b 100644 --- a/xmloff/source/text/XMLTextFrameContext.hxx +++ b/xmloff/source/text/XMLTextFrameContext.hxx @@ -28,6 +28,7 @@ #include <com/sun/star/text/TextContentAnchorType.hpp> #endif #include <xmloff/xmlictxt.hxx> +#include <xmloff/xmlmultiimagehelper.hxx> namespace com { namespace sun { namespace star { namespace text { class XTextCursor; class XTextContent; } @@ -36,7 +37,7 @@ namespace com { namespace sun { namespace star { class SvXMLAttributeList; class XMLTextFrameContextHyperlink_Impl; -class XMLTextFrameContext : public SvXMLImportContext +class XMLTextFrameContext : public SvXMLImportContext, public multiImageImportHelper { ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList > m_xAttrList; @@ -66,6 +67,11 @@ class XMLTextFrameContext : public SvXMLImportContext sal_Bool CreateIfNotThere( ::com::sun::star::uno::Reference < ::com::sun::star::beans::XPropertySet >& rPropSet ); +protected: + /// helper to get the created xShape instance, needs to be overloaded + virtual rtl::OUString getGraphicURLFromImportContext(const SvXMLImportContext& rContext) const; + virtual void removeGraphicFromImportContext(const SvXMLImportContext& rContext) const; + public: TYPEINFO(); diff --git a/xmloff/source/text/txtparae.cxx b/xmloff/source/text/txtparae.cxx index 290b5099ed3c..ecc672b257ee 100644 --- a/xmloff/source/text/txtparae.cxx +++ b/xmloff/source/text/txtparae.cxx @@ -1223,6 +1223,7 @@ XMLTextParagraphExport::XMLTextParagraphExport( sGraphicFilter(RTL_CONSTASCII_USTRINGPARAM("GraphicFilter")), sGraphicRotation(RTL_CONSTASCII_USTRINGPARAM("GraphicRotation")), sGraphicURL(RTL_CONSTASCII_USTRINGPARAM("GraphicURL")), + sReplacementGraphicURL(RTL_CONSTASCII_USTRINGPARAM("ReplacementGraphicURL")), sHeight(RTL_CONSTASCII_USTRINGPARAM("Height")), sHoriOrient(RTL_CONSTASCII_USTRINGPARAM("HoriOrient")), sHoriOrientPosition(RTL_CONSTASCII_USTRINGPARAM("HoriOrientPosition")), @@ -3018,9 +3019,33 @@ void XMLTextParagraphExport::_exportTextGraphic( sRet.makeStringAndClear() ); } + // original content + SvXMLElementExport aElem(GetExport(), XML_NAMESPACE_DRAW, XML_FRAME, sal_False, sal_True); - SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_DRAW, - XML_FRAME, sal_False, sal_True ); + // replacement graphic for backwards compatibility, but + // only for SVG currently + OUString sReplacementOrigURL; + rPropSet->getPropertyValue( sReplacementGraphicURL ) >>= sReplacementOrigURL; + + if(sReplacementOrigURL.getLength()) + { + const OUString sReplacementURL(GetExport().AddEmbeddedGraphicObject( sReplacementOrigURL )); + + // If there is no url, then then graphic is empty + if(sReplacementURL.getLength()) + { + GetExport().AddAttribute(XML_NAMESPACE_XLINK, XML_HREF, sReplacementURL); + GetExport().AddAttribute(XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE); + GetExport().AddAttribute(XML_NAMESPACE_XLINK, XML_SHOW, XML_EMBED); + GetExport().AddAttribute(XML_NAMESPACE_XLINK, XML_ACTUATE, XML_ONLOAD); + + // xlink:href for replacement, only written for Svg content + SvXMLElementExport aElement(GetExport(), XML_NAMESPACE_DRAW, XML_IMAGE, sal_False, sal_True); + + // optional office:binary-data + GetExport().AddEmbeddedGraphicObjectAsBase64(sReplacementURL); + } + } // xlink:href OUString sOrigURL; |