123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234 |
- // 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 <iostream>
- #include "stroke.hpp"
- #include "stroke_drawer.hpp"
- class StrokeImpl
- {
- public:
- Stroke::Dabs dabs;
- StrokeDrawer drawer;
- // Additional data which should be moved to the StrokeDrawer, since
- // its for caching only and can be generated
- //typedef std::vector<CL_Pointf> Normals;
- //Normals normals;
- mutable bool bounding_rect_needs_recalc;
- mutable CL_Rectf bounding_rect;
- CL_Rectf calc_bounding_rect() const
- {
- CL_Rectf rect;
- // FIXME: Keep the drawer into account (ie. brushsize)
- if (dabs.size() > 0)
- {
- rect.left = rect.right = dabs.front().pos.x;
- rect.top = rect.bottom = dabs.front().pos.y;
- for(Stroke::Dabs::const_iterator i = dabs.begin()+1; i != dabs.end(); ++i)
- {
- rect.left = std::min(i->pos.x, rect.left);
- rect.top = std::min(i->pos.y, rect.top);
- rect.right = std::max(i->pos.x, rect.right);
- rect.bottom = std::max(i->pos.y, rect.bottom);
- }
- }
- return rect;
- }
- StrokeImpl()
- : bounding_rect_needs_recalc(true)
- {
- }
- };
- Stroke::Stroke()
- : impl(new StrokeImpl())
- {
- }
- void
- Stroke::set_drawer(const StrokeDrawer& drawer_)
- {
- impl->drawer = drawer_;
- }
- StrokeDrawer
- Stroke::get_drawer()
- {
- return impl->drawer;
- }
- Stroke::Dabs
- Stroke::get_interpolated_dabs(float x_spacing, float y_spacing) const
- {
- if (impl->dabs.size() > 0)
- {
- Dabs interpolated_dabs;
- interpolated_dabs.push_back(impl->dabs.front());
- // The following code basically takes all the event dabs as recieved
- // by from the InputDevice and interpolates new dabs inbetween to
- // give them an equal spacing (ie. every dab is only 'spacing' away
- // from the next)
- float overspace = 0.0f;
- const Stroke::Dabs& dabs = impl->dabs;
- for(unsigned int j = 0; j < dabs.size()-1; ++j)
- {
- CL_Pointf dist = dabs[j+1].pos - dabs[j].pos;
- float length = sqrt(dist.x * dist.x + dist.y * dist.y);
- int n = 1;
- // Spacing is keep relative to the brush size
- // FIXME: This is specific to a Sprite based drawer, might not work for others
- // FIXME: y_spacing isn't taken into account either
- float local_spacing = x_spacing * dabs[j].pressure;
- while (length + overspace > (local_spacing * n))
- {
- float factor = (local_spacing/length) * n - (overspace/length);
- // FIXME: Interpolate tilting, pressure, etc. along the line
- interpolated_dabs.push_back(Dab(dabs[j].pos.x + dist.x * factor,
- dabs[j].pos.y + dist.y * factor,
- dabs[j].pressure));
- n += 1;
- }
- // calculate the space that wasn't used in the last iteration
- overspace = (length + overspace) - (local_spacing * (n-1));
- }
- return interpolated_dabs;
- }
- else
- {
- // No dabs available, so nothing to interpolate
- return impl->dabs;
- }
- }
- Stroke::Dabs
- Stroke::get_dabs() const
- {
- return impl->dabs;
- }
- int
- Stroke::get_dab_count() const
- {
- return impl->dabs.size();
- }
- void
- Stroke::draw(CL_GraphicContext* gc) const
- {
- if (!impl->drawer.is_null())
- {
- const_cast<StrokeDrawer&>(impl->drawer).draw(*this, gc);
- }
- else
- {
- std::cout << "No drawer set!" << std::endl;
- }
- }
- void
- Stroke::add_dab(const Dab& dab)
- {
- impl->dabs.push_back(dab);
- }
- /* // calc normals
- assert(normals.size() == 0);
- if (points.size() == 1)
- {
- normals.push_back(CL_Pointf(1.0f, 1.0f));
- }
- else if (points.size() == 2)
- {
- normals.push_back(CL_Pointf(1.0f, 1.0f));
- normals.push_back(CL_Pointf(1.0f, 1.0f));
- }
- else if (points.size() >= 3)
- {
- for(Points::size_type i = 0; i < int(points.size())-1; ++i)
- {
- CL_Pointf normal((points[i].y - points[i+1].y),
- -(points[i].x - points[i+1].x));
- float length = sqrt(normal.x * normal.x + normal.y * normal.y);
- normal.x /= length;
- normal.y /= length;
- normals.push_back(normal);
- }
- normals.push_back(CL_Pointf(1.0f, 1.0f));
- }
- //std::cout << normals.size() << " == " << points.size() << std::endl;
- assert(normals.size() == points.size());
- */
- /*
- // Calc bounding rect
- if (points.size() >= 1)
- {
- bounding_rect.left = bounding_rect.right = points.front().x;
- bounding_rect.top = bounding_rect.bottom = points.front().y;
- for(Points::iterator i = points.begin()+1; i != points.end(); ++i)
- {
- bounding_rect.left = Math::min(bounding_rect.left, i->x);
- bounding_rect.right = Math::max(bounding_rect.right, i->x);;
- bounding_rect.top = Math::min(bounding_rect.top, i->y);
- bounding_rect.bottom = Math::min(bounding_rect.bottom, i->y);
- }
- // FIXME: Need to take brush size into account
- }
- */
- CL_Rectf
- Stroke::get_bounding_rect() const
- {
- if (impl->bounding_rect_needs_recalc)
- {
- impl->bounding_rect = impl->calc_bounding_rect();
- impl->bounding_rect_needs_recalc = false;
- }
- return impl->bounding_rect;
- }
- bool
- Stroke::empty() const
- {
- return (impl->dabs.size() == 0);
- }
- /* EOF */
|