1 /***********************************************************************
2 created: Mon Jul 18 2005
3 author: Paul D Turner <paul@cegui.org.uk>
4 *************************************************************************/
5 /***************************************************************************
6 * Copyright (C) 2004 - 2012 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/FrameComponent.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/CoordConverter.h"
34 #include <iostream>
35 #include <cstdlib>
36
37 namespace CEGUI
38 {
39
40 //! Default values
41 const HorizontalFormatting FrameComponent::HorizontalFormattingDefault(HF_STRETCHED);
42 const VerticalFormatting FrameComponent::VerticalFormattingDefault(VF_STRETCHED);
43
44 //----------------------------------------------------------------------------//
FrameComponent()45 FrameComponent::FrameComponent() :
46 d_leftEdgeFormatting(VerticalFormattingDefault),
47 d_rightEdgeFormatting(VerticalFormattingDefault),
48 d_topEdgeFormatting(HorizontalFormattingDefault),
49 d_bottomEdgeFormatting(HorizontalFormattingDefault),
50 d_backgroundVertFormatting(VerticalFormattingDefault),
51 d_backgroundHorzFormatting(HorizontalFormattingDefault)
52 {
53 }
54
55 //----------------------------------------------------------------------------//
setLeftEdgeFormatting(VerticalFormatting fmt)56 void FrameComponent::setLeftEdgeFormatting(VerticalFormatting fmt)
57 {
58 d_leftEdgeFormatting.set(fmt);
59 }
60
61 //----------------------------------------------------------------------------//
setRightEdgeFormatting(VerticalFormatting fmt)62 void FrameComponent::setRightEdgeFormatting(VerticalFormatting fmt)
63 {
64 d_rightEdgeFormatting.set(fmt);
65 }
66
67 //----------------------------------------------------------------------------//
setTopEdgeFormatting(HorizontalFormatting fmt)68 void FrameComponent::setTopEdgeFormatting(HorizontalFormatting fmt)
69 {
70 d_topEdgeFormatting.set(fmt);
71 }
72
73 //----------------------------------------------------------------------------//
setBottomEdgeFormatting(HorizontalFormatting fmt)74 void FrameComponent::setBottomEdgeFormatting(HorizontalFormatting fmt)
75 {
76 d_bottomEdgeFormatting.set(fmt);
77 }
78
79 //----------------------------------------------------------------------------//
setBackgroundVerticalFormatting(VerticalFormatting fmt)80 void FrameComponent::setBackgroundVerticalFormatting(VerticalFormatting fmt)
81 {
82 d_backgroundVertFormatting.set(fmt);
83 }
84
85 //----------------------------------------------------------------------------//
setBackgroundHorizontalFormatting(HorizontalFormatting fmt)86 void FrameComponent::setBackgroundHorizontalFormatting(HorizontalFormatting fmt)
87 {
88 d_backgroundHorzFormatting.set(fmt);
89 }
90
91 //----------------------------------------------------------------------------//
setLeftEdgeFormattingPropertySource(const String & property_name)92 void FrameComponent::setLeftEdgeFormattingPropertySource(
93 const String& property_name)
94 {
95 d_leftEdgeFormatting.setPropertySource(property_name);
96 }
97
98 //----------------------------------------------------------------------------//
setRightEdgeFormattingPropertySource(const String & property_name)99 void FrameComponent::setRightEdgeFormattingPropertySource(
100 const String& property_name)
101 {
102 d_rightEdgeFormatting.setPropertySource(property_name);
103 }
104
105 //----------------------------------------------------------------------------//
setTopEdgeFormattingPropertySource(const String & property_name)106 void FrameComponent::setTopEdgeFormattingPropertySource(
107 const String& property_name)
108 {
109 d_topEdgeFormatting.setPropertySource(property_name);
110 }
111
112 //----------------------------------------------------------------------------//
setBottomEdgeFormattingPropertySource(const String & property_name)113 void FrameComponent::setBottomEdgeFormattingPropertySource(
114 const String& property_name)
115 {
116 d_bottomEdgeFormatting.setPropertySource(property_name);
117 }
118
119 //----------------------------------------------------------------------------//
setBackgroundVerticalFormattingPropertySource(const String & property_name)120 void FrameComponent::setBackgroundVerticalFormattingPropertySource(
121 const String& property_name)
122 {
123 d_backgroundVertFormatting.setPropertySource(property_name);
124 }
125
126 //----------------------------------------------------------------------------//
setBackgroundHorizontalFormattingPropertySource(const String & property_name)127 void FrameComponent::setBackgroundHorizontalFormattingPropertySource(
128 const String& property_name)
129 {
130 d_backgroundHorzFormatting.setPropertySource(property_name);
131 }
132
133 //----------------------------------------------------------------------------//
getLeftEdgeFormatting(const Window & wnd) const134 VerticalFormatting FrameComponent::getLeftEdgeFormatting(const Window& wnd) const
135 {
136 return d_leftEdgeFormatting.get(wnd);
137 }
138
139 //----------------------------------------------------------------------------//
getRightEdgeFormatting(const Window & wnd) const140 VerticalFormatting FrameComponent::getRightEdgeFormatting(const Window& wnd) const
141 {
142 return d_rightEdgeFormatting.get(wnd);
143 }
144
145 //----------------------------------------------------------------------------//
getTopEdgeFormatting(const Window & wnd) const146 HorizontalFormatting FrameComponent::getTopEdgeFormatting(const Window& wnd) const
147 {
148 return d_topEdgeFormatting.get(wnd);
149 }
150
151 //----------------------------------------------------------------------------//
getBottomEdgeFormatting(const Window & wnd) const152 HorizontalFormatting FrameComponent::getBottomEdgeFormatting(const Window& wnd) const
153 {
154 return d_bottomEdgeFormatting.get(wnd);
155 }
156
157 //----------------------------------------------------------------------------//
getBackgroundVerticalFormatting(const Window & wnd) const158 VerticalFormatting FrameComponent::getBackgroundVerticalFormatting(
159 const Window& wnd) const
160 {
161 return d_backgroundVertFormatting.get(wnd);
162 }
163
164 //----------------------------------------------------------------------------//
getBackgroundHorizontalFormatting(const Window & wnd) const165 HorizontalFormatting FrameComponent::getBackgroundHorizontalFormatting(
166 const Window& wnd) const
167 {
168 return d_backgroundHorzFormatting.get(wnd);
169 }
170
171 //----------------------------------------------------------------------------//
getImage(FrameImageComponent imageComponent,const Window & wnd) const172 const Image* FrameComponent::getImage(FrameImageComponent imageComponent,
173 const Window& wnd) const
174 {
175 assert(imageComponent < FIC_FRAME_IMAGE_COUNT);
176
177 if (!d_frameImages[imageComponent].d_specified)
178 return 0;
179
180 if (d_frameImages[imageComponent].d_propertyName.empty())
181 return d_frameImages[imageComponent].d_image;
182
183 return wnd.getProperty<Image*>(d_frameImages[imageComponent].d_propertyName);
184 }
185
186 //----------------------------------------------------------------------------//
getImage(FrameImageComponent imageComponent) const187 const Image* FrameComponent::getImage(FrameImageComponent imageComponent) const
188 {
189 assert(imageComponent < FIC_FRAME_IMAGE_COUNT);
190
191 if (!d_frameImages[imageComponent].d_specified)
192 return 0;
193
194 if (d_frameImages[imageComponent].d_propertyName.empty())
195 return d_frameImages[imageComponent].d_image;
196
197 return 0;
198 }
199
200 //----------------------------------------------------------------------------//
setImage(FrameImageComponent part,const Image * image)201 void FrameComponent::setImage(FrameImageComponent part, const Image* image)
202 {
203 assert(part < FIC_FRAME_IMAGE_COUNT);
204
205 d_frameImages[part].d_image = image;
206 d_frameImages[part].d_specified = image != 0;
207 d_frameImages[part].d_propertyName.clear();
208 }
209
210 //----------------------------------------------------------------------------//
setImage(FrameImageComponent part,const String & name)211 void FrameComponent::setImage(FrameImageComponent part, const String& name)
212 {
213 const Image* image;
214 CEGUI_TRY
215 {
216 image = &ImageManager::getSingleton().get(name);
217 }
218 CEGUI_CATCH (UnknownObjectException&)
219 {
220 image = 0;
221 }
222
223 setImage(part, image);
224 }
225
226 //----------------------------------------------------------------------------//
setImagePropertySource(FrameImageComponent part,const String & name)227 void FrameComponent::setImagePropertySource(FrameImageComponent part,
228 const String& name)
229 {
230 assert(part < FIC_FRAME_IMAGE_COUNT);
231
232 d_frameImages[part].d_image = 0;
233 d_frameImages[part].d_specified = !name.empty();
234 d_frameImages[part].d_propertyName = name;
235 }
236
237 //----------------------------------------------------------------------------//
isImageSpecified(FrameImageComponent part) const238 bool FrameComponent::isImageSpecified(FrameImageComponent part) const
239 {
240 assert(part < FIC_FRAME_IMAGE_COUNT);
241
242 return d_frameImages[part].d_specified;
243 }
244
245 //----------------------------------------------------------------------------//
isImageFetchedFromProperty(FrameImageComponent part) const246 bool FrameComponent::isImageFetchedFromProperty(FrameImageComponent part) const
247 {
248 assert(part < FIC_FRAME_IMAGE_COUNT);
249
250 return d_frameImages[part].d_specified &&
251 !d_frameImages[part].d_propertyName.empty();
252 }
253
254 //----------------------------------------------------------------------------//
getImagePropertySource(FrameImageComponent part) const255 const String& FrameComponent::getImagePropertySource(
256 FrameImageComponent part) const
257 {
258 assert(part < FIC_FRAME_IMAGE_COUNT);
259
260 return d_frameImages[part].d_propertyName;
261 }
262
263 //----------------------------------------------------------------------------//
render_impl(Window & srcWindow,Rectf & destRect,const CEGUI::ColourRect * modColours,const Rectf * clipper,bool clipToDisplay) const264 void FrameComponent::render_impl(Window& srcWindow, Rectf& destRect,
265 const CEGUI::ColourRect* modColours,
266 const Rectf* clipper, bool clipToDisplay) const
267 {
268 Rectf backgroundRect(destRect);
269 Rectf finalRect;
270 Sizef imageSize;
271 Vector2f imageOffsets;
272 ColourRect imageColours;
273 float leftfactor, rightfactor, topfactor, bottomfactor;
274 bool calcColoursPerImage;
275
276 // vars we use to track what to do with the side pieces.
277 float topOffset = 0, bottomOffset = 0, leftOffset = 0, rightOffset = 0;
278 float topWidth, bottomWidth, leftHeight, rightHeight;
279 topWidth = bottomWidth = destRect.getWidth();
280 leftHeight = rightHeight = destRect.getHeight();
281
282 // calculate final overall colours to be used
283 ColourRect finalColours;
284 initColoursRect(srcWindow, modColours, finalColours);
285
286 if (finalColours.isMonochromatic())
287 {
288 calcColoursPerImage = false;
289 imageColours = finalColours;
290 }
291 else
292 {
293 calcColoursPerImage = true;
294 }
295
296 // top-left image
297 if (const Image* const componentImage = getImage(FIC_TOP_LEFT_CORNER, srcWindow))
298 {
299 // calculate final destination area
300 imageSize = componentImage->getRenderedSize();
301 imageOffsets = componentImage->getRenderedOffset();
302 finalRect.d_min = destRect.d_min;
303 finalRect.setSize(imageSize);
304 finalRect = destRect.getIntersection(finalRect);
305
306 // update adjustments required to edges do to presence of this element.
307 topOffset += imageSize.d_width + imageOffsets.d_x;
308 leftOffset += imageSize.d_height + imageOffsets.d_y;
309 topWidth -= topOffset;
310 leftHeight -= leftOffset;
311
312 // calculate colours that are to be used to this component image
313 if (calcColoursPerImage)
314 {
315 leftfactor = (finalRect.left() + imageOffsets.d_x) / destRect.getWidth();
316 rightfactor = leftfactor + finalRect.getWidth() / destRect.getWidth();
317 topfactor = (finalRect.top() + imageOffsets.d_y) / destRect.getHeight();
318 bottomfactor = topfactor + finalRect.getHeight() / destRect.getHeight();
319
320 imageColours = finalColours.getSubRectangle( leftfactor, rightfactor, topfactor, bottomfactor);
321 }
322
323 // draw this element.
324 componentImage->render(srcWindow.getGeometryBuffer(), finalRect, clipper, imageColours);
325 }
326
327 // top-right image
328 if (const Image* const componentImage = getImage(FIC_TOP_RIGHT_CORNER, srcWindow))
329 {
330 // calculate final destination area
331 imageSize = componentImage->getRenderedSize();
332 imageOffsets = componentImage->getRenderedOffset();
333 finalRect.left(destRect.right() - imageSize.d_width);
334 finalRect.top(destRect.top());
335 finalRect.setSize(imageSize);
336 finalRect = destRect.getIntersection(finalRect);
337
338 // update adjustments required to edges do to presence of this element.
339 rightOffset += imageSize.d_height + imageOffsets.d_y;
340 topWidth -= imageSize.d_width - imageOffsets.d_x;
341 rightHeight -= rightOffset;
342
343 // calculate colours that are to be used to this component image
344 if (calcColoursPerImage)
345 {
346 leftfactor = (finalRect.left() + imageOffsets.d_x) / destRect.getWidth();
347 rightfactor = leftfactor + finalRect.getWidth() / destRect.getWidth();
348 topfactor = (finalRect.top() + imageOffsets.d_y) / destRect.getHeight();
349 bottomfactor = topfactor + finalRect.getHeight() / destRect.getHeight();
350
351 imageColours = finalColours.getSubRectangle(leftfactor, rightfactor, topfactor, bottomfactor);
352 }
353
354 // draw this element.
355 componentImage->render(srcWindow.getGeometryBuffer(), finalRect, clipper, imageColours);
356 }
357
358 // bottom-left image
359 if (const Image* const componentImage = getImage(FIC_BOTTOM_LEFT_CORNER, srcWindow))
360 {
361 // calculate final destination area
362 imageSize = componentImage->getRenderedSize();
363 imageOffsets = componentImage->getRenderedOffset();
364 finalRect.left(destRect.left());
365 finalRect.top(destRect.bottom() - imageSize.d_height);
366 finalRect.setSize(imageSize);
367 finalRect = destRect.getIntersection(finalRect);
368
369 // update adjustments required to edges do to presence of this element.
370 bottomOffset += imageSize.d_width + imageOffsets.d_x;
371 bottomWidth -= bottomOffset;
372 leftHeight -= imageSize.d_height - imageOffsets.d_y;
373
374 // calculate colours that are to be used to this component image
375 if (calcColoursPerImage)
376 {
377 leftfactor = (finalRect.left() + imageOffsets.d_x) / destRect.getWidth();
378 rightfactor = leftfactor + finalRect.getWidth() / destRect.getWidth();
379 topfactor = (finalRect.top() + imageOffsets.d_y) / destRect.getHeight();
380 bottomfactor = topfactor + finalRect.getHeight() / destRect.getHeight();
381
382 imageColours = finalColours.getSubRectangle(leftfactor, rightfactor, topfactor, bottomfactor);
383 }
384
385 // draw this element.
386 componentImage->render(srcWindow.getGeometryBuffer(), finalRect, clipper, imageColours);
387 }
388
389 // bottom-right image
390 if (const Image* const componentImage = getImage(FIC_BOTTOM_RIGHT_CORNER, srcWindow))
391 {
392 // calculate final destination area
393 imageSize = componentImage->getRenderedSize();
394 imageOffsets = componentImage->getRenderedOffset();
395 finalRect.left(destRect.right() - imageSize.d_width);
396 finalRect.top(destRect.bottom() - imageSize.d_height);
397 finalRect.setSize(imageSize);
398 finalRect = destRect.getIntersection(finalRect);
399
400 // update adjustments required to edges do to presence of this element.
401 bottomWidth -= imageSize.d_width - imageOffsets.d_x;
402 rightHeight -= imageSize.d_height - imageOffsets.d_y;
403
404 // calculate colours that are to be used to this component image
405 if (calcColoursPerImage)
406 {
407 leftfactor = (finalRect.left() + componentImage->getRenderedOffset().d_x) / destRect.getWidth();
408 rightfactor = leftfactor + finalRect.getWidth() / destRect.getWidth();
409 topfactor = (finalRect.top() + componentImage->getRenderedOffset().d_y) / destRect.getHeight();
410 bottomfactor = topfactor + finalRect.getHeight() / destRect.getHeight();
411
412 imageColours = finalColours.getSubRectangle( leftfactor, rightfactor, topfactor, bottomfactor);
413 }
414
415 // draw this element.
416 componentImage->render(srcWindow.getGeometryBuffer(), finalRect, clipper, imageColours);
417 }
418
419 // top image
420 if (const Image* const componentImage = getImage(FIC_TOP_EDGE, srcWindow))
421 {
422 // calculate final destination area
423 imageSize = componentImage->getRenderedSize();
424 finalRect.left(destRect.left() + topOffset);
425 finalRect.right(finalRect.left() + topWidth);
426 finalRect.top(destRect.top());
427 finalRect.bottom(finalRect.top() + imageSize.d_height);
428 finalRect = destRect.getIntersection(finalRect);
429
430 // adjust background area to miss this edge
431 backgroundRect.d_min.d_y += imageSize.d_height + componentImage->getRenderedOffset().d_y;
432
433 // calculate colours that are to be used to this component image
434 if (calcColoursPerImage)
435 {
436 leftfactor = (finalRect.left() + componentImage->getRenderedOffset().d_x) / destRect.getWidth();
437 rightfactor = leftfactor + finalRect.getWidth() / destRect.getWidth();
438 topfactor = (finalRect.top() + componentImage->getRenderedOffset().d_y) / destRect.getHeight();
439 bottomfactor = topfactor + finalRect.getHeight() / destRect.getHeight();
440
441 imageColours = finalColours.getSubRectangle( leftfactor, rightfactor, topfactor, bottomfactor);
442 }
443
444 // draw this element.
445 renderImage(srcWindow.getGeometryBuffer(), componentImage,
446 VF_TOP_ALIGNED, d_topEdgeFormatting.get(srcWindow),
447 finalRect, imageColours, clipper, clipToDisplay);
448 }
449
450 // bottom image
451 if (const Image* const componentImage = getImage(FIC_BOTTOM_EDGE, srcWindow))
452 {
453 // calculate final destination area
454 imageSize = componentImage->getRenderedSize();
455 finalRect.left(destRect.left() + bottomOffset);
456 finalRect.right(finalRect.left() + bottomWidth);
457 finalRect.bottom(destRect.bottom());
458 finalRect.top(finalRect.bottom() - imageSize.d_height);
459 finalRect = destRect.getIntersection (finalRect);
460
461 // adjust background area to miss this edge
462 backgroundRect.d_max.d_y -= imageSize.d_height - componentImage->getRenderedOffset().d_y;
463
464 // calculate colours that are to be used to this component image
465 if (calcColoursPerImage)
466 {
467 leftfactor = (finalRect.left() + componentImage->getRenderedOffset().d_x) / destRect.getWidth();
468 rightfactor = leftfactor + finalRect.getWidth() / destRect.getWidth();
469 topfactor = (finalRect.top() + componentImage->getRenderedOffset().d_y) / destRect.getHeight();
470 bottomfactor = topfactor + finalRect.getHeight() / destRect.getHeight();
471
472 imageColours = finalColours.getSubRectangle(leftfactor, rightfactor, topfactor, bottomfactor);
473 }
474
475 // draw this element.
476 renderImage(srcWindow.getGeometryBuffer(), componentImage,
477 VF_BOTTOM_ALIGNED, d_bottomEdgeFormatting.get(srcWindow),
478 finalRect, imageColours, clipper, clipToDisplay);
479 }
480
481 // left image
482 if (const Image* const componentImage = getImage(FIC_LEFT_EDGE, srcWindow))
483 {
484 // calculate final destination area
485 imageSize = componentImage->getRenderedSize();
486 finalRect.left(destRect.left());
487 finalRect.right(finalRect.left() + imageSize.d_width);
488 finalRect.top(destRect.top() + leftOffset);
489 finalRect.bottom(finalRect.top() + leftHeight);
490 finalRect = destRect.getIntersection(finalRect);
491
492 // adjust background area to miss this edge
493 backgroundRect.d_min.d_x += imageSize.d_width + componentImage->getRenderedOffset().d_x;
494
495 // calculate colours that are to be used to this component image
496 if (calcColoursPerImage)
497 {
498 leftfactor = (finalRect.left() + componentImage->getRenderedOffset().d_x) / destRect.getWidth();
499 rightfactor = leftfactor + finalRect.getWidth() / destRect.getWidth();
500 topfactor = (finalRect.top() + componentImage->getRenderedOffset().d_y) / destRect.getHeight();
501 bottomfactor = topfactor + finalRect.getHeight() / destRect.getHeight();
502
503 imageColours = finalColours.getSubRectangle( leftfactor, rightfactor, topfactor, bottomfactor);
504 }
505
506 // draw this element.
507 renderImage(srcWindow.getGeometryBuffer(), componentImage,
508 d_leftEdgeFormatting.get(srcWindow), HF_LEFT_ALIGNED,
509 finalRect, imageColours, clipper, clipToDisplay);
510 }
511
512 // right image
513 if (const Image* const componentImage = getImage(FIC_RIGHT_EDGE, srcWindow))
514 {
515 // calculate final destination area
516 imageSize = componentImage->getRenderedSize();
517 finalRect.top(destRect.top() + rightOffset);
518 finalRect.bottom(finalRect.top() + rightHeight);
519 finalRect.right(destRect.right());
520 finalRect.left(finalRect.right() - imageSize.d_width);
521 finalRect = destRect.getIntersection (finalRect);
522
523 // adjust background area to miss this edge
524 backgroundRect.d_max.d_x -= imageSize.d_width - componentImage->getRenderedOffset().d_x;
525
526 // calculate colours that are to be used to this component image
527 if (calcColoursPerImage)
528 {
529 leftfactor = (finalRect.left() + componentImage->getRenderedOffset().d_x) / destRect.getWidth();
530 rightfactor = leftfactor + finalRect.getWidth() / destRect.getWidth();
531 topfactor = (finalRect.top() + componentImage->getRenderedOffset().d_y) / destRect.getHeight();
532 bottomfactor = topfactor + finalRect.getHeight() / destRect.getHeight();
533
534 imageColours = finalColours.getSubRectangle( leftfactor, rightfactor, topfactor, bottomfactor);
535 }
536
537 // draw this element.
538 renderImage(srcWindow.getGeometryBuffer(), componentImage,
539 d_rightEdgeFormatting.get(srcWindow), HF_RIGHT_ALIGNED,
540 finalRect, imageColours, clipper, clipToDisplay);
541 }
542
543 if (const Image* const componentImage = getImage(FIC_BACKGROUND, srcWindow))
544 {
545 // calculate colours that are to be used to this component image
546 if (calcColoursPerImage)
547 {
548 leftfactor = (backgroundRect.left() + componentImage->getRenderedOffset().d_x) / destRect.getWidth();
549 rightfactor = leftfactor + backgroundRect.getWidth() / destRect.getWidth();
550 topfactor = (backgroundRect.top() + componentImage->getRenderedOffset().d_y) / destRect.getHeight();
551 bottomfactor = topfactor + backgroundRect.getHeight() / destRect.getHeight();
552
553 imageColours = finalColours.getSubRectangle( leftfactor, rightfactor, topfactor, bottomfactor);
554 }
555
556 const HorizontalFormatting horzFormatting =
557 d_backgroundHorzFormatting.get(srcWindow);
558
559 const VerticalFormatting vertFormatting =
560 d_backgroundVertFormatting.get(srcWindow);
561
562 renderImage(srcWindow.getGeometryBuffer(), componentImage,
563 vertFormatting, horzFormatting,
564 backgroundRect, imageColours, clipper, clipToDisplay);
565 }
566 }
567
568 //----------------------------------------------------------------------------//
renderImage(GeometryBuffer & buffer,const Image * image,VerticalFormatting vertFmt,HorizontalFormatting horzFmt,Rectf & destRect,const ColourRect & colours,const Rectf * clipper,bool) const569 void FrameComponent::renderImage(GeometryBuffer& buffer, const Image* image,
570 VerticalFormatting vertFmt,
571 HorizontalFormatting horzFmt,
572 Rectf& destRect, const ColourRect& colours,
573 const Rectf* clipper, bool /*clipToDisplay*/) const
574 {
575 uint horzTiles, vertTiles;
576 float xpos, ypos;
577
578 Sizef imgSz(image->getRenderedSize());
579
580 // calculate initial x co-ordinate and horizontal tile count according to formatting options
581 switch (horzFmt)
582 {
583 case HF_STRETCHED:
584 imgSz.d_width = destRect.getWidth();
585 xpos = destRect.left();
586 horzTiles = 1;
587 break;
588
589 case HF_TILED:
590 xpos = destRect.left();
591 horzTiles = std::abs(static_cast<int>(
592 (destRect.getWidth() + (imgSz.d_width - 1)) / imgSz.d_width));
593 break;
594
595 case HF_LEFT_ALIGNED:
596 xpos = destRect.left();
597 horzTiles = 1;
598 break;
599
600 case HF_CENTRE_ALIGNED:
601 xpos = destRect.left() + CoordConverter::alignToPixels((destRect.getWidth() - imgSz.d_width) * 0.5f);
602 horzTiles = 1;
603 break;
604
605 case HF_RIGHT_ALIGNED:
606 xpos = destRect.right() - imgSz.d_width;
607 horzTiles = 1;
608 break;
609
610 default:
611 CEGUI_THROW(InvalidRequestException(
612 "An unknown HorizontalFormatting value was specified."));
613 }
614
615 // calculate initial y co-ordinate and vertical tile count according to formatting options
616 switch (vertFmt)
617 {
618 case VF_STRETCHED:
619 imgSz.d_height = destRect.getHeight();
620 ypos = destRect.top();
621 vertTiles = 1;
622 break;
623
624 case VF_TILED:
625 ypos = destRect.top();
626 vertTiles = std::abs(static_cast<int>(
627 (destRect.getHeight() + (imgSz.d_height - 1)) / imgSz.d_height));
628 break;
629
630 case VF_TOP_ALIGNED:
631 ypos = destRect.top();
632 vertTiles = 1;
633 break;
634
635 case VF_CENTRE_ALIGNED:
636 ypos = destRect.top() + CoordConverter::alignToPixels((destRect.getHeight() - imgSz.d_height) * 0.5f);
637 vertTiles = 1;
638 break;
639
640 case VF_BOTTOM_ALIGNED:
641 ypos = destRect.bottom() - imgSz.d_height;
642 vertTiles = 1;
643 break;
644
645 default:
646 CEGUI_THROW(InvalidRequestException(
647 "An unknown VerticalFormatting value was specified."));
648 }
649
650 // perform final rendering (actually is now a caching of the images which will be drawn)
651 Rectf finalRect;
652 Rectf finalClipper;
653 const Rectf* clippingRect;
654 finalRect.d_min.d_y = ypos;
655 finalRect.d_max.d_y = ypos + imgSz.d_height;
656
657 for (uint row = 0; row < vertTiles; ++row)
658 {
659 finalRect.d_min.d_x = xpos;
660 finalRect.d_max.d_x = xpos + imgSz.d_width;
661
662 for (uint col = 0; col < horzTiles; ++col)
663 {
664 // use custom clipping for right and bottom edges when tiling the imagery
665 if (((vertFmt == VF_TILED) && row == vertTiles - 1) ||
666 ((horzFmt == HF_TILED) && col == horzTiles - 1))
667 {
668 finalClipper = clipper ? clipper->getIntersection(destRect) : destRect;
669 clippingRect = &finalClipper;
670 }
671 // not tiliing, or not on far edges, just used passed in clipper (if any).
672 else
673 clippingRect = clipper;
674
675 image->render(buffer, finalRect, clippingRect, colours);
676
677 finalRect.d_min.d_x += imgSz.d_width;
678 finalRect.d_max.d_x += imgSz.d_width;
679 }
680
681 finalRect.d_min.d_y += imgSz.d_height;
682 finalRect.d_max.d_y += imgSz.d_height;
683 }
684 }
685
686 //----------------------------------------------------------------------------//
writeXMLToStream(XMLSerializer & xml_stream) const687 void FrameComponent::writeXMLToStream(XMLSerializer& xml_stream) const
688 {
689 // opening tag
690 xml_stream.openTag(Falagard_xmlHandler::FrameComponentElement);
691 // write out area
692 d_area.writeXMLToStream(xml_stream);
693
694 // write images
695 for (int i = 0; i < FIC_FRAME_IMAGE_COUNT; ++i)
696 {
697 if (d_frameImages[i].d_specified)
698 {
699 if (d_frameImages[i].d_propertyName.empty())
700 xml_stream.openTag(Falagard_xmlHandler::ImageElement)
701 .attribute(Falagard_xmlHandler::ComponentAttribute, FalagardXMLHelper<FrameImageComponent>::toString(static_cast<FrameImageComponent>(i)))
702 .attribute(Falagard_xmlHandler::NameAttribute, d_frameImages[i].d_image->getName())
703 .closeTag();
704 else
705 xml_stream.openTag(Falagard_xmlHandler::ImagePropertyElement)
706 .attribute(Falagard_xmlHandler::ComponentAttribute, FalagardXMLHelper<FrameImageComponent>::toString(static_cast<FrameImageComponent>(i)))
707 .attribute(Falagard_xmlHandler::NameAttribute, d_frameImages[i].d_propertyName)
708 .closeTag();
709 }
710 }
711
712 // get base class to write colours
713 writeColoursXML(xml_stream);
714
715 if(d_leftEdgeFormatting.getValue() != VerticalFormattingDefault)
716 {
717 d_leftEdgeFormatting.writeXMLTagToStream(xml_stream);
718 xml_stream.attribute(Falagard_xmlHandler::ComponentAttribute, FalagardXMLHelper<FrameImageComponent>::LeftEdge);
719 d_leftEdgeFormatting.writeXMLAttributesToStream(xml_stream);
720 xml_stream.closeTag();
721 }
722
723 if(d_rightEdgeFormatting.getValue() != VerticalFormattingDefault)
724 {
725 d_rightEdgeFormatting.writeXMLTagToStream(xml_stream);
726 xml_stream.attribute(Falagard_xmlHandler::ComponentAttribute, FalagardXMLHelper<FrameImageComponent>::RightEdge);
727 d_rightEdgeFormatting.writeXMLAttributesToStream(xml_stream);
728 xml_stream.closeTag();
729 }
730
731 if(d_backgroundHorzFormatting.getValue() != HorizontalFormattingDefault)
732 {
733 d_backgroundHorzFormatting.writeXMLTagToStream(xml_stream);
734 xml_stream.attribute(Falagard_xmlHandler::ComponentAttribute, FalagardXMLHelper<FrameImageComponent>::Background);
735 d_backgroundHorzFormatting.writeXMLAttributesToStream(xml_stream);
736 xml_stream.closeTag();
737 }
738
739 if(d_topEdgeFormatting.getValue() != HorizontalFormattingDefault)
740 {
741 d_topEdgeFormatting.writeXMLTagToStream(xml_stream);
742 xml_stream.attribute(Falagard_xmlHandler::ComponentAttribute, FalagardXMLHelper<FrameImageComponent>::TopEdge);
743 d_topEdgeFormatting.writeXMLAttributesToStream(xml_stream);
744 xml_stream.closeTag();
745 }
746
747 if(d_bottomEdgeFormatting.getValue() != HorizontalFormattingDefault)
748 {
749 d_bottomEdgeFormatting.writeXMLTagToStream(xml_stream);
750 xml_stream.attribute(Falagard_xmlHandler::ComponentAttribute, FalagardXMLHelper<FrameImageComponent>::BottomEdge);
751 d_bottomEdgeFormatting.writeXMLAttributesToStream(xml_stream);
752 xml_stream.closeTag();
753 }
754
755 if(d_backgroundVertFormatting.getValue() != VerticalFormattingDefault)
756 {
757 d_backgroundVertFormatting.writeXMLTagToStream(xml_stream);
758 xml_stream.attribute(Falagard_xmlHandler::ComponentAttribute, FalagardXMLHelper<FrameImageComponent>::Background);
759 d_backgroundVertFormatting.writeXMLAttributesToStream(xml_stream);
760 xml_stream.closeTag();
761 }
762
763 // closing tag
764 xml_stream.closeTag();
765 }
766
767 //----------------------------------------------------------------------------//
operator ==(const FrameComponent & rhs) const768 bool FrameComponent::operator==(const FrameComponent& rhs) const
769 {
770 if (d_backgroundVertFormatting != rhs.d_backgroundVertFormatting ||
771 d_backgroundHorzFormatting != rhs.d_backgroundHorzFormatting)
772 return false;
773
774 for (int i = 0; i < FIC_FRAME_IMAGE_COUNT; ++i)
775 if (d_frameImages[i] != rhs.d_frameImages[i])
776 return false;
777
778 return true;
779 }
780
781 //----------------------------------------------------------------------------//
782
783 }
784
785