Posted by: nanaproject | July 14, 2012

Nana C++ Library for C++11 is available now

In the release of 0.2.5, it contains the first release for C++11, and there is a demo coming with the release.
Browse the source code of demo at http://nanapro.codeplex.com/SourceControl/changeset/view/aaeb36087e3c

What’s new in the release?

1, Refining the constructors and create() methods of widgets

Assume T is a widget type and its category is widget_tag.
T(); //Does not create the widget
T(window owner, bool visible);
T(window owner, const rectangle& r = rectangle(), bool visible = true);
bool T::create(window owner, bool visible);
bool T::create(window owner, const rectangle& = rectangle(), bool visible = true);

class form
form(const rectangle& = API::make_center(300, 150), const appearance& = appearance());
form(window owner, const appearance& = appearance());
form(window owner, const rectangle&, const appearance& = appearance());

class nested_form
nested_form(window owner, const appearance&);
nested_form(window owner, const rectangle& = rectangle(), const appearance& = appearance());

As you can see, the default arguments of constructor are a bit different between form and nested_form.
Calling the constructor of class form without specifying a rectangle uses the default rectangle. The default rectangle of form is a specified sized rectangle in the center of screen, however if calling the constructor with an owner, we can not refer to the owner in the parameter list. E.g.

form(window owner, const rectangle& = API::make_center(owner, 300, 150), …);
                                                                                      ^^^^undefined
So
form::form(window owner, const appearance& apr)
     : base(owner, API::make_center(owner, 300, 150), apr)
{}

2, Some bugfixs

Some information about Nana.C++11

deprecated:
Thread support classes
thread
token
mutex
condition

Utility classes
functor
many traits clases

Requires:
Core Language
nullptr, strong-typed enum, lambdas, auto specifier, trailing-return-type, range-based for
Standard Library
<mutex>,<condition_variable>,<functional>,<type_traits>, <memory>, <chrono>,<thread>

Compiler:
Windows -> Visual C++ 2012 RC
Linux-> GCC 4.7(Fedora 17)

Browse code at http://nanapro.codeplex.com

Welcome you to create a fork and “push” your modifications to the fork.

In C++, objects often provide copy ability and moveability to duplicate or move from an existing object. It was by making them copyable or movable caused more problems than it solves.

Complexity

If a widget could be copyable, what properties should be copied? E.g

form fm1;
button btn1(fm1);

form fm2;
button btn2(fm2);

btn1 = btn2; //Assume that copy is allowed.

We can say that after copying, the caption, position and size of btn1 is same to btn2’s. But, which should be the parent of btn1? fm1 or fm2? and another important question, is a widget reference semantics or value semantics?

Error-prone

A widget object is unlike other object that types are string, int and so on. A widget object owns event handles. E.g

class A
{
public:
    A();

    A(widget& wd)
        :btn_(wd)
    {
        //Nana feature: we should not take care about the event handle
        //when the btn_ is being destructed, the event handle will be
        //deleted automatically.
        btn_.make_event<events::click>(make_fun(*this, &A::_m_clicked));
    }

    A(const A& rhs)
        :btn_(rhs.btn_)
    {
        //btn_ is a duplication of rhs_.btn_
        //sould be re-make the click event?
    }

    A & operator=(const A& rhs);
    
    A(A && rhs)
        : btn_(std::move(rhs))
    {}

    A& operator=(const A&& rhs);    
private:
    void _m_clicked()
    {
        std::cout<<“Button is clicked”<<std::endl;
    }
private:
    button btn_;    
};

It’s error-prone, let’s prove it.

form fm;
A a;
{
    B b(fm);
    a = std::move(b);
}

After destruction of b, a refers the event handle that b is not existing. To fix there problems, we have to code more and face the complexities.

Posted by: nanaproject | June 29, 2012

It is time to reform

Nana C++ Library now is starting with C++11/Boost conversion.  There are so many components will be replaced with C++11/Boost libraries, and it will be a whole new library.

Posted by: nanaproject | June 23, 2012

A Git Repository is Established

Nana C++ Library has a git repository established.

http://nanapro.codeplex.com

You can browse source code directly at Codeplex or clone the git repository(read-only) at https://git01.codeplex.com/nanapro

Reporting bugs is appreciated!

http://sourceforge.net/tracker/?group_id=208683&atid=1006681

Though codeplex and sourceforge both provide bug tracker system, sourceforge should be primary. If you have a codeplex account and like to use codeplex, you could also report bugs at codeplex, but do not report the same bug repeatly at both codeplex and sourceforge.

Regards

Posted by: nanaproject | June 18, 2012

Introduce to The Support of Bidirectional Language

This update(0.2.4) introduced the basic support of bidirectional language into Nana C++ Library.

The vision of selected text is not continuous during different directional languages, because
the vision direction is same with the direction of language.

In some situations, the text is displayed in unexpected direction due to algorithm. For
example. If the text “Bidi example: ” is removed, the new text is begin with an Arabic word
and the display is

The display is unexcepted, because the text is begin with an Arabic word, the sentence is
treated as Right-to-Left. In the situation, we should adjust the direction with implicit
directional marks character.

nana::string text = STR(“مرحبا means Hello in Arabic.”);
text.insert(0, 1, nana::unicode_bidi::LRM);
textbox.caption(text);

Insert a LRM(left-to-right mark) character to make the algorithm treat the text as left-to-
right.

Posted by: nanaproject | May 16, 2012

Tutorial of Release 0.2.3

This release makes a great improvement for X11 support, such as Drag and Drop event and dataexch(clipboard), this indicates the Nana C++ Library should be work well with Linux(X11). In addition, there are new features in this release.

class msgbox
class msgbox is used for displaying a modal dialog box to prompt a biref message. A brief example.

nana::gui::msgbox m(STR(“msgbox example”));
m<<STR(“This is a msgbox example.”);
m();


The msgbox is a C++ stream style, so we can easy to display strings, numbers and all the objects whose type overloads an operator<<() for std::ostream.

Sometimes, the application should ask user for a decision, for example, ask user whether to exit.

void when_exit(const nana::gui::eventinfo& ei)
{
    nana::gui::msgbox m(ei.window, STR(“msgbox example”), nana::gui::msgbox::yes_no);
    m.icon(m.icon_question);
    m<<STR(“Are you sure you want to exit the game?”);
    ei.unload.cancel = (m() != m.pick_yes);
}

int main()
{
    using namespace nana::gui;
    form fm;
    fm.make_event<events::unload>(when_exit);
    fm.show();
    exec();
}

Window Icon
There are two interfaces to set an icon for a window which is a root_widget, such as form and nested_form, thay are defined in namespace nana::gui::API.

void window_icon_default(const nana::paint::image&);
void window_icon(nana::gui::window, const nana::paint::image&);

window_icon_default() sets a default icon, and after calling it, all windows will set the default icon automatically while they are creating.

Although the Nana C++ Library is aimed for cross-platform, there is a distinction in Nana between Windows and Linux(X11). The icon of a window only could be an ICON file in Windows. If cross-platform is desired, the code should be treated differently.

using namespace nana::gui;
form fm;
#if defined(NANA_WINDOWS)
API::window_icon(fm, nana::paint::image(STR(“icon.ico”)));
#else
API::window_icon(fm, nana::paint::image(STR(“icon.bmp”)));
#endif

Under Windows, the icon of window is the icon of exe file usually, the icon file is stored in the exe file as a resouce. To set the icon resouce for the window, we just open the exe with class image in this way.
API::window_icon_default(nana::paint::image(STR(“program.exe”)));
or
API::window_icon(a_form_object, nana::paint::image(STR(“program.exe”)));

In the release of 0.2.2, Nana C++ Library provides a mechanism which can flexibly configure the image processing algorithms. For an abstract algorithm, there would be many implementations. For example, Nana C++ Library provides two stretch algorithms, they are bilinear interoplation and proximal interoplation, you can switch the algorithms under your requirement.
See the example at:
http://stdex.sourceforge.net/help/paint/image_process_selector.htm

The algorithms provided by Nana are implemented without specific platform instructions for cross-platform, they should work fine in different compiler environment. In some situations, an extreme efficiency is desired. Although the Nana C++ Library does not provide such an algorithm with specific instructions, it is possible to implement the algorithm by yourself for your requirment, and configure it to make Nana apply it.

Let’s implement a blend algorithm with MMX instruction.

To implement a blend algorithm that can be applied by Nana C++ Library, we have to implement the algorithm with class blend_interface, the class is defined by Nana in header file <nana/paint/image_process_interface.hpp>.

class blend_interface
{
public:
    virtual ~blend_interface() = 0;
    virtual void process(nana::paint::drawable_type dw_dst, const nana::rectangle& r_dst, const paint::pixel_buffer& s_pixbuf, const nana::point& s_pos, double fade_rate) const = 0;
};

dw_dst: the destination object.
r_dst:    the destination blend area.
s_pixbuf: the source pixel buffer.
s_pos:    the source blend coordinate.
fade_rate: the rate at blend.

The blend area is always valid, it is calculated by Nana before passing it to the function. So we can use it without check.

The semantics of this interface is:
dw_dst = dw_dst * fade_rate + s_pixbuf * (1 – fade_rate)

Let’s start!

#include <nana/paint/image_process_interface.hpp>

class blend_mmx
    : public nana::paint::image_process::blend_interface
{

    virtual void process(nana::paint::drawable_type dw_dst, const nana::rectangle& r_dst, const nana::paint::pixel_buffer& s_pixbuf, const nana::point& s_pos, double fade_rate) const
    {
        nana::paint::pixel_buffer d_pixbuf(dw_dst, r_dst.y, r_dst.height);
        nana::pixel_rgb_t * d_rgb = d_pixbuf.raw_ptr();

        if(d_rgb)
        {
            d_rgb += r_dst.x;
            nana::pixel_rgb_t * s_rgb = s_pixbuf.raw_ptr(s_pos.y) + s_pos.x;

            const unsigned rest = r_dst.width & 0x3;
            const unsigned length_align4 = r_dst.width – rest;

            unsigned d_step_width = d_pixbuf.size().width;
            unsigned s_step_width = s_pixbuf.size().width;

            unsigned i_d_rate = static_cast<unsigned>(fade_rate * 255);
            unsigned i_s_rate = 255 – i_d_rate;

            __asm
            {
                pxor xmm7, xmm7
                movd xmm0, i_d_rate
                punpcklwd xmm0, xmm0
                punpcklwd xmm0, xmm0
                punpcklwd xmm0, xmm0

                movd xmm1, i_s_rate
                punpcklwd xmm1, xmm1
                punpcklwd xmm1, xmm1
                punpcklwd xmm1, xmm1
            }

            for(unsigned line = 0; line < r_dst.height; ++line)
            {
                __asm
                {
                    push eax
                    push ebx
                    push edx
                    mov edx, dword ptr[length_align4]
                    mov    eax, dword ptr[d_rgb]
                    mov ebx, dword ptr[s_rgb]
                    lea    edx, [edx * 4 + eax]
blend_mmx_3_for_each_pixel_in_line_loop_start:
                    cmp eax, edx
                    je blend_mmx_3_for_each_pixel_in_line_loop_end

                    //eax[0], eax[1]
                    movq xmm2, qword ptr[eax]
                    movq xmm3, qword ptr[ebx]
                    punpcklbw xmm2, xmm7
                    punpcklbw xmm3, xmm7
                    pmullw xmm2, xmm0
                    pmullw xmm3, xmm1
                    paddw    xmm2, xmm3
                    psrlw    xmm2, 8
                    packuswb xmm2, xmm7
                    movq    qword ptr[eax], xmm2
                        
                    //eax[2], eax[3]
                    movq xmm2, qword ptr[eax + 8]
                    movq xmm3, qword ptr[ebx + 8]
                    punpcklbw xmm2, xmm7
                    punpcklbw xmm3, xmm7
                    pmullw xmm2, xmm0
                    pmullw xmm3, xmm1
                    paddw    xmm2, xmm3
                    psrlw    xmm2, 8
                    packuswb xmm2, xmm7
                    movq    qword ptr[eax + 8], xmm2
                        
                    add eax, 16
                    add ebx, 16

                    jmp blend_mmx_3_for_each_pixel_in_line_loop_start
blend_mmx_3_for_each_pixel_in_line_loop_end:
                    push ecx
                    mov ecx, dword ptr[rest]
                    cmp ecx, 0
                    je blend_mmx_3_for_each_rest_pixel_loop_end
blend_mmx_3_for_each_rest_pixel_loop_start:
                    movd xmm2, dword ptr[eax]
                    movd xmm3, dword ptr[ebx]
                    punpcklbw xmm2, xmm7
                    punpcklbw xmm3, xmm7
                    pmullw xmm2, xmm0
                    pmullw xmm3, xmm1
                    paddw    xmm2, xmm3
                    psrlw    xmm2, 8
                    packuswb xmm2, xmm7
                    movd    dword ptr[eax], xmm2
                    add eax, 4
                    add ebx, 4
                    loop blend_mmx_3_for_each_rest_pixel_loop_start
blend_mmx_3_for_each_rest_pixel_loop_end:
                    pop ecx
                    pop edx
                    pop ebx
                    pop eax
                }
                d_rgb += d_step_width;
                s_rgb += s_step_width;
            }

            __asm emms

            nana::rectangle r = r_dst;
            r.y = 0;
            d_pixbuf.paste(r, dw_dst, r_dst.x, r_dst.y);
        }
    }
};

Apply it!

#include <nana/gui/wvl.hpp>
#include <nana/gui/timer.hpp>
#include <nana/paint/image_process_selector.hpp>

//Include the definition of blend_mmx that we implemented before.

class blend_form
    : public nana::gui::form
{
public:
    blend_form()
        :form(nana::gui::API::make_center(450, 300))
        ,fade_rate_(0.1), delta_(0.1)
    {
        this->show();

        nana::paint::image img(STR(“image01.bmp”));
        s_graph_.make(img.size().width, img.size().height);
        img.paste(s_graph_, 0, 0);

        d_image_.open(STR(“image02.bmp”));
        d_graph_.make(d_image_.size().width, d_image_.size().height);

        timer_.make_tick(nana::make_fun(*this, &tsform::_m_blend));
        timer_.interval(10);

        //Install the blend_mmx and apply it.
        nana::paint::image_process::selector sl;
        sl.add_blend<blend_mmx>(“blend_mmx”); //Give it a name
        sl.blend(“blend_mmx”); //Apply it
    }
private:
    void _m_blend()
    {
        fade_rate_ += delta_;
        if(fade_rate_ > 1)
        {
            fade_rate_ = 1;
            delta_ = -0.01;
        }
        else if(fade_rate_ < 0)
        {
            fade_rate_ = 0;
            delta_ = 0.01;
        }
                
        d_image_.paste(d_graph_, 0, 0);

        //The blend operation, it employes the blend_mmx algorithm.
        s_graph_.blend(d_graph_, 0, 0, fade_rate_);

        nana::gui::drawing drawing(*this);
        drawing.clear();
        drawing.bitblt(0, 0, 450, 300, d_graph_, 0, 0);
        drawing.update();
    }
private:
    double    fade_rate_;
    double    delta_;
    timer    timer_;
    nana::paint::graphics s_graph_, d_graph_;
    nana::paint::image d_image_;
};

It shows a method that user can implement an algorithm instead of the algorithm that Nana provides for various requirement.

Enjoy!

Posted by: nanaproject | February 22, 2012

Blending Images

Blending images is one of important method for makeing a powerful and fascinating GUI. This is a tutorial that is intended to show you how to blend images and display the result by using Nana C++ Library.

Before this tutorial, we have to prepare 2 image files for blending.

Image for blending

image01.png

image02.png

The format of images is PNG. Before using it, we should enable the PNG support for Nana.

Now, let’s code it.

#include <nana/gui/wvl.hpp>
#include <nana/gui/drawing.hpp>
#include <nana/gui/timer.hpp>

class tsform: public nana::gui::form
{
public:
    //Because the size of images that we prepared is 450*300,
    //the form is created with the same size as images’.
    tsform()
        :nana::gui::form(nana::gui::API::make_center(450, 300)), fade_rate_(0.1), delta_(0.1)
    {
        //Open the image files.
        image1_.open(STR(“image01.png”));
        image2_.open(STR(“image02.png”));
        timer_.make_tick(nana::make_fun(*this, &tsform::_m_blend));
        timer_.interval(10);
    }
private:
    void _m_blend()
    {
        fade_rate_ += delta_;
        if(fade_rate_ > 1)
        {
            fade_rate_ = 1;
            delta_ = -0.01;
        }
        else if(fade_rate_ < 0)
        {
            fade_rate_ = 0;
            delta_ = 0.01;
        }
        
        //Before blending, the image should be copied into graphics
        nana::paint::graphics graph1(450, 300);
        image1_.paste(graph1, 0, 0);

        nana::paint::graphics graph2(450, 300);
        image2_.paste(graph2, 0, 0);

        //Blend, the result is generated in graph2 object.
        graph1.blend(graph2, 0, 0, fade_rate_);

        //Display the result, copy the graph2 object to the form.
        nana::gui::drawing drawing(*this);
        drawing.clear();
        drawing.bitblt(0, 0, 450, 300, graph2, 0, 0);
        drawing.update();
    }
private:
    double    fade_rate_;
    double    delta_;
    nana::gui::timer    timer_;
    nana::paint::image image1_, image2_;
};

int main()
{
    tsform fm;
    fm.show();
    nana::gui::exec();
}

Run the program to show its work in practice.

Original Image

Blended Image

Final Image

The program blends images repeatly.

Posted by: nanaproject | February 21, 2012

Enable the PNG support for Nana C++ Library

In the release of 0.2, Nana provides the support for PNG, but defaultly Nana disables the feature of PNG for easy and fast configuration.

The support for PNG is introduced to Nana C++ Library by employing libpng(www.libpng.org), there are two strategies for the support:
1, use the libpng bundled with Nana;
2, use the libpng from operating system, it means that we have to install the libpng by ourselves.

Enable the support for PNG
Open the config.hpp in nana include folder, you can find a line of comment like is

//#define NANA_ENABLE_PNG

Cancel the comment to enable the support for PNG.

Now, the result looks like this:

#define NANA_ENABLE_PNG 1
#if defined(NANA_ENABLE_PNG)
    //Comment it for using the libpng from operating system.
    #define NANA_LIBPNG 1
#endif

Keep the #defined NANA_LIBPNG for using the libpng bundled with Nana.
Comment it for using the libpng from operating system.

By default, Nana uses the libpng bundled with it in win32 package, and the libpng from operating system in linux X11 package.

After configuration, rebuild the Nana C++ Library, and create an application for trial.

#include <nana/gui/wvl.hpp>
#include <nana/gui/widgets/picture.hpp>
#include <nana/gui/layout.hpp>

int main()
{
    using namespace nana::gui;
    form fm;
    picture pic(fm);

    gird    gd(fm);
    gd.push(pic, 0, 0);

    pic.load(STR(“a_png_file.png”));
    fm.show();
    exec();
}

Under Windows, link the static library of libpng in “%nana%/extrlib” folder.
libpng.a: For Dev-C++ and Code::Blocks
libpng.md.lib/libpng.md.x64.lib: For VC and Multi-threaded DLL runtime library.
libpng.mt.lib/libpng.mt.x64.lib: For VC and Multi-threaded runtime library.

Under Linux, modify the makefile and add a “-lpng” for compiler.

Older Posts »

Categories