diff options
Diffstat (limited to 'vcl/unx')
40 files changed, 897 insertions, 418 deletions
diff --git a/vcl/unx/gtk/a11y/atktext.cxx b/vcl/unx/gtk/a11y/atktext.cxx index 8d83ca008e4a..0a97e5ba1ca6 100644 --- a/vcl/unx/gtk/a11y/atktext.cxx +++ b/vcl/unx/gtk/a11y/atktext.cxx @@ -187,8 +187,16 @@ static accessibility::XAccessibleTextMarkup* if( !pWrap->mpTextMarkup && pWrap->mpContext ) { uno::Any any = pWrap->mpContext->queryInterface( accessibility::XAccessibleTextMarkup::static_type(NULL) ); - pWrap->mpTextMarkup = reinterpret_cast< accessibility::XAccessibleTextMarkup * > (any.pReserved); - pWrap->mpTextMarkup->acquire(); + /* Since this not a dedicated interface in Atk and thus has not + * been queried during wrapper initialization, we need to check + * the return value here. + */ + if( typelib_TypeClass_INTERFACE == any.pType->eTypeClass ) + { + pWrap->mpTextMarkup = reinterpret_cast< accessibility::XAccessibleTextMarkup * > (any.pReserved); + if( pWrap->mpTextMarkup ) + pWrap->mpTextMarkup->acquire(); + } } return pWrap->mpTextMarkup; diff --git a/vcl/unx/gtk/a11y/atkutil.cxx b/vcl/unx/gtk/a11y/atkutil.cxx index 5206c8ce87ca..c92a69d3fb49 100644 --- a/vcl/unx/gtk/a11y/atkutil.cxx +++ b/vcl/unx/gtk/a11y/atkutil.cxx @@ -221,7 +221,7 @@ void DocumentFocusListener::notifyEvent( const accessibility::AccessibleEventObj if( accessibility::AccessibleStateType::FOCUSED == nState ) atk_wrapper_focus_tracker_notify_when_idle( getAccessible(aEvent) ); } - catch(lang::IndexOutOfBoundsException e) + catch(const lang::IndexOutOfBoundsException &e) { g_warning("Focused object has invalid index in parent"); } @@ -577,7 +577,14 @@ static void handle_get_focus(::VclWindowEvent const * pEvent) if( g_aWindowList.find(pWindow) == g_aWindowList.end() ) { g_aWindowList.insert(pWindow); - aDocumentFocusListener->attachRecursive(xAccessible, xContext, xStateSet); + try + { + aDocumentFocusListener->attachRecursive(xAccessible, xContext, xStateSet); + } + catch( const uno::Exception &e ) + { + g_warning( "Exception caught processing focus events" ); + } } #ifdef ENABLE_TRACING else @@ -608,7 +615,7 @@ static void handle_menu_highlighted(::VclMenuEvent const * pEvent) } } } - catch( uno::Exception e ) + catch( const uno::Exception& e ) { g_warning( "Exception caught processing menu highlight events" ); } diff --git a/vcl/unx/gtk/gdi/salnativewidgets-gtk.cxx b/vcl/unx/gtk/gdi/salnativewidgets-gtk.cxx index f922552ce923..654f39c51a92 100644 --- a/vcl/unx/gtk/gdi/salnativewidgets-gtk.cxx +++ b/vcl/unx/gtk/gdi/salnativewidgets-gtk.cxx @@ -1091,6 +1091,19 @@ BOOL GtkSalGraphics::getNativeControlRegion( ControlType nType, rNativeContentRegion = Region( aIndicatorRect ); returnVal = TRUE; } + if( (nType == CTRL_EDITBOX || nType == CTRL_SPINBOX) && nPart == PART_ENTIRE_CONTROL ) + { + NWEnsureGTKEditBox( m_nScreen ); + GtkWidget* widget = gWidgetData[m_nScreen].gEditBoxWidget; + GtkRequisition aReq; + gtk_widget_size_request( widget, &aReq ); + Rectangle aEditRect = rControlRegion.GetBoundRect(); + aEditRect = Rectangle( aEditRect.TopLeft(), + Size( aEditRect.GetWidth(), aReq.height+1 ) ); + rNativeBoundingRegion = Region( aEditRect ); + rNativeContentRegion = rNativeBoundingRegion; + returnVal = TRUE; + } return( returnVal ); } diff --git a/vcl/unx/gtk/window/gtkframe.cxx b/vcl/unx/gtk/window/gtkframe.cxx index eff7319d6efc..92ff2d3b8d8e 100644 --- a/vcl/unx/gtk/window/gtkframe.cxx +++ b/vcl/unx/gtk/window/gtkframe.cxx @@ -772,7 +772,10 @@ void GtkSalFrame::Init( SalFrame* pParent, ULONG nStyle ) m_aForeignTopLevelWindow = None; m_nStyle = nStyle; - GtkWindowType eWinType = ((nStyle & SAL_FRAME_STYLE_FLOAT) && ! (nStyle & SAL_FRAME_STYLE_OWNERDRAWDECORATION)) + GtkWindowType eWinType = ( (nStyle & SAL_FRAME_STYLE_FLOAT) && + ! (nStyle & (SAL_FRAME_STYLE_OWNERDRAWDECORATION| + SAL_FRAME_STYLE_FLOAT_FOCUSABLE)) + ) ? GTK_WINDOW_POPUP : GTK_WINDOW_TOPLEVEL; if( nStyle & SAL_FRAME_STYLE_SYSTEMCHILD ) @@ -801,7 +804,7 @@ void GtkSalFrame::Init( SalFrame* pParent, ULONG nStyle ) bool bDecoHandling = ! isChild() && ( ! (nStyle & SAL_FRAME_STYLE_FLOAT) || - (nStyle & SAL_FRAME_STYLE_OWNERDRAWDECORATION) ); + (nStyle & (SAL_FRAME_STYLE_OWNERDRAWDECORATION|SAL_FRAME_STYLE_FLOAT_FOCUSABLE) ) ); /* #i100116# metacity has a peculiar behavior regarding WM_HINT accept focus and _NET_WM_USER_TIME at some point that may be fixed in metacity and we will have to revisit this @@ -832,6 +835,11 @@ void GtkSalFrame::Init( SalFrame* pParent, ULONG nStyle ) lcl_set_accept_focus( GTK_WINDOW(m_pWindow), FALSE, true ); bNoDecor = true; } + else if( (nStyle & SAL_FRAME_STYLE_FLOAT_FOCUSABLE) ) + { + eType = GDK_WINDOW_TYPE_HINT_UTILITY; + } + if( (nStyle & SAL_FRAME_STYLE_PARTIAL_FULLSCREEN ) ) { eType = GDK_WINDOW_TYPE_HINT_TOOLBAR; @@ -869,7 +877,7 @@ void GtkSalFrame::Init( SalFrame* pParent, ULONG nStyle ) if( bDecoHandling ) { gtk_window_set_resizable( GTK_WINDOW(m_pWindow), (nStyle & SAL_FRAME_STYLE_SIZEABLE) ? TRUE : FALSE ); - if( ( (nStyle & SAL_FRAME_STYLE_OWNERDRAWDECORATION) ) || bMetaCityToolWindowHack ) + if( ( (nStyle & (SAL_FRAME_STYLE_OWNERDRAWDECORATION)) ) || bMetaCityToolWindowHack ) lcl_set_accept_focus( GTK_WINDOW(m_pWindow), FALSE, false ); } @@ -2075,7 +2083,7 @@ void GtkSalFrame::ToTop( USHORT nFlags ) * to our window - which it of course won't since our input hint * is set to false. */ - if( (m_nStyle & SAL_FRAME_STYLE_OWNERDRAWDECORATION) ) + if( (m_nStyle & (SAL_FRAME_STYLE_OWNERDRAWDECORATION|SAL_FRAME_STYLE_FLOAT_FOCUSABLE)) ) XSetInputFocus( getDisplay()->GetDisplay(), GDK_WINDOW_XWINDOW( m_pWindow->window ), RevertToParent, CurrentTime ); } else @@ -2369,6 +2377,11 @@ void GtkSalFrame::createNewWindow( XLIB_Window aNewParent, bool bXEmbed, int nSc } } + // free xrender resources + for( unsigned int i = 0; i < sizeof(m_aGraphics)/sizeof(m_aGraphics[0]); i++ ) + if( m_aGraphics[i].bInUse ) + m_aGraphics[i].pGraphics->SetDrawable( None, m_nScreen ); + // first deinit frame if( m_pIMHandler ) { diff --git a/vcl/unx/headless/svpprn.cxx b/vcl/unx/headless/svpprn.cxx index 1882b50e6ad7..75d86959b2b5 100644 --- a/vcl/unx/headless/svpprn.cxx +++ b/vcl/unx/headless/svpprn.cxx @@ -123,6 +123,32 @@ static void copyJobDataToJobSetup( ImplJobSetup* pJobSetup, JobData& rData ) pJobSetup->mnPaperBin = 0xffff; } + // copy duplex + pKey = NULL; + pValue = NULL; + + pJobSetup->meDuplexMode = DUPLEX_UNKNOWN; + if( rData.m_pParser ) + pKey = rData.m_pParser->getKey( String( RTL_CONSTASCII_USTRINGPARAM( "Duplex" ) ) ); + if( pKey ) + pValue = rData.m_aContext.getValue( pKey ); + if( pKey && pValue ) + { + if( pValue->m_aOption.EqualsIgnoreCaseAscii( "None" ) || + pValue->m_aOption.EqualsIgnoreCaseAscii( "Simplex", 0, 7 ) + ) + { + pJobSetup->meDuplexMode = DUPLEX_OFF; + } + else if( pValue->m_aOption.EqualsIgnoreCaseAscii( "DuplexNoTumble" ) ) + { + pJobSetup->meDuplexMode = DUPLEX_LONGEDGE; + } + else if( pValue->m_aOption.EqualsIgnoreCaseAscii( "DuplexTumble" ) ) + { + pJobSetup->meDuplexMode = DUPLEX_SHORTEDGE; + } + } // copy the whole context if( pJobSetup->mpDriverData ) @@ -455,34 +481,6 @@ void PspSalInfoPrinter::InitPaperFormats( const ImplJobSetup* ) // ----------------------------------------------------------------------- -DuplexMode PspSalInfoPrinter::GetDuplexMode( const ImplJobSetup* pJobSetup ) -{ - DuplexMode aRet = DUPLEX_UNKNOWN; - PrinterInfo aInfo( PrinterInfoManager::get().getPrinterInfo( pJobSetup->maPrinterName ) ); - if ( pJobSetup->mpDriverData ) - JobData::constructFromStreamBuffer( pJobSetup->mpDriverData, pJobSetup->mnDriverDataLen, aInfo ); - if( aInfo.m_pParser ) - { - const PPDKey * pKey = aInfo.m_pParser->getKey( String( RTL_CONSTASCII_USTRINGPARAM( "Duplex" ) ) ); - if( pKey ) - { - const PPDValue* pVal = aInfo.m_aContext.getValue( pKey ); - if( pVal && ( - pVal->m_aOption.EqualsIgnoreCaseAscii( "None" ) || - pVal->m_aOption.EqualsIgnoreCaseAscii( "Simplex", 0, 7 ) - ) ) - { - aRet = DUPLEX_OFF; - } - else - aRet = DUPLEX_ON; - } - } - return aRet; -} - -// ----------------------------------------------------------------------- - int PspSalInfoPrinter::GetLandscapeAngle( const ImplJobSetup* ) { return 900; @@ -624,6 +622,37 @@ BOOL PspSalInfoPrinter::SetData( if( nSetDataFlags & SAL_JOBSET_ORIENTATION ) aData.m_eOrientation = pJobSetup->meOrientation == ORIENTATION_LANDSCAPE ? orientation::Landscape : orientation::Portrait; + // merge duplex if necessary + if( nSetDataFlags & SAL_JOBSET_DUPLEXMODE ) + { + pKey = aData.m_pParser->getKey( String( RTL_CONSTASCII_USTRINGPARAM( "Duplex" ) ) ); + if( pKey ) + { + pValue = NULL; + switch( pJobSetup->meDuplexMode ) + { + case DUPLEX_OFF: + pValue = pKey->getValue( String( RTL_CONSTASCII_USTRINGPARAM( "None" ) ) ); + if( pValue == NULL ) + pValue = pKey->getValue( String( RTL_CONSTASCII_USTRINGPARAM( "SimplexNoTumble" ) ) ); + break; + case DUPLEX_SHORTEDGE: + pValue = pKey->getValue( String( RTL_CONSTASCII_USTRINGPARAM( "DuplexTumble" ) ) ); + break; + case DUPLEX_LONGEDGE: + pValue = pKey->getValue( String( RTL_CONSTASCII_USTRINGPARAM( "DuplexNoTumble" ) ) ); + break; + case DUPLEX_UNKNOWN: + default: + pValue = 0; + break; + } + if( ! pValue ) + pValue = pKey->getDefaultValue(); + aData.m_aContext.setValue( pKey, pValue ); + } + } + m_aJobData = aData; copyJobDataToJobSetup( pJobSetup, aData ); return TRUE; @@ -725,9 +754,22 @@ ULONG PspSalInfoPrinter::GetCapabilities( const ImplJobSetup* pJobSetup, USHORT case PRINTER_CAPABILITIES_COPIES: return 0xffff; case PRINTER_CAPABILITIES_COLLATECOPIES: - return 0; + { + // see if the PPD contains a value to set Collate to True + JobData aData; + JobData::constructFromStreamBuffer( pJobSetup->mpDriverData, pJobSetup->mnDriverDataLen, aData ); + + const PPDKey* pKey = aData.m_pParser ? aData.m_pParser->getKey( String( RTL_CONSTASCII_USTRINGPARAM( "Collate" ) ) ) : NULL; + const PPDValue* pVal = pKey ? pKey->getValue( String( RTL_CONSTASCII_USTRINGPARAM( "True" ) ) ) : NULL; + + // PPDs don't mention the number of possible collated copies. + // so let's guess as many as we want ? + return pVal ? 0xffff : 0; + } case PRINTER_CAPABILITIES_SETORIENTATION: return 1; + case PRINTER_CAPABILITIES_SETDUPLEX: + return 1; case PRINTER_CAPABILITIES_SETPAPERBIN: return 1; case PRINTER_CAPABILITIES_SETPAPERSIZE: @@ -777,6 +819,7 @@ PspSalPrinter::PspSalPrinter( SalInfoPrinter* pInfoPrinter ) m_bSwallowFaxNo( false ), m_pGraphics( NULL ), m_nCopies( 1 ), + m_bCollate( false ), m_pInfoPrinter( pInfoPrinter ) { } @@ -802,7 +845,9 @@ BOOL PspSalPrinter::StartJob( const XubString* pFileName, const XubString& rJobName, const XubString& rAppName, - ULONG nCopies, BOOL /*bCollate*/, + ULONG nCopies, + bool bCollate, + bool /*bDirect*/, ImplJobSetup* pJobSetup ) { vcl_sal::PrinterUpdate::jobStarted(); @@ -811,13 +856,17 @@ BOOL PspSalPrinter::StartJob( m_bPdf = false; m_aFileName = pFileName ? *pFileName : String(); m_aTmpFile = String(); - m_nCopies = nCopies; + m_nCopies = nCopies; + m_bCollate = bCollate; JobData::constructFromStreamBuffer( pJobSetup->mpDriverData, pJobSetup->mnDriverDataLen, m_aJobData ); if( m_nCopies > 1 ) + { // in case user did not do anything (m_nCopies=1) // take the default from jobsetup m_aJobData.m_nCopies = m_nCopies; + m_aJobData.setCollate( bCollate ); + } // check wether this printer is configured as fax int nMode = 0; @@ -917,9 +966,12 @@ SalGraphics* PspSalPrinter::StartPage( ImplJobSetup* pJobSetup, BOOL ) m_pGraphics = new PspGraphics( &m_aJobData, &m_aPrinterGfx, m_bFax ? &m_aFaxNr : NULL, m_bSwallowFaxNo, m_pInfoPrinter ); m_pGraphics->SetLayout( 0 ); if( m_nCopies > 1 ) + { // in case user did not do anything (m_nCopies=1) // take the default from jobsetup m_aJobData.m_nCopies = m_nCopies; + m_aJobData.setCollate( m_nCopies > 1 && m_bCollate ); + } m_aPrintJob.StartPage( m_aJobData ); m_aPrinterGfx.Init( m_aPrintJob ); diff --git a/vcl/unx/headless/svpprn.hxx b/vcl/unx/headless/svpprn.hxx index c2d85c054fce..8f5a47fed118 100644 --- a/vcl/unx/headless/svpprn.hxx +++ b/vcl/unx/headless/svpprn.hxx @@ -63,7 +63,6 @@ public: virtual String GetPaperBinName( const ImplJobSetup* pSetupData, ULONG nPaperBin ); virtual void InitPaperFormats( const ImplJobSetup* pSetupData ); virtual int GetLandscapeAngle( const ImplJobSetup* pSetupData ); - virtual DuplexMode GetDuplexMode( const ImplJobSetup* pSetupData ); }; class PspSalPrinter : public SalPrinter @@ -80,6 +79,7 @@ public: psp::JobData m_aJobData; psp::PrinterGfx m_aPrinterGfx; ULONG m_nCopies; + bool m_bCollate; SalInfoPrinter* m_pInfoPrinter; PspSalPrinter( SalInfoPrinter* ); @@ -90,7 +90,9 @@ public: virtual BOOL StartJob( const XubString* pFileName, const XubString& rJobName, const XubString& rAppName, - ULONG nCopies, BOOL bCollate, + ULONG nCopies, + bool bCollate, + bool bDirect, ImplJobSetup* pSetupData ); virtual BOOL EndJob(); virtual BOOL AbortJob(); diff --git a/vcl/unx/headless/svppspgraphics.cxx b/vcl/unx/headless/svppspgraphics.cxx index 3e9d67bcbbe9..1311aaed4ee4 100644 --- a/vcl/unx/headless/svppspgraphics.cxx +++ b/vcl/unx/headless/svppspgraphics.cxx @@ -986,13 +986,6 @@ const void* PspGraphics::DoGetEmbedFontData( fontID aFont, const sal_Ucs* pUnico return NULL; // fill in font info - switch( aFontInfo.m_eType ) - { - case psp::fonttype::TrueType: rInfo.m_nFontType = FontSubsetInfo::SFNT_TTF; break; - case psp::fonttype::Type1: rInfo.m_nFontType = FontSubsetInfo::ANY_TYPE1; break; - default: - return NULL; - } rInfo.m_nAscent = aFontInfo.m_nAscend; rInfo.m_nDescent = aFontInfo.m_nDescend; rInfo.m_aPSName = rMgr.getPSName( aFont ); @@ -1029,9 +1022,22 @@ const void* PspGraphics::DoGetEmbedFontData( fontID aFont, const sal_Ucs* pUnico rInfo.m_nCapHeight = yMax; // Well ... for( int i = 0; i < 256; i++ ) - pWidths[i] = (aMetrics[i].width > 0 ? aMetrics[i].width : 0); + switch( aFontInfo.m_eType ) + { + case psp::fonttype::TrueType: + rInfo.m_nFontType = FontSubsetInfo::SFNT_TTF; + break; + case psp::fonttype::Type1: { + const bool bPFA = ((*(unsigned char*)pFile) < 0x80); + rInfo.m_nFontType = bPFA ? FontSubsetInfo::TYPE1_PFA : FontSubsetInfo::TYPE1_PFB; + } + break; + default: + return NULL; + } + return pFile; } diff --git a/vcl/unx/inc/kde_headers.h b/vcl/unx/inc/kde_headers.h deleted file mode 100644 index ccbffc99cb99..000000000000 --- a/vcl/unx/inc/kde_headers.h +++ /dev/null @@ -1,97 +0,0 @@ -/************************************************************************* - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright 2008 by Sun Microsystems, Inc. - * - * OpenOffice.org - a multi-platform office productivity suite - * - * $RCSfile: kde_headers.h,v $ - * $Revision: 1.6 $ - * - * 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. - * - ************************************************************************/ - -#ifndef INCLUDED_VCL_KDE_HEADERS_H -#define INCLUDED_VCL_KDE_HEADERS_H - -/* ********* Suppress warnings if needed */ -#include "sal/config.h" - -#if defined __GNUC__ -#pragma GCC system_header -#endif - - -/* ********* Hack, but needed because of conflicting types... */ -#define Region QtXRegion - - -/* ********* Qt headers */ -#include <qaccessible.h> -#include <qcheckbox.h> -#include <qcombobox.h> -#include <qfont.h> -#include <qframe.h> -#include <qlineedit.h> -#include <qlistview.h> -#include <qmainwindow.h> -#include <qmenudata.h> -#include <qpaintdevice.h> -#include <qpainter.h> -#include <qpushbutton.h> -#include <qradiobutton.h> -#include <qrangecontrol.h> -#include <qstring.h> -#include <qtabbar.h> -#include <qtabwidget.h> -#include <qtoolbar.h> -#include <qtoolbutton.h> -#include <qwidget.h> -#include <qprogressbar.h> - -/* ********* See hack on top of this file */ -#undef Region - - -/* ********* KDE base headers */ -#include <kaboutdata.h> -#include <kapplication.h> -#include <kcmdlineargs.h> -#include <kconfig.h> -#include <kdeversion.h> -#include <kemailsettings.h> -#include <kglobal.h> -#include <kglobalsettings.h> -#include <klocale.h> -#include <kmainwindow.h> -#include <kmenubar.h> -#include <kprotocolmanager.h> -#include <kstartupinfo.h> -#include <kstyle.h> - - -/* ********* KDE address book connectivity headers */ -#include <kabc/addressbook.h> -#include <kabc/addressee.h> -#include <kabc/field.h> -#include <kabc/stdaddressbook.h> - - -#endif diff --git a/vcl/unx/inc/plugins/gtk/gtkframe.hxx b/vcl/unx/inc/plugins/gtk/gtkframe.hxx index a8fc6f65d4ee..c2a147517ac8 100644 --- a/vcl/unx/inc/plugins/gtk/gtkframe.hxx +++ b/vcl/unx/inc/plugins/gtk/gtkframe.hxx @@ -242,9 +242,10 @@ class GtkSalFrame : public SalFrame bool isFloatGrabWindow() const { return - (m_nStyle & SAL_FRAME_STYLE_FLOAT) && // only a float can be floatgrab - !(m_nStyle & SAL_FRAME_STYLE_TOOLTIP) && // tool tips are not - !(m_nStyle & SAL_FRAME_STYLE_OWNERDRAWDECORATION); // toolbars are also not + (m_nStyle & SAL_FRAME_STYLE_FLOAT) && // only a float can be floatgrab + !(m_nStyle & SAL_FRAME_STYLE_TOOLTIP) && // tool tips are not + !(m_nStyle & SAL_FRAME_STYLE_OWNERDRAWDECORATION) && // toolbars are also not + !(m_nStyle & SAL_FRAME_STYLE_FLOAT_FOCUSABLE); // focusable floats are not } bool isChild( bool bPlug = true, bool bSysChild = true ) diff --git a/vcl/unx/inc/plugins/kde/kdedata.hxx b/vcl/unx/inc/plugins/kde/kdedata.hxx index 831621e38cc1..04730b39fad2 100644 --- a/vcl/unx/inc/plugins/kde/kdedata.hxx +++ b/vcl/unx/inc/plugins/kde/kdedata.hxx @@ -75,7 +75,7 @@ public: virtual SalGraphics* GetGraphics(); virtual void ReleaseGraphics( SalGraphics *pGraphics ); - virtual void updateGraphics(); + virtual void updateGraphics( bool bClear ); virtual void UpdateSettings( AllSettings& rSettings ); virtual void Show( BOOL bVisible, BOOL bNoActivate ); }; diff --git a/vcl/unx/inc/salframe.h b/vcl/unx/inc/salframe.h index 848f2250d31c..8dad0350a937 100644 --- a/vcl/unx/inc/salframe.h +++ b/vcl/unx/inc/salframe.h @@ -212,7 +212,9 @@ public: virtual SalGraphics* GetGraphics(); virtual void ReleaseGraphics( SalGraphics* pGraphics ); - virtual void updateGraphics(); + // call with true to clear graphics (setting None as drawable) + // call with false to setup graphics with window (GetWindow()) + virtual void updateGraphics( bool bClear ); virtual BOOL PostEvent( void* pData ); diff --git a/vcl/unx/inc/salprn.h b/vcl/unx/inc/salprn.h index 452fa5a89387..59a5c3eef56a 100644 --- a/vcl/unx/inc/salprn.h +++ b/vcl/unx/inc/salprn.h @@ -63,7 +63,6 @@ public: virtual String GetPaperBinName( const ImplJobSetup* pSetupData, ULONG nPaperBin ); virtual void InitPaperFormats( const ImplJobSetup* pSetupData ); virtual int GetLandscapeAngle( const ImplJobSetup* pSetupData ); - virtual DuplexMode GetDuplexMode( const ImplJobSetup* pSetupData ); }; class PspSalPrinter : public SalPrinter @@ -80,6 +79,7 @@ public: psp::JobData m_aJobData; psp::PrinterGfx m_aPrinterGfx; ULONG m_nCopies; + bool m_bCollate; SalInfoPrinter* m_pInfoPrinter; PspSalPrinter( SalInfoPrinter* ); @@ -90,7 +90,9 @@ public: virtual BOOL StartJob( const XubString* pFileName, const XubString& rJobName, const XubString& rAppName, - ULONG nCopies, BOOL bCollate, + ULONG nCopies, + bool bCollate, + bool bDirect, ImplJobSetup* pSetupData ); virtual BOOL EndJob(); virtual BOOL AbortJob(); diff --git a/vcl/unx/inc/salunx.h b/vcl/unx/inc/salunx.h index cdf45fd30867..c1fee6c68d94 100644 --- a/vcl/unx/inc/salunx.h +++ b/vcl/unx/inc/salunx.h @@ -38,12 +38,6 @@ #include <time.h> #include <sys/time.h> #include <strings.h> -#elif defined IRIX -#ifdef __cplusplus -#include <ctime> -#endif -#include <sys/time.h> -#include <unistd.h> #endif #include <svunx.h> #include <salstd.hxx> diff --git a/vcl/unx/inc/sm.hxx b/vcl/unx/inc/sm.hxx index 17bb40e2106a..09d2f5557e1d 100644 --- a/vcl/unx/inc/sm.hxx +++ b/vcl/unx/inc/sm.hxx @@ -69,7 +69,7 @@ public: static bool checkDocumentsSaved(); static bool queryInteraction(); static void saveDone(); - static void interactionDone(); + static void interactionDone( bool bCancelShutdown ); static String getExecName(); static VCL_DLLPUBLIC const ByteString& getSessionID(); diff --git a/vcl/unx/kde/kdedata.cxx b/vcl/unx/kde/kdedata.cxx index 1b5a2f86dcee..9da57b6e790d 100644 --- a/vcl/unx/kde/kdedata.cxx +++ b/vcl/unx/kde/kdedata.cxx @@ -29,7 +29,7 @@ #include "precompiled_vcl.hxx" #define _SV_SALDATA_CXX -#include "kde_headers.h" +#include <shell/kde_headers.h> #include <unistd.h> #include <fcntl.h> diff --git a/vcl/unx/kde/salnativewidgets-kde.cxx b/vcl/unx/kde/salnativewidgets-kde.cxx index 8046d22d75d3..cd461fc36c8f 100644 --- a/vcl/unx/kde/salnativewidgets-kde.cxx +++ b/vcl/unx/kde/salnativewidgets-kde.cxx @@ -32,7 +32,7 @@ #include "precompiled_vcl.hxx" #define _SV_SALNATIVEWIDGETS_KDE_CXX -#include "kde_headers.h" +#include <shell/kde_headers.h> #include <salunx.h> #include <saldata.hxx> @@ -2073,12 +2073,13 @@ void KDESalFrame::ReleaseGraphics( SalGraphics *pGraphics ) } } -void KDESalFrame::updateGraphics() +void KDESalFrame::updateGraphics( bool bClear ) { + Drawable aDrawable = bClear ? None : GetWindow(); for( int i = 0; i < nMaxGraphics; i++ ) { if( m_aGraphics[i].bInUse ) - m_aGraphics[i].pGraphics->SetDrawable( GetWindow(), GetScreenNumber() ); + m_aGraphics[i].pGraphics->SetDrawable( aDrawable, GetScreenNumber() ); } } diff --git a/vcl/unx/kde4/KDESalFrame.cxx b/vcl/unx/kde4/KDESalFrame.cxx index 796350a63d50..6177c4b2896a 100644 --- a/vcl/unx/kde4/KDESalFrame.cxx +++ b/vcl/unx/kde4/KDESalFrame.cxx @@ -181,7 +181,6 @@ void KDESalFrame::UpdateSettings( AllSettings& rSettings ) StyleSettings style( rSettings.GetStyleSettings() ); BOOL bSetTitleFont = false; - // General settings QPalette pal = kapp->palette(); @@ -214,6 +213,14 @@ void KDESalFrame::UpdateSettings( AllSettings& rSettings ) pKey = "Theme"; if ( aGroup.hasKey( pKey ) ) style.SetPreferredSymbolsStyleName( readEntryUntranslated( &aGroup, pKey ) ); + + //toolbar + pKey = "toolbarFont"; + if ( aGroup.hasKey( pKey ) ) + { + Font aFont = toFont( aGroup.readEntry( pKey, QFont() ), rSettings.GetUILocale() ); + style.SetToolFont( aFont ); + } } Color aFore = toColor( pal.color( QPalette::Active, QPalette::WindowText ) ); @@ -288,7 +295,7 @@ void KDESalFrame::UpdateSettings( AllSettings& rSettings ) style.SetFloatTitleFont( aFont ); style.SetMenuFont( aFont ); // will be changed according to pMenuBar - style.SetToolFont( aFont ); // will be changed according to pToolBar + //style.SetToolFont( aFont ); //already set above style.SetLabelFont( aFont ); style.SetInfoFont( aFont ); style.SetRadioCheckFont( aFont ); @@ -300,11 +307,9 @@ void KDESalFrame::UpdateSettings( AllSettings& rSettings ) int flash_time = QApplication::cursorFlashTime(); style.SetCursorBlinkTime( flash_time != 0 ? flash_time/2 : STYLE_CURSOR_NOBLINKTIME ); - KMainWindow qMainWindow; - // Menu style.SetSkipDisabledInMenus( TRUE ); - KMenuBar *pMenuBar = qMainWindow.menuBar(); + KMenuBar* pMenuBar = new KMenuBar(); if ( pMenuBar ) { // Color @@ -337,22 +342,11 @@ void KDESalFrame::UpdateSettings( AllSettings& rSettings ) style.SetMenuFont( aFont ); } - // Tool bar - KToolBar *pToolBar = qMainWindow.toolBar(); - if ( pToolBar ) - { - aFont = toFont( pToolBar->font(), rSettings.GetUILocale() ); - style.SetToolFont( aFont ); - } + delete pMenuBar; // Scroll bar size style.SetScrollBarSize( kapp->style()->pixelMetric( QStyle::PM_ScrollBarExtent ) ); - // #i59364# high contrast mode - BOOL bHC = ( style.GetFaceColor().IsDark() || - style.GetWindowColor().IsDark() ); - style.SetHighContrastMode( bHC ); - rSettings.SetStyleSettings( style ); } @@ -369,12 +363,13 @@ void KDESalFrame::ReleaseGraphics( SalGraphics *pGraphics ) } } -void KDESalFrame::updateGraphics() +void KDESalFrame::updateGraphics( bool bClear ) { + Drawable aDrawable = bClear ? None : GetWindow(); for( int i = 0; i < nMaxGraphics; i++ ) { if( m_aGraphics[i].bInUse ) - m_aGraphics[i].pGraphics->SetDrawable( GetWindow(), GetScreenNumber() ); + m_aGraphics[i].pGraphics->SetDrawable( aDrawable, GetScreenNumber() ); } } diff --git a/vcl/unx/kde4/KDESalFrame.hxx b/vcl/unx/kde4/KDESalFrame.hxx index 11a22bd93ba5..de3a5af189ee 100644 --- a/vcl/unx/kde4/KDESalFrame.hxx +++ b/vcl/unx/kde4/KDESalFrame.hxx @@ -52,7 +52,7 @@ class KDESalFrame : public X11SalFrame virtual SalGraphics* GetGraphics(); virtual void ReleaseGraphics( SalGraphics *pGraphics ); - virtual void updateGraphics(); + virtual void updateGraphics( bool bClear ); virtual void UpdateSettings( AllSettings& rSettings ); virtual void Show( BOOL bVisible, BOOL bNoActivate ); };
\ No newline at end of file diff --git a/vcl/unx/kde4/KDESalGraphics.cxx b/vcl/unx/kde4/KDESalGraphics.cxx index 2e8f0dcad96b..1c9882923b43 100644 --- a/vcl/unx/kde4/KDESalGraphics.cxx +++ b/vcl/unx/kde4/KDESalGraphics.cxx @@ -513,10 +513,12 @@ BOOL KDESalGraphics::drawNativeControl( ControlType type, ControlPart part, } else if (type == CTRL_FRAME) { + pixmap.fill(KApplication::palette().color(QPalette::Window)); lcl_drawFrame( widgetRect, painter, QStyle::PE_Frame, nControlState, value ); } else if (type == CTRL_FIXEDBORDER) { + pixmap.fill(KApplication::palette().color(QPalette::Window)); lcl_drawFrame( widgetRect, painter, QStyle::PE_FrameWindow, nControlState, value ); } else if (type == CTRL_WINDOW_BACKGROUND) diff --git a/vcl/unx/kde4/KDEXLib.cxx b/vcl/unx/kde4/KDEXLib.cxx index 70b1796df7f0..dedda64d157e 100644 --- a/vcl/unx/kde4/KDEXLib.cxx +++ b/vcl/unx/kde4/KDEXLib.cxx @@ -77,24 +77,30 @@ void KDEXLib::Init() pInputMethod->SetLocale(); XrmInitialize(); - KAboutData *kAboutData = new KAboutData( "OpenOffice.org", - "OpenOffice.org", + KAboutData *kAboutData = new KAboutData("OpenOffice.org", + "kdelibs4", ki18n( "OpenOffice.org" ), "3.0.0", ki18n( "OpenOffice.org with KDE Native Widget Support." ), KAboutData::License_LGPL, - ki18n( "Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008 Novell, Inc"), + ki18n( "Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Novell, Inc"), ki18n( "OpenOffice.org is an office suite.\n" ), "http://kde.openoffice.org/index.html", "dev@kde.openoffice.org" ); + kAboutData->addAuthor( ki18n( "Jan Holesovsky" ), ki18n( "Original author and maintainer of the KDE NWF." ), "kendy@artax.karlin.mff.cuni.cz", "http://artax.karlin.mff.cuni.cz/~kendy" ); + kAboutData->addAuthor( ki18n("Roman Shtylman"), + ki18n( "Porting to KDE 4." ), + "shtylman@gmail.com", "http://shtylman.com" ); kAboutData->addAuthor( ki18n("Eric Bischoff"), ki18n( "Accessibility fixes, porting to KDE 4." ), "bischoff@kde.org" ); + //kAboutData->setProgramIconName("OpenOffice"); + m_nFakeCmdLineArgs = 1; USHORT nIdx; vos::OExtCommandLine aCommandLine; @@ -135,6 +141,7 @@ void KDEXLib::Init() m_pApplication = new VCLKDEApplication(); kapp->disableSessionManagement(); + KApplication::setQuitOnLastWindowClosed(false); Display* pDisp = QX11Info::display(); SalKDEDisplay *pSalDisplay = new SalKDEDisplay(pDisp); diff --git a/vcl/unx/source/app/i18n_ic.cxx b/vcl/unx/source/app/i18n_ic.cxx index cacffbcfdbb1..bb8f86d93e01 100644 --- a/vcl/unx/source/app/i18n_ic.cxx +++ b/vcl/unx/source/app/i18n_ic.cxx @@ -340,7 +340,7 @@ SalI18N_InputContext::SalI18N_InputContext ( SalFrame *pFrame ) : if ( mnPreeditStyle != XIMPreeditNone ) { -#if defined LINUX || defined FREEBSD || defined NETBSD || defined IRIX +#if defined LINUX || defined FREEBSD || defined NETBSD if ( mpPreeditAttributes != NULL ) #endif mpAttributes = XVaAddToNestedList( mpAttributes, @@ -348,7 +348,7 @@ SalI18N_InputContext::SalI18N_InputContext ( SalFrame *pFrame ) : } if ( mnStatusStyle != XIMStatusNone ) { -#if defined LINUX || defined FREEBSD || defined NETBSD || defined IRIX +#if defined LINUX || defined FREEBSD || defined NETBSD if ( mpStatusAttributes != NULL ) #endif mpAttributes = XVaAddToNestedList( mpAttributes, diff --git a/vcl/unx/source/app/i18n_im.cxx b/vcl/unx/source/app/i18n_im.cxx index ae472d6323f4..0a48c054167f 100644 --- a/vcl/unx/source/app/i18n_im.cxx +++ b/vcl/unx/source/app/i18n_im.cxx @@ -59,7 +59,7 @@ using namespace vcl; #include "i18n_cb.hxx" -#if defined(SOLARIS) || defined(LINUX) || defined(IRIX) +#if defined(SOLARIS) || defined(LINUX) extern "C" char * XSetIMValues(XIM im, ...); #endif diff --git a/vcl/unx/source/app/randrwrapper.cxx b/vcl/unx/source/app/randrwrapper.cxx index 8d01b64d4680..4fbe5db97ab9 100644 --- a/vcl/unx/source/app/randrwrapper.cxx +++ b/vcl/unx/source/app/randrwrapper.cxx @@ -161,7 +161,13 @@ RandRWrapper::RandRWrapper( Display* pDisplay ) : if( ! m_bValid ) { rtl::OUString aLibName( RTL_CONSTASCII_USTRINGPARAM( "libXrandr.so.2" ) ); - m_pRandRLib = osl_loadModule( aLibName.pData, SAL_LOADMODULE_DEFAULT ); + // load and resolve dependencies immediately + // rationale: there are older distributions where libXrandr.so.2 is not linked + // with libXext.so, resulting in a missing symbol and terminating the office + // obviously they expected libXext to be linked in global symbolspace (that is + // linked by the application), which is not the case with us (because we want + // to be able to run in headless mode even without an installed X11 library) + m_pRandRLib = osl_loadModule( aLibName.pData, SAL_LOADMODULE_DEFAULT | SAL_LOADMODULE_NOW ); initFromModule(); } if( m_bValid ) diff --git a/vcl/unx/source/app/saldisp.cxx b/vcl/unx/source/app/saldisp.cxx index 07955d426b8c..558ae3714358 100644 --- a/vcl/unx/source/app/saldisp.cxx +++ b/vcl/unx/source/app/saldisp.cxx @@ -38,16 +38,13 @@ #include <stdio.h> #include <stdlib.h> #include <math.h> -#if defined(IRIX) -#include <ctime> -#endif #include <sys/time.h> #include <pthread.h> #include <unistd.h> #include <ctype.h> #include <string.h> -#if defined(SOLARIS) || defined(IRIX) +#if defined(SOLARIS) #include <sal/alloca.h> #include <osl/module.h> #endif @@ -898,7 +895,7 @@ void SalDisplay::Init() sscanf( pProperties, "%li", &nProperties_ ); else { -#if defined DBG_UTIL || defined SUN || defined LINUX || defined FREEBSD || defined IRIX +#if defined DBG_UTIL || defined SUN || defined LINUX || defined FREEBSD nProperties_ |= PROPERTY_FEATURE_Maximize; #endif // Server Bugs & Properties @@ -2307,11 +2304,7 @@ long SalX11Display::Dispatch( XEvent *pEvent ) return 0; SalInstance* pInstance = GetSalData()->m_pInstance; - if( pInstance->GetEventCallback() ) - { - YieldMutexReleaser aReleaser; - pInstance->CallEventCallback( pEvent, sizeof( XEvent ) ); - } + pInstance->CallEventCallback( pEvent, sizeof( XEvent ) ); switch( pEvent->type ) { diff --git a/vcl/unx/source/app/salinst.cxx b/vcl/unx/source/app/salinst.cxx index 1dc2d1404009..6b7753960290 100644 --- a/vcl/unx/source/app/salinst.cxx +++ b/vcl/unx/source/app/salinst.cxx @@ -50,7 +50,7 @@ #include "vcl/salwtype.hxx" #include "vcl/salatype.hxx" #include "vcl/helper.hxx" - +#include <tools/solarmutex.hxx> #include "vos/mutex.hxx" // ------------------------------------------------------------------------- @@ -63,6 +63,7 @@ SalYieldMutex::SalYieldMutex() { mnCount = 0; mnThreadId = 0; + ::tools::SolarMutex::SetSolarMutex( this ); } void SalYieldMutex::acquire() @@ -141,6 +142,7 @@ X11SalInstance::~X11SalInstance() delete pSalData; SetSalData( NULL ); + ::tools::SolarMutex::SetSolarMutex( 0 ); delete mpSalYieldMutex; } diff --git a/vcl/unx/source/app/saltimer.cxx b/vcl/unx/source/app/saltimer.cxx index bf8aa202b066..afcecc0d0667 100644 --- a/vcl/unx/source/app/saltimer.cxx +++ b/vcl/unx/source/app/saltimer.cxx @@ -32,9 +32,6 @@ #include "precompiled_vcl.hxx" #include <stdio.h> -#if defined(IRIX) -#include <ctime> -#endif #include <sys/time.h> #include <sys/times.h> #include <time.h> diff --git a/vcl/unx/source/app/sm.cxx b/vcl/unx/source/app/sm.cxx index ff981b04259b..c5605cec1dfb 100644 --- a/vcl/unx/source/app/sm.cxx +++ b/vcl/unx/source/app/sm.cxx @@ -114,7 +114,7 @@ void IceSalSession::queryInteraction() void IceSalSession::interactionDone() { - SessionManagerClient::interactionDone(); + SessionManagerClient::interactionDone( false ); } void IceSalSession::saveDone() @@ -129,6 +129,7 @@ void IceSalSession::saveDone() bool IceSalSession::cancelShutdown() { + SessionManagerClient::interactionDone( true ); return false; } @@ -368,6 +369,12 @@ void SessionManagerClient::SaveYourselfProc( IMPL_STATIC_LINK_NOINSTANCE( SessionManagerClient, ShutDownHdl, void*, EMPTYARG ) { + if( pOneInstance ) + { + SalSessionQuitEvent aEvent; + pOneInstance->CallCallback( &aEvent ); + } + const std::list< SalFrame* >& rFrames = GetX11SalData()->GetDisplay()->getFrames(); SMprintf( rFrames.begin() != rFrames.end() ? "shutdown on first frame\n" : "shutdown event but no frame\n" ); if( rFrames.begin() != rFrames.end() ) @@ -526,12 +533,12 @@ bool SessionManagerClient::queryInteraction() return bRet; } -void SessionManagerClient::interactionDone() +void SessionManagerClient::interactionDone( bool bCancelShutdown ) { if( aSmcConnection ) { ICEConnectionObserver::lock(); - SmcInteractDone( aSmcConnection, False ); + SmcInteractDone( aSmcConnection, bCancelShutdown ? True : False ); ICEConnectionObserver::unlock(); } } diff --git a/vcl/unx/source/dtrans/X11_selection.cxx b/vcl/unx/source/dtrans/X11_selection.cxx index 3f7dfc2df709..c6036ae4f78e 100644 --- a/vcl/unx/source/dtrans/X11_selection.cxx +++ b/vcl/unx/source/dtrans/X11_selection.cxx @@ -219,28 +219,64 @@ SelectionManager::SelectionManager() : m_aWindow( None ), m_nSelectionTimeout( 0 ), m_nSelectionTimestamp( CurrentTime ), + m_bDropEnterSent( true ), m_aCurrentDropWindow( None ), + m_nDropTime( None ), + m_nLastDropAction( 0 ), + m_nLastX( 0 ), + m_nLastY( 0 ), + m_nDropTimestamp( 0 ), m_bDropWaitingForCompletion( false ), m_aDropWindow( None ), m_aDropProxy( None ), m_aDragSourceWindow( None ), + m_nLastDragX( 0 ), + m_nLastDragY( 0 ), m_nNoPosX( 0 ), m_nNoPosY( 0 ), m_nNoPosWidth( 0 ), m_nNoPosHeight( 0 ), + m_nDragButton( 0 ), + m_nUserDragAction( 0 ), + m_nTargetAcceptAction( 0 ), + m_nSourceActions( 0 ), m_bLastDropAccepted( false ), m_bDropSuccess( false ), m_bDropSent( false ), m_bWaitingForPrimaryConversion( false ), + m_nDragTimestamp( None ), m_aMoveCursor( None ), m_aCopyCursor( None ), m_aLinkCursor( None ), m_aNoneCursor( None ), m_aCurrentCursor( None ), - m_nCurrentProtocolVersion( nXdndProtocolRevision ) + m_nCurrentProtocolVersion( nXdndProtocolRevision ), + m_nCLIPBOARDAtom( None ), + m_nTARGETSAtom( None ), + m_nTIMESTAMPAtom( None ), + m_nTEXTAtom( None ), + m_nINCRAtom( None ), + m_nCOMPOUNDAtom( None ), + m_nMULTIPLEAtom( None ), + m_nUTF16Atom( None ), + m_nImageBmpAtom( None ), + m_nXdndAware( None ), + m_nXdndEnter( None ), + m_nXdndLeave( None ), + m_nXdndPosition( None ), + m_nXdndStatus( None ), + m_nXdndDrop( None ), + m_nXdndFinished( None ), + m_nXdndSelection( None ), + m_nXdndTypeList( None ), + m_nXdndProxy( None ), + m_nXdndActionCopy( None ), + m_nXdndActionMove( None ), + m_nXdndActionLink( None ), + m_nXdndActionAsk( None ), + m_nXdndActionPrivate( None ) { m_aDropEnterEvent.data.l[0] = None; - m_bDropEnterSent = true; m_aDragRunning.reset(); } diff --git a/vcl/unx/source/gdi/pspgraphics.cxx b/vcl/unx/source/gdi/pspgraphics.cxx index 009b14c56062..227d6cd7e9b2 100644 --- a/vcl/unx/source/gdi/pspgraphics.cxx +++ b/vcl/unx/source/gdi/pspgraphics.cxx @@ -1094,13 +1094,6 @@ const void* PspGraphics::DoGetEmbedFontData( fontID aFont, const sal_Ucs* pUnico return NULL; // fill in font info - switch( aFontInfo.m_eType ) - { - case psp::fonttype::TrueType: rInfo.m_nFontType = FontSubsetInfo::SFNT_TTF; break; - case psp::fonttype::Type1: rInfo.m_nFontType = FontSubsetInfo::ANY_TYPE1; break; - default: - return NULL; - } rInfo.m_nAscent = aFontInfo.m_nAscend; rInfo.m_nDescent = aFontInfo.m_nDescend; rInfo.m_aPSName = rMgr.getPSName( aFont ); @@ -1137,9 +1130,22 @@ const void* PspGraphics::DoGetEmbedFontData( fontID aFont, const sal_Ucs* pUnico rInfo.m_nCapHeight = yMax; // Well ... for( int i = 0; i < 256; i++ ) - pWidths[i] = (aMetrics[i].width > 0 ? aMetrics[i].width : 0); + switch( aFontInfo.m_eType ) + { + case psp::fonttype::TrueType: + rInfo.m_nFontType = FontSubsetInfo::SFNT_TTF; + break; + case psp::fonttype::Type1: { + const bool bPFA = ((*(unsigned char*)pFile) < 0x80); + rInfo.m_nFontType = bPFA ? FontSubsetInfo::TYPE1_PFA : FontSubsetInfo::TYPE1_PFB; + } + break; + default: + return NULL; + } + return pFile; } diff --git a/vcl/unx/source/gdi/salgdi.cxx b/vcl/unx/source/gdi/salgdi.cxx index 34f2dfd4b935..5fe2295a8fed 100644 --- a/vcl/unx/source/gdi/salgdi.cxx +++ b/vcl/unx/source/gdi/salgdi.cxx @@ -50,6 +50,7 @@ #include "basegfx/polygon/b2dpolygonclipper.hxx" #include "basegfx/polygon/b2dlinegeometry.hxx" #include "basegfx/matrix/b2dhommatrix.hxx" +#include <basegfx/matrix/b2dhommatrixtools.hxx> #include "basegfx/polygon/b2dpolypolygoncutter.hxx" #include <vector> @@ -1028,11 +1029,12 @@ BOOL X11SalGraphics::drawEPS( long,long,long,long,void*,ULONG ) XID X11SalGraphics::GetXRenderPicture() { + XRenderPeer& rRenderPeer = XRenderPeer::GetInstance(); + if( !m_aRenderPicture ) { // check xrender support for matching visual // find a XRenderPictFormat compatible with the Drawable - XRenderPeer& rRenderPeer = XRenderPeer::GetInstance(); XRenderPictFormat* pVisualFormat = static_cast<XRenderPictFormat*>(GetXRenderFormat()); if( !pVisualFormat ) { @@ -1053,7 +1055,15 @@ XID X11SalGraphics::GetXRenderPicture() // TODO: avoid clipping if already set correctly if( pClipRegion_ && !XEmptyRegion( pClipRegion_ ) ) rRenderPeer.SetPictureClipRegion( aDstPic, pClipRegion_ ); + else #endif + { + // reset clip region + // TODO: avoid clip reset if already done + XRenderPictureAttributes aAttr; + aAttr.clip_mask = None; + rRenderPeer.ChangePicture( m_aRenderPicture, CPClipMask, &aAttr ); + } return m_aRenderPicture; } @@ -1096,6 +1106,7 @@ bool IsLeftOf( const XLineFixed& rA, const XLineFixed& rB ) const XFixed aXDiff = rU.p2.x - rU.p1.x; const XFixed aYDiff = rU.p2.y - rU.p1.y; + // compare upper point of lower segment with line through upper segment if( (rU.p1.y != rL.p1.y) || (rU.p1.x != rL.p1.x) ) { const sal_Int64 n1 = (sal_Int64)aXDiff * (rL.p1.y - rU.p1.y); @@ -1104,6 +1115,7 @@ bool IsLeftOf( const XLineFixed& rA, const XLineFixed& rB ) return ((n1 < n2) == bAbove); } + // compare lower point of lower segment with line through upper segment if( (rU.p2.y != rL.p2.y) || (rU.p2.x != rL.p2.x) ) { const sal_Int64 n3 = (sal_Int64)aXDiff * (rL.p2.y - rU.p1.y); @@ -1122,10 +1134,14 @@ struct HalfTrapezoid // maLine.p1.y <= mnY < maLine.p2.y XLineFixed maLine; XFixed mnY; + + XFixed getXMin() const { return std::min( maLine.p1.x, maLine.p2.x); } + XFixed getXMax() const { return std::max( maLine.p1.x, maLine.p2.x); } }; -struct HalfTrapCompare +class HalfTrapCompare { +public: bool operator()( const HalfTrapezoid& rA, const HalfTrapezoid& rB ) const { bool bIsTopLeft = false; @@ -1138,14 +1154,15 @@ struct HalfTrapCompare } }; -typedef std::priority_queue< HalfTrapezoid, std::vector<HalfTrapezoid>, HalfTrapCompare > HTQueueBase; +typedef std::vector< HalfTrapezoid > HTVector; +typedef std::priority_queue< HalfTrapezoid, HTVector, HalfTrapCompare > HTQueueBase; // we need a priority queue with a reserve() to prevent countless reallocations class HTQueue : public HTQueueBase { public: void reserve( size_t n ) { c.reserve( n ); } - int capacity() { return c.capacity(); } + void swapvec( HTVector& v ) { c.swap( v ); } }; typedef std::vector<XTrapezoid> TrapezoidVector; @@ -1173,6 +1190,10 @@ public: }; typedef std::multiset< int, TrapezoidYCompare > VerticalTrapSet; + +#ifndef DISABLE_SOLVECROSSOVER_WORKAROUND +void splitIntersectingSegments( HTVector&); +#endif // DISABLE_SOLVECROSSOVER_WORKAROUND } // end of anonymous namespace // draw a poly-polygon @@ -1210,7 +1231,7 @@ bool X11SalGraphics::drawPolyPolygon( const ::basegfx::B2DPolyPolygon& rOrigPoly // don't bother with polygons outside of visible area const basegfx::B2DRange aViewRange( 0, 0, GetGraphicsWidth(), GetGraphicsHeight() ); const basegfx::B2DRange aPolyRange = basegfx::tools::getRange( rOrigPolyPoly ); - const bool bNeedViewClip = !aPolyRange.isInside( aViewRange ); + const bool bNeedViewClip = aPolyRange.isInside( aViewRange ); if( !aPolyRange.overlaps( aViewRange ) ) return true; @@ -1237,6 +1258,15 @@ bool X11SalGraphics::drawPolyPolygon( const ::basegfx::B2DPolyPolygon& rOrigPoly if( !nClippedPolyCount ) continue; +#ifndef DISABLE_SOLVECROSSOVER_WORKAROUND + for( int nClippedPolyIdx = 0; nClippedPolyIdx < nClippedPolyCount; ++nClippedPolyIdx ) + { + const ::basegfx::B2DPolygon aSolvedPolygon = aClippedPolygon.getB2DPolygon( nClippedPolyIdx ); + const int nPointCount = aSolvedPolygon.count(); + aGoodPolyPoly.append( aSolvedPolygon ); + nHTQueueReserve += aSolvedPolygon.areControlPointsUsed() ? 8 * nPointCount : nPointCount; + } +#else // DISABLE_SOLVECROSSOVER_WORKAROUND // #i103259# polypoly.solveCrossover() fails to remove self-intersections // but polygon.solveCrossover() works. Use it to build the intersection-free polypolygon // TODO: if the self-intersection prevention is too expensive make the trap-algorithm tolerate intersections @@ -1255,11 +1285,12 @@ bool X11SalGraphics::drawPolyPolygon( const ::basegfx::B2DPolyPolygon& rOrigPoly nHTQueueReserve += aSolvedPolygon.areControlPointsUsed() ? 8 * nPointCount : nPointCount; } } +#endif // DISABLE_SOLVECROSSOVER_WORKAROUND } // #i100922# try to prevent priority-queue reallocations by reservering enough nHTQueueReserve = ((4*nHTQueueReserve) | 0x1FFF) + 1; - HTQueue aHTQueue; - aHTQueue.reserve( nHTQueueReserve ); + HTVector aHTVector; + aHTVector.reserve( nHTQueueReserve ); // first convert the B2DPolyPolygon to HalfTrapezoids const int nGoodPolyCount = aGoodPolyPoly.count(); @@ -1299,9 +1330,6 @@ bool X11SalGraphics::drawPolyPolygon( const ::basegfx::B2DPolyPolygon& rOrigPoly // check if enough data is available for a new HalfTrapezoid if( nPointIdx == 0 ) continue; - // ignore vertical segments - if( aNewXPF.y == aOldXPF.y ) - continue; // construct HalfTrapezoid as topdown segment HalfTrapezoid aHT; @@ -1326,14 +1354,33 @@ bool X11SalGraphics::drawPolyPolygon( const ::basegfx::B2DPolyPolygon& rOrigPoly #endif // queue up the HalfTrapezoid - aHTQueue.push( aHT ); + aHTVector.push_back( aHT ); } } } - if( aHTQueue.empty() ) + if( aHTVector.empty() ) return TRUE; +#ifndef DISABLE_SOLVECROSSOVER_WORKAROUND + // find intersecting halftraps and split them up + // TODO: remove when solveCrossOvers gets fast enough so its use can be enabled above + // FAQ: why should segment intersection be handled before adaptiveSubdivide()? + // Answer: because it is conceptually much faster + // Example: consider two intersecting circles with a diameter of 1000 pixels + // before subdivision: eight bezier segments + // after subdivision: more than a thousand line segments + // since even the best generic intersection finders have a complexity of O((n+k)*log(n+k)) + // it shows that testing while the segment count is still low is a much better approach. + splitIntersectingSegments( aHTVector); +#endif // DISABLE_SOLVECROSSOVER_WORKAROUND + + // build queue from vector of intersection-free segments + // TODO: is replacing the priority-queue by a sorted vector worth it? + std::make_heap( aHTVector.begin(), aHTVector.end(), HalfTrapCompare()); + HTQueue aHTQueue; + aHTQueue.swapvec( aHTVector); + // then convert the HalfTrapezoids into full Trapezoids TrapezoidVector aTrapVector; aTrapVector.reserve( aHTQueue.size() * 2 ); // just a guess @@ -1349,24 +1396,28 @@ bool X11SalGraphics::drawPolyPolygon( const ::basegfx::B2DPolyPolygon& rOrigPoly XTrapezoid aTrapezoid; // convert a HalfTrapezoid pair + // get the left side of the trapezoid const HalfTrapezoid& rLeft = aHTQueue.top(); aTrapezoid.top = rLeft.mnY; - aTrapezoid.bottom = rLeft.maLine.p2.y; aTrapezoid.left = rLeft.maLine; + aHTQueue.pop(); -#if 0 - // ignore empty trapezoids - if( aTrapezoid.bottom <= aTrapezoid.top ) + // ignore left segment that would result in an empty trapezoid + if( aTrapezoid.left.p2.y <= aTrapezoid.top ) continue; -#endif - aHTQueue.pop(); - if( aHTQueue.empty() ) // TODO: assert - break; - const HalfTrapezoid& rRight = aHTQueue.top(); - aTrapezoid.right = rRight.maLine; - aHTQueue.pop(); + // get the right side of the trapezoid + aTrapezoid.right.p2.y = aTrapezoid.bottom; + while( !aHTQueue.empty() ) { + const HalfTrapezoid& rRight = aHTQueue.top(); + aTrapezoid.right = rRight.maLine; + aHTQueue.pop(); + // ignore right segment that would result in an empty trapezoid + if( aTrapezoid.right.p2.y > aTrapezoid.top ) + break; + } + // the topmost endpoint determines the trapezoid bottom aTrapezoid.bottom = aTrapezoid.left.p2.y; if( aTrapezoid.bottom > aTrapezoid.right.p2.y ) aTrapezoid.bottom = aTrapezoid.right.p2.y; @@ -1374,44 +1425,49 @@ bool X11SalGraphics::drawPolyPolygon( const ::basegfx::B2DPolyPolygon& rOrigPoly // keep the full Trapezoid candidate aTrapVector.push_back( aTrapezoid ); - // unless it splits an older trapezoid + // unless it splits another trapezoid that is still active bool bSplit = false; - for(;;) + ActiveTrapSet::iterator aActiveTrapsIt = aActiveTraps.begin(); + for(; aActiveTrapsIt != aActiveTraps.end(); ++aActiveTrapsIt ) { - // check if the new trapezoid overlaps with an old trapezoid - ActiveTrapSet::iterator aActiveTrapsIt - = aActiveTraps.upper_bound( aTrapVector.size()-1 ); - if( aActiveTrapsIt == aActiveTraps.begin() ) - break; - --aActiveTrapsIt; - XTrapezoid& rLeftTrap = aTrapVector[ *aActiveTrapsIt ]; + // skip until first overlap candidate + // TODO: use stl::*er_bound() instead + if( IsLeftOf( aTrapezoid.left, rLeftTrap.left) ) + continue; + // in the ActiveTrapSet there are still trapezoids where // a vertical overlap with new trapezoids is no longer possible // they could have been removed in the verticaltraps loop below - // but this would have been expensive and is not needed as we can - // simply ignore them now and remove them from the ActiveTrapSet - // so they won't bother us in the future + // but this would be expensive and is not needed as we can + // simply ignore them until we stumble upon them here. if( rLeftTrap.bottom <= aTrapezoid.top ) { - aActiveTraps.erase( aActiveTrapsIt ); + ActiveTrapSet::iterator it = aActiveTrapsIt; + if( aActiveTrapsIt != aActiveTraps.begin() ) + --aActiveTrapsIt; + aActiveTraps.erase( it ); continue; } // check if there is horizontal overlap // aTrapezoid.left==rLeftTrap.right is allowed though if( !IsLeftOf( aTrapezoid.left, rLeftTrap.right ) ) - break; + continue; - // split the old trapezoid and keep its upper part + // prepare to split the old trapezoid and keep its upper part // find the old trapezoids entry in the VerticalTrapSet and remove it typedef std::pair<VerticalTrapSet::iterator, VerticalTrapSet::iterator> VTSPair; VTSPair aVTSPair = aVerticalTraps.equal_range( *aActiveTrapsIt ); VerticalTrapSet::iterator aVTSit = aVTSPair.first; - for(; (aVTSit != aVTSPair.second) && (*aVTSit != *aActiveTrapsIt); ++aVTSit ) ; - if( aVTSit != aVTSPair.second ) + for(; aVTSit != aVTSPair.second; ++aVTSit ) + { + if( *aVTSit != *aActiveTrapsIt ) + continue; aVerticalTraps.erase( aVTSit ); + break; + } // then update the old trapezoid's bottom rLeftTrap.bottom = aTrapezoid.top; // enter the updated old trapzoid in VerticalTrapSet @@ -1444,24 +1500,26 @@ bool X11SalGraphics::drawPolyPolygon( const ::basegfx::B2DPolyPolygon& rOrigPoly // mark trapezoids that can no longer be split as inactive // and recycle their sides which were not fully resolved static const XFixed nMaxTop = +0x7FFFFFFF; - XFixed nNewTop = aHTQueue.empty() ? nMaxTop : aHTQueue.top().mnY; + const XFixed nNewTop = aHTQueue.empty() ? nMaxTop : aHTQueue.top().mnY; while( !aVerticalTraps.empty() ) { + // check the next trapezoid to be retired const XTrapezoid& rOldTrap = aTrapVector[ *aVerticalTraps.begin() ]; if( nNewTop < rOldTrap.bottom ) break; - // the reference Trapezoid can no longer be split + // this trapezoid can no longer be split aVerticalTraps.erase( aVerticalTraps.begin() ); // recycle its sides that were not fully resolved HalfTrapezoid aHT; aHT.mnY = rOldTrap.bottom; - if( rOldTrap.left.p2.y > rOldTrap.bottom ) + + if( rOldTrap.left.p2.y > aHT.mnY ) { aHT.maLine = rOldTrap.left; aHTQueue.push( aHT ); } - if( rOldTrap.right.p2.y > rOldTrap.bottom ) + if( rOldTrap.right.p2.y > aHT.mnY ) { aHT.maLine = rOldTrap.right; aHTQueue.push( aHT ); @@ -1510,6 +1568,9 @@ bool X11SalGraphics::drawPolyLine(const ::basegfx::B2DPolygon& rPolygon, const : // the used basegfx::tools::createAreaGeometry is simply too // expensive with very big polygons; fallback to caller (who // should use ImplLineConverter normally) + // AW: ImplLineConverter had to be removed since it does not even + // know LineJoins, so the fallback will now prepare the line geometry + // the same way. return false; } const XRenderPeer& rRenderPeer = XRenderPeer::GetInstance(); @@ -1522,26 +1583,29 @@ bool X11SalGraphics::drawPolyLine(const ::basegfx::B2DPolygon& rPolygon, const : && !basegfx::fTools::equalZero( rLineWidth.getY() ) ) { // prepare for createAreaGeometry() with anisotropic linewidth - basegfx::B2DHomMatrix aAnisoMatrix; - aAnisoMatrix.scale( 1.0, rLineWidth.getX() / rLineWidth.getY() ); - aPolygon.transform( aAnisoMatrix ); + aPolygon.transform(basegfx::tools::createScaleB2DHomMatrix(1.0, rLineWidth.getX() / rLineWidth.getY())); + } + + // special handling for hairlines to improve the drawing performance + // TODO: revisit after basegfx performance related changes + const bool bIsHairline = (rLineWidth.getX() < 1.2) && (rLineWidth.getY() < 1.2); + if( bIsHairline ) + { + // for hairlines the linejoin style becomes irrelevant + eLineJoin = basegfx::B2DLINEJOIN_NONE; + // createAreaGeometry is still too expensive when beziers are involved + if( aPolygon.areControlPointsUsed() ) + aPolygon = ::basegfx::tools::adaptiveSubdivideByDistance( aPolygon, 0.125 ); } - // AW: reSegment no longer needed; new createAreaGeometry will remove exteme positions - // and create bezier polygons - //if( aPolygon.areControlPointsUsed() ) - // aPolygon = basegfx::tools::reSegmentPolygonEdges( aPolygon, 8, true, false ); - //const basegfx::B2DPolyPolygon aAreaPolyPoly = basegfx::tools::createAreaGeometryForSimplePolygon( - // aPolygon, 0.5*rLineWidth.getX(), eLineJoin ); - const basegfx::B2DPolyPolygon aAreaPolyPoly(basegfx::tools::createAreaGeometry(aPolygon, 0.5*rLineWidth.getX(), eLineJoin)); + // create the area-polygon for the line + const basegfx::B2DPolyPolygon aAreaPolyPoly( basegfx::tools::createAreaGeometry(aPolygon, 0.5*rLineWidth.getX(), eLineJoin) ); if( (rLineWidth.getX() != rLineWidth.getY()) && !basegfx::fTools::equalZero( rLineWidth.getX() ) ) { // postprocess createAreaGeometry() for anisotropic linewidth - basegfx::B2DHomMatrix aAnisoMatrix; - aAnisoMatrix.scale( 1.0, rLineWidth.getY() / rLineWidth.getX() ); - aPolygon.transform( aAnisoMatrix ); + aPolygon.transform(basegfx::tools::createScaleB2DHomMatrix(1.0, rLineWidth.getY() / rLineWidth.getX())); } // temporarily adjust brush color to pen color @@ -1568,3 +1632,259 @@ bool X11SalGraphics::drawPolyLine(const ::basegfx::B2DPolygon& rPolygon, const : // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +#ifndef DISABLE_SOLVECROSSOVER_WORKAROUND +// TODO: move the intersection solver into basegfx +// and then support bezier-intersection finding too + +namespace { // anonymous namespace to prevent export + +typedef HalfTrapezoid LineSeg; +typedef HTVector LSVector; + +inline bool operator==( const LineSeg& r1, const LineSeg& r2) +{ + if( r1.maLine.p2.y != r2.maLine.p2.y) return false; + if( r1.maLine.p2.x != r2.maLine.p2.x) return false; + if( r1.maLine.p1.y != r2.maLine.p1.y) return false; + if( r1.maLine.p1.x != r2.maLine.p1.x) return false; + return true; +} + +struct LSYMinCmp +{ + bool operator()( const LineSeg& r1, const LineSeg& r2) const + { return r2.maLine.p1.y < r1.maLine.p1.y; } +}; + +struct LSYMaxCmp +{ + bool operator()( const LineSeg& r1, const LineSeg& r2) const + { return r2.maLine.p2.y < r1.maLine.p2.y; } +}; + +struct LSXMinCmp +{ + bool operator()( const LineSeg& r1, const LineSeg& r2) const + { return( r1.getXMin() < r2.getXMin()); } +}; + +struct CutPoint +{ + XFixed mnSegmentId; + float mfCutParam; + XPointFixed maPoint; +}; + +struct CutPointCmp +{ + bool operator()( const CutPoint& r1, const CutPoint& r2) const + { + if( r1.mnSegmentId != r2.mnSegmentId) + return (r1.mnSegmentId < r2.mnSegmentId); + return (r1.mfCutParam < r2.mfCutParam); + } +}; + +bool findIntersection( const LineSeg& rLS1, const LineSeg& rLS2, CutPoint aCutPoints[2]) +{ + // segments intersect at r1.p1 + s*(r1.p2-r1.p1) == r2.p1 + t*(r2.p2-r2.p1) + // when both segment-parameters are ((0 <s<1) && (0<t<1)) + // (r1.p1 - r2.p1) == s * (r1.p1 - r1.p2) + t * (r2.p2 - r2.p1) + // => + // (r1.p1x - r2.p1x) == s * (r1.p1x - r1.p2x) + t * (r2.p2x - r2.p1x) + // (r1.p1y - r2.p1y) == s * (r1.p1y - r1.p2y) + t * (r2.p2y - r2.p1y) + // check if lines are identical or parallel => not intersecting + const XLineFixed& r1 = rLS1.maLine; + const XLineFixed& r2 = rLS2.maLine; + const double fDet = (double)(r1.p1.x - r1.p2.x) * (r2.p2.y - r2.p1.y) + - (double)(r2.p2.x - r2.p1.x) * (r1.p1.y - r1.p2.y); + static const double fEps = 1e-8; + if( fabs(fDet) < fEps) + return false; + // check if intersecting with first segment + const double fS1 = (double)(r2.p2.y - r2.p1.y) * (r1.p1.x - r2.p1.x); + const double fS2 = (double)(r2.p2.x - r2.p1.x) * (r2.p1.y - r1.p1.y); + const double fS = (fS1 + fS2) / fDet; + if( (fS <= +fEps) || (fS >= 1-fEps)) + return false; + // check if intersecting with second segment + const double fT1 = (double)(r1.p2.y - r1.p1.y) * (r1.p1.x - r2.p1.x); + const double fT2 = (double)(r1.p2.x - r1.p1.x) * (r2.p1.y - r1.p1.y); + const double fT = (fT1 + fT2) / fDet; + if( (fT <= +fEps) || (fT >= 1-fEps)) + return false; + // force the intersection point to be exactly identical on both segments + aCutPoints[0].maPoint.x = (XFixed)(r1.p1.x + fS * (r1.p2.x - r1.p1.x)); + aCutPoints[0].maPoint.y = (XFixed)(r1.p1.y + fS * (r1.p2.y - r1.p1.y)); + aCutPoints[1].maPoint.x = aCutPoints[0].maPoint.x; + aCutPoints[1].maPoint.y = aCutPoints[0].maPoint.y; + aCutPoints[0].mnSegmentId = rLS1.mnY; + aCutPoints[0].mfCutParam = (float)fS; + aCutPoints[1].mnSegmentId = rLS2.mnY; + aCutPoints[1].mfCutParam = (float)fT; + return true; +} + +typedef std::priority_queue< LineSeg, LSVector, LSYMinCmp> LSYMinQueueBase; +typedef std::priority_queue< LineSeg, LSVector, LSYMaxCmp> LSYMaxQueueBase; +typedef std::multiset< LineSeg, LSXMinCmp> LSXMinSet; +typedef std::set< CutPoint, CutPointCmp> CutPointSet; + +class LSYMinQueue : public LSYMinQueueBase +{ +public: + void reserve( size_t n) { c.reserve(n);} + void swapvec( LSVector& v) { c.swap(v);} +}; + +class LSYMaxQueue : public LSYMaxQueueBase +{ +public: + void reserve( size_t n) { c.reserve(n);} +}; + +void addAndCutSegment( LSVector& rLSVector, const LineSeg& rLS, CutPointSet& rCutPointSet) +{ + // short circuit when no segment was cut + if( rCutPointSet.empty()) { + rLSVector.push_back( rLS); + return; + } + + // find the first cut point for this segment + LineSeg aCS = rLS; + CutPoint aMinCutPoint; + aMinCutPoint.mnSegmentId = rLS.mnY; + aMinCutPoint.mfCutParam = 0.0; + CutPointSet::iterator itFirst = rCutPointSet.lower_bound( aMinCutPoint); + CutPointSet::iterator it = itFirst; + // iterate through all cut points of this segment + for(; it != rCutPointSet.end(); ++it) { + const CutPoint rCutPoint = (*it); + if( rCutPoint.mnSegmentId != rLS.mnY) + break; + // cut segment at the cutpoint + aCS.maLine.p2 = rCutPoint.maPoint; + rLSVector.push_back( aCS); + // prepare for next segment cut + aCS.maLine.p1 = aCS.maLine.p2; + } + // remove cutparams that will no longer be needed + // TODO: is it worth it or should we just keep the cutparams? + rCutPointSet.erase( itFirst, it); + + // add segment part remaining after last cut + aCS.maLine.p2 = rLS.maLine.p2; + rLSVector.push_back( aCS); +} + +void splitIntersectingSegments( LSVector& rLSVector) +{ + // get a unique id for each lineseg, temporarily abuse the mnY member + LSVector::iterator aLSit = rLSVector.begin(); + for( int i = 0; aLSit != rLSVector.end(); ++aLSit) { + LineSeg& rLS = *aLSit; + rLS.mnY = i++; + } + // get an y-sorted queue from the input vector + LSYMinQueue aYMinQueue; + std::make_heap( rLSVector.begin(), rLSVector.end(), LSYMinCmp()); + aYMinQueue.swapvec( rLSVector); + + // prepare the result vector + // try to avoid reallocations by guessing a reasonable result size + rLSVector.reserve( aYMinQueue.size() * 3/2 ); + + // find all intersections + CutPointSet aCutPointSet; + LSXMinSet aXMinSet; + LSYMaxQueue aYMaxQueue; + aYMaxQueue.reserve( aYMinQueue.size()); + // sweep-down and check all segment-pairs that overlap + while( !aYMinQueue.empty()) { + // get next input-segment + const LineSeg& rLS = aYMinQueue.top(); + // retire obsoleted segments + const XFixed fYCur = rLS.maLine.p1.y; + while( !aYMaxQueue.empty()) { + // check next segment to be retired + const LineSeg& rOS = aYMaxQueue.top(); + if( fYCur < rOS.maLine.p2.y) + break; + // emit resolved segment into result + addAndCutSegment( rLSVector, rOS, aCutPointSet); + // find segment to be retired in xmin-compare-set + LSXMinSet::iterator itR = aXMinSet.lower_bound( rOS); + while( !(*itR == rOS)) ++itR; + // retire segment from xmin-compare-set + aXMinSet.erase( itR); + // this segment is pining for the fjords + aYMaxQueue.pop(); + } + + // iterate over all segments that might overlap + // skip over the leftmost segments that cannot overlap + const XFixed fXMax = rLS.getXMax(); + LSXMinSet::const_iterator itC = aXMinSet.begin(); + for(; itC != aXMinSet.end(); ++itC) + if( (*itC).getXMin() <= fXMax) + break; + // TODO: if the linear search becomes too expensive + // then use an XMaxQueue based approach to replace it + const XFixed fXMin = rLS.getXMin(); + for(; itC != aXMinSet.end(); ++itC) { + const LineSeg& rOS = *itC; + if( fXMin >= rOS.getXMax()) + continue; + if( fXMax < rOS.getXMin()) + break; + CutPoint aCutPoints[2]; + if( !findIntersection( rLS, rOS, aCutPoints)) + continue; + // remember cut parameters + // TODO: std::set seems to use individual allocations + // which results in perf-problems for many entries + // => pre-allocate nodes by using a non-default allocator + aCutPointSet.insert( aCutPoints[0]); + aCutPointSet.insert( aCutPoints[1]); + } + // add segment to xmin-compare-set + // TODO: do we have a good insertion hint? + aXMinSet.insert( /*itC,*/ rLS); + // register segment for retirement + aYMaxQueue.push( rLS); + aYMinQueue.pop(); + } + + // retire the remaining segments + aXMinSet.clear(); + while( !aYMaxQueue.empty()) { + // emit segments and cut them up if needed + const LineSeg& rLS = aYMaxQueue.top(); + addAndCutSegment( rLSVector, rLS, aCutPointSet); + aYMaxQueue.pop(); + } + + // get the segments ready to be consumed by the drawPolygon() caller + aLSit = rLSVector.begin(); + LSVector::iterator aLSit2 = aLSit; + for(; aLSit != rLSVector.end(); ++aLSit) { + LineSeg& rLS = *aLSit; + // restore the segment top member + rLS.mnY = rLS.maLine.p1.y; + // remove horizontal segments for now + // TODO: until the trapezoid converter is adjusted to handle them + if( rLS.maLine.p1.y == rLS.maLine.p2.y ) + continue; + *(aLSit2++) = rLS; + } + if(aLSit2 != aLSit) + rLSVector.resize( aLSit2 - rLSVector.begin() ); +} + +} // end anonymous namespace + +#endif // DISABLE_SOLVECROSSOVER_WORKAROUND + +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + diff --git a/vcl/unx/source/gdi/salprnpsp.cxx b/vcl/unx/source/gdi/salprnpsp.cxx index 2cf4e3baedd3..d47e30a89633 100644 --- a/vcl/unx/source/gdi/salprnpsp.cxx +++ b/vcl/unx/source/gdi/salprnpsp.cxx @@ -177,6 +177,32 @@ static void copyJobDataToJobSetup( ImplJobSetup* pJobSetup, JobData& rData ) pJobSetup->mnPaperBin = 0; } + // copy duplex + pKey = NULL; + pValue = NULL; + + pJobSetup->meDuplexMode = DUPLEX_UNKNOWN; + if( rData.m_pParser ) + pKey = rData.m_pParser->getKey( String( RTL_CONSTASCII_USTRINGPARAM( "Duplex" ) ) ); + if( pKey ) + pValue = rData.m_aContext.getValue( pKey ); + if( pKey && pValue ) + { + if( pValue->m_aOption.EqualsIgnoreCaseAscii( "None" ) || + pValue->m_aOption.EqualsIgnoreCaseAscii( "Simplex", 0, 7 ) + ) + { + pJobSetup->meDuplexMode = DUPLEX_OFF; + } + else if( pValue->m_aOption.EqualsIgnoreCaseAscii( "DuplexNoTumble" ) ) + { + pJobSetup->meDuplexMode = DUPLEX_LONGEDGE; + } + else if( pValue->m_aOption.EqualsIgnoreCaseAscii( "DuplexTumble" ) ) + { + pJobSetup->meDuplexMode = DUPLEX_SHORTEDGE; + } + } // copy the whole context if( pJobSetup->mpDriverData ) @@ -525,34 +551,6 @@ void PspSalInfoPrinter::InitPaperFormats( const ImplJobSetup* ) // ----------------------------------------------------------------------- -DuplexMode PspSalInfoPrinter::GetDuplexMode( const ImplJobSetup* pJobSetup ) -{ - DuplexMode aRet = DUPLEX_UNKNOWN; - PrinterInfo aInfo( PrinterInfoManager::get().getPrinterInfo( pJobSetup->maPrinterName ) ); - if ( pJobSetup->mpDriverData ) - JobData::constructFromStreamBuffer( pJobSetup->mpDriverData, pJobSetup->mnDriverDataLen, aInfo ); - if( aInfo.m_pParser ) - { - const PPDKey * pKey = aInfo.m_pParser->getKey( String( RTL_CONSTASCII_USTRINGPARAM( "Duplex" ) ) ); - if( pKey ) - { - const PPDValue* pVal = aInfo.m_aContext.getValue( pKey ); - if( pVal && ( - pVal->m_aOption.EqualsIgnoreCaseAscii( "None" ) || - pVal->m_aOption.EqualsIgnoreCaseAscii( "Simplex", 0, 7 ) - ) ) - { - aRet = DUPLEX_OFF; - } - else - aRet = DUPLEX_ON; - } - } - return aRet; -} - -// ----------------------------------------------------------------------- - int PspSalInfoPrinter::GetLandscapeAngle( const ImplJobSetup* ) { return 900; @@ -727,6 +725,37 @@ BOOL PspSalInfoPrinter::SetData( if( nSetDataFlags & SAL_JOBSET_ORIENTATION ) aData.m_eOrientation = pJobSetup->meOrientation == ORIENTATION_LANDSCAPE ? orientation::Landscape : orientation::Portrait; + // merge duplex if necessary + if( nSetDataFlags & SAL_JOBSET_DUPLEXMODE ) + { + pKey = aData.m_pParser->getKey( String( RTL_CONSTASCII_USTRINGPARAM( "Duplex" ) ) ); + if( pKey ) + { + pValue = NULL; + switch( pJobSetup->meDuplexMode ) + { + case DUPLEX_OFF: + pValue = pKey->getValue( String( RTL_CONSTASCII_USTRINGPARAM( "None" ) ) ); + if( pValue == NULL ) + pValue = pKey->getValue( String( RTL_CONSTASCII_USTRINGPARAM( "SimplexNoTumble" ) ) ); + break; + case DUPLEX_SHORTEDGE: + pValue = pKey->getValue( String( RTL_CONSTASCII_USTRINGPARAM( "DuplexTumble" ) ) ); + break; + case DUPLEX_LONGEDGE: + pValue = pKey->getValue( String( RTL_CONSTASCII_USTRINGPARAM( "DuplexNoTumble" ) ) ); + break; + case DUPLEX_UNKNOWN: + default: + pValue = 0; + break; + } + if( ! pValue ) + pValue = pKey->getDefaultValue(); + aData.m_aContext.setValue( pKey, pValue ); + } + } + m_aJobData = aData; copyJobDataToJobSetup( pJobSetup, aData ); return TRUE; @@ -828,9 +857,22 @@ ULONG PspSalInfoPrinter::GetCapabilities( const ImplJobSetup* pJobSetup, USHORT case PRINTER_CAPABILITIES_COPIES: return 0xffff; case PRINTER_CAPABILITIES_COLLATECOPIES: - return 0; + { + // see if the PPD contains a value to set Collate to True + JobData aData; + JobData::constructFromStreamBuffer( pJobSetup->mpDriverData, pJobSetup->mnDriverDataLen, aData ); + + const PPDKey* pKey = aData.m_pParser ? aData.m_pParser->getKey( String( RTL_CONSTASCII_USTRINGPARAM( "Collate" ) ) ) : NULL; + const PPDValue* pVal = pKey ? pKey->getValue( String( RTL_CONSTASCII_USTRINGPARAM( "True" ) ) ) : NULL; + + // PPDs don't mention the number of possible collated copies. + // so let's guess as many as we want ? + return pVal ? 0xffff : 0; + } case PRINTER_CAPABILITIES_SETORIENTATION: return 1; + case PRINTER_CAPABILITIES_SETDUPLEX: + return 1; case PRINTER_CAPABILITIES_SETPAPERBIN: return 1; case PRINTER_CAPABILITIES_SETPAPERSIZE: @@ -860,6 +902,7 @@ ULONG PspSalInfoPrinter::GetCapabilities( const ImplJobSetup* pJobSetup, USHORT m_bSwallowFaxNo( false ), m_pGraphics( NULL ), m_nCopies( 1 ), + m_bCollate( false ), m_pInfoPrinter( pInfoPrinter ) { } @@ -885,7 +928,9 @@ BOOL PspSalPrinter::StartJob( const XubString* pFileName, const XubString& rJobName, const XubString& rAppName, - ULONG nCopies, BOOL /*bCollate*/, + ULONG nCopies, + bool bCollate, + bool bDirect, ImplJobSetup* pJobSetup ) { vcl_sal::PrinterUpdate::jobStarted(); @@ -894,13 +939,17 @@ BOOL PspSalPrinter::StartJob( m_bPdf = false; m_aFileName = pFileName ? *pFileName : String(); m_aTmpFile = String(); - m_nCopies = nCopies; + m_nCopies = nCopies; + m_bCollate = bCollate; JobData::constructFromStreamBuffer( pJobSetup->mpDriverData, pJobSetup->mnDriverDataLen, m_aJobData ); if( m_nCopies > 1 ) + { // in case user did not do anything (m_nCopies=1) // take the default from jobsetup m_aJobData.m_nCopies = m_nCopies; + m_aJobData.setCollate( bCollate ); + } // check wether this printer is configured as fax int nMode = 0; @@ -943,15 +992,6 @@ BOOL PspSalPrinter::StartJob( } m_aPrinterGfx.Init( m_aJobData ); - bool bIsQuickJob = false; - std::hash_map< rtl::OUString, rtl::OUString, rtl::OUStringHash >::const_iterator quick_it = - pJobSetup->maValueMap.find( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsQuickJob" ) ) ); - if( quick_it != pJobSetup->maValueMap.end() ) - { - if( quick_it->second.equalsIgnoreAsciiCaseAscii( "true" ) ) - bIsQuickJob = true; - } - // set/clear backwards compatibility flag bool bStrictSO52Compatibility = false; std::hash_map<rtl::OUString, rtl::OUString, rtl::OUStringHash >::const_iterator compat_it = @@ -964,7 +1004,7 @@ BOOL PspSalPrinter::StartJob( } m_aPrinterGfx.setStrictSO52Compatibility( bStrictSO52Compatibility ); - return m_aPrintJob.StartJob( m_aTmpFile.Len() ? m_aTmpFile : m_aFileName, nMode, rJobName, rAppName, m_aJobData, &m_aPrinterGfx, bIsQuickJob ) ? TRUE : FALSE; + return m_aPrintJob.StartJob( m_aTmpFile.Len() ? m_aTmpFile : m_aFileName, nMode, rJobName, rAppName, m_aJobData, &m_aPrinterGfx, bDirect ) ? TRUE : FALSE; } // ----------------------------------------------------------------------- @@ -1010,9 +1050,12 @@ SalGraphics* PspSalPrinter::StartPage( ImplJobSetup* pJobSetup, BOOL ) m_pGraphics = new PspGraphics( &m_aJobData, &m_aPrinterGfx, m_bFax ? &m_aFaxNr : NULL, m_bSwallowFaxNo, m_pInfoPrinter ); m_pGraphics->SetLayout( 0 ); if( m_nCopies > 1 ) + { // in case user did not do anything (m_nCopies=1) // take the default from jobsetup m_aJobData.m_nCopies = m_nCopies; + m_aJobData.setCollate( m_nCopies > 1 && m_bCollate ); + } m_aPrintJob.StartPage( m_aJobData ); m_aPrinterGfx.Init( m_aPrintJob ); diff --git a/vcl/unx/source/gdi/xrender_peer.cxx b/vcl/unx/source/gdi/xrender_peer.cxx index d8f2045c6fde..fc8de818fafd 100644 --- a/vcl/unx/source/gdi/xrender_peer.cxx +++ b/vcl/unx/source/gdi/xrender_peer.cxx @@ -142,6 +142,10 @@ void XRenderPeer::InitRenderLib() mpXRenderCreatePicture = (Picture(*)(Display*,Drawable,const XRenderPictFormat*, unsigned long,const XRenderPictureAttributes*))pFunc; + pFunc = osl_getAsciiFunctionSymbol( mpRenderLib, "XRenderChangePicture" ); + if( !pFunc ) return; + mpXRenderChangePicture = (void(*)(Display*,Picture,unsigned long,const XRenderPictureAttributes*))pFunc; + pFunc = osl_getAsciiFunctionSymbol( mpRenderLib, "XRenderSetPictureClipRegion" ); if( !pFunc ) return; mpXRenderSetPictureClipRegion = (void(*)(Display*,Picture,XLIB_Region))pFunc; diff --git a/vcl/unx/source/gdi/xrender_peer.hxx b/vcl/unx/source/gdi/xrender_peer.hxx index f1e2fd77a273..27c8fb3dcaeb 100644 --- a/vcl/unx/source/gdi/xrender_peer.hxx +++ b/vcl/unx/source/gdi/xrender_peer.hxx @@ -66,6 +66,8 @@ public: const XRenderPictFormat& ) const; Picture CreatePicture( Drawable, const XRenderPictFormat*, unsigned long nDrawable, const XRenderPictureAttributes* ) const; + void ChangePicture( Picture, unsigned long nValueMask, + const XRenderPictureAttributes* ) const; void SetPictureClipRegion( Picture, XLIB_Region ) const; void CompositePicture( int nOp, Picture aSrc, Picture aMask, Picture aDst, int nXSrc, int nYSrc, int nXMask, int nYMask, @@ -103,6 +105,8 @@ private: Picture (*mpXRenderCreatePicture)(Display*,Drawable, const XRenderPictFormat*, unsigned long,const XRenderPictureAttributes*); + void (*mpXRenderChangePicture)(Display*,Picture, + unsigned long,const XRenderPictureAttributes*); void (*mpXRenderSetPictureClipRegion)(Display*,Picture,XLIB_Region); void (*mpXRenderFreePicture)(Display*,Picture); void (*mpXRenderComposite)(Display*,int,Picture,Picture,Picture, @@ -194,6 +198,16 @@ inline Picture XRenderPeer::CreatePicture( Drawable aDrawable, #endif } +inline void XRenderPeer::ChangePicture( Picture aPicture, + unsigned long nValueMask, const XRenderPictureAttributes* pRenderAttr ) const +{ +#ifdef XRENDER_LINK + XRenderChangePicture( mpDisplay, aPicture, nValueMask, pRenderAttr ); +#else + (*mpXRenderChangePicture)( mpDisplay, aPicture, nValueMask, pRenderAttr ); +#endif +} + inline void XRenderPeer::SetPictureClipRegion( Picture aPicture, XLIB_Region aXlibRegion ) const { diff --git a/vcl/unx/source/plugadapt/salplug.cxx b/vcl/unx/source/plugadapt/salplug.cxx index 14de25b13e4d..08820b2cb7f9 100644 --- a/vcl/unx/source/plugadapt/salplug.cxx +++ b/vcl/unx/source/plugadapt/salplug.cxx @@ -149,34 +149,53 @@ static const rtl::OUString& get_desktop_environment() return aRet; } -static const char* autodetect_plugin() +static SalInstance* autodetect_plugin() { + static const char* pKDEFallbackList[] = + { + "kde4", "kde", "gtk", "gen", 0 + }; + + static const char* pStandardFallbackList[] = + { + "gtk", "gen", 0 + }; + + static const char* pHeadlessFallbackList[] = + { + "svp", 0 + }; + const rtl::OUString& desktop( get_desktop_environment() ); - const char * pRet = "gen"; + const char ** pList = pStandardFallbackList; + int nListEntry = 0; // no server at all: dummy plugin if ( desktop.equalsAscii( desktop_strings[DESKTOP_NONE] ) ) - pRet = "svp"; + pList = pHeadlessFallbackList; else if ( desktop.equalsAscii( desktop_strings[DESKTOP_GNOME] ) ) - pRet = "gtk"; + pList = pStandardFallbackList; else if( desktop.equalsAscii( desktop_strings[DESKTOP_KDE] ) ) - pRet = "kde"; - else if( desktop.equalsAscii( desktop_strings[DESKTOP_KDE4] ) ) - pRet = "kde4"; - else { - // #i95296# use the much nicer looking gtk plugin - // on desktops that set gtk variables (e.g. XFCE) - static const char* pEnv = getenv( "GTK2_RC_FILES" ); - if( pEnv && *pEnv ) // check for existance and non emptiness - pRet = "gtk"; + pList = pKDEFallbackList; + nListEntry = 1; } + else if( desktop.equalsAscii( desktop_strings[DESKTOP_KDE4] ) ) + pList = pKDEFallbackList; -#if OSL_DEBUG_LEVEL > 1 - std::fprintf( stderr, "plugin autodetection: %s\n", pRet ); -#endif + SalInstance* pInst = NULL; + while( pList[nListEntry] && pInst == NULL ) + { + rtl::OUString aTry( rtl::OUString::createFromAscii( pList[nListEntry] ) ); + pInst = tryInstance( aTry ); + #if OSL_DEBUG_LEVEL > 1 + if( pInst ) + std::fprintf( stderr, "plugin autodetection: %s\n", pList[nListEntry] ); + #endif + nListEntry++; + } - return pRet; + return pInst; } static SalInstance* check_headless_plugin() @@ -200,13 +219,12 @@ SalInstance *CreateSalInstance() if( !(pUsePlugin && *pUsePlugin) ) pInst = check_headless_plugin(); - - if( ! pInst && !(pUsePlugin && *pUsePlugin) ) - pUsePlugin = autodetect_plugin(); - - if( ! pInst && pUsePlugin && *pUsePlugin ) + else pInst = tryInstance( OUString::createFromAscii( pUsePlugin ) ); + if( ! pInst ) + pInst = autodetect_plugin(); + // fallback to gen if( ! pInst ) pInst = tryInstance( OUString( RTL_CONSTASCII_USTRINGPARAM( "gen" ) ) ); diff --git a/vcl/unx/source/printer/jobdata.cxx b/vcl/unx/source/printer/jobdata.cxx index 51e171d578d9..0410b349c93b 100644 --- a/vcl/unx/source/printer/jobdata.cxx +++ b/vcl/unx/source/printer/jobdata.cxx @@ -64,6 +64,28 @@ JobData& JobData::operator=(const JobData& rRight) return *this; } +void JobData::setCollate( bool bCollate ) +{ + const PPDParser* pParser = m_aContext.getParser(); + if( pParser ) + { + const PPDKey* pKey = pParser->getKey( String( RTL_CONSTASCII_USTRINGPARAM( "Collate" ) ) ); + if( pKey ) + { + const PPDValue* pVal = NULL; + if( bCollate ) + pVal = pKey->getValue( String( RTL_CONSTASCII_USTRINGPARAM( "True" ) ) ); + else + { + pVal = pKey->getValue( String( RTL_CONSTASCII_USTRINGPARAM( "False" ) ) ); + if( ! pVal ) + pVal = pKey->getValue( String( RTL_CONSTASCII_USTRINGPARAM( "None" ) ) ); + } + m_aContext.setValue( pKey, pVal ); + } + } +} + bool JobData::getStreamBuffer( void*& pData, int& bytes ) { // consistency checks diff --git a/vcl/unx/source/printer/printerinfomanager.cxx b/vcl/unx/source/printer/printerinfomanager.cxx index b3e5b4667a6a..53cd662db8e0 100644 --- a/vcl/unx/source/printer/printerinfomanager.cxx +++ b/vcl/unx/source/printer/printerinfomanager.cxx @@ -441,7 +441,7 @@ void PrinterInfoManager::initialize() * porters: please append your platform to the Solaris * case if your platform has SystemV printing per default. */ - #if defined SOLARIS || defined(IRIX) + #if defined SOLARIS aValue = "lp"; #else aValue = "lpr"; diff --git a/vcl/unx/source/printergfx/common_gfx.cxx b/vcl/unx/source/printergfx/common_gfx.cxx index 632f0d70aa2f..9b305ff323ba 100644 --- a/vcl/unx/source/printergfx/common_gfx.cxx +++ b/vcl/unx/source/printergfx/common_gfx.cxx @@ -7,7 +7,6 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: common_gfx.cxx,v $ - * $Revision: 1.20.18.1 $ * * This file is part of OpenOffice.org. * @@ -535,68 +534,47 @@ PrinterGfx::DrawPolyLineBezier (sal_uInt32 nPoints, const Point* pPath, const BY const sal_uInt32 nBezString = 1024; sal_Char pString[nBezString]; - if ( maLineColor.Is() && nPoints && pPath ) + if ( nPoints > 1 && maLineColor.Is() && pPath ) { PSSetColor (maLineColor); PSSetColor (); PSSetLineWidth (); - if (pFlgAry[0] != POLY_NORMAL) //There must be a starting point to moveto - { - return; - } - else - { - snprintf(pString, nBezString, "%li %li moveto\n", pPath[0].X(), pPath[0].Y()); - WritePS(mpPageBody, pString); - } + snprintf(pString, nBezString, "%li %li moveto\n", pPath[0].X(), pPath[0].Y()); + WritePS(mpPageBody, pString); // Handle the drawing of mixed lines mixed with curves // - a normal point followed by a normal point is a line // - a normal point followed by 2 control points and a normal point is a curve for (unsigned int i=1; i<nPoints;) { - if (pFlgAry[i+1] != POLY_CONTROL) //If the next point is a POLY_NORMAL, we're drawing a line + if (pFlgAry[i] != POLY_CONTROL) //If the next point is a POLY_NORMAL, we're drawing a line { - if (i+1 >= nPoints) return; //Make sure we don't pass the end of the array snprintf(pString, nBezString, "%li %li lineto\n", pPath[i].X(), pPath[i].Y()); i++; } else //Otherwise we're drawing a spline { - if (i+3 >= nPoints) return; //Make sure we don't pass the end of the array - snprintf(pString, nBezString, "%li %li %li %li %li %li curveto\n", - pPath[i+1].X(), pPath[i+1].Y(), - pPath[i+2].X(), pPath[i+2].Y(), - pPath[i+3].X(), pPath[i+3].Y()); + if (i+2 >= nPoints) + return; //Error: wrong sequence of contol/normal points somehow + if ((pFlgAry[i] == POLY_CONTROL) && (pFlgAry[i+1] == POLY_CONTROL) && + (pFlgAry[i+2] != POLY_CONTROL)) + { + snprintf(pString, nBezString, "%li %li %li %li %li %li curveto\n", + pPath[i].X(), pPath[i].Y(), + pPath[i+1].X(), pPath[i+1].Y(), + pPath[i+2].X(), pPath[i+2].Y()); + } + else + { + DBG_ERROR( "PrinterGfx::DrawPolyLineBezier: Strange output" ); + } i+=3; } WritePS(mpPageBody, pString); } - } - - // if eofill and stroke, save the current path - if( maFillColor.Is() && maLineColor.Is()) - PSGSave(); - - // first draw area - if( maFillColor.Is() ) - { - PSSetColor (maFillColor); - PSSetColor (); - WritePS (mpPageBody, "eofill\n"); - } - - // restore the current path - if( maFillColor.Is() && maLineColor.Is()) - PSGRestore(); - // now draw outlines - if( maLineColor.Is() ) - { - PSSetColor (maLineColor); - PSSetColor (); - PSSetLineWidth (); + // now draw outlines WritePS (mpPageBody, "stroke\n"); } } @@ -635,7 +613,7 @@ PrinterGfx::DrawPolygonBezier (sal_uInt32 nPoints, const Point* pPath, const BYT } else { - fprintf(stderr, "Strange output\n"); + DBG_ERROR( "PrinterGfx::DrawPolygonBezier: Strange output" ); } i+=3; } @@ -699,9 +677,7 @@ PrinterGfx::DrawPolyPolygonBezier (sal_uInt32 nPoly, const sal_uInt32 * pPoints, } else { -#if OSL_DEBUG_LEVEL > 1 - fprintf(stderr, "Strange output\n"); -#endif + DBG_ERROR( "PrinterGfx::DrawPolyPolygonBezier: Strange output" ); } j+=3; } diff --git a/vcl/unx/source/printergfx/glyphset.cxx b/vcl/unx/source/printergfx/glyphset.cxx index 156517d98220..5adff6683267 100644 --- a/vcl/unx/source/printergfx/glyphset.cxx +++ b/vcl/unx/source/printergfx/glyphset.cxx @@ -46,6 +46,7 @@ #include <set> #include <map> +#include <algorithm> using namespace vcl; using namespace psp; @@ -785,6 +786,17 @@ GlyphSet::PSUploadEncoding(osl::File* pOutFile, PrinterGfx &rGfx) return sal_True; } +struct EncEntry +{ + sal_uChar aEnc; + long aGID; + + EncEntry() : aEnc( 0 ), aGID( 0 ) {} + + bool operator<( const EncEntry& rRight ) const + { return aEnc < rRight.aEnc; } +}; + static void CreatePSUploadableFont( TrueTypeFont* pSrcFont, FILE* pTmpFile, const char* pGlyphSetName, int nGlyphCount, /*const*/ sal_uInt16* pRequestedGlyphs, /*const*/ sal_uChar* pEncoding, @@ -796,17 +808,29 @@ static void CreatePSUploadableFont( TrueTypeFont* pSrcFont, FILE* pTmpFile, if( bAllowType42 ) nTargetMask |= FontSubsetInfo::TYPE42_FONT; + std::vector< EncEntry > aSorted( nGlyphCount, EncEntry() ); + for( int i = 0; i < nGlyphCount; i++ ) + { + aSorted[i].aEnc = pEncoding[i]; + aSorted[i].aGID = pRequestedGlyphs[i]; + } + + std::stable_sort( aSorted.begin(), aSorted.end() ); + + std::vector< sal_uChar > aEncoding( nGlyphCount ); + std::vector< long > aRequestedGlyphs( nGlyphCount ); + + for( int i = 0; i < nGlyphCount; i++ ) + { + aEncoding[i] = aSorted[i].aEnc; + aRequestedGlyphs[i] = aSorted[i].aGID; + } + FontSubsetInfo aInfo; aInfo.LoadFont( pSrcFont ); -#if 1 // TODO: remove 16bit->long conversion when input args has been changed - long aRequestedGlyphs[256]; - for( int i = 0; i < nGlyphCount; ++i ) - aRequestedGlyphs[i] = pRequestedGlyphs[i]; -#endif - aInfo.CreateFontSubset( nTargetMask, pTmpFile, pGlyphSetName, - aRequestedGlyphs, pEncoding, nGlyphCount, NULL ); + &aRequestedGlyphs[0], &aEncoding[0], nGlyphCount, NULL ); } sal_Bool diff --git a/vcl/unx/source/printergfx/printerjob.cxx b/vcl/unx/source/printergfx/printerjob.cxx index 783dd5ff2b47..1c42cafa4cb9 100644 --- a/vcl/unx/source/printergfx/printerjob.cxx +++ b/vcl/unx/source/printergfx/printerjob.cxx @@ -681,14 +681,6 @@ PrinterJob::StartPage (const JobData& rJobSetup) if( ! (pPageHeader && pPageBody) ) return sal_False; - /* #i7262# write setup only before first page - * don't do this in StartJob since the jobsetup there may be - * different. - */ - bool bSuccess = true; - if( 1 == maPageList.size() ) - m_aDocumentJobData = rJobSetup; - // write page header according to Document Structuring Conventions (DSC) WritePS (pPageHeader, "%%Page: "); WritePS (pPageHeader, aPageNo); @@ -722,13 +714,25 @@ PrinterJob::StartPage (const JobData& rJobSetup) WritePS (pPageHeader, pBBox); - if (bSuccess) - bSuccess = writePageSetup ( pPageHeader, rJobSetup ); - if(bSuccess) - m_aLastJobData = rJobSetup; + /* #i7262# #i65491# write setup only before first page + * (to %%Begin(End)Setup, instead of %%Begin(End)PageSetup) + * don't do this in StartJob since the jobsetup there may be + * different. + */ + bool bWriteFeatures = true; + if( 1 == maPageList.size() ) + { + m_aDocumentJobData = rJobSetup; + bWriteFeatures = false; + } + if ( writePageSetup( pPageHeader, rJobSetup, bWriteFeatures ) ) + { + m_aLastJobData = rJobSetup; + return true; + } - return bSuccess; + return false; } sal_Bool @@ -828,12 +832,9 @@ bool PrinterJob::writeFeatureList( osl::File* pFile, const JobData& rJob, bool b if( pKey->getSetupType() == PPDKey::DocumentSetup ) bEmit = true; } - else - { - if( pKey->getSetupType() == PPDKey::PageSetup || - pKey->getSetupType() == PPDKey::AnySetup ) - bEmit = true; - } + if( pKey->getSetupType() == PPDKey::PageSetup || + pKey->getSetupType() == PPDKey::AnySetup ) + bEmit = true; if( bEmit ) { const PPDValue* pValue = rJob.m_aContext.getValue( pKey ); @@ -866,13 +867,13 @@ bool PrinterJob::writeFeatureList( osl::File* pFile, const JobData& rJob, bool b return bSuccess; } -bool PrinterJob::writePageSetup( osl::File* pFile, const JobData& rJob ) +bool PrinterJob::writePageSetup( osl::File* pFile, const JobData& rJob, bool bWriteFeatures ) { bool bSuccess = true; WritePS (pFile, "%%BeginPageSetup\n%\n"); - - bSuccess = writeFeatureList( pFile, rJob, false ); + if ( bWriteFeatures ) + bSuccess = writeFeatureList( pFile, rJob, false ); WritePS (pFile, "%%EndPageSetup\n"); sal_Char pTranslate [128]; diff --git a/vcl/unx/source/window/salframe.cxx b/vcl/unx/source/window/salframe.cxx index 6219b50d6ec3..68c99e05da77 100644 --- a/vcl/unx/source/window/salframe.cxx +++ b/vcl/unx/source/window/salframe.cxx @@ -930,12 +930,13 @@ void X11SalFrame::ReleaseGraphics( SalGraphics *pGraphics ) pGraphics_ = NULL; } -void X11SalFrame::updateGraphics() +void X11SalFrame::updateGraphics( bool bClear ) { + Drawable aDrawable = bClear ? None : GetWindow(); if( pGraphics_ ) - pGraphics_->SetDrawable( GetWindow(), m_nScreen ); + pGraphics_->SetDrawable( aDrawable, m_nScreen ); if( pFreeGraphics_ ) - pFreeGraphics_->SetDrawable( GetWindow(), m_nScreen ); + pFreeGraphics_->SetDrawable( aDrawable, m_nScreen ); } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= @@ -2726,6 +2727,7 @@ void X11SalFrame::createNewWindow( XLIB_Window aNewParent, int nScreen ) } // first deinit frame + updateGraphics(true); if( mpInputContext ) { mpInputContext->UnsetICFocus( this ); @@ -2748,7 +2750,7 @@ void X11SalFrame::createNewWindow( XLIB_Window aNewParent, int nScreen ) Init( nStyle_ & ~SAL_FRAME_STYLE_PLUG, nScreen, NULL, true ); // update graphics if necessary - updateGraphics(); + updateGraphics(false); if( m_aTitle.Len() ) SetTitle( m_aTitle ); |