Kaydet (Commit) f69df53b authored tarafından Armin Le Grand's avatar Armin Le Grand Kaydeden (comit) Caolán McNamara

Resolves: #i121297# corrected non-AAed gradient rendering...

when in rotated metafiles

(cherry picked from commit 2a063da1)

Conflicts:
	drawinglayer/Library_drawinglayer.mk
	drawinglayer/inc/drawinglayer/processor2d/vclprocessor2d.hxx
	drawinglayer/source/processor2d/vclhelpergradient.cxx
	drawinglayer/source/processor2d/vclhelpergradient.hxx
	drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx
	drawinglayer/source/processor2d/vclpixelprocessor2d.cxx

Change-Id: I0e4ff1d3bebbc738fb6d301da19747faa2efbe3d
üst 98910950
......@@ -145,7 +145,6 @@ $(eval $(call gb_Library_add_exception_objects,drawinglayer,\
drawinglayer/source/processor2d/vclhelperbitmaprender \
drawinglayer/source/processor2d/vclhelperbitmaptransform \
drawinglayer/source/processor2d/vclhelperbufferdevice \
drawinglayer/source/processor2d/vclhelpergradient \
drawinglayer/source/processor2d/vclmetafileprocessor2d \
drawinglayer/source/processor2d/vclpixelprocessor2d \
drawinglayer/source/processor2d/vclprocessor2d \
......
/* -*- 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 .
*/
#ifndef INCLUDED_DRAWINGLAYER_PROCESSOR2D_VCLHELPERGRADIENT_HXX
#define INCLUDED_DRAWINGLAYER_PROCESSOR2D_VCLHELPERGRADIENT_HXX
#include <sal/types.h>
#include <drawinglayer/attribute/fillgradientattribute.hxx>
//////////////////////////////////////////////////////////////////////////////
// predefines
class OutputDevice;
namespace basegfx {
class B2DPolyPolygon;
class BColor;
}
//////////////////////////////////////////////////////////////////////////////
// support methods for vcl direct gradient renderering
namespace drawinglayer
{
void impDrawGradientToOutDev(
OutputDevice& rOutDev,
const basegfx::B2DPolyPolygon& rTargetForm,
attribute::GradientStyle eGradientStyle,
sal_uInt32 nSteps,
const basegfx::BColor& rStart,
const basegfx::BColor& rEnd,
double fBorder, double fAngle, double fOffsetX, double fOffsetY, bool bSimple);
} // end of namespace drawinglayer
//////////////////////////////////////////////////////////////////////////////
#endif // INCLUDED_DRAWINGLAYER_PROCESSOR2D_VCLHELPERGRADIENT_HXX
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
......@@ -27,7 +27,6 @@
#include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx>
#include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
#include <drawinglayer/primitive2d/bitmapprimitive2d.hxx>
#include <drawinglayer/primitive2d/metafileprimitive2d.hxx>
#include <drawinglayer/primitive2d/maskprimitive2d.hxx>
#include <basegfx/polygon/b2dpolygonclipper.hxx>
#include <basegfx/polygon/b2dpolypolygontools.hxx>
......@@ -1645,9 +1644,6 @@ namespace drawinglayer
impStartSvtGraphicFill(pSvtGraphicFill);
mpOutputDevice->DrawGradient(aToolsPolyPolygon, aVCLGradient);
impEndSvtGraphicFill(pSvtGraphicFill);
// NO usage of common own gradient randerer, not used ATM for VCL MetaFile, see text above
// RenderPolyPolygonGradientPrimitive2D(static_cast< const primitive2d::PolyPolygonGradientPrimitive2D& >(rCandidate));
}
break;
......@@ -1712,24 +1708,6 @@ namespace drawinglayer
break;
}
case PRIMITIVE2D_ID_METAFILEPRIMITIVE2D :
{
static bool bUseMetaFilePrimitiveDecomposition(true);
const primitive2d::MetafilePrimitive2D& aMetafile = static_cast< const primitive2d::MetafilePrimitive2D& >(rCandidate);
if(bUseMetaFilePrimitiveDecomposition && !aMetafile.getMetaFile().GetUseCanvas())
{
// use new Metafile decomposition
process(rCandidate.get2DDecomposition(getViewInformation2D()));
}
else
{
// direct draw of MetaFile, use default pocessing
RenderMetafilePrimitive2D(aMetafile);
}
break;
}
case PRIMITIVE2D_ID_MASKPRIMITIVE2D :
{
// mask group. Special handling for MetaFiles.
......
......@@ -188,7 +188,29 @@ namespace drawinglayer
case PRIMITIVE2D_ID_POLYPOLYGONGRADIENTPRIMITIVE2D :
{
// direct draw of gradient
RenderPolyPolygonGradientPrimitive2D(static_cast< const primitive2d::PolyPolygonGradientPrimitive2D& >(rCandidate));
const primitive2d::PolyPolygonGradientPrimitive2D& rPolygonCandidate = static_cast< const primitive2d::PolyPolygonGradientPrimitive2D& >(rCandidate);
const attribute::FillGradientAttribute& rGradient(rPolygonCandidate.getFillGradient());
basegfx::BColor aStartColor(maBColorModifierStack.getModifiedColor(rGradient.getStartColor()));
basegfx::BColor aEndColor(maBColorModifierStack.getModifiedColor(rGradient.getEndColor()));
basegfx::B2DPolyPolygon aLocalPolyPolygon(rPolygonCandidate.getB2DPolyPolygon());
if(aLocalPolyPolygon.count())
{
aLocalPolyPolygon.transform(maCurrentTransformation);
if(aStartColor == aEndColor)
{
// no gradient at all, draw as polygon in AA and non-AA case
mpOutputDevice->SetLineColor();
mpOutputDevice->SetFillColor(Color(aStartColor));
mpOutputDevice->DrawPolyPolygon(aLocalPolyPolygon);
}
else
{
// use the primitive decomposition of the metafile
process(rPolygonCandidate.get2DDecomposition(getViewInformation2D()));
}
}
break;
}
case PRIMITIVE2D_ID_POLYPOLYGONGRAPHICPRIMITIVE2D :
......@@ -214,19 +236,8 @@ namespace drawinglayer
mpOutputDevice->SetAntialiasing(nOldAntiAliase | ANTIALIASING_PIXELSNAPHAIRLINE);
}
const primitive2d::MetafilePrimitive2D& rMetafilePrimitive( static_cast< const primitive2d::MetafilePrimitive2D& >(rCandidate) );
static bool bTestMetaFilePrimitiveDecomposition( true );
if( bTestMetaFilePrimitiveDecomposition && !rMetafilePrimitive.getMetaFile().GetUseCanvas() )
{
// use new Metafile decomposition
process(rCandidate.get2DDecomposition(getViewInformation2D()));
}
else
{
// direct draw of MetaFile
RenderMetafilePrimitive2D( rMetafilePrimitive );
}
if(bForceLineSnap)
{
......
......@@ -31,7 +31,6 @@
#include <drawinglayer/attribute/sdrfillgraphicattribute.hxx>
#include <drawinglayer/primitive2d/fillgraphicprimitive2d.hxx>
#include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx>
#include <vclhelpergradient.hxx>
#include <drawinglayer/primitive2d/metafileprimitive2d.hxx>
#include <drawinglayer/primitive2d/maskprimitive2d.hxx>
#include <basegfx/polygon/b2dpolypolygontools.hxx>
......@@ -696,44 +695,6 @@ namespace drawinglayer
}
}
// direct draw of gradient
void VclProcessor2D::RenderPolyPolygonGradientPrimitive2D(const primitive2d::PolyPolygonGradientPrimitive2D& rPolygonCandidate)
{
const attribute::FillGradientAttribute& rGradient(rPolygonCandidate.getFillGradient());
basegfx::BColor aStartColor(maBColorModifierStack.getModifiedColor(rGradient.getStartColor()));
basegfx::BColor aEndColor(maBColorModifierStack.getModifiedColor(rGradient.getEndColor()));
basegfx::B2DPolyPolygon aLocalPolyPolygon(rPolygonCandidate.getB2DPolyPolygon());
if(aLocalPolyPolygon.count())
{
aLocalPolyPolygon.transform(maCurrentTransformation);
if(aStartColor == aEndColor)
{
// no gradient at all, draw as polygon in AA and non-AA case
mpOutputDevice->SetLineColor();
mpOutputDevice->SetFillColor(Color(aStartColor));
mpOutputDevice->DrawPolyPolygon(aLocalPolyPolygon);
}
else if(getOptionsDrawinglayer().IsAntiAliasing())
{
// For AA, direct render has to be avoided since it uses XOR maskings which will not
// work with AA. Instead, the decompose which uses MaskPrimitive2D with fillings is
// used
process(rPolygonCandidate.get2DDecomposition(getViewInformation2D()));
}
else
{
static bool bSimple = false; // allow testing simple paint in debugger
impDrawGradientToOutDev(
*mpOutputDevice, aLocalPolyPolygon, rGradient.getStyle(), rGradient.getSteps(),
aStartColor, aEndColor, rGradient.getBorder(),
rGradient.getAngle(), rGradient.getOffsetX(), rGradient.getOffsetY(), bSimple);
}
}
}
// direct draw of Graphic
void VclProcessor2D::RenderPolyPolygonGraphicPrimitive2D(const primitive2d::PolyPolygonGraphicPrimitive2D& rPolygonCandidate)
{
......@@ -921,97 +882,6 @@ namespace drawinglayer
}
}
// direct draw of MetaFile
void VclProcessor2D::RenderMetafilePrimitive2D(const primitive2d::MetafilePrimitive2D& rMetaCandidate)
{
// decompose matrix to check for shear, rotate and mirroring
basegfx::B2DHomMatrix aLocalTransform(maCurrentTransformation * rMetaCandidate.getTransform());
basegfx::B2DVector aScale, aTranslate;
double fRotate, fShearX;
aLocalTransform.decompose(aScale, aTranslate, fRotate, fShearX);
if(basegfx::fTools::less(aScale.getX(), 0.0) && basegfx::fTools::less(aScale.getY(), 0.0))
{
// #i102175# handle special case: If scale is negative in (x,y) (3rd quadrant), it can
// be expressed as rotation by PI. This needs to be done for Metafiles since
// these can be rotated, but not really mirrored
aScale = basegfx::absolute(aScale);
fRotate += F_PI;
}
// get BoundRect
basegfx::B2DRange aOutlineRange(rMetaCandidate.getB2DRange(getViewInformation2D()));
aOutlineRange.transform(maCurrentTransformation);
// Due to the integer MapModes used from VCL aind inside MetaFiles errors of up to three
// pixels in size may happen. As long as there is no better way (e.g. convert the MetaFile
// to primitives) it is necessary to reduce maximum pixel size by 1 in X and Y and to use
// the inner pixel bounds accordingly (ceil resp. floor). This will also be done for logic
// units e.g. when creating a new MetaFile, but since much huger value ranges are used
// there typically will be okay for this compromize.
Rectangle aDestRectView(
// !!CAUTION!! Here, ceil and floor are exchanged BY PURPOSE, do NOT copy when
// looking for a standard conversion to rectangle (!)
(sal_Int32)ceil(aOutlineRange.getMinX()), (sal_Int32)ceil(aOutlineRange.getMinY()),
(sal_Int32)floor(aOutlineRange.getMaxX()), (sal_Int32)floor(aOutlineRange.getMaxY()));
// get metafile (copy it)
GDIMetaFile aMetaFile;
if(maBColorModifierStack.count())
{
const basegfx::BColor aRGBBaseColor(0, 0, 0);
const basegfx::BColor aRGBColor(maBColorModifierStack.getModifiedColor(aRGBBaseColor));
aMetaFile = rMetaCandidate.getMetaFile().GetMonochromeMtf(Color(aRGBColor));
}
else
{
aMetaFile = rMetaCandidate.getMetaFile();
}
// rotation
if(!basegfx::fTools::equalZero(fRotate))
{
// #i103530#
// MetaFile::Rotate has no input parameter check, so the parameter needs to be
// well-aligned to the old range [0..3600] 10th degrees with inverse orientation
sal_Int16 nRotation((sal_Int16)((fRotate / F_PI180) * -10.0));
while(nRotation < 0)
nRotation += 3600;
while(nRotation >= 3600)
nRotation -= 3600;
aMetaFile.Rotate(nRotation);
}
// Prepare target output size
Size aDestSize(aDestRectView.GetSize());
if(aDestSize.getWidth() && aDestSize.getHeight())
{
// Get preferred Metafile output size. When it's very equal to the output size, it's probably
// a rounding error somewhere, so correct it to get a 1:1 output without single pixel scalings
// of the Metafile (esp. for contaned Bitmaps, e.g 3D charts)
const Size aPrefSize(mpOutputDevice->LogicToPixel(aMetaFile.GetPrefSize(), aMetaFile.GetPrefMapMode()));
if(aPrefSize.getWidth() && (aPrefSize.getWidth() - 1 == aDestSize.getWidth() || aPrefSize.getWidth() + 1 == aDestSize.getWidth()))
{
aDestSize.setWidth(aPrefSize.getWidth());
}
if(aPrefSize.getHeight() && (aPrefSize.getHeight() - 1 == aDestSize.getHeight() || aPrefSize.getHeight() + 1 == aDestSize.getHeight()))
{
aDestSize.setHeight(aPrefSize.getHeight());
}
// paint it
aMetaFile.WindStart();
aMetaFile.Play(mpOutputDevice, aDestRectView.TopLeft(), aDestSize);
}
}
// mask group. Force output to VDev and create mask from given mask
void VclProcessor2D::RenderMaskPrimitive2DPixel(const primitive2d::MaskPrimitive2D& rMaskCandidate)
{
......
......@@ -94,10 +94,8 @@ namespace drawinglayer
void RenderPolygonHairlinePrimitive2D(const primitive2d::PolygonHairlinePrimitive2D& rPolygonCandidate, bool bPixelBased);
void RenderBitmapPrimitive2D(const primitive2d::BitmapPrimitive2D& rBitmapCandidate);
void RenderFillGraphicPrimitive2D(const primitive2d::FillGraphicPrimitive2D& rFillBitmapCandidate);
void RenderPolyPolygonGradientPrimitive2D(const primitive2d::PolyPolygonGradientPrimitive2D& rPolygonCandidate);
void RenderPolyPolygonGraphicPrimitive2D(const primitive2d::PolyPolygonGraphicPrimitive2D& rPolygonCandidate);
void RenderPolyPolygonColorPrimitive2D(const primitive2d::PolyPolygonColorPrimitive2D& rPolygonCandidate);
void RenderMetafilePrimitive2D(const primitive2d::MetafilePrimitive2D& rPolygonCandidate);
void RenderMaskPrimitive2DPixel(const primitive2d::MaskPrimitive2D& rMaskCandidate);
void RenderModifiedColorPrimitive2D(const primitive2d::ModifiedColorPrimitive2D& rModifiedCandidate);
void RenderUnifiedTransparencePrimitive2D(const primitive2d::UnifiedTransparencePrimitive2D& rTransCandidate);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment