1 #include "BlendedSprite.hpp"
5 #include "Viewport.hpp"
15 Font::Font(const char *src, int size, long index)
16 : handle(TTF_OpenFontIndex(src, size, index)) {
18 throw std::runtime_error(TTF_GetError());
24 TTF_CloseFont(handle);
28 Font::Font(Font &&other) noexcept
29 : handle(other.handle) {
30 other.handle = nullptr;
33 Font &Font::operator =(Font &&other) noexcept {
34 std::swap(handle, other.handle);
39 int Font::Style() const noexcept {
40 return TTF_GetFontStyle(handle);
43 void Font::Style(int s) const noexcept {
44 TTF_SetFontStyle(handle, s);
47 int Font::Outline() const noexcept {
48 return TTF_GetFontOutline(handle);
51 void Font::Outline(int px) noexcept {
52 TTF_SetFontOutline(handle, px);
56 int Font::Hinting() const noexcept {
57 return TTF_GetFontHinting(handle);
60 void Font::Hinting(int h) const noexcept {
61 TTF_SetFontHinting(handle, h);
64 bool Font::Kerning() const noexcept {
65 return TTF_GetFontKerning(handle);
68 void Font::Kerning(bool b) noexcept {
69 TTF_SetFontKerning(handle, b);
73 int Font::Height() const noexcept {
74 return TTF_FontHeight(handle);
77 int Font::Ascent() const noexcept {
78 return TTF_FontAscent(handle);
81 int Font::Descent() const noexcept {
82 return TTF_FontDescent(handle);
85 int Font::LineSkip() const noexcept {
86 return TTF_FontLineSkip(handle);
90 const char *Font::FamilyName() const noexcept {
91 return TTF_FontFaceFamilyName(handle);
94 const char *Font::StyleName() const noexcept {
95 return TTF_FontFaceStyleName(handle);
99 bool Font::HasGlyph(Uint16 c) const noexcept {
100 return TTF_GlyphIsProvided(handle, c);
104 glm::ivec2 Font::TextSize(const char *text) const {
106 if (TTF_SizeUTF8(handle, text, &size.x, &size.y) != 0) {
107 throw std::runtime_error(TTF_GetError());
112 Texture Font::Render(const char *text) const {
118 void Font::Render(const char *text, Texture &tex) const {
119 SDL_Surface *srf = TTF_RenderUTF8_Blended(handle, text, { 0xFF, 0xFF, 0xFF, 0xFF });
121 throw std::runtime_error(TTF_GetError());
124 tex.Data(*srf, false);
126 SDL_FreeSurface(srf);
130 void Format::ReadPixelFormat(const SDL_PixelFormat &fmt) {
131 if (fmt.BytesPerPixel == 4) {
132 if (fmt.Amask == 0xFF) {
133 if (fmt.Rmask == 0xFF00) {
138 type = GL_UNSIGNED_INT_8_8_8_8;
140 if (fmt.Rmask == 0xFF) {
145 type = GL_UNSIGNED_INT_8_8_8_8_REV;
149 if (fmt.Rmask == 0xFF) {
154 type = GL_UNSIGNED_BYTE;
164 glGenTextures(1, &handle);
167 Texture::~Texture() {
169 glDeleteTextures(1, &handle);
173 Texture::Texture(Texture &&other) noexcept
174 : handle(other.handle) {
177 height = other.height;
180 Texture &Texture::operator =(Texture &&other) noexcept {
181 std::swap(handle, other.handle);
183 height = other.height;
188 void Texture::Bind() noexcept {
189 glBindTexture(GL_TEXTURE_2D, handle);
193 bool ispow2(unsigned int i) {
194 // don't care about i == 0 here
195 return !(i & (i - 1));
199 void Texture::Data(const SDL_Surface &srf, bool pad2) noexcept {
201 format.ReadPixelFormat(*srf.format);
203 if (!pad2 || (ispow2(srf.w) && ispow2(srf.h))) {
204 int align = UnpackAlignmentFromPitch(srf.pitch);
206 int pitch = (srf.w * srf.format->BytesPerPixel + align - 1) / align * align;
207 if (srf.pitch - pitch >= align) {
208 UnpackRowLength(srf.pitch / srf.format->BytesPerPixel);
213 Data(srf.w, srf.h, format, srf.pixels);
216 } else if (srf.w > (1 << 30) || srf.h > (1 << 30)) {
218 throw std::runtime_error("texture too large");
221 GLsizei width = 1, height = 1;
222 while (width < srf.w) {
225 while (height < srf.h) {
228 size_t pitch = width * srf.format->BytesPerPixel;
229 size_t size = pitch * height;
230 size_t row_pad = pitch - srf.pitch;
231 std::unique_ptr<unsigned char[]> data(new unsigned char[size]);
232 unsigned char *src = reinterpret_cast<unsigned char *>(srf.pixels);
233 unsigned char *dst = data.get();
234 for (int row = 0; row < srf.h; ++row) {
235 std::memcpy(dst, src, srf.pitch);
238 std::memset(dst, 0, row_pad);
241 std::memset(dst, 0, (height - srf.h) * pitch);
242 UnpackAlignmentFromPitch(pitch);
243 Data(width, height, format, data.get());
249 void Texture::Data(GLsizei w, GLsizei h, const Format &format, GLvoid *data) noexcept {
255 format.format, format.type,
263 void Texture::FilterNearest() noexcept {
264 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
265 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
268 void Texture::FilterLinear() noexcept {
269 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
270 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
273 void Texture::FilterTrilinear() noexcept {
274 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
275 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
276 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
277 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
278 glGenerateMipmap(GL_TEXTURE_2D);
282 void Texture::UnpackAlignment(GLint i) noexcept {
283 glPixelStorei(GL_UNPACK_ALIGNMENT, i);
286 int Texture::UnpackAlignmentFromPitch(int pitch) noexcept {
288 while (pitch % align) {
291 UnpackAlignment(align);
295 void Texture::UnpackRowLength(GLint i) noexcept {
296 glPixelStorei(GL_UNPACK_ROW_LENGTH, i);