summaryrefslogtreecommitdiffhomepage
path: root/loader/texture.cpp
blob: 8ac9e793990d3a2d71b8a96ac7a3dede22a4b973 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#include "impl.hpp"
#include "compat/assert.hpp"
#include "compat/exception.hpp"
#include "compat/defs.hpp"
#include "compat/strerror.hpp"
#include <cstring>
#include <cstdio>
#include <Corrade/Utility/Path.h>
#include <Magnum/Trade/ImageData.h>

namespace floormat::loader_detail {

fm_noinline
Trade::ImageData2D loader_impl::texture(StringView prefix, StringView filename_) noexcept(false)
{
    ensure_plugins();

    constexpr size_t max_extension_length = 16;
    const auto N = prefix.size();
    if (N > 0) [[likely]]
        fm_assert(prefix[N-1] == '/');
    fm_soft_assert(filename_.size() + prefix.size() + max_extension_length + 1 < FILENAME_MAX);
    fm_soft_assert(check_atlas_name(filename_));
    fm_soft_assert(tga_importer);

    char buf[FILENAME_MAX];
    const auto path_no_ext = make_atlas_path(buf, prefix, filename_);
    const auto len = path_no_ext.size();

    for (auto extension : { ".tga"_s, ".png"_s, ".webp"_s, })
    {
        fm_soft_assert(len + extension.size() < std::size(buf));
        std::memcpy(buf + len, extension.data(), extension.size());
        buf[len + extension.size()] = '\0';
        auto path = StringView{buf, len + extension.size(), StringViewFlag::NullTerminated};
        fm_debug_assert(path.size() < std::size(buf));
        auto& importer = extension == ".tga"_s ? tga_importer : image_importer;
        if (Path::exists(path) && importer->openFile(path))
        {
            auto img = importer->image2D(0);
            if (!img)
                fm_abort("can't allocate image for '%s'", buf);
            auto ret = std::move(*img);
            return ret;
        }
    }

    const auto path = Path::currentDirectory();
    buf[len] = '\0';
    char errbuf[128];
    fm_throw("can't open image '{}' (cwd '{}'): {}"_cf, buf, path ? StringView{*path} : "(null)"_s, get_error_string(errbuf));
}

} // namespace floormat::loader_detail