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