1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 #include "precompiled_sd.hxx"
29 
30 #include "PresenterTextView.hxx"
31 
32 #include <i18npool/mslangid.hxx>
33 #include <cppcanvas/vclfactory.hxx>
34 #include <svl/itempool.hxx>
35 #include <svl/itemset.hxx>
36 #include <unotools/linguprops.hxx>
37 #include <unotools/lingucfg.hxx>
38 #include <editeng/colritem.hxx>
39 #include <editeng/editeng.hxx>
40 #include <editeng/editstat.hxx>
41 #include <editeng/eeitem.hxx>
42 #include <editeng/fhgtitem.hxx>
43 #include <editeng/fontitem.hxx>
44 #include <svx/xflclit.hxx>
45 #include <vcl/bitmapex.hxx>
46 #include <vcl/svapp.hxx>
47 #include <vcl/virdev.hxx>
48 #include <com/sun/star/awt/FontDescriptor.hpp>
49 #include <com/sun/star/awt/Size.hpp>
50 #include <com/sun/star/rendering/XSpriteCanvas.hpp>
51 #include <com/sun/star/util/Color.hpp>
52 #include <com/sun/star/i18n/ScriptType.hpp>
53 
54 
55 using namespace ::com::sun::star;
56 using namespace ::com::sun::star::uno;
57 using namespace ::com::sun::star::lang;
58 using ::rtl::OUString;
59 
60 namespace sd { namespace presenter {
61 
62 //===== Service ===============================================================
63 
64 Reference<XInterface> SAL_CALL PresenterTextViewService_createInstance (
65     const Reference<XComponentContext>& rxContext)
66 {
67     return Reference<XInterface>(static_cast<XWeak*>(new PresenterTextView(rxContext)));
68 }
69 
70 
71 
72 
73 ::rtl::OUString PresenterTextViewService_getImplementationName (void) throw(RuntimeException)
74 {
75     return OUString::createFromAscii("com.sun.star.comp.Draw.PresenterTextView");
76 }
77 
78 
79 
80 
81 Sequence<rtl::OUString> SAL_CALL PresenterTextViewService_getSupportedServiceNames (void)
82     throw (RuntimeException)
83 {
84 	static const ::rtl::OUString sServiceName(
85         ::rtl::OUString::createFromAscii("com.sun.star.drawing.PresenterTextView"));
86 	return Sequence<rtl::OUString>(&sServiceName, 1);
87 }
88 
89 
90 
91 //===== PresenterTextView::Implementation =====================================
92 
93 class PresenterTextView::Implementation
94 {
95 public:
96     const OUString msTextPropertyName;
97     const OUString msBitmapPropertyName;
98     const OUString msSizePropertyName;
99     const OUString msBackgroundColorPropertyName;
100     const OUString msTextColorPropertyName;
101     const OUString msFontDescriptorPropertyName;
102     const OUString msTopPropertyName;
103     const OUString msTopRelativePropertyName;
104     const OUString msTotalHeightPropertyName;
105 
106     Implementation (void);
107     ~Implementation (void);
108 
109     void SetCanvas (const cppcanvas::CanvasSharedPtr& rCanvas);
110     void SetSize (const Size aSize);
111     void SetBackgroundColor (const Color aColor);
112     void SetTextColor (const Color aColor);
113     void SetFontDescriptor (const awt::FontDescriptor& rFontDescriptor);
114     sal_Int32 GetTop (void) const;
115     void SetTop (const sal_Int32 nTop);
116     void SetText (const OUString& Text);
117     sal_Int32 ParseDistance (const OUString& rsDistance) const;
118     Reference<rendering::XBitmap> GetBitmap (void);
119     sal_Int32 GetTotalHeight (void);
120 
121 private:
122     Reference<rendering::XBitmap> mxBitmap;
123     cppcanvas::CanvasSharedPtr mpCanvas;
124     VirtualDevice* mpOutputDevice;
125     EditEngine* mpEditEngine;
126     SfxItemPool* mpEditEngineItemPool;
127     Size maSize;
128     Color maBackgroundColor;
129     Color maTextColor;
130     String msText;
131     sal_Int32 mnTop;
132     sal_Int32 mnTotalHeight;
133 
134     EditEngine * GetEditEngine (void);
135     EditEngine* CreateEditEngine (void);
136     void CheckTop (void);
137 };
138 
139 
140 
141 
142 //===== PresenterTextView =====================================================
143 
144 PresenterTextView::PresenterTextView (const Reference<XComponentContext>& rxContext)
145     : PresenterTextViewInterfaceBase(),
146       mpImplementation(new Implementation())
147 {
148     (void)rxContext;
149 }
150 
151 
152 
153 
154 PresenterTextView::~PresenterTextView (void)
155 {
156 }
157 
158 
159 
160 
161 void SAL_CALL PresenterTextView::disposing (void)
162 {
163     mpImplementation.reset();
164 }
165 
166 
167 
168 
169 //----- XInitialization -------------------------------------------------------
170 
171 void SAL_CALL PresenterTextView::initialize (const Sequence<Any>& rArguments)
172     throw (Exception, RuntimeException)
173 {
174     ThrowIfDisposed();
175 
176     if (rArguments.getLength() == 1)
177     {
178         try
179         {
180             Reference<rendering::XBitmapCanvas> xCanvas (rArguments[0], UNO_QUERY_THROW);
181             if (xCanvas.is())
182             {
183                 mpImplementation->SetCanvas(
184                     cppcanvas::VCLFactory::getInstance().createCanvas(xCanvas));
185             }
186         }
187         catch (RuntimeException&)
188         {
189             throw;
190         }
191     }
192     else
193     {
194         throw RuntimeException(
195             OUString::createFromAscii("PresenterTextView: invalid number of arguments"),
196                 static_cast<XWeak*>(this));
197     }
198 }
199 
200 
201 
202 
203 //-----------------------------------------------------------------------------
204 
205 Any PresenterTextView::GetPropertyValue (const OUString& rsPropertyName)
206 {
207     ThrowIfDisposed();
208 
209     if (rsPropertyName == mpImplementation->msBitmapPropertyName)
210     {
211         return Any(mpImplementation->GetBitmap());
212     }
213     else if (rsPropertyName == mpImplementation->msTopPropertyName)
214     {
215         return Any(mpImplementation->GetTop());
216     }
217     else if (rsPropertyName == mpImplementation->msTotalHeightPropertyName)
218     {
219         return Any(mpImplementation->GetTotalHeight());
220     }
221 
222     return Any();
223 }
224 
225 
226 
227 
228 Any PresenterTextView::SetPropertyValue (
229     const ::rtl::OUString& rsPropertyName,
230     const css::uno::Any& rValue)
231 {
232     ThrowIfDisposed();
233 
234     Any aOldValue;
235     if (rsPropertyName == mpImplementation->msTextPropertyName)
236     {
237         OUString sText;
238         if (rValue >>= sText)
239             mpImplementation->SetText(sText);
240     }
241     else if (rsPropertyName == mpImplementation->msSizePropertyName)
242     {
243         awt::Size aSize;
244         if (rValue >>= aSize)
245             mpImplementation->SetSize(Size(aSize.Width,aSize.Height));
246     }
247     else if (rsPropertyName == mpImplementation->msBackgroundColorPropertyName)
248     {
249         util::Color aColor = util::Color();
250         if (rValue >>= aColor)
251             mpImplementation->SetBackgroundColor(Color(aColor));
252     }
253     else if (rsPropertyName == mpImplementation->msTextColorPropertyName)
254     {
255         util::Color aColor = util::Color();
256         if (rValue >>= aColor)
257             mpImplementation->SetTextColor(Color(aColor));
258     }
259     else if (rsPropertyName == mpImplementation->msFontDescriptorPropertyName)
260     {
261         awt::FontDescriptor aFontDescriptor;
262         if (rValue >>= aFontDescriptor)
263             mpImplementation->SetFontDescriptor(aFontDescriptor);
264     }
265     else if (rsPropertyName == mpImplementation->msTopPropertyName)
266     {
267         sal_Int32 nTop = 0;
268         if (rValue >>= nTop)
269             mpImplementation->SetTop(nTop);
270     }
271     else if (rsPropertyName == mpImplementation->msTopRelativePropertyName)
272     {
273         OUString sDistance;
274         if (rValue >>= sDistance)
275             mpImplementation->SetTop(
276                 mpImplementation->GetTop()
277                     + mpImplementation->ParseDistance(sDistance));
278     }
279     return aOldValue;
280 }
281 
282 
283 
284 
285 void PresenterTextView::ThrowIfDisposed (void)
286     throw (::com::sun::star::lang::DisposedException)
287 {
288 	if (PresenterTextViewInterfaceBase::rBHelper.bDisposed
289         || PresenterTextViewInterfaceBase::rBHelper.bInDispose
290         || mpImplementation.get()==NULL)
291 	{
292         throw lang::DisposedException (
293             ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
294                 "PresenterTextView object has already been disposed")),
295             static_cast<uno::XWeak*>(this));
296     }
297 }
298 
299 
300 
301 
302 //===== PresenterTextView::Implementation =====================================
303 
304 PresenterTextView::Implementation::Implementation (void)
305     : msTextPropertyName(OUString::createFromAscii("Text")),
306       msBitmapPropertyName(OUString::createFromAscii("Bitmap")),
307       msSizePropertyName(OUString::createFromAscii("Size")),
308       msBackgroundColorPropertyName(OUString::createFromAscii("BackgroundColor")),
309       msTextColorPropertyName(OUString::createFromAscii("TextColor")),
310       msFontDescriptorPropertyName(OUString::createFromAscii("FontDescriptor")),
311       msTopPropertyName(OUString::createFromAscii("Top")),
312       msTopRelativePropertyName(OUString::createFromAscii("RelativeTop")),
313       msTotalHeightPropertyName(OUString::createFromAscii("TotalHeight")),
314       mxBitmap(),
315       mpCanvas(),
316       mpOutputDevice(new VirtualDevice(*Application::GetDefaultDevice(), 0, 0)),
317       mpEditEngine(NULL),
318       mpEditEngineItemPool(EditEngine::CreatePool()),
319       maSize(100,100),
320       maBackgroundColor(0xffffffff),
321       maTextColor(0x00000000),
322       msText(),
323       mnTop(0),
324       mnTotalHeight(-1)
325 {
326 	mpOutputDevice->SetMapMode(MAP_PIXEL);
327 
328     GetEditEngine();
329 }
330 
331 
332 
333 
334 PresenterTextView::Implementation::~Implementation (void)
335 {
336     delete mpEditEngine;
337     SfxItemPool::Free(mpEditEngineItemPool);
338     delete mpOutputDevice;
339 }
340 
341 
342 
343 
344 EditEngine * PresenterTextView::Implementation::GetEditEngine (void)
345 {
346     if (mpEditEngine == NULL)
347         mpEditEngine = CreateEditEngine ();
348     return mpEditEngine;
349 }
350 
351 
352 
353 
354 EditEngine* PresenterTextView::Implementation::CreateEditEngine (void)
355 {
356     EditEngine* pEditEngine = mpEditEngine;
357 	if (pEditEngine == NULL)
358 	{
359         //
360         // set fonts to be used
361         //
362         SvtLinguOptions aOpt;
363         SvtLinguConfig().GetOptions( aOpt );
364         //
365         struct FontDta {
366             sal_Int16       nFallbackLang;
367             sal_Int16       nLang;
368             sal_uInt16      nFontType;
369             sal_uInt16      nFontInfoId;
370             } aTable[3] =
371         {
372             // info to get western font to be used
373             {   LANGUAGE_ENGLISH_US,    LANGUAGE_NONE,
374                 DEFAULTFONT_SERIF,      EE_CHAR_FONTINFO },
375             // info to get CJK font to be used
376             {   LANGUAGE_JAPANESE,      LANGUAGE_NONE,
377                 DEFAULTFONT_CJK_TEXT,   EE_CHAR_FONTINFO_CJK },
378             // info to get CTL font to be used
379             {   LANGUAGE_ARABIC_SAUDI_ARABIA,  LANGUAGE_NONE,
380                 DEFAULTFONT_CTL_TEXT,   EE_CHAR_FONTINFO_CTL }
381         };
382         aTable[0].nLang = MsLangId::resolveSystemLanguageByScriptType(aOpt.nDefaultLanguage, ::com::sun::star::i18n::ScriptType::LATIN);
383         aTable[1].nLang = MsLangId::resolveSystemLanguageByScriptType(aOpt.nDefaultLanguage_CJK, ::com::sun::star::i18n::ScriptType::ASIAN);
384         aTable[2].nLang = MsLangId::resolveSystemLanguageByScriptType(aOpt.nDefaultLanguage_CTL, ::com::sun::star::i18n::ScriptType::COMPLEX);
385         //
386         for (int i = 0;  i < 3;  ++i)
387         {
388             const FontDta &rFntDta = aTable[i];
389             LanguageType nLang = (LANGUAGE_NONE == rFntDta.nLang) ?
390                 rFntDta.nFallbackLang : rFntDta.nLang;
391             Font aFont = Application::GetDefaultDevice()->GetDefaultFont(
392                 rFntDta.nFontType, nLang, DEFAULTFONT_FLAGS_ONLYONE);
393             mpEditEngineItemPool->SetPoolDefaultItem(
394                 SvxFontItem(
395                     aFont.GetFamily(),
396                     aFont.GetName(),
397                     aFont.GetStyleName(),
398                     aFont.GetPitch(),
399                     aFont.GetCharSet(),
400                     rFntDta.nFontInfoId));
401         }
402 
403 
404 		pEditEngine = new EditEngine (mpEditEngineItemPool);
405 
406 		pEditEngine->EnableUndo (sal_True);
407 		pEditEngine->SetDefTab (sal_uInt16(
408 			Application::GetDefaultDevice()->GetTextWidth(
409                 UniString::CreateFromAscii("XXXX"))));
410 
411 		pEditEngine->SetControlWord(
412 				(pEditEngine->GetControlWord()
413                     | EE_CNTRL_AUTOINDENTING) &
414 				(~EE_CNTRL_UNDOATTRIBS) &
415 				(~EE_CNTRL_PASTESPECIAL));
416 
417 		pEditEngine->SetWordDelimiters (
418             UniString::CreateFromAscii(" .=+-*/(){}[];\""));
419 		pEditEngine->SetRefMapMode (MAP_PIXEL);
420 		pEditEngine->SetPaperSize (Size(800, 0));
421 		pEditEngine->EraseVirtualDevice();
422 		pEditEngine->ClearModifyFlag();
423 	}
424 
425 	return pEditEngine;
426 }
427 
428 
429 
430 
431 void PresenterTextView::Implementation::SetCanvas (const cppcanvas::CanvasSharedPtr& rpCanvas)
432 {
433     mpCanvas = rpCanvas;
434     mxBitmap = NULL;
435 }
436 
437 
438 
439 
440 void PresenterTextView::Implementation::SetSize (const Size aSize)
441 {
442     DBG_ASSERT(mpEditEngine!=NULL, "EditEngine missing");
443 
444     maSize = aSize;
445     mpEditEngine->SetPaperSize(maSize);
446     mnTotalHeight = -1;
447     mxBitmap = NULL;
448 }
449 
450 
451 
452 
453 void PresenterTextView::Implementation::SetBackgroundColor (const Color aColor)
454 {
455     maBackgroundColor = aColor;
456     mxBitmap = NULL;
457 
458     DBG_ASSERT(mpEditEngine!=NULL, "EditEngine missing");
459     DBG_ASSERT(mpEditEngineItemPool!=NULL, "EditEngineItemPool missing");
460     mpEditEngine->SetBackgroundColor(aColor);
461     mpEditEngine->EnableAutoColor(sal_False);
462     mpEditEngine->ForceAutoColor(sal_False);
463 }
464 
465 
466 
467 
468 void PresenterTextView::Implementation::SetTextColor (const Color aColor)
469 {
470     maTextColor = aColor;
471     mxBitmap = NULL;
472 
473     DBG_ASSERT(mpEditEngineItemPool!=NULL, "EditEngineItemPool missing");
474     mpEditEngineItemPool->SetPoolDefaultItem(SvxColorItem(aColor, EE_CHAR_COLOR));
475 }
476 
477 
478 
479 
480 void PresenterTextView::Implementation::SetFontDescriptor (
481     const awt::FontDescriptor& rFontDescriptor)
482 {
483     mxBitmap = NULL;
484 
485     DBG_ASSERT(mpEditEngineItemPool!=NULL, "EditEngineItemPool missing");
486 
487     const sal_Int32 nFontHeight = rFontDescriptor.Height;
488 
489     SvxFontHeightItem aFontHeight(
490         Application::GetDefaultDevice()->LogicToPixel(
491             Size(0, nFontHeight), MapMode (MAP_POINT)).Height(),
492         100,
493         EE_CHAR_FONTHEIGHT);
494     mpEditEngineItemPool->SetPoolDefaultItem( aFontHeight);
495     aFontHeight.SetWhich (EE_CHAR_FONTHEIGHT_CJK);
496     mpEditEngineItemPool->SetPoolDefaultItem( aFontHeight);
497     aFontHeight.SetWhich (EE_CHAR_FONTHEIGHT_CTL);
498     mpEditEngineItemPool->SetPoolDefaultItem( aFontHeight);
499 
500     SvxFontItem aSvxFontItem (EE_CHAR_FONTINFO);
501     aSvxFontItem.SetFamilyName( rFontDescriptor.Name );
502     mpEditEngineItemPool->SetPoolDefaultItem(aSvxFontItem);
503 
504     mnTotalHeight = -1;
505     mxBitmap = NULL;
506 
507     CheckTop();
508     mnTotalHeight = -1;
509 }
510 
511 
512 
513 
514 sal_Int32 PresenterTextView::Implementation::GetTop (void) const
515 {
516     return mnTop;
517 }
518 
519 
520 
521 
522 void PresenterTextView::Implementation::SetTop (const sal_Int32 nTop)
523 {
524     if (nTop == mnTop)
525         return;
526 
527     mnTop = nTop;
528     mxBitmap = NULL;
529     CheckTop();
530 }
531 
532 
533 
534 
535 void PresenterTextView::Implementation::SetText (const OUString& rText)
536 {
537     DBG_ASSERT(mpEditEngine!=NULL, "EditEngine missing");
538     msText = rText;
539     mpEditEngine->SetPaperSize(maSize);
540     mnTotalHeight = -1;
541     mxBitmap = NULL;
542 }
543 
544 
545 
546 
547 sal_Int32 PresenterTextView::Implementation::ParseDistance (const OUString& rsDistance) const
548 {
549     DBG_ASSERT(mpEditEngine!=NULL, "EditEngine missing");
550     sal_Int32 nDistance (0);
551     if (rsDistance.endsWithAsciiL("px", 2))
552     {
553         nDistance = rsDistance.copy(0,rsDistance.getLength()-2).toInt32();
554     }
555     else if (rsDistance.endsWithAsciiL("l", 1))
556     {
557         const sal_Int32 nLines (rsDistance.copy(0,rsDistance.getLength()-1).toInt32());
558         // Take the height of the first line as the height of every line.
559         const sal_uInt32 nFirstLineHeight (mpEditEngine->GetLineHeight(0,0));
560         nDistance = nFirstLineHeight * nLines;
561     }
562 
563     return nDistance;
564 }
565 
566 
567 
568 
569 Reference<rendering::XBitmap> PresenterTextView::Implementation::GetBitmap (void)
570 {
571     DBG_ASSERT(mpEditEngine!=NULL, "EditEngine missing");
572 
573     if ( ! mxBitmap.is())
574     {
575         if (mpOutputDevice != NULL)
576             delete mpOutputDevice;
577         mpOutputDevice = new VirtualDevice(*Application::GetDefaultDevice(), 0, 0);
578         mpOutputDevice->SetMapMode(MAP_PIXEL);
579         mpOutputDevice->SetOutputSizePixel(maSize, sal_True);
580         mpOutputDevice->SetLineColor();
581         mpOutputDevice->SetFillColor();
582         mpOutputDevice->SetBackground(Wallpaper());
583         mpOutputDevice->Erase();
584 
585         MapMode aMapMode (mpOutputDevice->GetMapMode());
586         aMapMode.SetOrigin(Point(0,0));
587         mpOutputDevice->SetMapMode(aMapMode);
588         const Rectangle aWindowBox (Point(0,0), maSize);
589         mpOutputDevice->DrawRect(aWindowBox);
590 
591         mpEditEngine->Clear();
592         mpEditEngine->SetText(msText);
593         mpEditEngine->SetPaperSize(maSize);
594 
595         mpEditEngine->Draw(mpOutputDevice, aWindowBox, Point(0,mnTop));
596 
597         const BitmapEx aBitmap (mpOutputDevice->GetBitmapEx(Point(0,0), maSize));
598         mxBitmap = cppcanvas::VCLFactory::getInstance().createBitmap(
599             mpCanvas,
600             aBitmap
601             )->getUNOBitmap();
602     }
603     return mxBitmap;
604 }
605 
606 
607 
608 
609 sal_Int32 PresenterTextView::Implementation::GetTotalHeight (void)
610 {
611     DBG_ASSERT(mpEditEngine!=NULL, "EditEngine missing");
612 
613     if (mnTotalHeight < 0)
614     {
615         if ( ! mxBitmap.is())
616             GetBitmap();
617         mnTotalHeight = mpEditEngine->GetTextHeight();
618     }
619     return mnTotalHeight;
620 }
621 
622 
623 
624 
625 void PresenterTextView::Implementation::CheckTop (void)
626 {
627     DBG_ASSERT(mpEditEngine!=NULL, "EditEngine missing");
628 
629     if (mnTotalHeight < 0)
630         mnTotalHeight = mpEditEngine->GetTextHeight();
631     if (mpEditEngine!=NULL && mnTop >= mnTotalHeight)
632         mnTop = mnTotalHeight - mpEditEngine->GetLineHeight(0,0);
633 
634     if (mnTotalHeight < maSize.Height())
635         mnTop = 0;
636 
637     if (mnTotalHeight - mnTop < maSize.Height())
638         mnTop = mnTotalHeight - maSize.Height();
639 
640     if (mnTop < 0)
641         mnTop = 0;
642 }
643 
644 
645 } } // end of namespace ::sd::presenter
646