123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281 |
- // Flexlay - A Generic 2D Game Editor
- // Copyright (C) 2002 Ingo Ruhnke <grumbel@gmx.de>
- //
- // This program is free software: you can redistribute it and/or modify
- // it under the terms of the GNU General Public License as published by
- // the Free Software Foundation, either version 3 of the License, or
- // (at your option) any later version.
- //
- // This program is distributed in the hope that it will be useful,
- // but WITHOUT ANY WARRANTY; without even the implied warranty of
- // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- // GNU General Public License for more details.
- //
- // You should have received a copy of the GNU General Public License
- // along with this program. If not, see <http://www.gnu.org/licenses/>.
- #include "sprite_stroke_drawer.hpp"
- #include <ClanLib/Display/canvas.h>
- #include <ClanLib/gl.h>
- #include <assert.h>
- #include "stroke_drawer_impl.hpp"
- #include "drawer_properties.hpp"
- #include "bitmap_layer.hpp"
- CL_ProgramObject* program = 0;
- class SpriteStrokeDrawerImpl : public StrokeDrawerImpl
- {
- public:
- SpriteStrokeDrawer::DrawMode mode;
- SpriteStrokeDrawerImpl() {}
- void draw(const Stroke& stroke, CL_GraphicContext* gc);
- StrokeDrawerImpl* clone() const;
- };
- SpriteStrokeDrawer::SpriteStrokeDrawer(StrokeDrawer drawer)
- {
- impl = std::dynamic_pointer_cast<SpriteStrokeDrawerImpl>(drawer.impl);
- assert(impl.get());
- }
- SpriteStrokeDrawer::SpriteStrokeDrawer()
- : impl(new SpriteStrokeDrawerImpl())
- {
- impl->mode = SpriteStrokeDrawer::DM_NORMAL;
- }
- void
- SpriteStrokeDrawerImpl::draw(const Stroke& stroke, CL_GraphicContext* gc)
- {
- if (DrawerProperties::current()->get_brush().is_null() || stroke.get_dab_count() == 0)
- return;
- Stroke::Dabs dabs = stroke.get_interpolated_dabs(DrawerProperties::current()->get_spacing()
- * DrawerProperties::current()->get_size(),
- DrawerProperties::current()->get_spacing()
- * DrawerProperties::current()->get_size());
- for(Stroke::Dabs::iterator i = dabs.begin(); i != dabs.end(); ++i)
- {
- Dab& dab = *i;
- CL_Sprite sprite = DrawerProperties::current()->get_brush().get_sprite();
- CL_Color color = DrawerProperties::current()->get_color();
- sprite.set_color(color);
- sprite.set_alpha((color.get_alpha()/255.0f) * dab.pressure);
- sprite.set_scale(DrawerProperties::current()->get_size() * dab.pressure,
- DrawerProperties::current()->get_size() * dab.pressure);
- if (gc != 0)
- {
- /* Correct function:
- 1: dest
- 2: src
- R = R1 A1 (1 - A2) + R2 A2
- G = G1 A1 (1 - A2) + G2 A2
- B = B1 A1 (1 - A2) + B2 A2
- A = A1 (1 - A2) + A2
- // This is currently used, leads to premultiplied alpha
- Aout = Afgd + (1 - Afgd) * Abkg
- Cout' = Cfgd' + (1 - Afgd) * Cbkg'
- where
- Cfgd' = Cfgd * Afgd
- Cbkg' = Cbkg * Abkg
- Cout' = Cout * Aout
- Aout = (1 - (1 - Afgd) * (1 - Abkg))
- Cout = (Cfgd * Afgd) + (1 - Afgd * Cbkg * Abkg) / Aout
- where
- Cfgd = red, green, blue of foreground
- Cbkg = red, green, blue of background
- Afgd = alpha of foreground
- Abkg = alpha of background
- */
- // DO Multipass:
- // 1: GL_ZERO, GL_DST_ALPHA
- // 2: GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA
- /*brush.set_blend_func_separate(blend_zero, blend_dst_alpha,
- blend_zero, blend_one);
- brush.draw(dab.pos.x, dab.pos.y, gc);*/
- switch (mode)
- {
- case SpriteStrokeDrawer::DM_NORMAL:
- sprite.set_blend_func_separate(blend_src_alpha, blend_one_minus_src_alpha,
- blend_one, blend_one_minus_src_alpha);
- sprite.draw(dab.pos.x, dab.pos.y, gc);
- break;
- case SpriteStrokeDrawer::DM_ADDITION:
- sprite.set_blend_func_separate(blend_src_alpha, blend_one,
- blend_zero, blend_one);
- //blend_one, blend_one_minus_src_alpha);
- sprite.draw(dab.pos.x, dab.pos.y, gc);
- break;
- case SpriteStrokeDrawer::DM_ERASE:
- sprite.set_blend_func(blend_zero, blend_one_minus_src_alpha);
- sprite.draw(dab.pos.x, dab.pos.y, gc);
- break;
- case SpriteStrokeDrawer::DM_SMUDGE:
- {
- if (i != dabs.begin())
- {
- CL_Canvas* canvas = BitmapLayer::current()->get_canvas();
- CL_PixelBuffer buffer = canvas->get_pixeldata(CL_Rect(CL_Point(static_cast<int>((i-1)->pos.x) - sprite.get_width()/2,
- static_cast<int>((i-1)->pos.y) - sprite.get_height()/2),
- CL_Size(sprite.get_width(), sprite.get_height())));
- CL_Surface surface(buffer);
- //surface.set_blend_func_separate(blend_src_alpha, blend_one_minus_src_alpha,
- // blend_one, blend_zero);
- surface.set_alignment(origin_center);
- surface.set_alpha(0.5);
- //surface.set_scale(DrawerProperties::current()->get_size(),
- // DrawerProperties::current()->get_size());
- surface.draw(dab.pos.x, dab.pos.y, gc);
- }
- }
- break;
- case SpriteStrokeDrawer::DM_SHADER:
- {
- #if 0
- CL_OpenGLState state(gc);
- state.set_active();
- state.setup_2d();
- if (program == 0)
- {
- program = new CL_ProgramObject();
- CL_ShaderObject shader("shader", &(Flexlay::current()->resources));
- std::cout << "Shader status: " << (shader.get_compile_status() ? "true" : "false") << std::endl;
- std::cout << "Shader log: " << shader.get_info_log() << std::endl;
- std::cout << "Shader handle: " << shader.get_handle() << std::endl;
- program->attach(shader);
- program->link();
- std::cout << "Program status: " << (program->get_link_status() ? "true" : "false") << std::endl;
- std::cout << "Program log: " << program->get_info_log() << std::endl;
- std::cout << "Program handle: " << program->get_handle() << std::endl;
- clUseProgram(program->get_handle());
- }
- else
- {
- clUseProgram(program->get_handle());
- }
- CL_OpenGLSurface glsurface(sprite.get_frame_surface(0));
- glActiveTexture(GL_TEXTURE0);
- glsurface.bind();
- glEnable(GL_TEXTURE_2D);
- /*CL_OpenGLSurface glsurface2(SketchLayer::current()->get_background_surface());
- glActiveTexture(GL_TEXTURE1);
- glsurface2.bind();
- glEnable(GL_TEXTURE_2D);*/
- clUniform1i(program->get_attribute_location("mytex"), 0);
- //clUniform1i(program->get_attribute_location("background"), 1);
- //program->validate();
- //std::cout << "Program validate status: " << (program->get_validate_status() ? "true" : "false") << std::endl;
- //std::cout << "Program log: " << program->get_info_log() << std::endl;
- clBegin(CL_QUADS);
- clColor4b(color.get_red(), color.get_green(), color.get_blue(), color.get_alpha());
- float size = base_size * dab.pressure;
- clVertex2f((dab.pos.x - sprite.get_width()/2) * size, (dab.pos.y - sprite.get_height()/2) * size);
- clTexCoord2d(0.0, 0.0);
- clVertex2f((dab.pos.x + sprite.get_width()/2) * size, (dab.pos.y - sprite.get_height()/2) * size);
- clTexCoord2d(1.0, 0.0);
- clVertex2f((dab.pos.x + sprite.get_width()/2) * size, (dab.pos.y + sprite.get_height()/2) * size);
- clTexCoord2d(1.0, 1.0);
- clVertex2f((dab.pos.x - sprite.get_width()/2) * size, (dab.pos.y + sprite.get_height()/2) * size);
- clTexCoord2d(0.0, 1.0);
- clEnd();
- state.set_active();
- clUseProgram(0);
- #endif
- }
- break;
- default:
- std::cout << "Error: SpriteStrokeDrawer: Unknown draw mode: " << mode << std::endl;
- break;
- }
- }
- else
- {
- switch (mode)
- {
- case SpriteStrokeDrawer::DM_NORMAL:
- sprite.set_blend_func(blend_src_alpha, blend_one_minus_src_alpha);
- sprite.draw(dab.pos.x, dab.pos.y, gc);
- break;
- case SpriteStrokeDrawer::DM_ADDITION:
- sprite.set_blend_func(blend_src_alpha, blend_one);
- sprite.draw(dab.pos.x, dab.pos.y, gc);
- break;
- case SpriteStrokeDrawer::DM_ERASE:
- sprite.set_blend_func(blend_zero, blend_one_minus_src_alpha);
- sprite.draw(dab.pos.x, dab.pos.y, gc);
- break;
- case SpriteStrokeDrawer::DM_SMUDGE:
- sprite.set_blend_func(blend_src_alpha, blend_one_minus_src_alpha);
- sprite.draw(dab.pos.x, dab.pos.y, gc);
- break;
- default:
- std::cout << "Error: SpriteStrokeDrawer: Unknown draw mode: " << mode << std::endl;
- break;
- }
- }
- }
- }
- void
- SpriteStrokeDrawer::set_mode(DrawMode mode)
- {
- impl->mode = mode;
- }
- SpriteStrokeDrawer::DrawMode
- SpriteStrokeDrawer::get_mode()
- {
- return impl->mode;
- }
- StrokeDrawerImpl*
- SpriteStrokeDrawerImpl::clone() const
- {
- SpriteStrokeDrawerImpl* drawer = new SpriteStrokeDrawerImpl();
- *drawer = *this;
- return drawer;
- }
- StrokeDrawer
- SpriteStrokeDrawer::to_drawer()
- {
- return StrokeDrawer(impl);
- }
- /* EOF */
|