/* -*- 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 .
*/
// move left, top corner back to position of the // shape. Since we've already translated the // center of the shape to the origin (the // translate( -0.5, -0.5 ) above), translate to // center of final shape position here.
aTransform.translate( rShapeBounds.getCenterX(),
rShapeBounds.getCenterY() );
return aTransform;
}
}
// Value extraction from Any // =========================
/// extract unary double value from Any bool extractValue( double& o_rValue, const uno::Any& rSourceAny, const ShapeSharedPtr& rShape, const ::basegfx::B2DVector& rSlideBounds )
{ // try to extract numeric value (double, or smaller POD, like float or int) if( rSourceAny >>= o_rValue)
{ // succeeded returntrue;
}
// try to extract string
OUString aString; if( !(rSourceAny >>= aString) ) returnfalse; // nothing left to try
// parse the string into an ExpressionNode try
{ // Parse string into ExpressionNode, eval node at time 0.0
o_rValue = (*SmilFunctionParser::parseSmilValue(
aString,
calcRelativeShapeBounds(rSlideBounds,
rShape->getBounds()) ))(0.0);
} catch( ParseError& )
{ returnfalse;
}
returntrue;
}
/// extract enum/constant group value from Any bool extractValue( sal_Int32& o_rValue, const uno::Any& rSourceAny, const ShapeSharedPtr& /*rShape*/, const ::basegfx::B2DVector& /*rSlideBounds*/ )
{ // try to extract numeric value (int, or smaller POD, like byte) if( rSourceAny >>= o_rValue)
{ // succeeded returntrue;
}
// okay, no plain int. Maybe one of the domain-specific enums?
drawing::FillStyle eFillStyle; if( rSourceAny >>= eFillStyle )
{
o_rValue = sal::static_int_cast<sal_Int16>(eFillStyle);
/// extract bool value from Any bool extractValue( bool& o_rValue, const uno::Any& rSourceAny, const ShapeSharedPtr& /*rShape*/, const ::basegfx::B2DVector& /*rSlideBounds*/ )
{ bool bTmp; // try to extract bool value if( rSourceAny >>= bTmp )
{
o_rValue = bTmp;
// succeeded returntrue;
}
// try to extract string
OUString aString; if( !(rSourceAny >>= aString) ) returnfalse; // nothing left to try
// we also take the strings "true" and "false", // as well as "on" and "off" here if( aString.equalsIgnoreAsciiCase("true") ||
aString.equalsIgnoreAsciiCase("on") )
{
o_rValue = true; returntrue;
} if( aString.equalsIgnoreAsciiCase("false") ||
aString.equalsIgnoreAsciiCase("off") )
{
o_rValue = false; returntrue;
}
// TODO(F2): Currently, the positional attributes DO NOT mirror the XShape properties. // First and foremost, this is because we must operate with the shape boundrect, // not position and size (the conversion between logic rect, snap rect and boundrect // are non-trivial for draw shapes, and I won't duplicate them here). Thus, shapes // rotated on the page will still have 0.0 rotation angle, as the metafile // representation fetched over the API is our default zero case.
// scale, shear and rotation pivot point is the // sprite's pixel center - adapt origin accordingly
aTransform.translate( -0.5*rPixelSize.getX(),
-0.5*rPixelSize.getY() );
// move left, top corner back to original position of // the sprite (we've translated the center of the // sprite to the origin above).
aTransform.translate( 0.5*rPixelSize.getX(),
0.5*rPixelSize.getY() );
}
// return identity transform for un-attributed // shapes. This renders the sprite as-is, in its // document-supplied size. return aTransform;
}
if( pAttr &&
pAttr->isCharScaleValid() &&
fabs(pAttr->getCharScale()) > 1.0 )
{ // enlarge shape bounds. Have to consider the worst // case here (the text fully fills the shape)
constdouble nCharScale( pAttr->getCharScale() );
// center of scaling is the middle of the shape
aTransform.translate( -0.5, -0.5 );
aTransform.scale( nCharScale, nCharScale );
aTransform.translate( 0.5, 0.5 );
}
aTransform *= rShapeTransform;
// apply shape transformation to unit rect return ::canvas::tools::calcTransformedRectBounds(
rUnitBounds,
aTransform );
}
::basegfx::B2DRectangle getShapePosSize( const ::basegfx::B2DRectangle& rOrigBounds, const ShapeAttributeLayerSharedPtr& pAttr )
{ // an already empty shape bound need no further // treatment. In fact, any changes applied below would // actually remove the special empty state, thus, don't // change! if( !pAttr ||
rOrigBounds.isEmpty() )
{ return rOrigBounds;
} else
{ // cannot use maBounds anymore, attributes might have been // changed by now. // Have to use absolute values here, as negative sizes // (aka mirrored shapes) _still_ have the same bounds, // only with mirrored content.
::basegfx::B2DSize aSize;
aSize.setWidth( fabs( pAttr->isWidthValid() ?
pAttr->getWidth() :
rOrigBounds.getWidth() ) );
aSize.setHeight( fabs( pAttr->isHeightValid() ?
pAttr->getHeight() :
rOrigBounds.getHeight() ) );
// the positional attribute retrieved from the // ShapeAttributeLayer actually denotes the _middle_ // of the shape (do it as the PPTs do...) return ::basegfx::B2DRectangle(aPos - 0.5 * basegfx::B2DPoint(aSize),
aPos + 0.5 * basegfx::B2DPoint(aSize));
}
}
RGBColor unoColor2RGBColor( sal_Int32 nColor )
{ return RGBColor(
::cppcanvas::makeColor( // convert from API color to IntSRGBA color // (0xAARRGGBB -> 0xRRGGBBAA) static_cast< sal_uInt8 >( nColor >> 16U ), static_cast< sal_uInt8 >( nColor >> 8U ), static_cast< sal_uInt8 >( nColor ), static_cast< sal_uInt8 >( nColor >> 24U ) ) );
}
sal_Int32 RGBAColor2UnoColor( ::cppcanvas::IntSRGBA aColor )
{ return ::cppcanvas::makeColorARGB( // convert from IntSRGBA color to API color // (0xRRGGBBAA -> 0xAARRGGBB) static_cast< sal_uInt8 >(0),
::cppcanvas::getRed(aColor),
::cppcanvas::getGreen(aColor),
::cppcanvas::getBlue(aColor));
}
// set transformation to identity (->device pixel)
pCanvas->setTransformation( ::basegfx::B2DHomMatrix() );
// #i42440# Fill the _full_ background in // black. Since we had to extend the bitmap by one // pixel, and the bitmap is initialized white, // depending on the slide content a one pixel wide // line will show to the bottom and the right.
fillRect( pCanvas,
::basegfx::B2DRectangle( 0.0, 0.0,
rSize.getWidth(),
rSize.getHeight() ),
0x000000FFU );
// tdf#148884 in dark mode impress's auto text color assumes it will render against // the DOCCOLOR by default, so leaving this as white gives white on white, this // looks the simplest approach, propagate dark mode into slideshow mode instead // of reformatting to render onto a white slideshow
svtools::ColorConfig aColorConfig;
Color aApplicationDocumentColor = aColorConfig.GetColorValue(svtools::DOCCOLOR).nColor;
cppcanvas::IntSRGBA nCanvasColor = cppcanvas::makeColor(aApplicationDocumentColor.GetRed(),
aApplicationDocumentColor.GetGreen(),
aApplicationDocumentColor.GetBlue(),
0xFF);
// fill the bounds rectangle in DOCCOLOR (typically white). // Subtract one pixel from both width and height, because the slide // size is chosen one pixel larger than given by the drawing layer. // This is because shapes with line style, that have the size of // the slide would otherwise be cut off. OTOH, every other slide // background (solid fill, gradient, bitmap) render one pixel less, // thus revealing ugly white pixel to the right and the bottom.
fillRect( pCanvas,
::basegfx::B2DRectangle( 0.0, 0.0,
rSize.getWidth()-1,
rSize.getHeight()-1 ),
nCanvasColor );
}
::basegfx::B2DRectangle getAPIShapeBounds( const uno::Reference< drawing::XShape >& xShape )
{
uno::Reference< beans::XPropertySet > xPropSet( xShape,
uno::UNO_QUERY_THROW ); // read bound rect
awt::Rectangle aTmpRect; if( !(xPropSet->getPropertyValue(u"BoundRect"_ustr) >>= aTmpRect) )
{
ENSURE_OR_THROW( false, "getAPIShapeBounds(): Could not get \"BoundRect\" property from shape" );
}
// #i42440# Returned slide size is one pixel too small, as // rendering happens one pixel to the right and below the // actual bound rect. return basegfx::B2IVector(
basegfx::fround( aTmpRect.getRange().getX() ) + 1,
basegfx::fround( aTmpRect.getRange().getY() ) + 1 );
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.