1 /******************************************************************************
2  *  Warmux is a convivial mass murder game.
3  *  Copyright (C) 2001-2011 Warmux Team.
4  *
5  *  This program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2 of the License, or
8  *  (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program; if not, write to the Free Software
17  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
18  ******************************************************************************
19  * Picture widget: A widget containing a picture
20  *****************************************************************************/
21 
22 #include "gui/picture_widget.h"
23 #include "graphic/colors.h"
24 #include "graphic/sprite.h"
25 #include "graphic/video.h"
26 #include "include/app.h"
27 
PictureWidget(const Point2i & _size)28 PictureWidget::PictureWidget(const Point2i & _size)
29   : Widget(_size, false)
30   , disabled(false)
31   , loaded(false)
32   , type(NO_SCALING)
33   , picture_size(0, 0)
34   , spr(NULL)
35 {
36 }
37 
PictureWidget(const Point2i & _size,const std::string & resource_id,ScalingType _type)38 PictureWidget::PictureWidget(const Point2i & _size,
39                              const std::string & resource_id,
40                              ScalingType _type)
41   : Widget(_size, false)
42   , disabled(false)
43   , loaded(false)
44   , name(resource_id)
45   , type(_type)
46   , picture_size(0, 0)
47   , spr(NULL)
48 {
49 }
50 
PictureWidget(const Surface & s,ScalingType type)51 PictureWidget::PictureWidget(const Surface & s, ScalingType type)
52   : Widget(s.GetSize(), false)
53   , disabled(false)
54   , type(type)
55   , spr(NULL)
56 {
57   SetSurface(s, type);
58 }
59 
PictureWidget(Profile * profile,const xmlNode * pictureNode)60 PictureWidget::PictureWidget(Profile * profile,
61                              const xmlNode * pictureNode)
62   : Widget(profile, pictureNode)
63   , disabled(false)
64   , type(NO_SCALING)
65   , spr(NULL)
66 {
67 }
68 
~PictureWidget()69 PictureWidget::~PictureWidget()
70 {
71   if (spr != NULL) {
72     delete spr;
73   }
74 }
75 
76 /*
77   Picture node example :
78   <Picture file="menu/image.png"
79            alpha="false"
80            x="0" y="0"
81            width="100" height="100"
82            scale="true"
83            antialiasing="true" />
84 */
LoadXMLConfiguration()85 bool PictureWidget::LoadXMLConfiguration()
86 {
87   if (NULL == profile || NULL == widgetNode) {
88     //TODO error ... xml attributs not initialized !
89     return false;
90   }
91   XmlReader * xmlFile = profile->GetXMLDocument();
92 
93   std::string file("menu/pic_not_found.png");
94   xmlFile->ReadStringAttr(widgetNode, "file", file);
95 
96   bool activeAlpha = false;
97   xmlFile->ReadBoolAttr(widgetNode, "alpha", activeAlpha);
98 
99   file = profile->relative_path + file;
100   Surface surface(file.c_str());
101 
102   if (!activeAlpha) {
103     surface = surface.DisplayFormat();
104   } else {
105     surface = surface.DisplayFormatAlpha();
106   }
107 
108   ParseXMLGeometry();
109   ParseXMLMisc();
110 
111   bool activeScale = false;
112   xmlFile->ReadBoolAttr(widgetNode, "scale", activeScale);
113 
114   SetSurface(surface, activeScale ? FIT_SCALING : NO_SCALING);
115   return true;
116 }
117 
ApplyScaling(ScalingType t)118 void PictureWidget::ApplyScaling(ScalingType t)
119 {
120   if (spr) {
121     Point2d scale(Double(size.x) / picture_size.x,
122                   Double(size.y) / picture_size.y);
123 
124     if (size.x==0 || size.y==0)
125       return;
126 
127     switch (t) {
128     case NO_SCALING: break;
129     case X_SCALING: spr->Scale(scale.x, 1.0); break;
130     case Y_SCALING: spr->Scale(1.0, scale.x); break;
131     case STRETCH_SCALING: spr->Scale(scale.x, scale.y); break;
132     case FIT_SCALING:
133     default:
134       {
135         Double zoom = std::min(scale.x, scale.y);
136         spr->Scale(zoom, zoom);
137         break;
138       }
139     }
140   }
141 
142   type = t;
143 }
144 
SetSurface(const Surface & s,ScalingType type_)145 void PictureWidget::SetSurface(const Surface & s,
146                                ScalingType type_)
147 {
148   if (NULL != spr) {
149     delete spr;
150   }
151 
152   picture_size = s.GetSize();
153   spr = new Sprite(s);
154   type = type_;
155   loaded = true;
156   // Don't call immediately ApplyScaling(type) to save on rotozooms
157   NeedRedrawing();
158 }
159 
SetNoSurface()160 void PictureWidget::SetNoSurface()
161 {
162   NeedRedrawing();
163 
164   if (NULL != spr) {
165     delete spr;
166   }
167   spr = NULL;
168 }
169 
Draw(const Point2i &)170 void PictureWidget::Draw(const Point2i &/*mousePosition*/)
171 {
172   if (!loaded) {
173     if (name.empty())
174       return;
175     Profile *res = GetResourceManager().LoadXMLProfile("graphism.xml", false);
176     SetSurface(LOAD_RES_IMAGE(name), type);
177 
178     // Needed to set the resizing
179     ApplyScaling(type);
180   }
181 
182   if (NULL == spr) {
183     return;
184   }
185 
186   Surface & surf = GetMainWindow();
187   Point2i pos = GetPicturePosition();
188 
189   spr->Blit(surf, pos);
190 
191   // Draw a transparency mask
192   if (disabled) {
193     surf.BoxColor(Rectanglei(pos, spr->GetSize()), defaultOptionColorBox);
194   }
195 }
196 
GetPicturePosition() const197 Point2i PictureWidget::GetPicturePosition() const
198 {
199   return position + (size - spr->GetSize()) / 2;
200 }
201 
GetScale() const202 Point2f PictureWidget::GetScale() const
203 {
204   return Point2f(spr->GetScaleX().tofloat(), spr->GetScaleY().tofloat());
205 }
206