Files
libreoffice/vcl/ios/source/gdi/salgdiutils.cxx
Tor Lillqvist 83ba7b4e8f Copy and adapt current state of Norbert's CoreText work for iOS
Compiles, but I obviously have no idea how it works yet.

Yes, eventually we should factor out common parts from the iOS and
MacOSX code.
2012-04-15 11:56:47 +02:00

316 lines
9.6 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright 2000, 2010 Oracle and/or its affiliates.
*
* OpenOffice.org - a multi-platform office productivity suite
*
* This file is part of OpenOffice.org.
*
* OpenOffice.org is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 3
* only, as published by the Free Software Foundation.
*
* OpenOffice.org is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License version 3 for more details
* (a copy is included in the LICENSE file that accompanied this code).
*
* You should have received a copy of the GNU Lesser General Public License
* version 3 along with OpenOffice.org. If not, see
* <http://www.openoffice.org/license.html>
* for a copy of the LGPLv3 License.
*
************************************************************************/
#include <boost/bind.hpp>
#include "basebmp/scanlineformats.hxx"
#include "basebmp/color.hxx"
#include "basegfx/range/b2drectangle.hxx"
#include "basegfx/range/b2irange.hxx"
#include "basegfx/vector/b2ivector.hxx"
#include "basegfx/polygon/b2dpolygon.hxx"
#include "basegfx/polygon/b2dpolygontools.hxx"
#include "vcl/svapp.hxx"
#include "ios/salgdi.h"
#include "ios/salframe.h"
#include "ios/saldata.hxx"
// ----------------------------------------------------------------------
void IosSalGraphics::SetWindowGraphics( IosSalFrame* pFrame )
{
mpFrame = pFrame;
mbWindow = true;
mbPrinter = false;
mbVirDev = false;
}
void IosSalGraphics::SetPrinterGraphics( CGContextRef xContext, long nDPIX, long nDPIY, double fScale )
{
mbWindow = false;
mbPrinter = true;
mbVirDev = false;
mrContext = xContext;
mfFakeDPIScale = fScale;
mnRealDPIX = nDPIX;
mnRealDPIY = nDPIY;
// a previously set clip path is now invalid
if( mxClipPath )
{
CGPathRelease( mxClipPath );
mxClipPath = NULL;
}
if( mrContext )
{
CGContextSetFillColorSpace( mrContext, GetSalData()->mxRGBSpace );
CGContextSetStrokeColorSpace( mrContext, GetSalData()->mxRGBSpace );
CGContextSaveGState( mrContext );
SetState();
}
}
void IosSalGraphics::SetVirDevGraphics( CGLayerRef xLayer, CGContextRef xContext,
int nBitmapDepth )
{
mbWindow = false;
mbPrinter = false;
mbVirDev = true;
// set graphics properties
mxLayer = xLayer;
mrContext = xContext;
mnBitmapDepth = nBitmapDepth;
// return early if the virdev is being destroyed
if( !xContext )
return;
// get new graphics properties
if( !mxLayer )
{
mnWidth = CGBitmapContextGetWidth( mrContext );
mnHeight = CGBitmapContextGetHeight( mrContext );
}
else
{
const CGSize aSize = CGLayerGetSize( mxLayer );
mnWidth = static_cast<int>(aSize.width);
mnHeight = static_cast<int>(aSize.height);
}
// prepare graphics for drawing
const CGColorSpaceRef aCGColorSpace = GetSalData()->mxRGBSpace;
CGContextSetFillColorSpace( mrContext, aCGColorSpace );
CGContextSetStrokeColorSpace( mrContext, aCGColorSpace );
// re-enable XorEmulation for the new context
if( mpXorEmulation )
{
mpXorEmulation->SetTarget( mnWidth, mnHeight, mnBitmapDepth, mrContext, mxLayer );
if( mpXorEmulation->IsEnabled() )
mrContext = mpXorEmulation->GetMaskContext();
}
// initialize stack of CGContext states
CGContextSaveGState( mrContext );
SetState();
}
// ----------------------------------------------------------------------
void IosSalGraphics::InvalidateContext()
{
UnsetState();
mrContext = 0;
}
// ----------------------------------------------------------------------
void IosSalGraphics::UnsetState()
{
if( mrContext )
{
CGContextRestoreGState( mrContext );
mrContext = 0;
}
if( mxClipPath )
{
CGPathRelease( mxClipPath );
mxClipPath = NULL;
}
}
void IosSalGraphics::SetState()
{
CGContextRestoreGState( mrContext );
CGContextSaveGState( mrContext );
// setup clipping
if( mxClipPath )
{
CGContextBeginPath( mrContext ); // discard any existing path
CGContextAddPath( mrContext, mxClipPath ); // set the current path to the clipping path
CGContextClip( mrContext ); // use it for clipping
}
// set RGB colorspace and line and fill colors
CGContextSetFillColor( mrContext, maFillColor.AsArray() );
CGContextSetStrokeColor( mrContext, maLineColor.AsArray() );
CGContextSetShouldAntialias( mrContext, false );
if( mnXorMode == 2 )
CGContextSetBlendMode( mrContext, kCGBlendModeDifference );
}
// ----------------------------------------------------------------------
bool IosSalGraphics::CheckContext()
{
if( mbWindow && mpFrame != NULL )
{
const unsigned int nWidth = mpFrame->maGeometry.nWidth;
const unsigned int nHeight = mpFrame->maGeometry.nHeight;
CGContextRef rReleaseContext = 0;
CGLayerRef rReleaseLayer = NULL;
// check if a new drawing context is needed (e.g. after a resize)
if( (unsigned(mnWidth) != nWidth) || (unsigned(mnHeight) != nHeight) )
{
mnWidth = nWidth;
mnHeight = nHeight;
// prepare to release the corresponding resources
rReleaseContext = mrContext;
rReleaseLayer = mxLayer;
mrContext = NULL;
mxLayer = NULL;
}
if( !mrContext )
{
#if 0 // No idea
const CGSize aLayerSize = {nWidth,nHeight};
UIGraphicsContext* puiGContext = [UIGraphicsContext graphicsContextWithWindow: mpFrame->getWindow()];
CGContextRef xCGContext = reinterpret_cast<CGContextRef>([pUIGContext graphicsPort]);
mxLayer = CGLayerCreateWithContext( xCGContext, aLayerSize, NULL );
if( mxLayer )
mrContext = CGLayerGetContext( mxLayer );
#endif
if( mrContext )
{
// copy original layer to resized layer
if( rReleaseLayer )
CGContextDrawLayerAtPoint( mrContext, CGPointZero, rReleaseLayer );
CGContextTranslateCTM( mrContext, 0, nHeight );
CGContextScaleCTM( mrContext, 1.0, -1.0 );
CGContextSetFillColorSpace( mrContext, GetSalData()->mxRGBSpace );
CGContextSetStrokeColorSpace( mrContext, GetSalData()->mxRGBSpace );
CGContextSaveGState( mrContext );
SetState();
// re-enable XOR emulation for the new context
if( mpXorEmulation )
mpXorEmulation->SetTarget( mnWidth, mnHeight, mnBitmapDepth, mrContext, mxLayer );
}
}
if( rReleaseLayer )
CGLayerRelease( rReleaseLayer );
else if( rReleaseContext )
CGContextRelease( rReleaseContext );
}
DBG_ASSERT( mrContext || mbPrinter, "<<<WARNING>>> IosSalGraphics::CheckContext() FAILED!!!!\n" );
return (mrContext != NULL);
}
CGContextRef IosSalGraphics::GetContext()
{
if(!mrContext)
{
CheckContext();
}
return mrContext;
}
void IosSalGraphics::RefreshRect(float lX, float lY, float lWidth, float lHeight)
{
if( ! mbWindow ) // view only on Window graphics
return;
if( mpFrame )
{
// update a little more around the designated rectangle
// this helps with antialiased rendering
const Rectangle aVclRect(Point(static_cast<long int>(lX-1),
static_cast<long int>(lY-1) ),
Size( static_cast<long int>(lWidth+2),
static_cast<long int>(lHeight+2) ) );
mpFrame->maInvalidRect.Union( aVclRect );
}
}
CGPoint* IosSalGraphics::makeCGptArray(sal_uLong nPoints, const SalPoint* pPtAry)
{
CGPoint *CGpoints = new CGPoint[nPoints];
if ( CGpoints )
{
for(sal_uLong i=0;i<nPoints;i++)
{
CGpoints[i].x = (float)(pPtAry[i].mnX);
CGpoints[i].y = (float)(pPtAry[i].mnY);
}
}
return CGpoints;
}
// -----------------------------------------------------------------------
void IosSalGraphics::UpdateWindow( CGRect& )
{
#if 0 // Sigh, this is just basically a copy of the "aqua" code and not
// applicable to iOS.
if( !mpFrame )
return;
UIGraphicsContext* pContext = [UIGraphicsContext currentContext];
if( (mxLayer != NULL) && (pContext != NULL) )
{
CGContextRef rCGContext = reinterpret_cast<CGContextRef>([pContext graphicsPort]);
CGMutablePathRef rClip = mpFrame->getClipPath();
if( rClip )
{
CGContextSaveGState( rCGContext );
CGContextBeginPath( rCGContext );
CGContextAddPath( rCGContext, rClip );
CGContextClip( rCGContext );
}
ApplyXorContext();
CGContextDrawLayerAtPoint( rCGContext, CGPointZero, mxLayer );
if( rClip ) // cleanup clipping
CGContextRestoreGState( rCGContext );
}
else
DBG_ASSERT( mpFrame->mbInitShow, "UpdateWindow called on uneligible graphics" );
#endif
}
// -----------------------------------------------------------------------
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */