/* -*- 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 .
*/
// free support functions // ======================
namespace slideshow::internal
{ // TODO(E2): Detect the case when svx/drawing layer is not // in-process, or even not on the same machine, and // fallback to metafile streaming!
// For fixing #i48102#, have to be a _lot_ more selective // on which metafiles to convert to bitmaps. The problem // here is that we _always_ get the shape content as a // metafile, even if we have a bitmap graphic shape. Thus, // calling GetBitmapEx on such a Graphic (see below) will // result in one poorly scaled bitmap into another, // somewhat arbitrarily sized bitmap. staticbool hasUnsupportedActions( const GDIMetaFile& rMtf )
{ // search metafile for RasterOp action
MetaAction* pCurrAct;
// TODO(Q3): avoid const-cast for( pCurrAct = const_cast<GDIMetaFile&>(rMtf).FirstAction();
pCurrAct;
pCurrAct = const_cast<GDIMetaFile&>(rMtf).NextAction() )
{ switch( pCurrAct->GetType() )
{ case MetaActionType::RASTEROP: // overpaint is okay - that's the default, anyway if( RasterOp::OverPaint == static_cast<MetaRasterOpAction*>(pCurrAct)->GetRasterOp() )
{ break;
}
[[fallthrough]]; case MetaActionType::MOVECLIPREGION: case MetaActionType::REFPOINT: case MetaActionType::WALLPAPER: returntrue; // at least one unsupported // action encountered default: break;
}
}
@param bForeignSource When true, the source of the metafile might be a foreign application. The metafile is checked against unsupported content, and, if necessary, returned as a pre-rendered bitmap.
*/
GDIMetaFileSharedPtr getMtf( bool bForeignSource ) const
{
::osl::MutexGuard aGuard( m_aMutex );
// Quick'n'dirty way: tunnel Graphic (only works for // in-process slideshow, of course)
GDIMetaFileSharedPtr getMetaFile( const uno::Reference< lang::XComponent >& xSource, const uno::Reference< drawing::XDrawPage >& xContainingPage, int mtfLoadFlags, const uno::Reference< uno::XComponentContext >& rxContext )
{ if (!rxContext.is())
{
SAL_WARN("slideshow.opengl", "getMetaFile(): Invalid context" ); return GDIMetaFileSharedPtr();
}
// create dummy XGraphicRenderer, which receives the // generated XGraphic from the GraphicExporter
// TODO(P3): Move creation of DummyRenderer out of the // loop! Either by making it static, or transforming // the whole thing here into a class.
rtl::Reference<DummyRenderer> xRenderer( new DummyRenderer() );
// pRenderer is automatically destroyed when xRenderer // goes out of scope
// TODO(E3): Error handling. Exporter might have // generated nothing, a bitmap, threw an exception, // whatever. return xMtf;
}
sal_Int32 getNextActionOffset( MetaAction * pCurrAct )
{ // Special handling for actions that represent // more than one indexable action // ===========================================
switch (pCurrAct->GetType()) { case MetaActionType::TEXT: {
MetaTextAction * pAct = static_cast<MetaTextAction *>(pCurrAct);
sal_Int32 nLen = std::min(pAct->GetLen(), pAct->GetText().getLength() - pAct->GetIndex()); return nLen;
} case MetaActionType::TEXTARRAY: {
MetaTextArrayAction * pAct = static_cast<MetaTextArrayAction *>(pCurrAct);
sal_Int32 nLen = std::min(pAct->GetLen(), pAct->GetText().getLength() - pAct->GetIndex()); return nLen;
} case MetaActionType::STRETCHTEXT: {
MetaStretchTextAction * pAct = static_cast<MetaStretchTextAction *>(pCurrAct);
sal_Int32 nLen = std::min(pAct->GetLen(), pAct->GetText().getLength() - pAct->GetIndex()); return nLen;
} case MetaActionType::FLOATTRANSPARENT: {
MetaFloatTransparentAction * pAct = static_cast<MetaFloatTransparentAction*>(pCurrAct); // TODO(F2): Recurse into action metafile // (though this is currently not used from the // DrawingLayer - shape transparency gradients // don't affect shape text) return pAct->GetGDIMetaFile().GetActionSize();
} default: return 1;
}
}
// some loop invariants
::Animation aAnimation( pGraphic->GetAnimation() ); const Point aEmptyPoint; const Size aAnimSize( aAnimation.GetDisplaySizePixel() );
if (bFirstRun)
{ // setup VDev, into which all bitmaps are painted (want to // normalize animations to n bitmaps of same size. An Animation, // though, can contain bitmaps of varying sizes and different // update modes)
pVDev->SetOutputSizePixel(aAnimSize);
pVDev->EnableMapMode(false);
// setup mask VDev (alpha VDev is currently rather slow)
pVDevMask->SetOutputSizePixel(aAnimSize);
pVDevMask->EnableMapMode(false);
// tdf#156630 make erase calls fill with transparency
pVDev->SetBackground(Wallpaper(COL_BLACK));
pVDevMask->SetBackground(Wallpaper(COL_ALPHA_TRANSPARENT));
o_rLoopCount = aAnimation.GetLoopCount();
}
sal_uInt16 nCount = aAnimation.Count(); if (!bFirstRun && mnLoadedFrames + nFramesToLoad < nCount)
nCount = mnLoadedFrames + nFramesToLoad; for (sal_uInt16 i = mnLoadedFrames; i < nCount; ++i)
{ const AnimationFrame& rAnimationFrame( aAnimation.Get(i) ); bool bCalculateNow = !bFirstRun || i < nFramesToLoad; if (bCalculateNow)
{ switch (rAnimationFrame.meDisposal)
{ case Disposal::Not:
{
pVDev->DrawBitmapEx(rAnimationFrame.maPositionPixel,
rAnimationFrame.maBitmapEx);
AlphaMask aMask = rAnimationFrame.maBitmapEx.GetAlphaMask();
case Disposal::Back:
{ // #i70772# react on no mask const AlphaMask aMask(rAnimationFrame.maBitmapEx.GetAlphaMask()); const Bitmap& rContent(rAnimationFrame.maBitmapEx.GetBitmap());
case Disposal::Previous:
{
pVDev->DrawBitmapEx(rAnimationFrame.maPositionPixel,
rAnimationFrame.maBitmapEx);
pVDevMask->DrawBitmap(rAnimationFrame.maPositionPixel,
rAnimationFrame.maBitmapEx.GetAlphaMask().GetBitmap()); break;
}
}
} // extract current aVDev content into a new animation // frame
GDIMetaFileSharedPtr pMtf; if (bFirstRun)
{
pMtf = std::make_shared<GDIMetaFile>();
} else
{
pMtf = o_rFrames[i].mpMtf;
} bool useAlphaMask = false; #ifdefined(MACOSX) || defined(IOS)
useAlphaMask = true; #else // GetBitmap()-> AlphaMask is optimized with SkiaSalBitmap::InterpretAs8Bit(), 1bpp mask is not. if( SkiaHelper::isVCLSkiaEnabled())
useAlphaMask = true; #endif if (bCalculateNow)
{ if( useAlphaMask )
{
AlphaMask aAlphaMask(pVDevMask->GetBitmap(aEmptyPoint, aAnimSize));
pMtf->AddAction( new MetaBmpExAction( aEmptyPoint,
BitmapEx(
pVDev->GetBitmap(
aEmptyPoint,
aAnimSize ),
aAlphaMask)));
} else
{
Bitmap aAlphaMask = pVDevMask->GetBitmap(aEmptyPoint, aAnimSize);
aAlphaMask.Invert(); // convert from transparency to alpha
pMtf->AddAction( new MetaBmpExAction( aEmptyPoint,
BitmapEx(
pVDev->GetBitmap(
aEmptyPoint,
aAnimSize ),
aAlphaMask)));
}
mnLoadedFrames = i+1;
} if (bFirstRun)
{ // setup mtf dimensions and pref map mode (for // simplicity, keep it all in pixel. the metafile // renderer scales it down to (1, 1) box anyway)
pMtf->SetPrefMapMode(MapMode());
pMtf->SetPrefSize(aAnimSize);
// Take care of special value for MultiPage TIFFs. ATM these shall just // show their first page for _quite_ some time.
sal_Int32 nWaitTime100thSeconds(rAnimationFrame.mnWait); if (ANIMATION_TIMEOUT_ON_CLICK == nWaitTime100thSeconds)
{ // ATM the huge value would block the timer, so use a long // time to show first page (whole day)
nWaitTime100thSeconds = 100 * 60 * 60 * 24;
}
// There are animated GIFs with no WaitTime set. Take 0.1 sec, the // same duration that is used by the edit view. if (nWaitTime100thSeconds == 0)
nWaitTime100thSeconds = 10;
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.