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 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sdext.hxx"
30 
31 #include "PresenterTheme.hxx"
32 #include "PresenterBitmapContainer.hxx"
33 #include "PresenterCanvasHelper.hxx"
34 #include "PresenterComponent.hxx"
35 #include "PresenterConfigurationAccess.hxx"
36 #include "PresenterHelper.hxx"
37 #include <com/sun/star/awt/Point.hpp>
38 #include <com/sun/star/beans/UnknownPropertyException.hpp>
39 #include <com/sun/star/deployment/XPackageInformationProvider.hpp>
40 #include <com/sun/star/drawing/XPresenterHelper.hpp>
41 #include <com/sun/star/lang/IllegalArgumentException.hpp>
42 #include <com/sun/star/rendering/PanoseWeight.hpp>
43 #include <com/sun/star/rendering/XBitmap.hpp>
44 #include <com/sun/star/util/Color.hpp>
45 #include <boost/bind.hpp>
46 #include <map>
47 
48 using namespace ::com::sun::star;
49 using namespace ::com::sun::star::uno;
50 using namespace ::std;
51 using ::rtl::OUString;
52 
53 #define A2S(s) (::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(s)))
54 
55 namespace sdext { namespace presenter {
56 
57 namespace {
58 
59 class BorderSize
60 {
61 public:
62     const static sal_Int32 mnInvalidValue = -10000;
63 
64     BorderSize (void) : mnLeft(mnInvalidValue),
65                         mnTop(mnInvalidValue),
66                         mnRight(mnInvalidValue),
67                         mnBottom(mnInvalidValue) {}
68 
69     sal_Int32 mnLeft;
70     sal_Int32 mnTop;
71     sal_Int32 mnRight;
72     sal_Int32 mnBottom;
73 
74     vector<sal_Int32> ToVector (void)
75     {
76         vector<sal_Int32> aSequence (4);
77         aSequence[0] = mnLeft == mnInvalidValue ? 0 : mnLeft;
78         aSequence[1] = mnTop == mnInvalidValue ? 0 : mnTop;
79         aSequence[2] = mnRight == mnInvalidValue ? 0 : mnRight;
80         aSequence[3] = mnBottom == mnInvalidValue ? 0 : mnBottom;
81         return aSequence;
82     };
83 
84 
85     void Merge (const BorderSize& rBorderSize)
86     {
87         if (mnLeft == mnInvalidValue)
88             mnLeft = rBorderSize.mnLeft;
89         if (mnTop == mnInvalidValue)
90             mnTop = rBorderSize.mnTop;
91         if (mnRight == mnInvalidValue)
92             mnRight = rBorderSize.mnRight;
93         if (mnBottom == mnInvalidValue)
94             mnBottom = rBorderSize.mnBottom;
95     }
96 };
97 
98 
99 /** Reading a theme from the configurations is done in various classes.  The
100     ReadContext gives access to frequently used objects and functions to make
101     the configuration handling easier.
102 */
103 class ReadContext
104 {
105 public:
106     Reference<XComponentContext> mxComponentContext;
107     Reference<rendering::XCanvas> mxCanvas;
108     Reference<drawing::XPresenterHelper> mxPresenterHelper;
109     OUString msBasePath;
110 
111     ReadContext (
112         const Reference<XComponentContext>& rxContext,
113         const Reference<rendering::XCanvas>& rxCanvas);
114     ~ReadContext (void);
115 
116     /** Read data describing a font from the node that can be reached from
117         the given root via the given path.
118         @param rsFontPath
119             May be empty.
120     */
121     static PresenterTheme::SharedFontDescriptor ReadFont (
122         const css::uno::Reference<css::container::XHierarchicalNameAccess>& rxTheme,
123         const ::rtl::OUString& rsFontPath,
124         const PresenterTheme::SharedFontDescriptor& rpDefault);
125     static PresenterTheme::SharedFontDescriptor ReadFont (
126         const Reference<beans::XPropertySet>& rxFontProperties,
127         const PresenterTheme::SharedFontDescriptor& rpDefault);
128 
129     ::boost::shared_ptr<PresenterTheme::Theme> ReadTheme (
130         PresenterConfigurationAccess& rConfiguration,
131         const OUString& rsThemeName);
132 
133     BorderSize ReadBorderSize (const Reference<container::XNameAccess>& rxNode);
134 
135     void SetBitmapSourceExtension (const OUString& rsExtensionName);
136 
137 private:
138     Any GetByName (
139         const Reference<container::XNameAccess>& rxNode,
140         const OUString& rsName) const;
141 };
142 
143 
144 
145 
146 /** A PaneStyle describes how a pane is rendered.
147 */
148 class PaneStyle
149 {
150 public:
151     PaneStyle (void);
152     ~PaneStyle (void);
153 
154     const SharedBitmapDescriptor GetBitmap (const OUString& sBitmapName) const;
155 
156     OUString msStyleName;
157     ::boost::shared_ptr<PaneStyle> mpParentStyle;
158     PresenterTheme::SharedFontDescriptor mpFont;
159     BorderSize maInnerBorderSize;
160     BorderSize maOuterBorderSize;
161     ::boost::shared_ptr<PresenterBitmapContainer> mpBitmaps;
162 
163     PresenterTheme::SharedFontDescriptor GetFont (void) const;
164 
165 private:
166 
167     void UpdateBorderSize (BorderSize& rBorderSize, bool bInner);
168 };
169 
170 typedef ::boost::shared_ptr<PaneStyle> SharedPaneStyle;
171 
172 
173 
174 
175 class PaneStyleContainer : vector<SharedPaneStyle>
176 {
177 public:
178     void Read (
179         ReadContext& rReadContext,
180         const Reference<container::XHierarchicalNameAccess>& rThemeRoot);
181 
182     SharedPaneStyle GetPaneStyle (const OUString& rsStyleName) const;
183 
184 private:
185     void ProcessPaneStyle (
186         ReadContext& rReadContext,
187         const ::rtl::OUString& rsKey,
188         const ::std::vector<css::uno::Any>& rValues);
189 };
190 
191 
192 
193 
194 /** A ViewStyle describes how a view is displayed.
195 */
196 class ViewStyle
197 {
198 public:
199     ViewStyle (void);
200     ~ViewStyle (void);
201 
202     const SharedBitmapDescriptor GetBitmap (const OUString& sBitmapName) const;
203 
204     PresenterTheme::SharedFontDescriptor GetFont (void) const;
205 
206     OUString msStyleName;
207     ::boost::shared_ptr<ViewStyle> mpParentStyle;
208     PresenterTheme::SharedFontDescriptor mpFont;
209     ::boost::shared_ptr<PresenterBitmapContainer> mpBitmaps;
210     SharedBitmapDescriptor mpBackground;
211 };
212 
213 typedef ::boost::shared_ptr<ViewStyle> SharedViewStyle;
214 
215 
216 
217 
218 class ViewStyleContainer : vector<SharedViewStyle>
219 {
220 public:
221     void Read (
222         ReadContext& rReadContext,
223         const Reference<container::XHierarchicalNameAccess>& rThemeRoot);
224 
225     SharedViewStyle GetViewStyle (const OUString& rsStyleName) const;
226 
227 private:
228     void ProcessViewStyle(
229         ReadContext& rReadContext,
230         const Reference<beans::XPropertySet>& rxProperties);
231 };
232 
233 
234 
235 
236 class ViewDescriptor
237 {
238 };
239 typedef ::boost::shared_ptr<ViewDescriptor> SharedViewDescriptor;
240 typedef ::std::vector<SharedViewDescriptor> ViewDescriptorContainer;
241 
242 
243 
244 class StyleAssociationContainer
245 {
246 public:
247     void Read (
248         ReadContext& rReadContext,
249         const Reference<container::XHierarchicalNameAccess>& rThemeRoot);
250 
251     OUString GetStyleName (const OUString& rsResourceName) const;
252 
253 private:
254     typedef map<OUString, OUString> StyleAssociations;
255     StyleAssociations maStyleAssociations;
256 
257     void ProcessStyleAssociation(
258         ReadContext& rReadContext,
259         const ::rtl::OUString& rsKey,
260         const ::std::vector<css::uno::Any>& rValues);
261 };
262 
263 } // end of anonymous namespace
264 
265 
266 class PresenterTheme::Theme
267 {
268 public:
269     Theme (
270         const OUString& rsName,
271         const Reference<container::XHierarchicalNameAccess>& rThemeRoot,
272         const OUString& rsNodeName);
273     ~Theme (void);
274 
275     void Read (
276         PresenterConfigurationAccess& rConfiguration,
277         ReadContext& rReadContext);
278 
279     OUString msThemeName;
280     OUString msConfigurationNodeName;
281     ::boost::shared_ptr<Theme> mpParentTheme;
282     SharedBitmapDescriptor mpBackground;
283     PaneStyleContainer maPaneStyles;
284     ViewStyleContainer maViewStyles;
285     ViewDescriptorContainer maViewDescriptors;
286     StyleAssociationContainer maStyleAssociations;
287     Reference<container::XHierarchicalNameAccess> mxThemeRoot;
288     ::boost::shared_ptr<PresenterBitmapContainer> mpIconContainer;
289     typedef map<rtl::OUString,SharedFontDescriptor> FontContainer;
290     FontContainer maFontContainer;
291 
292     SharedPaneStyle GetPaneStyle (const OUString& rsStyleName) const;
293     SharedViewStyle GetViewStyle (const OUString& rsStyleName) const;
294 
295 private:
296     void ProcessFont(
297         ReadContext& rReadContext,
298         const OUString& rsKey,
299         const Reference<beans::XPropertySet>& rxProperties);
300 };
301 
302 
303 
304 
305 //===== PresenterTheme ========================================================
306 
307 PresenterTheme::PresenterTheme (
308     const css::uno::Reference<css::uno::XComponentContext>& rxContext,
309     const rtl::OUString& rsThemeName,
310     const css::uno::Reference<css::rendering::XCanvas>& rxCanvas)
311     : mxContext(rxContext),
312       msThemeName(rsThemeName),
313       mpTheme(),
314       mpBitmapContainer(),
315       mxCanvas(rxCanvas)
316 {
317     mpTheme = ReadTheme();
318 }
319 
320 
321 
322 
323 PresenterTheme::~PresenterTheme (void)
324 {
325 }
326 
327 
328 
329 
330 void SAL_CALL PresenterTheme::disposing (void)
331 {
332 }
333 
334 
335 
336 
337 ::boost::shared_ptr<PresenterTheme::Theme> PresenterTheme::ReadTheme (void)
338 {
339     ReadContext aReadContext(mxContext, mxCanvas);
340 
341     PresenterConfigurationAccess aConfiguration (
342         mxContext,
343         OUString::createFromAscii("/org.openoffice.Office.extension.PresenterScreen/"),
344         PresenterConfigurationAccess::READ_ONLY);
345 
346     return aReadContext.ReadTheme(aConfiguration, msThemeName);
347 }
348 
349 
350 
351 
352 bool PresenterTheme::HasCanvas (void) const
353 {
354     return mxCanvas.is();
355 }
356 
357 
358 
359 
360 void PresenterTheme::ProvideCanvas (const Reference<rendering::XCanvas>& rxCanvas)
361 {
362     if ( ! mxCanvas.is() && rxCanvas.is())
363     {
364         mxCanvas = rxCanvas;
365         ReadTheme();
366     }
367 }
368 
369 
370 
371 
372 OUString PresenterTheme::GetStyleName (const ::rtl::OUString& rsResourceURL) const
373 {
374     OUString sStyleName;
375     ::boost::shared_ptr<Theme> pTheme (mpTheme);
376     while (sStyleName.getLength()==0 && pTheme.get()!=NULL)
377     {
378         sStyleName = pTheme->maStyleAssociations.GetStyleName(rsResourceURL);
379         pTheme = pTheme->mpParentTheme;
380     }
381     return sStyleName;
382 }
383 
384 
385 
386 
387 ::std::vector<sal_Int32> PresenterTheme::GetBorderSize (
388     const ::rtl::OUString& rsStyleName,
389     const bool bOuter) const
390 {
391     OSL_ASSERT(mpTheme.get() != NULL);
392 
393     SharedPaneStyle pPaneStyle (mpTheme->GetPaneStyle(rsStyleName));
394     if (pPaneStyle.get() != NULL)
395         if (bOuter)
396             return pPaneStyle->maOuterBorderSize.ToVector();
397         else
398             return pPaneStyle->maInnerBorderSize.ToVector();
399     else
400     {
401         return ::std::vector<sal_Int32>(4,0);
402     }
403 }
404 
405 
406 
407 
408 PresenterTheme::SharedFontDescriptor PresenterTheme::ReadFont (
409     const Reference<container::XHierarchicalNameAccess>& rxNode,
410     const OUString& rsFontPath,
411     const PresenterTheme::SharedFontDescriptor& rpDefault)
412 {
413     return ReadContext::ReadFont(rxNode, rsFontPath, rpDefault);
414 }
415 
416 
417 
418 
419 bool PresenterTheme::ConvertToColor (
420     const Any& rColorSequence,
421     sal_uInt32& rColor)
422 {
423     Sequence<sal_Int8> aByteSequence;
424     if (rColorSequence >>= aByteSequence)
425     {
426         const sal_Int32 nByteCount (aByteSequence.getLength());
427         const sal_uInt8* pArray = reinterpret_cast<const sal_uInt8*>(aByteSequence.getConstArray());
428         rColor = 0;
429         for (sal_Int32 nIndex=0; nIndex<nByteCount; ++nIndex)
430         {
431             rColor = (rColor << 8) | *pArray++;
432         }
433         return true;
434     }
435     else
436         return false;
437 }
438 
439 
440 
441 
442 ::boost::shared_ptr<PresenterConfigurationAccess> PresenterTheme::GetNodeForViewStyle (
443     const ::rtl::OUString& rsStyleName,
444     const PresenterConfigurationAccess::WriteMode) const
445 {
446     if (mpTheme.get() == NULL)
447         return ::boost::shared_ptr<PresenterConfigurationAccess>();
448 
449     // Open configuration for writing.
450     ::boost::shared_ptr<PresenterConfigurationAccess> pConfiguration (
451         new PresenterConfigurationAccess(
452             mxContext,
453             OUString::createFromAscii("/org.openoffice.Office.extension.PresenterScreen/"),
454             PresenterConfigurationAccess::READ_WRITE));
455 
456     // Get configuration node for the view style container of the current
457     // theme.
458     if (pConfiguration->GoToChild(
459         A2S("Presenter/Themes/") + mpTheme->msConfigurationNodeName + A2S("/ViewStyles")))
460     {
461         pConfiguration->GoToChild(
462             ::boost::bind(&PresenterConfigurationAccess::IsStringPropertyEqual,
463                 rsStyleName,
464                 A2S("StyleName"),
465                 _2));
466     }
467     return pConfiguration;
468 }
469 
470 
471 
472 
473 ::rtl::OUString PresenterTheme::GetThemeName (void) const
474 {
475     if (mpTheme.get() != NULL)
476         return mpTheme->msThemeName;
477     else
478         return OUString();
479 }
480 
481 
482 
483 
484 SharedBitmapDescriptor PresenterTheme::GetBitmap (
485     const OUString& rsStyleName,
486     const OUString& rsBitmapName) const
487 {
488     if (mpTheme.get() != NULL)
489     {
490         if (rsStyleName.getLength() == 0)
491         {
492             if (rsBitmapName == A2S("Background"))
493             {
494                 ::boost::shared_ptr<Theme> pTheme (mpTheme);
495                 while (pTheme.get()!=NULL && pTheme->mpBackground.get()==NULL)
496                     pTheme = pTheme->mpParentTheme;
497                 if (pTheme.get() != NULL)
498                     return pTheme->mpBackground;
499                 else
500                     return SharedBitmapDescriptor();
501             }
502         }
503         else
504         {
505             SharedPaneStyle pPaneStyle (mpTheme->GetPaneStyle(rsStyleName));
506             if (pPaneStyle.get() != NULL)
507             {
508                 SharedBitmapDescriptor pBitmap (pPaneStyle->GetBitmap(rsBitmapName));
509                 if (pBitmap.get() != NULL)
510                     return pBitmap;
511             }
512 
513             SharedViewStyle pViewStyle (mpTheme->GetViewStyle(rsStyleName));
514             if (pViewStyle.get() != NULL)
515             {
516                 SharedBitmapDescriptor pBitmap (pViewStyle->GetBitmap(rsBitmapName));
517                 if (pBitmap.get() != NULL)
518                     return pBitmap;
519             }
520         }
521     }
522 
523     return SharedBitmapDescriptor();
524 }
525 
526 
527 
528 
529 SharedBitmapDescriptor PresenterTheme::GetBitmap (
530     const OUString& rsBitmapName) const
531 {
532     if (mpTheme.get() != NULL)
533     {
534         if (rsBitmapName == A2S("Background"))
535         {
536             ::boost::shared_ptr<Theme> pTheme (mpTheme);
537             while (pTheme.get()!=NULL && pTheme->mpBackground.get()==NULL)
538                 pTheme = pTheme->mpParentTheme;
539             if (pTheme.get() != NULL)
540                 return pTheme->mpBackground;
541             else
542                 return SharedBitmapDescriptor();
543         }
544         else
545         {
546             if (mpTheme->mpIconContainer.get() != NULL)
547                 return mpTheme->mpIconContainer->GetBitmap(rsBitmapName);
548         }
549     }
550 
551     return SharedBitmapDescriptor();
552 }
553 
554 
555 
556 
557 ::boost::shared_ptr<PresenterBitmapContainer> PresenterTheme::GetBitmapContainer (void) const
558 {
559     if (mpTheme.get() != NULL)
560         return mpTheme->mpIconContainer;
561     else
562         return ::boost::shared_ptr<PresenterBitmapContainer>();
563 }
564 
565 
566 
567 
568 PresenterTheme::SharedFontDescriptor PresenterTheme::GetFont (
569     const OUString& rsStyleName) const
570 {
571     if (mpTheme.get() != NULL)
572     {
573         SharedPaneStyle pPaneStyle (mpTheme->GetPaneStyle(rsStyleName));
574         if (pPaneStyle.get() != NULL)
575             return pPaneStyle->GetFont();
576 
577         SharedViewStyle pViewStyle (mpTheme->GetViewStyle(rsStyleName));
578         if (pViewStyle.get() != NULL)
579             return pViewStyle->GetFont();
580 
581         ::boost::shared_ptr<Theme> pTheme (mpTheme);
582         while (pTheme.get() != NULL)
583         {
584             Theme::FontContainer::const_iterator iFont (pTheme->maFontContainer.find(rsStyleName));
585             if (iFont != pTheme->maFontContainer.end())
586                 return iFont->second;
587 
588             pTheme = pTheme->mpParentTheme;
589         }
590     }
591 
592     return SharedFontDescriptor();
593 }
594 
595 
596 
597 
598 //===== FontDescriptor ========================================================
599 
600 PresenterTheme::FontDescriptor::FontDescriptor (void)
601     : msFamilyName(),
602       msStyleName(),
603       mnSize(12),
604       mnColor(0x00000000),
605       msAnchor(OUString::createFromAscii("Left")),
606       mnXOffset(0),
607       mnYOffset(0)
608 {
609 }
610 
611 
612 
613 
614 PresenterTheme::FontDescriptor::FontDescriptor (
615     const ::boost::shared_ptr<FontDescriptor>& rpDescriptor)
616     : msFamilyName(),
617       msStyleName(),
618       mnSize(12),
619       mnColor(0x00000000),
620       msAnchor(OUString::createFromAscii("Left")),
621       mnXOffset(0),
622       mnYOffset(0)
623 {
624     if (rpDescriptor.get() != NULL)
625     {
626         msFamilyName = rpDescriptor->msFamilyName;
627         msStyleName = rpDescriptor->msStyleName;
628         mnSize = rpDescriptor->mnSize;
629         mnColor = rpDescriptor->mnColor;
630         msAnchor = rpDescriptor->msAnchor;
631         mnXOffset = rpDescriptor->mnXOffset;
632         mnYOffset = rpDescriptor->mnYOffset;
633     }
634 }
635 
636 
637 
638 
639 bool PresenterTheme::FontDescriptor::PrepareFont (
640     const Reference<rendering::XCanvas>& rxCanvas)
641 {
642     if (mxFont.is())
643         return true;
644 
645     if ( ! rxCanvas.is())
646         return false;
647 
648 
649     const double nCellSize (GetCellSizeForDesignSize(rxCanvas, mnSize));
650     mxFont = CreateFont(rxCanvas, nCellSize);
651 
652     return mxFont.is();
653 }
654 
655 
656 
657 
658 Reference<rendering::XCanvasFont> PresenterTheme::FontDescriptor::CreateFont (
659     const Reference<rendering::XCanvas>& rxCanvas,
660     const double nCellSize) const
661 {
662     rendering::FontRequest aFontRequest;
663     aFontRequest.FontDescription.FamilyName = msFamilyName;
664     if (msFamilyName.getLength() == 0)
665         aFontRequest.FontDescription.FamilyName = A2S("Tahoma");
666     aFontRequest.FontDescription.StyleName = msStyleName;
667     aFontRequest.CellSize = nCellSize;
668 
669     // Make an attempt at translating the style name(s)into a corresponding
670     // font description.
671     if (msStyleName == A2S("Bold"))
672         aFontRequest.FontDescription.FontDescription.Weight = rendering::PanoseWeight::HEAVY;
673 
674     return rxCanvas->createFont(
675         aFontRequest,
676         Sequence<beans::PropertyValue>(),
677         geometry::Matrix2D(1,0,0,1));
678 }
679 
680 
681 
682 
683 double PresenterTheme::FontDescriptor::GetCellSizeForDesignSize (
684     const Reference<rendering::XCanvas>& rxCanvas,
685     const double nDesignSize) const
686 {
687     // Use the given design size as initial value in calculating the cell
688     // size.
689     double nCellSize (nDesignSize);
690 
691     if ( ! rxCanvas.is())
692     {
693         // We need the canvas to do the conversion.  Return the design size,
694         // it is the our best guess in this circumstance.
695         return nDesignSize;
696     }
697 
698     Reference<rendering::XCanvasFont> xFont (CreateFont(rxCanvas, nCellSize));
699     if ( ! xFont.is())
700         return nDesignSize;
701 
702     geometry::RealRectangle2D aBox (PresenterCanvasHelper::GetTextBoundingBox (xFont, A2S("X")));
703 
704     const double nAscent (-aBox.Y1);
705     const double nDescent (aBox.Y2);
706     const double nScale = (nAscent+nDescent) / nAscent;
707     return nDesignSize * nScale;
708 }
709 
710 
711 
712 
713 //===== Theme =================================================================
714 
715 PresenterTheme::Theme::Theme (
716     const OUString& rsName,
717     const Reference<container::XHierarchicalNameAccess>& rxThemeRoot,
718     const OUString& rsNodeName)
719     : msThemeName(rsName),
720       msConfigurationNodeName(rsNodeName),
721       mpParentTheme(),
722       maPaneStyles(),
723       maViewStyles(),
724       maStyleAssociations(),
725       mxThemeRoot(rxThemeRoot),
726       mpIconContainer()
727 {
728 }
729 
730 
731 
732 
733 PresenterTheme::Theme::~Theme (void)
734 {
735 }
736 
737 
738 
739 
740 void PresenterTheme::Theme::Read (
741     PresenterConfigurationAccess& rConfiguration,
742     ReadContext& rReadContext)
743 {
744     PresenterConfigurationAccess::GetConfigurationNode(mxThemeRoot, A2S("ThemeName"))
745         >>= msThemeName;
746 
747     // Parent theme name.
748     OUString sParentThemeName;
749     if ((PresenterConfigurationAccess::GetConfigurationNode(mxThemeRoot, A2S("ParentTheme"))
750             >>= sParentThemeName)
751         && sParentThemeName.getLength()>0)
752     {
753         mpParentTheme = rReadContext.ReadTheme(rConfiguration, sParentThemeName);
754     }
755 
756     // Read the extension that contains the bitmaps referenced in this
757     // theme.
758     OUString sBitmapSourceExtension;
759     if ((PresenterConfigurationAccess::GetConfigurationNode(
760         mxThemeRoot, A2S("BitmapSourceExtension")) >>= sBitmapSourceExtension)
761         && sBitmapSourceExtension.getLength()>0)
762     {
763         rReadContext.SetBitmapSourceExtension(sBitmapSourceExtension);
764     }
765     else
766     {
767         rReadContext.SetBitmapSourceExtension(PresenterComponent::gsExtensionIdentifier);
768     }
769 
770     // Background.
771     mpBackground = PresenterBitmapContainer::LoadBitmap(
772         mxThemeRoot,
773         A2S("Background"),
774         rReadContext.mxPresenterHelper,
775         rReadContext.msBasePath,
776         rReadContext.mxCanvas,
777         SharedBitmapDescriptor());
778 
779     // Style associations.
780     maStyleAssociations.Read(rReadContext, mxThemeRoot);
781 
782     // Pane styles.
783     maPaneStyles.Read(rReadContext, mxThemeRoot);
784 
785     // View styles.
786     maViewStyles.Read(rReadContext, mxThemeRoot);
787 
788     // Read bitmaps.
789     mpIconContainer.reset(
790         new PresenterBitmapContainer(
791             Reference<container::XNameAccess>(
792                 PresenterConfigurationAccess::GetConfigurationNode(mxThemeRoot, A2S("Bitmaps")),
793                 UNO_QUERY),
794             mpParentTheme.get()!=NULL
795                 ? mpParentTheme->mpIconContainer
796                 : ::boost::shared_ptr<PresenterBitmapContainer>(),
797             rReadContext.mxComponentContext,
798             rReadContext.mxCanvas,
799             rReadContext.msBasePath));
800 
801     // Read fonts.
802     Reference<container::XNameAccess> xFontNode(
803         PresenterConfigurationAccess::GetConfigurationNode(mxThemeRoot, A2S("Fonts")),
804         UNO_QUERY);
805     PresenterConfigurationAccess::ForAll(
806         xFontNode,
807         ::boost::bind(&PresenterTheme::Theme::ProcessFont,
808             this, ::boost::ref(rReadContext), _1, _2));
809 }
810 
811 
812 
813 
814 SharedPaneStyle PresenterTheme::Theme::GetPaneStyle (const OUString& rsStyleName) const
815 {
816     SharedPaneStyle pPaneStyle (maPaneStyles.GetPaneStyle(rsStyleName));
817     if (pPaneStyle.get() != NULL)
818         return pPaneStyle;
819     else if (mpParentTheme.get() != NULL)
820         return mpParentTheme->GetPaneStyle(rsStyleName);
821     else
822         return SharedPaneStyle();
823 }
824 
825 
826 
827 
828 SharedViewStyle PresenterTheme::Theme::GetViewStyle (const OUString& rsStyleName) const
829 {
830     SharedViewStyle pViewStyle (maViewStyles.GetViewStyle(rsStyleName));
831     if (pViewStyle.get() != NULL)
832         return pViewStyle;
833     else if (mpParentTheme.get() != NULL)
834         return mpParentTheme->GetViewStyle(rsStyleName);
835     else
836         return SharedViewStyle();
837 }
838 
839 
840 
841 
842 void PresenterTheme::Theme::ProcessFont(
843     ReadContext& rReadContext,
844     const OUString& rsKey,
845     const Reference<beans::XPropertySet>& rxProperties)
846 {
847     (void)rReadContext;
848     maFontContainer[rsKey] = ReadContext::ReadFont(rxProperties, SharedFontDescriptor());
849 }
850 
851 
852 
853 
854 namespace {
855 
856 //===== ReadContext ===========================================================
857 
858 ReadContext::ReadContext (
859     const css::uno::Reference<css::uno::XComponentContext>& rxContext,
860     const Reference<rendering::XCanvas>& rxCanvas)
861     : mxComponentContext(rxContext),
862       mxCanvas(rxCanvas),
863       mxPresenterHelper(),
864       msBasePath()
865 {
866     Reference<lang::XMultiComponentFactory> xFactory (rxContext->getServiceManager());
867     if (xFactory.is())
868     {
869         mxPresenterHelper = Reference<drawing::XPresenterHelper>(
870             xFactory->createInstanceWithContext(
871                 OUString::createFromAscii("com.sun.star.comp.Draw.PresenterHelper"),
872                 rxContext),
873             UNO_QUERY_THROW);
874     }
875 
876     // Get base path to bitmaps.
877     SetBitmapSourceExtension(PresenterComponent::gsExtensionIdentifier);
878 }
879 
880 
881 
882 
883 ReadContext::~ReadContext (void)
884 {
885 }
886 
887 
888 
889 
890 PresenterTheme::SharedFontDescriptor ReadContext::ReadFont (
891     const Reference<container::XHierarchicalNameAccess>& rxNode,
892     const OUString& rsFontPath,
893     const PresenterTheme::SharedFontDescriptor& rpDefault)
894 {
895     if ( ! rxNode.is())
896         return PresenterTheme::SharedFontDescriptor();
897 
898     try
899     {
900         Reference<container::XHierarchicalNameAccess> xFont (
901             PresenterConfigurationAccess::GetConfigurationNode(
902                 rxNode,
903                 rsFontPath),
904                 UNO_QUERY_THROW);
905 
906         Reference<beans::XPropertySet> xProperties (xFont, UNO_QUERY_THROW);
907         return ReadFont(xProperties, rpDefault);
908     }
909 	catch (Exception&)
910 	{
911         OSL_ASSERT(false);
912 	}
913 
914     return PresenterTheme::SharedFontDescriptor();
915 }
916 
917 
918 
919 
920 PresenterTheme::SharedFontDescriptor ReadContext::ReadFont (
921     const Reference<beans::XPropertySet>& rxProperties,
922     const PresenterTheme::SharedFontDescriptor& rpDefault)
923 {
924     ::boost::shared_ptr<PresenterTheme::FontDescriptor> pDescriptor (
925         new PresenterTheme::FontDescriptor(rpDefault));
926 
927     PresenterConfigurationAccess::GetProperty(rxProperties, A2S("FamilyName")) >>= pDescriptor->msFamilyName;
928     PresenterConfigurationAccess::GetProperty(rxProperties, A2S("Style")) >>= pDescriptor->msStyleName;
929     PresenterConfigurationAccess::GetProperty(rxProperties, A2S("Size")) >>= pDescriptor->mnSize;
930     PresenterTheme::ConvertToColor(
931         PresenterConfigurationAccess::GetProperty(rxProperties, A2S("Color")),
932         pDescriptor->mnColor);
933     PresenterConfigurationAccess::GetProperty(rxProperties, A2S("Anchor")) >>= pDescriptor->msAnchor;
934     PresenterConfigurationAccess::GetProperty(rxProperties, A2S("XOffset")) >>= pDescriptor->mnXOffset;
935     PresenterConfigurationAccess::GetProperty(rxProperties, A2S("YOffset")) >>= pDescriptor->mnYOffset;
936 
937     return pDescriptor;
938 }
939 
940 
941 
942 
943 Any ReadContext::GetByName (
944     const Reference<container::XNameAccess>& rxNode,
945     const OUString& rsName) const
946 {
947     OSL_ASSERT(rxNode.is());
948     if (rxNode->hasByName(rsName))
949         return rxNode->getByName(rsName);
950     else
951         return Any();
952 }
953 
954 
955 
956 
957 ::boost::shared_ptr<PresenterTheme::Theme> ReadContext::ReadTheme (
958     PresenterConfigurationAccess& rConfiguration,
959     const OUString& rsThemeName)
960 {
961     ::boost::shared_ptr<PresenterTheme::Theme> pTheme;
962 
963     OUString sCurrentThemeName (rsThemeName);
964      if (sCurrentThemeName.getLength() == 0)
965      {
966          // No theme name given.  Look up the CurrentTheme property.
967          rConfiguration.GetConfigurationNode(A2S("Presenter/CurrentTheme")) >>= sCurrentThemeName;
968          if (sCurrentThemeName.getLength() == 0)
969          {
970              // Still no name.  Use "DefaultTheme".
971              sCurrentThemeName = A2S("DefaultTheme");
972          }
973      }
974 
975     Reference<container::XNameAccess> xThemes (
976         rConfiguration.GetConfigurationNode(A2S("Presenter/Themes")),
977         UNO_QUERY);
978     if (xThemes.is())
979     {
980         // Iterate over all themes and search the one with the given name.
981         Sequence<OUString> aKeys (xThemes->getElementNames());
982         for (sal_Int32 nItemIndex=0; nItemIndex<aKeys.getLength(); ++nItemIndex)
983         {
984             const OUString& rsKey (aKeys[nItemIndex]);
985             Reference<container::XHierarchicalNameAccess> xTheme (
986                 xThemes->getByName(rsKey), UNO_QUERY);
987             if (xTheme.is())
988             {
989                 OUString sThemeName;
990                 PresenterConfigurationAccess::GetConfigurationNode(xTheme, A2S("ThemeName"))
991                     >>= sThemeName;
992                 if (sThemeName == sCurrentThemeName)
993                 {
994                     pTheme.reset(new PresenterTheme::Theme(sThemeName,xTheme,rsKey));
995                     break;
996                 }
997             }
998         }
999     }
1000 
1001     if (pTheme.get() != NULL)
1002     {
1003         pTheme->Read(rConfiguration, *this);
1004     }
1005 
1006     return pTheme;
1007 }
1008 
1009 
1010 
1011 
1012 BorderSize ReadContext::ReadBorderSize (const Reference<container::XNameAccess>& rxNode)
1013 {
1014     BorderSize aBorderSize;
1015 
1016     if (rxNode.is())
1017     {
1018         GetByName(rxNode, A2S("Left")) >>= aBorderSize.mnLeft;
1019         GetByName(rxNode, A2S("Top")) >>= aBorderSize.mnTop;
1020         GetByName(rxNode, A2S("Right")) >>= aBorderSize.mnRight;
1021         GetByName(rxNode, A2S("Bottom")) >>= aBorderSize.mnBottom;
1022     }
1023 
1024     return aBorderSize;
1025 }
1026 
1027 
1028 
1029 
1030 void ReadContext::SetBitmapSourceExtension (const OUString& rsExtensionIdentifier)
1031 {
1032     // Get base path to bitmaps.
1033     msBasePath = PresenterComponent::GetBasePath(mxComponentContext, rsExtensionIdentifier);
1034 }
1035 
1036 
1037 
1038 
1039 //===== PaneStyleContainer ====================================================
1040 
1041 void PaneStyleContainer::Read (
1042     ReadContext& rReadContext,
1043     const Reference<container::XHierarchicalNameAccess>& rxThemeRoot)
1044 {
1045     Reference<container::XNameAccess> xPaneStyleList (
1046         PresenterConfigurationAccess::GetConfigurationNode(
1047             rxThemeRoot,
1048             A2S("PaneStyles")),
1049         UNO_QUERY);
1050     if (xPaneStyleList.is())
1051     {
1052         ::std::vector<rtl::OUString> aProperties;
1053         aProperties.reserve(6);
1054         aProperties.push_back(A2S("StyleName"));
1055         aProperties.push_back(A2S("ParentStyle"));
1056         aProperties.push_back(A2S("TitleFont"));
1057         aProperties.push_back(A2S("InnerBorderSize"));
1058         aProperties.push_back(A2S("OuterBorderSize"));
1059         aProperties.push_back(A2S("BorderBitmapList"));
1060         PresenterConfigurationAccess::ForAll(
1061             xPaneStyleList,
1062             aProperties,
1063             ::boost::bind(&PaneStyleContainer::ProcessPaneStyle,
1064                 this, ::boost::ref(rReadContext), _1, _2));
1065     }
1066 }
1067 
1068 
1069 
1070 
1071 void PaneStyleContainer::ProcessPaneStyle(
1072     ReadContext& rReadContext,
1073     const OUString& rsKey,
1074     const ::std::vector<Any>& rValues)
1075 {
1076     (void)rsKey;
1077 
1078     if (rValues.size() != 6)
1079         return;
1080 
1081     ::boost::shared_ptr<PaneStyle> pStyle (new PaneStyle());
1082 
1083     rValues[0] >>= pStyle->msStyleName;
1084 
1085     OUString sParentStyleName;
1086     if (rValues[1] >>= sParentStyleName)
1087     {
1088         // Find parent style.
1089         PaneStyleContainer::const_iterator iStyle;
1090         for (iStyle=begin(); iStyle!=end(); ++iStyle)
1091             if ((*iStyle)->msStyleName.equals(sParentStyleName))
1092             {
1093                 pStyle->mpParentStyle = *iStyle;
1094                 break;
1095             }
1096     }
1097 
1098     Reference<container::XHierarchicalNameAccess> xFontNode (rValues[2], UNO_QUERY);
1099     pStyle->mpFont = rReadContext.ReadFont(
1100         xFontNode, A2S(""), PresenterTheme::SharedFontDescriptor());
1101 
1102     Reference<container::XNameAccess> xInnerBorderSizeNode (rValues[3], UNO_QUERY);
1103     pStyle->maInnerBorderSize = rReadContext.ReadBorderSize(xInnerBorderSizeNode);
1104     Reference<container::XNameAccess> xOuterBorderSizeNode (rValues[4], UNO_QUERY);
1105     pStyle->maOuterBorderSize = rReadContext.ReadBorderSize(xOuterBorderSizeNode);
1106 
1107     if (pStyle->mpParentStyle.get() != NULL)
1108     {
1109         pStyle->maInnerBorderSize.Merge(pStyle->mpParentStyle->maInnerBorderSize);
1110         pStyle->maOuterBorderSize.Merge(pStyle->mpParentStyle->maOuterBorderSize);
1111     }
1112 
1113     if (rReadContext.mxCanvas.is())
1114     {
1115         Reference<container::XNameAccess> xBitmapsNode (rValues[5], UNO_QUERY);
1116         pStyle->mpBitmaps.reset(new PresenterBitmapContainer(
1117             xBitmapsNode,
1118             pStyle->mpParentStyle.get()!=NULL
1119                 ? pStyle->mpParentStyle->mpBitmaps
1120                 : ::boost::shared_ptr<PresenterBitmapContainer>(),
1121             rReadContext.mxComponentContext,
1122             rReadContext.mxCanvas,
1123             rReadContext.msBasePath,
1124             rReadContext.mxPresenterHelper));
1125     }
1126 
1127     push_back(pStyle);
1128 }
1129 
1130 
1131 
1132 
1133 SharedPaneStyle PaneStyleContainer::GetPaneStyle (const OUString& rsStyleName) const
1134 {
1135     const_iterator iEnd (end());
1136     for (const_iterator iStyle=begin(); iStyle!=iEnd; ++iStyle)
1137         if ((*iStyle)->msStyleName == rsStyleName)
1138             return *iStyle;
1139     return SharedPaneStyle();
1140 }
1141 
1142 
1143 
1144 
1145 //===== PaneStyle =============================================================
1146 
1147 PaneStyle::PaneStyle (void)
1148     : msStyleName(),
1149       mpParentStyle(),
1150       mpFont(),
1151       maInnerBorderSize(),
1152       maOuterBorderSize(),
1153       mpBitmaps()
1154 {
1155 }
1156 
1157 
1158 
1159 
1160 PaneStyle::~PaneStyle (void)
1161 {
1162 }
1163 
1164 
1165 
1166 
1167 void PaneStyle::UpdateBorderSize (BorderSize& rBorderSize, bool bInner)
1168 {
1169     if (mpParentStyle.get() != NULL)
1170         mpParentStyle->UpdateBorderSize(rBorderSize, bInner);
1171 
1172     BorderSize& rThisBorderSize (bInner ? maInnerBorderSize : maOuterBorderSize);
1173     if (rThisBorderSize.mnLeft >= 0)
1174         rBorderSize.mnLeft = rThisBorderSize.mnLeft;
1175     if (rThisBorderSize.mnTop >= 0)
1176         rBorderSize.mnTop = rThisBorderSize.mnTop;
1177     if (rThisBorderSize.mnRight >= 0)
1178         rBorderSize.mnRight = rThisBorderSize.mnRight;
1179     if (rThisBorderSize.mnBottom >= 0)
1180         rBorderSize.mnBottom = rThisBorderSize.mnBottom;
1181 }
1182 
1183 
1184 
1185 
1186 const SharedBitmapDescriptor PaneStyle::GetBitmap (const OUString& rsBitmapName) const
1187 {
1188     if (mpBitmaps.get() != NULL)
1189     {
1190         const SharedBitmapDescriptor pBitmap = mpBitmaps->GetBitmap(rsBitmapName);
1191         if (pBitmap.get() != NULL)
1192             return pBitmap;
1193     }
1194 
1195     if (mpParentStyle.get() != NULL)
1196         return mpParentStyle->GetBitmap(rsBitmapName);
1197     else
1198         return SharedBitmapDescriptor();
1199 }
1200 
1201 
1202 
1203 
1204 PresenterTheme::SharedFontDescriptor PaneStyle::GetFont (void) const
1205 {
1206     if (mpFont.get() != NULL)
1207         return mpFont;
1208     else if (mpParentStyle.get() != NULL)
1209         return mpParentStyle->GetFont();
1210     else
1211         return PresenterTheme::SharedFontDescriptor();
1212 }
1213 
1214 
1215 
1216 
1217 //===== ViewStyleContainer ====================================================
1218 
1219 void ViewStyleContainer::Read (
1220     ReadContext& rReadContext,
1221     const Reference<container::XHierarchicalNameAccess>& rxThemeRoot)
1222 {
1223     (void)rReadContext;
1224 
1225     Reference<container::XNameAccess> xViewStyleList (
1226         PresenterConfigurationAccess::GetConfigurationNode(
1227             rxThemeRoot,
1228             A2S("ViewStyles")),
1229         UNO_QUERY);
1230     if (xViewStyleList.is())
1231     {
1232         PresenterConfigurationAccess::ForAll(
1233             xViewStyleList,
1234             ::boost::bind(&ViewStyleContainer::ProcessViewStyle,
1235                 this, ::boost::ref(rReadContext), _2));
1236     }
1237 }
1238 
1239 
1240 
1241 
1242 void ViewStyleContainer::ProcessViewStyle(
1243     ReadContext& rReadContext,
1244     const Reference<beans::XPropertySet>& rxProperties)
1245 {
1246     ::boost::shared_ptr<ViewStyle> pStyle (new ViewStyle());
1247 
1248     PresenterConfigurationAccess::GetProperty(rxProperties, A2S("StyleName"))
1249         >>= pStyle->msStyleName;
1250 
1251     OUString sParentStyleName;
1252     if (PresenterConfigurationAccess::GetProperty(rxProperties, A2S("ParentStyle"))
1253         >>= sParentStyleName)
1254     {
1255         // Find parent style.
1256         ViewStyleContainer::const_iterator iStyle;
1257         for (iStyle=begin(); iStyle!=end(); ++iStyle)
1258             if ((*iStyle)->msStyleName.equals(sParentStyleName))
1259             {
1260                 pStyle->mpParentStyle = *iStyle;
1261                 pStyle->mpFont = (*iStyle)->mpFont;
1262                 pStyle->mpBackground = (*iStyle)->mpBackground;
1263                 break;
1264             }
1265     }
1266 
1267     const OUString sPathToFont; // empty string
1268     Reference<container::XHierarchicalNameAccess> xFontNode (
1269         PresenterConfigurationAccess::GetProperty(rxProperties, A2S("Font")), UNO_QUERY);
1270     PresenterTheme::SharedFontDescriptor pFont (
1271         rReadContext.ReadFont(xFontNode, sPathToFont, PresenterTheme::SharedFontDescriptor()));
1272     if (pFont.get() != NULL)
1273         pStyle->mpFont = pFont;
1274 
1275     Reference<container::XHierarchicalNameAccess> xBackgroundNode (
1276         PresenterConfigurationAccess::GetProperty(rxProperties, A2S("Background")),
1277         UNO_QUERY);
1278     SharedBitmapDescriptor pBackground (PresenterBitmapContainer::LoadBitmap(
1279         xBackgroundNode,
1280         OUString(),
1281         rReadContext.mxPresenterHelper,
1282         rReadContext.msBasePath,
1283         rReadContext.mxCanvas,
1284         SharedBitmapDescriptor()));
1285     if (pBackground.get() != NULL && pBackground->GetNormalBitmap().is())
1286         pStyle->mpBackground = pBackground;
1287 
1288     push_back(pStyle);
1289 }
1290 
1291 
1292 
1293 
1294 SharedViewStyle ViewStyleContainer::GetViewStyle (const OUString& rsStyleName) const
1295 {
1296     const_iterator iEnd (end());
1297     for (const_iterator iStyle=begin(); iStyle!=iEnd; ++iStyle)
1298         if ((*iStyle)->msStyleName == rsStyleName)
1299             return *iStyle;
1300     return SharedViewStyle();
1301 }
1302 
1303 
1304 
1305 
1306 //===== ViewStyle =============================================================
1307 
1308 ViewStyle::ViewStyle (void)
1309     : msStyleName(),
1310       mpParentStyle(),
1311       mpFont(),
1312       mpBackground()
1313 {
1314 }
1315 
1316 
1317 
1318 
1319 ViewStyle::~ViewStyle (void)
1320 {
1321 }
1322 
1323 
1324 
1325 
1326 const SharedBitmapDescriptor ViewStyle::GetBitmap (const OUString& rsBitmapName) const
1327 {
1328     if (rsBitmapName == A2S("Background"))
1329         return mpBackground;
1330     else
1331         return SharedBitmapDescriptor();
1332 }
1333 
1334 
1335 
1336 
1337 PresenterTheme::SharedFontDescriptor ViewStyle::GetFont (void) const
1338 {
1339     if (mpFont.get() != NULL)
1340         return mpFont;
1341     else if (mpParentStyle.get() != NULL)
1342         return mpParentStyle->GetFont();
1343     else
1344         return PresenterTheme::SharedFontDescriptor();
1345 }
1346 
1347 
1348 
1349 
1350 //===== StyleAssociationContainer =============================================
1351 
1352 void StyleAssociationContainer::Read (
1353     ReadContext& rReadContext,
1354     const Reference<container::XHierarchicalNameAccess>& rxThemeRoot)
1355 {
1356     Reference<container::XNameAccess> xStyleAssociationList (
1357         PresenterConfigurationAccess::GetConfigurationNode(
1358             rxThemeRoot,
1359             A2S("StyleAssociations")),
1360         UNO_QUERY);
1361     if (xStyleAssociationList.is())
1362     {
1363         ::std::vector<rtl::OUString> aProperties (2);
1364         aProperties[0] = A2S("ResourceURL");
1365         aProperties[1] = A2S("StyleName");
1366         PresenterConfigurationAccess::ForAll(
1367             xStyleAssociationList,
1368             aProperties,
1369             ::boost::bind(&StyleAssociationContainer::ProcessStyleAssociation,
1370                 this, ::boost::ref(rReadContext), _1, _2));
1371     }
1372 }
1373 
1374 
1375 
1376 
1377 OUString StyleAssociationContainer::GetStyleName (const OUString& rsResourceName) const
1378 {
1379     StyleAssociations::const_iterator iAssociation (maStyleAssociations.find(rsResourceName));
1380     if (iAssociation != maStyleAssociations.end())
1381         return iAssociation->second;
1382     else
1383         return OUString();
1384 }
1385 
1386 
1387 
1388 
1389 void StyleAssociationContainer::ProcessStyleAssociation(
1390     ReadContext& rReadContext,
1391     const OUString& rsKey,
1392     const ::std::vector<Any>& rValues)
1393 {
1394     (void)rReadContext;
1395     (void)rsKey;
1396 
1397     if (rValues.size() != 2)
1398         return;
1399 
1400     OUString sResourceURL;
1401     OUString sStyleName;
1402     if ((rValues[0] >>= sResourceURL)
1403         && (rValues[1] >>= sStyleName))
1404     {
1405         maStyleAssociations[sResourceURL] = sStyleName;
1406     }
1407 }
1408 
1409 
1410 
1411 
1412 } // end of anonymous namespace
1413 
1414 } } // end of namespace ::sdext::presenter
1415