/* -*- 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 .
*/
// #i36950# Offset clip back to origin (as it's also moved // by rStartPoint) // #i53964# Also take VCL font rotation into account, // since this, opposed to the FontMatrix rotation // elsewhere, _does_ get incorporated into the render // state transform.
tools::modifyClip( o_rRenderState,
rState,
rCanvas,
rStartPoint,
nullptr,
&rState.fontRotation );
// TODO(F2): Also inversely-transform clip with // rTextTransform (which is actually rather hard, as the // text transform is _prepended_ to the render state)!
// prepend extra font transform to render state // (prepend it, because it's interpreted in the unit // rect coordinate space)
::canvas::tools::prependToRenderState( o_rRenderState,
rTextTransform );
}
void init( rendering::RenderState& o_rRenderState,
uno::Reference< rendering::XCanvasFont >& o_rFont, const ::basegfx::B2DPoint& rStartPoint, const OutDevState& rState, const CanvasSharedPtr& rCanvas )
{ // ensure that o_rFont is valid. It is possible that // text actions are generated without previously // setting a font. Then, just take a default font if( !o_rFont.is() )
{ // Use completely default FontRequest const rendering::FontRequest aFontRequest;
// TODO(F2): Also inversely-transform clip with // rTextTransform (which is actually rather hard, as the // text transform is _prepended_ to the render state)!
// prepend extra font transform to render state // (prepend it, because it's interpreted in the unit // rect coordinate space)
::canvas::tools::prependToRenderState( o_rRenderState,
rTextTransform );
}
if( rState.textAlignment )
{ // text origin is right, not left. Modify start point // accordingly, because XCanvas::drawTextLayout() // always aligns left!
ENSURE_OR_THROW( aOrigOffsets.getLength() >= rSubset.mnSubsetEnd, "::cppcanvas::internal::calcSubsetOffsets(): invalid subset range range" );
// determine leftmost position in given subset range - // as the DX array contains the output positions // starting with the second character (the first is // assumed to have output position 0), correct begin // iterator. constdouble nMinPos( rSubset.mnSubsetBegin <= 0 ? 0 :
*(std::min_element( pOffsets+rSubset.mnSubsetBegin-1,
pOffsets+rSubset.mnSubsetEnd )) );
// determine rightmost position in given subset range // - as the DX array contains the output positions // starting with the second character (the first is // assumed to have output position 0), correct begin // iterator. constdouble nMaxPos(
*(std::max_element( pOffsets + (rSubset.mnSubsetBegin <= 0 ?
0 : rSubset.mnSubsetBegin-1),
pOffsets + rSubset.mnSubsetEnd )) );
// Logical advancements always increase in logical text order. // For RTL text, nMaxPos is the distance from the right edge to // the leftmost position in the subset, so we have to convert // it to the offset from the origin (i.e. left edge ). // LTR: |---- min --->|---- max --->| | // RTL: | |<--- max ----|<--- min ---| // |<- nOffset ->| | constdouble nOffset = rOrigTextLayout->getMainTextDirection()
? nLayoutWidth - nMaxPos : nMinPos;
// adapt render state, to move text output to given offset
// TODO(F1): Strictly speaking, we also have to adapt // the clip here, which normally should _not_ move // with the output offset. Neglected for now, as it // does not matter for drawing layer output
if (nOffset > 0.0)
{
::basegfx::B2DHomMatrix aTranslation; if( rOrigTextLayout->getFont()->getFontRequest().FontDescription.IsVertical == css::util::TriState_YES )
{ // vertical text -> offset in y direction
aTranslation.translate(0.0, nOffset);
} else
{ // horizontal text -> offset in x direction
aTranslation.translate(nOffset, 0.0);
}
// move to new output position (subtract nMinPos, // which is the new '0' position), copy only the range // as given by rSubset.
std::transform( pOffsets + rSubset.mnSubsetBegin,
pOffsets + rSubset.mnSubsetEnd,
pAdaptedOffsets,
[nMinPos](double aPos) { return aPos - nMinPos; } );
o_rMinPos = nMinPos;
o_rMaxPos = nMaxPos;
return aAdaptedOffsets;
}
uno::Reference< rendering::XTextLayout >
createSubsetLayout( const rendering::StringContext& rOrigContext, const ::cppcanvas::internal::Action::Subset& rSubset, const uno::Reference< rendering::XTextLayout >& rOrigTextLayout )
{ // create temporary new text layout with subset string
@param io_rTextLayout Must contain original (full set) text layout on input, will contain subsetted text layout (or empty reference, for empty subsets) on output.
@param io_rRenderState Must contain original render state on input, will contain shifted render state concatenated with rTransformation on output.
@param rTransformation Additional transformation, to be prepended to render state
This is interface is used from the renderEffectText() method below, to call the client implementation.
*/ class TextRenderer
{ public: virtual ~TextRenderer() {}
/// Render text with given RenderState virtualbooloperator()( const rendering::RenderState& rRenderState, const ::Color& rTextFillColor, bool bNormalText ) const = 0;
};
/** Render effect text.
@param rRenderer Functor object, will be called to render the actual part of the text effect (the text itself and the means to render it are unknown to this method)
*/ bool renderEffectText( const TextRenderer& rRenderer, const rendering::RenderState& rRenderState, const uno::Reference< rendering::XCanvas >& xCanvas, const ::Color& rShadowColor, const ::basegfx::B2DSize& rShadowOffset, const ::Color& rReliefColor, const ::basegfx::B2DSize& rReliefOffset, const ::Color& rTextFillColor )
{
::Color aEmptyColor( COL_AUTO );
uno::Reference<rendering::XColorSpace> xColorSpace(
xCanvas->getDevice()->getDeviceColorSpace() );
private: // TODO(P2): This is potentially a real mass object // (every character might be a separate TextAction), // thus, make it as lightweight as possible. For // example, share common RenderState among several // TextActions, maybe using maOffsets for the // translation.
bool TextAction::renderSubset( const ::basegfx::B2DHomMatrix& rTransformation, const Subset& /*rSubset*/ ) const
{
SAL_WARN( "cppcanvas.emf", "TextAction::renderSubset(): Subset not supported by this object" );
// TODO(P1): Retrieve necessary font metric info for // TextAction from XCanvas. Currently, the // TextActionFactory does not generate this object for // _subsettable_ text return render( rTransformation );
}
::basegfx::B2DRange TextAction::getBounds( const ::basegfx::B2DHomMatrix& rTransformation ) const
{ // create XTextLayout, to have the // XTextLayout::queryTextBounds() method available
uno::Reference< rendering::XTextLayout > xTextLayout(
mxFont->createTextLayout(
maStringContext,
maTextDirection,
0 ) );
::basegfx::B2DRange TextAction::getBounds( const ::basegfx::B2DHomMatrix& rTransformation, const Subset& /*rSubset*/ ) const
{
SAL_WARN( "cppcanvas.emf", "TextAction::getBounds(): Subset not supported by this object" );
// TODO(P1): Retrieve necessary font metric info for // TextAction from XCanvas. Currently, the // TextActionFactory does not generate this object for // _subsettable_ text return getBounds( rTransformation );
}
sal_Int32 TextAction::getActionCount() const
{ // TODO(P1): Retrieve necessary font metric info for // TextAction from XCanvas. Currently, the // TextActionFactory does not generate this object for // _subsettable_ text return 1;
}
// TODO(P2): This is potentially a real mass object // (every character might be a separate TextAction), // thus, make it as lightweight as possible. For // example, share common RenderState among several // TextActions, maybe using maOffsets for the // translation.
//rhbz#1589029 non-transparent text fill background support if (rTextFillColor != COL_AUTO)
{
rendering::RenderState aLocalState( rRenderState );
aLocalState.DeviceColor = vcl::unotools::colorToDoubleSequence(
rTextFillColor, aCanvas->getDevice()->getDeviceColorSpace()); auto xTextBounds = queryTextBounds(aCanvas); // background of text
aCanvas->fillPolyPolygon(xTextBounds, aViewState, aLocalState);
}
bool EffectTextAction::renderSubset( const ::basegfx::B2DHomMatrix& rTransformation, const Subset& /*rSubset*/ ) const
{
SAL_WARN( "cppcanvas.emf", "EffectTextAction::renderSubset(): Subset not supported by this object" );
// TODO(P1): Retrieve necessary font metric info for // TextAction from XCanvas. Currently, the // TextActionFactory does not generate this object for // subsettable text return render( rTransformation );
}
geometry::RealRectangle2D EffectTextAction::queryTextBounds() const
{ // create XTextLayout, to have the // XTextLayout::queryTextBounds() method available
uno::Reference< rendering::XTextLayout > xTextLayout(
mxFont->createTextLayout(
maStringContext,
maTextDirection,
0 ) );
return xTextLayout->queryTextBounds();
}
css::uno::Reference<css::rendering::XPolyPolygon2D> EffectTextAction::queryTextBounds(const uno::Reference<rendering::XCanvas>& rCanvas) const
{ auto aTextBounds = queryTextBounds(); auto aB2DBounds = ::basegfx::unotools::b2DRectangleFromRealRectangle2D(aTextBounds); auto aTextBoundsPoly = ::basegfx::utils::createPolygonFromRect(aB2DBounds); return ::basegfx::unotools::xPolyPolygonFromB2DPolygon(rCanvas->getDevice(), aTextBoundsPoly);
}
::basegfx::B2DRange EffectTextAction::getBounds( const ::basegfx::B2DHomMatrix& rTransformation, const Subset& /*rSubset*/ ) const
{
SAL_WARN( "cppcanvas.emf", "EffectTextAction::getBounds(): Subset not supported by this object" );
// TODO(P1): Retrieve necessary font metric info for // TextAction from XCanvas. Currently, the // TextActionFactory does not generate this object for // _subsettable_ text return getBounds( rTransformation );
}
sal_Int32 EffectTextAction::getActionCount() const
{ // TODO(P1): Retrieve necessary font metric info for // TextAction from XCanvas. Currently, the // TextActionFactory does not generate this object for // subsettable text return 1;
}
private: // TODO(P2): This is potentially a real mass object // (every character might be a separate TextAction), // thus, make it as lightweight as possible. For // example, share common RenderState among several // TextActions, maybe using maOffsets for the // translation.
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 ist noch experimentell.