/* -*- 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 #include #include #include #include #include #include #include #include #include #include #include "outdev.h" #include "outdata.hxx" #include #include "salgdi.hxx" #include "sallayout.hxx" OutDevState::OutDevState() : mpMapMode(0) , mbMapActive(false) , mpClipRegion(0) , mpLineColor(0) , mpFillColor(0) , mpFont(0) , mpTextColor(0) , mpTextFillColor(0) , mpTextLineColor(0) , mpOverlineColor(0) , mpRefPoint(0) , meTextAlign(ALIGN_TOP) , meRasterOp(ROP_OVERPAINT) , mnTextLayoutMode(TEXT_LAYOUT_DEFAULT) , meTextLanguage(0) , mnFlags(PushFlags::NONE) { } OutDevState::~OutDevState() { delete mpLineColor; delete mpFillColor; delete mpFont; delete mpTextColor; delete mpTextFillColor; delete mpTextLineColor; delete mpOverlineColor; delete mpMapMode; delete mpClipRegion; delete mpRefPoint; } void OutputDevice::Push( PushFlags nFlags ) { if ( mpMetaFile ) mpMetaFile->AddAction( new MetaPushAction( nFlags ) ); OutDevState* pState = new OutDevState; pState->mnFlags = nFlags; if (nFlags & PushFlags::LINECOLOR && mbLineColor) { pState->mpLineColor = new Color( maLineColor ); } if (nFlags & PushFlags::FILLCOLOR && mbFillColor) { pState->mpFillColor = new Color( maFillColor ); } if ( nFlags & PushFlags::FONT ) pState->mpFont = new vcl::Font( maFont ); if ( nFlags & PushFlags::TEXTCOLOR ) pState->mpTextColor = new Color( GetTextColor() ); if (nFlags & PushFlags::TEXTFILLCOLOR && IsTextFillColor()) { pState->mpTextFillColor = new Color( GetTextFillColor() ); } if (nFlags & PushFlags::TEXTLINECOLOR && IsTextLineColor()) { pState->mpTextLineColor = new Color( GetTextLineColor() ); } if (nFlags & PushFlags::OVERLINECOLOR && IsOverlineColor()) { pState->mpOverlineColor = new Color( GetOverlineColor() ); } if ( nFlags & PushFlags::TEXTALIGN ) pState->meTextAlign = GetTextAlign(); if( nFlags & PushFlags::TEXTLAYOUTMODE ) pState->mnTextLayoutMode = GetLayoutMode(); if( nFlags & PushFlags::TEXTLANGUAGE ) pState->meTextLanguage = GetDigitLanguage(); if ( nFlags & PushFlags::RASTEROP ) pState->meRasterOp = GetRasterOp(); if ( nFlags & PushFlags::MAPMODE ) { pState->mpMapMode = new MapMode( maMapMode ); pState->mbMapActive = mbMap; } if (nFlags & PushFlags::CLIPREGION && mbClipRegion) { pState->mpClipRegion = new vcl::Region( maRegion ); } if (nFlags & PushFlags::REFPOINT && mbRefPoint) { pState->mpRefPoint = new Point( maRefPoint ); } mpOutDevStateStack->push_back( pState ); if( mpAlphaVDev ) mpAlphaVDev->Push(); } void OutputDevice::Pop() { if( mpMetaFile ) mpMetaFile->AddAction( new MetaPopAction() ); GDIMetaFile* pOldMetaFile = mpMetaFile; mpMetaFile = NULL; if ( mpOutDevStateStack->empty() ) { SAL_WARN( "vcl.gdi", "OutputDevice::Pop() without OutputDevice::Push()" ); return; } const OutDevState& rState = mpOutDevStateStack->back(); if( mpAlphaVDev ) mpAlphaVDev->Pop(); if ( rState.mnFlags & PushFlags::LINECOLOR ) { if ( rState.mpLineColor ) SetLineColor( *rState.mpLineColor ); else SetLineColor(); } if ( rState.mnFlags & PushFlags::FILLCOLOR ) { if ( rState.mpFillColor ) SetFillColor( *rState.mpFillColor ); else SetFillColor(); } if ( rState.mnFlags & PushFlags::FONT ) SetFont( *rState.mpFont ); if ( rState.mnFlags & PushFlags::TEXTCOLOR ) SetTextColor( *rState.mpTextColor ); if ( rState.mnFlags & PushFlags::TEXTFILLCOLOR ) { if ( rState.mpTextFillColor ) SetTextFillColor( *rState.mpTextFillColor ); else SetTextFillColor(); } if ( rState.mnFlags & PushFlags::TEXTLINECOLOR ) { if ( rState.mpTextLineColor ) SetTextLineColor( *rState.mpTextLineColor ); else SetTextLineColor(); } if ( rState.mnFlags & PushFlags::OVERLINECOLOR ) { if ( rState.mpOverlineColor ) SetOverlineColor( *rState.mpOverlineColor ); else SetOverlineColor(); } if ( rState.mnFlags & PushFlags::TEXTALIGN ) SetTextAlign( rState.meTextAlign ); if( rState.mnFlags & PushFlags::TEXTLAYOUTMODE ) SetLayoutMode( rState.mnTextLayoutMode ); if( rState.mnFlags & PushFlags::TEXTLANGUAGE ) SetDigitLanguage( rState.meTextLanguage ); if ( rState.mnFlags & PushFlags::RASTEROP ) SetRasterOp( rState.meRasterOp ); if ( rState.mnFlags & PushFlags::MAPMODE ) { if ( rState.mpMapMode ) SetMapMode( *rState.mpMapMode ); else SetMapMode(); mbMap = rState.mbMapActive; } if ( rState.mnFlags & PushFlags::CLIPREGION ) SetDeviceClipRegion( rState.mpClipRegion ); if ( rState.mnFlags & PushFlags::REFPOINT ) { if ( rState.mpRefPoint ) SetRefPoint( *rState.mpRefPoint ); else SetRefPoint(); } mpOutDevStateStack->pop_back(); mpMetaFile = pOldMetaFile; } sal_uInt32 OutputDevice::GetGCStackDepth() const { return mpOutDevStateStack->size(); } void OutputDevice::EnableOutput( bool bEnable ) { mbOutput = bEnable; if( mpAlphaVDev ) mpAlphaVDev->EnableOutput( bEnable ); } void OutputDevice::SetAntialiasing( AntialiasingFlags nMode ) { if ( mnAntialiasing != nMode ) { mnAntialiasing = nMode; mbInitFont = true; if(mpGraphics) { mpGraphics->setAntiAliasB2DDraw(bool(mnAntialiasing & AntialiasingFlags::EnableB2dDraw)); } } if( mpAlphaVDev ) mpAlphaVDev->SetAntialiasing( nMode ); } void OutputDevice::SetDrawMode( DrawModeFlags nDrawMode ) { mnDrawMode = nDrawMode; if( mpAlphaVDev ) mpAlphaVDev->SetDrawMode( nDrawMode ); } void OutputDevice::SetLayoutMode( ComplexTextLayoutMode nTextLayoutMode ) { if( mpMetaFile ) mpMetaFile->AddAction( new MetaLayoutModeAction( nTextLayoutMode ) ); mnTextLayoutMode = nTextLayoutMode; if( mpAlphaVDev ) mpAlphaVDev->SetLayoutMode( nTextLayoutMode ); } void OutputDevice::SetDigitLanguage( LanguageType eTextLanguage ) { if( mpMetaFile ) mpMetaFile->AddAction( new MetaTextLanguageAction( eTextLanguage ) ); meTextLanguage = eTextLanguage; if( mpAlphaVDev ) mpAlphaVDev->SetDigitLanguage( eTextLanguage ); } void OutputDevice::SetRasterOp( RasterOp eRasterOp ) { if ( mpMetaFile ) mpMetaFile->AddAction( new MetaRasterOpAction( eRasterOp ) ); if ( meRasterOp != eRasterOp ) { meRasterOp = eRasterOp; mbInitLineColor = mbInitFillColor = true; if( mpGraphics || AcquireGraphics() ) mpGraphics->SetXORMode( (ROP_INVERT == meRasterOp) || (ROP_XOR == meRasterOp), ROP_INVERT == meRasterOp ); } if( mpAlphaVDev ) mpAlphaVDev->SetRasterOp( eRasterOp ); } void OutputDevice::SetFillColor() { if ( mpMetaFile ) mpMetaFile->AddAction( new MetaFillColorAction( Color(), false ) ); if ( mbFillColor ) { mbInitFillColor = true; mbFillColor = false; maFillColor = Color( COL_TRANSPARENT ); } if( mpAlphaVDev ) mpAlphaVDev->SetFillColor(); } void OutputDevice::SetFillColor( const Color& rColor ) { Color aColor( rColor ); if( mnDrawMode & ( DrawModeFlags::BlackFill | DrawModeFlags::WhiteFill | DrawModeFlags::GrayFill | DrawModeFlags::NoFill | DrawModeFlags::GhostedFill | DrawModeFlags::SettingsFill ) ) { if( !ImplIsColorTransparent( aColor ) ) { if( mnDrawMode & DrawModeFlags::BlackFill ) { aColor = Color( COL_BLACK ); } else if( mnDrawMode & DrawModeFlags::WhiteFill ) { aColor = Color( COL_WHITE ); } else if( mnDrawMode & DrawModeFlags::GrayFill ) { const sal_uInt8 cLum = aColor.GetLuminance(); aColor = Color( cLum, cLum, cLum ); } else if( mnDrawMode & DrawModeFlags::NoFill ) { aColor = Color( COL_TRANSPARENT ); } else if( mnDrawMode & DrawModeFlags::SettingsFill ) { aColor = GetSettings().GetStyleSettings().GetWindowColor(); } if( mnDrawMode & DrawModeFlags::GhostedFill ) { aColor = Color( (aColor.GetRed() >> 1) | 0x80, (aColor.GetGreen() >> 1) | 0x80, (aColor.GetBlue() >> 1) | 0x80); } } } if ( mpMetaFile ) mpMetaFile->AddAction( new MetaFillColorAction( aColor, true ) ); if ( ImplIsColorTransparent( aColor ) ) { if ( mbFillColor ) { mbInitFillColor = true; mbFillColor = false; maFillColor = Color( COL_TRANSPARENT ); } } else { if ( maFillColor != aColor ) { mbInitFillColor = true; mbFillColor = true; maFillColor = aColor; } } if( mpAlphaVDev ) mpAlphaVDev->SetFillColor( COL_BLACK ); } void OutputDevice::SetLineColor() { if ( mpMetaFile ) mpMetaFile->AddAction( new MetaLineColorAction( Color(), false ) ); if ( mbLineColor ) { mbInitLineColor = true; mbLineColor = false; maLineColor = Color( COL_TRANSPARENT ); } if( mpAlphaVDev ) mpAlphaVDev->SetLineColor(); } void OutputDevice::SetLineColor( const Color& rColor ) { Color aColor = ImplDrawModeToColor( rColor ); if( mpMetaFile ) mpMetaFile->AddAction( new MetaLineColorAction( aColor, true ) ); if( ImplIsColorTransparent( aColor ) ) { if ( mbLineColor ) { mbInitLineColor = true; mbLineColor = false; maLineColor = Color( COL_TRANSPARENT ); } } else { if( maLineColor != aColor ) { mbInitLineColor = true; mbLineColor = true; maLineColor = aColor; } } if( mpAlphaVDev ) mpAlphaVDev->SetLineColor( COL_BLACK ); } void OutputDevice::SetBackground() { maBackground = Wallpaper(); mbBackground = false; if( mpAlphaVDev ) mpAlphaVDev->SetBackground(); } void OutputDevice::SetBackground( const Wallpaper& rBackground ) { maBackground = rBackground; if( rBackground.GetStyle() == WallpaperStyle::NONE ) mbBackground = false; else mbBackground = true; if( mpAlphaVDev ) mpAlphaVDev->SetBackground( rBackground ); } void OutputDevice::SetFont( const vcl::Font& rNewFont ) { vcl::Font aFont( rNewFont ); aFont.SetLanguage(rNewFont.GetLanguage()); if ( mnDrawMode & (DrawModeFlags::BlackText | DrawModeFlags::WhiteText | DrawModeFlags::GrayText | DrawModeFlags::GhostedText | DrawModeFlags::SettingsText | DrawModeFlags::BlackFill | DrawModeFlags::WhiteFill | DrawModeFlags::GrayFill | DrawModeFlags::NoFill | DrawModeFlags::GhostedFill | DrawModeFlags::SettingsFill ) ) { Color aTextColor( aFont.GetColor() ); if ( mnDrawMode & DrawModeFlags::BlackText ) aTextColor = Color( COL_BLACK ); else if ( mnDrawMode & DrawModeFlags::WhiteText ) aTextColor = Color( COL_WHITE ); else if ( mnDrawMode & DrawModeFlags::GrayText ) { const sal_uInt8 cLum = aTextColor.GetLuminance(); aTextColor = Color( cLum, cLum, cLum ); } else if ( mnDrawMode & DrawModeFlags::SettingsText ) aTextColor = GetSettings().GetStyleSettings().GetFontColor(); if ( mnDrawMode & DrawModeFlags::GhostedText ) { aTextColor = Color( (aTextColor.GetRed() >> 1 ) | 0x80, (aTextColor.GetGreen() >> 1 ) | 0x80, (aTextColor.GetBlue() >> 1 ) | 0x80 ); } aFont.SetColor( aTextColor ); bool bTransFill = aFont.IsTransparent(); if ( !bTransFill ) { Color aTextFillColor( aFont.GetFillColor() ); if ( mnDrawMode & DrawModeFlags::BlackFill ) aTextFillColor = Color( COL_BLACK ); else if ( mnDrawMode & DrawModeFlags::WhiteFill ) aTextFillColor = Color( COL_WHITE ); else if ( mnDrawMode & DrawModeFlags::GrayFill ) { const sal_uInt8 cLum = aTextFillColor.GetLuminance(); aTextFillColor = Color( cLum, cLum, cLum ); } else if( mnDrawMode & DrawModeFlags::SettingsFill ) aTextFillColor = GetSettings().GetStyleSettings().GetWindowColor(); else if ( mnDrawMode & DrawModeFlags::NoFill ) { aTextFillColor = Color( COL_TRANSPARENT ); bTransFill = true; } if ( !bTransFill && (mnDrawMode & DrawModeFlags::GhostedFill) ) { aTextFillColor = Color( (aTextFillColor.GetRed() >> 1) | 0x80, (aTextFillColor.GetGreen() >> 1) | 0x80, (aTextFillColor.GetBlue() >> 1) | 0x80 ); } aFont.SetFillColor( aTextFillColor ); } } if ( mpMetaFile ) { mpMetaFile->AddAction( new MetaFontAction( aFont ) ); // the color and alignment actions don't belong here // TODO: get rid of them without breaking anything... mpMetaFile->AddAction( new MetaTextAlignAction( aFont.GetAlign() ) ); mpMetaFile->AddAction( new MetaTextFillColorAction( aFont.GetFillColor(), !aFont.IsTransparent() ) ); } if ( !maFont.IsSameInstance( aFont ) ) { // Optimization MT/HDU: COL_TRANSPARENT means SetFont should ignore the font color, // because SetTextColor() is used for this. // #i28759# maTextColor might have been changed behind our back, commit then, too. if( aFont.GetColor() != COL_TRANSPARENT && (aFont.GetColor() != maFont.GetColor() || aFont.GetColor() != maTextColor ) ) { maTextColor = aFont.GetColor(); mbInitTextColor = true; if( mpMetaFile ) mpMetaFile->AddAction( new MetaTextColorAction( aFont.GetColor() ) ); } maFont = aFont; mbNewFont = true; if( mpAlphaVDev ) { // #i30463# // Since SetFont might change the text color, apply that only // selectively to alpha vdev (which normally paints opaque text // with COL_BLACK) if( aFont.GetColor() != COL_TRANSPARENT ) { mpAlphaVDev->SetTextColor( COL_BLACK ); aFont.SetColor( COL_TRANSPARENT ); } mpAlphaVDev->SetFont( aFont ); } } } void OutputDevice::InitLineColor() { DBG_TESTSOLARMUTEX(); if( mbLineColor ) { if( ROP_0 == meRasterOp ) mpGraphics->SetROPLineColor( SAL_ROP_0 ); else if( ROP_1 == meRasterOp ) mpGraphics->SetROPLineColor( SAL_ROP_1 ); else if( ROP_INVERT == meRasterOp ) mpGraphics->SetROPLineColor( SAL_ROP_INVERT ); else mpGraphics->SetLineColor( ImplColorToSal( maLineColor ) ); } else mpGraphics->SetLineColor(); mbInitLineColor = false; } void OutputDevice::InitFillColor() { DBG_TESTSOLARMUTEX(); if( mbFillColor ) { if( ROP_0 == meRasterOp ) mpGraphics->SetROPFillColor( SAL_ROP_0 ); else if( ROP_1 == meRasterOp ) mpGraphics->SetROPFillColor( SAL_ROP_1 ); else if( ROP_INVERT == meRasterOp ) mpGraphics->SetROPFillColor( SAL_ROP_INVERT ); else mpGraphics->SetFillColor( ImplColorToSal( maFillColor ) ); } else mpGraphics->SetFillColor(); mbInitFillColor = false; } void OutputDevice::ImplReleaseFonts() { mpGraphics->ReleaseFonts(); mbNewFont = true; mbInitFont = true; if ( mpFontEntry ) { mpFontCache->Release( mpFontEntry ); mpFontEntry = NULL; } if ( mpGetDevFontList ) { delete mpGetDevFontList; mpGetDevFontList = NULL; } if ( mpGetDevSizeList ) { delete mpGetDevSizeList; mpGetDevSizeList = NULL; } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */