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