/* -*- 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 .
*/
// prepare vdev if (!pContent->SetOutputSizePixel(rSizePixel, false))
{
SAL_WARN("vcl", "Cannot set VirtualDevice to size : " << rSizePixel.Width() << "x"
<< rSizePixel.Height()); return AlphaMask();
}
// create pixel processor, also already takes care of AAing and // checking the getOptionsDrawinglayer().IsAntiAliasing() switch. If // not wanted, change after this call as needed
std::unique_ptr<drawinglayer::processor2d::BaseProcessor2D> pContentProcessor
= drawinglayer::processor2d::createPixelProcessor2DFromOutputDevice(*pContent,
rViewInformation2D);
// prepare for mask creation
pContent->SetMapMode(MapMode(MapUnit::MapPixel));
// set transparency to all white (fully transparent)
pContent->Erase();
basegfx::BColorModifierSharedPtr aBColorModifier; if (bUseLuminance)
{ // new mode: bUseLuminance allows simple creation of alpha channels // for any content (e.g. gradients)
aBColorModifier = std::make_shared<basegfx::BColorModifier_luminance_to_alpha>();
} else
{ // Embed primitives to paint them black (fully opaque)
aBColorModifier
= std::make_shared<basegfx::BColorModifier_replace>(basegfx::BColor(0.0, 0.0, 0.0));
} const drawinglayer::primitive2d::Primitive2DReference xRef( new drawinglayer::primitive2d::ModifiedColorPrimitive2D(std::move(rSequence),
std::move(aBColorModifier))); const drawinglayer::primitive2d::Primitive2DContainer xSeq{ xRef };
// get alpha channel from vdev
pContent->EnableMapMode(false); const Point aEmptyPoint;
// Convert from transparency->alpha. // FIXME in theory I should be able to directly construct alpha by using black as background // and white as foreground, but that doesn't work for some reason.
Bitmap aContentBitmap = pContent->GetBitmap(aEmptyPoint, rSizePixel);
aContentBitmap.Invert();
if (!implPrepareConversion(aSequence, nDiscreteWidth, nDiscreteHeight, nMaxSquarePixels))
{ return BitmapEx();
}
#if USE_HEADLESS_CODE // shortcut: try to directly create a PixelProcessor2D with // RGBA support - that's what we need // Currently only implemented for CairoSDPR, so add code only // for USE_HEADLESS_CODE, but is designed as a general functionality
std::unique_ptr<processor2d::BaseProcessor2D> pRGBAProcessor
= processor2d::createPixelProcessor2DFromScratch(rViewInformation2D, nDiscreteWidth, nDiscreteHeight, true); if (pRGBAProcessor)
{ // render content
pRGBAProcessor->process(aSequence);
// create final BitmapEx result (content) const BitmapEx aRetval(processor2d::extractBitmapExFromBaseProcessor2D(pRGBAProcessor));
// check if we have a result and return if so if (!aRetval.IsEmpty()) return aRetval;
} #endif
const Point aEmptyPoint; const Size aSizePixel(nDiscreteWidth, nDiscreteHeight);
// Create target VirtualDevice. Go back to using a simple RGB // target version (compared with former version, see history). // Reasons are manyfold: // - Avoid the RGBA mode for VirtualDevice (two VDevs) // - It's not suggested to be used outside presentation engine // - It only works *by chance* with VCLPrimitiveRenderer // - Usage of two-VDev alpha-VDev avoided alpha blending against // COL_WHITE in the 1st layer of targets (not in buffers below) // but is kind of a 'hack' doing so // - Other renderers (system-dependent PrimitiveRenderers, other // than the VCL-based ones) will probably not support splitted // VDevs for content/alpha, so require a method that works with // RGB targeting (for now) // - Less resource usage, better speed (no 2 VDevs, no merge of // AlphaChannels) // As long as not all our mechanisms are changed to RGBA completely, // mixing these is just too dangerous and expensive and may to wrong // or deliver bad quality results. // Nonetheless we need a RGBA result here. Luckily we are able to // create a complete and valid AlphaChannel using 'createAlphaMask' // above. // When we know the content (RGB result from renderer), alpha // (result from createAlphaMask) and the start condition (content // rendered against COL_WHITE), it is possible to calculate back // the content, quasi 'remove' that initial blending against // COL_WHITE. // That is what the helper Bitmap::RemoveBlendedStartColor does. // Luckily we only need it for this 'convertToBitmapEx', not in // any other rendering. It could be further optimized, too. // This gives good results, it is in principle comparable with // the results using pre-multiplied alpha tooling, also reducing // the range of values where high alpha values are used.
ScopedVclPtrInstance<VirtualDevice> pContent(*Application::GetDefaultDevice());
// prepare vdev if (!pContent->SetOutputSizePixel(aSizePixel, false))
{
SAL_WARN("vcl", "Cannot set VirtualDevice to size : " << aSizePixel.Width() << "x"
<< aSizePixel.Height()); return BitmapEx();
}
// We map to pixel, use that MapMode. Init by erasing.
pContent->SetMapMode(MapMode(MapUnit::MapPixel));
pContent->Erase();
// create pixel processor, also already takes care of AAing and // checking the getOptionsDrawinglayer().IsAntiAliasing() switch. If // not wanted, change after this call as needed
std::unique_ptr<processor2d::BaseProcessor2D> pContentProcessor
= processor2d::createPixelProcessor2DFromOutputDevice(*pContent, rViewInformation2D);
// create final BitmapEx result (content)
Bitmap aRetval(pContent->GetBitmap(aEmptyPoint, aSizePixel));
#ifdef DBG_UTIL staticbool bDoSaveForVisualControl(false); // loplugin:constvars:ignore if (bDoSaveForVisualControl)
{ // VCL_DUMP_BMP_PATH should be like C:/path/ or ~/path/ staticconst OUString sDumpPath(
OUString::createFromAscii(std::getenv("VCL_DUMP_BMP_PATH"))); if (!sDumpPath.isEmpty())
{
SvFileStream aNew(sDumpPath + "test_content.bmp",
StreamMode::WRITE | StreamMode::TRUNC);
WriteDIB(aRetval, aNew, false, true);
}
} #endif
// Create the AlphaMask using a method that does this always correct (also used // now in GlowPrimitive2D and ShadowPrimitive2D which both only need the // AlphaMask to do their job, so speeding that up, too).
AlphaMask aAlpha(implcreateAlphaMask(aSequence, rViewInformation2D, aSizePixel, false));
#ifdef DBG_UTIL if (bDoSaveForVisualControl)
{ // VCL_DUMP_BMP_PATH should be like C:/path/ or ~/path/ staticconst OUString sDumpPath(
OUString::createFromAscii(std::getenv("VCL_DUMP_BMP_PATH"))); if (!sDumpPath.isEmpty())
{
SvFileStream aNew(sDumpPath + "test_alpha.bmp", StreamMode::WRITE | StreamMode::TRUNC);
WriteDIB(aAlpha.GetBitmap(), aNew, false, true);
}
} #endif
if (bForceAlphaMaskCreation || aAlpha.hasAlpha())
{ // Need to correct content using known alpha to get to background-free // RGBA result, usable e.g. in PNG export(s) or convert-to-bitmap. // Now that vcl supports bitmaps with an alpha channel, only apply // this correction to bitmaps without an alpha channel. if (pContent->GetBitCount() < 32)
{
aRetval.RemoveBlendedStartColor(COL_BLACK, aAlpha);
} else
{ // tdf#157558 invert and remove blended white color // Before commit 81994cb2b8b32453a92bcb011830fcb884f22ff3, // RemoveBlendedStartColor(COL_BLACK, aAlpha) would darken // the bitmap when running a slideshow, printing, or exporting // to PDF. To get the same effect, the alpha mask must be // inverted, RemoveBlendedStartColor(COL_WHITE, aAlpha) // called, and the alpha mask uninverted.
aAlpha.Invert();
aRetval.RemoveBlendedStartColor(COL_WHITE, aAlpha);
aAlpha.Invert();
} // return combined result return BitmapEx(aRetval, aAlpha);
} else return BitmapEx(aRetval);
}
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.