OXYGENHUB
◆ main openmsx / src / console / OSDRectangle.cc
4.4 KiB · C++ · last changed chore(): initial commit 1 month ago source blame history raw
1
#include "OSDRectangle.hh"
2
3
#include "CommandException.hh"
4
#include "FileContext.hh"
5
#include "FileOperations.hh"
6
#include "GLImage.hh"
7
#include "TclObject.hh"
8
9
#include "stl.hh"
10
11
#include <cassert>
12
#include <cmath>
13
#include <cstdint>
14
#include <memory>
15
16
using namespace gl;
17
18
namespace openmsx {
19
20
OSDRectangle::OSDRectangle(Display& display_, const TclObject& name_)
21
	: OSDImageBasedWidget(display_, name_)
22
{
23
}
24
25
void OSDRectangle::setProperty(
26
	Interpreter& interp, std::string_view propName, const TclObject& value)
27
{
28
	if (propName == "-w") {
29
		float w = value.getFloat(interp);
30
		if (size.x != w) {
31
			size.x = w;
32
			invalidateRecursive();
33
		}
34
	} else if (propName == "-h") {
35
		float h = value.getFloat(interp);
36
		if (size.y != h) {
37
			size.y = h;
38
			invalidateRecursive();
39
		}
40
	} else if (propName == "-relw") {
41
		float relw = value.getFloat(interp);
42
		if (relSize.x != relw) {
43
			relSize.x = relw;
44
			invalidateRecursive();
45
		}
46
	} else if (propName == "-relh") {
47
		float relh = value.getFloat(interp);
48
		if (relSize.y != relh) {
49
			relSize.y = relh;
50
			invalidateRecursive();
51
		}
52
	} else if (propName == "-scale") {
53
		float scale2 = value.getFloat(interp);
54
		if (scale != scale2) {
55
			scale = scale2;
56
			invalidateRecursive();
57
		}
58
	} else if (propName == "-image") {
59
		std::string_view val = value.getString();
60
		if (imageName != val) {
61
			if (!val.empty()) {
62
				if (auto file = systemFileContext().resolve(val);
63
				    !FileOperations::isRegularFile(file)) {
64
					throw CommandException("Not a valid image file: ", val);
65
				}
66
			}
67
			imageName = val;
68
			invalidateRecursive();
69
		}
70
	} else if (propName == "-bordersize") {
71
		float newSize = value.getFloat(interp);
72
		if (borderSize != newSize) {
73
			borderSize = newSize;
74
			invalidateLocal();
75
		}
76
	} else if (propName == "-relbordersize") {
77
		float newSize = value.getFloat(interp);
78
		if (relBorderSize != newSize) {
79
			relBorderSize = newSize;
80
			invalidateLocal();
81
		}
82
	} else if (propName == "-borderrgba") {
83
		uint32_t newRGBA = value.getInt(interp);
84
		if (borderRGBA != newRGBA) {
85
			borderRGBA = newRGBA;
86
			invalidateLocal();
87
		}
88
	} else {
89
		OSDImageBasedWidget::setProperty(interp, propName, value);
90
	}
91
}
92
93
void OSDRectangle::getProperty(std::string_view propName, TclObject& result) const
94
{
95
	if (propName == "-w") {
96
		result = size.x;
97
	} else if (propName == "-h") {
98
		result = size.y;
99
	} else if (propName == "-relw") {
100
		result = relSize.x;
101
	} else if (propName == "-relh") {
102
		result = relSize.y;
103
	} else if (propName == "-scale") {
104
		result = scale;
105
	} else if (propName == "-image") {
106
		result = imageName;
107
	} else if (propName == "-bordersize") {
108
		result = borderSize;
109
	} else if (propName == "-relbordersize") {
110
		result = relBorderSize;
111
	} else if (propName == "-borderrgba") {
112
		result = borderRGBA;
113
	} else {
114
		OSDImageBasedWidget::getProperty(propName, result);
115
	}
116
}
117
118
std::string_view OSDRectangle::getType() const
119
{
120
	return "rectangle";
121
}
122
123
bool OSDRectangle::takeImageDimensions() const
124
{
125
	return (size == vec2()) && (relSize == vec2());
126
}
127
128
vec2 OSDRectangle::getSize(const OutputSurface& output) const
129
{
130
	if (!imageName.empty() && image && takeImageDimensions()) {
131
		return vec2(image->getSize());
132
	} else {
133
		return (size * float(getScaleFactor(output)) * scale) +
134
		       (getParent()->getSize(output) * relSize);
135
	}
136
}
137
138
uint8_t OSDRectangle::getFadedAlpha() const
139
{
140
	return uint8_t(255 * getRecursiveFadeValue());
141
}
142
143
std::unique_ptr<GLImage> OSDRectangle::create(OutputSurface& output)
144
{
145
	if (imageName.empty()) {
146
		if (hasConstantAlpha() && ((getRGBA(0) & 0xff) == 0) &&
147
		    (((borderRGBA & 0xFF) == 0) || (borderSize == 0.0f))) {
148
			// optimization: Sometimes it's useful to have a
149
			//   rectangle that will never be drawn, it only exists
150
			//   as a parent for sub-widgets. For those cases
151
			//   creating an IMAGE only wastes memory. So postpone
152
			//   creating it till alpha changes.
153
			return nullptr;
154
		}
155
		vec2 sz = getSize(output);
156
		auto factor = narrow<float>(getScaleFactor(output)) * scale;
157
		auto bs = narrow_cast<int>(lrintf(factor * borderSize + sz.x * relBorderSize));
158
		assert(bs >= 0);
159
		return std::make_unique<GLImage>(round(sz), getRGBA4(), bs, borderRGBA);
160
	} else {
161
		auto file = systemFileContext().resolve(imageName);
162
		if (takeImageDimensions()) {
163
			auto factor = narrow<float>(getScaleFactor(output)) * scale;
164
			return std::make_unique<GLImage>(file, factor);
165
		} else {
166
			ivec2 iSize = round(getSize(output));
167
			return std::make_unique<GLImage>(file, iSize);
168
		}
169
	}
170
}
171
172
} // namespace openmsx