/* -*- 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 graphics context // convert image from user input if available constbool bSkipConversion = !m_pUserBuffer; if( bSkipConversion )
AllocateUserData();
// default to RGBA color space
CGColorSpaceRef aCGColorSpace = GetSalData()->mxRGBSpace;
CGBitmapInfo aCGBmpInfo = kCGImageAlphaNoneSkipFirst;
// convert data into something accepted by CGBitmapContextCreate()
size_t bitsPerComponent = 8;
sal_uInt32 nContextBytesPerRow = mnBytesPerRow; if( mnBits == 32 )
{ // no conversion needed for truecolor
m_pContextBuffer = m_pUserBuffer;
} elseif( mnBits == 8 && maPalette.IsGreyPalette8Bit() )
{ // no conversion needed for grayscale
m_pContextBuffer = m_pUserBuffer;
aCGColorSpace = GetSalData()->mxGraySpace;
aCGBmpInfo = kCGImageAlphaNone;
bitsPerComponent = mnBits;
} // TODO: is special handling for 1bit input buffers worth it? else
{ // convert user data to 32 bit
nContextBytesPerRow = mnWidth << 2; try
{
m_pContextBuffer = o3tl::make_shared_array<sal_uInt8>(mnHeight * nContextBytesPerRow);
if( !bConverted )
{ // TODO: this implementation is for clarity, not for speed
auto pTarget = vcl::bitmap::getScanlineTransformer(nDestBits, rDestPalette); auto pSource = vcl::bitmap::getScanlineTransformer(nSrcBits, rSrcPalette);
if (pTarget && pSource)
{
sal_uInt32 nY = nHeight; while( nY-- )
{
pTarget->startLine(pDestData);
pSource->startLine(pSrcData);
// at this point we should provide some kind of default palette // since all other platforms do so, too. staticbool bDefPalInit = false; static BitmapPalette aDefPalette256; static BitmapPalette aDefPalette2; if( ! bDefPalInit )
{
bDefPalInit = true;
aDefPalette256.SetEntryCount( 256 );
aDefPalette2.SetEntryCount( 2 );
// Standard colors unsignedint i; for( i = 0; i < 16; i++ )
{
aDefPalette256[i] = BitmapColor( aImplSalSysPalEntryAry[i].mnRed,
aImplSalSysPalEntryAry[i].mnGreen,
aImplSalSysPalEntryAry[i].mnBlue );
}
CGImageRef QuartzSalBitmap::CreateWithMask( const SalBitmap& rMask, int nX, int nY, int nWidth, int nHeight ) const
{ return CreateWithSalBitmapAndMask( *this, rMask, nX, nY, nWidth, nHeight );
}
/** creates an image from the given rectangle, replacing all black pixels
with nMaskColor and make all other full transparent */
CGImageRef QuartzSalBitmap::CreateColorMask( int nX, int nY, int nWidth, int nHeight, Color nMaskColor ) const
{
CGImageRef xMask = nullptr; if (m_pUserBuffer && (nX + nWidth <= mnWidth) && (nY + nHeight <= mnHeight))
{ auto pSourcePixels = vcl::bitmap::getScanlineTransformer(mnBits, maPalette); // Don't allocate destination buffer if there is no scanline transformer if( !pSourcePixels ) return xMask;
sal_uInt8* pSource = m_pUserBuffer.get();
sal_uInt32* pDest = pMaskBuffer.get(); // First to nY on y-axis, as that is our starting point (sub-image) if( nY )
pSource += nY * mnBytesPerRow;
int y = nHeight; while( y-- )
{
pSourcePixels->startLine( pSource );
pSourcePixels->skipPixel(nX); // Skip on x axis to nX
sal_uInt32 x = nWidth; while( x-- )
{ // Fix failure to generate the correct color mask // OutputDevice::ImplDrawRotateText() draws black text but // that will generate gray pixels due to antialiasing so // count dark gray the same as black, light gray the same // as white, and the rest as medium gray. // The results are not smooth since LibreOffice appears to // redraw these semi-transparent masks repeatedly without // clearing the background so the semi-transparent pixels // will grow darker with repeatedly redraws due to // cumulative blending. But it is now better than before.
sal_uInt8 nAlpha = 255 - pSourcePixels->readPixel().GetRed();
sal_uInt32 nPremultColor = nColor; if ( nAlpha < 192 )
{ if ( nAlpha < 64 )
{
nPremultColor = 0;
} else
{ reinterpret_cast<sal_uInt8*>(&nPremultColor)[0] /= 2; reinterpret_cast<sal_uInt8*>(&nPremultColor)[1] /= 2; reinterpret_cast<sal_uInt8*>(&nPremultColor)[2] /= 2; reinterpret_cast<sal_uInt8*>(&nPremultColor)[3] /= 2;
}
}
*pDest++ = nPremultColor;
}
pSource += mnBytesPerRow;
}
/** QuartzSalBitmap::GetSystemData Get platform native image data from existing image * * @param rData struct BitmapSystemData, defined in vcl/inc/bitmap.hxx * @return true if successful
**/ bool QuartzSalBitmap::GetSystemData( BitmapSystemData& rData )
{ bool bRet = false;
if (!maGraphicContext.isSet())
CreateContext();
if (maGraphicContext.isSet())
{
bRet = true;
if ((CGBitmapContextGetBitsPerPixel(maGraphicContext.get()) == 32) &&
(CGBitmapContextGetBitmapInfo(maGraphicContext.get()) & kCGBitmapByteOrderMask) != kCGBitmapByteOrder32Host)
{ /** * We need to hack things because VCL does not use kCGBitmapByteOrder32Host, while Cairo requires it. * * Not sure what the above comment means. We don't use Cairo on macOS or iOS. * * This whole if statement was originally (before 2011) inside #ifdef CAIRO. Did we use Cairo on Mac back then? * Anyway, nowadays (since many years, I think) we don't, so should this if statement be dropped? Fun.
*/
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.