diff options
Diffstat (limited to 'drawinglayer/source/primitive2d')
19 files changed, 2152 insertions, 824 deletions
diff --git a/drawinglayer/source/primitive2d/baseprimitive2d.cxx b/drawinglayer/source/primitive2d/baseprimitive2d.cxx index 54b23ed50930..293f9fdd0868 100644 --- a/drawinglayer/source/primitive2d/baseprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/baseprimitive2d.cxx @@ -1,30 +1,21 @@ /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/************************************************************************* +/* + * This file is part of the LibreOffice project. * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. * - * Copyright 2000, 2010 Oracle and/or its affiliates. + * This file incorporates work covered by the following license notice: * - * 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. - * - ************************************************************************/ + * 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 . + */ #include <drawinglayer/primitive2d/baseprimitive2d.hxx> #include <drawinglayer/geometry/viewinformation2d.hxx> @@ -117,6 +108,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/borderlineprimitive2d.cxx b/drawinglayer/source/primitive2d/borderlineprimitive2d.cxx index 36c916d07be0..31f78f5b2144 100644 --- a/drawinglayer/source/primitive2d/borderlineprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/borderlineprimitive2d.cxx @@ -1,30 +1,21 @@ /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/************************************************************************* +/* + * This file is part of the LibreOffice project. * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. * - * Copyright 2000, 2010 Oracle and/or its affiliates. + * This file incorporates work covered by the following license notice: * - * 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. - * - ************************************************************************/ + * 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 . + */ #include <drawinglayer/geometry/viewinformation2d.hxx> #include <drawinglayer/primitive2d/borderlineprimitive2d.hxx> diff --git a/drawinglayer/source/primitive2d/chartprimitive2d.cxx b/drawinglayer/source/primitive2d/chartprimitive2d.cxx deleted file mode 100644 index ebe19288d299..000000000000 --- a/drawinglayer/source/primitive2d/chartprimitive2d.cxx +++ /dev/null @@ -1,79 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/************************************************************************* - * - * 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 <drawinglayer/primitive2d/chartprimitive2d.hxx> -#include <basegfx/tools/canvastools.hxx> -#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx> - -////////////////////////////////////////////////////////////////////////////// - -using namespace com::sun::star; - -////////////////////////////////////////////////////////////////////////////// - -namespace drawinglayer -{ - namespace primitive2d - { - ChartPrimitive2D::ChartPrimitive2D( - const uno::Reference< frame::XModel >& rxChartModel, - const basegfx::B2DHomMatrix& rTransformation, - const Primitive2DSequence& rChildren) - : GroupPrimitive2D(rChildren), - mxChartModel(rxChartModel), - maTransformation(rTransformation) - { - } - - bool ChartPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const - { - if(GroupPrimitive2D::operator==(rPrimitive)) - { - const ChartPrimitive2D& rCompare = static_cast< const ChartPrimitive2D& >(rPrimitive); - - return (getChartModel() == rCompare.getChartModel() - && getTransformation() == rCompare.getTransformation()); - } - - return false; - } - - // provide unique ID - ImplPrimitrive2DIDBlock(ChartPrimitive2D, PRIMITIVE2D_ID_CHARTPRIMITIVE2D) - - basegfx::B2DRange ChartPrimitive2D::getB2DRange(const geometry::ViewInformation2D& /*rViewInformation*/) const - { - basegfx::B2DRange aRetval(0.0, 0.0, 1.0, 1.0); - aRetval.transform(getTransformation()); - return aRetval; - } - - } // end of namespace primitive2d -} // end of namespace drawinglayer - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/drawinglayer/source/primitive2d/controlprimitive2d.cxx b/drawinglayer/source/primitive2d/controlprimitive2d.cxx index 12c3f83796e1..cb09566ccf17 100644 --- a/drawinglayer/source/primitive2d/controlprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/controlprimitive2d.cxx @@ -1,30 +1,21 @@ /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/************************************************************************* +/* + * This file is part of the LibreOffice project. * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. * - * Copyright 2000, 2010 Oracle and/or its affiliates. + * This file incorporates work covered by the following license notice: * - * 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. - * - ************************************************************************/ + * 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 . + */ #include <drawinglayer/primitive2d/controlprimitive2d.hxx> #include <com/sun/star/beans/XPropertySet.hpp> diff --git a/drawinglayer/source/primitive2d/cropprimitive2d.cxx b/drawinglayer/source/primitive2d/cropprimitive2d.cxx new file mode 100644 index 000000000000..9ce8f82f0b77 --- /dev/null +++ b/drawinglayer/source/primitive2d/cropprimitive2d.cxx @@ -0,0 +1,196 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ + +#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 + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/drawinglayer/source/primitive2d/epsprimitive2d.cxx b/drawinglayer/source/primitive2d/epsprimitive2d.cxx index 9f14316084ab..e265b8c4f432 100644 --- a/drawinglayer/source/primitive2d/epsprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/epsprimitive2d.cxx @@ -1,30 +1,21 @@ /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/************************************************************************* +/* + * This file is part of the LibreOffice project. * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. * - * Copyright 2000, 2010 Oracle and/or its affiliates. + * This file incorporates work covered by the following license notice: * - * 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. - * - ************************************************************************/ + * 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 . + */ #include <drawinglayer/primitive2d/epsprimitive2d.hxx> #include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx> diff --git a/drawinglayer/source/primitive2d/fillgradientprimitive2d.cxx b/drawinglayer/source/primitive2d/fillgradientprimitive2d.cxx index 9da78c2a3e0d..2420241946b2 100644 --- a/drawinglayer/source/primitive2d/fillgradientprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/fillgradientprimitive2d.cxx @@ -1,30 +1,21 @@ /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/************************************************************************* +/* + * This file is part of the LibreOffice project. * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. * - * Copyright 2000, 2010 Oracle and/or its affiliates. + * This file incorporates work covered by the following license notice: * - * 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. - * - ************************************************************************/ + * 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 . + */ #include <drawinglayer/primitive2d/fillgradientprimitive2d.hxx> #include <basegfx/polygon/b2dpolygon.hxx> diff --git a/drawinglayer/source/primitive2d/graphicprimitive2d.cxx b/drawinglayer/source/primitive2d/graphicprimitive2d.cxx index cee3c2c9693b..74d8f0c21dfb 100644 --- a/drawinglayer/source/primitive2d/graphicprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/graphicprimitive2d.cxx @@ -1,42 +1,33 @@ /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/************************************************************************* +/* + * This file is part of the LibreOffice project. * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. * - * Copyright 2000, 2010 Oracle and/or its affiliates. + * This file incorporates work covered by the following license notice: * - * 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. - * - ************************************************************************/ + * 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 . + */ #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 @@ -247,8 +238,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()) { @@ -281,6 +272,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)); @@ -291,46 +308,33 @@ namespace drawinglayer case GRAPHIC_GDIMETAFILE : { - // create MetafilePrimitive2D - const GDIMetaFile& rMetafile = aTransformedGraphic.GetGDIMetaFile(); - - if( aTransformedGraphic.IsRenderGraphic() ) - { - 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( + // create MetafilePrimitive2D + const GDIMetaFile& rMetafile = aTransformedGraphic.GetGDIMetaFile(); + + 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 children 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)); - } - } - + 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)); + } break; } @@ -346,16 +350,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); @@ -377,68 +371,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 5f2239780142..791801bbb607 100644 --- a/drawinglayer/source/primitive2d/metafileprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/metafileprimitive2d.cxx @@ -1,30 +1,21 @@ /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/************************************************************************* +/* + * This file is part of the LibreOffice project. * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. * - * Copyright 2000, 2010 Oracle and/or its affiliates. + * This file incorporates work covered by the following license notice: * - * 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. - * - ************************************************************************/ + * 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 . + */ #include <drawinglayer/primitive2d/metafileprimitive2d.hxx> #include <basegfx/tools/canvastools.hxx> @@ -61,7 +52,6 @@ #include <drawinglayer/primitive2d/textlineprimitive2d.hxx> #include <drawinglayer/primitive2d/textstrikeoutprimitive2d.hxx> #include <drawinglayer/primitive2d/epsprimitive2d.hxx> -#include <drawinglayer/primitive2d/rendergraphicprimitive2d.hxx> #include <numeric> ////////////////////////////////////////////////////////////////////////////// @@ -709,7 +699,8 @@ namespace const drawinglayer::attribute::LineAttribute aLineAttribute( rProperties.getLineColor(), bWidthUsed ? rLineInfo.GetWidth() : 0.0, - rLineInfo.GetLineJoin()); + rLineInfo.GetLineJoin(), + rLineInfo.GetLineCap()); if(bDashDotUsed) { @@ -3067,33 +3058,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..f7c665384a53 --- /dev/null +++ b/drawinglayer/source/primitive2d/patternfillprimitive2d.cxx @@ -0,0 +1,150 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ + +#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 + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/drawinglayer/source/primitive2d/polygonprimitive2d.cxx b/drawinglayer/source/primitive2d/polygonprimitive2d.cxx index 373698db2b6b..ccc52baf6e94 100644 --- a/drawinglayer/source/primitive2d/polygonprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/polygonprimitive2d.cxx @@ -1,30 +1,21 @@ /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/************************************************************************* +/* + * This file is part of the LibreOffice project. * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. * - * Copyright 2000, 2010 Oracle and/or its affiliates. + * This file incorporates work covered by the following license notice: * - * 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. - * - ************************************************************************/ + * 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 . + */ #include <drawinglayer/primitive2d/polygonprimitive2d.hxx> #include <basegfx/tools/canvastools.hxx> @@ -34,6 +25,7 @@ #include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx> #include <drawinglayer/geometry/viewinformation2d.hxx> #include <basegfx/polygon/b2dlinegeometry.hxx> +#include <com/sun/star/drawing/LineCap.hpp> ////////////////////////////////////////////////////////////////////////////// @@ -254,13 +246,17 @@ namespace drawinglayer // create fat line data const double fHalfLineWidth(getLineAttribute().getWidth() / 2.0); const basegfx::B2DLineJoin aLineJoin(getLineAttribute().getLineJoin()); + const com::sun::star::drawing::LineCap aLineCap(getLineAttribute().getLineCap()); basegfx::B2DPolyPolygon aAreaPolyPolygon; for(sal_uInt32 a(0L); a < nCount; a++) { // New version of createAreaGeometry; now creates bezier polygons aAreaPolyPolygon.append(basegfx::tools::createAreaGeometry( - aHairLinePolyPolygon.getB2DPolygon(a), fHalfLineWidth, aLineJoin)); + aHairLinePolyPolygon.getB2DPolygon(a), + fHalfLineWidth, + aLineJoin, + aLineCap)); } // prepare return value @@ -341,10 +337,28 @@ namespace drawinglayer if(getLineAttribute().getWidth()) { + bool bUseDecomposition(false); + if(basegfx::B2DLINEJOIN_MITER == getLineAttribute().getLineJoin()) { // if line is mitered, use parent call since mitered line // geometry may use more space than the geometry grown by half line width + bUseDecomposition = true; + } + + if(!bUseDecomposition && com::sun::star::drawing::LineCap_SQUARE == getLineAttribute().getLineCap()) + { + // when drawing::LineCap_SQUARE is used the below method to grow the polygon + // range by half line width will not work, so use decomposition. Interestingly, + // the grow method below works perfectly for LineCap_ROUND since the grow is in + // all directions and the rounded cap needs the same grow in all directions independent + // from it's orientation. Unfortunately this is not the case for drawing::LineCap_SQUARE + bUseDecomposition = true; + } + + if(bUseDecomposition) + { + // get correct range by using the decomposition fallback, reasons see above cases aRetval = BufferedDecompositionPrimitive2D::getB2DRange(rViewInformation); } else diff --git a/drawinglayer/source/primitive2d/polypolygonprimitive2d.cxx b/drawinglayer/source/primitive2d/polypolygonprimitive2d.cxx index 13149c1d7695..1006842963de 100644 --- a/drawinglayer/source/primitive2d/polypolygonprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/polypolygonprimitive2d.cxx @@ -1,30 +1,21 @@ /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/************************************************************************* +/* + * This file is part of the LibreOffice project. * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. * - * Copyright 2000, 2010 Oracle and/or its affiliates. + * This file incorporates work covered by the following license notice: * - * 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. - * - ************************************************************************/ + * 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 . + */ #include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx> #include <basegfx/polygon/b2dpolypolygontools.hxx> @@ -210,6 +201,16 @@ namespace drawinglayer { } + PolyPolygonStrokePrimitive2D::PolyPolygonStrokePrimitive2D( + const basegfx::B2DPolyPolygon& rPolyPolygon, + const attribute::LineAttribute& rLineAttribute) + : BufferedDecompositionPrimitive2D(), + maPolyPolygon(rPolyPolygon), + maLineAttribute(rLineAttribute), + maStrokeAttribute() + { + } + bool PolyPolygonStrokePrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const { if(BufferedDecompositionPrimitive2D::operator==(rPrimitive)) diff --git a/drawinglayer/source/primitive2d/rendergraphicprimitive2d.cxx b/drawinglayer/source/primitive2d/rendergraphicprimitive2d.cxx deleted file mode 100644 index 8e317a14301c..000000000000 --- a/drawinglayer/source/primitive2d/rendergraphicprimitive2d.cxx +++ /dev/null @@ -1,79 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/************************************************************************* - * - * 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 <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) - { - } - - 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 - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/drawinglayer/source/primitive2d/sceneprimitive2d.cxx b/drawinglayer/source/primitive2d/sceneprimitive2d.cxx index 165fcc9f795c..32bc48ca763e 100644 --- a/drawinglayer/source/primitive2d/sceneprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/sceneprimitive2d.cxx @@ -1,30 +1,21 @@ /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/************************************************************************* +/* + * This file is part of the LibreOffice project. * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. * - * Copyright 2000, 2010 Oracle and/or its affiliates. + * This file incorporates work covered by the following license notice: * - * 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. - * - ************************************************************************/ + * 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 . + */ #include <drawinglayer/primitive2d/sceneprimitive2d.hxx> #include <basegfx/tools/canvastools.hxx> @@ -207,24 +198,84 @@ namespace drawinglayer } } - // calculate logic render size in world coordinates for usage in renderer - basegfx::B2DVector aLogicRenderSize( - aDiscreteRange.getWidth() * fReduceFactor, - aDiscreteRange.getHeight() * fReduceFactor); - aLogicRenderSize *= rViewInformation.getInverseObjectToViewTransformation(); - // determine the oversample value static sal_uInt16 nDefaultOversampleValue(3); const sal_uInt16 nOversampleValue(aDrawinglayerOpt.IsAntiAliasing() ? nDefaultOversampleValue : 0); + geometry::ViewInformation3D aViewInformation3D(getViewInformation3D()); + { + // calculate a transformation from DiscreteRange to evtl. rotated/sheared content. + // Start with full transformation from object to discrete units + basegfx::B2DHomMatrix aObjToUnit(rViewInformation.getObjectToViewTransformation() * getObjectTransformation()); + + // bring to unit coordinates by applying inverse DiscreteRange + aObjToUnit.translate(-aDiscreteRange.getMinX(), -aDiscreteRange.getMinY()); + aObjToUnit.scale(1.0 / aDiscreteRange.getWidth(), 1.0 / aDiscreteRange.getHeight()); + + // calculate transformed user coordinate system + const basegfx::B2DPoint aStandardNull(0.0, 0.0); + const basegfx::B2DPoint aUnitRangeTopLeft(aObjToUnit * aStandardNull); + const basegfx::B2DVector aStandardXAxis(1.0, 0.0); + const basegfx::B2DVector aUnitRangeXAxis(aObjToUnit * aStandardXAxis); + const basegfx::B2DVector aStandardYAxis(0.0, 1.0); + const basegfx::B2DVector aUnitRangeYAxis(aObjToUnit * aStandardYAxis); + + if(!aUnitRangeTopLeft.equal(aStandardNull) || !aUnitRangeXAxis.equal(aStandardXAxis) || !aUnitRangeYAxis.equal(aStandardYAxis)) + { + // build transformation from unit range to user coordinate system; the unit range + // X and Y axes are the column vectors, the null point is the offset + basegfx::B2DHomMatrix aUnitRangeToUser; + + aUnitRangeToUser.set3x2( + aUnitRangeXAxis.getX(), aUnitRangeYAxis.getX(), aUnitRangeTopLeft.getX(), + aUnitRangeXAxis.getY(), aUnitRangeYAxis.getY(), aUnitRangeTopLeft.getY()); + + // decompose to allow to apply this to the 3D transformation + basegfx::B2DVector aScale, aTranslate; + double fRotate, fShearX; + aUnitRangeToUser.decompose(aScale, aTranslate, fRotate, fShearX); + + // apply before DeviceToView and after Projection, 3D is in range [-1.0 .. 1.0] in X,Y and Z + // and not yet flipped in Y + basegfx::B3DHomMatrix aExtendedProjection(aViewInformation3D.getProjection()); + + // bring to unit coordiantes, flip Y, leave Z unchanged + aExtendedProjection.scale(0.5, -0.5, 1.0); + aExtendedProjection.translate(0.5, 0.5, 0.0); + + // apply extra; Y is flipped now, go with positive shear and rotate values + aExtendedProjection.scale(aScale.getX(), aScale.getY(), 1.0); + aExtendedProjection.shearXZ(fShearX, 0.0); + aExtendedProjection.rotate(0.0, 0.0, fRotate); + aExtendedProjection.translate(aTranslate.getX(), aTranslate.getY(), 0.0); + + // back to state after projection + aExtendedProjection.translate(-0.5, -0.5, 0.0); + aExtendedProjection.scale(2.0, -2.0, 1.0); + + aViewInformation3D = geometry::ViewInformation3D( + aViewInformation3D.getObjectTransformation(), + aViewInformation3D.getOrientation(), + aExtendedProjection, + aViewInformation3D.getDeviceToView(), + aViewInformation3D.getViewTime(), + aViewInformation3D.getExtendedInformationSequence()); + } + } + + // calculate logic render size in world coordinates for usage in renderer + const basegfx::B2DHomMatrix aInverseOToV(rViewInformation.getInverseObjectToViewTransformation()); + const double fLogicX((aInverseOToV * basegfx::B2DVector(aDiscreteRange.getWidth() * fReduceFactor, 0.0)).getLength()); + const double fLogicY((aInverseOToV * basegfx::B2DVector(0.0, aDiscreteRange.getHeight() * fReduceFactor)).getLength()); + // use default 3D primitive processor to create BitmapEx for aUnitVisiblePart and process processor3d::ZBufferProcessor3D aZBufferProcessor3D( - getViewInformation3D(), + aViewInformation3D, rViewInformation, getSdrSceneAttribute(), getSdrLightingAttribute(), - aLogicRenderSize.getX(), - aLogicRenderSize.getY(), + fLogicX, + fLogicY, aUnitVisibleRange, nOversampleValue); @@ -245,7 +296,7 @@ namespace drawinglayer aNew2DTransform.set(1, 2, aVisibleDiscreteRange.getMinY()); // transform back to world coordinates for usage in primitive creation - aNew2DTransform *= rViewInformation.getInverseObjectToViewTransformation(); + aNew2DTransform *= aInverseOToV; // create bitmap primitive and add const Primitive2DReference xRef(new BitmapPrimitive2D(maOldRenderedBitmap, aNew2DTransform)); diff --git a/drawinglayer/source/primitive2d/svggradientprimitive2d.cxx b/drawinglayer/source/primitive2d/svggradientprimitive2d.cxx new file mode 100644 index 000000000000..a8c60da51299 --- /dev/null +++ b/drawinglayer/source/primitive2d/svggradientprimitive2d.cxx @@ -0,0 +1,1087 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ + +#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 +{ + sal_uInt32 calculateStepsForSvgGradient(const basegfx::BColor& rColorA, const basegfx::BColor& rColorB, double fDelta, double fDiscreteUnit) + { + // use color distance, assume to do every color step (full quality) + sal_uInt32 nSteps(basegfx::fround(rColorA.getDistance(rColorB) * 255.0)); + + if(nSteps) + { + // calc discrete length to change color all 1.5 disctete units (pixels) + const sal_uInt32 nDistSteps(basegfx::fround(fDelta / (fDiscreteUnit * 1.5))); + + nSteps = std::min(nSteps, nDistSteps); + } + + // roughly cut when too big or too small + nSteps = std::min(nSteps, sal_uInt32(255)); + nSteps = std::max(nSteps, sal_uInt32(1)); + + return nSteps; + } +} // end of anonymous namespace + +////////////////////////////////////////////////////////////////////////////// + +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) + : maPolyPolygon(rPolyPolygon), + maGradientEntries(rGradientEntries), + maStart(rStart), + maSpreadMethod(aSpreadMethod), + mbPreconditionsChecked(false), + mbCreatesContent(false), + mbSingleEntry(false), + mbFullyOpaque(true) + { + } + + bool SvgGradientHelper::equalTo(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()); + } + + } // 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::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 + { + rTargetColor.push_back( + new SvgLinearAtomPrimitive2D( + rFrom.getColor(), rFrom.getOffset() + nOffset, + rTo.getColor(), rTo.getOffset() + nOffset)); + + 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)); + } + } + + 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) + : BufferedDecompositionPrimitive2D(), + SvgGradientHelper(rPolyPolygon, rGradientEntries, rStart, aSpreadMethod), + maEnd(rEnd) + { + } + + bool SvgLinearGradientPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const + { + const SvgGradientHelper* pSvgGradientHelper = dynamic_cast< const SvgGradientHelper* >(&rPrimitive); + + if(pSvgGradientHelper && SvgGradientHelper::equalTo(*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::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 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)); + } + else + { + rTargetColor.push_back( + new SvgRadialAtomPrimitive2D( + rFrom.getColor(), fScaleFrom, + rTo.getColor(), fScaleTo)); + } + + 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); + + 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)); + } + else + { + rTargetOpacity.push_back( + new SvgRadialAtomPrimitive2D( + aColorFrom, fScaleFrom, + aColorTo, fScaleTo)); + } + } + } + + 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 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) + : BufferedDecompositionPrimitive2D(), + SvgGradientHelper(rPolyPolygon, rGradientEntries, rStart, aSpreadMethod), + 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::equalTo(*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)) + { + // use one discrete unit for overlap (one pixel) + const double fDiscreteUnit(getDiscreteUnit()); + + // use color distance and discrete lengths to calculate step count + const sal_uInt32 nSteps(calculateStepsForSvgGradient(getColorA(), getColorB(), fDelta, fDiscreteUnit)); + + // prepare loop and polygon (with overlap for linear gradients) + double fStart(0.0); + double fStep(fDelta / nSteps); + const basegfx::B2DPolygon aPolygon( + basegfx::tools::createPolygonFromRect( + basegfx::B2DRange( + getOffsetA() - fDiscreteUnit, + 0.0, + getOffsetA() + fStep + fDiscreteUnit, + 1.0))); + + // loop and create primitives + xRetval.realloc(nSteps); + + for(sal_uInt32 a(0); a < nSteps; a++, fStart += fStep) + { + basegfx::B2DPolygon aNew(aPolygon); + + aNew.transform(basegfx::tools::createTranslateB2DHomMatrix(fStart, 0.0)); + xRetval[a] = new PolyPolygonColorPrimitive2D( + basegfx::B2DPolyPolygon(aNew), + basegfx::interpolate(getColorA(), getColorB(), fStart/fDelta)); + } + } + + return xRetval; + } + + SvgLinearAtomPrimitive2D::SvgLinearAtomPrimitive2D( + const basegfx::BColor& aColorA, double fOffsetA, + const basegfx::BColor& aColorB, double fOffsetB) + : DiscreteMetricDependentPrimitive2D(), + maColorA(aColorA), + maColorB(aColorB), + mfOffsetA(fOffsetA), + mfOffsetB(fOffsetB) + { + if(mfOffsetA > mfOffsetB) + { + OSL_ENSURE(false, "Wrong offset order (!)"); + ::std::swap(mfOffsetA, mfOffsetB); + } + } + + 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()); + } + + 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)) + { + // use one discrete unit for overlap (one pixel) + const double fDiscreteUnit(getDiscreteUnit()); + + // use color distance and discrete lengths to calculate step count + const sal_uInt32 nSteps(calculateStepsForSvgGradient(getColorA(), getColorB(), fDeltaScale, fDiscreteUnit)); + + // prepare loop (outside to inside, full polygons, no polypolygons with holes) + double fEndScale(getScaleB()); + double fStepScale(fDeltaScale / nSteps); + + // loop and create primitives + xRetval.realloc(nSteps); + + for(sal_uInt32 a(0); a < nSteps; a++, fEndScale -= fStepScale) + { + const double fUnitScale(fEndScale/fDeltaScale); + basegfx::B2DHomMatrix aTransform; + + if(isTranslateSet()) + { + const basegfx::B2DVector aTranslate( + basegfx::interpolate( + getTranslateA(), + getTranslateB(), + fUnitScale)); + + aTransform = basegfx::tools::createScaleTranslateB2DHomMatrix( + fEndScale, + fEndScale, + aTranslate.getX(), + aTranslate.getY()); + } + else + { + aTransform = basegfx::tools::createScaleB2DHomMatrix( + fEndScale, + fEndScale); + } + + basegfx::B2DPolygon aNew(basegfx::tools::createPolygonFromUnitCircle()); + + aNew.transform(aTransform); + xRetval[a] = new PolyPolygonColorPrimitive2D( + basegfx::B2DPolyPolygon(aNew), + basegfx::interpolate(getColorA(), getColorB(), fUnitScale)); + } + } + + return xRetval; + } + + SvgRadialAtomPrimitive2D::SvgRadialAtomPrimitive2D( + const basegfx::BColor& aColorA, double fScaleA, const basegfx::B2DVector& rTranslateA, + const basegfx::BColor& aColorB, double fScaleB, const basegfx::B2DVector& rTranslateB) + : DiscreteMetricDependentPrimitive2D(), + maColorA(aColorA), + maColorB(aColorB), + mfScaleA(fScaleA), + mfScaleB(fScaleB), + mpTranslate(0) + { + // check and evtl. set translations + if(!rTranslateA.equal(rTranslateB)) + { + mpTranslate = new VectorPair(rTranslateA, rTranslateB); + } + + // scale A and B have to be positive + mfScaleA = ::std::max(mfScaleA, 0.0); + mfScaleB = ::std::max(mfScaleB, 0.0); + + // scale B has to be bigger than scale A; swap if different + if(mfScaleA > mfScaleB) + { + OSL_ENSURE(false, "Wrong offset order (!)"); + ::std::swap(mfScaleA, mfScaleB); + + if(mpTranslate) + { + ::std::swap(mpTranslate->maTranslateA, mpTranslate->maTranslateB); + } + } + } + + SvgRadialAtomPrimitive2D::SvgRadialAtomPrimitive2D( + const basegfx::BColor& aColorA, double fScaleA, + const basegfx::BColor& aColorB, double fScaleB) + : DiscreteMetricDependentPrimitive2D(), + maColorA(aColorA), + maColorB(aColorB), + mfScaleA(fScaleA), + mfScaleB(fScaleB), + mpTranslate(0) + { + // scale A and B have to be positive + mfScaleA = ::std::max(mfScaleA, 0.0); + mfScaleB = ::std::max(mfScaleB, 0.0); + + // scale B has to be bigger than scale A; swap if different + if(mfScaleA > mfScaleB) + { + OSL_ENSURE(false, "Wrong offset order (!)"); + ::std::swap(mfScaleA, mfScaleB); + } + } + + SvgRadialAtomPrimitive2D::~SvgRadialAtomPrimitive2D() + { + if(mpTranslate) + { + delete mpTranslate; + mpTranslate = 0; + } + } + + bool SvgRadialAtomPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const + { + if(DiscreteMetricDependentPrimitive2D::operator==(rPrimitive)) + { + const SvgRadialAtomPrimitive2D& rCompare = static_cast< const SvgRadialAtomPrimitive2D& >(rPrimitive); + + if(getColorA() == rCompare.getColorA() + && getColorB() == rCompare.getColorB() + && getScaleA() == rCompare.getScaleA() + && getScaleB() == rCompare.getScaleB()) + { + if(isTranslateSet() && rCompare.isTranslateSet()) + { + return (getTranslateA() == rCompare.getTranslateA() + && getTranslateB() == rCompare.getTranslateB()); + } + else if(!isTranslateSet() && !rCompare.isTranslateSet()) + { + return true; + } + } + } + + return false; + } + + // provide unique ID + ImplPrimitrive2DIDBlock(SvgRadialAtomPrimitive2D, PRIMITIVE2D_ID_SVGRADIALATOMPRIMITIVE2D) + + } // end of namespace primitive2d +} // end of namespace drawinglayer + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/drawinglayer/source/primitive2d/textbreakuphelper.cxx b/drawinglayer/source/primitive2d/textbreakuphelper.cxx new file mode 100644 index 000000000000..6a4a40cc1076 --- /dev/null +++ b/drawinglayer/source/primitive2d/textbreakuphelper.cxx @@ -0,0 +1,303 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ + +#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> +#include <com/sun/star/i18n/CharType.hpp> + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace primitive2d + { + TextBreakupHelper::TextBreakupHelper(const TextSimplePortionPrimitive2D& rSource) + : mrSource(rSource), + mxResult(), + maTextLayouter(), + maDecTrans(), + mbNoDXArray(false) + { + OSL_ENSURE(dynamic_cast< const TextSimplePortionPrimitive2D* >(&mrSource), "TextBreakupHelper with illegal primitive created (!)"); + maDecTrans = mrSource.getTextTransform(); + mbNoDXArray = mrSource.getDXArray().empty(); + + if(mbNoDXArray) + { + // init TextLayouter when no dxarray + maTextLayouter.setFontAttribute( + mrSource.getFontAttribute(), + maDecTrans.getScale().getX(), + maDecTrans.getScale().getY(), + mrSource.getLocale()); + } + } + + TextBreakupHelper::~TextBreakupHelper() + { + } + + void TextBreakupHelper::breakupPortion(Primitive2DVector& rTempResult, sal_uInt32 nIndex, sal_uInt32 nLength, bool bWordLineMode) + { + if(nLength && !(nIndex == mrSource.getTextPosition() && nLength == mrSource.getTextLength())) + { + // prepare values for new portion + basegfx::B2DHomMatrix aNewTransform; + ::std::vector< double > aNewDXArray; + const bool bNewStartIsNotOldStart(nIndex > mrSource.getTextPosition()); + + if(!mbNoDXArray) + { + // prepare new DXArray for the single word + aNewDXArray = ::std::vector< double >( + mrSource.getDXArray().begin() + (nIndex - mrSource.getTextPosition()), + mrSource.getDXArray().begin() + ((nIndex + nLength) - mrSource.getTextPosition())); + } + + if(bNewStartIsNotOldStart) + { + // needs to be moved to a new start position + double fOffset(0.0); + + if(mbNoDXArray) + { + // evaluate using TextLayouter + fOffset = maTextLayouter.getTextWidth(mrSource.getText(), mrSource.getTextPosition(), nIndex); + } + else + { + // get from DXArray + const sal_uInt32 nIndex2(static_cast< sal_uInt32 >(nIndex - mrSource.getTextPosition())); + fOffset = mrSource.getDXArray()[nIndex2 - 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* >(&mrSource); + + if(pTextDecoratedPortionPrimitive2D) + { + // create a TextDecoratedPortionPrimitive2D + rTempResult.push_back( + new TextDecoratedPortionPrimitive2D( + aNewTransform, + mrSource.getText(), + nIndex, + nLength, + aNewDXArray, + mrSource.getFontAttribute(), + mrSource.getLocale(), + mrSource.getFontColor(), + + pTextDecoratedPortionPrimitive2D->getOverlineColor(), + pTextDecoratedPortionPrimitive2D->getTextlineColor(), + pTextDecoratedPortionPrimitive2D->getFontOverline(), + pTextDecoratedPortionPrimitive2D->getFontUnderline(), + pTextDecoratedPortionPrimitive2D->getUnderlineAbove(), + pTextDecoratedPortionPrimitive2D->getTextStrikeout(), + + // reset WordLineMode when BreakupUnit_word is executed; else copy original + bWordLineMode ? false : pTextDecoratedPortionPrimitive2D->getWordLineMode(), + + pTextDecoratedPortionPrimitive2D->getTextEmphasisMark(), + pTextDecoratedPortionPrimitive2D->getEmphasisMarkAbove(), + pTextDecoratedPortionPrimitive2D->getEmphasisMarkBelow(), + pTextDecoratedPortionPrimitive2D->getTextRelief(), + pTextDecoratedPortionPrimitive2D->getShadow())); + } + else + { + // create a SimpleTextPrimitive + rTempResult.push_back( + new TextSimplePortionPrimitive2D( + aNewTransform, + mrSource.getText(), + nIndex, + nLength, + aNewDXArray, + mrSource.getFontAttribute(), + mrSource.getLocale(), + mrSource.getFontColor())); + } + } + } + } + + bool TextBreakupHelper::allowChange(sal_uInt32 /*nCount*/, basegfx::B2DHomMatrix& /*rNewTransform*/, sal_uInt32 /*nIndex*/, sal_uInt32 /*nLength*/) + { + return true; + } + + void TextBreakupHelper::breakup(BreakupUnit aBreakupUnit) + { + if(mrSource.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 = mrSource.getText(); + const sal_Int32 nTextLength(mrSource.getTextLength()); + const ::com::sun::star::lang::Locale& rLocale = mrSource.getLocale(); + const sal_Int32 nTextPosition(mrSource.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, false); + nCurrent = a; + nNextCellBreak = xBreakIterator->nextCharacters(rTxt, a, rLocale, ::com::sun::star::i18n::CharacterIteratorMode::SKIPCELL, 1, nDone); + } + } + + breakupPortion(aTempResult, nCurrent, a - nCurrent, false); + 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) + { + if(a > nCurrent) + { + breakupPortion(aTempResult, nCurrent, a - nCurrent, true); + } + + nCurrent = a; + + // skip spaces (maybe enhanced with a bool later if needed) + { + const sal_Int32 nEndOfSpaces(xBreakIterator->endOfCharBlock(rTxt, a, rLocale, ::com::sun::star::i18n::CharType::SPACE_SEPARATOR)); + + if(nEndOfSpaces > a) + { + nCurrent = nEndOfSpaces; + } + } + + nNextWordBoundary = xBreakIterator->getWordBoundary(rTxt, a + 1, rLocale, ::com::sun::star::i18n::WordType::ANY_WORD, sal_True); + } + } + + if(a > nCurrent) + { + breakupPortion(aTempResult, nCurrent, a - nCurrent, true); + } + 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, false); + nCurrent = a; + nNextSentenceBreak = xBreakIterator->endOfSentence(rTxt, a + 1, rLocale); + } + } + + breakupPortion(aTempResult, nCurrent, a - nCurrent, false); + break; + } + } + } + + mxResult = Primitive2DVectorToPrimitive2DSequence(aTempResult); + } + } + + const Primitive2DSequence& TextBreakupHelper::getResult(BreakupUnit aBreakupUnit) const + { + if(!mxResult.hasElements()) + { + const_cast< TextBreakupHelper* >(this)->breakup(aBreakupUnit); + } + + return mxResult; + } + + } // end of namespace primitive2d +} // end of namespace drawinglayer + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/drawinglayer/source/primitive2d/textdecoratedprimitive2d.cxx b/drawinglayer/source/primitive2d/textdecoratedprimitive2d.cxx index 1c6fca4b8200..ba4fbd4788b1 100644 --- a/drawinglayer/source/primitive2d/textdecoratedprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/textdecoratedprimitive2d.cxx @@ -1,45 +1,33 @@ /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/************************************************************************* +/* + * This file is part of the LibreOffice project. * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. * - * Copyright 2000, 2010 Oracle and/or its affiliates. + * This file incorporates work covered by the following license notice: * - * 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. - * - ************************************************************************/ + * 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 . + */ #include <drawinglayer/primitive2d/textdecoratedprimitive2d.hxx> -#include <drawinglayer/primitive2d/textlayoutdevice.hxx> #include <drawinglayer/primitive2d/polygonprimitive2d.hxx> #include <drawinglayer/attribute/strokeattribute.hxx> #include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx> #include <basegfx/matrix/b2dhommatrixtools.hxx> -#include <comphelper/processfactory.hxx> -#include <com/sun/star/i18n/WordType.hpp> #include <drawinglayer/primitive2d/texteffectprimitive2d.hxx> #include <drawinglayer/primitive2d/shadowprimitive2d.hxx> -#include <com/sun/star/i18n/XBreakIterator.hpp> #include <drawinglayer/primitive2d/transformprimitive2d.hxx> #include <drawinglayer/primitive2d/textlineprimitive2d.hxx> #include <drawinglayer/primitive2d/textstrikeoutprimitive2d.hxx> +#include <drawinglayer/primitive2d/textbreakuphelper.hxx> ////////////////////////////////////////////////////////////////////////////// @@ -167,232 +155,47 @@ namespace drawinglayer // TODO: Handle Font Emphasis Above/Below } - void TextDecoratedPortionPrimitive2D::impCorrectTextBoundary(::com::sun::star::i18n::Boundary& rNextWordBoundary) const - { - // truncate aNextWordBoundary to min/max possible values. This is necessary since the word start may be - // before/after getTextPosition() when a long string is the content and getTextPosition() - // is right inside a word. Same for end. - const sal_Int32 aMinPos(static_cast< sal_Int32 >(getTextPosition())); - const sal_Int32 aMaxPos(aMinPos + static_cast< sal_Int32 >(getTextLength())); - - if(rNextWordBoundary.startPos < aMinPos) - { - rNextWordBoundary.startPos = aMinPos; - } - else if(rNextWordBoundary.startPos > aMaxPos) - { - rNextWordBoundary.startPos = aMaxPos; - } - - if(rNextWordBoundary.endPos < aMinPos) - { - rNextWordBoundary.endPos = aMinPos; - } - else if(rNextWordBoundary.endPos > aMaxPos) - { - rNextWordBoundary.endPos = aMaxPos; - } - } - - void TextDecoratedPortionPrimitive2D::impSplitSingleWords( - std::vector< Primitive2DReference >& rTarget, - basegfx::tools::B2DHomMatrixBufferedOnDemandDecompose& rDecTrans) const + Primitive2DSequence TextDecoratedPortionPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const { - // break iterator support - // made static so it only needs to be fetched once, even with many single - // constructed VclMetafileProcessor2D. It's still incarnated on demand, - // but exists for OOo runtime now by purpose. - static ::com::sun::star::uno::Reference< ::com::sun::star::i18n::XBreakIterator > xLocalBreakIterator; - - if(!xLocalBreakIterator.is()) - { - ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xMSF(::comphelper::getProcessServiceFactory()); - xLocalBreakIterator.set(xMSF->createInstance("com.sun.star.i18n.BreakIterator"), ::com::sun::star::uno::UNO_QUERY); - } - - if(xLocalBreakIterator.is() && getTextLength()) + if(getWordLineMode()) { - // init word iterator, get first word and truncate to possibilities - ::com::sun::star::i18n::Boundary aNextWordBoundary(xLocalBreakIterator->getWordBoundary( - getText(), getTextPosition(), getLocale(), ::com::sun::star::i18n::WordType::ANYWORD_IGNOREWHITESPACES, sal_True)); - - if(aNextWordBoundary.endPos == getTextPosition()) - { - // backward hit, force next word - aNextWordBoundary = xLocalBreakIterator->getWordBoundary( - getText(), getTextPosition() + 1, getLocale(), ::com::sun::star::i18n::WordType::ANYWORD_IGNOREWHITESPACES, sal_True); - } + // support for single word mode; split to single word primitives + // using TextBreakupHelper + const TextBreakupHelper aTextBreakupHelper(*this); + const Primitive2DSequence aBroken(aTextBreakupHelper.getResult(BreakupUnit_word)); - impCorrectTextBoundary(aNextWordBoundary); - - // prepare new font attributes WITHOUT outline - const attribute::FontAttribute aNewFontAttribute( - getFontAttribute().getFamilyName(), - getFontAttribute().getStyleName(), - getFontAttribute().getWeight(), - getFontAttribute().getSymbol(), - getFontAttribute().getVertical(), - getFontAttribute().getItalic(), - getFontAttribute().getMonospaced(), - false, // no outline anymore, handled locally - getFontAttribute().getRTL(), - getFontAttribute().getBiDiStrong()); - - if(aNextWordBoundary.startPos == getTextPosition() && aNextWordBoundary.endPos == getTextLength()) + if(aBroken.hasElements()) { - // it IS only a single word, handle as one word - impCreateGeometryContent(rTarget, rDecTrans, getText(), getTextPosition(), getTextLength(), getDXArray(), aNewFontAttribute); + // was indeed split to several words, use as result + return aBroken; } else { - // prepare TextLayouter - const bool bNoDXArray(getDXArray().empty()); - TextLayouterDevice aTextLayouter; - - if(bNoDXArray) - { - // ..but only completely when no DXArray - aTextLayouter.setFontAttribute( - getFontAttribute(), - rDecTrans.getScale().getX(), - rDecTrans.getScale().getY(), - getLocale()); - } - - // do iterate over single words - while(aNextWordBoundary.startPos != aNextWordBoundary.endPos) - { - // prepare values for new portion - const xub_StrLen nNewTextStart(static_cast< xub_StrLen >(aNextWordBoundary.startPos)); - const xub_StrLen nNewTextEnd(static_cast< xub_StrLen >(aNextWordBoundary.endPos)); - - // prepare transform for the single word - basegfx::B2DHomMatrix aNewTransform; - ::std::vector< double > aNewDXArray; - const bool bNewStartIsNotOldStart(nNewTextStart > getTextPosition()); - - if(!bNoDXArray) - { - // prepare new DXArray for the single word - aNewDXArray = ::std::vector< double >( - getDXArray().begin() + static_cast< sal_uInt32 >(nNewTextStart - getTextPosition()), - getDXArray().begin() + static_cast< sal_uInt32 >(nNewTextEnd - getTextPosition())); - } - - if(bNewStartIsNotOldStart) - { - // needs to be moved to a new start position - double fOffset(0.0); - - if(bNoDXArray) - { - // evaluate using TextLayouter - fOffset = aTextLayouter.getTextWidth(getText(), getTextPosition(), nNewTextStart); - } - else - { - // get from DXArray - const sal_uInt32 nIndex(static_cast< sal_uInt32 >(nNewTextStart - getTextPosition())); - fOffset = 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(rDecTrans.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(!bNoDXArray) - { - // 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 *= rDecTrans.getB2DHomMatrix(); - - // create geometry content for the single word. Do not forget - // to use the new transformation - basegfx::tools::B2DHomMatrixBufferedOnDemandDecompose aDecTrans(aNewTransform); - - impCreateGeometryContent(rTarget, aDecTrans, getText(), nNewTextStart, - nNewTextEnd - nNewTextStart, aNewDXArray, aNewFontAttribute); - - if(aNextWordBoundary.endPos >= getTextPosition() + getTextLength()) - { - // end reached - aNextWordBoundary.startPos = aNextWordBoundary.endPos; - } - else - { - // get new word portion - const sal_Int32 nLastEndPos(aNextWordBoundary.endPos); - - aNextWordBoundary = xLocalBreakIterator->getWordBoundary( - getText(), aNextWordBoundary.endPos, getLocale(), - ::com::sun::star::i18n::WordType::ANYWORD_IGNOREWHITESPACES, sal_True); - - if(nLastEndPos == aNextWordBoundary.endPos) - { - // backward hit, force next word - aNextWordBoundary = xLocalBreakIterator->getWordBoundary( - getText(), nLastEndPos + 1, getLocale(), - ::com::sun::star::i18n::WordType::ANYWORD_IGNOREWHITESPACES, sal_True); - } - - impCorrectTextBoundary(aNextWordBoundary); - } - } + // no split, was already a single word. Continue to + // decompse local entity } } - } - - Primitive2DSequence TextDecoratedPortionPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const - { std::vector< Primitive2DReference > aNewPrimitives; basegfx::tools::B2DHomMatrixBufferedOnDemandDecompose aDecTrans(getTextTransform()); Primitive2DSequence aRetval; // create basic geometry such as SimpleTextPrimitive, Overline, Underline, // Strikeout, etc... - if(getWordLineMode()) - { - // support for single word mode - impSplitSingleWords(aNewPrimitives, aDecTrans); - } - else - { - // prepare new font attributes WITHOUT outline - const attribute::FontAttribute aNewFontAttribute( - getFontAttribute().getFamilyName(), - getFontAttribute().getStyleName(), - getFontAttribute().getWeight(), - getFontAttribute().getSymbol(), - getFontAttribute().getVertical(), - getFontAttribute().getItalic(), - false, // no outline anymore, handled locally - getFontAttribute().getRTL(), - getFontAttribute().getBiDiStrong()); - - // handle as one word - impCreateGeometryContent(aNewPrimitives, aDecTrans, getText(), getTextPosition(), getTextLength(), getDXArray(), aNewFontAttribute); - } + // prepare new font attributes WITHOUT outline + const attribute::FontAttribute aNewFontAttribute( + getFontAttribute().getFamilyName(), + getFontAttribute().getStyleName(), + getFontAttribute().getWeight(), + getFontAttribute().getSymbol(), + getFontAttribute().getVertical(), + getFontAttribute().getItalic(), + getFontAttribute().getMonospaced(), + false, // no outline anymore, handled locally + getFontAttribute().getRTL(), + getFontAttribute().getBiDiStrong()); + + // handle as one word + impCreateGeometryContent(aNewPrimitives, aDecTrans, getText(), getTextPosition(), getTextLength(), getDXArray(), aNewFontAttribute); // convert to Primitive2DSequence const sal_uInt32 nMemberCount(aNewPrimitives.size()); @@ -545,6 +348,16 @@ namespace drawinglayer { } + bool TextDecoratedPortionPrimitive2D::decoratedIsNeeded() const + { + return (TEXT_LINE_NONE != getFontOverline() + || TEXT_LINE_NONE != getFontUnderline() + || TEXT_STRIKEOUT_NONE != getTextStrikeout() + || TEXT_EMPHASISMARK_NONE != getTextEmphasisMark() + || TEXT_RELIEF_NONE != getTextRelief() + || getShadow()); + } + bool TextDecoratedPortionPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const { if(TextSimplePortionPrimitive2D::operator==(rPrimitive)) @@ -573,15 +386,7 @@ namespace drawinglayer // inking area, so add them if needed basegfx::B2DRange TextDecoratedPortionPrimitive2D::getB2DRange(const geometry::ViewInformation2D& rViewInformation) const { - const bool bDecoratedIsNeeded( - TEXT_LINE_NONE != getFontOverline() - || TEXT_LINE_NONE != getFontUnderline() - || TEXT_STRIKEOUT_NONE != getTextStrikeout() - || TEXT_EMPHASISMARK_NONE != getTextEmphasisMark() - || TEXT_RELIEF_NONE != getTextRelief() - || getShadow()); - - if(bDecoratedIsNeeded) + if(decoratedIsNeeded()) { // decoration is used, fallback to BufferedDecompositionPrimitive2D::getB2DRange which uses // the own local decomposition for computation and thus creates all necessary diff --git a/drawinglayer/source/primitive2d/textlayoutdevice.cxx b/drawinglayer/source/primitive2d/textlayoutdevice.cxx index 01379dd4bca9..4e1e87319931 100644 --- a/drawinglayer/source/primitive2d/textlayoutdevice.cxx +++ b/drawinglayer/source/primitive2d/textlayoutdevice.cxx @@ -1,30 +1,21 @@ /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/************************************************************************* +/* + * This file is part of the LibreOffice project. * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. * - * Copyright 2000, 2010 Oracle and/or its affiliates. + * This file incorporates work covered by the following license notice: * - * 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. - * - ************************************************************************/ + * 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 . + */ #include <drawinglayer/primitive2d/textlayoutdevice.hxx> #include <comphelper/processfactory.hxx> diff --git a/drawinglayer/source/primitive2d/textprimitive2d.cxx b/drawinglayer/source/primitive2d/textprimitive2d.cxx index 64e3ddd32b02..444df44f44d4 100644 --- a/drawinglayer/source/primitive2d/textprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/textprimitive2d.cxx @@ -1,30 +1,21 @@ /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/************************************************************************* +/* + * This file is part of the LibreOffice project. * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. * - * Copyright 2000, 2010 Oracle and/or its affiliates. + * This file incorporates work covered by the following license notice: * - * 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. - * - ************************************************************************/ + * 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 . + */ #include <drawinglayer/primitive2d/textprimitive2d.hxx> #include <drawinglayer/primitive2d/textlayoutdevice.hxx> |