1 /***********************************************************************
2     created:    Wed Feb 16 2011
3     author:     Paul D Turner <paul@cegui.org.uk>
4 *************************************************************************/
5 /***************************************************************************
6  *   Copyright (C) 2004 - 2011 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/BasicImage.h"
28 #include "CEGUI/GeometryBuffer.h"
29 #include "CEGUI/Texture.h"
30 #include "CEGUI/Vertex.h"
31 #include "CEGUI/ColourRect.h"
32 #include "CEGUI/XMLAttributes.h"
33 #include "CEGUI/System.h" // this being here is a bit nasty IMO
34 #include "CEGUI/CoordConverter.h"
35 
36 // Start of CEGUI namespace section
37 namespace CEGUI
38 {
39 const String ImageTypeAttribute( "type" );
40 const String ImageNameAttribute( "name" );
41 const String ImageTextureAttribute( "texture" );
42 const String ImageXPosAttribute( "xPos" );
43 const String ImageYPosAttribute( "yPos" );
44 const String ImageWidthAttribute( "width" );
45 const String ImageHeightAttribute( "height" );
46 const String ImageXOffsetAttribute( "xOffset" );
47 const String ImageYOffsetAttribute( "yOffset" );
48 const String ImageAutoScaledAttribute( "autoScaled" );
49 const String ImageNativeHorzResAttribute( "nativeHorzRes" );
50 const String ImageNativeVertResAttribute( "nativeVertRes" );
51 
52 //----------------------------------------------------------------------------//
BasicImage(const String & name)53 BasicImage::BasicImage(const String& name) :
54     d_name(name),
55     d_texture(0),
56     d_pixelSize(0, 0),
57     d_area(0.0f, 0.0f, 0.0f, 0.0f),
58     d_pixelOffset(0.0f, 0.0f),
59     d_autoScaled(ASM_Disabled),
60     d_nativeResolution(640, 480),
61     d_scaledSize(0, 0),
62     d_scaledOffset(0, 0)
63 {
64 }
65 
66 //----------------------------------------------------------------------------//
BasicImage(const XMLAttributes & attributes)67 BasicImage::BasicImage(const XMLAttributes& attributes) :
68     d_name(attributes.getValueAsString(ImageNameAttribute)),
69     d_texture(&System::getSingleton().getRenderer()->getTexture(
70               attributes.getValueAsString(ImageTextureAttribute))),
71     d_pixelSize(static_cast<float>(attributes.getValueAsInteger(ImageWidthAttribute, 0)),
72                 static_cast<float>(attributes.getValueAsInteger(ImageHeightAttribute, 0))),
73     d_area(Vector2f(static_cast<float>(attributes.getValueAsInteger(ImageXPosAttribute, 0)),
74                     static_cast<float>(attributes.getValueAsInteger(ImageYPosAttribute, 0))),
75            d_pixelSize),
76     d_pixelOffset(Vector2f(
77         static_cast<float>(attributes.getValueAsInteger(ImageXOffsetAttribute, 0)),
78         static_cast<float>(attributes.getValueAsInteger(ImageYOffsetAttribute, 0)))),
79     d_nativeResolution(Sizef(
80         static_cast<float>(attributes.getValueAsInteger(ImageNativeHorzResAttribute, 640)),
81         static_cast<float>(attributes.getValueAsInteger(ImageNativeVertResAttribute, 480))))
82 {
83     d_autoScaled = PropertyHelper<AutoScaledMode>::fromString(attributes.getValueAsString(ImageAutoScaledAttribute));
84 
85     // force initialisation of the autoscaling fields.
86     updateScaledSizeAndOffset(
87         System::getSingleton().getRenderer()->getDisplaySize());
88 }
89 
90 //----------------------------------------------------------------------------//
BasicImage(const String & name,Texture * texture,const Rectf & pixel_area,const Vector2f & pixel_offset,const AutoScaledMode autoscaled,const Sizef & native_res)91 BasicImage::BasicImage(const String& name, Texture* texture,
92                        const Rectf& pixel_area, const Vector2f& pixel_offset,
93                        const AutoScaledMode autoscaled, const Sizef& native_res) :
94     d_name(name),
95     d_texture(texture),
96     d_pixelSize(pixel_area.getSize()),
97     d_area(pixel_area),
98     d_pixelOffset(pixel_offset),
99     d_autoScaled(autoscaled),
100     d_nativeResolution(native_res)
101 
102 {
103     // force initialisation of the autoscaling fields.
104     updateScaledSizeAndOffset(
105         System::getSingleton().getRenderer()->getDisplaySize());
106 }
107 
108 //----------------------------------------------------------------------------//
setTexture(Texture * texture)109 void BasicImage::setTexture(Texture* texture)
110 {
111     d_texture = texture;
112 }
113 
114 //----------------------------------------------------------------------------//
setArea(const Rectf & pixel_area)115 void BasicImage::setArea(const Rectf& pixel_area)
116 {
117     d_area = pixel_area;
118     d_pixelSize = pixel_area.getSize();
119 
120     if (d_autoScaled != ASM_Disabled)
121         updateScaledSize(
122             System::getSingleton().getRenderer()->getDisplaySize());
123     else
124         d_scaledSize = d_pixelSize;
125 }
126 
127 //----------------------------------------------------------------------------//
setOffset(const Vector2f & pixel_offset)128 void BasicImage::setOffset(const Vector2f& pixel_offset)
129 {
130     d_pixelOffset = pixel_offset;
131 
132     if (d_autoScaled != ASM_Disabled)
133         updateScaledOffset(
134             System::getSingleton().getRenderer()->getDisplaySize());
135     else
136         d_scaledOffset = d_pixelOffset;
137 }
138 
139 //----------------------------------------------------------------------------//
setAutoScaled(const AutoScaledMode autoscaled)140 void BasicImage::setAutoScaled(const AutoScaledMode autoscaled)
141 {
142     d_autoScaled = autoscaled;
143 
144     if (d_autoScaled != ASM_Disabled)
145     {
146         updateScaledSizeAndOffset(
147             System::getSingleton().getRenderer()->getDisplaySize());
148     }
149     else
150     {
151         d_scaledSize = d_pixelSize;
152         d_scaledOffset = d_pixelOffset;
153     }
154 }
155 
156 //----------------------------------------------------------------------------//
setNativeResolution(const Sizef & native_res)157 void BasicImage::setNativeResolution(const Sizef& native_res)
158 {
159     d_nativeResolution = native_res;
160 
161     if (d_autoScaled != ASM_Disabled)
162         updateScaledSizeAndOffset(
163             System::getSingleton().getRenderer()->getDisplaySize());
164 }
165 
166 //----------------------------------------------------------------------------//
getName() const167 const String& BasicImage::getName() const
168 {
169     return d_name;
170 }
171 
172 //----------------------------------------------------------------------------//
getRenderedSize() const173 const Sizef& BasicImage::getRenderedSize() const
174 {
175     return d_scaledSize;
176 }
177 
178 //----------------------------------------------------------------------------//
getRenderedOffset() const179 const Vector2f& BasicImage::getRenderedOffset() const
180 {
181     return d_scaledOffset;
182 }
183 
184 //----------------------------------------------------------------------------//
render(GeometryBuffer & buffer,const Rectf & dest_area,const Rectf * clip_area,const ColourRect & colours) const185 void BasicImage::render(GeometryBuffer& buffer, const Rectf& dest_area,
186                         const Rectf* clip_area, const ColourRect& colours) const
187 {
188     const QuadSplitMode quad_split_mode(TopLeftToBottomRight);
189 
190     Rectf dest(dest_area);
191     // apply rendering offset to the destination Rect
192     dest.offset(d_scaledOffset);
193 
194     // get the rect area that we will actually draw to (i.e. perform clipping)
195     Rectf final_rect(clip_area ? dest.getIntersection(*clip_area) : dest );
196 
197     // check if rect was totally clipped
198     if ((final_rect.getWidth() == 0) || (final_rect.getHeight() == 0))
199         return;
200 
201     // Obtain correct scale values from the texture
202     const Vector2f& scale = d_texture->getTexelScaling();
203     const Vector2f tex_per_pix(d_area.getWidth() / dest.getWidth(), d_area.getHeight() / dest.getHeight());
204 
205     // calculate final, clipped, texture co-ordinates
206     const Rectf tex_rect((d_area.d_min + ((final_rect.d_min - dest.d_min) * tex_per_pix)) * scale,
207                           (d_area.d_max + ((final_rect.d_max - dest.d_max) * tex_per_pix)) * scale);
208 
209     // URGENT FIXME: Shouldn't this be in the hands of the user?
210     final_rect.d_min.d_x = CoordConverter::alignToPixels(final_rect.d_min.d_x);
211     final_rect.d_min.d_y = CoordConverter::alignToPixels(final_rect.d_min.d_y);
212     final_rect.d_max.d_x = CoordConverter::alignToPixels(final_rect.d_max.d_x);
213     final_rect.d_max.d_y = CoordConverter::alignToPixels(final_rect.d_max.d_y);
214 
215     Vertex vbuffer[6];
216 
217     // vertex 0
218     vbuffer[0].position   = Vector3f(final_rect.left(), final_rect.top(), 0.0f);
219     vbuffer[0].colour_val = colours.d_top_left;
220     vbuffer[0].tex_coords = Vector2f(tex_rect.left(), tex_rect.top());
221 
222     // vertex 1
223     vbuffer[1].position   = Vector3f(final_rect.left(), final_rect.bottom(), 0.0f);
224     vbuffer[1].colour_val = colours.d_bottom_left;
225     vbuffer[1].tex_coords = Vector2f(tex_rect.left(), tex_rect.bottom());
226 
227     // vertex 2
228     vbuffer[2].position.d_x   = final_rect.right();
229     vbuffer[2].position.d_z   = 0.0f;
230     vbuffer[2].colour_val     = colours.d_bottom_right;
231     vbuffer[2].tex_coords.d_x = tex_rect.right();
232 
233     // top-left to bottom-right diagonal
234     if (quad_split_mode == TopLeftToBottomRight)
235     {
236         vbuffer[2].position.d_y   = final_rect.bottom();
237         vbuffer[2].tex_coords.d_y = tex_rect.bottom();
238     }
239     // bottom-left to top-right diagonal
240     else
241     {
242         vbuffer[2].position.d_y   = final_rect.top();
243         vbuffer[2].tex_coords.d_y = tex_rect.top();
244     }
245 
246     // vertex 3
247     vbuffer[3].position   = Vector3f(final_rect.right(), final_rect.top(), 0.0f);
248     vbuffer[3].colour_val = colours.d_top_right;
249     vbuffer[3].tex_coords = Vector2f(tex_rect.right(), tex_rect.top());
250 
251     // vertex 4
252     vbuffer[4].position.d_x   = final_rect.left();
253     vbuffer[4].position.d_z   = 0.0f;
254     vbuffer[4].colour_val     = colours.d_top_left;
255     vbuffer[4].tex_coords.d_x = tex_rect.left();
256 
257     // top-left to bottom-right diagonal
258     if (quad_split_mode == TopLeftToBottomRight)
259     {
260         vbuffer[4].position.d_y   = final_rect.top();
261         vbuffer[4].tex_coords.d_y = tex_rect.top();
262     }
263     // bottom-left to top-right diagonal
264     else
265     {
266         vbuffer[4].position.d_y   = final_rect.bottom();
267         vbuffer[4].tex_coords.d_y = tex_rect.bottom();
268     }
269 
270     // vertex 5
271     vbuffer[5].position = Vector3f(final_rect.right(), final_rect.bottom(), 0.0f);
272     vbuffer[5].colour_val= colours.d_bottom_right;
273     vbuffer[5].tex_coords = Vector2f(tex_rect.right(), tex_rect.bottom());
274 
275     buffer.setActiveTexture(d_texture);
276     buffer.appendGeometry(vbuffer, 6);
277 }
278 
279 //----------------------------------------------------------------------------//
notifyDisplaySizeChanged(const Sizef & renderer_display_size)280 void BasicImage::notifyDisplaySizeChanged(const Sizef& renderer_display_size)
281 {
282     //If we use autoscaling of any sort we must update the scaled size and offset
283     if (d_autoScaled != ASM_Disabled)
284         updateScaledSizeAndOffset(renderer_display_size);
285 }
286 
287 //----------------------------------------------------------------------------//
288 
updateScaledSizeAndOffset(const Sizef & renderer_display_size)289 void BasicImage::updateScaledSizeAndOffset(const Sizef& renderer_display_size)
290 {
291     Vector2f scaleFactors;
292 
293     computeScalingFactors(d_autoScaled, renderer_display_size, d_nativeResolution,
294         scaleFactors.d_x, scaleFactors.d_y);
295 
296     d_scaledSize = d_pixelSize * scaleFactors;
297     d_scaledOffset = d_pixelOffset * scaleFactors;
298 }
299 
300 //----------------------------------------------------------------------------//
updateScaledSize(const Sizef & renderer_display_size)301 void BasicImage::updateScaledSize(const Sizef& renderer_display_size)
302 {
303     Vector2f scaleFactors;
304 
305     computeScalingFactors(d_autoScaled, renderer_display_size, d_nativeResolution,
306         scaleFactors.d_x, scaleFactors.d_y);
307 
308     d_scaledSize = d_pixelSize * scaleFactors;
309 }
310 
311 //----------------------------------------------------------------------------//
updateScaledOffset(const Sizef & renderer_display_size)312 void BasicImage::updateScaledOffset(const Sizef& renderer_display_size)
313 {
314     Vector2f scaleFactors;
315 
316     computeScalingFactors(d_autoScaled, renderer_display_size, d_nativeResolution,
317         scaleFactors.d_x, scaleFactors.d_y);
318 
319     d_scaledOffset = d_pixelOffset * scaleFactors;
320 }
321 
322 } // End of  CEGUI namespace section
323 
324