1/**
2 * Copyright (c) 2006-2023 LOVE Development Team
3 *
4 * This software is provided 'as-is', without any express or implied
5 * warranty. In no event will the authors be held liable for any damages
6 * arising from the use of this software.
7 *
8 * Permission is granted to anyone to use this software for any purpose,
9 * including commercial applications, and to alter it and redistribute it
10 * freely, subject to the following restrictions:
11 *
12 * 1. The origin of this software must not be misrepresented; you must not
13 * claim that you wrote the original software. If you use this software
14 * in a product, an acknowledgment in the product documentation would be
15 * appreciated but is not required.
16 * 2. Altered source versions must be plainly marked as such, and must not be
17 * misrepresented as being the original software.
18 * 3. This notice may not be removed or altered from any source distribution.
19 **/
20
21#include "wrap_Image.h"
22#include "data/wrap_Data.h"
23#include "common/Data.h"
24#include "common/StringMap.h"
25
26#include "Image.h"
27
28#include "filesystem/wrap_Filesystem.h"
29
30namespace love
31{
32namespace image
33{
34
35#define instance() (Module::getInstance<Image>(Module::M_IMAGE))
36
37int w_newImageData(lua_State *L)
38{
39 // Case 1: width & height.
40 if (lua_isnumber(L, 1))
41 {
42 int w = (int) luaL_checkinteger(L, 1);
43 int h = (int) luaL_checkinteger(L, 2);
44 if (w <= 0 || h <= 0)
45 return luaL_error(L, "Invalid image size.");
46
47 PixelFormat format = PIXELFORMAT_RGBA8;
48
49 if (!lua_isnoneornil(L, 3))
50 {
51 const char *fstr = luaL_checkstring(L, 3);
52 if (!getConstant(fstr, format))
53 return luax_enumerror(L, "pixel format", fstr);
54 }
55
56 size_t numbytes = 0;
57 const char *bytes = nullptr;
58
59 if (luax_istype(L, 4, Data::type))
60 {
61 Data *data = data::luax_checkdata(L, 4);
62 bytes = (const char *) data->getData();
63 numbytes = data->getSize();
64 }
65 else if (!lua_isnoneornil(L, 4))
66 bytes = luaL_checklstring(L, 4, &numbytes);
67
68 ImageData *t = nullptr;
69 luax_catchexcept(L, [&](){ t = instance()->newImageData(w, h, format); });
70
71 if (bytes)
72 {
73 if (numbytes != t->getSize())
74 {
75 t->release();
76 return luaL_error(L, "The size of the raw byte string must match the ImageData's actual size in bytes.");
77 }
78
79 memcpy(t->getData(), bytes, t->getSize());
80 }
81
82 luax_pushtype(L, t);
83 t->release();
84 return 1;
85 }
86 else if (filesystem::luax_cangetdata(L, 1)) // Case 2: File(Data).
87 {
88 Data *data = love::filesystem::luax_getdata(L, 1);
89
90 ImageData *t = nullptr;
91 luax_catchexcept(L,
92 [&]() { t = instance()->newImageData(data); },
93 [&](bool) { data->release(); }
94 );
95
96 luax_pushtype(L, t);
97 t->release();
98 return 1;
99 }
100 else
101 {
102 return luax_typerror(L, 1, "value");
103 }
104}
105
106int w_newCompressedData(lua_State *L)
107{
108 Data *data = love::filesystem::luax_getdata(L, 1);
109
110 CompressedImageData *t = nullptr;
111 luax_catchexcept(L,
112 [&]() { t = instance()->newCompressedData(data); },
113 [&](bool) { data->release(); }
114 );
115
116 luax_pushtype(L, CompressedImageData::type, t);
117 t->release();
118 return 1;
119}
120
121int w_isCompressed(lua_State *L)
122{
123 Data *data = love::filesystem::luax_getdata(L, 1);
124 bool compressed = instance()->isCompressed(data);
125 data->release();
126
127 luax_pushboolean(L, compressed);
128 return 1;
129}
130
131int w_newCubeFaces(lua_State *L)
132{
133 ImageData *id = luax_checkimagedata(L, 1);
134 std::vector<StrongRef<ImageData>> faces;
135 luax_catchexcept(L, [&](){ faces = instance()->newCubeFaces(id); });
136 for (auto face : faces)
137 luax_pushtype(L, face);
138 return (int) faces.size();
139}
140
141// List of functions to wrap.
142static const luaL_Reg functions[] =
143{
144 { "newImageData", w_newImageData },
145 { "newCompressedData", w_newCompressedData },
146 { "isCompressed", w_isCompressed },
147 { "newCubeFaces", w_newCubeFaces },
148 { 0, 0 }
149};
150
151static const lua_CFunction types[] =
152{
153 luaopen_imagedata,
154 luaopen_compressedimagedata,
155 0
156};
157
158extern "C" int luaopen_love_image(lua_State *L)
159{
160 Image *instance = instance();
161 if (instance == nullptr)
162 {
163 luax_catchexcept(L, [&](){ instance = new love::image::Image(); });
164 }
165 else
166 instance->retain();
167
168 WrappedModule w;
169 w.module = instance;
170 w.name = "image";
171 w.type = &Image::type;
172 w.functions = functions;
173 w.types = types;
174
175 return luax_register_module(L, w);
176}
177
178} // image
179} // love
180