/* -*- 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 .
*/
if( mp2ndOutDevProvider )
mp2ndOutDevProvider->getOutDev().DrawPolyPolygon( aPolyPoly );
} else
{ // mixed open/closed state. Cannot render open polygon // via DrawPolyPolygon(), since that implicitly // closed every polygon. OTOH, no need to distinguish // further and render closed polygons via // DrawPolygon(), and open ones via DrawPolyLine(): // closed polygons will simply already contain the // closing segment.
sal_uInt16 nSize( aPolyPoly.Count() );
// apply dashing, if any if( strokeAttributes.DashArray.hasElements() )
{ const std::vector<double> aDashArray(
::comphelper::sequenceToContainer< std::vector<double> >(strokeAttributes.DashArray) );
::basegfx::B2DPolyPolygon aDashedPolyPoly;
for( sal_uInt32 i=0; i<aPolyPoly.count(); ++i )
{ // AW: new interface; You may also get gaps in the same run now
basegfx::utils::applyLineDashing(aPolyPoly.getB2DPolygon(i), aDashArray, &aDashedPolyPoly); //aDashedPolyPoly.append( // ::basegfx::utils::applyLineDashing( aPolyPoly.getB2DPolygon(i), // aDashArray ) );
}
aPolyPoly = std::move(aDashedPolyPoly);
}
::basegfx::B2DSize aLinePixelSize(strokeAttributes.StrokeWidth,
strokeAttributes.StrokeWidth);
aLinePixelSize *= aMatrix;
::basegfx::B2DPolyPolygon aStrokedPolyPoly; if( aLinePixelSize.getLength() < 1.42 )
{ // line width < 1.0 in device pixel, thus, output as a // simple hairline poly-polygon
setupOutDevState( viewState, renderState, LINE_COLOR );
aStrokedPolyPoly = std::move(aPolyPoly);
} else
{ // render as a 'thick' line
setupOutDevState( viewState, renderState, FILL_COLOR );
// transform only _now_, all the StrokeAttributes are in // user coordinates.
aStrokedPolyPoly.transform( aMatrix );
// TODO(F2): When using alpha here, must handle that via // temporary surface or somesuch.
// Note: the generated stroke poly-polygon is NOT free of // self-intersections. Therefore, if we would render it // via OutDev::DrawPolyPolygon(), on/off fill would // generate off areas on those self-intersections. for( sal_uInt32 i=0; i<aStrokedPolyPoly.count(); ++i )
{ const basegfx::B2DPolygon& polygon = aStrokedPolyPoly.getB2DPolygon( i ); if( polygon.isClosed()) {
mpOutDevProvider->getOutDev().DrawPolygon( polygon ); if( mp2ndOutDevProvider )
mp2ndOutDevProvider->getOutDev().DrawPolygon( polygon );
} else {
mpOutDevProvider->getOutDev().DrawPolyLine( polygon ); if( mp2ndOutDevProvider )
mp2ndOutDevProvider->getOutDev().DrawPolyLine( polygon );
}
}
}
// TODO(P1): Provide caching here. return uno::Reference< rendering::XCachedPrimitive >(nullptr);
}
// change text direction and layout mode
vcl::text::ComplexTextLayoutFlags nLayoutMode(vcl::text::ComplexTextLayoutFlags::Default); switch( textDirection )
{ case rendering::TextDirection::WEAK_LEFT_TO_RIGHT: case rendering::TextDirection::STRONG_LEFT_TO_RIGHT:
nLayoutMode |= vcl::text::ComplexTextLayoutFlags::BiDiStrong;
nLayoutMode |= vcl::text::ComplexTextLayoutFlags::TextOriginLeft; break;
case rendering::TextDirection::WEAK_RIGHT_TO_LEFT:
nLayoutMode |= vcl::text::ComplexTextLayoutFlags::BiDiRtl;
[[fallthrough]]; case rendering::TextDirection::STRONG_RIGHT_TO_LEFT:
nLayoutMode |= vcl::text::ComplexTextLayoutFlags::BiDiRtl | vcl::text::ComplexTextLayoutFlags::BiDiStrong;
nLayoutMode |= vcl::text::ComplexTextLayoutFlags::TextOriginRight; break;
}
// TODO(T3): Race condition. We're taking the font // from xLayoutedText, and then calling draw() at it, // without exclusive access. Move setupTextOutput(), // e.g. to impltools?
// TODO(F2): Implement modulation again for other color // channels (currently, works only for alpha). Note: this // is already implemented in transformBitmap() if( bModulateColors &&
renderState.DeviceColor.getLength() > 3 )
{ // optimize away the case where alpha modulation value // is 1.0 - we then simply switch off modulation at all
bModulateColors = !::rtl::math::approxEqual(
renderState.DeviceColor[3], 1.0);
}
// check whether we can render bitmap as-is: must not // modulate colors, matrix must either be the identity // transform (that's clear), _or_ contain only // translational components. if( !bModulateColors &&
(aMatrix.isIdentity() ||
(::basegfx::fTools::equalZero( aMatrix.get(0,1) ) &&
::basegfx::fTools::equalZero( aMatrix.get(1,0) ) &&
::rtl::math::approxEqual(aMatrix.get(0,0), 1.0) &&
::rtl::math::approxEqual(aMatrix.get(1,1), 1.0)) ) )
{ // optimized case: identity matrix, or only // translational components.
mpOutDevProvider->getOutDev().DrawBitmapEx( vcl::unotools::pointFromB2DPoint( aOutputPos ),
aBmpEx );
if( mp2ndOutDevProvider )
{ // HACK. Normally, CanvasHelper does not care about // actually what mp2ndOutDev is... well, here we do & // assume a 1bpp target - everything beyond 97% // transparency is fully transparent if( aBmpEx.IsAlpha() && !SkiaHelper::isVCLSkiaEnabled())
{
BitmapFilter::Filter(aBmpEx, BitmapAlphaClampFilter(253));
}
// Returning a cache object is not useful, the XBitmap // itself serves this purpose return uno::Reference< rendering::XCachedPrimitive >(nullptr);
} elseif( mpOutDevProvider->getOutDev().HasFastDrawTransformedBitmap())
{
::basegfx::B2DHomMatrix aSizeTransform;
aSizeTransform.scale( aBmpEx.GetSizePixel().Width(), aBmpEx.GetSizePixel().Height() );
aMatrix = aMatrix * aSizeTransform; constdouble fAlpha = bModulateColors ? renderState.DeviceColor[3] : 1.0;
mpOutDevProvider->getOutDev().DrawTransformedBitmapEx( aMatrix, aBmpEx, fAlpha ); if( mp2ndOutDevProvider )
{ if( aBmpEx.IsAlpha() )
{ // tdf#157790 invert alpha mask // Due to commit 81994cb2b8b32453a92bcb011830fcb884f22ff3, // the alpha mask needs to be inverted. Note: when // testing tdf#157790, this code only gets executed // when Skia is enabled.
AlphaMask aAlpha( aBmpEx.GetAlphaMask() );
aAlpha.Invert();
aBmpEx = BitmapEx( aBmpEx.GetBitmap(), aAlpha );
// HACK. Normally, CanvasHelper does not care about // actually what mp2ndOutDev is... well, here we do & // assume a 1bpp target - everything beyond 97% // transparency is fully transparent if( !SkiaHelper::isVCLSkiaEnabled())
{
BitmapFilter::Filter(aBmpEx, BitmapAlphaClampFilter(253));
}
}
// TODO(F1): Note that the GraphicManager has a // subtle difference in how it calculates the // resulting alpha value: it's using the inverse // alpha values (i.e. 'transparency'), and // calculates transOrig + transModulate, instead // of transOrig + transModulate - // transOrig*transModulate (which would be // equivalent to the origAlpha*modulateAlpha the // DX canvas performs)
aGrfAttr.SetAlpha( static_cast< sal_uInt8 >(
::basegfx::fround( 255.0 * nAlphaModulation ) ) );
}
if( ::basegfx::fTools::equalZero( nShearX ) )
{ // no shear, GraphicObject is enough (the // GraphicObject only supports scaling, rotation // and translation)
// #i75339# don't apply mirror flags, having // negative size values is enough to make // GraphicObject flip the bitmap
// The angle has to be mapped from radian to tenths of // degrees with the orientation reversed: [0,2Pi) -> // (3600,0]. Note that the original angle may have // values outside the [0,2Pi) interval. constdouble nAngleInTenthOfDegrees (3600.0 - basegfx::rad2deg<10>(nRotate));
aGrfAttr.SetRotation( Degree10(::basegfx::fround(nAngleInTenthOfDegrees)) );
pGrfObj = std::make_shared<GraphicObject>( aBmpEx );
} else
{ // modify output position, to account for the fact // that transformBitmap() always normalizes its output // bitmap into the smallest enclosing box.
::basegfx::B2DRectangle aDestRect = ::canvas::tools::calcTransformedRectBounds(
::basegfx::B2DRectangle(0,
0,
aBmpSize.Width(),
aBmpSize.Height()),
aMatrix );
// TODO(P2): Don't change clipping all the time, maintain current clip // state and change only when update is necessary
::canvas::tools::clipOutDev(viewState, renderState, rOutDev, p2ndOutDev);
// setup font color
aVCLFont.SetColor( aColor );
aVCLFont.SetFillColor( aColor );
// no need to replicate this for mp2ndOutDev, we're modifying only aVCLFont here. if( !tools::setupFontTransform( o_rOutPos, aVCLFont, viewState, renderState, rOutDev ) ) returnfalse;
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.