openMSX
OSDRectangle.cc
Go to the documentation of this file.
1 #include "OSDRectangle.hh"
2 #include "SDLImage.hh"
3 #include "CommandException.hh"
4 #include "FileContext.hh"
5 #include "FileOperations.hh"
6 #include "TclObject.hh"
7 #include "stl.hh"
8 #include "components.hh"
9 #include <cassert>
10 #include <cmath>
11 #include <memory>
12 #if COMPONENT_GL
13 #include "GLImage.hh"
14 #endif
15 
16 using std::string;
17 using std::vector;
18 using namespace gl;
19 
20 namespace openmsx {
21 
22 OSDRectangle::OSDRectangle(Display& display_, const TclObject& name_)
23  : OSDImageBasedWidget(display_, name_)
24  , scale(1.0), borderSize(0.0), relBorderSize(0.0)
25  , borderRGBA(0x000000ff)
26 {
27 }
28 
29 vector<std::string_view> OSDRectangle::getProperties() const
30 {
31  auto result = OSDImageBasedWidget::getProperties();
32  static constexpr const char* const vals[] = {
33  "-w", "-h", "-relw", "-relh", "-scale", "-image",
34  "-bordersize", "-relbordersize", "-borderrgba",
35  };
36  append(result, vals);
37  return result;
38 }
39 
41  Interpreter& interp, std::string_view propName, const TclObject& value)
42 {
43  if (propName == "-w") {
44  float w = value.getDouble(interp);
45  if (size[0] != w) {
46  size[0] = w;
48  }
49  } else if (propName == "-h") {
50  float h = value.getDouble(interp);
51  if (size[1] != h) {
52  size[1] = h;
54  }
55  } else if (propName == "-relw") {
56  float relw = value.getDouble(interp);
57  if (relSize[0] != relw) {
58  relSize[0] = relw;
60  }
61  } else if (propName == "-relh") {
62  float relh = value.getDouble(interp);
63  if (relSize[1] != relh) {
64  relSize[1] = relh;
66  }
67  } else if (propName == "-scale") {
68  float scale2 = value.getDouble(interp);
69  if (scale != scale2) {
70  scale = scale2;
72  }
73  } else if (propName == "-image") {
74  std::string_view val = value.getString();
75  if (imageName != val) {
76  if (!val.empty()) {
77  if (string file = systemFileContext().resolve(val);
79  throw CommandException("Not a valid image file: ", val);
80  }
81  }
82  imageName = val;
84  }
85  } else if (propName == "-bordersize") {
86  float newSize = value.getDouble(interp);
87  if (borderSize != newSize) {
88  borderSize = newSize;
90  }
91  } else if (propName == "-relbordersize") {
92  float newSize = value.getDouble(interp);
93  if (relBorderSize != newSize) {
94  relBorderSize = newSize;
96  }
97  } else if (propName == "-borderrgba") {
98  unsigned newRGBA = value.getInt(interp);
99  if (borderRGBA != newRGBA) {
100  borderRGBA = newRGBA;
101  invalidateLocal();
102  }
103  } else {
104  OSDImageBasedWidget::setProperty(interp, propName, value);
105  }
106 }
107 
108 void OSDRectangle::getProperty(std::string_view propName, TclObject& result) const
109 {
110  if (propName == "-w") {
111  result = size[0];
112  } else if (propName == "-h") {
113  result = size[1];
114  } else if (propName == "-relw") {
115  result = relSize[0];
116  } else if (propName == "-relh") {
117  result = relSize[1];
118  } else if (propName == "-scale") {
119  result = scale;
120  } else if (propName == "-image") {
121  result = imageName;
122  } else if (propName == "-bordersize") {
123  result = borderSize;
124  } else if (propName == "-relbordersize") {
125  result = relBorderSize;
126  } else if (propName == "-borderrgba") {
127  result = borderRGBA;
128  } else {
129  OSDImageBasedWidget::getProperty(propName, result);
130  }
131 }
132 
133 std::string_view OSDRectangle::getType() const
134 {
135  return "rectangle";
136 }
137 
138 bool OSDRectangle::takeImageDimensions() const
139 {
140  return (size == vec2()) && (relSize == vec2());
141 }
142 
143 vec2 OSDRectangle::getSize(const OutputSurface& output) const
144 {
145  if (!imageName.empty() && image && takeImageDimensions()) {
146  return vec2(image->getSize());
147  } else {
148  return (size * float(getScaleFactor(output)) * scale) +
149  (getParent()->getSize(output) * relSize);
150  }
151  //std::cout << "rectangle getWH " << getName() << " " << width << " x " << height << '\n';
152 }
153 
154 uint8_t OSDRectangle::getFadedAlpha() const
155 {
156  return uint8_t(255 * getRecursiveFadeValue());
157 }
158 
159 template<typename IMAGE> std::unique_ptr<BaseImage> OSDRectangle::create(
160  OutputSurface& output)
161 {
162  if (imageName.empty()) {
163  bool constAlpha = hasConstantAlpha();
164  if (constAlpha && ((getRGBA(0) & 0xff) == 0) &&
165  (((borderRGBA & 0xFF) == 0) || (borderSize == 0.0f))) {
166  // optimization: Sometimes it's useful to have a
167  // rectangle that will never be drawn, it only exists
168  // as a parent for sub-widgets. For those cases
169  // creating an IMAGE only wastes memory. So postpone
170  // creating it till alpha changes.
171  return nullptr;
172  }
173  ivec2 iSize = round(getSize(output));
174  float factor = getScaleFactor(output) * scale;
175  int bs = lrintf(factor * borderSize + iSize[0] * relBorderSize);
176  assert(bs >= 0);
177  return std::make_unique<IMAGE>(output, iSize, getRGBA4(), bs, borderRGBA);
178  } else {
179  string file = systemFileContext().resolve(imageName);
180  if (takeImageDimensions()) {
181  float factor = getScaleFactor(output) * scale;
182  return std::make_unique<IMAGE>(output, file, factor);
183  } else {
184  ivec2 iSize = round(getSize(output));
185  return std::make_unique<IMAGE>(output, file, iSize);
186  }
187  }
188 }
189 
190 std::unique_ptr<BaseImage> OSDRectangle::createSDL(OutputSurface& output)
191 {
192  return create<SDLImage>(output);
193 }
194 
195 std::unique_ptr<BaseImage> OSDRectangle::createGL(OutputSurface& output)
196 {
197 #if COMPONENT_GL
198  return create<GLImage>(output);
199 #else
200  (void)&output;
201  return nullptr;
202 #endif
203 }
204 
205 } // namespace openmsx
Represents the output window/screen of openMSX.
Definition: Display.hh:33
std::string resolve(std::string_view filename) const
Definition: FileContext.cc:80
span< const uint32_t, 4 > getRGBA4() const
uint32_t getRGBA(uint32_t corner) const
void setProperty(Interpreter &interp, std::string_view name, const TclObject &value) override
std::vector< std::string_view > getProperties() const override
std::unique_ptr< BaseImage > image
float getRecursiveFadeValue() const override
void getProperty(std::string_view name, TclObject &result) const override
void getProperty(std::string_view name, TclObject &result) const override
std::vector< std::string_view > getProperties() const override
Definition: OSDRectangle.cc:29
void setProperty(Interpreter &interp, std::string_view name, const TclObject &value) override
Definition: OSDRectangle.cc:40
std::string_view getType() const override
int getScaleFactor(const OutputSurface &output) const
Definition: OSDWidget.cc:362
virtual gl::vec2 getSize(const OutputSurface &output) const =0
OSDWidget * getParent()
Definition: OSDWidget.hh:27
void invalidateRecursive()
Definition: OSDWidget.cc:305
double getDouble(Interpreter &interp) const
Definition: TclObject.cc:101
int getInt(Interpreter &interp) const
Definition: TclObject.cc:72
zstring_view getString() const
Definition: TclObject.cc:111
constexpr double round(double x)
Definition: cstd.hh:355
Definition: gl_mat.hh:23
vecN< 2, float > vec2
Definition: gl_vec.hh:139
constexpr mat4 scale(const vec3 &xyz)
Definition: gl_transform.hh:19
bool isRegularFile(const Stat &st)
This file implemented 3 utility functions:
Definition: Autofire.cc:9
const FileContext & systemFileContext()
Definition: FileContext.cc:156