/* -*- 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 <sax/tools/converter.hxx>
#include <sal/log.hxx>
#include "ximp3dscene.hxx"
#include <xmloff/xmluconv.hxx>
#include <xexptran.hxx>
#include <xmloff/xmltoken.hxx>
#include <xmloff/xmlnamespace.hxx>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/drawing/Direction3D.hpp>
#include <com/sun/star/drawing/CameraGeometry.hpp>
#include "eventimp.hxx"
#include "descriptionimp.hxx"
using namespace ::com::sun::star;
using namespace ::xmloff::token;
// dr3d:3dlight context
SdXML3DLightContext::SdXML3DLightContext(
SvXMLImport& rImport,
const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList)
: SvXMLImportContext( rImport ),
maDiffuseColor(0x00000000),
maDirection(0.0, 0.0, 1.0),
mbEnabled(
false ),
mbSpecular(
false )
{
// read attributes for the 3DScene
for (
auto & aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
{
switch (aIter.getToken())
{
case XML_ELEMENT(DR3D, XML_DIFFUSE_COLOR):
{
::sax::Converter::convertColor(maDiffuseColor, aIter.toView());
break ;
}
case XML_ELEMENT(DR3D, XML_DIRECTION):
{
::basegfx::B3DVector aVal;
SvXMLUnitConverter::convertB3DVector(aVal, aIter.toView());
if (!std::isnan(aVal.getX()) && !std::isnan(aVal.getY()) && !std::isnan(aVal.getZ()))
{
maDirection = aVal;
}
else
{
SAL_WARN(
"xmloff" ,
"NaNs found in light direction: " << aIter.toString());
}
break ;
}
case XML_ELEMENT(DR3D, XML_ENABLED):
{
(
void )::sax::Converter::convertBool(mbEnabled, aIter.toView());
break ;
}
case XML_ELEMENT(DR3D, XML_SPECULAR):
{
(
void )::sax::Converter::convertBool(mbSpecular, aIter.toView());
break ;
}
default :
XMLOFF_WARN_UNKNOWN(
"xmloff" , aIter);
}
}
}
SdXML3DLightContext::~SdXML3DLightContext()
{
}
SdXML3DSceneShapeContext::SdXML3DSceneShapeContext(
SvXMLImport& rImport,
const css::uno::Reference< css::xml::sax::XFastAttributeList>& xAttrList,
uno::Reference< drawing::XShapes >
const & rShapes,
bool bTemporaryShapes)
: SdXMLShapeContext( rImport, xAttrList, rShapes, bTemporaryShapes ), SdXML3DSceneAttri
butesHelper( rImport )
{
}
SdXML3DSceneShapeContext::~SdXML3DSceneShapeContext()
{
}
void SdXML3DSceneShapeContext::startFastElement(
sal_Int32 nElement,
const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
{
// create new 3DScene shape and add it to rShapes, use it
// as base for the new 3DScene import
AddShape( u"com.sun.star.drawing.Shape3DSceneObject" _ustr );
if ( mxShape.is() )
{
SetStyle();
mxChildren.set( mxShape, uno::UNO_QUERY );
if ( mxChildren.is() )
GetImport().GetShapeImport()->pushGroupForPostProcessing( mxChildren );
SetLayer();
// set pos, size, shear and rotate
SetTransformation();
}
// read attributes for the 3DScene
for ( auto & aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
processSceneAttribute( aIter );
// #91047# call parent function is missing here, added it
if (mxShape.is())
{
// call parent
SdXMLShapeContext::startFastElement(nElement, xAttrList);
}
}
void SdXML3DSceneShapeContext::endFastElement(sal_Int32 nElement)
{
if (!mxShape.is())
return ;
uno::Reference< beans::XPropertySet > xPropSet(mxShape, uno::UNO_QUERY);
if (xPropSet.is())
{
setSceneAttributes( xPropSet );
}
if ( mxChildren.is() )
GetImport().GetShapeImport()->popGroupAndPostProcess();
// call parent
SdXMLShapeContext::endFastElement(nElement);
}
css::uno::Reference< css::xml::sax::XFastContextHandler > SdXML3DSceneShapeContext::createFastChildContext(
sal_Int32 nElement,
const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
{
SvXMLImportContextRef xContext;
switch (nElement)
{
// #i68101#
case XML_ELEMENT(SVG, XML_TITLE):
case XML_ELEMENT(SVG_COMPAT, XML_TITLE):
case XML_ELEMENT(SVG, XML_DESC):
case XML_ELEMENT(SVG_COMPAT, XML_DESC):
xContext = new SdXMLDescriptionContext( GetImport(), nElement, mxShape );
break ;
case XML_ELEMENT(OFFICE, XML_EVENT_LISTENERS):
xContext = new SdXMLEventsContext( GetImport(), mxShape );
break ;
// look for local light context first
case XML_ELEMENT(DR3D, XML_LIGHT):
// dr3d:light inside dr3d:scene context
xContext = create3DLightContext( xAttrList );
break ;
default :
// call GroupChildContext function at common ShapeImport
return XMLShapeImportHelper::Create3DSceneChildContext(
GetImport(), nElement, xAttrList, mxChildren);
}
return xContext;
}
SdXML3DSceneAttributesHelper::SdXML3DSceneAttributesHelper( SvXMLImport& rImporter )
: mrImport( rImporter ),
mbSetTransform( false ),
mxPrjMode(drawing::ProjectionMode_PERSPECTIVE),
mnDistance(1000),
mnFocalLength(1000),
mnShadowSlant(0),
mxShadeMode(drawing::ShadeMode_SMOOTH),
maAmbientColor(0x00666666),
mbLightingMode(false ),
maVRP(0.0, 0.0, 1.0),
maVPN(0.0, 0.0, 1.0),
maVUP(0.0, 1.0, 0.0),
mbVRPUsed(false )
{
}
/** creates a 3d light context and adds it to the internal list for later processing */
SvXMLImportContext * SdXML3DSceneAttributesHelper::create3DLightContext( const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList)
{
const rtl::Reference<SdXML3DLightContext> xContext{new SdXML3DLightContext(mrImport, xAttrList)};
// remember SdXML3DLightContext for later evaluation
maList.push_back(xContext);
return xContext.get();
}
/** this should be called for each scene attribute */
void SdXML3DSceneAttributesHelper::processSceneAttribute( const sax_fastparser::FastAttributeList::FastAttributeIter & aIter )
{
auto nAttributeToken = aIter.getToken();
if ( !IsTokenInNamespace(nAttributeToken, XML_NAMESPACE_DR3D) )
return ;
switch (nAttributeToken & TOKEN_MASK)
{
case XML_TRANSFORM:
{
SdXMLImExTransform3D aTransform(aIter.toString(), mrImport.GetMM100UnitConverter());
if (aTransform.NeedsAction())
mbSetTransform = aTransform.GetFullHomogenTransform(mxHomMat);
return ;
}
case XML_VRP:
{
::basegfx::B3DVector aNewVec;
SvXMLUnitConverter::convertB3DVector(aNewVec, aIter.toView());
if (aNewVec != maVRP)
{
maVRP = aNewVec;
mbVRPUsed = true ;
}
return ;
}
case XML_VPN:
{
::basegfx::B3DVector aNewVec;
SvXMLUnitConverter::convertB3DVector(aNewVec, aIter.toView());
if (aNewVec != maVPN)
{
maVPN = aNewVec;
}
return ;
}
case XML_VUP:
{
::basegfx::B3DVector aNewVec;
SvXMLUnitConverter::convertB3DVector(aNewVec, aIter.toView());
if (aNewVec != maVUP)
{
maVUP = aNewVec;
}
return ;
}
case XML_PROJECTION:
{
if ( IsXMLToken( aIter, XML_PARALLEL ) )
mxPrjMode = drawing::ProjectionMode_PARALLEL;
else
mxPrjMode = drawing::ProjectionMode_PERSPECTIVE;
return ;
}
case XML_DISTANCE:
{
mrImport.GetMM100UnitConverter().convertMeasureToCore(mnDistance,
aIter.toView());
return ;
}
case XML_FOCAL_LENGTH:
{
mrImport.GetMM100UnitConverter().convertMeasureToCore(mnFocalLength,
aIter.toView());
return ;
}
case XML_SHADOW_SLANT:
{
double fAngle = 0.0;
if (::sax::Converter::convertAngle(fAngle, aIter.toView()))
mnShadowSlant = static_cast <sal_Int32>(basegfx::fround(fAngle));
else
mnShadowSlant = 0;
return ;
}
case XML_SHADE_MODE:
{
if ( IsXMLToken( aIter, XML_FLAT ) )
mxShadeMode = drawing::ShadeMode_FLAT;
else if ( IsXMLToken( aIter, XML_PHONG ) )
mxShadeMode = drawing::ShadeMode_PHONG;
else if ( IsXMLToken( aIter, XML_GOURAUD ) )
mxShadeMode = drawing::ShadeMode_SMOOTH;
else
mxShadeMode = drawing::ShadeMode_DRAFT;
return ;
}
case XML_AMBIENT_COLOR:
{
::sax::Converter::convertColor(maAmbientColor, aIter.toView());
return ;
}
case XML_LIGHTING_MODE:
{
(void )::sax::Converter::convertBool(mbLightingMode, aIter.toView());
return ;
}
default :
XMLOFF_WARN_UNKNOWN("xmloff" , aIter);
}
}
/** this sets the scene attributes at this propertyset */
void SdXML3DSceneAttributesHelper::setSceneAttributes( const css::uno::Reference< css::beans::XPropertySet >& xPropSet )
{
uno::Any aAny;
// world transformation
if (mbSetTransform)
{
xPropSet->setPropertyValue(u"D3DTransformMatrix" _ustr, uno::Any(mxHomMat));
}
// distance
xPropSet->setPropertyValue(u"D3DSceneDistance" _ustr, uno::Any(mnDistance));
// focalLength
xPropSet->setPropertyValue(u"D3DSceneFocalLength" _ustr, uno::Any(mnFocalLength));
// shadowSlant
xPropSet->setPropertyValue(u"D3DSceneShadowSlant" _ustr, uno::Any(static_cast <sal_Int16>(mnShadowSlant)));
// shadeMode
xPropSet->setPropertyValue(u"D3DSceneShadeMode" _ustr, uno::Any(mxShadeMode));
// ambientColor
xPropSet->setPropertyValue(u"D3DSceneAmbientColor" _ustr, uno::Any(maAmbientColor));
// lightingMode
xPropSet->setPropertyValue(u"D3DSceneTwoSidedLighting" _ustr, uno::Any(mbLightingMode));
if ( !maList.empty() )
{
uno::Any aAny2;
uno::Any aAny3;
// set lights
for ( size_t a = 0; a < maList.size(); a++)
{
SdXML3DLightContext* pCtx = maList[ a ].get();
// set anys
aAny <<= pCtx->GetDiffuseColor();
drawing::Direction3D aLightDir;
aLightDir.DirectionX = pCtx->GetDirection().getX();
aLightDir.DirectionY = pCtx->GetDirection().getY();
aLightDir.DirectionZ = pCtx->GetDirection().getZ();
aAny2 <<= aLightDir;
aAny3 <<= pCtx->GetEnabled();
switch (a)
{
case 0:
{
xPropSet->setPropertyValue(u"D3DSceneLightColor1" _ustr, aAny);
xPropSet->setPropertyValue(u"D3DSceneLightDirection1" _ustr, aAny2);
xPropSet->setPropertyValue(u"D3DSceneLightOn1" _ustr, aAny3);
break ;
}
case 1:
{
xPropSet->setPropertyValue(u"D3DSceneLightColor2" _ustr, aAny);
xPropSet->setPropertyValue(u"D3DSceneLightDirection2" _ustr, aAny2);
xPropSet->setPropertyValue(u"D3DSceneLightOn2" _ustr, aAny3);
break ;
}
case 2:
{
xPropSet->setPropertyValue(u"D3DSceneLightColor3" _ustr, aAny);
xPropSet->setPropertyValue(u"D3DSceneLightDirection3" _ustr, aAny2);
xPropSet->setPropertyValue(u"D3DSceneLightOn3" _ustr, aAny3);
break ;
}
case 3:
{
xPropSet->setPropertyValue(u"D3DSceneLightColor4" _ustr, aAny);
xPropSet->setPropertyValue(u"D3DSceneLightDirection4" _ustr, aAny2);
xPropSet->setPropertyValue(u"D3DSceneLightOn4" _ustr, aAny3);
break ;
}
case 4:
{
xPropSet->setPropertyValue(u"D3DSceneLightColor5" _ustr, aAny);
xPropSet->setPropertyValue(u"D3DSceneLightDirection5" _ustr, aAny2);
xPropSet->setPropertyValue(u"D3DSceneLightOn5" _ustr, aAny3);
break ;
}
case 5:
{
xPropSet->setPropertyValue(u"D3DSceneLightColor6" _ustr, aAny);
xPropSet->setPropertyValue(u"D3DSceneLightDirection6" _ustr, aAny2);
xPropSet->setPropertyValue(u"D3DSceneLightOn6" _ustr, aAny3);
break ;
}
case 6:
{
xPropSet->setPropertyValue(u"D3DSceneLightColor7" _ustr, aAny);
xPropSet->setPropertyValue(u"D3DSceneLightDirection7" _ustr, aAny2);
xPropSet->setPropertyValue(u"D3DSceneLightOn7" _ustr, aAny3);
break ;
}
case 7:
{
xPropSet->setPropertyValue(u"D3DSceneLightColor8" _ustr, aAny);
xPropSet->setPropertyValue(u"D3DSceneLightDirection8" _ustr, aAny2);
xPropSet->setPropertyValue(u"D3DSceneLightOn8" _ustr, aAny3);
break ;
}
}
}
}
// CameraGeometry and camera settings
drawing::CameraGeometry aCamGeo;
aCamGeo.vrp.PositionX = maVRP.getX();
aCamGeo.vrp.PositionY = maVRP.getY();
aCamGeo.vrp.PositionZ = maVRP.getZ();
aCamGeo.vpn.DirectionX = maVPN.getX();
aCamGeo.vpn.DirectionY = maVPN.getY();
aCamGeo.vpn.DirectionZ = maVPN.getZ();
aCamGeo.vup.DirectionX = maVUP.getX();
aCamGeo.vup.DirectionY = maVUP.getY();
aCamGeo.vup.DirectionZ = maVUP.getZ();
xPropSet->setPropertyValue(u"D3DCameraGeometry" _ustr, uno::Any(aCamGeo));
// #91047# set drawing::ProjectionMode AFTER camera geometry is set
// projection "D3DScenePerspective" drawing::ProjectionMode
xPropSet->setPropertyValue(u"D3DScenePerspective" _ustr, uno::Any(mxPrjMode));
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Messung V0.5 C=93 H=96 G=94
¤ Dauer der Verarbeitung: 0.13 Sekunden
(vorverarbeitet)
¤
*© Formatika GbR, Deutschland