1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <vcl/event.hxx>
21 #include <vcl/metaact.hxx>
22 #include <vcl/field.hxx>
23 #include <vcl/settings.hxx>
24 #include <vcl/toolbox.hxx>
25 #include <svtools/valueset.hxx>
26 #include <svl/eitem.hxx>
27 #include <sfx2/dispatch.hxx>
28 #include <svtools/colrdlg.hxx>
29 
30 #include <svx/colorbox.hxx>
31 #include <svx/dialmgr.hxx>
32 #include <svx/dlgctrl.hxx>
33 #include <svx/bmpmask.hxx>
34 #include <svx/strings.hrc>
35 #include <svx/svxids.hrc>
36 #include <memory>
37 #include <helpids.h>
38 
39 #define OWN_CALLMODE    SfxCallMode::ASYNCHRON | SfxCallMode::RECORD
40 
41 
42 #define TEST_COLS()                                                 \
43 {                                                                   \
44     nR = aCol.GetRed(); nG = aCol.GetGreen(); nB = aCol.GetBlue();  \
45     for( i = 0; i < nCount; i++ )                                   \
46     {                                                               \
47         if ( ( pMinR[i] <= nR ) && ( pMaxR[i] >= nR ) &&            \
48              ( pMinG[i] <= nG ) && ( pMaxG[i] >= nG ) &&            \
49              ( pMinB[i] <= nB ) && ( pMaxB[i] >= nB ) )             \
50         {                                                           \
51             aCol = pDstCols[i]; bReplace = true; break;             \
52         }                                                           \
53     }                                                               \
54 }
55 
56 SFX_IMPL_DOCKINGWINDOW_WITHID( SvxBmpMaskChildWindow, SID_BMPMASK )
57 
58 class BmpColorWindow : public Control
59 {
60     Color       aColor;
61 
62 
63 public:
BmpColorWindow(vcl::Window * pParent)64     explicit BmpColorWindow(vcl::Window* pParent)
65         : Control(pParent, WB_BORDER)
66         , aColor( COL_WHITE )
67     {
68     }
69 
SetColor(const Color & rColor)70     void SetColor( const Color& rColor )
71     {
72         aColor = rColor;
73         Invalidate();
74     }
75 
76     virtual void Paint( vcl::RenderContext& /*rRenderContext*/, const tools::Rectangle& rRect ) override;
77 
GetOptimalSize() const78     virtual Size GetOptimalSize() const override
79     {
80         return LogicToPixel(Size(43, 14), MapMode(MapUnit::MapAppFont));
81     }
82 };
83 
84 class MaskSet : public ValueSet
85 {
86     VclPtr<SvxBmpMask> pSvxBmpMask;
87 
88 public:
89     MaskSet(SvxBmpMask* pMask, vcl::Window* pParent);
~MaskSet()90     virtual ~MaskSet() override { disposeOnce(); }
dispose()91     virtual void dispose() override { pSvxBmpMask.clear(); ValueSet::dispose(); }
92     virtual void Select() override;
93     virtual void KeyInput( const KeyEvent& rKEvt ) override;
94     virtual void GetFocus() override;
GetOptimalSize() const95     virtual Size GetOptimalSize() const override
96     {
97         return LogicToPixel(Size(24, 12), MapMode(MapUnit::MapAppFont));
98     }
99 
100     void onEditColor();
101 };
102 
MaskSet(SvxBmpMask * pMask,vcl::Window * pParent)103 MaskSet::MaskSet(SvxBmpMask* pMask, vcl::Window* pParent)
104     : ValueSet(pParent, WB_TABSTOP)
105     , pSvxBmpMask(pMask)
106 {
107     SetHelpId(HID_BMPMASK_CTL_QCOL_1);
108 }
109 
Select()110 void MaskSet::Select()
111 {
112     ValueSet::Select();
113 
114     pSvxBmpMask->onSelect( this );
115 }
116 
GetFocus()117 void MaskSet::GetFocus()
118 {
119     ValueSet::GetFocus();
120     SelectItem( 1 );
121     pSvxBmpMask->onSelect( this );
122 }
123 
KeyInput(const KeyEvent & rKEvt)124 void MaskSet::KeyInput( const KeyEvent& rKEvt )
125 {
126     vcl::KeyCode aCode = rKEvt.GetKeyCode();
127 
128     // if the key has a modifier we don't care
129     if( aCode.GetModifier() )
130     {
131         ValueSet::KeyInput( rKEvt );
132     }
133     else
134     {
135         // check for keys that interests us
136         switch ( aCode.GetCode() )
137         {
138             case KEY_SPACE:
139                 onEditColor();
140                 break;
141             default:
142                 ValueSet::KeyInput( rKEvt );
143         }
144 
145     }
146 }
147 
onEditColor()148 void MaskSet::onEditColor()
149 {
150     SvColorDialog aColorDlg;
151 
152     aColorDlg.SetColor(GetItemColor(1));
153 
154     if (aColorDlg.Execute(GetFrameWeld()))
155         SetItemColor(1, aColorDlg.GetColor());
156 }
157 
158 class MaskData
159 {
160     VclPtr<SvxBmpMask>     pMask;
161     bool            bIsReady;
162     bool            bExecState;
163     SfxBindings&    rBindings;
164 
165 public:
166                 MaskData( SvxBmpMask* pBmpMask, SfxBindings& rBind );
167 
IsCbxReady() const168     bool        IsCbxReady() const { return bIsReady; }
SetExecState(bool bState)169     void        SetExecState( bool bState ) { bExecState = bState; }
IsExecReady() const170     bool        IsExecReady() const { return bExecState; }
171 
172                 DECL_LINK( PipetteHdl, ToolBox*, void );
173                 DECL_LINK( CbxHdl, Button*, void);
174                 DECL_LINK( CbxTransHdl, Button*, void );
175                 DECL_LINK( FocusLbHdl, Control&, void );
176                 DECL_LINK(ExecHdl, Button*, void);
177 };
178 
179 
MaskData(SvxBmpMask * pBmpMask,SfxBindings & rBind)180 MaskData::MaskData( SvxBmpMask* pBmpMask, SfxBindings& rBind ) :
181 
182     pMask       ( pBmpMask ),
183     bIsReady    ( false ),
184     bExecState  ( false ),
185     rBindings   ( rBind )
186 
187 {
188 }
189 
IMPL_LINK(MaskData,PipetteHdl,ToolBox *,pTbx,void)190 IMPL_LINK( MaskData, PipetteHdl, ToolBox*, pTbx, void )
191 {
192     SfxBoolItem aBItem( SID_BMPMASK_PIPETTE,
193                         pTbx->IsItemChecked( pTbx->GetItemId(0) ) );
194 
195     rBindings.GetDispatcher()->ExecuteList(SID_BMPMASK_PIPETTE, OWN_CALLMODE,
196             { &aBItem });
197 }
198 
IMPL_LINK(MaskData,CbxHdl,Button *,pButton,void)199 IMPL_LINK( MaskData, CbxHdl, Button*, pButton, void )
200 {
201     CheckBox* pCbx = static_cast<CheckBox*>(pButton);
202     bIsReady =  pMask->m_pCbx1->IsChecked() || pMask->m_pCbx2->IsChecked() ||
203                 pMask->m_pCbx3->IsChecked() || pMask->m_pCbx4->IsChecked();
204 
205     if ( bIsReady && IsExecReady() )
206         pMask->m_pBtnExec->Enable();
207     else
208         pMask->m_pBtnExec->Disable();
209 
210     // When a checkbox is checked, the pipette is enabled
211     if ( pCbx->IsChecked() )
212     {
213         MaskSet* pSet = nullptr;
214 
215         if (pCbx == pMask->m_pCbx1)
216             pSet = pMask->m_pQSet1;
217         else if (pCbx == pMask->m_pCbx2)
218             pSet = pMask->m_pQSet2;
219         else if (pCbx == pMask->m_pCbx3)
220             pSet = pMask->m_pQSet3;
221         else // if ( pCbx == pMask->m_pCbx4 )
222             pSet = pMask->m_pQSet4;
223 
224         pSet->SelectItem( 1 );
225         pSet->Select();
226 
227         pMask->m_pTbxPipette->CheckItem( pMask->m_pTbxPipette->GetItemId(0) );
228         PipetteHdl(pMask->m_pTbxPipette);
229     }
230 }
231 
232 
IMPL_LINK(MaskData,CbxTransHdl,Button *,pButton,void)233 IMPL_LINK( MaskData, CbxTransHdl, Button*, pButton, void )
234 {
235     CheckBox* pCbx = static_cast<CheckBox*>(pButton);
236     bIsReady = pCbx->IsChecked();
237     if ( bIsReady )
238     {
239         pMask->m_pQSet1->Disable();
240         pMask->m_pQSet2->Disable();
241         pMask->m_pQSet3->Disable();
242         pMask->m_pQSet4->Disable();
243         pMask->m_pCtlPipette->Disable();
244         pMask->m_pCbx1->Disable();
245         pMask->m_pSp1->Disable();
246         pMask->m_pCbx2->Disable();
247         pMask->m_pSp2->Disable();
248         pMask->m_pCbx3->Disable();
249         pMask->m_pSp3->Disable();
250         pMask->m_pCbx4->Disable();
251         pMask->m_pSp4->Disable();
252         pMask->m_pTbxPipette->Disable();
253 
254         pMask->m_pLbColor1->Disable();
255         pMask->m_pLbColor2->Disable();
256         pMask->m_pLbColor3->Disable();
257         pMask->m_pLbColor4->Disable();
258         pMask->m_pLbColorTrans->Enable();
259     }
260     else
261     {
262         pMask->m_pQSet1->Enable();
263         pMask->m_pQSet2->Enable();
264         pMask->m_pQSet3->Enable();
265         pMask->m_pQSet4->Enable();
266         pMask->m_pCtlPipette->Enable();
267         pMask->m_pCbx1->Enable();
268         pMask->m_pSp1->Enable();
269         pMask->m_pCbx2->Enable();
270         pMask->m_pSp2->Enable();
271         pMask->m_pCbx3->Enable();
272         pMask->m_pSp3->Enable();
273         pMask->m_pCbx4->Enable();
274         pMask->m_pSp4->Enable();
275         pMask->m_pTbxPipette->Enable();
276 
277         pMask->m_pLbColor1->Enable();
278         pMask->m_pLbColor2->Enable();
279         pMask->m_pLbColor3->Enable();
280         pMask->m_pLbColor4->Enable();
281         pMask->m_pLbColorTrans->Disable();
282 
283         bIsReady = pMask->m_pCbx1->IsChecked() || pMask->m_pCbx2->IsChecked() ||
284                    pMask->m_pCbx3->IsChecked() || pMask->m_pCbx4->IsChecked();
285     }
286 
287     if ( bIsReady && IsExecReady() )
288         pMask->m_pBtnExec->Enable();
289     else
290         pMask->m_pBtnExec->Disable();
291 }
292 
293 
IMPL_LINK(MaskData,FocusLbHdl,Control &,rControl,void)294 IMPL_LINK( MaskData, FocusLbHdl, Control&, rControl, void )
295 {
296     SvxColorListBox* pLb = static_cast<SvxColorListBox*>(&rControl);
297     // MT: bFireFox as API parameter is ugly, find better solution????
298     pMask->m_pQSet1->SelectItem( pLb == pMask->m_pLbColor1 ? 1 : 0 /* , false */ );
299     pMask->m_pQSet2->SelectItem( pLb == pMask->m_pLbColor2 ? 1 : 0 /* , false */ );
300     pMask->m_pQSet3->SelectItem( pLb == pMask->m_pLbColor3 ? 1 : 0 /* , false */ );
301     pMask->m_pQSet4->SelectItem( pLb == pMask->m_pLbColor4 ? 1 : 0 /* , false */ );
302 }
303 
304 
IMPL_LINK_NOARG(MaskData,ExecHdl,Button *,void)305 IMPL_LINK_NOARG(MaskData, ExecHdl, Button*, void)
306 {
307     SfxBoolItem aBItem( SID_BMPMASK_EXEC, true );
308     rBindings.GetDispatcher()->ExecuteList(SID_BMPMASK_EXEC, OWN_CALLMODE,
309             { &aBItem });
310 }
311 
Paint(vcl::RenderContext & rRenderContext,const tools::Rectangle &)312 void BmpColorWindow::Paint( vcl::RenderContext& rRenderContext, const tools::Rectangle& /*Rect*/)
313 {
314     rRenderContext.Push(PushFlags::LINECOLOR | PushFlags::FILLCOLOR);
315     rRenderContext.SetLineColor(aColor);
316     rRenderContext.SetFillColor(aColor);
317     rRenderContext.DrawRect(tools::Rectangle(Point(), GetSizePixel()));
318     rRenderContext.Pop();
319 }
320 
SvxBmpMaskSelectItem(SvxBmpMask & rMask,SfxBindings & rBindings)321 SvxBmpMaskSelectItem::SvxBmpMaskSelectItem( SvxBmpMask& rMask,
322                                             SfxBindings& rBindings ) :
323             SfxControllerItem   ( SID_BMPMASK_EXEC, rBindings ),
324             rBmpMask            ( rMask)
325 {
326 }
327 
StateChanged(sal_uInt16 nSID,SfxItemState,const SfxPoolItem * pItem)328 void SvxBmpMaskSelectItem::StateChanged( sal_uInt16 nSID, SfxItemState /*eState*/,
329                                          const SfxPoolItem* pItem )
330 {
331     if ( ( nSID == SID_BMPMASK_EXEC ) && pItem )
332     {
333         const SfxBoolItem* pStateItem = dynamic_cast<const SfxBoolItem*>( pItem  );
334         assert(pStateItem); // SfxBoolItem expected
335         if (pStateItem)
336             rBmpMask.SetExecState( pStateItem->GetValue() );
337     }
338 }
339 
SvxBmpMaskChildWindow(vcl::Window * pParent_,sal_uInt16 nId,SfxBindings * pBindings,SfxChildWinInfo * pInfo)340 SvxBmpMaskChildWindow::SvxBmpMaskChildWindow(vcl::Window* pParent_, sal_uInt16 nId,
341                                              SfxBindings* pBindings,
342                                              SfxChildWinInfo* pInfo)
343     : SfxChildWindow(pParent_, nId)
344 {
345     VclPtr<SvxBmpMask> pDlg = VclPtr<SvxBmpMask>::Create(pBindings, this, pParent_);
346 
347     SetWindow( pDlg );
348 
349     pDlg->Initialize( pInfo );
350 }
351 
SvxBmpMask(SfxBindings * pBindinx,SfxChildWindow * pCW,vcl::Window * pParent)352 SvxBmpMask::SvxBmpMask(SfxBindings *pBindinx, SfxChildWindow *pCW, vcl::Window* pParent)
353     : SfxDockingWindow(pBindinx, pCW, pParent, "DockingColorReplace",
354                        "svx/ui/dockingcolorreplace.ui" )
355     , pData(new MaskData(this, *pBindinx))
356     , aPipetteColor(COL_WHITE)
357     , aSelItem(*this, *pBindinx)
358 {
359     get(m_pTbxPipette, "toolbar");
360     m_pTbxPipette->SetItemBits(m_pTbxPipette->GetItemId(0),
361         ToolBoxItemBits::AUTOCHECK);
362     get(m_pBtnExec, "replace");
363     m_pCtlPipette = VclPtr<BmpColorWindow>::Create(get<Window>("toolgrid"));
364     m_pCtlPipette->Show();
365     m_pCtlPipette->set_grid_left_attach(1);
366     m_pCtlPipette->set_grid_top_attach(0);
367     m_pCtlPipette->set_hexpand(true);
368     get(m_pCbx1, "cbx1");
369     Window *pGrid = get<Window>("colorgrid");
370     m_pQSet1 = VclPtr<MaskSet>::Create(this, pGrid);
371     m_pQSet1->set_grid_left_attach(1);
372     m_pQSet1->set_grid_top_attach(1);
373     m_pQSet1->Show();
374     get(m_pSp1, "tol1");
375     get(m_pLbColor1, "color1");
376     m_pLbColor1->SetSlotId(SID_BMPMASK_COLOR);
377     get(m_pCbx2, "cbx2");
378     m_pQSet2 = VclPtr<MaskSet>::Create(this, pGrid);
379     m_pQSet2->set_grid_left_attach(1);
380     m_pQSet2->set_grid_top_attach(2);
381     m_pQSet2->Show();
382     get(m_pSp2, "tol2");
383     get(m_pLbColor2, "color2");
384     m_pLbColor2->SetSlotId(SID_BMPMASK_COLOR);
385     get(m_pCbx3, "cbx3");
386     m_pQSet3 = VclPtr<MaskSet>::Create(this, pGrid);
387     m_pQSet3->set_grid_left_attach(1);
388     m_pQSet3->set_grid_top_attach(3);
389     m_pQSet3->Show();
390     get(m_pSp3, "tol3");
391     get(m_pLbColor3, "color3");
392     m_pLbColor3->SetSlotId(SID_BMPMASK_COLOR);
393     get(m_pCbx4, "cbx4");
394     m_pQSet4   = VclPtr<MaskSet>::Create(this, pGrid);
395     m_pQSet4->set_grid_left_attach(1);
396     m_pQSet4->set_grid_top_attach(4);
397     m_pQSet4->Show();
398     get(m_pSp4, "tol4");
399     get(m_pLbColor4, "color4");
400     m_pLbColor4->SetSlotId(SID_BMPMASK_COLOR);
401     get(m_pCbxTrans, "cbx5");
402     get(m_pLbColorTrans, "color5");
403 
404     m_pLbColorTrans->SelectEntry(COL_BLACK);
405     m_pLbColor1->SelectEntry(COL_TRANSPARENT);
406     m_pLbColor2->SelectEntry(COL_TRANSPARENT);
407     m_pLbColor3->SelectEntry(COL_TRANSPARENT);
408     m_pLbColor4->SelectEntry(COL_TRANSPARENT);
409 
410     m_pTbxPipette->SetSelectHdl( LINK( pData.get(), MaskData, PipetteHdl ) );
411     m_pBtnExec->SetClickHdl( LINK( pData.get(), MaskData, ExecHdl ) );
412 
413     m_pCbx1->SetClickHdl( LINK( pData.get(), MaskData, CbxHdl ) );
414     m_pCbx2->SetClickHdl( LINK( pData.get(), MaskData, CbxHdl ) );
415     m_pCbx3->SetClickHdl( LINK( pData.get(), MaskData, CbxHdl ) );
416     m_pCbx4->SetClickHdl( LINK( pData.get(), MaskData, CbxHdl ) );
417     m_pCbxTrans->SetClickHdl( LINK( pData.get(), MaskData, CbxTransHdl ) );
418 
419     SetAccessibleNames ();
420 
421     m_pLbColor1->SetGetFocusHdl( LINK( pData.get(), MaskData, FocusLbHdl ) );
422     m_pLbColor2->SetGetFocusHdl( LINK( pData.get(), MaskData, FocusLbHdl ) );
423     m_pLbColor3->SetGetFocusHdl( LINK( pData.get(), MaskData, FocusLbHdl ) );
424     m_pLbColor4->SetGetFocusHdl( LINK( pData.get(), MaskData, FocusLbHdl ) );
425     m_pLbColorTrans->Disable();
426 
427     OUString sColorPalette (SvxResId( RID_SVXDLG_BMPMASK_STR_PALETTE));
428     OUString sColorPaletteN;
429 
430     m_pQSet1->SetStyle( m_pQSet1->GetStyle() | WB_DOUBLEBORDER | WB_ITEMBORDER );
431     m_pQSet1->SetColCount();
432     m_pQSet1->SetLineCount( 1 );
433     sColorPaletteN = sColorPalette + " 1";
434     m_pQSet1->InsertItem( 1, aPipetteColor, sColorPaletteN);
435     m_pQSet1->SelectItem( 1 );
436 
437     m_pQSet2->SetStyle( m_pQSet2->GetStyle() | WB_DOUBLEBORDER | WB_ITEMBORDER );
438     m_pQSet2->SetColCount();
439     m_pQSet2->SetLineCount( 1 );
440     sColorPaletteN = sColorPalette + " 2";
441     m_pQSet2->InsertItem( 1, aPipetteColor, sColorPaletteN);
442     m_pQSet2->SelectItem( 0 );
443 
444     m_pQSet3->SetStyle( m_pQSet3->GetStyle() | WB_DOUBLEBORDER | WB_ITEMBORDER );
445     m_pQSet3->SetColCount();
446     m_pQSet3->SetLineCount( 1 );
447     sColorPaletteN = sColorPalette + " 3";
448     m_pQSet3->InsertItem( 1, aPipetteColor, sColorPaletteN);
449     m_pQSet3->SelectItem( 0 );
450 
451     m_pQSet4->SetStyle( m_pQSet4->GetStyle() | WB_DOUBLEBORDER | WB_ITEMBORDER );
452     m_pQSet4->SetColCount();
453     m_pQSet4->SetLineCount( 1 );
454     sColorPaletteN = sColorPalette + " 4";
455     m_pQSet4->InsertItem( 1, aPipetteColor, sColorPaletteN);
456     m_pQSet4->SelectItem( 0 );
457 
458     m_pQSet1->Show();
459     m_pQSet2->Show();
460     m_pQSet3->Show();
461     m_pQSet4->Show();
462 }
463 
~SvxBmpMask()464 SvxBmpMask::~SvxBmpMask()
465 {
466     disposeOnce();
467 }
468 
dispose()469 void SvxBmpMask::dispose()
470 {
471     m_pQSet1.disposeAndClear();
472     m_pQSet2.disposeAndClear();
473     m_pQSet3.disposeAndClear();
474     m_pQSet4.disposeAndClear();
475     m_pCtlPipette.disposeAndClear();
476     pData.reset();
477     m_pTbxPipette.clear();
478     m_pBtnExec.clear();
479     m_pCbx1.clear();
480     m_pSp1.clear();
481     m_pLbColor1.clear();
482     m_pCbx2.clear();
483     m_pSp2.clear();
484     m_pLbColor2.clear();
485     m_pCbx3.clear();
486     m_pSp3.clear();
487     m_pLbColor3.clear();
488     m_pCbx4.clear();
489     m_pSp4.clear();
490     m_pLbColor4.clear();
491     m_pCbxTrans.clear();
492     m_pLbColorTrans.clear();
493     aSelItem.dispose();
494     SfxDockingWindow::dispose();
495 }
496 
497 /** is called by a MaskSet when it is selected */
onSelect(MaskSet * pSet)498 void SvxBmpMask::onSelect( MaskSet* pSet )
499 {
500     // now deselect all other value sets
501     if( pSet != m_pQSet1 )
502         m_pQSet1->SelectItem( 0 );
503 
504     if( pSet != m_pQSet2 )
505         m_pQSet2->SelectItem( 0 );
506 
507     if( pSet != m_pQSet3 )
508         m_pQSet3->SelectItem( 0 );
509 
510     if( pSet != m_pQSet4 )
511         m_pQSet4->SelectItem( 0 );
512 }
513 
Close()514 bool SvxBmpMask::Close()
515 {
516     SfxBoolItem aItem2( SID_BMPMASK_PIPETTE, false );
517     GetBindings().GetDispatcher()->ExecuteList(SID_BMPMASK_PIPETTE,
518             OWN_CALLMODE, { &aItem2 });
519 
520     return SfxDockingWindow::Close();
521 }
522 
SetColor(const Color & rColor)523 void SvxBmpMask::SetColor( const Color& rColor )
524 {
525     aPipetteColor = rColor;
526     m_pCtlPipette->SetColor( aPipetteColor );
527 }
528 
PipetteClicked()529 void SvxBmpMask::PipetteClicked()
530 {
531     if( m_pQSet1->GetSelectedItemId() == 1 )
532     {
533         m_pCbx1->Check();
534         pData->CbxHdl(m_pCbx1);
535         m_pQSet1->SetItemColor( 1, aPipetteColor );
536         m_pQSet1->SetFormat();
537     }
538     else if( m_pQSet2->GetSelectedItemId() == 1 )
539     {
540         m_pCbx2->Check();
541         pData->CbxHdl(m_pCbx2);
542         m_pQSet2->SetItemColor( 1, aPipetteColor );
543         m_pQSet2->SetFormat();
544     }
545     else if( m_pQSet3->GetSelectedItemId() == 1 )
546     {
547         m_pCbx3->Check();
548         pData->CbxHdl(m_pCbx3);
549         m_pQSet3->SetItemColor( 1, aPipetteColor );
550         m_pQSet3->SetFormat();
551     }
552     else if( m_pQSet4->GetSelectedItemId() == 1 )
553     {
554         m_pCbx4->Check();
555         pData->CbxHdl(m_pCbx4);
556         m_pQSet4->SetItemColor( 1, aPipetteColor );
557         m_pQSet4->SetFormat();
558     }
559 
560     m_pTbxPipette->CheckItem( m_pTbxPipette->GetItemId(0), false );
561     pData->PipetteHdl(m_pTbxPipette);
562 }
563 
SetExecState(bool bEnable)564 void SvxBmpMask::SetExecState( bool bEnable )
565 {
566     pData->SetExecState( bEnable );
567 
568     if ( pData->IsExecReady() && pData->IsCbxReady() )
569         m_pBtnExec->Enable();
570     else
571         m_pBtnExec->Disable();
572 }
573 
574 
InitColorArrays(Color * pSrcCols,Color * pDstCols,sal_uInt8 * pTols)575 sal_uInt16 SvxBmpMask::InitColorArrays( Color* pSrcCols, Color* pDstCols, sal_uInt8* pTols )
576 {
577     sal_uInt16  nCount = 0;
578 
579     if ( m_pCbx1->IsChecked() )
580     {
581         pSrcCols[nCount] = m_pQSet1->GetItemColor( 1 );
582         pDstCols[nCount] = m_pLbColor1->GetSelectEntryColor();
583         pTols[nCount++] = static_cast<sal_uIntPtr>(m_pSp1->GetValue());
584     }
585 
586     if ( m_pCbx2->IsChecked() )
587     {
588         pSrcCols[nCount] = m_pQSet2->GetItemColor( 1 );
589         pDstCols[nCount] = m_pLbColor2->GetSelectEntryColor();
590         pTols[nCount++] = static_cast<sal_uIntPtr>(m_pSp2->GetValue());
591     }
592 
593     if ( m_pCbx3->IsChecked() )
594     {
595         pSrcCols[nCount] = m_pQSet3->GetItemColor( 1 );
596         pDstCols[nCount] = m_pLbColor3->GetSelectEntryColor();
597         pTols[nCount++] = static_cast<sal_uIntPtr>(m_pSp3->GetValue());
598     }
599 
600     if ( m_pCbx4->IsChecked() )
601     {
602         pSrcCols[nCount] = m_pQSet4->GetItemColor( 1 );
603         pDstCols[nCount] = m_pLbColor4->GetSelectEntryColor();
604         pTols[nCount++] = static_cast<sal_uIntPtr>(m_pSp4->GetValue());
605     }
606 
607     return nCount;
608 }
609 
ImpMask(BitmapEx & rBitmap)610 void SvxBmpMask::ImpMask( BitmapEx& rBitmap )
611 {
612     Color           pSrcCols[4];
613     Color           pDstCols[4];
614     sal_uInt8       pTols[4];
615     const sal_uInt16 nCount = InitColorArrays( pSrcCols, pDstCols, pTols );
616 
617     EnterWait();
618     rBitmap.Replace( pSrcCols, pDstCols, nCount, pTols );
619     LeaveWait();
620 }
621 
ImpMaskTransparent(const BitmapEx & rBitmapEx,const Color & rColor,const sal_uInt8 nTol)622 BitmapEx SvxBmpMask::ImpMaskTransparent( const BitmapEx& rBitmapEx, const Color& rColor, const sal_uInt8 nTol )
623 {
624     EnterWait();
625 
626     BitmapEx    aBmpEx;
627     Bitmap      aMask( rBitmapEx.GetBitmap().CreateMask( rColor, nTol ) );
628 
629     if( rBitmapEx.IsTransparent() )
630         aMask.CombineSimple( rBitmapEx.GetMask(), BmpCombine::Or );
631 
632     aBmpEx = BitmapEx( rBitmapEx.GetBitmap(), aMask );
633     LeaveWait();
634 
635     return aBmpEx;
636 }
637 
638 
ImpMask(const Animation & rAnimation)639 Animation SvxBmpMask::ImpMask( const Animation& rAnimation )
640 {
641     Animation   aAnimation( rAnimation );
642     Color       pSrcCols[4];
643     Color       pDstCols[4];
644     sal_uInt8   pTols[4];
645     InitColorArrays( pSrcCols, pDstCols, pTols );
646     sal_uInt16  nAnimationCount = aAnimation.Count();
647 
648     for( sal_uInt16 i = 0; i < nAnimationCount; i++ )
649     {
650         AnimationBitmap aAnimationBitmap( aAnimation.Get( i ) );
651         aAnimationBitmap.maBitmapEx = Mask(aAnimationBitmap.maBitmapEx).GetBitmapEx();
652         aAnimation.Replace(aAnimationBitmap, i);
653     }
654 
655     return aAnimation;
656 }
657 
658 
ImpMask(const GDIMetaFile & rMtf)659 GDIMetaFile SvxBmpMask::ImpMask( const GDIMetaFile& rMtf )
660 {
661     GDIMetaFile aMtf;
662     Color       pSrcCols[4];
663     Color       pDstCols[4];
664     sal_uInt8   pTols[4];
665     sal_uInt16  nCount = InitColorArrays( pSrcCols, pDstCols, pTols );
666 
667     // If no color is selected, we copy only the Mtf
668     if( !nCount )
669         aMtf = rMtf;
670     else
671     {
672         bool        pTrans[4];
673         Color       aCol;
674         long        nR;
675         long        nG;
676         long        nB;
677         std::unique_ptr<long[]> pMinR(new long[nCount]);
678         std::unique_ptr<long[]> pMaxR(new long[nCount]);
679         std::unique_ptr<long[]> pMinG(new long[nCount]);
680         std::unique_ptr<long[]> pMaxG(new long[nCount]);
681         std::unique_ptr<long[]> pMinB(new long[nCount]);
682         std::unique_ptr<long[]> pMaxB(new long[nCount]);
683         sal_uInt16      i;
684 
685         aMtf.SetPrefSize( rMtf.GetPrefSize() );
686         aMtf.SetPrefMapMode( rMtf.GetPrefMapMode() );
687 
688         // Prepare Color comparison array
689         for( i = 0; i < nCount; i++ )
690         {
691             long nTol = ( pTols[i] * 255L ) / 100L;
692 
693             long nVal = static_cast<long>(pSrcCols[i].GetRed());
694             pMinR[i] = std::max( nVal - nTol, 0L );
695             pMaxR[i] = std::min( nVal + nTol, 255L );
696 
697             nVal = static_cast<long>(pSrcCols[i].GetGreen());
698             pMinG[i] = std::max( nVal - nTol, 0L );
699             pMaxG[i] = std::min( nVal + nTol, 255L );
700 
701             nVal = static_cast<long>(pSrcCols[i].GetBlue());
702             pMinB[i] = std::max( nVal - nTol, 0L );
703             pMaxB[i] = std::min( nVal + nTol, 255L );
704 
705             pTrans[ i ] = (pDstCols[ i ] == COL_TRANSPARENT);
706         }
707 
708         // Investigate actions and if necessary replace colors
709         for( size_t nAct = 0, nActCount = rMtf.GetActionSize(); nAct < nActCount; nAct++ )
710         {
711             MetaAction* pAction = rMtf.GetAction( nAct );
712 
713             bool bReplace = false;
714 
715             switch( pAction->GetType() )
716             {
717                 case MetaActionType::PIXEL:
718                 {
719                     MetaPixelAction* pAct = static_cast<MetaPixelAction*>(pAction);
720 
721                     aCol = pAct->GetColor();
722                     TEST_COLS();
723 
724                     if( bReplace )
725                         pAct = new MetaPixelAction( pAct->GetPoint(), aCol );
726 
727                     aMtf.AddAction( pAct );
728                 }
729                 break;
730 
731                 case MetaActionType::LINECOLOR:
732                 {
733                     MetaLineColorAction* pAct = static_cast<MetaLineColorAction*>(pAction);
734 
735                     aCol = pAct->GetColor();
736                     TEST_COLS();
737 
738                     if( bReplace )
739                         pAct = new MetaLineColorAction( aCol, !pTrans[ i ] );
740 
741                     aMtf.AddAction( pAct );
742                 }
743                 break;
744 
745                 case MetaActionType::FILLCOLOR:
746                 {
747                     MetaFillColorAction* pAct = static_cast<MetaFillColorAction*>(pAction);
748 
749                     aCol = pAct->GetColor();
750                     TEST_COLS();
751 
752                     if( bReplace )
753                         pAct = new MetaFillColorAction( aCol, !pTrans[ i ] );
754 
755                     aMtf.AddAction( pAct );
756                 }
757                 break;
758 
759                 case MetaActionType::TEXTCOLOR:
760                 {
761                     MetaTextColorAction* pAct = static_cast<MetaTextColorAction*>(pAction);
762 
763                     aCol = pAct->GetColor();
764                     TEST_COLS();
765 
766                     if( bReplace )
767                         pAct = new MetaTextColorAction( aCol );
768 
769                     aMtf.AddAction( pAct );
770                 }
771                 break;
772 
773                 case MetaActionType::TEXTFILLCOLOR:
774                 {
775                     MetaTextFillColorAction* pAct = static_cast<MetaTextFillColorAction*>(pAction);
776 
777                     aCol = pAct->GetColor();
778                     TEST_COLS();
779 
780                     if( bReplace )
781                         pAct = new MetaTextFillColorAction( aCol, !pTrans[ i ] );
782 
783                     aMtf.AddAction( pAct );
784                 }
785                 break;
786 
787                 case MetaActionType::FONT:
788                 {
789                     MetaFontAction* pAct = static_cast<MetaFontAction*>(pAction);
790                     vcl::Font       aFont( pAct->GetFont() );
791 
792                     aCol = aFont.GetColor();
793                     TEST_COLS();
794 
795                     if( bReplace )
796                     {
797                         aFont.SetColor( aCol );
798                         pAct = new MetaFontAction( aFont );
799                     }
800 
801                     aMtf.AddAction( pAct );
802                 }
803                 break;
804 
805                 case MetaActionType::WALLPAPER:
806                 {
807                     MetaWallpaperAction*    pAct = static_cast<MetaWallpaperAction*>(pAction);
808                     Wallpaper               aWall( pAct->GetWallpaper() );
809 
810                     aCol = aWall.GetColor();
811                     TEST_COLS();
812 
813                     if( bReplace )
814                     {
815                         aWall.SetColor( aCol );
816                         pAct = new MetaWallpaperAction( pAct->GetRect(), aWall );
817                     }
818 
819                     aMtf.AddAction( pAct );
820                 }
821                 break;
822 
823                 case MetaActionType::BMP:
824                 {
825                     MetaBmpAction*  pAct = static_cast<MetaBmpAction*>(pAction);
826                     const Bitmap    aBmp( Mask( pAct->GetBitmap() ).GetBitmapEx().GetBitmap() );
827 
828                     pAct = new MetaBmpAction( pAct->GetPoint(), aBmp );
829                     aMtf.AddAction( pAct );
830                 }
831                 break;
832 
833                 case MetaActionType::BMPSCALE:
834                 {
835                     MetaBmpScaleAction* pAct = static_cast<MetaBmpScaleAction*>(pAction);
836                     const Bitmap        aBmp( Mask( pAct->GetBitmap() ).GetBitmapEx().GetBitmap() );
837 
838                     pAct = new MetaBmpScaleAction( pAct->GetPoint(), pAct->GetSize(), aBmp );
839                     aMtf.AddAction( pAct );
840                 }
841                 break;
842 
843                 case MetaActionType::BMPSCALEPART:
844                 {
845                     MetaBmpScalePartAction* pAct = static_cast<MetaBmpScalePartAction*>(pAction);
846                     const Bitmap            aBmp( Mask( pAct->GetBitmap() ).GetBitmapEx().GetBitmap() );
847 
848                     pAct = new MetaBmpScalePartAction( pAct->GetDestPoint(), pAct->GetDestSize(),
849                                                        pAct->GetSrcPoint(), pAct->GetSrcSize(), aBmp );
850                     aMtf.AddAction( pAct );
851                 }
852                 break;
853 
854                 case MetaActionType::BMPEX:
855                 {
856                     MetaBmpExAction*    pAct = static_cast<MetaBmpExAction*>(pAction);
857                     const BitmapEx      aBmpEx( Mask( pAct->GetBitmapEx() ).GetBitmapEx() );
858 
859                     pAct = new MetaBmpExAction( pAct->GetPoint(), aBmpEx );
860                     aMtf.AddAction( pAct );
861                 }
862                 break;
863 
864                 case MetaActionType::BMPEXSCALE:
865                 {
866                     MetaBmpExScaleAction*   pAct = static_cast<MetaBmpExScaleAction*>(pAction);
867                     const BitmapEx          aBmpEx( Mask( pAct->GetBitmapEx() ).GetBitmapEx() );
868 
869                     pAct = new MetaBmpExScaleAction( pAct->GetPoint(), pAct->GetSize(), aBmpEx );
870                     aMtf.AddAction( pAct );
871                 }
872                 break;
873 
874                 case MetaActionType::BMPEXSCALEPART:
875                 {
876                     MetaBmpExScalePartAction*   pAct = static_cast<MetaBmpExScalePartAction*>(pAction);
877                     const BitmapEx              aBmpEx( Mask( pAct->GetBitmapEx() ).GetBitmapEx() );
878 
879                     pAct = new MetaBmpExScalePartAction( pAct->GetDestPoint(), pAct->GetDestSize(),
880                                                          pAct->GetSrcPoint(), pAct->GetSrcSize(), aBmpEx );
881                     aMtf.AddAction( pAct );
882                 }
883                 break;
884 
885                 default:
886                 {
887                     aMtf.AddAction( pAction );
888                 }
889                 break;
890             }
891         }
892     }
893 
894     LeaveWait();
895 
896     return aMtf;
897 }
898 
899 
ImpReplaceTransparency(const Animation & rAnim,const Color & rColor)900 Animation SvxBmpMask::ImpReplaceTransparency( const Animation& rAnim, const Color& rColor )
901 {
902     Animation   aAnimation( rAnim );
903     sal_uInt16      nAnimationCount = aAnimation.Count();
904 
905     for( sal_uInt16 i = 0; i < nAnimationCount; i++ )
906     {
907         AnimationBitmap aAnimationBitmap(aAnimation.Get(i));
908         aAnimationBitmap.maBitmapEx.ReplaceTransparency(rColor);
909         aAnimation.Replace(aAnimationBitmap, i);
910     }
911 
912     return aAnimation;
913 }
914 
915 
ImpReplaceTransparency(const GDIMetaFile & rMtf,const Color & rColor)916 GDIMetaFile SvxBmpMask::ImpReplaceTransparency( const GDIMetaFile& rMtf, const Color& rColor )
917 {
918     ScopedVclPtrInstance< VirtualDevice > pVDev;
919     GDIMetaFile     aMtf;
920     const MapMode&  rPrefMap = rMtf.GetPrefMapMode();
921     const Size&     rPrefSize = rMtf.GetPrefSize();
922     const size_t    nActionCount = rMtf.GetActionSize();
923 
924     pVDev->EnableOutput( false );
925     aMtf.Record( pVDev );
926     aMtf.SetPrefSize( rPrefSize );
927     aMtf.SetPrefMapMode( rPrefMap );
928     pVDev->SetLineColor( rColor );
929     pVDev->SetFillColor( rColor );
930 
931     // retrieve one action at the time; first
932     // set the whole area to the replacement color.
933     pVDev->DrawRect( tools::Rectangle( rPrefMap.GetOrigin(), rPrefSize ) );
934     for ( size_t i = 0; i < nActionCount; i++ )
935     {
936         MetaAction* pAct = rMtf.GetAction( i );
937         aMtf.AddAction( pAct );
938     }
939 
940     aMtf.Stop();
941     aMtf.WindStart();
942 
943     return aMtf;
944 }
945 
GetMetaFile(const Graphic & rGraphic)946 GDIMetaFile SvxBmpMask::GetMetaFile(const Graphic& rGraphic)
947 {
948     // Replace transparency?
949     if (m_pCbxTrans->IsChecked())
950         return ImpReplaceTransparency(rGraphic.GetGDIMetaFile(), m_pLbColorTrans->GetSelectEntryColor());
951     return ImpMask(rGraphic.GetGDIMetaFile());
952 }
953 
Mask(const Graphic & rGraphic)954 Graphic SvxBmpMask::Mask( const Graphic& rGraphic )
955 {
956     Graphic     aGraphic( rGraphic );
957     const Color aReplColor( m_pLbColorTrans->GetSelectEntryColor() );
958 
959     switch( rGraphic.GetType() )
960     {
961         case GraphicType::Bitmap:
962         {
963             if( rGraphic.IsAnimated() )
964             {
965                 // Replace transparency?
966                 if ( m_pCbxTrans->IsChecked() )
967                     aGraphic = ImpReplaceTransparency( rGraphic.GetAnimation(), aReplColor );
968                 else
969                     aGraphic = ImpMask( rGraphic.GetAnimation() );
970             }
971             else
972             {
973                 // Replace transparency?
974                 if( m_pCbxTrans->IsChecked() )
975                 {
976                     BitmapEx aBmpEx = aGraphic.GetBitmapEx();
977                     aBmpEx.ReplaceTransparency(aReplColor);
978                     aGraphic = aBmpEx;
979                 }
980                 else
981                 {
982                     Color   pSrcCols[4];
983                     Color   pDstCols[4];
984                     sal_uInt8   pTols[4];
985                     sal_uInt16  nCount = InitColorArrays( pSrcCols, pDstCols, pTols );
986 
987                     if( nCount )
988                     {
989                         // first set all transparent colors
990                         for( sal_uInt16 i = 0; i < nCount; i++ )
991                         {
992                             // Do we have a transparent color?
993                             if (pDstCols[i] == COL_TRANSPARENT)
994                             {
995                                 BitmapEx    aBmpEx( ImpMaskTransparent( aGraphic.GetBitmapEx(),
996                                                                         pSrcCols[ i ], pTols[ i ] ) );
997                                 const Size  aSize( aBmpEx.GetSizePixel() );
998 
999                                 if( aSize.Width() && aSize.Height() )
1000                                     aGraphic = aBmpEx;
1001                             }
1002                         }
1003 
1004                         // now replace it again with the normal colors
1005                         BitmapEx  aBitmapEx( aGraphic.GetBitmapEx() );
1006                         if ( aBitmapEx.GetSizePixel().Width() && aBitmapEx.GetSizePixel().Height() )
1007                         {
1008                             ImpMask( aBitmapEx );
1009                             if ( aGraphic.IsTransparent() )
1010                                 aGraphic = Graphic( BitmapEx( aBitmapEx.GetBitmap(), aBitmapEx.GetMask() ) );
1011                             else
1012                                 aGraphic = aBitmapEx;
1013                         }
1014                     }
1015                 }
1016             }
1017         }
1018         break;
1019 
1020         case GraphicType::GdiMetafile:
1021         {
1022             GDIMetaFile aMtf(GetMetaFile(rGraphic));
1023             Size aSize( aMtf.GetPrefSize() );
1024             if ( aSize.Width() && aSize.Height() )
1025                 aGraphic = Graphic( aMtf );
1026             else
1027                 aGraphic = rGraphic;
1028         }
1029         break;
1030 
1031         default:
1032             aGraphic = rGraphic;
1033         break;
1034     }
1035 
1036     if( aGraphic != rGraphic )
1037     {
1038         aGraphic.SetPrefSize( rGraphic.GetPrefSize() );
1039         aGraphic.SetPrefMapMode( rGraphic.GetPrefMapMode() );
1040     }
1041 
1042     return aGraphic;
1043 }
1044 
IsEyedropping() const1045 bool SvxBmpMask::IsEyedropping() const
1046 {
1047     return m_pTbxPipette->IsItemChecked( m_pTbxPipette->GetItemId(0) );
1048 }
1049 
1050 /** Set an accessible name for the source color check boxes.  Without this
1051     the lengthy description is read.
1052 */
SetAccessibleNames()1053 void SvxBmpMask::SetAccessibleNames()
1054 {
1055     // set the accessible name for valueset
1056     OUString sColorPalette (SvxResId( RID_SVXDLG_BMPMASK_STR_PALETTE));
1057     OUString sColorPaletteN;
1058 
1059     sColorPaletteN = sColorPalette + " 1";
1060     m_pQSet1->SetText (sColorPaletteN);
1061     sColorPaletteN = sColorPalette + " 2";
1062     m_pQSet2->SetText (sColorPaletteN);
1063     sColorPaletteN = sColorPalette + " 3";
1064     m_pQSet3->SetText (sColorPaletteN);
1065     sColorPaletteN = sColorPalette + " 4";
1066     m_pQSet4->SetText (sColorPaletteN);
1067 }
1068 
1069 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1070