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 namespace gl;
17 
18 namespace openmsx {
19 
20 OSDRectangle::OSDRectangle(Display& display_, const TclObject& name_)
21  : OSDImageBasedWidget(display_, name_)
22  , scale(1.0), borderSize(0.0), relBorderSize(0.0)
23  , borderRGBA(0x000000ff)
24 {
25 }
26 
28  Interpreter& interp, std::string_view propName, const TclObject& value)
29 {
30  if (propName == "-w") {
31  float w = value.getDouble(interp);
32  if (size[0] != w) {
33  size[0] = w;
35  }
36  } else if (propName == "-h") {
37  float h = value.getDouble(interp);
38  if (size[1] != h) {
39  size[1] = h;
41  }
42  } else if (propName == "-relw") {
43  float relw = value.getDouble(interp);
44  if (relSize[0] != relw) {
45  relSize[0] = relw;
47  }
48  } else if (propName == "-relh") {
49  float relh = value.getDouble(interp);
50  if (relSize[1] != relh) {
51  relSize[1] = relh;
53  }
54  } else if (propName == "-scale") {
55  float scale2 = value.getDouble(interp);
56  if (scale != scale2) {
57  scale = scale2;
59  }
60  } else if (propName == "-image") {
61  std::string_view val = value.getString();
62  if (imageName != val) {
63  if (!val.empty()) {
64  if (auto file = systemFileContext().resolve(val);
66  throw CommandException("Not a valid image file: ", val);
67  }
68  }
69  imageName = val;
71  }
72  } else if (propName == "-bordersize") {
73  float newSize = value.getDouble(interp);
74  if (borderSize != newSize) {
75  borderSize = newSize;
77  }
78  } else if (propName == "-relbordersize") {
79  float newSize = value.getDouble(interp);
80  if (relBorderSize != newSize) {
81  relBorderSize = newSize;
83  }
84  } else if (propName == "-borderrgba") {
85  unsigned newRGBA = value.getInt(interp);
86  if (borderRGBA != newRGBA) {
87  borderRGBA = newRGBA;
89  }
90  } else {
91  OSDImageBasedWidget::setProperty(interp, propName, value);
92  }
93 }
94 
95 void OSDRectangle::getProperty(std::string_view propName, TclObject& result) const
96 {
97  if (propName == "-w") {
98  result = size[0];
99  } else if (propName == "-h") {
100  result = size[1];
101  } else if (propName == "-relw") {
102  result = relSize[0];
103  } else if (propName == "-relh") {
104  result = relSize[1];
105  } else if (propName == "-scale") {
106  result = scale;
107  } else if (propName == "-image") {
108  result = imageName;
109  } else if (propName == "-bordersize") {
110  result = borderSize;
111  } else if (propName == "-relbordersize") {
112  result = relBorderSize;
113  } else if (propName == "-borderrgba") {
114  result = borderRGBA;
115  } else {
116  OSDImageBasedWidget::getProperty(propName, result);
117  }
118 }
119 
120 std::string_view OSDRectangle::getType() const
121 {
122  return "rectangle";
123 }
124 
125 bool OSDRectangle::takeImageDimensions() const
126 {
127  return (size == vec2()) && (relSize == vec2());
128 }
129 
130 vec2 OSDRectangle::getSize(const OutputSurface& output) const
131 {
132  if (!imageName.empty() && image && takeImageDimensions()) {
133  return vec2(image->getSize());
134  } else {
135  return (size * float(getScaleFactor(output)) * scale) +
136  (getParent()->getSize(output) * relSize);
137  }
138  //std::cout << "rectangle getWH " << getName() << " " << width << " x " << height << '\n';
139 }
140 
141 uint8_t OSDRectangle::getFadedAlpha() const
142 {
143  return uint8_t(255 * getRecursiveFadeValue());
144 }
145 
146 template<typename IMAGE> std::unique_ptr<BaseImage> OSDRectangle::create(
147  OutputSurface& output)
148 {
149  if (imageName.empty()) {
150  bool constAlpha = hasConstantAlpha();
151  if (constAlpha && ((getRGBA(0) & 0xff) == 0) &&
152  (((borderRGBA & 0xFF) == 0) || (borderSize == 0.0f))) {
153  // optimization: Sometimes it's useful to have a
154  // rectangle that will never be drawn, it only exists
155  // as a parent for sub-widgets. For those cases
156  // creating an IMAGE only wastes memory. So postpone
157  // creating it till alpha changes.
158  return nullptr;
159  }
160  ivec2 iSize = round(getSize(output));
161  float factor = getScaleFactor(output) * scale;
162  int bs = lrintf(factor * borderSize + iSize[0] * relBorderSize);
163  assert(bs >= 0);
164  return std::make_unique<IMAGE>(output, iSize, getRGBA4(), bs, borderRGBA);
165  } else {
166  auto file = systemFileContext().resolve(imageName);
167  if (takeImageDimensions()) {
168  float factor = getScaleFactor(output) * scale;
169  return std::make_unique<IMAGE>(output, file, factor);
170  } else {
171  ivec2 iSize = round(getSize(output));
172  return std::make_unique<IMAGE>(output, file, iSize);
173  }
174  }
175 }
176 
177 std::unique_ptr<BaseImage> OSDRectangle::createSDL(OutputSurface& output)
178 {
179  return create<SDLImage>(output);
180 }
181 
182 std::unique_ptr<BaseImage> OSDRectangle::createGL(OutputSurface& output)
183 {
184 #if COMPONENT_GL
185  return create<GLImage>(output);
186 #else
187  (void)&output;
188  return nullptr;
189 #endif
190 }
191 
192 } // namespace openmsx
Represents the output window/screen of openMSX.
Definition: Display.hh:33
std::string resolve(std::string_view filename) const
Definition: FileContext.cc:81
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::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
Definition: OSDRectangle.cc:95
void setProperty(Interpreter &interp, std::string_view name, const TclObject &value) override
Definition: OSDRectangle.cc:27
std::string_view getType() const override
int getScaleFactor(const OutputSurface &output) const
Definition: OSDWidget.cc:349
virtual gl::vec2 getSize(const OutputSurface &output) const =0
OSDWidget * getParent()
Definition: OSDWidget.hh:37
void invalidateRecursive()
Definition: OSDWidget.cc:292
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:157