Files
loongoffice/drawinglayer/source/processor3d/defaultprocessor3d.cxx
Stephan Bergmann fe6cce01c8 Fix loplugin:simplifypointertobool for libstdc++ std::shared_ptr
...where the get member function is defined on a std::__shared_ptr base class,
so loplugin:simplifypointertobool used to miss those until now.  (While e.g.
using libc++ on macOS found those cases.)

366d08f2f6d4de922f6099c62bb81b49d89e0a68 "new loplugin:simplifypointertobool"
was mistaken in breaking isSmartPointerType(const clang::Type* t) out of
isSmartPointerType(const Expr* e); c874294ad9fb178df47c66875bfbdec466e39763 "Fix
detection of std::unique_ptr/shared_ptr in loplugin:redundantpointerops" had
introduced that indivisible two-step algorithm on purpose.

The amount of additional hits (on Linux) apparently asked for turning
loplugin:simplifypointertobool into a rewriting plugin.  Which in turn showed
that the naive adivce to just "drop the get()" is not sufficient in places that
are not contextually converted to bool, as those places need to be wrapped in a
bool(...) functional cast now.  If the expression was already wrapped in
parentheses, those could be reused as part of the functional cast, but
implementing that showed that such cases are not yet found at all by the
existing loplugin:simplifypointertobool.  Lets leave that TODO for another
commit.

Besides the changes to compilerplugins/ itself, this change has been generated
fully automatically with the rewriting plugin on Linux.

Change-Id: I83107d6f634fc9ac232986f49044d7017df83e2a
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/94888
Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
Reviewed-by: Stephan Bergmann <sbergman@redhat.com>
Tested-by: Jenkins
2020-05-26 22:33:02 +02:00

603 lines
27 KiB
C++

/* -*- 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 <processor3d/defaultprocessor3d.hxx>
#include <primitive3d/textureprimitive3d.hxx>
#include <texture/texture.hxx>
#include <texture/texture3d.hxx>
#include <primitive3d/hatchtextureprimitive3d.hxx>
#include <drawinglayer/primitive3d/modifiedcolorprimitive3d.hxx>
#include <drawinglayer/primitive3d/polygonprimitive3d.hxx>
#include <basegfx/polygon/b3dpolygontools.hxx>
#include <drawinglayer/attribute/materialattribute3d.hxx>
#include <drawinglayer/primitive3d/polypolygonprimitive3d.hxx>
#include <basegfx/polygon/b3dpolypolygontools.hxx>
#include <com/sun/star/drawing/ShadeMode.hpp>
#include <drawinglayer/primitive3d/transformprimitive3d.hxx>
#include <drawinglayer/primitive3d/drawinglayer_primitivetypes3d.hxx>
#include <vcl/bitmapex.hxx>
#include <drawinglayer/attribute/sdrsceneattribute3d.hxx>
#include <drawinglayer/attribute/sdrlightingattribute3d.hxx>
#include <vcl/graph.hxx>
#include <basegfx/matrix/b2dhommatrixtools.hxx>
using namespace com::sun::star;
namespace drawinglayer::processor3d
{
void DefaultProcessor3D::impRenderGradientTexturePrimitive3D(const primitive3d::GradientTexturePrimitive3D& rPrimitive, bool bTransparence)
{
const primitive3d::Primitive3DContainer& rSubSequence = rPrimitive.getChildren();
if(rSubSequence.empty())
return;
// rescue values
const bool bOldModulate(getModulate()); mbModulate = rPrimitive.getModulate();
const bool bOldFilter(getFilter()); mbFilter = rPrimitive.getFilter();
const bool bOldSimpleTextureActive(getSimpleTextureActive());
std::shared_ptr< texture::GeoTexSvx > pOldTex = bTransparence ? mpTransparenceGeoTexSvx : mpGeoTexSvx;
// create texture
const attribute::FillGradientAttribute& rFillGradient = rPrimitive.getGradient();
const basegfx::B2DRange aOutlineRange(0.0, 0.0, rPrimitive.getTextureSize().getX(), rPrimitive.getTextureSize().getY());
const attribute::GradientStyle aGradientStyle(rFillGradient.getStyle());
sal_uInt32 nSteps(rFillGradient.getSteps());
const basegfx::BColor& aStart(rFillGradient.getStartColor());
const basegfx::BColor& aEnd(rFillGradient.getEndColor());
const sal_uInt32 nMaxSteps(sal_uInt32((aStart.getMaximumDistance(aEnd) * 127.5) + 0.5));
std::shared_ptr< texture::GeoTexSvx > pNewTex;
if(nMaxSteps)
{
// there IS a color distance
if(nSteps == 0)
{
nSteps = nMaxSteps;
}
if(nSteps < 2)
{
nSteps = 2;
}
if(nSteps > nMaxSteps)
{
nSteps = nMaxSteps;
}
switch(aGradientStyle)
{
case attribute::GradientStyle::Linear:
{
pNewTex = std::make_shared<texture::GeoTexSvxGradientLinear>(
aOutlineRange,
aOutlineRange,
aStart,
aEnd,
nSteps,
rFillGradient.getBorder(),
rFillGradient.getAngle());
break;
}
case attribute::GradientStyle::Axial:
{
pNewTex = std::make_shared<texture::GeoTexSvxGradientAxial>(
aOutlineRange,
aOutlineRange,
aStart,
aEnd,
nSteps,
rFillGradient.getBorder(),
rFillGradient.getAngle());
break;
}
case attribute::GradientStyle::Radial:
{
pNewTex =
std::make_shared<texture::GeoTexSvxGradientRadial>(
aOutlineRange,
aStart,
aEnd,
nSteps,
rFillGradient.getBorder(),
rFillGradient.getOffsetX(),
rFillGradient.getOffsetY());
break;
}
case attribute::GradientStyle::Elliptical:
{
pNewTex =
std::make_shared<texture::GeoTexSvxGradientElliptical>(
aOutlineRange,
aStart,
aEnd,
nSteps,
rFillGradient.getBorder(),
rFillGradient.getOffsetX(),
rFillGradient.getOffsetY(),
rFillGradient.getAngle());
break;
}
case attribute::GradientStyle::Square:
{
pNewTex =
std::make_shared<texture::GeoTexSvxGradientSquare>(
aOutlineRange,
aStart,
aEnd,
nSteps,
rFillGradient.getBorder(),
rFillGradient.getOffsetX(),
rFillGradient.getOffsetY(),
rFillGradient.getAngle());
break;
}
case attribute::GradientStyle::Rect:
{
pNewTex =
std::make_shared<texture::GeoTexSvxGradientRect>(
aOutlineRange,
aStart,
aEnd,
nSteps,
rFillGradient.getBorder(),
rFillGradient.getOffsetX(),
rFillGradient.getOffsetY(),
rFillGradient.getAngle());
break;
}
}
mbSimpleTextureActive = false;
}
else
{
// no color distance -> same color, use simple texture
pNewTex = std::make_shared<texture::GeoTexSvxMono>(aStart, 1.0 - aStart.luminance());
mbSimpleTextureActive = true;
}
// set created texture
if(bTransparence)
{
mpTransparenceGeoTexSvx = pNewTex;
}
else
{
mpGeoTexSvx = pNewTex;
}
// process sub-list
process(rSubSequence);
// restore values
mbModulate = bOldModulate;
mbFilter = bOldFilter;
mbSimpleTextureActive = bOldSimpleTextureActive;
if(bTransparence)
{
mpTransparenceGeoTexSvx = pOldTex;
}
else
{
mpGeoTexSvx = pOldTex;
}
}
void DefaultProcessor3D::impRenderHatchTexturePrimitive3D(const primitive3d::HatchTexturePrimitive3D& rPrimitive)
{
const primitive3d::Primitive3DContainer& rSubSequence = rPrimitive.getChildren();
if(rSubSequence.empty())
return;
// rescue values
const bool bOldModulate(getModulate()); mbModulate = rPrimitive.getModulate();
const bool bOldFilter(getFilter()); mbFilter = rPrimitive.getFilter();
std::shared_ptr< texture::GeoTexSvx > pOldTex = mpGeoTexSvx;
// calculate logic pixel size in object coordinates. Create transformation view
// to object by inverting ObjectToView
basegfx::B3DHomMatrix aInvObjectToView(getViewInformation3D().getObjectToView());
aInvObjectToView.invert();
// back-project discrete coordinates to object coordinates and extract
// maximum distance
const basegfx::B3DPoint aZero(aInvObjectToView * basegfx::B3DPoint(0.0, 0.0, 0.0));
const basegfx::B3DPoint aOne(aInvObjectToView * basegfx::B3DPoint(1.0, 1.0, 1.0));
const basegfx::B3DVector aLogicPixel(aOne - aZero);
double fLogicPixelSizeWorld(std::max(std::max(fabs(aLogicPixel.getX()), fabs(aLogicPixel.getY())), fabs(aLogicPixel.getZ())));
// calculate logic pixel size in texture coordinates
const double fLogicTexSizeX(fLogicPixelSizeWorld / rPrimitive.getTextureSize().getX());
const double fLogicTexSizeY(fLogicPixelSizeWorld / rPrimitive.getTextureSize().getY());
const double fLogicTexSize(std::max(fLogicTexSizeX, fLogicTexSizeY));
// create texture and set
mpGeoTexSvx = std::make_shared<texture::GeoTexSvxMultiHatch>(rPrimitive, fLogicTexSize);
// process sub-list
process(rSubSequence);
// restore values
mbModulate = bOldModulate;
mbFilter = bOldFilter;
mpGeoTexSvx = pOldTex;
}
void DefaultProcessor3D::impRenderBitmapTexturePrimitive3D(const primitive3d::BitmapTexturePrimitive3D& rPrimitive)
{
const primitive3d::Primitive3DContainer& rSubSequence = rPrimitive.getChildren();
if(rSubSequence.empty())
return;
// rescue values
const bool bOldModulate(getModulate()); mbModulate = rPrimitive.getModulate();
const bool bOldFilter(getFilter()); mbFilter = rPrimitive.getFilter();
std::shared_ptr< texture::GeoTexSvx > pOldTex = mpGeoTexSvx;
// create texture
const attribute::FillGraphicAttribute& rFillGraphicAttribute = rPrimitive.getFillGraphicAttribute();
// #121194# For 3D texture we will use the BitmapRex representation
const BitmapEx aBitmapEx(rFillGraphicAttribute.getGraphic().GetBitmapEx());
// create range scaled by texture size
basegfx::B2DRange aGraphicRange(rFillGraphicAttribute.getGraphicRange());
aGraphicRange.transform(
basegfx::utils::createScaleB2DHomMatrix(
rPrimitive.getTextureSize()));
if(rFillGraphicAttribute.getTiling())
{
mpGeoTexSvx =
std::make_shared<texture::GeoTexSvxBitmapExTiled>(
aBitmapEx,
aGraphicRange,
rFillGraphicAttribute.getOffsetX(),
rFillGraphicAttribute.getOffsetY());
}
else
{
mpGeoTexSvx =
std::make_shared<texture::GeoTexSvxBitmapEx>(
aBitmapEx,
aGraphicRange);
}
// process sub-list
process(rSubSequence);
// restore values
mbModulate = bOldModulate;
mbFilter = bOldFilter;
mpGeoTexSvx = pOldTex;
}
void DefaultProcessor3D::impRenderModifiedColorPrimitive3D(const primitive3d::ModifiedColorPrimitive3D& rModifiedCandidate)
{
const primitive3d::Primitive3DContainer& rSubSequence = rModifiedCandidate.getChildren();
if(!rSubSequence.empty())
{
// put modifier on stack
maBColorModifierStack.push(rModifiedCandidate.getColorModifier());
// process sub-list
process(rModifiedCandidate.getChildren());
// remove modifier from stack
maBColorModifierStack.pop();
}
}
void DefaultProcessor3D::impRenderPolygonHairlinePrimitive3D(const primitive3d::PolygonHairlinePrimitive3D& rPrimitive) const
{
basegfx::B3DPolygon aHairline(rPrimitive.getB3DPolygon());
if(!aHairline.count())
return;
// hairlines need no extra data, clear it
aHairline.clearTextureCoordinates();
aHairline.clearNormals();
aHairline.clearBColors();
// transform to device coordinates (-1.0 .. 1.0) and check for visibility
aHairline.transform(getViewInformation3D().getObjectToView());
const basegfx::B3DRange a3DRange(basegfx::utils::getRange(aHairline));
const basegfx::B2DRange a2DRange(a3DRange.getMinX(), a3DRange.getMinY(), a3DRange.getMaxX(), a3DRange.getMaxY());
if(a2DRange.overlaps(maRasterRange))
{
const attribute::MaterialAttribute3D aMaterial(maBColorModifierStack.getModifiedColor(rPrimitive.getBColor()));
rasterconvertB3DPolygon(aMaterial, aHairline);
}
}
void DefaultProcessor3D::impRenderPolyPolygonMaterialPrimitive3D(const primitive3d::PolyPolygonMaterialPrimitive3D& rPrimitive) const
{
basegfx::B3DPolyPolygon aFill(rPrimitive.getB3DPolyPolygon());
basegfx::BColor aObjectColor(rPrimitive.getMaterial().getColor());
bool bPaintIt(aFill.count());
// #i98295# get ShadeMode. Correct early when only flat is possible due to missing normals
const css::drawing::ShadeMode aShadeMode(
aFill.areNormalsUsed() ?
getSdrSceneAttribute().getShadeMode() : css::drawing::ShadeMode_FLAT);
if(bPaintIt)
{
// get rid of texture coordinates if there is no texture
if(aFill.areTextureCoordinatesUsed() && !getGeoTexSvx() && !getTransparenceGeoTexSvx())
{
aFill.clearTextureCoordinates();
}
// #i98295# get rid of normals and color early when not needed
if(css::drawing::ShadeMode_FLAT == aShadeMode)
{
aFill.clearNormals();
aFill.clearBColors();
}
// transform to device coordinates (-1.0 .. 1.0) and check for visibility
aFill.transform(getViewInformation3D().getObjectToView());
const basegfx::B3DRange a3DRange(basegfx::utils::getRange(aFill));
const basegfx::B2DRange a2DRange(a3DRange.getMinX(), a3DRange.getMinY(), a3DRange.getMaxX(), a3DRange.getMaxY());
bPaintIt = a2DRange.overlaps(maRasterRange);
}
// check if it shall be painted regarding hiding of normals (backface culling)
if(bPaintIt && !rPrimitive.getDoubleSided())
{
// get plane normal of polygon in view coordinates (with ZBuffer values),
// left-handed coordinate system
const basegfx::B3DVector aPlaneNormal(aFill.getB3DPolygon(0).getNormal());
if(aPlaneNormal.getZ() > 0.0)
{
bPaintIt = false;
}
}
if(!bPaintIt)
return;
// prepare ObjectToEye in NormalTransform
basegfx::B3DHomMatrix aNormalTransform(getViewInformation3D().getOrientation() * getViewInformation3D().getObjectTransformation());
if(getSdrSceneAttribute().getTwoSidedLighting())
{
// get plane normal of polygon in view coordinates (with ZBuffer values),
// left-handed coordinate system
const basegfx::B3DVector aPlaneNormal(aFill.getB3DPolygon(0).getNormal());
if(aPlaneNormal.getZ() > 0.0)
{
// mirror normals
aNormalTransform.scale(-1.0, -1.0, -1.0);
}
}
switch(aShadeMode)
{
case css::drawing::ShadeMode_PHONG:
{
// phong shading. Transform normals to eye coor
aFill.transformNormals(aNormalTransform);
break;
}
case css::drawing::ShadeMode_SMOOTH:
{
// gouraud shading. Transform normals to eye coor
aFill.transformNormals(aNormalTransform);
// prepare color model parameters, evtl. use blend color
const basegfx::BColor aColor(getModulate() ? basegfx::BColor(1.0, 1.0, 1.0) : rPrimitive.getMaterial().getColor());
const basegfx::BColor& rSpecular(rPrimitive.getMaterial().getSpecular());
const basegfx::BColor& rEmission(rPrimitive.getMaterial().getEmission());
const sal_uInt16 nSpecularIntensity(rPrimitive.getMaterial().getSpecularIntensity());
// solve color model for each normal vector, set colors at points. Clear normals.
for(sal_uInt32 a(0); a < aFill.count(); a++)
{
basegfx::B3DPolygon aPartFill(aFill.getB3DPolygon(a));
for(sal_uInt32 b(0); b < aPartFill.count(); b++)
{
// solve color model. Transform normal to eye coor
const basegfx::B3DVector aNormal(aPartFill.getNormal(b));
const basegfx::BColor aSolvedColor(getSdrLightingAttribute().solveColorModel(aNormal, aColor, rSpecular, rEmission, nSpecularIntensity));
aPartFill.setBColor(b, aSolvedColor);
}
// clear normals on this part polygon and write it back
aPartFill.clearNormals();
aFill.setB3DPolygon(a, aPartFill);
}
break;
}
case css::drawing::ShadeMode_FLAT:
{
// flat shading. Get plane vector in eye coordinates
const basegfx::B3DVector aPlaneEyeNormal(aNormalTransform * rPrimitive.getB3DPolyPolygon().getB3DPolygon(0).getNormal());
// prepare color model parameters, evtl. use blend color
const basegfx::BColor aColor(getModulate() ? basegfx::BColor(1.0, 1.0, 1.0) : rPrimitive.getMaterial().getColor());
const basegfx::BColor& rSpecular(rPrimitive.getMaterial().getSpecular());
const basegfx::BColor& rEmission(rPrimitive.getMaterial().getEmission());
const sal_uInt16 nSpecularIntensity(rPrimitive.getMaterial().getSpecularIntensity());
// solve color model for plane vector and use that color for whole plane
aObjectColor = getSdrLightingAttribute().solveColorModel(aPlaneEyeNormal, aColor, rSpecular, rEmission, nSpecularIntensity);
break;
}
default: // case css::drawing::ShadeMode_DRAFT:
{
// draft, just use object color which is already set. Delete all other infos
aFill.clearNormals();
aFill.clearBColors();
break;
}
}
// draw it to ZBuffer
const attribute::MaterialAttribute3D aMaterial(
maBColorModifierStack.getModifiedColor(aObjectColor),
rPrimitive.getMaterial().getSpecular(),
rPrimitive.getMaterial().getEmission(),
rPrimitive.getMaterial().getSpecularIntensity());
rasterconvertB3DPolyPolygon(aMaterial, aFill);
}
void DefaultProcessor3D::impRenderTransformPrimitive3D(const primitive3d::TransformPrimitive3D& rTransformCandidate)
{
// transform group. Remember current transformations
const geometry::ViewInformation3D aLastViewInformation3D(getViewInformation3D());
// create new transformation; add new object transform from right side
const geometry::ViewInformation3D aNewViewInformation3D(
aLastViewInformation3D.getObjectTransformation() * rTransformCandidate.getTransformation(),
aLastViewInformation3D.getOrientation(),
aLastViewInformation3D.getProjection(),
aLastViewInformation3D.getDeviceToView(),
aLastViewInformation3D.getViewTime(),
aLastViewInformation3D.getExtendedInformationSequence());
updateViewInformation(aNewViewInformation3D);
// let break down recursively
process(rTransformCandidate.getChildren());
// restore transformations
updateViewInformation(aLastViewInformation3D);
}
void DefaultProcessor3D::processBasePrimitive3D(const primitive3d::BasePrimitive3D& rBasePrimitive)
{
// it is a BasePrimitive3D implementation, use getPrimitive3DID() call for switch
switch(rBasePrimitive.getPrimitive3DID())
{
case PRIMITIVE3D_ID_GRADIENTTEXTUREPRIMITIVE3D :
{
// GradientTexturePrimitive3D
const primitive3d::GradientTexturePrimitive3D& rPrimitive = static_cast< const primitive3d::GradientTexturePrimitive3D& >(rBasePrimitive);
impRenderGradientTexturePrimitive3D(rPrimitive, false);
break;
}
case PRIMITIVE3D_ID_HATCHTEXTUREPRIMITIVE3D :
{
// hatchTexturePrimitive3D
const primitive3d::HatchTexturePrimitive3D& rPrimitive = static_cast< const primitive3d::HatchTexturePrimitive3D& >(rBasePrimitive);
impRenderHatchTexturePrimitive3D(rPrimitive);
break;
}
case PRIMITIVE3D_ID_BITMAPTEXTUREPRIMITIVE3D :
{
// BitmapTexturePrimitive3D
const primitive3d::BitmapTexturePrimitive3D& rPrimitive = static_cast< const primitive3d::BitmapTexturePrimitive3D& >(rBasePrimitive);
impRenderBitmapTexturePrimitive3D(rPrimitive);
break;
}
case PRIMITIVE3D_ID_TRANSPARENCETEXTUREPRIMITIVE3D :
{
// TransparenceTexturePrimitive3D
const primitive3d::TransparenceTexturePrimitive3D& rPrimitive = static_cast< const primitive3d::TransparenceTexturePrimitive3D& >(rBasePrimitive);
mnTransparenceCounter++;
impRenderGradientTexturePrimitive3D(rPrimitive, true);
mnTransparenceCounter--;
break;
}
case PRIMITIVE3D_ID_MODIFIEDCOLORPRIMITIVE3D :
{
// ModifiedColorPrimitive3D
// Force output to unified color.
const primitive3d::ModifiedColorPrimitive3D& rPrimitive = static_cast< const primitive3d::ModifiedColorPrimitive3D& >(rBasePrimitive);
impRenderModifiedColorPrimitive3D(rPrimitive);
break;
}
case PRIMITIVE3D_ID_POLYGONHAIRLINEPRIMITIVE3D :
{
// directdraw of PolygonHairlinePrimitive3D
const primitive3d::PolygonHairlinePrimitive3D& rPrimitive = static_cast< const primitive3d::PolygonHairlinePrimitive3D& >(rBasePrimitive);
impRenderPolygonHairlinePrimitive3D(rPrimitive);
break;
}
case PRIMITIVE3D_ID_POLYPOLYGONMATERIALPRIMITIVE3D :
{
// directdraw of PolyPolygonMaterialPrimitive3D
const primitive3d::PolyPolygonMaterialPrimitive3D& rPrimitive = static_cast< const primitive3d::PolyPolygonMaterialPrimitive3D& >(rBasePrimitive);
impRenderPolyPolygonMaterialPrimitive3D(rPrimitive);
break;
}
case PRIMITIVE3D_ID_TRANSFORMPRIMITIVE3D :
{
// transform group (TransformPrimitive3D)
impRenderTransformPrimitive3D(static_cast< const primitive3d::TransformPrimitive3D& >(rBasePrimitive));
break;
}
default:
{
// process recursively
process(rBasePrimitive.get3DDecomposition(getViewInformation3D()));
break;
}
}
}
DefaultProcessor3D::DefaultProcessor3D(
const geometry::ViewInformation3D& rViewInformation,
const attribute::SdrSceneAttribute& rSdrSceneAttribute,
const attribute::SdrLightingAttribute& rSdrLightingAttribute)
: BaseProcessor3D(rViewInformation),
mrSdrSceneAttribute(rSdrSceneAttribute),
mrSdrLightingAttribute(rSdrLightingAttribute),
maRasterRange(),
maBColorModifierStack(),
mpGeoTexSvx(),
mpTransparenceGeoTexSvx(),
maDrawinglayerOpt(),
mnTransparenceCounter(0),
mbModulate(false),
mbFilter(false),
mbSimpleTextureActive(false)
{
// a derivation has to set maRasterRange which is used in the basic render methods.
// Setting to default here ([0.0 .. 1.0] in X,Y) to avoid problems
maRasterRange.expand(basegfx::B2DTuple(0.0, 0.0));
maRasterRange.expand(basegfx::B2DTuple(1.0, 1.0));
}
DefaultProcessor3D::~DefaultProcessor3D()
{
}
} // end of namespace
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */