1 /***********************************************************************
2     created:    Mon Jun 13 2005
3     author:     Paul D Turner <paul@cegui.org.uk>
4 *************************************************************************/
5 /***************************************************************************
6  *   Copyright (C) 2004 - 2006 Paul D Turner & The CEGUI Development Team
7  *
8  *   Permission is hereby granted, free of charge, to any person obtaining
9  *   a copy of this software and associated documentation files (the
10  *   "Software"), to deal in the Software without restriction, including
11  *   without limitation the rights to use, copy, modify, merge, publish,
12  *   distribute, sublicense, and/or sell copies of the Software, and to
13  *   permit persons to whom the Software is furnished to do so, subject to
14  *   the following conditions:
15  *
16  *   The above copyright notice and this permission notice shall be
17  *   included in all copies or substantial portions of the Software.
18  *
19  *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20  *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21  *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
22  *   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
23  *   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24  *   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25  *   OTHER DEALINGS IN THE SOFTWARE.
26  ***************************************************************************/
27 #include "CEGUI/falagard/ImageryComponent.h"
28 #include "CEGUI/falagard/XMLEnumHelper.h"
29 #include "CEGUI/falagard/XMLHandler.h"
30 #include "CEGUI/Exceptions.h"
31 #include "CEGUI/ImageManager.h"
32 #include "CEGUI/Image.h"
33 #include "CEGUI/PropertyHelper.h"
34 #include "CEGUI/CoordConverter.h"
35 #include <iostream>
36 #include <cstdlib>
37 
38 // void	draw(const Rect& dest_rect, float z, const Rect& clip_rect,const ColourRect& colours);
39 
40 // Start of CEGUI namespace section
41 namespace CEGUI
42 {
ImageryComponent()43     ImageryComponent::ImageryComponent() :
44         d_image(0),
45         d_vertFormatting(VF_TOP_ALIGNED),
46         d_horzFormatting(HF_LEFT_ALIGNED)
47     {}
48 
getImage() const49     const Image* ImageryComponent::getImage() const
50     {
51         return d_image;
52     }
53 
setImage(const Image * image)54     void ImageryComponent::setImage(const Image* image)
55     {
56         d_image = image;
57     }
58 
setImage(const String & name)59     void ImageryComponent::setImage(const String& name)
60     {
61         CEGUI_TRY
62         {
63             d_image = &ImageManager::getSingleton().get(name);
64         }
65         CEGUI_CATCH (UnknownObjectException&)
66         {
67             d_image = 0;
68         }
69     }
70 
getVerticalFormatting(const Window & wnd) const71     VerticalFormatting ImageryComponent::getVerticalFormatting(const Window& wnd) const
72     {
73         return d_vertFormatting.get(wnd);
74     }
75 
getVerticalFormattingFromComponent() const76     VerticalFormatting ImageryComponent::getVerticalFormattingFromComponent() const
77     {
78         return d_vertFormatting.getValue();
79     }
80 
setVerticalFormatting(VerticalFormatting fmt)81     void ImageryComponent::setVerticalFormatting(VerticalFormatting fmt)
82     {
83         d_vertFormatting.set(fmt);
84     }
85 
getHorizontalFormatting(const Window & wnd) const86     HorizontalFormatting ImageryComponent::getHorizontalFormatting(const Window& wnd) const
87     {
88         return d_horzFormatting.get(wnd);
89     }
90 
getHorizontalFormattingFromComponent() const91     HorizontalFormatting ImageryComponent::getHorizontalFormattingFromComponent() const
92     {
93         return d_horzFormatting.getValue();
94     }
95 
setHorizontalFormatting(HorizontalFormatting fmt)96     void ImageryComponent::setHorizontalFormatting(HorizontalFormatting fmt)
97     {
98         d_horzFormatting.set(fmt);
99     }
100 
getHorizontalFormattingPropertySource() const101     const String& ImageryComponent::getHorizontalFormattingPropertySource() const
102     {
103         return d_horzFormatting.getPropertySource();
104     }
105 
setHorizontalFormattingPropertySource(const String & property_name)106     void ImageryComponent::setHorizontalFormattingPropertySource(
107                                                 const String& property_name)
108     {
109         d_horzFormatting.setPropertySource(property_name);
110     }
111 
getVerticalFormattingPropertySource() const112     const String& ImageryComponent::getVerticalFormattingPropertySource() const
113     {
114         return d_vertFormatting.getPropertySource();
115     }
116 
setVerticalFormattingPropertySource(const String & property_name)117     void ImageryComponent::setVerticalFormattingPropertySource(
118                                                 const String& property_name)
119     {
120         d_vertFormatting.setPropertySource(property_name);
121     }
122 
render_impl(Window & srcWindow,Rectf & destRect,const CEGUI::ColourRect * modColours,const Rectf * clipper,bool) const123     void ImageryComponent::render_impl(Window& srcWindow, Rectf& destRect, const CEGUI::ColourRect* modColours, const Rectf* clipper, bool /*clipToDisplay*/) const
124     {
125         // get final image to use.
126         const Image* img = isImageFetchedFromProperty() ?
127             srcWindow.getProperty<Image*>(d_imagePropertyName) :
128             d_image;
129 
130         // do not draw anything if image is not set.
131         if (!img)
132             return;
133 
134         const HorizontalFormatting horzFormatting = d_horzFormatting.get(srcWindow);
135         const VerticalFormatting vertFormatting = d_vertFormatting.get(srcWindow);
136 
137         uint horzTiles, vertTiles;
138         float xpos, ypos;
139 
140         Sizef imgSz(img->getRenderedSize());
141 
142         // calculate final colours to be used
143         ColourRect finalColours;
144         initColoursRect(srcWindow, modColours, finalColours);
145 
146         // calculate initial x co-ordinate and horizontal tile count according to formatting options
147         switch (horzFormatting)
148         {
149             case HF_STRETCHED:
150                 imgSz.d_width = destRect.getWidth();
151                 xpos = destRect.left();
152                 horzTiles = 1;
153                 break;
154 
155             case HF_TILED:
156                 xpos = destRect.left();
157                 horzTiles = std::abs(static_cast<int>(
158                     (destRect.getWidth() + (imgSz.d_width - 1)) / imgSz.d_width));
159                 break;
160 
161             case HF_LEFT_ALIGNED:
162                 xpos = destRect.left();
163                 horzTiles = 1;
164                 break;
165 
166             case HF_CENTRE_ALIGNED:
167                 xpos = destRect.left() + CoordConverter::alignToPixels((destRect.getWidth() - imgSz.d_width) * 0.5f);
168                 horzTiles = 1;
169                 break;
170 
171             case HF_RIGHT_ALIGNED:
172                 xpos = destRect.right() - imgSz.d_width;
173                 horzTiles = 1;
174                 break;
175 
176             default:
177                 CEGUI_THROW(InvalidRequestException(
178                     "An unknown HorizontalFormatting value was specified."));
179         }
180 
181         // calculate initial y co-ordinate and vertical tile count according to formatting options
182         switch (vertFormatting)
183         {
184             case VF_STRETCHED:
185                 imgSz.d_height = destRect.getHeight();
186                 ypos = destRect.top();
187                 vertTiles = 1;
188                 break;
189 
190             case VF_TILED:
191                 ypos = destRect.top();
192                 vertTiles = std::abs(static_cast<int>(
193                     (destRect.getHeight() + (imgSz.d_height - 1)) / imgSz.d_height));
194                 break;
195 
196             case VF_TOP_ALIGNED:
197                 ypos = destRect.top();
198                 vertTiles = 1;
199                 break;
200 
201             case VF_CENTRE_ALIGNED:
202                 ypos = destRect.top() + CoordConverter::alignToPixels((destRect.getHeight() - imgSz.d_height) * 0.5f);
203                 vertTiles = 1;
204                 break;
205 
206             case VF_BOTTOM_ALIGNED:
207                 ypos = destRect.bottom() - imgSz.d_height;
208                 vertTiles = 1;
209                 break;
210 
211             default:
212                 CEGUI_THROW(InvalidRequestException(
213                     "An unknown VerticalFormatting value was specified."));
214         }
215 
216         // perform final rendering (actually is now a caching of the images which will be drawn)
217         Rectf finalRect;
218         Rectf finalClipper;
219         const Rectf* clippingRect;
220         finalRect.top(ypos);
221         finalRect.bottom(ypos + imgSz.d_height);
222 
223         for (uint row = 0; row < vertTiles; ++row)
224         {
225             finalRect.left(xpos);
226             finalRect.right(xpos + imgSz.d_width);
227 
228             for (uint col = 0; col < horzTiles; ++col)
229             {
230                 // use custom clipping for right and bottom edges when tiling the imagery
231                 if (((vertFormatting == VF_TILED) && row == vertTiles - 1) ||
232                     ((horzFormatting == HF_TILED) && col == horzTiles - 1))
233                 {
234                     finalClipper = clipper ? clipper->getIntersection(destRect) : destRect;
235                     clippingRect = &finalClipper;
236                 }
237                 // not tiliing, or not on far edges, just used passed in clipper (if any).
238                 else
239                 {
240                     clippingRect = clipper;
241                 }
242 
243                 // add geometry for image to the target window.
244                 img->render(srcWindow.getGeometryBuffer(), finalRect, clippingRect, finalColours);
245 
246                 finalRect.d_min.d_x += imgSz.d_width;
247                 finalRect.d_max.d_x += imgSz.d_width;
248             }
249 
250             finalRect.d_min.d_y += imgSz.d_height;
251             finalRect.d_max.d_y += imgSz.d_height;
252         }
253     }
254 
writeXMLToStream(XMLSerializer & xml_stream) const255     void ImageryComponent::writeXMLToStream(XMLSerializer& xml_stream) const
256     {
257         // opening tag
258         xml_stream.openTag(Falagard_xmlHandler::ImageryComponentElement);
259         // write out area
260         d_area.writeXMLToStream(xml_stream);
261 
262         // write image
263         if (isImageFetchedFromProperty())
264             xml_stream.openTag(Falagard_xmlHandler::ImagePropertyElement)
265             .attribute(Falagard_xmlHandler::NameAttribute, d_imagePropertyName)
266                 .closeTag();
267         else
268             xml_stream.openTag(Falagard_xmlHandler::ImageElement)
269                 .attribute(Falagard_xmlHandler::NameAttribute, d_image->getName())
270                 .closeTag();
271 
272         // get base class to write colours
273         writeColoursXML(xml_stream);
274 
275         d_vertFormatting.writeXMLToStream(xml_stream);
276         d_horzFormatting.writeXMLToStream(xml_stream);
277 
278         // closing tag
279         xml_stream.closeTag();
280     }
281 
isImageFetchedFromProperty() const282     bool ImageryComponent::isImageFetchedFromProperty() const
283     {
284         return !d_imagePropertyName.empty();
285     }
286 
getImagePropertySource() const287     const String& ImageryComponent::getImagePropertySource() const
288     {
289         return d_imagePropertyName;
290     }
291 
setImagePropertySource(const String & property)292     void ImageryComponent::setImagePropertySource(const String& property)
293     {
294         d_imagePropertyName = property;
295     }
296 
297 } // End of  CEGUI namespace section
298