cnjinhao / nana

a modern C++ GUI library
https://nana.acemind.cn
Boost Software License 1.0
2.32k stars 333 forks source link

nana::menu custom renderer gives garbage std::u8string_view input #660

Open ventsin opened 2 years ago

ventsin commented 2 years ago

Not sure why there's any support for char8_t variants, but this definitely breaks when compiled with MSVC C++20:

class renderer : public nana::menu::renderer_interface
{
    using color_rgb = ::nana::color_rgb;
public:
    renderer(const nana::pat::cloneable<renderer_interface>& rd)
        : reuse_(rd) //Reuses the current renderer
    {}
private:
    void background(graph_reference graph, nana::window wd) override
    {
        graph.rectangle(true, nana::colors::white);
        graph.rectangle(false, static_cast<color_rgb>(0x5DC1AC));
    }

    void item(graph_reference graph, const nana::rectangle& r, const attr& atr) override
    {
        if (state::active == atr.item_state)
            graph.rectangle(r, true, static_cast<color_rgb>(0x9ADCCA));
    }

    void item_image(graph_reference graph, const nana::point& pos, unsigned image_px, const nana::paint::image& img) override
    {
        reuse_->item_image(graph, pos, image_px, img);
    }

    void item_text(graph_reference graph, const nana::point& pos, const std::string& text, unsigned pixels, const attr& atr) override
    {
        reuse_->item_text(graph, pos, text, pixels, atr);
    }

        //so for some reason we need to fill this when compiling with C++20, but "text" is always garbage
    void item_text(graph_reference graph, const nana::point& pos, std::u8string_view text, unsigned pixels, const attr& atr) override
    {
        reuse_->item_text(graph, pos, text, pixels, atr);
    };

    void sub_arrow(graph_reference graph, const nana::point& pos, unsigned pixels, const attr& atr) override
    {
        reuse_->sub_arrow(graph, pos, pixels, atr);
    }
private:
    nana::pat::cloneable<renderer_interface> reuse_;
};

int main()
{
    nana::form fm;
    fm.caption("menu test");

    nana::menubar menubar;
    nana::menu* filemenu = nullptr;

    menubar.create(fm);

        //add menu
    filemenu = &menubar.push_back("File");

        //set menu renderer
        filemenu->renderer(renderer(filemenu->renderer()));

        //fill with something to look at
        filemenu->append("New", [](nana::menu::item_proxy& ip) {});
    filemenu->append("Open", [](nana::menu::item_proxy& ip) {});
    filemenu->append("Save", [](nana::menu::item_proxy& ip) {});
    filemenu->append("Save As", [](nana::menu::item_proxy& ip) {});
    filemenu->append("Export As", [](nana::menu::item_proxy& ip) {});
    filemenu->append("Close", [](nana::menu::item_proxy& ip) {});
    filemenu->append_splitter();
    filemenu->append("Exit", [](nana::menu::item_proxy& ip) {});

    fm.show();
    nana::exec();
    return 0;
}

I get an exception when trying to read or use text.

When I tried peeking into it, the contents appear to be garbage, and the length was 7824718.

This only happens when using custom renderers.

I'm not sure where the garbage is coming from, but a nice fix would be to remove this overload entirely, since char8_t variants aren't exactly useful in the current standard and the other overload worked just fine before C++20. And, to me, it also makes no sense to have two pure virtual overloads for the same exact purpose.