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