office-gobmx/vcl/quartz/salvd.cxx
Norbert Thiebaud b20becf9e3 cosmetic: clean-up vcl/quartz
Change-Id: I6f15e7ce90598eb4f8e7bb59c7c65d1aa333b972
Reviewed-on: https://gerrit.libreoffice.org/17661
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Norbert Thiebaud <nthiebaud@gmail.com>
2015-08-12 09:54:56 +00:00

337 lines
11 KiB
C++

/* -*- 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 .
*/
#include <sal/config.h>
#include "vcl/svapp.hxx"
#include "vcl/sysdata.hxx"
#ifdef MACOSX
#include "osx/salinst.h"
#include "osx/saldata.hxx"
#include "osx/salframe.h"
#else
#include "headless/svpframe.hxx"
#include "headless/svpgdi.hxx"
#include "headless/svpinst.hxx"
#include "headless/svpvd.hxx"
#endif
#include "quartz/salgdi.h"
#include "quartz/salvd.h"
#include "quartz/utils.h"
SalVirtualDevice* AquaSalInstance::CreateVirtualDevice( SalGraphics* pGraphics,
long &nDX, long &nDY,
sal_uInt16 nBitCount,
const SystemGraphicsData *pData )
{
// #i92075# can be called first in a thread
SalData::ensureThreadAutoreleasePool();
#ifdef IOS
if( pData )
{
return new AquaSalVirtualDevice( static_cast< AquaSalGraphics* >( pGraphics ),
nDX, nDY, nBitCount, pData );
}
else
{
AquaSalVirtualDevice* pNew = new AquaSalVirtualDevice( NULL, nDX, nDY, nBitCount, NULL );
pNew->SetSize( nDX, nDY );
return pNew;
}
#else
return new AquaSalVirtualDevice( static_cast< AquaSalGraphics* >( pGraphics ),
nDX, nDY, nBitCount, pData );
#endif
}
AquaSalVirtualDevice::AquaSalVirtualDevice( AquaSalGraphics* pGraphic, long &nDX, long &nDY,
sal_uInt16 nBitCount, const SystemGraphicsData *pData )
: mbGraphicsUsed( false )
, mxBitmapContext( NULL )
, mnBitmapDepth( 0 )
, mxLayer( NULL )
{
SAL_INFO( "vcl.virdev", "AquaSalVirtualDevice::AquaSalVirtualDevice() this=" << this
<< " size=(" << nDX << "x" << nDY << ") bitcount=" << nBitCount <<
" pData=" << pData << " context=" << (pData ? pData->rCGContext : 0) );
if( pGraphic && pData && pData->rCGContext )
{
// Create virtual device based on existing SystemGraphicsData
// We ignore nDx and nDY, as the desired size comes from the SystemGraphicsData.
// the mxContext is from pData (what "mxContext"? there is no such field anywhere in vcl;)
mbForeignContext = true;
mpGraphics = new AquaSalGraphics( /*pGraphic*/ );
if (nDX == 0)
{
nDX = 1;
}
if (nDY == 0)
{
nDY = 1;
}
mxLayer = CGLayerCreateWithContext( pData->rCGContext, CGSizeMake( nDX, nDY), NULL );
// Interrogate the context as to its real size
if (mxLayer)
{
const CGSize aSize = CGLayerGetSize( mxLayer );
nDX = static_cast<long>(aSize.width);
nDY = static_cast<long>(aSize.height);
}
else
{
nDX = 0;
nDY = 0;
}
SAL_INFO( "vcl.cg", "CGLayerCreateWithContext(" << pData->rCGContext <<
"," << CGSizeMake( nDX, nDY) << ",NULL) = " << mxLayer );
mpGraphics->SetVirDevGraphics( mxLayer, pData->rCGContext );
}
else
{
// create empty new virtual device
mbForeignContext = false; // the mxContext is created within VCL
mpGraphics = new AquaSalGraphics(); // never fails
mnBitmapDepth = nBitCount;
#ifdef MACOSX
// inherit resolution from reference device
if( pGraphic )
{
AquaSalFrame* pFrame = pGraphic->getGraphicsFrame();
if( pFrame && AquaSalFrame::isAlive( pFrame ) )
{
mpGraphics->setGraphicsFrame( pFrame );
mpGraphics->copyResolution( *pGraphic );
}
}
#endif
if( nDX && nDY )
{
SetSize( nDX, nDY );
}
// NOTE: if SetSize does not succeed, we just ignore the nDX and nDY
}
}
AquaSalVirtualDevice::~AquaSalVirtualDevice()
{
SAL_INFO( "vcl.virdev", "AquaSalVirtualDevice::~AquaSalVirtualDevice() this=" << this );
if( mpGraphics )
{
mpGraphics->SetVirDevGraphics( NULL, NULL );
delete mpGraphics;
mpGraphics = 0;
}
Destroy();
}
void AquaSalVirtualDevice::Destroy()
{
SAL_INFO( "vcl.virdev", "AquaSalVirtualDevice::Destroy() this=" << this << " mbForeignContext=" << mbForeignContext );
if( mbForeignContext )
{
// Do not delete mxContext that we have received from outside VCL
mxLayer = NULL;
return;
}
if( mxLayer )
{
if( mpGraphics )
{
mpGraphics->SetVirDevGraphics( NULL, NULL );
}
SAL_INFO( "vcl.cg", "CGLayerRelease(" << mxLayer << ")" );
CGLayerRelease( mxLayer );
mxLayer = NULL;
}
if( mxBitmapContext )
{
void* pRawData = CGBitmapContextGetData( mxBitmapContext );
rtl_freeMemory( pRawData );
SAL_INFO( "vcl.cg", "CGContextRelease(" << mxBitmapContext << ")" );
CGContextRelease( mxBitmapContext );
mxBitmapContext = NULL;
}
}
SalGraphics* AquaSalVirtualDevice::AcquireGraphics()
{
if( mbGraphicsUsed || !mpGraphics )
{
return 0;
}
mbGraphicsUsed = true;
return mpGraphics;
}
void AquaSalVirtualDevice::ReleaseGraphics( SalGraphics* )
{
mbGraphicsUsed = false;
}
bool AquaSalVirtualDevice::SetSize( long nDX, long nDY )
{
SAL_INFO( "vcl.virdev", "AquaSalVirtualDevice::SetSize() this=" << this <<
" (" << nDX << "x" << nDY << ") mbForeignContext=" << mbForeignContext );
if( mbForeignContext )
{
// Do not delete/resize mxContext that we have received from outside VCL
return true;
}
if( mxLayer )
{
const CGSize aSize = CGLayerGetSize( mxLayer );
SAL_INFO( "vcl.cg", "CGlayerGetSize(" << mxLayer << ") = " << aSize );
if( (nDX == aSize.width) && (nDY == aSize.height) )
{
// Yay, we do not have to do anything :)
return true;
}
}
Destroy();
// create a Quartz layer matching to the intended virdev usage
CGContextRef xCGContext = NULL;
if( mnBitmapDepth && (mnBitmapDepth < 16) )
{
mnBitmapDepth = 8; // TODO: are 1bit vdevs worth it?
const int nBytesPerRow = (mnBitmapDepth * nDX + 7) / 8;
void* pRawData = rtl_allocateMemory( nBytesPerRow * nDY );
#ifdef DBG_UTIL
for (ssize_t i = 0; i < nBytesPerRow * nDY; i++)
{
static_cast<sal_uInt8*>(pRawData)[i] = (i & 0xFF);
}
#endif
mxBitmapContext = CGBitmapContextCreate( pRawData, nDX, nDY,
mnBitmapDepth, nBytesPerRow,
GetSalData()->mxGraySpace, kCGImageAlphaNone );
SAL_INFO( "vcl.cg", "CGBitmapContextCreate(" << nDX << "x" << nDY << "x" << mnBitmapDepth << ") = " << mxBitmapContext );
xCGContext = mxBitmapContext;
}
else
{
#ifdef MACOSX
// default to a NSView target context
AquaSalFrame* pSalFrame = mpGraphics->getGraphicsFrame();
if( !pSalFrame || !AquaSalFrame::isAlive( pSalFrame ))
{
if( !GetSalData()->maFrames.empty() )
{
// get the first matching frame
pSalFrame = *GetSalData()->maFrames.begin();
}
else
{
// ensure we don't reuse a dead AquaSalFrame on the very
// unlikely case of no other frame to use
pSalFrame = NULL;
}
// update the frame reference
mpGraphics->setGraphicsFrame( pSalFrame );
}
if( pSalFrame )
{
// #i91990#
NSWindow* pNSWindow = pSalFrame->getNSWindow();
if ( pNSWindow )
{
NSGraphicsContext* pNSContext = [NSGraphicsContext graphicsContextWithWindow: pNSWindow];
if( pNSContext )
{
xCGContext = static_cast<CGContextRef>([pNSContext graphicsPort]);
}
}
else
{
// fall back to a bitmap context
mnBitmapDepth = 32;
const int nBytesPerRow = (mnBitmapDepth * nDX) / 8;
void* pRawData = rtl_allocateMemory( nBytesPerRow * nDY );
#ifdef DBG_UTIL
for (ssize_t i = 0; i < nBytesPerRow * nDY; i++)
{
static_cast<sal_uInt8*>(pRawData)[i] = (i & 0xFF);
}
#endif
mxBitmapContext = CGBitmapContextCreate( pRawData, nDX, nDY,
8, nBytesPerRow, GetSalData()->mxRGBSpace, kCGImageAlphaNoneSkipFirst );
SAL_INFO( "vcl.cg", "CGBitmapContextCreate(" << nDX << "x" << nDY << "x32) = " << mxBitmapContext );
xCGContext = mxBitmapContext;
}
}
#else
mnBitmapDepth = 32;
const int nBytesPerRow = (mnBitmapDepth * nDX) / 8;
void* pRawData = rtl_allocateMemory( nBytesPerRow * nDY );
#ifdef DBG_UTIL
for (ssize_t i = 0; i < nBytesPerRow * nDY; i++)
{
((sal_uInt8*)pRawData)[i] = (i & 0xFF);
}
#endif
mxBitmapContext = CGBitmapContextCreate( pRawData, nDX, nDY,
8, nBytesPerRow, GetSalData()->mxRGBSpace, kCGImageAlphaNoneSkipFirst );
SAL_INFO( "vcl.cg", "CGBitmapContextCreate(" << nDX << "x" << nDY << "x32) = " << mxBitmapContext );
xCGContext = mxBitmapContext;
#endif
}
SAL_WARN_IF( !xCGContext, "vcl.quartz", "No context" );
const CGSize aNewSize = { static_cast<CGFloat>(nDX), static_cast<CGFloat>(nDY) };
mxLayer = CGLayerCreateWithContext( xCGContext, aNewSize, NULL );
SAL_INFO( "vcl.cg", "CGLayerCreateWithContext(" << xCGContext << "," << aNewSize << ",NULL) = " << mxLayer );
if( mxLayer && mpGraphics )
{
// get the matching Quartz context
CGContextRef xDrawContext = CGLayerGetContext( mxLayer );
SAL_INFO( "vcl.cg", "CGLayerGetContext(" << mxLayer << ") = " << xDrawContext );
mpGraphics->SetVirDevGraphics( mxLayer, xDrawContext, mnBitmapDepth );
}
return (mxLayer != NULL);
}
long AquaSalVirtualDevice::GetWidth() const
{
const CGSize aSize = CGLayerGetSize( mxLayer );
return aSize.width;
}
long AquaSalVirtualDevice::GetHeight() const
{
const CGSize aSize = CGLayerGetSize( mxLayer );
return aSize.height;
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */