/* * Copyright (c) 2005 Boudewijn Rempt (boud@valdyas.org) * * 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 2 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "kis_ws_engine_filter.h" #include "kis_wet_sticky_colorspace.h" /** * The Wet & Sticky Engine filter is based on the wet & sticky model * for computer painting designed by Tunde Cockshott and implemented * by David England and Kevin Waite. * * The filter implements the engine that moves the paint according to * gravity, viscosity and absorbency. * */ KisWSEngineFilter::KisWSEngineFilter() : KisFilter(id(), "", i18n("&Wet & Sticky paint engine...")) { } /** * Sets the POINT giving the coordinate location of the next * cell on the canvas to be visited. There is an even probability * of each cell being visited. */ TQPoint next_cell(TQ_UINT32 width, TQ_UINT32 height) { return TQPoint(random() * width, random() * height); } void single_step(KisColorSpace * cs, KisPaintDeviceSP src, KisPaintDeviceSP dst, const TQRect & rect, bool native) { using namespace WetAndSticky; TQPoint p = next_cell( rect.width(), rect.height() ); // XXX: We could optimize by randomly doing lines of 64 pixels // -- maybe that would be enough to avoid the windscreen wiper // effect. KisHLineIterator iter = src -> createHLineIterator(p.x(), p.y(), 1, false); TQ_UINT8 *orig = iter.rawData(); TQ_UINT8 *pix = orig; if (!orig) return; if (!native ) { TQColor c; TQ_UINT8 opacity; src -> colorSpace() -> toTQColor(pix, &c, &opacity); TQ_UINT8 *pix = new TQ_UINT8[sizeof( cell )]; TQ_CHECK_PTR(pix); cs -> fromTQColor(c, opacity, pix); } // Process CELL_PTR c = ( CELL_PTR )pix; if ( !native ) { // Set RGBA back } } void KisWSEngineFilter::process(KisPaintDeviceSP src, KisPaintDeviceSP dst, KisFilterConfiguration* configuration, const TQRect& rect) { m_src = src; m_dst = dst; m_cfg = ( KisWSEngineFilterConfiguration * )configuration; m_rect = rect; kdDebug(DBG_AREA_FILTERS) << "WSEnginefilter called!\n"; TQTime t; t.restart(); // Two possibilities: we have our own, cool w&s pixel, and // then we have real data to mess with, or we're filtering a // boring shoup-model paint device and we can only work by // synthesizing w&s pixels. bool native = false; // XXX: We need a better way to ID color strategies if ( src -> colorSpace() -> id() == KisID("W&S","") ) native = true; // XXX: We need a better way to ID color strategies KisColorSpace * cs = KisColorSpaceRegistry::instance()->get("W&S"); TQ_UINT32 pixels = 400; //m_cfg -> pixels(); kdDebug(DBG_AREA_FILTERS) << "Going to singlestep " << pixels << " pixels.\n"; // Determine whether we want an infinite loop if ( pixels == 0 ) { while ( true ) single_step (cs, src, dst, rect, native); } // Or not. else { for ( TQ_UINT32 i = 0; i < pixels; ++i ) { single_step (cs, src, dst, rect, native); } } kdDebug(DBG_AREA_FILTERS) << "Done in " << t.elapsed() << " ms\n"; } KisFilterConfigWidget * KisWSEngineFilter::createConfigurationWidget(TQWidget* parent, KisPaintDeviceSP dev) { // KisWSEngineFilterConfigurationWidget* kefcw = new KisWSEngineFilterConfigurationWidget(this,parent, ""); // kdDebug(DBG_AREA_FILTERS) << kefcw << endl; // return kefcw ; return 0; } KisFilterConfiguration* KisWSEngineFilter::configuration(TQWidget* nwidget, KisPaintDeviceSP dev) { // KisWSEngineFilterConfigurationWidget* widget = (KisWSEngineFilterConfigurationWidget*) nwidget; // if( widget == 0 ) // { // return new KisWSEngineFilterConfiguration(30); // } else { // TQ_UINT32 depth = widget -> baseWidget() -> depthSpinBox -> value(); // return new KisWSEngineFilterConfiguration(depth); // } return new KisWSEngineFilterConfiguration( m_rect.height() * m_rect.width() ); }