diff options
Diffstat (limited to 'vcl/source')
39 files changed, 1476 insertions, 721 deletions
diff --git a/vcl/source/app/dbggui.cxx b/vcl/source/app/dbggui.cxx index b22a7d21f357..dd9a5b4a15ee 100644 --- a/vcl/source/app/dbggui.cxx +++ b/vcl/source/app/dbggui.cxx @@ -1783,8 +1783,6 @@ void DbgDialogTest( Window* pWindow ) } // ======================================================================= -void DbgPrintShell( const char* pLine ); - #ifndef WNT #define USE_VCL_MSGBOX #define COPY_BUTTON_ID 25 @@ -1963,27 +1961,6 @@ void DbgPrintWindow( const char* pLine ) bIn = FALSE; } -// ----------------------------------------------------------------------- - -void DbgPrintShell( const char* pLine ) -{ -#if defined( WNT ) - // TODO: Shouldn't this be a IsDebuggerPresent()? - if ( GetSystemMetrics( SM_DEBUG ) ) - { - strcpy( aDbgOutBuf, pLine ); - strcat( aDbgOutBuf, "\r\n" ); - OutputDebugString( aDbgOutBuf ); - return; - } - - DbgPrintWindow( pLine ); -#endif -#ifdef UNX - fprintf( stderr, "%s\n", pLine ); -#endif -} - // ======================================================================= #ifdef WNT @@ -1996,7 +1973,6 @@ void DbgGUIInit() { DbgSetPrintMsgBox( DbgPrintMsgBox ); DbgSetPrintWindow( DbgPrintWindow ); - DbgSetPrintShell( DbgPrintShell ); #ifdef WNT DbgSetTestSolarMutex( ImplDbgTestSolarMutex ); #endif @@ -2008,7 +1984,6 @@ void DbgGUIDeInit() { DbgSetPrintMsgBox( NULL ); DbgSetPrintWindow( NULL ); - DbgSetPrintShell( NULL ); #ifdef WNT DbgSetTestSolarMutex( NULL ); #endif diff --git a/vcl/source/app/settings.cxx b/vcl/source/app/settings.cxx index 1aebe5913959..5ad3f6787461 100644..100755 --- a/vcl/source/app/settings.cxx +++ b/vcl/source/app/settings.cxx @@ -433,6 +433,7 @@ ImplStyleData::ImplStyleData() mnToolbarIconSize = STYLE_TOOLBAR_ICONSIZE_UNKNOWN; mnSymbolsStyle = STYLE_SYMBOLS_AUTO; mnPreferredSymbolsStyle = STYLE_SYMBOLS_AUTO; + mpFontOptions = NULL; SetStandardStyles(); } @@ -539,6 +540,7 @@ ImplStyleData::ImplStyleData( const ImplStyleData& rData ) : mnToolbarIconSize = rData.mnToolbarIconSize; mnSymbolsStyle = rData.mnSymbolsStyle; mnPreferredSymbolsStyle = rData.mnPreferredSymbolsStyle; + mpFontOptions = rData.mpFontOptions; } // ----------------------------------------------------------------------- diff --git a/vcl/source/control/button.cxx b/vcl/source/control/button.cxx index 1cda2308aa9c..1f45b5902381 100644 --- a/vcl/source/control/button.cxx +++ b/vcl/source/control/button.cxx @@ -1191,7 +1191,10 @@ void PushButton::ImplDrawPushButtonContent( OutputDevice* pDev, ULONG nDrawFlags else { Rectangle aSymbolRect; - ImplDrawAlignedImage( pDev, aPos, aSize, bLayout, 1, nDrawFlags, + ULONG nImageSep = 1 + (pDev->GetTextHeight()-10)/2; + if( nImageSep < 1 ) + nImageSep = 1; + ImplDrawAlignedImage( pDev, aPos, aSize, bLayout, nImageSep, nDrawFlags, nTextStyle, IsSymbol() ? &aSymbolRect : NULL ); if ( IsSymbol() && ! bLayout ) @@ -1320,6 +1323,7 @@ void PushButton::ImplDrawPushButton( bool bLayout ) if( bNativeOK ) return; + bool bRollOver = (IsMouseOver() && aInRect.IsInside( GetPointerPosPixel() )); if ( (bNativeOK=IsNativeControlSupported(CTRL_PUSHBUTTON, PART_ENTIRE_CONTROL)) == TRUE ) { PushButtonValue aPBVal; @@ -1334,7 +1338,7 @@ void PushButton::ImplDrawPushButton( bool bLayout ) if ( ImplGetButtonState() & BUTTON_DRAW_DEFAULT ) nState |= CTRL_STATE_DEFAULT; if ( Window::IsEnabled() ) nState |= CTRL_STATE_ENABLED; - if ( IsMouseOver() && aInRect.IsInside( GetPointerPosPixel() ) ) + if ( bRollOver ) nState |= CTRL_STATE_ROLLOVER; if( GetStyle() & WB_BEVELBUTTON ) @@ -1359,8 +1363,15 @@ void PushButton::ImplDrawPushButton( bool bLayout ) Size aInRectSize( LogicToPixel( Size( aInRect.GetWidth(), aInRect.GetHeight() ) ) ); aPBVal.mbSingleLine = (aInRectSize.Height() < 2 * aFontSize.Height() ); - bNativeOK = DrawNativeControl( CTRL_PUSHBUTTON, PART_ENTIRE_CONTROL, aCtrlRegion, nState, - aControlValue, rtl::OUString()/*PushButton::GetText()*/ ); + if( ((nState & CTRL_STATE_ROLLOVER) || HasFocus()) || ! (GetStyle() & WB_FLATBUTTON) ) + { + bNativeOK = DrawNativeControl( CTRL_PUSHBUTTON, PART_ENTIRE_CONTROL, aCtrlRegion, nState, + aControlValue, rtl::OUString()/*PushButton::GetText()*/ ); + } + else + { + bNativeOK = true; + } // draw content using the same aInRect as non-native VCL would do ImplDrawPushButtonContent( this, @@ -1374,8 +1385,21 @@ void PushButton::ImplDrawPushButton( bool bLayout ) if ( bNativeOK == FALSE ) { // draw PushButtonFrame, aInRect has content size afterwards - if( ! bLayout ) - ImplDrawPushButtonFrame( this, aInRect, nButtonStyle ); + if( (GetStyle() & WB_FLATBUTTON) ) + { + Rectangle aTempRect( aInRect ); + if( ! bLayout && (bRollOver || HasFocus()) ) + ImplDrawPushButtonFrame( this, aTempRect, nButtonStyle ); + aInRect.Left() += 2; + aInRect.Top() += 2; + aInRect.Right() -= 2; + aInRect.Bottom() -= 2; + } + else + { + if( ! bLayout ) + ImplDrawPushButtonFrame( this, aInRect, nButtonStyle ); + } // draw content ImplDrawPushButtonContent( this, 0, aInRect, bLayout ); diff --git a/vcl/source/control/fixed.cxx b/vcl/source/control/fixed.cxx index 4b83540c1aa1..37406293d7cf 100644 --- a/vcl/source/control/fixed.cxx +++ b/vcl/source/control/fixed.cxx @@ -496,16 +496,11 @@ void FixedLine::ImplDraw( bool bLayout ) { Size aOutSize = GetOutputSizePixel(); String aText = GetText(); - const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings(); WinBits nWinStyle = GetStyle(); MetricVector* pVector = bLayout ? &mpControlData->mpLayoutData->m_aUnicodeBoundRects : NULL; String* pDisplayText = bLayout ? &mpControlData->mpLayoutData->m_aDisplayText : NULL; - if ( rStyleSettings.GetOptions() & STYLE_OPTION_MONO ) - SetLineColor( Color( COL_BLACK ) ); - else - SetLineColor( rStyleSettings.GetShadowColor() ); - + DecorationView aDecoView( this ); if ( !aText.Len() || (nWinStyle & WB_VERT) ) { if( !pVector ) @@ -516,21 +511,12 @@ void FixedLine::ImplDraw( bool bLayout ) if ( nWinStyle & WB_VERT ) { nX = (aOutSize.Width()-1)/2; - DrawLine( Point( nX, 0 ), Point( nX, aOutSize.Height()-1 ) ); + aDecoView.DrawSeparator( Point( nX, 0 ), Point( nX, aOutSize.Height()-1 ) ); } else { nY = (aOutSize.Height()-1)/2; - DrawLine( Point( 0, nY ), Point( aOutSize.Width()-1, nY ) ); - } - - if ( !(rStyleSettings.GetOptions() & STYLE_OPTION_MONO) ) - { - SetLineColor( rStyleSettings.GetLightColor() ); - if ( nWinStyle & WB_VERT ) - DrawLine( Point( nX+1, 0 ), Point( nX+1, aOutSize.Height()-1 ) ); - else - DrawLine( Point( 0, nY+1 ), Point( aOutSize.Width()-1, nY+1 ) ); + aDecoView.DrawSeparator( Point( 0, nY ), Point( aOutSize.Width()-1, nY ), false ); } } } @@ -538,6 +524,7 @@ void FixedLine::ImplDraw( bool bLayout ) { USHORT nStyle = TEXT_DRAW_MNEMONIC | TEXT_DRAW_LEFT | TEXT_DRAW_VCENTER | TEXT_DRAW_ENDELLIPSIS; Rectangle aRect( 0, 0, aOutSize.Width(), aOutSize.Height() ); + const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings(); if ( !IsEnabled() ) nStyle |= TEXT_DRAW_DISABLE; @@ -551,12 +538,7 @@ void FixedLine::ImplDraw( bool bLayout ) if( !pVector ) { long nTop = aRect.Top() + ((aRect.GetHeight()-1)/2); - DrawLine( Point( aRect.Right()+FIXEDLINE_TEXT_BORDER, nTop ), Point( aOutSize.Width()-1, nTop ) ); - if ( !(rStyleSettings.GetOptions() & STYLE_OPTION_MONO) ) - { - SetLineColor( rStyleSettings.GetLightColor() ); - DrawLine( Point( aRect.Right()+FIXEDLINE_TEXT_BORDER, nTop+1 ), Point( aOutSize.Width()-1, nTop+1 ) ); - } + aDecoView.DrawSeparator( Point( aRect.Right()+FIXEDLINE_TEXT_BORDER, nTop ), Point( aOutSize.Width()-1, nTop ), false ); } } } diff --git a/vcl/source/control/slider.cxx b/vcl/source/control/slider.cxx index 5e7e9709607f..2390a8e3e9a6 100644 --- a/vcl/source/control/slider.cxx +++ b/vcl/source/control/slider.cxx @@ -168,6 +168,7 @@ void Slider::ImplInitSettings() void Slider::ImplUpdateRects( BOOL bUpdate ) { Rectangle aOldThumbRect = maThumbRect; + bool bInvalidateAll = false; if ( mnThumbPixRange ) { @@ -193,6 +194,18 @@ void Slider::ImplUpdateRects( BOOL bUpdate ) } else maChannel2Rect.SetEmpty(); + + const Region aControlRegion( Rectangle( Point(0,0), Size( SLIDER_THUMB_SIZE, 10 ) ) ); + Region aThumbBounds, aThumbContent; + if ( GetNativeControlRegion( CTRL_SLIDER, PART_THUMB_HORZ, + aControlRegion, 0, ImplControlValue(), rtl::OUString(), + aThumbBounds, aThumbContent ) ) + { + Rectangle aRect( aThumbBounds.GetBoundRect() ); + maThumbRect.Left() = mnThumbPixPos - aRect.GetWidth()/2; + maThumbRect.Right() = maThumbRect.Left() + aRect.GetWidth() - 1; + bInvalidateAll = true; + } } else { @@ -216,6 +229,18 @@ void Slider::ImplUpdateRects( BOOL bUpdate ) } else maChannel2Rect.SetEmpty(); + + const Region aControlRegion( Rectangle( Point(0,0), Size( 10, SLIDER_THUMB_SIZE ) ) ); + Region aThumbBounds, aThumbContent; + if ( GetNativeControlRegion( CTRL_SLIDER, PART_THUMB_VERT, + aControlRegion, 0, ImplControlValue(), rtl::OUString(), + aThumbBounds, aThumbContent ) ) + { + Rectangle aRect( aThumbBounds.GetBoundRect() ); + maThumbRect.Top() = mnThumbPixPos - aRect.GetHeight()/2; + maThumbRect.Bottom() = maThumbRect.Top() + aRect.GetHeight() - 1; + bInvalidateAll = true; + } } } else @@ -229,17 +254,22 @@ void Slider::ImplUpdateRects( BOOL bUpdate ) { if ( aOldThumbRect != maThumbRect ) { - Region aInvalidRegion( aOldThumbRect ); - aInvalidRegion.Union( maThumbRect ); - - if( !IsBackground() && GetParent() ) + if( bInvalidateAll ) + Invalidate(); + else { - const Point aPos( GetPosPixel() ); - aInvalidRegion.Move( aPos.X(), aPos.Y() ); - GetParent()->Invalidate( aInvalidRegion, INVALIDATE_TRANSPARENT | INVALIDATE_UPDATE ); + Region aInvalidRegion( aOldThumbRect ); + aInvalidRegion.Union( maThumbRect ); + + if( !IsBackground() && GetParent() ) + { + const Point aPos( GetPosPixel() ); + aInvalidRegion.Move( aPos.X(), aPos.Y() ); + GetParent()->Invalidate( aInvalidRegion, INVALIDATE_TRANSPARENT | INVALIDATE_UPDATE ); + } + else + Invalidate( aInvalidRegion ); } - else - Invalidate( aInvalidRegion ); } } } @@ -357,6 +387,29 @@ void Slider::ImplDraw( USHORT nDrawFlags ) if ( mbCalcSize ) ImplCalc( FALSE ); + ControlPart nPart = (GetStyle() & WB_HORZ) ? PART_TRACK_HORZ_AREA : PART_TRACK_VERT_AREA; + ImplControlValue aControlValue( BUTTONVALUE_DONTKNOW, rtl::OUString(), 0 ); + ControlState nState = ( IsEnabled() ? CTRL_STATE_ENABLED : 0 ) | ( HasFocus() ? CTRL_STATE_FOCUSED : 0 ); + SliderValue sldValue; + + sldValue.mnMin = mnMinRange; + sldValue.mnMax = mnMaxRange; + sldValue.mnCur = mnThumbPos; + sldValue.maThumbRect = maThumbRect; + + if( IsMouseOver() ) + { + if( maThumbRect.IsInside( GetPointerPosPixel() ) ) + sldValue.mnThumbState |= CTRL_STATE_ROLLOVER; + } + aControlValue.setOptionalVal( (void *)(&sldValue) ); + + const Region aCtrlRegion( Rectangle( Point(0,0), GetOutputSizePixel() ) ); + bool bNativeOK = DrawNativeControl( CTRL_SLIDER, nPart, + aCtrlRegion, nState, aControlValue, rtl::OUString() ); + if( bNativeOK ) + return; + if ( (nDrawFlags & SLIDER_DRAW_CHANNEL1) && !maChannel1Rect.IsEmpty() ) { long nRectSize; diff --git a/vcl/source/control/tabctrl.cxx b/vcl/source/control/tabctrl.cxx index 5c08cdb8a36b..741267044829 100644 --- a/vcl/source/control/tabctrl.cxx +++ b/vcl/source/control/tabctrl.cxx @@ -174,6 +174,9 @@ void TabControl::ImplInit( Window* pParent, WinBits nStyle ) // otherwise they will paint with a wrong background if( IsNativeControlSupported(CTRL_TAB_PANE, PART_ENTIRE_CONTROL) ) EnableChildTransparentMode( TRUE ); + + if ( pParent->IsDialog() ) + pParent->AddChildEventListener( LINK( this, TabControl, ImplWindowEventListener ) ); } // ----------------------------------------------------------------- @@ -288,6 +291,9 @@ void TabControl::ImplLoadRes( const ResId& rResId ) TabControl::~TabControl() { + if ( GetParent()->IsDialog() ) + GetParent()->RemoveChildEventListener( LINK( this, TabControl, ImplWindowEventListener ) ); + ImplFreeLayoutData(); // TabCtrl-Daten loeschen @@ -1070,6 +1076,42 @@ void TabControl::ImplDrawItem( ImplTabItem* pItem, const Rectangle& rCurRect, bo // ----------------------------------------------------------------------- +long TabControl::ImplHandleKeyEvent( const KeyEvent& rKeyEvent ) +{ + long nRet = 0; + + if ( GetPageCount() > 1 ) + { + KeyCode aKeyCode = rKeyEvent.GetKeyCode(); + USHORT nKeyCode = aKeyCode.GetCode(); + + if ( aKeyCode.IsMod1() ) + { + if ( aKeyCode.IsShift() || (nKeyCode == KEY_PAGEUP) ) + { + if ( (nKeyCode == KEY_TAB) || (nKeyCode == KEY_PAGEUP) ) + { + ImplActivateTabPage( FALSE ); + nRet = 1; + } + } + else + { + if ( (nKeyCode == KEY_TAB) || (nKeyCode == KEY_PAGEDOWN) ) + { + ImplActivateTabPage( TRUE ); + nRet = 1; + } + } + } + } + + return nRet; +} + + +// ----------------------------------------------------------------------- + IMPL_LINK( TabControl, ImplScrollBtnHdl, PushButton*, EMPTYARG ) { ImplSetScrollBtnsState(); @@ -1086,6 +1128,24 @@ IMPL_LINK( TabControl, ImplListBoxSelectHdl, ListBox*, EMPTYARG ) // ----------------------------------------------------------------------- +IMPL_LINK( TabControl, ImplWindowEventListener, VclSimpleEvent*, pEvent ) +{ + if ( pEvent && pEvent->ISA( VclWindowEvent ) && (pEvent->GetId() == VCLEVENT_WINDOW_KEYINPUT) ) + { + VclWindowEvent* pWindowEvent = static_cast< VclWindowEvent* >(pEvent); + // Do not handle events from TabControl or it's children, which is done in Notify(), where the events can be consumed. + if ( !IsWindowOrChild( pWindowEvent->GetWindow() ) ) + { + KeyEvent* pKeyEvent = static_cast< KeyEvent* >(pWindowEvent->GetData()); + ImplHandleKeyEvent( *pKeyEvent ); + } + } + return 0; +} + + +// ----------------------------------------------------------------------- + void TabControl::MouseButtonDown( const MouseEvent& rMEvt ) { if( mpTabCtrlData->mpListBox == NULL ) @@ -1655,44 +1715,14 @@ long TabControl::PreNotify( NotifyEvent& rNEvt ) // ----------------------------------------------------------------------- -bool TabControl::ImplHandleNotifyEvent( NotifyEvent& rNEvt ) -{ - if ( (rNEvt.GetType() == EVENT_KEYINPUT) && (GetPageCount() > 1) ) - { - const KeyEvent* pKEvt = rNEvt.GetKeyEvent(); - KeyCode aKeyCode = pKEvt->GetKeyCode(); - USHORT nKeyCode = aKeyCode.GetCode(); - - if ( aKeyCode.IsMod1() ) - { - if ( aKeyCode.IsShift() || (nKeyCode == KEY_PAGEUP) ) - { - if ( (nKeyCode == KEY_TAB) || (nKeyCode == KEY_PAGEUP) ) - { - ImplActivateTabPage( FALSE ); - return TRUE; - } - } - else - { - if ( (nKeyCode == KEY_TAB) || (nKeyCode == KEY_PAGEDOWN) ) - { - ImplActivateTabPage( TRUE ); - return TRUE; - } - } - } - } - return false; -} - - -// ----------------------------------------------------------------------- - long TabControl::Notify( NotifyEvent& rNEvt ) { + long nRet = 0; + + if ( rNEvt.GetType() == EVENT_KEYINPUT ) + nRet = ImplHandleKeyEvent( *rNEvt.GetKeyEvent() ); - return ImplHandleNotifyEvent( rNEvt ) ? TRUE : Control::Notify( rNEvt ); + return nRet ? nRet : Control::Notify( rNEvt ); } // ----------------------------------------------------------------------- diff --git a/vcl/source/fontsubset/cff.cxx b/vcl/source/fontsubset/cff.cxx index 39964f635c9c..9884e7016fee 100644 --- a/vcl/source/fontsubset/cff.cxx +++ b/vcl/source/fontsubset/cff.cxx @@ -391,11 +391,9 @@ public: // used by charstring converter void setCharStringType( int); void fakeLocalSubrCount( int nLocalSubrs ) { maCffLocal[0].mnLocalSubrCount=nLocalSubrs;} - void readCharString( const U8* pTypeOps, int nTypeLen); protected: int convert2Type1Ops( CffLocal*, const U8* pType2Ops, int nType2Len, U8* pType1Ops); private: - void readTypeOp( CffSubsetterContext&); void convertOneTypeOp( void); void convertOneTypeEsc( void); void callType2Subr( bool bGlobal, int nSubrNumber); @@ -431,7 +429,6 @@ private: int getGlyphSID( int nGlyphIndex) const; const char* getGlyphName( int nGlyphIndex); - void readTypeOp( void); void read2push( void); void pop2write( void); void writeType1Val( ValType); @@ -611,25 +608,6 @@ void CffSubsetterContext::setCharStringType( int nVal) // -------------------------------------------------------------------- -void CffSubsetterContext::readCharString( const U8* pTypeOps, int nTypeLen) -{ - mnStackIdx = 0; - mnHintSize = 0; - mnHorzHintSize = 0; - maCharWidth = -1; - - assert( nTypeLen >= 0); -// assert( nEnd <= getLength()); - mpReadPtr = pTypeOps; - mpReadEnd = mpReadPtr + nTypeLen; - // reset the execution context - while( mpReadPtr < mpReadEnd) - readTypeOp(); -//### assert( tellRel() == nEnd); -} - -// -------------------------------------------------------------------- - void CffSubsetterContext::readDictOp( void) { ValType nVal = 0; @@ -765,112 +743,6 @@ void CffSubsetterContext::readDictOp( void) // -------------------------------------------------------------------- -void CffSubsetterContext::readTypeOp( void) -{ - int nVal = 0; - const U8 c = *mpReadPtr; - if( (c <= 31) && (c != 28) ) { - const int nOpId = *(mpReadPtr++); - const char* pCmdName; - if( nOpId != 12) - pCmdName = mpCharStringOps[ nOpId]; - else { - const int nExtId = *(mpReadPtr++); - pCmdName = mpCharStringEscs[ nExtId]; - } - - if( !pCmdName ) - pCmdName = ".NULL"; - // handle typeop parameters - int nMinStack = -1, nMaxStack = -1; - switch( *pCmdName) { - default: fprintf( stderr, "unsupported TypeOp.type=\'%c\'\n", *pCmdName); break; - case '.': nMinStack = 0; nMaxStack = 999; break; - case '0': nMinStack = nMaxStack = 0; break; - case '1': nMinStack = nMaxStack = 1; break; - case '2': nMinStack = nMaxStack = 2; break; - case '4': nMinStack = nMaxStack = 4; break; - case '5': nMinStack = nMaxStack = 5; break; // not used for Type2 ops - case '6': nMinStack = nMaxStack = 6; break; - case '7': nMinStack = nMaxStack = 7; break; - case '9': nMinStack = nMaxStack = 9; break; - case 'f': nMinStack = nMaxStack = 11; break; - case 'F': nMinStack = nMaxStack = 13; break; - case 'A': nMinStack = 2; nMaxStack = 999; break; - case 'C': nMinStack = 6; nMaxStack = 999; break; - case 'E': nMinStack = 1; nMaxStack = 999; break; - case 'G': nMinStack = 1; nMaxStack = 999; // global subr - nVal = peekInt(); - // TODO global subr - break; - case 'L': // local subr - nMinStack = 1; nMaxStack = 999; - nVal = peekInt(); - // TODO local subr - break; - case 'I': // operands for "index" -#if 0 - nMinStack = nValStack[ nStackIdx-1]; - if( nMinStack < 0) nMinStack = 0; - nMinStack += 1; -#else - fprintf( stderr, "TODO: Iindex op\n"); -#endif - break; - case 'R': // operands for "rol" -#if 0 - nMinStack = nValStack[ nStackIdx-2]; -#else - fprintf( stderr, "TODO: Rrol op\n"); -#endif - case 'X': // operands for "return" - nMinStack = 0; - nMaxStack = /*### (!bInSubrs)? 0 :###*/999; - break; - case 'H': // "hstemhm" - case 'h': // "hstem" - addHints( false); - nMinStack = nMaxStack = 0; - break; - case 'V': // "vstemhm" - case 'v': // "vstem" - addHints( true); - nMinStack = nMaxStack = 0; - break; - case 'K': // "hintmask" or "cntrmask" - addHints( true); // implicit vstemhm - nMinStack = nMaxStack = 0; - break; - case 'e': // endchar - updateWidth( (size() >= 1) && (size() != 4)); - nMinStack = nMaxStack = 0; - if( size() == 4) - fprintf( stderr,"Deprecated SEAC-like endchar is not supported for CFF subsetting!\n"); // TODO: handle deprecated op - break; - case 'm': // hmoveto or vmoveto - updateWidth( size() > 1); - nMinStack = 1; - nMaxStack = nMinStack; - break; - case 'M': // rmoveto - updateWidth( size() > 2); - nMinStack = 2; - nMaxStack = nMinStack; - break; - } - - clear(); - return; - } - - if( (c >= 32) || (c == 28)) { -// --mpReadPtr; - read2push(); - } -} - -// -------------------------------------------------------------------- - void CffSubsetterContext::read2push() { ValType aVal = 0; diff --git a/vcl/source/gdi/bitmapex.cxx b/vcl/source/gdi/bitmapex.cxx index a5b274bfd8e8..38402af626c2 100644 --- a/vcl/source/gdi/bitmapex.cxx +++ b/vcl/source/gdi/bitmapex.cxx @@ -811,7 +811,7 @@ sal_uInt8 BitmapEx::GetTransparency(sal_Int32 nX, sal_Int32 nY) const } else { - if(0x00 != aBitmapColor.GetIndex()) + if(0x00 == aBitmapColor.GetIndex()) { nTransparency = 0x00; } diff --git a/vcl/source/gdi/outdev3.cxx b/vcl/source/gdi/outdev3.cxx index 895a98dfaf1a..630e58a1f2bf 100644 --- a/vcl/source/gdi/outdev3.cxx +++ b/vcl/source/gdi/outdev3.cxx @@ -68,6 +68,9 @@ #ifdef ENABLE_GRAPHITE #include <vcl/graphite_features.hxx> #endif +#ifdef USE_BUILTIN_RASTERIZER +#include <vcl/glyphcache.hxx> +#endif #include <vcl/unohelp.hxx> #include <pdfwriter_impl.hxx> @@ -995,21 +998,28 @@ ImplFontEntry::~ImplFontEntry() // ----------------------------------------------------------------------- -inline void ImplFontEntry::AddFallbackForUnicode( sal_UCS4 cChar, const String& rFontName ) +size_t ImplFontEntry::GFBCacheKey_Hash::operator()( const GFBCacheKey& rData ) const +{ + std::hash<sal_UCS4> a; + std::hash<int > b; + return a(rData.first) ^ b(rData.second); +} + +inline void ImplFontEntry::AddFallbackForUnicode( sal_UCS4 cChar, FontWeight eWeight, const String& rFontName ) { if( !mpUnicodeFallbackList ) mpUnicodeFallbackList = new UnicodeFallbackList; - (*mpUnicodeFallbackList)[cChar] = rFontName; + (*mpUnicodeFallbackList)[ GFBCacheKey(cChar,eWeight) ] = rFontName; } // ----------------------------------------------------------------------- -inline bool ImplFontEntry::GetFallbackForUnicode( sal_UCS4 cChar, String* pFontName ) const +inline bool ImplFontEntry::GetFallbackForUnicode( sal_UCS4 cChar, FontWeight eWeight, String* pFontName ) const { if( !mpUnicodeFallbackList ) return false; - UnicodeFallbackList::const_iterator it = mpUnicodeFallbackList->find( cChar ); + UnicodeFallbackList::const_iterator it = mpUnicodeFallbackList->find( GFBCacheKey(cChar,eWeight) ); if( it == mpUnicodeFallbackList->end() ) return false; @@ -1019,10 +1029,10 @@ inline bool ImplFontEntry::GetFallbackForUnicode( sal_UCS4 cChar, String* pFontN // ----------------------------------------------------------------------- -inline void ImplFontEntry::IgnoreFallbackForUnicode( sal_UCS4 cChar, const String& rFontName ) +inline void ImplFontEntry::IgnoreFallbackForUnicode( sal_UCS4 cChar, FontWeight eWeight, const String& rFontName ) { // DBG_ASSERT( mpUnicodeFallbackList, "ImplFontEntry::IgnoreFallbackForUnicode no list" ); - UnicodeFallbackList::iterator it = mpUnicodeFallbackList->find( cChar ); + UnicodeFallbackList::iterator it = mpUnicodeFallbackList->find( GFBCacheKey(cChar,eWeight) ); // DBG_ASSERT( it != mpUnicodeFallbackList->end(), "ImplFontEntry::IgnoreFallbackForUnicode no match" ); if( it == mpUnicodeFallbackList->end() ) return; @@ -1327,6 +1337,7 @@ void ImplDevFontList::InitGenericGlyphFallback( void ) const "muktinarrow", "", "phetsarathot", "", "padauk", "pinlonmyanmar", "", + "iskoolapota", "lklug", "", 0 }; @@ -1417,7 +1428,7 @@ ImplDevFontListData* ImplDevFontList::GetGlyphFallbackFont( ImplFontSelectData& while( nStrIndex < rMissingCodes.getLength() ) { cChar = rMissingCodes.iterateCodePoints( &nStrIndex ); - bCached = rFontSelData.mpFontEntry->GetFallbackForUnicode( cChar, &rFontSelData.maSearchName ); + bCached = rFontSelData.mpFontEntry->GetFallbackForUnicode( cChar, rFontSelData.GetWeight(), &rFontSelData.maSearchName ); // ignore entries which don't have a fallback if( !bCached || (rFontSelData.maSearchName.Len() != 0) ) break; @@ -1433,7 +1444,7 @@ ImplDevFontListData* ImplDevFontList::GetGlyphFallbackFont( ImplFontSelectData& while( nStrIndex < rMissingCodes.getLength() ) { cChar = rMissingCodes.iterateCodePoints( &nStrIndex ); - bCached = rFontSelData.mpFontEntry->GetFallbackForUnicode( cChar, &aFontName ); + bCached = rFontSelData.mpFontEntry->GetFallbackForUnicode( cChar, rFontSelData.GetWeight(), &aFontName ); if( !bCached || (rFontSelData.maSearchName != aFontName) ) pRemainingCodes[ nRemainingLength++ ] = cChar; } @@ -1452,8 +1463,8 @@ ImplDevFontListData* ImplDevFontList::GetGlyphFallbackFont( ImplFontSelectData& // cache the result even if there was no match for(;;) { - if( !rFontSelData.mpFontEntry->GetFallbackForUnicode( cChar, &rFontSelData.maSearchName ) ) - rFontSelData.mpFontEntry->AddFallbackForUnicode( cChar, rFontSelData.maSearchName ); + if( !rFontSelData.mpFontEntry->GetFallbackForUnicode( cChar, rFontSelData.GetWeight(), &rFontSelData.maSearchName ) ) + rFontSelData.mpFontEntry->AddFallbackForUnicode( cChar, rFontSelData.GetWeight(), rFontSelData.maSearchName ); if( nStrIndex >= aOldMissingCodes.getLength() ) break; cChar = aOldMissingCodes.iterateCodePoints( &nStrIndex ); @@ -1464,7 +1475,7 @@ ImplDevFontListData* ImplDevFontList::GetGlyphFallbackFont( ImplFontSelectData& for( nStrIndex = 0; nStrIndex < rMissingCodes.getLength(); ) { cChar = rMissingCodes.iterateCodePoints( &nStrIndex ); - rFontSelData.mpFontEntry->IgnoreFallbackForUnicode( cChar, rFontSelData.maSearchName ); + rFontSelData.mpFontEntry->IgnoreFallbackForUnicode( cChar, rFontSelData.GetWeight(), rFontSelData.maSearchName ); } } } @@ -2080,11 +2091,14 @@ ImplDevFontListData* ImplDevFontList::FindDefaultFont() const ImplDevFontList* ImplDevFontList::Clone( bool bScalable, bool bEmbeddable ) const { ImplDevFontList* pClonedList = new ImplDevFontList; - pClonedList->mbMatchData = mbMatchData; +// pClonedList->mbMatchData = mbMatchData; pClonedList->mbMapNames = mbMapNames; pClonedList->mpPreMatchHook = mpPreMatchHook; pClonedList->mpFallbackHook = mpFallbackHook; + // TODO: clone the config-font attributes too? + pClonedList->mbMatchData = false; + DevFontList::const_iterator it = maDevFontList.begin(); for(; it != maDevFontList.end(); ++it ) { @@ -2780,6 +2794,11 @@ void ImplFontCache::Invalidate() maFontInstanceList.clear(); DBG_ASSERT( (mnRef0Count==0), "ImplFontCache::Invalidate() - mnRef0Count non-zero" ); + +#ifdef USE_BUILTIN_RASTERIZER + // TODO: eventually move into SalGraphics layer + GlyphCache::GetInstance().InvalidateAllGlyphs(); +#endif } // ======================================================================= @@ -5893,15 +5912,16 @@ SalLayout* OutputDevice::ImplLayout( const String& rOrigStr, ImplInitFont(); // check string index and length - String aStr = rOrigStr; - if( (ULONG)nMinIndex + nLen >= aStr.Len() ) + if( (unsigned)nMinIndex + nLen > rOrigStr.Len() ) { - if( nMinIndex < aStr.Len() ) - nLen = aStr.Len() - nMinIndex; - else + const int nNewLen = (int)rOrigStr.Len() - nMinIndex; + if( nNewLen <= 0 ) return NULL; + nLen = static_cast<xub_StrLen>(nNewLen); } + String aStr = rOrigStr; + // filter out special markers if( bFilter ) { diff --git a/vcl/source/gdi/outmap.cxx b/vcl/source/gdi/outmap.cxx index 568e8d836045..189ba4c29e59 100644 --- a/vcl/source/gdi/outmap.cxx +++ b/vcl/source/gdi/outmap.cxx @@ -50,6 +50,7 @@ #include <vcl/outdev.h> #include <vcl/salgdi.hxx> #include <basegfx/matrix/b2dhommatrix.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> #include <basegfx/polygon/b2dpolypolygon.hxx> #define USE_64BIT_INTS @@ -1097,6 +1098,41 @@ basegfx::B2DHomMatrix OutputDevice::GetInverseViewTransformation() const // ----------------------------------------------------------------------- +// #i75163# +basegfx::B2DHomMatrix OutputDevice::GetViewTransformation( const MapMode& rMapMode ) const +{ + // #i82615# + ImplMapRes aMapRes; + ImplThresholdRes aThresRes; + ImplCalcMapResolution( rMapMode, mnDPIX, mnDPIY, aMapRes, aThresRes ); + + basegfx::B2DHomMatrix aTransform; + + const double fScaleFactorX((double)mnDPIX * (double)aMapRes.mnMapScNumX / (double)aMapRes.mnMapScDenomX); + const double fScaleFactorY((double)mnDPIY * (double)aMapRes.mnMapScNumY / (double)aMapRes.mnMapScDenomY); + const double fZeroPointX(((double)aMapRes.mnMapOfsX * fScaleFactorX) + (double)mnOutOffOrigX); + const double fZeroPointY(((double)aMapRes.mnMapOfsY * fScaleFactorY) + (double)mnOutOffOrigY); + + aTransform.set(0, 0, fScaleFactorX); + aTransform.set(1, 1, fScaleFactorY); + aTransform.set(0, 2, fZeroPointX); + aTransform.set(1, 2, fZeroPointY); + + return aTransform; +} + +// ----------------------------------------------------------------------- + +// #i75163# +basegfx::B2DHomMatrix OutputDevice::GetInverseViewTransformation( const MapMode& rMapMode ) const +{ + basegfx::B2DHomMatrix aMatrix( GetViewTransformation( rMapMode ) ); + aMatrix.invert(); + return aMatrix; +} + +// ----------------------------------------------------------------------- + basegfx::B2DHomMatrix OutputDevice::ImplGetDeviceTransformation() const { basegfx::B2DHomMatrix aTransformation = GetViewTransformation(); @@ -1218,6 +1254,26 @@ PolyPolygon OutputDevice::LogicToPixel( const PolyPolygon& rLogicPolyPoly ) cons // ----------------------------------------------------------------------- +basegfx::B2DPolygon OutputDevice::LogicToPixel( const basegfx::B2DPolygon& rLogicPoly ) const +{ + basegfx::B2DPolygon aTransformedPoly = rLogicPoly; + const ::basegfx::B2DHomMatrix& rTransformationMatrix = GetViewTransformation(); + aTransformedPoly.transform( rTransformationMatrix ); + return aTransformedPoly; +} + +// ----------------------------------------------------------------------- + +basegfx::B2DPolyPolygon OutputDevice::LogicToPixel( const basegfx::B2DPolyPolygon& rLogicPolyPoly ) const +{ + basegfx::B2DPolyPolygon aTransformedPoly = rLogicPolyPoly; + const ::basegfx::B2DHomMatrix& rTransformationMatrix = GetViewTransformation(); + aTransformedPoly.transform( rTransformationMatrix ); + return aTransformedPoly; +} + +// ----------------------------------------------------------------------- + Region OutputDevice::LogicToPixel( const Region& rLogicRegion ) const { DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); @@ -1402,6 +1458,28 @@ PolyPolygon OutputDevice::LogicToPixel( const PolyPolygon& rLogicPolyPoly, // ----------------------------------------------------------------------- +basegfx::B2DPolyPolygon OutputDevice::LogicToPixel( const basegfx::B2DPolyPolygon& rLogicPolyPoly, + const MapMode& rMapMode ) const +{ + basegfx::B2DPolyPolygon aTransformedPoly = rLogicPolyPoly; + const ::basegfx::B2DHomMatrix& rTransformationMatrix = GetViewTransformation( rMapMode ); + aTransformedPoly.transform( rTransformationMatrix ); + return aTransformedPoly; +} + +// ----------------------------------------------------------------------- + +basegfx::B2DPolygon OutputDevice::LogicToPixel( const basegfx::B2DPolygon& rLogicPoly, + const MapMode& rMapMode ) const +{ + basegfx::B2DPolygon aTransformedPoly = rLogicPoly; + const ::basegfx::B2DHomMatrix& rTransformationMatrix = GetViewTransformation( rMapMode ); + aTransformedPoly.transform( rTransformationMatrix ); + return aTransformedPoly; +} + +// ----------------------------------------------------------------------- + Region OutputDevice::LogicToPixel( const Region& rLogicRegion, const MapMode& rMapMode ) const { @@ -1553,6 +1631,26 @@ PolyPolygon OutputDevice::PixelToLogic( const PolyPolygon& rDevicePolyPoly ) con // ----------------------------------------------------------------------- +basegfx::B2DPolygon OutputDevice::PixelToLogic( const basegfx::B2DPolygon& rPixelPoly ) const +{ + basegfx::B2DPolygon aTransformedPoly = rPixelPoly; + const ::basegfx::B2DHomMatrix& rTransformationMatrix = GetInverseViewTransformation(); + aTransformedPoly.transform( rTransformationMatrix ); + return aTransformedPoly; +} + +// ----------------------------------------------------------------------- + +basegfx::B2DPolyPolygon OutputDevice::PixelToLogic( const basegfx::B2DPolyPolygon& rPixelPolyPoly ) const +{ + basegfx::B2DPolyPolygon aTransformedPoly = rPixelPolyPoly; + const ::basegfx::B2DHomMatrix& rTransformationMatrix = GetInverseViewTransformation(); + aTransformedPoly.transform( rTransformationMatrix ); + return aTransformedPoly; +} + +// ----------------------------------------------------------------------- + Region OutputDevice::PixelToLogic( const Region& rDeviceRegion ) const { DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); @@ -1732,6 +1830,28 @@ PolyPolygon OutputDevice::PixelToLogic( const PolyPolygon& rDevicePolyPoly, // ----------------------------------------------------------------------- +basegfx::B2DPolygon OutputDevice::PixelToLogic( const basegfx::B2DPolygon& rPixelPoly, + const MapMode& rMapMode ) const +{ + basegfx::B2DPolygon aTransformedPoly = rPixelPoly; + const ::basegfx::B2DHomMatrix& rTransformationMatrix = GetInverseViewTransformation( rMapMode ); + aTransformedPoly.transform( rTransformationMatrix ); + return aTransformedPoly; +} + +// ----------------------------------------------------------------------- + +basegfx::B2DPolyPolygon OutputDevice::PixelToLogic( const basegfx::B2DPolyPolygon& rPixelPolyPoly, + const MapMode& rMapMode ) const +{ + basegfx::B2DPolyPolygon aTransformedPoly = rPixelPolyPoly; + const ::basegfx::B2DHomMatrix& rTransformationMatrix = GetInverseViewTransformation( rMapMode ); + aTransformedPoly.transform( rTransformationMatrix ); + return aTransformedPoly; +} + +// ----------------------------------------------------------------------- + Region OutputDevice::PixelToLogic( const Region& rDeviceRegion, const MapMode& rMapMode ) const { @@ -2159,6 +2279,96 @@ Size OutputDevice::LogicToLogic( const Size& rSzSource, // ----------------------------------------------------------------------- +basegfx::B2DPolygon OutputDevice::LogicToLogic( const basegfx::B2DPolygon& rPolySource, + const MapMode& rMapModeSource, + const MapMode& rMapModeDest ) +{ + if ( rMapModeSource == rMapModeDest ) + return rPolySource; + + MapUnit eUnitSource = rMapModeSource.GetMapUnit(); + MapUnit eUnitDest = rMapModeDest.GetMapUnit(); + ENTER2( eUnitSource, eUnitDest ); + + basegfx::B2DHomMatrix aTransform; + + if ( rMapModeSource.mpImplMapMode->mbSimple && + rMapModeDest.mpImplMapMode->mbSimple ) + { + ENTER3( eUnitSource, eUnitDest ); + + const double fScaleFactor((double)nNumerator / (double)nDenominator); + aTransform.set(0, 0, fScaleFactor); + aTransform.set(1, 1, fScaleFactor); + } + else + { + ENTER4( rMapModeSource, rMapModeDest ); + + const double fScaleFactorX( (double(aMapResSource.mnMapScNumX) * double(aMapResDest.mnMapScDenomX)) + / (double(aMapResSource.mnMapScDenomX) * double(aMapResDest.mnMapScNumX)) ); + const double fScaleFactorY( (double(aMapResSource.mnMapScNumY) * double(aMapResDest.mnMapScDenomY)) + / (double(aMapResSource.mnMapScDenomY) * double(aMapResDest.mnMapScNumY)) ); + const double fZeroPointX(double(aMapResSource.mnMapOfsX) * fScaleFactorX - double(aMapResDest.mnMapOfsX)); + const double fZeroPointY(double(aMapResSource.mnMapOfsY) * fScaleFactorY - double(aMapResDest.mnMapOfsY)); + + aTransform.set(0, 0, fScaleFactorX); + aTransform.set(1, 1, fScaleFactorY); + aTransform.set(0, 2, fZeroPointX); + aTransform.set(1, 2, fZeroPointY); + } + basegfx::B2DPolygon aPoly( rPolySource ); + aPoly.transform( aTransform ); + return aPoly; +} + +// ----------------------------------------------------------------------- + +basegfx::B2DPolyPolygon OutputDevice::LogicToLogic( const basegfx::B2DPolyPolygon& rPolySource, + const MapMode& rMapModeSource, + const MapMode& rMapModeDest ) +{ + if ( rMapModeSource == rMapModeDest ) + return rPolySource; + + MapUnit eUnitSource = rMapModeSource.GetMapUnit(); + MapUnit eUnitDest = rMapModeDest.GetMapUnit(); + ENTER2( eUnitSource, eUnitDest ); + + basegfx::B2DHomMatrix aTransform; + + if ( rMapModeSource.mpImplMapMode->mbSimple && + rMapModeDest.mpImplMapMode->mbSimple ) + { + ENTER3( eUnitSource, eUnitDest ); + + const double fScaleFactor((double)nNumerator / (double)nDenominator); + aTransform.set(0, 0, fScaleFactor); + aTransform.set(1, 1, fScaleFactor); + } + else + { + ENTER4( rMapModeSource, rMapModeDest ); + + const double fScaleFactorX( (double(aMapResSource.mnMapScNumX) * double(aMapResDest.mnMapScDenomX)) + / (double(aMapResSource.mnMapScDenomX) * double(aMapResDest.mnMapScNumX)) ); + const double fScaleFactorY( (double(aMapResSource.mnMapScNumY) * double(aMapResDest.mnMapScDenomY)) + / (double(aMapResSource.mnMapScDenomY) * double(aMapResDest.mnMapScNumY)) ); + const double fZeroPointX(double(aMapResSource.mnMapOfsX) * fScaleFactorX - double(aMapResDest.mnMapOfsX)); + const double fZeroPointY(double(aMapResSource.mnMapOfsY) * fScaleFactorY - double(aMapResDest.mnMapOfsY)); + + aTransform.set(0, 0, fScaleFactorX); + aTransform.set(1, 1, fScaleFactorY); + aTransform.set(0, 2, fZeroPointX); + aTransform.set(1, 2, fZeroPointY); + } + basegfx::B2DPolyPolygon aPoly( rPolySource ); + aPoly.transform( aTransform ); + return aPoly; +} + +// ----------------------------------------------------------------------- + Rectangle OutputDevice::LogicToLogic( const Rectangle& rRectSource, const MapMode& rMapModeSource, const MapMode& rMapModeDest ) diff --git a/vcl/source/gdi/pdfextoutdevdata.cxx b/vcl/source/gdi/pdfextoutdevdata.cxx index fefe904e371a..046bc4a8951d 100644 --- a/vcl/source/gdi/pdfextoutdevdata.cxx +++ b/vcl/source/gdi/pdfextoutdevdata.cxx @@ -27,10 +27,12 @@ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_vcl.hxx" -#include <vcl/pdfextoutdevdata.hxx> -#include <vcl/graph.hxx> -#include <vcl/outdev.hxx> -#include <vcl/gfxlink.hxx> +#include "vcl/pdfextoutdevdata.hxx" +#include "vcl/graph.hxx" +#include "vcl/outdev.hxx" +#include "vcl/gfxlink.hxx" +#include "basegfx/polygon/b2dpolygon.hxx" +#include "basegfx/polygon/b2dpolygontools.hxx" #include <boost/shared_ptr.hpp> @@ -430,7 +432,10 @@ sal_Bool PageSyncData::PlaySyncPageAct( PDFWriter& rWriter, sal_uInt32& rCurGDIM if ( bClippingNeeded ) { rWriter.Push(); - rWriter.SetClipRegion( aVisibleOutputRect ); + basegfx::B2DPolyPolygon aRect( basegfx::tools::createPolygonFromRect( + basegfx::B2DRectangle( aVisibleOutputRect.Left(), aVisibleOutputRect.Top(), + aVisibleOutputRect.Right(), aVisibleOutputRect.Bottom() ) ) ); + rWriter.SetClipRegion( aRect); } Bitmap aMask; SvMemoryStream aTmp; diff --git a/vcl/source/gdi/pdfwriter.cxx b/vcl/source/gdi/pdfwriter.cxx index 040d38f538c9..5dcce25a0315 100644 --- a/vcl/source/gdi/pdfwriter.cxx +++ b/vcl/source/gdi/pdfwriter.cxx @@ -346,7 +346,7 @@ void PDFWriter::SetClipRegion() ((PDFWriterImpl*)pImplementation)->clearClipRegion(); } -void PDFWriter::SetClipRegion( const Region& rRegion ) +void PDFWriter::SetClipRegion( const basegfx::B2DPolyPolygon& rRegion ) { ((PDFWriterImpl*)pImplementation)->setClipRegion( rRegion ); } @@ -356,7 +356,7 @@ void PDFWriter::MoveClipRegion( long nHorzMove, long nVertMove ) ((PDFWriterImpl*)pImplementation)->moveClipRegion( nHorzMove, nVertMove ); } -void PDFWriter::IntersectClipRegion( const Region& rRegion ) +void PDFWriter::IntersectClipRegion( const basegfx::B2DPolyPolygon& rRegion ) { ((PDFWriterImpl*)pImplementation)->intersectClipRegion( rRegion ); } diff --git a/vcl/source/gdi/pdfwriter_impl.cxx b/vcl/source/gdi/pdfwriter_impl.cxx index 4371feb8ee37..6a24775219d9 100644 --- a/vcl/source/gdi/pdfwriter_impl.cxx +++ b/vcl/source/gdi/pdfwriter_impl.cxx @@ -37,6 +37,8 @@ #include <basegfx/polygon/b2dpolypolygon.hxx> #include <basegfx/polygon/b2dpolygontools.hxx> #include <basegfx/polygon/b2dpolypolygontools.hxx> +#include <basegfx/polygon/b2dpolypolygoncutter.hxx> +#include <basegfx/matrix/b2dhommatrix.hxx> #include <rtl/ustrbuf.hxx> #include <tools/debug.hxx> #include <tools/zcodec.hxx> @@ -115,7 +117,7 @@ void doTestCode() aDocInfo.Title = OUString( RTL_CONSTASCII_USTRINGPARAM( "PDF export test document" ) ); aDocInfo.Producer = OUString( RTL_CONSTASCII_USTRINGPARAM( "VCL" ) ); aWriter.SetDocInfo( aDocInfo ); - aWriter.NewPage(); + aWriter.NewPage( 595, 842 ); aWriter.BeginStructureElement( PDFWriter::Document ); // set duration of 3 sec for first page aWriter.SetAutoAdvanceTime( 3 ); @@ -166,7 +168,7 @@ void doTestCode() TEXT_DRAW_MULTILINE | TEXT_DRAW_WORDBREAK ); - aWriter.NewPage(); + aWriter.NewPage( 595, 842 ); // test AddStream interface aWriter.AddStream( String( RTL_CONSTASCII_USTRINGPARAM( "text/plain" ) ), new PDFTestOutputStream(), true ); // set transitional mode @@ -208,7 +210,25 @@ void doTestCode() aWriter.BeginStructureElement( PDFWriter::Caption ); aWriter.DrawText( Point( 4500, 9000 ), String( RTL_CONSTASCII_USTRINGPARAM( "Some drawing stuff inside the structure" ) ) ); aWriter.EndStructureElement(); + + // test clipping + basegfx::B2DPolyPolygon aClip; + basegfx::B2DPolygon aClipPoly; + aClipPoly.append( basegfx::B2DPoint( 8250, 9600 ) ); + aClipPoly.append( basegfx::B2DPoint( 16500, 11100 ) ); + aClipPoly.append( basegfx::B2DPoint( 8250, 12600 ) ); + aClipPoly.append( basegfx::B2DPoint( 4500, 11100 ) ); + aClipPoly.setClosed( true ); + //aClipPoly.flip(); + aClip.append( aClipPoly ); + + aWriter.Push( PUSH_CLIPREGION | PUSH_FILLCOLOR ); + aWriter.SetClipRegion( aClip ); + aWriter.DrawEllipse( Rectangle( Point( 4500, 9600 ), Size( 12000, 3000 ) ) ); + aWriter.MoveClipRegion( 1000, 500 ); + aWriter.SetFillColor( Color( COL_RED ) ); aWriter.DrawEllipse( Rectangle( Point( 4500, 9600 ), Size( 12000, 3000 ) ) ); + aWriter.Pop(); // test transparency // draw background Rectangle aTranspRect( Point( 7500, 13500 ), Size( 9000, 6000 ) ); @@ -288,7 +308,7 @@ void doTestCode() aLIPoly.Move( 1000, 1000 ); aWriter.DrawPolyLine( aLIPoly, aLI ); - aWriter.NewPage(); + aWriter.NewPage( 595, 842 ); aWriter.SetMapMode( MapMode( MAP_100TH_MM ) ); Wallpaper aWall( aTransMask ); aWall.SetStyle( WALLPAPER_TILE ); @@ -312,7 +332,7 @@ void doTestCode() aWriter.SetLineColor( Color( COL_LIGHTBLUE ) ); aWriter.DrawRect( aPolyRect ); - aWriter.NewPage(); + aWriter.NewPage( 595, 842 ); aWriter.SetMapMode( MapMode( MAP_100TH_MM ) ); aWriter.SetFont( Font( String( RTL_CONSTASCII_USTRINGPARAM( "Times" ) ), Size( 0, 500 ) ) ); aWriter.SetTextColor( Color( COL_BLACK ) ); @@ -632,30 +652,25 @@ static void appendUnicodeTextString( const rtl::OUString& rString, OStringBuffer } } -OString PDFWriterImpl::convertWidgetFieldName( const rtl::OUString& rString ) +void PDFWriterImpl::createWidgetFieldName( sal_Int32 i_nWidgetIndex, const PDFWriter::AnyWidget& i_rControl ) { - OStringBuffer aBuffer( rString.getLength()+64 ); - /* #i80258# previously we use appendName here however we need a slightly different coding scheme than the normal name encoding for field names - - also replace all '.' by '_' as '.' indicates a hierarchy level which - we do not have here */ - - OString aStr( OUStringToOString( rString, RTL_TEXTENCODING_UTF8 ) ); + const OUString& rName = (m_aContext.Version > PDFWriter::PDF_1_2) ? i_rControl.Name : i_rControl.Text; + OString aStr( OUStringToOString( rName, RTL_TEXTENCODING_UTF8 ) ); const sal_Char* pStr = aStr.getStr(); int nLen = aStr.getLength(); + + OStringBuffer aBuffer( rName.getLength()+64 ); for( int i = 0; i < nLen; i++ ) { /* #i16920# PDF recommendation: output UTF8, any byte - * outside the interval [33(=ASCII'!');126(=ASCII'~')] + * outside the interval [32(=ASCII' ');126(=ASCII'~')] * should be escaped hexadecimal */ - if( pStr[i] == '.' ) - aBuffer.append( '_' ); - else if( (pStr[i] >= 33 && pStr[i] <= 126 ) ) + if( (pStr[i] >= 32 && pStr[i] <= 126 ) ) aBuffer.append( pStr[i] ); else { @@ -664,31 +679,135 @@ OString PDFWriterImpl::convertWidgetFieldName( const rtl::OUString& rString ) } } - OString aRet = aBuffer.makeStringAndClear(); + OString aFullName( aBuffer.makeStringAndClear() ); + + /* #i82785# create hierarchical fields down to the for each dot in i_rName */ + sal_Int32 nTokenIndex = 0, nLastTokenIndex = 0; + OString aPartialName; + OString aDomain; + do + { + nLastTokenIndex = nTokenIndex; + aPartialName = aFullName.getToken( 0, '.', nTokenIndex ); + if( nTokenIndex != -1 ) + { + // find or create a hierarchical field + // first find the fully qualified name up to this field + aDomain = aFullName.copy( 0, nTokenIndex-1 ); + std::hash_map< rtl::OString, sal_Int32, rtl::OStringHash >::const_iterator it = m_aFieldNameMap.find( aDomain ); + if( it == m_aFieldNameMap.end() ) + { + // create new hierarchy field + sal_Int32 nNewWidget = m_aWidgets.size(); + m_aWidgets.push_back( PDFWidget() ); + m_aWidgets[nNewWidget].m_nObject = createObject(); + m_aWidgets[nNewWidget].m_eType = PDFWriter::Hierarchy; + m_aWidgets[nNewWidget].m_aName = aPartialName; + m_aWidgets[i_nWidgetIndex].m_nParent = m_aWidgets[nNewWidget].m_nObject; + m_aFieldNameMap[aDomain] = nNewWidget; + m_aWidgets[i_nWidgetIndex].m_nParent = m_aWidgets[nNewWidget].m_nObject; + if( nLastTokenIndex > 0 ) + { + // this field is not a root field and + // needs to be inserted to its parent + OString aParentDomain( aDomain.copy( 0, nLastTokenIndex-1 ) ); + it = m_aFieldNameMap.find( aParentDomain ); + OSL_ENSURE( it != m_aFieldNameMap.end(), "field name not found" ); + if( it != m_aFieldNameMap.end() ) + { + OSL_ENSURE( it->second < sal_Int32(m_aWidgets.size()), "invalid field number entry" ); + if( it->second < sal_Int32(m_aWidgets.size()) ) + { + PDFWidget& rParentField( m_aWidgets[it->second] ); + rParentField.m_aKids.push_back( m_aWidgets[nNewWidget].m_nObject ); + rParentField.m_aKidsIndex.push_back( nNewWidget ); + m_aWidgets[nNewWidget].m_nParent = rParentField.m_nObject; + } + } + } + } + else if( m_aWidgets[it->second].m_eType != PDFWriter::Hierarchy ) + { + // this is invalid, someone tries to have a terminal field as parent + // example: a button with the name foo.bar exists and + // another button is named foo.bar.no + // workaround: put the second terminal field as much up in the hierarchy as + // necessary to have a non-terminal field as parent (or none at all) + // since it->second already is terminal, we just need to use its parent + aDomain = OString(); + aPartialName = aFullName.copy( aFullName.lastIndexOf( '.' )+1 ); + if( nLastTokenIndex > 0 ) + { + aDomain = aFullName.copy( 0, nLastTokenIndex-1 ); + OStringBuffer aBuf( aDomain.getLength() + 1 + aPartialName.getLength() ); + aBuf.append( aDomain ); + aBuf.append( '.' ); + aBuf.append( aPartialName ); + aFullName = aBuf.makeStringAndClear(); + } + else + aFullName = aPartialName; + break; + } + } + } while( nTokenIndex != -1 ); + + // insert widget into its hierarchy field + if( aDomain.getLength() ) + { + std::hash_map< rtl::OString, sal_Int32, rtl::OStringHash >::const_iterator it = m_aFieldNameMap.find( aDomain ); + if( it != m_aFieldNameMap.end() ) + { + OSL_ENSURE( it->second >= 0 && it->second < sal_Int32( m_aWidgets.size() ), "invalid field index" ); + if( it->second >= 0 && it->second < sal_Int32(m_aWidgets.size()) ) + { + m_aWidgets[i_nWidgetIndex].m_nParent = m_aWidgets[it->second].m_nObject; + m_aWidgets[it->second].m_aKids.push_back( m_aWidgets[i_nWidgetIndex].m_nObject); + m_aWidgets[it->second].m_aKidsIndex.push_back( i_nWidgetIndex ); + } + } + } + + if( aPartialName.getLength() == 0 ) + { + // how funny, an empty field name + if( i_rControl.getType() == PDFWriter::RadioButton ) + { + aPartialName = "RadioGroup"; + aPartialName += OString::valueOf( static_cast<const PDFWriter::RadioButtonWidget&>(i_rControl).RadioGroup ); + } + else + aPartialName = OString( "Widget" ); + } + if( ! m_aContext.AllowDuplicateFieldNames ) { - std::hash_map<OString, sal_Int32, OStringHash>::iterator it = m_aFieldNameMap.find( aRet ); + std::hash_map<OString, sal_Int32, OStringHash>::iterator it = m_aFieldNameMap.find( aFullName ); if( it != m_aFieldNameMap.end() ) // not unique { std::hash_map< OString, sal_Int32, OStringHash >::const_iterator check_it; OString aTry; + sal_Int32 nTry = 2; do { - OStringBuffer aUnique( aRet.getLength() + 16 ); - aUnique.append( aRet ); + OStringBuffer aUnique( aFullName.getLength() + 16 ); + aUnique.append( aFullName ); aUnique.append( '_' ); - aUnique.append( it->second ); - it->second++; + aUnique.append( nTry++ ); aTry = aUnique.makeStringAndClear(); check_it = m_aFieldNameMap.find( aTry ); } while( check_it != m_aFieldNameMap.end() ); - aRet = aTry; + aFullName = aTry; + m_aFieldNameMap[ aFullName ] = i_nWidgetIndex; + aPartialName = aFullName.copy( aFullName.lastIndexOf( '.' )+1 ); } else - m_aFieldNameMap[ aRet ] = 2; + m_aFieldNameMap[ aFullName ] = i_nWidgetIndex; } - return aRet; + + // finally + m_aWidgets[i_nWidgetIndex].m_aName = aPartialName; } static void appendFixedInt( sal_Int32 nValue, OStringBuffer& rBuffer, sal_Int32 nPrecision = nLog10Divisor ) @@ -720,7 +839,7 @@ static void appendFixedInt( sal_Int32 nValue, OStringBuffer& rBuffer, sal_Int32 // appends a double. PDF does not accept exponential format, only fixed point -static void appendDouble( double fValue, OStringBuffer& rBuffer, int nPrecision = 5 ) +static void appendDouble( double fValue, OStringBuffer& rBuffer, sal_Int32 nPrecision = 5 ) { bool bNeg = false; if( fValue < 0.0 ) @@ -1273,6 +1392,19 @@ void PDFWriterImpl::PDFPage::appendPoint( const Point& rPoint, OStringBuffer& rB appendFixedInt( nValue, rBuffer ); } +void PDFWriterImpl::PDFPage::appendPixelPoint( const basegfx::B2DPoint& rPoint, OStringBuffer& rBuffer ) const +{ + double fValue = pixelToPoint(rPoint.getX()); + + appendDouble( fValue, rBuffer, nLog10Divisor ); + + rBuffer.append( ' ' ); + + fValue = double(getHeight()) - pixelToPoint(rPoint.getY()); + + appendDouble( fValue, rBuffer, nLog10Divisor ); +} + void PDFWriterImpl::PDFPage::appendRect( const Rectangle& rRect, OStringBuffer& rBuffer ) const { appendPoint( rRect.BottomLeft() + Point( 0, 1 ), rBuffer ); @@ -1345,6 +1477,82 @@ void PDFWriterImpl::PDFPage::appendPolygon( const Polygon& rPoly, OStringBuffer& } } +void PDFWriterImpl::PDFPage::appendPolygon( const basegfx::B2DPolygon& rPoly, OStringBuffer& rBuffer, bool bClose ) const +{ + basegfx::B2DPolygon aPoly( lcl_convert( m_pWriter->m_aGraphicsStack.front().m_aMapMode, + m_pWriter->m_aMapMode, + m_pWriter->getReferenceDevice(), + rPoly ) ); + + if( basegfx::tools::isRectangle( aPoly ) ) + { + basegfx::B2DRange aRange( aPoly.getB2DRange() ); + basegfx::B2DPoint aBL( aRange.getMinX(), aRange.getMaxY() ); + appendPixelPoint( aBL, rBuffer ); + rBuffer.append( ' ' ); + appendMappedLength( aRange.getWidth(), rBuffer, false, NULL, nLog10Divisor ); + rBuffer.append( ' ' ); + appendMappedLength( aRange.getHeight(), rBuffer, true, NULL, nLog10Divisor ); + rBuffer.append( " re\n" ); + return; + } + sal_uInt32 nPoints = aPoly.count(); + if( nPoints > 0 ) + { + sal_uInt32 nBufLen = rBuffer.getLength(); + basegfx::B2DPoint aLastPoint( aPoly.getB2DPoint( 0 ) ); + appendPixelPoint( aLastPoint, rBuffer ); + rBuffer.append( " m\n" ); + for( sal_uInt32 i = 1; i <= nPoints; i++ ) + { + if( i != nPoints || aPoly.isClosed() ) + { + sal_uInt32 nCurPoint = i % nPoints; + sal_uInt32 nLastPoint = i-1; + basegfx::B2DPoint aPoint( aPoly.getB2DPoint( nCurPoint ) ); + if( aPoly.isNextControlPointUsed( nLastPoint ) && + aPoly.isPrevControlPointUsed( nCurPoint ) ) + { + appendPixelPoint( aPoly.getNextControlPoint( nLastPoint ), rBuffer ); + rBuffer.append( ' ' ); + appendPixelPoint( aPoly.getPrevControlPoint( nCurPoint ), rBuffer ); + rBuffer.append( ' ' ); + appendPixelPoint( aPoint, rBuffer ); + rBuffer.append( " c" ); + } + else if( aPoly.isNextControlPointUsed( nLastPoint ) ) + { + appendPixelPoint( aPoly.getNextControlPoint( nLastPoint ), rBuffer ); + rBuffer.append( ' ' ); + appendPixelPoint( aPoint, rBuffer ); + rBuffer.append( " y" ); + } + else if( aPoly.isPrevControlPointUsed( nCurPoint ) ) + { + appendPixelPoint( aPoly.getPrevControlPoint( nCurPoint ), rBuffer ); + rBuffer.append( ' ' ); + appendPixelPoint( aPoint, rBuffer ); + rBuffer.append( " v" ); + } + else + { + appendPixelPoint( aPoint, rBuffer ); + rBuffer.append( " l" ); + } + if( (rBuffer.getLength() - nBufLen) > 65 ) + { + rBuffer.append( "\n" ); + nBufLen = rBuffer.getLength(); + } + else + rBuffer.append( " " ); + } + } + if( bClose ) + rBuffer.append( "h\n" ); + } +} + void PDFWriterImpl::PDFPage::appendPolyPolygon( const PolyPolygon& rPolyPoly, OStringBuffer& rBuffer, bool bClose ) const { USHORT nPolygons = rPolyPoly.Count(); @@ -1352,6 +1560,13 @@ void PDFWriterImpl::PDFPage::appendPolyPolygon( const PolyPolygon& rPolyPoly, OS appendPolygon( rPolyPoly[n], rBuffer, bClose ); } +void PDFWriterImpl::PDFPage::appendPolyPolygon( const basegfx::B2DPolyPolygon& rPolyPoly, OStringBuffer& rBuffer, bool bClose ) const +{ + sal_uInt32 nPolygons = rPolyPoly.count(); + for( sal_uInt32 n = 0; n < nPolygons; n++ ) + appendPolygon( rPolyPoly.getB2DPolygon( n ), rBuffer, bClose ); +} + void PDFWriterImpl::PDFPage::appendMappedLength( sal_Int32 nLength, OStringBuffer& rBuffer, bool bVertical, sal_Int32* pOutLength ) const { sal_Int32 nValue = nLength; @@ -1371,7 +1586,7 @@ void PDFWriterImpl::PDFPage::appendMappedLength( sal_Int32 nLength, OStringBuffe appendFixedInt( nValue, rBuffer, 1 ); } -void PDFWriterImpl::PDFPage::appendMappedLength( double fLength, OStringBuffer& rBuffer, bool bVertical, sal_Int32* pOutLength ) const +void PDFWriterImpl::PDFPage::appendMappedLength( double fLength, OStringBuffer& rBuffer, bool bVertical, sal_Int32* pOutLength, sal_Int32 nPrecision ) const { Size aSize( lcl_convert( m_pWriter->m_aGraphicsStack.front().m_aMapMode, m_pWriter->m_aMapMode, @@ -1380,7 +1595,7 @@ void PDFWriterImpl::PDFPage::appendMappedLength( double fLength, OStringBuffer& if( pOutLength ) *pOutLength = (sal_Int32)(fLength*(double)(bVertical ? aSize.Height() : aSize.Width())/1000.0); fLength *= pixelToPoint((double)(bVertical ? aSize.Height() : aSize.Width()) / 1000.0); - appendDouble( fLength, rBuffer ); + appendDouble( fLength, rBuffer, nPrecision ); } bool PDFWriterImpl::PDFPage::appendLineInfo( const LineInfo& rInfo, OStringBuffer& rBuffer ) const @@ -5189,78 +5404,82 @@ bool PDFWriterImpl::emitWidgetAnnotations() aLine.append( rWidget.m_nObject ); aLine.append( " 0 obj\n" "<<" ); - // emit widget annotation only for terminal fields - if( rWidget.m_aKids.empty() ) - { - aLine.append( "/Type/Annot/Subtype/Widget/F 4\n" - "/Rect[" ); - appendFixedInt( rWidget.m_aRect.Left()-1, aLine ); - aLine.append( ' ' ); - appendFixedInt( rWidget.m_aRect.Top()+1, aLine ); - aLine.append( ' ' ); - appendFixedInt( rWidget.m_aRect.Right()+1, aLine ); - aLine.append( ' ' ); - appendFixedInt( rWidget.m_aRect.Bottom()-1, aLine ); - aLine.append( "]\n" ); - } - aLine.append( "/FT/" ); - switch( rWidget.m_eType ) + if( rWidget.m_eType != PDFWriter::Hierarchy ) { - case PDFWriter::RadioButton: - case PDFWriter::CheckBox: - // for radio buttons only the RadioButton field, not the - // CheckBox children should have a value, else acrobat reader - // does not always check the right button - // of course real check boxes (not belonging to a readio group) - // need their values, too - if( rWidget.m_eType == PDFWriter::RadioButton || rWidget.m_nRadioGroup < 0 ) - { - aValue.append( "/" ); - // check for radio group with all buttons unpressed - if( rWidget.m_aValue.getLength() == 0 ) - aValue.append( "Off" ); - else - appendName( rWidget.m_aValue, aValue ); - } - case PDFWriter::PushButton: - aLine.append( "Btn" ); - break; - case PDFWriter::ListBox: - if( rWidget.m_nFlags & 0x200000 ) // multiselect - { - aValue.append( "[" ); - for( unsigned int i = 0; i < rWidget.m_aSelectedEntries.size(); i++ ) + // emit widget annotation only for terminal fields + if( rWidget.m_aKids.empty() ) + { + aLine.append( "/Type/Annot/Subtype/Widget/F 4\n" + "/Rect[" ); + appendFixedInt( rWidget.m_aRect.Left()-1, aLine ); + aLine.append( ' ' ); + appendFixedInt( rWidget.m_aRect.Top()+1, aLine ); + aLine.append( ' ' ); + appendFixedInt( rWidget.m_aRect.Right()+1, aLine ); + aLine.append( ' ' ); + appendFixedInt( rWidget.m_aRect.Bottom()-1, aLine ); + aLine.append( "]\n" ); + } + aLine.append( "/FT/" ); + switch( rWidget.m_eType ) + { + case PDFWriter::RadioButton: + case PDFWriter::CheckBox: + // for radio buttons only the RadioButton field, not the + // CheckBox children should have a value, else acrobat reader + // does not always check the right button + // of course real check boxes (not belonging to a readio group) + // need their values, too + if( rWidget.m_eType == PDFWriter::RadioButton || rWidget.m_nRadioGroup < 0 ) { - sal_Int32 nEntry = rWidget.m_aSelectedEntries[i]; - if( nEntry >= 0 && nEntry < sal_Int32(rWidget.m_aListEntries.size()) ) - appendUnicodeTextStringEncrypt( rWidget.m_aListEntries[ nEntry ], rWidget.m_nObject, aValue ); + aValue.append( "/" ); + // check for radio group with all buttons unpressed + if( rWidget.m_aValue.getLength() == 0 ) + aValue.append( "Off" ); + else + appendName( rWidget.m_aValue, aValue ); } - aValue.append( "]" ); - } - else if( rWidget.m_aSelectedEntries.size() > 0 && - rWidget.m_aSelectedEntries[0] >= 0 && - rWidget.m_aSelectedEntries[0] < sal_Int32(rWidget.m_aListEntries.size()) ) - { - appendUnicodeTextStringEncrypt( rWidget.m_aListEntries[ rWidget.m_aSelectedEntries[0] ], rWidget.m_nObject, aValue ); - } - else - appendUnicodeTextStringEncrypt( rtl::OUString(), rWidget.m_nObject, aValue ); - aLine.append( "Ch" ); - break; - case PDFWriter::ComboBox: - appendUnicodeTextStringEncrypt( rWidget.m_aValue, rWidget.m_nObject, aValue ); - aLine.append( "Ch" ); - break; - case PDFWriter::Edit: - aLine.append( "Tx" ); - appendUnicodeTextStringEncrypt( rWidget.m_aValue, rWidget.m_nObject, aValue ); - break; + case PDFWriter::PushButton: + aLine.append( "Btn" ); + break; + case PDFWriter::ListBox: + if( rWidget.m_nFlags & 0x200000 ) // multiselect + { + aValue.append( "[" ); + for( unsigned int i = 0; i < rWidget.m_aSelectedEntries.size(); i++ ) + { + sal_Int32 nEntry = rWidget.m_aSelectedEntries[i]; + if( nEntry >= 0 && nEntry < sal_Int32(rWidget.m_aListEntries.size()) ) + appendUnicodeTextStringEncrypt( rWidget.m_aListEntries[ nEntry ], rWidget.m_nObject, aValue ); + } + aValue.append( "]" ); + } + else if( rWidget.m_aSelectedEntries.size() > 0 && + rWidget.m_aSelectedEntries[0] >= 0 && + rWidget.m_aSelectedEntries[0] < sal_Int32(rWidget.m_aListEntries.size()) ) + { + appendUnicodeTextStringEncrypt( rWidget.m_aListEntries[ rWidget.m_aSelectedEntries[0] ], rWidget.m_nObject, aValue ); + } + else + appendUnicodeTextStringEncrypt( rtl::OUString(), rWidget.m_nObject, aValue ); + aLine.append( "Ch" ); + break; + case PDFWriter::ComboBox: + appendUnicodeTextStringEncrypt( rWidget.m_aValue, rWidget.m_nObject, aValue ); + aLine.append( "Ch" ); + break; + case PDFWriter::Edit: + aLine.append( "Tx" ); + appendUnicodeTextStringEncrypt( rWidget.m_aValue, rWidget.m_nObject, aValue ); + break; + case PDFWriter::Hierarchy: // make the compiler happy + break; + } + aLine.append( "\n" ); + aLine.append( "/P " ); + aLine.append( m_aPages[ rWidget.m_nPage ].m_nPageObject ); + aLine.append( " 0 R\n" ); } - aLine.append( "\n" ); - aLine.append( "/P " ); - aLine.append( m_aPages[ rWidget.m_nPage ].m_nPageObject ); - aLine.append( " 0 R\n" ); - if( rWidget.m_nParent ) { aLine.append( "/Parent " ); @@ -5284,7 +5503,7 @@ bool PDFWriterImpl::emitWidgetAnnotations() appendLiteralStringEncrypt( rWidget.m_aName, rWidget.m_nObject, aLine ); aLine.append( "\n" ); } - if( m_aContext.Version > PDFWriter::PDF_1_2 ) + if( m_aContext.Version > PDFWriter::PDF_1_2 && rWidget.m_aDescription.getLength() ) { // the alternate field name should be unicode able since it is // supposed to be used in UI @@ -5346,7 +5565,7 @@ bool PDFWriterImpl::emitWidgetAnnotations() if(!m_bIsPDF_A1) { OStringBuffer aDest; - if( appendDest( rWidget.m_nDest, aDest ) ) + if( rWidget.m_nDest != -1 && appendDest( rWidget.m_nDest, aDest ) ) { aLine.append( "/AA<</D<</Type/Action/S/GoTo/D " ); aLine.append( aDest.makeStringAndClear() ); @@ -6379,16 +6598,19 @@ void PDFWriterImpl::sortWidgets() for( int nW = 0; nW < nWidgets; nW++ ) { const PDFWidget& rWidget = m_aWidgets[nW]; - AnnotSortContainer& rCont = sorted[ rWidget.m_nPage ]; - // optimize vector allocation - if( rCont.aSortedAnnots.empty() ) - rCont.aSortedAnnots.reserve( m_aPages[ rWidget.m_nPage ].m_aAnnotations.size() ); - // insert widget to tab sorter - // RadioButtons are not page annotations, only their individual check boxes are - if( rWidget.m_eType != PDFWriter::RadioButton ) - { - rCont.aObjects.insert( rWidget.m_nObject ); - rCont.aSortedAnnots.push_back( AnnotationSortEntry( rWidget.m_nTabOrder, rWidget.m_nObject, nW ) ); + if( rWidget.m_nPage >= 0 ) + { + AnnotSortContainer& rCont = sorted[ rWidget.m_nPage ]; + // optimize vector allocation + if( rCont.aSortedAnnots.empty() ) + rCont.aSortedAnnots.reserve( m_aPages[ rWidget.m_nPage ].m_aAnnotations.size() ); + // insert widget to tab sorter + // RadioButtons are not page annotations, only their individual check boxes are + if( rWidget.m_eType != PDFWriter::RadioButton ) + { + rCont.aObjects.insert( rWidget.m_nObject ); + rCont.aSortedAnnots.push_back( AnnotationSortEntry( rWidget.m_nTabOrder, rWidget.m_nObject, nW ) ); + } } } for( std::hash_map< sal_Int32, AnnotSortContainer >::iterator it = sorted.begin(); it != sorted.end(); ++it ) @@ -8278,7 +8500,7 @@ void PDFWriterImpl::beginRedirect( SvStream* pStream, const Rectangle& rTargetRe { push( PUSH_ALL ); - setClipRegion( Region() ); + clearClipRegion(); updateGraphicsState(); m_aOutputStreams.push_front( StreamRedirect() ); @@ -10214,25 +10436,17 @@ void PDFWriterImpl::updateGraphicsState() { rNewState.m_nUpdateFlags &= ~GraphicsState::updateClipRegion; - Region& rNewClip = rNewState.m_aClipRegion; - - /* #103137# equality operator is not implemented - * const as API promises but may change Region - * from Polygon to rectangles. Arrrgghh !!!! - */ - Region aLeft = m_aCurrentPDFState.m_aClipRegion; - Region aRight = rNewClip; - if( aLeft != aRight ) + if( m_aCurrentPDFState.m_bClipRegion != rNewState.m_bClipRegion || + ( rNewState.m_bClipRegion && m_aCurrentPDFState.m_aClipRegion != rNewState.m_aClipRegion ) ) { - if( ! m_aCurrentPDFState.m_aClipRegion.IsEmpty() && - ! m_aCurrentPDFState.m_aClipRegion.IsNull() ) + if( m_aCurrentPDFState.m_bClipRegion && m_aCurrentPDFState.m_aClipRegion.count() ) { aLine.append( "Q " ); // invalidate everything but the clip region m_aCurrentPDFState = GraphicsState(); rNewState.m_nUpdateFlags = sal::static_int_cast<sal_uInt16>(~GraphicsState::updateClipRegion); } - if( ! rNewClip.IsEmpty() && ! rNewClip.IsNull() ) + if( rNewState.m_bClipRegion && rNewState.m_aClipRegion.count() ) { // clip region is always stored in private PDF mapmode MapMode aNewMapMode = rNewState.m_aMapMode; @@ -10241,32 +10455,8 @@ void PDFWriterImpl::updateGraphicsState() m_aCurrentPDFState.m_aMapMode = rNewState.m_aMapMode; aLine.append( "q " ); - if( rNewClip.HasPolyPolygon() ) - { - m_aPages.back().appendPolyPolygon( rNewClip.GetPolyPolygon(), aLine ); - aLine.append( "W* n\n" ); - } - else - { - // need to clip all rectangles - RegionHandle aHandle = rNewClip.BeginEnumRects(); - Rectangle aRect; - while( rNewClip.GetNextEnumRect( aHandle, aRect ) ) - { - m_aPages.back().appendRect( aRect, aLine ); - if( aLine.getLength() > 80 ) - { - aLine.append( "\n" ); - writeBuffer( aLine.getStr(), aLine.getLength() ); - aLine.setLength( 0 ); - } - else - aLine.append( ' ' ); - } - rNewClip.EndEnumRects( aHandle ); - aLine.append( "W* n\n" ); - } - + m_aPages.back().appendPolyPolygon( rNewState.m_aClipRegion, aLine ); + aLine.append( "W* n\n" ); rNewState.m_aMapMode = aNewMapMode; getReferenceDevice()->SetMapMode( rNewState.m_aMapMode ); m_aCurrentPDFState.m_aMapMode = rNewState.m_aMapMode; @@ -10380,9 +10570,12 @@ void PDFWriterImpl::pop() if( ! (aState.m_nFlags & PUSH_MAPMODE) ) setMapMode( aState.m_aMapMode ); if( ! (aState.m_nFlags & PUSH_CLIPREGION) ) + { // do not use setClipRegion here // it would convert again assuming the current mapmode rOld.m_aClipRegion = aState.m_aClipRegion; + rOld.m_bClipRegion = aState.m_bClipRegion; + } if( ! (aState.m_nFlags & PUSH_TEXTLINECOLOR ) ) setTextLineColor( aState.m_aTextLineColor ); if( ! (aState.m_nFlags & PUSH_OVERLINECOLOR ) ) @@ -10406,45 +10599,59 @@ void PDFWriterImpl::setMapMode( const MapMode& rMapMode ) m_aCurrentPDFState.m_aMapMode = rMapMode; } -void PDFWriterImpl::setClipRegion( const Region& rRegion ) +void PDFWriterImpl::setClipRegion( const basegfx::B2DPolyPolygon& rRegion ) { - Region aRegion = getReferenceDevice()->LogicToPixel( rRegion, m_aGraphicsStack.front().m_aMapMode ); + basegfx::B2DPolyPolygon aRegion = getReferenceDevice()->LogicToPixel( rRegion, m_aGraphicsStack.front().m_aMapMode ); aRegion = getReferenceDevice()->PixelToLogic( aRegion, m_aMapMode ); m_aGraphicsStack.front().m_aClipRegion = aRegion; + m_aGraphicsStack.front().m_bClipRegion = true; m_aGraphicsStack.front().m_nUpdateFlags |= GraphicsState::updateClipRegion; } void PDFWriterImpl::moveClipRegion( sal_Int32 nX, sal_Int32 nY ) { - Point aPoint( lcl_convert( m_aGraphicsStack.front().m_aMapMode, + if( m_aGraphicsStack.front().m_bClipRegion && m_aGraphicsStack.front().m_aClipRegion.count() ) + { + Point aPoint( lcl_convert( m_aGraphicsStack.front().m_aMapMode, + m_aMapMode, + getReferenceDevice(), + Point( nX, nY ) ) ); + aPoint -= lcl_convert( m_aGraphicsStack.front().m_aMapMode, m_aMapMode, getReferenceDevice(), - Point( nX, nY ) ) ); - aPoint -= lcl_convert( m_aGraphicsStack.front().m_aMapMode, - m_aMapMode, - getReferenceDevice(), - Point() ); - m_aGraphicsStack.front().m_aClipRegion.Move( aPoint.X(), aPoint.Y() ); - m_aGraphicsStack.front().m_nUpdateFlags |= GraphicsState::updateClipRegion; + Point() ); + basegfx::B2DHomMatrix aMat; + aMat.translate( aPoint.X(), aPoint.Y() ); + m_aGraphicsStack.front().m_aClipRegion.transform( aMat ); + m_aGraphicsStack.front().m_nUpdateFlags |= GraphicsState::updateClipRegion; + } } bool PDFWriterImpl::intersectClipRegion( const Rectangle& rRect ) { - Rectangle aRect( lcl_convert( m_aGraphicsStack.front().m_aMapMode, - m_aMapMode, - getReferenceDevice(), - rRect ) ); - m_aGraphicsStack.front().m_nUpdateFlags |= GraphicsState::updateClipRegion; - return m_aGraphicsStack.front().m_aClipRegion.Intersect( aRect ); + basegfx::B2DPolyPolygon aRect( basegfx::tools::createPolygonFromRect( + basegfx::B2DRectangle( rRect.Left(), rRect.Top(), rRect.Right(), rRect.Bottom() ) ) ); + return intersectClipRegion( aRect ); } -bool PDFWriterImpl::intersectClipRegion( const Region& rRegion ) +bool PDFWriterImpl::intersectClipRegion( const basegfx::B2DPolyPolygon& rRegion ) { - Region aRegion = getReferenceDevice()->LogicToPixel( rRegion, m_aGraphicsStack.front().m_aMapMode ); + basegfx::B2DPolyPolygon aRegion( getReferenceDevice()->LogicToPixel( rRegion, m_aGraphicsStack.front().m_aMapMode ) ); aRegion = getReferenceDevice()->PixelToLogic( aRegion, m_aMapMode ); m_aGraphicsStack.front().m_nUpdateFlags |= GraphicsState::updateClipRegion; - return m_aGraphicsStack.front().m_aClipRegion.Intersect( aRegion ); + if( m_aGraphicsStack.front().m_bClipRegion ) + { + basegfx::B2DPolyPolygon aOld( basegfx::tools::prepareForPolygonOperation( m_aGraphicsStack.front().m_aClipRegion ) ); + aRegion = basegfx::tools::prepareForPolygonOperation( aRegion ); + m_aGraphicsStack.front().m_aClipRegion = basegfx::tools::solvePolygonOperationAnd( aOld, aRegion ); + } + else + { + m_aGraphicsStack.front().m_aClipRegion = aRegion; + m_aGraphicsStack.front().m_bClipRegion = true; + } + return true; } void PDFWriterImpl::createNote( const Rectangle& rRect, const PDFNote& rNote, sal_Int32 nPageNr ) @@ -11528,18 +11735,7 @@ sal_Int32 PDFWriterImpl::findRadioGroupWidget( const PDFWriter::RadioButtonWidge m_aWidgets.back().m_nRadioGroup = rBtn.RadioGroup; m_aWidgets.back().m_nFlags |= 0x00008000; - // create radio button field name - const rtl::OUString& rName = (m_aContext.Version > PDFWriter::PDF_1_2) ? - rBtn.Name : rBtn.Text; - if( rName.getLength() ) - { - m_aWidgets.back().m_aName = convertWidgetFieldName( rName ); - } - else - { - m_aWidgets.back().m_aName = "RadioGroup"; - m_aWidgets.back().m_aName += OString::valueOf( rBtn.RadioGroup ); - } + createWidgetFieldName( sal_Int32(m_aWidgets.size()-1), rBtn ); } else nRadioGroupWidget = it->second; @@ -11555,44 +11751,27 @@ sal_Int32 PDFWriterImpl::createControl( const PDFWriter::AnyWidget& rControl, sa if( nPageNr < 0 || nPageNr >= (sal_Int32)m_aPages.size() ) return -1; + sal_Int32 nNewWidget = m_aWidgets.size(); m_aWidgets.push_back( PDFWidget() ); - sal_Int32 nNewWidget = m_aWidgets.size()-1; - - // create eventual radio button before getting any references - // from m_aWidgets as the push_back operation potentially assigns new - // memory to the vector and thereby invalidates the reference - int nRadioGroupWidget = -1; - if( rControl.getType() == PDFWriter::RadioButton ) - nRadioGroupWidget = findRadioGroupWidget( static_cast<const PDFWriter::RadioButtonWidget&>(rControl) ); - PDFWidget& rNewWidget = m_aWidgets[nNewWidget]; - rNewWidget.m_nObject = createObject(); - rNewWidget.m_aRect = rControl.Location; - rNewWidget.m_nPage = nPageNr; - rNewWidget.m_eType = rControl.getType(); + m_aWidgets.back().m_nObject = createObject(); + m_aWidgets.back().m_aRect = rControl.Location; + m_aWidgets.back().m_nPage = nPageNr; + m_aWidgets.back().m_eType = rControl.getType(); + sal_Int32 nRadioGroupWidget = -1; // for unknown reasons the radio buttons of a radio group must not have a // field name, else the buttons are in fact check boxes - // that is multiple buttons of the radio group can be selected - if( rControl.getType() != PDFWriter::RadioButton ) + if( rControl.getType() == PDFWriter::RadioButton ) + nRadioGroupWidget = findRadioGroupWidget( static_cast<const PDFWriter::RadioButtonWidget&>(rControl) ); + else { - // acrobat reader since 3.0 does not support unicode text - // strings for the field name; so we need to encode unicodes - // larger than 255 - - rNewWidget.m_aName = - convertWidgetFieldName( (m_aContext.Version > PDFWriter::PDF_1_2) ? - rControl.Name : rControl.Text ); - // #i88040# acrobat reader crashes on empty field names, - // so always create one - if( rNewWidget.m_aName.getLength() == 0 ) - { - OUStringBuffer aBuf( 32 ); - aBuf.appendAscii( "Widget" ); - aBuf.append( nNewWidget ); - rNewWidget.m_aName = convertWidgetFieldName( aBuf.makeStringAndClear() ); - } + createWidgetFieldName( nNewWidget, rControl ); } + + // caution: m_aWidgets must not be changed after here or rNewWidget may be invalid + PDFWidget& rNewWidget = m_aWidgets[nNewWidget]; rNewWidget.m_aDescription = rControl.Description; rNewWidget.m_aText = rControl.Text; rNewWidget.m_nTextStyle = rControl.TextStyle & @@ -11823,6 +12002,7 @@ bool PDFWriterImpl::endControlAppearance( PDFWriter::WidgetState eState ) break; case PDFWriter::ListBox: case PDFWriter::ComboBox: + case PDFWriter::Hierarchy: break; } if( aState.getLength() && aStyle.getLength() ) diff --git a/vcl/source/gdi/pdfwriter_impl.hxx b/vcl/source/gdi/pdfwriter_impl.hxx index 4adf54ea98a3..2eacdc215dd8 100644 --- a/vcl/source/gdi/pdfwriter_impl.hxx +++ b/vcl/source/gdi/pdfwriter_impl.hxx @@ -146,14 +146,20 @@ public: // if pOutPoint is set it will be updated to the emitted point // (in PDF map mode, that is 10th of point) void appendPoint( const Point& rPoint, rtl::OStringBuffer& rBuffer, bool bNeg = false, Point* pOutPoint = NULL ) const; + // appends a B2DPoint without further transformation + void appendPixelPoint( const basegfx::B2DPoint& rPoint, rtl::OStringBuffer& rBuffer ) const; // appends a rectangle void appendRect( const Rectangle& rRect, rtl::OStringBuffer& rBuffer ) const; // converts a rectangle to 10th points page space void convertRect( Rectangle& rRect ) const; // appends a polygon optionally closing it void appendPolygon( const Polygon& rPoly, rtl::OStringBuffer& rBuffer, bool bClose = true ) const; + // appends a polygon optionally closing it + void appendPolygon( const basegfx::B2DPolygon& rPoly, rtl::OStringBuffer& rBuffer, bool bClose = true ) const; // appends a polypolygon optionally closing the subpaths void appendPolyPolygon( const PolyPolygon& rPolyPoly, rtl::OStringBuffer& rBuffer, bool bClose = true ) const; + // appends a polypolygon optionally closing the subpaths + void appendPolyPolygon( const basegfx::B2DPolyPolygon& rPolyPoly, rtl::OStringBuffer& rBuffer, bool bClose = true ) const; // converts a length (either vertical or horizontal; this // can be important if the source MapMode is not // symmetrical) to page length and appends it to the buffer @@ -161,7 +167,7 @@ public: // (in PDF map mode, that is 10th of point) void appendMappedLength( sal_Int32 nLength, rtl::OStringBuffer& rBuffer, bool bVertical = true, sal_Int32* pOutLength = NULL ) const; // the same for double values - void appendMappedLength( double fLength, rtl::OStringBuffer& rBuffer, bool bVertical = true, sal_Int32* pOutLength = NULL ) const; + void appendMappedLength( double fLength, rtl::OStringBuffer& rBuffer, bool bVertical = true, sal_Int32* pOutLength = NULL, sal_Int32 nPrecision = 5 ) const; // appends LineInfo // returns false if too many dash array entry were created for // the implementation limits of some PDF readers @@ -695,19 +701,20 @@ private: // graphics state struct GraphicsState { - Font m_aFont; - MapMode m_aMapMode; - Color m_aLineColor; - Color m_aFillColor; - Color m_aTextLineColor; - Color m_aOverlineColor; - Region m_aClipRegion; - sal_Int32 m_nAntiAlias; - sal_Int32 m_nLayoutMode; - LanguageType m_aDigitLanguage; - sal_Int32 m_nTransparentPercent; - sal_uInt16 m_nFlags; - sal_uInt16 m_nUpdateFlags; + Font m_aFont; + MapMode m_aMapMode; + Color m_aLineColor; + Color m_aFillColor; + Color m_aTextLineColor; + Color m_aOverlineColor; + basegfx::B2DPolyPolygon m_aClipRegion; + bool m_bClipRegion; + sal_Int32 m_nAntiAlias; + sal_Int32 m_nLayoutMode; + LanguageType m_aDigitLanguage; + sal_Int32 m_nTransparentPercent; + sal_uInt16 m_nFlags; + sal_uInt16 m_nUpdateFlags; static const sal_uInt16 updateFont = 0x0001; static const sal_uInt16 updateMapMode = 0x0002; @@ -726,6 +733,7 @@ private: m_aFillColor( COL_TRANSPARENT ), m_aTextLineColor( COL_TRANSPARENT ), m_aOverlineColor( COL_TRANSPARENT ), + m_bClipRegion( false ), m_nAntiAlias( 1 ), m_nLayoutMode( 0 ), m_aDigitLanguage( 0 ), @@ -741,6 +749,7 @@ private: m_aTextLineColor( rState.m_aTextLineColor ), m_aOverlineColor( rState.m_aOverlineColor ), m_aClipRegion( rState.m_aClipRegion ), + m_bClipRegion( rState.m_bClipRegion ), m_nAntiAlias( rState.m_nAntiAlias ), m_nLayoutMode( rState.m_nLayoutMode ), m_aDigitLanguage( rState.m_aDigitLanguage ), @@ -759,6 +768,7 @@ private: m_aTextLineColor = rState.m_aTextLineColor; m_aOverlineColor = rState.m_aOverlineColor; m_aClipRegion = rState.m_aClipRegion; + m_bClipRegion = rState.m_bClipRegion; m_nAntiAlias = rState.m_nAntiAlias; m_nLayoutMode = rState.m_nLayoutMode; m_aDigitLanguage = rState.m_aDigitLanguage; @@ -1049,7 +1059,7 @@ i12626 void createDefaultListBoxAppearance( PDFWidget&, const PDFWriter::ListBoxWidget& rWidget ); /* ensure proper escapement and uniqueness of field names */ - rtl::OString convertWidgetFieldName( const rtl::OUString& rString ); + void createWidgetFieldName( sal_Int32 i_nWidgetsIndex, const PDFWriter::AnyWidget& i_rInWidget ); /* adds an entry to m_aObjects and returns its index+1, * sets the offset to ~0 */ @@ -1209,17 +1219,18 @@ public: void clearClipRegion() { - m_aGraphicsStack.front().m_aClipRegion.SetNull(); + m_aGraphicsStack.front().m_aClipRegion.clear(); + m_aGraphicsStack.front().m_bClipRegion = false; m_aGraphicsStack.front().m_nUpdateFlags |= GraphicsState::updateClipRegion; } - void setClipRegion( const Region& rRegion ); + void setClipRegion( const basegfx::B2DPolyPolygon& rRegion ); void moveClipRegion( sal_Int32 nX, sal_Int32 nY ); bool intersectClipRegion( const Rectangle& rRect ); - bool intersectClipRegion( const Region& rRegion ); + bool intersectClipRegion( const basegfx::B2DPolyPolygon& rRegion ); void setLayoutMode( sal_Int32 nLayoutMode ) { diff --git a/vcl/source/gdi/pngwrite.cxx b/vcl/source/gdi/pngwrite.cxx index bd28135ca498..47152ea6ac11 100644 --- a/vcl/source/gdi/pngwrite.cxx +++ b/vcl/source/gdi/pngwrite.cxx @@ -131,6 +131,7 @@ PNGWriterImpl::PNGWriterImpl( const BitmapEx& rBmpEx, mpAccess ( NULL ), mpMaskAccess ( NULL ), mpZCodec ( new ZCodec( DEFAULT_IN_BUFSIZE, DEFAULT_OUT_BUFSIZE, MAX_MEM_USAGE ) ), + mnCRC(0UL), mnLastPercent ( 0UL ) { if ( !rBmpEx.IsEmpty() ) diff --git a/vcl/source/gdi/print3.cxx b/vcl/source/gdi/print3.cxx index de7cd2e139da..191f8f26dc75 100644 --- a/vcl/source/gdi/print3.cxx +++ b/vcl/source/gdi/print3.cxx @@ -36,6 +36,7 @@ #include "vcl/svids.hrc" #include "vcl/metaact.hxx" #include "vcl/msgbox.hxx" +#include "vcl/configsettings.hxx" #include "tools/urlobj.hxx" @@ -171,13 +172,15 @@ public: // set by user through printer config dialog // if set, pages are centered and trimmed onto the fixed page Size maFixedPageSize; + sal_Int32 mnDefaultPaperBin; ImplPrinterControllerData() : mbFirstPage( sal_True ), mbLastPage( sal_False ), mbReversePageOrder( sal_False ), meJobState( view::PrintableState_JOB_STARTED ), - mpProgress( NULL ) + mpProgress( NULL ), + mnDefaultPaperBin( -1 ) {} ~ImplPrinterControllerData() { delete mpProgress; } @@ -327,9 +330,25 @@ void Printer::ImplPrintJob( const boost::shared_ptr<PrinterController>& i_pContr // setup printer // if no specific printer is already set, create one + + // #i108686# + // in case of a UI (platform independent or system dialog) print job, make the printer persistent over jobs + // however if no printer was already set by the print job's originator, + // and this is an API job, then use the system default location (because + // this is the only sensible default available if the user has no means of changing + // the destination if( ! pController->getPrinter() ) { - boost::shared_ptr<Printer> pPrinter( new Printer( i_rInitSetup.GetPrinterName() ) ); + rtl::OUString aPrinterName( i_rInitSetup.GetPrinterName() ); + if( ! aPrinterName.getLength() && pController->isShowDialogs() && ! pController->isDirectPrint() ) + { + // get printer name from configuration + SettingsConfigItem* pItem = SettingsConfigItem::get(); + aPrinterName = pItem->getValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintDialog" ) ), + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "LastPrinterUsed" ) ) ); + } + + boost::shared_ptr<Printer> pPrinter( new Printer( aPrinterName ) ); pController->setPrinter( pPrinter ); } @@ -440,7 +459,12 @@ void Printer::ImplPrintJob( const boost::shared_ptr<PrinterController>& i_pContr return; } pController->setValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "LocalFileName" ) ), - makeAny( aFile ) ); + makeAny( aFile ) ); + } + else if( aDlg.isSingleJobs() ) + { + pController->setValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintCollateAsSingleJobs" ) ), + makeAny( sal_True ) ); } } catch( std::bad_alloc& ) @@ -501,6 +525,13 @@ bool Printer::StartJob( const rtl::OUString& i_rJobName, boost::shared_ptr<vcl:: if ( !mpPrinter ) return FALSE; + sal_Bool bSinglePrintJobs = sal_False; + beans::PropertyValue* pSingleValue = i_pController->getValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintCollateAsSingleJobs" ) ) ); + if( pSingleValue ) + { + pSingleValue->Value >>= bSinglePrintJobs; + } + // remark: currently it is still possible to use EnablePrintFile and // SetPrintFileName to redirect printout into file // it can be argued that those methods should be removed in favor @@ -514,6 +545,7 @@ bool Printer::StartJob( const rtl::OUString& i_rJobName, boost::shared_ptr<vcl:: { mbPrintFile = TRUE; maPrintFile = aFile; + bSinglePrintJobs = sal_False; } } @@ -561,49 +593,90 @@ bool Printer::StartJob( const rtl::OUString& i_rJobName, boost::shared_ptr<vcl:: i_pController->setJobState( view::PrintableState_JOB_STARTED ); i_pController->jobStarted(); - if( mpPrinter->StartJob( pPrintFile, - i_rJobName, - Application::GetDisplayName(), - nCopies, - bCollateCopy, - i_pController->isDirectPrint(), - maJobSetup.ImplGetConstData() ) ) + int nJobs = 1; + int nRepeatCount = bUserCopy ? mnCopyCount : 1; + if( bSinglePrintJobs ) { - mbJobActive = TRUE; - i_pController->createProgressDialog(); - int nPages = i_pController->getFilteredPageCount(); - int nRepeatCount = bUserCopy ? mnCopyCount : 1; - for( int nIteration = 0; nIteration < nRepeatCount; nIteration++ ) + nJobs = mnCopyCount; + nCopies = 1; + nRepeatCount = 1; + } + + for( int nJobIteration = 0; nJobIteration < nJobs; nJobIteration++ ) + { + bool bError = false; + if( mpPrinter->StartJob( pPrintFile, + i_rJobName, + Application::GetDisplayName(), + nCopies, + bCollateCopy, + i_pController->isDirectPrint(), + maJobSetup.ImplGetConstData() ) ) { - for( int nPage = 0; nPage < nPages; nPage++ ) + mbJobActive = TRUE; + i_pController->createProgressDialog(); + int nPages = i_pController->getFilteredPageCount(); + for( int nIteration = 0; nIteration < nRepeatCount; nIteration++ ) { - if( nPage == nPages-1 && nIteration == nRepeatCount-1 ) - i_pController->setLastPage( sal_True ); - i_pController->printFilteredPage( nPage ); + for( int nPage = 0; nPage < nPages; nPage++ ) + { + if( nPage == nPages-1 && nIteration == nRepeatCount-1 && nJobIteration == nJobs-1 ) + i_pController->setLastPage( sal_True ); + i_pController->printFilteredPage( nPage ); + } + // FIXME: duplex ? + } + EndJob(); + + if( nJobIteration < nJobs-1 ) + { + mpPrinter = pSVData->mpDefInst->CreatePrinter( mpInfoPrinter ); + + if ( mpPrinter ) + { + maJobName = i_rJobName; + mnCurPage = 1; + mnCurPrintPage = 1; + mbPrinting = TRUE; + } + else + bError = true; } - // FIXME: duplex ? } - EndJob(); + else + bError = true; - if( i_pController->getJobState() == view::PrintableState_JOB_STARTED ) - i_pController->setJobState( view::PrintableState_JOB_SPOOLED ); + if( bError ) + { + mnError = ImplSalPrinterErrorCodeToVCL( mpPrinter->GetErrorCode() ); + if ( !mnError ) + mnError = PRINTER_GENERALERROR; + i_pController->setJobState( mnError == PRINTER_ABORT + ? view::PrintableState_JOB_ABORTED + : view::PrintableState_JOB_FAILED ); + if( mpPrinter ) + pSVData->mpDefInst->DestroyPrinter( mpPrinter ); + mnCurPage = 0; + mnCurPrintPage = 0; + mbPrinting = FALSE; + mpPrinter = NULL; + + return false; + } } - else - { - mnError = ImplSalPrinterErrorCodeToVCL( mpPrinter->GetErrorCode() ); - if ( !mnError ) - mnError = PRINTER_GENERALERROR; - i_pController->setJobState( mnError == PRINTER_ABORT - ? view::PrintableState_JOB_ABORTED - : view::PrintableState_JOB_FAILED ); - pSVData->mpDefInst->DestroyPrinter( mpPrinter ); - mnCurPage = 0; - mnCurPrintPage = 0; - mbPrinting = FALSE; - mpPrinter = NULL; - return false; - } + if( i_pController->getJobState() == view::PrintableState_JOB_STARTED ) + i_pController->setJobState( view::PrintableState_JOB_SPOOLED ); + } + + // make last used printer persistent for UI jobs + if( i_pController->isShowDialogs() && ! i_pController->isDirectPrint() ) + { + SettingsConfigItem* pItem = SettingsConfigItem::get(); + pItem->setValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintDialog" ) ), + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "LastPrinterUsed" ) ), + GetName() + ); } return true; @@ -634,6 +707,7 @@ void PrinterController::setPrinter( const boost::shared_ptr<Printer>& i_rPrinter mpImplData->mpPrinter = i_rPrinter; setValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Name" ) ), makeAny( rtl::OUString( i_rPrinter->GetName() ) ) ); + mpImplData->mnDefaultPaperBin = mpImplData->mpPrinter->GetPaperBin(); } bool PrinterController::setupPrinter( Window* i_pParent ) @@ -668,27 +742,55 @@ PrinterController::PageSize vcl::ImplPrinterControllerData::modifyJobSetup( cons { PrinterController::PageSize aPageSize; aPageSize.aSize = mpPrinter->GetPaperSize(); + awt::Size aSetSize, aIsSize; + sal_Int32 nPaperBin = mnDefaultPaperBin; for( sal_Int32 nProperty = 0, nPropertyCount = i_rProps.getLength(); nProperty < nPropertyCount; ++nProperty ) { - if( i_rProps[ nProperty ].Name.equalsAscii( "PageSize" ) ) + if( i_rProps[ nProperty ].Name.equalsAscii( "PreferredPageSize" ) ) { - awt::Size aSize; - i_rProps[ nProperty].Value >>= aSize; - aPageSize.aSize.Width() = aSize.Width; - aPageSize.aSize.Height() = aSize.Height; - - Size aCurSize( mpPrinter->GetPaperSize() ); - Size aRealPaperSize( getRealPaperSize( aPageSize.aSize ) ); - if( aRealPaperSize != aCurSize ) - mpPrinter->SetPaperSizeUser( aRealPaperSize, ! isFixedPageSize() ); + i_rProps[ nProperty ].Value >>= aSetSize; } - if( i_rProps[ nProperty ].Name.equalsAscii( "PageIncludesNonprintableArea" ) ) + else if( i_rProps[ nProperty ].Name.equalsAscii( "PageSize" ) ) + { + i_rProps[ nProperty ].Value >>= aIsSize; + } + else if( i_rProps[ nProperty ].Name.equalsAscii( "PageIncludesNonprintableArea" ) ) { sal_Bool bVal = sal_False; - i_rProps[ nProperty].Value >>= bVal; + i_rProps[ nProperty ].Value >>= bVal; aPageSize.bFullPaper = static_cast<bool>(bVal); } + else if( i_rProps[ nProperty ].Name.equalsAscii( "PrinterPaperTray" ) ) + { + sal_Int32 nBin = -1; + i_rProps[ nProperty ].Value >>= nBin; + if( nBin >= 0 && nBin < mpPrinter->GetPaperBinCount() ) + nPaperBin = nBin; + } + } + + Size aCurSize( mpPrinter->GetPaperSize() ); + if( aSetSize.Width && aSetSize.Height ) + { + Size aSetPaperSize( aSetSize.Width, aSetSize.Height ); + Size aRealPaperSize( getRealPaperSize( aSetPaperSize ) ); + if( aRealPaperSize != aCurSize ) + aIsSize = aSetSize; } + + if( aIsSize.Width && aIsSize.Height ) + { + aPageSize.aSize.Width() = aIsSize.Width; + aPageSize.aSize.Height() = aIsSize.Height; + + Size aRealPaperSize( getRealPaperSize( aPageSize.aSize ) ); + if( aRealPaperSize != aCurSize ) + mpPrinter->SetPaperSizeUser( aRealPaperSize, ! isFixedPageSize() ); + } + + if( nPaperBin != -1 && nPaperBin != mpPrinter->GetPaperBin() ) + mpPrinter->SetPaperBin( nPaperBin ); + return aPageSize; } @@ -1393,6 +1495,8 @@ void PrinterController::createProgressDialog() mpImplData->mpProgress->Show(); } } + else + mpImplData->mpProgress->reset(); } void PrinterController::setMultipage( const MultiPageSetup& i_rMPS ) diff --git a/vcl/source/gdi/region.cxx b/vcl/source/gdi/region.cxx index 07351e1c0fce..4931ee66e93f 100644 --- a/vcl/source/gdi/region.cxx +++ b/vcl/source/gdi/region.cxx @@ -45,6 +45,7 @@ #include <basegfx/matrix/b2dhommatrix.hxx> #include <basegfx/polygon/b2dpolypolygontools.hxx> +#include <basegfx/polygon/b2dpolygontools.hxx> #include <basegfx/range/b2drange.hxx> #include <basegfx/matrix/b2dhommatrixtools.hxx> @@ -2004,6 +2005,32 @@ const basegfx::B2DPolyPolygon Region::GetB2DPolyPolygon() const // ----------------------------------------------------------------------- +basegfx::B2DPolyPolygon Region::ConvertToB2DPolyPolygon() +{ + DBG_CHKTHIS( Region, ImplDbgTestRegion ); + + basegfx::B2DPolyPolygon aRet; + + if( HasPolyPolygon() ) + aRet = GetB2DPolyPolygon(); + else + { + RegionHandle aHdl = BeginEnumRects(); + Rectangle aSubRect; + while( GetNextEnumRect( aHdl, aSubRect ) ) + { + basegfx::B2DPolygon aPoly( basegfx::tools::createPolygonFromRect( + basegfx::B2DRectangle( aSubRect.Left(), aSubRect.Top(), aSubRect.Right(), aSubRect.Bottom() ) ) ); + aRet.append( aPoly ); + } + EndEnumRects( aHdl ); + } + + return aRet; +} + +// ----------------------------------------------------------------------- + BOOL Region::ImplGetFirstRect( ImplRegionInfo& rImplRegionInfo, long& rX, long& rY, long& rWidth, long& rHeight ) const diff --git a/vcl/source/gdi/salgdilayout.cxx b/vcl/source/gdi/salgdilayout.cxx index 9354b0f72130..55d6f7bdd892 100644 --- a/vcl/source/gdi/salgdilayout.cxx +++ b/vcl/source/gdi/salgdilayout.cxx @@ -689,6 +689,12 @@ void SalGraphics::mirror( ControlType nType, const ImplControlValue& rVal, const { switch( nType ) { + case CTRL_SLIDER: + { + SliderValue* pSlVal = reinterpret_cast<SliderValue*>(rVal.getOptionalVal()); + mirror(pSlVal->maThumbRect,pOutDev,bBack); + } + break; case CTRL_SCROLLBAR: { ScrollbarValue* pScVal = reinterpret_cast<ScrollbarValue*>(rVal.getOptionalVal()); diff --git a/vcl/source/gdi/sallayout.cxx b/vcl/source/gdi/sallayout.cxx index 344867ebb0b0..bf462d1d8add 100755 --- a/vcl/source/gdi/sallayout.cxx +++ b/vcl/source/gdi/sallayout.cxx @@ -133,13 +133,13 @@ int GetVerticalFlags( sal_UCS4 nChar ) /* #i52932# remember: nChar == 0x2010 || nChar == 0x2015 nChar == 0x2016 || nChar == 0x2026 - are GF_NONE also, but already handled in the first if */ if((nChar >= 0x3008 && nChar <= 0x301C && nChar != 0x3012) - || nChar == 0xFF3B || nChar == 0xFF3D + || (nChar == 0xFF3B || nChar == 0xFF3D) || (nChar >= 0xFF5B && nChar <= 0xFF9F) // halfwidth forms - || nChar == 0xFFE3 ) + || (nChar == 0xFFE3) + || (nChar >= 0x02F800 && nChar <= 0x02FFFF) ) return GF_NONE; // not rotated else if( nChar == 0x30fc ) return GF_ROTR; // right diff --git a/vcl/source/glyphs/gcach_ftyp.cxx b/vcl/source/glyphs/gcach_ftyp.cxx index a337f2553ff7..ebdd59f517af 100644 --- a/vcl/source/glyphs/gcach_ftyp.cxx +++ b/vcl/source/glyphs/gcach_ftyp.cxx @@ -38,8 +38,6 @@ #include "vcl/svapp.hxx" #include "vcl/outfont.hxx" #include "vcl/impfont.hxx" -#include "vcl/bitmap.hxx" -#include "vcl/bmpacc.hxx" #include "tools/poly.hxx" #include "basegfx/matrix/b2dhommatrix.hxx" @@ -80,7 +78,7 @@ typedef FT_Vector* FT_Vector_CPtr; // TODO: move file mapping stuff to OSL #if defined(UNX) #if !defined(HPUX) - // PORTERS: dlfcn is used for code dependend on FT version + // PORTERS: dlfcn is used for getting symbols from FT versions newer than baseline #include <dlfcn.h> #endif #include <unistd.h> @@ -93,10 +91,6 @@ typedef FT_Vector* FT_Vector_CPtr; #define strncasecmp strnicmp #endif -#include "vcl/svapp.hxx" -#include "vcl/settings.hxx" -#include "i18npool/lang.h" - typedef const unsigned char* CPU8; inline sal_uInt16 NEXT_U16( CPU8& p ) { p+=2; return (p[-2]<<8)|p[-1]; } inline sal_Int16 NEXT_S16( CPU8& p ) { return (sal_Int16)NEXT_U16(p); } @@ -623,9 +617,6 @@ long FreetypeManager::AddFontDir( const String& rUrlName ) aDFA.mbSubsettable= false; aDFA.mbEmbeddable = false; - aDFA.meEmbeddedBitmap = EMBEDDEDBITMAP_DONTKNOW; - aDFA.meAntiAlias = ANTIALIAS_DONTKNOW; - FT_Done_Face( aFaceFT ); AddFontFile( aCFileName, nFaceNum, ++mnNextFontId, aDFA, NULL ); ++nCount; @@ -705,6 +696,7 @@ FreetypeServerFont::FreetypeServerFont( const ImplFontSelectData& rFSD, FtFontIn : ServerFont( rFSD ), mnPrioEmbedded(nDefaultPrioEmbedded), mnPrioAntiAlias(nDefaultPrioAntiAlias), + mnPrioAutoHint(nDefaultPrioAutoHint), mpFontInfo( pFI ), maFaceFT( NULL ), maSizeFT( NULL ), @@ -838,46 +830,71 @@ FreetypeServerFont::FreetypeServerFont( const ImplFontSelectData& rFSD, FtFontIn mbArtItalic = (rFSD.meItalic != ITALIC_NONE && pFI->GetFontAttributes().GetSlant() == ITALIC_NONE); mbArtBold = (rFSD.meWeight > WEIGHT_MEDIUM && pFI->GetFontAttributes().GetWeight() <= WEIGHT_MEDIUM); - - //static const int TT_CODEPAGE_RANGE_874 = (1L << 16); // Thai - //static const int TT_CODEPAGE_RANGE_932 = (1L << 17); // JIS/Japan - //static const int TT_CODEPAGE_RANGE_936 = (1L << 18); // Chinese: Simplified - //static const int TT_CODEPAGE_RANGE_949 = (1L << 19); // Korean Wansung - //static const int TT_CODEPAGE_RANGE_950 = (1L << 20); // Chinese: Traditional - //static const int TT_CODEPAGE_RANGE_1361 = (1L << 21); // Korean Johab - static const int TT_CODEPAGE_RANGES1_CJKT = 0x3F0000; // all of the above - const TT_OS2* pOs2 = (const TT_OS2*)FT_Get_Sfnt_Table( maFaceFT, ft_sfnt_os2 ); - if ((pOs2) && (pOs2->ulCodePageRange1 & TT_CODEPAGE_RANGES1_CJKT ) + mbUseGamma = false; + if( mbArtBold ) + { + //static const int TT_CODEPAGE_RANGE_874 = (1L << 16); // Thai + //static const int TT_CODEPAGE_RANGE_932 = (1L << 17); // JIS/Japan + //static const int TT_CODEPAGE_RANGE_936 = (1L << 18); // Chinese: Simplified + //static const int TT_CODEPAGE_RANGE_949 = (1L << 19); // Korean Wansung + //static const int TT_CODEPAGE_RANGE_950 = (1L << 20); // Chinese: Traditional + //static const int TT_CODEPAGE_RANGE_1361 = (1L << 21); // Korean Johab + static const int TT_CODEPAGE_RANGES1_CJKT = 0x3F0000; // all of the above + const TT_OS2* pOs2 = (const TT_OS2*)FT_Get_Sfnt_Table( maFaceFT, ft_sfnt_os2 ); + if ((pOs2) && (pOs2->ulCodePageRange1 & TT_CODEPAGE_RANGES1_CJKT ) && rFSD.mnHeight < 20) mbUseGamma = true; - else - mbUseGamma = false; + } + + if( ((mnCos != 0) && (mnSin != 0)) || (mnPrioEmbedded <= 0) ) + mnLoadFlags |= FT_LOAD_NO_BITMAP; +} + +void FreetypeServerFont::SetFontOptions( const ImplFontOptions& rFontOptions) +{ + FontAutoHint eHint = rFontOptions.GetUseAutoHint(); + if( eHint == AUTOHINT_DONTKNOW ) + eHint = mbUseGamma ? AUTOHINT_TRUE : AUTOHINT_FALSE; - if (mbUseGamma) + if( eHint == AUTOHINT_TRUE ) mnLoadFlags |= FT_LOAD_FORCE_AUTOHINT; if( (mnSin != 0) && (mnCos != 0) ) // hinting for 0/90/180/270 degrees only mnLoadFlags |= FT_LOAD_NO_HINTING; mnLoadFlags |= FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH; //#88334# - if (mpFontInfo->DontUseAntiAlias()) - mnPrioAntiAlias = 0; - if (mpFontInfo->DontUseEmbeddedBitmaps()) - mnPrioEmbedded = 0; + if( rFontOptions.DontUseAntiAlias() ) + mnPrioAntiAlias = 0; + if( rFontOptions.DontUseEmbeddedBitmaps() ) + mnPrioEmbedded = 0; + if( rFontOptions.DontUseHinting() ) + mnPrioAutoHint = 0; #if (FTVERSION >= 2005) || defined(TT_CONFIG_OPTION_BYTECODE_INTERPRETER) - if( nDefaultPrioAutoHint <= 0 ) + if( mnPrioAutoHint <= 0 ) #endif mnLoadFlags |= FT_LOAD_NO_HINTING; -#ifdef FT_LOAD_TARGET_LIGHT - // enable "light hinting" if available +#if defined(FT_LOAD_TARGET_LIGHT) && defined(FT_LOAD_TARGET_NORMAL) if( !(mnLoadFlags & FT_LOAD_NO_HINTING) && (nFTVERSION >= 2103)) - mnLoadFlags |= FT_LOAD_TARGET_LIGHT; + { + mnLoadFlags |= FT_LOAD_TARGET_NORMAL; + switch( rFontOptions.GetHintStyle() ) + { + case HINT_NONE: + mnLoadFlags |= FT_LOAD_NO_HINTING; + break; + case HINT_SLIGHT: + mnLoadFlags |= FT_LOAD_TARGET_LIGHT; + break; + case HINT_MEDIUM: + break; + case HINT_FULL: + default: + break; + } + } #endif - - if( ((mnCos != 0) && (mnSin != 0)) || (mnPrioEmbedded <= 0) ) - mnLoadFlags |= FT_LOAD_NO_BITMAP; } // ----------------------------------------------------------------------- @@ -1231,13 +1248,15 @@ int FreetypeServerFont::FixupGlyphIndex( int nGlyphIndex, sal_UCS4 aChar ) const } } -#if !defined(TT_CONFIG_OPTION_BYTECODE_INTERPRETER) +#if 0 // #95556# autohinting not yet optimized for non-western glyph styles if( !(mnLoadFlags & (FT_LOAD_NO_HINTING | FT_LOAD_FORCE_AUTOHINT) ) && ( (aChar >= 0x0600 && aChar < 0x1E00) // south-east asian + arabic ||(aChar >= 0x2900 && aChar < 0xD800) // CJKV ||(aChar >= 0xF800) ) ) // presentation + symbols + { nGlyphFlags |= GF_UNHINTED; + } #endif if( nGlyphIndex != 0 ) @@ -1377,13 +1396,13 @@ bool FreetypeServerFont::GetGlyphBitmap1( int nGlyphIndex, RawBitmap& rRawBitmap nLoadFlags |= FT_LOAD_NO_BITMAP; #if (FTVERSION >= 2002) - // for 0/90/180/270 degree fonts enable autohinting even if not advisable + // for 0/90/180/270 degree fonts enable hinting even if not advisable // non-hinted and non-antialiased bitmaps just look too ugly - if( (mnCos==0 || mnSin==0) && (nDefaultPrioAutoHint > 0) ) + if( (mnCos==0 || mnSin==0) && (mnPrioAutoHint > 0) ) nLoadFlags &= ~FT_LOAD_NO_HINTING; #endif - if( mnPrioEmbedded <= nDefaultPrioAutoHint ) + if( mnPrioEmbedded <= mnPrioAutoHint ) nLoadFlags |= FT_LOAD_NO_BITMAP; FT_Error rc = -1; @@ -1548,7 +1567,7 @@ bool FreetypeServerFont::GetGlyphBitmap8( int nGlyphIndex, RawBitmap& rRawBitmap // autohinting in FT<=2.0.4 makes antialiased glyphs look worse nLoadFlags |= FT_LOAD_NO_HINTING; #else - if( (nGlyphFlags & GF_UNHINTED) || (nDefaultPrioAutoHint < mnPrioAntiAlias) ) + if( (nGlyphFlags & GF_UNHINTED) || (mnPrioAutoHint < mnPrioAntiAlias) ) nLoadFlags |= FT_LOAD_NO_HINTING; #endif diff --git a/vcl/source/glyphs/gcach_ftyp.hxx b/vcl/source/glyphs/gcach_ftyp.hxx index 2a181b494c9f..5ebe70bcbdf9 100644 --- a/vcl/source/glyphs/gcach_ftyp.hxx +++ b/vcl/source/glyphs/gcach_ftyp.hxx @@ -33,6 +33,7 @@ #include <ft2build.h> #include FT_FREETYPE_H + class FreetypeServerFont; struct FT_GlyphRec_; @@ -85,10 +86,6 @@ public: int GetFaceNum() const { return mnFaceNum; } int GetSynthetic() const { return mnSynthetic; } sal_IntPtr GetFontId() const { return mnFontId; } - bool DontUseAntiAlias() const - { return maDevFontAttributes.UseAntiAlias() == ANTIALIAS_FALSE; } - bool DontUseEmbeddedBitmaps() const - { return maDevFontAttributes.UseEmbeddedBitmap() == EMBEDDEDBITMAP_FALSE; } bool IsSymbolFont() const { return maDevFontAttributes.IsSymbolFont(); } const ImplFontAttributes& GetFontAttributes() const { return maDevFontAttributes; } @@ -178,6 +175,7 @@ public: virtual int GetFontFaceNum() const { return mpFontInfo->GetFaceNum(); } virtual bool TestFont() const; virtual void* GetFtFace() const; + virtual void SetFontOptions( const ImplFontOptions&); virtual int GetLoadFlags() const { return (mnLoadFlags & ~FT_LOAD_IGNORE_TRANSFORM); } virtual bool NeedsArtificialBold() const { return mbArtBold; } virtual bool NeedsArtificialItalic() const { return mbArtItalic; } @@ -213,6 +211,7 @@ private: int mnWidth; int mnPrioEmbedded; int mnPrioAntiAlias; + int mnPrioAutoHint; FtFontInfo* mpFontInfo; FT_Int mnLoadFlags; double mfStretch; diff --git a/vcl/source/glyphs/glyphcache.cxx b/vcl/source/glyphs/glyphcache.cxx index 34133a39ac95..ea0f18896b7a 100644 --- a/vcl/source/glyphs/glyphcache.cxx +++ b/vcl/source/glyphs/glyphcache.cxx @@ -69,13 +69,22 @@ GlyphCache::GlyphCache( GlyphCachePeer& rPeer ) GlyphCache::~GlyphCache() { -// TODO: -// for( FontList::iterator it = maFontList.begin(); it != maFontList.end(); ++it ) -// delete const_cast<ServerFont*>( it->second ); + InvalidateAllGlyphs(); if( mpFtManager ) delete mpFtManager; } +// ----------------------------------------------------------------------- + +void GlyphCache::InvalidateAllGlyphs() +{ +#if 0 // TODO: implement uncaching of all glyph shapes and metrics + for( FontList::iterator it = maFontList.begin(); it != maFontList.end(); ++it ) + delete const_cast<ServerFont*>( it->second ); + maFontList.clear(); + mpCurrentGCFont = NULL; +#endif +} // ----------------------------------------------------------------------- @@ -582,3 +591,4 @@ int ExtraKernInfo::GetUnscaledKernValue( sal_Unicode cLeft, sal_Unicode cRight ) } // ======================================================================= + diff --git a/vcl/source/glyphs/graphite_adaptors.cxx b/vcl/source/glyphs/graphite_adaptors.cxx index 4afced765612..f66f5b48e39e 100644 --- a/vcl/source/glyphs/graphite_adaptors.cxx +++ b/vcl/source/glyphs/graphite_adaptors.cxx @@ -168,7 +168,7 @@ GraphiteFontAdaptor::~GraphiteFontAdaptor() throw() mpFeatures = NULL; } -void GraphiteFontAdaptor::UniqueCacheInfo(sil_std::wstring & face_name_out, bool & bold_out, bool & italic_out) +void GraphiteFontAdaptor::UniqueCacheInfo(ext_std::wstring & face_name_out, bool & bold_out, bool & italic_out) { face_name_out = maFontProperties.szFaceName; bold_out = maFontProperties.fBold; diff --git a/vcl/source/glyphs/graphite_cache.cxx b/vcl/source/glyphs/graphite_cache.cxx index 713f3c1ed088..64bbb0a38d60 100644 --- a/vcl/source/glyphs/graphite_cache.cxx +++ b/vcl/source/glyphs/graphite_cache.cxx @@ -36,10 +36,10 @@ #include <tools/debug.hxx> #include <vcl/sallayout.hxx> -#include "pregraphitestl.h" +#include <tools/preextstl.h> #include <graphite/GrClient.h> #include <graphite/Segment.h> -#include "postgraphitestl.h" +#include <tools/postextstl.h> #include <rtl/ustring.hxx> #include <vcl/graphite_layout.hxx> diff --git a/vcl/source/glyphs/graphite_features.cxx b/vcl/source/glyphs/graphite_features.cxx index bae96642da30..1cb25306c4ee 100644 --- a/vcl/source/glyphs/graphite_features.cxx +++ b/vcl/source/glyphs/graphite_features.cxx @@ -88,7 +88,7 @@ GrFeatureParser::GrFeatureParser(gr::Font & font, const std::string features, co gr::isocode aLang = maLang; for (size_t i = pos; i < nFeatEnd; i++) aLang.rgch[i-pos] = features[i]; - sil_std::pair<gr::LanguageIterator,gr::LanguageIterator> aSupported + ext_std::pair<gr::LanguageIterator,gr::LanguageIterator> aSupported = font.getSupportedLanguages(); gr::LanguageIterator iL = aSupported.first; while (iL != aSupported.second) @@ -139,7 +139,7 @@ void GrFeatureParser::setLang(gr::Font & font, const std::string & lang) if (lang[i] == '-') break; aLang.rgch[i] = lang[i]; } - sil_std::pair<gr::LanguageIterator,gr::LanguageIterator> aSupported + ext_std::pair<gr::LanguageIterator,gr::LanguageIterator> aSupported = font.getSupportedLanguages(); gr::LanguageIterator iL = aSupported.first; while (iL != aSupported.second) @@ -186,7 +186,7 @@ bool GrFeatureParser::isValid(gr::Font & font, gr::FeatureSetting & setting) { return false; } - sil_std::pair< gr::FeatureSettingIterator, gr::FeatureSettingIterator > + ext_std::pair< gr::FeatureSettingIterator, gr::FeatureSettingIterator > validValues = font.getFeatureSettings(i); gr::FeatureSettingIterator j = validValues.first; while (j != validValues.second) diff --git a/vcl/source/glyphs/graphite_layout.cxx b/vcl/source/glyphs/graphite_layout.cxx index 25ea77dd07a3..6e75d1fde868 100644 --- a/vcl/source/glyphs/graphite_layout.cxx +++ b/vcl/source/glyphs/graphite_layout.cxx @@ -63,13 +63,13 @@ #include <unicode/uscript.h> // Graphite Libraries (must be after vcl headers on windows) -#include "pregraphitestl.h" +#include <tools/preextstl.h> #include <graphite/GrClient.h> #include <graphite/Font.h> #include <graphite/ITextSource.h> #include <graphite/Segment.h> #include <graphite/SegmentPainter.h> -#include "postgraphitestl.h" +#include <tools/postextstl.h> #include <vcl/graphite_layout.hxx> #include <vcl/graphite_features.hxx> @@ -104,8 +104,8 @@ FILE * grLog() namespace { - typedef sil_std::pair<gr::GlyphIterator, gr::GlyphIterator> glyph_range_t; - typedef sil_std::pair<gr::GlyphSetIterator, gr::GlyphSetIterator> glyph_set_range_t; + typedef ext_std::pair<gr::GlyphIterator, gr::GlyphIterator> glyph_range_t; + typedef ext_std::pair<gr::GlyphSetIterator, gr::GlyphSetIterator> glyph_set_range_t; inline long round(const float n) { return long(n + (n < 0 ? -0.5 : 0.5)); @@ -170,7 +170,7 @@ GraphiteLayout::Glyphs::fill_from(gr::Segment & rSegment, ImplLayoutArgs &rArgs, bool bRtl, long &rWidth, float fScaling, std::vector<int> & rChar2Base, std::vector<int> & rGlyph2Char, std::vector<int> & rCharDxs) { // Create a glyph item for each of the glyph and append it to the base class glyph list. - typedef sil_std::pair< gr::GlyphSetIterator, gr::GlyphSetIterator > GrGlyphSet; + typedef ext_std::pair< gr::GlyphSetIterator, gr::GlyphSetIterator > GrGlyphSet; int nChar = rArgs.mnEndCharPos - rArgs.mnMinCharPos; glyph_range_t iGlyphs = rSegment.glyphs(); int nGlyphs = iGlyphs.second - iGlyphs.first; @@ -585,7 +585,7 @@ public: sal_Int32 hashCode(const grutils::GrFeatureParser * mpFeatures) { // is this sufficient? - sil_std::wstring aFace; + ext_std::wstring aFace; bool bBold; bool bItalic; UniqueCacheInfo(aFace, bBold, bItalic); diff --git a/vcl/source/glyphs/graphite_textsrc.cxx b/vcl/source/glyphs/graphite_textsrc.cxx index d7547662e065..5764ba9454c9 100644 --- a/vcl/source/glyphs/graphite_textsrc.cxx +++ b/vcl/source/glyphs/graphite_textsrc.cxx @@ -135,16 +135,16 @@ gr::isocode TextSourceAdaptor::getLanguage(gr::toffset) return unknown; } -sil_std::pair<gr::toffset, gr::toffset> TextSourceAdaptor::propertyRange(gr::toffset nCharIdx) +ext_std::pair<gr::toffset, gr::toffset> TextSourceAdaptor::propertyRange(gr::toffset nCharIdx) { if (nCharIdx < unsigned(maLayoutArgs.mnMinCharPos)) - return sil_std::make_pair(0, maLayoutArgs.mnMinCharPos); + return ext_std::make_pair(0, maLayoutArgs.mnMinCharPos); if (nCharIdx < mnEnd) - return sil_std::make_pair(maLayoutArgs.mnMinCharPos, mnEnd); + return ext_std::make_pair(maLayoutArgs.mnMinCharPos, mnEnd); - return sil_std::make_pair(mnEnd, maLayoutArgs.mnLength); + return ext_std::make_pair(mnEnd, maLayoutArgs.mnLength); } size_t TextSourceAdaptor::getFontFeatures(gr::toffset, gr::FeatureSetting * settings) @@ -156,7 +156,7 @@ size_t TextSourceAdaptor::getFontFeatures(gr::toffset, gr::FeatureSetting * sett bool TextSourceAdaptor::sameSegment(gr::toffset char_idx1, gr::toffset char_idx2) { - const sil_std::pair<gr::toffset, gr::toffset> + const ext_std::pair<gr::toffset, gr::toffset> range1 = propertyRange(char_idx1), range2 = propertyRange(char_idx2); diff --git a/vcl/source/glyphs/graphite_textsrc.hxx b/vcl/source/glyphs/graphite_textsrc.hxx index 2397d6a5f701..2b9c705a5ea7 100644 --- a/vcl/source/glyphs/graphite_textsrc.hxx +++ b/vcl/source/glyphs/graphite_textsrc.hxx @@ -59,11 +59,11 @@ #include "vcl/dllapi.h" // Libraries -#include "pregraphitestl.h" +#include <tools/preextstl.h> #include <graphite/GrClient.h> #include <graphite/Font.h> #include <graphite/ITextSource.h> -#include "postgraphitestl.h" +#include <tools/postextstl.h> // Module type definitions and forward declarations. // @@ -90,7 +90,7 @@ public: virtual float getVerticalOffset(gr::toffset ich); virtual gr::isocode getLanguage(gr::toffset ich); - virtual sil_std::pair<gr::toffset, gr::toffset> propertyRange(gr::toffset ich); + virtual ext_std::pair<gr::toffset, gr::toffset> propertyRange(gr::toffset ich); virtual size_t getFontFeatures(gr::toffset ich, gr::FeatureSetting * prgfset); virtual bool sameSegment(gr::toffset ich1, gr::toffset ich2); diff --git a/vcl/source/helper/xconnection.cxx b/vcl/source/helper/xconnection.cxx index 19ac9103bf96..caf7ee237d67 100644 --- a/vcl/source/helper/xconnection.cxx +++ b/vcl/source/helper/xconnection.cxx @@ -141,12 +141,16 @@ bool DisplayConnection::dispatchEvent( void* pThis, void* pData, int nBytes ) SolarMutexReleaser aRel; DisplayConnection* This = (DisplayConnection*)pThis; - MutexGuard aGuard( This->m_aMutex ); Sequence< sal_Int8 > aSeq( (sal_Int8*)pData, nBytes ); Any aEvent; aEvent <<= aSeq; - for( ::std::list< Reference< XEventHandler > >::const_iterator it = This->m_aHandlers.begin(); it != This->m_aHandlers.end(); ++it ) + ::std::list< Reference< XEventHandler > > handlers; + { + MutexGuard aGuard( This->m_aMutex ); + handlers = This->m_aHandlers; + } + for( ::std::list< Reference< XEventHandler > >::const_iterator it = handlers.begin(); it != handlers.end(); ++it ) if( (*it)->handleEvent( aEvent ) ) return true; return false; @@ -157,12 +161,16 @@ bool DisplayConnection::dispatchErrorEvent( void* pThis, void* pData, int nBytes SolarMutexReleaser aRel; DisplayConnection* This = (DisplayConnection*)pThis; - MutexGuard aGuard( This->m_aMutex ); Sequence< sal_Int8 > aSeq( (sal_Int8*)pData, nBytes ); Any aEvent; aEvent <<= aSeq; - for( ::std::list< Reference< XEventHandler > >::const_iterator it = This->m_aErrorHandlers.begin(); it != This->m_aErrorHandlers.end(); ++it ) + ::std::list< Reference< XEventHandler > > handlers; + { + MutexGuard aGuard( This->m_aMutex ); + handlers = This->m_aErrorHandlers; + } + for( ::std::list< Reference< XEventHandler > >::const_iterator it = handlers.begin(); it != handlers.end(); ++it ) if( (*it)->handleEvent( aEvent ) ) return true; diff --git a/vcl/source/window/decoview.cxx b/vcl/source/window/decoview.cxx index 03675ccf69ca..a32790cfb0d4 100644 --- a/vcl/source/window/decoview.cxx +++ b/vcl/source/window/decoview.cxx @@ -1353,3 +1353,36 @@ Rectangle DecorationView::DrawButton( const Rectangle& rRect, USHORT nStyle ) return aRect; } + +// ----------------------------------------------------------------------- + +void DecorationView::DrawSeparator( const Point& rStart, const Point& rStop, bool bVertical ) +{ + Point aStart( rStart ), aStop( rStop ); + const StyleSettings& rStyleSettings = mpOutDev->GetSettings().GetStyleSettings(); + + mpOutDev->Push( PUSH_LINECOLOR ); + if ( rStyleSettings.GetOptions() & STYLE_OPTION_MONO ) + mpOutDev->SetLineColor( Color( COL_BLACK ) ); + else + mpOutDev->SetLineColor( rStyleSettings.GetShadowColor() ); + + mpOutDev->DrawLine( aStart, aStop ); + if ( !(rStyleSettings.GetOptions() & STYLE_OPTION_MONO) ) + { + mpOutDev->SetLineColor( rStyleSettings.GetLightColor() ); + if( bVertical ) + { + aStart.X()++; + aStop.X()++; + } + else + { + aStart.Y()++; + aStop.Y()++; + } + mpOutDev->DrawLine( aStart, aStop ); + } + mpOutDev->Pop(); +} + diff --git a/vcl/source/window/dlgctrl.cxx b/vcl/source/window/dlgctrl.cxx index daa26e2c7782..64f2b7e0d2a1 100644 --- a/vcl/source/window/dlgctrl.cxx +++ b/vcl/source/window/dlgctrl.cxx @@ -886,20 +886,6 @@ BOOL Window::ImplDlgCtrl( const KeyEvent& rKEvt, BOOL bKeyInput ) return TRUE; } - // if we have come here (and therefore the strange "formular" logic above - // turned up no result, then let's try to find a customer for Ctrl-TAB - if ( nKeyCode == KEY_TAB && aKeyCode.IsMod1() && ! aKeyCode.IsMod2() ) - { - TabDialog* pDlg = dynamic_cast<TabDialog*>(this); - if( pDlg ) - { - TabControl* pTabCtrl = pDlg->ImplGetFirstTabControl(); - NotifyEvent aEvt( bKeyInput ? EVENT_KEYINPUT : EVENT_KEYUP, - pTabCtrl, &rKEvt ); - return pTabCtrl->ImplHandleNotifyEvent( aEvt ); - } - } - return FALSE; } @@ -1093,10 +1079,15 @@ Window* Window::GetLabelFor() const return pWindow; sal_Unicode nAccel = getAccel( GetText() ); - if( GetType() == WINDOW_FIXEDTEXT || - GetType() == WINDOW_FIXEDLINE || - GetType() == WINDOW_GROUPBOX ) + + WindowType nMyType = GetType(); + if( nMyType == WINDOW_FIXEDTEXT || + nMyType == WINDOW_FIXEDLINE || + nMyType == WINDOW_GROUPBOX ) { + // #i100833# MT 2010/02: Group box and fixed lines can also lable a fixed text. + // See tools/options/print for example. + BOOL bThisIsAGroupControl = (nMyType == WINDOW_GROUPBOX) || (nMyType == WINDOW_FIXEDLINE); Window* pSWindow = NULL; // get index, form start and form end USHORT nIndex=0, nFormStart=0, nFormEnd=0; @@ -1128,9 +1119,14 @@ Window* Window::GetLabelFor() const FALSE ); if( pSWindow && pSWindow->IsVisible() && ! (pSWindow->GetStyle() & WB_NOLABEL) ) { - if( pSWindow->GetType() != WINDOW_FIXEDTEXT && - pSWindow->GetType() != WINDOW_FIXEDLINE && - pSWindow->GetType() != WINDOW_GROUPBOX ) + WindowType nType = pSWindow->GetType(); + if( nType != WINDOW_FIXEDTEXT && + nType != WINDOW_FIXEDLINE && + nType != WINDOW_GROUPBOX ) + { + pWindow = pSWindow; + } + else if( bThisIsAGroupControl && ( nType == WINDOW_FIXEDTEXT ) ) { pWindow = pSWindow; } @@ -1163,9 +1159,13 @@ Window* Window::GetLabeledBy() const if( GetType() == WINDOW_CHECKBOX || GetType() == WINDOW_RADIOBUTTON ) return NULL; - if( ! ( GetType() == WINDOW_FIXEDTEXT || - GetType() == WINDOW_FIXEDLINE || - GetType() == WINDOW_GROUPBOX ) ) +// if( ! ( GetType() == WINDOW_FIXEDTEXT || +// GetType() == WINDOW_FIXEDLINE || +// GetType() == WINDOW_GROUPBOX ) ) + // #i100833# MT 2010/02: Group box and fixed lines can also lable a fixed text. + // See tools/options/print for example. + WindowType nMyType = GetType(); + if ( (nMyType != WINDOW_GROUPBOX) && (nMyType != WINDOW_FIXEDLINE) ) { // search for a control that labels this window // a label is considered the last fixed text, fixed line or group box @@ -1196,14 +1196,18 @@ Window* Window::GetLabeledBy() const nSearchIndex, nFoundIndex, FALSE ); - if( pSWindow && pSWindow->IsVisible() && - ! (pSWindow->GetStyle() & WB_NOLABEL) && - ( pSWindow->GetType() == WINDOW_FIXEDTEXT || - pSWindow->GetType() == WINDOW_FIXEDLINE || - pSWindow->GetType() == WINDOW_GROUPBOX ) ) + if( pSWindow && pSWindow->IsVisible() && !(pSWindow->GetStyle() & WB_NOLABEL) ) { - pWindow = pSWindow; - break; + WindowType nType = pSWindow->GetType(); + if ( ( nType == WINDOW_FIXEDTEXT || + nType == WINDOW_FIXEDLINE || + nType == WINDOW_GROUPBOX ) ) + { + // a fixed text can't be labeld by a fixed text. + if ( ( nMyType != WINDOW_FIXEDTEXT ) || ( nType != WINDOW_FIXEDTEXT ) ) + pWindow = pSWindow; + break; + } } if( nFoundIndex > nSearchIndex || nSearchIndex == 0 ) break; diff --git a/vcl/source/window/introwin.cxx b/vcl/source/window/introwin.cxx index 02ccc2282a42..03f88adc3566 100644 --- a/vcl/source/window/introwin.cxx +++ b/vcl/source/window/introwin.cxx @@ -77,3 +77,12 @@ void IntroWindow::SetBackgroundBitmap( const Bitmap& rBitmap ) ImplGetFrame()->SetBackgroundBitmap( pBmp ); } } + +void IntroWindow::SetBackgroundBitmap( const BitmapEx& rBitmapEx ) +{ + if( ! rBitmapEx.IsEmpty() ) + { + SalBitmap* pBmp = rBitmapEx.ImplGetBitmapImpBitmap()->ImplGetSalBitmap(); + ImplGetFrame()->SetBackgroundBitmap( pBmp ); + } +} diff --git a/vcl/source/window/mnemonic.cxx b/vcl/source/window/mnemonic.cxx index 74926ad3de4b..c2c6c18135f2 100644 --- a/vcl/source/window/mnemonic.cxx +++ b/vcl/source/window/mnemonic.cxx @@ -332,39 +332,41 @@ BOOL MnemonicGenerator::CreateMnemonic( XubString& rKey ) } } - if( ! bChanged ) - { - /* - * #97809# if all else fails use the first character of a word - * anyway and live with duplicate mnemonics - */ - nIndex = 0; - do - { - c = aKey.GetChar( nIndex ); - - nMnemonicIndex = ImplGetMnemonicIndex( c ); - if ( nMnemonicIndex != MNEMONIC_INDEX_NOTFOUND ) - { - maMnemonics[nMnemonicIndex] = 0; - rKey.Insert( MNEMONIC_CHAR, nIndex ); - bChanged = TRUE; - break; - } - - // Search for next word - do - { - nIndex++; - c = aKey.GetChar( nIndex ); - if ( c == ' ' ) - break; - } - while ( nIndex < nLen ); - nIndex++; - } - while ( nIndex < nLen ); - } +// #i87415# Duplicates mnemonics are bad for consistent keyboard accessibility +// It's probably better to not have mnemonics for some widgets, than to have ambiguous ones. +// if( ! bChanged ) +// { +// /* +// * #97809# if all else fails use the first character of a word +// * anyway and live with duplicate mnemonics +// */ +// nIndex = 0; +// do +// { +// c = aKey.GetChar( nIndex ); +// +// nMnemonicIndex = ImplGetMnemonicIndex( c ); +// if ( nMnemonicIndex != MNEMONIC_INDEX_NOTFOUND ) +// { +// maMnemonics[nMnemonicIndex] = 0; +// rKey.Insert( MNEMONIC_CHAR, nIndex ); +// bChanged = TRUE; +// break; +// } +// +// // Search for next word +// do +// { +// nIndex++; +// c = aKey.GetChar( nIndex ); +// if ( c == ' ' ) +// break; +// } +// while ( nIndex < nLen ); +// nIndex++; +// } +// while ( nIndex < nLen ); +// } return bChanged; } diff --git a/vcl/source/window/printdlg.cxx b/vcl/source/window/printdlg.cxx index caf5705cbcd9..33e58b51d6d0 100644 --- a/vcl/source/window/printdlg.cxx +++ b/vcl/source/window/printdlg.cxx @@ -42,16 +42,22 @@ #include "vcl/help.hxx" #include "vcl/decoview.hxx" #include "vcl/svapp.hxx" +#include "vcl/unohelp.hxx" #include "unotools/localedatawrapper.hxx" #include "rtl/ustrbuf.hxx" +#include "com/sun/star/lang/XMultiServiceFactory.hpp" +#include "com/sun/star/container/XNameAccess.hpp" +#include "com/sun/star/beans/PropertyValue.hpp" #include "com/sun/star/awt/Size.hpp" using namespace vcl; using namespace com::sun::star; using namespace com::sun::star::uno; +using namespace com::sun::star::lang; +using namespace com::sun::star::container; using namespace com::sun::star::beans; #define HELPID_PREFIX ".HelpId:vcl:PrintDialog" @@ -66,7 +72,7 @@ PrintDialog::PrintPreviewWindow::PrintPreviewWindow( Window* i_pParent, const Re { SetPaintTransparent( TRUE ); SetBackground(); - if( GetSettings().GetStyleSettings().GetHighContrastMode() ) + if( useHCColorReplacement() ) maPageVDev.SetBackground( GetSettings().GetStyleSettings().GetWindowColor() ); else maPageVDev.SetBackground( Color( COL_WHITE ) ); @@ -76,12 +82,76 @@ PrintDialog::PrintPreviewWindow::~PrintPreviewWindow() { } +bool PrintDialog::PrintPreviewWindow::useHCColorReplacement() const +{ + bool bRet = false; + if( GetSettings().GetStyleSettings().GetHighContrastMode() ) + { + try + { + // get service provider + Reference< XMultiServiceFactory > xSMgr( unohelper::GetMultiServiceFactory() ); + // create configuration hierachical access name + if( xSMgr.is() ) + { + try + { + Reference< XMultiServiceFactory > xConfigProvider( + Reference< XMultiServiceFactory >( + xSMgr->createInstance( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.configuration.ConfigurationProvider" ))), + UNO_QUERY ) + ); + if( xConfigProvider.is() ) + { + Sequence< Any > aArgs(1); + PropertyValue aVal; + aVal.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "nodepath" ) ); + aVal.Value <<= rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/org.openoffice.Office.Common/Accessibility" ) ); + aArgs.getArray()[0] <<= aVal; + Reference< XNameAccess > xConfigAccess( + Reference< XNameAccess >( + xConfigProvider->createInstanceWithArguments( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.configuration.ConfigurationAccess" )), + aArgs ), + UNO_QUERY ) + ); + if( xConfigAccess.is() ) + { + try + { + sal_Bool bValue = sal_False; + Any aAny = xConfigAccess->getByName( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsForPagePreviews" ) ) ); + if( aAny >>= bValue ) + bRet = bool(bValue); + } + catch( NoSuchElementException& ) + { + } + catch( WrappedTargetException& ) + { + } + } + } + } + catch( Exception& ) + { + } + } + } + catch( WrappedTargetException& ) + { + } + } + return bRet; +} + void PrintDialog::PrintPreviewWindow::DataChanged( const DataChangedEvent& i_rDCEvt ) { // react on settings changed if( i_rDCEvt.GetType() == DATACHANGED_SETTINGS ) { - if( GetSettings().GetStyleSettings().GetHighContrastMode() ) + if( useHCColorReplacement() ) maPageVDev.SetBackground( GetSettings().GetStyleSettings().GetWindowColor() ); else maPageVDev.SetBackground( Color( COL_WHITE ) ); @@ -118,6 +188,23 @@ void PrintDialog::PrintPreviewWindow::Resize() } aScaledSize.Width() = long(aScaledSize.Width()*fScale); aScaledSize.Height() = long(aScaledSize.Height()*fScale); + + maPreviewSize = aScaledSize; + + // #i104784# if we render the page too small then rounding issues result in + // layout artifacts looking really bad. So scale the page unto a device that is not + // full page size but not too small either. This also results in much better visual + // quality of the preview, e.g. when its height approaches the number of text lines + // find a good scaling factor + Size aPreviewMMSize( maPageVDev.PixelToLogic( aScaledSize, MapMode( MAP_100TH_MM ) ) ); + double fZoom = double(maOrigSize.Height())/double(aPreviewMMSize.Height()); + while( fZoom > 10 ) + { + aScaledSize.Width() *= 2; + aScaledSize.Height() *= 2; + fZoom /= 2.0; + } + maPageVDev.SetOutputSizePixel( aScaledSize, FALSE ); } @@ -129,9 +216,14 @@ void PrintDialog::PrintPreviewWindow::Paint( const Rectangle& ) // replacement is active Push(); Rectangle aTextRect( Point( 0, 0 ), aSize ); - Font aFont( GetSettings().GetStyleSettings().GetFieldFont() ); - aFont.SetSize( Size( 0, aSize.Height()/12 ) ); - SetFont( aFont ); + DecorationView aVw( this ); + aVw.DrawFrame( aTextRect, FRAME_DRAW_GROUP ); + aTextRect.Left() += 2; + aTextRect.Top() += 2; + aTextRect.Right() -= 2; + aTextRect.Bottom() -= 2; + Font aFont( GetSettings().GetStyleSettings().GetLabelFont() ); + SetZoomedPointFont( aFont ); DrawText( aTextRect, maReplacementString, TEXT_DRAW_CENTER | TEXT_DRAW_VCENTER | TEXT_DRAW_WORDBREAK | TEXT_DRAW_MULTILINE ); @@ -141,11 +233,11 @@ void PrintDialog::PrintPreviewWindow::Paint( const Rectangle& ) { GDIMetaFile aMtf( maMtf ); - Size aPreviewSize = maPageVDev.GetOutputSizePixel(); - Point aOffset( (aSize.Width() - aPreviewSize.Width()) / 2, - (aSize.Height() - aPreviewSize.Height()) / 2 ); + Point aOffset( (aSize.Width() - maPreviewSize.Width()) / 2, + (aSize.Height() - maPreviewSize.Height()) / 2 ); - const Size aLogicSize( maPageVDev.PixelToLogic( aPreviewSize, MapMode( MAP_100TH_MM ) ) ); + Size aVDevSize( maPageVDev.GetOutputSizePixel() ); + const Size aLogicSize( maPageVDev.PixelToLogic( aVDevSize, MapMode( MAP_100TH_MM ) ) ); Size aOrigSize( maOrigSize ); if( aOrigSize.Width() < 1 ) aOrigSize.Width() = aLogicSize.Width(); @@ -165,11 +257,11 @@ void PrintDialog::PrintPreviewWindow::Paint( const Rectangle& ) SetMapMode( MAP_PIXEL ); maPageVDev.SetMapMode( MAP_PIXEL ); - DrawOutDev( aOffset, aPreviewSize, Point( 0, 0 ), aPreviewSize, maPageVDev ); + DrawOutDev( aOffset, maPreviewSize, Point( 0, 0 ), aVDevSize, maPageVDev ); DecorationView aVw( this ); - aOffset.X() -= 1; aOffset.Y() -=1; aPreviewSize.Width() += 2; aPreviewSize.Height() += 2; - aVw.DrawFrame( Rectangle( aOffset, aPreviewSize ), FRAME_DRAW_GROUP ); + Rectangle aFrame( aOffset + Point( -1, -1 ), Size( maPreviewSize.Width() + 2, maPreviewSize.Height() + 2 ) ); + aVw.DrawFrame( aFrame, FRAME_DRAW_GROUP ); } } @@ -211,9 +303,7 @@ void PrintDialog::PrintPreviewWindow::setPreview( const GDIMetaFile& i_rNewPrevi #endif SetQuickHelpText( aBuf.makeStringAndClear() ); maMtf = i_rNewPreview; - if( GetSettings().GetStyleSettings().GetHighContrastMode() && - GetSettings().GetStyleSettings().GetWindowColor().IsDark() - ) + if( useHCColorReplacement() ) { maMtf.ReplaceColors( Color( COL_BLACK ), Color( COL_WHITE ), 30 ); } @@ -834,6 +924,7 @@ PrintDialog::PrintDialog( Window* i_pParent, const boost::shared_ptr<PrinterCont maNUpPage.maBorderCB.SetClickHdl( LINK( this, PrintDialog, ClickHdl ) ); maOptionsPage.maToFileBox.SetToggleHdl( LINK( this, PrintDialog, ClickHdl ) ); maOptionsPage.maReverseOrderBox.SetToggleHdl( LINK( this, PrintDialog, ClickHdl ) ); + maOptionsPage.maCollateSingleJobsBox.SetToggleHdl( LINK( this, PrintDialog, ClickHdl ) ); maNUpPage.maPagesBtn.SetToggleHdl( LINK( this, PrintDialog, ClickHdl ) ); // setup modify hdl @@ -1027,6 +1118,11 @@ bool PrintDialog::isCollate() return maJobPage.maCopyCountField.GetValue() > 1 ? maJobPage.maCollateBox.IsChecked() : FALSE; } +bool PrintDialog::isSingleJobs() +{ + return maOptionsPage.maCollateSingleJobsBox.IsChecked(); +} + static void setSmartId( Window* i_pWindow, const char* i_pType, sal_Int32 i_nId = -1, const rtl::OUString& i_rPropName = rtl::OUString() ) { rtl::OUStringBuffer aBuf( 256 ); @@ -1049,10 +1145,17 @@ static void setSmartId( Window* i_pWindow, const char* i_pType, sal_Int32 i_nId i_pWindow->SetSmartHelpId( SmartId( aBuf.makeStringAndClear(), HID_PRINTDLG ) ); } -static void setHelpText( Window* i_pWindow, const Sequence< rtl::OUString >& i_rHelpTexts, sal_Int32 i_nIndex ) +static void setHelpText( Window* /*i_pWindow*/, const Sequence< rtl::OUString >& /*i_rHelpTexts*/, sal_Int32 /*i_nIndex*/ ) { + // without a help text set and the correct smartID, + // help texts will be retrieved from the online help system + + // passed help texts for optional UI is used only for native dialogs which currently + // cannot access the same (rather implicit) mechanism + #if 0 if( i_nIndex >= 0 && i_nIndex < i_rHelpTexts.getLength() ) i_pWindow->SetHelpText( i_rHelpTexts.getConstArray()[i_nIndex] ); + #endif } void updateMaxSize( const Size& i_rCheckSize, Size& o_rMaxSize ) @@ -1572,6 +1675,12 @@ void PrintDialog::setupOptionalUI() maJobPage.maLayout.setBorders( nIndex-1, 0, 0, 0, aBorder.Width() ); #endif + // create auto mnemomnics now so they can be calculated in layout + ImplWindowAutoMnemonic( &maJobPage ); + ImplWindowAutoMnemonic( &maNUpPage ); + ImplWindowAutoMnemonic( &maOptionsPage ); + ImplWindowAutoMnemonic( this ); + // calculate job page Size aMaxSize = maJobPage.maLayout.getOptimalSize( WINDOWSIZE_PREFERRED ); // and layout page @@ -1654,6 +1763,7 @@ void PrintDialog::checkControlDependencies() maJobPage.maCollateImage.SetSizePixel( aImgSize ); maJobPage.maCollateImage.SetImage( bHC ? aHCImg : aImg ); maJobPage.maCollateImage.SetModeImage( aHCImg, BMP_COLOR_HIGHCONTRAST ); + maJobPage.maLayout.resize(); // enable setup button only for printers that can be setup bool bHaveSetup = maPController->getPrinter()->HasSupport( SUPPORT_SETUPDIALOG ); @@ -2444,6 +2554,11 @@ void PrintProgressDialog::tick() setProgress( ++mnCur ); } +void PrintProgressDialog::reset() +{ + setProgress( 0 ); +} + void PrintProgressDialog::Paint( const Rectangle& ) { if( maProgressRect.IsEmpty() ) diff --git a/vcl/source/window/status.cxx b/vcl/source/window/status.cxx index 9987dae32dbb..c139ae1ffb30 100644 --- a/vcl/source/window/status.cxx +++ b/vcl/source/window/status.cxx @@ -61,13 +61,17 @@ public: ~ImplData(); VirtualDevice* mpVirDev; - BOOL mbTopBorder:1; + long mnItemBorderWidth; + bool mbTopBorder:1; + bool mbDrawItemFrames:1; }; StatusBar::ImplData::ImplData() { mpVirDev = NULL; - mbTopBorder = FALSE; + mbTopBorder = false; + mbDrawItemFrames = false; + mnItemBorderWidth = 0; } StatusBar::ImplData::~ImplData() @@ -351,9 +355,7 @@ Rectangle StatusBar::ImplGetItemRectPos( USHORT nPos ) const { Rectangle aRect; ImplStatusItem* pItem; - pItem = mpItemList->GetObject( nPos ); - if ( pItem ) { if ( pItem->mbVisible ) @@ -372,6 +374,25 @@ Rectangle StatusBar::ImplGetItemRectPos( USHORT nPos ) const // ----------------------------------------------------------------------- +USHORT StatusBar::ImplGetFirstVisiblePos() const +{ + ImplStatusItem* pItem; + + for( USHORT nPos = 0; nPos < mpItemList->Count(); nPos++ ) + { + pItem = mpItemList->GetObject( nPos ); + if ( pItem ) + { + if ( pItem->mbVisible ) + return nPos; + } + } + + return ~0; +} + +// ----------------------------------------------------------------------- + void StatusBar::ImplDrawText( BOOL bOffScreen, long nOldTextWidth ) { // Das ueberschreiben der Item-Box verhindern @@ -418,8 +439,9 @@ void StatusBar::ImplDrawItem( BOOL bOffScreen, USHORT nPos, BOOL bDrawText, BOOL // Ausgabebereich berechnen ImplStatusItem* pItem = mpItemList->GetObject( nPos ); - Rectangle aTextRect( aRect.Left()+1, aRect.Top()+1, - aRect.Right()-1, aRect.Bottom()-1 ); + long nW = mpImplData->mnItemBorderWidth + 1; + Rectangle aTextRect( aRect.Left()+nW, aRect.Top()+nW, + aRect.Right()-nW, aRect.Bottom()-nW ); Size aTextRectSize( aTextRect.GetSize() ); if ( bOffScreen ) @@ -470,17 +492,36 @@ void StatusBar::ImplDrawItem( BOOL bOffScreen, USHORT nPos, BOOL bDrawText, BOOL SetClipRegion(); // Frame ausgeben - if ( bDrawFrame && !(pItem->mnBits & SIB_FLAT) ) + if ( bDrawFrame ) { - USHORT nStyle; + if( mpImplData->mbDrawItemFrames ) + { + if( !(pItem->mnBits & SIB_FLAT) ) + { + USHORT nStyle; - if ( pItem->mnBits & SIB_IN ) - nStyle = FRAME_DRAW_IN; - else - nStyle = FRAME_DRAW_OUT; + if ( pItem->mnBits & SIB_IN ) + nStyle = FRAME_DRAW_IN; + else + nStyle = FRAME_DRAW_OUT; + + DecorationView aDecoView( this ); + aDecoView.DrawFrame( aRect, nStyle ); + } + } + else if( nPos != ImplGetFirstVisiblePos() ) + { + // draw separator + Point aFrom( aRect.TopLeft() ); + aFrom.X()--; + aFrom.Y()++; + Point aTo( aRect.BottomLeft() ); + aTo.X()--; + aTo.Y()--; - DecorationView aDecoView( this ); - aDecoView.DrawFrame( aRect, nStyle ); + DecorationView aDecoView( this ); + aDecoView.DrawSeparator( aFrom, aTo ); + } } if ( !ImplIsRecordLayout() ) @@ -688,8 +729,6 @@ void StatusBar::ImplCalcProgressRect() } if( ! bNativeOK ) maPrgsTxtPos.Y() = mnTextY; - - } // ----------------------------------------------------------------------- @@ -1227,8 +1266,11 @@ Rectangle StatusBar::GetItemRect( USHORT nItemId ) const { // Rechteck holen und Rahmen abziehen aRect = ImplGetItemRectPos( nPos ); - aRect.Left()++; - aRect.Right()--; + long nW = mpImplData->mnItemBorderWidth+1; + aRect.Top() += nW-1; + aRect.Bottom() -= nW-1; + aRect.Left() += nW; + aRect.Right() -= nW; return aRect; } } @@ -1248,8 +1290,9 @@ Point StatusBar::GetItemTextPos( USHORT nItemId ) const // Rechteck holen ImplStatusItem* pItem = mpItemList->GetObject( nPos ); Rectangle aRect = ImplGetItemRectPos( nPos ); - Rectangle aTextRect( aRect.Left()+1, aRect.Top()+1, - aRect.Right()-1, aRect.Bottom()-1 ); + long nW = mpImplData->mnItemBorderWidth + 1; + Rectangle aTextRect( aRect.Left()+nW, aRect.Top()+nW, + aRect.Right()-nW, aRect.Bottom()-nW ); Point aPos = ImplGetItemTextPos( aTextRect.GetSize(), Size( GetTextWidth( pItem->maText ), GetTextHeight() ), pItem->mnBits ); @@ -1524,9 +1567,9 @@ void StatusBar::SetBottomBorder( BOOL bBottomBorder ) void StatusBar::SetTopBorder( BOOL bTopBorder ) { - if ( mpImplData->mbTopBorder != bTopBorder ) + if ( mpImplData->mbTopBorder != static_cast<bool>(bTopBorder) ) { - mpImplData->mbTopBorder = bTopBorder; + mpImplData->mbTopBorder = static_cast<bool>(bTopBorder); ImplCalcBorder(); } } @@ -1690,7 +1733,22 @@ Size StatusBar::CalcWindowSizePixel() const } } - nCalcHeight = nMinHeight+nBarTextOffset; + if( mpImplData->mbDrawItemFrames && + pThis->IsNativeControlSupported( CTRL_FRAME, PART_BORDER ) ) + { + ImplControlValue aControlValue( FRAME_DRAW_NODRAW ); + Region aBound, aContent; + Region aNatRgn( Rectangle( Point( 0, 0 ), Size( 150, 50 ) ) ); + if( pThis->GetNativeControlRegion(CTRL_FRAME, PART_BORDER, + aNatRgn, 0, aControlValue, rtl::OUString(), aBound, aContent) ) + { + mpImplData->mnItemBorderWidth = + ( aBound.GetBoundRect().GetHeight() - + aContent.GetBoundRect().GetHeight() ) / 2; + } + } + + nCalcHeight = nMinHeight+nBarTextOffset + 2*mpImplData->mnItemBorderWidth; if( nCalcHeight < nProgressHeight+2 ) nCalcHeight = nProgressHeight+2; diff --git a/vcl/source/window/tabdlg.cxx b/vcl/source/window/tabdlg.cxx index 02a8b6a5b717..874881c0c5ef 100644 --- a/vcl/source/window/tabdlg.cxx +++ b/vcl/source/window/tabdlg.cxx @@ -274,20 +274,3 @@ void TabDialog::AdjustLayout() ImplPosControls(); } -// ----------------------------------------------------------------------- - -TabControl* TabDialog::ImplGetFirstTabControl() const -{ - Window* pChild = GetWindow( WINDOW_FIRSTCHILD ); - while ( pChild ) - { - if ( pChild->IsVisible() && (pChild != mpViewWindow) ) - { - if ( pChild->GetType() == WINDOW_TABCONTROL ) - return (TabControl*)pChild; - } - pChild = pChild->GetWindow( WINDOW_NEXT ); - } - return NULL; -} - diff --git a/vcl/source/window/window.cxx b/vcl/source/window/window.cxx index 516bc53d8920..b47aa50a2e72 100644 --- a/vcl/source/window/window.cxx +++ b/vcl/source/window/window.cxx @@ -502,6 +502,13 @@ void Window::ImplUpdateGlobalSettings( AllSettings& rSettings, BOOL bCallHdl ) } } + static const char* pEnvHC = getenv( "SAL_FORCE_HC" ); + if( pEnvHC && *pEnvHC ) + { + aStyleSettings.SetHighContrastMode( TRUE ); + rSettings.SetStyleSettings( aStyleSettings ); + } + #ifdef DBG_UTIL // Evt. AppFont auf Fett schalten, damit man feststellen kann, // ob fuer die Texte auf anderen Systemen genuegend Platz @@ -8147,7 +8154,7 @@ const XubString& Window::GetHelpText() const { rtl::OUStringBuffer aTxt( 64+mpWindowImpl->maHelpText.Len() ); aTxt.append( mpWindowImpl->maHelpText ); - aTxt.appendAscii( "\n+++++++++++++++\n" ); + aTxt.appendAscii( "\n------------------\n" ); if( bStrHelpId ) aTxt.append( rtl::OUString( aStrHelpId ) ); else diff --git a/vcl/source/window/window3.cxx b/vcl/source/window/window3.cxx index 9c10c5f131bf..aecbc9c3ef0c 100644 --- a/vcl/source/window/window3.cxx +++ b/vcl/source/window/window3.cxx @@ -104,6 +104,12 @@ void Window::ImplMoveControlValue( ControlType nType, const ImplControlValue& aV { switch( nType ) { + case CTRL_SLIDER: + { + SliderValue* pSlVal = reinterpret_cast<SliderValue*>(aValue.getOptionalVal()); + pSlVal->maThumbRect.Move( rDelta.X(), rDelta.Y() ); + } + break; case CTRL_SCROLLBAR: { ScrollbarValue* pScVal = reinterpret_cast<ScrollbarValue*>(aValue.getOptionalVal()); diff --git a/vcl/source/window/winproc.cxx b/vcl/source/window/winproc.cxx index 93e1b0837429..95ac5940b6d2 100644 --- a/vcl/source/window/winproc.cxx +++ b/vcl/source/window/winproc.cxx @@ -295,7 +295,7 @@ static BOOL ImplCallCommand( Window* pChild, USHORT nEvt, void* pData = NULL, else { // simulate mouseposition at center of window - Size aSize = pChild->GetOutputSize(); + Size aSize( pChild->GetOutputSizePixel() ); aPos = Point( aSize.getWidth()/2, aSize.getHeight()/2 ); } } |