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<string_view> OSDRectangle::getProperties() const
30 {
31  auto result = OSDImageBasedWidget::getProperties();
32  static 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, 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  string val = value.getString().str();
75  if (imageName != val) {
76  if (!val.empty() && !FileOperations::isRegularFile(val)) {
77  throw CommandException("Not a valid image file: ", val);
78  }
79  imageName = val;
81  }
82  } else if (propName == "-bordersize") {
83  float newSize = value.getDouble(interp);
84  if (borderSize != newSize) {
85  borderSize = newSize;
87  }
88  } else if (propName == "-relbordersize") {
89  float newSize = value.getDouble(interp);
90  if (relBorderSize != newSize) {
91  relBorderSize = newSize;
93  }
94  } else if (propName == "-borderrgba") {
95  unsigned newRGBA = value.getInt(interp);
96  if (borderRGBA != newRGBA) {
97  borderRGBA = newRGBA;
99  }
100  } else {
101  OSDImageBasedWidget::setProperty(interp, propName, value);
102  }
103 }
104 
105 void OSDRectangle::getProperty(string_view propName, TclObject& result) const
106 {
107  if (propName == "-w") {
108  result = size[0];
109  } else if (propName == "-h") {
110  result = size[1];
111  } else if (propName == "-relw") {
112  result = relSize[0];
113  } else if (propName == "-relh") {
114  result = relSize[1];
115  } else if (propName == "-scale") {
116  result = scale;
117  } else if (propName == "-image") {
118  result = imageName;
119  } else if (propName == "-bordersize") {
120  result = borderSize;
121  } else if (propName == "-relbordersize") {
122  result = relBorderSize;
123  } else if (propName == "-borderrgba") {
124  result = borderRGBA;
125  } else {
126  OSDImageBasedWidget::getProperty(propName, result);
127  }
128 }
129 
131 {
132  return "rectangle";
133 }
134 
135 bool OSDRectangle::takeImageDimensions() const
136 {
137  return (size == vec2()) && (relSize == vec2());
138 }
139 
140 vec2 OSDRectangle::getSize(const OutputSurface& output) const
141 {
142  if (!imageName.empty() && image && takeImageDimensions()) {
143  return vec2(image->getSize());
144  } else {
145  return (size * float(getScaleFactor(output)) * scale) +
146  (getParent()->getSize(output) * relSize);
147  }
148  //std::cout << "rectangle getWH " << getName() << " " << width << " x " << height << '\n';
149 }
150 
151 uint8_t OSDRectangle::getFadedAlpha() const
152 {
153  return uint8_t(255 * getRecursiveFadeValue());
154 }
155 
156 template <typename IMAGE> std::unique_ptr<BaseImage> OSDRectangle::create(
157  OutputSurface& output)
158 {
159  if (imageName.empty()) {
160  bool constAlpha = hasConstantAlpha();
161  if (constAlpha && ((getRGBA(0) & 0xff) == 0) &&
162  (((borderRGBA & 0xFF) == 0) || (borderSize == 0.0f))) {
163  // optimization: Sometimes it's useful to have a
164  // rectangle that will never be drawn, it only exists
165  // as a parent for sub-widgets. For those cases
166  // creating an IMAGE only wastes memory. So postpone
167  // creating it till alpha changes.
168  return nullptr;
169  }
170  ivec2 iSize = round(getSize(output));
171  float factor = getScaleFactor(output) * scale;
172  int bs = lrintf(factor * borderSize + iSize[0] * relBorderSize);
173  assert(bs >= 0);
174  return std::make_unique<IMAGE>(output, iSize, getRGBA4(), bs, borderRGBA);
175  } else {
176  string file = systemFileContext().resolve(imageName);
177  if (takeImageDimensions()) {
178  float factor = getScaleFactor(output) * scale;
179  return std::make_unique<IMAGE>(output, file, factor);
180  } else {
181  ivec2 iSize = round(getSize(output));
182  return std::make_unique<IMAGE>(output, file, iSize);
183  }
184  }
185 }
186 
187 std::unique_ptr<BaseImage> OSDRectangle::createSDL(OutputSurface& output)
188 {
189  return create<SDLImage>(output);
190 }
191 
192 std::unique_ptr<BaseImage> OSDRectangle::createGL(OutputSurface& output)
193 {
194 #if COMPONENT_GL
195  return create<GLImage>(output);
196 #else
197  (void)&output;
198  return nullptr;
199 #endif
200 }
201 
202 } // namespace openmsx
bool isRegularFile(const Stat &st)
string_view getType() const override
Represents the output window/screen of openMSX.
Definition: Display.hh:31
void invalidateRecursive()
Definition: OSDWidget.cc:306
void setProperty(Interpreter &interp, string_view name, const TclObject &value) override
FileContext systemFileContext()
Definition: FileContext.cc:148
std::unique_ptr< BaseImage > image
string_view getString() const
Definition: TclObject.cc:102
A frame buffer where pixels can be written to.
std::string resolve(string_view filename) const
Definition: FileContext.cc:76
void setProperty(Interpreter &interp, string_view name, const TclObject &value) override
Definition: OSDRectangle.cc:40
std::vector< string_view > getProperties() const override
Definition: OSDRectangle.cc:29
mat4 scale(const vec3 &xyz)
Definition: gl_transform.hh:19
virtual gl::vec2 getSize(const OutputSurface &output) const =0
const uint32_t * getRGBA4() const
void append(Result &)
Definition: stl.hh:354
int getScaleFactor(const OutputSurface &output) const
Definition: OSDWidget.cc:363
Thanks to enen for testing this on a real cartridge:
Definition: Autofire.cc:5
float getRecursiveFadeValue() const override
void getProperty(string_view name, TclObject &result) const override
double getDouble(Interpreter &interp) const
Definition: TclObject.cc:92
OSDWidget * getParent()
Definition: OSDWidget.hh:27
This class implements a (close approximation) of the std::string_view class.
Definition: string_view.hh:16
int getInt(Interpreter &interp) const
Definition: TclObject.cc:72
std::string str() const
Definition: string_view.cc:12
void getProperty(string_view name, TclObject &result) const override
std::vector< string_view > getProperties() const override
vecN< 2, float > vec2
Definition: gl_vec.hh:139
uint32_t getRGBA(uint32_t corner) const
Definition: gl_mat.hh:24