diff options
| author | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-01-20 01:29:50 +0000 | 
|---|---|---|
| committer | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-01-20 01:29:50 +0000 | 
| commit | 8362bf63dea22bbf6736609b0f49c152f975eb63 (patch) | |
| tree | 0eea3928e39e50fae91d4e68b21b1e6cbae25604 /krita/plugins/viewplugins | |
| download | koffice-8362bf63dea22bbf6736609b0f49c152f975eb63.tar.gz koffice-8362bf63dea22bbf6736609b0f49c152f975eb63.zip  | |
Added old abandoned KDE3 version of koffice
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/koffice@1077364 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'krita/plugins/viewplugins')
215 files changed, 20204 insertions, 0 deletions
diff --git a/krita/plugins/viewplugins/Makefile.am b/krita/plugins/viewplugins/Makefile.am new file mode 100644 index 000000000..e5739b36d --- /dev/null +++ b/krita/plugins/viewplugins/Makefile.am @@ -0,0 +1,24 @@ +if compile_kross +SCRIPTINGDIR = scripting +endif + +SUBDIRS = \ +    substrate \ +    colorrange \ +    colorspaceconversion \ +    dropshadow \ +    filtersgallery \ +    histogram \ +    histogram_docker \ +    imagesize \ +    modify_selection \ +    rotateimage \ +    screenshot \ +    separate_channels \ +    shearimage \ +    selectopaque \ +    $(SCRIPTINGDIR) + +# variations +# history_docker +# performancetest diff --git a/krita/plugins/viewplugins/colorrange/Makefile.am b/krita/plugins/viewplugins/colorrange/Makefile.am new file mode 100644 index 000000000..90a260a3e --- /dev/null +++ b/krita/plugins/viewplugins/colorrange/Makefile.am @@ -0,0 +1,24 @@ +INCLUDES  =  -I$(srcdir)/../../../sdk \ +	-I$(srcdir)/../../../core \ +	-I$(srcdir)/../../../kritacolor/ \ +	-I$(srcdir)/../../../ui \ +	$(KOFFICE_INCLUDES) \ +	$(all_includes) + +kde_module_LTLIBRARIES = kritacolorrange.la + +kritacolorrange_la_SOURCES = colorrange.cc dlg_colorrange.cc wdg_colorrange.ui +noinst_HEADERS = wdg_colorrange.h dlg_colorrange.h colorrange.h + +kritacolorrange_la_LIBADD =  ../../../libkritacommon.la +kritacolorrange_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) + +kritarcdir = $(kde_datadir)/kritaplugins +kritarc_DATA = colorrange.rc +EXTRA_DIST = $(kritarc_DATA) + +kde_services_DATA = kritacolorrange.desktop + +kritacolorrange_la_METASOURCES = AUTO + +KDE_OPTIONS = nofinal diff --git a/krita/plugins/viewplugins/colorrange/colorrange.cc b/krita/plugins/viewplugins/colorrange/colorrange.cc new file mode 100644 index 000000000..9c52e027e --- /dev/null +++ b/krita/plugins/viewplugins/colorrange/colorrange.cc @@ -0,0 +1,82 @@ +/* + * colorrange.h -- Part of Krita + * + * Copyright (c) 2004 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 <math.h> + +#include <stdlib.h> + +#include <qslider.h> +#include <qpoint.h> + +#include <klocale.h> +#include <kiconloader.h> +#include <kinstance.h> +#include <kmessagebox.h> +#include <kstandarddirs.h> +#include <ktempfile.h> +#include <kdebug.h> +#include <kgenericfactory.h> + +#include <kis_doc.h> +#include <kis_image.h> +#include <kis_layer.h> +#include <kis_paint_device.h> +#include <kis_global.h> +#include <kis_types.h> +#include <kis_view.h> +#include <kis_selection.h> +#include <kis_selection_manager.h> +#include "colorrange.h" +#include "dlg_colorrange.h" + +typedef KGenericFactory<ColorRange> ColorRangeFactory; +K_EXPORT_COMPONENT_FACTORY( kritacolorrange, ColorRangeFactory( "krita" ) ) + +ColorRange::ColorRange(QObject *parent, const char *name, const QStringList &) +    : KParts::Plugin(parent, name) +{ + +    if (parent->inherits("KisView")) { +        setInstance(ColorRangeFactory::instance()); +        setXMLFile(locate("data","kritaplugins/colorrange.rc"), true); +        m_view = dynamic_cast<KisView*>(parent); +        m_view->canvasSubject()->selectionManager()->addSelectionAction( new KAction(i18n("&Color Range..."), 0, 0, this, SLOT(slotActivated()), actionCollection(), "colorrange") ); + +    } +} + +ColorRange::~ColorRange() +{ +} + +void ColorRange::slotActivated() +{ +    KisPaintDeviceSP layer = m_view->canvasSubject()->currentImg()->activeDevice(); +    if (!layer) return; + +    DlgColorRange * dlgColorRange = new DlgColorRange(m_view, layer, m_view, "ColorRange"); +    Q_CHECK_PTR(dlgColorRange); + +    dlgColorRange->exec(); +} + +#include "colorrange.moc" + diff --git a/krita/plugins/viewplugins/colorrange/colorrange.h b/krita/plugins/viewplugins/colorrange/colorrange.h new file mode 100644 index 000000000..1cc10cef9 --- /dev/null +++ b/krita/plugins/viewplugins/colorrange/colorrange.h @@ -0,0 +1,44 @@ +/*  + * colorrange.h -- Part of Krita + * + *  Copyright (c) 2004 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. + */ + +#ifndef COLORRANGE_H +#define COLORRANGE_H + +#include <kparts/plugin.h> + +class KisView; + +class ColorRange : public KParts::Plugin +{ +        Q_OBJECT +    public: +        ColorRange(QObject *parent, const char *name, const QStringList &); +        virtual ~ColorRange(); +     +    private slots: +        void slotActivated(); + +    private: +        KisView * m_view; +        KisPainter * m_painter; + +}; + +#endif // COLORRANGE_H diff --git a/krita/plugins/viewplugins/colorrange/colorrange.rc b/krita/plugins/viewplugins/colorrange/colorrange.rc new file mode 100644 index 000000000..344fad33a --- /dev/null +++ b/krita/plugins/viewplugins/colorrange/colorrange.rc @@ -0,0 +1,10 @@ +<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd"> +<kpartgui library="kritacolorrange" version="1"> +<MenuBar> +    <Menu name="Select"><text>Select</text> +	<Separator/> +	<Action name="colorrange"/> +	<Separator/> +    </Menu> +</MenuBar> +</kpartgui> diff --git a/krita/plugins/viewplugins/colorrange/dlg_colorrange.cc b/krita/plugins/viewplugins/colorrange/dlg_colorrange.cc new file mode 100644 index 000000000..1cd115c12 --- /dev/null +++ b/krita/plugins/viewplugins/colorrange/dlg_colorrange.cc @@ -0,0 +1,351 @@ +/* + *  dlg_colorrange.cc - part of KimageShop^WKrayon^WKrita + * + *  Copyright (c) 2004 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 <qapplication.h> +#include <qpushbutton.h> +#include <qcheckbox.h> +#include <qslider.h> +#include <qcombobox.h> +#include <qpixmap.h> +#include <qimage.h> +#include <qlabel.h> +#include <qcolor.h> +#include <qradiobutton.h> + +#include <knuminput.h> +#include <klocale.h> +#include <kdebug.h> +#include <kaction.h> + +#include <kis_canvas_subject.h> +#include <kis_iterators_pixel.h> +#include <kis_layer.h> +#include <kis_paint_device.h> +#include <kis_selection.h> +#include <kis_selection_manager.h> +#include <kis_types.h> +#include <kis_undo_adapter.h> +#include <kis_view.h> +#include <kis_colorspace.h> +#include <kis_profile.h> +#include <kis_color_conversions.h> +#include <kis_selected_transaction.h> +#include <kis_cursor.h> + +#include "dlg_colorrange.h" +#include "wdg_colorrange.h" + +namespace { + +// XXX: Poynton says: hsv/hls is not what one ought to use for colour calculations. +//      Unfortunately, I don't know enough to be able to use anything else. + +    bool isReddish(int h) +    { +        return ((h > 330 && h < 360) || ( h > 0 && h < 40)); +    } + +    bool isYellowish(int h) +    { +        return (h> 40 && h < 65); +    } + +    bool isGreenish(int h) +    { +        return (h > 70 && h < 155); +    } + +    bool isCyanish(int h) +    { +        return (h > 150 && h < 190); +    } + +    bool isBlueish(int h) +    { +        return (h > 185 && h < 270); +    } + +    bool isMagentaish(int h) +    { +        return (h > 265 && h < 330); +    } + +    bool isHighlight(int v) +    { +        return (v > 200); +    } + +    bool isMidTone(int v) +    { +        return (v > 100 && v < 200); +    } + +    bool isShadow(int v) +    { +        return (v < 100); +    } + +} + +Q_UINT32 matchColors(const QColor & c, enumAction action) +{ +    int r = c.red(); +    int g = c.green(); +    int b = c.blue(); + +    int h, s, v; +    rgb_to_hsv(r, g, b, &h, &s, &v); + + + +    // XXX: Map the degree in which the colors conform to the requirement +    //      to a range of selectedness between 0 and 255 + +    // XXX: Implement out-of-gamut using lcms + +    switch(action) { + +        case REDS: +            if (isReddish(h)) +                return MAX_SELECTED; +            else +                return MIN_SELECTED; +        case YELLOWS: +            if (isYellowish(h)) { +                return MAX_SELECTED; +            } +            else +                return MIN_SELECTED; +        case GREENS: +            if (isGreenish(h)) +                return MAX_SELECTED; +            else +                return MIN_SELECTED; +        case CYANS: +            if (isCyanish(h)) +                return MAX_SELECTED; +            else +                return MIN_SELECTED; +        case BLUES: +            if (isBlueish(h)) +                return MAX_SELECTED; +            else +                return MIN_SELECTED; +        case MAGENTAS: +            if (isMagentaish(h)) +                return MAX_SELECTED; +            else +                return MIN_SELECTED; +        case HIGHLIGHTS: +            if (isHighlight(v)) +                return MAX_SELECTED; +            else +                return MIN_SELECTED; +        case MIDTONES: +            if (isMidTone(v)) +                return MAX_SELECTED; +            else +                return MIN_SELECTED; +        case SHADOWS: +            if (isShadow(v)) +                return MAX_SELECTED; +            else +                return MIN_SELECTED; +    }; + +    return MIN_SELECTED; +} + + + +DlgColorRange::DlgColorRange( KisView * view, KisPaintDeviceSP dev, QWidget *  parent, const char * name) +    : super (parent, name, true, i18n("Color Range"), Ok | Cancel, Ok) +{ +    m_dev = dev; +    m_view = view; + +    m_subject = view->canvasSubject(); + +    m_page = new WdgColorRange(this, "color_range"); +    Q_CHECK_PTR(m_page); + +    setCaption(i18n("Color Range")); +    setMainWidget(m_page); +    resize(m_page->sizeHint()); + +    if (m_dev->image()->undo()) m_transaction = new KisSelectedTransaction(i18n("Select by Color Range"), m_dev); + +    if(! m_dev->hasSelection()) +        m_dev->selection()->clear(); +    m_selection = m_dev->selection(); + +    updatePreview(); + +    m_invert = false; +    m_mode = SELECTION_ADD; +    m_currentAction = REDS; + +    connect(this, SIGNAL(okClicked()), +        this, SLOT(okClicked())); + +    connect(this, SIGNAL(cancelClicked()), +        this, SLOT(cancelClicked())); + +    connect(m_page->chkInvert, SIGNAL(clicked()), +        this, SLOT(slotInvertClicked())); + +    connect(m_page->cmbSelect, SIGNAL(activated(int)), +        this, SLOT(slotSelectionTypeChanged(int))); + +    connect (m_page->radioAdd, SIGNAL(toggled(bool)), +         this, SLOT(slotAdd(bool))); + +    connect (m_page->radioSubtract, SIGNAL(toggled(bool)), +         this, SLOT(slotSubtract(bool))); + +    connect (m_page->bnSelect, SIGNAL(clicked()), +        this, SLOT(slotSelectClicked())); + +    connect (m_page->bnDeselect, SIGNAL(clicked()), +        this, SLOT(slotDeselectClicked())); + +} + +DlgColorRange::~DlgColorRange() +{ +    delete m_page; +} + + +void DlgColorRange::updatePreview() +{ +    if (!m_selection) return; + +    Q_INT32 x, y, w, h; +    m_dev->exactBounds(x, y, w, h); +    QPixmap pix = QPixmap(m_selection->maskImage().smoothScale(350, 350, QImage::ScaleMin)); +    m_subject->canvasController()->updateCanvas(); +    m_page->pixSelection->setPixmap(pix); +} + +void DlgColorRange::okClicked() +{ +    m_dev->setDirty(); +    m_dev->emitSelectionChanged(); + +    if (m_dev->image()->undo()) m_subject->undoAdapter()->addCommand(m_transaction); +    accept(); +} + +void DlgColorRange::cancelClicked() +{ +    if (m_dev->image()->undo()) m_transaction->unexecute(); + +    m_subject->canvasController()->updateCanvas(); +    reject(); +} + +void DlgColorRange::slotInvertClicked() +{ +    m_invert = m_page->chkInvert->isChecked(); +} + +void DlgColorRange::slotSelectionTypeChanged(int index) +{ +    m_currentAction = (enumAction)index; +} + +void DlgColorRange::slotSubtract(bool on) +{ +    if (on) +        m_mode = SELECTION_SUBTRACT; +} +void DlgColorRange::slotAdd(bool on) +{ +    if (on) +        m_mode = SELECTION_ADD; +} + +void DlgColorRange::slotSelectClicked() +{ +    QApplication::setOverrideCursor(KisCursor::waitCursor()); +    // XXX: Multithread this! +    Q_INT32 x, y, w, h; +    m_dev->exactBounds(x, y, w, h); +    KisColorSpace * cs = m_dev->colorSpace(); +    Q_UINT8 opacity; +    for (int y2 = y; y2 < h - y; ++y2) { +        KisHLineIterator hiter = m_dev->createHLineIterator(x, y2, w, false); +        KisHLineIterator selIter = m_selection ->createHLineIterator(x, y2, w, true); +        while (!hiter.isDone()) { +            QColor c; + +            cs->toQColor(hiter.rawData(), &c, &opacity); +            // Don't try to select transparent pixels. +            if (opacity > OPACITY_TRANSPARENT) { +                Q_UINT8 match = matchColors(c, m_currentAction); + +                if (match) { +                    // Personally, I think the invert option a bit silly. But it's possible I don't quite understand it. BSAR. +                    if (!m_invert) { +                        if (m_mode == SELECTION_ADD) { +                            *(selIter.rawData()) =  match; +                        } +                        else if (m_mode == SELECTION_SUBTRACT) { +                            Q_UINT8 selectedness = *(selIter.rawData()); +                            if (match < selectedness) { +                                *(selIter.rawData()) = selectedness - match; +                            } +                            else { +                                *(selIter.rawData()) = 0; +                            } +                        } +                    } +                    else { +                        if (m_mode == SELECTION_ADD) { +                            Q_UINT8 selectedness = *(selIter.rawData()); +                            if (match < selectedness) { +                                *(selIter.rawData()) = selectedness - match; +                            } +                            else { +                                *(selIter.rawData()) = 0; +                            } +                        } +                        else if (m_mode == SELECTION_SUBTRACT) { +                            *(selIter.rawData()) =  match; +                        } +                    } +                } +            } +            ++hiter; +            ++selIter; +        } +    } +    updatePreview(); +    QApplication::restoreOverrideCursor(); +} + +void DlgColorRange::slotDeselectClicked() +{ +    m_dev->selection()->clear(); +    updatePreview(); +} + + +#include "dlg_colorrange.moc" diff --git a/krita/plugins/viewplugins/colorrange/dlg_colorrange.h b/krita/plugins/viewplugins/colorrange/dlg_colorrange.h new file mode 100644 index 000000000..5a792abd6 --- /dev/null +++ b/krita/plugins/viewplugins/colorrange/dlg_colorrange.h @@ -0,0 +1,99 @@ +/* + *  dlg_colorrange.h -- part of KimageShop^WKrayon^WKrita + * + *  Copyright (c) 2004 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. + */ +#ifndef DLG_COLORRANGE +#define DLG_COLORRANGE + +#include <qcursor.h> + +#include <kdialogbase.h> + +#include <kis_types.h> + +#include <kis_selection.h> // For enums +#include <kis_types.h> +#include <kis_global.h> + + +class KisView; +class KisCanvasSubject; +class DlgColorRange; +class KisSelectedTransaction; +class WdgColorRange; + +enum enumAction { +    REDS, +    YELLOWS, +    GREENS, +    CYANS, +    BLUES, +    MAGENTAS, +    HIGHLIGHTS, +    MIDTONES, +    SHADOWS +}; + + + /** + * This dialog allows the user to create a selection mask based + * on a (range of) colors. + */ +class DlgColorRange: public KDialogBase { +    typedef KDialogBase super; +    Q_OBJECT + + + +public: + +    DlgColorRange(KisView * view, KisPaintDeviceSP layer, QWidget * parent = 0, const char* name = 0); +    ~DlgColorRange(); + +private slots: + +    void okClicked(); +    void cancelClicked(); + +    void slotInvertClicked(); +    void slotSelectionTypeChanged(int index); +    void updatePreview(); +    void slotSubtract(bool on); +    void slotAdd(bool on); +    void slotSelectClicked(); +    void slotDeselectClicked(); + +private: +    QImage createMask(KisSelectionSP selection, KisPaintDeviceSP layer); + +private: + +    WdgColorRange * m_page; +    KisSelectionSP m_selection; +    KisPaintDeviceSP m_dev; +    KisView * m_view; +    KisCanvasSubject * m_subject; +    enumSelectionMode m_mode; +    QCursor m_oldCursor; +    KisSelectedTransaction *m_transaction; +    enumAction m_currentAction; +    bool m_invert; +}; + + +#endif // DLG_COLORRANGE diff --git a/krita/plugins/viewplugins/colorrange/kritacolorrange.desktop b/krita/plugins/viewplugins/colorrange/kritacolorrange.desktop new file mode 100644 index 000000000..22b070eb9 --- /dev/null +++ b/krita/plugins/viewplugins/colorrange/kritacolorrange.desktop @@ -0,0 +1,40 @@ +[Desktop Entry] +Name=Colorrange +Name[bg]=Цветови обхват +Name[ca]=Rang de color +Name[da]=Farveområde +Name[de]=Farbbereich +Name[el]=Χρωματικό εύρος +Name[en_GB]=Colourrange +Name[eo]=Kolorgamo +Name[et]=Värvivahemik +Name[fa]=گسترۀ رنگ +Name[fr]=Plage de couleurs +Name[fy]=Kleurberik +Name[gl]=Gamas de Cores +Name[he]=טווח צבעים +Name[hu]=Egyszerű +Name[is]=Litasvið +Name[it]=Intervallo di colori +Name[ja]=色の範囲 +Name[km]=ជួរពណ៌ +Name[nb]=Fargeområde +Name[nds]=Klörenrebeet +Name[ne]=रङदायरा +Name[nl]=Kleurbereik +Name[pl]=Zakres kolorów +Name[pt]=Gamas de Cores +Name[pt_BR]=Intervalos de Cores +Name[ru]=Цвета +Name[se]=Ivdnegaskkadat +Name[sk]=Rozsah farieb +Name[sl]=Barvni razpon +Name[sr]=Опсег боја +Name[sr@Latn]=Opseg boja +Name[sv]=Färgintervall +Name[uk]=Діапазон кольорів +Name[zh_TW]=色彩範圍 +ServiceTypes=Krita/ViewPlugin +Type=Service +X-KDE-Library=kritacolorrange +X-Krita-Version=2 diff --git a/krita/plugins/viewplugins/colorrange/wdg_colorrange.ui b/krita/plugins/viewplugins/colorrange/wdg_colorrange.ui new file mode 100644 index 000000000..e9ed74f5e --- /dev/null +++ b/krita/plugins/viewplugins/colorrange/wdg_colorrange.ui @@ -0,0 +1,252 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>WdgColorRange</class> +<widget class="QWidget"> +    <property name="name"> +        <cstring>WdgColorRange</cstring> +    </property> +    <property name="geometry"> +        <rect> +            <x>0</x> +            <y>0</y> +            <width>515</width> +            <height>528</height> +        </rect> +    </property> +    <property name="caption"> +        <string>Color Range</string> +    </property> +    <vbox> +        <property name="name"> +            <cstring>unnamed</cstring> +        </property> +        <widget class="QLayoutWidget"> +            <property name="name"> +                <cstring>layout10</cstring> +            </property> +            <hbox> +                <property name="name"> +                    <cstring>unnamed</cstring> +                </property> +                <widget class="QLayoutWidget"> +                    <property name="name"> +                        <cstring>layout8</cstring> +                    </property> +                    <vbox> +                        <property name="name"> +                            <cstring>unnamed</cstring> +                        </property> +                        <widget class="QLayoutWidget"> +                            <property name="name"> +                                <cstring>layout7</cstring> +                            </property> +                            <hbox> +                                <property name="name"> +                                    <cstring>unnamed</cstring> +                                </property> +                                <widget class="QComboBox"> +                                    <item> +                                        <property name="text"> +                                            <string>Reds</string> +                                        </property> +                                    </item> +                                    <item> +                                        <property name="text"> +                                            <string>Yellows</string> +                                        </property> +                                    </item> +                                    <item> +                                        <property name="text"> +                                            <string>Greens</string> +                                        </property> +                                    </item> +                                    <item> +                                        <property name="text"> +                                            <string>Cyans</string> +                                        </property> +                                    </item> +                                    <item> +                                        <property name="text"> +                                            <string>Blues</string> +                                        </property> +                                    </item> +                                    <item> +                                        <property name="text"> +                                            <string>Magentas</string> +                                        </property> +                                    </item> +                                    <item> +                                        <property name="text"> +                                            <string>Highlights</string> +                                        </property> +                                    </item> +                                    <item> +                                        <property name="text"> +                                            <string>Midtones</string> +                                        </property> +                                    </item> +                                    <item> +                                        <property name="text"> +                                            <string>Shadows</string> +                                        </property> +                                    </item> +                                    <item> +                                        <property name="text"> +                                            <string>Out of Gamut</string> +                                        </property> +                                    </item> +                                    <property name="name"> +                                        <cstring>cmbSelect</cstring> +                                    </property> +                                </widget> +                                <widget class="QCheckBox"> +                                    <property name="name"> +                                        <cstring>chkInvert</cstring> +                                    </property> +                                    <property name="text"> +                                        <string>&Invert</string> +                                    </property> +                                </widget> +                            </hbox> +                        </widget> +                        <widget class="QButtonGroup"> +                            <property name="name"> +                                <cstring>grpSelection</cstring> +                            </property> +                            <property name="title"> +                                <string></string> +                            </property> +                            <vbox> +                                <property name="name"> +                                    <cstring>unnamed</cstring> +                                </property> +                                <widget class="QRadioButton"> +                                    <property name="name"> +                                        <cstring>radioAdd</cstring> +                                    </property> +                                    <property name="text"> +                                        <string>&Add to current selection</string> +                                    </property> +                                    <property name="checked"> +                                        <bool>true</bool> +                                    </property> +                                </widget> +                                <widget class="QRadioButton"> +                                    <property name="name"> +                                        <cstring>radioSubtract</cstring> +                                    </property> +                                    <property name="text"> +                                        <string>&Subtract from current selection</string> +                                    </property> +                                </widget> +                            </vbox> +                        </widget> +                    </vbox> +                </widget> +                <widget class="QLayoutWidget"> +                    <property name="name"> +                        <cstring>layout9</cstring> +                    </property> +                    <vbox> +                        <property name="name"> +                            <cstring>unnamed</cstring> +                        </property> +                        <widget class="QPushButton"> +                            <property name="name"> +                                <cstring>bnSelect</cstring> +                            </property> +                            <property name="text"> +                                <string>&Select</string> +                            </property> +                        </widget> +                        <widget class="QPushButton"> +                            <property name="name"> +                                <cstring>bnDeselect</cstring> +                            </property> +                            <property name="text"> +                                <string>&Deselect</string> +                            </property> +                        </widget> +                        <spacer> +                            <property name="name"> +                                <cstring>spacer9</cstring> +                            </property> +                            <property name="orientation"> +                                <enum>Vertical</enum> +                            </property> +                            <property name="sizeType"> +                                <enum>Expanding</enum> +                            </property> +                            <property name="sizeHint"> +                                <size> +                                    <width>20</width> +                                    <height>40</height> +                                </size> +                            </property> +                        </spacer> +                    </vbox> +                </widget> +            </hbox> +        </widget> +        <widget class="QGroupBox"> +            <property name="name"> +                <cstring>grpPreview</cstring> +            </property> +            <property name="sizePolicy"> +                <sizepolicy> +                    <hsizetype>7</hsizetype> +                    <vsizetype>7</vsizetype> +                    <horstretch>1</horstretch> +                    <verstretch>1</verstretch> +                </sizepolicy> +            </property> +            <property name="title"> +                <string>Preview</string> +            </property> +            <property name="flat"> +                <bool>false</bool> +            </property> +            <grid> +                <property name="name"> +                    <cstring>unnamed</cstring> +                </property> +                <widget class="QLabel" row="0" column="0"> +                    <property name="name"> +                        <cstring>pixSelection</cstring> +                    </property> +                    <property name="sizePolicy"> +                        <sizepolicy> +                            <hsizetype>7</hsizetype> +                            <vsizetype>7</vsizetype> +                            <horstretch>1</horstretch> +                            <verstretch>1</verstretch> +                        </sizepolicy> +                    </property> +                    <property name="frameShape"> +                        <enum>NoFrame</enum> +                    </property> +                    <property name="frameShadow"> +                        <enum>Plain</enum> +                    </property> +                    <property name="pixmap"> +                        <pixmap>image0</pixmap> +                    </property> +                    <property name="scaledContents"> +                        <bool>false</bool> +                    </property> +                    <property name="alignment"> +                        <set>AlignCenter</set> +                    </property> +                </widget> +            </grid> +        </widget> +    </vbox> +</widget> +<images> +    <image name="image0"> +        <data format="XPM.GZ" length="55092">789cccbd47b7eb38b2ef397f9fa2d6e5ecae5e7cf266d0035266cb6da7ed77af1ed07b2f1aa9bf7c83883f704c56d5cd7c75bb5f95d6c9ca5f8a22114044202200f0fccffffcdbe7d3fddffef37ffe8fea625c02eb6f966f947ffb4fbb4e92ebfff57fff9fffcffff88fe160f0b7fecf68389bfe6df41fffc7fff80febf96fd6df9401ff5fcff64232ffde36244f7a762ac953fefd56f29cf35cf2a267f3072ff9f733c906e7836493f35eb2c59fd74ab6797b1f243bfcfb46b2cb7fef0a1e72799c5af2907f7f94cce5732cc963fefd483297cf3a8387d43f992999ffde0c25f3dfb79a64de5f662099dfcfe924cf386f24f3fe4a44ff0fd17e5b327f9e772799dfcfb8078fa87d662499cbebbb9249de6fc9bcbd9d2f99dab795ccc7b31a48e6e3b71a4ae6e315ed25f3f1b04f82a93f0dc1636a9ff32999daf32599f757a54ae6fde17e48e6fae23892b97e78a2bd63ea1f438cef849e97e892f9f7652b99b76f3d91cce53763f0947e6f08fd9c1137b664de5e43c83fc7f53bf0022cf475499c8be719c4f113d824de5cc01671fd0eb6895dbaff50d8ab174ae6f2ad3ac9a47f63c924df4832d73f732a99f777f324998fb73993ccfb5f7f96ccc7df3a49e6e3514592b9bd3aa664ae1fd6bd646eaf9a2b98f4ddf52573fdb58e60d89f6d49e6df9b13c97c3c1d45326fbf634826ffb2934cfee40086fdf88164de7ff65232d9eb9b646e1fa607867e9bbe641a8f816092cf14f2423f4d070c7d8b9f25f3e7bbaf60e89fb791ccfb3b15df43ffe22f30f42f13f240ffea1b18fab716bf877ee967b043dc92bf1f0ea16fdd9af3a8f740bc3dbe64f2f70bc9bcbfcd2fc9bcbfbd4432f90b4730f5cff55e3297bfc9c0187f732899f4772099c6e35b321f7f6b0fc6f8daa6649aff7692f9f3724d32d7f7cb4932ef6ffb4e32e9b302c6f86723c9dcdefc50326f9ff32e99f7975382a10fd75c32d7e795906742fdd3bd49e6df67a2bdd09ff20886beb89164fefcd54932ef9ffa2c98fca72bda0b7d6a9f25f3feb0c4f842bf9a07b0d02fd13fd0afe2090cffd6c660e85b24ae87be05a40f63e1df8277c9bc7debab643e5e575732efef6e2799cb1bfcf89ecbdbed2573fd5cfd781e1fcf952d98fa3b91cf277f74cd24f3fe0f3ec08807ba8d64ae9fc54232e98f27993faff9f13df787ae680ff4d57995cce57103c95c7fac3bc97c7c7c5f308d67b8028bf9f72299cbd3dc49e6f2981f92797fd69664de5f7e2499dbb33b92ccdb6f2dc1d067772099fca72e99b7ff6a49a6f946f437f4b9bd48267934b0d0ef77c9bc7dad68df9cee9fee25f3fe69447fcc31df88f1843eaf6e92f9f3da89649a0fee25f3f1cb85be41ff0331bed07f5f8ca7f0a7d43f13a1df9d2a99f777f32899dfffea80111faeae92b93cee41f090f7effa0c463ce77f48a6f9ee51321fafeb4930f547bb01433fecb164fe7cff5b321f2f2f92ccfb3f93d793bd745b30f421ae2593bfd94be6fd1b2692b93cde4e32b79fda164ced8ddec1d017e74332f9dbb564de5e772899e299140c7dcaa692b93db8df92797fe61d18fe3117e303fd59b792e979b164de3f8918ff05f5cf46f40ff4c715e301fdb9bd80e13f57f792797fad4a30fce906bf17f3f51ae331c4fc19a13d43f89780e693a9f0a7ed028cebfd4e321fafe6198c7cc00b2473f9bc77c95cdf4a4ff0908fc75a5c8f78bfb52553fcf02999ebbfdf08a6f10e5ec1c2bfdc49a6f97c2b99e6ff27c9642f3fbee7fab416f2407fc299643efe912f99ec692099cbd3b492b9bc9ab8ff94c63711fd0bfdb2a792c93e2ac9140f689229df5125f3feed5660e85ffd2a99fce34432efdfee00867e5e14c9941f8ec0d0bfcc904cf9572a99b7a76e25f3fe73c760a1afaa646ebf99e85fe86f2ec61bfaea0b79e11f0ba12f2eda8bfb4b7d267b98897c64dd81a1cfeb503297afbd934cf1d45e30fc93f81ef363b896ccefbf3a4a26793dc1149fae7d30f247ff2a99ea1d3fbee7fed68b05a31eb1924cf9c2083ca5f6076bc9542fd948e6fa900e2473fdbbbc09463d630246be1a6692f9f84481643edef95532b73f5df01cfd7993ccdb7be92453beb5924cf3c14432efbf5cfc7e01fffa2999e6bfb1646e5f9b022ce2cba364de3e37114cfec132c0d047f74d32f9e37b30f26b2f05431f5763c9bc7f42c1d04797e6cf99d0c71be41fc21fa52a18fe24207d9f0bfd5a1d04d3f8570fe009d573dca3642e7fbb054f697ca237c1246f3a944cf53a5b32c5a72f60f81bd796ccaf4f2bc994af2d2593be6f2453bea682e7345eed4e32d5ff14c9bcbf2f57c95cff7dd15ef8a35097ccdb93cd25537e2bfa6b3124fffd055ec2bfcc24537c548045fe518331decda7647ebd2eda6ba37fc478c01f6d44ffb8d43e1ded17e3af3960cc97f5022cf481e257a6dd149fd96bf08cc6ffe64aa6f92604c35eec4032b7efab2799e2375b30e94b2aae5f50ff58aa642e6fe148a67ce1065e927fb80d2553bd2494cc9fdf3e49a6fc45c863c07e1dc97cfcd3a3606a5f7d05633e887682497faf4bb08df8e2030cfb2bc9de17a2ff4bf49f886762f4cf10f666bd80618f3e8dff92f5177f5e914be6ed2f36e005c91b5f24533cf22598ecafeec04be467ae64f28757b041bfaf5f040f29fe68c0268d9726da63917e14a2bdd0c7f424998f5f44fdb314fd91bf83a18f8105467fdc4660e86783e789fee94a30e215e3118c78a3a0f9dc60fd45fa34072f491fc329d8a0f685a964aae7dfc0265d5f2f05537f568f60d86bb091ccfbe36248e6fad988dfbba85f8e24533e48f66f88fe892b30fa67634ba6f97508467f6d1cb0a827435ed11f35fa6388f9c9a7f8c814f157fd065e92fe5f6e6083e42f5cb0897ac417d8227dca3fc036f55fb305431fba77c1747f3b02bba4df3ad9ab29e42f669229df46fb647fe460d8d3aa0243fecd2758d4bbefc0a21eb403a33f2a8a772c263f6fff35055ba827d1f85aa2bf2f1a58f4f70a8cfb252a18febdf1c0f02701f58f2dda7f5d48a6fe9b8071fff21d2cfc83603caf51c1b87fb106433f4b1a1f87fd17eebf1b17ec903efbd43e46b0f71a0c79cb2d58c4e72d18cf2f1bb078be0dc6f3339abf5cd11f8906c6f5de1a8cf846e3f6c1cbe724df068cf6548964ae3f1b130c7f9096608c7f7603a3bde90e8ce7bb2f60b4d77e00c39f075c9f98f639e47fa34832d7e7f84c2c9eb7ba80216ffb08c6f3cc042cd64f1a30e42f9760d88fe382d19e1ced19c11e42aebf0cf17cd306435ecb04a33d610e16f20b16f1470a16ed3981457cf9443c82bdae2660e19f79bc341c8be7d70e18cfd71ec022df8ac178feaa05e379d72bf108e3df70ff369cc8fe1d8345bc9c81d1fe60452cfaeb7a03c3be74ba7e2adbd382f1fbcb3b18e3910dc1689f4df24e657fd4603cafb2c168bffb0cc6f32b1ebf0c67e2fe01e9d34cdcef1283e12faa6f30ee67f860e1ffe660a1efdc7f0ee7e2fed58c58b6e70cc6ef8d002cd6173db0a83f2dc0d0b78edbf77021e5bd078bf6aec1f87d41fabd14f2155bb0f8fd108cdfeb2330da93de83f1fc8ac6d310f2ac1a309ed772ff3734c5fdb48d64ee0fb72e58d4e75ec0f87d7202a33f0d713df4a5237bb7e4782a60b11ee681d15eed112cee1782a1cf158f4f86b6b8bf6581c5fa2af5a733823f762d30eed7d2efdd11f2efcd1d18d76bdc5e468311f2a3c007e379f5082cea75f760e8fbfa8d782cf49dfba3d150fcbebc030b7bdc83a17f099faf472371ffe64c2ceed73460e883cefb6b3416f7ab4fc463e10f2c30e46b8927e279b94b2cee6f6cc1d087ec092cec4930c6f342f24f85fc46442caef75660e8cf85fb93d18cfd9ec783f1162ceaa37cfe19cdc5fd3ceabfb990d79d80d13eeb152cd64fe9fa85f8de7c05a33df9188cf66cbec0d0c7f50d0c7df3b8ff1f2d85bcce002ce227078ceb1d0f2cfca54e3c41fb6f74bd21ef5780f17c5d058bf53beeaf46e618ebd77a2299c77f5bba9f25c6b7f4c1c2bfbd80d19eeb07f104fda1933cb678de2603e37eba01c6ef6f57b0a8ff71ff3d72c6a8b7e8d47faee88fb507c6effd188cdf3bdc1ec67d38c739e2e3c5a63393e21723269e60fde4f22c99d677b93e307577285eb7b8fd8f27ecfe9cf50e0c7d8a79ff8ca7ec7bfefb6b412cc627db81c57e823730ead9eb1158d43fb8bce399b8fe7a0716eb5d7330c663c3fb733c67eda1fa484d2cc6c39a83a11fed193ca57a651282b13e16f3f96ebc9860bdc8d880c5fe810c2cf21bae8fe3e544d4cb23c93c5ed30a30ea071b170cff92d0f81813d443d71730eaed9a07c6f53eb7b7b1c9bee7fa117c49a6f5024b30c5b3760cb6b19ec9e3adb13331e8face93ccfbaf3883f13c23013ba8a72e05d3fd0d1b8c7c734df23b53d8df86facf9da03e7e1b80f1fc82f7e76430813e6d63e229fa3be5e333194e4cd40b52b04ded31b8fe4e4653110ff2fa0a73a736f28d9a788afd67fa180cfd6a1db0588fe3fe7f32610accfb77c3f59721f2c77c493cc5fe0aaf00e37eb731788afa4e059ed1f8361f60d48f6dde1f93d914ebc7460a46bd2fe4fd37994fc7940f6cbec1e89f98cf5f93a578def5013c433d86da6f4c51bf09b9bd4dcce982f2b39cebcbc49a22fff6b83e4dec29ea15d95932adb704c433acffebf43c776ad1fd039d7886f5d315bf3f5356f09acf77d3d1d4a5fa65734f3cc3fe035d134cf7372c30ec355b824dc413dc3fb0e9906574dcdf79c4e2f74501c6fa5b74104cdfb73c3e9d4ea6d6887f7fdb10b3e791bef1f9940ddf1ceb078fe005f5b7c5e7e3e96c86f58f8d0246fd3a76c1f311f9b377b043e31bf07c693a9fa1de19df816dec07f804bb584fa3fe5accc47a86069e517b82002cd6f775b043f39bc6e3dde9923d8eeb7332035bd47f3705ec60ff824d3cc7fecf84ebefd498c19e2faf609bfa2be6f9f0d49c2d51cff5c016e5fb2b176c8f78fb8b15d8a5fa99c9e7d7a93543fdab1b831dfafde6287844f5d10e8cf1af49bfac39c63bff024f499e98ee6fb3fb937f7d023bd4fed407bb435aafb124d37e2d5d30b53f03cf87d43eeb0d8cf5dd7803c67cb7e1f63d75587f707df1e9fece7c30a2fd5d7b30f6b3469f9269fdc792cce5594dc1587fba52ffb84c1edebecd5e326f7f41faebceb19f2cda8271bfa6133ca2e727e0118d4fb2164cfa9c2892f978af4c30eca1f1c19321d7bf2bff7e3660e34ff5e53bb043cfaf5dc174bf6c0076a97fdb929805acfcfb6d0446bdbee4ed9f0d857eddd660f89b6e2298da5f05c4ac3f687e6bc0c311ad87e07a263f9f0fda77f094da537f8067245fc5f569369a1963d29f2b31eb5fdabfe20ba6e7a777e0d188ff3eb9815906c29fa78227d04f053ca3f6b65c3f6663260fd553a93d2cfca4fec91bc95cfeea041e517f5fb8fece2662fcdd023c86ff33c1d31167cd06cf21cf5c308d679d8017d41f0df72fb3e9cc1ef3ebab14ec8c69bfc05432ed47d38885fe5d4cc9b4fe37028fc8fecb37c9649f25784cf6ebbf82e7f47dbc042fe87e05f5cf4ce8936b82e7f4fb36113ca6f17a002fe8f986b8de80fe8bef4dd28fc292cce52fa68269fc4d1effb0db2f49decd0c0c7fdc92fe2ce6131a3f6d2d98fcb7bf02cf49bf370330d68fea5a30fdde38831dfabea3fe59b2fea178b0009bd41e4f03db23aeff37713decb5f00593fc2df5a7c1ee47eb6f2330eadd17156c8ea87ff7609bfc45590b267f78d5c02e714bfa6ab2f1207ff80136c87ef22918f34dfe06c67cd186c48b018dafcee3cd99c5ee47faa48217647f99609bf4c7a0f1b2160392afa3f6da6cfc68bcd69279ff949f6093daef4ec1f067f5817831a4e76de8f70ebb9ece177c806d6abfb3235ec0dfba2bc9b4df9bc6d7ed1376ae5f5c3fe703263f6f4f520a1e53fc99102f66d4be8cf7cf7cc8e4e3d7673e784c7cdd82a7d4de5a03c3fe751e9f3265c2fca09be009d94fc2e397394b87c99f186bf08cfa4fe3fd3b9fb0e7717dacc792e97c0b8f5f58f8bb20d6793d613e5f2cc7b49fc5005bd49e35b56fb1c4fcecf1fe9e2fd9f7743dfdde582ca83f8267b049ed59f3f9686eb2eb69fd782699d62fa83de67244f67de1fa3eb79643b237ef2698f4ab9e8347d4feb0008fc99e1c6a8fbd70d05f4762261e6f9f46e3e730a6f3160618fdbbe6f9c6dc5d0ea8bd0df5bf6b88f89aebdfa25f00a5f8ff4e32edd749c0636aff66019ee17939780e7de2f92a73f643e8bb031e537b7c133c237bf5dec073ba7f44f71f1a225ea3e78f447f79dfe011ddcfe3f22dc68c29feff06e379ba0e9ed2ef0b1effb1747d44f3b1fd0d5ed2f78d0236c65cdf367c7e5fb0009858bf07cfd15f7bf082f4a3492473f96f19d8257b6df8f82e66cb05f55fbe223630ff6f797cbc98b3f67079527afe82319d17e1f6b7581a03fafdc693ccc7d7a0fb194b97da7bbb111b63f2af1bae9f0bd31810eb7cbd61612d1dd2bf94da671943c8cfe7af856d8c69be6e0563be594f2573fdd7b8bd2c1c763ded0f53c01392c7bb4ae6fdd3717d5db8c684fa4bbb134cdfa767f094e28180fba3e5c080fff15fc0b309f5ef9764d24ff13dfc43cae7a3e5d0807d6cf8782d47acbdfcfeed0b783ea1fad50ebca0ef6f3ed82079a32f30f2c5644f6c627f5acce7df655fd0e1e3930460a662dc3f1cc14beaaf40133ca178a8069bf47cdf90ccc74ff3c10e8de78dfa676c8afd09b564daff5982b1ff36a6f64c58ffd2fed40b7836a1fac504bc9c50fd6101c6fc97abc426e2b3700fc67911f3018cf33ac99d643e1edd198cf3176e07463da4fa0063bf8826be47bd53e7fe773965e345fded806db217eb1d8c78f29612b3f6923ea9603cbffb0663bf4949d7b38083c663b3022f68fceb7bb043f6118682a9ff8c02ec92bfcbe9fe7dba49f5c30d18fb636c9e2f2ce7ecf7144f2a6097e4bbe5c4ecf7140fcdc0b0b734018bfde03a784af3c53504cfb15f47dc0ffb0bbb8160ecbffc002fa95e58edc1d8bf1a4dc1163d2f36c1a8575495609c5f1a4aa6f3a134febd83e2ed2f376093faafa3e72fcc01f1f50b3c217ddd5660ac37ad63f00cfe5407cf69beef5230ea35c6026c60bfe55532e55b39d8a4eb6f73b0d8df20ee6f637fe04a32cdff03b043fd757b904cf9d9168c7ae7ed2299ce7b3692697fc898d8c2f99ddb128cf3b317f49f85fa6348f75f1a06d9afb604c37ff817b04dfa1c0ec10ee9bb4ef22ecd015d7fdd8047345eb5079e907e598e60d2d7b40363ffe3762598e2d5750e16e703d692297ffc128cf35768af897afb36108cfaee5c32d56b0f9269fe2e24f3f61731d880ff5125d37ed80558ac974c25d37ec09d64de7fe64132f73fea27d8a2f15732c9b4bea008a6f655a23fb1dfb28c24d3fe470d8c7ae1ed5132e95b2099cf8fa6e82fd4e3c32fc9b4bee3125b38ef7723ff641816d99b7d03dbe48fc22bd8a1f9f95a825d9adf4af28706eb1ede5eaf060fe97aaf133ca1fc5605237e6d8ee009e5bbd5198cf58b4efc1efb6fb71730f67bae66e025c5df8a09c6fecae020998fafd248a6f3ba909fd93b6f4f71025bb0af52329ddf9849e6cf533fc036e993924ba6f96726993f2fcec00ef57ff12e99e2c34a32ed7f0cc1f017d5bb649aef7cc9bc3f22f13c97fa4fc3f859388f5a6d25f3f69443c1d86f3b06e37c4be54ae6edd354c9bc7dd791643aefdc4aa67acf2b18e7f134f13dced325a4ef26d3379affc95f9826e2cb952a99c6f7153ca57835fd0463ff691108267fb579028b78c2001b34dee14532bf7f62814df88b4832d52f2ab085f59d0118eba3752899ecff2699eae307c9b43fb405431f9454329d2fbb97ccdb938cc02ee95b2adaebd2f8b590dfc279e448974ce3f12998e67b4d30ce074713c934ff403e0be72d2dba9fc5e607defeca014fc85f5413f094e2313b954cfea0114cfe467901233fd41792a99e6a49a6f527c198afd71bc9549fb9822dea8fba944cf9502799dad782b17e6d7592c9be6782495fea42321fdff8c7f77cbcb477b043fa1deb9229ff4904e37cc697641a7f0decd27828aa647abfc45032ade7b982495f13b25fcbc2fb0c944032d9cb93606abf5949a6f314cf60bc4fc00a24f3f6b79960d29f5a914cf11dfa53d87bf82999d6df303e16ceb755a4cf369b3fc8ff7660ec3f57de04933ff0f760ac5f665bc114df2b67c1a44f57156c507f5f1cc9b49ff3198cfdc69bab60aac7ac4f601be7fd22c1781fc95132ddaf95ccdbabd492b93e794f60e883229e87fd9ef959326fbf3a964cf9e00318fe5d9d4be6fda192fed916ce83a92f92a93dbe64ca8fd11f229e4c6f92f9f3938164ca1f4f82b1fe994ae6df871f60acf79a6bc9bc7f62f49785f3b1b75230d95775914cf30bfacfc279b22df90f47c413a621995f9f7be011f99b6d2b98e2136d021e4f683d63059e4cb83e7ae2fa19dd4f3b83e734df943118f581f22099cba33c8397549f592dc026d69b8f9279fb6f9f60e453d6156c537f5a63c9644f8160aa47695330fc8dee0aa6e7c5b964f28791648a6fe692297e580aa6fa6628da8bf8c3bc974cf9642118fa38954cf58f89649acf1692e93c27e9936361ffbdd149e6df2b9e609c1f7d96ccf549ad24d37974e887d0676721998f8fba924cf1fa9364b247713df687754f92e9fc672399ea45a23d581f35af92f9f7b9f81eef13885ac1181f4b32d5dfa10f16f6a3044bc974dee9158cfd3f892399fcbb2d993fff26fa6786fd3ba23f711ef146d7bbcc7e283f7b944ce7995ec0639aafab25784af671db0a9e52feb200cfc9fe320f2cec650f5e52beae7d49a6f319e2fe4bd457766083f453bf80b11fa878154cf6b2adc1585f37c4fde0af235530f251717fc45b9e90d7c17ca848a67add5530ad1f74a160aa8f76e279c8e7c34630f97f3b174cf2379a645abf247fe35a781f90ff2818f3c1443297571d49a67cfd4930cd87da1b58e8ff5630ece74b32cd1fa564aaef7982697dc87900633f73694ae6faa0be4aa6fd789a648aa724637fd25a32ed3f79924ceb3d3330f6f325ad64de1fd98364927f2598facbd42553fd3594ccafcf311e16cecbdf22c95c5e652a99de7f267e8ff3c9e1bb641a6f4732bf3efb008bfd812f92297eb32473794b31bec87fa30a2ccea3ee0493ff30f79269bfe23718f53e6b2099ea0377609c7f34be2453fc7b914cf91c1f2f63c0e6478a0fb6e019d58be207c1538aff8fe039e503712b99e6eb5c3297a750c04b1afff22618fb1922c1347fc73bc9b47f4630f2f9eda360b2efab2e98fcd1ea158cfd83452598f47f6b48e6cf8feec1a8b7a40bc1f05f3bc9bcffb61918f596f85d32d5e3447fbaa48ff94030f6ffdc24737bf267c416f6a7ac3f2453fe580bc67e99122cceeb9c24533d6b2299f4ad108cfce30773fd500cc9341f7792a9fe6b0ba6f5da6b2399ce372ec1d85f1d9d25f3efd59b60f89f3bc9bc3fd4a364f22f6f60ec97543792797fa8a960d8c74d32f9932918f61ed49269ff832d99e44d24f3f61a23c1d43f96fc1ef1fe1c8cf763448e645a3f16cfc3fe3d632899e2955832cdafd01f0be7d5ad4a32ad9f3792b9fcc64030ced3d792b93e9723c9b41feb02c6fe67732b99f68b7c4aa6faa3180f9c17f6499ffa032dc46bf098ec5d8f24d3fe08133ca1f530ed049e527eb7f50593ffb83c48a6fd570a7846f7d36b30e6fff25b32d5ab73c1145f28ef82299ed1e660d473b64f92a9def92698fcdd5a3cdf46fd24914cfbcd74c9b43e21e445fda611f7437cb1fe124cf65edcc02edd3f7225d3fb001e05d3fc5ebd108b7879bb93ccfbc72f05937e66a9605abf538e92493f56e021d99f6249a6fa5b2b98fc9f72914cedc3785a789f52f12698e42943c964ef17c9e40fe792697e1849e6f2648e60ac470660bc9f243b4aa6fd3fa1647ebda20826f9d24c32ef0ff55e32d5d7447f60fe2f9f25933f5a4aa6f8e62c18f9502299f40ffa61e1fd4b4a2899f6279492495ed19e29e297028cf795048d64dedef05530e29137c9e47fe4efb19f740cc6fed152134ced0f55c9fcfb488c17dedf74b9934cf64dfa3c326754ffab0cc1643f510ac67a78ba04633e77466083ecb309c026cdffa921998f476582b19fa7ba0aa6f93e5e0ba6fca6188051bf4b447bb1bf4aff00237ff60f92e9fd41f792e9bc7d2599e6f717c1d8cf247e8f7a5d160ba6fecf23c1b4bf21a0f86264e13c72f82499f2fd57c1f06727c954bfcec098df755b30d9ef7a2e98ecdf78974cf54cb447d47b3d5330e2cb0fc9b4df47dc0ffbd12ea9647a9fec1e2cde07f92e99f60b1c05239e3e4ba6f9df974cf9d74932ed9ffff17b2e5f70014f90ef288261df8664b25f5332bd6f0ae36be1fc4ef92499f22d4b3297ff593c0fefb7525dc9e4df3c30de5fa53a9229feb12553bc2ec66f46f2565f92c97f37609ca7b4df25d37e825a32adff89fba39eaafb92293fea24f3ebb7627cb13ebbfd944cfbadbf2453fe37154cf287a664d257d15e715e80fa6fcce673f2af117846f94076075e503d2188c1d88f9a9b82c91f2457c954cf38832df2279ba9647adfe70a8cfaecf62098e2ef6e2699ce27ed04533cb2d5c0d8efaa3c09a6fa46f12199ec5d3c0feba51dcd9f63517f5dbd0886bd3f4be6d76f7f30d59b62c164afde5432d5271f2453bdf0118c7abd77124ced4f1ac914afae2553bd5edc0ff3b9f32498ec6d1308a6f66c55c9341fdd83313f9ba23da8ef46a564dabf664aa6fd21f27b8a37e291643abfe249a6f9ce174cfb13a2028cf78b25b9647a1fd4a364f20fdf92c97f0c25d37a512599d607a03f22bf375ac994ffa49229ff78944cf94a2618fe48fe1ef59e4632bd3f270163becf2ac994bf8beb71fe4b0d2453bd27964cf552d13fa807da2f9269ff612499e627d13ed40f424330b55f13d763bfc6ed4332c50f37c1f0f78a64daff3d964cfb43c578637daf7a138cfd39429f719e6745fa30314df21f590ec6fedd32134cfbb10c5d30f98bcb8b64da2f3c01dbd87fbc174cf5c92001e37c4d25eee760fff1b7605a0fc8b792e9fc81b8bf43f149740263ff68fe2a989eb722fb9c8878201849a6f75f9e25d3f37cc974fee15532bdaf752898ecdd0904d37a475080512faf7e30e9432e18e7f56e82914f5482c91e0bf13ce4ff7e2698c627fb924cebcfe2f7d8ff1b3e80719eaa934cfaee3992491e717ff80f6f2699f22ff13dcecfa753c9e4bf0e92293f394aa6fd139660b2cfc8904cf9df4230e68b4a32add78bf1c0feda740ec6fbebcab3648a8f2792c95fd492299e1848a67ccd164cf25b2d58f887ab64f2379d64de3fea4132bd6f4efc7e8e7827944cfb7f1e2553bd4f134cfa6c799269ffb6781eea8df14432b57f2718ebe591645a2f8b05231f15bfc77e0f652699e229f13cbc7faa9a4ba6f361427fb03f5013fa8cf5e2c495ccbfd73dc924af180fec0fd33e24737922f17c9c6f6cc91ea626f69b5e13f082fccfe64d32d547bfc0385f565ec0886fba1cecd07a663394ccfb237b05633d627b144cf6779949a6f75fd682c93f06349f4dc5fa433d154cfaace982697d721b4aa6f3c11918f585742299fce5bd64aa67958229be5ac560ac27ac12c178bfd79b64da0ff1e37b7adf95fc3dcef70592a95ebb174cfe3a10cf47fda01c08c67e1b5f32bdcfb0134cfde12a92493ed17f585fc81f25d378dc49a6f8e253308d57249e3f417c7a904cfbcd7e30c5d382b11e982592797f24df82b1de954ba67aa6907f4af69baec138af6c8d24533d692f99ea733bc1e4ff3c0b2cde37be944cfe712499f2b1b964b2675732c52bd0670bfb45d54832e58fba64da0fb301e3fd8d4a2499d67f857ee0fc72f82d99be5f81713e3e194aa6fd49e27e588fb89ec1884fae13c9d4ffa27fb0bff0229e67537fae481f66e612fb2d776083ec3debc026eaa53618f18a3b0323fe580f04d3f5c98b64da7f63825df217852e99ce77907c33113f6c4dc134df6f1f24d37c9982b17ee04f05537b9a77c9148f88dfa3deb07a92ccfb7f73168cf365778229be48bf25537d19f28bf501e55e309d4fc94f92c97fcec158cf2b12c1e41fbb4fc9b43e3d104cf3f7f6158cf87ebb170cffe448267942c1e47fba05187f1f455049a6f5614330f4ff0d8cf3b88ab83fde3770d94ba6fafc12bca0f6a557c1c80f6dc9644fb964aa7f1492a99eb1934cf3f718bc44fd632199f2ab67c914bfd782518f16e389f78346a23dd8bfa58c25d379ba4030c95b5f2453fc5c824deacfec2299f6eb6c25d37ae74630e2b94632ad170bf9b13fb87b964cf514713df61bd4aa643a9f0f7bb31cecbf10fa28f6e3f89269bd83e2adb9399f52bd33032fa6fcfef9086cd07e8d95f81eeb1b97a964b2bf0dd8a2f958ff02dbb41fbbbb825d9a3f2eb5608a3fe28560caafb6141fcd45fdb11a83b11e180f05d37e5c5f114cfe669d8051ef6f3dc1a40fab108cf3d9e55a30ce3b1a60d4d78bab649a5fe5f7645f978364dededbb360f247452899ea616730d6e7d6779269fdfb4330f9bbd4148cf8e7058cf5b8e44932bdffe25e30f6835c24d3f9d1b964b27f713decdd16ed9b937fd2f792a99ed2082679a247b0380f33964cf3ab18af05c52f57d1df381f5baf2453bcff0046fcacfe60daaf6a4aa6f9ed4b30ce7fce25d3fedd1918f65f8af1c37e6d4f954cf9cf5a32c927fa17fbede254326faf22aec77c1bd582a9fd971d58ecef3524d3fe5ea1bfd84f97d1f82ec47a83be124cf5c8ca07dba4efbab8de9df2dffba44f0b51afeb5cc1747d32154cf61eecc043ccf74f9269ffd3098cf7495c1e25d3f9c14a30ad9f281f92693de2001ee3bcf34430e94f71114cfe259883f17ef6b52599de2f36144cfaa23c4aa6fafd188cfa79d60a267de832c1345f1786649a3f7e30cd97a2bdc86ff55232c54fb9648a6fc4f367e44fbaa1649a5f669269ffb7f87e4ef6915f2453beaf4ba6f9443c1feb655a2c99e47b944cfb532493ff6bef25d3f86ec1e2bc532318ef1712fa82f3cdc55e32b5ff1b0c7b5acd25d3df9fa04ba67ac25e32bd0f44b4cfc0f95ad13f787f759c08c6fb8f34c9141f6e2453fee80b46fe22fac7c2fbafef24933f17fa8efdf9590dc6fb8d4a8a079626ceb3d513b04bfa5a527cb664f645eb65067848f359fd8369bfec063cc27ae45532d5e31f25f3f15c3d83315f5d12c9544f740553fe1e6592a93f3dc158bfb88127145ffb9560b2873a96cce5d75f25537ce90ba6fa62f283a95e2ae49bd2f82b0f82c93ef385645a6f17ed453d39984aa6fac04c32fdfd5607c1a42ff14a30cdb7b74232e5a76f60e483fe5132cdafb960c4fb5f60c4aba52218ebaf7b30d69fb6e27b9c1f0ceec1d82f962b92c95f1d24537da7148cf93d05239f534f92e9bc8bb81fcefb1547c9544fabc1383fe68af1c67e92f807d3fe43213ff6af7662fcb19fdaa37cc410f5ebfc5e30cd1f6b07ecd2f85a347e06332faa8f1cc0d0efdb17784cf6e91a82499ff44ff004eb318f92693fdebd649adf5f05937efa67c1347fe91618e7bb6e7782112faa60ac8736a1601a8fac00a31ee98c05e37d155bc1347ff8aa647a1fc009bca0f1f21682c99f9ae2fe0b6acf360763fd62bb168cfcb0148cf7790879f1be9ad4954cf53cd17fd8bfe49f24533db1164cfdbd7d07e33cd346fc1efb17b789643a4f300423bf303760bcdfec42f669b27885ee47f38169e1bc977e124cf18d3706e3fd11fa163c22fdda9482a7b43e7805c3ff058660ba9f2b9e87f364d14632d5fb4792e9ef37fe02e33cd926028bf364efe039c9b712f747fdd9ad24d3f58231fee58b601affdb9b648a6f7230dedfe12d25d3fa760a467d3817f218145fd99f9269bda1924cefdf93df23fe7e009b349f98623c2c1a5ffb2298ee97d8609c3f32e6609c3f8b2cc9646f0bc914cf3f4aa6786607c6fe958ee20f8bcdafb43f81e20b165e93fe5c3e25d37e30f13dea3ddd093cc27ede2d18f5983804e3fd1d9a25989ed7168269ff61fa089e223f9e8167d47f862699d6f39e25d3fe68152ce2b70318e7c9ec67c9f4fe12138cf70f252918f1932b9e67507caf08f9f1be9938069b648fc15e308dbf32108cf7df88e7637f627c150cff7a0163ff42f000c6f99c88ec9b4d37a867d1fc62b3f1a3fd3c743f5b8c5ff102463cb2da82117fb4df9269bde12498ec510f25d3fef01c8cfcb8b425d37eaa5232bd5f2506235ed85a9269bda4154ce31d89f6cef17ea8037841f76b447b17d84fb6012fa9fd6b211fea49978b608a4f0c156c423f3bc9b49f3602c31e6f7bc1d0bf4a32c50fe44f6c1bfb3be22918e7e93a6287d907adb70ec063eacfd51b784afdb3d1c0c85f8a5232cd97afe0398ddf652d99fcf75130e5879d09c67c961482c97eae7bb049f74b3ac9349e86649a4f2692b93cb978be8df749b88229be509660eca7f39f24d3f922713dd6afaedf8269bcd690c7c6f9d755001e52bc5b533ceb5a63d29fab2199ce63edc1139a9f82083c25f9f5068cf745dd2cf082c6238d25d3fb1d378229bf503ec178dfce6a0946fce9bd0aa6fe5ccf04e37d0af27aca77ac1bd8a2e747df9229fe2dc136f98ffc4530e9f34a934cf9f10fa6e78be739387f48fde9daa8f7273c3e310716f67b260f9269ffde1318efefb91e24537dcd06e3fd79f6156ca0deb1904cf6a080d1fe6a2199e67b5f303d4fbb801dd8fb0a8cf8f9a611db78ff5dac8211df745f60d413133e7e2c389be17ccc183c27ff97459279ffac4b30de27947e0826f94c4532bd7f5d032fa9fd6d2a784af58e21d8a0f9e1aa48a6f53f5b30d58ffd6730de5f94ad89ed01d9ef86eb2b0b2eb0feac6fc04b92af7525d3fbcd8f6093fccde64532d9cb4d30c57fe1128cfd33eb77c1a41feb028cf7355a1f82e9f9ee1cec62ffea9b60f227892918e785f0bd8dfdafe9b3601a4f270463fda81980f17ea59adbbf3966fd41ef472dc14bf2075b1b6c60fdec4132d50f0bc9944f1cc126c693dad7bf5e9ff2075c6f63bd6b45fd33b1e6549fb8adc0580fdc7682c97fdd5ab035a5f74309c67961e50bec523c1de2f736eaf7f11c3ca4feaba8bfa6d664467fffdc080c7f53b492a97e6f08a6f686776013fab4964cf69982717ed224ff30b5b15fe81608c6fbd3ce60c48b2d8dd78cdd8ff2eb5430c5839b5730f2dff60086be74a4af33d6ff148fdd8391ff6a74bf390b30693de808b6917f64c436ce8fdf1230f6bfb7345e0b6b3a27fbe9c0f319bdaf8bfcc782a5f7e43f0f60cc4705f99f256b3fedf71c826d92ef3625b627349f68dcdf9b2c9f9b927f237d3458ffd1fc5b8327f007241f530f1aaf6b00467cad51ffb2f8674efd41fed5b6711ed0e4fac192cf39b57733022fe97ecf977feda32abf7d8c9f3e26ffa7827fa74fcf0afb9da5daaac3fe58ff6a0be8f3df21cb2f72b9ecf3bb5c0afe9b90afff77f7df5116d62247f5d81ffad87ddba87590cbfd87bfb3f1f9779605f20899fa6be8cfffb79fff167b71e9f393743ffadc1663f4e33aa96fbdedf8eccf3f18b9ffff65e16dfbc90e6009240d1fa9bf2b3bc9439ee0df4d1661eb3f64f9313a3f24f3e4e717cbfa7791e5379fecfefa91d758f05a8e94457a8a7f2b590235542335561335553335570b364ea55aa917b5669f86e951ab76ec7365b2de544dd5d99f15ff9dc67eb1fe379365a3aed827652391a85bf6b963d2ecd43dfbec982c07464726dd91fdfb4e3da9f74cce7bf5817d0c76e53ff4daff5b6479e43dfdc446e699fddb597d515fb94ebda9efea87faa906ec9a9449f8c524f85607ea501da96375a24ed5993a67d2fc1bc9c25a7a5637ec9f91ba607f02d8fd92c9f2cafe6929aafaa4284cc7be15431d2ba662b18fad380af31a8aa7f8ff3d92fcf7cc954aa0844aa4c44aa2a44aa6e44ccf5ca63d2dfbf4b6622a059b45064aa954ca45a9954669954eb92a3745537465a5acffe8b5ff37cab251b6ca9db253cf8aa2ec95036bf1513929f7ca83f2a83c29cfca5979515e9537e55df9503e952ff6dfbf9581325446ca589928d37f23596c65a6cc9505d3b393b26413cd83f261288661b044c0b00dc7700dcff08dc0088dc8888dc4488dccc88dc2288dcab8a87746fddf23c99f9345b58ca6ff23a390df6677a3353ae36adc0ccdd08d95b13636c6d6b83376c69efd391847e364dcb3cf897d8e8c1fd8e7d178329e8db3f162bc1a6fc6bbf1c1b4b0cf02685e757f9b797f9aadfe999ff8af6561527c1a5feccfb7313086c6c818315fd4186363624c8d194b9916c6b2370ad3304dd3326de3683aa68b8fc73ebe19b04f684666c465eaa53a9a31936a6726666a66666e16666956e6c5accdc66ccdcebc9a375333757365aecdcd2f33b1f2eb1cfcd764311a736bde3169becd9db9e7b21ccc8379344fe6bdf9603e9a4fe6b379365fcc57f3cd7c373fcc4ff38b7dbecd8139c467648ed967c23e63736aceccb9b960992a3334e3de322cd3b22cdb722cd7f22cdf0aacd08aacd84aacd4caacdc2aac12b9dc2f91c5ffaa2c56655dac4b3f2e566d0cad5a3d5b8dd55a9d75b56e9666e9d6ca5a5b1bd6d3f7ccd96ead3bd6522689b5b3f61677bfd6019f2393666a9dac7beb817d1ead27ebd93ab351da592fd6abf566bd5b1fd6274b98bf5884b0601e3d61b3e9c0faeea3cf1fd1d1bfa2634cb31a8bfe82f001fff74a89aca135b2c6d6c49a5a336b6e2d7acdb196cc74fa4a9ed18f85b5b34d48f2439643bf4c614e6ddb766cd77ab03ddbb7033bb42326cfc178b4633bb1533bb37336abda766197ea935dd997de92fecce74fc932307756cdc6646055aa67d77663b776675fed9badd9ba71303fec95bdb6376c249ef9676fed9924625414662bcc5e602bf766681bf6d6beb377f6de3eb0cfde3eda27fb9e8debde7eb01fed27fbd93eb319d7b35fec57656fbfb1d1b07efffcafc9f27cb16a66274cb78cc6f8b4df992c1ff6a7fd657fdb037bc8faf3c47a7864bbe6dc1edb137b6a2db924bb7e64fab161ff9cb1f6ce85fd9b91bdb0972c485698ddcc1dc3311d662c8eed384cd2bde33a9ee33b8113b218f5dd89545df17fcdecfe155954d7183ab113333bb1edda499cd4c9ec2f27778a5e0ea7640ff0ed3d6b55653d3b17361acf4cc706cc6216dc6ed8ff3b356b6be3b44ca6b9d3998173756e8e66f7938feeac9cb5b3b1b7ecf78eb365d21c8d9d73e7ec9cbd73708ecec9b9771e7ec9107ecb7a7eb6a03f234b2f09f3c683fe7ecea3f3e43c3b67e7c58cadb33db1ced6b33d6656cc3ece2b6b5dc5dab5c0a7f765ec63cfe9e374f8bc39efbd24f6d20e9d0f66fd47e7d3f9ea7fe954ce379366dffff5f6cec8e9ff5acca933b3eb9fe4f8576599ab9db3b05f9c25fba1e21a6ce2b08c23f34accd3bab6ebb8aebd702a73e17ab66b1f5d9ff9a8931b981fccdacfaca5f76ec86c2ae673e6d18ddcd84d98bde0e3746e6a7acc73b02b594fbcd93336be67377373b7704bb7722f6e6d176e63356e6b358ae67656f3afe8987a70afaaeddeecd6d55cdd5db96b3626cfeec6dd9a43f7ceddb97b3622dbde86dd837bb4576e6031ed331df7e4debb0feea3fbe43e1b817b765fdc472195fbeabeb9efec5707f7c3f9703fdd2ff7db1db84377c474f1c0fe7dec4edca93b73e7eec25daabd2f6091b8a7aa81f70fbdda9f91c533d8f46d79b6e778ae937b9e71b2179eef055ec8e4601fdbf0222ff612e6030eb6d1eb8c977a99977b85577a9577f16aaff15aaff3aedecdd33cdd5b796b36e7c7c6c9db785befce7a70471ebb0b1b5d9dfd3ff36fde8e59cec1db7b07efe89dbc7bb5f01e58467af31ebcc71f5af5bb1ff853b23c79cfded97bf15ebd37a730637362dbde3bd32f2e099368cbe6f229b39ae7de76bd0fefd3fbf2bebd8137f446ded89b78536fe6cdbd85b76441d7a3aff8866ffa966ffb8e71f45ddfb31e7c9ff9e8ad6df8811ff663e547ee8069e4831ffb899ffa198bd6be51bffd523c9189fe75599e2f7eee177ee957fec5af0d6603e6d46f7a49fc967d3aff6acead27ffd6cf77bee6ebfeca5ffb1b7febdff93b7fef1ffca37f62f966a2bef8f78aea3ff88ffe93ffec9ffd17ffd57ff3df8da3bdf03ffc4fff8bf9f485bd30c74ee57ffb037fe88f8cbd3ff627fed49ff9737fa1382c27fd6679f70f597ea97dfc99d8d25f066aa004060b112da65f6aff97c0f7fae5b7811d38fe3570cd0fe31478811f04411844411c24411a64411e14411954c14509839a7d1afb3d68838ee59af3e06a3f07b7400bf460c5fc48ef0d9560ddeb99ad30d906f6c27a0e36ecaedbe02ed8057ba50e0e4a191c8353708f0af54f35ab3f2d8b1d3c048fc153f01c9ccdd829ad73f012bcf6da15bc05ef81137c049fccf38c83afe03b1804c360148c8309fb330d66c19c49b47016c1325443253442d3188416fbc39c71e8865ee88741188651c86cc73a8709f3cb4698f29881c50f61d6fbfc300f8bb00cabf012d661e32fd421d3b41fb2387f94e5e77af6cf63d25f1db661175ec39b19875aa8b3bbafac636f27e13a5c33795e8c7b2f0d37e136bc0b77e13e3c84c7f014de870fe163f8143e8767f52d7c095fc337ab08dfc38ff033fc62d2982c22f6d97ff90e07e1301c8563e3184ed82cb40dd6e1943d63e6ee99fd7c9b53f6dfe7e1225c466aa428456444e68fcacdaf5a46b288ff862c28f1d4c8525fd5d7c88e1c7f19b9e673e41987c8376751c02375a61351c8e2f7cf88e524511c25511a65c62dca8347ab65f369cafe3c4645f01895aa1255d125aaa3266a5910d345d7e8166966678ccc75d4467ab48ad6d126da4677c629da452c82f0039ef778d68ecdb40bf6bc7d74888ed129ba77d2e8217aecefcdabed866af4d1eeaff6f2932c068fb043b77516ca2e7a8a9ea373f4629ea357f6a437e6750d16a79ca37773c2e6e8aad7eae823fa8cbea2ef68a0ce153f1a2aea8f2a2c7f9e1b8da27134096d2b8ca6d1cc8aa379b48896b11a2b56111b319bac629b85166eccbc3d9f73962c7f93b29843e33ef6e3200ea3fb388ae3f081f554cadbcafc5a1f25fe2c0b7ff68f7131d4f8f9e22cd4f73889d3388bf3b888cbb86277bcb0f87111d7d6dedd5b4f7c2639b959dcc46ddcc557ff515dfdb4f662cb3bbaca5875e25bacc5ba3f8b57f13adec4dbf82edec57ba5890fea323ec6a7f83e7e881fe327e3143fb3d866c9bc7380b86e689de373fc120ce2d76011bfc5effd88736b3055a38fdeff992c0ad34726cb6b9cb8adba8a3f4c23fe649db7641ec6b09ee3da665ed3fc0c33f6dcaff83b1ec4c378a456eaca7e51ee94713c862c3c1eecff9dfdb7493c55f57816cfe345bc4c54e3c17e4894c448ccc44aecc449dcc44bfc24484263efde9b3e8bd8d887e7a42c3b65f3d6d17c4da2244e92244db2a84872b1baf07765b1c886f8155b36bbb2fe65914fa2b8499194e69b71f26fd69e8dc9d9b998dff6c13ad953e39054c925a99326d6d5f7beea9db4ccca52f40d55c1d97d95bb385332bb4abae49adc12cd38252ceb4956c93ad924dbe42eba26bb641f1c9243724cd82c657a8ec272014364d94c9b4b2f4dee9387e4d158264f09b34ab146d2e722ff4c96e499f5e198e50e2bf6efe7e4257935dfad3e3f3f276f56ff8afa7df26ece8dfb709c7c249fc957f29d0c143d192a8b64c4abe3bdc7b4fbac8dc9c264b2df93713231de9269324be6c63159d8c76469c6a99a2aa9919aa995daa9e3dfa76eeaa5bef1603a2cbfe1b2f45910cb54b769601cd3308dd2384dd294cbc2d76dfa7cc4180aaff6932c96b0fe3453466e6b97cc8e9d344f8bb4343fd22a4c98f75a5afdfe8687f4621becee75daa46ddaa5d7d451f4a04b6fa996ea91c9fd3f978549c3644957e93adda4dbf42eddb15fedd3837d4c8fe9c9d8a7f7e943fa18fae953642b7a344c9fd373fa92bed2c8902c2ca7db4681719fbea5efe947fa997ef5feb197a56f7f9f5bfd2acb8f91e17a78607dbb5412ff2139a7dfce9069eb673ae86da5f7c54ee5fa696f8f553a4ac7e9249da6b3a4b50b65c3f42c5177fe23ef31361a7d0edad724d379ba4897999a29c63163f971b4efb3e3ccecb3e2649559999d39ea57ea0475e6665ee66781e9fa81a3a06ab0eb675096e1c5599845599c25ce23b3172e8b6af5b9d52fb2889a9add3f99d14efd4a064ccf952c553eb2cc74cc2fe61b077dcecbf477613d982316e37efaeb2ccf8aaccc2a61e7e45b98b34db24b56678d5dc763f53b6bb32ebb662c62f343d6df6ff6c2fd66de9c652c99661ce3a74ccf56d93adb306bd3b36d76e74efa5999c53363a603cf76bfcd8445369691edb23d93e5901db313d31d85db7491ddff268bf28b2ca67a973d3032b24743c99eb82ccc37f67d642ebcc4661146f69c9db397ec357bcbde852c1855577d4bdaec23fb8c9e93419a655fd97736c8d8e866a36cec8eb24936355da7cc66d9bcf7ebacbf17d93257734509552b377233b7723b77d8377d3d6dc29edad74398b7cedddccbfdec900779a828ff4496be024a7dabf8bd36f63edacc23c330ee982cbd97efed70c024619219f7799c27fe364ff32c3c30597eac4172bf95e779919779a556f925aff3266f8d63dee5d75eb7dc613f1ef9cdfdeeb3e25cb316f153aee7ab7cad9eed32dfe4dbfcced67396c1b09879c8729a4bafd9feb7719f29f93e3fe4c73cc88e4c9b1392c52afe812cbd0f559209d332db2ed5263f1926f32baed05ca6678eed5877ecbfbce6f7fe5dfe104cf347a3fd690d92d97afe943f671725cecff94bfe9abfe5ef7dd4937ff49909af719cddaf6cca73628dcd8871fe997fe5dff9404d9cc833f3613ecac7f1579ff1997dbc4c51b4cfee30c9a7f92cc9988e1d59a699f47e377c0bdffe200bb75792259fab7b854d65ea77be302c63cfd2fb1dd5bc481673943bf9b2500b8545f5b3e8814547b6dcabc0575793b1fa919f0ba33059b7d9ac557d2cbfe8f312ebaeb7e4c2e96b1785cb62ad53e1157e111461112923d52ee22229d22233f67d5ec365611ac6aecdd98cb92f8aa22caa3c2459faf6b398f5f597f9e5375958c6b34f6fcc62be8b0b7be4ce74a97227646177ae8ba6688b2e288a6b714bf25f7684303d53fc645268855eac8ab5710835e7b597a5d8b06cabaf6a7ef4d5be60cd243916dbe2aed815fbe2a0d8c5317b284ec57df1503c16cc3efa1a279764614e0b268f7128cec54bf15abcfd248b1aaa7f57164fcab22bde59fe742a3ed894b5efa33c5420875c9645f1597c15dfc5a01806398ba2c90bffd8555114a3625c4c8a692f4931ebd72c989ea8c5bc8f467b5b6677e03163b12cd5ecbb544287c540d7d250c2d22cadd22e9dd2354ebc22c2ae36c7f6a1f498cdc6a55f06e1ae64290dd731f7efc822d654c40cf3adb665c472b053191b2ecbef852cfb5e16f3cb3a9749999659996749745f163f564a7824669465599597b22e9b5e92b2cd34661b565f3b6371dc985bb4e10ffaaca7ecca6b79b3be4acd0a4a9d8d67c4a45995eb72536e992cbabdeda326368e5bebbecf64cabb7257ee7b591425cd7a6d28b552fb45961fd13ef773ea8dcd103b75c56439183e1bebc81c5b7d3d2cb0674e63cfcb63792aefcb87f2b17c6271ce86e527a398c594ca9d5d97cfe5b97c295fcbb7f29d79d12eef32adafee9bb3bebec13f337b5f7eb079bc2c3fcbaff2bb1c985d392c47e5b89c94d3c42d67e5bc5c944be3c45c7d156a7c4c0f665f1939564a655466d06746a7e0d4ef2ab2aadf62fedefb3059d8b7663f36c8d834bbaa2c26cbbd19b2deec97483a264b6b06c6a1b22bc79bc5e3a00996e5c4dc562e538ba86236cfa29545e5574115329fca66bb3ea736471513d73a313946fd9a4515dbdb2aa9d22aabf2aaa84a2bacaaea52d55553b5556745c1b1ba062b362e5ba7a355b57ebda3aff254b74aabf42467b21c83a36ad9f51f641151a5cf6571d488e9e246bd315559556b264bc4662c268b193269f64c96a37bf65a6fae2e2387e9eb5bb5a9b6d55db5abf6cab53a54c7ea54f575e17be6c717d681c5d5233e26a3fe2ebd3d570f4c96c7eaa97af646d5b97ab1aaead5dc556fd57bf5517d565ff128afabef5e966ac07ac2e5f5cf678bddb11a56a36a9ce4ce23c6c5339adf627e4bca6270efba60d1ee539ac5a36a524db98e912c51af654c965335f33a8f656bca3c34ccae9a87af9eaac6ac3f17d5f2a26637f7f5a25cb81fb615f38349d17f26b406c3ee7570377d7e75312fd6c5be38e1cbc5bd78179f8d897f092e6134b8449798c9d2b91fccbadefb159cde673059946a7449823e47f6d9c7fea32ca859283c96225912f549bdbfa4ec9e593fc6fdfa9c6df523d4af3d18a774e75d2fb9925e8ad0c8eefbbcfd525eaacbe5525f9a4b6b9c2edde56a6fcdd1e5165f98bd93244764f10773e445d68e5da55df4cbeab2b6c2cbe6b2bddc5d7655a7b697fde57039ba2fbd2c173633b1d8cde27fd5d684fde2fef27079e4b2a0adfd5add3f95256071f24d29c2faf27479eeb585d61bfb95a07ecd81e9d8a377f35545b3df7975c88ca6feec72bebc5c5ecdc4383afae58daf136d8235f75dbd7e8db92c7c3d96f5f196c5dd5333bebc5f3e2e9f97afcb777cbcf06a13d388e16578195dc66c869ddb6c66cd466c967db5ee7adbbf4c2ed3cb8ccba2f0bcc2fe5d16392f4096545373b5cdcf97f9657159f6eb90bdcdb2d8b85fd50accc08d8c83a7298f8a1fb4c620fca8d55a49b6b5519bc98ac9f9565bb56def1cc38bfaf99ecd8d336ef74cc7b8341e9b3146e6dcdef82cdeac9ddaadbddaaf83484b46e9ad0eeba88eeb84e5ca9fcce3796c6e9db008f4c9dd32590e755a67756e325990875bfd0aeaeff9cbcfb2287eaa2b6e5dd4a5f25557c68149c0bc0fb3dfa8978569716cc69eee2b6aa9cc422bfc8caa9a4590ec7f0d6b5beb7eb84347cdaf2c63af9cd73063f67faa22f6ebdeaff7d27875c746f9cbfc626d5cd6d7fa566bb55eafea35d36ca77c8af27a536fcdd8b9b23cdceb6318d6239bdec2eabb7a57efcb3d932515759e3fe695d8112074cc55efd44370523ae5b13e184cb3597e7f6fdbbc12cfda581f599b4ff57dfde0b6a1556d13b77eac9fea67e3549feb17a65b8bfab59f159cd728b02d1691ceeb37bfb1b7fe376fd994b220ca89acbdfb5abfd71ff56738a8bfeaef7a500fcba01e992ed3c27db17077aec3f29881cb324b63578feb493de5b2507ef20f7264f6a797a59ffb13f6ff0d9bfda7f5ac9ed70b9657b2fc8bc52e5b7b592f9d779bcdc98dda288de13f5a35f3ca1f8dd958c64363db47f6d9374e3f438693be6ed3fbb2c665ff34a2d0def09a9af1cb1ae0d074eb5be3357e1334a1f3d4444ddc244dcafae291e54977eeaec9ac2dfb158b429bbc299ab2a9b8bdd09ca8f42b763fcb42732397c5e4b364aa8cd2cc99c77a7369eaa6316377c3eefb7039352d0b8359d6e186c6aee99a6b738badd0b48a466b74fbc18c9b557aecc7c57c6fd64cdfc76c2c3efa5cbdd9345bebdcdcb9dbbe8283d53fac9c9b5ebfb3a4d935fbe6604d9a63736aee9b0726c363f3d43c3799bbeb6be64c2fe3e6dcbc34afcd9b948559c51f65a1d95ecaa2f1959bb5faa138cd7bf3c1a22ac7ff609e89d973bfa6686f9b4fe3e0dbcd57f31dbae167ad3483669828d60b7bde283359ae356bc66c961b46611f41369366dacc9ab971b296eeb6e1e3815566167d9b9ed3354b63efad5bb5555aa3355bcbe8ebd581396efb15c45d9f2b87ba71689dd66dbdd6ef63181e7719aadfaf09ff365752a5cfa4bdc2fdfa937a8bc76de03dc65d1b1afd4afdb658703fbbed6dba8d8c531bb7499b865ef5de666d9e9fdaa22ddbcad8370fed85595585fce4beaddba66ddbaebd5e5876dfded8bcf3ddd70ee4eabfefed5aaddf1de36baddeaeda755bb35f6dda6df0dede056f5ec89eb7734a63d7eedb437b6c4f52163f38fd41161bd97abff39945bc2c951e313ddbe5b9a2b7f7ed43fbc8b4f7686ffa9d05b5d53ef55adf326fdf9edb97f6d518861f4e5c44ed5bb269df59ccb3cf3b7bc9645ef5f949fbd17eb65fed773b6887eda865b3068b697aed123b19f67e906bf6b69db0acf8d44edb593b6751cb397875ed76d12e3bb59fdbeace38754a67746667c571922779af472c8e39fe4116e75759d84c99a94967770e93e6dab99d67192cd770d89cb063be56ef7c7b5b9f7d3753baa00bbba8da767197746997b1b0b8e8ca7e6dc8db75157bfea5abbbc6df756dd775d7eed6699ddeadfaac8e723b5ec95b326b687b8fe2fb4e65dce75db7ee36eeaedb76776c02d875fbe6397aef0eddb13b75f7dd43f7f8ab2cbfc563b40fdae2fbb87b59fabdb76ef7d43de7cfddb97be95e6bc738b9ae7de8ff1a4166c38eb3eddeba77964f9cba8feeb3fbeabe9d85fad80dba6137eac6d19d195b0b33f6b56ed24dbb5937ef16ddf2aa5e95ab71358d9dfbca7763f9bd1ce6d00ffa99fd6ad97bc7bada4cbe73b7bb322bb18ee1cadd5d5deffdea3109dfaffe35b886d7280fa302b66ffe1d1d13eb0b72bf196a7fdcef5de36b52b2d65d53ebe19ab119ef6c9dddcf7eb5f79ab3ff5a5ccb6bc5e29897ebe55a5bfeb5b9b6d7ee7acd27d7db55bb321d5533b30bdf8da69c5c57d7f57573dde6937efe655aa8f4750ce623a2be06c6f7638dd87c74ecfd38d515ade7de5aaa8171bcde5d77d7bdda3847b5edab2c5993353c07367f9c07f8afd7f89ca7ebe17a8cd953afa7eb3d3dddbf998b6641d1eef5e1fa787dba3e5fcfd797eb6bad3069deaeefd78febe7f5ebfa5d75d74139bc0eafa3eb987d26d7e975769d7b6bd60b8bcccccceb92dba2f5f327f2dd7d73c7fc1c27ebcc52c3a79b7263f955348c4c36f3b9aa6dbf33591cbebef31764b99937eb66df1cd6379ecb66877edf8bad140b2fb9b139d0b8f7b51b0b346f8152ddc25b748bd5db2db9a5b7ec96df8a68d025e15755df4a7377ab6e97f0e3c626c65b5bac6e9db1ef772df0fd16d6af1f5eafb0d86cc4246aee7236b3dcaeb7db4d4bc6d133cb2d44fefb87ddf3ffb52ce6e34dbfad6eeb86c5860d1b0d663515f3f8ecff6d8fc5eecc9fe593dbe6b6bdddd5a5fa62d7cae2b65386b7fdeda0d4ea58dd869f55773bde4eb7fbcbddede1f6787bba3ddfce51623f180fb71733643e7af24759983454afa4fbbfdede54f7f67efb48068a226ac97f7d7d3f2a6e9fb7afdbf76dc02b565f2cb35c58776c86d89a73162f6d6e43e3741bddc6b7c96d9abab759eadce6f1241ef77bf56f8bc80a5fa2eab6d4d4a8d394a85202f5ac199aa9599aadb1b16e5acdedade4e78fbbef3396c82759cc58f3345f0bb4508bf242d1d20ce3f287d3597fc25e1eb5584bb454cbfad981dd7b617e7a119385f624cdedad96f733a75668a5566917ad564325615ed0b65fe289b25322add15aadd3aedacdf84c1dd573979aa6e9da4a5b6b1b7ba16da99af0ebc8b03f2a8bb1ad7667dada9db653bba0b9bddbef2c7f37642dcfa1f8f22fc8926a7beda01db59376af3db008efce9cfa1f2c3bda71eb6451633568f92e43ed517bd29eb5b3f6a2bd46b935d2de8c85f61e4fb40f36269f2c216e94246ccb2767e999da97f6ad0d3436a6edeeefd98bf5dcee2c35f2b59136d6260a8bd955d72eed525db37111f562ef2fcbf2a84db59936d716da52578d7da8318f79673d9993b86e6fecb363518056b6bac26c79a71bbad92a9dab5bc64db77527327457c97596ee844e7fe622ce597e32d4033dd4233dd6133dedc7e0d74f98f5b2447e2f95bbd7333dcfebb2d20bf6fbfe0c84266b797c86ff2b3a16157aa957fa45aff5466ff5aedf11c3f2de39af8f322fa45ffb798faffbfaa6ebbe66817ed3355dd757fa5adfe85bfdcef850bff59dbe77c6d5413fe847fda4dfeb0ffaa3fe14bd07aece722db28dde4ef86e0bf3e78fe9e8e764adbfe8af4aa36ead86cdca34abf4f6eff075c43fbd8724c9f537fdbdb8ea1ffaa7fea57febcc07588affed6ed3ca56a3f7beea637afd3a561f4733895c33d687fa888dd0589fe8537da6cff585be5ca92b6565accc95e5eddd3c7ded778d38d5ca5e39b6e1eec90f0b0ff68b2cae7170dc95bbf2567e3c535f56415f310a4e2cdeea57df6a5a7bfb73b2048fab701505b355bc4a56e92a5be5ed78555807166b6efa5ccb3afe248bc9b28265dee5ceed8565b4b755b9aa5697555dcd568d3e5ab5b1c7f7c23129dcddaaeb76abab395e752c5bbbe3f66e626ef955166f7533e3b261f9d270a5b1f178e335567efeafaf2afd9571311f57fa6ab55a6bb362b8daacb6abbbcbc76ad75767d2a05f79b0b67d0ecf64796372ec983c0adfc570cff7819ef85efea3d8cf6bdcbbdf76e87ff8cd6abf3aac8ead1d7cb84edffa7e9e679aa6b63b6627bfcae2af4eab7b9643ad570fcdfbea919fce727f3a052c4f69fca971795a3dafceab176db67ad5ebd5dbea7df5b1fa8cbff26ef595f615a31fbbddf98749f7c177bc0f9d57f6795b7daf06d17e35147b2cfbbdbccd9339ee7739b58bd5a8d72e173b9358e3acdf65b1ceab717d67ec5693d574355bcd51c3b7708ec1fdf3314c92af16abe55a5d2b6b439badcdb5b5b6d7ceda5d7bc69e45cffb1f7bdefb489eaffb32097a7b62b3105fc7e3fba9f9beea7e36627e6318266b7f1dacc3c0091cbecb91452c6431bd17f85d967e7473dbd8d7efeb681dab77e20c2d9745f9b16be9cff8b1f03198af933c5d5bc1789daeb375be2ed6e5ba5a5fd6b5b5b437741601fbf7fbd5b30fbe57a25f6bb15a16fc34ceba757416dfb3e83e9ce9d77ecd807df6ebceefd6cc62bc50c8d2eeb411f366bfd90bd7d26374b7beadb53573e4b2fee5fed5793f628aba5eaf37ebedfa6ebd5befd787f5717d5adfaf1fd68feba790c5fdd69eef5ac1b8b04fbf9ef76a7e704b3e584bbedb9f5950bffba8f7e2eb7e97fcb1df83b63eaf5f02d736cc28effa73246c8e1feb193f73d2e7373edfafe4b23c69bb7e5dbf35cafa7dfdc1e617c8f2f7f78ffdf38ff3283f69566595d196e7f5e7fa6bfdbd1eac87eb11d335bea38c568b980e4db0afbf8fa6c6acc7cffc04c6b2dfadd7cbe90f7a7bea77569a43967505d5e0a69a713e6171d79d36d1f3f5b8f776eb49bfa3b61f93cb389f38de7aba9eade7eabdd8d32b674be7afc8f2d3d9621ecf798f6a11dcaf179774bdcc5f36ea46d9181bb37faead164ebf368979c230a77db5439cb4602336661ab91436d3dc39174ba1fd0a2caa7f6511e4ae0f0b36569fdfacc6cce59f8ce3c6c9271b77e36dfc4d607da94f56f35b9bfed2b8fc7eb6381a2a9ee2da55972acd26dc449b78936cd24db6c9f9aa0bcb6eac27ffdbf68bbc782effdf76ae6549552488eee733a6f615fdba7dbb6356a899203e5a6db51f3b4444f0c14b1489987f9faa8202a4bd37b457331113b9d010943a661645669d93b6d9e37b5a6207f5ce54d90a7b630ee6244ed8f3c2d4532060d9afca32ad349d280e4d481246103617866ae8b10a11c3b2b36c86248e1fe983506f36cb7bd7f59cde1344592e9dd23decc91c0e90c0115250a0014d680104cf80a691efb672cf7c667bc1191af13a6a6c8d2ed758790ea8a041fba8a546ca6681e23a2c67047dffd9b4a1130fb9e20cbad0833e2ce34747a706bc2c0e85fef98baee722bfd4f4404187dc51957668dcd0c2d0b660004318c12b8c61025378f3347fb13bb0acbe5df0f8ab3a31cdd0e01d3ee0136ee036e9c2ddb1ed7437f7e95459c13d7169c0bcfd003fe0117eb2bb700a4ff08c94def1b9eef5e9337dca1557dfc052a8ea8aefae6ed98c216b9d45ef4ffa485524aebeeaa181333471eeaa5edbb7f71bff47100423b4421517519a70a1686ff7106f632dbe471b97ebe0a027b3a4874ec8a276354cdffc603e255ca59dee228325a4b8c2354b719e8d29bbca113774bcb961e319c8f15c1f6327bd3884873ca043ee1bdcda7dce35430f7d0c30740718e10e636fed2f7ddd7f0cc2861b3aa1161991827b3cecfa8d66ec6112bce2115354f693204dfadb96d559cd6ccab25f967cd21655d61b3627a2d61336b0892d72a03dc20e53978ef868d8fa229f5faee75a7fe935c07eb745b764495b08ec7d0311d5f514356ca3bffd70224ff774bfb3f1822818bb5ad8461d3bd8c5de6e837df6fe0507fb088787258ef015c7d68bd0fa1a7cc79ef3f0a8623d21573237714a0f6bb636061dba66de58d0211dac1b76bfe293ef6039b59ad281736c393795d713791dceebf80ee712f96e3009ddd07544a5d179e13613e6e4967d435ca3ec245389a0cad56bfd58aad7bf7aee9fc122ff178e852391e3f3ba9c7d9399eff23a234758aeb7d96b869def6fe7fb0f468e60216ac18678a2378b9890bd31a42ee18c42f1d27b720dcf09969c1fb0909d7904e76ec356026184f0baafc89d66956e3da5fecbf6f6f369d67545d6b5c5d924df135a7ec542cb5e26e49a7cbfc201afa191da8093df3604f79408ae9ab0ad576031ca9ca3caca1635c83935653d22cfb448ce3bcf6adc752c32e62a9eb9443352aa19aaaae7e288acea1ab4729f2cb50e052bf5d4871cf952b02732ae47d9db635ea9689b453c57bc2062244752ad5f5e84c592fcc3e1ee4c949995795bc152fdbea830d827ffc84c20e9088f91d2fb395e4b665b520152c3422492ebf27dce3a1163b10a2cc60916c11710bad85b6ed69a7320cdc09db863ceee0a1533e20c1ccef6c814cd995eb334f9fc9ecf4b7ebda988b5c23b67b1108e04dff03d63da7fc32f8b9a5f4caeec2fc7c9c7e6f5bc5e154b795ce2e596e3679fca7dd222b624e3bc58134fe3a1e0bbcd199677fcb81c4b3d6a7ea7d6aeb0fb7e71ceb9a3f5738b7cbeda2ba7de3ba79caf57e52fff15fb1fcbbfd3fefcfbaf3ffe0193cc32fd</data> +    </image> +</images> +<tabstops> +</tabstops> +<layoutdefaults spacing="6" margin="11"/> +</UI> diff --git a/krita/plugins/viewplugins/colorspaceconversion/Makefile.am b/krita/plugins/viewplugins/colorspaceconversion/Makefile.am new file mode 100644 index 000000000..a3f9bd936 --- /dev/null +++ b/krita/plugins/viewplugins/colorspaceconversion/Makefile.am @@ -0,0 +1,26 @@ +kritarcdir = $(kde_datadir)/kritaplugins +kritarc_DATA = colorspaceconversion.rc + +EXTRA_DIST = $(kritarc_DATA) + +INCLUDES  =  -I$(srcdir)/../../../sdk \ +	-I$(srcdir)/../../../core \ +	-I$(srcdir)/../../../kritacolor/ \ +	-I$(srcdir)/../../../ui \ +	-I$/../../../ui \ +	$(KOFFICE_INCLUDES) \ +	$(all_includes) + + +kde_module_LTLIBRARIES = kritacolorspaceconversion.la + +kritacolorspaceconversion_la_SOURCES = wdgconvertcolorspace.ui colorspaceconversion.cc dlg_colorspaceconversion.cc +noinst_HEADERS = wdgconvertcolorspace.h dlg_colorspaceconversion.h colorspaceconversion.h + +kritacolorspaceconversion_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) +kritacolorspaceconversion_la_LIBADD =  ../../../libkritacommon.la + +kritacolorspaceconversion_la_METASOURCES = AUTO + +kde_services_DATA = kritacolorspaceconversion.desktop + diff --git a/krita/plugins/viewplugins/colorspaceconversion/colorspaceconversion.cc b/krita/plugins/viewplugins/colorspaceconversion/colorspaceconversion.cc new file mode 100644 index 000000000..62528a0c0 --- /dev/null +++ b/krita/plugins/viewplugins/colorspaceconversion/colorspaceconversion.cc @@ -0,0 +1,155 @@ +/* + * colorspaceconversion.cc -- Part of Krita + * + * Copyright (c) 2004 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 <stdlib.h> + +#include <qradiobutton.h> +#include <qcheckbox.h> +#include <qlabel.h> +#include <qcombobox.h> +#include <qbuttongroup.h> +#include <qapplication.h> +#include <qcursor.h> + +#include <klocale.h> +#include <kiconloader.h> +#include <kinstance.h> +#include <kmessagebox.h> +#include <kstandarddirs.h> +#include <ktempfile.h> +#include <kdebug.h> +#include <kgenericfactory.h> + +#include <kis_doc.h> +#include <kis_config.h> +#include <kis_cursor.h> +#include <kis_image.h> +#include <kis_layer.h> +#include <kis_global.h> +#include <kis_types.h> +#include "kis_meta_registry.h" +#include <kis_view.h> +#include <kis_paint_device.h> +#include <kis_colorspace_factory_registry.h> +#include <kis_cmb_idlist.h> +#include <squeezedcombobox.h> + +#include "colorspaceconversion.h" +#include "dlg_colorspaceconversion.h" +#include "wdgconvertcolorspace.h" + +typedef KGenericFactory<ColorSpaceConversion> ColorSpaceConversionFactory; +K_EXPORT_COMPONENT_FACTORY( kritacolorspaceconversion, ColorSpaceConversionFactory( "krita" ) ) + + +ColorSpaceConversion::ColorSpaceConversion(QObject *parent, const char *name, const QStringList &) +    : KParts::Plugin(parent, name) +{ + +    if ( parent->inherits("KisView") ) +    { +        m_view = (KisView*) parent; + +        setInstance(ColorSpaceConversionFactory::instance()); +        setXMLFile(locate("data","kritaplugins/colorspaceconversion.rc"), true); + +        (void) new KAction(i18n("&Convert Image Type..."), 0, 0, this, SLOT(slotImgColorSpaceConversion()), actionCollection(), "imgcolorspaceconversion"); +        (void) new KAction(i18n("&Convert Layer Type..."), 0, 0, this, SLOT(slotLayerColorSpaceConversion()), actionCollection(), "layercolorspaceconversion"); + +    } +} + +ColorSpaceConversion::~ColorSpaceConversion() +{ +    m_view = 0; +} + +void ColorSpaceConversion::slotImgColorSpaceConversion() +{ +    KisImageSP image = m_view->canvasSubject()->currentImg(); + +    if (!image) return; + + +    if (image->colorSpace()->willDegrade(TO_LAB16)) { +        if (KMessageBox::warningContinueCancel(m_view, +            i18n("This conversion will convert your %1 image through 16-bit L*a*b* and back.\n" +                    "Watercolor and openEXR colorspaces will even be converted through 8-bit RGB.\n") +                    .arg(image->colorSpace()->id().name()), +            i18n("Colorspace Conversion"), +            KGuiItem(i18n("Continue")), +            "lab16degradation") != KMessageBox::Continue) return; + +    } + +    DlgColorSpaceConversion * dlgColorSpaceConversion = new DlgColorSpaceConversion(m_view, "ColorSpaceConversion"); +    Q_CHECK_PTR(dlgColorSpaceConversion); + +    dlgColorSpaceConversion->setCaption(i18n("Convert All Layers From ") + image->colorSpace()->id().name()); + +    if (dlgColorSpaceConversion->exec() == QDialog::Accepted) { +        // XXX: Do the rest of the stuff +        KisID cspace = dlgColorSpaceConversion->m_page->cmbColorSpaces->currentItem(); +        KisColorSpace * cs = KisMetaRegistry::instance()->csRegistry()->getColorSpace(cspace, dlgColorSpaceConversion->m_page->cmbDestProfile->currentText()); + +        QApplication::setOverrideCursor(KisCursor::waitCursor()); +        image->convertTo(cs, dlgColorSpaceConversion->m_page->grpIntent->selectedId()); +        QApplication::restoreOverrideCursor(); +    } +    delete dlgColorSpaceConversion; +} + +void ColorSpaceConversion::slotLayerColorSpaceConversion() +{ + +    KisImageSP image = m_view->canvasSubject()->currentImg(); +    if (!image) return; + +    KisPaintDeviceSP dev = image->activeDevice(); +    if (!dev) return; + +    if (dev->colorSpace()->willDegrade(TO_LAB16)) { +        if (KMessageBox::warningContinueCancel(m_view, +            i18n("This conversion will convert your %1 layer through 16-bit L*a*b* and back.\n" +                    "Watercolor and openEXR colorspaces will even be converted through 8-bit RGB.\n") +                    .arg(dev->colorSpace()->id().name()), +            i18n("Colorspace Conversion"), +            KGuiItem(i18n("Continue")), +            "lab16degradation") != KMessageBox::Continue) return; + +    } + +    DlgColorSpaceConversion * dlgColorSpaceConversion = new DlgColorSpaceConversion(m_view, "ColorSpaceConversion"); +    Q_CHECK_PTR(dlgColorSpaceConversion); + +    dlgColorSpaceConversion->setCaption(i18n("Convert Current Layer From") + dev->colorSpace()->id().name()); + +    if (dlgColorSpaceConversion->exec() == QDialog::Accepted) { +        KisID cspace = dlgColorSpaceConversion->m_page->cmbColorSpaces->currentItem(); +        KisColorSpace * cs = KisMetaRegistry::instance()->csRegistry() -> +                getColorSpace(cspace, dlgColorSpaceConversion->m_page->cmbDestProfile->currentText()); + +        QApplication::setOverrideCursor(KisCursor::waitCursor()); +        dev->convertTo(cs, dlgColorSpaceConversion->m_page->grpIntent->selectedId()); +        QApplication::restoreOverrideCursor(); +    } +    delete dlgColorSpaceConversion; +} + +#include "colorspaceconversion.moc" diff --git a/krita/plugins/viewplugins/colorspaceconversion/colorspaceconversion.h b/krita/plugins/viewplugins/colorspaceconversion/colorspaceconversion.h new file mode 100644 index 000000000..3bf85530c --- /dev/null +++ b/krita/plugins/viewplugins/colorspaceconversion/colorspaceconversion.h @@ -0,0 +1,50 @@ +/*  + * colorspaceconversion.h -- Part of Krita + * + * Copyright (c) 2004 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. + */ + +#ifndef COLORSPACECONVERSION_H +#define COLORSPACECONVERSION_H + +#include <kparts/plugin.h> + +class KisView; + +/** + * Dialog for converting between color models. + */ +class ColorSpaceConversion : public KParts::Plugin +{ +    Q_OBJECT +public: +    ColorSpaceConversion(QObject *parent, const char *name, const QStringList &); +    virtual ~ColorSpaceConversion(); +     +private slots: + +    void slotImgColorSpaceConversion(); +    void slotLayerColorSpaceConversion(); + +private: + +    KisView * m_view; +    KisPainter * m_painter; + +}; + +#endif // COLORSPACECONVERSION_H diff --git a/krita/plugins/viewplugins/colorspaceconversion/colorspaceconversion.rc b/krita/plugins/viewplugins/colorspaceconversion/colorspaceconversion.rc new file mode 100644 index 000000000..01feae6c7 --- /dev/null +++ b/krita/plugins/viewplugins/colorspaceconversion/colorspaceconversion.rc @@ -0,0 +1,11 @@ +<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd"> +<kpartgui library="kritacolorspaceconversion" version="1"> +<MenuBar> +    <Menu name="Image"><text>&Image</text> +		<Action name="imgcolorspaceconversion"/> +    </Menu> +    <Menu name="Layer"><text>La&yer</text> +		<Action name="layercolorspaceconversion"/> +    </Menu> +</MenuBar> +</kpartgui> diff --git a/krita/plugins/viewplugins/colorspaceconversion/dlg_colorspaceconversion.cc b/krita/plugins/viewplugins/colorspaceconversion/dlg_colorspaceconversion.cc new file mode 100644 index 000000000..b59fb5464 --- /dev/null +++ b/krita/plugins/viewplugins/colorspaceconversion/dlg_colorspaceconversion.cc @@ -0,0 +1,91 @@ +/* + *  dlg_colorspaceconversion.cc - part of KimageShop^WKrayon^WKrita + * + *  Copyright (c) 2004 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 <qradiobutton.h> +#include <qcheckbox.h> +#include <qlabel.h> +#include <qcombobox.h> +#include <qptrlist.h> + +#include <klocale.h> +#include <knuminput.h> +#include <kdebug.h> + +#include "kis_meta_registry.h" +#include <kis_colorspace_factory_registry.h> +#include "kis_profile.h" +#include "kis_colorspace.h" +#include <kis_id.h> +#include <kis_cmb_idlist.h> +#include <squeezedcombobox.h> + +#include "wdgconvertcolorspace.h" +#include "dlg_colorspaceconversion.h" + +DlgColorSpaceConversion::DlgColorSpaceConversion( QWidget *  parent, +                          const char * name) +    : super (parent, name, true, i18n("Image Size"), Ok | Cancel, Ok) +{ +    m_page = new WdgConvertColorSpace(this, "colorspace_conversion"); +    Q_CHECK_PTR(m_page); + +    setMainWidget(m_page); +    resize(m_page->sizeHint()); + +    m_page->cmbColorSpaces->setIDList(KisMetaRegistry::instance()->csRegistry()->listKeys()); + +    fillCmbDestProfile(m_page->cmbColorSpaces->currentItem()); + +    connect(m_page->cmbColorSpaces, SIGNAL(activated(const KisID &)), +        this, SLOT(fillCmbDestProfile(const KisID &))); + + +    connect(this, SIGNAL(okClicked()), +        this, SLOT(okClicked())); + +} + +DlgColorSpaceConversion::~DlgColorSpaceConversion() +{ +    delete m_page; +} + +// SLOTS + +void DlgColorSpaceConversion::okClicked() +{ +    accept(); +} + + +void DlgColorSpaceConversion::fillCmbDestProfile(const KisID & s) +{ +    m_page->cmbDestProfile->clear(); + +    QValueVector<KisProfile *>  profileList = KisMetaRegistry::instance()->csRegistry()->profilesFor(s); +        QValueVector<KisProfile *> ::iterator it; +        for ( it = profileList.begin(); it != profileList.end(); ++it ) { +        m_page->cmbDestProfile->insertItem((*it)->productName()); + +    } +} + + +#include "dlg_colorspaceconversion.moc" diff --git a/krita/plugins/viewplugins/colorspaceconversion/dlg_colorspaceconversion.h b/krita/plugins/viewplugins/colorspaceconversion/dlg_colorspaceconversion.h new file mode 100644 index 000000000..ed086a8d8 --- /dev/null +++ b/krita/plugins/viewplugins/colorspaceconversion/dlg_colorspaceconversion.h @@ -0,0 +1,49 @@ +/* + *  dlg_colorspaceconversion.h -- part of KimageShop^WKrayon^WKrita + * + *  Copyright (c) 2004 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. + */ +#ifndef DLG_COLORSPACECONVERSION +#define DLG_COLORSPACECONVERSION + +#include <kdialogbase.h> + +#include <kis_id.h> + +class WdgConvertColorSpace; + +/** + * XXX + */ +class DlgColorSpaceConversion: public KDialogBase { +    typedef KDialogBase super; +    Q_OBJECT + +public: + +    DlgColorSpaceConversion(QWidget * parent = 0, const char* name = 0); +    ~DlgColorSpaceConversion(); + +    WdgConvertColorSpace * m_page; + +public slots: + +    void okClicked(); +    void fillCmbDestProfile(const KisID &); +}; + +#endif // DLG_COLORSPACECONVERSION diff --git a/krita/plugins/viewplugins/colorspaceconversion/kritacolorspaceconversion.desktop b/krita/plugins/viewplugins/colorspaceconversion/kritacolorspaceconversion.desktop new file mode 100644 index 000000000..15436a120 --- /dev/null +++ b/krita/plugins/viewplugins/colorspaceconversion/kritacolorspaceconversion.desktop @@ -0,0 +1,40 @@ +[Desktop Entry] +Name=Colorspace Conversion +Name[bg]=Цветово обръщане +Name[ca]=Conversió d'espai de color +Name[da]=Farverumskonvertering +Name[de]=Farbraumumwandlung +Name[el]=Μετατροπή χρωματικού χώρου +Name[en_GB]=Colourspace Conversion +Name[eo]=Kolorspackonvertado +Name[es]=Conversión de espacio de color +Name[et]=Värviruumi teisendus +Name[fa]=تبدیل فاصله رنگ +Name[fr]=Conversion d'espaces de couleurs +Name[fy]=Konversje fan kleurspektrum +Name[gl]=Conversión de Espazos de Cores +Name[hu]=Színtér-konverzió +Name[is]=Litasvæðis umbreyting +Name[it]=Conversione dello spazio dei colori +Name[ja]=カラースペース変換 +Name[km]=បម្លែងប្រភេទពណ៌ +Name[nb]=Fargerom-konvertering +Name[nds]=Klörenruum-Ümwanneln +Name[ne]=रङ खालीस्थान रूपानान्तरण +Name[nl]=Conversie van kleurspectrum +Name[pl]=Konwersja przestrzeni barw +Name[pt]=Conversão de Espaços de Cores +Name[pt_BR]=Conversão de Espaços de Cores +Name[ru]=Цветовые пространства +Name[se]=Ivdnegaskkadat-konveršuvdna +Name[sk]=Konverzia farebného priestoru +Name[sl]=Pretvorba barvnega prostora +Name[sr]=Претварање простора боја +Name[sr@Latn]=Pretvaranje prostora boja +Name[sv]=Färgrymdskonvertering +Name[uk]=Перетворення простору кольорів +Name[zh_TW]=色彩空間轉換 +ServiceTypes=Krita/ViewPlugin +Type=Service +X-KDE-Library=kritacolorspaceconversion +X-Krita-Version=2 diff --git a/krita/plugins/viewplugins/colorspaceconversion/wdgconvertcolorspace.ui b/krita/plugins/viewplugins/colorspaceconversion/wdgconvertcolorspace.ui new file mode 100644 index 000000000..31f29be53 --- /dev/null +++ b/krita/plugins/viewplugins/colorspaceconversion/wdgconvertcolorspace.ui @@ -0,0 +1,218 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>WdgConvertColorSpace</class> +<widget class="QWidget"> +    <property name="name"> +        <cstring>WdgConvertColorSpace</cstring> +    </property> +    <property name="geometry"> +        <rect> +            <x>0</x> +            <y>0</y> +            <width>399</width> +            <height>228</height> +        </rect> +    </property> +    <property name="caption"> +        <string>Colorspace Conversion</string> +    </property> +    <grid> +        <property name="name"> +            <cstring>unnamed</cstring> +        </property> +        <widget class="QLabel" row="0" column="0"> +            <property name="name"> +                <cstring>lblConvert</cstring> +            </property> +            <property name="text"> +                <string>&Target color space:</string> +            </property> +            <property name="buddy" stdset="0"> +                <cstring>cmbColorSpaces</cstring> +            </property> +        </widget> +        <widget class="KisCmbIDList" row="0" column="1"> +            <property name="name"> +                <cstring>cmbColorSpaces</cstring> +            </property> +            <property name="sizePolicy"> +                <sizepolicy> +                    <hsizetype>3</hsizetype> +                    <vsizetype>0</vsizetype> +                    <horstretch>0</horstretch> +                    <verstretch>0</verstretch> +                </sizepolicy> +            </property> +        </widget> +        <widget class="SqueezedComboBox" row="1" column="1"> +            <item> +                <property name="text"> +                    <string>Default</string> +                </property> +            </item> +            <property name="name"> +                <cstring>cmbDestProfile</cstring> +            </property> +        </widget> +        <widget class="QButtonGroup" row="2" column="0" rowspan="1" colspan="2"> +            <property name="name"> +                <cstring>grpIntent</cstring> +            </property> +            <property name="title"> +                <string>&Rendering Intent</string> +            </property> +            <property name="toolTip" stdset="0"> +                <string></string> +            </property> +            <grid> +                <property name="name"> +                    <cstring>unnamed</cstring> +                </property> +                <widget class="QRadioButton" row="0" column="0"> +                    <property name="name"> +                        <cstring>radioPerceptual</cstring> +                    </property> +                    <property name="text"> +                        <string>Perceptual</string> +                    </property> +                    <property name="accel"> +                        <string></string> +                    </property> +                    <property name="checked"> +                        <bool>true</bool> +                    </property> +                    <property name="toolTip" stdset="0"> +                        <string>For images</string> +                    </property> +                    <property name="whatsThis" stdset="0"> +                        <string>Hue hopefully maintained (but not required), +lightness and saturation sacrificed to maintain +the perceived color. White point changed to +result in neutral grays. Intended for images.</string> +                    </property> +                </widget> +                <widget class="QRadioButton" row="1" column="0"> +                    <property name="name"> +                        <cstring>radioRelativeColorimetric</cstring> +                    </property> +                    <property name="text"> +                        <string>Relative colorimetric</string> +                    </property> +                    <property name="accel"> +                        <string></string> +                    </property> +                    <property name="whatsThis" stdset="0"> +                        <string>Within and outside gamut; same as Absolute +Colorimetric. White point changed to result in +neutral grays. + +If adequate table is present in profile, +then, it is used. Else reverts to perceptual +intent.</string> +                    </property> +                </widget> +                <widget class="QRadioButton" row="2" column="0"> +                    <property name="name"> +                        <cstring>radioSaturation</cstring> +                    </property> +                    <property name="text"> +                        <string>Saturation</string> +                    </property> +                    <property name="accel"> +                        <string></string> +                    </property> +                    <property name="toolTip" stdset="0"> +                        <string>Best for graphs and charts</string> +                    </property> +                    <property name="whatsThis" stdset="0"> +                        <string>Hue and saturation maintained with lightness +sacrificed to maintain saturation. White point +changed to result in neutral grays. Intended for +business graphics (make it colorful charts, +graphs, overheads, ...) + +If adequate table is present in profile, +then, it is used. Else reverts to perceptual +intent.</string> +                    </property> +                </widget> +                <widget class="QRadioButton" row="3" column="0"> +                    <property name="name"> +                        <cstring>radioAbsoluteColorimetric</cstring> +                    </property> +                    <property name="text"> +                        <string>Absolute colorimetric</string> +                    </property> +                    <property name="accel"> +                        <string></string> +                    </property> +                    <property name="toolTip" stdset="0"> +                        <string>Best for spot colours</string> +                    </property> +                    <property name="whatsThis" stdset="0"> +                        <string>Within the destination device gamut; hue, +lightness and saturation are maintained. Outside +the gamut; hue and lightness are maintained, +saturation is sacrificed. White point for source +and destination; unchanged. Intended for spot +colors (Pantone, TruMatch, logo colors, ...)</string> +                    </property> +                </widget> +            </grid> +        </widget> +        <widget class="QLabel" row="1" column="0"> +            <property name="name"> +                <cstring>lblDestICMProfile</cstring> +            </property> +            <property name="text"> +                <string>&Destination ICM profile:</string> +            </property> +            <property name="buddy" stdset="0"> +                <cstring>cmbDestProfile</cstring> +            </property> +        </widget> +    </grid> +</widget> +<customwidgets> +    <customwidget> +        <class>KisCmbIDList</class> +        <header location="local">kis_cmb_idlist.h</header> +        <sizehint> +            <width>1</width> +            <height>24</height> +        </sizehint> +        <container>0</container> +        <sizepolicy> +            <hordata>5</hordata> +            <verdata>5</verdata> +            <horstretch>0</horstretch> +            <verstretch>0</verstretch> +        </sizepolicy> +        <pixmap>image0</pixmap> +    </customwidget> +    <customwidget> +        <class>SqueezedComboBox</class> +        <header location="local">squeezedcombobox.h</header> +        <sizehint> +            <width>-1</width> +            <height>i24</height> +        </sizehint> +        <container>0</container> +        <sizepolicy> +            <hordata>3</hordata> +            <verdata>0</verdata> +            <horstretch>0</horstretch> +            <verstretch>0</verstretch> +        </sizepolicy> +        <pixmap>image1</pixmap> +    </customwidget> +</customwidgets> +<images> +    <image name="image0"> +        <data format="PNG" length="870">89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b0000032d49444154388db59531681c4714863f892dde8004b320c32e3870020b74458a6b0f5458e581c016a809a8496b42208454098604d2c4904a6954a410511ae752085b858c1208dc35221244b00119f60ac12ee860062c980719708a95a248f129459cd7cceeccf0edb76fff61a706830197d5ed765ff3166a30184c4d5d829fed3c7bdd5e6ce3bda71a5738ef301802e1d6d179477152303c1842bc822797a64fbf7b4a9a43be00ada817cb0e12011c2611205ccd73755f9c087c6b19bef0d7c100f5b8267d07caf10fe8ab9210156320fc01be16aa5a11043307f30b20a21041019985f48ef2f7fa0becc68e80475fd584e831b396f210f67795c3831a4940a3228925bb27f4d652ba4b01a199b73342f3981be0ca57745042ac30c632d853b6373d44b056c8ef0922508d94d14be59b2f4aeaf58cd5751069e06f3436890114332b9487d0bf80f61e64dc5f813c3790045453f67703fd4d4f7f6b4496b5597e689044af194f5f5e841800210478bee3d1a8f41e64acbe0f69ae6852e1cf0ccf7f74f4d652defbc042226c6f55e8f89f91bb6e9c387c9d521c9558db988a3416fe3c67e32b4779ec7167f0e8939ce19ea7fc5d298a80c875f03563930855ed2081bc05e91d5014ef53363eaf288e3d6285ee520a338e76c7a251a94e41e30470d3631004a262672e3eca59cec6978ef2b889979d11f2bb904af3be92081a416e28dfe831983920b1142345d5b0ff2234a6334276d7321ad53c795c511ca654a5a251996f19b83d158ef602b45a423d52f67703abeb29ee4ce9de4fc93378f218462f6b3efdb042cf3d59666977a0aa6fe9310888d25b13342afd4dcffeaee3d147399da540ab13f8f8b39c2cb3f8710d11ba2b96f9c57fcd7180287497a03ecde86f8dd8fe1a867b9ef6bb1612a84a871f6bd35b94e217a53832589970f2dcd85d9c7d4580d57521cbdaf4bfaf288e95e268d4ec8e60e72ccb0f2dbffea454e71e8d29f57882717152509482a48d8924b0bc12e82ee51445a03a6da079cbd0eec0fc22142b06620e89a3fc8d3783870743d814d2bc8994aa6ff286472e764902e5a96f72bbd3b4c37b280e95aa9e604c84e1cf978b37c74935797d7ae2ca7fac6968fe51ff0bf86dc30783c1d49f0baa9bb819e612310000000049454e44ae426082</data> +    </image> +    <image name="image1"> +        <data format="PNG" length="1003">89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b000003b249444154388db5944d4c5c5518869f73ce9db9cc40f929cc30300e18129a50685268a28291982e1a2175212eaab1c49d3f8971e7aec6aedb54a32b435dd8685cb8c0c4b8b0feb421b7bd8186a069d23209144b18cb0c02f3732ff3c3ccbdd705a571941213f1dd9d93739ef37e6fbeef08d334d9d5d0d090c701c8344d2176c1a6697a5d5d5dd8b64d2a95c2b2ac7f05b12c8b783c8e6118d8b6fd685fdb753a39394928e2a7c55724d693a7e214104220242805520a84d8b9e4790f0b1302c7751958f1e30534be9fa41a0c60db362dbe227f64af91b6e7719c2dfc0117a71c603da591de2882a7d3d4ec27122b10acad50aeb88044d542b84de3af7ab44aa55274f4e449dbf354bc347aa096fbf37e7efa2ecbad1b36907d78b289de8120232f37726250c3f52cf0a026a0f6065b9645d929e038167aa096d91b307171059034b5f8e9e9eb44fa052b4b25eeccd9dc99cb71f6ad082fbea2e351c075bdbdc13b9109fc01b83fef63e2e232e03076b68393231a0dcd024daf502c1e66e67a89cb971ef0e5a74bb4b61e6378248094b92ab0ac024b70ca017ef8360394187b2dc6d8b89ffa500e4d4f93d9083275d5e6f9913ade3dd70ee87c7d25c95646a25415aadab152b09ed4f8c5cc130a853839eac3951b684a61e70ef3f9c739668c24eba912afbfddc6d4d506e6a6d7b8b7d082aa8eb8dab19482cdcd220e36dd3dc19df23545de0a71f952861923493456cfd3cf36123c54a0b7bf0e8064621b21f7712c040857071ca4eea0f40a99f510573ec971cb48030e811a1faded3e94be85f2fb00703d1ff26f96ab9f011a5b04d0c4f26fdb948a754c1b25668c2491483d5d5d611617d6b8f0fe32cb779b492ce65168b4c774a4701eefd8f3a02d56e6e8f13aeefe9a63fa5a89d1970e91d908f3d46003e1480d173e28b37827c9b977348ab92ce16890237d1ec907ee3e8e3d8f60d0e1f4583d009f7d9860662acff89bad1c1faad0717493f7ce7713ed8cb0995c255f2a317a26427b67198f6a70f51c0a41b902279ed1187f23cc17130b7c74de65eac77a7a8f05517e41e2deefa4930576db60fa7a8ee1535134df3e93e7b82e0817476439fd6a9070a49f6fbe4a3077739db99b15c001146dd13a46cf1cc1f83943c62e51de76b0738fc9381e8f3390f0236b252e124999e11724fd833196164bacadb87848224fe874f779b43fe9f2dca928956d505a96dbb3f9bdc18661e00534c26d1a7a40e13912a11c9454280da41048a9915c75585df500074d53d816dc9edd229528ef0db66dbbea3ffdaffa471f1f28d8344df1bf800f1a6e9aa6f813c39885bc050f269c0000000049454e44ae426082</data> +    </image> +</images> +<layoutdefaults spacing="6" margin="11"/> +</UI> diff --git a/krita/plugins/viewplugins/dropshadow/Makefile.am b/krita/plugins/viewplugins/dropshadow/Makefile.am new file mode 100644 index 000000000..c339627ec --- /dev/null +++ b/krita/plugins/viewplugins/dropshadow/Makefile.am @@ -0,0 +1,30 @@ +kritarcdir = $(kde_datadir)/kritaplugins +kritarc_DATA = dropshadow.rc +EXTRA_DIST = $(kritarc_DATA) + +INCLUDES  =  -I$(srcdir)/../../../sdk \ +	-I$(srcdir)/../../../core \ +	-I$(srcdir)/../../../kritacolor/ \ +	-I$(srcdir)/../../../colorspaces/rgb_u8 \ +	-I$(srcdir)/../../../ui \ +	$(KOFFICE_INCLUDES) \ +	$(all_includes) + + +kde_module_LTLIBRARIES = kritadropshadow.la + +kritadropshadow_la_SOURCES = wdg_dropshadow.ui \ +	kis_dropshadow.cc dlg_dropshadow.cc  \ +	kis_dropshadow_plugin.cc + +noinst_HEADERS = wdg_dropshadow.h kis_dropshadow_plugin.h \ +		kis_dropshadow.h dlg_dropshadow.h + +kritadropshadow_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) +kritadropshadow_la_LIBADD =  ../../../libkritacommon.la ../../../colorspaces/rgb_u8/libkritargb.la + +kde_services_DATA = kritadropshadow.desktop + +kritadropshadow_la_METASOURCES = AUTO + +KDE_OPTIONS = nofinal diff --git a/krita/plugins/viewplugins/dropshadow/dlg_dropshadow.cc b/krita/plugins/viewplugins/dropshadow/dlg_dropshadow.cc new file mode 100644 index 000000000..545f886f4 --- /dev/null +++ b/krita/plugins/viewplugins/dropshadow/dlg_dropshadow.cc @@ -0,0 +1,117 @@ +/* + *  dlg_dropshadow.cc - part of KimageShop^WKrayon^WKrita + * + *  Copyright (c) 2005 Michael Thaler <michael.thaler@physik.tu-muenchen.de> + *  Copyright (c) 2006 Cyrille Berger <cberger@cberger.net> + * + *  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 <qbutton.h> +#include <qbuttongroup.h> +#include <qcheckbox.h> +#include <qcolor.h> +#include <qcombobox.h> +#include <qlabel.h> +#include <qradiobutton.h> +#include <qslider.h> + +#include <kcolorbutton.h> +#include <kconfig.h> +#include <kdebug.h> +#include <klocale.h> +#include <knuminput.h> + +#include "dlg_dropshadow.h" +#include "wdg_dropshadow.h" + +DlgDropshadow::DlgDropshadow( const QString & /*imageCS*/, +                          const QString & /*layerCS*/, +                          QWidget *  parent, +                          const char * name) +    : super (parent, name, true, i18n("Drop Shadow"), Ok | Cancel, Ok) +{ +    m_page = new WdgDropshadow(this, "dropshadow"); +    Q_CHECK_PTR(m_page); +    setMainWidget(m_page); +    resize(m_page->sizeHint()); + +    KConfig * cfg = KGlobal::config(); +    m_page->xOffsetSpinBox->setValue( cfg->readNumEntry("dropshadow_x", 8) ); +    m_page->yOffsetSpinBox->setValue( cfg->readNumEntry("dropshadow_y", 8) ); +    m_page->blurRadiusSpinBox->setValue( cfg->readNumEntry("dropshadow_blurRadius", 5) ); +    QColor black(0,0,0); +    m_page->shadowColorButton->setColor( cfg->readColorEntry("dropshadow_color", &black) ); +    m_page->opacitySlider->setValue( cfg->readNumEntry("dropshadow_opacity", 80 ) ); +    m_page->opacitySpinBox->setValue( cfg->readNumEntry("dropshadow_opacity", 80 ) ); +    m_page->allowResizingCheckBox->setChecked( cfg->readBoolEntry("dropshadow_resizing", true ) ); +     +    connect(this, SIGNAL(okClicked()), +        this, SLOT(okClicked())); +} + +DlgDropshadow::~DlgDropshadow() +{ +    delete m_page; +} + +Q_INT32 DlgDropshadow::getXOffset() +{ +    return m_page->xOffsetSpinBox->value(); +} + +Q_INT32 DlgDropshadow::getYOffset() +{ +    return m_page->yOffsetSpinBox->value(); +} + +Q_INT32 DlgDropshadow::getBlurRadius() +{ +    return m_page->blurRadiusSpinBox->value(); +} + +Q_UINT8 DlgDropshadow::getShadowOpacity() +{ +    double opacity = (double)m_page->opacitySpinBox->value(); +    //convert percent to a 8 bit opacity value +    return (Q_UINT8)(opacity / 100 * 255); +} + +QColor DlgDropshadow::getShadowColor() +{ +    return m_page->shadowColorButton->color(); +} + +bool DlgDropshadow::allowResizingChecked() +{ +    return m_page->allowResizingCheckBox->isChecked(); +} + +// SLOTS + +void DlgDropshadow::okClicked() +{ +    KConfig * cfg = KGlobal::config(); +    cfg->writeEntry("dropshadow_x", m_page->xOffsetSpinBox->value()); +    cfg->writeEntry("dropshadow_y", m_page->yOffsetSpinBox->value()); +    cfg->writeEntry("dropshadow_blurRadius", m_page->blurRadiusSpinBox->value()); +    cfg->writeEntry("dropshadow_color", m_page->shadowColorButton->color()); +    cfg->writeEntry("dropshadow_opacity", m_page->opacitySpinBox->value()); +    cfg->writeEntry("dropshadow_resizing", m_page->allowResizingCheckBox->isChecked()); +     +    accept(); +} + +#include "dlg_dropshadow.moc" diff --git a/krita/plugins/viewplugins/dropshadow/dlg_dropshadow.h b/krita/plugins/viewplugins/dropshadow/dlg_dropshadow.h new file mode 100644 index 000000000..8e5146587 --- /dev/null +++ b/krita/plugins/viewplugins/dropshadow/dlg_dropshadow.h @@ -0,0 +1,59 @@ +/* + *  dlg_dropshadow.h -- part of KimageShop^WKrayon^WKrita + * + *  Copyright (c) 2005 Michael Thaler <michael.thaler@physik.tu-muenchen.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 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. + */ +#ifndef DLG_DROPSHADOW +#define DLG_DROPSHADOW + +#include <kdialogbase.h> +#include <kis_dropshadow.h> + +class WdgDropshadow; +class QColor; + +/** + * This dialog allows the user to configure the decomposition of an image + * into layers: one layer for each color channel. + */ +class DlgDropshadow: public KDialogBase { +    typedef KDialogBase super; +    Q_OBJECT + +public: + +    DlgDropshadow(const QString & imageCS, const QString & layerCS, QWidget * parent = 0, +             const char* name = 0); +    ~DlgDropshadow(); + +public: + +    Q_INT32 getXOffset(); +    Q_INT32 getYOffset(); +    Q_INT32 getBlurRadius(); +    Q_UINT8 getShadowOpacity(); +    QColor getShadowColor(); +    bool allowResizingChecked(); +private slots: +    void okClicked(); + +private: + +    WdgDropshadow * m_page; +}; + +#endif // DLG_DROPSHADOW diff --git a/krita/plugins/viewplugins/dropshadow/dropshadow.rc b/krita/plugins/viewplugins/dropshadow/dropshadow.rc new file mode 100644 index 000000000..e5a446b25 --- /dev/null +++ b/krita/plugins/viewplugins/dropshadow/dropshadow.rc @@ -0,0 +1,11 @@ +<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd"> +<kpartgui library="kritadropshadow" version="6"> +<MenuBar> +    <Menu name="Layer"><text>La&yer</text> +       <Separator/> +       <Menu name="layerEffects"><text>Layer Effects</text> +            <Action name="dropshadow"/> +       </Menu> +    </Menu> +</MenuBar> +</kpartgui> diff --git a/krita/plugins/viewplugins/dropshadow/kis_dropshadow.cc b/krita/plugins/viewplugins/dropshadow/kis_dropshadow.cc new file mode 100644 index 000000000..7881f568f --- /dev/null +++ b/krita/plugins/viewplugins/dropshadow/kis_dropshadow.cc @@ -0,0 +1,758 @@ +/* + * This file is part of Krita + * + * Copyright (c) 2005 Michael Thaler <michael.thaler@physik.tu-muenchen.de> + * + * The gaussian blur algoithm is ported from gimo + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + *  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 <limits.h> + +#include <stdlib.h> +#include <vector> + +#include <qcolor.h> + +#include <klocale.h> +#include <kiconloader.h> +#include <kinstance.h> +#include <kmessagebox.h> +#include <kstandarddirs.h> +#include <ktempfile.h> +#include <kdebug.h> +#include <kgenericfactory.h> +#include <knuminput.h> + +#include <kis_doc.h> +#include <kis_image.h> +#include <kis_iterators_pixel.h> +#include <kis_layer.h> +#include <kis_paint_layer.h> +#include <kis_group_layer.h> +#include "kis_meta_registry.h" +#include <kis_transaction.h> +#include <kis_undo_adapter.h> +#include <kis_global.h> +#include <kis_types.h> +#include <kis_progress_subject.h> +#include <kis_progress_display_interface.h> +#include <kis_colorspace.h> +#include <kis_colorspace_factory_registry.h> +#include <kis_view.h> +#include <kis_paint_device.h> +#include <kis_channelinfo.h> +#include <kis_convolution_painter.h> +#include "kis_rgb_colorspace.h" + +#include "kis_dropshadow.h" + +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) +#define MAX(a, b) (((a) > (b)) ? (a) : (b)) + +KisDropshadow::KisDropshadow(KisView * view) +    : m_view(view) +{ +} + +void KisDropshadow::dropshadow(KisProgressDisplayInterface * progress, Q_INT32 xoffset, Q_INT32 yoffset, Q_INT32 blurradius, QColor color, Q_UINT8 opacity, bool allowResize) +{ +    KisImageSP image = m_view->canvasSubject()->currentImg(); +    if (!image) return; + +    KisLayerSP src = image->activeLayer(); +    if (!src) return; + +    KisPaintDeviceSP dev = image->activeDevice(); +    if (!dev) return; + +    m_cancelRequested = false; +    if ( progress ) +        progress->setSubject(this, true, true); +    emit notifyProgressStage(i18n("Add drop shadow..."), 0); + +    if (image->undo()) { +        image->undoAdapter()->beginMacro(i18n("Add Drop Shadow")); +    } + +    KisPaintDeviceSP shadowDev = new KisPaintDevice( KisMetaRegistry::instance()->csRegistry()->getColorSpace(KisID("RGBA",""),"" ), "Shadow"); +    KisPaintDeviceSP bShadowDev; +    KisRgbColorSpace *rgb8cs = static_cast<KisRgbColorSpace *>(shadowDev->colorSpace()); + +    QRect rect = dev->exactBounds(); + +    for (Q_INT32 row = 0; row < rect.height(); ++row) +    { +        KisHLineIteratorPixel srcIt = dev->createHLineIterator(rect.x(), rect.y() + row, rect.width(), false); +        KisHLineIteratorPixel dstIt = shadowDev->createHLineIterator(rect.x(), rect.y() + row, rect.width(), true); +        while( ! srcIt.isDone() ) +        { +            if (srcIt.isSelected()) +            { +                //set the shadow color +                Q_UINT8 alpha = dev->colorSpace()->getAlpha(srcIt.rawData()); +                rgb8cs->setPixel(dstIt.rawData(), color.red(), color.green(), color.blue(), alpha); +            } +            ++srcIt; +            ++dstIt; +        } +        emit notifyProgress((row * 100) / rect.height() ); +    } + +    if( blurradius > 0 ) +    { +        bShadowDev = new KisPaintDevice( KisMetaRegistry::instance()->csRegistry()->getColorSpace(KisID("RGBA",""),"" ), "bShadow"); +        gaussianblur(shadowDev, bShadowDev, rect, blurradius, blurradius, BLUR_RLE, progress); +        shadowDev = bShadowDev; +    } + +    if (!m_cancelRequested) { +        shadowDev->move (xoffset,yoffset); + +        KisGroupLayerSP parent = image->rootLayer(); +        if (image->activeLayer()) +            parent = image->activeLayer()->parent().data(); + +        KisPaintLayerSP l = new KisPaintLayer(image, i18n("Drop Shadow"), opacity, shadowDev); +        image->addLayer( l.data(), parent, src->siblingBelow() ); + +        if (allowResize) +        { +            QRect shadowBounds = shadowDev->exactBounds(); + +            if (!image->bounds().contains(shadowBounds)) { + +                QRect newImageSize = image->bounds() | shadowBounds; +                image->resize(newImageSize.width(), newImageSize.height()); + +                if (shadowBounds.left() < 0 || shadowBounds.top() < 0) { + +                    Q_INT32 newRootX = image->rootLayer()->x(); +                    Q_INT32 newRootY = image->rootLayer()->y(); + +                    if (shadowBounds.left() < 0) { +                        newRootX += -shadowBounds.left(); +                    } +                    if (shadowBounds.top() < 0) { +                        newRootY += -shadowBounds.top(); +                    } + +                    KCommand *moveCommand = image->rootLayer()->moveCommand(QPoint(image->rootLayer()->x(), image->rootLayer()->y()), +                                                                            QPoint(newRootX, newRootY)); +                    Q_ASSERT(moveCommand != 0); + +                    if (moveCommand) { +                        moveCommand->execute(); +                        if (image->undo()) { +                            image->undoAdapter()->addCommand(moveCommand); +                        } else { +                            delete moveCommand; +                        } +                    } +                } +            } +        } +        m_view->canvasSubject()->document()->setModified(true); +    } + +    if (image->undo()) { +        image->undoAdapter()->endMacro(); +    } + +    emit notifyProgressDone(); +} + +void KisDropshadow::gaussianblur (KisPaintDeviceSP srcDev, KisPaintDeviceSP dstDev, QRect& rect, double horz, double vert, BlurMethod method, KisProgressDisplayInterface *) +{ +    Q_INT32 width, height; +    Q_INT32 bytes; +    Q_UINT8 *dest, *dp; +    Q_UINT8 *src, *sp, *sp_p, *sp_m; +    Q_INT32 *buf = NULL; +    Q_INT32 *bb; +    double n_p[5], n_m[5]; +    double d_p[5], d_m[5]; +    double bd_p[5], bd_m[5]; +    double *val_p = NULL; +    double *val_m = NULL; +    double *vp, *vm; +    Q_INT32 x1, y1, x2, y2; +    Q_INT32 i, j; +    Q_INT32 row, col, b; +    Q_INT32 terms; +    double progress, max_progress; +    Q_INT32 initial_p[4]; +    Q_INT32 initial_m[4]; +    double std_dev; +    Q_INT32 pixels; +    Q_INT32 total = 1; +    Q_INT32 start, end; +    Q_INT32 *curve; +    Q_INT32 *sum = NULL; +    Q_INT32 val; +    Q_INT32 length; +    Q_INT32 initial_pp, initial_mm; + +    x1 = (Q_INT32)(rect.x() - horz); +    y1 = (Q_INT32)(rect.y() - vert); +    width = (Q_INT32)(rect.width() + 2 * horz); +    height = (Q_INT32)(rect.height() + 2 * vert); +    x2 = x1 + width; +    y2 = y1 + height; + +    if (width < 1 || height < 1) return; + +    emit notifyProgressStage(i18n("Blur..."), 0); + +    bytes = srcDev->pixelSize(); + +    switch (method) +    { +    case BLUR_IIR: +        val_p = new double[MAX (width, height) * bytes]; +        val_m = new double[MAX (width, height) * bytes]; +        break; + +    case BLUR_RLE: +        buf = new Q_INT32[MAX (width, height) * 2]; +        break; +    } + +    src =  new Q_UINT8[MAX (width, height) * bytes]; +    dest = new Q_UINT8[MAX (width, height) * bytes]; + +    progress = 0.0; +    max_progress  = (horz <= 0.0 ) ? 0 : width * height * horz; +    max_progress += (vert <= 0.0 ) ? 0 : width * height * vert; + + +    /*  First the vertical pass  */ +    if (vert > 0.0) +    { +        vert = fabs (vert) + 1.0; +        std_dev = sqrt (-(vert * vert) / (2 * log (1.0 / 255.0))); + +        switch (method) +        { +        case BLUR_IIR: +            /*  derive the constants for calculating the gaussian +             *  from the std dev +             */ +            find_constants (n_p, n_m, d_p, d_m, bd_p, bd_m, std_dev); +            break; + +        case BLUR_RLE: +            curve = make_curve (std_dev, &length); +            sum = new Q_INT32[2 * length + 1]; + +            sum[0] = 0; + +            for (i = 1; i <= length*2; i++) +                sum[i] = curve[i-length-1] + sum[i-1]; +            sum += length; + +            total = sum[length] - sum[-length]; +            break; +        } + +        for (col = 0; col < width; col++) +        { +            switch (method) +            { +            case BLUR_IIR: +                memset (val_p, 0, height * bytes * sizeof (double)); +                memset (val_m, 0, height * bytes * sizeof (double)); +                break; + +            case BLUR_RLE: +                break; +            } + +            //gimp_pixel_rgn_get_col (&src_rgn, src, col + x1, y1, height); +            srcDev->readBytes(src, col+x1, y1, 1, height); + +            multiply_alpha (src, height, bytes); + +            switch (method) +            { +            case BLUR_IIR: +                sp_p = src; +                sp_m = src + (height - 1) * bytes; +                vp = val_p; +                vm = val_m + (height - 1) * bytes; + +                /*  Set up the first vals  */ +                for (i = 0; i < bytes; i++) +                { +                    initial_p[i] = sp_p[i]; +                    initial_m[i] = sp_m[i]; +                } + +                for (row = 0; row < height; row++) +                { +                    double *vpptr, *vmptr; +                    terms = (row < 4) ? row : 4; + +                    for (b = 0; b < bytes; b++) +                    { +                        vpptr = vp + b; vmptr = vm + b; +                        for (i = 0; i <= terms; i++) +                        { +                            *vpptr += n_p[i] * sp_p[(-i * bytes) + b] - +                                      d_p[i] * vp[(-i * bytes) + b]; +                            *vmptr += n_m[i] * sp_m[(i * bytes) + b] - +                                      d_m[i] * vm[(i * bytes) + b]; +                        } +                        for (j = i; j <= 4; j++) +                        { +                            *vpptr += (n_p[j] - bd_p[j]) * initial_p[b]; +                            *vmptr += (n_m[j] - bd_m[j]) * initial_m[b]; +                        } +                    } + +                    sp_p += bytes; +                    sp_m -= bytes; +                    vp += bytes; +                    vm -= bytes; +                } + +                transfer_pixels (val_p, val_m, dest, bytes, height); +                break; + +            case BLUR_RLE: +                sp = src; +                dp = dest; + +                for (b = 0; b < bytes; b++) +                { +                    initial_pp = sp[b]; +                    initial_mm = sp[(height-1) * bytes + b]; + +                    /*  Determine a run-length encoded version of the row  */ +                    run_length_encode (sp + b, buf, bytes, height); + +                    for (row = 0; row < height; row++) +                    { +                        start = (row < length) ? -row : -length; +                        end = (height <= (row + length) ? +                               (height - row - 1) : length); + +                        val = 0; +                        i = start; +                        bb = buf + (row + i) * 2; + +                        if (start != -length) +                            val += initial_pp * (sum[start] - sum[-length]); + +                        while (i < end) +                        { +                            pixels = bb[0]; +                            i += pixels; +                            if (i > end) +                                i = end; +                            val += bb[1] * (sum[i] - sum[start]); +                            bb += (pixels * 2); +                            start = i; +                        } + +                        if (end != length) +                            val += initial_mm * (sum[length] - sum[end]); + +                        dp[row * bytes + b] = val / total; +                    } +                } +                break; +            } + +            separate_alpha (src, height, bytes); + +            dstDev->writeBytes(dest, col + x1, y1, 1, height); + +            progress += height * vert; +            if ((col % 5) == 0) emit notifyProgress( (Q_UINT32)((progress * 100) / max_progress)); +        } +    } + +    /*  Now the horizontal pass  */ +    if (horz > 0.0) +    { +        horz = fabs (horz) + 1.0; + +        if (horz != vert) +        { +            std_dev = sqrt (-(horz * horz) / (2 * log (1.0 / 255.0))); + +            switch (method) +            { +            case BLUR_IIR: +                /*  derive the constants for calculating the gaussian +                 *  from the std dev +                 */ +                find_constants (n_p, n_m, d_p, d_m, bd_p, bd_m, std_dev); +                break; + +            case BLUR_RLE: +                curve = make_curve (std_dev, &length); +                sum = new Q_INT32[2 * length + 1]; + +                sum[0] = 0; + +                for (i = 1; i <= length*2; i++) +                    sum[i] = curve[i-length-1] + sum[i-1]; +                sum += length; + +                total = sum[length] - sum[-length]; +                break; +            } +        } + +        for (row = 0; row < height; row++) +        { +            switch (method) +            { +            case BLUR_IIR: +                memset (val_p, 0, width * bytes * sizeof (double)); +                memset (val_m, 0, width * bytes * sizeof (double)); +                break; + +            case BLUR_RLE: +                break; +            } + + +            //gimp_pixel_rgn_get_row (&src_rgn, src, x1, row + y1, width); +            dstDev->readBytes(src, x1, row + y1, width, 1); + +            multiply_alpha (dest, width, bytes); + +            switch (method) +            { +            case BLUR_IIR: +                sp_p = src; +                sp_m = src + (width - 1) * bytes; +                vp = val_p; +                vm = val_m + (width - 1) * bytes; + +                /*  Set up the first vals  */ +                for (i = 0; i < bytes; i++) +                { +                    initial_p[i] = sp_p[i]; +                    initial_m[i] = sp_m[i]; +                } + +                for (col = 0; col < width; col++) +                { +                    double *vpptr, *vmptr; +                    terms = (col < 4) ? col : 4; + +                    for (b = 0; b < bytes; b++) +                    { +                        vpptr = vp + b; vmptr = vm + b; +                        for (i = 0; i <= terms; i++) +                        { +                            *vpptr += n_p[i] * sp_p[(-i * bytes) + b] - +                                      d_p[i] * vp[(-i * bytes) + b]; +                            *vmptr += n_m[i] * sp_m[(i * bytes) + b] - +                                      d_m[i] * vm[(i * bytes) + b]; +                        } +                        for (j = i; j <= 4; j++) +                        { +                            *vpptr += (n_p[j] - bd_p[j]) * initial_p[b]; +                            *vmptr += (n_m[j] - bd_m[j]) * initial_m[b]; +                        } +                    } + +                    sp_p += bytes; +                    sp_m -= bytes; +                    vp += bytes; +                    vm -= bytes; +                } + +                transfer_pixels (val_p, val_m, dest, bytes, width); +                break; + +            case BLUR_RLE: +                sp = src; +                dp = dest; + +                for (b = 0; b < bytes; b++) +                { +                    initial_pp = sp[b]; +                    initial_mm = sp[(width-1) * bytes + b]; + +                    /*  Determine a run-length encoded version of the row  */ +                    run_length_encode (sp + b, buf, bytes, width); + +                    for (col = 0; col < width; col++) +                    { +                        start = (col < length) ? -col : -length; +                        end = (width <= (col + length)) ? (width - col - 1) : length; + +                        val = 0; +                        i = start; +                        bb = buf + (col + i) * 2; + +                        if (start != -length) +                            val += initial_pp * (sum[start] - sum[-length]); + +                        while (i < end) +                        { +                            pixels = bb[0]; +                            i += pixels; +                            if (i > end) +                                i = end; +                            val += bb[1] * (sum[i] - sum[start]); +                            bb += (pixels * 2); +                            start = i; +                        } + +                        if (end != length) +                            val += initial_mm * (sum[length] - sum[end]); + +                        dp[col * bytes + b] = val / total; +                    } +                } +                break; +            } + +            separate_alpha (dest, width, bytes); + +            //gimp_pixel_rgn_set_row (&dest_rgn, dest, x1, row + y1, width); +            dstDev->writeBytes(dest, x1, row + y1, width, 1); + +            progress += width * horz; +            //if ((row % 5) == 0) gimp_progress_update (progress / max_progress); +            if ((row % 5) == 0) emit notifyProgress( (Q_UINT32)((progress * 100) / max_progress )); +        } +    } + +    /*  free up buffers  */ +    switch (method) +    { +    case BLUR_IIR: +        delete[] val_p; +        delete[] val_m; +        break; + +    case BLUR_RLE: +        delete[] buf; +        break; +    } + +    delete[] src; +    delete[] dest; +} + +void KisDropshadow::find_constants (double n_p[], double n_m[], double d_p[], double d_m[], double bd_p[], double bd_m[], double std_dev) +{ +    Q_INT32    i; +    double constants [8]; +    double div; + +    /*  The constants used in the implemenation of a casual sequence +     *  using a 4th order approximation of the gaussian operator +     */ + +    div = sqrt(2 * M_PI) * std_dev; +    constants [0] = -1.783 / std_dev; +    constants [1] = -1.723 / std_dev; +    constants [2] = 0.6318 / std_dev; +    constants [3] = 1.997  / std_dev; +    constants [4] = 1.6803 / div; +    constants [5] = 3.735 / div; +    constants [6] = -0.6803 / div; +    constants [7] = -0.2598 / div; + +    n_p [0] = constants[4] + constants[6]; +    n_p [1] = exp (constants[1]) * +              (constants[7] * sin (constants[3]) - +               (constants[6] + 2 * constants[4]) * cos (constants[3])) + +              exp (constants[0]) * +              (constants[5] * sin (constants[2]) - +               (2 * constants[6] + constants[4]) * cos (constants[2])); +    n_p [2] = 2 * exp (constants[0] + constants[1]) * +              ((constants[4] + constants[6]) * cos (constants[3]) * cos (constants[2]) - +               constants[5] * cos (constants[3]) * sin (constants[2]) - +               constants[7] * cos (constants[2]) * sin (constants[3])) + +              constants[6] * exp (2 * constants[0]) + +              constants[4] * exp (2 * constants[1]); +    n_p [3] = exp (constants[1] + 2 * constants[0]) * +              (constants[7] * sin (constants[3]) - constants[6] * cos (constants[3])) + +              exp (constants[0] + 2 * constants[1]) * +              (constants[5] * sin (constants[2]) - constants[4] * cos (constants[2])); +    n_p [4] = 0.0; + +    d_p [0] = 0.0; +    d_p [1] = -2 * exp (constants[1]) * cos (constants[3]) - +              2 * exp (constants[0]) * cos (constants[2]); +    d_p [2] = 4 * cos (constants[3]) * cos (constants[2]) * exp (constants[0] + constants[1]) + +              exp (2 * constants[1]) + exp (2 * constants[0]); +    d_p [3] = -2 * cos (constants[2]) * exp (constants[0] + 2 * constants[1]) - +              2 * cos (constants[3]) * exp (constants[1] + 2 * constants[0]); +    d_p [4] = exp (2 * constants[0] + 2 * constants[1]); + +    for (i = 0; i <= 4; i++) +        d_m [i] = d_p [i]; + +    n_m[0] = 0.0; +    for (i = 1; i <= 4; i++) +        n_m [i] = n_p[i] - d_p[i] * n_p[0]; + +    { +        double sum_n_p, sum_n_m, sum_d; +        double a, b; + +        sum_n_p = 0.0; +        sum_n_m = 0.0; +        sum_d = 0.0; +        for (i = 0; i <= 4; i++) +        { +            sum_n_p += n_p[i]; +            sum_n_m += n_m[i]; +            sum_d += d_p[i]; +        } + +        a = sum_n_p / (1.0 + sum_d); +        b = sum_n_m / (1.0 + sum_d); + +        for (i = 0; i <= 4; i++) +        { +            bd_p[i] = d_p[i] * a; +            bd_m[i] = d_m[i] * b; +        } +    } +} + + +void KisDropshadow::transfer_pixels (double *src1, double *src2, Q_UINT8 *dest, Q_INT32 bytes, Q_INT32 width) +{ +    Q_INT32    b; +    Q_INT32    bend = bytes * width; +    double sum; + +    for(b = 0; b < bend; b++) +    { +        sum = *src1++ + *src2++; +        if (sum > 255) sum = 255; +        else if(sum < 0) sum = 0; + +        *dest++ = (Q_UINT8) sum; +    } +} + +//The equations: g(r) = exp (- r^2 / (2 * sigma^2)), r = sqrt (x^2 + y ^2) +Q_INT32 * KisDropshadow::make_curve(double sigma, Q_INT32 *length) +{ +    int    *curve; +    double  sigma2; +    double  l; +    int     temp; +    int     i, n; + +    sigma2 = 2 * sigma * sigma; +    l = sqrt (-sigma2 * log (1.0 / 255.0)); + +    n = (int)(ceil (l) * 2); +    if ((n % 2) == 0) +        n += 1; + +    curve = new Q_INT32[n]; + +    *length = n / 2; +    curve += *length; +    curve[0] = 255; + +    for (i = 1; i <= *length; i++) +    { +        temp = (Q_INT32) (exp (- (i * i) / sigma2) * 255); +        curve[-i] = temp; +        curve[i] = temp; +    } + +    return curve; +} + +void KisDropshadow::run_length_encode (Q_UINT8 *src, Q_INT32 *dest, Q_INT32 bytes, Q_INT32 width) +{ +    Q_INT32   start; +    Q_INT32   i; +    Q_INT32   j; +    Q_UINT8 last; + +    last = *src; +    src += bytes; +    start = 0; + +    for (i = 1; i < width; i++) +    { +        if (*src != last) +        { +            for (j = start; j < i; j++) +            { +                *dest++ = (i - j); +                *dest++ = last; +            } +            start = i; +            last = *src; +        } +        src += bytes; +    } + +    for (j = start; j < i; j++) +    { +        *dest++ = (i - j); +        *dest++ = last; +    } +} + +void KisDropshadow::multiply_alpha (Q_UINT8 *buf, Q_INT32 width, Q_INT32 bytes) +{ +    Q_INT32    i, j; +    double alpha; + +    for (i = 0; i < width * bytes; i += bytes) +    { +        alpha = buf[i + bytes - 1] * (1.0 / 255.0); +        for (j = 0; j < bytes - 1; j++) { +            double a = (double)(buf[i + j]) * alpha; +            buf[i + j] = (Q_UINT8)a; +        } +    } +} + +void KisDropshadow::separate_alpha (Q_UINT8 *buf, Q_INT32 width, Q_INT32 bytes) +{ +    Q_INT32   i, j; +    Q_UINT8 alpha; +    double recip_alpha; +    Q_UINT32    new_val; + +    for (i = 0; i < width * bytes; i += bytes) +    { +        alpha = buf[i + bytes - 1]; +        if (alpha != 0 && alpha != 255) +        { +            recip_alpha = 255.0 / alpha; +            for (j = 0; j < bytes - 1; j++) +            { +                new_val = (Q_UINT32)(buf[i + j] * recip_alpha); +                buf[i + j] = MIN (255, new_val); +            } +        } +    } +} + +#include "kis_dropshadow.moc" diff --git a/krita/plugins/viewplugins/dropshadow/kis_dropshadow.h b/krita/plugins/viewplugins/dropshadow/kis_dropshadow.h new file mode 100644 index 000000000..3aca424fe --- /dev/null +++ b/krita/plugins/viewplugins/dropshadow/kis_dropshadow.h @@ -0,0 +1,71 @@ +/* + * This file is part of the KDE project + * + * Copyright (c) Michael Thaler <michael.thaler@physik.tu-muenchen.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 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. + */ + +#ifndef _KIS_DROPSHADOW_H_ +#define _KIS_DROPSHADOW_H_ + +#include <kis_progress_subject.h> +#include <kis_paint_device.h> + +typedef enum +{ +  BLUR_IIR, +  BLUR_RLE +} BlurMethod; + + +class QColor; +class KisView; +class KisProgressDisplayInterface; + +class KisDropshadow : public KisProgressSubject { + +    Q_OBJECT + +public: + +    KisDropshadow(KisView * view); +    virtual ~KisDropshadow() {}; + +    void dropshadow(KisProgressDisplayInterface * progress, Q_INT32 xoffset, Q_INT32 yoffset, Q_INT32 blurradius, QColor color, Q_UINT8 opacity, bool allowResize); + +public: // Implement KisProgressSubject +        virtual void cancel() { m_cancelRequested = true; } + +private: +    void gaussianblur (KisPaintDeviceSP src, KisPaintDeviceSP dst, +                       QRect& rect, double horz, double vert, +                       BlurMethod method, +                       KisProgressDisplayInterface * progressDisplay); +    //gaussian blur helper functions +    void find_constants(double n_p[], double n_m[], double d_p[], double d_m[], double bd_p[], double bd_m[], double  std_dev); +    void transfer_pixels(double *src1, double *src2, Q_UINT8  *dest, Q_INT32 bytes, Q_INT32 width); +    Q_INT32* make_curve(double sigma, Q_INT32 *length); +    void run_length_encode (Q_UINT8 *src, Q_INT32 *dest, Q_INT32 bytes, Q_INT32 width); +    void multiply_alpha (Q_UINT8 *buf, Q_INT32 width, Q_INT32 bytes); +    void separate_alpha (Q_UINT8 *buf, Q_INT32 width, Q_INT32 bytes); + +private: +    KisView * m_view; +    bool m_cancelRequested; + +}; + +#endif diff --git a/krita/plugins/viewplugins/dropshadow/kis_dropshadow_plugin.cc b/krita/plugins/viewplugins/dropshadow/kis_dropshadow_plugin.cc new file mode 100644 index 000000000..efe01a957 --- /dev/null +++ b/krita/plugins/viewplugins/dropshadow/kis_dropshadow_plugin.cc @@ -0,0 +1,91 @@ +/* + * This file is part of the KDE project + * + * Copyright (c) 2005 Michael Thaler <michael.thaler@physik.tu-muenchen.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 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 <klocale.h> +#include <kiconloader.h> +#include <kinstance.h> +#include <kmessagebox.h> +#include <kstandarddirs.h> +#include <ktempfile.h> +#include <kdebug.h> +#include <kgenericfactory.h> + +#include <kis_view.h> +#include <kis_types.h> +#include <kis_image.h> +#include <kis_paint_device.h> +#include <kis_layer.h> + +#include "kis_dropshadow_plugin.h" +#include "kis_dropshadow.h" +#include "dlg_dropshadow.h" + +K_EXPORT_COMPONENT_FACTORY( kritadropshadow, KGenericFactory<KisDropshadowPlugin>( "krita" ) ) + +KisDropshadowPlugin::KisDropshadowPlugin(QObject *parent, const char *name, const QStringList &) +    : KParts::Plugin(parent, name) +{ +    if ( parent->inherits("KisView") ) { + +        setInstance(KGenericFactory<KisDropshadowPlugin>::instance()); +        setXMLFile(locate("data","kritaplugins/dropshadow.rc"), true); + +        m_view = (KisView*) parent; +        (void) new KAction(i18n("Add Drop Shadow..."), 0, 0, this, SLOT(slotDropshadow()), actionCollection(), "dropshadow"); +    } +} + +KisDropshadowPlugin::~KisDropshadowPlugin() +{ +} + +void KisDropshadowPlugin::slotDropshadow() +{ +    KisImageSP image = m_view->canvasSubject()->currentImg(); +    if (!image) return; + +    KisPaintDeviceSP dev = image->activeDevice(); +    if (!dev) return; + +    DlgDropshadow * dlgDropshadow = new DlgDropshadow(dev->colorSpace()->id().name(), +                                                      image->colorSpace()->id().name(), +                                                      m_view, "Dropshadow"); +    Q_CHECK_PTR(dlgDropshadow); + +    dlgDropshadow->setCaption(i18n("Drop Shadow")); + +    if (dlgDropshadow->exec() == QDialog::Accepted) { + +        KisDropshadow dropshadow(m_view); +        dropshadow.dropshadow(m_view->canvasSubject()->progressDisplay(), +                           dlgDropshadow->getXOffset(), +                           dlgDropshadow->getYOffset(), +                           dlgDropshadow->getBlurRadius(), +                           dlgDropshadow->getShadowColor(), +                           dlgDropshadow->getShadowOpacity(), +                           dlgDropshadow->allowResizingChecked()); + +    } + +    delete dlgDropshadow; + +} + +#include "kis_dropshadow_plugin.moc" diff --git a/krita/plugins/viewplugins/dropshadow/kis_dropshadow_plugin.h b/krita/plugins/viewplugins/dropshadow/kis_dropshadow_plugin.h new file mode 100644 index 000000000..fd64acdba --- /dev/null +++ b/krita/plugins/viewplugins/dropshadow/kis_dropshadow_plugin.h @@ -0,0 +1,45 @@ +/* + * This file is part of Krita + * + * Copyright (c) Michael Thaler <michael.thaler@physik.tu-muenchen.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 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. */ + +#ifndef _KIS_DROPSHADOW_PLUGIN_H_ +#define _KIS_DROPSHADOW_PLUGIN_H_ + +#include <kparts/plugin.h> + +class KisView; + + + +class KisDropshadowPlugin : public KParts::Plugin +{ +    Q_OBJECT +public: +    KisDropshadowPlugin(QObject *parent, const char *name, const QStringList &); +    virtual ~KisDropshadowPlugin(); + +private slots: + +    void slotDropshadow(); + +private: + +    KisView * m_view; +}; + +#endif diff --git a/krita/plugins/viewplugins/dropshadow/kritadropshadow.desktop b/krita/plugins/viewplugins/dropshadow/kritadropshadow.desktop new file mode 100644 index 000000000..cec207274 --- /dev/null +++ b/krita/plugins/viewplugins/dropshadow/kritadropshadow.desktop @@ -0,0 +1,39 @@ +[Desktop Entry] +Name=Dropshadow +Name[bg]=Сянка +Name[ca]=Gota d'ombra +Name[da]=Faldskygge +Name[de]=Schattenwurf +Name[el]=Ρίψη σκιάς +Name[et]=Varju heitmine +Name[fa]=سایۀ قطره +Name[fr]=Jet d'ombre +Name[fy]=Skaad sette +Name[gl]=Sombreado +Name[hu]=Ejtett árnyék +Name[is]=Undirskuggi +Name[it]=Getta ombra +Name[ja]=影付け +Name[km]=ទម្លាក់ស្រមោល +Name[nb]=Skygge +Name[nds]=Schaddeneffekt +Name[ne]=छायाँ छोड्नुहोस् +Name[nl]=Schaduw plaatsen +Name[pl]=Dodaj cień +Name[pt]=Sombreado +Name[pt_BR]=Sombreado +Name[ru]=Тень +Name[se]=Suoivvan +Name[sk]=Tieň +Name[sl]=Senca +Name[sr]=Падајућа сенка +Name[sr@Latn]=Padajuća senka +Name[sv]=Fallskugga +Name[uk]=Тінь +Name[uz]=Soya tushirish +Name[uz@cyrillic]=Соя тушириш +Name[zh_CN]=阴影 +ServiceTypes=Krita/ViewPlugin +Type=Service +X-KDE-Library=kritadropshadow +X-Krita-Version=2 diff --git a/krita/plugins/viewplugins/dropshadow/wdg_dropshadow.ui b/krita/plugins/viewplugins/dropshadow/wdg_dropshadow.ui new file mode 100644 index 000000000..d78999c83 --- /dev/null +++ b/krita/plugins/viewplugins/dropshadow/wdg_dropshadow.ui @@ -0,0 +1,235 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>WdgDropshadow</class> +<widget class="QWidget"> +    <property name="name"> +        <cstring>WdgDropshadow</cstring> +    </property> +    <property name="geometry"> +        <rect> +            <x>0</x> +            <y>0</y> +            <width>403</width> +            <height>258</height> +        </rect> +    </property> +    <grid> +        <property name="name"> +            <cstring>unnamed</cstring> +        </property> +        <widget class="QLabel" row="0" column="0"> +            <property name="name"> +                <cstring>textLabel1</cstring> +            </property> +            <property name="text"> +                <string>Offset X:</string> +            </property> +        </widget> +        <widget class="QLabel" row="1" column="0"> +            <property name="name"> +                <cstring>textLabel1_2</cstring> +            </property> +            <property name="text"> +                <string>Offset Y:</string> +            </property> +        </widget> +        <widget class="QLabel" row="2" column="0"> +            <property name="name"> +                <cstring>textLabel2</cstring> +            </property> +            <property name="text"> +                <string>Blur radius:</string> +            </property> +        </widget> +        <widget class="QLabel" row="3" column="0"> +            <property name="name"> +                <cstring>textLabel3</cstring> +            </property> +            <property name="text"> +                <string>Color:</string> +            </property> +        </widget> +        <widget class="QLabel" row="4" column="0"> +            <property name="name"> +                <cstring>textLabel4</cstring> +            </property> +            <property name="text"> +                <string>Opacity:</string> +            </property> +        </widget> +        <widget class="QSlider" row="4" column="1" rowspan="1" colspan="2"> +            <property name="name"> +                <cstring>opacitySlider</cstring> +            </property> +            <property name="maxValue"> +                <number>100</number> +            </property> +            <property name="value"> +                <number>80</number> +            </property> +            <property name="orientation"> +                <enum>Horizontal</enum> +            </property> +        </widget> +        <widget class="QSpinBox" row="4" column="3"> +            <property name="name"> +                <cstring>opacitySpinBox</cstring> +            </property> +            <property name="suffix"> +                <string>%</string> +            </property> +            <property name="maxValue"> +                <number>100</number> +            </property> +            <property name="value"> +                <number>80</number> +            </property> +        </widget> +        <widget class="QCheckBox" row="5" column="0" rowspan="1" colspan="4"> +            <property name="name"> +                <cstring>allowResizingCheckBox</cstring> +            </property> +            <property name="text"> +                <string>Allow resizing</string> +            </property> +            <property name="checked"> +                <bool>true</bool> +            </property> +        </widget> +        <widget class="QSpinBox" row="0" column="1"> +            <property name="name"> +                <cstring>xOffsetSpinBox</cstring> +            </property> +            <property name="minValue"> +                <number>-99</number> +            </property> +            <property name="value"> +                <number>8</number> +            </property> +        </widget> +        <spacer row="0" column="2" rowspan="1" colspan="2"> +            <property name="name"> +                <cstring>spacer7</cstring> +            </property> +            <property name="orientation"> +                <enum>Horizontal</enum> +            </property> +            <property name="sizeType"> +                <enum>Expanding</enum> +            </property> +            <property name="sizeHint"> +                <size> +                    <width>200</width> +                    <height>20</height> +                </size> +            </property> +        </spacer> +        <widget class="QSpinBox" row="1" column="1"> +            <property name="name"> +                <cstring>yOffsetSpinBox</cstring> +            </property> +            <property name="minValue"> +                <number>-99</number> +            </property> +            <property name="value"> +                <number>8</number> +            </property> +        </widget> +        <spacer row="1" column="2" rowspan="1" colspan="2"> +            <property name="name"> +                <cstring>spacer8</cstring> +            </property> +            <property name="orientation"> +                <enum>Horizontal</enum> +            </property> +            <property name="sizeType"> +                <enum>Expanding</enum> +            </property> +            <property name="sizeHint"> +                <size> +                    <width>200</width> +                    <height>20</height> +                </size> +            </property> +        </spacer> +        <widget class="QSpinBox" row="2" column="1"> +            <property name="name"> +                <cstring>blurRadiusSpinBox</cstring> +            </property> +            <property name="value"> +                <number>5</number> +            </property> +        </widget> +        <spacer row="2" column="2" rowspan="1" colspan="2"> +            <property name="name"> +                <cstring>spacer9</cstring> +            </property> +            <property name="orientation"> +                <enum>Horizontal</enum> +            </property> +            <property name="sizeType"> +                <enum>Expanding</enum> +            </property> +            <property name="sizeHint"> +                <size> +                    <width>190</width> +                    <height>20</height> +                </size> +            </property> +        </spacer> +        <widget class="KColorButton" row="3" column="1"> +            <property name="name"> +                <cstring>shadowColorButton</cstring> +            </property> +            <property name="text"> +                <string></string> +            </property> +        </widget> +        <spacer row="3" column="2" rowspan="1" colspan="2"> +            <property name="name"> +                <cstring>spacer4</cstring> +            </property> +            <property name="orientation"> +                <enum>Horizontal</enum> +            </property> +            <property name="sizeType"> +                <enum>Expanding</enum> +            </property> +            <property name="sizeHint"> +                <size> +                    <width>120</width> +                    <height>31</height> +                </size> +            </property> +        </spacer> +    </grid> +</widget> +<customwidgets> +</customwidgets> +<connections> +    <connection> +        <sender>opacitySpinBox</sender> +        <signal>valueChanged(int)</signal> +        <receiver>opacitySlider</receiver> +        <slot>setValue(int)</slot> +    </connection> +    <connection> +        <sender>opacitySlider</sender> +        <signal>valueChanged(int)</signal> +        <receiver>opacitySpinBox</receiver> +        <slot>setValue(int)</slot> +    </connection> +</connections> +<tabstops> +    <tabstop>xOffsetSpinBox</tabstop> +    <tabstop>yOffsetSpinBox</tabstop> +    <tabstop>blurRadiusSpinBox</tabstop> +    <tabstop>shadowColorButton</tabstop> +    <tabstop>opacitySlider</tabstop> +    <tabstop>opacitySpinBox</tabstop> +    <tabstop>allowResizingCheckBox</tabstop> +</tabstops> +<layoutdefaults spacing="6" margin="11"/> +<includehints> +    <includehint>kcolorbutton.h</includehint> +</includehints> +</UI> diff --git a/krita/plugins/viewplugins/filtersgallery/Makefile.am b/krita/plugins/viewplugins/filtersgallery/Makefile.am new file mode 100644 index 000000000..5c463f96f --- /dev/null +++ b/krita/plugins/viewplugins/filtersgallery/Makefile.am @@ -0,0 +1,25 @@ +kritarcdir = $(kde_datadir)/kritaplugins +kritarc_DATA = kritafiltersgallery.rc + +EXTRA_DIST = $(kritarc_DATA) + +INCLUDES  =  -I$(srcdir)/../../../sdk \ +	-I$(srcdir)/../../../core \ +	-I$(srcdir)/../../../kritacolor/ \ +	-I$(srcdir)/../../../ui \ +	-I../../../ui \ +	$(KOFFICE_INCLUDES) \ +	$(all_includes) + +kritafiltersgallery_la_SOURCES = filters_gallery.cc \ +		kis_dlg_filtersgallery.cc kis_wdg_filtersgallery.ui + +kde_module_LTLIBRARIES = kritafiltersgallery.la +noinst_HEADERS = filters_gallery.h kis_dlg_filtersgallery.h + +kde_services_DATA = kritafiltersgallery.desktop + +kritafiltersgallery_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) +kritafiltersgallery_la_LIBADD =  ../../../libkritacommon.la  + +kritafiltersgallery_la_METASOURCES = AUTO diff --git a/krita/plugins/viewplugins/filtersgallery/filters_gallery.cc b/krita/plugins/viewplugins/filtersgallery/filters_gallery.cc new file mode 100644 index 000000000..f0849807c --- /dev/null +++ b/krita/plugins/viewplugins/filtersgallery/filters_gallery.cc @@ -0,0 +1,138 @@ +/* + * This file is part of Krita + * + * Copyright (c) 2005 Cyrille Berger <cberger@cberger.net> + * + *  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 "filters_gallery.h" + +#include <qapplication.h> + +#include <kdebug.h> +#include <kgenericfactory.h> +#include <kstandarddirs.h> + +#include <kopalettemanager.h> + +#include <kis_colorspace_factory_registry.h> +#include "kis_progress_display_interface.h" +#include <kis_dlg_filtersgallery.h> +#include <kis_doc.h> +#include <kis_filter.h> +#include <kis_filters_listview.h> +#include <kis_meta_registry.h> +#include <kis_paint_device.h> +#include <kis_selection.h> +#include <kis_view.h> +#include <kis_transaction.h> + +namespace Krita { +namespace Plugins { +namespace FiltersGallery { + +typedef KGenericFactory<KritaFiltersGallery> KritaFiltersGalleryFactory; +K_EXPORT_COMPONENT_FACTORY( kritafiltersgallery, KritaFiltersGalleryFactory( "krita" ) ) + +KritaFiltersGallery::KritaFiltersGallery(QObject *parent, const char *name, const QStringList &) +        : KParts::Plugin(parent, name) +{ + +    if ( parent->inherits("KisView") ) +    { +        setInstance(KritaFiltersGallery::instance()); +        setXMLFile(locate("data","kritaplugins/kritafiltersgallery.rc"), true); + +        m_view = (KisView*) parent; + +        (void) new KAction(i18n("&Filters Gallery"), 0, 0, this, SLOT(showFiltersGalleryDialog()), actionCollection(), "krita_filters_gallery"); + +        // Add a docker with the list of filters +//         QImage img; +//         if(img.load(locate("data","krita/images/previewfilter.png"))) +//         { +//            KisPaintDeviceSP preview = new KisPaintDevice(KisMetaRegistry::instance()->csRegistry()->getColorSpace(KisID("RGBA",""),"")); +//            preview->convertFromQImage(img,""); +//            m_view->canvasSubject()->paletteManager()->addWidget(new KisFiltersListView(preview,m_view),"filterslist",krita::EFFECTSBOX, 0); +//         } + +    } + + +} + +KritaFiltersGallery::~KritaFiltersGallery() +{ +} + +void KritaFiltersGallery::showFiltersGalleryDialog() +{ +    KisDlgFiltersGallery dlg(m_view, m_view); +    if (dlg.exec()) +    { +        QApplication::setOverrideCursor( Qt::waitCursor ); + +        KisFilter* filter = dlg.currentFilter(); +        if(filter ) +        { +            KisImageSP img = m_view->canvasSubject()->currentImg(); +            if (!img) return; + +            KisPaintDeviceSP dev = img->activeDevice(); +            if (!dev) return; +            QRect r1 = dev->exactBounds(); +            QRect r2 = img->bounds(); + +            QRect rect = r1.intersect(r2); + +            if (dev->hasSelection()) { +                QRect r3 = dev->selection()->selectedExactRect(); +                rect = rect.intersect(r3); +            } +            KisFilterConfiguration* config = filter->configuration( dlg.currentConfigWidget()); + +            filter->enableProgress(); +            m_view->canvasSubject()->progressDisplay()->setSubject(filter, true, true); +            filter->setProgressDisplay(m_view->canvasSubject()->progressDisplay()); + +            KisTransaction * cmd = new KisTransaction(filter->id().name(), dev); + +            filter->process(dev,dev, config, rect); + +            delete config; +            if (filter->cancelRequested()) { +                cmd->unexecute(); +                delete cmd; +            } else { +                dev->setDirty(rect); +                if (img->undo()) +                    img->undoAdapter()->addCommand(cmd); +                else +                    delete cmd; +            } +            filter->disableProgress(); +            QApplication::restoreOverrideCursor(); + +        } +    } +} + +} +} +} + +#include "filters_gallery.moc" diff --git a/krita/plugins/viewplugins/filtersgallery/filters_gallery.h b/krita/plugins/viewplugins/filtersgallery/filters_gallery.h new file mode 100644 index 000000000..0e45e582b --- /dev/null +++ b/krita/plugins/viewplugins/filtersgallery/filters_gallery.h @@ -0,0 +1,53 @@ +/* + * This file is part of Krita + * + * Copyright (c) 2005 Cyrille Berger <cberger@cberger.net> + * + *  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. + */ + +#ifndef _KRITA_FILTERS_PREVIEW_H_ +#define _KRITA_FILTERS_PREVIEW_H_ + +#include <kparts/plugin.h> + +class KisView; + +namespace Krita { +namespace Plugins { +namespace FiltersGallery { +    class KritaFiltersGallery : public KParts::Plugin +    { +        Q_OBJECT +        public: +            KritaFiltersGallery(QObject *parent, const char *name, const QStringList &); +            virtual ~KritaFiltersGallery(); +        public slots: +            void showFiltersGalleryDialog(); +        private: +         +            KisView * m_view; +     +     +    }; + +} +} +} + + + +#endif diff --git a/krita/plugins/viewplugins/filtersgallery/kis_dlg_filtersgallery.cc b/krita/plugins/viewplugins/filtersgallery/kis_dlg_filtersgallery.cc new file mode 100644 index 000000000..bb7c20ee1 --- /dev/null +++ b/krita/plugins/viewplugins/filtersgallery/kis_dlg_filtersgallery.cc @@ -0,0 +1,133 @@ +/* + * This file is part of Krita + * + * Copyright (c) 2005-2006 Cyrille Berger <cberger@cberger.net> + * Copyright (c) 2007 Benjamin Schleimer <bensch128@yahoo.com> + * + *  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 "kis_dlg_filtersgallery.h" + +#include <qgroupbox.h> +#include <qlayout.h> +#include <qlabel.h> +#include <qdatetime.h> + +#include <kis_filter.h> +#include <kis_filter_config_widget.h> +#include <kis_filters_listview.h> +#include <kis_paint_device.h> +#include <kis_paint_layer.h> +#include <kis_previewwidget.h> +#include <kis_transaction.h> +#include <kis_types.h> +#include <kis_view.h> + +#include "kis_wdg_filtersgallery.h" + +namespace Krita { +namespace Plugins { +namespace FiltersGallery { + + +KisDlgFiltersGallery::KisDlgFiltersGallery(KisView* view, QWidget* parent,const char *name) +  : KDialogBase(parent,name, true,i18n("Filters Gallery"), Ok | Cancel), m_view(view),m_currentConfigWidget(0), m_currentFilter(0) +{ +   // Initialize main widget +    m_widget = new KisWdgFiltersGallery(this); +    m_widget->filtersList->setLayer(view->canvasSubject()->currentImg()->activeLayer()); +    m_widget->filtersList->setProfile(view->canvasSubject()->monitorProfile()); +     +    setMainWidget(m_widget); +    // Initialize filters list +    connect(m_widget->filtersList , SIGNAL(selectionChanged(QIconViewItem*)), this, SLOT(selectionHasChanged(QIconViewItem* ))); +    // Initialize configWidgetHolder +    m_widget->configWidgetHolder->setColumnLayout ( 0, Qt::Horizontal ); +    //m_widget->configWidgetHolder->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum); +    // Initialize preview widget +     +    if (m_view->canvasSubject()->currentImg() && m_view->canvasSubject()->currentImg()->activeDevice()) +    { +        m_widget->previewWidget->slotSetDevice( m_view->canvasSubject()->currentImg()->activeDevice().data() ); +    } +    connect( m_widget->previewWidget, SIGNAL(updated()), this, SLOT(refreshPreview())); +    resize( minimumSizeHint()); +    m_widget->previewWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::MinimumExpanding); +    m_labelNoCW = new QLabel(i18n("No configuration options are available for this filter."), m_widget->configWidgetHolder); +    m_widget->configWidgetHolder->layout()->add(m_labelNoCW); +    m_labelNoCW->hide(); +} + +KisDlgFiltersGallery::~KisDlgFiltersGallery() +{ +} + +void KisDlgFiltersGallery::selectionHasChanged ( QIconViewItem * item ) +{ +    KisFiltersIconViewItem* kisitem = (KisFiltersIconViewItem*) item; +    m_currentFilter = kisitem->filter(); +    if(m_currentConfigWidget != 0) +    { +        m_widget->configWidgetHolder->layout()->remove(m_currentConfigWidget); +        delete m_currentConfigWidget; +        m_currentConfigWidget = 0; +    } else { +        m_labelNoCW->hide(); +    } +    KisImageSP img = m_view->canvasSubject()->currentImg(); +    KisPaintLayerSP activeLayer = dynamic_cast<KisPaintLayer*>(img->activeLayer().data()); +     +    if (activeLayer) +       m_currentConfigWidget = m_currentFilter->createConfigurationWidget(m_widget->configWidgetHolder, activeLayer->paintDevice()); +     +    if(m_currentConfigWidget != 0) { +        //m_currentConfigWidget->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); +        m_widget->configWidgetHolder->layout()->add(m_currentConfigWidget); +        m_currentConfigWidget->show(); +        connect(m_currentConfigWidget, SIGNAL(sigPleaseUpdatePreview()), this, SLOT(slotConfigChanged())); +    } +    else { +        m_labelNoCW->show(); +    } +     +    refreshPreview(); +} + +void KisDlgFiltersGallery::slotConfigChanged() +{ +    if(m_widget->previewWidget->getAutoUpdate()) +    { +        refreshPreview(); +    } else { +        m_widget->previewWidget->needUpdate(); +    } +} + + +void KisDlgFiltersGallery::refreshPreview( ) +{ +    if(!m_currentFilter) return; + +    KisFilterConfiguration* config = m_currentFilter->configuration(m_currentConfigWidget); + +    m_widget->previewWidget->runFilter(m_currentFilter, config); +} + +} +} +} + +#include "kis_dlg_filtersgallery.moc" diff --git a/krita/plugins/viewplugins/filtersgallery/kis_dlg_filtersgallery.h b/krita/plugins/viewplugins/filtersgallery/kis_dlg_filtersgallery.h new file mode 100644 index 000000000..a6a216cab --- /dev/null +++ b/krita/plugins/viewplugins/filtersgallery/kis_dlg_filtersgallery.h @@ -0,0 +1,68 @@ +/* + * This file is part of Krita + * + * Copyright (c) 2005-2006 Cyrille Berger <cberger@cberger.net> + * Copyright (c) 2007 Benjamin Schleimer <bensch128@yahoo.com> + * + *  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. + */ +#ifndef KISDLGFILTERSPREVIEW_H +#define KISDLGFILTERSPREVIEW_H + +#include <kdialogbase.h> + +class KisView; +class KisFilter; +class QIconViewItem; +class QLabel; +class QHBoxLayout; +class KisPreviewWidget; +class KisWdgFiltersGallery; +class KisFiltersListView; +     +namespace Krita { +namespace Plugins { +namespace FiltersGallery { + +/** +@author Cyrille Berger +*/ +class KisDlgFiltersGallery : public KDialogBase +{ +    Q_OBJECT +    public: +        KisDlgFiltersGallery(KisView* view, QWidget* parent,const char *name = ""); +        ~KisDlgFiltersGallery(); +    public: +        inline KisFilter* currentFilter() { return m_currentFilter; }; +        inline  QWidget* currentConfigWidget() { return m_currentConfigWidget; } +    private slots: +        void slotConfigChanged(); +        void refreshPreview(); +        void selectionHasChanged ( QIconViewItem * item ); +    private: +        KisWdgFiltersGallery* m_widget; +        KisView* m_view; +        QWidget* m_currentConfigWidget; +        KisFilter* m_currentFilter; +        QLabel* m_labelNoCW; +}; + +} +} +} + +#endif diff --git a/krita/plugins/viewplugins/filtersgallery/kis_wdg_filtersgallery.ui b/krita/plugins/viewplugins/filtersgallery/kis_wdg_filtersgallery.ui new file mode 100644 index 000000000..35553294f --- /dev/null +++ b/krita/plugins/viewplugins/filtersgallery/kis_wdg_filtersgallery.ui @@ -0,0 +1,123 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>KisWdgFiltersGallery</class> +<widget class="QWidget"> +    <property name="name"> +        <cstring>KisWdgFiltersGallery</cstring> +    </property> +    <property name="geometry"> +        <rect> +            <x>0</x> +            <y>0</y> +            <width>763</width> +            <height>296</height> +        </rect> +    </property> +    <grid> +        <property name="name"> +            <cstring>unnamed</cstring> +        </property> +        <property name="margin"> +            <number>0</number> +        </property> +        <widget class="KisPreviewWidget" row="0" column="1"> +            <property name="name"> +                <cstring>previewWidget</cstring> +            </property> +            <property name="sizePolicy"> +                <sizepolicy> +                    <hsizetype>5</hsizetype> +                    <vsizetype>7</vsizetype> +                    <horstretch>0</horstretch> +                    <verstretch>0</verstretch> +                </sizepolicy> +            </property> +        </widget> +        <widget class="KisFiltersListView" row="0" column="0"> +            <property name="name"> +                <cstring>filtersList</cstring> +            </property> +        </widget> +        <widget class="QGroupBox" row="0" column="2"> +            <property name="name"> +                <cstring>configWidgetHolder</cstring> +            </property> +            <property name="sizePolicy"> +                <sizepolicy> +                    <hsizetype>1</hsizetype> +                    <vsizetype>7</vsizetype> +                    <horstretch>0</horstretch> +                    <verstretch>0</verstretch> +                </sizepolicy> +            </property> +            <property name="minimumSize"> +                <size> +                    <width>0</width> +                    <height>0</height> +                </size> +            </property> +            <property name="title"> +                <string>Configuration</string> +            </property> +        </widget> +    </grid> +</widget> +<customwidgets> +    <customwidget> +        <class>KisPreviewWidget</class> +        <header location="local">kis_previewwidget.h</header> +        <sizehint> +            <width>-1</width> +            <height>-1</height> +        </sizehint> +        <container>0</container> +        <sizepolicy> +            <hordata>5</hordata> +            <verdata>5</verdata> +            <horstretch>0</horstretch> +            <verstretch>0</verstretch> +        </sizepolicy> +        <pixmap>image0</pixmap> +        <signal>moved(QPoint)</signal> +        <signal>moving(QPoint)</signal> +        <signal>startMoving(QPoint)</signal> +        <slot access="public" specifier="">zoomIn()</slot> +        <slot access="public" specifier="">slot()</slot> +        <slot access="public" specifier="">zoomOut()</slot> +        <slot access="public" specifier="">slot()</slot> +        <slot access="public" specifier="">slot()</slot> +        <slot access="public" specifier="">slotMoving(QPoint)</slot> +        <slot access="public" specifier="">slotMoved(QPoint)</slot> +        <slot access="public" specifier="">slot()</slot> +        <slot access="public" specifier="">slotStartMoving(QPoint)</slot> +    </customwidget> +    <customwidget> +        <class>KisFiltersListView</class> +        <header location="local">kis_filters_listview.h</header> +        <sizehint> +            <width>-1</width> +            <height>-1</height> +        </sizehint> +        <container>0</container> +        <sizepolicy> +            <hordata>5</hordata> +            <verdata>5</verdata> +            <horstretch>0</horstretch> +            <verstretch>0</verstretch> +        </sizepolicy> +        <pixmap>image1</pixmap> +    </customwidget> +</customwidgets> +<images> +    <image name="image0"> +        <data format="PNG" length="1002">89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b000003b149444154388dad945f4c5b551cc73fe7dc4b7b4bcba0762d45c43114323599ee6192609c51d883892ce083f1718b3ebb185f8dc91e972cf39d2d2a2f1af664b6f1e0fe3863a0718969700eb0c52142da0242a1bd6d696f7bcff101585203ceb8fd9ece39f99dcff9fe7edf939f88c562ec465f5f9fe609442c161362173c3e3eae7b7a7ac8e7f36432196cdbfe4f907c3e4f2291201e8fe338cec3737357e9e8e828aded1e229d650e1f2d51754b082110124c13a4dc5ea341eb9dc284c0558a853f3ce8cb0677ef500fde7d39d2596679e326597b8e9abb85d7a770ab16ab6983ec5a05b487a70e36f0f4e10afe408d6a558310980108478dba4a1e8233990c5d474b64ed39aa3a8fe5f3317fbf81dbd70bccfeb205947632fd74f6589c1c6ea2f70d03a58ba0c1f2c9bdc1b66de3b8256a6e11cbe7e3ee1d181b590124fe2693aeee08d223c82c3a2c24b7b874bec8f26288774f7bd054504aef0dde6e99c0eb83f9fb266323cb80a27fb0958141836044605a2ee5523393371cc646fee2da37195aa35d0c0c5b4859ac03d7e91712dcaac5adab3650a3ff9d08ef7dd8404bb48869e5d958b5b87dadc4c9a1464e9f0d0326df7ebd86bd2e310cb1bf62d384d59441f2d70a070e1c60e09489929b988681bdd9cc97170bcc4c65595f71f8e0e3301337fc24a7732467831875a47f289652b0be5e4151e6d07316c1b0c0340d8ab92023e76d66a6b2840e36d2fb7a13fee632475e6edc367ea98a90fb98b7dd6310ca0328a44761582e1bab41befabcc0ec940d28bc5e93b68e064cab84e1d9beaeb48934eac1f53b01c1b000fca496aa54b61a99fcde61662a4b4b4b23d1680be9d426173e4df3602a48ea411989a4fd590f52a8fd156b05ed9d350e3defe3cfdf4b4c7ce770ea7d3fb9f520afbe1620daeee5c26735d20b9b9cfb6811a754a439e4e5c5639a4caa1e5caf586bfc0197b78702005cb9b4cae4cd3267ce8638fe964bd72b393e39d74928d242617303a756a37f284447770dcdbffc6384a05a85de1306e9a52057c7527c7131c3c42d3f475eb2303c82d4fc3276d6811db37efeb148723082d9b08f79f97c1e5729109a9a28307cc622d2d6cdf52b2b24efe548dedb00142009862cfa879ee1a71f6cec928353511472fbf4389148b0b0e0c108081412458dfe21c9f11351e67e7358595468246d1d1e5e38a6e9e851bc39d84ab502a669331dafec0d8ec7e3e8cb06e1a881d727d1ae40180a434a8c9db129a54126ad48a7358c2b4c5352c8c374bcccdab2bb37d8719cba79fab8211f9df218e0582c261e95f8bfc04f1a1e8bc5c4dfe0a190172af6a9690000000049454e44ae426082</data> +    </image> +    <image name="image1"> +        <data format="PNG" length="1122">89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b0000042949444154388db5954d6c545514c77ff7de37eff1a6a550da994e5ba798868f948fc847a2a2911816c436b0a02ed0083161a1981877ee10d90aa94656063491882c5cd4c4b8103f20cd806909a98604da8482341de80cb69de9bcd799799d79efba980f1da3a80b4f727273939bdff99f9b93f3175a6b6a21849080020c4002a29a8f0a5dcd002803bed63a1035f0d0d0504b6f6fef51d7758fa4d3e98d8ee3fc03af128ee3303939399548242eb8aefb09300f78464de9f0f0f0d148cc7caf3d5424de97a7ec17104220242805520a44557bbd4b21f083801d33e63a6d1bc7bf19c6064e0319a35a58b9ae7ba43d54e4d7c54b64dc097c7f09d30ef04b36736983cc7c11b4456b9b492c5e20dc54a6540e00896a8268a7017010f8bcae1830d2e9f4c69ebe3c197782b2ce60d94ddc9b30f9feeb45ae5d7181c5ead35636ef08d3ffe26a76ee3208b4031a56d80aa00768fda362e9380e25bf80ef3b587613d7afc099533380a4b5dda46fcb5aa42998b9eb7173dce5e6788e434763ec7fc942532008ea436003660d2caa7f8d69c3bd8910674e4d033e83877ad8d36fb0aa4d6058658ac5358c5df6383bf480f31fdda5a3632bbbfb6da4ccd5c00a10b2012cc12fd97cfb5516f0187c25cee0619396480ec3ca909d0f3372d1e5f9fe66de3ad605587c712ec55256a2540d5519d19ae24a29057329839f7ecc138944d833102290f3184ae1e6d6f0e98739c61229e6d21eafbed1c9c8c5558c8f3ee4ceed76946a1c43d97091828585223e2eebfbc295f60d45de89707628cb58224577bc85a79e5d4d786581cddb9b0148259711b20145836221400416e0232d1f6595c9ce4538773ac7b54406f0b15784e8e80aa1ac2594190220d021e49f2437960156b70ba095e95f96f18acd8c263cc6122962b1167a7ba34cdd7ec8c977a699bed546722a8fc2a02b6e2185fff78ab586ce78894ddb9ab9f5738ed14b1e030756929d8ff2e4ae5544632b38f96e89a99b298ebd6950cc2d12ed0eb3618b26f520788462ad09877df60db600f0f1fb49c646f21c7ebd836dcf94e9d9b4c0db27d6d3bd36c6426a96bce731703046d7da129a4670836284a054869d4f1b1c7e2dca67676ef3c1898091ef5ad8bc358c3205c93bf7c9a40ad4c660f4728edd7bbb3142ea2fc1da711cfc200011e08b45f6bd1c261adbce9717928c5f9d63fc6a19f0014567773303073790f8214bd6f5282dfbb8b9fa1f6b40d7c1939393533b92e63ad9240990484aec7e41b27d579cbb531e0f67023492d86316ebb768ba1e0f786e6f37e56550c62237aee7011e54abd7c1412291b8a06de378b4d3c0b215da9708e5a3a442192085404a83d4accfecac067c0c43e13a70e3fa12e96409e0325000966bbb354465339d04a6f9dd15fe6dde07ce030780278088d05ad72cc9a6b2f2daaaa74d75a1f0e8d0d5f60b40868a8364ead6248430000b0857a126ffcdf396abf03ce089ffcb4c7f033046c6b4a995e7a00000000049454e44ae426082</data> +    </image> +</images> +<layoutdefaults spacing="6" margin="11"/> +<includehints> +    <includehint>kis_previewwidget.h</includehint> +    <includehint>kis_filters_listview.h</includehint> +</includehints> +</UI> diff --git a/krita/plugins/viewplugins/filtersgallery/kritafiltersgallery.desktop b/krita/plugins/viewplugins/filtersgallery/kritafiltersgallery.desktop new file mode 100644 index 000000000..8d60672f0 --- /dev/null +++ b/krita/plugins/viewplugins/filtersgallery/kritafiltersgallery.desktop @@ -0,0 +1,45 @@ +[Desktop Entry] +Name=Filters Gallery +Name[bg]=Галерия с филтри +Name[ca]=Galeria de filtres +Name[da]=Filtergalleri +Name[de]=Filtergallerie +Name[el]=Συλλογή φίλτρων +Name[eo]=Filtrilgalerio +Name[es]=Galería de filtros +Name[et]=Filtrigalerii +Name[fa]=گالری پالایهها +Name[fr]=Galerie de filtres +Name[fy]=Filtergallerij +Name[ga]=Gailearaí na Scagairí +Name[gl]=Galería de Filtros +Name[he]=גלריית מסננים +Name[hu]=Szűrőgaléria +Name[is]=Síusafn +Name[it]=Galleria dei filtri +Name[ja]=フィルタギャラリー +Name[km]=វិចិត្រសាលតម្រង +Name[lv]=Filtru galerija +Name[nb]=Filtergalleri +Name[nds]=Filtersammeln +Name[ne]=फिल्टर ग्यालेरी +Name[nl]=Filtergalerij +Name[pl]=Galeria filtrów +Name[pt]=Galeria de Filtros +Name[pt_BR]=Galeria de Filtros +Name[ru]=Галерея фильтров +Name[se]=Sillegalleriija +Name[sk]=Zbierka filtrov +Name[sl]=Galerija filtrov +Name[sr]=Галерија филтера +Name[sr@Latn]=Galerija filtera +Name[sv]=Filtrergalleri +Name[uk]=Галерея фільтрів +Name[uz]=Filterlar toʻplami +Name[uz@cyrillic]=Филтерлар тўплами +Name[zh_CN]=滤镜库 +Name[zh_TW]=濾鏡畫廊 +ServiceTypes=Krita/ViewPlugin +Type=Service +X-KDE-Library=kritafiltersgallery +X-Krita-Version=2 diff --git a/krita/plugins/viewplugins/filtersgallery/kritafiltersgallery.rc b/krita/plugins/viewplugins/filtersgallery/kritafiltersgallery.rc new file mode 100644 index 000000000..6a35a631b --- /dev/null +++ b/krita/plugins/viewplugins/filtersgallery/kritafiltersgallery.rc @@ -0,0 +1,9 @@ +<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd"> +<kpartgui library="kritafiltersgallery" version="7"> +<MenuBar> +<Menu name="Filter"><text>&Filter</text> +	<Seperator/> +	<Action name="krita_filters_gallery"/> +</Menu> +</MenuBar> +</kpartgui> diff --git a/krita/plugins/viewplugins/histogram/Makefile.am b/krita/plugins/viewplugins/histogram/Makefile.am new file mode 100644 index 000000000..a8dd17a17 --- /dev/null +++ b/krita/plugins/viewplugins/histogram/Makefile.am @@ -0,0 +1,24 @@ +kritarcdir = $(kde_datadir)/kritaplugins +kritarc_DATA = histogram.rc + +EXTRA_DIST = $(kritarc_DATA) + +INCLUDES  =  -I$(srcdir)/../../../sdk \ +	-I$(srcdir)/../../../core \ +	-I$(srcdir)/../../../kritacolor/ \ +	-I$(srcdir)/../../../ui \ +	-I../../../ui \ +	$(KOFFICE_INCLUDES) \ +	$(all_includes) + +kde_module_LTLIBRARIES = kritahistogram.la + +kritahistogram_la_SOURCES = histogram.cc dlg_histogram.cc wdghistogram.ui kis_histogram_widget.cc +noinst_HEADERS = dlg_histogram.h histogram.h wdghistogram.h kis_histogram_widget.h + +kde_services_DATA = kritahistogram.desktop + +kritahistogram_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) +kritahistogram_la_LIBADD =  ../../../libkritacommon.la + +kritahistogram_la_METASOURCES = AUTO diff --git a/krita/plugins/viewplugins/histogram/dlg_histogram.cc b/krita/plugins/viewplugins/histogram/dlg_histogram.cc new file mode 100644 index 000000000..0440c9db6 --- /dev/null +++ b/krita/plugins/viewplugins/histogram/dlg_histogram.cc @@ -0,0 +1,68 @@ +/* + *  dlg_histogram.cc - part of KimageShop^WKrayon^WKrita + * + *  Copyright (c) 2004 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 <qbuttongroup.h> +#include <qpushbutton.h> +#include <qcheckbox.h> +#include <qslider.h> +#include <qcombobox.h> +#include <qpixmap.h> +#include <qimage.h> +#include <qlabel.h> + +#include <knuminput.h> +#include <klocale.h> +#include <kdebug.h> + +#include "kis_types.h" +#include "kis_histogram.h" +#include "kis_layer.h" +#include "kis_paint_device.h" + +#include "dlg_histogram.h" +#include "kis_histogram_widget.h" + + +DlgHistogram::DlgHistogram( QWidget *  parent, const char * name) +    : super (parent, name, true, i18n("Histogram"), Ok | Cancel, Ok) +{ +    m_page = new KisHistogramWidget(this, "histogram"); +    Q_CHECK_PTR(m_page); + +    setCaption(i18n("Histogram")); +    setMainWidget(m_page); +    resize(m_page->sizeHint()); +} + +DlgHistogram::~DlgHistogram() +{ +    delete m_page; +} + +void DlgHistogram::setPaintDevice(KisPaintDeviceSP dev) +{ +    m_page->setPaintDevice(dev); +} + +void DlgHistogram::okClicked() +{ +    accept(); +} + +#include "dlg_histogram.moc" diff --git a/krita/plugins/viewplugins/histogram/dlg_histogram.h b/krita/plugins/viewplugins/histogram/dlg_histogram.h new file mode 100644 index 000000000..790e77ef8 --- /dev/null +++ b/krita/plugins/viewplugins/histogram/dlg_histogram.h @@ -0,0 +1,57 @@ +/* + *  dlg_histogram.h -- part of KimageShop^WKrayon^WKrita + * + *  Copyright (c) 2004 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. + */ +#ifndef DLG_HISTOGRAM +#define DLG_HISTOGRAM + +#include <kdialogbase.h> + +#include "kis_types.h" + +class KisHistogramWidget; + +/** + * This dialog shows the histogram for the (selected) portion + * of the current layer. + * + * XXX: Also for complete image? + */ +class DlgHistogram: public KDialogBase { +    typedef KDialogBase super; +    Q_OBJECT + +public: + +    DlgHistogram(QWidget * parent = 0, +             const char* name = 0); +    ~DlgHistogram(); + +    void setPaintDevice(KisPaintDeviceSP dev); + +private slots: +    void okClicked(); + +private: + +    KisHistogramWidget * m_page; +    KisHistogramSP m_histogram; +    KisLayerSP m_layer; +}; + +#endif // DLG_HISTOGRAM diff --git a/krita/plugins/viewplugins/histogram/histogram.cc b/krita/plugins/viewplugins/histogram/histogram.cc new file mode 100644 index 000000000..7db92deea --- /dev/null +++ b/krita/plugins/viewplugins/histogram/histogram.cc @@ -0,0 +1,105 @@ +/* + * histogram.h -- Part of Krita + * + * Copyright (c) 2004 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 <math.h> + +#include <stdlib.h> + +#include <qslider.h> +#include <qpoint.h> + +#include <klocale.h> +#include <kiconloader.h> +#include <kinstance.h> +#include <kmessagebox.h> +#include <kstandarddirs.h> +#include <ktempfile.h> +#include <kdebug.h> +#include <kgenericfactory.h> + +#include <kis_doc.h> +#include <kis_image.h> +#include <kis_layer.h> +#include <kis_paint_device.h> +#include <kis_global.h> +#include <kis_types.h> +#include <kis_view.h> +#include <kis_selection.h> + +#include "histogram.h" +#include "dlg_histogram.h" +#include "kis_colorspace.h" +#include "kis_histogram.h" + +typedef KGenericFactory<Histogram> HistogramFactory; +K_EXPORT_COMPONENT_FACTORY( kritahistogram, HistogramFactory( "krita" ) ) + +Histogram::Histogram(QObject *parent, const char *name, const QStringList &) +    : KParts::Plugin(parent, name) +{ + +    if ( parent->inherits("KisView") ) { + +        setInstance(HistogramFactory::instance()); +        setXMLFile(locate("data","kritaplugins/histogram.rc"), true); + +        m_action = new KAction(i18n("&Histogram"), 0, 0, this, SLOT(slotActivated()), actionCollection(), "histogram"); + +        m_view = (KisView*) parent; +        if (KisImageSP img = m_view->canvasSubject()->currentImg()) { +            connect(img, SIGNAL(sigLayersChanged(KisGroupLayerSP)), this, SLOT(slotLayersChanged())); +            connect(img, SIGNAL(sigLayerAdded(KisLayerSP)), this, SLOT(slotLayersChanged())); +            connect(img, SIGNAL(sigLayerActivated(KisLayerSP)), this, SLOT(slotLayersChanged())); +            connect(img, SIGNAL(sigLayerPropertiesChanged(KisLayerSP)), this, SLOT(slotLayersChanged())); +            connect(img, SIGNAL(sigLayerRemoved(KisLayerSP, KisGroupLayerSP, KisLayerSP)), +                    this, SLOT(slotLayersChanged())); +            connect(img, SIGNAL(sigLayerMoved(KisLayerSP, KisGroupLayerSP, KisLayerSP)), +                    this, SLOT(slotLayersChanged())); +            m_img = img; +        } +    } +} + +Histogram::~Histogram() +{ +} + +void Histogram::slotLayersChanged() { +    m_action->setEnabled(m_img && m_img->activeLayer() && m_img->activeLayer()->visible()); +} + +void Histogram::slotActivated() +{ +    DlgHistogram * dlgHistogram = new DlgHistogram(m_view, "Histogram"); +    Q_CHECK_PTR(dlgHistogram); + +    KisPaintDeviceSP dev = m_view->canvasSubject()->currentImg()->activeDevice(); +    if (dev) +        dlgHistogram->setPaintDevice(dev); + +    if (dlgHistogram->exec() == QDialog::Accepted) { +        // Do nothing; this is an informational dialog +    } +    delete dlgHistogram; +} + +#include "histogram.moc" + diff --git a/krita/plugins/viewplugins/histogram/histogram.h b/krita/plugins/viewplugins/histogram/histogram.h new file mode 100644 index 000000000..adaa6bfd1 --- /dev/null +++ b/krita/plugins/viewplugins/histogram/histogram.h @@ -0,0 +1,49 @@ +/*  + * histogram.h -- Part of Krita + * + * Copyright (c) 2004 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. + */ + +#ifndef HISTOGRAM_H +#define HISTOGRAM_H + +#include <kparts/plugin.h> + +class KisView; +class KAction; +class KisImage; + +class Histogram : public KParts::Plugin +{ +        Q_OBJECT +    public: +        Histogram(QObject *parent, const char *name, const QStringList &); +        virtual ~Histogram(); +     +    private slots: +        void slotActivated(); +        void slotLayersChanged(); + +    private: +        KisImage* m_img; +        KisView * m_view; +        KisPainter * m_painter; +        KAction* m_action; + +}; + +#endif // HISTOGRAM_H diff --git a/krita/plugins/viewplugins/histogram/histogram.rc b/krita/plugins/viewplugins/histogram/histogram.rc new file mode 100644 index 000000000..f41b50e74 --- /dev/null +++ b/krita/plugins/viewplugins/histogram/histogram.rc @@ -0,0 +1,10 @@ +<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd"> +<kpartgui library="kritahistogram" version="6"> +<MenuBar> +    <Menu name="Layer"><text>&Layer</text> +	<Separator/> +	<Action name="histogram"/> +	<Separator/> +    </Menu> +</MenuBar> +</kpartgui> diff --git a/krita/plugins/viewplugins/histogram/kis_histogram_widget.cc b/krita/plugins/viewplugins/histogram/kis_histogram_widget.cc new file mode 100644 index 000000000..0e7384355 --- /dev/null +++ b/krita/plugins/viewplugins/histogram/kis_histogram_widget.cc @@ -0,0 +1,147 @@ +/* + *  Copyright (c) 2004 Boudewijn Rempt + *            (c) 2005 Bart Coppens <kde@bartcoppens.be> + * + *  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 <qpainter.h> +#include <qpixmap.h> +#include <qlabel.h> +#include <qcombobox.h> +#include <qbuttongroup.h> +#include <qpushbutton.h> +#include <qscrollbar.h> +#include <qtooltip.h> + +#include <kdebug.h> + +#include "kis_channelinfo.h" +#include "kis_histogram_view.h" +#include "kis_histogram_widget.h" +#include "kis_histogram.h" +#include "kis_global.h" +#include "kis_types.h" +#include "kis_layer.h" +#include "kis_paint_device.h" +#include "kis_colorspace.h" + + +KisHistogramWidget::KisHistogramWidget(QWidget *parent, const char *name) +    : super(parent, name) +{ +    m_from = 0.0; +    m_width = 0.0; +} + +KisHistogramWidget::~KisHistogramWidget() +{ +} + +void KisHistogramWidget::setPaintDevice(KisPaintDeviceSP dev) +{ +    grpType->disconnect(this); +    cmbChannel->disconnect(this); +     +    m_histogramView->setPaintDevice(dev); +    setActiveChannel(0); // So we have the colored one if there are colors + +    // The channels +    cmbChannel->clear(); +    cmbChannel->insertStringList(m_histogramView->channelStrings()); +    cmbChannel->setCurrentItem(0); + +    // View display +    currentView->setMinValue(0); +    currentView->setMaxValue(100); + +    updateEnabled(); + +    m_from = m_histogramView->currentProducer()->viewFrom(); +    m_width = m_histogramView->currentProducer()->viewWidth(); + +    connect(grpType, SIGNAL(clicked(int)), this, SLOT(slotTypeSwitched(int))); +    connect(cmbChannel, SIGNAL(activated(int)), this, SLOT(setActiveChannel(int))); +    connect(zoomIn, SIGNAL(clicked()), this, SLOT(slotZoomIn())); +    connect(zoomOut, SIGNAL(clicked()), this, SLOT(slotZoomOut())); +    connect(currentView, SIGNAL(valueChanged(int)), this, SLOT(slide(int))); +} + +void KisHistogramWidget::setActiveChannel(int channel) +{ +    m_histogramView->setActiveChannel(channel); +    updateEnabled(); +} + +void KisHistogramWidget::slotTypeSwitched(int id) +{ +    if (id == LINEAR) +        m_histogramView->setHistogramType(LINEAR); +    else if (id == LOGARITHMIC) +        m_histogramView->setHistogramType(LOGARITHMIC); +} + +void KisHistogramWidget::setView(double from, double size) +{ +    m_from = from; +    m_width = size; +    if (m_from + m_width > 1.0) +        m_from = 1.0 - m_width; +    m_histogramView->setView(m_from, m_width); +    updateEnabled(); +} + +void KisHistogramWidget::slotZoomIn() { +    if ((m_width / 2) >= m_histogramView->currentProducer()->maximalZoom()) { +        setView(m_from, m_width / 2); +    } +} + +void KisHistogramWidget::slotZoomOut() { +    if (m_width * 2 <= 1.0) { +        setView(m_from, m_width * 2); +    } +} + +void KisHistogramWidget::slide(int val) { +    // Beware: at the END (e.g. 100), we want to still view m_width: +    setView((static_cast<double>(val) / 100.0) * (1.0 - m_width), m_width); +} + +void KisHistogramWidget::updateEnabled() { +    if (m_histogramView->currentProducer()->maximalZoom() < 1.0) { +        if ((m_width / 2) >= m_histogramView->currentProducer()->maximalZoom()) { +            zoomIn->setEnabled(true); +        } else { +            zoomIn->setEnabled(false); +        } +        if (m_width * 2 <= 1.0) { +            zoomOut->setEnabled(true); +        } else { +            zoomOut->setEnabled(false); +        } +        if (m_width < 1.0) +            currentView->setEnabled(true); +        else +            currentView->setEnabled(false); +    } else { +        zoomIn->setEnabled(false); +        zoomOut->setEnabled(false); +        currentView->setEnabled(false); +    } +} + +#include "kis_histogram_widget.moc" + diff --git a/krita/plugins/viewplugins/histogram/kis_histogram_widget.h b/krita/plugins/viewplugins/histogram/kis_histogram_widget.h new file mode 100644 index 000000000..84b551d8d --- /dev/null +++ b/krita/plugins/viewplugins/histogram/kis_histogram_widget.h @@ -0,0 +1,54 @@ +/* + *  Copyright (c) 2004 Boudewijn Rempt + * + *  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. + */ +#ifndef KIS_HISTOGRAM_WIDGET_ +#define KIS_HISTOGRAM_WIDGET_ + +#include "kis_types.h" +#include "wdghistogram.h" + +class KisColorSpace; + +/** + * The histogram widget takes a paint device or an image and + * draws a histogram for the given KisHistogram. + */ +class KisHistogramWidget : public WdgHistogram { +    typedef WdgHistogram super; +    Q_OBJECT + +public: +    KisHistogramWidget(QWidget *parent, const char *name); +    virtual ~KisHistogramWidget(); + +    void setPaintDevice(KisPaintDeviceSP dev); + +private slots: +    void setActiveChannel(int channel); +    void slotTypeSwitched(int id); +    void slotZoomIn(); +    void slotZoomOut(); +    void slide(int val); + +private: +    void setView(double from, double size); +    void updateEnabled(); +    double m_from, m_width; +}; + + +#endif // KIS_HISTOGRAM_WIDGET_ diff --git a/krita/plugins/viewplugins/histogram/kritahistogram.desktop b/krita/plugins/viewplugins/histogram/kritahistogram.desktop new file mode 100644 index 000000000..552f27d6a --- /dev/null +++ b/krita/plugins/viewplugins/histogram/kritahistogram.desktop @@ -0,0 +1,43 @@ +[Desktop Entry] +Name=Histogram Plugin +Name[bg]=Приставка за Histogram +Name[ca]=Connector d'histograma +Name[da]=Plugin med histogram +Name[de]=Histogramm-Modul +Name[el]=Πρόσθετο ιστογράμματος +Name[eo]=Histograma kromaĵo +Name[es]=Complemento de histograma +Name[et]=Histogrammiplugin +Name[fa]=وصلۀ سابقهنما +Name[fr]=Module d'histogramme +Name[fy]=Histogramplugin +Name[gl]=Plugin de Histograma +Name[hu]=Hisztogram modul +Name[is]=Súluritssía +Name[it]=Plugin per gli istogrammi +Name[ja]=ヒストグラムプラグイン +Name[km]=កម្មវិធីជំនួយអ៊ីស្តូក្រាម +Name[lt]=Histogramos įskiepis +Name[nb]=Programtillegg for histogram +Name[nds]=Histogramm-Moduul +Name[ne]=हिस्टोग्राम प्लगइन +Name[nl]=Histogramplugin +Name[pl]=Wtyczka histogramu +Name[pt]='Plugin' do Histograma +Name[pt_BR]=Plugin do Histograma +Name[ru]=Модуль гистограммы +Name[se]=Histogram lassemoduvla +Name[sk]=Modul histogram +Name[sl]=Vstavek za histograme +Name[sr]=Хистограмски прикључак +Name[sr@Latn]=Histogramski priključak +Name[sv]=Insticksprogram med histogram +Name[uk]=Втулок гістограм +Name[uz]=Gistogramma plagini +Name[uz@cyrillic]=Гистограмма плагини +Name[zh_CN]=直方图插件 +Name[zh_TW]=直方圖外掛程式 +ServiceTypes=Krita/ViewPlugin +Type=Service +X-KDE-Library=kritahistogram +X-Krita-Version=2 diff --git a/krita/plugins/viewplugins/histogram/wdghistogram.ui b/krita/plugins/viewplugins/histogram/wdghistogram.ui new file mode 100644 index 000000000..e538adae1 --- /dev/null +++ b/krita/plugins/viewplugins/histogram/wdghistogram.ui @@ -0,0 +1,229 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>WdgHistogram</class> +<widget class="QWidget"> +    <property name="name"> +        <cstring>WdgHistogram</cstring> +    </property> +    <property name="geometry"> +        <rect> +            <x>0</x> +            <y>0</y> +            <width>450</width> +            <height>380</height> +        </rect> +    </property> +    <vbox> +        <property name="name"> +            <cstring>unnamed</cstring> +        </property> +        <widget class="QButtonGroup"> +            <property name="name"> +                <cstring>grpType</cstring> +            </property> +            <property name="title"> +                <string>Method</string> +            </property> +            <grid> +                <property name="name"> +                    <cstring>unnamed</cstring> +                </property> +                <widget class="QRadioButton" row="0" column="2"> +                    <property name="name"> +                        <cstring>radioLinear</cstring> +                    </property> +                    <property name="text"> +                        <string>&Linear</string> +                    </property> +                    <property name="checked"> +                        <bool>true</bool> +                    </property> +                </widget> +                <widget class="QRadioButton" row="1" column="2" rowspan="2" colspan="1"> +                    <property name="name"> +                        <cstring>radioLog</cstring> +                    </property> +                    <property name="text"> +                        <string>&Logarithmic</string> +                    </property> +                </widget> +                <spacer row="2" column="1"> +                    <property name="name"> +                        <cstring>spacer1</cstring> +                    </property> +                    <property name="orientation"> +                        <enum>Vertical</enum> +                    </property> +                    <property name="sizeType"> +                        <enum>Preferred</enum> +                    </property> +                    <property name="sizeHint"> +                        <size> +                            <width>20</width> +                            <height>20</height> +                        </size> +                    </property> +                </spacer> +                <widget class="QComboBox" row="0" column="1" rowspan="2" colspan="1"> +                    <property name="name"> +                        <cstring>cmbChannel</cstring> +                    </property> +                    <property name="sizePolicy"> +                        <sizepolicy> +                            <hsizetype>7</hsizetype> +                            <vsizetype>0</vsizetype> +                            <horstretch>0</horstretch> +                            <verstretch>0</verstretch> +                        </sizepolicy> +                    </property> +                    <property name="minimumSize"> +                        <size> +                            <width>200</width> +                            <height>0</height> +                        </size> +                    </property> +                </widget> +                <widget class="QLabel" row="0" column="0" rowspan="2" colspan="1"> +                    <property name="name"> +                        <cstring>lblChannel</cstring> +                    </property> +                    <property name="text"> +                        <string>&Channel:</string> +                    </property> +                    <property name="buddy" stdset="0"> +                        <cstring>cmbChannel</cstring> +                    </property> +                </widget> +                <spacer row="2" column="0"> +                    <property name="name"> +                        <cstring>spacer2</cstring> +                    </property> +                    <property name="orientation"> +                        <enum>Vertical</enum> +                    </property> +                    <property name="sizeType"> +                        <enum>Preferred</enum> +                    </property> +                    <property name="sizeHint"> +                        <size> +                            <width>20</width> +                            <height>21</height> +                        </size> +                    </property> +                </spacer> +            </grid> +        </widget> +        <widget class="KisHistogramView"> +            <property name="name"> +                <cstring>m_histogramView</cstring> +            </property> +            <property name="sizePolicy"> +                <sizepolicy> +                    <hsizetype>7</hsizetype> +                    <vsizetype>7</vsizetype> +                    <horstretch>0</horstretch> +                    <verstretch>0</verstretch> +                </sizepolicy> +            </property> +            <property name="minimumSize"> +                <size> +                    <width>256</width> +                    <height>150</height> +                </size> +            </property> +        </widget> +        <widget class="QLayoutWidget"> +            <property name="name"> +                <cstring>layout2</cstring> +            </property> +            <hbox> +                <property name="name"> +                    <cstring>unnamed</cstring> +                </property> +                <widget class="QLabel"> +                    <property name="name"> +                        <cstring>textLabel1</cstring> +                    </property> +                    <property name="text"> +                        <string>View:</string> +                    </property> +                </widget> +                <widget class="QPushButton"> +                    <property name="name"> +                        <cstring>zoomIn</cstring> +                    </property> +                    <property name="sizePolicy"> +                        <sizepolicy> +                            <hsizetype>5</hsizetype> +                            <vsizetype>5</vsizetype> +                            <horstretch>0</horstretch> +                            <verstretch>0</verstretch> +                        </sizepolicy> +                    </property> +                    <property name="text"> +                        <string>+</string> +                    </property> +                </widget> +                <widget class="QPushButton"> +                    <property name="name"> +                        <cstring>zoomOut</cstring> +                    </property> +                    <property name="sizePolicy"> +                        <sizepolicy> +                            <hsizetype>5</hsizetype> +                            <vsizetype>5</vsizetype> +                            <horstretch>0</horstretch> +                            <verstretch>0</verstretch> +                        </sizepolicy> +                    </property> +                    <property name="text"> +                        <string>-</string> +                    </property> +                </widget> +                <widget class="QScrollBar"> +                    <property name="name"> +                        <cstring>currentView</cstring> +                    </property> +                    <property name="sizePolicy"> +                        <sizepolicy> +                            <hsizetype>7</hsizetype> +                            <vsizetype>0</vsizetype> +                            <horstretch>0</horstretch> +                            <verstretch>0</verstretch> +                        </sizepolicy> +                    </property> +                    <property name="orientation"> +                        <enum>Horizontal</enum> +                    </property> +                </widget> +            </hbox> +        </widget> +    </vbox> +</widget> +<customwidgets> +    <customwidget> +        <class>KisHistogramView</class> +        <header location="local">kis_histogram_view.h</header> +        <sizehint> +            <width>-1</width> +            <height>-1</height> +        </sizehint> +        <container>0</container> +        <sizepolicy> +            <hordata>5</hordata> +            <verdata>5</verdata> +            <horstretch>0</horstretch> +            <verstretch>0</verstretch> +        </sizepolicy> +        <pixmap>image0</pixmap> +    </customwidget> +</customwidgets> +<images> +    <image name="image0"> +        <data format="PNG" length="1002">89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b000003b149444154388dad945f4c5b551cc73fe7dc4b7b4bcba0762d45c43114323599ee6192609c51d883892ce083f1718b3ebb185f8dc91e972cf39d2d2a2f1af664b6f1e0fe3863a0718969700eb0c52142da0242a1bd6d696f7bcff101585203ceb8fd9ece39f99dcff9fe7edf939f88c562ec465f5f9fe609442c161362173c3e3eae7b7a7ac8e7f36432196cdbfe4f907c3e4f2291201e8fe338cec3737357e9e8e828aded1e229d650e1f2d51754b082110124c13a4dc5ea341eb9dc284c0558a853f3ce8cb0677ef500fde7d39d2596679e326597b8e9abb85d7a770ab16ab6983ec5a05b487a70e36f0f4e10afe408d6a558310980108478dba4a1e8233990c5d474b64ed39aa3a8fe5f3317fbf81dbd70bccfeb205947632fd74f6589c1c6ea2f70d03a58ba0c1f2c9bdc1b66de3b8256a6e11cbe7e3ee1d181b590124fe2693aeee08d223c82c3a2c24b7b874bec8f26288774f7bd054504aef0dde6e99c0eb83f9fb266323cb80a27fb0958141836044605a2ee5523393371cc646fee2da37195aa35d0c0c5b4859ac03d7e91712dcaac5adab3650a3ff9d08ef7dd8404bb48869e5d958b5b87dadc4c9a1464e9f0d0326df7ebd86bd2e310cb1bf62d384d59441f2d70a070e1c60e09489929b988681bdd9cc97170bcc4c65595f71f8e0e3301337fc24a7732467831875a47f289652b0be5e4151e6d07316c1b0c0340d8ab92023e76d66a6b2840e36d2fb7a13fee632475e6edc367ea98a90fb98b7dd6310ca0328a44761582e1bab41befabcc0ec940d28bc5e93b68e064cab84e1d9beaeb48934eac1f53b01c1b000fca496aa54b61a99fcde61662a4b4b4b23d1680be9d426173e4df3602a48ea411989a4fd590f52a8fd156b05ed9d350e3defe3cfdf4b4c7ce770ea7d3fb9f520afbe1620daeee5c26735d20b9b9cfb6811a754a439e4e5c5639a4caa1e5caf586bfc0197b78702005cb9b4cae4cd3267ce8638fe964bd72b393e39d74928d242617303a756a37f284447770dcdbffc6384a05a85de1306e9a52057c7527c7131c3c42d3f475eb2303c82d4fc3276d6811db37efeb148723082d9b08f79f97c1e5729109a9a28307cc622d2d6cdf52b2b24efe548dedb00142009862cfa879ee1a71f6cec928353511472fbf4389148b0b0e0c108081412458dfe21c9f11351e67e7358595468246d1d1e5e38a6e9e851bc39d84ab502a669331dafec0d8ec7e3e8cb06e1a881d727d1ae40180a434a8c9db129a54126ad48a7358c2b4c5352c8c374bcccdab2bb37d8719cba79fab8211f9df218e0582c261e95f8bfc04f1a1e8bc5c4dfe0a190172af6a9690000000049454e44ae426082</data> +    </image> +</images> +<layoutdefaults spacing="6" margin="11"/> +<includehints> +    <includehint>kis_histogram_view.h</includehint> +</includehints> +</UI> diff --git a/krita/plugins/viewplugins/histogram_docker/Makefile.am b/krita/plugins/viewplugins/histogram_docker/Makefile.am new file mode 100644 index 000000000..6d1163583 --- /dev/null +++ b/krita/plugins/viewplugins/histogram_docker/Makefile.am @@ -0,0 +1,21 @@ +kde_services_DATA = kritahistogramdocker.desktop +kritarcdir = $(kde_datadir)/kritaplugins +kritarc_DATA = kritahistogramdocker.rc + +INCLUDES  = -I$(srcdir)/../../../sdk \ +	-I$(srcdir)/../../../core \ +	-I$(srcdir)/../../../kritacolor/ \ +	-I$(srcdir)/../../../ui \ +	-I$/../../../ui \ +	$(KOFFICE_INCLUDES) \ +	$(all_includes) + +kritahistogramdocker_la_SOURCES = histogramdocker.cc  kis_imagerasteredcache.cc kis_cachedhistogram.cc kis_accumulating_producer.cc + +kde_module_LTLIBRARIES = kritahistogramdocker.la +noinst_HEADERS = histogramdocker.h kis_imagerasteredcache.h kis_cachedhistogram.h kis_accumulating_producer.h + +kritahistogramdocker_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) +kritahistogramdocker_la_LIBADD =  ../../../libkritacommon.la + +kritahistogramdocker_la_METASOURCES = AUTO diff --git a/krita/plugins/viewplugins/histogram_docker/histogramdocker.cc b/krita/plugins/viewplugins/histogram_docker/histogramdocker.cc new file mode 100644 index 000000000..93d77bfb5 --- /dev/null +++ b/krita/plugins/viewplugins/histogram_docker/histogramdocker.cc @@ -0,0 +1,192 @@ +/* + * This file is part of the KDE project + * + *  Copyright (c) 2005 Bart Coppens <kde@bartcoppens.be> + * + *  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 <qtooltip.h> + +#include <klocale.h> +#include <kiconloader.h> +#include <kinstance.h> +#include <kmessagebox.h> +#include <kstandarddirs.h> +#include <ktempfile.h> +#include <kdebug.h> +#include <kgenericfactory.h> + +#include <kopalettemanager.h> + +#include "kis_meta_registry.h" +#include <kis_doc.h> +#include <kis_global.h> +#include <kis_types.h> +#include <kis_view.h> + +#include <kis_basic_histogram_producers.h> +#include <kis_colorspace_factory_registry.h> + +#include "histogramdocker.h" +#include "kis_imagerasteredcache.h" +#include "kis_accumulating_producer.h" + +typedef KGenericFactory<KritaHistogramDocker> KritaHistogramDockerFactory; +K_EXPORT_COMPONENT_FACTORY( kritahistogramdocker, KritaHistogramDockerFactory( "krita" ) ) + +KritaHistogramDocker::KritaHistogramDocker(QObject *parent, const char *name, const QStringList&) +        : KParts::Plugin(parent, name) +{ + +    if ( parent->inherits("KisView") ) { +        m_view = dynamic_cast<KisView*>(parent); + +        setInstance(KritaHistogramDockerFactory::instance()); +        setXMLFile(locate("data","kritaplugins/kritahistogramdocker.rc"), true); + +        KisImageSP img = m_view->canvasSubject()->currentImg(); +        if (!img) { +            m_cache = 0; +            return; +        } + +        m_hview = 0; // producerChanged wants to setCurrentChannels, prevent that here +        m_cache = 0; // we try to delete it in producerChanged +        colorSpaceChanged(img->colorSpace()); // calls producerChanged(0) + + +        m_hview = new KisHistogramView(m_view); +        QToolTip::add(m_hview, i18n("Right-click to select histogram type")); +        m_hview->setHistogram(m_histogram); +        m_hview->setColor(true); +        m_hview->setCurrentChannels(m_producer, m_producer->channels()); +        m_hview->setFixedSize(256, 100); // XXX if not it keeps expanding +        m_hview->setCaption(i18n("Histogram")); + + +        connect(m_hview, SIGNAL(rightClicked(const QPoint&)), +                this, SLOT(popupMenu(const QPoint&))); +        connect(m_cache, SIGNAL(cacheUpdated()), +                new HistogramDockerUpdater(this, m_histogram, m_hview, m_producer), SLOT(updated())); +        connect(&m_popup, SIGNAL(activated(int)), +                this, SLOT(producerChanged(int))); +        connect(img, SIGNAL(sigColorSpaceChanged(KisColorSpace*)), +                this, SLOT(colorSpaceChanged(KisColorSpace*))); // No need to force updates here + +        // Add it to the control palette +        m_view->canvasSubject()->paletteManager()->addWidget( +            m_hview, "histodocker", krita::CONTROL_PALETTE); +    } else { +        m_cache = 0; +    } +} + +KritaHistogramDocker::~KritaHistogramDocker() +{ +    uint count = m_producers . count(); +    for (uint i = 0; i < count; i++) { +        delete m_producers . at(i); +    } + +    if (m_cache) +        m_cache->deleteLater(); +} + +void KritaHistogramDocker::producerChanged(int pos) +{ +    if (m_cache) +        m_cache->deleteLater(); +    m_cache = 0; + +    if (m_currentProducerPos < m_popup.count()) +        m_popup.setItemChecked(m_currentProducerPos, false); +    m_currentProducerPos = pos; +    m_popup.setItemChecked(m_currentProducerPos, true); + +    uint count = m_producers . count(); +    for (uint i = 0; i < count; i++) { +        delete m_producers . at(i); +    } +    m_producers.clear(); + +    KisIDList keys = KisHistogramProducerFactoryRegistry::instance() -> +            listKeysCompatibleWith(m_cs); + +    m_factory = KisHistogramProducerFactoryRegistry::instance()->get(*(keys.at(pos))); + +    KisCachedHistogramObserver observer(&m_producers, m_factory, 0, 0, 0, 0, false); + +    // We can reference observer because it will be only used as a factory to create new +    // instances +    m_cache = new KisImageRasteredCache(m_view, &observer); + +    m_producer = new KisAccumulatingHistogramProducer(&m_producers); + +    // use dummy layer as a source; we are not going to actually use or need it +    // All of these are SP, no need to delete them afterwards +    m_histogram = new KisHistogram( new KisPaintDevice(KisMetaRegistry::instance()->csRegistry()->getAlpha8(), "dummy histogram"), m_producer, LOGARITHMIC); + +    if (m_hview) { +        m_hview->setHistogram(m_histogram); +        m_hview->setColor(true); +        m_hview->setCurrentChannels(m_producer, m_producer->channels()); + +        connect(m_cache, SIGNAL(cacheUpdated()), +                new HistogramDockerUpdater(this, m_histogram, m_hview, m_producer), SLOT(updated())); +    } +} + +void KritaHistogramDocker::popupMenu(const QPoint& pos) +{ +    m_popup.popup(pos, m_currentProducerPos); +} + +void KritaHistogramDocker::colorSpaceChanged(KisColorSpace* cs) +{ +    m_cs = cs; + +    KisIDList keys = KisHistogramProducerFactoryRegistry::instance() -> +            listKeysCompatibleWith(m_cs); + +    m_popup.clear(); +    m_currentProducerPos = 0; + +    for (uint i = 0; i < keys.count(); i++) { +        KisID id(*(keys.at(i))); +        m_popup . insertItem(id.name(), static_cast<int>(i)); +    } + +    producerChanged(0); +} + +HistogramDockerUpdater::HistogramDockerUpdater(QObject* /*parent*/, KisHistogramSP h, KisHistogramView* v, +                                               KisAccumulatingHistogramProducer* p) +    : m_histogram(h), m_view(v), m_producer(p) +{ +    connect(p, SIGNAL(completed()), this, SLOT(completed())); +} + +void HistogramDockerUpdater::updated() { +    // We don't [!] do m_histogram->updateHistogram();, because that will try to compute +    // the histogram synchronously, while we want it asynchronously. +    m_producer->addRegionsToBinAsync(); +} + +void HistogramDockerUpdater::completed() { +    m_histogram->computeHistogram(); +    m_view->updateHistogram(); +} + +#include "histogramdocker.moc" diff --git a/krita/plugins/viewplugins/histogram_docker/histogramdocker.h b/krita/plugins/viewplugins/histogram_docker/histogramdocker.h new file mode 100644 index 000000000..5cc57e184 --- /dev/null +++ b/krita/plugins/viewplugins/histogram_docker/histogramdocker.h @@ -0,0 +1,79 @@ +/* + * This file is part of Krita + * + * Copyright (c) 2005 Bart Coppens <kde@bartcoppens.be> + * + *  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. + */ + +#ifndef _HISTOGRAMDOCKER_H_ +#define _HISTOGRAMDOCKER_H_ + +#include <qobject.h> +#include <qpopupmenu.h> + +#include <kparts/plugin.h> +#include <kis_histogram_view.h> +#include <kis_histogram.h> + +#include "kis_cachedhistogram.h" + +class KisAccumulatingHistogramProducer; +class KisColorSpace; +class KisHistogramView; +class KisView; +class KisColorSpace; + +class KritaHistogramDocker : public KParts::Plugin +{ +Q_OBJECT +public: +    KritaHistogramDocker(QObject *parent, const char *name, const QStringList &); +    virtual ~KritaHistogramDocker(); +private slots: +    void producerChanged(int pos); +    void popupMenu(const QPoint & pos); +    void colorSpaceChanged(KisColorSpace* cs); +private: +    KisHistogramProducerFactory* m_factory; +    KisCachedHistogramObserver::Producers m_producers; +    KisAccumulatingHistogramProducer* m_producer; +    KisColorSpace* m_cs; +    KisView* m_view; +    KisHistogramView* m_hview; +    KisImageRasteredCache* m_cache; +    QPopupMenu m_popup; +    KisHistogramSP m_histogram; +    uint m_currentProducerPos; +}; + +class KisGenericRGBHistogramProducerFactory; + +class HistogramDockerUpdater : public QObject { +Q_OBJECT +public: +    HistogramDockerUpdater(QObject* parent, KisHistogramSP h, KisHistogramView* v, +                           KisAccumulatingHistogramProducer* p); +public slots: +    void updated(); +private slots: +    void completed(); +private: +    KisHistogramSP m_histogram; +    KisHistogramView* m_view; +    KisAccumulatingHistogramProducer* m_producer; +}; + +#endif //_HISTOGRAMDOCKER_H_ diff --git a/krita/plugins/viewplugins/histogram_docker/kis_accumulating_producer.cc b/krita/plugins/viewplugins/histogram_docker/kis_accumulating_producer.cc new file mode 100644 index 000000000..f899f2af1 --- /dev/null +++ b/krita/plugins/viewplugins/histogram_docker/kis_accumulating_producer.cc @@ -0,0 +1,102 @@ +/* + * This file is part of Krita + * + * Copyright (c) 2005 Bart Coppens <kde@bartcoppens.be> + * + *  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 <qthread.h> +#include <qapplication.h> +#include <qevent.h> + +#include "kis_accumulating_producer.h" + +static const int EmitCompletedType = QEvent::User + 1; + +/** + * The threaded producer definition in c++ file because this is really an internal affair. + * Note that since we _know_ that we'll only have a single instance of it running, at most, + * we don't care too much about locking and synchronization + **/ +class KisAccumulatingHistogramProducer::ThreadedProducer : public QThread { +    KisAccumulatingHistogramProducer* m_source; +    bool m_stop; +protected: +    virtual void run(); +public: +    ThreadedProducer(KisAccumulatingHistogramProducer* source) +        : m_source(source), m_stop(false) {} +    void cancel() { m_stop = true; } +}; + +KisAccumulatingHistogramProducer::KisAccumulatingHistogramProducer(KisCachedHistogramObserver::Producers* source) +    : KisBasicHistogramProducer( +        KisID("ACCHISTO", ""), +        source->at(0)->channels().count(), +        source->at(0)->numberOfBins(), +        0), +      m_source(source) +{ +    m_thread = new ThreadedProducer(this); +} + +KisAccumulatingHistogramProducer::~KisAccumulatingHistogramProducer() { +    m_thread->cancel(); +    m_thread->wait(); +    delete m_thread; +} + +void KisAccumulatingHistogramProducer::addRegionsToBinAsync() { +    m_thread->cancel(); +    m_thread->wait(); +    clear(); +    m_thread->start(); +} + +void KisAccumulatingHistogramProducer::ThreadedProducer::run() { +    m_stop = false; + +    uint count = m_source->m_source->count(); // Talk about bad naming schemes... +    KisCachedHistogramObserver::Producers* source = m_source->m_source; +    QValueVector<vBins>& bins = m_source->m_bins; +    int channels = m_source->m_channels; +    int nrOfBins = m_source->m_nrOfBins; + +    for (uint i = 0; i < count && !m_stop; i++) { +        KisHistogramProducer* p = source->at(i); +        m_source->m_count += p->count(); + +        for (int j = 0; j < channels && !m_stop; j++) { +            for (int k = 0; k < nrOfBins; k++) { +                bins.at(j).at(k) += p->getBinAt(j, k); +            } +        } +    } + +    if (!m_stop) { +        // This function is thread-safe; and it takes ownership of the event +        QApplication::postEvent(m_source, new QCustomEvent(EmitCompletedType)); +    } +} + +void KisAccumulatingHistogramProducer::customEvent(QCustomEvent* e) { +    if (e->type() == EmitCompletedType) { +        emit completed(); +    } +} + +#include "kis_accumulating_producer.moc" + diff --git a/krita/plugins/viewplugins/histogram_docker/kis_accumulating_producer.h b/krita/plugins/viewplugins/histogram_docker/kis_accumulating_producer.h new file mode 100644 index 000000000..4ef9f02a4 --- /dev/null +++ b/krita/plugins/viewplugins/histogram_docker/kis_accumulating_producer.h @@ -0,0 +1,76 @@ +/* + * This file is part of Krita + * + * Copyright (c) 2005 Bart Coppens <kde@bartcoppens.be> + * + *  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. + */ + +#ifndef _KIS_ACCUMULATING_PRODUCER_H_ +#define _KIS_ACCUMULATING_PRODUCER_H_ + +#include <qobject.h> + +#include <kis_basic_histogram_producers.h> +#include "kis_cachedhistogram.h" + +/** + * Kept very minimalistic because all options would require much reiterating which we don't want. + * This class is multithreading! Don't expect it to contain the right data after an + * addRegionsToBinAsync call, but await it's completed() signal. Also beware! This function + * _does_ clear() before addRegionsToBinAsync! (hence not conforming to the regular semantics + * of HistogramProducers if you'd take addRegionsToBinAsync = addRegionToBin, but since that is + * already violated with the asynchronousity of it that is not really an issue anymore, I think) + **/ +class KisAccumulatingHistogramProducer : public QObject, public KisBasicHistogramProducer { +Q_OBJECT +public: +    KisAccumulatingHistogramProducer(KisCachedHistogramObserver::Producers* source); +    ~KisAccumulatingHistogramProducer(); +    /// Does _nothing_, use addRegionsToBinAsync +    virtual void addRegionToBin(Q_UINT8 *, Q_UINT8*, Q_UINT32, KisColorSpace *) {} +    virtual void addRegionsToBinAsync(); +    virtual QString positionToString(double pos) const +        { return m_source->at(0)->positionToString(pos); } + +    virtual void setView(double, double) {} // No view support +    virtual double maximalZoom() const { return 1.0; } + +    virtual Q_INT32 numberOfBins() { return m_source->at(0)->numberOfBins(); } + +    virtual QValueVector<KisChannelInfo *> channels() { return m_source->at(0)->channels(); } + +    /// Call this when the 'source' list has changed colorspace +    virtual void changedSourceProducer() { +        m_count = m_source->at(0)->channels().count(); +        m_external.clear(); +        makeExternalToInternal(); +    } + +signals: +    void completed(); + +protected: +    virtual void customEvent(QCustomEvent* e); +    /// source already converts external to internal +    virtual int externalToInternal(int ext) { return ext; } +    KisCachedHistogramObserver::Producers* m_source; + +    class ThreadedProducer; +    friend class ThreadedProducer; +    ThreadedProducer* m_thread; +}; + +#endif // _KIS_ACCUMULATING_PRODUCER_H_ diff --git a/krita/plugins/viewplugins/histogram_docker/kis_cachedhistogram.cc b/krita/plugins/viewplugins/histogram_docker/kis_cachedhistogram.cc new file mode 100644 index 000000000..2b0c9b851 --- /dev/null +++ b/krita/plugins/viewplugins/histogram_docker/kis_cachedhistogram.cc @@ -0,0 +1,37 @@ +/* + * This file is part of Krita + * + * Copyright (c) 2005 Bart Coppens <kde@bartcoppens.be> + * + *  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 <kis_paint_device.h> +#include <kis_iterators_pixel.h> + +#include "kis_cachedhistogram.h" + +void KisCachedHistogramObserver::regionUpdated(KisPaintDeviceSP dev) { +    m_producer->clear(); +    KisRectIteratorPixel srcIt = dev->createRectIterator(m_x, m_y, m_w, m_h, false); +    int i; +    while ( !srcIt.isDone() ) { +        i = srcIt.nConseqPixels(); +        m_producer->addRegionToBin(srcIt.rawData(), srcIt.selectionMask(), i, dev->colorSpace()); +        srcIt += i; +        if (i == 0) +            ++srcIt; +    } +} diff --git a/krita/plugins/viewplugins/histogram_docker/kis_cachedhistogram.h b/krita/plugins/viewplugins/histogram_docker/kis_cachedhistogram.h new file mode 100644 index 000000000..dfe7a05eb --- /dev/null +++ b/krita/plugins/viewplugins/histogram_docker/kis_cachedhistogram.h @@ -0,0 +1,53 @@ +/* + * This file is part of Krita + * + * Copyright (c) 2005 Bart Coppens <kde@bartcoppens.be> + * + *  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. + */ + +#ifndef _CACHED_HISTOGRAM_H_ +#define _CACHED_HISTOGRAM_H_ + +#include <qvaluevector.h> +#include <kis_histogram_producer.h> + +#include "kis_imagerasteredcache.h" + +class KisCachedHistogramObserver : public KisImageRasteredCache::Observer { +public: +    typedef QValueVector<KisHistogramProducer*> Producers; +    KisCachedHistogramObserver(Producers* p, KisHistogramProducerFactory* f, +                               int x, int y, int w, int h, bool add = true) +        : m_producers(p), m_factory(f), m_x(x), m_y(y), m_w(w), m_h(h) +    { +        m_producer = m_factory->generate(); +        if (add) +            m_producers->append(m_producer); +    } +    virtual ~KisCachedHistogramObserver() {} + +    virtual Observer* createNew(int x, int y, int w, int h) +        { return new KisCachedHistogramObserver(m_producers, m_factory, x, y, w, h); } +         +    virtual void regionUpdated(KisPaintDeviceSP dev); +private: +    Producers* m_producers; +    KisHistogramProducerFactory* m_factory; +    KisHistogramProducerSP m_producer; +    int m_x, m_y, m_w, m_h; +}; + +#endif // _CACHED_HISTOGRAM_H_ diff --git a/krita/plugins/viewplugins/histogram_docker/kis_imagerasteredcache.cc b/krita/plugins/viewplugins/histogram_docker/kis_imagerasteredcache.cc new file mode 100644 index 000000000..2c6562df7 --- /dev/null +++ b/krita/plugins/viewplugins/histogram_docker/kis_imagerasteredcache.cc @@ -0,0 +1,162 @@ +/* + * This file is part of the KDE project + * + *  Copyright (c) 2005 Bart Coppens <kde@bartcoppens.be> + * + *  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 <cmath> + +#include <qapplication.h> + +#include <kdebug.h> + +#include <kis_doc.h> +#include <kis_global.h> +#include <kis_types.h> +#include <kis_view.h> + +#include "kis_imagerasteredcache.h" + +KisImageRasteredCache::KisImageRasteredCache(KisView* view, Observer* o)  +    : m_observer(o->createNew(0, 0, 0, 0)), m_view(view) +{ +    m_busy = false; +    m_imageProjection = 0; +    m_rasterSize = 64*4; +    m_timeOutMSec = 1000; + +    KisImageSP img = view->canvasSubject()->currentImg(); + +    if (!img) { +        return; +    } + +    imageSizeChanged(img->width(), img->height()); + +    connect(img, SIGNAL(sigImageUpdated(QRect)), +            this, SLOT(imageUpdated(QRect))); +    connect(img, SIGNAL(sigSizeChanged(Q_INT32, Q_INT32)), +            this, SLOT(imageSizeChanged(Q_INT32, Q_INT32))); +    connect(&m_timer, SIGNAL(timeout()), this, SLOT(timeOut())); +} + +KisImageRasteredCache::~KisImageRasteredCache() { +    cleanUpElements(); +} + +void KisImageRasteredCache::imageUpdated(QRect rc) { + +    if (rc.isValid()) { +        QRect r(0, 0, m_width * m_rasterSize, m_height * m_rasterSize); +        r &= rc; + +        uint x = static_cast<int>(r.x() / m_rasterSize); +        uint y = static_cast<int>(r.y() / m_rasterSize); +        uint x2 = static_cast<int>(ceil(float(r.x() + r.width()) / float(m_rasterSize))); +        uint y2 = static_cast<int>(ceil(float(r.y() + r.height()) / float(m_rasterSize))); + +        if (!m_raster.empty()) { +            for ( ; x < x2; x++) { +                for (uint i = y; i < y2; i++) { +                    if (x < m_raster.size()) { +                        if (i < m_raster.at(x).size()) { +                            Element* e = m_raster.at(x).at(i); +                            if (e && e->valid) { +                                e->valid = false; +                                m_queue.push_back(e); +                            } +                        } +                    } +                } +            } +        } +    } + +    if (!m_busy) { +        // If the timer is already started, this resets it. That way, we update always +        // m_timeOutMSec milliseconds after the lastly monitored activity +        m_timer.start(m_timeOutMSec, true); // true->singleshot +    } +} + +void KisImageRasteredCache::imageSizeChanged(Q_INT32 w, Q_INT32 h) { + +    KisImageSP image = m_view->canvasSubject()->currentImg(); + +    cleanUpElements(); +    m_busy = false; + +    m_width = static_cast<int>(ceil(float(w) / float(m_rasterSize))); +    m_height = static_cast<int>(ceil(float(h) / float(m_rasterSize))); + +    m_raster.resize(m_width); + +    int rasterX = 0; + +    for (int i = 0; i < m_width *  m_rasterSize; i += m_rasterSize) { +        int rasterY = 0; + +        m_raster.at(rasterX).resize(m_height + 1); + +        for (int j = 0; j < m_height * m_rasterSize; j += m_rasterSize) { +            Element* e = new Element(m_observer->createNew(i, j, m_rasterSize, m_rasterSize)); +            m_raster.at(rasterX).at(rasterY) = e; +            rasterY++; +        } +        rasterX++; +    } + +    imageUpdated(QRect(0,0, image->width(), image->height())); +} + +void KisImageRasteredCache::timeOut() { +    m_busy = true; +    KisImageSP img = m_view->canvasSubject()->currentImg(); + +    // Temporary cache: while we are busy, we won't get the mergeImage time and again. +    if (!m_imageProjection) +        m_imageProjection = img->mergedImage(); + +    // Pick one element of the cache, and update it +    if (!m_queue.isEmpty()) { +        m_queue.front()->observer->regionUpdated(m_imageProjection); +        m_queue.front()->valid = true; +        m_queue.pop_front(); +    } + +    // If there are still elements, we need to be called again (this emulates processEvents) +    if (!m_queue.isEmpty()) { +        QTimer::singleShot(0, this, SLOT(timeOut())); +    } else { +        emit cacheUpdated(); +        m_imageProjection = 0; +        m_busy = false; +    } +} + +void KisImageRasteredCache::cleanUpElements() { +    for (uint i = 0; i < m_raster.count(); i++) { +        for (uint j = 0; j < m_raster.at(i).count(); j++) { +            delete m_raster.at(i).at(j); +        } +        m_raster.at(i).clear(); +    } +    m_raster.clear(); +    m_queue.clear(); +} + +#include "kis_imagerasteredcache.moc" diff --git a/krita/plugins/viewplugins/histogram_docker/kis_imagerasteredcache.h b/krita/plugins/viewplugins/histogram_docker/kis_imagerasteredcache.h new file mode 100644 index 000000000..6335eadb6 --- /dev/null +++ b/krita/plugins/viewplugins/histogram_docker/kis_imagerasteredcache.h @@ -0,0 +1,80 @@ +/* + * This file is part of the KDE project + * + *  Copyright (c) 2005 Bart Coppens <kde@bartcoppens.be> + * + *  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. + */ + +#ifndef _KIS_IMAGE_RASTERED_CACHE_H_ +#define _KIS_IMAGE_RASTERED_CACHE_H_ + +#include <qobject.h> +#include <qvaluevector.h> +#include <qvaluelist.h> +#include <qtimer.h> + +#include <kis_paint_device.h> + +class KisView; + +class KisImageRasteredCache : public QObject { +Q_OBJECT + +public: +    class Observer { +    public: +        virtual Observer* createNew(int x, int y, int w, int h) = 0; +        virtual void regionUpdated(KisPaintDeviceSP dev) = 0; +        virtual ~Observer() {} +    }; + +    KisImageRasteredCache(KisView* view, Observer* o); +    virtual ~KisImageRasteredCache(); + +signals: +    void cacheUpdated(); + +private slots: +    void imageUpdated(QRect rc); +    void imageSizeChanged(Q_INT32 w, Q_INT32 h); +    void timeOut(); + +private: +    class Element { +    public: +        Element(Observer* o) : observer(o), valid(true) {} +        Observer* observer; +        bool valid; +    }; +    typedef QValueVector< QValueVector<Element*> > Raster; +    typedef QValueList<Element*> Queue; + +    void cleanUpElements(); + +    Observer* m_observer; +    Raster m_raster; +    Queue m_queue; +    QTimer m_timer; +    int m_timeOutMSec; +    int m_rasterSize; +    int m_width, m_height; +    KisView * m_view; +    bool m_busy; + +    KisPaintDeviceSP m_imageProjection; +}; + +#endif // _KIS_IMAGE_RASTERED_CACHE_H_ diff --git a/krita/plugins/viewplugins/histogram_docker/kritahistogramdocker.desktop b/krita/plugins/viewplugins/histogram_docker/kritahistogramdocker.desktop new file mode 100644 index 000000000..1603058dd --- /dev/null +++ b/krita/plugins/viewplugins/histogram_docker/kritahistogramdocker.desktop @@ -0,0 +1,40 @@ +[Desktop Entry] +Name=Histogram Docker +Name[ca]=Amarrador  de l'histograma +Name[cy]=Bachydd Histogram +Name[da]=Histogramdokning +Name[de]=Histogramm-Docker +Name[el]=Προσάρτηση ιστογράμματος +Name[eo]=Histogramdokilo +Name[es]=Anclaje del histograma +Name[et]=Histogrammi dokk +Name[fa]=پیونددهندۀ سابقهنما +Name[fr]=Ancrage d'histogramme +Name[fy]=Histogramkomponint +Name[gl]=Acoplador de Histogramas +Name[hu]=Hisztogramdokkoló +Name[is]=Súluritsspjald +Name[it]=Aggancia-istogrammi +Name[ja]=ヒストグラムドッカー +Name[km]=កន្លែងចតអ៊ីស្តូក្រាម +Name[nb]=Histogramdokker +Name[nds]=Histogramm-Docker +Name[ne]=हिस्टोग्राम डकर +Name[nl]=Histogramcomponent +Name[pl]=Doker histogramu +Name[pt]=Acoplador de Histogramas +Name[pt_BR]=Acoplador de Histogramas +Name[ru]=Панель гистограммы +Name[sk]=Histogram +Name[sl]=Histogram +Name[sr]=Сидраш хистограма +Name[sr@Latn]=Sidraš histograma +Name[sv]=Histogramdockning +Name[uk]=Швартувальник гістограм +Name[uz]=Gistogramma paneli +Name[uz@cyrillic]=Гистограмма панели +Name[zh_TW]=直方圖停駐點 +ServiceTypes=Krita/ViewPlugin +Type=Service +X-KDE-Library=kritahistogramdocker +X-Krita-Version=2 diff --git a/krita/plugins/viewplugins/histogram_docker/kritahistogramdocker.rc b/krita/plugins/viewplugins/histogram_docker/kritahistogramdocker.rc new file mode 100644 index 000000000..525fd65b7 --- /dev/null +++ b/krita/plugins/viewplugins/histogram_docker/kritahistogramdocker.rc @@ -0,0 +1,3 @@ +<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd"> +<kpartgui library="kritahistogramdocker" version="1"> +</kpartgui>
\ No newline at end of file diff --git a/krita/plugins/viewplugins/history_docker/Makefile.am b/krita/plugins/viewplugins/history_docker/Makefile.am new file mode 100644 index 000000000..0432d54d2 --- /dev/null +++ b/krita/plugins/viewplugins/history_docker/Makefile.am @@ -0,0 +1,18 @@ +#kde_services_DATA = kritahistorydocker.desktop + +INCLUDES  = -I$(srcdir)/../../../sdk \ +	-I$(srcdir)/../../../core \ +	-I$(srcdir)/../../../kritacolor/ \ +	-I$(srcdir)/../../../ui \ +	$(KOFFICE_INCLUDES) \ +	$(all_includes) + +kritahistorydocker_la_SOURCES = historydocker.cc  + +kde_module_LTLIBRARIES = kritahistorydocker.la +noinst_HEADERS = historydocker.h  + +kritahistorydocker_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) +kritahistorydocker_la_LIBADD =  ../../../libkritacommon.la + +kritahistorydocker_la_METASOURCES = AUTO diff --git a/krita/plugins/viewplugins/history_docker/historydocker.cc b/krita/plugins/viewplugins/history_docker/historydocker.cc new file mode 100644 index 000000000..20b1d0130 --- /dev/null +++ b/krita/plugins/viewplugins/history_docker/historydocker.cc @@ -0,0 +1,58 @@ +/* + * This file is part of the KDE project + * + *  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 <klocale.h> +#include <kiconloader.h> +#include <kinstance.h> +#include <kmessagebox.h> +#include <kstandarddirs.h> +#include <ktempfile.h> +#include <kdebug.h> +#include <kgenericfactory.h> + +#include <kis_doc.h> +#include <kis_global.h> +#include <kis_types.h> +#include <kis_view.h> + +#include "historydocker.h" + +typedef KGenericFactory<KritaHistoryDocker> KritaHistoryDockerFactory; +K_EXPORT_COMPONENT_FACTORY( kritahistorydocker, KritaHistoryDockerFactory( "krita" ) ) + +KritaHistoryDocker::KritaHistoryDocker(QObject *parent, const char *name, const QStringList &) +        : KParts::Plugin(parent, name) +{ +     + + +    if ( parent->inherits("KisView") ) +    { +        setInstance(KritaHistoryDockerFactory::instance()); +        // Create history docker +        // Add the docker to the docker manager +        // Connect the undo system to the docker +    } + +} + +KritaHistoryDocker::~KritaHistoryDocker() +{ +} diff --git a/krita/plugins/viewplugins/history_docker/historydocker.h b/krita/plugins/viewplugins/history_docker/historydocker.h new file mode 100644 index 000000000..8556d37c7 --- /dev/null +++ b/krita/plugins/viewplugins/history_docker/historydocker.h @@ -0,0 +1,34 @@ +/* + * This file is part of Krita + * + * 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. + */ + +#ifndef _HISTORYDOCKER_H  +#define _HISTORYDOCKER_H + +#include <kparts/plugin.h> + +class KritaHistoryDocker : public KParts::Plugin +{ +public: +    KritaHistoryDocker(QObject *parent, const char *name, const QStringList &); +    virtual ~KritaHistoryDocker(); +}; + + +#endif //_HISTORYDOCKER_H diff --git a/krita/plugins/viewplugins/history_docker/kritahistorydocker.desktop b/krita/plugins/viewplugins/history_docker/kritahistorydocker.desktop new file mode 100644 index 000000000..52d5e40a2 --- /dev/null +++ b/krita/plugins/viewplugins/history_docker/kritahistorydocker.desktop @@ -0,0 +1,73 @@ +[Desktop Entry] +Name=History Docker +Name[ca]=Amarrador d'història +Name[cy]=Bachydd Hanes +Name[da]=Historikdokning +Name[de]=Verlauf-Docker +Name[el]=Προσάρτηση ιστορικού +Name[eo]=Historidokilo +Name[es]=Anclaje del histórico +Name[et]=Ajaloo dokk +Name[fa]=پیونددهندۀ سابقهنما +Name[fr]=Ancrage d'historique +Name[fy]=Histoarjekomponint +Name[gl]=Acoplador de Histórico +Name[hu]=Előzménydokkoló +Name[is]=Söguspjald +Name[it]=Aggancia-cronologia +Name[ja]=履歴ドックパネル +Name[km]=កន្លែងចតប្រវត្តិ +Name[nb]=Hiastoriedokker +Name[nds]=Vörgeschicht-Docker +Name[ne]=इतिहास डकर +Name[nl]=Geschiedeniscomponent +Name[pl]=Doker historii +Name[pt]=Acoplador de Histórico +Name[pt_BR]=Acoplador de Histórico +Name[ru]=История команд +Name[sk]=História +Name[sl]=Zgodovina +Name[sr]=Сидраш историјата +Name[sr@Latn]=Sidraš istorijata +Name[sv]=Historikdockning +Name[uk]=Швартувальник історії +Name[zh_TW]=歷史紀錄停駐點 +Comment=Command history docker for Krita +Comment[bg]=Основната функционалност на Krita +Comment[ca]=Amarrador d'història d'ordres per a Krita +Comment[cy]=Bachydd yr hanes gorchmynion ar gyfer Krita +Comment[da]=Dokning af kommandohistorik for Krita +Comment[de]=Befehlsverlauf-Docker für Krita +Comment[el]=Άρθρωμα προσάρτησης ιστορικού εντολών για το Krita +Comment[es]=Anclaje con el histórico de órdenes para Krita +Comment[et]=Krita käskude ajaloo dokk +Comment[fa]=پیونددهنده تاریخچۀ فرمان برای Krita +Comment[fr]=Ancrage de l'historique des commandes pour Krita +Comment[fy]=Komponint mei bewurkingshistoarje foar Krita" +Comment[gl]=Un módulo acoplado co historial de comandos para Krita +Comment[hu]=Krita parancselőzmény-dokkoló +Comment[is]=Skipanasöguspjald fyrir Krita +Comment[it]=Aggancia-cronologia dei comandi di Krita +Comment[ja]=Krita コマンド履歴ドックパネル +Comment[km]=កន្លែងចតប្រវត្តិពាក្យបញ្ជាសម្រាប់ Krita +Comment[nb]=Kommandohistorie-dokker for Krita +Comment[nds]=Befehlsvörgeschicht-Docker för Krita +Comment[ne]=क्रिताका लागि आदेश इतिहास +Comment[nl]=Component met bewerkingsgeschiedenis voor Krita +Comment[pl]=Doker historii poleceń dla Krita +Comment[pt]=Um módulo acoplado de histórico de comandos do Krita +Comment[pt_BR]=Um módulo acoplado de histórico de comandos do Krita +Comment[ru]=Панель истории команд Krita +Comment[sk]=História príkazov pre Krita +Comment[sl]=Zgodovina ukazov za Krito +Comment[sr]=Сидраш историјата наредби за Krita-у +Comment[sr@Latn]=Sidraš istorijata naredbi za Krita-u +Comment[sv]=Dockning av kommandohistorik för Krita +Comment[uk]=Швартувальник історії команд для Krita +Comment[uz]=Krita uchun buyruqlar tarixi paneli +Comment[uz@cyrillic]=Krita учун буйруқлар тарихи панели +Comment[zh_TW]=Krita 的指令紀錄停駐點 +ServiceTypes=Krita/ViewPlugin +Type=Service +X-KDE-Library=kritahistorydocker +X-Krita-Version=2 diff --git a/krita/plugins/viewplugins/imagesize/Makefile.am b/krita/plugins/viewplugins/imagesize/Makefile.am new file mode 100644 index 000000000..12cd96bbb --- /dev/null +++ b/krita/plugins/viewplugins/imagesize/Makefile.am @@ -0,0 +1,24 @@ +kritarcdir = $(kde_datadir)/kritaplugins +kritarc_DATA = imagesize.rc +EXTRA_DIST = $(kritarc_DATA) + +kde_services_DATA = kritaimagesize.desktop + + +INCLUDES  =  -I$(srcdir)/../../../sdk \ +	-I$(srcdir)/../../../core \ +	-I$(srcdir)/../../../kritacolor/ \ +	-I$(srcdir)/../../../ui \ +	$(KOFFICE_INCLUDES) \ +	$(all_includes) + +kritaimagesize_la_SOURCES = wdg_imagesize.ui wdg_layersize.ui imagesize.cc dlg_imagesize.cc dlg_layersize.cc wdg_resolution.ui + +noinst_HEADERS = wdg_imagesize.h dlg_imagesize.h imagesize.h dlg_layersize.h + +kde_module_LTLIBRARIES = kritaimagesize.la + +kritaimagesize_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) +kritaimagesize_la_LIBADD =  ../../../libkritacommon.la  + +kritaimagesize_la_METASOURCES = AUTO diff --git a/krita/plugins/viewplugins/imagesize/configure.in.in b/krita/plugins/viewplugins/imagesize/configure.in.in new file mode 100644 index 000000000..0875ce322 --- /dev/null +++ b/krita/plugins/viewplugins/imagesize/configure.in.in @@ -0,0 +1 @@ +AC_CHECK_DECLS([round], [], [], [#include <math.h>]) diff --git a/krita/plugins/viewplugins/imagesize/dlg_imagesize.cc b/krita/plugins/viewplugins/imagesize/dlg_imagesize.cc new file mode 100644 index 000000000..9a641b94d --- /dev/null +++ b/krita/plugins/viewplugins/imagesize/dlg_imagesize.cc @@ -0,0 +1,277 @@ +/* + *  dlg_imagesize.cc - part of KimageShop^WKrayon^WKrita + * + *  Copyright (c) 2004 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 <config.h> + +#include <math.h> + +#include <iostream> + +using namespace std; + +#include <qradiobutton.h> +#include <qcheckbox.h> +#include <qbuttongroup.h> +#include <qlabel.h> +#include <qcombobox.h> + +#include <klocale.h> +#include <knuminput.h> +#include <kdebug.h> + +#include <kis_cmb_idlist.h> +#include <kis_filter_strategy.h> + +#include "dlg_imagesize.h" +#include "wdg_imagesize.h" + + +// XXX: I'm really real bad at arithmetic, let alone math. Here +// be rounding errors. (Boudewijn) +DlgImageSize::DlgImageSize( QWidget *  parent, +                const char * name) +    : super (parent, name, true, i18n("Image Size"), Ok | Cancel, Ok) +{ +    m_lock = false; + +    m_page = new WdgImageSize(this, "image_size"); +    Q_CHECK_PTR(m_page); + +    m_page->cmbFilterType->setIDList(KisFilterStrategyRegistry::instance()->listKeys()); +    m_page->cmbFilterType->setCurrentText("Mitchell"); + +    setMainWidget(m_page); +    resize(m_page->sizeHint()); + +    unblockAll(); + + +    connect(this, SIGNAL(okClicked()), +        this, SLOT(okClicked())); + +} + +DlgImageSize::~DlgImageSize() +{ +    delete m_page; +} + +void DlgImageSize::hideScaleBox() +{ +    m_page->grpResizeScale->hide(); +} + +void DlgImageSize::setWidth(Q_UINT32 w) +{ +    blockAll(); + +    m_page->lblWidthOriginal->setNum((int)w); +    m_page->intWidth->setValue(w); +    m_oldW = w; +    m_origW = w; + +    unblockAll(); +} + +void DlgImageSize::setWidthPercent(Q_UINT32 w) +{ +    blockAll(); + +    m_page->intWidthPercent->setValue(w); +    m_oldWPercent = w; + +    unblockAll(); +} + + +void DlgImageSize::setMaximumWidth(Q_UINT32 w) +{ +    m_page->intWidth->setMaxValue(w); +    m_maxW = w; +} + +Q_INT32 DlgImageSize::width() +{ +    //return (Q_INT32)qRound(m_oldW); +    return (Q_INT32)qRound(m_page->intWidth->value()); +} + +void DlgImageSize::setHeight(Q_UINT32 h) +{ +    blockAll(); + +    m_page->lblHeightOriginal->setNum((int)h); +    m_page->intHeight->setValue(h); +    m_oldH = h; +    m_origH = h; + +    unblockAll(); +} + + +void DlgImageSize::setHeightPercent(Q_UINT32 h) +{ +    blockAll(); + +    m_page->intHeightPercent->setValue(h); +    m_oldHPercent = h; + +    unblockAll(); +} + + + +void DlgImageSize::setMaximumHeight(Q_UINT32 h) +{ +    m_page->intHeight->setMaxValue(h); +    m_maxH = h; +} + + +Q_INT32 DlgImageSize::height() +{ +    //return (Q_INT32)qRound(m_oldH); +    return (Q_INT32)qRound(m_page->intHeight->value()); +} + +bool DlgImageSize::scale() +{ +    return m_page->radioScale->isChecked(); +} + +bool DlgImageSize::cropLayers() +{ +    return m_page->chkCrop->isChecked(); +} + +KisFilterStrategy *DlgImageSize::filterType() +{ +    KisID filterID = m_page->cmbFilterType->currentItem(); +    KisFilterStrategy *filter = KisFilterStrategyRegistry::instance()->get(filterID); +    return filter; +} + +// SLOTS + +void DlgImageSize::okClicked() +{ +    accept(); +} + +void DlgImageSize::slotWidthPixelsChanged(int w) +{ +    blockAll(); + +    double wPercent = double(w) * 100 / double(m_origW); + +    m_page->intWidthPercent->setValue(qRound(wPercent)); + +    // Set height in pixels and percent of necessary +    if (m_page->chkConstrain->isChecked()) { +        m_page->intHeightPercent->setValue(qRound(wPercent)); + +        m_oldH = qRound(m_origH * wPercent / 100); +        m_page->intHeight->setValue(qRound(m_oldH)); + +    } +    m_oldW = w; + +    unblockAll(); +} + +void DlgImageSize::slotHeightPixelsChanged(int h) +{ +    blockAll(); + +    double hPercent = double(h) * 100 / double(m_origH); + +    m_page->intHeightPercent->setValue(qRound(hPercent)); + +    // Set width in pixels and percent of necessary +    if (m_page->chkConstrain->isChecked()) { +        m_page->intWidthPercent->setValue(qRound(hPercent)); + +        m_oldW = qRound(m_origW * hPercent / 100); +        m_page->intWidth->setValue(qRound(m_oldW)); + +    } +    m_oldH = h; + +    unblockAll(); +} + +void DlgImageSize::slotWidthPercentChanged(int w) +{ +    blockAll(); + +    m_page->intWidth->setValue(qRound(w * m_origW / 100)); + +    if (m_page->chkConstrain->isChecked()) { +        m_page->intHeightPercent->setValue(w); +        m_page->intHeight->setValue(qRound( w * m_origH / 100)); +    } + +    unblockAll(); +} + +void DlgImageSize::slotHeightPercentChanged(int h) +{ +    blockAll(); + +    m_page->intHeight->setValue(qRound(h * m_origH / 100)); +    if (m_page->chkConstrain->isChecked()) { +        m_page->intWidthPercent->setValue(h); +        m_page->intWidth->setValue(qRound( h * m_origW / 100)); +    } + +    unblockAll(); + +} + + +void DlgImageSize::blockAll() +{ +    // XXX: more efficient to use blockSignals? +    m_page->intWidth->disconnect(); +    m_page->intHeight->disconnect(); +    m_page->intWidthPercent->disconnect(); +    m_page->intHeightPercent->disconnect(); + +} + +void DlgImageSize::unblockAll() +{ +    // XXX: more efficient to use blockSignals? +    connect (m_page->intWidth, SIGNAL(valueChanged(int)), +         this, SLOT(slotWidthPixelsChanged(int))); + +    connect (m_page->intHeight, SIGNAL(valueChanged(int)), +         this, SLOT(slotHeightPixelsChanged(int))); + +    connect (m_page->intWidthPercent, SIGNAL(valueChanged(int)), +         this, SLOT(slotWidthPercentChanged(int))); + +    connect (m_page->intHeightPercent, SIGNAL(valueChanged(int)), +         this, SLOT(slotHeightPercentChanged(int))); + + +} + +#include "dlg_imagesize.moc" diff --git a/krita/plugins/viewplugins/imagesize/dlg_imagesize.h b/krita/plugins/viewplugins/imagesize/dlg_imagesize.h new file mode 100644 index 000000000..169d8cbd5 --- /dev/null +++ b/krita/plugins/viewplugins/imagesize/dlg_imagesize.h @@ -0,0 +1,82 @@ +/* + *  dlg_imagesize.h -- part of KimageShop^WKrayon^WKrita + * + *  Copyright (c) 2004 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. + */ +#ifndef DLG_IMAGESIZE +#define DLG_IMAGESIZE + +#include <kdialogbase.h> + +class KisFilterStrategy; +class WdgImageSize; + +/** + * This dialog allows the user to create a selection mask based + * on a (range of) colors. + */ +class DlgImageSize: public KDialogBase { +    typedef KDialogBase super; +    Q_OBJECT + +public: + +    DlgImageSize(QWidget * parent = 0, +             const char* name = 0); +    ~DlgImageSize(); + +    void hideScaleBox(); + +    void setWidth(Q_UINT32 w); +    void setWidthPercent(Q_UINT32 w); +    void setMaximumWidth(Q_UINT32 w); +    Q_INT32 width(); + +    void setHeight(Q_UINT32 h); +    void setHeightPercent(Q_UINT32 h); +    void setMaximumHeight(Q_UINT32 h); +    Q_INT32 height(); + +    bool scale(); +    bool cropLayers(); + +    KisFilterStrategy *filterType(); + +private slots: + +    void okClicked(); +    void slotWidthPixelsChanged(int w); +    void slotHeightPixelsChanged(int h); +    void slotWidthPercentChanged(int w); +    void slotHeightPercentChanged(int h); + +private: + +    void blockAll(); +    void unblockAll(); + +    WdgImageSize * m_page; +    double m_oldW, m_oldH; +    double m_oldWPercent, m_oldHPercent; +    double m_origW, m_origH; +    double m_maxW, m_maxH; + +    bool m_lock; + +}; + +#endif // DLG_IMAGESIZE diff --git a/krita/plugins/viewplugins/imagesize/dlg_layersize.cc b/krita/plugins/viewplugins/imagesize/dlg_layersize.cc new file mode 100644 index 000000000..ba942eca1 --- /dev/null +++ b/krita/plugins/viewplugins/imagesize/dlg_layersize.cc @@ -0,0 +1,261 @@ +/* + *  dlg_layersize.cc - part of Krita + * + *  Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org> + *  Copyright (c) 2005 Sven Langkamp <longamp@reallygood.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 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 <config.h> + +#include <math.h> + +#include <iostream> + +using namespace std; + +#include <qradiobutton.h> +#include <qcheckbox.h> +#include <qbuttongroup.h> +#include <qlabel.h> +#include <qcombobox.h> + +#include <klocale.h> +#include <knuminput.h> +#include <kdebug.h> + +#include <kis_cmb_idlist.h> +#include <kis_filter_strategy.h> + +#include "dlg_layersize.h" +#include "wdg_layersize.h" + + +// XXX: I'm really real bad at arithmetic, let alone math. Here +// be rounding errors. (Boudewijn) +DlgLayerSize::DlgLayerSize( QWidget *  parent, +                const char * name) +    : super (parent, name, true, i18n("Scale Layer"), Ok | Cancel, Ok) +{ +    m_lock = false; + +    m_page = new WdgLayerSize(this, "layer_size"); +    Q_CHECK_PTR(m_page); +     +    m_page->cmbFilterType->setIDList(KisFilterStrategyRegistry::instance()->listKeys()); +    m_page->cmbFilterType->setCurrentText("Mitchell"); + +    setMainWidget(m_page); +    resize(m_page->sizeHint()); + +    unblockAll(); + + +    connect(this, SIGNAL(okClicked()), +        this, SLOT(okClicked())); + +} + +DlgLayerSize::~DlgLayerSize() +{ +    delete m_page; +} + +void DlgLayerSize::setWidth(Q_UINT32 w) +{ +    blockAll(); + +    m_page->lblWidthOriginal->setNum((int)w); +    m_page->intWidth->setValue(w); +    m_oldW = w; +    m_origW = w; + +    unblockAll(); +} + +void DlgLayerSize::setWidthPercent(Q_UINT32 w) +{ +    blockAll(); + +    m_page->intWidthPercent->setValue(w); +    m_oldWPercent = w; + +    unblockAll(); +} + + +void DlgLayerSize::setMaximumWidth(Q_UINT32 w) +{ +    m_page->intWidth->setMaxValue(w); +    m_maxW = w; +} + +Q_INT32 DlgLayerSize::width() +{ +    //return (Q_INT32)qRound(m_oldW); +    return (Q_INT32)qRound(m_page->intWidth->value()); +} + +void DlgLayerSize::setHeight(Q_UINT32 h) +{ +    blockAll(); + +    m_page->lblHeightOriginal->setNum((int)h); +    m_page->intHeight->setValue(h); +    m_oldH = h; +    m_origH = h; + +    unblockAll(); +} + + +void DlgLayerSize::setHeightPercent(Q_UINT32 h) +{ +    blockAll(); + +    m_page->intHeightPercent->setValue(h); +    m_oldHPercent = h; + +    unblockAll(); +} + +void DlgLayerSize::setMaximumHeight(Q_UINT32 h) +{ +    m_page->intHeight->setMaxValue(h); +    m_maxH = h; +} + +Q_INT32 DlgLayerSize::height() +{ +    //return (Q_INT32)qRound(m_oldH); +    return (Q_INT32)qRound(m_page->intHeight->value()); +} + +KisFilterStrategy *DlgLayerSize::filterType() +{ +    KisID filterID = m_page->cmbFilterType->currentItem(); +    KisFilterStrategy *filter = KisFilterStrategyRegistry::instance()->get(filterID); +    return filter; +} + + +// SLOTS + +void DlgLayerSize::okClicked() +{ +    accept(); +} + +void DlgLayerSize::slotWidthPixelsChanged(int w) +{ +    blockAll(); + +    double wPercent = double(w) * 100 / double(m_origW); + +    m_page->intWidthPercent->setValue(qRound(wPercent)); + +    // Set height in pixels and percent of necessary +    if (m_page->chkConstrain->isChecked()) { +        m_page->intHeightPercent->setValue(qRound(wPercent)); + +        m_oldH = qRound(m_origH * wPercent / 100); +        m_page->intHeight->setValue(qRound(m_oldH)); + +    } +    m_oldW = w; + +    unblockAll(); +} + +void DlgLayerSize::slotHeightPixelsChanged(int h) +{ +    blockAll(); + +    double hPercent = double(h) * 100 / double(m_origH); + +    m_page->intHeightPercent->setValue(qRound(hPercent)); + +    // Set width in pixels and percent of necessary +    if (m_page->chkConstrain->isChecked()) { +        m_page->intWidthPercent->setValue(qRound(hPercent)); + +        m_oldW = qRound(m_origW * hPercent / 100); +        m_page->intWidth->setValue(qRound(m_oldW)); + +    } +    m_oldH = h; + +    unblockAll(); +} + +void DlgLayerSize::slotWidthPercentChanged(int w) +{ +    blockAll(); + +    m_page->intWidth->setValue(qRound(w * m_origW / 100)); + +    if (m_page->chkConstrain->isChecked()) { +        m_page->intHeightPercent->setValue(w); +        m_page->intHeight->setValue(qRound( w * m_origH / 100)); +    } + +    unblockAll(); +} + +void DlgLayerSize::slotHeightPercentChanged(int h) +{ +    blockAll(); + +    m_page->intHeight->setValue(qRound(h * m_origH / 100)); +    if (m_page->chkConstrain->isChecked()) { +        m_page->intWidthPercent->setValue(h); +        m_page->intWidth->setValue(qRound( h * m_origW / 100)); +    } + +    unblockAll(); + +} + + +void DlgLayerSize::blockAll() +{ +    // XXX: more efficient to use blockSignals? +    m_page->intWidth->disconnect(); +    m_page->intHeight->disconnect(); +    m_page->intWidthPercent->disconnect(); +    m_page->intHeightPercent->disconnect(); + +} + +void DlgLayerSize::unblockAll() +{ +    // XXX: more efficient to use blockSignals? +    connect (m_page->intWidth, SIGNAL(valueChanged(int)), +         this, SLOT(slotWidthPixelsChanged(int))); + +    connect (m_page->intHeight, SIGNAL(valueChanged(int)), +         this, SLOT(slotHeightPixelsChanged(int))); + +    connect (m_page->intWidthPercent, SIGNAL(valueChanged(int)), +         this, SLOT(slotWidthPercentChanged(int))); + +    connect (m_page->intHeightPercent, SIGNAL(valueChanged(int)), +         this, SLOT(slotHeightPercentChanged(int))); + + +} + +#include "dlg_layersize.moc" diff --git a/krita/plugins/viewplugins/imagesize/dlg_layersize.h b/krita/plugins/viewplugins/imagesize/dlg_layersize.h new file mode 100644 index 000000000..fa27b7329 --- /dev/null +++ b/krita/plugins/viewplugins/imagesize/dlg_layersize.h @@ -0,0 +1,73 @@ +/* + *  dlg_layersize.h -- part of Krita + * + *  Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org> + *  Copyright (c) 2005 Sven Langkamp <longamp@reallygood.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 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. + */ +#ifndef DLG_LAYERSIZE +#define DLG_LAYERSIZE + +#include <kdialogbase.h> + +class WdgLayerSize; +class KisFilterStrategy; + +class DlgLayerSize: public KDialogBase { +    typedef KDialogBase super; +    Q_OBJECT + +public: + +    DlgLayerSize(QWidget * parent = 0, +             const char* name = 0); +    ~DlgLayerSize(); + +    void setWidth(Q_UINT32 w); +    void setWidthPercent(Q_UINT32 w); +    void setMaximumWidth(Q_UINT32 w); +    Q_INT32 width(); + +    void setHeight(Q_UINT32 h); +    void setHeightPercent(Q_UINT32 h); +    void setMaximumHeight(Q_UINT32 h); +    Q_INT32 height(); +    KisFilterStrategy *filterType(); + +private slots: + +    void okClicked(); +    void slotWidthPixelsChanged(int w); +    void slotHeightPixelsChanged(int h); +    void slotWidthPercentChanged(int w); +    void slotHeightPercentChanged(int h); + +private: + +    void blockAll(); +    void unblockAll(); + +    WdgLayerSize * m_page; +    double m_oldW, m_oldH; +    double m_oldWPercent, m_oldHPercent; +    double m_origW, m_origH; +    double m_maxW, m_maxH; + +    bool m_lock; + +}; + +#endif // DLG_IMAGESIZE diff --git a/krita/plugins/viewplugins/imagesize/imagesize.cc b/krita/plugins/viewplugins/imagesize/imagesize.cc new file mode 100644 index 000000000..df400b5ab --- /dev/null +++ b/krita/plugins/viewplugins/imagesize/imagesize.cc @@ -0,0 +1,190 @@ +/* + * imagesize.cc -- Part of Krita + * + * Copyright (c) 2004 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 <math.h> + +#include <stdlib.h> + +#include <qslider.h> +#include <qrect.h> +#include <qpoint.h> + +#include <klocale.h> +#include <kiconloader.h> +#include <kinstance.h> +#include <kmessagebox.h> +#include <kstandarddirs.h> +#include <ktempfile.h> +#include <kdebug.h> +#include <kgenericfactory.h> +#include <kstdaction.h> + +#include <kis_doc.h> +#include <kis_config.h> +#include <kis_image.h> +#include <kis_layer.h> +#include <kis_global.h> +#include <kis_types.h> +#include <kis_view.h> +#include <kis_selection.h> +#include <kis_selection_manager.h> +#include <kis_transaction.h> +#include <kis_canvas_controller.h> +#include <kis_scale_visitor.h> + +#include "imagesize.h" +#include "dlg_imagesize.h" +#include "dlg_layersize.h" +#include "kis_filter_strategy.h" + +typedef KGenericFactory<ImageSize> ImageSizeFactory; +K_EXPORT_COMPONENT_FACTORY( kritaimagesize, ImageSizeFactory( "krita" ) ) + +ImageSize::ImageSize(QObject *parent, const char *name, const QStringList &) +    : KParts::Plugin(parent, name) +{ +    if ( parent->inherits("KisView") ) +    { +        setInstance(ImageSizeFactory::instance()); +        setXMLFile(locate("data","kritaplugins/imagesize.rc"), true); + +        (void) new KAction(i18n("Change &Image Size..."), 0, "Shift-s", this, SLOT(slotImageSize()), actionCollection(), "imagesize"); +        (void) new KAction(i18n("&Scale Layer..."), 0, 0, this, SLOT(slotLayerSize()), actionCollection(), "layerscale"); + + +        m_view = (KisView*) parent; +        // Selection manager takes ownership? +        KAction * a = new KAction(i18n("&Scale Selection..."), 0, 0, this, SLOT(slotSelectionScale()), actionCollection(), "selectionscale"); +        Q_CHECK_PTR(a); +        m_view ->canvasSubject()-> selectionManager()->addSelectionAction(a); +    } +} + +ImageSize::~ImageSize() +{ +    m_view = 0; +} + +void ImageSize::slotImageSize() +{ +    KisImageSP image = m_view->canvasSubject()->currentImg(); + +    if (!image) return; + +    DlgImageSize * dlgImageSize = new DlgImageSize(m_view, "ImageSize"); +    Q_CHECK_PTR(dlgImageSize); + +    dlgImageSize->setCaption(i18n("Image Size")); + +    KisConfig cfg; + +    dlgImageSize->setWidth(image->width()); +    dlgImageSize->setHeight(image->height()); + +    if (dlgImageSize->exec() == QDialog::Accepted) { +        Q_INT32 w = dlgImageSize->width(); +        Q_INT32 h = dlgImageSize->height(); + +        if (dlgImageSize->scale()) { +            m_view->scaleCurrentImage((double)w / ((double)(image->width())), +                            (double)h / ((double)(image->height())), +                            dlgImageSize->filterType()); +        } +        else { +            m_view->resizeCurrentImage(w, h, dlgImageSize->cropLayers()); +        } +    } + +    delete dlgImageSize; +} + +void ImageSize::slotLayerSize() +{ +    KisImageSP image = m_view->canvasSubject()->currentImg(); + +    if (!image) return; + +    DlgLayerSize * dlgLayerSize = new DlgLayerSize(m_view, "LayerSize"); +    Q_CHECK_PTR(dlgLayerSize); + +    dlgLayerSize->setCaption(i18n("Layer Size")); + +    KisConfig cfg; +    KisPaintDeviceSP dev = image->activeDevice(); + +    QRect rc = dev->exactBounds(); + +    dlgLayerSize->setWidth(rc.width()); +    dlgLayerSize->setHeight(rc.height()); + +    if (dlgLayerSize->exec() == QDialog::Accepted) { +        Q_INT32 w = dlgLayerSize->width(); +        Q_INT32 h = dlgLayerSize->height(); + +        m_view->scaleLayer((double)w / ((double)(rc.width())), +                           (double)h / ((double)(rc.height())), +                           dlgLayerSize->filterType()); +    } +    delete dlgLayerSize; +} + +void ImageSize::slotSelectionScale() +{ +    KisImageSP image = m_view->canvasSubject()->currentImg(); + +    if (!image) return; + +    KisPaintDeviceSP layer = image->activeDevice(); + +    if (!layer) return; + +    if (!layer->hasSelection()) return; + + +    DlgLayerSize * dlgLayerSize = new DlgLayerSize(m_view, "SelectionScale"); +    Q_CHECK_PTR(dlgLayerSize); + +    dlgLayerSize->setCaption(i18n("Scale Selection")); + +    KisConfig cfg; +    QRect rc = layer->selection()->selectedRect(); + +    dlgLayerSize->setWidth(rc.width()); +    dlgLayerSize->setHeight(rc.height()); + +    if (dlgLayerSize->exec() == QDialog::Accepted) { +        Q_INT32 w = dlgLayerSize->width(); +        Q_INT32 h = dlgLayerSize->height(); + +        KisScaleWorker worker (layer->selection().data(), +                               (double)w / ((double)(rc.width())), +                               (double)h / ((double)(rc.height())), +                               dlgLayerSize->filterType()); +        worker.run(); + +        m_view->getCanvasController()->updateCanvas(); + +    } +    delete dlgLayerSize; +} + + +#include "imagesize.moc" diff --git a/krita/plugins/viewplugins/imagesize/imagesize.h b/krita/plugins/viewplugins/imagesize/imagesize.h new file mode 100644 index 000000000..ce8f0f418 --- /dev/null +++ b/krita/plugins/viewplugins/imagesize/imagesize.h @@ -0,0 +1,48 @@ +/*  + * imagesize.h -- Part of Krita + * + * Copyright (c) 2004 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. + */ +#ifndef IMAGESIZE_H +#define IMAGESIZE_H + +#include <kparts/plugin.h> + +class KisView; +class KisPainter; + +class ImageSize : public KParts::Plugin +{ +    Q_OBJECT +public: +    ImageSize(QObject *parent, const char *name, const QStringList &); +    virtual ~ImageSize(); +     +private slots: + +    void slotImageSize(); +    void slotLayerSize(); +    void slotSelectionScale(); + +private: + +    KisView * m_view; +    KisPainter * m_painter; + +}; + +#endif // IMAGESIZE_H diff --git a/krita/plugins/viewplugins/imagesize/imagesize.rc b/krita/plugins/viewplugins/imagesize/imagesize.rc new file mode 100644 index 000000000..8b7e12c9a --- /dev/null +++ b/krita/plugins/viewplugins/imagesize/imagesize.rc @@ -0,0 +1,15 @@ +<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd"> +<kpartgui library="kritaimagesize" version="6"> +<MenuBar> +    <Menu name="Image"><text>Image</text> +	<Action name="imagesize"/> +	<Action name="imageresolution"/> +    </Menu> +    <Menu name="Layer"><text>Layer</text> +	<Action name="layerscale"/> +    </Menu> +    <Menu name="Select"><text>&Select</text> +	<Action name="selectionscale"/> +    </Menu> +</MenuBar> +</kpartgui> diff --git a/krita/plugins/viewplugins/imagesize/kritaimagesize.desktop b/krita/plugins/viewplugins/imagesize/kritaimagesize.desktop new file mode 100644 index 000000000..edf202f4f --- /dev/null +++ b/krita/plugins/viewplugins/imagesize/kritaimagesize.desktop @@ -0,0 +1,39 @@ +[Desktop Entry] +Name=Image Resize and Scale Plugin +Name[bg]=Приставка за оразмеряване +Name[ca]=Connector de redimensionament i escala d'imatge +Name[da]=Plugin for størrelsesændring og skalering +Name[de]=Bildgrößenänderungs- und Skalierungsmodul +Name[el]=Πρόσθετο αλλαγής μεγέθους και κλιμάκωσης εικόνας +Name[es]=Complemento para cambiar de tamaño y para escalar la imagen +Name[et]=Pildi suuruse muutmise ja skaleerimise plugin +Name[fa]=تغییر اندازۀ تصویر و مقیاسبندی وصله +Name[fr]=Module de redimensionnement d'images +Name[fy]=Grutte wizigje en skale fan de ôfbylding +Name[gl]=Plugin de Redimensionamento e Escalado da Imaxe +Name[he]=תוסף לשינוי גודל וזוויות של תמונ +Name[hu]=Képátméretező és -nyújtó modul +Name[is]=Breytingar á stærð og skala mynda íforrit +Name[it]=Plugin di ridimensionamento e riscalamento delle immagini +Name[ja]=画像 リサイズ/スケール プラグイン +Name[km]=កម្មវិធីជំនួយដើម្បីប្ដូរទំហំ និងធ្វើមាត្រដ្ឋានរូបភាព +Name[nb]=Programtillegg for skalering og endring av bildestørrelse +Name[nds]=Moduul för't Ännern un Topassen vun de Bildgrött +Name[ne]=छवि रिसाइज र स्केल प्लगइन +Name[nl]=Grootte wijzigen en schalen van afbeelding +Name[pl]=Wtyczka skalowania i zmiany rozmiarów obrazków +Name[pt]='Plugin' de Dimensionamento e Escala da Imagem +Name[pt_BR]=Plugin de Redimensionamento e Escala da Imagem +Name[ru]=Модуль масштабирования и изменения размера +Name[se]=Lassemoduvla mii skále ja rievdada govvasturrodaga +Name[sk]=Modul na zmenu veľkosti a škály obrázkov +Name[sl]=Vstavek za spreminjanje velikosti in povečavo slike +Name[sr]=Прикључак за промену величине и скалирање слика +Name[sr@Latn]=Priključak za promenu veličine i skaliranje slika +Name[sv]=Insticksprogram för bildstorleksändring och skalning +Name[uk]=Втулок зміни розміру та масштабування зображень +Name[zh_TW]=圖片大小與縮放外掛程式 +ServiceTypes=Krita/ViewPlugin +Type=Service +X-KDE-Library=kritaimagesize +X-Krita-Version=2 diff --git a/krita/plugins/viewplugins/imagesize/wdg_imagesize.ui b/krita/plugins/viewplugins/imagesize/wdg_imagesize.ui new file mode 100644 index 000000000..896bbb054 --- /dev/null +++ b/krita/plugins/viewplugins/imagesize/wdg_imagesize.ui @@ -0,0 +1,365 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>WdgImageSize</class> +<widget class="QWidget"> +    <property name="name"> +        <cstring>WdgImageSize</cstring> +    </property> +    <property name="geometry"> +        <rect> +            <x>0</x> +            <y>0</y> +            <width>397</width> +            <height>382</height> +        </rect> +    </property> +    <property name="caption"> +        <string>Image Size</string> +    </property> +    <grid> +        <property name="name"> +            <cstring>unnamed</cstring> +        </property> +        <widget class="QButtonGroup" row="0" column="0" rowspan="1" colspan="2"> +            <property name="name"> +                <cstring>grpResizeScale</cstring> +            </property> +            <property name="title"> +                <string></string> +            </property> +            <grid> +                <property name="name"> +                    <cstring>unnamed</cstring> +                </property> +                <widget class="QLabel" row="0" column="0"> +                    <property name="name"> +                        <cstring>pixmapLabel1_2</cstring> +                    </property> +                    <property name="pixmap"> +                        <pixmap>image0</pixmap> +                    </property> +                    <property name="scaledContents"> +                        <bool>true</bool> +                    </property> +                </widget> +                <spacer row="1" column="1" rowspan="1" colspan="2"> +                    <property name="name"> +                        <cstring>spacer2_2</cstring> +                    </property> +                    <property name="orientation"> +                        <enum>Horizontal</enum> +                    </property> +                    <property name="sizeType"> +                        <enum>Expanding</enum> +                    </property> +                    <property name="sizeHint"> +                        <size> +                            <width>65</width> +                            <height>20</height> +                        </size> +                    </property> +                </spacer> +                <spacer row="0" column="1" rowspan="1" colspan="2"> +                    <property name="name"> +                        <cstring>spacer1_2</cstring> +                    </property> +                    <property name="orientation"> +                        <enum>Horizontal</enum> +                    </property> +                    <property name="sizeType"> +                        <enum>Expanding</enum> +                    </property> +                    <property name="sizeHint"> +                        <size> +                            <width>65</width> +                            <height>20</height> +                        </size> +                    </property> +                </spacer> +                <widget class="QLabel" row="0" column="3"> +                    <property name="name"> +                        <cstring>pixmapLabel2_2</cstring> +                    </property> +                    <property name="sizePolicy"> +                        <sizepolicy> +                            <hsizetype>0</hsizetype> +                            <vsizetype>0</vsizetype> +                            <horstretch>0</horstretch> +                            <verstretch>0</verstretch> +                        </sizepolicy> +                    </property> +                    <property name="pixmap"> +                        <pixmap>image1</pixmap> +                    </property> +                    <property name="scaledContents"> +                        <bool>true</bool> +                    </property> +                </widget> +                <widget class="QRadioButton" row="1" column="0"> +                    <property name="name"> +                        <cstring>radioResize</cstring> +                    </property> +                    <property name="text"> +                        <string>&Resize</string> +                    </property> +                </widget> +                <widget class="QCheckBox" row="2" column="0" rowspan="1" colspan="2"> +                    <property name="name"> +                        <cstring>chkCrop</cstring> +                    </property> +                    <property name="text"> +                        <string>&Crop layers on image resize</string> +                    </property> +                    <property name="checked"> +                        <bool>true</bool> +                    </property> +                </widget> +                <spacer row="2" column="2" rowspan="1" colspan="2"> +                    <property name="name"> +                        <cstring>spacer3</cstring> +                    </property> +                    <property name="orientation"> +                        <enum>Horizontal</enum> +                    </property> +                    <property name="sizeType"> +                        <enum>Expanding</enum> +                    </property> +                    <property name="sizeHint"> +                        <size> +                            <width>121</width> +                            <height>20</height> +                        </size> +                    </property> +                </spacer> +                <widget class="QRadioButton" row="1" column="3"> +                    <property name="name"> +                        <cstring>radioScale</cstring> +                    </property> +                    <property name="text"> +                        <string>&Scale</string> +                    </property> +                    <property name="checked"> +                        <bool>true</bool> +                    </property> +                </widget> +            </grid> +        </widget> +        <widget class="QButtonGroup" row="1" column="0" rowspan="1" colspan="2"> +            <property name="name"> +                <cstring>grpPixelDimensions</cstring> +            </property> +            <property name="title"> +                <string>&Pixel Dimensions</string> +            </property> +            <grid> +                <property name="name"> +                    <cstring>unnamed</cstring> +                </property> +                <widget class="QLabel" row="0" column="1"> +                    <property name="name"> +                        <cstring>lblWidth</cstring> +                    </property> +                    <property name="text"> +                        <string>&Width:</string> +                    </property> +                    <property name="buddy" stdset="0"> +                        <cstring>intWidth</cstring> +                    </property> +                </widget> +                <widget class="KIntNumInput" row="2" column="2"> +                    <property name="name"> +                        <cstring>intHeight</cstring> +                    </property> +                    <property name="minValue"> +                        <number>0</number> +                    </property> +                </widget> +                <widget class="QLabel" row="0" column="2"> +                    <property name="name"> +                        <cstring>textLabel2</cstring> +                    </property> +                    <property name="text"> +                        <string>&Height:</string> +                    </property> +                    <property name="buddy" stdset="0"> +                        <cstring>intHeight</cstring> +                    </property> +                </widget> +                <widget class="QLabel" row="1" column="1"> +                    <property name="name"> +                        <cstring>lblWidthOriginal</cstring> +                    </property> +                    <property name="frameShape"> +                        <enum>WinPanel</enum> +                    </property> +                    <property name="frameShadow"> +                        <enum>Sunken</enum> +                    </property> +                    <property name="text"> +                        <string></string> +                    </property> +                    <property name="alignment"> +                        <set>AlignVCenter|AlignRight</set> +                    </property> +                </widget> +                <widget class="QLabel" row="1" column="2"> +                    <property name="name"> +                        <cstring>lblHeightOriginal</cstring> +                    </property> +                    <property name="frameShape"> +                        <enum>WinPanel</enum> +                    </property> +                    <property name="frameShadow"> +                        <enum>Sunken</enum> +                    </property> +                    <property name="text"> +                        <string></string> +                    </property> +                    <property name="alignment"> +                        <set>AlignVCenter|AlignRight</set> +                    </property> +                </widget> +                <widget class="QLabel" row="1" column="0"> +                    <property name="name"> +                        <cstring>lblOrignal</cstring> +                    </property> +                    <property name="text"> +                        <string>Original:</string> +                    </property> +                </widget> +                <widget class="QLabel" row="2" column="0"> +                    <property name="name"> +                        <cstring>lblNew</cstring> +                    </property> +                    <property name="text"> +                        <string>&New:</string> +                    </property> +                    <property name="buddy" stdset="0"> +                        <cstring>intWidth</cstring> +                    </property> +                </widget> +                <widget class="KIntNumInput" row="2" column="1"> +                    <property name="name"> +                        <cstring>intWidth</cstring> +                    </property> +                    <property name="minValue"> +                        <number>0</number> +                    </property> +                </widget> +                <widget class="KIntNumInput" row="3" column="1"> +                    <property name="name"> +                        <cstring>intWidthPercent</cstring> +                    </property> +                    <property name="value"> +                        <number>100</number> +                    </property> +                    <property name="minValue"> +                        <number>0</number> +                    </property> +                    <property name="referencePoint"> +                        <number>100</number> +                    </property> +                    <property name="suffix"> +                        <string>%</string> +                    </property> +                </widget> +                <widget class="KIntNumInput" row="3" column="2"> +                    <property name="name"> +                        <cstring>intHeightPercent</cstring> +                    </property> +                    <property name="value"> +                        <number>100</number> +                    </property> +                    <property name="minValue"> +                        <number>0</number> +                    </property> +                    <property name="suffix"> +                        <string>%</string> +                    </property> +                </widget> +                <widget class="QLabel" row="3" column="0"> +                    <property name="name"> +                        <cstring>lblPercent</cstring> +                    </property> +                    <property name="text"> +                        <string>&Percent:</string> +                    </property> +                    <property name="buddy" stdset="0"> +                        <cstring>intWidthPercent</cstring> +                    </property> +                </widget> +                <widget class="QCheckBox" row="4" column="0" rowspan="1" colspan="3"> +                    <property name="name"> +                        <cstring>chkConstrain</cstring> +                    </property> +                    <property name="text"> +                        <string>&Constrain proportions</string> +                    </property> +                    <property name="checked"> +                        <bool>true</bool> +                    </property> +                </widget> +            </grid> +        </widget> +        <widget class="QLabel" row="2" column="0"> +            <property name="name"> +                <cstring>lblFilterType</cstring> +            </property> +            <property name="text"> +                <string>Filter:</string> +            </property> +            <property name="alignment"> +                <set>AlignVCenter|AlignRight</set> +            </property> +            <property name="buddy" stdset="0"> +                <cstring>cmbFilterType</cstring> +            </property> +        </widget> +        <widget class="KisCmbIDList" row="2" column="1"> +            <property name="name"> +                <cstring>cmbFilterType</cstring> +            </property> +        </widget> +    </grid> +</widget> +<customwidgets> +    <customwidget> +        <class>KisCmbIDList</class> +        <header location="local">kis_cmb_idlist.h</header> +        <sizehint> +            <width>1</width> +            <height>24</height> +        </sizehint> +        <container>0</container> +        <sizepolicy> +            <hordata>5</hordata> +            <verdata>5</verdata> +            <horstretch>0</horstretch> +            <verstretch>0</verstretch> +        </sizepolicy> +        <pixmap>image2</pixmap> +    </customwidget> +</customwidgets> +<images> +    <image name="image0"> +        <data format="PNG" length="4407">89504e470d0a1a0a0000000d494844520000006e0000002e0806000000c9032c97000010fe49444154789ced9b79741455bec73f55bdd0d94893054212c32a10821064095b44458119c1618928038af8e61c78e3783cfee13bcfa7c020eaf00e1c90a3ce24f890454438a0cce8cc1b8808610f04599c17c0b0bcb0042421fbda55d575df1f9dea7477ba4967018ecefb9e53dd55f7debaf7d6ef5bbfe52e256566660aee31de78e38da4f2f2f26b0042dcf3e6bd2049120053a64c99f6d24b2fcda8abab76754880d0759001dd5556a7b1afba2b411702245759d0119ee58c0b570202dd558d68fcf14c6b2ce3be4f074c8de94e5709a70024937cf6ecf9a3595959996680050b1674a028ee8cacac2c2c164b8210e29a21b4fb0d21043367ce1c3b65ca53cf5b2cd6b6d6e2f11fe89c46428d73e17e7185e7b96ebc3b02a10bd7bf10d842ecfc61f97fc6039f995bd5b5c6ca8510e88d6f9defb9bfc3c88b8c8c0440922491959545972e5d5ad3fc5d8549128ef628bf10783cab679a77beeb5a6a2c2b79dc27f994c1230d9c4e1d4b278184e604ac72dbbbda7e582c96fbd9fc7dc5a64d9bda76a370a971ab34aeb2b2124d034992319bcd5cb97295ae5dedd8ed76005455e51fff384f48880db359263a3aaaf1dc7f33aaaab6adf3f719959595389d2049264c261357ae5c253e3ec66d415455e5cc997c424242b0584c74ed1a4b48880d93c9d442cdc12368e284101417979094d4039bcde507745da3aaaaca4d5c6e6e1e13274e70df535454cadebd393cf9e404b739f5447b346e6786940aec03ecc00660fef41d6db775cd7b171825252524262679c9a1babada4ddc9123b93cfef8a3eef24545a51c3efc2d93264d74a7bdf0c20b6dee2bb86226bff0f45d062449c2330ad434dd1d951d3f7e82f1e31ff52affd5573b193870406359ad591bed0c4ea645f64cb58ffab79d58c2ec2f02eb7766b4bd3e4df34f5d70727022cb2e511e3b96c7b871e95ee5fffad7bf909232b0cd7df384ea74fd0724eef0e1a3e4e4e472e2c477ee20c36432a1aa4d0408a1131616c6a54b97494979884e9d9a4cc1575fed2239b92f090909e8baee65163bca445ac2ec74ef7d86f4e72bb0d878917692e70f9e723060369bbde4a0eb82b0b0302e5ebc44fffe03b05a9be4f0f5d7bb193c3899c4c444af7a376ddae415bcf98367bed3e9f4caf34b5c4ece7e060c18c4e38f8fa173e7ae6cdcb88d8b170b5154d9cbbc454444b06fdf615455101d1de94e3f72e43bcaca7e64e8d0a10821d034edee8dd76a7388ec06e97331c83bb53343b2770481be72d8b0612b172ffe2f0d0ec94b0e9d3b87f3cd37fba9afd7888a6a92c3d1a327a9aa2a65d8b0615ef5fa93c59d481442347bd9fd1267b3d9282cbc0140bf7e0ff0e4939349ead58b7e7dba633635dd121e16c6238f3c4a6a6a8a3bede6cddbe4e61e64c68c1900e8ba8ed3d9644a3a1cbaeb888c85f467c1d209b7ef6b2f79fee490d8a3170ff68ef3924358681863c7a6336448b23bede6cddb9c387194679ec970a77912f3fcf3cffb6dd373f8042eb3acaa2abaae7bb916bfc1c9a85169ac5bb789f8f8ae444686939060a7fe87cd545cdc43f8843fba6f33994c8485857addfbe9a79b98376f8edb37a8aa8a2449adf2673b33a447815771051e81d0d3f5844d47642c4c7a090e6e27b5f236fb80c776664815c1042dbaae377be3db23872d5b36f39bdfcc7775d1673c6bc0dfe0db13469aa669cde41730aa9c356b3abb771f2423e397949fde4897ca3d848c7f0fc5d4d4c1eef1b15ef7e4e59da57bf738424242703a9d7e1bf444205f278469677cda54bbbd474f709ef622c7f3088ded09da69b7d6a183c502e9d3e0e04e522b4b5b479e3f3cfbec0c76ed3ad06a392426261212121290904f3ffd94b973e70624d280a669e8badecc620524aea2a29291a3d36828caa3cba53fc2137f42682ac2ac40e3b450e9ed4a6c61a18485b8ec7dbf7e7dd8bb771f0e87c35d4fdb2247c93eeaf5d5503b14d40a70025a80a38e66845a2c903e050e7e4d6a6519fb80e93b33a4c2b690d75639ecdf7f004dd3bc047e271fe69b67a419160b086c2a2b2baba9ad55282baba4b4b49c31e9c350774c064b0d2857118e4244a77877f9db37afa02b95f4199c8e5353e8d44966fcf8f1e4e49c202c2c045d57e9d7af07515151ad16187a21e8152e32749fc357fbfce45b2c903e190efe9dd4ca724ee1d2bcd3c190d7117218376e1cbb761d2222220c703270601fa2a2a2dc8418da168830c3b719e7be0ae0a57f870ee51217174d4a4a6f06a73e447dd975421d27c0741e6a73c079d12b2c359914ba687fa3f8da251c0a5455d592981847dfbe0f327a741afdfba7909777b2451f1730af1544f9cbb79821fd09888b97ed20ed734de5b78c8e9243af5ebd193efc617af6eccbd1a3c75b6cd793444f577347e25455c5643223cb20498dd1a0a31642711d35eb41ca4773368d5f1455c16e3b80f5e6124acbeb70284eeaea1a703a9d5cba7495babafaa08213bf26a40d44f9cb979189eb6e45088b5d88c033359ec1c9dd9083a2285e1ab679f366bfcf6f9c1bfebf45e26a6a6ab87af532efbfbf961d3bb2b978e93ad6d028549b09a281f02a74d39f716a0e340d1c0aa8ce320447e96afb8cba4b1f515ee5a4b6b61e4d7372fb76159b366d2639b95faba3ca2669e29fac2089742a3237ae59f9fe1408216d1022b83edcba7583356b3eee30396cdebc85e4e47ecddaf14718e0652203c14d9c2449cc9a3593a95327101bdb8983fb77610a8da53ee2510807ba8008ed82a2eaa8aac0a180a2e888082016faaa6f71bb20879a3a27d5d575984c269292fa60b158da4e5cb064f9e6e9e0545da49d3c0e9ac60690e6cbb21254b3f3e6cd61eedc19f4ee1dc3f1dc7ded96c3030ff4f29a6817423067ce9c663e4e0881d3e9748fd9fc1d06dcb51989313131c4c4c4d0ad5b37f24ee633a2d7121aae7d8bad0f5033829a6a1587e336d5d555a8ea752c76a01684650c515d92c9bf5c04ba46616121b76e5d253e3e843e7dfa0078459b2da1aea404ab2a7b47943ed1a58c4016a219914e55e6c6152b278f81a6893f03f31f1e2171ea44f093dad1d1d1444747131717c777a7ce31ac1d72282ebe46626238bd7bf7f622c91746e8efef250f388ef3cd50558d9a8a4aaafa8dc512b50dcefe165b3f33f6a8f398cd7d4888fb0eb335072aa1b6280547ff6d5c3dfd2385970b3199ca18336638c9c9bf222222c25da7b1ac11c4aa4045de87efd823a2ad4da4786a5ae37f648c469f215a73f378c5cac95c706ada6959d6e6037c7fca46b0a6d2130e8742754539550fb65e0e66733963c70e2739791ae1e1e14053d4b865cb1666cf9e0d34cd2ef95b41090437712693c96ba47ef9f20d9e7e7a2267ce5c24a6dbafb03184b2efdec71ef337cc09a3a1e67fa8bf7213a779314a8f57d97d209ff8b808626234a033050505141414f86d54b4204149d2a6979ecf7fb5f48e3327a267ec80213dfb8c125079daad6965c556ce9e72912649da6340852cdbd03498f96543c0dafccd9c689a467efe259e7a6a42abe53069523af9f9798c1c39d278e680ed1aa4dd695a30288ddbbbf70053a63c8d2441dfbe496cd9f2df24f54a62d8a095dcae3c8b282802691452e779dcaa0b277bcbdfe999d49dd4d4019c3f7f8ca953a762369bd175dd2d108bc582aeeb2c5dba34bbb8b8f872604260fa0e91f3e54c4bcee40fb760559ff36b2ebf7e47ff3de6c825987091a6c894ddb272f230d4567b9066b2a1a9e28ea405c2eedd7b983871b2971c7af44ee2e1944072d845cfa438525307a0eb3ac78e9de1cc99ef193cf821c09bbcd9b367a3ebba7bb9abb531805fe2c2c343d8b7ef2003060c64edda8f090f97e9da1532d7e5f0d0e03144dafba3282a47fff22d3555579930611c172efcc0f6ede500c4c6c6fa35874b962cd9939999f92f0d0d0dc51b366c68b173791fbe4340734923119ea41d84da2a6fd29c9a862c375f0b0c06e1e1a1e4e41ca27fff643efef8bf888cb4a0392cac5d7f809441a33ce4b097daeaab3cf1443a05052e398c1b379acb97cf9192e29a0ef39cce32b4aca5c8d11341695c7afa38f2f24eb0614316cf3cf34bfaf7ef0fc0a04137c8cfbfc6d0c1432829a9e49b5d452c5dfa1fc8b2cc638f491c3d7a948282db343434b807a856ab6b5a68d1a2457bde7befbdf9353535d783f17592a4517a3e9fd280f98090d11c50fea39593fba1b64a3d2d49cec7808ad0701bb5d51a92a411ec5497e7ac05c0f8f18f70ecd871366f5ec7af7f3d95010306208460d0a0419c3953c8d0c13d2929a964cfee22de7efb4d64d93573949b9bcbba75993cfdf404860f1fee55bf6116b76fdf4e464646fb89f3c58811c3193162b8575a42423cfbf7e761b78770e1c2351e78a09b975d1e397224050505ee7188c562415114962e5dba67f9f2e5f3333333af071a78faa22561efcc90a82a2aa4ac7c3ca7f61fa1ae5a392d49ba8bb4081bb555ad23cde84f4d4d0db22cd3a95327cc6633696923494b1be9b5129e9090c0b7dfe6bae5909414e7b52a9e9696465a5a9abb7ca0e0a33d3b0002469581101e6e66e5ca3f71eb5609191993bc26408d73d72c8c09455178f7dd77f7ac58b1627e5151d1751f5f477171719b3b0e6c70545c7df5d0dacfec92a49d86f691064d2f92c3e14051144c26d766205996ddff0622222cac5c994971b14b0e060c9f6e9842cfb19aa78c67cd9ad5aabe053d1c088469d3a606acd878305996a9abab63e5ca957b56ad5a355f0871ddb3ec92254bc8cccc6c55c77d317d8728dc9921758919f838a3a740f9b9239ccc81da2a154972b69a34dfe730846f987ccf41b02ccbfce21713dd323366f10dd2fc5992f66efe0d38e565369b3be400d72ea8575e7965c3aa55ab5eacafafbfded0d0e08e30df7cf34dde7efbed0edbcae032973d38b91feaaa953693e6cf8cf9ce58782e0eabaa8aa228288a82a6696e0df377af3fd2b66ddbd686a76d825be3eaebebdb254ccf0ebef6da6b6bb2b3b3ffbdb4b4b44151144f5fc7f2e5cb3b74ff89a3e22a87d67e86246980de664d332049925ba8cf3df71c005bb76ef5ba6e293fd8ebd668a16f59e96e7cf4b170e1c2ce999999d5d3a64dc366b301f0eebbefb262c50a2fd27cb7b9dd0f187d983c79f23b3b76ec78539224bf5b09ef372449a273e7ce2c5bb62c7bf1e2c573cc0b172e948410646565b160c102f7f2437b1a98376f1e1b376ef4f475ac5ab5ea9e9154121d4d6c69a081c49d21cbf2dddbd8e481400ba4069a6958e3b5d137b39168040b66b3b9ddc419fea2a4a484c58b17f3c5175ff8edcc3f33645946d3341c0e4750f23648d6755d0624b37153565616d0e1be8eececec7b6e0edba26dc6cbd6e625a856429665aaaaaa3877ee1c56abd53dce332259df0db02693899090100a0b0beb01cd6b006e90d751b81fa4b517f7923887c34174743483070f769b4e7ff2926519555559bd7af5f91d3b767c0054bb89bb1b1f37decb0f263dd11e1f772f2184409665ac56abd7e2a92f545565e3c68d17962d5bf63b87c371005f8dfb67474b014347c268c330d19edbf0dc0148e3b878cd9a353fbcf5d65b2f3b1c8e7d42085d92a4e03fb3fa29a13dda76af89337c9be78e2e5dd7b15aad343434f0c1071f9c5fba74e9ef1c0ec77e219a3e2cff5912d716b466f5b92360f8332320f124ce6c36535757c7faf5eb2f2c5ab4c820cd6b70795f3f25be5b28898ebedf5d080a9ec419e4812b82fce8a38f2ebcfefaebbf6d348fcd6604fe5fe37c702f4da5a7d6699a86c562c1e974f2f9e79fdf5cbd7af56287c371c8d33c7ae26749dc4fc5c719ed18df0fcab2cc975f7e59fcf2cb2fff6b7d7dfd2e2144c06d713f4be2da83fb419c2ccb288ac2279f7cf2c39a356b7edf1269f03325eea7328e03dc0bce5bb76e2d688c1e0fb5441adc07e28cc0c110ecddba6e2d244992434343dd03e27b81b0b030cacacad8b871e30f8b162d7ad9e170e408219c2ddf791f88f3d584bb7d1d2c144569c8ceceae976559ba1743035996a9a9a9e1d0a14317d6af5fff5a63c81f146900d24f6d2eb1a3e1e1cfecb83e4fb601f74a281250015c0682fbb0a111ff075b8fc771a1b0847a0000000049454e44ae426082</data> +    </image> +    <image name="image1"> +        <data format="PNG" length="5498">89504e470d0a1a0a0000000d494844520000006e0000002e0806000000c9032c970000154149444154789ced9b797014d79dc73fdd3df7a19991348390408045c469a4981b1b13c026ae0427c626c956eda61cb27f381b672b9baaddd42665cc5249586fd965c7760ec9a9d8e0d871126393908a8d09e6306064c020620e21400c022124746b46337dbefd6334c38c90401cb6e38abf552df5bc7efddeebf77dbfb35f4b555555828f183ff8c10f4a3b3b3bcf0208f191779f0349920058ba74e97ddffce637efefebeb4d0d4880b02c90012b55d7a27fac56aac01202a4545db010d9f5d23f520508ac5433a2ff4f76597f9dcc7d16a0f4979ba91aa60024453e7ab46e4f757575950de0a1871eba8953716554575763b7db4b841067d393f6714308c1030f3c70fbd2a55ffcbaddeeb8de56b2fe0f754e3fa1e9739159b822fbdc4aaf1d81b044eabf10b8dc41fef7b1ff2b065eb65dd3d0fa1b174260f5afba81e7831de96b81400000499244757535a150e85abaff50a14842bd11e11782ac67cd2ecbbd9efa2df5d795b2ee9306d421ab0c4cd3c2ee14481826e090af7fa8370ebbddfe7176ffc9844889f135495c7777378601922463b3d93873a69148244830180440d7753ef8a00eb7db85cd26535090df7f3e7837baaedff073fca362d8c40921686dbd4869e9185cae941db02c839e9e9e0c713535fb58b26471e69ea6a676b66eddcedd772fcea8d36cdc88c46d582e5502db8020b01658b16cfdf5ebbacb47f7f78d215565b6ed4a439224b2bd40c3b0325ed9debdfb59b0e07339f5376edcc0e4c913fbeb1a97f57183cec97d81b195c139dfdf80dd1bfc06f0c286e5d7df9e617c78d4f5f6f6a169faa08bf75aa19ba9ff434adceedd7bd034c8cb73327dfa6d08215014055d3770bb9d000861e1f57a3975aa8129536ec5e95432f76fdcb8894993c6535252826559396af166a948bb37c8c85b0e31ffeb5dec5ccb37f4246c582edd90e45d0fb217732cd6475b5b179aa6e376bbb02c8b4442c56e87c2c2104ea713594ec98ba6e9ecdf7f0cbfdf4b3299c4e773130e07f1f93c993ae9b64dd3cce97350e2b66fdfc1d4a99fa5b0308ffafab3ac5bf77be6cd9b8525941cf5e6f7fbd9b66d3753a64ca6a02090297ff7ddf7e9e8b8c08205cb10426018c68717afc5b7131801f3ff0576bec437f424951b964b0b81ae8f92c0f4f3e9ba4e414190bc3c6fe65a47470fc78e1dc3e9b461b7db339ae6f0e10666cf9e86d7eb02e0c28576dadabaa9a9394a45c52d8c185198697be0621f5455ba5c2ea2d1f30094978fe6eebbefa174dc38cacb4662532edde2f37ab9f3cecf5159392553d6dcdc464dcd4eeebfff7e002ccbc234cdcc0abae9b05247200cf3bf06762719db7723aaf35a910e7d4cd3c2b22e5f30f1781c555533049f3c7996d2d29119d2008a8a0a0885fc184692eeee0e20654e743da566b34dcba0123767ce6c7efdeb17292e8e1008f82829099238fe125d27b7e05bfc8bcc6d8aa2e0f57a72eefdcd6f5ee4c107ff396323755d4792a46bb2671b964b9f03be4bcaf1180a63814b31ae4891f7f96fc2ce57a9ec6e631bb070c3726958926759d6756985ec5835fdfb52d09d2ebbd4b61082aeae5e34cd64d4a8484e3d55d578fbed3de4e7cb39fe84611897cddf9036eeab5f5dc65b6fed64f9f22fd059bb8e50f716dc0bd6a02997881a591cceb967dfbea38c1c5984dbedc634cd413bccc650b64e086543f1ec7b83c13163c1accd2127fbf084c782519b913a2cb0db61fe7db0730395ddedd746de7071faf479eaea4e138904993cf9961cf5971b40a790ed93e8bac1b16351162e9c99f5bc00828d1bb7e1f3598442051416a6d4a4611858967599c61a92b8aeae6e66cd9d4db2691fa153bf80bb7e893074844d83feb4507b5b372eaf07af3b65f7cacbcbd8ba751baaaa66dab93ecf510acef9afa720fe59d0bbc0048c218e3e2e23d46e87f94b61e79fa9ecee601bb06cc372297a33c86b68680260d1a299ecd9f301afbcb289850ba7337264049bcd4667672f91c8c0b49940557584101c3c788239736ebd74a59fe8b7dfde871071f2f3f3894422f87cbe8c6d4bcf61f65ce6d0d8ddddcbf9f3ed1c3edc4043430b23471660edfe36c83da0352262b588ace4695bf3191a8fd6a0e9904868389d320b162c60fbf6fdecdb7784f7deaba5b3b3f39a5525005614acae1419d68063a0f40d72dd6e87f9f7402044257010a8bc1936eff0e1939494847138ec2c58701bf3e74fe70f7fd8caae5d07397cf8d4a0c90621c0e1f070e8d019cacbc7e0f5bafbcb536af6e8d1d3343737120af9894422040201ec767bc6a91b6cfe7288dbb5ab86a2a202a64cb9856995b792e8388747dd0f4a1dc4b7837932c72d55148d90f1175acf9e42d5a0a727cea851458c1fff19e6ce9dcd840953d8b7efc055891bf2da351035d875bb0de6df0545c57210a46da954fe8da1a0208f9a9a2399df858521962c99c3fcf9d3a9a828efb74db9f15ada568d193392d1a347f4dbffd4d1dadac9c183870887bd84c36142a1100e8723c7d45c91385dd751141bb20c92d4ef0daa71f0903a622f807404c3bc14486bba46d0f50e8ee655b477f6a16a267d7d494cd3e4d4a946fafa12c3724e06750aae83a8c1aecbc8148d7420843d28c4d0999ae13a27b7dd3691fdfb3fa0b1f1025d5d31baba7aa8ac9c4047470f275ffd1ad21bf730589cadeb3073e694ace47b2abedbb2e55df2f2140a0a0a282828c0e572653c49e0eac4c562311a1b1bf8e94f9f63fdfacd9c3c750e87271fdda54001e0ebc152fe8869a81806a81ae86607823d445c2fd377eae774f698c4e3090cc3a4adad87175f7c894993caaf4f55c2d0640d93485393397fd6c1df0e8210d25a216e5ce29c4e270b174ee7f5d7b7d2d4d4cad8b1c51cfb5b2dd6efa730deefc07fdf1f19e85586427e962c999b1532080cc362e3c61db85c060505f984c3617c3e1fb22ca3eb7a46450e850c719224f1d5af3ec0bdf72e261c76b273c726144f9884ff73e00342203c2134dd42d705aa069a6621fc4018c6eb8fd056bf9d589f496f6f1f8aa2505a5a96f1b8ae8bb8e19235f09a05a69e22edc05e300cd682b44296b56b1fc3004892c4e4c96594978f66ca945b387daa8150ed7f503cf7df61d1cf11b2eb32afd26eb761b7dbb0ac14699665d2d5d54b6beb455a5a7ac9cbcbc3ebf522cb32a6696662b6c18e346cd90302282c2ca4b0b090112346b0efc011668e5b45f2ecdbb8ca80d84c62bd3aaada466f6f0fba7e0e7b108883b0cf233f3489230d4d601944a3515a5a1a292e765356560690e36d5e0d7d172fe2d0e55c8f72807729239085b88c485397397fc6c181f7c030c41f8115b7cd9438b8ffe6bc468ac51254544c2099d4481efe35e312e760dc17a1bb0111d720303e535708c1c58b5df4f4c4282d2dea4f4808dc6e27b7dd36852d5bf6108f27b02c2be3fa0fb6c8878ce3065ed075835857373de5b763cfff3d1cfd36ae721bc1fc3a6cb6324a8adec7e6d80edd106f9a823ae1f734d65e20da1045513a98376f0693267d19bfdf9f69535152b9cc61bc15e8daf7b31f07fd058e4ba4644b5affff40a141598571b97a3ce3e0400d9886512bcbc60a80bf1d7471a3aa5208414b4b3bcdcd6d54549473fce04e269daf8611b320d690da6e909411796599d8ccb204c9a4ca3b3bdee3fe07eec16653300c13d3b49830612c0d0de73870e00489844924924f4141004551aeaaa132c4298a9213a937349ce74b5f5ac2a14327291cf1655c54d0f1fe4f0916fe055bc95c881d2671a619d3f628da98eff2d63b47282ef25358680079d4d7d7535f5f3fd4045c715492642c6baf3bf2ddf62b664ec4d8f0c48ab165730474d76624ada3d5c1d18329d224c9580874c9b20bc380075e4f0ed9da50ce89ae1b1c39728ae6e68bb4b474e0f57a282a2a484d6ce36fa0b3038a7b403d033610ba3bd3961016a669611826e3020d6cddb293858befe827ce44d70de6ce9dc65b6fd5609a360e1d8ad2d6d6452492c71d77dc8ac77329d9312c89dbbaf51d962efd129204e3c797f2dbdfbe41e9b852a64f7d82b6eea388fa2690e620e53d484b9f8fcdbf7d93b1a523a9ac9c485ddd7bdc7befbdd86c362ccbca3c84dd6ec7b22c56af5ebdb9b5b5b5e14ac42d5b2fb6bffe807dfb3d3ffb2d0efd9f0655977ffeb1f53fd802ab504891a6c974b43838b01be2bd59a4292e0c5d5c91b42ba1a3a31b97cbc1a245b37038529ae2fdf78f01201adf49d9ff9e0360cc00c012a17e5b662184d5af022dfcce0b947863d4d6869930610c8691224e089832a58c8e8e1eeeba6b168661b2756b0d6d6d6d9496960e39ae4189f3f9dc6cdbb693891327f3dc73bfc2e7938944a0ead7dbb975da3c02c109689ace9e3fbd4daca791c58befe0c489e3bcfa6a2700e170785075b86ad5aa2d555555ff9a4c265bd7ae5d7bd549dbf7b31f33a4baa49f886cd27642bc279734d33090e5cbdf050e17ba6ee0f77b33a4c1a5fd237629095ec09584f657a1682ea0f62f5813cb4a798fa6698068a73cd2c8b1fd161de115381c0e745def6fdf43347a9ebaba28e3c615a3aa0962b1580e27c392b8f9f3ef60dfbefdac5d5bcd57bef205264c9800c0d4a9e73972e42c9f9d56c1c58bddfc755313ab57ff10599659b85062cf9e3dd4d7b7914c263381bac3914affac5cb972cb9a356b56c462b173c3b1759264d05e7784f621af0342c650a1f38283033b20dea3d74a92b910e8f2f85cc47b0d24c960b8a9aeb4bb9e3d17866170f8f069dadb7b2829091308f8323196092989f3034a33a86f20a4b91886d94f58ca96e9ba8910a7207188cf8fd8c8baed6398b76011baaea3693aaaaa535a3a929a9a0f3870e018f1782fe5e545c3236e2066ce9cc1cc993372ca4a4a8ad9b1631fc1a09b1327ce327af4889ce4e7ac59b3a8afafcfc42176bb1d4dd358bd7af596c71e7b6c455555d5b9975e7a2967a286c2d5267bc372899ea6281d9d0b38b8e35dfa7ab55a49b252a4f95dc47bae8db4f47862b118b22ce3743ab1d96c8c1a358296968becdd7b8053a79a48262deebcf3368400dd3f013c6753090a3fe04b226227310c0b5d37fadf8e182995289f01571c5700ee8eac66776d316565a35155ad9f3c8dd1a38b387ab49e193346e3743aaf38d621bdcaa1e0f3d978e2895fd2d27291e5cb3f9f93004d9fa7b2300a9aa6f1939ffc64cbe38f3fbea2a9a9e9dc005b476b6bebb0277510ac55bb1abfbbebb997839264d4c28d9106971692aaaa689a86a228c8b2ccf8f1a3894402cc9e3d894422c1e9d3eda8aa86145e8c2eb660f792923c1f08358069a6c84aa7ad745d47764aa93a26dc12394fedfb3fe382f7fb389d2995994c6ae8ba4e7e7e8868b483f1e3c75fbbaabc12eebbefde41cb2549ca489f2ccbf4f5f5f1c4134f6c79f2c927570821ce65d75db56a15555555c3ea6f282c5b2fa21b964ba1c2c98b98bb143a8fbdcb81ed10efd19124f39a491bf81ca90c879951f93e9f0fa7d389699ac4e32667cfb65072fbc39c5dff14b78c6b053760cf03a9045d33d1753de380689a8ec3e64bd55101274c0eaabc113d47696909aaaa914caa24931af17882e6e6362a2bbb183d7a74ceb8b29121ce66b3ddd0f6024992329b612e5ebcc8a38f3ebaf6b5d75e7b249148342593c96c5bc79a356bae9ad2192e06a84b24c9ba2ed206db189586a22828caa56d1b93268d63f7eec32c59328fbecf3c4b4fe3d7c88b48a0e423a40867cfb6108d9ea7a7bb1387a31b35719cb99536b02b6037397fc28967f61aa69e879a9a0f70b91cc46271ec764138ec63dab4a9b8dd578e7533c42512891b262efdb0dffbdef79edebc79f37fb7b7b727354dcbb6753cf6d8633775ff89dad5c8aee75e46920ce0fa48cbc670d27389848e65a5c2823973be4c74cb4a8c236bc89fee62444441b30e533062066ea70f97bd15cce65428a3cbb41eb3a14dde80e519454dcd9b4812381c0633668cc2e7f3e1f57af1783cf8fdfeababcaeaeaea1b7ad881d8bc79f3caaaaaaae4005bc7e38f3f7e5349fba87773413a208f72c71d951c3f1ee5fdf7ebf8eca21f12dd5bc1c53ffc276316b732fe9638d862a91b8c38584962d15e5a8f4ec236b90ad3338a975f7a83b2b252c2e1207bf71e22180c52545484cfe7c3e1700cb989380ddbb7bef52d4908417575350f3df4109aa6ddb0e43df8e083ac5bb72edbd6f1e4934f7eec5fe60c07b22c5f7163d3c993e7282d1d4928e467f6eca9ecde7d88b7dedac3bc790b51a61e205af322e6aefdb8f38ee00a87e96bacc73083d84b7e8cf3f6bb696ebec89b1b52a4cd993315d3141c3f7e86baba26c68e1d8bdfef4796e5cb242cfd3b3d365bba30ed2c7c08b68ed75e7b2da7f34f2ababa7a89c5542a2a2666623e97cbc9a64dbb3975aa91a9533fc3b8cfdc47b8e01b5896891002dfb8d4a6a933679a39f0a7ed44a38d949414535e3e3af3a6e0f6db2b79fef9d799366d5c7f9baecbfa4eab70cbb26440b2a5494aabcb9b6cebd8bc79f32742d2d28bed4a362e10f0a169492e5ce8c0eff7b07efd5f696838cdd4a9c5141515d0d6769ea347eb89c7351c0e278a22d1dd1da7bbbb07b75ba1ac2cc25d77dd8aaec3b66dfb2829194138ace0703858b66c16bdbdbd747575e578b369288a82dbed261a8d26002347917e08b6ee13415a36ae449c2ccb4c9f3e814d9bdee5f8f1b31417fb59b4e85682c120a15088f2723badad1d3435f5306fde342ccb4255759e79e6156ebfbd9cc2c242f2f3f3713a9d8c19338a37dfdccdc489d399366d5ac6cb1e6cbed22f579f7aeaa9baf5ebd73f0bf46688fb303e6efc283f98fc282049126eb79bc58b67525131ae7fdbb88f502884d7eb4551140281007bf7fe359364eee8e8c1b2343c1e0f914884c2c2421445213f3f9f050b2a90651987c391f3f27420745d67ddba75277ef4a31f7d4755d577182871ffe8186a4755366c361b81400097cb856118381c0e1c0e47c66970b95cc8f2a5d744a74f9f2714f2e076bbf17abd9978d6e17010080488c7e30039dbf0320e48bf67f9f4d34f1f7fe491471e5655759b10c2922469f89f59fda36038719ccd661bd25d972489bc3c2f7bf71e2114f2535f1f251209e0f1787236ce4a9284a22899ad0ad93bba2ccbc2e170904c2679f6d967eb56af5efd1d55557788aced631feb17a97f4fb8199f40a5b178f10cfc7e85d6d67394947899366d3c7ebf3f236d70e993b5f4b7158661640e21047d7d7dfcea57bf3ab172e5caefc4e3f11d42889c77539f4adc8780fcfc2077de39fbaaf5b2894b7b9176bb1d455178e699674eac5ab5eadb69f538f0de4f891b80ebde91769dfda4c9330c03bbdd8e699abcf2ca2bcd4f3df5d4a3aaaaee1a8c34f894b8cbf051130764d4a32ccbbcfefaebad0f3ffcf0bf2512894d428821b7c57d4adc007c1cc4c9b28ca6693cfffcf3c79f7efae9ffb91a69f029711f3bd249f8dffdee77f5fddee3aeab91069f1297812449b2c7e3c904c41f05bc5e2f1d1d1dac5bb7eef8ca952b1f565575bb10c2bcfa9d9f129781a669c9cd9b37276459966e66683014645926168bb16bd7ae132fbcf0c2f7fae3b4619106207dd27289371b59f62c48eaf3641703bfdaf810bb07ba8006e09a3e6cf87fd8857d4933e0288e0000000049454e44ae426082</data> +    </image> +    <image name="image2"> +        <data format="PNG" length="1002">89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b000003b149444154388dad945f4c5b551cc73fe7dc4b7b4bcba0762d45c43114323599ee6192609c51d883892ce083f1718b3ebb185f8dc91e972cf39d2d2a2f1af664b6f1e0fe3863a0718969700eb0c52142da0242a1bd6d696f7bcff101585203ceb8fd9ece39f99dcff9fe7edf939f88c562ec465f5f9fe609442c161362173c3e3eae7b7a7ac8e7f36432196cdbfe4f907c3e4f2291201e8fe338cec3737357e9e8e828aded1e229d650e1f2d51754b082110124c13a4dc5ea341eb9dc284c0558a853f3ce8cb0677ef500fde7d39d2596679e326597b8e9abb85d7a770ab16ab6983ec5a05b487a70e36f0f4e10afe408d6a558310980108478dba4a1e8233990c5d474b64ed39aa3a8fe5f3317fbf81dbd70bccfeb205947632fd74f6589c1c6ea2f70d03a58ba0c1f2c9bdc1b66de3b8256a6e11cbe7e3ee1d181b590124fe2693aeee08d223c82c3a2c24b7b874bec8f26288774f7bd054504aef0dde6e99c0eb83f9fb266323cb80a27fb0958141836044605a2ee5523393371cc646fee2da37195aa35d0c0c5b4859ac03d7e91712dcaac5adab3650a3ff9d08ef7dd8404bb48869e5d958b5b87dadc4c9a1464e9f0d0326df7ebd86bd2e310cb1bf62d384d59441f2d70a070e1c60e09489929b988681bdd9cc97170bcc4c65595f71f8e0e3301337fc24a7732467831875a47f289652b0be5e4151e6d07316c1b0c0340d8ab92023e76d66a6b2840e36d2fb7a13fee632475e6edc367ea98a90fb98b7dd6310ca0328a44761582e1bab41befabcc0ec940d28bc5e93b68e064cab84e1d9beaeb48934eac1f53b01c1b000fca496aa54b61a99fcde61662a4b4b4b23d1680be9d426173e4df3602a48ea411989a4fd590f52a8fd156b05ed9d350e3defe3cfdf4b4c7ce770ea7d3fb9f520afbe1620daeee5c26735d20b9b9cfb6811a754a439e4e5c5639a4caa1e5caf586bfc0197b78702005cb9b4cae4cd3267ce8638fe964bd72b393e39d74928d242617303a756a37f284447770dcdbffc6384a05a85de1306e9a52057c7527c7131c3c42d3f475eb2303c82d4fc3276d6811db37efeb148723082d9b08f79f97c1e5729109a9a28307cc622d2d6cdf52b2b24efe548dedb00142009862cfa879ee1a71f6cec928353511472fbf4389148b0b0e0c108081412458dfe21c9f11351e67e7358595468246d1d1e5e38a6e9e851bc39d84ab502a669331dafec0d8ec7e3e8cb06e1a881d727d1ae40180a434a8c9db129a54126ad48a7358c2b4c5352c8c374bcccdab2bb37d8719cba79fab8211f9df218e0582c261e95f8bfc04f1a1e8bc5c4dfe0a190172af6a9690000000049454e44ae426082</data> +    </image> +</images> +<tabstops> +    <tabstop>intWidth</tabstop> +    <tabstop>intHeight</tabstop> +    <tabstop>intWidthPercent</tabstop> +    <tabstop>intHeightPercent</tabstop> +    <tabstop>chkConstrain</tabstop> +    <tabstop>radioScale</tabstop> +</tabstops> +<layoutdefaults spacing="6" margin="11"/> +<includehints> +    <includehint>knuminput.h</includehint> +</includehints> +</UI> diff --git a/krita/plugins/viewplugins/imagesize/wdg_layersize.ui b/krita/plugins/viewplugins/imagesize/wdg_layersize.ui new file mode 100644 index 000000000..1b642fd8d --- /dev/null +++ b/krita/plugins/viewplugins/imagesize/wdg_layersize.ui @@ -0,0 +1,234 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>WdgLayerSize</class> +<widget class="QWidget"> +    <property name="name"> +        <cstring>WdgLayerSize</cstring> +    </property> +    <property name="geometry"> +        <rect> +            <x>0</x> +            <y>0</y> +            <width>391</width> +            <height>224</height> +        </rect> +    </property> +    <property name="caption"> +        <string>Image Size</string> +    </property> +    <grid> +        <property name="name"> +            <cstring>unnamed</cstring> +        </property> +        <property name="margin"> +            <number>0</number> +        </property> +        <widget class="QButtonGroup" row="0" column="0" rowspan="1" colspan="2"> +            <property name="name"> +                <cstring>grpPixelDimensions</cstring> +            </property> +            <property name="title"> +                <string>&Pixel Dimensions</string> +            </property> +            <grid> +                <property name="name"> +                    <cstring>unnamed</cstring> +                </property> +                <widget class="QLabel" row="0" column="1"> +                    <property name="name"> +                        <cstring>lblWidth</cstring> +                    </property> +                    <property name="text"> +                        <string>&Width:</string> +                    </property> +                    <property name="buddy" stdset="0"> +                        <cstring>intWidth</cstring> +                    </property> +                </widget> +                <widget class="KIntNumInput" row="2" column="2"> +                    <property name="name"> +                        <cstring>intHeight</cstring> +                    </property> +                    <property name="minValue"> +                        <number>0</number> +                    </property> +                </widget> +                <widget class="QLabel" row="0" column="2"> +                    <property name="name"> +                        <cstring>textLabel2</cstring> +                    </property> +                    <property name="text"> +                        <string>&Height:</string> +                    </property> +                    <property name="buddy" stdset="0"> +                        <cstring>intHeight</cstring> +                    </property> +                </widget> +                <widget class="QLabel" row="1" column="1"> +                    <property name="name"> +                        <cstring>lblWidthOriginal</cstring> +                    </property> +                    <property name="frameShape"> +                        <enum>WinPanel</enum> +                    </property> +                    <property name="frameShadow"> +                        <enum>Sunken</enum> +                    </property> +                    <property name="text"> +                        <string></string> +                    </property> +                    <property name="alignment"> +                        <set>AlignVCenter|AlignRight</set> +                    </property> +                </widget> +                <widget class="QLabel" row="1" column="2"> +                    <property name="name"> +                        <cstring>lblHeightOriginal</cstring> +                    </property> +                    <property name="frameShape"> +                        <enum>WinPanel</enum> +                    </property> +                    <property name="frameShadow"> +                        <enum>Sunken</enum> +                    </property> +                    <property name="text"> +                        <string></string> +                    </property> +                    <property name="alignment"> +                        <set>AlignVCenter|AlignRight</set> +                    </property> +                </widget> +                <widget class="QLabel" row="1" column="0"> +                    <property name="name"> +                        <cstring>lblOrignal</cstring> +                    </property> +                    <property name="text"> +                        <string>Original:</string> +                    </property> +                </widget> +                <widget class="QLabel" row="2" column="0"> +                    <property name="name"> +                        <cstring>lblNew</cstring> +                    </property> +                    <property name="text"> +                        <string>&New:</string> +                    </property> +                    <property name="buddy" stdset="0"> +                        <cstring>intWidth</cstring> +                    </property> +                </widget> +                <widget class="KIntNumInput" row="2" column="1"> +                    <property name="name"> +                        <cstring>intWidth</cstring> +                    </property> +                    <property name="minValue"> +                        <number>0</number> +                    </property> +                </widget> +                <widget class="KIntNumInput" row="3" column="1"> +                    <property name="name"> +                        <cstring>intWidthPercent</cstring> +                    </property> +                    <property name="value"> +                        <number>100</number> +                    </property> +                    <property name="minValue"> +                        <number>0</number> +                    </property> +                    <property name="referencePoint"> +                        <number>100</number> +                    </property> +                    <property name="suffix"> +                        <string>%</string> +                    </property> +                </widget> +                <widget class="KIntNumInput" row="3" column="2"> +                    <property name="name"> +                        <cstring>intHeightPercent</cstring> +                    </property> +                    <property name="value"> +                        <number>100</number> +                    </property> +                    <property name="minValue"> +                        <number>0</number> +                    </property> +                    <property name="suffix"> +                        <string>%</string> +                    </property> +                </widget> +                <widget class="QLabel" row="3" column="0"> +                    <property name="name"> +                        <cstring>lblPercent</cstring> +                    </property> +                    <property name="text"> +                        <string>&Percent:</string> +                    </property> +                    <property name="buddy" stdset="0"> +                        <cstring>intWidthPercent</cstring> +                    </property> +                </widget> +                <widget class="QCheckBox" row="4" column="0" rowspan="1" colspan="3"> +                    <property name="name"> +                        <cstring>chkConstrain</cstring> +                    </property> +                    <property name="text"> +                        <string>&Constrain proportions</string> +                    </property> +                    <property name="checked"> +                        <bool>true</bool> +                    </property> +                </widget> +            </grid> +        </widget> +        <widget class="QLabel" row="1" column="0"> +            <property name="name"> +                <cstring>lblFilterType</cstring> +            </property> +            <property name="text"> +                <string>&Filter:</string> +            </property> +            <property name="buddy" stdset="0"> +                <cstring>cmbFilterType</cstring> +            </property> +        </widget> +        <widget class="KisCmbIDList" row="1" column="1"> +            <property name="name"> +                <cstring>cmbFilterType</cstring> +            </property> +        </widget> +    </grid> +</widget> +<customwidgets> +    <customwidget> +        <class>KisCmbIDList</class> +        <header location="local">kis_cmb_idlist.h</header> +        <sizehint> +            <width>1</width> +            <height>24</height> +        </sizehint> +        <container>0</container> +        <sizepolicy> +            <hordata>5</hordata> +            <verdata>5</verdata> +            <horstretch>0</horstretch> +            <verstretch>0</verstretch> +        </sizepolicy> +        <pixmap>image0</pixmap> +    </customwidget> +</customwidgets> +<images> +    <image name="image0"> +        <data format="PNG" length="1002">89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b000003b149444154388dad945f4c5b551cc73fe7dc4b7b4bcba0762d45c43114323599ee6192609c51d883892ce083f1718b3ebb185f8dc91e972cf39d2d2a2f1af664b6f1e0fe3863a0718969700eb0c52142da0242a1bd6d696f7bcff101585203ceb8fd9ece39f99dcff9fe7edf939f88c562ec465f5f9fe609442c161362173c3e3eae7b7a7ac8e7f36432196cdbfe4f907c3e4f2291201e8fe338cec3737357e9e8e828aded1e229d650e1f2d51754b082110124c13a4dc5ea341eb9dc284c0558a853f3ce8cb0677ef500fde7d39d2596679e326597b8e9abb85d7a770ab16ab6983ec5a05b487a70e36f0f4e10afe408d6a558310980108478dba4a1e8233990c5d474b64ed39aa3a8fe5f3317fbf81dbd70bccfeb205947632fd74f6589c1c6ea2f70d03a58ba0c1f2c9bdc1b66de3b8256a6e11cbe7e3ee1d181b590124fe2693aeee08d223c82c3a2c24b7b874bec8f26288774f7bd054504aef0dde6e99c0eb83f9fb266323cb80a27fb0958141836044605a2ee5523393371cc646fee2da37195aa35d0c0c5b4859ac03d7e91712dcaac5adab3650a3ff9d08ef7dd8404bb48869e5d958b5b87dadc4c9a1464e9f0d0326df7ebd86bd2e310cb1bf62d384d59441f2d70a070e1c60e09489929b988681bdd9cc97170bcc4c65595f71f8e0e3301337fc24a7732467831875a47f289652b0be5e4151e6d07316c1b0c0340d8ab92023e76d66a6b2840e36d2fb7a13fee632475e6edc367ea98a90fb98b7dd6310ca0328a44761582e1bab41befabcc0ec940d28bc5e93b68e064cab84e1d9beaeb48934eac1f53b01c1b000fca496aa54b61a99fcde61662a4b4b4b23d1680be9d426173e4df3602a48ea411989a4fd590f52a8fd156b05ed9d350e3defe3cfdf4b4c7ce770ea7d3fb9f520afbe1620daeee5c26735d20b9b9cfb6811a754a439e4e5c5639a4caa1e5caf586bfc0197b78702005cb9b4cae4cd3267ce8638fe964bd72b393e39d74928d242617303a756a37f284447770dcdbffc6384a05a85de1306e9a52057c7527c7131c3c42d3f475eb2303c82d4fc3276d6811db37efeb148723082d9b08f79f97c1e5729109a9a28307cc622d2d6cdf52b2b24efe548dedb00142009862cfa879ee1a71f6cec928353511472fbf4389148b0b0e0c108081412458dfe21c9f11351e67e7358595468246d1d1e5e38a6e9e851bc39d84ab502a669331dafec0d8ec7e3e8cb06e1a881d727d1ae40180a434a8c9db129a54126ad48a7358c2b4c5352c8c374bcccdab2bb37d8719cba79fab8211f9df218e0582c261e95f8bfc04f1a1e8bc5c4dfe0a190172af6a9690000000049454e44ae426082</data> +    </image> +</images> +<tabstops> +    <tabstop>intWidth</tabstop> +    <tabstop>intHeight</tabstop> +    <tabstop>intWidthPercent</tabstop> +    <tabstop>intHeightPercent</tabstop> +    <tabstop>chkConstrain</tabstop> +</tabstops> +<layoutdefaults spacing="6" margin="11"/> +<includehints> +    <includehint>knuminput.h</includehint> +</includehints> +</UI> diff --git a/krita/plugins/viewplugins/imagesize/wdg_resolution.ui b/krita/plugins/viewplugins/imagesize/wdg_resolution.ui new file mode 100644 index 000000000..ead018192 --- /dev/null +++ b/krita/plugins/viewplugins/imagesize/wdg_resolution.ui @@ -0,0 +1,152 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>WdgResolution</class> +<widget class="QWidget"> +    <property name="name"> +        <cstring>WdgResolution</cstring> +    </property> +    <property name="geometry"> +        <rect> +            <x>0</x> +            <y>0</y> +            <width>487</width> +            <height>265</height> +        </rect> +    </property> +    <property name="caption"> +        <string>Image Resolution</string> +    </property> +    <grid> +        <property name="name"> +            <cstring>unnamed</cstring> +        </property> +        <widget class="QGroupBox" row="1" column="0" rowspan="1" colspan="2"> +            <property name="name"> +                <cstring>grpSize</cstring> +            </property> +            <property name="title"> +                <string>Print Size</string> +            </property> +            <grid> +                <property name="name"> +                    <cstring>unnamed</cstring> +                </property> +                <widget class="QLabel" row="1" column="0"> +                    <property name="name"> +                        <cstring>lblHeight</cstring> +                    </property> +                    <property name="text"> +                        <string>Height:</string> +                    </property> +                </widget> +                <widget class="QLabel" row="0" column="0"> +                    <property name="name"> +                        <cstring>lblWidth</cstring> +                    </property> +                    <property name="text"> +                        <string>Width:</string> +                    </property> +                </widget> +                <widget class="KIntNumInput" row="0" column="1"> +                    <property name="name"> +                        <cstring>intWidth</cstring> +                    </property> +                    <property name="suffix"> +                        <string> "</string> +                    </property> +                </widget> +                <widget class="KIntNumInput" row="1" column="1"> +                    <property name="name"> +                        <cstring>intHeight</cstring> +                    </property> +                    <property name="suffix"> +                        <string> "</string> +                    </property> +                </widget> +            </grid> +        </widget> +        <widget class="QGroupBox" row="0" column="0" rowspan="1" colspan="2"> +            <property name="name"> +                <cstring>grpResolution</cstring> +            </property> +            <property name="title"> +                <string>Image Resolution</string> +            </property> +            <grid> +                <property name="name"> +                    <cstring>unnamed</cstring> +                </property> +                <widget class="QLabel" row="0" column="0"> +                    <property name="name"> +                        <cstring>lblScreen</cstring> +                    </property> +                    <property name="text"> +                        <string>Screen resolution:</string> +                    </property> +                </widget> +                <widget class="QLabel" row="0" column="1"> +                    <property name="name"> +                        <cstring>lblScreenResolution</cstring> +                    </property> +                    <property name="frameShape"> +                        <enum>Panel</enum> +                    </property> +                    <property name="frameShadow"> +                        <enum>Sunken</enum> +                    </property> +                    <property name="text"> +                        <string>100</string> +                    </property> +                    <property name="alignment"> +                        <set>AlignVCenter|AlignRight</set> +                    </property> +                </widget> +                <widget class="QLabel" row="2" column="0"> +                    <property name="name"> +                        <cstring>lblYResolution</cstring> +                    </property> +                    <property name="text"> +                        <string>Image Y resolution:</string> +                    </property> +                </widget> +                <widget class="QLabel" row="1" column="0"> +                    <property name="name"> +                        <cstring>lblImageXRes</cstring> +                    </property> +                    <property name="text"> +                        <string>Image X resolution:</string> +                    </property> +                </widget> +                <widget class="KIntNumInput" row="1" column="1"> +                    <property name="name"> +                        <cstring>intXRes</cstring> +                    </property> +                    <property name="suffix"> +                        <string> dpi</string> +                    </property> +                </widget> +                <widget class="KIntNumInput" row="2" column="1"> +                    <property name="name"> +                        <cstring>intYRes</cstring> +                    </property> +                    <property name="suffix"> +                        <string> dpi</string> +                    </property> +                </widget> +            </grid> +        </widget> +    </grid> +</widget> +<customwidgets> +</customwidgets> +<layoutdefaults spacing="6" margin="11"/> +<includehints> +    <includehint>knuminput.h</includehint> +    <includehint>knuminput.h</includehint> +    <includehint>knuminput.h</includehint> +    <includehint>knuminput.h</includehint> +    <includehint>knuminput.h</includehint> +    <includehint>knuminput.h</includehint> +    <includehint>knuminput.h</includehint> +    <includehint>knuminput.h</includehint> +</includehints> +</UI> diff --git a/krita/plugins/viewplugins/modify_selection/Makefile.am b/krita/plugins/viewplugins/modify_selection/Makefile.am new file mode 100644 index 000000000..f70b7cf24 --- /dev/null +++ b/krita/plugins/viewplugins/modify_selection/Makefile.am @@ -0,0 +1,26 @@ +kritarcdir = $(kde_datadir)/kritaplugins +kritarc_DATA = modify_selection.rc +EXTRA_DIST = $(kritarc_DATA) + +kde_services_DATA = kritamodifyselection.desktop + + +INCLUDES  =  -I$(srcdir)/../../../sdk \ +	-I$(srcdir)/../../../core \ +	-I$(srcdir)/../../../kritacolor/ \ +	-I$(srcdir)/../../../ui \ +	$(KOFFICE_INCLUDES) \ +	$(all_includes) + +kritamodifyselection_la_SOURCES = wdg_grow_selection.ui wdg_shrink_selection.ui wdg_border_selection.ui \ +dlg_grow_selection.cc dlg_shrink_selection.cc dlg_border_selection.cc modify_selection.cc + +noinst_HEADERS = wdg_grow_selection.h wdg_shrink_selection.h wdg_border_selection.h dlg_grow_selection.h \ +dlg_shrink_selection.h dlg_border_selection.h modify_selection.h + +kde_module_LTLIBRARIES = kritamodifyselection.la + +kritamodifyselection_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) +kritamodifyselection_la_LIBADD =  ../../../libkritacommon.la  + +kritamodifyselection_la_METASOURCES = AUTO diff --git a/krita/plugins/viewplugins/modify_selection/dlg_border_selection.cc b/krita/plugins/viewplugins/modify_selection/dlg_border_selection.cc new file mode 100644 index 000000000..748c5b9b4 --- /dev/null +++ b/krita/plugins/viewplugins/modify_selection/dlg_border_selection.cc @@ -0,0 +1,76 @@ +/* + *  dlg_border_selection.cc - part of Krita + * + *  Copyright (c) 2006 Michael Thaler <michael.thaler@physik.tu-muenchen.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 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 <config.h> + +#include <math.h> + +#include <iostream> + +using namespace std; + +#include <qradiobutton.h> +#include <qcheckbox.h> +#include <qbuttongroup.h> +#include <qlabel.h> +#include <qcombobox.h> + +#include <klocale.h> +#include <knuminput.h> +#include <kdebug.h> + +#include "dlg_border_selection.h" +#include "wdg_border_selection.h" + +DlgBorderSelection::DlgBorderSelection( QWidget *  parent, const char * name) : super (parent, name, true, i18n("Border Selection"), Ok | Cancel, Ok) +{ +    m_page = new WdgBorderSelection(this, "border_selection"); +    Q_CHECK_PTR(m_page); + +    setMainWidget(m_page); +    resize(m_page->sizeHint()); + +    connect(this, SIGNAL(okClicked()), this, SLOT(okClicked())); +} + +DlgBorderSelection::~DlgBorderSelection() +{ +    delete m_page; +} + +Q_INT32 DlgBorderSelection::xradius() +{ +    return m_page->radiusSpinBox->value(); +} + +Q_INT32 DlgBorderSelection::yradius() +{ +    return m_page->radiusSpinBox->value(); +} + + +// SLOTS + +void DlgBorderSelection::okClicked() +{ +    accept(); +} + +#include "dlg_border_selection.moc" diff --git a/krita/plugins/viewplugins/modify_selection/dlg_border_selection.h b/krita/plugins/viewplugins/modify_selection/dlg_border_selection.h new file mode 100644 index 000000000..baf716d47 --- /dev/null +++ b/krita/plugins/viewplugins/modify_selection/dlg_border_selection.h @@ -0,0 +1,48 @@ +/* + *  dlg_border_selection.h -- part of Krita + * + *  Copyright (c) 2006 Michael Thaler <michael.thaler@physik.tu-muenchen.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 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. + */ +#ifndef DLG_BORDER_SELECTION_H +#define DLG_BORDER_SELECTION_H + +#include <kdialogbase.h> + +class WdgBorderSelection; + +class DlgBorderSelection: public KDialogBase { +    typedef KDialogBase super; +    Q_OBJECT + +public: + +    DlgBorderSelection(QWidget * parent = 0, const char* name = 0); +    ~DlgBorderSelection(); + +    Q_INT32 xradius(); +    Q_INT32 yradius(); + +private slots: + +    void okClicked(); + +private: + +    WdgBorderSelection * m_page; +}; + +#endif // DLG_BORDER_SELECTION_H diff --git a/krita/plugins/viewplugins/modify_selection/dlg_grow_selection.cc b/krita/plugins/viewplugins/modify_selection/dlg_grow_selection.cc new file mode 100644 index 000000000..82055aeb1 --- /dev/null +++ b/krita/plugins/viewplugins/modify_selection/dlg_grow_selection.cc @@ -0,0 +1,76 @@ +/* + *  dlg_grow_selection.cc - part of Krita + * + *  Copyright (c) 2006 Michael Thaler <michael.thaler@physik.tu-muenchen.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 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 <config.h> + +#include <math.h> + +#include <iostream> + +using namespace std; + +#include <qradiobutton.h> +#include <qcheckbox.h> +#include <qbuttongroup.h> +#include <qlabel.h> +#include <qcombobox.h> + +#include <klocale.h> +#include <knuminput.h> +#include <kdebug.h> + +#include "dlg_grow_selection.h" +#include "wdg_grow_selection.h" + +DlgGrowSelection::DlgGrowSelection( QWidget *  parent, const char * name) : super (parent, name, true, i18n("Grow Selection"), Ok | Cancel, Ok) +{ +    m_page = new WdgGrowSelection(this, "grow_selection"); +    Q_CHECK_PTR(m_page); + +    setMainWidget(m_page); +    resize(m_page->sizeHint()); + +    connect(this, SIGNAL(okClicked()), this, SLOT(okClicked())); +} + +DlgGrowSelection::~DlgGrowSelection() +{ +    delete m_page; +} + +Q_INT32 DlgGrowSelection::xradius() +{ +    return m_page->radiusSpinBox->value(); +} + +Q_INT32 DlgGrowSelection::yradius() +{ +    return m_page->radiusSpinBox->value(); +} + + +// SLOTS + +void DlgGrowSelection::okClicked() +{ +    accept(); +} + +#include "dlg_grow_selection.moc" diff --git a/krita/plugins/viewplugins/modify_selection/dlg_grow_selection.h b/krita/plugins/viewplugins/modify_selection/dlg_grow_selection.h new file mode 100644 index 000000000..f5cd36ffa --- /dev/null +++ b/krita/plugins/viewplugins/modify_selection/dlg_grow_selection.h @@ -0,0 +1,48 @@ +/* + *  dlg_grow_selection.h -- part of Krita + * + *  Copyright (c) 2006 Michael Thaler <michael.thaler@physik.tu-muenchen.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 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. + */ +#ifndef DLG_GROW_SELECTION_H +#define DLG_GROW_SELECTION_H + +#include <kdialogbase.h> + +class WdgGrowSelection; + +class DlgGrowSelection: public KDialogBase { +    typedef KDialogBase super; +    Q_OBJECT + +public: + +    DlgGrowSelection(QWidget * parent = 0, const char* name = 0); +    ~DlgGrowSelection(); + +    Q_INT32 xradius(); +    Q_INT32 yradius(); + +private slots: + +    void okClicked(); + +private: + +    WdgGrowSelection * m_page; +}; + +#endif // DLG_GROW_SELECTION_H diff --git a/krita/plugins/viewplugins/modify_selection/dlg_shrink_selection.cc b/krita/plugins/viewplugins/modify_selection/dlg_shrink_selection.cc new file mode 100644 index 000000000..69e31d1d2 --- /dev/null +++ b/krita/plugins/viewplugins/modify_selection/dlg_shrink_selection.cc @@ -0,0 +1,81 @@ +/* + *  dlg_shrink_selection.cc - part of Krita + * + *  Copyright (c) 2006 Michael Thaler <michael.thaler@physik.tu-muenchen.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 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 <config.h> + +#include <math.h> + +#include <iostream> + +using namespace std; + +#include <qradiobutton.h> +#include <qcheckbox.h> +#include <qbuttongroup.h> +#include <qlabel.h> +#include <qcombobox.h> + +#include <klocale.h> +#include <knuminput.h> +#include <kdebug.h> + +#include "dlg_shrink_selection.h" +#include "wdg_shrink_selection.h" + +DlgShrinkSelection::DlgShrinkSelection( QWidget *  parent, const char * name) : super (parent, name, true, i18n("Shrink Selection"), Ok | Cancel, Ok) +{ +    m_page = new WdgShrinkSelection(this, "shrink_selection"); +    Q_CHECK_PTR(m_page); + +    setMainWidget(m_page); +    resize(m_page->sizeHint()); + +    connect(this, SIGNAL(okClicked()), this, SLOT(okClicked())); +} + +DlgShrinkSelection::~DlgShrinkSelection() +{ +    delete m_page; +} + +Q_INT32 DlgShrinkSelection::xradius() +{ +    return m_page->radiusSpinBox->value(); +} + +Q_INT32 DlgShrinkSelection::yradius() +{ +    return m_page->radiusSpinBox->value(); +} + +bool DlgShrinkSelection::shrinkFromImageBorder() +{ +    return m_page->shrinkFromImageBorderCheckBox->isChecked(); +} + + +// SLOTS + +void DlgShrinkSelection::okClicked() +{ +    accept(); +} + +#include "dlg_shrink_selection.moc" diff --git a/krita/plugins/viewplugins/modify_selection/dlg_shrink_selection.h b/krita/plugins/viewplugins/modify_selection/dlg_shrink_selection.h new file mode 100644 index 000000000..e8e32f43e --- /dev/null +++ b/krita/plugins/viewplugins/modify_selection/dlg_shrink_selection.h @@ -0,0 +1,49 @@ +/* + *  dlg_shrink_selection.h -- part of Krita + * + *  Copyright (c) 2006 Michael Thaler <michael.thaler@physik.tu-muenchen.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 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. + */ +#ifndef DLG_SHRINK_SELECTION_H +#define DLG_SHRINK_SELECTION_H + +#include <kdialogbase.h> + +class WdgShrinkSelection; + +class DlgShrinkSelection: public KDialogBase { +    typedef KDialogBase super; +    Q_OBJECT + +public: + +    DlgShrinkSelection(QWidget * parent = 0, const char* name = 0); +    ~DlgShrinkSelection(); + +    Q_INT32 xradius(); +    Q_INT32 yradius(); +    bool shrinkFromImageBorder(); + +private slots: + +    void okClicked(); + +private: + +    WdgShrinkSelection * m_page; +}; + +#endif // DLG_SHRINK_SELECTION_H diff --git a/krita/plugins/viewplugins/modify_selection/kritamodifyselection.desktop b/krita/plugins/viewplugins/modify_selection/kritamodifyselection.desktop new file mode 100644 index 000000000..cc3acc48d --- /dev/null +++ b/krita/plugins/viewplugins/modify_selection/kritamodifyselection.desktop @@ -0,0 +1,40 @@ +[Desktop Entry] +Name=Modify Selection +Name[bg]=Промяна на маркираното +Name[br]=Kemmañ an dibab +Name[ca]=Selecció de modificació +Name[da]=Ændr markering +Name[de]=Auswahl verändern +Name[el]=Τροποποίηση επιλογής +Name[eo]=Modifi elekton +Name[es]=Modificar selección +Name[et]=Valiku muutmine +Name[fa]=تغییر گزینش +Name[fr]=Modifier la sélection +Name[fy]=Seleksje oanpasse +Name[ga]=Athraigh an Roghnúchán +Name[gl]=Modificación da Selección +Name[hu]=A kijelölés módosítása +Name[it]=Modifica la selezione +Name[ja]=選択領域を変更 +Name[km]=កែប្រែការជ្រើស +Name[lv]=Mainīt izvēli +Name[nb]=Endre utvalg +Name[nds]=Utwahl ännern +Name[ne]=चयन परिमार्जन गर्नुहोस् +Name[nl]=Selectie aanpassen +Name[pl]=Zmiana wyboru +Name[pt]=Modificar a Selecção +Name[pt_BR]=Modificar a Seleção +Name[ru]=Выделение +Name[sk]=Zmeniť výber +Name[sl]=Spremeni izbiro +Name[sr]=Измена избора +Name[sr@Latn]=Izmena izbora +Name[sv]=Ändra markering +Name[uk]=Зміна виділення +Name[zh_TW]=變更選取 +ServiceTypes=Krita/ViewPlugin +Type=Service +X-KDE-Library=kritamodifyselection +X-Krita-Version=2 diff --git a/krita/plugins/viewplugins/modify_selection/modify_selection.cc b/krita/plugins/viewplugins/modify_selection/modify_selection.cc new file mode 100644 index 000000000..6f2d05117 --- /dev/null +++ b/krita/plugins/viewplugins/modify_selection/modify_selection.cc @@ -0,0 +1,158 @@ +/* + * modify_selection.cc -- Part of Krita + * + * Copyright (c) 2006 Michael Thaler (michael.thaler@physik.tu-muenchen.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 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 <math.h> + +#include <stdlib.h> + +#include <qslider.h> +#include <qpoint.h> + +#include <klocale.h> +#include <kiconloader.h> +#include <kinstance.h> +#include <kmessagebox.h> +#include <kstandarddirs.h> +#include <ktempfile.h> +#include <kdebug.h> +#include <kgenericfactory.h> +#include <kstdaction.h> + +#include <kis_doc.h> +#include <kis_config.h> +#include <kis_image.h> +#include <kis_layer.h> +#include <kis_global.h> +#include <kis_types.h> +#include <kis_view.h> +#include <kis_selection.h> +#include <kis_selection_manager.h> +#include <kis_transaction.h> + +#include "modify_selection.h" +#include "dlg_grow_selection.h" +#include "dlg_shrink_selection.h" +#include "dlg_border_selection.h" + +typedef KGenericFactory<ModifySelection> ModifySelectionFactory; +K_EXPORT_COMPONENT_FACTORY( kritamodifyselection, ModifySelectionFactory( "krita" ) ) + +ModifySelection::ModifySelection(QObject *parent, const char *name, const QStringList &) +    : KParts::Plugin(parent, name) +{ +    if ( parent->inherits("KisView") ) +    { +        setInstance(ModifySelectionFactory::instance()); +        setXMLFile(locate("data","kritaplugins/modify_selection.rc"), true); + +        m_view = (KisView*) parent; + +        // Selection manager takes ownership? +        KAction* a = new KAction(i18n("Grow Selection..."), 0, 0, this, SLOT(slotGrowSelection()), actionCollection(), "growselection"); +        KAction* b = new KAction(i18n("Shrink Selection..."), 0, 0, this, SLOT(slotShrinkSelection()), actionCollection(), "shrinkselection"); +        KAction* c = new KAction(i18n("Border Selection..."), 0, 0, this, SLOT(slotBorderSelection()), actionCollection(), "borderselection"); + +        Q_CHECK_PTR(a); +        Q_CHECK_PTR(b); +        Q_CHECK_PTR(c); + +        m_view ->canvasSubject()-> selectionManager()->addSelectionAction(a); +        m_view ->canvasSubject()-> selectionManager()->addSelectionAction(b); +        m_view ->canvasSubject()-> selectionManager()->addSelectionAction(c); +    } +} + +ModifySelection::~ModifySelection() +{ +    m_view = 0; +} + +void ModifySelection::slotGrowSelection() +{ +    KisImageSP image = m_view->canvasSubject()->currentImg(); + +    if (!image) return; + +    DlgGrowSelection * dlgGrowSelection = new DlgGrowSelection(m_view, "GrowSelection"); +    Q_CHECK_PTR(dlgGrowSelection); + +    dlgGrowSelection->setCaption(i18n("Grow Selection")); + +    KisConfig cfg; + +    if (dlgGrowSelection->exec() == QDialog::Accepted) { +        Q_INT32 xradius = dlgGrowSelection->xradius(); +        Q_INT32 yradius = dlgGrowSelection->yradius(); + +        m_view ->canvasSubject()-> selectionManager()->grow(xradius, yradius); +    } + +    delete dlgGrowSelection; +} + +void ModifySelection::slotShrinkSelection() +{ +    KisImageSP image = m_view->canvasSubject()->currentImg(); + +    if (!image) return; + +    DlgShrinkSelection * dlgShrinkSelection = new DlgShrinkSelection(m_view, "ShrinkSelection"); +    Q_CHECK_PTR(dlgShrinkSelection); + +    dlgShrinkSelection->setCaption(i18n("Shrink Selection")); + +    KisConfig cfg; + +    if (dlgShrinkSelection->exec() == QDialog::Accepted) { +        Q_INT32 xradius = dlgShrinkSelection->xradius(); +        Q_INT32 yradius = dlgShrinkSelection->yradius(); +        bool shrinkFromImageBorder = dlgShrinkSelection->shrinkFromImageBorder(); + +        m_view ->canvasSubject()-> selectionManager()->shrink(xradius, yradius, shrinkFromImageBorder); +    } + +    delete dlgShrinkSelection; +} + +void ModifySelection::slotBorderSelection() +{ +    KisImageSP image = m_view->canvasSubject()->currentImg(); + +    if (!image) return; + +    DlgBorderSelection * dlgBorderSelection = new DlgBorderSelection(m_view, "BorderSelection"); +    Q_CHECK_PTR(dlgBorderSelection); + +    dlgBorderSelection->setCaption(i18n("Border Selection")); + +    KisConfig cfg; + +    if (dlgBorderSelection->exec() == QDialog::Accepted) { +        Q_INT32 xradius = dlgBorderSelection->xradius(); +        Q_INT32 yradius = dlgBorderSelection->yradius(); + +        m_view ->canvasSubject()-> selectionManager()->border(xradius, yradius); +    } + +    delete dlgBorderSelection; +} + +#include "modify_selection.moc" diff --git a/krita/plugins/viewplugins/modify_selection/modify_selection.h b/krita/plugins/viewplugins/modify_selection/modify_selection.h new file mode 100644 index 000000000..d36770881 --- /dev/null +++ b/krita/plugins/viewplugins/modify_selection/modify_selection.h @@ -0,0 +1,46 @@ +/*  + * modify_selection.h -- Part of Krita + * + * Copyright (c) 2006 Michael Thaler (michael.thaler@physik.tu-muenchen.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 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. + */ +#ifndef MODIFY_SELECTION_H +#define MODIFY_SELECTION_H + +#include <kparts/plugin.h> + +class KisView; + +class ModifySelection : public KParts::Plugin +{ +    Q_OBJECT +public: +    ModifySelection(QObject *parent, const char *name, const QStringList &); +    virtual ~ModifySelection(); +     +private slots: + +    void slotGrowSelection(); +    void slotShrinkSelection(); +    void slotBorderSelection(); + +private: + +    KisView * m_view; + +}; + +#endif // MODIFY_SELECTION_H diff --git a/krita/plugins/viewplugins/modify_selection/modify_selection.rc b/krita/plugins/viewplugins/modify_selection/modify_selection.rc new file mode 100644 index 000000000..131534e38 --- /dev/null +++ b/krita/plugins/viewplugins/modify_selection/modify_selection.rc @@ -0,0 +1,10 @@ +<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd"> +<kpartgui library="kritamodifyselection" version="6"> +    <MenuBar> +        <Menu name="Select"><text>&Select</text> +            <Action name="growselection"/> +            <Action name="shrinkselection"/> +            <Action name="borderselection"/> +        </Menu> +    </MenuBar> +</kpartgui> diff --git a/krita/plugins/viewplugins/modify_selection/wdg_border_selection.ui b/krita/plugins/viewplugins/modify_selection/wdg_border_selection.ui new file mode 100644 index 000000000..621685da1 --- /dev/null +++ b/krita/plugins/viewplugins/modify_selection/wdg_border_selection.ui @@ -0,0 +1,57 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>WdgBorderSelection</class> +<widget class="QWidget"> +    <property name="name"> +        <cstring>WdgBorderSelection</cstring> +    </property> +    <property name="geometry"> +        <rect> +            <x>0</x> +            <y>0</y> +            <width>255</width> +            <height>101</height> +        </rect> +    </property> +    <grid> +        <property name="name"> +            <cstring>unnamed</cstring> +        </property> +        <widget class="QLabel" row="0" column="0"> +            <property name="name"> +                <cstring>textLabel1</cstring> +            </property> +            <property name="text"> +                <string>Border selection by</string> +            </property> +        </widget> +        <widget class="QSpinBox" row="1" column="0"> +            <property name="name"> +                <cstring>radiusSpinBox</cstring> +            </property> +            <property name="maxValue"> +                <number>10000</number> +            </property> +            <property name="minValue"> +                <number>1</number> +            </property> +            <property name="value"> +                <number>1</number> +            </property> +        </widget> +        <widget class="QComboBox" row="1" column="1"> +            <item> +                <property name="text"> +                    <string>pixels</string> +                </property> +            </item> +            <property name="name"> +                <cstring>comboBox1</cstring> +            </property> +        </widget> +    </grid> +</widget> +<tabstops> +    <tabstop>radiusSpinBox</tabstop> +</tabstops> +<layoutdefaults spacing="6" margin="11"/> +</UI> diff --git a/krita/plugins/viewplugins/modify_selection/wdg_grow_selection.ui b/krita/plugins/viewplugins/modify_selection/wdg_grow_selection.ui new file mode 100644 index 000000000..d2eb12aa3 --- /dev/null +++ b/krita/plugins/viewplugins/modify_selection/wdg_grow_selection.ui @@ -0,0 +1,57 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>WdgGrowSelection</class> +<widget class="QWidget"> +    <property name="name"> +        <cstring>WdgGrowSelection</cstring> +    </property> +    <property name="geometry"> +        <rect> +            <x>0</x> +            <y>0</y> +            <width>255</width> +            <height>101</height> +        </rect> +    </property> +    <grid> +        <property name="name"> +            <cstring>unnamed</cstring> +        </property> +        <widget class="QLabel" row="0" column="0"> +            <property name="name"> +                <cstring>textLabel1</cstring> +            </property> +            <property name="text"> +                <string>Grow selection by</string> +            </property> +        </widget> +        <widget class="QSpinBox" row="1" column="0"> +            <property name="name"> +                <cstring>radiusSpinBox</cstring> +            </property> +            <property name="maxValue"> +                <number>10000</number> +            </property> +            <property name="minValue"> +                <number>1</number> +            </property> +            <property name="value"> +                <number>1</number> +            </property> +        </widget> +        <widget class="QComboBox" row="1" column="1"> +            <item> +                <property name="text"> +                    <string>pixels</string> +                </property> +            </item> +            <property name="name"> +                <cstring>comboBox1</cstring> +            </property> +        </widget> +    </grid> +</widget> +<tabstops> +    <tabstop>radiusSpinBox</tabstop> +</tabstops> +<layoutdefaults spacing="6" margin="11"/> +</UI> diff --git a/krita/plugins/viewplugins/modify_selection/wdg_shrink_selection.ui b/krita/plugins/viewplugins/modify_selection/wdg_shrink_selection.ui new file mode 100644 index 000000000..2896325fb --- /dev/null +++ b/krita/plugins/viewplugins/modify_selection/wdg_shrink_selection.ui @@ -0,0 +1,68 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>WdgShrinkSelection</class> +<widget class="QWidget"> +    <property name="name"> +        <cstring>WdgShrinkSelection</cstring> +    </property> +    <property name="geometry"> +        <rect> +            <x>0</x> +            <y>0</y> +            <width>255</width> +            <height>117</height> +        </rect> +    </property> +    <grid> +        <property name="name"> +            <cstring>unnamed</cstring> +        </property> +        <widget class="QLabel" row="0" column="0" rowspan="1" colspan="2"> +            <property name="name"> +                <cstring>textLabel1</cstring> +            </property> +            <property name="text"> +                <string>Shrink selection by</string> +            </property> +        </widget> +        <widget class="QSpinBox" row="1" column="0"> +            <property name="name"> +                <cstring>radiusSpinBox</cstring> +            </property> +            <property name="maxValue"> +                <number>10000</number> +            </property> +            <property name="minValue"> +                <number>1</number> +            </property> +            <property name="value"> +                <number>1</number> +            </property> +        </widget> +        <widget class="QComboBox" row="1" column="1"> +            <item> +                <property name="text"> +                    <string>pixels</string> +                </property> +            </item> +            <property name="name"> +                <cstring>comboBox1</cstring> +            </property> +        </widget> +        <widget class="QCheckBox" row="2" column="0" rowspan="1" colspan="2"> +            <property name="name"> +                <cstring>shrinkFromImageBorderCheckBox</cstring> +            </property> +            <property name="text"> +                <string>Shrink from image border</string> +            </property> +            <property name="checked"> +                <bool>true</bool> +            </property> +        </widget> +    </grid> +</widget> +<tabstops> +    <tabstop>radiusSpinBox</tabstop> +</tabstops> +<layoutdefaults spacing="6" margin="11"/> +</UI> diff --git a/krita/plugins/viewplugins/performancetest/Makefile.am b/krita/plugins/viewplugins/performancetest/Makefile.am new file mode 100644 index 000000000..bcbd2d186 --- /dev/null +++ b/krita/plugins/viewplugins/performancetest/Makefile.am @@ -0,0 +1,24 @@ +kritarcdir = $(kde_datadir)/kritaplugins +kritarc_DATA = perftest.rc + +EXTRA_DIST = $(kritarc_DATA) + +INCLUDES  =  -I$(srcdir)/../../../sdk \ +	-I$(srcdir)/../../../core \ +	-I$(srcdir)/../../../kritacolor/ \ +	-I$(srcdir)/../../../ui \ +	-I$/../../../ui \ +	$(KOFFICE_INCLUDES) \ +	$(all_includes) + +kde_module_LTLIBRARIES = kritaperftest.la + +kritaperftest_la_SOURCES = wdg_perftest.ui perftest.cc dlg_perftest.cc +noinst_HEADERS = wdg_perftest.h dlg_perftest.h perftest.h + +kritaperftest_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) +kritaperftest_la_LIBADD =  ../../../libkritacommon.la + +kde_services_DATA = kritaperftest.desktop + +kritaperftest_la_METASOURCES = AUTO diff --git a/krita/plugins/viewplugins/performancetest/dlg_perftest.cc b/krita/plugins/viewplugins/performancetest/dlg_perftest.cc new file mode 100644 index 000000000..1d9a045eb --- /dev/null +++ b/krita/plugins/viewplugins/performancetest/dlg_perftest.cc @@ -0,0 +1,110 @@ +/* + *  dlg_perftest.cc - part of KimageShop^WKrayon^WKrita + * + *  Copyright (c) 2004 Michael Thaler <michael.thaler@physik.tu-muenchen.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 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 <config.h> + +#include <math.h> + +#include <iostream> + +using namespace std; + +#include <qradiobutton.h> +#include <qpushbutton.h> +#include <qcheckbox.h> +#include <qlabel.h> + +#include <klocale.h> +#include <knuminput.h> +#include <kdebug.h> + +#include "dlg_perftest.h" +#include "wdg_perftest.h" + + +DlgPerfTest::DlgPerfTest( QWidget *  parent, +                const char * name) +    : super (parent, name, true, i18n("Performance Test"), Ok | Cancel, Ok) +{ +    m_lock = false; + +    m_page = new WdgPerfTest(this, "perf_test"); +    Q_CHECK_PTR(m_page); + +    setMainWidget(m_page); +    resize(m_page->sizeHint()); + +    connect(this, SIGNAL(okClicked()), +        this, SLOT(okClicked())); + +    connect(m_page->btnSelectAll, SIGNAL(clicked()), this, SLOT(selectAllClicked())); +    connect(m_page->btnDeselectAll, SIGNAL(clicked()), this, SLOT(deselectAllClicked())); +} + +DlgPerfTest::~DlgPerfTest() +{ +    delete m_page; +} + +WdgPerfTest * DlgPerfTest::page() +{ +    return m_page; +} + +// SLOTS + +void DlgPerfTest::okClicked() +{ +    accept(); +} + +void DlgPerfTest::setAllTestCheckBoxes(bool checked) +{ +    m_page->chkBitBlt->setChecked(checked); +    m_page->chkFill->setChecked(checked); +    m_page->chkGradient->setChecked(checked); +    m_page->chkPixel->setChecked(checked); +    m_page->chkShape->setChecked(checked); +    m_page->chkLayer->setChecked(checked); +    m_page->chkScale->setChecked(checked); +    m_page->chkRotate->setChecked(checked); +    m_page->chkRender->setChecked(checked); +    m_page->chkSelection->setChecked(checked); +    m_page->chkColorConversion->setChecked(checked); +    m_page->chkFilter->setChecked(checked); +    m_page->chkReadBytes->setChecked(checked); +    m_page->chkWriteBytes->setChecked(checked); +    m_page->chkIterators->setChecked(checked); +    m_page->chkPaintView->setChecked(checked); +    m_page->chkPaintViewFPS->setChecked(checked); +} + +void DlgPerfTest::selectAllClicked() +{ +    setAllTestCheckBoxes(true); +} + +void DlgPerfTest::deselectAllClicked() +{ +    setAllTestCheckBoxes(false); +} + + +#include "dlg_perftest.moc" diff --git a/krita/plugins/viewplugins/performancetest/dlg_perftest.h b/krita/plugins/viewplugins/performancetest/dlg_perftest.h new file mode 100644 index 000000000..7cb4f1592 --- /dev/null +++ b/krita/plugins/viewplugins/performancetest/dlg_perftest.h @@ -0,0 +1,55 @@ +/* + *  dlg_perftest.h -- part of KimageShop^WKrayon^WKrita + * + *  Copyright (c) 2004 Michael Thaler <michael.thaler@physik.tu-muenchen.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 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. + */ +#ifndef DLG_PERFTEST_H_ +#define DLG_PERFTEST_H_ + +#include <kdialogbase.h> + +class WdgPerfTest; + +class DlgPerfTest: public KDialogBase { +    typedef KDialogBase super; +    Q_OBJECT + +public: + +    DlgPerfTest(QWidget * parent = 0, +             const char* name = 0); +    ~DlgPerfTest(); + +    WdgPerfTest * page(); + +private slots: + +    void okClicked(); +    void selectAllClicked(); +    void deselectAllClicked(); + +    void setAllTestCheckBoxes(bool checked); + +private: + +    WdgPerfTest * m_page; +    double m_oldAngle; +    bool m_lock; + +}; + +#endif // DLG_PERFTEST_H diff --git a/krita/plugins/viewplugins/performancetest/kritaperftest.desktop b/krita/plugins/viewplugins/performancetest/kritaperftest.desktop new file mode 100644 index 000000000..44af65588 --- /dev/null +++ b/krita/plugins/viewplugins/performancetest/kritaperftest.desktop @@ -0,0 +1,41 @@ +[Desktop Entry] +Name=Performance Test +Name[bg]=Тест за производителност +Name[ca]=Prova d'execució +Name[da]=Ydelsestest +Name[de]=Leistungstest +Name[el]=Δοκιμή επίδοσης +Name[es]=Prueba de rendimiento +Name[et]=Jõudlustest +Name[fa]=آزمون کارایی +Name[fr]=Test de performances +Name[fy]=Prestaasjemjitting +Name[gl]=Probas de Rendemento +Name[he]=בדיקת ביצועים +Name[hu]=Teljesítményteszt +Name[is]=Afkastapróf +Name[it]=Prova delle prestazioni +Name[ja]=パフォーマンステスト +Name[km]=សាកល្បងការសម្ដែង +Name[lv]=Veiktspējas tests +Name[nb]=Ytelsestest +Name[nds]=Leistenprööv +Name[ne]=कार्य सम्पादन परीक्षण +Name[nl]=Prestatiemeting +Name[pl]=Test wydajności +Name[pt]=Teste de Performance +Name[pt_BR]=Teste de Desempenho +Name[ru]=Модуль производительности +Name[sk]=Test výkonnosti +Name[sl]=Preizkus zmogljivosti +Name[sr]=Проба перформанси +Name[sr@Latn]=Proba performansi +Name[sv]=Prestandatest +Name[uk]=Тест швидкодії +Name[uz]=Unumdorilkni tekshirish +Name[uz@cyrillic]=Унумдорилкни текшириш +Name[zh_TW]=效能測試 +ServiceTypes=Krita/ViewPlugin +Type=Service +X-KDE-Library=kritaperftest +X-Krita-Version=2 diff --git a/krita/plugins/viewplugins/performancetest/perftest.cc b/krita/plugins/viewplugins/performancetest/perftest.cc new file mode 100644 index 000000000..1c5ede342 --- /dev/null +++ b/krita/plugins/viewplugins/performancetest/perftest.cc @@ -0,0 +1,1198 @@ +/* + * perftest.cc -- Part of Krita + * + * Copyright (c) 2004 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 <math.h> + +#include <stdlib.h> + +#include <qslider.h> +#include <qpoint.h> +#include <qradiobutton.h> +#include <qcheckbox.h> +#include <qlabel.h> +#include <qtextedit.h> +#include <qdatetime.h> + +#include <klocale.h> +#include <kiconloader.h> +#include <kinstance.h> +#include <kdialogbase.h> +#include <kmessagebox.h> +#include <kstandarddirs.h> +#include <ktempfile.h> +#include <kdebug.h> +#include <kgenericfactory.h> +#include <knuminput.h> + +#include <qcolor.h> + +#include "kis_meta_registry.h" +#include <kis_resourceserver.h> +#include "kis_cursor.h" +#include <kis_doc.h> +#include <kis_config.h> +#include <kis_image.h> +#include <kis_layer.h> +#include <kis_global.h> +#include <kis_types.h> +#include <kis_view.h> +#include <kis_selection.h> +#include <kis_colorspace_factory_registry.h> +#include <kis_colorspace.h> +#include <kis_painter.h> +#include <kis_fill_painter.h> +#include <kis_id.h> +#include <kis_paint_device.h> +#include <kis_iterators_pixel.h> +#include "perftest.h" +#include "kis_filter_config_widget.h" +#include "kis_factory.h" + +#include "dlg_perftest.h" +#include "wdg_perftest.h" + +#define USE_CALLGRIND 0 + +#if USE_CALLGRIND +#include <valgrind/callgrind.h> +#endif + + +typedef KGenericFactory<PerfTest> PerfTestFactory; +K_EXPORT_COMPONENT_FACTORY( kritaperftest, PerfTestFactory( "krita" ) ) + +PerfTest::PerfTest(QObject *parent, const char *name, const QStringList &) +    : KParts::Plugin(parent, name) +{ +    if ( parent->inherits("KisView") ) +    { +        setInstance(PerfTestFactory::instance()); +        setXMLFile(locate("data","kritaplugins/perftest.rc"), true); + +        (void) new KAction(i18n("&Performance Test..."), 0, 0, this, SLOT(slotPerfTest()), actionCollection(), "perf_test"); + +        m_view = (KisView*) parent; +    } +} + +PerfTest::~PerfTest() +{ +    m_view = 0; +} + +void PerfTest::slotPerfTest() +{ +    KisImageSP image = m_view->canvasSubject()->currentImg(); + +    if (!image) return; + +    DlgPerfTest * dlgPerfTest = new DlgPerfTest(m_view, "PerfTest"); +    Q_CHECK_PTR(dlgPerfTest); + +    dlgPerfTest->setCaption(i18n("Performance Test")); + +    QString report = QString(""); + +        if (dlgPerfTest->exec() == QDialog::Accepted) { + +        Q_INT32 testCount = (Q_INT32)qRound(dlgPerfTest->page()->intTestCount->value()); + +        if (dlgPerfTest->page()->chkBitBlt->isChecked()) { +            kdDebug() << "bltTest:\n"; +            QString s = bltTest(testCount); +            report = report.append(s); +            kdDebug() << s << "\n"; +        } +        if (dlgPerfTest->page()->chkFill->isChecked()) { +            kdDebug() << "Filltest\n"; +            QString s= fillTest(testCount); +            report = report.append(s); +            kdDebug() << s << "\n"; +        } +        if (dlgPerfTest->page()->chkGradient->isChecked()) { +            kdDebug() << "Gradienttest\n"; +            QString s = gradientTest(testCount); +            report = report.append(s); +            kdDebug() << s << "\n"; +        } +        if (dlgPerfTest->page()->chkPixel->isChecked()) { +            kdDebug() << "Pixeltest\n"; +            QString s = pixelTest(testCount); +            report = report.append(s); +            kdDebug() << s << "\n"; +        } +        if (dlgPerfTest->page()->chkShape->isChecked()) { +            kdDebug() << "Shapetest\n"; +            QString s = shapeTest(testCount); +            report = report.append(s); +            kdDebug() << s << "\n"; +        } +        if (dlgPerfTest->page()->chkLayer->isChecked()) { +            kdDebug() << "LayerTest\n"; +            QString s = layerTest(testCount); +            report = report.append(s); +            kdDebug() << s << "\n"; +        } +        if (dlgPerfTest->page()->chkScale->isChecked()) { +            kdDebug() << "Scaletest\n"; +            QString s = scaleTest(testCount); +            report = report.append(s); +            kdDebug() << s << "\n"; +        } +        if (dlgPerfTest->page()->chkRotate->isChecked()) { +            kdDebug() << "Rotatetest\n"; +            QString s = rotateTest(testCount); +            report = report.append(s); +            kdDebug() << s << "\n"; +        } +        if (dlgPerfTest->page()->chkRender->isChecked()) { +            kdDebug() << "Rendertest\n"; +            QString s = renderTest(testCount); +            report = report.append(s); +            kdDebug() << s << "\n"; +        } +        if (dlgPerfTest->page()->chkSelection->isChecked()) { +            kdDebug() << "Selectiontest\n"; +            QString s = selectionTest(testCount); +            report = report.append(s); +            kdDebug() << s << "\n"; +        } +        if (dlgPerfTest->page()->chkColorConversion->isChecked()) { +            kdDebug() << "Colorconversiontest\n"; +            QString s = colorConversionTest(testCount); +            report = report.append(s); +            kdDebug() << s << "\n"; +        } +        if (dlgPerfTest->page()->chkFilter-> isChecked()) { +            kdDebug() << "filtertest\n"; +            QString s = filterTest(testCount); +            report = report.append(s); +            kdDebug() << s << "\n"; +        } +        if (dlgPerfTest->page()->chkReadBytes->isChecked()) { +            kdDebug() << "Readbytes test\n"; +            QString s = readBytesTest(testCount); +            report = report.append(s); +            kdDebug() << s << "\n"; +        } +        if (dlgPerfTest->page()->chkWriteBytes-> isChecked()) { +            kdDebug() << "Writebytes test\n"; +            QString s = writeBytesTest(testCount); +            report = report.append(s); +            kdDebug() << s << "\n"; +        } +        if (dlgPerfTest->page()->chkIterators->isChecked()) { +            kdDebug() << "Iterators test\n"; +            QString s = iteratorTest(testCount); +            report = report.append(s); +            kdDebug() << s << "\n"; +        } +        if (dlgPerfTest->page()->chkPaintView->isChecked()) { +            kdDebug() << "paintview test\n"; +            QString s = paintViewTest(testCount); +            report = report.append(s); +            kdDebug() << s << "\n"; +        } +        if (dlgPerfTest->page()->chkPaintViewFPS->isChecked()) { +            kdDebug() << "paint current view (fps) test\n"; +            QString s = paintViewFPSTest(); +            report = report.append(s); +            kdDebug() << s << "\n"; +        } +        KDialogBase * d = new KDialogBase(m_view, "", true, "", KDialogBase::Ok); +        Q_CHECK_PTR(d); + +        d->setCaption("Performance test results"); +        QTextEdit * e = new QTextEdit(d); +        Q_CHECK_PTR(e); +        d->setMainWidget(e); +        e->setText(report); +        e->setMinimumWidth(600); +        e->setMinimumHeight(600); +        d->exec(); +        delete d; + +    } +        delete dlgPerfTest; +} + +QString PerfTest::bltTest(Q_UINT32 testCount) +{ +    QString report = QString("* bitBlt test\n"); + +    KisDoc * doc = m_view->canvasSubject()->document(); +    KisIDList l = KisMetaRegistry::instance()->csRegistry()->listKeys(); + +    for (KisIDList::Iterator it = l.begin(); it != l.end(); ++it) { + +        kdDebug() << "Image->" << (*it).name() << "\n"; + +        report = report.append( "  Testing blitting on " + (*it).name() + "\n"); + +         KisImageSP img = doc->newImage("blt-" + (*it).name(), 1000, 1000, +                KisMetaRegistry::instance()->csRegistry()->getColorSpace(*it,"")); + +        report = report.append(doBlit(COMPOSITE_OVER, *it, OPACITY_OPAQUE, testCount, img)); +        report = report.append( "\n"); +        report = report.append(doBlit(COMPOSITE_OVER, *it, OPACITY_OPAQUE / 2, testCount, img)); +        report = report.append( "\n"); +        report = report.append(doBlit(COMPOSITE_COPY, *it, OPACITY_OPAQUE, testCount, img)); +        report = report.append( "\n"); +        report = report.append(doBlit(COMPOSITE_COPY, *it, OPACITY_OPAQUE / 2, testCount, img)); +        report = report.append( "\n"); +    } + +    return report; + + +} + + +QString PerfTest::doBlit(const KisCompositeOp& op, +                         KisID cspace, +                         Q_UINT8 opacity, +                         Q_UINT32 testCount, +                         KisImageSP img) +{ + +    QTime t; +    QString report; + +    // ------------------------------------------------------------------------------ +    // Small + +    KisPaintDeviceSP small = new KisPaintDevice(KisMetaRegistry::instance()->csRegistry()->getColorSpace(cspace,""), "small blit"); +    Q_CHECK_PTR(small); + +    KisFillPainter pf(small.data()) ; +    pf.fillRect(0, 0, 32, 32, KisColor(Qt::black, KisMetaRegistry::instance()->csRegistry()->getRGB8())); +    pf.end(); + +    t.restart(); +    KisPainter p(img->activeDevice()); +    for (Q_UINT32 i = 0; i < testCount; ++i) { +        p.bitBlt(0, 0, op, small.data(),0,0,32, 32); +    } +    p.end(); + +    report = report.append(QString("   %1 blits of rectangles < tilesize with opacity %2 and composite op %3: %4ms\n") +                   .arg(testCount) +                   .arg(opacity) +                   .arg(op.id().name()) +                   .arg(t.elapsed())); + + +    // ------------------------------------------------------------------------------ +    // Medium +    KisPaintDeviceSP medium = new KisPaintDevice(KisMetaRegistry::instance()->csRegistry()->getColorSpace(cspace,""), "medium blit"); +    Q_CHECK_PTR(medium); + +    pf.begin(medium.data()) ; +    pf.fillRect(0, 0, 64 * 3, 64 * 3, KisColor(Qt::black, KisMetaRegistry::instance()->csRegistry()->getRGB8())); +    pf.end(); + +    t.restart(); +    p.begin(img->activeDevice().data()); +    for (Q_UINT32 i = 0; i < testCount; ++i) { +        p.bitBlt(0, 0, op, medium.data(),0,0,96, 96); +    } +    p.end(); + +    report = report.append(QString("   %1 blits of rectangles 3 * tilesize with opacity %2 and composite op %3: %4ms\n") +                   .arg(testCount) +                   .arg(opacity) +                   .arg(op.id().name()) +                   .arg(t.elapsed())); + + +    // ------------------------------------------------------------------------------ +    // Big +    KisPaintDeviceSP big = new KisPaintDevice(KisMetaRegistry::instance()->csRegistry()->getColorSpace(cspace,""), "big blit"); +    Q_CHECK_PTR(big); + +    pf.begin(big.data()) ; +    pf.fillRect(0, 0, 800, 800, KisColor(Qt::black, KisMetaRegistry::instance()->csRegistry()->getRGB8())); +    pf.end(); + +    t.restart(); +    p.begin(img->activeDevice().data()); +    for (Q_UINT32 i = 0; i < testCount; ++i) { +        p.bitBlt(0, 0, op, big.data(),0,0,800,800); + +    } +    p.end(); +    report = report.append(QString("   %1 blits of rectangles 800 x 800 with opacity %2 and composite op %3: %4ms\n") +                   .arg(testCount) +                   .arg(opacity) +                   .arg(op.id().name()) +                   .arg(t.elapsed())); + + +    // ------------------------------------------------------------------------------ +    // Outside + +    KisPaintDeviceSP outside = new KisPaintDevice(KisMetaRegistry::instance()->csRegistry()->getColorSpace(cspace,""), "outside blit"); +    Q_CHECK_PTR(outside); +    pf.begin(outside.data()) ; +    pf.fillRect(0, 0, 500, 500, KisColor(Qt::black, KisMetaRegistry::instance()->csRegistry()->getRGB8())); +    pf.end(); + +    t.restart(); +    p.begin(img->activeDevice().data()); +    for (Q_UINT32 i = 0; i < testCount; ++i) { +        p.bitBlt(600, 600, op, outside.data(),0,0,500,500); + +    } +    p.end(); +    report = report.append(QString("   %1 blits of rectangles 500 x 500 at 600,600 with opacity %2 and composite op %3: %4ms\n") +                   .arg(testCount) +                   .arg(opacity) +                   .arg(op.id().name()) +                   .arg(t.elapsed())); + +    // ------------------------------------------------------------------------------ +    // Small with varied source opacity + +    KisPaintDeviceSP small_with_alpha = new KisPaintDevice(KisMetaRegistry::instance()->csRegistry()->getColorSpace(cspace,""), "small blit with alpha"); +    Q_CHECK_PTR(small_with_alpha); + +    pf.begin(small_with_alpha.data()) ; +    pf.fillRect(0, 0, 32, 32, KisColor(Qt::black, KisMetaRegistry::instance()->csRegistry()->getRGB8()), OPACITY_TRANSPARENT); +    pf.fillRect(4, 4, 24, 24, KisColor(Qt::black, KisMetaRegistry::instance()->csRegistry()->getRGB8()), OPACITY_OPAQUE / 2); +    pf.fillRect(8, 8, 16, 16, KisColor(Qt::black, KisMetaRegistry::instance()->csRegistry()->getRGB8()), OPACITY_OPAQUE); +    pf.end(); + +    t.restart(); +    p.begin(img->activeDevice().data()); +    for (Q_UINT32 i = 0; i < testCount; ++i) { +        p.bitBlt(0, 0, op, small_with_alpha.data(), 0, 0, 32, 32); +    } +    p.end(); + +    report = report.append(QString("   %1 blits of rectangles < tilesize with source alpha, with opacity %2 and composite op %3: %4ms\n") +                   .arg(testCount) +                   .arg(opacity) +                   .arg(op.id().name()) +                   .arg(t.elapsed())); + +    return report; + +} + +QString PerfTest::fillTest(Q_UINT32 testCount) +{ +    QString report = QString("* Fill test\n"); + +    KisDoc * doc = m_view->canvasSubject()->document(); +    KisIDList l = KisMetaRegistry::instance()->csRegistry()->listKeys(); + +    for (KisIDList::Iterator it = l.begin(); it != l.end(); ++it) { +        kdDebug() << "Filltest on " << (*it).name() + "\n"; + +        report = report.append( "  Testing blitting on " + (*it).name() + "\n"); + +        KisImageSP img = doc->newImage("fill-" + (*it).name(), 1000, 1000, KisMetaRegistry::instance()->csRegistry()->getColorSpace(*it,"")); +        KisPaintDeviceSP l = img->activeDevice(); + +        // Rect fill +        KisFillPainter p(l.data()); +        QTime t; +        t.restart(); +        for (Q_UINT32 i = 0; i < testCount; ++i) { +            p.eraseRect(0, 0, 1000, 1000); +        } +        report = report.append(QString("    Erased 1000 x 1000 layer %1 times: %2\n").arg(testCount).arg(t.elapsed())); + + +        t.restart(); +        for (Q_UINT32 i = 0; i < testCount; ++i) { +            p.eraseRect(50, 50, 500, 500); +        } +        report = report.append(QString("    Erased 500 x 500 layer %1 times: %2\n").arg(testCount).arg(t.elapsed())); + + +        t.restart(); +        for (Q_UINT32 i = 0; i < testCount; ++i) { +            p.eraseRect(-50, -50, 1100, 1100); +        } +        report = report.append(QString("    Erased rect bigger than layer %1 times: %2\n").arg(testCount).arg(t.elapsed())); + + +        // Opaque Rect fill +        t.restart(); +        for (Q_UINT32 i = 0; i < testCount; ++i) { +            p.fillRect(0, 0, 1000, 1000, KisColor(Qt::black, KisMetaRegistry::instance()->csRegistry()->getRGB8())); +        } +        report = report.append(QString("    Opaque fill 1000 x 1000 layer %1 times: %2\n").arg(testCount).arg(t.elapsed())); + + +        t.restart(); +        for (Q_UINT32 i = 0; i < testCount; ++i) { +            p.fillRect(50, 50, 500, 500, KisColor(Qt::black, KisMetaRegistry::instance()->csRegistry()->getRGB8())); +        } +        report = report.append(QString("    Opaque fill 500 x 500 layer %1 times: %2\n").arg(testCount).arg(t.elapsed())); + + +        t.restart(); +        for (Q_UINT32 i = 0; i < testCount; ++i) { +            p.fillRect(-50, -50, 1100, 1100, KisColor(Qt::black, KisMetaRegistry::instance()->csRegistry()->getRGB8())); +        } +        report = report.append(QString("    Opaque fill rect bigger than layer %1 times: %2\n").arg(testCount).arg(t.elapsed())); + +        // Transparent rect fill + +        t.restart(); +        for (Q_UINT32 i = 0; i < testCount; ++i) { +            p.fillRect(0, 0, 1000, 1000, KisColor(Qt::black, KisMetaRegistry::instance()->csRegistry()->getRGB8()), OPACITY_OPAQUE / 2); +        } +        report = report.append(QString("    Opaque fill 1000 x 1000 layer %1 times: %2\n").arg(testCount).arg(t.elapsed())); + + +        t.restart(); +        for (Q_UINT32 i = 0; i < testCount; ++i) { +            p.fillRect(50, 50, 500, 500, KisColor(Qt::black, KisMetaRegistry::instance()->csRegistry()->getRGB8()), OPACITY_OPAQUE / 2); +        } +        report = report.append(QString("    Opaque fill 500 x 500 layer %1 times: %2\n").arg(testCount).arg(t.elapsed())); + + +        t.restart(); +        for (Q_UINT32 i = 0; i < testCount; ++i) { +            p.fillRect(-50, -50, 1100, 1100, KisColor(Qt::black, KisMetaRegistry::instance()->csRegistry()->getRGB8()), OPACITY_OPAQUE / 2); +        } +        report = report.append(QString("    Opaque fill rect bigger than layer %1 times: %2\n").arg(testCount).arg(t.elapsed())); + +        // Colour fill + +        t.restart(); +        for (Q_UINT32 i = 0; i < testCount; ++i) { +            p.eraseRect(0, 0, 1000, 1000); +//             p.paintEllipse(500, 1000, 100, 0, 0); +            p.setPaintColor(KisColor(Qt::black, KisMetaRegistry::instance()->csRegistry()->getRGB8())); +            p.setFillThreshold(15); +            p.setCompositeOp(COMPOSITE_OVER); +            p.fillColor(0,0); +        } +        report = report.append(QString("    Opaque floodfill of whole circle (incl. erase and painting of circle) %1 times: %2\n").arg(testCount).arg(t.elapsed())); + + +        // Pattern fill +        t.restart(); +        for (Q_UINT32 i = 0; i < testCount; ++i) { +            p.eraseRect(0, 0, 1000, 1000); +//             p.paintEllipse(500, 1000, 100, 0, 0); +            p.setPaintColor(KisColor(Qt::black, KisMetaRegistry::instance()->csRegistry()->getRGB8())); +            KisResourceServerBase* r = KisResourceServerRegistry::instance()->get("PatternServer"); +            Q_CHECK_PTR(r); +            p.setPattern((KisPattern*)r->resources().first()); +            p.setFillThreshold(15); +            p.setCompositeOp(COMPOSITE_OVER); +            p.fillPattern(0,0); +        } +        report = report.append(QString("    Opaque patternfill  of whole circle (incl. erase and painting of circle) %1 times: %2\n").arg(testCount).arg(t.elapsed())); + + + +    } + + + +    return report; + +} + +QString PerfTest::gradientTest(Q_UINT32 testCount) +{ +    return QString("Gradient test\n"); +} + +QString PerfTest::pixelTest(Q_UINT32 testCount) +{ +    QString report = QString("* pixel/setpixel test\n"); + +    KisDoc * doc = m_view->canvasSubject()->document(); +    KisIDList l = KisMetaRegistry::instance()->csRegistry()->listKeys(); + + +    for (KisIDList::Iterator it = l.begin(); it != l.end(); ++it) { +        report = report.append( "  Testing pixel/setpixel on " + (*it).name() + "\n"); + +         KisImageSP img = doc->newImage("fill-" + (*it).name(), 1000, 1000, KisMetaRegistry::instance()->csRegistry()->getColorSpace(*it,"")); + +        KisPaintDeviceSP l = img->activeDevice(); + +         QTime t; +         t.restart(); + +        QColor c = Qt::black; +        Q_UINT8 opacity = OPACITY_OPAQUE; +         for (Q_UINT32 i = 0; i < testCount; ++i) { +            for (Q_UINT32 x = 0; x < 1000; ++x) { +                for (Q_UINT32 y = 0; y < 1000; ++y) { +                    l->pixel(x, y, &c, &opacity); +                } +            } +         } +        report = report.append(QString("    read 1000 x 1000 pixels %1 times: %2\n").arg(testCount).arg(t.elapsed())); + +        c= Qt::black; +         t.restart(); +         for (Q_UINT32 i = 0; i < testCount; ++i) { +            for (Q_UINT32 x = 0; x < 1000; ++x) { +                for (Q_UINT32 y = 0; y < 1000; ++y) { +                    l->setPixel(x, y, c, 128); +                } +            } +         } +        report = report.append(QString("    written 1000 x 1000 pixels %1 times: %2\n").arg(testCount).arg(t.elapsed())); + +    } + + + + +    return report; + +} + +QString PerfTest::shapeTest(Q_UINT32 testCount) +{ +    return QString("Shape test\n"); +} + +QString PerfTest::layerTest(Q_UINT32 testCount) +{ +    return QString("Layer test\n"); +} + +QString PerfTest::scaleTest(Q_UINT32 testCount) +{ +    return QString("Scale test\n"); +} + +QString PerfTest::rotateTest(Q_UINT32 testCount) +{ +    QString report = QString("* Rotate test\n"); + +    KisDoc * doc = m_view->canvasSubject()->document(); +    KisIDList l = KisMetaRegistry::instance()->csRegistry()->listKeys(); +    for (KisIDList::Iterator it = l.begin(); it != l.end(); ++it) { + +        doc->undoAdapter()->setUndo( false ); +        QTime t; + +        for (uint i = 0; i < testCount; ++i) { +            for (double angle = 0; angle < 360; ++angle) { +                kdDebug() << "Rotating " << (*it).name() << " at " << angle << " degrees\n"; +                KisImage * img = doc->newImage("cs-" + (*it).name(), 1000, 1000, KisMetaRegistry::instance()->csRegistry()->getColorSpace(*it,"")); +                img->rotate(angle, m_view->canvasSubject()->progressDisplay()); +                kdDebug() << "Size: " << img->projection()->extent() << endl; +                delete img; +            } +        } +        report = report.append(QString("    rotated  1000 x 1000 pixels over 360 degrees, degree by degree, %1 times: %2\n").arg(testCount).arg(t.elapsed())); +    } +    return report; +} + +QString PerfTest::renderTest(Q_UINT32 restCount) +{ +    return QString("Render test\n"); +} + +QString PerfTest::selectionTest(Q_UINT32 testCount) +{ +    return QString("Selection test\n"); +} + +QString PerfTest::colorConversionTest(Q_UINT32 testCount) +{ +    QString report = QString("* Colorspace conversion test\n"); + +    KisDoc * doc = m_view->canvasSubject()->document(); +    KisIDList l = KisMetaRegistry::instance()->csRegistry()->listKeys(); +    for (KisIDList::Iterator it = l.begin(); it != l.end(); ++it) { + +        KisImage * img = doc->newImage("cs-" + (*it).name(), 1000, 1000, KisMetaRegistry::instance()->csRegistry()->getColorSpace(*it,"")); + +        QTime t; + +        KisIDList l2 = KisMetaRegistry::instance()->csRegistry()->listKeys(); +        for (KisIDList::Iterator it2 = l2.begin(); it2 != l2.end(); ++it2) { +            kdDebug() << "test conversion from " << (*it).name() << " to " << (*it2).name() << endl; +             +            t.restart(); +            for (uint i = 0; i < testCount; ++i) { +                KisImage * img2 = new KisImage(*img); +                img2->convertTo(KisMetaRegistry::instance()->csRegistry()->getColorSpace(*it2,"")); +                delete img2; +            } +            report = report.append(QString("    converted from " + (*it).name() + " to " + (*it2).name() + " 1000 x 1000 pixels %1 times: %2\n").arg(testCount).arg(t.elapsed())); + +        } + +        delete img; + +    } +    return report; + +} + +QString PerfTest::filterTest(Q_UINT32 testCount) +{ + +    QString report = QString("* Filter test\n"); + +    KisIDList filters = KisFilterRegistry::instance()->listKeys(); +    KisDoc * doc = m_view->canvasSubject()->document(); +    KisIDList l = KisMetaRegistry::instance()->csRegistry()->listKeys(); + +    for (KisIDList::Iterator it = l.begin(); it != l.end(); ++it) { +        report = report.append( "  Testing filtering on " + (*it).name() + "\n"); + +        KisImageSP img = doc->newImage("filter-" + (*it).name(), 1000, 1000, KisMetaRegistry::instance()->csRegistry()->getColorSpace(*it,"")); +        KisPaintDeviceSP l = img->activeDevice(); + +        QTime t; + +        for (KisIDList::Iterator it = filters.begin(); it != filters.end(); ++it) { +             +            KisFilterSP f = KisFilterRegistry::instance()->get(*it); +            t.restart(); +            kdDebug() << "test filter " << f->id().name() << " on " << img->colorSpace()->id().name() << endl; +            for (Q_UINT32 i = 0; i < testCount; ++i) { +                f->enableProgress(); +                f->process(l.data(), l.data(), f->configuration(f->createConfigurationWidget(m_view, l.data())), QRect(0, 0, 1000, 1000)); +                f->disableProgress(); +            } +            report = report.append(QString("    filtered " + (*it).name() + "1000 x 1000 pixels %1 times: %2\n").arg(testCount).arg(t.elapsed())); + +        } + +    } +    return report; + +} + +QString PerfTest::readBytesTest(Q_UINT32 testCount) +{ +    QString report = QString("* Read bytes test\n\n"); + +    // On default tiles +    KisDoc * doc = m_view->canvasSubject()->document(); +    KisImageSP img = doc->newImage("Readbytes ", 1000, 1000, KisMetaRegistry::instance()->csRegistry()->getColorSpace(KisID("RGBA",""),"")); +    KisPaintDeviceSP l = img->activeDevice(); + +    QTime t; +    t.restart(); + +    for (Q_UINT32 i = 0; i < testCount; ++i) { +        Q_UINT8 * newData = new Q_UINT8[1000 * 1000 * l->pixelSize()]; +        Q_CHECK_PTR(newData); +        l->readBytes(newData, 0, 0, 1000, 1000); +        delete[] newData; +    } + +    report = report.append(QString("    read 1000 x 1000 pixels %1 times from empty image: %2\n").arg(testCount).arg(t.elapsed())); + +    // On tiles with data + +    KisFillPainter p(l.data()); +    p.fillRect(0, 0, 1000, 1000, KisColor(Qt::black, KisMetaRegistry::instance()->csRegistry()->getRGB8())); +    p.end(); + +    t.restart(); + +    for (Q_UINT32 i = 0; i < testCount; ++i) { +        Q_UINT8 * newData = new Q_UINT8[1000 * 1000 * l->pixelSize()]; +        Q_CHECK_PTR(newData); +        l->readBytes(newData, 0, 0, 1000, 1000); +        delete[] newData; +    } + +    report = report.append(QString("    read 1000 x 1000 pixels %1 times from filled image: %2\n").arg(testCount).arg(t.elapsed())); + +    return report; +} + + +QString PerfTest::writeBytesTest(Q_UINT32 testCount) +{ +    QString report = QString("* Write bytes test"); + +    // On default tiles +    KisDoc * doc = m_view->canvasSubject()->document(); +    KisImageSP img = doc->newImage("Writebytes ", 1000, 1000, KisMetaRegistry::instance()->csRegistry()->getColorSpace(KisID("RGBA", ""),"")); +    KisPaintDeviceSP l = img->activeDevice(); +    KisFillPainter p(l.data()); +    p.fillRect(0, 0, 1000, 1000, KisColor(Qt::black, KisMetaRegistry::instance()->csRegistry()->getRGB8())); +    p.end(); + + +    Q_UINT8 * data = new Q_UINT8[1000 * 1000 * l->pixelSize()]; +    Q_CHECK_PTR(data); +    l->readBytes(data, 0, 0, 1000, 1000); + +    QTime t; +    t.restart(); +    for (Q_UINT32 i = 0; i < testCount; ++i) { +        l->writeBytes(data, 0, 0, 1000, 1000); +    } +    delete[] data; +    report = report.append(QString("    written 1000 x 1000 pixels %1 times: %2\n").arg(testCount).arg(t.elapsed())); +    return report; + + +} + +/////// Iterator tests + + +QString hlineRODefault(KisDoc * doc, Q_UINT32 testCount) +{ +    KisImageSP img = doc->newImage("", 1000, 1000, KisMetaRegistry::instance()->csRegistry()->getColorSpace(KisID("RGBA", ""),"")); +    KisPaintDeviceSP l = img->activeDevice(); + +    QTime t; +    t.restart(); + + +    for (Q_UINT32 i = 0; i < testCount; ++i) { +         int adv; + +        for(Q_INT32 y2 = 0; y2 < 0 + 1000; y2++) +        { +            KisHLineIterator hiter = l->createHLineIterator(0, y2, 1000, false); +            while(! hiter.isDone()) +            { +                 adv = hiter.nConseqHPixels(); +                 hiter += adv; +            } +        } + +    } + +    return QString("    hline iterated read-only 1000 x 1000 pixels %1 times over default tile: %2\n").arg(testCount).arg(t.elapsed()); + + +} + +QString hlineRO(KisDoc * doc, Q_UINT32 testCount) +{ +    KisImageSP img = doc->newImage("", 1000, 1000, KisMetaRegistry::instance()->csRegistry()->getColorSpace(KisID("RGBA", ""),"")); +    KisPaintDeviceSP l = img->activeDevice(); + +    KisFillPainter p(l.data()); +    p.fillRect(0, 0, 1000, 1000, KisColor(Qt::black, KisMetaRegistry::instance()->csRegistry()->getRGB8())); +    p.end(); + +    QTime t; +    t.restart(); + +    for (Q_UINT32 i = 0; i < testCount; ++i) { +         int adv; + +        for(Q_INT32 y2 = 0; y2 < 0 + 1000; y2++) +        { +            KisHLineIterator hiter = l->createHLineIterator(0, y2, 1000, false); +            while(! hiter.isDone()) +            { +                 adv = hiter.nConseqHPixels(); +                 hiter += adv; +            } +        } + +    } + +    return QString("    hline iterated read-only 1000 x 1000 pixels %1 times over existing tile: %2\n").arg(testCount).arg(t.elapsed()); + +} + +QString hlineWRDefault(KisDoc * doc, Q_UINT32 testCount) +{ +    KisImageSP img = doc->newImage("", 1000, 1000, KisMetaRegistry::instance()->csRegistry()->getColorSpace(KisID("RGBA", ""),"")); +    KisPaintDeviceSP l = img->activeDevice(); + +    QTime t; +    t.restart(); + +    for (Q_UINT32 i = 0; i < testCount; ++i) { +         int adv; + +        for(Q_INT32 y2 = 0; y2 < 0 + 1000; y2++) +        { +            KisHLineIterator hiter = l->createHLineIterator(0, y2, 1000, true); +            while(! hiter.isDone()) +            { +                 adv = hiter.nConseqHPixels(); +                 hiter += adv; +            } +        } + +    } + +    return QString("    hline iterated writable 1000 x 1000 pixels %1 times over default tile: %2\n").arg(testCount).arg(t.elapsed()); + +} + +QString hlineWR(KisDoc * doc, Q_UINT32 testCount) +{ +    KisImageSP img = doc->newImage("", 1000, 1000, KisMetaRegistry::instance()->csRegistry()->getColorSpace(KisID("RGBA", ""),"")); +    KisPaintDeviceSP l = img->activeDevice(); + +    KisFillPainter p(l.data()); +    p.fillRect(0, 0, 1000, 1000, KisColor(Qt::black, KisMetaRegistry::instance()->csRegistry()->getRGB8())); +    p.end(); + + +    QTime t; +    t.restart(); + +    for (Q_UINT32 i = 0; i < testCount; ++i) { +         int adv; +        for(Q_INT32 y2 = 0; y2 < 0 + 1000; y2++) +        { +            KisHLineIterator hiter = l->createHLineIterator(0, y2, 1000, true); +            while(! hiter.isDone()) +            { +                 adv = hiter.nConseqHPixels(); +                 hiter += adv; +            } +        } + +    } + +    return QString("    hline iterated writable 1000 x 1000 pixels %1 times over existing tile: %2\n").arg(testCount).arg(t.elapsed()); + +} + + +QString vlineRODefault(KisDoc * doc, Q_UINT32 testCount) +{ +    KisImageSP img = doc->newImage("", 1000, 1000, KisMetaRegistry::instance()->csRegistry()->getColorSpace(KisID("RGBA", ""),"")); +    KisPaintDeviceSP l = img->activeDevice(); + +    QTime t; +    t.restart(); + +    for (Q_UINT32 i = 0; i < testCount; ++i) { +        for(Q_INT32 y2 = 0; y2 < 0 + 1000; y2++) +        { +            KisVLineIterator hiter = l->createVLineIterator(y2, 0, 1000, true); +            while(! hiter.isDone()) +            { +                 ++hiter; +            } +        } + +    } + +    return QString("    vline iterated read-only 1000 x 1000 pixels %1 times over default tile: %2\n").arg(testCount).arg(t.elapsed()); + +} + +QString vlineRO(KisDoc * doc, Q_UINT32 testCount) +{ +    KisImageSP img = doc->newImage("", 1000, 1000, KisMetaRegistry::instance()->csRegistry()->getColorSpace(KisID("RGBA", ""),"")); +    KisPaintDeviceSP l = img->activeDevice(); + +    KisFillPainter p(l.data()); +    p.fillRect(0, 0, 1000, 1000, KisColor(Qt::black, KisMetaRegistry::instance()->csRegistry()->getRGB8())); +    p.end(); + + +    QTime t; +    t.restart(); + +    for (Q_UINT32 i = 0; i < testCount; ++i) { +        for(Q_INT32 y2 = 0; y2 < 0 + 1000; y2++) +        { +            KisVLineIterator hiter = l->createVLineIterator(y2, 0, 1000, true); +            while(! hiter.isDone()) +            { +                 ++hiter; +            } +        } + +    } + +    return QString("    vline iterated read-only 1000 x 1000 pixels %1 times over existing tile: %2\n").arg(testCount).arg(t.elapsed()); + +} + +QString vlineWRDefault(KisDoc * doc, Q_UINT32 testCount) +{ +    KisImageSP img = doc->newImage("", 1000, 1000, KisMetaRegistry::instance()->csRegistry()->getColorSpace(KisID("RGBA", ""),"")); +    KisPaintDeviceSP l = img->activeDevice(); + +    QTime t; +    t.restart(); + +    for (Q_UINT32 i = 0; i < testCount; ++i) { + +        for(Q_INT32 y2 = 0; y2 < 0 + 1000; y2++) +        { +            KisVLineIterator hiter = l->createVLineIterator(y2, 0, 1000, true); +            while(! hiter.isDone()) +            { +                 ++hiter; +            } +        } + +    } + +    return QString("    vline iterated writable 1000 x 1000 pixels %1 times over default tile: %2\n").arg(testCount).arg(t.elapsed()); +} + +QString vlineWR(KisDoc * doc, Q_UINT32 testCount) +{ + +    KisImageSP img = doc->newImage("", 1000, 1000, KisMetaRegistry::instance()->csRegistry()->getColorSpace(KisID("RGBA", ""),"")); +    KisPaintDeviceSP l = img->activeDevice(); + +    KisFillPainter p(l.data()); +    p.fillRect(0, 0, 1000, 1000, KisColor(Qt::black, KisMetaRegistry::instance()->csRegistry()->getRGB8())); +    p.end(); + +    QTime t; +    t.restart(); + +    for (Q_UINT32 i = 0; i < testCount; ++i) { +        for(Q_INT32 y2 = 0; y2 < 0 + 1000; y2++) +        { +            KisHLineIterator hiter = l->createHLineIterator(y2, 0, 1000, true); +            while(! hiter.isDone()) +            { +                 ++hiter; +            } +        } + +    } + +    return QString("    vline iterated writable 1000 x 1000 pixels %1 times over existing tile: %2\n").arg(testCount).arg(t.elapsed()); + +} + +QString rectRODefault(KisDoc * doc, Q_UINT32 testCount) +{ +    KisImageSP img = doc->newImage("", 1000, 1000, KisMetaRegistry::instance()->csRegistry()->getColorSpace(KisID("RGBA", ""),"")); +    KisPaintDeviceSP l = img->activeDevice(); +; +    QTime t; +    t.restart(); + +    for (Q_UINT32 i = 0; i < testCount; ++i) { +        KisRectIterator r = l->createRectIterator(0, 0, 1000, 1000, false); +        while(! r.isDone()) +        { +            ++r; +        } +    } + +    return QString("    rect iterated read-only 1000 x 1000 pixels %1 times over default tile: %2\n").arg(testCount).arg(t.elapsed()); + + +} + +QString rectRO(KisDoc * doc, Q_UINT32 testCount) +{ +    KisImageSP img = doc->newImage("", 1000, 1000, KisMetaRegistry::instance()->csRegistry()->getColorSpace(KisID("RGBA", ""),"")); +    KisPaintDeviceSP l = img->activeDevice(); + +    KisFillPainter p(l.data()); +    p.fillRect(0, 0, 1000, 1000, KisColor(Qt::black, KisMetaRegistry::instance()->csRegistry()->getRGB8())); +    p.end(); + +    QTime t; +    t.restart(); + +    for (Q_UINT32 i = 0; i < testCount; ++i) { +        KisRectIterator r = l->createRectIterator(0, 0, 1000, 1000, false); +        while(! r.isDone()) +        { +            ++r; +        } +    } + +    return QString("    rect iterated read-only 1000 x 1000 pixels %1 times over existing tile: %2\n").arg(testCount).arg(t.elapsed()); + +} + +QString rectWRDefault(KisDoc * doc, Q_UINT32 testCount) +{ + + +    KisImageSP img = doc->newImage("", 1000, 1000, KisMetaRegistry::instance()->csRegistry()->getColorSpace(KisID("RGBA", ""),"")); +    KisPaintDeviceSP l = img->activeDevice(); + +    QTime t; +    t.restart(); + +    for (Q_UINT32 i = 0; i < testCount; ++i) { +        KisRectIterator r = l->createRectIterator(0, 0, 1000, 1000, true); +        while(! r.isDone()) +        { +            ++r; +        } +    } + +    return QString("    rect iterated writable 1000 x 1000 pixels %1 times over default tile: %2\n").arg(testCount).arg(t.elapsed()); + +} + +QString rectWR(KisDoc * doc, Q_UINT32 testCount) +{ +    KisImageSP img = doc->newImage("", 1000, 1000, KisMetaRegistry::instance()->csRegistry()->getColorSpace(KisID("RGBA", ""),"")); +    KisPaintDeviceSP l = img->activeDevice(); + +    KisFillPainter p(l.data()); +    p.fillRect(0, 0, 1000, 1000, KisColor(Qt::black, KisMetaRegistry::instance()->csRegistry()->getRGB8())); +    p.end(); + + +    QTime t; +    t.restart(); + + +    for (Q_UINT32 i = 0; i < testCount; ++i) { +        KisRectIterator r = l->createRectIterator(0, 0, 1000, 1000, true); +        while(! r.isDone()) +        { +            ++r; +        } +    } + + +    return QString("    rect iterated writable 1000 x 1000 pixels %1 times over existing tile: %2\n").arg(testCount).arg(t.elapsed()); + + +} +QString PerfTest::iteratorTest(Q_UINT32 testCount) +{ +    QString report = "Iterator test"; + +    KisDoc * doc = m_view->canvasSubject()->document(); + +    report = report.append(hlineRODefault(doc, testCount)); +    report = report.append(hlineRO(doc, testCount)); +    report = report.append(hlineWRDefault(doc, testCount)); +    report = report.append(hlineWR(doc, testCount)); + +    report = report.append(vlineRODefault(doc, testCount)); +    report = report.append(vlineRO(doc, testCount)); +    report = report.append(vlineWRDefault(doc, testCount)); +    report = report.append(vlineWR(doc, testCount)); + +    report = report.append(rectRODefault(doc, testCount)); +    report = report.append(rectRO(doc, testCount)); +    report = report.append(rectWRDefault(doc, testCount)); +    report = report.append(rectWR(doc, testCount)); + +    return report; + + +} + +QString PerfTest::paintViewTest(Q_UINT32 testCount) +{ +    QString report = QString("* paintView test\n\n"); + +    KisDoc * doc = m_view->canvasSubject()->document(); + +    KisImageSP img = doc->currentImage(); +    img->resize(512,512); + + +    KisPaintDeviceSP l = img->activeDevice(); + +    KisFillPainter p(l.data()); +    p.fillRect(0, 0, 512, 512, KisColor(Qt::black, KisMetaRegistry::instance()->csRegistry()->getRGB8())); +    p.end(); + +    QTime t; +    t.restart(); + +#if USE_CALLGRIND +    CALLGRIND_ZERO_STATS(); +#endif + +    for (Q_UINT32 i = 0; i < testCount; ++i) { +        m_view->getCanvasController()->updateCanvas(QRect(0, 0, 512, 512)); +    } + +#if USE_CALLGRIND +    CALLGRIND_DUMP_STATS(); +#endif + +    report = report.append(QString("    painted a 512 x 512 image %1 times: %2 ms\n").arg(testCount).arg(t.elapsed())); + +    img->newLayer("layer 2", OPACITY_OPAQUE); +    l = img->activeDevice(); + +    p.begin(l.data()); +    p.fillRect(0, 0, 512, 512, KisColor(Qt::black, KisMetaRegistry::instance()->csRegistry()->getRGB8())); +    p.end(); + +    img->newLayer("layer 3", OPACITY_OPAQUE); +    l = img->activeDevice(); + +    p.begin(l.data()); +    p.fillRect(0, 0, 512, 512, KisColor(Qt::black, KisMetaRegistry::instance()->csRegistry()->getRGB8())); +    p.end(); + +    t.restart(); + +    for (Q_UINT32 i = 0; i < testCount; ++i) { +        m_view->getCanvasController()->updateCanvas(QRect(0, 0, 512, 512)); +    } + +    report = report.append(QString("    painted a 512 x 512 image with 3 layers %1 times: %2 ms\n").arg(testCount).arg(t.elapsed())); + +    return report; +} + +QString PerfTest::paintViewFPSTest() +{ +    QString report = QString("* paintView (fps) test\n\n"); + +    QTime t; +    t.restart(); + +#if USE_CALLGRIND +    CALLGRIND_ZERO_STATS(); +#endif + +    int numViewsPainted = 0; +    const int millisecondsPerSecond = 1000; + +    while (t.elapsed() < millisecondsPerSecond) { +        m_view->getCanvasController()->updateCanvas(); +        numViewsPainted++; +    } + +#if USE_CALLGRIND +    CALLGRIND_DUMP_STATS(); +#endif + +    report = report.append(QString("    painted current view at %1 frames per second\n").arg(numViewsPainted)); + +    return report; +} + +#include "perftest.moc" diff --git a/krita/plugins/viewplugins/performancetest/perftest.h b/krita/plugins/viewplugins/performancetest/perftest.h new file mode 100644 index 000000000..6a3365c5a --- /dev/null +++ b/krita/plugins/viewplugins/performancetest/perftest.h @@ -0,0 +1,75 @@ +/*  + * perftest.h -- Part of Krita + * + * 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. + */ + +#ifndef PERFTEST_H_ +#define PERFTEST_H_ + +#include <kparts/plugin.h> +#include <kis_types.h> +#include <kis_global.h> + +class KisView; +class KisID; + +class PerfTest : public KParts::Plugin +{ +    Q_OBJECT +public: +    PerfTest(QObject *parent, const char *name, const QStringList &); +    virtual ~PerfTest(); +     +private slots: + +    void slotPerfTest(); + +private: + +    QString bltTest(Q_UINT32 testCount); +    QString fillTest(Q_UINT32 testCount); +    QString gradientTest(Q_UINT32 testCount); +    QString pixelTest(Q_UINT32 testCount); +    QString shapeTest(Q_UINT32 testCount); +    QString layerTest(Q_UINT32 testCount); +    QString scaleTest(Q_UINT32 testCount); +    QString rotateTest(Q_UINT32 testCount); +    QString renderTest(Q_UINT32 restCount); +    QString selectionTest(Q_UINT32 testCount); +    QString colorConversionTest(Q_UINT32 testCount); +    QString filterTest(Q_UINT32 testCount); +    QString readBytesTest(Q_UINT32 testCount); +    QString writeBytesTest(Q_UINT32 testCount); +    QString iteratorTest(Q_UINT32 testCount); +    QString paintViewTest(Q_UINT32 testCount); +    QString paintViewFPSTest(); + +    QString doBlit(const KisCompositeOp& op,  +               KisID cspace, +               Q_UINT8 opacity, +               Q_UINT32 testCount, +               KisImageSP img); + +private: + +    KisView * m_view; +    KisPainter * m_painter; + +}; + +#endif // PERFTEST_H_ diff --git a/krita/plugins/viewplugins/performancetest/perftest.rc b/krita/plugins/viewplugins/performancetest/perftest.rc new file mode 100644 index 000000000..6010e8f3f --- /dev/null +++ b/krita/plugins/viewplugins/performancetest/perftest.rc @@ -0,0 +1,9 @@ +<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd"> +<kpartgui library="kritaperftest" version="1"> +<MenuBar> +    <Menu name="Tools"><text>&Tools</text> +	<Separator/> +	<Action name="perf_test"/> +    </Menu> +</MenuBar> +</kpartgui>
\ No newline at end of file diff --git a/krita/plugins/viewplugins/performancetest/wdg_perftest.ui b/krita/plugins/viewplugins/performancetest/wdg_perftest.ui new file mode 100644 index 000000000..4f9ca4a09 --- /dev/null +++ b/krita/plugins/viewplugins/performancetest/wdg_perftest.ui @@ -0,0 +1,283 @@ +<!DOCTYPE UI><UI version="3.2" stdsetdef="1"> +<class>WdgPerfTest</class> +<widget class="QWidget"> +    <property name="name"> +        <cstring>WdgPerfTest</cstring> +    </property> +    <property name="geometry"> +        <rect> +            <x>0</x> +            <y>0</y> +            <width>377</width> +            <height>566</height> +        </rect> +    </property> +    <property name="caption"> +        <string>Image Size</string> +    </property> +    <grid> +        <property name="name"> +            <cstring>unnamed</cstring> +        </property> +        <widget class="QButtonGroup" row="0" column="0"> +            <property name="name"> +                <cstring>grpPerfTest</cstring> +            </property> +            <property name="title"> +                <string>&Performance Test</string> +            </property> +            <grid> +                <property name="name"> +                    <cstring>unnamed</cstring> +                </property> +                <widget class="QLabel" row="0" column="0"> +                    <property name="name"> +                        <cstring>lblTests</cstring> +                    </property> +                    <property name="text"> +                        <string>Number of tests:</string> +                    </property> +                    <property name="buddy" stdset="0"> +                        <cstring>intWidth</cstring> +                    </property> +                </widget> +                <widget class="QCheckBox" row="1" column="0"> +                    <property name="name"> +                        <cstring>chkBitBlt</cstring> +                    </property> +                    <property name="text"> +                        <string>bitBlt</string> +                    </property> +                    <property name="checked"> +                        <bool>true</bool> +                    </property> +                </widget> +                <widget class="QCheckBox" row="2" column="0"> +                    <property name="name"> +                        <cstring>chkFill</cstring> +                    </property> +                    <property name="text"> +                        <string>Fill</string> +                    </property> +                    <property name="checked"> +                        <bool>true</bool> +                    </property> +                </widget> +                <widget class="QCheckBox" row="3" column="0"> +                    <property name="name"> +                        <cstring>chkGradient</cstring> +                    </property> +                    <property name="text"> +                        <string>Gradients</string> +                    </property> +                    <property name="checked"> +                        <bool>true</bool> +                    </property> +                </widget> +                <widget class="QCheckBox" row="4" column="0" rowspan="1" colspan="2"> +                    <property name="name"> +                        <cstring>chkPixel</cstring> +                    </property> +                    <property name="text"> +                        <string>setPixel/getPixel</string> +                    </property> +                    <property name="checked"> +                        <bool>true</bool> +                    </property> +                </widget> +                <widget class="QCheckBox" row="5" column="0"> +                    <property name="name"> +                        <cstring>chkShape</cstring> +                    </property> +                    <property name="text"> +                        <string>Shapes</string> +                    </property> +                    <property name="checked"> +                        <bool>true</bool> +                    </property> +                </widget> +                <widget class="QCheckBox" row="6" column="0"> +                    <property name="name"> +                        <cstring>chkLayer</cstring> +                    </property> +                    <property name="text"> +                        <string>Layers</string> +                    </property> +                    <property name="checked"> +                        <bool>true</bool> +                    </property> +                </widget> +                <widget class="QCheckBox" row="7" column="0"> +                    <property name="name"> +                        <cstring>chkScale</cstring> +                    </property> +                    <property name="text"> +                        <string>Scaling</string> +                    </property> +                    <property name="checked"> +                        <bool>true</bool> +                    </property> +                </widget> +                <widget class="QCheckBox" row="8" column="0"> +                    <property name="name"> +                        <cstring>chkRotate</cstring> +                    </property> +                    <property name="text"> +                        <string>Rotating</string> +                    </property> +                    <property name="checked"> +                        <bool>true</bool> +                    </property> +                </widget> +                <widget class="QCheckBox" row="9" column="0"> +                    <property name="name"> +                        <cstring>chkRender</cstring> +                    </property> +                    <property name="text"> +                        <string>Rendering</string> +                    </property> +                    <property name="checked"> +                        <bool>true</bool> +                    </property> +                </widget> +                <widget class="QCheckBox" row="10" column="0"> +                    <property name="name"> +                        <cstring>chkSelection</cstring> +                    </property> +                    <property name="text"> +                        <string>Selection</string> +                    </property> +                    <property name="checked"> +                        <bool>true</bool> +                    </property> +                </widget> +                <widget class="QCheckBox" row="11" column="0" rowspan="1" colspan="2"> +                    <property name="name"> +                        <cstring>chkColorConversion</cstring> +                    </property> +                    <property name="text"> +                        <string>Color conversion</string> +                    </property> +                    <property name="checked"> +                        <bool>true</bool> +                    </property> +                </widget> +                <widget class="QCheckBox" row="12" column="0"> +                    <property name="name"> +                        <cstring>chkFilter</cstring> +                    </property> +                    <property name="text"> +                        <string>Filters</string> +                    </property> +                    <property name="checked"> +                        <bool>true</bool> +                    </property> +                </widget> +                <widget class="KIntNumInput" row="0" column="1"> +                    <property name="name"> +                        <cstring>intTestCount</cstring> +                    </property> +                    <property name="value"> +                        <number>10</number> +                    </property> +                    <property name="minValue"> +                        <number>0</number> +                    </property> +                    <property name="maxValue"> +                        <number>1000000</number> +                    </property> +                </widget> +                <widget class="QCheckBox" row="13" column="0"> +                    <property name="name"> +                        <cstring>chkReadBytes</cstring> +                    </property> +                    <property name="text"> +                        <string>Read bytes</string> +                    </property> +                    <property name="checked"> +                        <bool>true</bool> +                    </property> +                </widget> +                <widget class="QCheckBox" row="14" column="0"> +                    <property name="name"> +                        <cstring>chkWriteBytes</cstring> +                    </property> +                    <property name="text"> +                        <string>Write bytes</string> +                    </property> +                    <property name="checked"> +                        <bool>true</bool> +                    </property> +                </widget> +                <widget class="QCheckBox" row="15" column="0"> +                    <property name="name"> +                        <cstring>chkIterators</cstring> +                    </property> +                    <property name="text"> +                        <string>Iterators</string> +                    </property> +                    <property name="checked"> +                        <bool>true</bool> +                    </property> +                </widget> +                <widget class="QCheckBox" row="16" column="0"> +                    <property name="name"> +                        <cstring>chkPaintView</cstring> +                    </property> +                    <property name="text"> +                        <string>PaintView</string> +                    </property> +                    <property name="checked"> +                        <bool>true</bool> +                    </property> +                </widget> +                <widget class="QLayoutWidget" row="18" column="0" rowspan="1" colspan="2"> +                    <property name="name"> +                        <cstring>layout5</cstring> +                    </property> +                    <hbox> +                        <property name="name"> +                            <cstring>unnamed</cstring> +                        </property> +                        <widget class="QPushButton"> +                            <property name="name"> +                                <cstring>btnSelectAll</cstring> +                            </property> +                            <property name="text"> +                                <string>&Select All</string> +                            </property> +                        </widget> +                        <widget class="QPushButton"> +                            <property name="name"> +                                <cstring>btnDeselectAll</cstring> +                            </property> +                            <property name="text"> +                                <string>&Deselect All</string> +                            </property> +                        </widget> +                    </hbox> +                </widget> +                <widget class="QCheckBox" row="17" column="0"> +                    <property name="name"> +                        <cstring>chkPaintViewFPS</cstring> +                    </property> +                    <property name="text"> +                        <string>PaintView (fps)</string> +                    </property> +                    <property name="checked"> +                        <bool>true</bool> +                    </property> +                </widget> +            </grid> +        </widget> +    </grid> +</widget> +<tabstops> +    <tabstop>intTestCount</tabstop> +</tabstops> +<layoutdefaults spacing="6" margin="11"/> +<includehints> +    <includehint>knuminput.h</includehint> +    <includehint>knuminput.h</includehint> +</includehints> +</UI> diff --git a/krita/plugins/viewplugins/rotateimage/Makefile.am b/krita/plugins/viewplugins/rotateimage/Makefile.am new file mode 100644 index 000000000..55546f31e --- /dev/null +++ b/krita/plugins/viewplugins/rotateimage/Makefile.am @@ -0,0 +1,24 @@ +kritarcdir = $(kde_datadir)/kritaplugins +kritarc_DATA = rotateimage.rc + +EXTRA_DIST = $(kritarc_DATA) + + +INCLUDES  =  -I$(srcdir)/../../../sdk \ +	-I$(srcdir)/../../../core \ +	-I$(srcdir)/../../../kritacolor/ \ +	-I$(srcdir)/../../../ui \ +	$(KOFFICE_INCLUDES) \ +	$(all_includes) + +kde_module_LTLIBRARIES = kritarotateimage.la + +kritarotateimage_la_SOURCES = wdg_rotateimage.ui rotateimage.cc dlg_rotateimage.cc +noinst_HEADERS = wdg_rotateimage.h dlg_rotateimage.h rotateimage.h + +kritarotateimage_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) +kritarotateimage_la_LIBADD =  ../../../libkritacommon.la + +kde_services_DATA = kritarotateimage.desktop + +kritarotateimage_la_METASOURCES = AUTO diff --git a/krita/plugins/viewplugins/rotateimage/dlg_rotateimage.cc b/krita/plugins/viewplugins/rotateimage/dlg_rotateimage.cc new file mode 100644 index 000000000..9bf20fec5 --- /dev/null +++ b/krita/plugins/viewplugins/rotateimage/dlg_rotateimage.cc @@ -0,0 +1,147 @@ +/* + *  dlg_rotateimage.cc - part of KimageShop^WKrayon^WKrita + * + *  Copyright (c) 2004 Michael Thaler <michael.thaler@physik.tu-muenchen.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 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 <config.h> + +#include <math.h> + +#include <iostream> + +using namespace std; + +#include <qgroupbox.h> +#include <qradiobutton.h> +#include <qcheckbox.h> +#include <qlabel.h> + +#include <klocale.h> +#include <knuminput.h> +#include <kdebug.h> + +#include "dlg_rotateimage.h" +#include "wdg_rotateimage.h" + + +DlgRotateImage::DlgRotateImage( QWidget *  parent, +                const char * name) +    : super (parent, name, true, i18n("Rotate Image"), Ok | Cancel, Ok) +{ +    m_lock = false; + +    m_page = new WdgRotateImage(this, "rotate_image"); +    Q_CHECK_PTR(m_page); + +    setMainWidget(m_page); +    resize(m_page->sizeHint()); + +    connect(this, SIGNAL(okClicked()), +        this, SLOT(okClicked())); +        connect( m_page->doubleCustom, SIGNAL( valueChanged ( double ) ), +                 this, SLOT( slotAngleValueChanged( double ) ) ); + +} + +DlgRotateImage::~DlgRotateImage() +{ +    delete m_page; +} + +void DlgRotateImage::slotAngleValueChanged( double ) +{ +    m_page->radioCustom->setChecked(true); +} + +void DlgRotateImage::setAngle(double angle) +{ +    if (angle == 90) { +        m_page->radio90->setChecked(true); +    } +    else if (angle == 180) { +        m_page->radio180->setChecked(true); +    } +    else if (angle == 270) { +        m_page->radio270->setChecked(true); +    } +    else { +        m_page->radioCustom->setChecked(true); +        m_page->doubleCustom->setValue(angle); +    } + +    if (m_oldAngle != angle) +        resetPreview(); + +    m_oldAngle = angle; + +} + +double DlgRotateImage::angle() +{ +    double angle = 0; +    if (m_page->radio90->isChecked()) { +        angle = 90; +    } +    else if (m_page->radio180->isChecked()) { +        angle = 180; +    } +    else if (m_page->radio270->isChecked()) { +        angle = 270; +    } +    else { +        angle = qRound(m_page->doubleCustom->value()); +    } +    if (m_page->radioCW->isChecked()) { +        return angle; +    } +    else { +        return -angle; +    } +} + +void DlgRotateImage::setDirection (enumRotationDirection direction) +{ +    if (direction == CLOCKWISE) { +        m_page->radioCW->setChecked(true); +    } +    else if (direction== COUNTERCLOCKWISE) { +        m_page->radioCCW->setChecked(true); +    } +} + +enumRotationDirection DlgRotateImage::direction() +{ +    if (m_page->radioCCW->isChecked()) { +        return COUNTERCLOCKWISE; +    } +    else { +        return CLOCKWISE; +    } +} + +void DlgRotateImage::okClicked() +{ +    accept(); +} + +void DlgRotateImage::resetPreview() +{ +    // Code to update preview here. +} + +#include "dlg_rotateimage.moc" diff --git a/krita/plugins/viewplugins/rotateimage/dlg_rotateimage.h b/krita/plugins/viewplugins/rotateimage/dlg_rotateimage.h new file mode 100644 index 000000000..c6eef1350 --- /dev/null +++ b/krita/plugins/viewplugins/rotateimage/dlg_rotateimage.h @@ -0,0 +1,65 @@ +/* + *  dlg_rotateimage.h -- part of KimageShop^WKrayon^WKrita + * + *  Copyright (c) 2004 Michael Thaler <michael.thaler@physik.tu-muenchen.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 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. + */ +#ifndef DLG_ROTATEIMAGE +#define DLG_ROTATEIMAGE + +#include <kdialogbase.h> + +#include <kis_global.h> + +class WdgRotateImage; + +enum enumRotationDirection { +    CLOCKWISE, +    COUNTERCLOCKWISE +}; + + +class DlgRotateImage: public KDialogBase { +    typedef KDialogBase super; +    Q_OBJECT + +public: + +    DlgRotateImage(QWidget * parent = 0, +             const char* name = 0); +    ~DlgRotateImage(); + +    void setAngle(double w); +    double angle(); + +    void setDirection (enumRotationDirection direction); +    enumRotationDirection direction(); + +private slots: + +    void okClicked(); +    void resetPreview(); +    void slotAngleValueChanged( double ); + +private: + +    WdgRotateImage * m_page; +    double m_oldAngle; +    bool m_lock; + +}; + +#endif // DLG_ROTATEIMAGE diff --git a/krita/plugins/viewplugins/rotateimage/kritarotateimage.desktop b/krita/plugins/viewplugins/rotateimage/kritarotateimage.desktop new file mode 100644 index 000000000..6db00fc69 --- /dev/null +++ b/krita/plugins/viewplugins/rotateimage/kritarotateimage.desktop @@ -0,0 +1,40 @@ +[Desktop Entry] +Name=Rotate Image Plugin +Name[bg]=Приставка за въртене на изображение +Name[ca]=Connector de rotació d'imatge +Name[da]=Plugin for rotering af billede +Name[de]="Bild rotieren"-Modul +Name[el]=Πρόσθετο περιστροφής εικόνας +Name[es]=Complemento para girar la imagen +Name[et]=Pildi pööramise plugin +Name[fa]=چرخش وصلۀ تصویر +Name[fr]=Module de rotation d'images +Name[fy]=Plugin foar ôfbyldingsrotaasje +Name[gl]=Plugin para Rodar a Imaxe +Name[he]=תוסף לשינוי גודל של תמונה +Name[hu]=Képelforgató modul +Name[is]=Snúa mynd íforrit +Name[it]=Plugin per ruotare le immagini +Name[ja]=画像回転プラグイン +Name[km]=កម្មវិធីត្រឡប់រូបភាព +Name[nb]=Programtillegg for bilderotering +Name[nds]=Moduul för't Bilddreihen +Name[ne]=छवि प्लगइन परिक्रमा गर्नुहोस् +Name[nl]=Plugin voor afbeeldingrotatie +Name[pl]=Wtyczka obrotu obrazków +Name[pt]='Plugin' para Rodar a Imagem +Name[pt_BR]=Plugin para Rodar a Imagem +Name[ru]=Модуль вращения +Name[sk]=Modul rotácia obrázkov +Name[sl]=Vstavek za vrtenje slike +Name[sr]=Прикључак за ротирање слике +Name[sr@Latn]=Priključak za rotiranje slike +Name[sv]=Insticksprogram för rotera bild +Name[uk]=Втулок обертання зображень +Name[uz]=Rasmni burish plagini +Name[uz@cyrillic]=Расмни буриш плагини +Name[zh_TW]=旋轉圖片外掛程式 +ServiceTypes=Krita/ViewPlugin +Type=Service +X-KDE-Library=kritarotateimage +X-Krita-Version=2 diff --git a/krita/plugins/viewplugins/rotateimage/rotateimage.cc b/krita/plugins/viewplugins/rotateimage/rotateimage.cc new file mode 100644 index 000000000..8b85ef3ac --- /dev/null +++ b/krita/plugins/viewplugins/rotateimage/rotateimage.cc @@ -0,0 +1,134 @@ +/* + * rotateimage.cc -- Part of Krita + * + * Copyright (c) 2004 Michael Thaler + * + *  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 <math.h> + +#include <stdlib.h> + +#include <qslider.h> +#include <qpoint.h> + +#include <klocale.h> +#include <kiconloader.h> +#include <kinstance.h> +#include <kmessagebox.h> +#include <kstandarddirs.h> +#include <ktempfile.h> +#include <kdebug.h> +#include <kgenericfactory.h> + +#include <kis_doc.h> +#include <kis_config.h> +#include <kis_image.h> +#include <kis_layer.h> +#include <kis_global.h> +#include <kis_types.h> +#include <kis_view.h> +#include <kis_selection.h> + +#include "rotateimage.h" +#include "dlg_rotateimage.h" + +typedef KGenericFactory<RotateImage> RotateImageFactory; +K_EXPORT_COMPONENT_FACTORY( kritarotateimage, RotateImageFactory( "krita" ) ) + +// XXX: this plugin could also provide layer scaling/resizing +RotateImage::RotateImage(QObject *parent, const char *name, const QStringList &) +    : KParts::Plugin(parent, name) +{ + +    if ( parent->inherits("KisView") ) { +        setInstance(RotateImageFactory::instance()); +        setXMLFile(locate("data","kritaplugins/rotateimage.rc"), true); +        m_view = (KisView*) parent; +        (void) new KAction(i18n("&Rotate Image..."), 0, 0, this, SLOT(slotRotateImage()), actionCollection(), "rotateimage"); +        (void) new KAction(i18n("Rotate Image CW"), "rotate_cw", 0, this, SLOT(slotRotateImage90()), actionCollection(), "rotateImageCW90"); +        (void) new KAction(i18n("Rotate Image 1&80"), 0, 0, this, SLOT(slotRotateImage180()), actionCollection(), "rotateImage180"); +        (void) new KAction(i18n("Rotate Image CCW"), "rotate_ccw", 0, this, SLOT(slotRotateImage270()), actionCollection(), "rotateImageCCW90"); + +        (void) new KAction(i18n("&Rotate Layer..."), 0, 0, this, SLOT(slotRotateLayer()), actionCollection(), "rotatelayer"); + +        (void)new KAction(i18n("Rotate 1&80"), 0, m_view, SLOT(rotateLayer180()), actionCollection(), "rotateLayer180"); +        (void)new KAction(i18n("Rotate CCW"), "rotate_ccw", 0, m_view, SLOT(rotateLayerLeft90()), actionCollection(), "rotateLayerCCW90"); +        (void)new KAction(i18n("Rotate CW"), "rotate_cw", 0, m_view, SLOT(rotateLayerRight90()), actionCollection(), "rotateLayerCW90"); +    } +} + +RotateImage::~RotateImage() +{ +    m_view = 0; +} + +void RotateImage::slotRotateImage() +{ +    KisImageSP image = m_view->canvasSubject()->currentImg(); + +    if (!image) return; + +    DlgRotateImage * dlgRotateImage = new DlgRotateImage(m_view, "RotateImage"); +    Q_CHECK_PTR(dlgRotateImage); + +    dlgRotateImage->setCaption(i18n("Rotate Image")); + +        if (dlgRotateImage->exec() == QDialog::Accepted) { +        double angle = dlgRotateImage->angle(); +        angle *= M_PI/180; +        m_view->rotateCurrentImage(angle); +    } +    delete dlgRotateImage; +} + +void RotateImage::slotRotateImage90() +{ +    m_view->rotateCurrentImage( M_PI/2); +} + +void RotateImage::slotRotateImage180() +{ +    m_view->rotateCurrentImage( M_PI ); +} + + +void RotateImage::slotRotateImage270() +{ +    m_view->rotateCurrentImage( - M_PI/2 + M_PI*2 ); +} + +void RotateImage::slotRotateLayer() +{ +    KisImageSP image = m_view->canvasSubject()->currentImg(); + +    if (!image) return; + +    DlgRotateImage * dlgRotateImage = new DlgRotateImage(m_view, "RotateLayer"); +    Q_CHECK_PTR(dlgRotateImage); + +    dlgRotateImage->setCaption(i18n("Rotate Layer")); + +    if (dlgRotateImage->exec() == QDialog::Accepted) { +        double angle = dlgRotateImage->angle(); +        angle *= M_PI/180; +        m_view->rotateLayer(angle); +    } +    delete dlgRotateImage; +} + +#include "rotateimage.moc" diff --git a/krita/plugins/viewplugins/rotateimage/rotateimage.h b/krita/plugins/viewplugins/rotateimage/rotateimage.h new file mode 100644 index 000000000..7c09179c5 --- /dev/null +++ b/krita/plugins/viewplugins/rotateimage/rotateimage.h @@ -0,0 +1,49 @@ +/* + * rotateimage.h -- Part of Krita + * + * Copyright (c) 2004 Michael Thaler (michael.thaler@physik.tu-muenchen.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 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. */ + +#ifndef ROTATEIMAGE_H +#define ROTATEIMAGE_H + +#include <kparts/plugin.h> + +class KisView; + +class RotateImage : public KParts::Plugin +{ +    Q_OBJECT +public: +    RotateImage(QObject *parent, const char *name, const QStringList &); +    virtual ~RotateImage(); + +private slots: + +    void slotRotateImage(); +    void slotRotateImage90();  +    void slotRotateImage180();  +    void slotRotateImage270(); +    void slotRotateLayer(); + +private: + +    KisView * m_view; +    KisPainter * m_painter; + +}; + +#endif // ROTATEIMAGE_H diff --git a/krita/plugins/viewplugins/rotateimage/rotateimage.rc b/krita/plugins/viewplugins/rotateimage/rotateimage.rc new file mode 100644 index 000000000..b5f19e6ad --- /dev/null +++ b/krita/plugins/viewplugins/rotateimage/rotateimage.rc @@ -0,0 +1,25 @@ +<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd"> +<kpartgui library="kritarotateimage" version="7"> +<MenuBar> +    <Menu name="Image"><text>&Image</text> +        <Menu name="Rotate"><text>&Rotate</text> +           <Action name="rotateimage"/> +        <Separator /> +           <Action name="rotateImageCW90"/> +           <Action name="rotateImageCCW90"/> +           <Action name="rotateImage180"/> +       </Menu> +    </Menu> + +    <Menu name="Layer"><text>La&yer</text> +        <Menu name="Rotate"><text>&Rotate</text> +        <Action name="rotatelayer"/> +        <Separator /> +        <Action name="rotateLayerCW90"/> +        <Action name="rotateLayerCCW90"/> +        <Action name="rotateLayer180"/> +        </Menu> +    </Menu> +</MenuBar> + +</kpartgui> diff --git a/krita/plugins/viewplugins/rotateimage/wdg_rotateimage.ui b/krita/plugins/viewplugins/rotateimage/wdg_rotateimage.ui new file mode 100644 index 000000000..f672db7fc --- /dev/null +++ b/krita/plugins/viewplugins/rotateimage/wdg_rotateimage.ui @@ -0,0 +1,245 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>WdgRotateImage</class> +<widget class="QWidget"> +    <property name="name"> +        <cstring>WdgRotateImage</cstring> +    </property> +    <property name="geometry"> +        <rect> +            <x>0</x> +            <y>0</y> +            <width>489</width> +            <height>447</height> +        </rect> +    </property> +    <property name="caption"> +        <string>Rotate Image</string> +    </property> +    <grid> +        <property name="name"> +            <cstring>unnamed</cstring> +        </property> +        <widget class="QButtonGroup" row="0" column="0"> +            <property name="name"> +                <cstring>grpDirection</cstring> +            </property> +            <property name="title"> +                <string>Direction</string> +            </property> +            <grid> +                <property name="name"> +                    <cstring>unnamed</cstring> +                </property> +                <widget class="QLayoutWidget" row="0" column="0" rowspan="1" colspan="2"> +                    <property name="name"> +                        <cstring>layout6</cstring> +                    </property> +                    <hbox> +                        <property name="name"> +                            <cstring>unnamed</cstring> +                        </property> +                        <spacer> +                            <property name="name"> +                                <cstring>spacer3</cstring> +                            </property> +                            <property name="orientation"> +                                <enum>Horizontal</enum> +                            </property> +                            <property name="sizeType"> +                                <enum>Expanding</enum> +                            </property> +                            <property name="sizeHint"> +                                <size> +                                    <width>20</width> +                                    <height>20</height> +                                </size> +                            </property> +                        </spacer> +                        <widget class="QLabel"> +                            <property name="name"> +                                <cstring>pixmapLabel1</cstring> +                            </property> +                            <property name="pixmap"> +                                <pixmap>image0</pixmap> +                            </property> +                            <property name="scaledContents"> +                                <bool>false</bool> +                            </property> +                            <property name="alignment"> +                                <set>AlignCenter</set> +                            </property> +                        </widget> +                        <spacer> +                            <property name="name"> +                                <cstring>spacer1</cstring> +                            </property> +                            <property name="orientation"> +                                <enum>Horizontal</enum> +                            </property> +                            <property name="sizeType"> +                                <enum>Expanding</enum> +                            </property> +                            <property name="sizeHint"> +                                <size> +                                    <width>41</width> +                                    <height>20</height> +                                </size> +                            </property> +                        </spacer> +                        <widget class="QLabel"> +                            <property name="name"> +                                <cstring>pixmapLabel2</cstring> +                            </property> +                            <property name="pixmap"> +                                <pixmap>image1</pixmap> +                            </property> +                            <property name="scaledContents"> +                                <bool>false</bool> +                            </property> +                            <property name="alignment"> +                                <set>AlignCenter</set> +                            </property> +                        </widget> +                        <spacer> +                            <property name="name"> +                                <cstring>spacer2</cstring> +                            </property> +                            <property name="orientation"> +                                <enum>Horizontal</enum> +                            </property> +                            <property name="sizeType"> +                                <enum>Expanding</enum> +                            </property> +                            <property name="sizeHint"> +                                <size> +                                    <width>31</width> +                                    <height>20</height> +                                </size> +                            </property> +                        </spacer> +                    </hbox> +                </widget> +                <widget class="QRadioButton" row="1" column="1"> +                    <property name="name"> +                        <cstring>radioCW</cstring> +                    </property> +                    <property name="text"> +                        <string>C&lockwise</string> +                    </property> +                    <property name="checked"> +                        <bool>true</bool> +                    </property> +                </widget> +                <widget class="QRadioButton" row="1" column="0"> +                    <property name="name"> +                        <cstring>radioCCW</cstring> +                    </property> +                    <property name="text"> +                        <string>Cou&nter-clockwise</string> +                    </property> +                </widget> +            </grid> +        </widget> +        <widget class="QButtonGroup" row="1" column="0"> +            <property name="name"> +                <cstring>grpAngle</cstring> +            </property> +            <property name="title"> +                <string>Angle</string> +            </property> +            <vbox> +                <property name="name"> +                    <cstring>unnamed</cstring> +                </property> +                <widget class="QRadioButton"> +                    <property name="name"> +                        <cstring>radio90</cstring> +                    </property> +                    <property name="text"> +                        <string>90 &degrees</string> +                    </property> +                </widget> +                <widget class="QRadioButton"> +                    <property name="name"> +                        <cstring>radio180</cstring> +                    </property> +                    <property name="text"> +                        <string>180 d&egrees</string> +                    </property> +                </widget> +                <widget class="QRadioButton"> +                    <property name="name"> +                        <cstring>radio270</cstring> +                    </property> +                    <property name="text"> +                        <string>270 de&grees</string> +                    </property> +                </widget> +                <widget class="QLayoutWidget"> +                    <property name="name"> +                        <cstring>layout1</cstring> +                    </property> +                    <hbox> +                        <property name="name"> +                            <cstring>unnamed</cstring> +                        </property> +                        <widget class="QRadioButton"> +                            <property name="name"> +                                <cstring>radioCustom</cstring> +                            </property> +                            <property name="text"> +                                <string>&Custom:</string> +                            </property> +                            <property name="checked"> +                                <bool>true</bool> +                            </property> +                        </widget> +                        <widget class="KDoubleSpinBox"> +                            <property name="name"> +                                <cstring>doubleCustom</cstring> +                            </property> +                            <property name="maxValue"> +                                <number>360</number> +                            </property> +                            <property name="lineStep"> +                                <number>1</number> +                            </property> +                        </widget> +                    </hbox> +                </widget> +            </vbox> +        </widget> +        <spacer row="2" column="0"> +            <property name="name"> +                <cstring>spacer4</cstring> +            </property> +            <property name="orientation"> +                <enum>Vertical</enum> +            </property> +            <property name="sizeType"> +                <enum>Expanding</enum> +            </property> +            <property name="sizeHint"> +                <size> +                    <width>20</width> +                    <height>91</height> +                </size> +            </property> +        </spacer> +    </grid> +</widget> +<customwidgets> +</customwidgets> +<images> +    <image name="image0"> +        <data format="PNG" length="371">89504e470d0a1a0a0000000d494844520000002c0000002e0806000000534cfb0a0000013a494441545885ed994b0ec330084487aaf7bf32dd5689297f9b489d6d24fc3c02db106266a445c460a67c205daf7404a2821ddb9503de0c0b64800fc00251e043b00040eea28bc21615a50fb8cad904bc1db8230d02e0671cbeca01ee2bbaaecbc16184bfe8a405b4cd58a00c86c48eb588d3cc54b1a9f8c5114d0f0d5c81ce5dcd999c0e42e71f3f5dd0826245572dc9d1c586f20e57a8ed1cdead85f373808d2ecf01366a16f0cae54b5acc0236e80fdcadc701bfc52f99c77ae35065edf0c1ae58d31d78302c302d870d9dcc2c6083e4a2bbaa7b3a694cc5bbc39bc6a626a5dec39dc5e888bd06965cee8076741b40a4e82aa103b164e0442b6ed2af183fd6d69b500dce5ba4c978b6aeb962cc5434aa3a3b6efd56794fd7793e3b62d74d2f23da3ef939f0bfa36e54557d9a48cb8c98ad39f4b8e7e5e3803f91a1a32701eeec170000000049454e44ae426082</data> +    </image> +    <image name="image1"> +        <data format="PNG" length="363">89504e470d0a1a0a0000000d494844520000002c0000002e0806000000534cfb0a00000132494441545885ed994b12032108449b54ee7f65b3cd5440f92a56a5f7326f5a11451a63608b8806c6a0689857068b5a446177f6020361e8fdc04008fa0c30e086a6b4a4f3ba664cc418704212013041fb80b340bfa5847e9b825680022687f549d70016d03aac815d7d988be1a87c6be015acb7dc3ac7cd8167b091734160acbc861bc2029e4a77101690f661c9dd840f46a577b8012cc00157edb749d239dcc45de0e4f1d2a927705235aad4e50e5fa03f70b56c0778ab227bba90ec7d1d167eb62f30c0423f81b9696856aa7b3bcc487fa7f3543ccb18e54cfe3adca914332ce7aff9c6d83cb0e47205b4f176634fba4c68472c1978b69633a09db7f2753330bb91128ca7eb5e56b5aaac316069b756573ce54cf5b8e65fd3d0769870e6c920305bfb1e659296541ef0265d77bcbc0ef803779f9c39421cd9b50000000049454e44ae426082</data> +    </image> +</images> +<layoutdefaults spacing="6" margin="11"/> +<includehints> +    <includehint>knuminput.h</includehint> +</includehints> +</UI> diff --git a/krita/plugins/viewplugins/screenshot/Makefile.am b/krita/plugins/viewplugins/screenshot/Makefile.am new file mode 100644 index 000000000..616ebdcd6 --- /dev/null +++ b/krita/plugins/viewplugins/screenshot/Makefile.am @@ -0,0 +1,26 @@ +kritarcdir = $(kde_datadir)/kritaplugins +kritarc_DATA = screenshot-krita.rc + +EXTRA_DIST =  $(kritarc_DATA) + +INCLUDES =  -I$(srcdir)/../../../sdk \ +	-I$(srcdir)/../../../core \ +	-I$(srcdir)/../../../kritacolor/ \ +	-I$(srcdir)/../../../ui \ +	$(KOFFICE_INCLUDES) \ +	$(all_includes) + +kde_module_LTLIBRARIES = kritascreenshot.la + +kritascreenshot_la_SOURCES = screenshot.cpp ksnapshot.cpp regiongrabber.cpp ksnapshotwidget.ui +noinst_HEADERS = screenshot.h ksnapshot.h regiongrabber.h ksnapshotwidget.h ksnapshotwidget.ui.h + +kritascreenshot_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) +kritascreenshot_la_LIBADD =  ../../../libkritacommon.la  + +kde_services_DATA = kritascreenshot.desktop + +kritascreenshot_la_METASOURCES = AUTO + +messages: rc.cpp +	$(XGETTEXT) *.cpp -o $(podir)/kscreenshot_plugin.pot diff --git a/krita/plugins/viewplugins/screenshot/kritascreenshot.desktop b/krita/plugins/viewplugins/screenshot/kritascreenshot.desktop new file mode 100644 index 000000000..2420e5272 --- /dev/null +++ b/krita/plugins/viewplugins/screenshot/kritascreenshot.desktop @@ -0,0 +1,47 @@ +[Desktop Entry] +Name=Screenshot +Name[bg]=Снимка на екрана +Name[br]=Skrammpaker +Name[ca]=Captura de pantalla +Name[cy]=Sgrinlun +Name[da]=Skærmaftryk +Name[de]=Bildschirmphoto +Name[el]=Στιγμιότυπο οθόνης +Name[eo]=Ekrankopio +Name[es]=Captura de pantalla +Name[et]=Ekraanipilt +Name[fa]=تصویر پرده +Name[fr]=Capture d'écran +Name[fy]=Skermôfbylding +Name[ga]=Seat den Scáileán +Name[gl]=Captura de Pantalla +Name[he]=תמונת מסך +Name[hu]=Képernyőfelvétel +Name[is]=Skjámynd +Name[it]=Schermata +Name[ja]=スクリーンショット +Name[km]=រូបថតអេក្រង់ +Name[lv]=Ekrānattēls +Name[nb]=Skjermbilde +Name[nds]=Schirmbild +Name[ne]=स्क्रिनसट +Name[nl]=Schermafbeelding +Name[pl]=Zrzut ekranu +Name[pt]=Captura +Name[pt_BR]=Captura de Tela +Name[ru]=Снимок экрана +Name[se]=Šearbmagovva +Name[sk]=Snímač obrazovky +Name[sl]=Posnetek zaslona +Name[sr]=Снимак екрана +Name[sr@Latn]=Snimak ekrana +Name[sv]=Skärmdump +Name[uk]=Знімок екрана +Name[uz]=Skrinshot +Name[uz@cyrillic]=Скриншот +Name[zh_CN]=抓图 +Name[zh_TW]=螢幕快照 +ServiceTypes=Krita/ViewPlugin +Type=Service +X-KDE-Library=kritascreenshot +X-Krita-Version=2 diff --git a/krita/plugins/viewplugins/screenshot/ksnapshot.cpp b/krita/plugins/viewplugins/screenshot/ksnapshot.cpp new file mode 100644 index 000000000..77b4da4bb --- /dev/null +++ b/krita/plugins/viewplugins/screenshot/ksnapshot.cpp @@ -0,0 +1,499 @@ +/* + * KSnapshot + * + * (c) Richard J. Moore 1997-2002 + * (c) Matthias Ettrich 2000 + * (c) Aaron J. Seigo 2002 + * (c) Nadeem Hasan 2003 + * This adaptation: (c) Boudewijn Rempt 2005  + * + * Released under the GPL see file LICENSE for details. + */ + +#include <kapplication.h> +#include <klocale.h> +#include <kimageio.h> +#include <kfiledialog.h> +#include <kimagefilepreview.h> +#include <kmessagebox.h> +#include <kdebug.h> +#include <kprinter.h> +#include <kio/netaccess.h> +#include <ksavefile.h> +#include <ktempfile.h> + +#include <qbitmap.h> +#include <qdragobject.h> +#include <qimage.h> +#include <qclipboard.h> +#include <qvbox.h> + +#include <kaccel.h> +#include <knotifyclient.h> +#include <khelpmenu.h> +#include <kpopupmenu.h> +#include <kpushbutton.h> +#include <kstartupinfo.h> + +#include <qcursor.h> +#include <qregexp.h> +#include <qpainter.h> +#include <qpaintdevicemetrics.h> +#include <qwhatsthis.h> + +#include <stdlib.h> + +#include "ksnapshot.h" +#include "regiongrabber.h" +#include "ksnapshotwidget.h" + +#include <X11/Xlib.h> +#include <X11/Xatom.h> + +#include <config.h> + +#ifdef HAVE_X11_EXTENSIONS_SHAPE_H +#include <X11/extensions/shape.h> +#endif + +#include <kglobal.h> + +KSnapshot::KSnapshot(QWidget *parent, const char *name) +    : super(parent, name, false, QString::null, Ok|Cancel) +{ +    grabber = new QWidget( 0, 0, WStyle_Customize | WX11BypassWM ); +    Q_CHECK_PTR(grabber); +    grabber->move( -1000, -1000 ); +    grabber->installEventFilter( this ); + +#ifdef HAVE_X11_EXTENSIONS_SHAPE_H +    int tmp1, tmp2; +    //Check whether the extension is available +    haveXShape = XShapeQueryExtension( qt_xdisplay(), &tmp1, &tmp2 ); +#endif + +    QVBox *vbox = makeVBoxMainWidget(); +    mainWidget = new KSnapshotWidget( vbox, "mainWidget" ); +    Q_CHECK_PTR(mainWidget); + +    mainWidget->btnSave->hide(); +    mainWidget->btnPrint->hide(); +    connect(mainWidget, SIGNAL(startImageDrag()), SLOT(slotDragSnapshot())); + +    connect( mainWidget, SIGNAL( newClicked() ), SLOT( slotGrab() ) ); +    connect( mainWidget, SIGNAL( printClicked() ), SLOT( slotPrint() ) ); + +    grabber->show(); +    grabber->grabMouse( waitCursor ); +     +    snapshot = QPixmap::grabWindow( qt_xrootwin() ); +    updatePreview(); +    grabber->releaseMouse(); +    grabber->hide(); + +    KConfig *conf=KGlobal::config(); +    conf->setGroup("GENERAL"); +    mainWidget->setDelay(conf->readNumEntry("delay",0)); +    mainWidget->setMode( conf->readNumEntry( "mode", 0 ) ); +    mainWidget->setIncludeDecorations(conf->readBoolEntry("includeDecorations",true)); + +    connect( &grabTimer, SIGNAL( timeout() ), this, SLOT(  grabTimerDone() ) ); + +    KAccel* accel = new KAccel(this); +    Q_CHECK_PTR(accel); +    accel->insert(KStdAccel::Print, this, SLOT(slotPrint())); +    accel->insert(KStdAccel::New, this, SLOT(slotGrab())); + +    accel->insert( "Print2", Qt::Key_P, this, SLOT(slotPrint())); +    accel->insert( "New2", Qt::Key_N, this, SLOT(slotGrab())); +    accel->insert( "New3", Qt::Key_Space, this, SLOT(slotGrab())); + +    mainWidget->btnNew->setFocus(); +     +} + +KSnapshot::~KSnapshot() +{ +} + +bool KSnapshot::save( const QString &filename ) +{ +    return save( KURL::fromPathOrURL( filename )); +} + +bool KSnapshot::save( const KURL& url ) +{ +    QString type( KImageIO::type(url.path()) ); +    if ( type.isNull() ) +        type = "PNG"; + +    bool ok = false; + +    if ( url.isLocalFile() ) { +        KSaveFile saveFile( url.path() ); +        if ( saveFile.status() == 0 ) { +            if ( snapshot.save( saveFile.file(), type.latin1() ) ) +                ok = saveFile.close(); +        } +    } +    else { +        KTempFile tmpFile; +        tmpFile.setAutoDelete( true ); +        if ( tmpFile.status() == 0 ) { +            if ( snapshot.save( tmpFile.file(), type.latin1() ) ) { +                if ( tmpFile.close() ) +                    ok = KIO::NetAccess::upload( tmpFile.name(), url, this ); +            } +        } +    } + +    QApplication::restoreOverrideCursor(); +    if ( !ok ) { +        kdWarning() << "KSnapshot was unable to save the snapshot" << endl; + +        QString caption = i18n("Unable to Save Image"); +        QString text = i18n("KSnapshot was unable to save the image to\n%1.") +            .arg(url.prettyURL()); +        KMessageBox::error(this, text, caption); +    } + +    return ok; +} + +void KSnapshot::slotCopy() +{ +    QClipboard *cb = QApplication::clipboard(); +    cb->setPixmap( snapshot ); +} + +void KSnapshot::slotDragSnapshot() +{ +    QDragObject *drobj = new QImageDrag(snapshot.convertToImage(), this); +    Q_CHECK_PTR(drobj); +    drobj->setPixmap(mainWidget->preview()); +    drobj->dragCopy(); +} + +void KSnapshot::slotGrab() +{ +    hide(); +    if ( mainWidget->mode() == Region ) +    { +        rgnGrab = new RegionGrabber(); +        Q_CHECK_PTR(rgnGrab); +        connect( rgnGrab, SIGNAL( regionGrabbed( const QPixmap & ) ), +             SLOT( slotRegionGrabbed( const QPixmap & ) ) ); +    } +    else +    { +        if ( mainWidget->delay() ) +            grabTimer.start( mainWidget->delay() * 1000, true ); +        else { +            grabber->show(); +            grabber->grabMouse( crossCursor ); +        } +    } +} + +void KSnapshot::slotPrint() +{ +    KPrinter printer; +    if (snapshot.width() > snapshot.height()) +        printer.setOrientation(KPrinter::Landscape); +    else +        printer.setOrientation(KPrinter::Portrait); + +    qApp->processEvents(); + +    if (printer.setup(this, i18n("Print Screenshot"))) +    { +        qApp->processEvents(); + +        QPainter painter(&printer); +        QPaintDeviceMetrics metrics(painter.device()); + +        float w = snapshot.width(); +        float dw = w - metrics.width(); +        float h = snapshot.height(); +        float dh = h - metrics.height(); +        bool scale = false; + +        if ( (dw > 0.0) || (dh > 0.0) ) +            scale = true; + +        if ( scale ) { + +            QImage img = snapshot.convertToImage(); +            qApp->processEvents(); + +            float newh, neww; +            if ( dw > dh ) { +                neww = w-dw; +                newh = neww/w*h; +            } +            else { +                newh = h-dh; +                neww = newh/h*w; +            } + +            img = img.smoothScale( int(neww), int(newh), QImage::ScaleMin ); +            qApp->processEvents(); + +            int x = (metrics.width()-img.width())/2; +            int y = (metrics.height()-img.height())/2; + +            painter.drawImage( x, y, img); +        } +        else { +            int x = (metrics.width()-snapshot.width())/2; +            int y = (metrics.height()-snapshot.height())/2; +            painter.drawPixmap( x, y, snapshot ); +        } +    } + +    qApp->processEvents(); +} + +void KSnapshot::slotRegionGrabbed( const QPixmap &pix ) +{ +    if ( !pix.isNull() ) +    { +        snapshot = pix; +        updatePreview(); +        modified = true; +    } + +    delete rgnGrab; +    QApplication::restoreOverrideCursor(); +    show(); +} + +bool KSnapshot::eventFilter( QObject* o, QEvent* e) +{ +    if ( o == grabber && e->type() == QEvent::MouseButtonPress ) { +        QMouseEvent* me = (QMouseEvent*) e; +        if ( QWidget::mouseGrabber() != grabber ) +            return false; +        if ( me->button() == LeftButton ) +            performGrab(); +    } +    return false; +} + +void KSnapshot::updatePreview() +{ +    QImage img = snapshot.convertToImage(); +    double r1 = ((double) snapshot.height() ) / snapshot.width(); +    if ( r1 * mainWidget->previewWidth()  < mainWidget->previewHeight() ) +        img = img.smoothScale( mainWidget->previewWidth(), +                       int( mainWidget->previewWidth() * r1 )); +    else +        img = img.smoothScale( (int) (((double)mainWidget->previewHeight()) / r1), +                       (mainWidget->previewHeight() ) ); + +    QPixmap pm; +    pm.convertFromImage( img ); +    mainWidget->setPreview( pm ); +} + +void KSnapshot::grabTimerDone() +{ +    performGrab(); +    KNotifyClient::beep(i18n("The screen has been successfully grabbed.")); +} + +static  +Window findRealWindow( Window w, int depth = 0 ) +{ +    if( depth > 5 ) +        return None; +    static Atom wm_state = XInternAtom( qt_xdisplay(), "WM_STATE", False ); +    Atom type; +    int format; +    unsigned long nitems, after; +    unsigned char* prop; +    if( XGetWindowProperty( qt_xdisplay(), w, wm_state, 0, 0, False, AnyPropertyType, +                &type, &format, &nitems, &after, &prop ) == Success ) { +        if( prop != NULL ) +            XFree( prop ); +        if( type != None ) +            return w; +    } +    Window root, parent; +    Window* children; +    unsigned int nchildren; +    Window ret = None; +    if( XQueryTree( qt_xdisplay(), w, &root, &parent, &children, &nchildren ) != 0 ) { +        for( unsigned int i = 0; +             i < nchildren && ret == None; +             ++i ) +            ret = findRealWindow( children[ i ], depth + 1 ); +        if( children != NULL ) +            XFree( children ); +    } +    return ret; +} + +void KSnapshot::performGrab() +{ +    grabber->releaseMouse(); +    grabber->hide(); +    grabTimer.stop(); +    XGrabServer( qt_xdisplay()); +    if ( mainWidget->mode() == WindowUnderCursor ) { +        Window root; +        Window child; +        uint mask; +        int rootX, rootY, winX, winY; +        XQueryPointer( qt_xdisplay(), qt_xrootwin(), &root, &child, +                   &rootX, &rootY, &winX, &winY, +                   &mask); +        if( child == None ) +            child = qt_xrootwin(); +        if( !mainWidget->includeDecorations()) { +            Window real_child = findRealWindow( child ); +            if( real_child != None ) // test just in case +                child = real_child; +        } +        int x, y; +        unsigned int w, h; +        unsigned int border; +        unsigned int depth; +        XGetGeometry( qt_xdisplay(), child, &root, &x, &y, +                  &w, &h, &border, &depth ); +        w += 2 * border; +        h += 2 * border; + +        Window parent; +        Window* children; +        unsigned int nchildren; +        if( XQueryTree( qt_xdisplay(), child, &root, &parent, +                &children, &nchildren ) != 0 ) { +            if( children != NULL ) +                XFree( children ); +            int newx, newy; +            Window dummy; +            if( XTranslateCoordinates( qt_xdisplay(), parent, qt_xrootwin(), +                           x, y, &newx, &newy, &dummy )) { +                x = newx; +                y = newy; +            } +        } + +        snapshot = QPixmap::grabWindow( qt_xrootwin(), x, y, w, h ); + +#ifdef HAVE_X11_EXTENSIONS_SHAPE_H +        //No XShape - no work. +        if (haveXShape) { +            QBitmap mask(w, h); +            //As the first step, get the mask from XShape. +            int count, order; +            XRectangle* rects = XShapeGetRectangles( qt_xdisplay(), child, +                                 ShapeBounding, &count, &order); +            //The ShapeBounding region is the outermost shape of the window; +            //ShapeBounding - ShapeClipping is defined to be the border. +            //Since the border area is part of the window, we use bounding +            // to limit our work region +            if (rects) { +                //Create a QRegion from the rectangles describing the bounding mask. +                QRegion contents; +                for (int pos = 0; pos < count; pos++) +                    contents += QRegion(rects[pos].x, rects[pos].y, +                                rects[pos].width, rects[pos].height); +                XFree(rects); + +                //Create the bounding box. +                QRegion bbox(0, 0, snapshot.width(), snapshot.height()); +                 +                if( border > 0 ) { +                    contents.translate( border, border ); +                    contents += QRegion( 0, 0, border, h ); +                    contents += QRegion( 0, 0, w, border ); +                    contents += QRegion( 0, h - border, w, border ); +                    contents += QRegion( w - border, 0, border, h ); +                } +                 +                //Get the masked away area. +                QRegion maskedAway = bbox - contents; +                QMemArray<QRect> maskedAwayRects = maskedAway.rects(); + +                //Construct a bitmap mask from the rectangles +                QPainter p(&mask); +                p.fillRect(0, 0, w, h, Qt::color1); +                for (uint pos = 0; pos < maskedAwayRects.count(); pos++) +                    p.fillRect(maskedAwayRects[pos], Qt::color0); +                p.end(); + +                snapshot.setMask(mask); +            } +        } +#endif +    } +    else { +        snapshot = QPixmap::grabWindow( qt_xrootwin() ); +    } +    XUngrabServer( qt_xdisplay()); +    updatePreview(); +    QApplication::restoreOverrideCursor(); +    modified = true; +//     show(); +    slotOk(); +} + +void KSnapshot::setTime(int newTime) +{ +    mainWidget->setDelay(newTime); +} + +void KSnapshot::setURL( const QString &url ) +{ +    KURL newURL = KURL::fromPathOrURL( url ); +    if ( newURL == filename ) +        return; + +    filename = newURL; +} + +void KSnapshot::setGrabMode( int m ) +{ +    mainWidget->setMode( m ); +} + +void KSnapshot::slotMovePointer(int x, int y) +{ +    QCursor::setPos( x, y ); +} + +void KSnapshot::exit() +{ + +    KConfig *conf=KGlobal::config(); +    conf->setGroup("GENERAL"); +    conf->writeEntry("delay",mainWidget->delay()); +    conf->writeEntry("mode",mainWidget->mode()); +    conf->writeEntry("includeDecorations",mainWidget->includeDecorations()); +    KURL url = filename; +    url.setPass( QString::null ); +    conf->writePathEntry("filename",url.url()); + +    reject(); +} + +void KSnapshot::slotOk() +{ + +    KConfig *conf=KGlobal::config(); +    conf->setGroup("GENERAL"); +    conf->writeEntry("delay",mainWidget->delay()); +    conf->writeEntry("mode",mainWidget->mode()); +    conf->writeEntry("includeDecorations",mainWidget->includeDecorations()); +    KURL url = filename; +    url.setPass( QString::null ); +    conf->writePathEntry("filename",url.url()); + +    emit screenGrabbed(); + +    accept(); +} + +#include "ksnapshot.moc" diff --git a/krita/plugins/viewplugins/screenshot/ksnapshot.h b/krita/plugins/viewplugins/screenshot/ksnapshot.h new file mode 100644 index 000000000..7eeccb628 --- /dev/null +++ b/krita/plugins/viewplugins/screenshot/ksnapshot.h @@ -0,0 +1,135 @@ +// -*- c++ -*- +/*  + * (c) Richard J. Moore 1997-2002 + * (c) Matthias Ettrich 2000 + * (c) Aaron J. Seigo 2002 + * (c) Nadeem Hasan 2003 + * + *  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. + */ + +#ifndef KSNAPSHOT_H +#define KSNAPSHOT_H + +#include <qlabel.h> +#include <qpixmap.h> +#include <qtimer.h> + +#include <dcopclient.h> +#include <kglobalsettings.h> +#include <kdialogbase.h> +#include <kurl.h> + +class RegionGrabber; +class KSnapshotWidget; + +class KSnapshotThumb : public QLabel +{ +    Q_OBJECT + +public: +    KSnapshotThumb(QWidget *parent, const char *name = 0) +        : QLabel(parent, name) +        { +            setAlignment(AlignHCenter | AlignVCenter); +        } +    virtual ~KSnapshotThumb() {} + +signals: +    void startDrag(); + +protected: +    void mousePressEvent(QMouseEvent * e) +        { +            mClickPt = e->pos(); +        } + +    void mouseMoveEvent(QMouseEvent * e) +        { +            if (mClickPt != QPoint(0, 0) && +                (e->pos() - mClickPt).manhattanLength() > KGlobalSettings::dndEventDelay()) +            { +                mClickPt = QPoint(0, 0); +                emit startDrag(); +            } +        } + +    void mouseReleaseEvent(QMouseEvent * /*e*/) +        { +            mClickPt = QPoint(0, 0); +        } + +    QPoint mClickPt; +}; + +class KSnapshot : public KDialogBase +{ +    typedef KDialogBase super; +    Q_OBJECT + +public: +    KSnapshot(QWidget *parent= 0, const char *name= 0); +    ~KSnapshot(); + +    enum CaptureMode { FullScreen=0, WindowUnderCursor=1, Region=2 }; + +    bool save( const QString &filename ); +    bool save( const KURL& url ); + +    QString url() const { return filename.url(); } + +signals: +    void screenGrabbed(); + +protected slots: +    void slotGrab(); +    void slotCopy(); +    void slotPrint(); +    void slotMovePointer( int x, int y ); + +    void setTime(int newTime); +    void setURL(const QString &newURL); +    void setGrabMode( int m ); +    void exit(); + +    void slotOk(); + + +protected: +    void reject() { close(); } +    bool eventFilter( QObject*, QEvent* ); +     +private slots: +    void grabTimerDone(); +    void slotDragSnapshot(); +    void slotRegionGrabbed( const QPixmap & ); + +private: +    void updatePreview(); +    void performGrab(); +    void autoincFilename(); + +    QPixmap snapshot; +    QTimer grabTimer; +    QWidget* grabber; +    KURL filename; +    KSnapshotWidget *mainWidget; +    RegionGrabber *rgnGrab; +    bool modified; +    bool haveXShape; +}; + +#endif // KSNAPSHOT_H + diff --git a/krita/plugins/viewplugins/screenshot/ksnapshotwidget.ui b/krita/plugins/viewplugins/screenshot/ksnapshotwidget.ui new file mode 100644 index 000000000..bd24e6efa --- /dev/null +++ b/krita/plugins/viewplugins/screenshot/ksnapshotwidget.ui @@ -0,0 +1,335 @@ +<!DOCTYPE UI><UI version="3.2" stdsetdef="1"> +<class>KSnapshotWidget</class> +<widget class="QWidget"> +    <property name="name"> +        <cstring>KSnapshotWidget</cstring> +    </property> +    <property name="geometry"> +        <rect> +            <x>0</x> +            <y>0</y> +            <width>358</width> +            <height>241</height> +        </rect> +    </property> +    <grid> +        <property name="name"> +            <cstring>unnamed</cstring> +        </property> +        <property name="margin"> +            <number>0</number> +        </property> +        <widget class="KSnapshotThumb" row="0" column="0" rowspan="4" colspan="3"> +            <property name="name"> +                <cstring>lblImage</cstring> +            </property> +            <property name="minimumSize"> +                <size> +                    <width>200</width> +                    <height>130</height> +                </size> +            </property> +            <property name="toolTip" stdset="0"> +                <string>Thumbnail of the current snapshot</string> +            </property> +            <property name="whatsThis" stdset="0"> +                <string>This is a thumbnail of the current snapshot. + +The image can be dragged to another application or document to copy the full screenshot there. Try it with the Konqueror file manager.</string> +            </property> +        </widget> +        <widget class="KPushButton" row="0" column="3"> +            <property name="name"> +                <cstring>btnNew</cstring> +            </property> +            <property name="text"> +                <string>&New Snapshot</string> +            </property> +            <property name="iconSet"> +                <iconset>"tool_screenshot"</iconset> +            </property> +            <property name="whatsThis" stdset="0"> +                <string>Click this button to take a new snapshot.</string> +            </property> +        </widget> +        <widget class="KPushButton" row="2" column="3"> +            <property name="name"> +                <cstring>btnSave</cstring> +            </property> +            <property name="text"> +                <string>&Save As...</string> +            </property> +            <property name="iconSet"> +                <iconset>"filesave"</iconset> +            </property> +            <property name="whatsThis" stdset="0"> +                <string>Click this button to save the current snapshot. To quickly save the snapshot without showing the file dialog, press Ctrl+Shift+S. The filename is automatically incremented after each save.</string> +            </property> +        </widget> +        <spacer row="1" column="3"> +            <property name="name"> +                <cstring>Spacer6</cstring> +            </property> +            <property name="orientation"> +                <enum>Vertical</enum> +            </property> +            <property name="sizeType"> +                <enum>Expanding</enum> +            </property> +            <property name="sizeHint"> +                <size> +                    <width>16</width> +                    <height>16</height> +                </size> +            </property> +        </spacer> +        <widget class="KPushButton" row="3" column="3"> +            <property name="name"> +                <cstring>btnPrint</cstring> +            </property> +            <property name="text"> +                <string>&Print...</string> +            </property> +            <property name="iconSet"> +                <iconset>"fileprint"</iconset> +            </property> +            <property name="whatsThis" stdset="0"> +                <string>Click this button to print the current screenshot.</string> +            </property> +        </widget> +        <widget class="Line" row="4" column="0" rowspan="1" colspan="4"> +            <property name="name"> +                <cstring>line1</cstring> +            </property> +            <property name="frameShape"> +                <enum>HLine</enum> +            </property> +            <property name="frameShadow"> +                <enum>Sunken</enum> +            </property> +            <property name="orientation"> +                <enum>Horizontal</enum> +            </property> +        </widget> +        <widget class="QSpinBox" row="6" column="1"> +            <property name="name"> +                <cstring>spinDelay</cstring> +            </property> +            <property name="suffix"> +                <string> sec</string> +            </property> +            <property name="specialValueText"> +                <string>No delay</string> +            </property> +            <property name="toolTip" stdset="0"> +                <string>Snapshot delay in seconds</string> +            </property> +            <property name="whatsThis" stdset="0"> +                <string><qt> +This is the number of seconds to wait after clicking the <i>New Snapshot</i> button before taking the snapshot. +<p> +This is very useful for getting windows, menus and other items on the screen set up just the way you want. +<p> +If <i>no delay</i> is set, the program will wait for a mouse click before taking a snapshot. +</p> +</qt></string> +            </property> +        </widget> +        <widget class="QLabel" row="6" column="0"> +            <property name="name"> +                <cstring>lblDelay</cstring> +            </property> +            <property name="text"> +                <string>Snapshot &delay:</string> +            </property> +            <property name="buddy" stdset="0"> +                <cstring>spinDelay</cstring> +            </property> +        </widget> +        <widget class="QLabel" row="5" column="0"> +            <property name="name"> +                <cstring>textLabel1</cstring> +            </property> +            <property name="text"> +                <string>Cap&ture mode:</string> +            </property> +            <property name="buddy" stdset="0"> +                <cstring>comboMode</cstring> +            </property> +        </widget> +        <spacer row="6" column="2" rowspan="1" colspan="2"> +            <property name="name"> +                <cstring>Spacer1</cstring> +            </property> +            <property name="orientation"> +                <enum>Horizontal</enum> +            </property> +            <property name="sizeType"> +                <enum>Expanding</enum> +            </property> +            <property name="sizeHint"> +                <size> +                    <width>156</width> +                    <height>16</height> +                </size> +            </property> +        </spacer> +        <widget class="QCheckBox" row="7" column="0" rowspan="1" colspan="4"> +            <property name="name"> +                <cstring>cbIncludeDecorations</cstring> +            </property> +            <property name="text"> +                <string>Include &window decorations</string> +            </property> +            <property name="checked"> +                <bool>true</bool> +            </property> +            <property name="whatsThis" stdset="0"> +                <string>When enabled, snapshot of a window will also include the window decorations</string> +            </property> +        </widget> +        <widget class="QComboBox" row="5" column="1" rowspan="1" colspan="3"> +            <item> +                <property name="text"> +                    <string>Full Screen</string> +                </property> +            </item> +            <item> +                <property name="text"> +                    <string>Window Under Cursor</string> +                </property> +            </item> +            <item> +                <property name="text"> +                    <string>Region</string> +                </property> +            </item> +            <property name="name"> +                <cstring>comboMode</cstring> +            </property> +            <property name="whatsThis" stdset="0"> +                <string><qt>Using this menu, you can select from the three following snapshot modes: +<p> +<b>Full Screen</b> - captures the entire desktop.<br> +<b>Window Under Cursor</b> - captures only the window (or menu) that is under the mouse cursor when the snapshot is taken.<br> +<b>Region</b> - captures only the region of the desktop that you specify. When taking a new snapshot in this mode you will be able to select any area of the screen by clicking and dragging the mouse.</p></qt></string> +            </property> +        </widget> +        <spacer row="8" column="1"> +            <property name="name"> +                <cstring>spacer3</cstring> +            </property> +            <property name="orientation"> +                <enum>Vertical</enum> +            </property> +            <property name="sizeType"> +                <enum>Expanding</enum> +            </property> +            <property name="sizeHint"> +                <size> +                    <width>20</width> +                    <height>31</height> +                </size> +            </property> +        </spacer> +    </grid> +</widget> +<customwidgets> +    <customwidget> +        <class>KSnapshotThumb</class> +        <header location="local">ksnapshot.h</header> +        <sizehint> +            <width>-1</width> +            <height>-1</height> +        </sizehint> +        <container>0</container> +        <sizepolicy> +            <hordata>5</hordata> +            <verdata>5</verdata> +            <horstretch>0</horstretch> +            <verstretch>0</verstretch> +        </sizepolicy> +        <pixmap>image0</pixmap> +        <signal>startDrag()</signal> +    </customwidget> +</customwidgets> +<images> +    <image name="image0"> +        <data format="XPM.GZ" length="5230">789c9597db4e1d4b0e86eff31428be8b46b5fb54dd551acd051020211c4320c0682eecaa5e9ccf90005bf3ee53cbbfe9d9c9c548a38ea27c2977b5cbfe6dd7fae3c3c2e1cee6c2873fde3d3cf2e3595a48a77cbff0213f5d5dbdfcf35ffff8f3ddfba65998fff161a179ffb777ef771f17d2c2d6cdf53807c705a889cdac6ee72c47736eebd637b5f2b672d70ecd30e744ca7d9b9a4ad7579587363433e527e5d072abefbb03636978ceb4a31c5bc13a91716ad41f89e0aec2fe74abcc6d6ad5f9e4945357375ef75f997357751dd61d19c71afb61bdef421b951f274ebaffb6716cb3f2b2f230f18d3183dd95b1b441d7d59f2e94757ccf1b27eceff69563618d0f5dcfd9d7beeb7a5dd7f3fac6fb4ee32b87c619f1168d976f7d6ff6df26d6ef4b301e1bac7f54f63e747a5e87f5c173276aff605c22a8fefc540e5e3af5972f956359577bf2c6d978cb78d6697edc9eb2f8b143fed7945359d778b0e6c3e7be81bf7465dce23cf4ac3c16567f19fecefaae53bd081b7baccbb131b7d05f679ca03f27c6b9d1f388c6bbaffab7f80dca4d1fed7bfafdbeedb9533d490f1e2ae8d5693ccacb83d77cd027e3d4416faa97beefa3d7f8f086f168f9d9020f43a3f5c5aa877e28eb88f74fe319becfaa873e0c15de775f95639f3dec37c143d361bf2be3cef4b76bdcb7d84ff5d2cbd0227facf1ecd360fa67d54b9f078ffcd10f636e11ff53e3847853ad3c1b668837e9fe43358c2df45a81430b3db2e6676842d368fd48abdc068b87e0fd2e788bf792b21f861e7afd0e0e5ce37dcdd7d0872218e5d789f57b3218a71ae7bb501eca3af67b510e21c05fd27a1b6218ac3ef17d0ed68fe8cb1be3fc6e5159863ca0bfed824340fe687d62c4838c23f677f0370de380fcdd2be7e03dfab1d6cf300bcd80fa80bfb358dbf9547fa18abe413d68fe421d63ade7737aded094cf63fdcc38f4d0bfee17dac2d08380a3a0dff24cb90bdc23ffaa87e0636c912fed87612e38d4df1e982bc4dbdd29872001f14aca319413eb793e83cbfbe8af27606e4c0f5f8d3bcb7763ec6b8da73b57e69083d61f9d82b9b5fada31f635fcaf8d7b7b5ffb41f16e34ff34fe214dfc0c8e1ef1a22330bfcdc345e31e4c33e3c1e6e181b1609e3ac43f8759803e8cd9f2e7e0ff18ab80ef5d8239e2fc0ef129f90ff0bf0773347fee8d13ce279bc6b34af5c61abf58157bf4b765b05435f4abfec726968c2b67e536fa80fe388279067f680d2c750dff75fe9766da07e44bc02521ba4e1d584c1fb261dcc23fd97f63f8c3af136bfc687362c4e76962ed8fac7a2ecdb7853f7c63ec6bf467bd3fc421c680780c60b6f9275fc045aea84fadaf18a2e0fc04ff0237bd9e8fefc0d236e8ef3f8d83c57fdd38daf94edeb886be74fec618b3ed7f3731e66b0fe67a403e76c0454ef8de9231dbfe9f8dc5fc47be38a6887ad2f950964d2fdc1a27d3c7b6710693f6ef9864b4fdb4ffc6cc5540fea0972c339c87afc1c9f4443a5fe2c84d40bd2f82cb3ae6c7b1716dbc37b1e68bf5be118b7e3dead78125d87d0bfa99bd7d8fb78c1bdb4fcfcfd51bcb9d716bebda3fb8966cf7cf57709103f2e327c6fe5a2fdc4ab4fb01deef5283fa65d50ffb54c13fd67ec37d61e845fb070f8571df7c341eec7e7a691c6ae453fb771937d1fa999ebfa43358bf573d3327c6fdd0a9de59b87414e59f60911ef3ff07380d16bf0b63b6fbb8ce0f4e523a80ee8ff8a5f21fe83f384f2e8cf9d419db7d4bb4bff32cb1dd871ae38c79417962dd9f8f2786bfaa3fa992ddbf68d5d8d6797d62dc27b4bf4a9bdeee5be7c619efbb169c2b9bb7aa67e972857a67d59bf8943cf4a6f5237dae3b9c3f4f8cef5713637e6a3c6548e546a7eb87e0b28e7cf7c68ddd2fb15f28acf166bd2f484c19f921f8cbc57de84ff52c397b8f7e178d7bbb7f7e9f18f743d593ccd210d12f9e8c05fd8417c1e5e704e2afefa7aa5cf850ff4fc6a1473debfc4d7561c4ebd3c48897f69fd4e4d8eb7e4efb736a0b23fe9adfd465bb3f388d6ff22933fa1df6f7597ad483c62371f6e6ff8671b6f89e198fb8cfb0ea3f49619c6f6562cc27d5474a7906e6b589d1df549f29e78479450fe0b1c2fc67d5731a0ba33ffc97a167fd7d92ebb1b1f9a87acdcdd8a23ff2e3c4a81fed0fb91bbb88f8e9f772f9b9c6b8bfac187bd41febbcc8c35831f4bb6edc227eeec8b847bc58ef0f398d91a1179d6f391746bdebfd60ac4716b0180bd8a97e473f8ea2dfdb7d9c3f8e1cff8f8760057b27e57f92cb6e743377e24efff29cb97377e12edd55b190c99eddb5bb71b7eeceddbb07f7e89edc0ff7d33dbb17f7ea16dd925b761fdd8a63d8174f52b15e756bee93fbecd6dd17b7e136dd96db763b6ed77d2dd67bee9bdb77078ed49e8b27b7c5fabb3b7447eed855ae768d6bcbd339ef7a37b8e022392a2734fbd1dd119350a24c23cde8844ee98ccee9c2f9c2977445d77443b793fd8ceee89e1ee8919ee807fdb4e7995ee8b5d82fd252b15ffe8bfd097da4155aa535fa34597fa6f5f2f717da28f69bb445dbb433d99fd22e7da53dfa3659efd3017da7c3f2af233aa68aeadfec1b6aa9236fd63d0d14ca15c0719913737b965fedcbf0c83cc29a677cc2a77cc6e77cc1977cc5d7c5fee637fbdbb2db9d5adff343b17ee427fec1737ee69762fffa9bfd222ff17259fdc82bbcca6bfc893ff33a7fe10ddee42ddee69ddfec77f92beff137dee703fece877cc4c7aee58a6b6ee8b8fc10ed7eb13f635f9a4bc5e54719477152ba671977a505c84845c57222a7bfd89fcb999ccb855cca955cbfc5546ee456ee68b14cf67b799047799aec2fdc92fc28999cef567224cff222afb2c85b32e36d599265f9282bb23ad95fba6559934f2593f3e798b74acc8fd5f6b3accb17d9904dd9926db3a7520d1fdd37d9915df95a72599e1291566df7e49beccb817c974339829eb55e56dc7e51ec0d2dcbb1545297a791563af1c5eff2d3beb4faf8562f568f0744745b9e9d5f1f7992d5e412a186ffef7afff7dfdffd077c99ae99</data> +    </image> +</images> +<connections> +    <connection> +        <sender>comboMode</sender> +        <signal>activated(int)</signal> +        <receiver>KSnapshotWidget</receiver> +        <slot>slotModeChanged(int)</slot> +    </connection> +    <connection> +        <sender>btnNew</sender> +        <signal>clicked()</signal> +        <receiver>KSnapshotWidget</receiver> +        <slot>slotNewClicked()</slot> +    </connection> +    <connection> +        <sender>btnPrint</sender> +        <signal>clicked()</signal> +        <receiver>KSnapshotWidget</receiver> +        <slot>slotPrintClicked()</slot> +    </connection> +    <connection> +        <sender>btnSave</sender> +        <signal>clicked()</signal> +        <receiver>KSnapshotWidget</receiver> +        <slot>slotSaveClicked()</slot> +    </connection> +    <connection> +        <sender>lblImage</sender> +        <signal>startDrag()</signal> +        <receiver>KSnapshotWidget</receiver> +        <slot>slotStartDrag()</slot> +    </connection> +</connections> +<tabstops> +    <tabstop>btnNew</tabstop> +    <tabstop>btnSave</tabstop> +    <tabstop>btnPrint</tabstop> +    <tabstop>comboMode</tabstop> +    <tabstop>spinDelay</tabstop> +    <tabstop>cbIncludeDecorations</tabstop> +</tabstops> +<includes> +    <include location="global" impldecl="in implementation">kdialog.h</include> +    <include location="global" impldecl="in implementation">kiconloader.h</include> +    <include location="global" impldecl="in implementation">kglobalsettings.h</include> +    <include location="local" impldecl="in implementation">ksnapshotwidget.ui.h</include> +</includes> +<signals> +    <signal>newClicked()</signal> +    <signal>saveClicked()</signal> +    <signal>printClicked()</signal> +    <signal>startImageDrag()</signal> +</signals> +<slots> +    <slot access="protected" specifier="non virtual">slotModeChanged( int mode )</slot> +    <slot access="protected" specifier="non virtual">slotNewClicked()</slot> +    <slot access="protected" specifier="non virtual">slotSaveClicked()</slot> +    <slot access="protected" specifier="non virtual">slotPrintClicked()</slot> +    <slot access="protected" specifier="non virtual">slotStartDrag()</slot> +    <slot specifier="non virtual" returnType="int">previewWidth()</slot> +    <slot specifier="non virtual" returnType="int">previewHeight()</slot> +</slots> +<functions> +    <function specifier="non virtual">setPreview( const QPixmap & pm )</function> +    <function specifier="non virtual">setDelay( int i )</function> +    <function specifier="non virtual">setIncludeDecorations( bool b )</function> +    <function specifier="non virtual">setMode( int mode )</function> +    <function specifier="non virtual" returnType="int">delay()</function> +    <function specifier="non virtual" returnType="bool">includeDecorations()</function> +    <function specifier="non virtual" returnType="int">mode()</function> +    <function specifier="non virtual" returnType="QPixmap">preview()</function> +</functions> +<pixmapfunction>SmallIconSet</pixmapfunction> +<layoutdefaults spacing="6" margin="11"/> +<layoutfunctions spacing="KDialog::spacingHint" margin="KDialog::marginHint"/> +</UI> diff --git a/krita/plugins/viewplugins/screenshot/ksnapshotwidget.ui.h b/krita/plugins/viewplugins/screenshot/ksnapshotwidget.ui.h new file mode 100644 index 000000000..e61b0c6ec --- /dev/null +++ b/krita/plugins/viewplugins/screenshot/ksnapshotwidget.ui.h @@ -0,0 +1,118 @@ +/**************************************************************************** +** ui.h extension file, included from the uic-generated form implementation. +** +** If you wish to add, delete or rename functions or slots use +** Qt Designer which will update this file, preserving your code. Create an +** init() function in place of a constructor, and a destroy() function in +** place of a destructor. +*****************************************************************************/ + + +void KSnapshotWidget::slotModeChanged( int mode ) +{ +    switch ( mode ) +    { +    case 0: +    lblDelay->setEnabled(true); +    spinDelay->setEnabled(true); +    cbIncludeDecorations->setEnabled(false); +    break; +    case 1: +    lblDelay->setEnabled(true); +    spinDelay->setEnabled(true); +    cbIncludeDecorations->setEnabled(true); +    break; +    case 2: +    lblDelay->setEnabled(false); +    spinDelay->setEnabled(false); +    cbIncludeDecorations->setEnabled(false); +    default: +    break; +    } +} + + +void KSnapshotWidget::setPreview( const QPixmap &pm ) +{ +    lblImage->setPixmap(pm); +} + + +void KSnapshotWidget::setDelay( int i ) +{ +    spinDelay->setValue(i); +} + + +void KSnapshotWidget::setIncludeDecorations( bool b ) +{ +    cbIncludeDecorations->setChecked(b); +} + + +void KSnapshotWidget::setMode( int mode ) +{ +    comboMode->setCurrentItem(mode); +    slotModeChanged(mode); +} + + +int KSnapshotWidget::delay() +{ +    return spinDelay->value(); +} + + +bool KSnapshotWidget::includeDecorations() +{ +    return cbIncludeDecorations->isChecked(); +} + + +int KSnapshotWidget::mode() +{ +    return comboMode->currentItem(); +} + + +void KSnapshotWidget::slotNewClicked() +{ +    emit newClicked(); +} + + +void KSnapshotWidget::slotSaveClicked() +{ +    emit saveClicked(); +} + + +void KSnapshotWidget::slotPrintClicked() +{ +    emit printClicked(); +} + + +void KSnapshotWidget::slotStartDrag() +{ +    emit startImageDrag(); +} + + +QPixmap KSnapshotWidget::preview() +{ +    return *lblImage->pixmap(); +} + + +int KSnapshotWidget::previewWidth() +{ +    return lblImage->width(); +} + + +int KSnapshotWidget::previewHeight() +{ +    return lblImage->height(); +} + diff --git a/krita/plugins/viewplugins/screenshot/main.cpp b/krita/plugins/viewplugins/screenshot/main.cpp new file mode 100644 index 000000000..70f613495 --- /dev/null +++ b/krita/plugins/viewplugins/screenshot/main.cpp @@ -0,0 +1,38 @@ +#include <kapplication.h> +#include "ksnapshot.h" +#include <kimageio.h> +#include <klocale.h> +#include <kcmdlineargs.h> +#include <kaboutdata.h> +#include <kiconloader.h> + +static const char description[] = +    I18N_NOOP("KDE Screenshot Utility"); + +int main(int argc, char **argv) +{ +  KAboutData aboutData( "ksnapshot", I18N_NOOP("KSnapshot"), +    KSNAPVERSION, description, KAboutData::License_GPL, +    "(c) 1997-2003, Richard J. Moore,\n(c) 2000, Matthias Ettrich,\n(c) 2002-2003 Aaron J. Seigo"); +  aboutData.addAuthor("Richard J. Moore",0, "rich@kde.org"); +  aboutData.addAuthor("Matthias Ettrich",0, "ettrich@kde.org"); +  aboutData.addAuthor("Aaron J. Seigo", 0, "aseigo@kde.org"); +  aboutData.addCredit( "Nadeem Hasan", "Region Grabbing\nReworked GUI", +      "nhasan@kde.org" ); +  KCmdLineArgs::init( argc, argv, &aboutData ); + +  KApplication app; + +  KImageIO::registerFormats(); + +  // Create top level window +  KSnapshot *toplevel= new KSnapshot(); +  Q_CHECK_PTR(toplevel); +  app.dcopClient()->setDefaultObject( toplevel->objId() ); +  toplevel->setCaption( app.makeStdCaption("") ); +  toplevel->setIcon(SmallIcon("tool_screenshot")); +  app.setMainWidget(toplevel); +  toplevel->show(); +  return app.exec(); +} + diff --git a/krita/plugins/viewplugins/screenshot/regiongrabber.cpp b/krita/plugins/viewplugins/screenshot/regiongrabber.cpp new file mode 100644 index 000000000..f42f6b941 --- /dev/null +++ b/krita/plugins/viewplugins/screenshot/regiongrabber.cpp @@ -0,0 +1,170 @@ +/* + * This file was copied from ksnapshot + * + * Copyright (C) 2003 Nadeem Hasan <nhasan@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library 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 "regiongrabber.h" + +#include <qpainter.h> +#include <qpalette.h> +#include <qstyle.h> +#include <qtimer.h> +#include <qtooltip.h> + +#include <kglobalsettings.h> + +SizeTip::SizeTip( QWidget *parent, const char *name ) +    : QLabel( parent, name, WStyle_Customize | WX11BypassWM | +      WStyle_StaysOnTop | WStyle_NoBorder | WStyle_Tool ) +{ +  setMargin( 2 ); +  setIndent( 0 ); +  setFrameStyle( QFrame::Plain | QFrame::Box ); + +  setPalette( QToolTip::palette() ); +} + +void SizeTip::setTip( const QRect &rect ) +{ +  QString tip = QString( "%1x%2" ).arg( rect.width() ) +      .arg( rect.height() ); + +  setText( tip ); +  adjustSize(); + +  positionTip( rect ); +} + +void SizeTip::positionTip( const QRect &rect ) +{ +  QRect tipRect = geometry(); +  tipRect.moveTopLeft( QPoint( 0, 0 ) ); + +  if ( rect.intersects( tipRect ) ) +  { +    QRect deskR = KGlobalSettings::desktopGeometry( QPoint( 0, 0 ) ); + +    tipRect.moveCenter( QPoint( deskR.width()/2, deskR.height()/2 ) ); +    if ( !rect.contains( tipRect, true ) && rect.intersects( tipRect ) ) +      tipRect.moveBottomRight( geometry().bottomRight() ); +  } + +  move( tipRect.topLeft() ); +} + +RegionGrabber::RegionGrabber() +  : QWidget( 0, 0 ), +    mouseDown( false ), sizeTip( 0L ) +{ +  sizeTip = new SizeTip( ( QWidget * )0L ); + +  tipTimer = new QTimer( this ); +  Q_CHECK_PTR(tipTimer); +  connect( tipTimer, SIGNAL( timeout() ), SLOT( updateSizeTip() ) ); + +  QTimer::singleShot( 200, this, SLOT( initGrabber() ) ); +} + +RegionGrabber::~RegionGrabber() +{ +  delete sizeTip; +} + +void RegionGrabber::initGrabber() +{ +  pixmap = QPixmap::grabWindow( qt_xrootwin() ); +  setPaletteBackgroundPixmap( pixmap ); + +  showFullScreen(); + +  grabMouse( crossCursor ); +} + +void RegionGrabber::mousePressEvent( QMouseEvent *e ) +{ +  if ( e->button() == LeftButton ) +  { +    mouseDown = true; +    grabRect = QRect( e->pos(), e->pos() ); +  } +} + +void RegionGrabber::mouseMoveEvent( QMouseEvent *e ) +{ +  if ( mouseDown ) +  { +    sizeTip->hide(); +    tipTimer->start( 250, true ); + +    drawRubber(); +    grabRect.setBottomRight( e->pos() ); +    drawRubber(); +  } +} + +void RegionGrabber::mouseReleaseEvent( QMouseEvent *e ) +{ +  mouseDown = false; +  drawRubber(); +  sizeTip->hide(); + +  grabRect.setBottomRight( e->pos() ); +  grabRect = grabRect.normalize(); + +  QPixmap region = QPixmap::grabWindow( winId(), grabRect.x(), grabRect.y(), +      grabRect.width(), grabRect.height() ); + +  releaseMouse(); + +  emit regionGrabbed( region ); +} + +void RegionGrabber::keyPressEvent( QKeyEvent *e ) +{ +  if ( e->key() == Qt::Key_Escape ) +  { +    releaseMouse(); +    emit regionGrabbed( QPixmap() ); +  } +  else +    e->ignore(); +} + +void RegionGrabber::updateSizeTip() +{ +  QRect rect = grabRect.normalize(); + +  sizeTip->setTip( rect ); +  sizeTip->show(); +} + +void RegionGrabber::drawRubber() +{ +  QPainter p; +  p.begin( this ); +  p.setRasterOp( NotROP ); +  p.setPen( QPen( color0, 1 ) ); +  p.setBrush( NoBrush ); + +  style().drawPrimitive( QStyle::PE_FocusRect, &p, grabRect, colorGroup(), +      QStyle::Style_Default, QStyleOption( colorGroup().base() ) ); + +  p.end(); +} + +#include "regiongrabber.moc" diff --git a/krita/plugins/viewplugins/screenshot/regiongrabber.h b/krita/plugins/viewplugins/screenshot/regiongrabber.h new file mode 100644 index 000000000..74bf78c92 --- /dev/null +++ b/krita/plugins/viewplugins/screenshot/regiongrabber.h @@ -0,0 +1,71 @@ +/* + * This file is copied from ksnapshot. + * + * Copyright (C) 2003 Nadeem Hasan <nhasan@kde.org> + * + * This library 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 + * Library 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. + */ + +#ifndef REGIONGRABBER_H +#define REGIONGRABBER_H + +#include <qlabel.h> +#include <qpixmap.h> + +class QTimer; + +class SizeTip : public QLabel +{ +public: +    SizeTip( QWidget *parent, const char *name=0 ); +    ~SizeTip() {} + +    void setTip( const QRect &rect ); +    void positionTip( const QRect &rect ); +}; + +class RegionGrabber : public QWidget +{ +    Q_OBJECT + +public: +    RegionGrabber(); +    ~RegionGrabber(); + +protected slots: +    void initGrabber(); +    void updateSizeTip(); + +    signals: +    void regionGrabbed( const QPixmap & ); + +protected: +    void mousePressEvent( QMouseEvent *e ); +    void mouseReleaseEvent( QMouseEvent *e ); +    void mouseMoveEvent( QMouseEvent *e ); +    void keyPressEvent( QKeyEvent *e ); + +    void drawRubber(); + +    bool mouseDown; +    QRect grabRect; +    QPixmap pixmap; + +    SizeTip *sizeTip; +    QTimer *tipTimer; +}; + +#endif // REGIONGRABBER_H + diff --git a/krita/plugins/viewplugins/screenshot/screenshot-kpresenter.rc b/krita/plugins/viewplugins/screenshot/screenshot-kpresenter.rc new file mode 100644 index 000000000..14cd9d2e2 --- /dev/null +++ b/krita/plugins/viewplugins/screenshot/screenshot-kpresenter.rc @@ -0,0 +1,9 @@ +<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd"> +<kpartgui library="kritascreenshot" version="1"> +<MenuBar> +    <Menu name="Insert"><text>&Insert</text> +	<Separator/> +	<Action name="screenshot"/> +    </Menu> +</MenuBar> +</kpartgui> diff --git a/krita/plugins/viewplugins/screenshot/screenshot-krita.rc b/krita/plugins/viewplugins/screenshot/screenshot-krita.rc new file mode 100644 index 000000000..07f14197c --- /dev/null +++ b/krita/plugins/viewplugins/screenshot/screenshot-krita.rc @@ -0,0 +1,9 @@ +<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd"> +<kpartgui library="kritascreenshot" version="1"> +<MenuBar> +    <Menu name="Tools"><text>&Tools</text> +	<Seperator/> +	<Action name="screenshot"/> +    </Menu> +</MenuBar> +</kpartgui> diff --git a/krita/plugins/viewplugins/screenshot/screenshot-kword.rc b/krita/plugins/viewplugins/screenshot/screenshot-kword.rc new file mode 100644 index 000000000..f1f3fce11 --- /dev/null +++ b/krita/plugins/viewplugins/screenshot/screenshot-kword.rc @@ -0,0 +1,9 @@ +<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd"> +<kpartgui library="kritascreenshot" version="1"> +<MenuBar> +    <Menu name="insert"><text>&Insert</text> +	<Separator/> +	<Action name="screenshot"/> +    </Menu> +</MenuBar> +</kpartgui> diff --git a/krita/plugins/viewplugins/screenshot/screenshot.cpp b/krita/plugins/viewplugins/screenshot/screenshot.cpp new file mode 100644 index 000000000..c7508ae97 --- /dev/null +++ b/krita/plugins/viewplugins/screenshot/screenshot.cpp @@ -0,0 +1,78 @@ +/* + * This file is part of the KDE project + * + * This file was copied from ksnapshot + * + * Copyright (C) 2001 Nikolas Zimmermann <wildfox@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library 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 <klocale.h> +#include <kiconloader.h> +#include <kinstance.h> +#include <kmessagebox.h> +#include <kstandarddirs.h> +#include <ktempfile.h> +#include <kdebug.h> +#include <KoView.h> +#include <KoDocument.h> +#include <kgenericfactory.h> +#include <klocale.h> + +#include "ksnapshot.h" +#include <kimageio.h> +#include <kis_view.h> +#include <kis_image.h> +#include "screenshot.moc" + + +K_EXPORT_COMPONENT_FACTORY( kritascreenshot, KGenericFactory<Screenshot>( "krita" ) ) + +Screenshot::Screenshot(QObject *parent, const char *name, const QStringList &) +        : KParts::Plugin(parent, name) +{ +    KGlobal::locale()->insertCatalogue("kscreenshot_plugin"); +    setInstance(KGenericFactory<Screenshot>::instance()); +    setXMLFile(locate("data","kritaplugins/screenshot-krita.rc"), true); +    KImageIO::registerFormats(); + +    snapshot = new KSnapshot(); +    Q_CHECK_PTR(snapshot); +    connect( snapshot, SIGNAL( screenGrabbed() ), SLOT( slotScreenGrabbed() ) ); + +    (void) new KAction(i18n("&Screenshot..."), SmallIcon("tool_screenshot"), 0, this, SLOT(slotScreenshot()), actionCollection(), "screenshot"); + +} + +Screenshot::~Screenshot() +{ +    delete snapshot; +} + +void Screenshot::slotScreenshot() +{ +    snapshot->show(); +} + +void Screenshot::slotScreenGrabbed() +{ +    KTempFile temp(locateLocal("tmp", "screenshot"), ".png"); +    snapshot->save(temp.name()); + +    KisView *view = dynamic_cast<KisView *>(parent()); +    if(view) +        view->importImage(temp.name()); +} diff --git a/krita/plugins/viewplugins/screenshot/screenshot.h b/krita/plugins/viewplugins/screenshot/screenshot.h new file mode 100644 index 000000000..5e4c7c5d9 --- /dev/null +++ b/krita/plugins/viewplugins/screenshot/screenshot.h @@ -0,0 +1,42 @@ +/* This file is part of the KDE project + * Copyright (C) 2001 Nikolas Zimmermann <wildfox@kde.org> + * Copyright (C) 2004 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. +*/ + +#ifndef SCREENSHOT_H +#define SCREENSHOT_H + +#include <kparts/plugin.h> + +class KSnapshot; + +class Screenshot : public KParts::Plugin +{ +    Q_OBJECT +public: +    Screenshot(QObject *parent, const char *name, const QStringList &); +    virtual ~Screenshot(); + +private slots: +    void slotScreenshot(); +    void slotScreenGrabbed(); + +private: +    KSnapshot * snapshot; +}; + +#endif diff --git a/krita/plugins/viewplugins/scripting/Makefile.am b/krita/plugins/viewplugins/scripting/Makefile.am new file mode 100644 index 000000000..f361a6ce7 --- /dev/null +++ b/krita/plugins/viewplugins/scripting/Makefile.am @@ -0,0 +1,28 @@ +SUBDIRS = kritascripting kritacore samples + +kritarcdir = $(kde_datadir)/kritaplugins +kritarc_DATA = scripting.rc + +kde_services_DATA = kritascripting.desktop + + +INCLUDES  =  -I$(top_srcdir)/krita/sdk \ +	-I$(top_srcdir)/krita/core \ +	-I$(top_srcdir)/krita/kritacolor/ \ +	-I$(top_srcdir)/krita/ui \ +        -I$(top_builddir)/lib/kross/main \ +	$(KROSS_INCLUDES) \ +	$(KOFFICE_INCLUDES) \ +	$(all_includes) + +kritascripting_la_SOURCES = scripting.cc + +kde_module_LTLIBRARIES = kritascripting.la +noinst_HEADERS = scripting.h + +kritascripting_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) +kritascripting_la_LIBADD =  $(top_builddir)/krita/libkritacommon.la $(top_builddir)/lib/kross/main/libkrossmain.la ./kritascripting/libkritascripting.la + +KDE_CXXFLAGS = $(USE_EXCEPTIONS) + +kritascripting_la_METASOURCES = AUTO diff --git a/krita/plugins/viewplugins/scripting/kritacore/Makefile.am b/krita/plugins/viewplugins/scripting/kritacore/Makefile.am new file mode 100644 index 000000000..e948f6475 --- /dev/null +++ b/krita/plugins/viewplugins/scripting/kritacore/Makefile.am @@ -0,0 +1,29 @@ + +INCLUDES = -I$(top_srcdir)/core -I$(top_srcdir)/krita/plugins/viewplugins/scripting/kritascripting \ +	-I$(top_srcdir)/krita $(KOFFICECORE_INCLUDES) $(KROSS_INCLUDES) \ +	-I$(top_srcdir)/krita/ui -I$(top_srcdir)/krita/core -I$(top_srcdir)/krita/sdk \ +	-I$(top_srcdir)/krita/kritacolor $(all_includes) + +kde_module_LTLIBRARIES = krosskritacore.la + +krosskritacore_la_SOURCES = kritacoremodule.cpp krs_doc.cpp krs_paint_layer.cpp \ +	krs_image.cpp krs_histogram.cpp krs_script_progress.cpp krs_painter.cpp krs_color.cpp \ +	krs_brush.cpp krs_pattern.cpp krs_filter.cpp krs_filter_configuration.cpp \ +	krs_wavelet.cpp + +krosskritacore_la_LDFLAGS = $(all_libraries) $(KDE_PLUGIN) -module +krosskritacore_la_LIBADD = \ +    $(LIB_QT) \ +    $(LIB_KDECORE) \ +    $(top_builddir)/lib/kross/api/libkrossapi.la \ +    $(top_builddir)/lib/kross/main/libkrossmain.la \ +    $(top_builddir)/krita/libkritacommon.la \ +    $(top_builddir)/krita/plugins/viewplugins/scripting/kritascripting/libkritascripting.la + +METASOURCES = AUTO +SUBDIRS = . + +KDE_CXXFLAGS = $(USE_EXCEPTIONS) + +noinst_HEADERS = krs_doc.h krs_iterator.h krs_painter.h krs_color.h krs_brush.h \ +	krs_filter.h krs_filter_configuration.h krs_wavelet.h diff --git a/krita/plugins/viewplugins/scripting/kritacore/kritacoremodule.cpp b/krita/plugins/viewplugins/scripting/kritacore/kritacoremodule.cpp new file mode 100644 index 000000000..899291ce7 --- /dev/null +++ b/krita/plugins/viewplugins/scripting/kritacore/kritacoremodule.cpp @@ -0,0 +1,288 @@ +/* + *  Copyright (c) 2005 Cyrille Berger <cberger@cberger.net> + * + *  This program is free software; you can redistribute it and/or modify + *  it under the terms of the GNU Library 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 Library General Public License for more details. + * + *  You should have received a copy of the GNU Library 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 "kritacoremodule.h" + +#include <kdebug.h> + +//#include <api/variant.h> +#include <api/qtobject.h> +#include <main/manager.h> + +#include <kis_autobrush_resource.h> +#include <kis_brush.h> +#include <kis_colorspace_factory_registry.h> +#include <kis_doc.h> +#include <kis_filter.h> +#include <kis_filter_registry.h> +#include <kis_image.h> +#include <kis_meta_registry.h> +#include <kis_pattern.h> +#include <kis_resourceserver.h> + +#include "kis_script_progress.h" + +#include "krs_brush.h" +#include "krs_color.h" +#include "krs_doc.h" +#include "krs_filter.h" +#include "krs_image.h" +#include "krs_pattern.h" +#include "krs_script_progress.h" + +extern "C" +{ +    /** +     * Exported an loadable function as entry point to use +     * the \a KexiAppModule. +     */ +    Kross::Api::Object* KDE_EXPORT init_module(Kross::Api::Manager* manager) +    { +        return new Kross::KritaCore::KritaCoreModule(manager); +    } +} + + +using namespace Kross::KritaCore; + +KritaCoreFactory::KritaCoreFactory(QString packagePath) : Kross::Api::Event<KritaCoreFactory>("KritaCoreFactory"), m_packagePath(packagePath) +{ +    addFunction("newRGBColor", &KritaCoreFactory::newRGBColor); +    addFunction("newHSVColor", &KritaCoreFactory::newHSVColor); +    addFunction("getPattern", &KritaCoreFactory::getPattern); +    addFunction("loadPattern", &KritaCoreFactory::loadPattern); +    addFunction("getBrush", &KritaCoreFactory::getBrush); +    addFunction("loadBrush", &KritaCoreFactory::loadBrush); +    addFunction("getFilter", &KritaCoreFactory::getFilter); +    addFunction("newCircleBrush", &KritaCoreFactory::newCircleBrush); +    addFunction("newRectBrush", &KritaCoreFactory::newRectBrush); +    addFunction("newImage", &KritaCoreFactory::newImage); +    addFunction("getPackagePath", &KritaCoreFactory::getPackagePath); +} + +Kross::Api::Object::Ptr KritaCoreFactory::newRGBColor(Kross::Api::List::Ptr args) +{ +    Color* c = new Color(Kross::Api::Variant::toUInt(args->item(0)), Kross::Api::Variant::toUInt(args->item(1)), Kross::Api::Variant::toUInt(args->item(2)), QColor::Rgb); +    return c; +} +Kross::Api::Object::Ptr KritaCoreFactory::newHSVColor(Kross::Api::List::Ptr args) +{ +    return new Color(Kross::Api::Variant::toUInt(args->item(0)), Kross::Api::Variant::toUInt(args->item(1)), Kross::Api::Variant::toUInt(args->item(2)), QColor::Hsv); +} + +Kross::Api::Object::Ptr KritaCoreFactory::getPattern(Kross::Api::List::Ptr args) +{ +    KisResourceServerBase* rServer = KisResourceServerRegistry::instance()->get("PatternServer"); +    QValueList<KisResource*> resources = rServer->resources(); + +    QString name = Kross::Api::Variant::toString(args->item(0)); + +    for (QValueList<KisResource*>::iterator it = resources.begin(); it != resources.end(); ++it ) +    { +        if((*it)->name() == name) +        { +            return new Pattern(dynamic_cast<KisPattern*>(*it), true); +        } +    } +    throw Kross::Api::Exception::Ptr( new Kross::Api::Exception(  i18n("Unknown pattern") ) ); +    return 0; + +} + +Kross::Api::Object::Ptr KritaCoreFactory::loadPattern(Kross::Api::List::Ptr args) +{ +    QString filename = Kross::Api::Variant::toString(args->item(0)); +    KisPattern* pattern = new KisPattern(filename); +    if(pattern->load()) +    { +        return new Pattern( pattern, false ); +    } else { +        delete pattern; +        throw Kross::Api::Exception::Ptr( new Kross::Api::Exception( i18n("Unknown pattern") ) ); +        return 0; +    } +} + +Kross::Api::Object::Ptr KritaCoreFactory::getBrush(Kross::Api::List::Ptr args) +{ +    KisResourceServerBase* rServer = KisResourceServerRegistry::instance()->get("BrushServer"); +    QValueList<KisResource*> resources = rServer->resources(); + +    QString name = Kross::Api::Variant::toString(args->item(0)); + +    for (QValueList<KisResource*>::iterator it = resources.begin(); it != resources.end(); ++it ) +    { +        if((*it)->name() == name) +        { +            return new Brush(dynamic_cast<KisBrush*>(*it), true); +        } +    } +    throw Kross::Api::Exception::Ptr( new Kross::Api::Exception( i18n("Unknown brush") ) ); +    return 0; +} + +Kross::Api::Object::Ptr KritaCoreFactory::loadBrush(Kross::Api::List::Ptr args) +{ +    QString filename = Kross::Api::Variant::toString(args->item(0)); +    KisBrush* brush = new KisBrush(filename); +    if(brush->load()) +    { +        return new Brush( brush, false ); +    } else { +        delete brush; +        throw Kross::Api::Exception::Ptr( new Kross::Api::Exception( i18n("Unknown brush") ) ); +        return 0; +    } +} + +Kross::Api::Object::Ptr KritaCoreFactory::getFilter(Kross::Api::List::Ptr args) +{ +    QString name = Kross::Api::Variant::toString(args->item(0)); +    KisFilter* filter = KisFilterRegistry::instance()->get(name); +    if(filter) +    { +      return new Filter(filter); +    } else { +      return 0; +    } +} + +Kross::Api::Object::Ptr KritaCoreFactory::newCircleBrush(Kross::Api::List::Ptr args) +{ +    uint w = QMAX(1, Kross::Api::Variant::toUInt(args->item(0))); +    uint h = QMAX(1, Kross::Api::Variant::toUInt(args->item(1))); +    uint hf = 0; +    uint vf = 0; +    if( args.count() > 2) +    { +        hf = Kross::Api::Variant::toUInt(args->item(2)); +        vf = Kross::Api::Variant::toUInt(args->item(3)); +    } +    KisAutobrushShape* kas = new KisAutobrushCircleShape(w, h, hf, vf); +    QImage* brsh = new QImage(); +    kas->createBrush(brsh); +    return new Brush(new KisAutobrushResource(*brsh), false); +} +Kross::Api::Object::Ptr KritaCoreFactory::newRectBrush(Kross::Api::List::Ptr args) +{ +    uint w = QMAX(1, Kross::Api::Variant::toUInt(args->item(0))); +    uint h = QMAX(1, Kross::Api::Variant::toUInt(args->item(1))); +    uint hf = 0; +    uint vf = 0; +    if( args.count() > 2) +    { +        hf = Kross::Api::Variant::toUInt(args->item(2)); +        vf = Kross::Api::Variant::toUInt(args->item(3)); +    } +    KisAutobrushShape* kas = new KisAutobrushRectShape(w, h, hf, vf); +    QImage* brsh = new QImage(); +    kas->createBrush(brsh); +    return new Brush(new KisAutobrushResource(*brsh), false);; +} + +Kross::Api::Object::Ptr KritaCoreFactory::newImage(Kross::Api::List::Ptr args) +{ +    int w = Kross::Api::Variant::toInt(args->item(0)); +    int h = Kross::Api::Variant::toInt(args->item(1)); +    QString csname = Kross::Api::Variant::toString(args->item(2)); +    QString name = Kross::Api::Variant::toString(args->item(3)); +    if( w < 0 || h < 0) +    { +        throw Kross::Api::Exception::Ptr( new Kross::Api::Exception( i18n("Invalid image size") ) ); +        return 0; +    } +    KisColorSpace * cs = KisMetaRegistry::instance()->csRegistry()->getColorSpace(KisID(csname, ""), ""); +    if(!cs) +    { +        throw Kross::Api::Exception::Ptr( new Kross::Api::Exception( i18n("Colorspace %0 is not available, please check your installation.").arg(csname ) ) ); +        return 0; +    } + +    return new Image(new KisImage(0,w,h, cs, name)); +} + +Kross::Api::Object::Ptr KritaCoreFactory::getPackagePath(Kross::Api::List::Ptr) +{ +    return new Kross::Api::Variant(m_packagePath); +} + +KritaCoreModule::KritaCoreModule(Kross::Api::Manager* manager) +    : Kross::Api::Module("kritacore") , m_manager(manager), m_factory(0) +{ + +    QMap<QString, Object::Ptr> children = manager->getChildren(); +    kdDebug(41011) << " there are " << children.size() << endl; +    for(QMap<QString, Object::Ptr>::const_iterator it = children.begin(); it != children.end(); it++) +    { +        kdDebug(41011) << it.key() << " " << it.data() << endl; +    } + +    // Wrap doc +    Kross::Api::Object::Ptr kritadocument = manager->getChild("KritaDocument"); +    if(kritadocument) { +        Kross::Api::QtObject* kritadocumentqt = (Kross::Api::QtObject*)( kritadocument.data() ); +        if(kritadocumentqt) { +            ::KisDoc* document = (::KisDoc*)( kritadocumentqt->getObject() ); +            if(document) { +                addChild( new Doc(document) ); +            } else { +                throw Kross::Api::Exception::Ptr( new Kross::Api::Exception("There was no 'KritaDocument' published.") ); +            } +         } +    } +   // Wrap KritaScriptProgress +    QString packagePath; +    Kross::Api::Object::Ptr kritascriptprogress = manager->getChild("KritaScriptProgress"); +    if(kritadocument) { +        Kross::Api::QtObject* kritascriptprogressqt = (Kross::Api::QtObject*)( kritascriptprogress.data() ); +        if(kritascriptprogressqt) { +                ::KisScriptProgress* scriptprogress = (::KisScriptProgress*)( kritascriptprogressqt->getObject() ); +                scriptprogress->activateAsSubject(); +                packagePath = scriptprogress->packagePath(); +                if(scriptprogress) { +                    addChild( new ScriptProgress(scriptprogress) ); +                } else { +                    throw Kross::Api::Exception::Ptr( new Kross::Api::Exception("There was no 'KritaScriptProgress' published.") ); +                } +        } +    } +    m_factory = new KritaCoreFactory(packagePath); +} + +KritaCoreModule::~KritaCoreModule() +{ +    if(m_factory) +        delete m_factory; +} + + +const QString KritaCoreModule::getClassName() const +{ +    return "Kross::KritaCore::KritaCoreModule"; +} + +Kross::Api::Object::Ptr KritaCoreModule::call(const QString& name, Kross::Api::List::Ptr arguments) +{ +    kdDebug(41011) << "KritaCoreModule::call = " << name << endl; +    if( m_factory->isAFunction(name)) +    { +        return m_factory->call(name, arguments); +    } else { +        return Kross::Api::Module::call(name, arguments); +    } +} diff --git a/krita/plugins/viewplugins/scripting/kritacore/kritacoremodule.h b/krita/plugins/viewplugins/scripting/kritacore/kritacoremodule.h new file mode 100644 index 000000000..97abc8b99 --- /dev/null +++ b/krita/plugins/viewplugins/scripting/kritacore/kritacoremodule.h @@ -0,0 +1,205 @@ +/* + *  Copyright (c) 2005 Cyrille Berger <cberger@cberger.net> + * + *  This program is free software; you can redistribute it and/or modify + *  it under the terms of the GNU Library 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 Library General Public License for more details. + * + *  You should have received a copy of the GNU Library 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. + */ + +#ifndef KRITA_KROSS_KRITACOREMODULE_H +#define KRITA_KROSS_KRITACOREMODULE_H + +#include <qstring.h> +#include <qvariant.h> + +#define KROSS_MAIN_EXPORT KDE_EXPORT + +#include <api/module.h> +#include <api/event.h> + +namespace Kross { namespace Api { +    class Manager; +}} + +namespace Kross { namespace KritaCore { +    /** +     * This class contains functions use to create new Kross object in a script +     */ +    class KritaCoreFactory : public Kross::Api::Event<KritaCoreFactory> +    { +        public: +            KritaCoreFactory(QString packagePath); +        private: +            /** +             * This function return a new Image. +             * It takes four arguments : +             *  - width +             *  - height +             *  - colorspace id +             *  - name of the image +             * +             * And in return you get an Image object. +             *  +             * For example (in ruby) : +             * @code +             * Krosskritacore::newImage(10,20, "RGBA", "kikoo") +             * @endcode +             */ +            Kross::Api::Object::Ptr newImage(Kross::Api::List::Ptr); +            /** +             * This function return a new Color with the given RGB triplet +             * It takes three arguments : +             *  - red color (0 to 255) +             *  - blue color (0 to 255) +             *  - green color (0 to 255) +             *  +             * For example (in ruby) : +             * @code +             * Krosskritacore::newRGBColor(255,0,0) # create a red color +             * Krosskritacore::newRGBColor(255,255,255) # create a white color +             * @endcode +             */ +            Kross::Api::Object::Ptr newRGBColor(Kross::Api::List::Ptr); +            /** +             * This function return a new Color with the given HSV triplet +             * It takes three arguments : +             *  - hue color (0 to 255) +             *  - saturation color (0 to 255) +             *  - value color (0 to 255) +             *  +             * For example (in ruby) : +             * @code +             * Krosskritacore::newRGBColor(255,125,0) +             * @endcode +             */ +            Kross::Api::Object::Ptr newHSVColor(Kross::Api::List::Ptr); +            /** +             * This function return a Pattern taken from the list of ressources +             * of krita +             * It takes one argument : +             *  - the name of the pattern +             *  +             * For example (in ruby) : +             * @code +             * Krosskritacore::getPattern("Bricks") +             * @endcode +             */ +            Kross::Api::Object::Ptr getPattern(Kross::Api::List::Ptr); +            /** +             * This function return a Brush taken from the list of ressources +             * of krita +             * It takes one argument : +             *  - the name of the pattern +             *  +             * For example (in ruby) : +             * @code +             * Krosskritacore::getBrush("Circle (05)") +             * @endcode +             */ +            Kross::Api::Object::Ptr getBrush(Kross::Api::List::Ptr); +            /** +             * This function return a Brush with a circular shape +             * It takes at least two arguments : +             *  - width +             *  - height +             *  +             * It can takes two other arguments : +             *  - width of the shading +             *  - height of the shading +             *  +             * If the shading isn't specified, no shading will be used. +             *  +             * For example (in ruby) : +             * @code +             * Krosskritacore::newCircleBrush(10,20) # create a plain circle +             * Krosskritacore::newCircleBrush(10,20,5,10) # create a gradient +             * @endcode +             */ +            Kross::Api::Object::Ptr newCircleBrush(Kross::Api::List::Ptr); +            /** +             * This function return a Brush with a rectangular shape +             * It takes at least two arguments : +             *  - width +             *  - height +             *  +             * It can takes two other arguments : +             *  - width of the shading +             *  - height of the shading +             *  +             * If the shading isn't specified, no shading will be used. +             *  +             * For example (in ruby) : +             * @code +             * Krosskritacore::newRectBrush(10,20) # create a plain rectangle +             * Krosskritacore::newRectBrush(10,20,5,10) # create a gradient +             * @endcode +             */ +            Kross::Api::Object::Ptr newRectBrush(Kross::Api::List::Ptr); +            /** +             * This function return a Filter taken from the list of ressources +             * of krita +             * It takes one argument : +             *  - the name of the filter +             *  +             * For example (in ruby) : +             * @code +             * Krosskritacore::getFilter("invert") +             * @endcode +             */ +            Kross::Api::Object::Ptr getFilter(Kross::Api::List::Ptr); +            /** +             * This function loads a Brush and then returns it. +             * It takes one argument: the filename of the brush. +             */ +            Kross::Api::Object::Ptr loadBrush(Kross::Api::List::Ptr); +            /** +             * This function loads a Pattern and then returns it. +             * It takes one argument: the filename of the pattern. +             */ +            Kross::Api::Object::Ptr loadPattern(Kross::Api::List::Ptr); +            /** +             * This function return the directory where the script is located. +             */ +            Kross::Api::Object::Ptr getPackagePath(Kross::Api::List::Ptr); +        private: +            QString m_packagePath; +    }; +    /** +     * +     */ +    class KritaCoreModule : public Kross::Api::Module +    { +        public: +            /** +             * Constructor. +             */ +            KritaCoreModule(Kross::Api::Manager* manager); + +            /** +             * Destructor. +             */ +            virtual ~KritaCoreModule(); + +            /// \see Kross::Api::Object::getClassName +            virtual const QString getClassName() const; +            virtual Kross::Api::Object::Ptr call(const QString& name, Kross::Api::List::Ptr arguments); +        private: +            Kross::Api::Manager* m_manager; +            KritaCoreFactory* m_factory; +    }; +     + +}} + +#endif + diff --git a/krita/plugins/viewplugins/scripting/kritacore/krs_brush.cpp b/krita/plugins/viewplugins/scripting/kritacore/krs_brush.cpp new file mode 100644 index 000000000..a6ae513ce --- /dev/null +++ b/krita/plugins/viewplugins/scripting/kritacore/krs_brush.cpp @@ -0,0 +1,41 @@ +/* + *  Copyright (c) 2005 Cyrille Berger <cberger@cberger.net> + * + *  This program is free software; you can redistribute it and/or modify + *  it under the terms of the GNU Library 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 Library General Public License for more details. + * + *  You should have received a copy of the GNU Library 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 "krs_brush.h" + +#include <kis_brush.h> + +namespace Kross { + +namespace KritaCore { + +Brush::Brush(KisBrush* brush, bool sharedBrush) : Kross::Api::Class<Brush>("KritaBrush"), m_brush(brush), m_sharedBrush(sharedBrush) +{ +} + +Brush::~Brush() +{ +    if(!m_sharedBrush) +    { +        delete m_brush; +    } +} + +} + +} diff --git a/krita/plugins/viewplugins/scripting/kritacore/krs_brush.h b/krita/plugins/viewplugins/scripting/kritacore/krs_brush.h new file mode 100644 index 000000000..f31e877de --- /dev/null +++ b/krita/plugins/viewplugins/scripting/kritacore/krs_brush.h @@ -0,0 +1,48 @@ +/* + *  Copyright (c) 2005 Cyrille Berger <cberger@cberger.net> + * + *  This program is free software; you can redistribute it and/or modify + *  it under the terms of the GNU Library 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 Library General Public License for more details. + * + *  You should have received a copy of the GNU Library 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. + */ + +#ifndef KROSS_KRITACOREKRS_BRUSH_H +#define KROSS_KRITACOREKRS_BRUSH_H + +#include <api/class.h> + +class KisBrush; + +namespace Kross { + +namespace KritaCore { + +class Brush : public Kross::Api::Class<Brush>{ +    public: +        /** +         * @param sharedBrush tell if the brush should be deleted or not when this object is deleted +         */ +        Brush(KisBrush*, bool sharedBrush ); +        ~Brush(); +    public: +        inline KisBrush* getBrush() { return m_brush; } +    private: +        KisBrush* m_brush; +        bool m_sharedBrush; +}; + +} + +} + +#endif diff --git a/krita/plugins/viewplugins/scripting/kritacore/krs_color.cpp b/krita/plugins/viewplugins/scripting/kritacore/krs_color.cpp new file mode 100644 index 000000000..e459b1cd1 --- /dev/null +++ b/krita/plugins/viewplugins/scripting/kritacore/krs_color.cpp @@ -0,0 +1,42 @@ +/* + *  Copyright (c) 2005 Cyrille Berger <cberger@cberger.net> + * + *  This program is free software; you can redistribute it and/or modify + *  it under the terms of the GNU Library 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 Library General Public License for more details. + * + *  You should have received a copy of the GNU Library 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 "krs_color.h" + +namespace Kross { + +namespace KritaCore { + +Color::Color ( int x, int y, int z, QColor::Spec colorSpec ) +    : Kross::Api::Class<Color>("KritaColor"), m_color(x,y,z,colorSpec) +{ +} + +Color::Color() + : Kross::Api::Class<Color>("KritaColor") +{ +} + +Color::~Color() +{ +} + + +} + +} diff --git a/krita/plugins/viewplugins/scripting/kritacore/krs_color.h b/krita/plugins/viewplugins/scripting/kritacore/krs_color.h new file mode 100644 index 000000000..8d46760b9 --- /dev/null +++ b/krita/plugins/viewplugins/scripting/kritacore/krs_color.h @@ -0,0 +1,49 @@ +/* + *  Copyright (c) 2005 Cyrille Berger <cberger@cberger.net> + * + *  This program is free software; you can redistribute it and/or modify + *  it under the terms of the GNU Library 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 Library General Public License for more details. + * + *  You should have received a copy of the GNU Library 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. + */ + +#ifndef KROSS_APIKRS_COLOR_H +#define KROSS_APIKRS_COLOR_H + +#include <qcolor.h> + +#include <api/class.h> + +namespace Kross { + +namespace KritaCore { + +class Color : public Kross::Api::Class<Color> +{ +    public: +        Color ( int x, int y, int z, QColor::Spec colorSpec ); +        Color (); + +        ~Color(); +    public: +        inline const QString getClassName() const +        { return "Kross::Krita::Color"; }; +        inline QColor toQColor() { return m_color; }; +    private: +        QColor m_color; +}; + +} + +} + +#endif diff --git a/krita/plugins/viewplugins/scripting/kritacore/krs_doc.cpp b/krita/plugins/viewplugins/scripting/kritacore/krs_doc.cpp new file mode 100644 index 000000000..23dffabb3 --- /dev/null +++ b/krita/plugins/viewplugins/scripting/kritacore/krs_doc.cpp @@ -0,0 +1,46 @@ +/* + *  Copyright (c) 2005 Cyrille Berger <cberger@cberger.net> + * + *  This program is free software; you can redistribute it and/or modify + *  it under the terms of the GNU Library 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 Library General Public License for more details. + * + *  You should have received a copy of the GNU Library 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 "krs_doc.h" + +#include <kis_doc.h> +#include <kis_image.h> + +#include "krs_image.h" + +namespace Kross { namespace KritaCore { + +Doc::Doc(::KisDoc* doc) : Kross::Api::Class<Doc>("KritaDocument"), m_doc(doc) { +    addFunction("getImage", &Doc::getImage); +} + +Doc::~Doc() { +     +} + +const QString Doc::getClassName() const { +    return "Kross::KritaCore::Doc"; +} + +Kross::Api::Object::Ptr Doc::getImage(Kross::Api::List::Ptr) +{ +    return new Image(m_doc->currentImage(), m_doc); +} + +} +} diff --git a/krita/plugins/viewplugins/scripting/kritacore/krs_doc.h b/krita/plugins/viewplugins/scripting/kritacore/krs_doc.h new file mode 100644 index 000000000..16336f94a --- /dev/null +++ b/krita/plugins/viewplugins/scripting/kritacore/krs_doc.h @@ -0,0 +1,53 @@ +/* + *  Copyright (c) 2005 Cyrille Berger <cberger@cberger.net> + * + *  This program is free software; you can redistribute it and/or modify + *  it under the terms of the GNU Library 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 Library General Public License for more details. + * + *  You should have received a copy of the GNU Library 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. + */ + +#ifndef _KROSS_KRS_DOC_H_ +#define _KROSS_KRS_DOC_H_ + +class KisDoc; + +#include <api/class.h> + +namespace Kross { namespace KritaCore { + +class Doc : public Kross::Api::Class<Doc> +{ +    public: +        explicit Doc(::KisDoc* doc); +        virtual ~Doc(); +        virtual const QString getClassName() const; +    private: +        /** +         * This function return the Image associated with this Doc. +         *  +         * Example (in Ruby) : +         * @code +         * doc = krosskritacore::get("KritaDocument") +         * image = doc.getImage() +         * @endcode +         */ +        Kross::Api::Object::Ptr getImage(Kross::Api::List::Ptr); +    private: +        KisDoc* m_doc; + +}; +} +} + + +#endif diff --git a/krita/plugins/viewplugins/scripting/kritacore/krs_filter.cpp b/krita/plugins/viewplugins/scripting/kritacore/krs_filter.cpp new file mode 100644 index 000000000..ee11d35de --- /dev/null +++ b/krita/plugins/viewplugins/scripting/kritacore/krs_filter.cpp @@ -0,0 +1,76 @@ +/* + *  Copyright (c) 2006 Cyrille Berger <cberger@cberger.net> + * + *  This program is free software; you can redistribute it and/or modify + *  it under the terms of the GNU Library 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 Library General Public License for more details. + * + *  You should have received a copy of the GNU Library 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 "krs_filter.h" + +#include <kis_filter.h> +#include <kis_paint_layer.h> + +#include "krs_filter_configuration.h" +#include "krs_paint_layer.h" + +namespace Kross { +namespace KritaCore { + +Filter::Filter(KisFilter* filter) +    : Kross::Api::Class<Filter>("KritaFilter"), m_filter(filter), m_config( new FilterConfiguration(filter->configuration()) ) +{ +    addFunction("process", &Filter::process); +    addFunction("getFilterConfiguration", &Filter::getFilterConfiguration); + +} + +Filter::~Filter() +{ +} + +const QString Filter::getClassName() const { +    return "Kross::KritaCore::Filter"; +} + +Kross::Api::Object::Ptr Filter::getFilterConfiguration(Kross::Api::List::Ptr ) +{ +     return m_config; +} + +Kross::Api::Object::Ptr Filter::process(Kross::Api::List::Ptr args) +{ +    PaintLayer* src = (PaintLayer*)args->item(0).data(); +    if(!m_filter->workWith( src->paintLayer()->paintDevice()->colorSpace())) +    { +        throw Kross::Api::Exception::Ptr( new Kross::Api::Exception( i18n("An error has occured in %1").arg("process") ) ); +    } +    QRect rect; +    if( args->count() >1) +    { +        uint x = Kross::Api::Variant::toVariant(args->item(1)).toUInt(); +        uint y = Kross::Api::Variant::toVariant(args->item(2)).toUInt(); +        uint w = Kross::Api::Variant::toVariant(args->item(3)).toUInt(); +        uint h = Kross::Api::Variant::toVariant(args->item(4)).toUInt(); +        rect = QRect(x, y, w, h); +    } else { +        QRect r1 = src->paintLayer()->paintDevice()->extent(); +        QRect r2 = src->paintLayer()->image()->bounds(); +        rect = r1.intersect(r2); +    } +    m_filter->process( src->paintLayer()->paintDevice(), src->paintLayer()->paintDevice(), m_config->filterConfiguration(), rect ); +    return 0; +} + +} +} diff --git a/krita/plugins/viewplugins/scripting/kritacore/krs_filter.h b/krita/plugins/viewplugins/scripting/kritacore/krs_filter.h new file mode 100644 index 000000000..62554ef9c --- /dev/null +++ b/krita/plugins/viewplugins/scripting/kritacore/krs_filter.h @@ -0,0 +1,76 @@ +/* + *  Copyright (c) 2006 Cyrille Berger <cberger@cberger.net> + * + *  This program is free software; you can redistribute it and/or modify + *  it under the terms of the GNU Library 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 Library General Public License for more details. + * + *  You should have received a copy of the GNU Library 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. + */ + +#ifndef KROSS_KRITACOREKRS_FILTER_H +#define KROSS_KRITACOREKRS_FILTER_H + +#include <api/class.h> + +class KisFilter; + +namespace Kross { +namespace KritaCore { +    class FilterConfiguration; + +class Filter : public Kross::Api::Class<Filter> +{ +    public: +        Filter(KisFilter*); +        ~Filter(); +    private: +        /** +         * This function return the FilterConfiguration associated with this filter. +         */ +        Kross::Api::Object::Ptr getFilterConfiguration(Kross::Api::List::Ptr args); +        /** +         * This function will apply the filter. +         * It takes one argument : +         *  - the source layer +         * You can also use this four aguments : +         *  - x +         *  - y +         *  - width +         *  - height +         *  +         * (x,y, width, height) defines the rectangular area on which the filter will be computed. +         * If the rectangle is not defined, then the filter will be apply on alll the source layer. +         *  +         * For example (in ruby) +         * @code +         * doc = Krosskritacore::get("KritaDocument") +         * image = doc.getImage() +         * layer = image.getActivePaintLayer() +         * width = layer.getWidth() +         * height = layer.getHeight() +         * filter = Krosskritacore::getFilter("invert") +         * filter.process(layer, layer) +         * filter.process(layer, layer, 10, 10, 20, 20 ) +         * @endcode +         */ +        Kross::Api::Object::Ptr process(Kross::Api::List::Ptr args); +    public: +        virtual const QString getClassName() const; +    private: +        KisFilter* m_filter; +        FilterConfiguration* m_config; +}; + +} +} + +#endif diff --git a/krita/plugins/viewplugins/scripting/kritacore/krs_filter_configuration.cpp b/krita/plugins/viewplugins/scripting/kritacore/krs_filter_configuration.cpp new file mode 100644 index 000000000..3479cf384 --- /dev/null +++ b/krita/plugins/viewplugins/scripting/kritacore/krs_filter_configuration.cpp @@ -0,0 +1,72 @@ +/* + *  Copyright (c) 2006 Cyrille Berger <cberger@cberger.net> + * + *  This program is free software; you can redistribute it and/or modify + *  it under the terms of the GNU Library 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 Library General Public License for more details. + * + *  You should have received a copy of the GNU Library 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 "krs_filter_configuration.h" + +#include <api/variant.h> + +#include <kis_filter_configuration.h> + +namespace Kross { +namespace KritaCore { + +    FilterConfiguration::FilterConfiguration(KisFilterConfiguration* fConfig) +    : Kross::Api::Class<FilterConfiguration>("KritaFilterConfiguration"), m_fConfig(fConfig) +{ +    addFunction("setProperty", &FilterConfiguration::setProperty); +    addFunction("getProperty", &FilterConfiguration::getProperty); +    addFunction("fromXML", &FilterConfiguration::fromXML); +} + +FilterConfiguration::~FilterConfiguration() +{ +} + +const QString FilterConfiguration::getClassName() const { +    return "Kross::KritaCore::FilterConfiguration"; +} + + +Kross::Api::Object::Ptr FilterConfiguration::setProperty(Kross::Api::List::Ptr args) +{ +    QString name = Kross::Api::Variant::toString(args->item(0)); +    QVariant value = Kross::Api::Variant::toVariant(args->item(1)); +    m_fConfig->setProperty(name, value); +    return 0; +} +Kross::Api::Object::Ptr FilterConfiguration::getProperty(Kross::Api::List::Ptr args) +{ +    QString name = Kross::Api::Variant::toString(args->item(0)); +    QVariant value; +    if(m_fConfig->getProperty( name, value)) +    { +        return new Kross::Api::Variant(value); +    } else { +        return 0; +    } +} + +Kross::Api::Object::Ptr FilterConfiguration::fromXML(Kross::Api::List::Ptr args) +{ +    QString xml = Kross::Api::Variant::toString(args->item(0)); +    m_fConfig->fromXML( xml ); +    return 0; +} + +} +} diff --git a/krita/plugins/viewplugins/scripting/kritacore/krs_filter_configuration.h b/krita/plugins/viewplugins/scripting/kritacore/krs_filter_configuration.h new file mode 100644 index 000000000..7c8c3020c --- /dev/null +++ b/krita/plugins/viewplugins/scripting/kritacore/krs_filter_configuration.h @@ -0,0 +1,65 @@ +/* + *  Copyright (c) 2006 Cyrille Berger <cberger@cberger.net> + * + *  This program is free software; you can redistribute it and/or modify + *  it under the terms of the GNU Library 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 Library General Public License for more details. + * + *  You should have received a copy of the GNU Library 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. + */ + +#ifndef KROSS_KRITACOREKRS_FILTER_CONFIGURATION_H +#define KROSS_KRITACOREKRS_FILTER_CONFIGURATION_H + +#include <api/class.h> + +class KisFilterConfiguration; + +namespace Kross { +namespace KritaCore { + +/** +	@author Cyrille Berger <cberger@cberger.net> +*/ +class FilterConfiguration : public Kross::Api::Class<FilterConfiguration> +{ +    public: +        FilterConfiguration(KisFilterConfiguration*); +        ~FilterConfiguration(); +    public: +        virtual const QString getClassName() const; +        inline KisFilterConfiguration* filterConfiguration() { return m_fConfig; }; +    private: +        /** +         * This function define a parameter of the associated Filter. +         * It takes two arguments : +         *  - the name of the parameter +         *  - the value, whose type depends of the Filter +         */ +        Kross::Api::Object::Ptr setProperty(Kross::Api::List::Ptr args); +        /** +         * This function return the value of a parameter of the associated Filter. +         * It takes one argument : +         *  - the name of the parameter +         */ +        Kross::Api::Object::Ptr getProperty(Kross::Api::List::Ptr args); +        /** +         * Deserialize +         */ +        Kross::Api::Object::Ptr fromXML(Kross::Api::List::Ptr args); +    private: +        KisFilterConfiguration* m_fConfig; +}; + +} +} + +#endif diff --git a/krita/plugins/viewplugins/scripting/kritacore/krs_histogram.cpp b/krita/plugins/viewplugins/scripting/kritacore/krs_histogram.cpp new file mode 100644 index 000000000..953eb8688 --- /dev/null +++ b/krita/plugins/viewplugins/scripting/kritacore/krs_histogram.cpp @@ -0,0 +1,104 @@ +/* + *  Copyright (c) 2005 Cyrille Berger <cberger@cberger.net> + * + *  This program is free software; you can redistribute it and/or modify + *  it under the terms of the GNU Library 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 Library General Public License for more details. + * + *  You should have received a copy of the GNU Library 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 "krs_histogram.h" + +#include <kis_paint_layer.h> + +namespace Kross { + +namespace KritaCore { + +Histogram::Histogram(KisPaintLayerSP layer, +                     KisHistogramProducerSP producer, +                     const enumHistogramType type) + : Kross::Api::Class<Histogram>("KritaHistogram") +{ +    m_histogram = new KisHistogram(layer, producer, type); +    addFunction("getMax", &Histogram::getMax); +    addFunction("getMin", &Histogram::getMin); +    addFunction("getHighest", &Histogram::getHighest); +    addFunction("getLowest", &Histogram::getLowest); +    addFunction("getMean", &Histogram::getMean); +    addFunction("getCount", &Histogram::getCount); +    addFunction("getTotal", &Histogram::getTotal); +    addFunction("setChannel", &Histogram::setChannel); +    addFunction("getChannel", &Histogram::getChannel); +    addFunction("getValue", &Histogram::getValue); +    addFunction("getNumberOfBins", &Histogram::getNumberOfBins); +} + +Histogram::~Histogram() +{ +} + +const QString Histogram::getClassName() const { +    return "Kross::KritaCore::Histogram"; +} + +Kross::Api::Object::Ptr Histogram::setChannel(Kross::Api::List::Ptr args) +{ +    m_histogram->setChannel(Kross::Api::Variant::toUInt(args->item(0))); +    return 0; +} +Kross::Api::Object::Ptr Histogram::getChannel(Kross::Api::List::Ptr) +{ +    return new Kross::Api::Variant( m_histogram->channel()); +} +Kross::Api::Object::Ptr Histogram::getMax(Kross::Api::List::Ptr) +{ +    return new Kross::Api::Variant( m_histogram->calculations().getMax()); +} +Kross::Api::Object::Ptr Histogram::getMin(Kross::Api::List::Ptr) +{ +    return new Kross::Api::Variant( m_histogram->calculations().getMin() ); +} +Kross::Api::Object::Ptr Histogram::getHighest(Kross::Api::List::Ptr) +{ +    return new Kross::Api::Variant( m_histogram->calculations().getHighest() ); +} +Kross::Api::Object::Ptr Histogram::getLowest(Kross::Api::List::Ptr) +{ +    return new Kross::Api::Variant( m_histogram->calculations().getLowest() ); +} +Kross::Api::Object::Ptr Histogram::getMean(Kross::Api::List::Ptr) +{ +    return new Kross::Api::Variant( m_histogram->calculations().getMean() ); +} +Kross::Api::Object::Ptr Histogram::getCount(Kross::Api::List::Ptr) +{ +    return new Kross::Api::Variant( m_histogram->calculations().getCount() ); +} +Kross::Api::Object::Ptr Histogram::getTotal(Kross::Api::List::Ptr) +{ +    return new Kross::Api::Variant( m_histogram->calculations().getTotal() ); +} +Kross::Api::Object::Ptr Histogram::getValue(Kross::Api::List::Ptr args) +{ +    return new Kross::Api::Variant( m_histogram->getValue( Kross::Api::Variant::toUInt(args->item(0)) ) ); +} + +Kross::Api::Object::Ptr Histogram::getNumberOfBins(Kross::Api::List::Ptr) +{ +    return new Kross::Api::Variant( m_histogram->producer()->numberOfBins() ); +} + + +} + +} diff --git a/krita/plugins/viewplugins/scripting/kritacore/krs_histogram.h b/krita/plugins/viewplugins/scripting/kritacore/krs_histogram.h new file mode 100644 index 000000000..b238c5db9 --- /dev/null +++ b/krita/plugins/viewplugins/scripting/kritacore/krs_histogram.h @@ -0,0 +1,115 @@ +/* + *  Copyright (c) 2005 Cyrille Berger <cberger@cberger.net> + * + *  This program is free software; you can redistribute it and/or modify + *  it under the terms of the GNU Library 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 Library General Public License for more details. + * + *  You should have received a copy of the GNU Library 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. + */ + +#ifndef KROSS_KRITACOREHISTOGRAM_H +#define KROSS_KRITACOREHISTOGRAM_H + +#include <api/class.h> + +#include <kis_types.h> +#include <kis_histogram.h> + +namespace Kross { + +namespace KritaCore { + +/** + * This class allow to access the histogram of a PaintLayer. + *  + * Example (in Ruby) : + * @code + * doc = krosskritacore::get("KritaDocument") + * image = doc.getImage() + * layer = image.getActiveLayer() + * histo = layer.createHistogram("RGB8HISTO",0) + * min = layer.getMin() * 255 + * max = layer.getMax() * 255 + * for i in min..max + *   print layer.getValue(i) + *   print "\n" + * end + * @endcode + */ +class Histogram : public Kross::Api::Class<Histogram> +{ +    public: +        Histogram(KisPaintLayerSP layer, KisHistogramProducerSP producer, const enumHistogramType type); +        ~Histogram(); +        virtual const QString getClassName() const; +    private: +        /** +         * This function return the maximum bound of the histogram +         * (values at greater position than the maximum are null). +         * The value is in the range 0.0 - 1.0. +         */ +        Kross::Api::Object::Ptr getMax(Kross::Api::List::Ptr); +        /** +         * This function return the minimum bound of the histogram +         * (values at smaller position than the minimum are null) +         * The value is in the range 0.0 - 1.0. +         */ +        Kross::Api::Object::Ptr getMin(Kross::Api::List::Ptr); +        /** +         * This function return the highest value of the histogram +         */ +        Kross::Api::Object::Ptr getHighest(Kross::Api::List::Ptr); +        /** +         * This function return the lowest value of the histogram +         */ +        Kross::Api::Object::Ptr getLowest(Kross::Api::List::Ptr); +        /** +         * This function return the mean of the histogram +         */ +        Kross::Api::Object::Ptr getMean(Kross::Api::List::Ptr); +        /** +         * This function return the number of pixels used by the histogram +         */ +        Kross::Api::Object::Ptr getCount(Kross::Api::List::Ptr); +        /** +         * This function return the sum of all values of the histogram +         */ +        Kross::Api::Object::Ptr getTotal(Kross::Api::List::Ptr); +        /** +         * Select the channel of the layer on which to get the result of the histogram. +         * This function takes one argument : +         *  - channel number +         */ +        Kross::Api::Object::Ptr setChannel(Kross::Api::List::Ptr); +        /** +         * Return the selected channel +         */ +        Kross::Api::Object::Ptr getChannel(Kross::Api::List::Ptr); +        /** +         * Return the value of a bin of the histogram. +         * This function takes one argument : +         *  - index, in the range [0..255],  +         */ +        Kross::Api::Object::Ptr getValue(Kross::Api::List::Ptr); +        /** +         * Return the number of bins of this histogram. +         */ +        Kross::Api::Object::Ptr getNumberOfBins(Kross::Api::List::Ptr); +    private: +        KisHistogram* m_histogram; +}; + +} + +} + +#endif diff --git a/krita/plugins/viewplugins/scripting/kritacore/krs_image.cpp b/krita/plugins/viewplugins/scripting/kritacore/krs_image.cpp new file mode 100644 index 000000000..b274ad33e --- /dev/null +++ b/krita/plugins/viewplugins/scripting/kritacore/krs_image.cpp @@ -0,0 +1,148 @@ +/* + *  Copyright (c) 2005 Cyrille Berger <cberger@cberger.net> + * + *  This program is free software; you can redistribute it and/or modify + *  it under the terms of the GNU Library 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 Library General Public License for more details. + * + *  You should have received a copy of the GNU Library 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 "krs_image.h" + +#include <klocale.h> + +#include <kis_colorspace_factory_registry.h> +#include <kis_image.h> +#include <kis_filter_strategy.h> +#include <kis_group_layer.h> +#include <kis_paint_layer.h> +#include <kis_meta_registry.h> + + +#include "krs_paint_layer.h" + +namespace Kross { + +namespace KritaCore { + +    Image::Image(KisImageSP image, KisDoc* doc) +    : Kross::Api::Class<Image>("KritaImage"), m_image(image), m_doc(doc) +{ +    addFunction("getActivePaintLayer", &Image::getActivePaintLayer); +    addFunction("getWidth", &Image::getWidth); +    addFunction("getHeight", &Image::getHeight); +    addFunction("convertToColorspace", &Image::convertToColorspace); +    addFunction("createPaintLayer", &Image::createPaintLayer); +    addFunction("colorSpaceId", &Image::colorSpaceId); +    addFunction("scale", &Image::scale); +    addFunction("resize", &Image::resize); +} + + +Image::~Image() +{ +} + +const QString Image::getClassName() const { +    return "Kross::KritaCore::Image"; +} + +Kross::Api::Object::Ptr Image::getActivePaintLayer(Kross::Api::List::Ptr) +{ +    KisPaintLayer* activePaintLayer = dynamic_cast<KisPaintLayer*>(m_image->activeLayer().data()); +    if(activePaintLayer ) +    { +        return new PaintLayer(activePaintLayer, m_doc); +    } else { +        throw Kross::Api::Exception::Ptr( new Kross::Api::Exception("The active layer is not paintable.") ); +        return 0; +    } +} +Kross::Api::Object::Ptr Image::getWidth(Kross::Api::List::Ptr) +{ +    return new Kross::Api::Variant(m_image->width()); +} +Kross::Api::Object::Ptr Image::getHeight(Kross::Api::List::Ptr) +{ +    return new Kross::Api::Variant(m_image->height()); +} +Kross::Api::Object::Ptr Image::convertToColorspace(Kross::Api::List::Ptr args) +{ +    KisColorSpace * dstCS = KisMetaRegistry::instance()->csRegistry()->getColorSpace(KisID(Kross::Api::Variant::toString(args->item(0)), ""), ""); +    if(!dstCS) +    { +        throw Kross::Api::Exception::Ptr( new Kross::Api::Exception( i18n("Colorspace %0 is not available, please check your installation.").arg(Kross::Api::Variant::toString(args->item(0))) ) ); +        return 0; +    } +    m_image->convertTo(dstCS); +    return 0; +} + +Kross::Api::Object::Ptr Image::colorSpaceId(Kross::Api::List::Ptr ) +{ +    return new Kross::Api::Variant( m_image->colorSpace()->id().id() ); +} + + +Kross::Api::Object::Ptr Image::createPaintLayer(Kross::Api::List::Ptr args) +{ +    QString name = Kross::Api::Variant::toString(args->item(0)); +    int opacity = Kross::Api::Variant::toInt(args->item(1)); +    opacity = CLAMP(opacity, 0, 255); +    QString csname; +    if(args->count() > 2) +    { +        csname = Kross::Api::Variant::toString(args->item(2)); +    } else { +        csname = m_image->colorSpace()->id().id(); +    } +    KisColorSpace * cs = KisMetaRegistry::instance()->csRegistry()->getColorSpace(KisID(csname, ""), ""); +    KisPaintLayer* layer; +    if(cs) +    { +        layer = new KisPaintLayer(m_image, name, opacity, cs); +    } else { +        layer = new KisPaintLayer(m_image, name, opacity); +    } +    layer->setVisible(true); + +    m_image->addLayer(layer, m_image->rootLayer(), 0); +    return new PaintLayer(layer); + +} + +Kross::Api::Object::Ptr Image::scale(Kross::Api::List::Ptr args) +{ +    double cw = Kross::Api::Variant::toDouble(args->item(0)); +    double ch = Kross::Api::Variant::toDouble(args->item(1)); +    m_image->scale( cw, ch, 0, KisFilterStrategyRegistry::instance()->get( "Mitchell") ); +    return 0; +} +Kross::Api::Object::Ptr Image::resize(Kross::Api::List::Ptr args) +{ +    int nw = Kross::Api::Variant::toInt(args->item(0)); +    int nh = Kross::Api::Variant::toInt(args->item(1)); +    int x = 0; +    int y = 0; +    if(args->count() > 2) +    { +        x = Kross::Api::Variant::toInt(args->item(2)); +        y = Kross::Api::Variant::toInt(args->item(3)); +    } +    m_image->resize( nw, nh, x, y ); +    return 0; +} + + +} + +} diff --git a/krita/plugins/viewplugins/scripting/kritacore/krs_image.h b/krita/plugins/viewplugins/scripting/kritacore/krs_image.h new file mode 100644 index 000000000..0be2e46f8 --- /dev/null +++ b/krita/plugins/viewplugins/scripting/kritacore/krs_image.h @@ -0,0 +1,94 @@ +/* + *  Copyright (c) 2005 Cyrille Berger <cberger@cberger.net> + * + *  This program is free software; you can redistribute it and/or modify + *  it under the terms of the GNU Library 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 Library General Public License for more details. + * + *  You should have received a copy of the GNU Library 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. + */ + +#ifndef KROSS_KRITACOREKRSIMAGE_H +#define KROSS_KRITACOREKRSIMAGE_H + +#include <api/class.h> + +#include <kis_types.h> + +class KisDoc; + +namespace Kross { + +namespace KritaCore { + +class Image : public Kross::Api::Class<Image> +{ +    public: +        Image(KisImageSP image, KisDoc* doc = 0); +        ~Image(); +        virtual const QString getClassName() const; +    private: +        /** +         * Return the active PaintLayer, if any. +         */ +        Kross::Api::Object::Ptr getActivePaintLayer(Kross::Api::List::Ptr); +        /** +         * Return the width of the image. +         */ +        Kross::Api::Object::Ptr getWidth(Kross::Api::List::Ptr); +        /** +         * Return the height of the image. +         */ +        Kross::Api::Object::Ptr getHeight(Kross::Api::List::Ptr); +        /** +         * Resize an image +         */ +        Kross::Api::Object::Ptr resize(Kross::Api::List::Ptr); +        /** +         * Scale an image +         */ +        Kross::Api::Object::Ptr scale(Kross::Api::List::Ptr); +        /** +         * Convert the image to a colorspace. +         * This function takes one argument : +         *  - the name of the destination colorspace +         *  +         * For example (in Ruby) : +         * @code +         * image.convertToColorspace("CMYK") +         * @endcode +         */ +        Kross::Api::Object::Ptr convertToColorspace(Kross::Api::List::Ptr args); +        /** +         * Return the id of the colorspace of this image. +         */ +        Kross::Api::Object::Ptr colorSpaceId(Kross::Api::List::Ptr ); +        /** +         * Create a new PaintLayer for this image, and return it. +         * This function takes at least two arguments : +         *  - the name of the layer +         *  - the opacity of the layer (between 0 and 255) +         *  +         * This function can take one optional argument : +         *  - the id of the colorSpace (if this is not specified, the new PaintLayer +         *      will have the same colorspace as the image) +         */ +        Kross::Api::Object::Ptr createPaintLayer(Kross::Api::List::Ptr args); +    private: +        KisImageSP m_image; +        KisDoc* m_doc; +}; + +} + +} + +#endif diff --git a/krita/plugins/viewplugins/scripting/kritacore/krs_iterator.h b/krita/plugins/viewplugins/scripting/kritacore/krs_iterator.h new file mode 100644 index 000000000..9493f49a7 --- /dev/null +++ b/krita/plugins/viewplugins/scripting/kritacore/krs_iterator.h @@ -0,0 +1,306 @@ +/* + *  Copyright (c) 2005 Cyrille Berger <cberger@cberger.net> + * + *  This program is free software; you can redistribute it and/or modify + *  it under the terms of the GNU Library 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 Library General Public License for more details. + * + *  You should have received a copy of the GNU Library 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. + */ + +#ifndef KROSS_KRITACOREKRS_ITERATOR_H +#define KROSS_KRITACOREKRS_ITERATOR_H + +#include <qobject.h> +#include <api/class.h> +//#include <api/proxy.h> +//#include <api/variant.h> + +#include <klocale.h> + +#include <kis_paint_layer.h> +#include <kis_paint_device.h> +#include <kis_types.h> + +#include <kis_script_monitor.h> + +namespace Kross { + +namespace KritaCore { + +//<beurk> stupid Qt which doesn't support templated QObject +class IteratorMemoryManaged { +    public: +        virtual void invalidateIterator() = 0; +}; +     +class IteratorMemoryManager : public QObject { +    Q_OBJECT +    public: +        IteratorMemoryManager(IteratorMemoryManaged* it) : m_it(it) +        { +            // Connect the Monitor to know when the invalidating of iterator is needed +            connect(KisScriptMonitor::instance(), SIGNAL(executionFinished(const Kross::Api::ScriptAction* )), this, SLOT(invalidateIterator())); + +        } +    public slots: +        void invalidateIterator() +        { +            m_it->invalidateIterator(); +        } +    private: +        IteratorMemoryManaged* m_it; +}; +//</beurk> +/** + * This object allow to change the value of pixel one by one. + * The name of some function depends of the colorspace, for instance, if + * the colorspace of the layer is RGB, you will have setR, setG, setB... and for CMYK, + * setC, setM, setY, setK. In the doc bellow we will consider the colorspace is called ABC with + * three channels : A, B and C. + *  + * Function: setA setB setC + * Those functions take one argument: + *  - the new value of one of the channel of this pixel + *  + * Function: setABC + * Set the value of all channels. + * This function take one argument: + *  - an array with the new value for all channels + */ +template<class _T_It> +class Iterator : public Kross::Api::Class<Iterator<_T_It> >, private IteratorMemoryManaged +{ +    public: +        Iterator(_T_It it, KisPaintLayerSP layer) : Kross::Api::Class<Iterator<_T_It> >("KritaIterator"), m_itmm (new IteratorMemoryManager(this)), m_it(new _T_It(it)), nchannels(layer->paintDevice()->nChannels()), m_layer(layer) +        { +            // navigate in the iterator +            this->addFunction("next", +                new Kross::Api::ProxyFunction< +                    Iterator<_T_It>, // instance +                    bool (Iterator<_T_It>::*)(), // method +                    Kross::Api::Variant // return-value +                >(this, &Iterator<_T_It>::next)); +            this->addFunction("isDone", +                new Kross::Api::ProxyFunction< +                    Iterator<_T_It>, // instance +                    bool (Iterator<_T_It>::*)(), // method +                    Kross::Api::Variant // return-value +                >(this, &Iterator<_T_It>::isDone)); + +            // get/set value +            QValueVector<KisChannelInfo *> channels = layer->paintDevice()->colorSpace()->channels(); +            QString initiales = ""; +            for(QValueVector<KisChannelInfo *>::iterator itC = channels.begin(); itC != channels.end(); itC++) +            { +                KisChannelInfo * ci = *itC; +                initiales += ci->name().left(1); +                switch(ci->channelValueType()) +                { +                    case KisChannelInfo::UINT8: +                        this->addFunction("get"+ci->name(), +                            new Kross::Api::Function1< Iterator<_T_It> , uint >( +                                this, &Iterator<_T_It>::getChannelUINT8, ci->pos() ) ); +                        this->addFunction("set"+ci->name(), +                            new Kross::Api::Function1< Iterator<_T_It> , uint >( +                                this, &Iterator<_T_It>::setChannelUINT8, ci->pos() ) ); +                        break; +                    case KisChannelInfo::UINT16: +                        this->addFunction("get"+ci->name(), +                            new Kross::Api::Function1< Iterator<_T_It> , uint >( +                                this, &Iterator<_T_It>::getChannelUINT16, ci->pos() ) ); +                        this->addFunction("set"+ci->name(), +                            new Kross::Api::Function1< Iterator<_T_It> , uint >( +                                this, &Iterator<_T_It>::setChannelUINT16, ci->pos() ) ); +                        break; +                    case KisChannelInfo::FLOAT32: +                        this->addFunction("get"+ci->name(), +                            new Kross::Api::Function1< Iterator<_T_It> , uint >( +                                this, &Iterator<_T_It>::getChannelFLOAT, ci->pos() ) ); +                        this->addFunction("set"+ci->name(), +                            new Kross::Api::Function1< Iterator<_T_It> , uint >( +                                this, &Iterator<_T_It>::setChannelFLOAT, ci->pos() ) ); +                        break; +                    default: +                        kdDebug(41011) << "unsupported data format in scripts" << endl; +                        break; +                } +            } +            initiales = initiales.upper(); +            // set/get general +            addFunction("set" + initiales, &Iterator::setPixel); +            addFunction("get" + initiales, &Iterator::getPixel); +            kdDebug(41011) << ( "get" + initiales ) << endl; +            // Various colorSpace +            addFunction("invertColor", &Iterator::invertColor); +            addFunction("darken", &Iterator::darken); +        } +     +        ~Iterator() +        { +            invalidateIterator(); +            delete m_itmm; +        } +        virtual const QString getClassName() const { +            return "Kross::KritaCore::KrsDoc"; +        }; +    private: +        /** +         * Darken a pixel. +         * This functions at least one argument: +         *  - shade amount use to darken all color channels +         *  +         * This function can take the following optional argument: +         *  - compensation to limit the darkening +         */ +        Kross::Api::Object::Ptr darken(Kross::Api::List::Ptr args) +        { +            Q_INT32 shade = Kross::Api::Variant::toUInt( args->item(0) ); +            bool compensate = (args->count() == 2); +            double compensation = compensate ? Kross::Api::Variant::toDouble( args->item(2) ) : 0.; +            m_layer->paintDevice()->colorSpace()->darken(m_it->rawData(), m_it->rawData(), shade, compensate, compensation, 1); +            return 0; +        } +        /** +         * Invert the color of a pixel. +         */ +        Kross::Api::Object::Ptr invertColor(Kross::Api::List::Ptr ) +        { +            m_layer->paintDevice()->colorSpace()->invertColor(m_it->rawData(), 1); +            return 0; +        } +        /** +         * Increment the positon, and go to the next pixel. +         */ +        bool next() +        { +            ++(*m_it); +            return m_it->isDone(); +        } +        /** +         * Return true if the iterator is at the end, and that no more pixels are available. +         */ +        bool isDone() +        { +            return m_it->isDone(); +        } +        Kross::Api::Object::Ptr getChannelUINT8(Kross::Api::List::Ptr, uint channelpos) +        { +            Q_UINT8* data = (Q_UINT8*)(m_it->rawData() + channelpos); +            return new Kross::Api::Variant( * data); +        } +        Kross::Api::Object::Ptr setChannelUINT8(Kross::Api::List::Ptr args, uint channelpos) +        { +            Q_UINT8* data = (Q_UINT8*)(m_it->rawData() + channelpos); //*(uint*)channelpos); +            *data = Kross::Api::Variant::toUInt( args->item(0) ); +            return 0; +        } +        Kross::Api::Object::Ptr getChannelUINT16(Kross::Api::List::Ptr, uint channelpos) +        { +            Q_UINT16* data = (Q_UINT16*)(m_it->rawData() + channelpos); +            return new Kross::Api::Variant( * data); +        } +        Kross::Api::Object::Ptr setChannelUINT16(Kross::Api::List::Ptr args, uint channelpos) +        { +            Q_UINT16* data = (Q_UINT16*)(m_it->rawData() + channelpos); +            *data =  Kross::Api::Variant::toUInt( args->item(0) ); +            return 0; +        } +        Kross::Api::Object::Ptr getChannelFLOAT(Kross::Api::List::Ptr, uint channelpos) +        { +            float* data = (float*)(m_it->rawData() + channelpos); +            return new Kross::Api::Variant( * data); +        } +        Kross::Api::Object::Ptr setChannelFLOAT(Kross::Api::List::Ptr args, uint channelpos) +        { +            float* data = (float*)(m_it->rawData() + channelpos); +            *data = Kross::Api::Variant::toUInt( args->item(0) ); +            return 0; +        } +        Kross::Api::Object::Ptr getPixel(Kross::Api::List::Ptr) +        { +            QValueVector<KisChannelInfo *> channels = m_layer->paintDevice()->colorSpace()->channels(); +            QValueList<QVariant> pixel; +            for(QValueVector<KisChannelInfo *>::iterator itC = channels.begin(); itC != channels.end(); itC++) +            { +                KisChannelInfo * ci = *itC; +                Q_UINT8* data = (Q_UINT8*)(m_it->rawData() + ci->pos()); +                switch(ci->channelValueType()) +                { +                    case KisChannelInfo::UINT8: +                        pixel.push_back( *data); +                        break; +                    case KisChannelInfo::UINT16: +                        pixel.push_back( *((Q_UINT16*) data) ); +                        break; +                    case KisChannelInfo::FLOAT32: +                        pixel.push_back( *((float*) data) ); +                        break; +                    default: +                        kdDebug(41011) << i18n("An error has occurred in %1").arg("getPixel") << endl; +                        kdDebug(41011) << i18n("unsupported data format in scripts") << endl; +                        break; +                } +            } +            return new Kross::Api::Variant( pixel); +        } +        Kross::Api::Object::Ptr setPixel(Kross::Api::List::Ptr args) +        { +            QValueList<QVariant> pixel = Kross::Api::Variant::toList( args->item(0) ); +            QValueVector<KisChannelInfo *> channels = m_layer->paintDevice()->colorSpace()->channels(); +            uint i = 0; +            for(QValueVector<KisChannelInfo *>::iterator itC = channels.begin(); itC != channels.end(); itC++, i++) +            { +                KisChannelInfo * ci = *itC; +                Q_UINT8* data = (Q_UINT8*)(m_it->rawData() + ci->pos()); +                switch(ci->channelValueType()) +                { +                    case KisChannelInfo::UINT8: +                        *data = pixel[i].toUInt(); +                        break; +                    case KisChannelInfo::UINT16: +                        *((Q_UINT16*) data) = pixel[i].toUInt(); +                        break; +                    case KisChannelInfo::FLOAT32: +                        *((float*) data) = pixel[i].toDouble(); +                        break; +                    default: +                        kdDebug(41011) << i18n("An error has occurred in %1").arg("setPixel") << endl; +                        kdDebug(41011) << i18n("unsupported data format in scripts") << endl; +                        break; +                } +            } +            return 0; +        } +    private: +        virtual void invalidateIterator() +        { +            kdDebug(41011) << "invalidating iterator" << endl; +            if(m_it) +            { +                kdDebug(41011) << "deleting iterator" << endl; +                delete m_it; +            } +            m_it = 0; +            kdDebug() << " Iterator = " << m_it << endl; +        } +    private: +        IteratorMemoryManager* m_itmm; +        _T_It* m_it; +        int nchannels; +        KisPaintLayerSP m_layer; +}; + +} + +} + +#endif diff --git a/krita/plugins/viewplugins/scripting/kritacore/krs_paint_layer.cpp b/krita/plugins/viewplugins/scripting/kritacore/krs_paint_layer.cpp new file mode 100644 index 000000000..1f79b22cd --- /dev/null +++ b/krita/plugins/viewplugins/scripting/kritacore/krs_paint_layer.cpp @@ -0,0 +1,207 @@ +/* + *  Copyright (c) 2005 Cyrille Berger <cberger@cberger.net> + * + *  This program is free software; you can redistribute it and/or modify + *  it under the terms of the GNU Library 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 Library General Public License for more details. + * + *  You should have received a copy of the GNU Library 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 "krs_paint_layer.h" + +#include <klocale.h> + +#include <kis_colorspace_factory_registry.h> +#include <kis_doc.h> +#include <kis_layer.h> +#include <kis_meta_registry.h> +#include <kis_iterators_pixel.h> +#include <kis_transaction.h> +#include <kis_math_toolbox.h> + +#include "krs_iterator.h" +#include "krs_histogram.h" +#include "krs_painter.h" +#include "krs_wavelet.h" + +namespace Kross { + +namespace KritaCore { + +PaintLayer::PaintLayer(KisPaintLayerSP layer, KisDoc* doc) +    : Kross::Api::Class<PaintLayer>("KritaLayer"), m_layer(layer), m_doc(doc), m_cmd(0) +{ +    addFunction("createRectIterator", &PaintLayer::createRectIterator); +    addFunction("createHLineIterator", &PaintLayer::createHLineIterator); +    addFunction("createVLineIterator", &PaintLayer::createVLineIterator); +    addFunction("getWidth", &PaintLayer::getWidth); +    addFunction("getHeight", &PaintLayer::getHeight); +    addFunction("createHistogram", &PaintLayer::createHistogram); +    addFunction("createPainter", &PaintLayer::createPainter); +    addFunction("beginPainting", &PaintLayer::beginPainting); +    addFunction("endPainting", &PaintLayer::endPainting); +    addFunction("convertToColorspace", &PaintLayer::convertToColorspace); +    addFunction("fastWaveletTransformation", &PaintLayer::fastWaveletTransformation); +    addFunction("fastWaveletUntransformation", &PaintLayer::fastWaveletUntransformation); +    addFunction("colorSpaceId", &PaintLayer::colorSpaceId); +} + + +PaintLayer::~PaintLayer() +{ +} + +const QString PaintLayer::getClassName() const { +    return "Kross::KritaCore::PaintLayer"; +} + +Kross::Api::Object::Ptr PaintLayer::createRectIterator(Kross::Api::List::Ptr args) +{ +    return new Iterator<KisRectIteratorPixel>( +            paintLayer()->paintDevice()->createRectIterator(Kross::Api::Variant::toUInt(args->item(0)), +                                        Kross::Api::Variant::toUInt(args->item(1)), +                                        Kross::Api::Variant::toUInt(args->item(2)), +                                        Kross::Api::Variant::toUInt(args->item(3)), true), +            paintLayer()); +} +Kross::Api::Object::Ptr PaintLayer::createHLineIterator(Kross::Api::List::Ptr args) +{ +    return new Iterator<KisHLineIteratorPixel>( +            paintLayer()->paintDevice()->createHLineIterator(Kross::Api::Variant::toUInt(args->item(0)), +                                        Kross::Api::Variant::toUInt(args->item(1)), +                                        Kross::Api::Variant::toUInt(args->item(2)), true), +            paintLayer()); +} +Kross::Api::Object::Ptr PaintLayer::createVLineIterator(Kross::Api::List::Ptr args) +{ +    return new Iterator<KisVLineIteratorPixel>( +            paintLayer()->paintDevice()->createVLineIterator(Kross::Api::Variant::toUInt(args->item(0)), +                                        Kross::Api::Variant::toUInt(args->item(1)), +                                        Kross::Api::Variant::toUInt(args->item(2)), true), +            paintLayer()); +} +Kross::Api::Object::Ptr PaintLayer::getWidth(Kross::Api::List::Ptr) +{ +    QRect r1 = paintLayer()->extent(); +    QRect r2 = paintLayer()->image()->bounds(); +    QRect rect = r1.intersect(r2); +    return new Kross::Api::Variant(rect.width()); +} +Kross::Api::Object::Ptr PaintLayer::getHeight(Kross::Api::List::Ptr) +{ +    QRect r1 = paintLayer()->extent(); +    QRect r2 = paintLayer()->image()->bounds(); +    QRect rect = r1.intersect(r2); +    return new Kross::Api::Variant(rect.height()); +} + +Kross::Api::Object::Ptr PaintLayer::createHistogram(Kross::Api::List::Ptr args) +{ +    QString histoname = Kross::Api::Variant::toString(args->item(0)); +    KisHistogramProducerFactory* factory = KisHistogramProducerFactoryRegistry::instance()->get(histoname); + +/*    KisIDList listID = KisHistogramProducerFactoryRegistry::instance()->listKeys(); +    for(KisIDList::iterator it = listID.begin(); it != listID.end(); it++) +    { +        kdDebug(41011) << (*it).name() << " " << (*it).id() << endl; +    }*/ + +    enumHistogramType type ; +    switch( Kross::Api::Variant::toUInt(args->item(1)) ) +    { +        case 1: +            type = LOGARITHMIC; +            break; +        case 0: +        default: +            type = LINEAR; +            break; +    } +    if(factory && factory->isCompatibleWith( paintLayer()->paintDevice()->colorSpace() )) +    { +        return new Histogram( paintLayer().data(), factory->generate() , type); +    } else { +        throw Kross::Api::Exception::Ptr( new Kross::Api::Exception( i18n("An error has occured in %1").arg("createHistogram") + "\n" + i18n("The histogram %1 is not available").arg(histoname) ) ); +    } +    return 0; +} + +Kross::Api::Object::Ptr PaintLayer::createPainter(Kross::Api::List::Ptr ) +{ +    return new Painter(paintLayer()); +} + +Kross::Api::Object::Ptr PaintLayer::beginPainting(Kross::Api::List::Ptr args) +{ +    QString name = Kross::Api::Variant::toString(args->item(0)); +    if(m_cmd != 0) +    { +        delete m_cmd; +    } +    m_cmd = new KisTransaction(name, paintLayer()->paintDevice()); +    Q_CHECK_PTR(m_cmd); +    return 0; +} + +Kross::Api::Object::Ptr PaintLayer::endPainting(Kross::Api::List::Ptr) +{ +    if(doc() !=0) +    { +        doc()->setModified(true); +        doc()->currentImage()->activeLayer()->setDirty(); +    } +    if(m_cmd != 0) +    { +        paintLayer()->image()->undoAdapter()->addCommand(m_cmd); +    } +    return 0; +} + +Kross::Api::Object::Ptr PaintLayer::convertToColorspace(Kross::Api::List::Ptr args) +{ +    KisColorSpace * dstCS = KisMetaRegistry::instance()->csRegistry()->getColorSpace(KisID(Kross::Api::Variant::toString(args->item(0)), ""), ""); +    if(!dstCS) +    { +        // FIXME: inform user +        throw Kross::Api::Exception::Ptr( new Kross::Api::Exception( i18n("An error has occured in %1").arg("convertToColorspace") + "\n" + i18n("Colorspace %1 is not available, please check your installation.").arg(Kross::Api::Variant::toString(args->item(0))) ) ); +        return 0; +    } +    paintLayer()->paintDevice()->convertTo(dstCS); +    return 0; +} + +Kross::Api::Object::Ptr PaintLayer::colorSpaceId(Kross::Api::List::Ptr ) +{ +    return new Kross::Api::Variant( paintLayer()->paintDevice()->colorSpace()->id().id() ); +} + + +Kross::Api::Object::Ptr PaintLayer::fastWaveletTransformation(Kross::Api::List::Ptr ) +{ +    KisMathToolbox* mathToolbox = KisMetaRegistry::instance()->mtRegistry()->get( paintLayer()->paintDevice()->colorSpace()->mathToolboxID() ); +    QRect rect = paintLayer()->exactBounds(); +    KisMathToolbox::KisWavelet* wav = mathToolbox->fastWaveletTransformation(paintLayer()->paintDevice(), rect); +    return new Wavelet(wav); +} +Kross::Api::Object::Ptr PaintLayer::fastWaveletUntransformation(Kross::Api::List::Ptr args) +{ +    Wavelet* wav = (Wavelet*)args->item(0).data(); +    KisMathToolbox* mathToolbox = KisMetaRegistry::instance()->mtRegistry()->get( paintLayer()->paintDevice()->colorSpace()->mathToolboxID() ); +    QRect rect = paintLayer()->exactBounds(); +    mathToolbox->fastWaveletUntransformation( paintLayer()->paintDevice(), rect, wav->wavelet() ); +    return 0; +} + + +} + +} diff --git a/krita/plugins/viewplugins/scripting/kritacore/krs_paint_layer.h b/krita/plugins/viewplugins/scripting/kritacore/krs_paint_layer.h new file mode 100644 index 000000000..4ddfd4bdf --- /dev/null +++ b/krita/plugins/viewplugins/scripting/kritacore/krs_paint_layer.h @@ -0,0 +1,140 @@ +/* + *  Copyright (c) 2005 Cyrille Berger <cberger@cberger.net> + * + *  This program is free software; you can redistribute it and/or modify + *  it under the terms of the GNU Library 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 Library General Public License for more details. + * + *  You should have received a copy of the GNU Library 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. + */ + +#ifndef KROSS_KRITACOREKRSLAYER_H +#define KROSS_KRITACOREKRSLAYER_H + +#include <api/class.h> + +#include <kis_types.h> +#include <kis_paint_layer.h> + +class KisDoc; +class KisTransaction; + +namespace Kross { + +namespace KritaCore { + +/** +@author Cyrille Berger +*/ +class PaintLayer : public Kross::Api::Class<PaintLayer> +{ +    public: +        explicit PaintLayer(KisPaintLayerSP layer, KisDoc* doc = 0); +        virtual ~PaintLayer(); +        virtual const QString getClassName() const; +    private: +        /** +         * Create an iterator over a layer, it will iterate on a rectangle area. +         * This function takes four arguments : +         *  - x +         *  - y +         *  - width of the rectangle +         *  - height of the rectangle +         */ +        Kross::Api::Object::Ptr createRectIterator(Kross::Api::List::Ptr); +        /** +         * Create an iterator over a layer, it will iterate on a row. +         * This function takes three arguments : +         *  - x start in the row +         *  - y vertical position of the row +         *  - width of the row +         */ +        Kross::Api::Object::Ptr createHLineIterator(Kross::Api::List::Ptr); +        /** +         * Create an iterator over a layer, it will iterate on a column. +         * This function takes three arguments : +         *  - x horizontal position of the column +         *  - y start in the column +         *  - height of the column +         */ +        Kross::Api::Object::Ptr createVLineIterator(Kross::Api::List::Ptr); +        /** +         * Return the width of the layer +         */ +        Kross::Api::Object::Ptr getWidth(Kross::Api::List::Ptr); +        /** +         * Return the height of the layer +         */ +        Kross::Api::Object::Ptr getHeight(Kross::Api::List::Ptr); +        /** +         * This function creates an Histogram for this layer. +         * It takes two arguments : +         *  - the type of the histogram ("RGB8HISTO") +         *  - 0 if the histogram is linear, or 1 if it is logarithmic +         */ +        Kross::Api::Object::Ptr createHistogram(Kross::Api::List::Ptr); +        /** +         * This function create a Painter which will allow you to some painting on the layer. +         */ +        Kross::Api::Object::Ptr createPainter(Kross::Api::List::Ptr); +        /** +         * Uses this function to create a new undo entry. +         */ +        Kross::Api::Object::Ptr beginPainting(Kross::Api::List::Ptr args); +        /** +         * Uses this function to close the current undo entry and add it to the history. +         */ +        Kross::Api::Object::Ptr endPainting(Kross::Api::List::Ptr args); +        /** +         * Convert the image to a colorspace. +         * This function takes one argument : +         *  - the name of the destination colorspace +         *  +         * For example (in Ruby) : +         * @code +         * image.convertToColorspace("CMYK") +         * @endcode +         */ +        Kross::Api::Object::Ptr convertToColorspace(Kross::Api::List::Ptr args); +        /** +         * Return the id of the colorspace of this paint layer. +         */ +        Kross::Api::Object::Ptr colorSpaceId(Kross::Api::List::Ptr ); +        /** +         * Return the fast wavelet transformed of the layer +         */ +        Kross::Api::Object::Ptr fastWaveletTransformation(Kross::Api::List::Ptr args); +        /** +         * Untransform a fast wavelet into this layer +         * It takes one argument : +         *  - a wavelet object +         *  +         * For example (in Ruby) : +         * @code +         * wavelet = layer.fastWaveletTransformation() +         * layer.fastWaveletUntransformation(wavelet) +         * @endcode +         */ +        Kross::Api::Object::Ptr fastWaveletUntransformation(Kross::Api::List::Ptr args); +    public: +        inline KisPaintLayerSP paintLayer() { return m_layer; } +        inline KisDoc* doc() { return m_doc; } +    private: +        KisPaintLayerSP m_layer; +        KisDoc* m_doc; +        KisTransaction* m_cmd; +}; + +} + +} + +#endif diff --git a/krita/plugins/viewplugins/scripting/kritacore/krs_painter.cpp b/krita/plugins/viewplugins/scripting/kritacore/krs_painter.cpp new file mode 100644 index 000000000..621a173d7 --- /dev/null +++ b/krita/plugins/viewplugins/scripting/kritacore/krs_painter.cpp @@ -0,0 +1,358 @@ +/* + *  Copyright (c) 2005-2006 Cyrille Berger <cberger@cberger.net> + * + *  This program is free software; you can redistribute it and/or modify + *  it under the terms of the GNU Library 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 Library General Public License for more details. + * + *  You should have received a copy of the GNU Library 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 "krs_painter.h" + +#include <kis_convolution_painter.h> +#include <kis_fill_painter.h> +#include <kis_paint_layer.h> +#include <kis_paintop_registry.h> +#include <kis_painter.h> + +#include "krs_brush.h" +#include "krs_color.h" +#include "krs_pattern.h" + +namespace Kross { + +namespace KritaCore { + +Painter::Painter(KisPaintLayerSP layer) +    : Kross::Api::Class<Painter>("KritaPainter"), m_layer(layer),m_painter(new KisPainter(layer->paintDevice())),m_threshold(1) +{ +    // convolution +    addFunction("convolve", &Painter::convolve); +    // Fill specific +    addFunction("setFillThreshold", &Painter::setFillThreshold); +    addFunction("fillColor", &Painter::fillColor); +    addFunction("fillPattern", &Painter::fillPattern); + +    // Painting operations +    addFunction("paintPolyline", &Painter::paintPolyline); +    addFunction("paintLine", &Painter::paintLine); +    addFunction("paintBezierCurve", &Painter::paintBezierCurve); +    addFunction("paintEllipse", &Painter::paintEllipse); +    addFunction("paintPolygon", &Painter::paintPolygon); +    addFunction("paintRect", &Painter::paintRect); +    addFunction("paintAt", &Painter::paintAt); +    addFunction("setBackgroundColor", &Painter::setBackgroundColor); +    addFunction("setPaintColor", &Painter::setPaintColor); +     +    // Color operations +    addFunction("setPattern", &Painter::setPattern); +    addFunction("setBrush", &Painter::setBrush); +     +    // How is painting done operations +    addFunction("setPaintOp", &Painter::setPaintOp); +    // Special settings +    addFunction("setDuplicateOffset", &Painter::setDuplicateOffset); +     +    // Style operation +    addFunction("setOpacity", &Painter::setOpacity); +    addFunction("setStrokeStyle", &Painter::setStrokeStyle); +    addFunction("setFillStyle", &Painter::setFillStyle); +} + + +Painter::~Painter() +{ +    delete m_painter; +} + +Kross::Api::Object::Ptr Painter::convolve(Kross::Api::List::Ptr args) +{ +    KisConvolutionPainter* cp = new KisConvolutionPainter(m_painter->device()); +    QRect rect; +    KisKernel kernel; +    kernel.factor = Kross::Api::Variant::toInt(args->item(1)); +    kernel.offset = Kross::Api::Variant::toInt(args->item(2)); +     +    uint borderop = 3; +    if( args.count() > 3 ) +    { +        borderop = Kross::Api::Variant::toUInt(args->item(3)); +    } +    uint channelsFlag = KisChannelInfo::FLAG_COLOR; +    if( args.count() > 4 ) +    { +        channelsFlag = Kross::Api::Variant::toUInt(args->item(4)); +    } +    if( args.count() > 5) +    { +        uint x = Kross::Api::Variant::toUInt(args->item(5)); +        uint y = Kross::Api::Variant::toUInt(args->item(6)); +        uint w = Kross::Api::Variant::toUInt(args->item(7)); +        uint h = Kross::Api::Variant::toUInt(args->item(8)); +        rect = QRect(x,y,w,h); +    } else { +        QRect r1 = paintLayer()->paintDevice()->extent(); +        QRect r2 = paintLayer()->image()->bounds(); +        rect = r1.intersect(r2); +    } +     +    QValueList<QVariant> kernelH = Kross::Api::Variant::toList( args->item(0) ); +     +    QVariant firstlineVariant = *kernelH.begin(); +    if(firstlineVariant.type() != QVariant::List) +    { +        throw Kross::Api::Exception::Ptr( new Kross::Api::Exception(i18n("An error has occured in %1").arg("applyConvolution")) ); +    } +     +    QValueList<QVariant> firstline = firstlineVariant.toList(); +     +    kernel.height = kernelH.size(); +    kernel.width = firstline.size(); +     +    kernel.data = new Q_INT32[kernel.height * kernel.width]; +     +    uint i = 0; +    for(QValueList<QVariant>::iterator itK = kernelH.begin(); itK != kernelH.end(); itK++, i ++ ) +    { +        QVariant lineVariant = *kernelH.begin(); +        if(lineVariant.type() != QVariant::List) +        { +            throw Kross::Api::Exception::Ptr( new Kross::Api::Exception(i18n("An error has occured in %1").arg("applyConvolution")) ); +        } +        QValueList<QVariant> line = firstlineVariant.toList(); +        if(line.size() != kernel.width) +        { +            throw Kross::Api::Exception::Ptr( new Kross::Api::Exception(i18n("An error has occured in %1").arg("applyConvolution")) ); +        } +        uint j = 0; +        for(QValueList<QVariant>::iterator itLine = line.begin(); itLine != line.end(); itLine++, j ++ ) +        { +            kernel.data[ j + i * kernel.width ] = (*itLine).toInt(); +        } +    } +    cp->applyMatrix(&kernel, rect.x(), rect.y(), rect.width(), rect.height(), (KisConvolutionBorderOp)borderop, (KisChannelInfo::enumChannelFlags) channelsFlag); +     +    delete[] kernel.data; +    return 0; +} + + +KisFillPainter* Painter::createFillPainter() +{ +    KisFillPainter* fp = new KisFillPainter(m_painter->device()); +    fp->setBrush( m_painter->brush() ); +    fp->setFillColor( m_painter->fillColor() ); +    fp->setPaintColor( m_painter->paintColor() ); +    fp->setFillStyle( m_painter->fillStyle() ); +    fp->setOpacity( m_painter->opacity() ); +    fp->setPattern( m_painter->pattern() ); +    return fp; +} + +Kross::Api::Object::Ptr Painter::setFillThreshold(Kross::Api::List::Ptr args) +{ +    m_threshold = Kross::Api::Variant::toInt(args->item(0)); +    return 0; +} +Kross::Api::Object::Ptr Painter::fillColor(Kross::Api::List::Ptr args) +{ +    KisFillPainter* fp = createFillPainter(); +    uint x = Kross::Api::Variant::toUInt(args->item(0)); +    uint y = Kross::Api::Variant::toUInt(args->item(1)); + +    fp->fillColor( x, y ); +    return 0; +} +Kross::Api::Object::Ptr Painter::fillPattern(Kross::Api::List::Ptr args) +{ +    KisFillPainter* fp = createFillPainter(); +    uint x = Kross::Api::Variant::toUInt(args->item(0)); +    uint y = Kross::Api::Variant::toUInt(args->item(1)); +    fp->fillPattern(x, y); +    return 0; +} + +Kross::Api::Object::Ptr Painter::setStrokeStyle(Kross::Api::List::Ptr args) +{ +    uint style = Kross::Api::Variant::toVariant(args->item(0)).toUInt(); +    KisPainter::StrokeStyle strokestyle; +    switch(style) +    { +        case 1: +            strokestyle = KisPainter::StrokeStyleBrush; +            break; +        default: +            strokestyle = KisPainter::StrokeStyleNone; +    } +    m_painter->setStrokeStyle(strokestyle); +    return 0; +} + +Kross::Api::Object::Ptr Painter::setFillStyle(Kross::Api::List::Ptr args) +{ +    uint style = Kross::Api::Variant::toVariant(args->item(0)).toUInt(); +    KisPainter::FillStyle fillstyle; +    switch(style) +    { +        case 1: +            fillstyle = KisPainter::FillStyleForegroundColor; +            break; +        case 2: +            fillstyle = KisPainter::FillStyleBackgroundColor; +            break; +        case 3: +            fillstyle = KisPainter::FillStylePattern; +            break; +        default: +            fillstyle = KisPainter::FillStyleNone; +    } +    m_painter->setFillStyle(fillstyle); +    return 0; +} + +Kross::Api::Object::Ptr Painter::setOpacity(Kross::Api::List::Ptr args) +{ +    Q_UINT8 opacity = Kross::Api::Variant::toVariant(args->item(0)).toUInt(); +    m_painter->setOpacity(opacity); +    return 0; +} + +Kross::Api::Object::Ptr Painter::setDuplicateOffset(Kross::Api::List::Ptr args) +{ +    double x1 = Kross::Api::Variant::toVariant(args->item(0)).toDouble(); +    double y1 = Kross::Api::Variant::toVariant(args->item(1)).toDouble(); +    m_painter->setDuplicateOffset(KisPoint(x1,y1)); +    return 0; +} + +Kross::Api::Object::Ptr Painter::paintPolyline(Kross::Api::List::Ptr args) +{ +    QValueList<QVariant> pointsX = Kross::Api::Variant::toList( args->item(0) ); +    QValueList<QVariant> pointsY = Kross::Api::Variant::toList( args->item(1) ); +    if(pointsX.size() != pointsY.size()) +    { +        throw Kross::Api::Exception::Ptr( new Kross::Api::Exception("the two lists should have the same size.") ); +    } +    m_painter->paintPolyline( createPointsVector( pointsX, pointsY)); +    return 0; +} + +Kross::Api::Object::Ptr Painter::paintLine(Kross::Api::List::Ptr args) +{ +    double x1 = Kross::Api::Variant::toVariant(args->item(0)).toDouble(); +    double y1 = Kross::Api::Variant::toVariant(args->item(1)).toDouble(); +    double p1 = Kross::Api::Variant::toVariant(args->item(2)).toDouble(); +    double x2 = Kross::Api::Variant::toVariant(args->item(3)).toDouble(); +    double y2 = Kross::Api::Variant::toVariant(args->item(4)).toDouble(); +    double p2 = Kross::Api::Variant::toVariant(args->item(5)).toDouble(); +    m_painter->paintLine(KisPoint( x1, y1), p1, 0.0, 0.0, KisPoint( x2, y2 ), p2, 0.0, 0.0 ); +    return 0; +} + +Kross::Api::Object::Ptr Painter::paintBezierCurve(Kross::Api::List::Ptr args) +{ +    double x1 = Kross::Api::Variant::toVariant(args->item(0)).toDouble(); +    double y1 = Kross::Api::Variant::toVariant(args->item(1)).toDouble(); +    double p1 = Kross::Api::Variant::toVariant(args->item(2)).toDouble(); +    double cx1 = Kross::Api::Variant::toVariant(args->item(3)).toDouble(); +    double cy1 = Kross::Api::Variant::toVariant(args->item(4)).toDouble(); +    double cx2 = Kross::Api::Variant::toVariant(args->item(5)).toDouble(); +    double cy2 = Kross::Api::Variant::toVariant(args->item(6)).toDouble(); +    double x2 = Kross::Api::Variant::toVariant(args->item(7)).toDouble(); +    double y2 = Kross::Api::Variant::toVariant(args->item(8)).toDouble(); +    double p2 = Kross::Api::Variant::toVariant(args->item(9)).toDouble(); +    m_painter->paintBezierCurve( KisPoint(x1,y1), p1, 0.0, 0.0, KisPoint(cx1,cy1), KisPoint(cx2,cy2), KisPoint(x2,y2), p2, 0.0, 0.0); +    return 0; +} + +Kross::Api::Object::Ptr Painter::paintEllipse(Kross::Api::List::Ptr args) +{ +    double x1 = Kross::Api::Variant::toVariant(args->item(0)).toDouble(); +    double y1 = Kross::Api::Variant::toVariant(args->item(1)).toDouble(); +    double x2 = Kross::Api::Variant::toVariant(args->item(2)).toDouble(); +    double y2 = Kross::Api::Variant::toVariant(args->item(3)).toDouble(); +    double p1 = Kross::Api::Variant::toVariant(args->item(4)).toDouble(); +    m_painter->paintEllipse( KisPoint(x1,y1), KisPoint(x2,y2), p1, 0.0, 0.0 ); +    return 0; +} + +Kross::Api::Object::Ptr Painter::paintPolygon(Kross::Api::List::Ptr args) +{ +    QValueList<QVariant> pointsX = Kross::Api::Variant::toList( args->item(0) ); +    QValueList<QVariant> pointsY = Kross::Api::Variant::toList( args->item(1) ); +    if(pointsX.size() != pointsY.size()) +    { +        throw Kross::Api::Exception::Ptr( new Kross::Api::Exception("the two lists should have the same size.") ); +    } +    m_painter->paintPolygon( createPointsVector(pointsX, pointsY)); +    return 0; +} + +Kross::Api::Object::Ptr Painter::paintRect(Kross::Api::List::Ptr args) +{ +    double x1 = Kross::Api::Variant::toVariant(args->item(0)).toDouble(); +    double y1 = Kross::Api::Variant::toVariant(args->item(1)).toDouble(); +    double x2 = Kross::Api::Variant::toVariant(args->item(2)).toDouble(); +    double y2 = Kross::Api::Variant::toVariant(args->item(3)).toDouble(); +    double p1 = Kross::Api::Variant::toVariant(args->item(4)).toDouble(); +    m_painter->paintRect( KisPoint(x1, y1), KisPoint(x2,y2), p1, 0, 0); +    return 0; +} + +Kross::Api::Object::Ptr Painter::paintAt(Kross::Api::List::Ptr args) +{ +    double x1 = Kross::Api::Variant::toVariant(args->item(0)).toDouble(); +    double y1 = Kross::Api::Variant::toVariant(args->item(1)).toDouble(); +    double p1 = Kross::Api::Variant::toVariant(args->item(2)).toDouble(); +    m_painter->paintAt( KisPoint( x1, y1 ), p1, 0.0, 0.0); +    return 0; +} + +Kross::Api::Object::Ptr Painter::setBackgroundColor(Kross::Api::List::Ptr args) +{ +    Color* c = (Color*)args->item(0).data(); +    m_painter->setBackgroundColor( KisColor(c->toQColor(), paintLayer()->paintDevice()->colorSpace() )); +    return 0; +} + +Kross::Api::Object::Ptr Painter::setPaintColor(Kross::Api::List::Ptr args) +{ +    Color* c = (Color*)args->item(0).data(); +    m_painter->setPaintColor( KisColor(c->toQColor(), paintLayer()->paintDevice()->colorSpace() )); +    return 0; +} + +Kross::Api::Object::Ptr Painter::setPattern(Kross::Api::List::Ptr args) +{ +    Pattern* p = (Pattern*)args->item(0).data(); +    m_painter->setPattern( p->getPattern()); +    return 0; +} + + +Kross::Api::Object::Ptr Painter::setBrush(Kross::Api::List::Ptr args) +{ +    Brush* b = (Brush*)args->item(0).data(); +    m_painter->setBrush( b->getBrush()); +    return 0; +} +Kross::Api::Object::Ptr Painter::setPaintOp(Kross::Api::List::Ptr args) +{ +    QString id = Kross::Api::Variant::toString(args->item(0)); +    KisPaintOp* op = KisPaintOpRegistry::instance()->paintOp( id, 0, m_painter ); +    m_painter->setPaintOp( op ); +    return 0; +} + +} + +} diff --git a/krita/plugins/viewplugins/scripting/kritacore/krs_painter.h b/krita/plugins/viewplugins/scripting/kritacore/krs_painter.h new file mode 100644 index 000000000..37ae79930 --- /dev/null +++ b/krita/plugins/viewplugins/scripting/kritacore/krs_painter.h @@ -0,0 +1,242 @@ +/* + *  Copyright (c) 2005-2006 Cyrille Berger <cberger@cberger.net> + * + *  This program is free software; you can redistribute it and/or modify + *  it under the terms of the GNU Library 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 Library General Public License for more details. + * + *  You should have received a copy of the GNU Library 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. + */ + +#ifndef KROSS_KRITACOREKRS_PAINTER_H +#define KROSS_KRITACOREKRS_PAINTER_H + +#include <api/class.h> + +#include <kis_point.h> +#include <kis_types.h> +#include <kis_paint_layer.h> + +class KisPainter; +class KisFillPainter; + +namespace Kross { + +namespace KritaCore { + +class Painter : public Kross::Api::Class<Painter> +{ +    public: +        explicit Painter(KisPaintLayerSP layer); +        ~Painter(); +    private: +        // Convolution +        /** +         * This function apply a convolution kernel to an image. +         * It takes at least three arguments : +         *  - a list of a list with the kernel (all lists need to have the same size) +         *  - factor +         *  - offset +         *  +         * The value of a pixel will be given by the following function K*P/factor + offset, +         * where K is the kernel and P is the neighbourhood. +         *  +         * It can takes the following optional arguments : +         *  - borderOp control how to convolve the pixels on the border of an image ( 0 use the default color +         * 1 use the pixel on the opposite side of the image 2 use the border pixel 3 avoid border pixels) +         *  - channel ( 1 for color 2 for alpha 3 for both) +         *  - x +         *  - y +         *  - width +         *  - height +         */ +        Kross::Api::Object::Ptr convolve(Kross::Api::List::Ptr args); +        // Fill specific +        /** +         * Set the threshold the fill threshold. +         * It takes one argument : +         *  - threshold +         */ +        Kross::Api::Object::Ptr setFillThreshold(Kross::Api::List::Ptr args); +        /** +         * Start filling color. +         * It takes two argument : +         *  - x +         *  - y +         */ +        Kross::Api::Object::Ptr fillColor(Kross::Api::List::Ptr args); +        /** +         * start filling a pattern +         * It takes two argument : +         *  - x +         *  - y +         */ +        Kross::Api::Object::Ptr fillPattern(Kross::Api::List::Ptr args); +        // Painting operations +        /** +         * This function will paint a polyline. +         * It takes two arguments : +         *  - a list of x position +         *  - a list of y position +         */ +        Kross::Api::Object::Ptr paintPolyline(Kross::Api::List::Ptr args); +        /** +         * This function will paint a line. +         * It takes five arguments : +         *  - x1 +         *  - y1 +         *  - x2 +         *  - y2 +         *  - pressure +         */ +        Kross::Api::Object::Ptr paintLine(Kross::Api::List::Ptr args); +        /** +         * This function will paint a Bezier curve. +         * It takes ten arguments : +         *  - x1 +         *  - y1 +         *  - p1 +         *  - cx1 +         *  - cy1 +         *  - cx2 +         *  - cx2 +         *  - x2 +         *  - y2 +         *  - p2 +         *  +         * Where (x1,y1) is the start position, p1 is the pressure at the start, +         * (x2,y2) is the ending position, p2 is the pressure at the end. (cx1,cy1) and (cx2,cy2) +         * are the position of the control points. +         */ +        Kross::Api::Object::Ptr paintBezierCurve(Kross::Api::List::Ptr args); +        /** +         * This function will paint an ellipse. +         * It takes five arguments : +         *  - x1 +         *  - y1 +         *  - x2 +         *  - y2 +         *  - pressure +         *  +         * Where (x1,y1) and (x2,y2) are the position of the two centers. +         */ +        Kross::Api::Object::Ptr paintEllipse(Kross::Api::List::Ptr args); +        /** +         * This function will paint a polygon. +         * It takes two arguments : +         *  - a list of x position +         *  - a list of y position +         */ +        Kross::Api::Object::Ptr paintPolygon(Kross::Api::List::Ptr args); +        /** +         * This function will paint a rectangle. +         * It takes five arguments : +         *  - x +         *  - y +         *  - width +         *  - height +         *  - pressure +         */ +        Kross::Api::Object::Ptr paintRect(Kross::Api::List::Ptr args); +        /** +         * This function will paint at a given position. +         * It takes three arguments : +         *  - x +         *  - y +         *  - pressure +         */ +        Kross::Api::Object::Ptr paintAt(Kross::Api::List::Ptr args); +        // Color operations +        /** +         * This functions set the paint color (also called foreground color). +         * It takes one argument : +         *  - a Color +         */ +        Kross::Api::Object::Ptr setPaintColor(Kross::Api::List::Ptr args); +        /** +         * This functions set the background color. +         * It takes one argument : +         *  - a Color +         */ +        Kross::Api::Object::Ptr setBackgroundColor(Kross::Api::List::Ptr args); +        // How is painting done operations +        /** +         * This functions set the pattern used for filling. +         * It takes one argument : +         *  - a Pattern object +         */ +        Kross::Api::Object::Ptr setPattern(Kross::Api::List::Ptr args); +        /** +         * This functions set the brush used for painting. +         * It takes one argument : +         *  - a Brush object +         */ +        Kross::Api::Object::Ptr setBrush(Kross::Api::List::Ptr args); +        /** +         * This function define the paint operation. +         * It takes one argument : +         *  - the name of the paint operation +         */ +        Kross::Api::Object::Ptr setPaintOp(Kross::Api::List::Ptr args); +        // Special settings +        /** +         * This function define the duplicate offset. +         * It takes two arguments : +         *  - horizontal offset +         *  - vertical offset +         */ +        Kross::Api::Object::Ptr setDuplicateOffset(Kross::Api::List::Ptr args); +        // Style operation +        /** +         * This function set the opacity of the painting +         * It takes one argument : +         *  - opacity in the range 0 to 255 +         */ +        Kross::Api::Object::Ptr setOpacity(Kross::Api::List::Ptr args); +        /** +         * This function set the style of the stroke. +         * It takes one argument : +         *  - 0 for none 1 for brush +         */ +        Kross::Api::Object::Ptr setStrokeStyle(Kross::Api::List::Ptr args); +        /** +         * This function set the fill style of the Painter. +         * It takes one argument : +         *  - 0 for none 1 for fill with foreground color 2 for fill with background color +         * 3 for fill with a pattern +         */ +        Kross::Api::Object::Ptr setFillStyle(Kross::Api::List::Ptr args); +    protected: +        inline KisPaintLayerSP paintLayer() { return m_layer; } +    private: +        inline vKisPoint createPointsVector( QValueList<QVariant> xs, QValueList<QVariant> ys) +        { +            vKisPoint a; +            QValueList<QVariant>::iterator itx = xs.begin(); +            QValueList<QVariant>::iterator ity = ys.begin(); +            for(; itx != xs.end(); ++itx, ++ity) +            { +                a.push_back(KisPoint( (*itx).toDouble(), (*ity).toDouble())); +            } +            return a; +        } +        inline KisFillPainter* createFillPainter(); +    private: +        KisPaintLayerSP m_layer; +        KisPainter* m_painter; +        int m_threshold; +}; + +} + +} + +#endif diff --git a/krita/plugins/viewplugins/scripting/kritacore/krs_pattern.cpp b/krita/plugins/viewplugins/scripting/kritacore/krs_pattern.cpp new file mode 100644 index 000000000..8b89c8a73 --- /dev/null +++ b/krita/plugins/viewplugins/scripting/kritacore/krs_pattern.cpp @@ -0,0 +1,39 @@ +/* + *  Copyright (c) 2006 Cyrille Berger <cberger@cberger.net> + * + *  This program is free software; you can redistribute it and/or modify + *  it under the terms of the GNU Library 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 Library General Public License for more details. + * + *  You should have received a copy of the GNU Library 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 "krs_pattern.h" + +#include <kis_pattern.h> + +namespace Kross { + +namespace KritaCore { + +Pattern::Pattern(KisPattern* pattern, bool sharedPattern) : Kross::Api::Class<Pattern>("KritaPattern"), m_pattern(pattern), m_sharedPattern(sharedPattern) +{ +} + +Pattern::~Pattern() +{ +    if(!m_sharedPattern) +        delete m_pattern; +} + +} + +} diff --git a/krita/plugins/viewplugins/scripting/kritacore/krs_pattern.h b/krita/plugins/viewplugins/scripting/kritacore/krs_pattern.h new file mode 100644 index 000000000..f7dd7e356 --- /dev/null +++ b/krita/plugins/viewplugins/scripting/kritacore/krs_pattern.h @@ -0,0 +1,48 @@ +/* + *  Copyright (c) 2006 Cyrille Berger <cberger@cberger.net> + * + *  This program is free software; you can redistribute it and/or modify + *  it under the terms of the GNU Library 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 Library General Public License for more details. + * + *  You should have received a copy of the GNU Library 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. + */ + +#ifndef KROSS_KRITACOREKRS_PATTERN_H +#define KROSS_KRITACOREKRS_PATTERN_H + +#include <api/class.h> + +class KisPattern; + +namespace Kross { + +namespace KritaCore { + +class Pattern : public Kross::Api::Class<Pattern>{ +    public: +        /** +         * @param sharedPattern tell if the pattern should be deleted or not when this object is deleted +         */ +        Pattern(KisPattern*, bool sharedPattern); +        ~Pattern(); +    public: +        inline KisPattern* getPattern() { return m_pattern; } +    private: +        KisPattern* m_pattern; +        bool m_sharedPattern; +}; + +} + +} + +#endif diff --git a/krita/plugins/viewplugins/scripting/kritacore/krs_script_progress.cpp b/krita/plugins/viewplugins/scripting/kritacore/krs_script_progress.cpp new file mode 100644 index 000000000..e653f12a4 --- /dev/null +++ b/krita/plugins/viewplugins/scripting/kritacore/krs_script_progress.cpp @@ -0,0 +1,67 @@ +/* + *  Copyright (c) 2005 Cyrille Berger <cberger@cberger.net> + * + *  This program is free software; you can redistribute it and/or modify + *  it under the terms of the GNU Library 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 Library General Public License for more details. + * + *  You should have received a copy of the GNU Library 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 "krs_script_progress.h" + +#include "kis_script_progress.h" + +namespace Kross { + +namespace KritaCore { + +ScriptProgress::ScriptProgress(KisScriptProgress* script): Kross::Api::Class<ScriptProgress>("KritaScript"), m_script(script) +{ +    addFunction("setProgressTotalSteps", &ScriptProgress::setProgressTotalSteps); +    addFunction("setProgressTotalSteps", &ScriptProgress::setProgressTotalSteps); +    addFunction("setProgress", &ScriptProgress::setProgress); +    addFunction("incProgress", &ScriptProgress::incProgress); +    addFunction("setProgressStage", &ScriptProgress::setProgressStage); +} + + +ScriptProgress::~ScriptProgress() +{ +} + +Kross::Api::Object::Ptr ScriptProgress::setProgressTotalSteps(Kross::Api::List::Ptr args) +{ +    m_script->setProgressTotalSteps( Kross::Api::Variant::toUInt(args->item(0)) ); +    return 0; +} + +Kross::Api::Object::Ptr ScriptProgress::setProgress(Kross::Api::List::Ptr args) +{ +    m_script->setProgress( Kross::Api::Variant::toUInt(args->item(0)) ); +    return 0; +} + +Kross::Api::Object::Ptr ScriptProgress::incProgress(Kross::Api::List::Ptr) +{ +    m_script->incProgress(); +    return 0; +} + +Kross::Api::Object::Ptr ScriptProgress::setProgressStage(Kross::Api::List::Ptr args) +{ +    m_script->setProgressStage( Kross::Api::Variant::toString(args->item(0)), Kross::Api::Variant::toUInt(args->item(1)) ); +    return 0; +} + +} + +} diff --git a/krita/plugins/viewplugins/scripting/kritacore/krs_script_progress.h b/krita/plugins/viewplugins/scripting/kritacore/krs_script_progress.h new file mode 100644 index 000000000..535485cb5 --- /dev/null +++ b/krita/plugins/viewplugins/scripting/kritacore/krs_script_progress.h @@ -0,0 +1,77 @@ +/* + *  Copyright (c) 2005 Cyrille Berger <cberger@cberger.net> + * + *  This program is free software; you can redistribute it and/or modify + *  it under the terms of the GNU Library 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 Library General Public License for more details. + * + *  You should have received a copy of the GNU Library 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. + */ + +#ifndef KROSS_KRITACOREKRS_SCRIPTPROGRESS_H +#define KROSS_KRITACOREKRS_SCRIPTPROGRESS_H + +#include <api/class.h> + +class KisScriptProgress; + +namespace Kross { + +namespace KritaCore { + +/** + * ScriptProgress is used to manage the progress bar of the status bar in krita + *  + * For example (in ruby) : + * @code + * script = Krosskritacore::get("KritaScript") + * script.setProgressTotalSteps(1000) + * script.setProgressStage("progressive", 0) + * for i in 1..900 + *   script.incProgress() + * end + * script.setProgressStage("brutal", 1000) + * @endcode + */ +class ScriptProgress : public Kross::Api::Class<ScriptProgress> { +    public: +        ScriptProgress(KisScriptProgress* Script); +        ~ScriptProgress(); +    private: +        /** +         * This function set the number of steps that the script will require. +         * It takes one argument : +         * - maximum value of the progress +         */ +        Kross::Api::Object::Ptr setProgressTotalSteps(Kross::Api::List::Ptr); +        /** +         * This function set the value of progress. +         * It takes one argument : +         * - value of the progress +         */ +        Kross::Api::Object::Ptr setProgress(Kross::Api::List::Ptr); +        /** +         * This function increment of one step the position of the progress. +         */ +        Kross::Api::Object::Ptr incProgress(Kross::Api::List::Ptr); +        /** +         * This function set the value of the progress and display the text  +         */ +        Kross::Api::Object::Ptr setProgressStage(Kross::Api::List::Ptr); +    private: +        KisScriptProgress* m_script; +}; + +} + +} + +#endif diff --git a/krita/plugins/viewplugins/scripting/kritacore/krs_wavelet.cpp b/krita/plugins/viewplugins/scripting/kritacore/krs_wavelet.cpp new file mode 100644 index 000000000..d2786780c --- /dev/null +++ b/krita/plugins/viewplugins/scripting/kritacore/krs_wavelet.cpp @@ -0,0 +1,114 @@ +/* + *  This file is part of the KDE project + * + *  Copyright (c) 2006 Cyrille Berger <cberger@cberger.net> + * + *  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 "krs_wavelet.h" + +#include <klocale.h> + +#include <kis_math_toolbox.h> + +namespace Kross { + +namespace KritaCore { + +Wavelet::Wavelet(KisMathToolbox::KisWavelet* kwl) +    : Kross::Api::Class<Wavelet>("KritaWavelet"), m_wavelet(kwl) +{ +    addFunction("getNCoeff", &Wavelet::getNCoeff); +    addFunction("setNCoeff", &Wavelet::setNCoeff); +    addFunction("getXYCoeff", &Wavelet::getXYCoeff); +    addFunction("setXYCoeff", &Wavelet::setXYCoeff); +    addFunction("getDepth", &Wavelet::getDepth); +    addFunction("getSize", &Wavelet::getSize); +    addFunction("getNumCoeffs", &Wavelet::getNumCoeffs); +    m_numCoeff = m_wavelet->size*m_wavelet->size*m_wavelet->depth; +} + + +Wavelet::~Wavelet() +{ +} + + +Kross::Api::Object::Ptr Wavelet::getNCoeff(Kross::Api::List::Ptr args) +{ +    Q_UINT32 n = Kross::Api::Variant::toUInt(args->item(0)); +    if( n > m_numCoeff) +    { +        throw Kross::Api::Exception::Ptr( new Kross::Api::Exception( i18n("An error has occured in %1").arg("getNCoeff") + "\n" + i18n("Index out of bound") ) ); +    } +    return new Kross::Api::Variant(*(m_wavelet->coeffs + n )); +} + +Kross::Api::Object::Ptr Wavelet::setNCoeff(Kross::Api::List::Ptr args) +{ +    Q_UINT32 n = Kross::Api::Variant::toUInt(args->item(0)); +    double v = Kross::Api::Variant::toDouble(args->item(1)); +    if( n > m_numCoeff) +    { +        throw Kross::Api::Exception::Ptr( new Kross::Api::Exception( i18n("An error has occured in %1").arg("setNCoeff") + "\n" + i18n("Index out of bound") ) ); +    } +    *(m_wavelet->coeffs + n ) = v; +    return 0; +} + +Kross::Api::Object::Ptr Wavelet::getXYCoeff(Kross::Api::List::Ptr args) +{ +    Q_UINT32 x = Kross::Api::Variant::toUInt(args->item(0)); +    Q_UINT32 y = Kross::Api::Variant::toUInt(args->item(1)); +    if( x > m_wavelet->size && y > m_wavelet->size) +    { +        throw Kross::Api::Exception::Ptr( new Kross::Api::Exception( i18n("An error has occured in %1").arg("getXYCoeff") + "\n" + i18n("Index out of bound") ) ); +    } +    return new Kross::Api::Variant(*(m_wavelet->coeffs  + (x + y * m_wavelet->size ) * m_wavelet->depth )); +} + +Kross::Api::Object::Ptr Wavelet::setXYCoeff(Kross::Api::List::Ptr args) +{ +    Q_UINT32 x = Kross::Api::Variant::toUInt(args->item(0)); +    Q_UINT32 y = Kross::Api::Variant::toUInt(args->item(1)); +    double v = Kross::Api::Variant::toDouble(args->item(2)); +    if( x > m_wavelet->size && y > m_wavelet->size) +    { +        throw Kross::Api::Exception::Ptr( new Kross::Api::Exception( i18n("An error has occured in %1").arg("setXYCoeff") + "\n" + i18n("Index out of bound") )); +    } +    *(m_wavelet->coeffs + (x + y * m_wavelet->size ) * m_wavelet->depth ) = v; +    return 0; +} + +Kross::Api::Object::Ptr Wavelet::getDepth(Kross::Api::List::Ptr /*args*/) +{ +    return new Kross::Api::Variant(m_wavelet->depth); +} + +Kross::Api::Object::Ptr Wavelet::getSize(Kross::Api::List::Ptr) +{ +    return new Kross::Api::Variant(m_wavelet->size); +} + +Kross::Api::Object::Ptr Wavelet::getNumCoeffs(Kross::Api::List::Ptr) +{ +    return new Kross::Api::Variant(m_numCoeff); +} + + +} + +} diff --git a/krita/plugins/viewplugins/scripting/kritacore/krs_wavelet.h b/krita/plugins/viewplugins/scripting/kritacore/krs_wavelet.h new file mode 100644 index 000000000..bee73e9bf --- /dev/null +++ b/krita/plugins/viewplugins/scripting/kritacore/krs_wavelet.h @@ -0,0 +1,92 @@ +/* + *  This file is part of the KDE project + * + *  Copyright (c) 2006 Cyrille Berger <cberger@cberger.net> + * + *  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. + */ + +#ifndef KROSS_KRITACOREKRS_WAVELET_H +#define KROSS_KRITACOREKRS_WAVELET_H + +#include <api/class.h> + +#include <kis_math_toolbox.h> + +namespace Kross { + +namespace KritaCore { + +/** +	@author Cyrille Berger <cberger@cberger.net> +*/ +class Wavelet : public Kross::Api::Class<Wavelet> +{ +    public: +        Wavelet(KisMathToolbox::KisWavelet* wavelet); +        ~Wavelet(); +    private: +        /** +         * Return the value of the Nth coefficient +         * The function takes one argument : +         * - the index of the coefficient +         */ +        Kross::Api::Object::Ptr getNCoeff(Kross::Api::List::Ptr); +        /** +         * Set the value of the Nth coefficient +         * The function takes two arguments : +         * - the index of the coefficient +         * - the new value of the coefficient +         */ +        Kross::Api::Object::Ptr setNCoeff(Kross::Api::List::Ptr); +        /** +         * Return the value of a coefficient +         * The function takes two arguments : +         *  - x +         *  - y +         */ +        Kross::Api::Object::Ptr getXYCoeff(Kross::Api::List::Ptr); +        /** +         * Set the value of a coefficient +         * The function takes three arguments : +         * - x +         * - y +         * - the new value of the coefficient +         */ +        Kross::Api::Object::Ptr setXYCoeff(Kross::Api::List::Ptr); +        /** +         * Return the depth of the layer +         */ +        Kross::Api::Object::Ptr getDepth(Kross::Api::List::Ptr); +        /** +         * Return the size of the wavelet (size = width = height) +         */ +        Kross::Api::Object::Ptr getSize(Kross::Api::List::Ptr); +        /** +         * Return the number of coefficients in this wavelet (= size * size * depth) +         */ +        Kross::Api::Object::Ptr getNumCoeffs(Kross::Api::List::Ptr); +    public: +        KisMathToolbox::KisWavelet* wavelet() { return m_wavelet; } +    private: +        KisMathToolbox::KisWavelet* m_wavelet; +        uint m_numCoeff; +}; + +} + +} + +#endif diff --git a/krita/plugins/viewplugins/scripting/kritascripting.desktop b/krita/plugins/viewplugins/scripting/kritascripting.desktop new file mode 100644 index 000000000..cfdbbbf4d --- /dev/null +++ b/krita/plugins/viewplugins/scripting/kritascripting.desktop @@ -0,0 +1,81 @@ +[Desktop Entry] +Name=Scripting plugin +Name[bg]=Приставка за скриптове +Name[ca]=Connector de seqüenciació +Name[da]=Scriptplugin +Name[de]=Skripting-Modul +Name[el]=Πρόσθετο γραφής σεναρίων +Name[eo]=Skriptad-kromaĵo +Name[es]=Complemento para guiones +Name[et]=Skriptiplugin +Name[fa]=وصلۀ دستنوشته +Name[fr]=Module de scriptage +Name[fy]=Skriptplugin +Name[ga]=Breiseán scriptithe +Name[gl]=Plugin de programación +Name[he]=תוסף לתסריטים +Name[hu]=Szkript modul +Name[is]=Skriftu íforrit +Name[it]=Plugin di scripting +Name[ja]=スクリプトプラグイン +Name[km]=កម្មវិធីជំនួយសម្រាប់ស្គ្រីប +Name[nb]=Programtillegg for skripting +Name[nds]=Skriptmoduul +Name[ne]=प्लगइन स्क्रिप्ट गर्दै +Name[nl]=Scriptplugin +Name[pl]=Wtyczka obsługi języków skryptowych +Name[pt]='Plugin' de programação +Name[pt_BR]=Plugin de programação +Name[ru]=Модуль поддержки сценариев +Name[sk]=Modul pre skripty +Name[sl]=Vstavek za skripte +Name[sr]=Прикључак за скриптовање +Name[sr@Latn]=Priključak za skriptovanje +Name[sv]=Skriptinsticksprogram +Name[uk]=Втулок для скриптів +Name[uz]=Skriptlash plagini +Name[uz@cyrillic]=Скриптлаш плагини +Name[zh_CN]=脚本插件 +Name[zh_TW]=命令稿外掛程式 +Comment=Allow execution of scripts +Comment[bg]=Изпълнение на скриптове +Comment[ca]=Permet l'execució de seqüències +Comment[da]=Tillad kørsel af script +Comment[de]=Ermöglicht das Ausführen von Skripten +Comment[el]=Επιτρέπει την εκτέλεση σεναρίων +Comment[eo]=Permesi ruligon de skriptoj +Comment[es]=Permite la ejecución de guiones +Comment[et]=Võimaldab skriptide käivitamist +Comment[fa]=اجازۀ اجرای دستنوشتهها +Comment[fr]=Permet d'exécuter des scripts +Comment[fy]=Hjirmei kinne skripts útfierd wurde +Comment[gl]=Permite executar guións +Comment[he]=אפשרות להרצת תסריטים +Comment[hu]=Lehetővé teszi szkriptek végrehajtását +Comment[is]=Leyfa að skriftur séu keyrðar +Comment[it]=Permette di eseguire script +Comment[ja]=スクリプトの実行を可能にします +Comment[km]=អនុញ្ញាតឲ្យប្រតិបត្តិស្គ្រីប +Comment[lv]=Atļaut skriptu izpildi +Comment[nb]=Tillater skriptkjøring +Comment[nds]=Skripten utföhren +Comment[ne]=स्क्रिप्टको कार्यान्वयनलाई अनुमति दिनुहोस् +Comment[nl]=Hiermee kunnen scripts uitgevoerd worden +Comment[pl]=Zezwala na wykonywanie skryptów +Comment[pt]=Permitir executar programas ou 'scripts' +Comment[pt_BR]=Permitir executar programas ou 'scripts' +Comment[ru]=Возможность выполнения сценариев +Comment[sk]=Povoliť vykonávanie skriptov +Comment[sl]=Dovoli izvedbo skriptov +Comment[sr]=Омогући извршавање скрипти +Comment[sr@Latn]=Omogući izvršavanje skripti +Comment[sv]=Tillåt körning av skript +Comment[uk]=Дає змогу виконувати скрипти +Comment[uz]=Skriptlarni ishga tushirishga ruxsat berish +Comment[uz@cyrillic]=Скриптларни ишга туширишга рухсат бериш +Comment[zh_CN]=允许执行脚本 +Comment[zh_TW]=允許執行命令稿 +ServiceTypes=Krita/ViewPlugin +Type=Service +X-KDE-Library=kritascripting +X-Krita-Version=2 diff --git a/krita/plugins/viewplugins/scripting/kritascripting/Makefile.am b/krita/plugins/viewplugins/scripting/kritascripting/Makefile.am new file mode 100644 index 000000000..76dc7ea52 --- /dev/null +++ b/krita/plugins/viewplugins/scripting/kritascripting/Makefile.am @@ -0,0 +1,19 @@ +INCLUDES  =  -I$(top_srcdir)/krita/sdk \ +	-I$(top_srcdir)/krita/core \ +	-I$(top_srcdir)/krita/kritacolor/ \ +	-I$(top_srcdir)/krita/ui \ +	$(KROSS_INCLUDES) \ +	$(KOFFICE_INCLUDES) \ +	$(all_includes) + + +lib_LTLIBRARIES = libkritascripting.la +libkritascripting_la_SOURCES = kis_script_progress.cpp kis_script_monitor.cpp +noinst_HEADERS = kis_script_progress.h + +libkritascripting_la_LDFLAGS = -no-undefined $(all_libraries) +libkritascripting_la_LIBADD =  $(top_builddir)/krita/libkritacommon.la $(top_builddir)/lib/kross/main/libkrossmain.la + +KDE_CXXFLAGS = $(USE_EXCEPTIONS) + +libkritascripting_la_METASOURCES = AUTO diff --git a/krita/plugins/viewplugins/scripting/kritascripting/kis_script_monitor.cpp b/krita/plugins/viewplugins/scripting/kritascripting/kis_script_monitor.cpp new file mode 100644 index 000000000..8bb125963 --- /dev/null +++ b/krita/plugins/viewplugins/scripting/kritascripting/kis_script_monitor.cpp @@ -0,0 +1,51 @@ +/* + *  Copyright (c) 2006 Cyrille Berger <cberger@cberger.net> + * + *  This program is free software; you can redistribute it and/or modify + *  it under the terms of the GNU Library 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 Library General Public License for more details. + * + *  You should have received a copy of the GNU Library 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 "kis_script_monitor.h" + +#include <main/scriptaction.h> +#include <main/scriptguiclient.h> + + +KisScriptMonitor::KisScriptMonitor() +{ +} + + +KisScriptMonitor::~KisScriptMonitor() +{ +    s_instance = 0; +} + +void KisScriptMonitor::monitor(Kross::Api::ScriptGUIClient* guiClient) +{ +    connect(guiClient, SIGNAL(executionFinished( const Kross::Api::ScriptAction* )), SIGNAL(executionFinished( const Kross::Api::ScriptAction* ))); +    connect(guiClient, SIGNAL(executionStarted( const Kross::Api::ScriptAction* )), SIGNAL(executionStarted( const Kross::Api::ScriptAction* ))); +} + +KisScriptMonitor* KisScriptMonitor::s_instance = 0; + +KisScriptMonitor* KisScriptMonitor::instance() +{ +    if(s_instance == 0) +        s_instance = new KisScriptMonitor(); +    return s_instance; +} + +#include "kis_script_monitor.moc" + diff --git a/krita/plugins/viewplugins/scripting/kritascripting/kis_script_monitor.h b/krita/plugins/viewplugins/scripting/kritascripting/kis_script_monitor.h new file mode 100644 index 000000000..de1e03801 --- /dev/null +++ b/krita/plugins/viewplugins/scripting/kritascripting/kis_script_monitor.h @@ -0,0 +1,50 @@ +/* + *  Copyright (c) 2006 Cyrille Berger <cberger@cberger.net> + * + *  This program is free software; you can redistribute it and/or modify + *  it under the terms of the GNU Library 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 Library General Public License for more details. + * + *  You should have received a copy of the GNU Library 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. + */ + +#ifndef KIS_SCRIPT_MONITOR_H +#define KIS_SCRIPT_MONITOR_H + +#include <qobject.h> + +namespace Kross { +    namespace Api { +        class ScriptGUIClient; +        class ScriptAction; +    } +} + +/** +	@author Cyrille Berger <cberger@cberger.net> +*/ +class KisScriptMonitor : public QObject { +    Q_OBJECT +    private: +        KisScriptMonitor(); +        ~KisScriptMonitor(); +    public: +        static KisScriptMonitor* instance(); +        void monitor(Kross::Api::ScriptGUIClient* guiClient); +    signals: +        void executionFinished(const Kross::Api::ScriptAction* ); +        void executionStarted(const Kross::Api::ScriptAction* ); +    private: +        static KisScriptMonitor* s_instance; + +}; + +#endif diff --git a/krita/plugins/viewplugins/scripting/kritascripting/kis_script_progress.cpp b/krita/plugins/viewplugins/scripting/kritascripting/kis_script_progress.cpp new file mode 100644 index 000000000..c36293049 --- /dev/null +++ b/krita/plugins/viewplugins/scripting/kritascripting/kis_script_progress.cpp @@ -0,0 +1,64 @@ +/* + *  Copyright (c) 2005 Cyrille Berger <cberger@cberger.net> + * + *  This program is free software; you can redistribute it and/or modify + *  it under the terms of the GNU Library 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 Library General Public License for more details. + * + *  You should have received a copy of the GNU Library 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 "kis_script_progress.h" + +#include <kis_progress_display_interface.h> +#include <kis_view.h> + +void KisScriptProgress::activateAsSubject() +{ +    m_view->canvasSubject()->progressDisplay()->setSubject( this, true, false /* TODO: how to cancel a script ? */ ); +} + +void KisScriptProgress::setProgressTotalSteps(Q_INT32 totalSteps) +{ +    m_progressTotalSteps = totalSteps; +    m_progressSteps = 0; +    m_lastProgressPerCent = 0; +    emit notifyProgress(0); +} + +void KisScriptProgress::setProgress(Q_INT32 progress) +{ +    m_progressSteps = progress; +    Q_INT32 progressPerCent = (m_progressSteps * 100) / (m_progressTotalSteps > 0 ? m_progressTotalSteps : 1); + +    if (progressPerCent != m_lastProgressPerCent) { + +        m_lastProgressPerCent = progressPerCent; +        emit notifyProgress(progressPerCent); +    } +} + +void KisScriptProgress::incProgress() +{ +    setProgress( ++m_progressSteps ); +} + +void KisScriptProgress::setProgressStage(const QString& stage, Q_INT32 progress) +{ +    Q_INT32 progressPerCent = (progress * 100) / (m_progressTotalSteps > 0 ? m_progressTotalSteps : 1); +    m_lastProgressPerCent = progress; +    emit notifyProgressStage( stage, progressPerCent); +} + +void KisScriptProgress::progressDone() +{ +    emit notifyProgressDone(); +} diff --git a/krita/plugins/viewplugins/scripting/kritascripting/kis_script_progress.h b/krita/plugins/viewplugins/scripting/kritascripting/kis_script_progress.h new file mode 100644 index 000000000..864a67607 --- /dev/null +++ b/krita/plugins/viewplugins/scripting/kritascripting/kis_script_progress.h @@ -0,0 +1,54 @@ +/* + *  Copyright (c) 2005 Cyrille Berger <cberger@cberger.net> + * + *  This program is free software; you can redistribute it and/or modify + *  it under the terms of the GNU Library 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 Library General Public License for more details. + * + *  You should have received a copy of the GNU Library 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. + */ + +#ifndef _KIS_SCRIPT_PROGRESS_H_ +#define _KIS_SCRIPT_PROGRESS_H_ + +#include <kis_progress_subject.h> + +class KisView; + +/** + * TODO: clarify the situation, while, in the future, multiple scripts could be running at a same time, + * some of the functions are global to all script and some aren't. + */ +class KisScriptProgress : public KisProgressSubject +{ +    public: +        KisScriptProgress(KisView* view) : m_view(view) {}; +    public: +        /** +         * This function will set this class as the KisProgressSubject in view +         */ +        void activateAsSubject(); +        virtual void cancel() {}; +    public: +        void setProgressTotalSteps(Q_INT32 totalSteps); +        void setProgress(Q_INT32 progress); +        void incProgress(); +        void setProgressStage(const QString& stage, Q_INT32 progress); +        void progressDone(); +        inline void setPackagePath(QString path) { m_packagePath = path; }; +        inline QString packagePath() { return m_packagePath; } +    private: +        Q_INT32 m_progressSteps, m_progressTotalSteps, m_lastProgressPerCent; +        KisView * m_view; +        QString m_packagePath; +}; + +#endif diff --git a/krita/plugins/viewplugins/scripting/samples/Makefile.am b/krita/plugins/viewplugins/scripting/samples/Makefile.am new file mode 100644 index 000000000..1eebb4c75 --- /dev/null +++ b/krita/plugins/viewplugins/scripting/samples/Makefile.am @@ -0,0 +1,3 @@ +INCLUDES = -I$(srcdir)/../../../sdk 	-I$(srcdir)/../../../core 	-I$(srcdir)/../../../kritacolor/ 	-I$(srcdir)/../../../ui 	-I$(top_srcdir)/kexi/scriptingcore/main 	$(KOFFICE_INCLUDES) 	$(all_includes) +METASOURCES = AUTO +SUBDIRS = python ruby diff --git a/krita/plugins/viewplugins/scripting/samples/python/Makefile.am b/krita/plugins/viewplugins/scripting/samples/python/Makefile.am new file mode 100644 index 000000000..5b1f28f36 --- /dev/null +++ b/krita/plugins/viewplugins/scripting/samples/python/Makefile.am @@ -0,0 +1,5 @@ +scriptinvertdir = $(kde_datadir)/krita/scripts/invertpython +scriptinvert_SCRIPTS = invert.py invertpython.rc + +scriptreshapedir = $(kde_datadir)/krita/scripts/reshapehisto +scriptreshape_SCRIPTS = reshapehisto.py reshapehisto.rc diff --git a/krita/plugins/viewplugins/scripting/samples/python/invert.py b/krita/plugins/viewplugins/scripting/samples/python/invert.py new file mode 100644 index 000000000..2c87593d6 --- /dev/null +++ b/krita/plugins/viewplugins/scripting/samples/python/invert.py @@ -0,0 +1,48 @@ +# This file is part of Krita +# +# Copyright (c) 2005-2006 Cyrille Berger <cberger@cberger.net> +# +#  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. + +class Inverter: +    def __init__(self): +        try: +            import krosskritacore +        except: +            raise "Import of the KritaCore module failed." +        doc = krosskritacore.get("KritaDocument") +        script = krosskritacore.get("KritaScript") +        image = doc.getImage() +        layer = image.getActivePaintLayer() +        if(layer.colorSpaceId() != "RGBA" ): +            raise("This script works only for 8bit RGBA layers") +        width = layer.getWidth() +        height = layer.getHeight() +        script.setProgressTotalSteps(width * height) +        layer.beginPainting("invert") +        it = layer.createRectIterator( 0, 0, width, height ) +        print "kikoo\n" +        finesh = it.isDone() +        while (not finesh) : +            p = it.getRGBA() +            p[0] = 255 - p[0] +            p[1] = 255 - p[1] +            p[2] = 255 - p[2] +            it.setRGBA(p) +            script.incProgress() +            finesh = it.next() +        layer.endPainting() + +Inverter() diff --git a/krita/plugins/viewplugins/scripting/samples/python/invertpython.rc b/krita/plugins/viewplugins/scripting/samples/python/invertpython.rc new file mode 100644 index 000000000..d22243110 --- /dev/null +++ b/krita/plugins/viewplugins/scripting/samples/python/invertpython.rc @@ -0,0 +1,9 @@ +<KrossScripting> +    <ScriptAction +      name="InvertPython" +      text="Invert (python)" +      description="Invert the pixel of an image (python)" +      icon="" +      interpreter="python" +      file="invert.py" /> +</KrossScripting> diff --git a/krita/plugins/viewplugins/scripting/samples/python/reshapehisto.py b/krita/plugins/viewplugins/scripting/samples/python/reshapehisto.py new file mode 100644 index 000000000..4a79e68c7 --- /dev/null +++ b/krita/plugins/viewplugins/scripting/samples/python/reshapehisto.py @@ -0,0 +1,300 @@ +# This file is part of Krita +# +# Copyright (c) 2005 Cyrille Berger <cberger@cberger.net> +# +#  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. + +import math + +# it's an experimental script to try to reshape histogram, while the results are far to be convincing yet +# it is still an example on how to use histogram in a script + +def sign(a): +    if a < 0: +        return -1 +    else: +        return 1 +#def abs(a): +    #if a < + +def computeDiff(histo, histoTarget): +    diff = [ ] +    histoMax = histo.getHighest() +    count = 0 +    while( count < 256 ) : +        v = histo.getValue(count) +        diff.append( v / histoMax - histoTarget[count]) +        count += 1 +    derivdiff = [ ] +    derivdiff.append(diff[1] - diff[0] ) +    count = 1 +    while( count < 255 ) : +        derivdiff.append((diff[count+1] - diff[count - 1])/2.0) +        print count +        print " " +        print derivdiff[count] +        print " " +        count += 1 +    derivdiff.append(diff[255] - diff[254] ) +    return diff +         +try: +    import krosskritacore +except: +    raise "Import of the KritaCore module failed." + +#histoTarget = [ 0.0, 0.01226531745085, 0.024528789662323, 0.0367885716726463, 0.049042819075215, 0.0612896882960706, 0.0735273368712555, 0.0857539237239997, 0.0979676094416996, 0.110166556552646, 0.122348929802458, 0.13451289643019, 0.146656626444054, 0.158778292896733, 0.170876072160234, 0.18294814420024, 0.194992692849922, 0.207007906083172, 0.218991976287209, 0.230943100534525, 0.242859480854121, 0.254739324502003, 0.266580844230888, 0.278382258559083, 0.290141792038499, 0.301857675521758, 0.313528146428344, 0.325151449009778, 0.336725834613756, 0.348249561947225, 0.359720897338346, 0.371138114997318, 0.38249949727601, 0.393803334926368, 0.405047927357568, 0.416231582891849, 0.427352619019025, 0.4384093626496, 0.449400150366478, 0.460323328675215, 0.471177254252771, 0.481960294194744, 0.492670826261026, 0.50330723911986, 0.513867932590253, 0.524351317882718, 0.534755817838293, 0.545079867165813, 0.555321912677404, 0.565480413522147, 0.575553841417885, 0.585540680881154, 0.595439429455167, 0.605248597935856, 0.614966710595909, 0.624592305406788, 0.634123934258679, 0.643560163178352, 0.652899572544893, 0.662140757303275, 0.671282327175744, 0.680322906870975, 0.689261136290974, 0.698095670735701, 0.706825181105366, 0.715448354100387, 0.723963892418968, 0.732370514952268, 0.740666956977137, 0.748851970346384, 0.756924323676554, 0.764882802533185, 0.772726209613504, 0.780453364926561, 0.788063105970749, 0.795554287908693, 0.802925783739486, 0.810176484468239, 0.817305299272921, 0.824311155668464, 0.83119299966812, 0.837949795942015, 0.84458052797292, 0.851084198209167, 0.857459828214736, 0.863706458816447, 0.869823150248263, 0.875808982292675, 0.881663054419139, 0.887384485919556, 0.892972416040772, 0.898426004114068, 0.903744429681637, 0.908926892620016, 0.913972613260457, 0.918880832506229, 0.923650811946811, 0.928281833968988, 0.93277320186481, 0.937124239936404, 0.941334293597632, 0.945402729472569, 0.949328935490789, 0.953112320979447, 0.956752316752142, 0.960248375194552, 0.963599970346811, 0.966806597982642, 0.969867775685214, 0.972783042919718, 0.97555196110265, 0.978174113667795, 0.980649106128898, 0.982976566139007, 0.985156143546496, 0.987187510447739, 0.989070361236445, 0.990804412649628, 0.99238940381023, 0.993825096266363, 0.995111274027184, 0.99624774359539, 0.997234333996328, 0.998070896803715, 0.998757306161974, 0.99929345880516, 0.999679274072503, 0.999914693920536, 0.999999682931835, 0.99993422832034, 0.999718339933283, 0.999352050249705, 0.998835414375572, 0.998168510035481, 0.997351437560967, 0.996384319875413, 0.995267302475555, 0.994000553409588, 0.992584263251893, 0.991018645074359, 0.989303934414332, 0.987440389239176, 0.985428289907469, 0.983267939126818, 0.980959661908326, 0.978503805517689, 0.975900739422957, 0.973150855238948, 0.970254566668332, 0.967212309439392, 0.964024541240472, 0.960691741651122, 0.957214412069943, 0.953593075639162, 0.949828277165924, 0.945920583040329, 0.941870581150226, 0.937678880792763, 0.933346112582728, 0.928872928357675, 0.924260001079857, 0.919508024734984, 0.914617714227821, 0.909589805274631, 0.90442505429249, 0.899124238285494, 0.89368815472786, 0.888117621443952, 0.882413476485242, 0.876576578004235, 0.870607804125365, 0.86450805281288, 0.858278241735758, 0.851919308129644, 0.845432208655849, 0.83881791925743, 0.832077435012361, 0.825211769983833, 0.818221957067693, 0.811109047837053, 0.803874112384084, 0.796518239159033, 0.789042534806467, 0.781448123998789, 0.773736149267035, 0.76590777082899, 0.757964166414642, 0.749906531088995, 0.741736077072283, 0.733454033557598, 0.725061646525966, 0.716560178558895, 0.707950908648432, 0.699235132004742, 0.690414159861254, 0.681489319277395, 0.672461952938941, 0.663333418956019, 0.654105090658787, 0.644778356390828, 0.635354619300277, 0.625835297128734, 0.616221821997965, 0.606515640194456, 0.596718211951823, 0.586831011231134, 0.576855525499155, 0.566793255504575, 0.556645715052225, 0.546414430775338, 0.536100941905873, 0.525706800042952, 0.515233568919429, 0.504682824166636, 0.49405615307734, 0.483355154366944, 0.472581437932973, 0.461736624612871, 0.450822345940161, 0.439840243898986, 0.428791970677089, 0.417679188417244, 0.406503568967204, 0.39526679362818, 0.383970552901897, 0.372616546236274, 0.361206481769749, 0.349742076074299, 0.338225053897198, 0.326657147901536, 0.315040098405551, 0.303375653120808, 0.291665566889271, 0.279911601419294, 0.268115525020586, 0.256279112338177, 0.244404144085436, 0.232492406776176, 0.220545692455878, 0.208565798432095, 0.196554527004056, 0.184513685191523, 0.172445084462932, 0.160350540462877, 0.148231872738948, 0.136090904468, 0.123929462181863, 0.111749375492553, 0.0995524768170189, 0.0873406011014653, 0.0751155855452987, 0.0628792693247314, 0.0506334933160884, 0.0383800998188613, 0.0261209322785436, 0.0138578350092972 ] + +histoTarget = [ 0.0, 0.00392156862745098, 0.00784313725490196, 0.0117647058823529, 0.0156862745098039, 0.0196078431372549, 0.0235294117647059, 0.0274509803921569, 0.0313725490196078, 0.0352941176470588, 0.0392156862745098, 0.0431372549019608, 0.0470588235294118, 0.0509803921568627, 0.0549019607843137, 0.0588235294117647, 0.0627450980392157, 0.0666666666666667, 0.0705882352941176, 0.0745098039215686, 0.0784313725490196, 0.0823529411764706, 0.0862745098039216, 0.0901960784313725, 0.0941176470588235, 0.0980392156862745, 0.101960784313725, 0.105882352941176, 0.109803921568627, 0.113725490196078, 0.117647058823529, 0.12156862745098, 0.125490196078431, 0.129411764705882, 0.133333333333333, 0.137254901960784, 0.141176470588235, 0.145098039215686, 0.149019607843137, 0.152941176470588, 0.156862745098039, 0.16078431372549, 0.164705882352941, 0.168627450980392, 0.172549019607843, 0.176470588235294, 0.180392156862745, 0.184313725490196, 0.188235294117647, 0.192156862745098, 0.196078431372549, 0.2, 0.203921568627451, 0.207843137254902, 0.211764705882353, 0.215686274509804, 0.219607843137255, 0.223529411764706, 0.227450980392157, 0.231372549019608, 0.235294117647059, 0.23921568627451, 0.243137254901961, 0.247058823529412, 0.250980392156863, 0.254901960784314, 0.258823529411765, 0.262745098039216, 0.266666666666667, 0.270588235294118, 0.274509803921569, 0.27843137254902, 0.282352941176471, 0.286274509803922, 0.290196078431373, 0.294117647058824, 0.298039215686275, 0.301960784313725, 0.305882352941176, 0.309803921568627, 0.313725490196078, 0.317647058823529, 0.32156862745098, 0.325490196078431, 0.329411764705882, 0.333333333333333, 0.337254901960784, 0.341176470588235, 0.345098039215686, 0.349019607843137, 0.352941176470588, 0.356862745098039, 0.36078431372549, 0.364705882352941, 0.368627450980392, 0.372549019607843, 0.376470588235294, 0.380392156862745, 0.384313725490196, 0.388235294117647, 0.392156862745098, 0.396078431372549, 0.4, 0.403921568627451, 0.407843137254902, 0.411764705882353, 0.415686274509804, 0.419607843137255, 0.423529411764706, 0.427450980392157, 0.431372549019608, 0.435294117647059, 0.43921568627451, 0.443137254901961, 0.447058823529412, 0.450980392156863, 0.454901960784314, 0.458823529411765, 0.462745098039216, 0.466666666666667, 0.470588235294118, 0.474509803921569, 0.47843137254902, 0.482352941176471, 0.486274509803922, 0.490196078431373, 0.494117647058824, 0.498039215686275, 0.501960784313725, 0.505882352941176, 0.509803921568627, 0.513725490196078, 0.517647058823529, 0.52156862745098, 0.525490196078431, 0.529411764705882, 0.533333333333333, 0.537254901960784, 0.541176470588235, 0.545098039215686, 0.549019607843137, 0.552941176470588, 0.556862745098039, 0.56078431372549, 0.564705882352941, 0.568627450980392, 0.572549019607843, 0.576470588235294, 0.580392156862745, 0.584313725490196, 0.588235294117647, 0.592156862745098, 0.596078431372549, 0.6, 0.603921568627451, 0.607843137254902, 0.611764705882353, 0.615686274509804, 0.619607843137255, 0.623529411764706, 0.627450980392157, 0.631372549019608, 0.635294117647059, 0.63921568627451, 0.643137254901961, 0.647058823529412, 0.650980392156863, 0.654901960784314, 0.658823529411765, 0.662745098039216, 0.666666666666667, 0.670588235294118, 0.674509803921569, 0.67843137254902, 0.682352941176471, 0.686274509803922, 0.690196078431373, 0.694117647058824, 0.698039215686274, 0.701960784313725, 0.705882352941177, 0.709803921568627, 0.713725490196078, 0.717647058823529, 0.72156862745098, 0.725490196078431, 0.729411764705882, 0.733333333333333, 0.737254901960784, 0.741176470588235, 0.745098039215686, 0.749019607843137, 0.752941176470588, 0.756862745098039, 0.76078431372549, 0.764705882352941, 0.768627450980392, 0.772549019607843, 0.776470588235294, 0.780392156862745, 0.784313725490196, 0.788235294117647, 0.792156862745098, 0.796078431372549, 0.8, 0.803921568627451, 0.807843137254902, 0.811764705882353, 0.815686274509804, 0.819607843137255, 0.823529411764706, 0.827450980392157, 0.831372549019608, 0.835294117647059, 0.83921568627451, 0.843137254901961, 0.847058823529412, 0.850980392156863, 0.854901960784314, 0.858823529411765, 0.862745098039216, 0.866666666666667, 0.870588235294118, 0.874509803921569, 0.87843137254902, 0.882352941176471, 0.886274509803922, 0.890196078431372, 0.894117647058824, 0.898039215686275, 0.901960784313726, 0.905882352941176, 0.909803921568627, 0.913725490196078, 0.917647058823529, 0.92156862745098, 0.925490196078431, 0.929411764705882, 0.933333333333333, 0.937254901960784, 0.941176470588235, 0.945098039215686, 0.949019607843137, 0.952941176470588, 0.956862745098039, 0.96078431372549, 0.964705882352941, 0.968627450980392, 0.972549019607843, 0.976470588235294, 0.980392156862745, 0.984313725490196, 0.988235294117647, 0.992156862745098, 0.996078431372549, 1.0 ] + +doc = krosskritacore.get("KritaDocument") +image = doc.getImage() +layer = image.getActivePaintLayer() +if (layer.colorSpaceId() != "RGBA" ): +    raise("This script works only for 8bit RGBA layers") + +width = layer.getWidth() +height = layer.getHeight() + +countreshaping = 0 +while countreshaping < 1: +    histo = layer.createHistogram("RGB8HISTO",0) +    print "################################### histogram reshaping ##################################################" +    if histo == 0: +        raise "Uncompatible histogram\n" +    print "Max : " + str( histo.getMax() ) + " Min : " + str( histo.getMin() ) +     +    #Compute the area of the target histogram +    aireHistoTarget = 0.0 +    count = 0 +    while( count < 256 ) : +        aireHistoTarget += histoTarget[count] +        count += 1 +         +    #compute the table for the blue channel +    histo.setChannel(0) +    tableb = [ ] +    histoMax = histo.getHighest() +    aireHisto = width * height +    coeff = aireHistoTarget / aireHisto +    count = 0 +    position = 0 +    residu = 0. +    while( count < 256 ) : +        residu += histo.getValue(count) * coeff +        while residu > 0.0: +            residu -= histoTarget[position] +            position += 1 +        tableb.append( position ) +        count += 1 +    #compute the table for the green channel +    histo.setChannel(1) +    tableg = [ ] +    histoMax = histo.getHighest() +    aireHisto = width * height +    coeff = aireHistoTarget / aireHisto +    count = 0 +    position = 0 +    residu = 0. +    while( count < 256 ) : +        residu += histo.getValue(count) * coeff +        while residu > 0.0: +            residu -= histoTarget[position] +            position += 1 +        tableg.append( position ) +        count += 1 +    #compute the table for the red channel +    histo.setChannel(2) +    tabler = [ ] +    histoMax = histo.getHighest() +    aireHisto = width * height +    coeff = aireHistoTarget / aireHisto +    count = 0 +    position = 0 +    residu = 0. +    while( count < 256 ) : +        residu += histo.getValue(count) * coeff +        while residu > 0.0: +            residu -= histoTarget[position] +            position += 1 +        tabler.append( position ) +        count += 1 +         +    it = layer.createRectIterator( 0, 0, width, height ) +    print "kikoo : " + str(countreshaping) +    while (not it.isDone()) : +        r = it.getRed() +        g = it.getGreen() +        b = it.getBlue() +        #var = ( tabler[r] - r + tableg[g] - g + tableb[b] - b ) / 3 +        #ng = g + var +        #nr = r + var +        #nb = b + var +        it.setRed(tabler[r]) +        it.setGreen(tableg[g]) +        it.setBlue(tableb[b]) +        it.next() +     +    #histo.setChannel(0) +    #diff = [ ] +    #histoMax = histo.getHighest() +    #count = 0 +    #while( count < 256 ) : +        #v = histo.getValue(count) +        #diff.append( v / histoMax - histoTarget[count]) +        #count += 1 +    #diffb = [ ] +    #diffb.append(diff[1] - diff[0] ) +    #count = 1 +    #while( count < 255 ) : +        #diffb.append((diff[count+1] - diff[count - 1])/2.0) +        #count += 1 +    #diffb.append(diff[255] - diff[254] ) +     +    #histo.setChannel(1) +    #diff = [ ] +    #histoMax = histo.getHighest() +    #count = 0 +    #while( count < 256 ) : +        #v = histo.getValue(count) +        #diff.append( v / histoMax - histoTarget[count]) +        #count += 1 +    #diffg = [ ] +    #diffg.append(diff[1] - diff[0] ) +    #count = 1 +    #while( count < 255 ) : +        #diffg.append((diff[count+1] - diff[count - 1])/2.0) +        #count += 1 +    #diffg.append(diff[255] - diff[254] ) +     +    #histo.setChannel(2) +    #diff = [ ] +    #histoMax = histo.getHighest() +    #count = 0 +    #while( count < 256 ) : +        #v = histo.getValue(count) +        #diff.append( v / histoMax - histoTarget[count]) +        #count += 1 +    #diffr = [ ] +    #diffr.append(diff[1] - diff[0] ) +    #count = 1 +    #while( count < 255 ) : +        #diffr.append((diff[count+1] - diff[count - 1])/2.0) +        #count += 1 +    #diffr.append(diff[255] - diff[254] ) +     +     +    #histo.setChannel(0) +    #diff = [ ] +    #histoMax = histo.getHighest() +    #count = 0 +    #while( count < 256 ) : +        #v = histo.getValue(count) +        #diff.append( v / histoMax - histoTarget[count]) +        #count += 1 +    #diffb = [ ] +    #diffb.append( sign(diff[1] - diff[0] ) * abs(diff[0]) ) +    #count = 1 +    #while( count < 255 ) : +        #diffb.append( sign(diff[count+1] - diff[count - 1]) * abs(diff[count]) ) +        #count += 1 +    #diffb.append( sign(diff[255] - diff[254] ) * abs(diff[255]) ) +     +    #histo.setChannel(1) +    #diff = [ ] +    #histoMax = histo.getHighest() +    #count = 0 +    #while( count < 256 ) : +        #v = histo.getValue(count) +        #diff.append( v / histoMax - histoTarget[count]) +        #count += 1 +    #diffg = [ ] +    #diffg.append( sign(diff[1] - diff[0] ) * abs(diff[0]) ) +    #count = 1 +    #while( count < 255 ) : +        #diffg.append( sign(diff[count+1] - diff[count - 1]) * abs(diff[count]) ) +        #count += 1 +    #diffg.append( sign(diff[255] - diff[254] ) * abs(diff[255]) ) +     +    #histo.setChannel(2) +    #diff = [ ] +    #histoMax = histo.getHighest() +    #count = 0 +    #while( count < 256 ) : +        #v = histo.getValue(count) +        #diff.append( v / histoMax - histoTarget[count]) +        #count += 1 +    #diffr = [ ] +    #diffr.append( sign(diff[1] - diff[0] ) * abs(diff[0]) ) +    #count = 1 +    #while( count < 255 ) : +        #diffr.append( sign(diff[count+1] - diff[count - 1]) * abs(diff[count]) ) +        #count += 1 +    #diffr.append( sign(diff[255] - diff[254] ) * abs(diff[255]) ) +     +     +        #print str(diffr) + " " + str(diff[count+1]) + " " + str(diff[count-1]) +     +    #histo.setChannel(0) +    #diffb = computeDiff(histo, histoTarget) +    #print "##########################" +    #count = 0 +    #while( count < 256 ) : +        #print count +        #print " " +        #print diffb[count] +        #print "\n" +        #count += 1 +     +    #histo.setChannel(1) +    #diffg = computeDiff(histo, histoTarget) +    #print "##########################" +    #count = 0 +    #while( count < 256 ) : +        #print count +        #print " " +        #print diffg[count] +        #print "\n" +        #count += 1 +     +    #histo.setChannel(2) +    #diffr = computeDiff(histo, histoTarget) +    #print "##########################" +    #count = 0 +    #while( count < 256 ) : +        #print count +        #print " " +        #print diffr[count] +        #print "\n" +        #count += 1 +     +    #it = layer.createRectIterator( 0, 0, width, height ) +    #print "kikoo : " + str(countreshaping) +    #while (not it.isDone()) : +        #r = it.getRed() +        #g = it.getGreen() +        #b = it.getBlue() +        #coeff = 1.0 - ( diffr[r] + diffg[g] + diffb[b] ) / 3.0 +        ##print str(r) + " = " + str(diffr[r]) + " " + str(g) + " = " + str(diffg[g]) + " " + str(b) + " = " + str(diffb[b]) + " coeff = " + str(coeff) +        #ng = g * coeff +        #nr = r * coeff +        #nb = b * coeff +        #it.setRed(nr) +        #it.setGreen(ng) +        #it.setBlue(nb) +        #it.next() +    countreshaping += 1 +     +doc.notifyModification() diff --git a/krita/plugins/viewplugins/scripting/samples/python/reshapehisto.rc b/krita/plugins/viewplugins/scripting/samples/python/reshapehisto.rc new file mode 100644 index 000000000..481f5764e --- /dev/null +++ b/krita/plugins/viewplugins/scripting/samples/python/reshapehisto.rc @@ -0,0 +1,9 @@ +<KrossScripting> +    <ScriptAction +      name="ReshapeHistogramPython" +      text="Reshape Histogram (python)" +      description="It's an experimental approach to improve color of image, it doesn't work as it, but it show how to use an histogram in a script :)" +      icon="" +      interpreter="python" +      file="reshapehisto.py" /> +</KrossScripting> diff --git a/krita/plugins/viewplugins/scripting/samples/ruby/Makefile.am b/krita/plugins/viewplugins/scripting/samples/ruby/Makefile.am new file mode 100644 index 000000000..2aa794163 --- /dev/null +++ b/krita/plugins/viewplugins/scripting/samples/ruby/Makefile.am @@ -0,0 +1,18 @@ +scriptsinvertdir = $(kde_datadir)/krita/scripts/invertruby +scriptsinvert_SCRIPTS = invert.rb invertruby.rc + +scriptschangecsdir = $(kde_datadir)/krita/scripts/changecs +scriptschangecs_SCRIPTS = changecs.rb changecs.rc + +scriptsrandompaintdir = $(kde_datadir)/krita/scripts/randompaint +scriptsrandompaint_SCRIPTS = randompaint.rb randompaint.rc + +scriptsfilterstestdir = $(kde_datadir)/krita/scripts/filterstest +scriptsfilterstest_SCRIPTS = filterstest.rb filterstest.rc + +scriptstorturefiltersdir = $(kde_datadir)/krita/scripts/torturefilters +scriptstorturefilters_SCRIPTS = torture-filters.rb torture-filters.rc + +scriptstorturepaintingdir = $(kde_datadir)/krita/scripts/torturepainting +scriptstorturepainting_SCRIPTS = torture-painting.rb torture-painting.rc + diff --git a/krita/plugins/viewplugins/scripting/samples/ruby/changecs.rb b/krita/plugins/viewplugins/scripting/samples/ruby/changecs.rb new file mode 100644 index 000000000..f5d99a3f0 --- /dev/null +++ b/krita/plugins/viewplugins/scripting/samples/ruby/changecs.rb @@ -0,0 +1,5 @@ +require "krosskritacore" + +doc = Krosskritacore::get("KritaDocument") +image = doc.getImage() +image.convertToColorspace("LABA") diff --git a/krita/plugins/viewplugins/scripting/samples/ruby/changecs.rc b/krita/plugins/viewplugins/scripting/samples/ruby/changecs.rc new file mode 100644 index 000000000..4121693d5 --- /dev/null +++ b/krita/plugins/viewplugins/scripting/samples/ruby/changecs.rc @@ -0,0 +1,9 @@ +<KrossScripting> +    <ScriptAction +      name="ChangeColorspaceRuby" +      text="Change Colorspace" +      description="Demonstrate how to change the colorspace in a script" +      icon="" +      interpreter="ruby" +      file="changecs.rb" /> +</KrossScripting> diff --git a/krita/plugins/viewplugins/scripting/samples/ruby/filterstest.rb b/krita/plugins/viewplugins/scripting/samples/ruby/filterstest.rb new file mode 100644 index 000000000..20d42dbfb --- /dev/null +++ b/krita/plugins/viewplugins/scripting/samples/ruby/filterstest.rb @@ -0,0 +1,31 @@ +# This file is part of Krita +# +# Copyright (c) 2005-2006 Cyrille Berger <cberger@cberger.net> +# +#  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. + +require "krosskritacore" + +doc = Krosskritacore::get("KritaDocument") + +image = doc.getImage() +layer = image.getActivePaintLayer() +width = layer.getWidth() +height = layer.getHeight() + +filter = Krosskritacore::getFilter("invert") + +filter.process(layer ) +filter.process(layer, 10, 10, 20, 20 ) diff --git a/krita/plugins/viewplugins/scripting/samples/ruby/filterstest.rc b/krita/plugins/viewplugins/scripting/samples/ruby/filterstest.rc new file mode 100644 index 000000000..2f8dfb987 --- /dev/null +++ b/krita/plugins/viewplugins/scripting/samples/ruby/filterstest.rc @@ -0,0 +1,9 @@ +<KrossScripting> +    <ScriptAction +      name="FiltersTestRuby" +      text="Filters Test" +      description="Test of filters in scripting (ruby)" +      icon="" +      interpreter="ruby" +      file="filterstest.rb" /> +</KrossScripting> diff --git a/krita/plugins/viewplugins/scripting/samples/ruby/invert.rb b/krita/plugins/viewplugins/scripting/samples/ruby/invert.rb new file mode 100644 index 000000000..0a0550289 --- /dev/null +++ b/krita/plugins/viewplugins/scripting/samples/ruby/invert.rb @@ -0,0 +1,45 @@ +# This file is part of Krita +# +# Copyright (c) 2005-2006 Cyrille Berger <cberger@cberger.net> +# +#  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. + +require "krosskritacore" + +doc = Krosskritacore::get("KritaDocument") +script = Krosskritacore::get("KritaScript") +image = doc.getImage() +layer = image.getActivePaintLayer() + +if(layer.colorSpaceId() != "RGBA" ) +    raise("This script works only for 8bit RGBA layers") +end + +width = layer.getWidth() +height = layer.getHeight() +script.setProgressTotalSteps(width * height) +layer.beginPainting("invert") +it = layer.createRectIterator( 0, 0, width, height ) +while (it.isDone() == 0) +    p = it.getRGBA() +    p[0] = 255 - p[0] +    p[1] = 255 - p[1] +    p[2] = 255 - p[2] +    it.setRGBA(p) +    script.incProgress() +    it.next() +end + +layer.endPainting() diff --git a/krita/plugins/viewplugins/scripting/samples/ruby/invertruby.rc b/krita/plugins/viewplugins/scripting/samples/ruby/invertruby.rc new file mode 100644 index 000000000..9cc7bd6af --- /dev/null +++ b/krita/plugins/viewplugins/scripting/samples/ruby/invertruby.rc @@ -0,0 +1,9 @@ +<KrossScripting> +    <ScriptAction +      name="InvertRuby" +      text="Invert (ruby)" +      description="Invert the pixel of an image (ruby)" +      icon="" +      interpreter="ruby" +      file="invert.rb" /> +</KrossScripting> diff --git a/krita/plugins/viewplugins/scripting/samples/ruby/randompaint.rb b/krita/plugins/viewplugins/scripting/samples/ruby/randompaint.rb new file mode 100644 index 000000000..9e2f504f0 --- /dev/null +++ b/krita/plugins/viewplugins/scripting/samples/ruby/randompaint.rb @@ -0,0 +1,98 @@ +def randomizeStyle(painter) +    painter.setFillStyle(4 *rand) +    painter.setStrokeStyle(2 *rand) +end + +require "krosskritacore" + +doc = Krosskritacore::get("KritaDocument") +script = Krosskritacore::get("KritaScript") + +image = doc.getImage() +layer = image.getActivePaintLayer() +width = layer.getWidth() +height = layer.getHeight() + +script.setProgressTotalSteps(110) +layer.beginPainting("random paint") + +painter = layer.createPainter() + +# create painting color +blackcolor = Krosskritacore::newRGBColor(0,0,0) + +# set painting color +painter.setPaintColor( blackcolor ) + +# get the brush +brush =  Krosskritacore::getBrush("Circle (05)") + +# define the brush +painter.setBrush(brush) + +# get the pattern +pattern = Krosskritacore::getPattern("Bricks") + +# set the pattern +painter.setPattern(pattern) + +# define the paint operation +painter.setPaintOp("paintbrush") + +# randomly paint +for i in 1..10 +    # set painting color +    painter.setPaintColor( Krosskritacore::newRGBColor(rand*255,rand*255,rand*255) ) +    painter.paintAt(rand * width , rand * height,1.1) +    script.incProgress() +end + +# randomly rect or circle paint +for i in 1..100 +    # set painting color +    painter.setPaintColor( Krosskritacore::newRGBColor(rand*255,rand*255,rand*255) ) +    painter.setBackgroundColor( Krosskritacore::newRGBColor(rand*255,rand*255,rand*255) ) +    painter.setOpacity( rand*255 ) +# set the brush +    if(rand < 0.5) +        painter.setBrush( Krosskritacore::newRectBrush(rand*20,rand*20,rand*10,rand*10) ) +    else +        painter.setBrush( Krosskritacore::newCircleBrush(rand*20,rand*20,rand*10,rand*10) ) +    end +    # paint a point +    shape = rand * 7 +    painter.setStrokeStyle(1) +    if( shape < 1 ) +        painter.paintAt(rand * width , rand * height,1.1) +    elsif(shape < 2 ) +        xs = Array.new +        ys = Array.new +        for i in 0..6 +            xs[i] = rand*width +            ys[i] = rand*height +        end +        painter.paintPolyline(xs,ys) +    elsif(shape < 3) +        painter.paintLine(rand * width, rand * height, 1.1, rand * width, rand * height,1.1) +    elsif(shape < 4) +        painter.paintBezierCurve(rand * width, rand * height, 1.1, rand * width, rand * height, rand * width , rand * height, rand * width, rand * height, 1.1) +    elsif(shape < 5) +        randomizeStyle(painter) +        painter.paintEllipse(rand * width, rand * height, rand * width, rand * height, 1.1) +    elsif(shape < 6) +        xs = Array.new +        ys = Array.new +        for i in 0..6 +            xs[i] = rand*width +            ys[i] = rand*height +        end +        randomizeStyle(painter) +        painter.paintPolygon(xs, ys) +    elsif(shape < 7) +        randomizeStyle(painter) +        painter.paintRect(rand * width, rand * height, rand * width, rand * height, 1.1) +    end +    script.incProgress() +end + +layer.endPainting() diff --git a/krita/plugins/viewplugins/scripting/samples/ruby/randompaint.rc b/krita/plugins/viewplugins/scripting/samples/ruby/randompaint.rc new file mode 100644 index 000000000..3697f7005 --- /dev/null +++ b/krita/plugins/viewplugins/scripting/samples/ruby/randompaint.rc @@ -0,0 +1,9 @@ +<KrossScripting> +    <ScriptAction +      name="RandomPaintRuby" +      text="Random Paint" +      description="Demonstrate how to use the Painter script API and paint random shape on screen" +      icon="" +      interpreter="ruby" +      file="randompaint.rb" /> +</KrossScripting> diff --git a/krita/plugins/viewplugins/scripting/samples/ruby/torture-filters.rb b/krita/plugins/viewplugins/scripting/samples/ruby/torture-filters.rb new file mode 100644 index 000000000..58cddcd6b --- /dev/null +++ b/krita/plugins/viewplugins/scripting/samples/ruby/torture-filters.rb @@ -0,0 +1,70 @@ +# This file is part of Krita +# +# Copyright (c) 2006 Cyrille Berger <cberger@cberger.net> +# +#  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. + +require "krosskritacore" + +doc = Krosskritacore::get("KritaDocument") + +image = doc.getImage() +layer = image.getActivePaintLayer() + +def testFilter(layer, filterid) +    print " applying filter ", filterid, "\n" +    begin +        filter = Krosskritacore::getFilter(filterid) +        filter.process(layer) +    rescue +        print " WARNING: this filter is incompatible with this colorspace\n" +    end +end + + +def testColorspace(layer, colorspaceid) +    print "Testing for ", colorspaceid, "\n" +    if (layer.colorSpaceId() != colorspaceid) +        layer.convertToColorspace(colorspaceid) +    end +    testFilter(layer, "invert") +    testFilter(layer, "bumpmap") +    testFilter(layer, "cimg") +    testFilter(layer, "desaturate") +    testFilter(layer, "autocontrast") +    testFilter(layer, "brightnesscontrast") +    testFilter(layer, "gaussian blur") +    testFilter(layer, "cubism") +    testFilter(layer, "emboss") +    testFilter(layer, "simplenoisereducer") +    testFilter(layer, "waveletnoisereducer") +    testFilter(layer, "oilpaint") +    testFilter(layer, "pixelize") +    testFilter(layer, "raindrops") +    testFilter(layer, "roundcorners") +    testFilter(layer, "smalltiles") +    testFilter(layer, "sobel") +end + +testColorspace(layer, "RGBA") +testColorspace(layer, "RGBA16") +testColorspace(layer, "RGBAF16HALF") +testColorspace(layer, "RGBAF32") +testColorspace(layer, "CMYK") +testColorspace(layer, "CMYKA16") +testColorspace(layer, "CMYK") +testColorspace(layer, "CMYKA16") +testColorspace(layer, "LABA") +testColorspace(layer, "LMSAF32") diff --git a/krita/plugins/viewplugins/scripting/samples/ruby/torture-filters.rc b/krita/plugins/viewplugins/scripting/samples/ruby/torture-filters.rc new file mode 100644 index 000000000..c56c2818a --- /dev/null +++ b/krita/plugins/viewplugins/scripting/samples/ruby/torture-filters.rc @@ -0,0 +1,9 @@ +<KrossScripting> +    <ScriptAction +                 name="TortureFiltersRuby" +                 text="Torture Krita with Filters" +                 description="Test all filters with all colorspaces (ruby)" +                 icon="" +                 interpreter="ruby" +                 file="torture-filters.rb" /> +</KrossScripting> diff --git a/krita/plugins/viewplugins/scripting/samples/ruby/torture-painting.rb b/krita/plugins/viewplugins/scripting/samples/ruby/torture-painting.rb new file mode 100644 index 000000000..67042de2c --- /dev/null +++ b/krita/plugins/viewplugins/scripting/samples/ruby/torture-painting.rb @@ -0,0 +1,133 @@ +# This file is part of Krita +# +# Copyright (c) 2006 Cyrille Berger <cberger@cberger.net> +# +#  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. + +require "krosskritacore" + +class TorturePainting + +    def initialize() +     +        doc = Krosskritacore::get("KritaDocument") +        @script = Krosskritacore::get("KritaScript") +         +        @image = doc.getImage() +        @width = @image.getWidth() +        @height = @image.getHeight() +         +        @script.setProgressTotalSteps(30 * 10) +         +        testColorspace("RGBA") +        testColorspace("RGBA16") +        testColorspace("RGBAF16HALF") +        testColorspace("RGBAF32") +        testColorspace("CMYK") +        testColorspace("CMYKA16") +        testColorspace("CMYK") +        testColorspace("CMYKA16") +        testColorspace("LABA") +        testColorspace("LMSAF32") +         +     +    end +     +    def randomizeStyle(painter) +        painter.setFillStyle(4 *rand) +        painter.setStrokeStyle(2 *rand) +    end +     +     +    def testColorspace(cs) +        print "Torturing for ", cs, "\n" +        layer = @image.createPaintLayer("torture", 255 * rand, "RGBA" ); +        torture(layer) +    end +     +     +    def torture(layer) +        layer.beginPainting("torture painting") +         +        painter = layer.createPainter() +         +        # create painting color +        blackcolor = Krosskritacore::newRGBColor(0,0,0) +         +        # set painting color +        painter.setPaintColor( blackcolor ) +         +        # get the pattern +        pattern = Krosskritacore::getPattern("Bricks") +         +        # set the pattern +        painter.setPattern(pattern) +         +        # define the paint operation +        painter.setPaintOp("paintbrush") +         +        # randomly rect or circle paint +        for i in 1..30 +            # set painting color +            painter.setPaintColor( Krosskritacore::newRGBColor(rand*255,rand*255,rand*255) ) +            painter.setBackgroundColor( Krosskritacore::newRGBColor(rand*255,rand*255,rand*255) ) +            painter.setOpacity( rand*255 ) +            # set the brush +            if(rand < 0.5) +                painter.setBrush( Krosskritacore::newRectBrush(rand*20,rand*20,rand*10,rand*10) ) +            else +                painter.setBrush( Krosskritacore::newCircleBrush(rand*20,rand*20,rand*10,rand*10) ) +            end +            # paint a point +            shape = rand * 7 +            painter.setStrokeStyle(1) +            if( shape < 1 ) +                painter.paintAt(rand * @width , rand * @height,1.1) +            elsif(shape < 2 ) +                xs = Array.new +                ys = Array.new +                for i in 0..6 +                    xs[i] = rand*@width +                    ys[i] = rand*@height +                end +                painter.paintPolyline(xs,ys) +            elsif(shape < 3) +                painter.paintLine(rand * @width, rand * @height, 1.1, rand * @width, rand * @height,1.1) +            elsif(shape < 4) +                painter.paintBezierCurve(rand * @width, rand * @height, 1.1, rand * @width, rand * @height, rand * @width , rand * @height, rand * @width, rand * @height, 1.1) +            elsif(shape < 5) +                randomizeStyle(painter) +                painter.paintEllipse(rand * @width, rand * @height, rand * @width, rand * @height, 1.1) +            elsif(shape < 6) +                xs = Array.new +                ys = Array.new +                for i in 0..6 +                    xs[i] = rand*@width +                    ys[i] = rand*@height +                end +                randomizeStyle(painter) +                painter.paintPolygon(xs, ys) +            elsif(shape < 7) +                randomizeStyle(painter) +                painter.paintRect(rand * @width, rand * @height, rand * @width, rand * @height, 1.1) +            end +            @script.incProgress() +        end +        layer.endPainting() +    end + +end + +TorturePainting.new()
\ No newline at end of file diff --git a/krita/plugins/viewplugins/scripting/samples/ruby/torture-painting.rc b/krita/plugins/viewplugins/scripting/samples/ruby/torture-painting.rc new file mode 100644 index 000000000..6b54fa9d5 --- /dev/null +++ b/krita/plugins/viewplugins/scripting/samples/ruby/torture-painting.rc @@ -0,0 +1,9 @@ +<KrossScripting> +    <ScriptAction +      name="TorturePainting" +      text="Torture Krita with Painting" +      description="Paint on an image and create multiple layers" +      icon="" +      interpreter="ruby" +      file="torture-painting.rb" /> +</KrossScripting> diff --git a/krita/plugins/viewplugins/scripting/scripting.cc b/krita/plugins/viewplugins/scripting/scripting.cc new file mode 100644 index 000000000..d7f5fde75 --- /dev/null +++ b/krita/plugins/viewplugins/scripting/scripting.cc @@ -0,0 +1,111 @@ +/* + * This file is part of the KDE project + * + * Copyright (c) 2005 Cyrille Berger <cberger@cberger.net> + *  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 "scripting.h" + +#include <stdlib.h> +#include <vector> + +#include <qapplication.h> +#include <qpoint.h> + +#include <kdebug.h> +#include <kfiledialog.h> +#include <kgenericfactory.h> +#include <kiconloader.h> +#include <kinstance.h> +#include <klocale.h> +#include <kmessagebox.h> +#include <kstandarddirs.h> +#include <ktempfile.h> + +#define KROSS_MAIN_EXPORT KDE_EXPORT +#include <main/manager.h> +#include <main/scriptguiclient.h> +#include <main/wdgscriptsmanager.h> + +#include <kopalettemanager.h> + +#include <kis_doc.h> +#include <kis_global.h> +#include <kis_types.h> +#include <kis_view.h> +#include <kis_image.h> +#include <kis_layer.h> + +#include "kritascripting/kis_script_progress.h" +#include "kritascripting/kis_script_monitor.h" + +typedef KGenericFactory<Scripting> KritaScriptingFactory; +K_EXPORT_COMPONENT_FACTORY( kritascripting, KritaScriptingFactory( "krita" ) ) + +Scripting::Scripting(QObject *parent, const char *name, const QStringList &) +        : KParts::Plugin(parent, name) +{ +    setInstance(KritaScriptingFactory::instance()); + + +    if ( parent->inherits("KisView") ) +    { +        setInstance(Scripting::instance()); +        m_view = (KisView*) parent; +        m_scriptguiclient = new Kross::Api::ScriptGUIClient( m_view, m_view ); +//         m_scriptguiclient ->setXMLFile(locate("data","kritaplugins/scripting.rc"), true); +        //BEGIN TODO: understand why the ScriptGUIClient doesn't "link" its actions to the menu +        setXMLFile(locate("data","kritaplugins/scripting.rc"), true); +        new KAction(i18n("Execute Script File..."), 0, 0, m_scriptguiclient, SLOT(executeScriptFile()), actionCollection(), "executescriptfile"); +        new KAction(i18n("Script Manager..."), 0, 0, m_scriptguiclient, SLOT(showScriptManager()), actionCollection(), "configurescripts"); +        //END TODO + +        QWidget * w = new Kross::Api::WdgScriptsManager(m_scriptguiclient, m_view); + +        m_view->canvasSubject()->paletteManager()->addWidget(w, "Scripts Manager", krita::LAYERBOX, 10,  PALETTE_DOCKER, false); + +        connect(m_scriptguiclient, SIGNAL(executionFinished( const Kross::Api::ScriptAction* )), this, SLOT(executionFinished(const Kross::Api::ScriptAction*))); +        connect(m_scriptguiclient, SIGNAL(executionStarted( const Kross::Api::ScriptAction* )), this, SLOT(executionStarted(const Kross::Api::ScriptAction*))); +        KisScriptMonitor::instance()->monitor( m_scriptguiclient ); + +        Kross::Api::Manager::scriptManager()->addQObject(m_view->canvasSubject()->document(), "KritaDocument"); +        Kross::Api::Manager::scriptManager()->addQObject(m_view, "KritaView"); +        m_scriptProgress = new KisScriptProgress(m_view); +        Kross::Api::Manager::scriptManager()->addQObject(m_scriptProgress, "KritaScriptProgress"); + +    } + +} + +Scripting::~Scripting() +{ +} + +void Scripting::executionFinished(const Kross::Api::ScriptAction*) +{ +    m_view->canvasSubject()->document()->setModified(true); +    m_view->canvasSubject()->document()->currentImage()->activeLayer()->setDirty(); +    m_scriptProgress->progressDone(); +    QApplication::restoreOverrideCursor(); +} + +void Scripting::executionStarted(const Kross::Api::ScriptAction* act) +{ +    kdDebug(41011) << act->getPackagePath() << endl; +    m_scriptProgress->setPackagePath( act->getPackagePath() ); +} + + +#include "scripting.moc" diff --git a/krita/plugins/viewplugins/scripting/scripting.h b/krita/plugins/viewplugins/scripting/scripting.h new file mode 100644 index 000000000..238483c8e --- /dev/null +++ b/krita/plugins/viewplugins/scripting/scripting.h @@ -0,0 +1,53 @@ +/* + * This file is part of Krita + * + * Copyright (c) 2005 Cyrille Berger <cberger@cberger.net> + * + *  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. + */ + +#ifndef SCRIPTING_H +#define SCRIPTING_H + +#include <kparts/plugin.h> + +class KisView; +class KisScript; +class KisScriptProgress; + +namespace Kross { +    namespace Api { +        class ScriptGUIClient; +        class ScriptAction; +    } +} + +class Scripting : public KParts::Plugin +{ +    Q_OBJECT +    public: +        Scripting(QObject *parent, const char *name, const QStringList &); +        virtual ~Scripting(); +    private slots: +        void executionFinished(const Kross::Api::ScriptAction*); +        void executionStarted(const Kross::Api::ScriptAction*); +    private: +        KisView * m_view; +        Kross::Api::ScriptGUIClient* m_scriptguiclient; +        KisScriptProgress* m_scriptProgress; +}; + + +#endif diff --git a/krita/plugins/viewplugins/scripting/scripting.rc b/krita/plugins/viewplugins/scripting/scripting.rc new file mode 100644 index 000000000..8d2ba496a --- /dev/null +++ b/krita/plugins/viewplugins/scripting/scripting.rc @@ -0,0 +1,10 @@ +<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd"> +<kpartgui library="kritascripting" version="3"> +  <MenuBar> +    <Menu name="Scripts"><text>S&cripts</text> +      <Separator/> +      <Action name="executescriptfile"/> +      <Action name="configurescripts"/> +    </Menu> +  </MenuBar> +</kpartgui> diff --git a/krita/plugins/viewplugins/selectopaque/Makefile.am b/krita/plugins/viewplugins/selectopaque/Makefile.am new file mode 100644 index 000000000..2c382ce32 --- /dev/null +++ b/krita/plugins/viewplugins/selectopaque/Makefile.am @@ -0,0 +1,24 @@ +INCLUDES  =  -I$(srcdir)/../../../sdk \ +	-I$(srcdir)/../../../core \ +	-I$(srcdir)/../../../kritacolor/ \ +	-I$(srcdir)/../../../ui \ +	$(KOFFICE_INCLUDES) \ +	$(all_includes) + +kde_module_LTLIBRARIES = kritaselectopaque.la + +kritaselectopaque_la_SOURCES = selectopaque.cc  +noinst_HEADERS = selectopaque.h + +kritaselectopaque_la_LIBADD =  ../../../libkritacommon.la +kritaselectopaque_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) + +kritarcdir = $(kde_datadir)/kritaplugins +kritarc_DATA = selectopaque.rc +EXTRA_DIST = $(kritarc_DATA) + +kde_services_DATA = kritaselectopaque.desktop + +kritaselectopaque_la_METASOURCES = AUTO + +KDE_OPTIONS = nofinal diff --git a/krita/plugins/viewplugins/selectopaque/kritaselectopaque.desktop b/krita/plugins/viewplugins/selectopaque/kritaselectopaque.desktop new file mode 100644 index 000000000..69690306d --- /dev/null +++ b/krita/plugins/viewplugins/selectopaque/kritaselectopaque.desktop @@ -0,0 +1,26 @@ +[Desktop Entry] +Name=SelectOpaque +Name[bg]=Негатив +Name[da]=Markér ugennemsigtig +Name[de]=UndurchsichtigeAuswählen +Name[et]=Läbipaistmatute pikslite valik +Name[fy]=Untrochsichtige selektearje +Name[it]=Seleziona i pixel opachi +Name[km]=ជ្រើសស្រអាប់ +Name[nds]=Decken utsöken +Name[ne]=अपारदर्शी चयन +Name[nl]=Ondoorzichtige selecteren +Name[pl]=Zaznaczanie nieprzezroczystości +Name[pt]=Selecção Opaca +Name[pt_BR]=Seleção Opaca +Name[ru]=Выделение непрозрачных областей +Name[sk]=Invertovať Výber +Name[sr]=Избор непрозирног +Name[sr@Latn]=Izbor neprozirnog +Name[sv]=Markera ogenomskinliga +Name[uk]=Виділення непрозорих ділянок +Name[zh_TW]=選擇不透明 +ServiceTypes=Krita/ViewPlugin +Type=Service +X-KDE-Library=kritaselectopaque +X-Krita-Version=2 diff --git a/krita/plugins/viewplugins/selectopaque/selectopaque.cc b/krita/plugins/viewplugins/selectopaque/selectopaque.cc new file mode 100644 index 000000000..cfbcb4e76 --- /dev/null +++ b/krita/plugins/viewplugins/selectopaque/selectopaque.cc @@ -0,0 +1,116 @@ +/* + * selectopague.h -- Part of Krita + * + * Copyright (c) 2004 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 <math.h> + +#include <stdlib.h> + +#include <qcursor.h> +#include <qapplication.h> + +#include <klocale.h> +#include <kiconloader.h> +#include <kinstance.h> +#include <kmessagebox.h> +#include <kstandarddirs.h> +#include <ktempfile.h> +#include <kdebug.h> +#include <kgenericfactory.h> + +#include <kis_selected_transaction.h> +#include <kis_cursor.h> +#include <kis_doc.h> +#include <kis_image.h> +#include <kis_layer.h> +#include <kis_paint_device.h> +#include <kis_iterator.h> +#include <kis_iterators_pixel.h> +#include <kis_global.h> +#include <kis_types.h> +#include <kis_view.h> +#include <kis_selection.h> +#include <kis_selection_manager.h> +#include "selectopaque.h" + +typedef KGenericFactory<SelectOpaque> SelectOpaqueFactory; +K_EXPORT_COMPONENT_FACTORY( kritaselectopaque, SelectOpaqueFactory( "krita" ) ) + +SelectOpaque::SelectOpaque(QObject *parent, const char *name, const QStringList &) +    : KParts::Plugin(parent, name) +{ + +    if (parent->inherits("KisView")) { +        setInstance(SelectOpaqueFactory::instance()); +        setXMLFile(locate("data","kritaplugins/selectopaque.rc"), true); +        m_view = dynamic_cast<KisView*>(parent); +        m_view->canvasSubject()->selectionManager()->addSelectionAction( new KAction(i18n("&Select All Opaque Pixels..."), 0, 0, this, SLOT(slotActivated()), actionCollection(), "selectopaque") ); + +    } +} + +SelectOpaque::~SelectOpaque() +{ +} + +void SelectOpaque::slotActivated() +{ +    KisSelectedTransaction *transaction; + +    KisPaintDeviceSP layer = m_view->canvasSubject()->currentImg()->activeDevice(); +    if (!layer) return; +    QApplication::setOverrideCursor(KisCursor::waitCursor()); + +    if (layer->image()->undo()) transaction = new KisSelectedTransaction(i18n("Select Opaque Pixels"), layer); +    // XXX: Multithread this! +    Q_INT32 x, y, w, h; +    layer->exactBounds(x, y, w, h); + +    KisColorSpace * cs = layer->colorSpace(); + +    if(! layer->hasSelection()) +        layer->selection()->clear(); +    KisSelectionSP selection = layer->selection(); + +    KisHLineIterator hiter = layer->createHLineIterator(x, y, w, false); +    KisHLineIterator selIter = selection ->createHLineIterator(x, y, w, true); + +    for (int row = 0; row < h; ++row) { +        while (!hiter.isDone()) { +            // Don't try to select transparent pixels. +            if (cs->getAlpha( hiter.rawData() ) > OPACITY_TRANSPARENT) { +                *(selIter.rawData()) = MAX_SELECTED; +            } +            ++hiter; +            ++selIter; +        } +        hiter.nextRow(); +        selIter.nextRow(); +    } +    QApplication::restoreOverrideCursor(); +    layer->setDirty(); +    layer->emitSelectionChanged(); + +    if (layer->image()->undo()) m_view->canvasSubject()->undoAdapter()->addCommand(transaction); + +} + +#include "selectopaque.moc" + diff --git a/krita/plugins/viewplugins/selectopaque/selectopaque.h b/krita/plugins/viewplugins/selectopaque/selectopaque.h new file mode 100644 index 000000000..5215ecfe2 --- /dev/null +++ b/krita/plugins/viewplugins/selectopaque/selectopaque.h @@ -0,0 +1,44 @@ +/*  + * selectopaque.h -- Part of Krita + * + *  Copyright (c) 2004 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. + */ + +#ifndef SELECTOPAQUE_H +#define SELECTOPAQUE_H + +#include <kparts/plugin.h> + +class KisView; + +class SelectOpaque : public KParts::Plugin +{ +        Q_OBJECT +    public: +        SelectOpaque(QObject *parent, const char *name, const QStringList &); +        virtual ~SelectOpaque(); +     +    private slots: +        void slotActivated(); + +    private: +        KisView * m_view; +        KisPainter * m_painter; + +}; + +#endif // SELECTOPAQUE_H diff --git a/krita/plugins/viewplugins/selectopaque/selectopaque.rc b/krita/plugins/viewplugins/selectopaque/selectopaque.rc new file mode 100644 index 000000000..1696d3d03 --- /dev/null +++ b/krita/plugins/viewplugins/selectopaque/selectopaque.rc @@ -0,0 +1,10 @@ +<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd"> +<kpartgui library="kritaselectopaque" version="1"> +<MenuBar> +    <Menu name="Select"><text>Select</text> +	<Separator/> +	<Action name="selectopaque"/> +	<Separator/> +    </Menu> +</MenuBar> +</kpartgui> diff --git a/krita/plugins/viewplugins/separate_channels/Makefile.am b/krita/plugins/viewplugins/separate_channels/Makefile.am new file mode 100644 index 000000000..238e41844 --- /dev/null +++ b/krita/plugins/viewplugins/separate_channels/Makefile.am @@ -0,0 +1,26 @@ +kritarcdir = $(kde_datadir)/kritaplugins +kritarc_DATA = imageseparate.rc +EXTRA_DIST = $(kritarc_DATA) + +INCLUDES  =  -I$(srcdir)/../../../sdk \ +	-I$(srcdir)/../../../core \ +	-I$(srcdir)/../../../kritacolor/ \ +	-I$(srcdir)/../../../ui \ +	$(KOFFICE_INCLUDES) \ +	$(all_includes) + +kde_module_LTLIBRARIES = kritaseparatechannels.la + +kritaseparatechannels_la_SOURCES = wdg_separations.ui \ +	kis_channel_separator.cc dlg_separate.cc  \ +	kis_separate_channels_plugin.cc + +noinst_HEADERS = wdg_separations.h kis_separate_channels_plugin.h \ +		kis_channel_separator.h dlg_separate.h + +kde_services_DATA = kritaseparatechannels.desktop + +kritaseparatechannels_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) +kritaseparatechannels_la_LIBADD =  ../../../libkritacommon.la  + +kritaseparatechannels_la_METASOURCES = AUTO diff --git a/krita/plugins/viewplugins/separate_channels/dlg_separate.cc b/krita/plugins/viewplugins/separate_channels/dlg_separate.cc new file mode 100644 index 000000000..760786ec1 --- /dev/null +++ b/krita/plugins/viewplugins/separate_channels/dlg_separate.cc @@ -0,0 +1,110 @@ +/* + *  dlg_separate.cc - part of KimageShop^WKrayon^WKrita + * + *  Copyright (c) 2004 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 <qradiobutton.h> +#include <qcheckbox.h> +#include <qbuttongroup.h> +#include <qlabel.h> +#include <qcombobox.h> +#include <qbutton.h> + +#include <klocale.h> +#include <knuminput.h> +#include <kdebug.h> + +#include "dlg_separate.h" +#include "wdg_separations.h" + +DlgSeparate::DlgSeparate( const QString & imageCS, +                          const QString & layerCS, +                          QWidget *  parent, +                          const char * name) +    : super (parent, name, true, i18n("Separate Image"), Ok | Cancel, Ok), +      m_imageCS(imageCS), +      m_layerCS(layerCS) +{ +    m_page = new WdgSeparations(this, "separate_image"); +    Q_CHECK_PTR(m_page); +    setMainWidget(m_page); +    resize(m_page->sizeHint()); + +    m_page->lblColormodel->setText(layerCS); +    m_page->grpOutput->hide(); +    connect(m_page->grpSource, SIGNAL(clicked(int)), this, SLOT(slotSetColorSpaceLabel(int))); +    connect(m_page->chkColors, SIGNAL(toggled(bool)), m_page->chkDownscale, SLOT(setDisabled(bool))); + +    connect(this, SIGNAL(okClicked()), +        this, SLOT(okClicked())); +} + +DlgSeparate::~DlgSeparate() +{ +    delete m_page; +} + + + +enumSepAlphaOptions DlgSeparate::getAlphaOptions() +{ +    return (enumSepAlphaOptions)m_page->grpAlpha->selectedId(); +} + +enumSepSource DlgSeparate::getSource() +{ +    return (enumSepSource)m_page->grpSource->selectedId(); +} + +enumSepOutput DlgSeparate::getOutput() +{ +    return (enumSepOutput)m_page->grpOutput->selectedId(); +} + + +bool DlgSeparate::getDownscale() +{ +    return m_page->chkDownscale->isChecked(); +} + +bool DlgSeparate::getToColor() +{ +    return m_page->chkColors->isChecked(); +} + +// SLOTS + +void DlgSeparate::okClicked() +{ +    accept(); +} + +void DlgSeparate::slotSetColorSpaceLabel(int buttonid) +{ +    if (buttonid == 0) { +        m_page->lblColormodel->setText(m_layerCS); +    } +    else { +        m_page->lblColormodel->setText(m_imageCS); +    } +} +void DlgSeparate::enableDownscale(bool enable) { +    m_page->chkDownscale->setEnabled(enable); +} + +#include "dlg_separate.moc" diff --git a/krita/plugins/viewplugins/separate_channels/dlg_separate.h b/krita/plugins/viewplugins/separate_channels/dlg_separate.h new file mode 100644 index 000000000..08432014b --- /dev/null +++ b/krita/plugins/viewplugins/separate_channels/dlg_separate.h @@ -0,0 +1,67 @@ +/* + *  dlg_imagesize.h -- part of KimageShop^WKrayon^WKrita + * + *  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. + */ +#ifndef DLG_SEPARATE +#define DLG_SEPARATE + +#include <kdialogbase.h> +#include <kis_channel_separator.h> + +class WdgSeparations; + +/** + * This dialog allows the user to configure the decomposition of an image + * into layers: one layer for each color channel. + */ +class DlgSeparate: public KDialogBase { +    typedef KDialogBase super; +    Q_OBJECT + +public: + +    DlgSeparate(const QString & imageCS, const QString & layerCS, QWidget * parent = 0, +             const char* name = 0); +    ~DlgSeparate(); + +public: + +    enumSepAlphaOptions getAlphaOptions(); +    enumSepSource getSource(); +    enumSepOutput getOutput(); + +    bool getDownscale(); +    void enableDownscale(bool enable); + +    bool getToColor(); + + +private slots: +     +    void slotSetColorSpaceLabel(int buttonid); +    void okClicked(); + +private: + +    WdgSeparations * m_page; +    QString m_imageCS; +    QString m_layerCS; + +}; + +#endif // DLG_SEPARATE diff --git a/krita/plugins/viewplugins/separate_channels/imageseparate.rc b/krita/plugins/viewplugins/separate_channels/imageseparate.rc new file mode 100644 index 000000000..4f587123f --- /dev/null +++ b/krita/plugins/viewplugins/separate_channels/imageseparate.rc @@ -0,0 +1,9 @@ +<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd"> +<kpartgui library="kritaseparatechannels" version="6"> +<MenuBar> +    <Menu name="Image"><text>Image</text> +	<Separator/> +	<Action name="separate"/> +    </Menu> +</MenuBar> +</kpartgui> diff --git a/krita/plugins/viewplugins/separate_channels/kis_channel_separator.cc b/krita/plugins/viewplugins/separate_channels/kis_channel_separator.cc new file mode 100644 index 000000000..75622312c --- /dev/null +++ b/krita/plugins/viewplugins/separate_channels/kis_channel_separator.cc @@ -0,0 +1,301 @@ +/* + * This file is part of Krita + * + * Copyright (c) 2005 Michael Thaler <michael.thaler@physik.tu-muenchen.de> + * + * ported from Gimp, Copyright (C) 1997 Eiichi Takamori <taka@ma1.seikyou.ne.jp> + * original pixelize.c for GIMP 0.54 by Tracy Scott + * + *  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 <limits.h> + +#include <stdlib.h> +#include <vector> + +#include <klocale.h> +#include <kiconloader.h> +#include <kinstance.h> +#include <kmessagebox.h> +#include <kstandarddirs.h> +#include <ktempfile.h> +#include <kdebug.h> +#include <kgenericfactory.h> +#include <knuminput.h> +#include <kfiledialog.h> + + +#include <KoFilterManager.h> + +#include <kis_doc.h> +#include <kis_image.h> +#include "kis_meta_registry.h" +#include <kis_iterators_pixel.h> +#include <kis_layer.h> +#include <kis_paint_layer.h> +#include <kis_group_layer.h> +#include <kis_transaction.h> +#include <kis_undo_adapter.h> +#include <kis_global.h> +#include <kis_types.h> +#include <kis_progress_subject.h> +#include <kis_progress_display_interface.h> +#include <kis_colorspace.h> +#include <kis_colorspace_factory_registry.h> +#include <kis_view.h> +#include <kis_paint_device.h> +#include <kis_channelinfo.h> + +#include "kis_channel_separator.h" + +KisChannelSeparator::KisChannelSeparator(KisView * view) +    : m_view(view) +{ +} + +void KisChannelSeparator::separate(KisProgressDisplayInterface * progress, enumSepAlphaOptions alphaOps, enumSepSource sourceOps, enumSepOutput outputOps, bool downscale, bool toColor) +{ +    KisImageSP image = m_view->canvasSubject()->currentImg(); +    if (!image) return; + +    KisLayerSP layer = image->activeLayer(); +    if (!layer) return; + +    KisPaintDeviceSP src = image->activeDevice(); +    if (!src) return; + +    m_cancelRequested = false; +    if ( progress ) +        progress->setSubject(this, true, true); +    emit notifyProgressStage(i18n("Separating image..."), 0); + +    KisColorSpace * dstCs = 0; + +    Q_UINT32 numberOfChannels = src->nChannels(); +    KisColorSpace * srcCs  = src->colorSpace(); +    QValueVector<KisChannelInfo *> channels = srcCs->channels(); + +    // Use the flattened image, if required +    switch(sourceOps) { + +        case(ALL_LAYERS): +            src = image->mergedImage(); +            break; +        default: +            break; +    } + +    vKisPaintDeviceSP layers; + +    QValueVector<KisChannelInfo *>::const_iterator begin = channels.begin(); +    QValueVector<KisChannelInfo *>::const_iterator end = channels.end(); + + +    QRect rect = src->exactBounds(); + +    int i = 0; +    Q_UINT32 channelIndex = 0; +    for (QValueVector<KisChannelInfo *>::const_iterator it = begin; it != end; ++it, ++channelIndex) +    { + +        KisChannelInfo * ch = (*it); + +        if (ch->channelType() == KisChannelInfo::ALPHA && alphaOps != CREATE_ALPHA_SEPARATION) { +            continue; +        } + +        Q_INT32 channelSize = ch->size(); +        Q_INT32 channelPos = ch->pos(); +        Q_INT32 destSize = 1; + +        KisPaintDeviceSP dev; +        if (toColor) { +            // We don't downscale if we separate to color channels +            dev = new KisPaintDevice(srcCs, "color separations"); +        } +        else { +            if (channelSize == 1 || downscale) { +                dev = new KisPaintDevice( KisMetaRegistry::instance()->csRegistry()->getColorSpace(KisID("GRAYA",""),"" ), "8 bit grayscale sep"); +            } +            else { +                dev = new KisPaintDevice( KisMetaRegistry::instance()->csRegistry()->getColorSpace(KisID("GRAYA16",""),"" ), "16 bit grayscale sep"); +                destSize = 2; +            } +        } + +        dstCs = dev->colorSpace(); + +        layers.push_back(dev); + +        for (Q_INT32 row = 0; row < rect.height(); ++row) { + +            KisHLineIteratorPixel srcIt = src->createHLineIterator(rect.x(), rect.y() + row, rect.width(), false); +            KisHLineIteratorPixel dstIt = dev->createHLineIterator(rect.x(), rect.y() + row, rect.width(), true); + +            while( ! srcIt.isDone() ) +            { +                if (srcIt.isSelected()) +                { +                    if (toColor) { +                        dstCs->getSingleChannelPixel(dstIt.rawData(), srcIt.rawData(), channelIndex); + +                        if (alphaOps == COPY_ALPHA_TO_SEPARATIONS) { +                            //dstCs->setAlpha(dstIt.rawData(), srcIt.rawData()[srcAlphaPos], 1); +                            dstCs->setAlpha(dstIt.rawData(), srcCs->getAlpha(srcIt.rawData()), 1); +                        } +                        else { +                            dstCs->setAlpha(dstIt.rawData(), OPACITY_OPAQUE, 1); +                        } +                    } +                    else { + +                        // To grayscale + +                        // Decide wether we need downscaling +                        if (channelSize == 1 && destSize == 1) { + +                            // Both 8-bit channels +                            dstIt.rawData()[0] = srcIt.rawData()[channelPos]; + +                            if (alphaOps == COPY_ALPHA_TO_SEPARATIONS) { +                                dstCs->setAlpha(dstIt.rawData(), srcCs->getAlpha(srcIt.rawData()), 1); +                            } +                            else { +                                dstCs->setAlpha(dstIt.rawData(), OPACITY_OPAQUE, 1); +                            } +                        } +                        else if (channelSize == 2 && destSize == 2) { + +                            // Both 16-bit +                            dstIt.rawData()[0] = srcIt.rawData()[channelPos]; +                            dstIt.rawData()[1] = srcIt.rawData()[channelPos + 1]; + +                            if (alphaOps == COPY_ALPHA_TO_SEPARATIONS) { +                                dstCs->setAlpha(dstIt.rawData(), srcCs->getAlpha(srcIt.rawData()), 1); +                            } +                            else { +                                dstCs->setAlpha(dstIt.rawData(), OPACITY_OPAQUE, 1); +                            } +                        } +                        else if (channelSize != 1 && destSize == 1) { +                            // Downscale +                            memset(dstIt.rawData(), srcCs->scaleToU8(srcIt.rawData(), channelPos), 1); + +                            // XXX: Do alpha +                            dstCs->setAlpha(dstIt.rawData(), OPACITY_OPAQUE, 1); +                        } +                        else if (channelSize != 2 && destSize == 2) { +                            // Upscale +                            dstIt.rawData()[0] = srcCs->scaleToU8(srcIt.rawData(), channelPos); + +                            // XXX: Do alpha +                            dstCs->setAlpha(dstIt.rawData(), OPACITY_OPAQUE, 1); + +                        } +                    } +                } +                ++dstIt; +                ++srcIt; +            } +        } +        ++i; + +        emit notifyProgress((i * 100) / numberOfChannels); +        if (m_cancelRequested) { +            break; +        } +    } + +    vKisPaintDeviceSP_it deviceIt = layers.begin(); + +    emit notifyProgressDone(); + +    if (!m_cancelRequested) { + +        KisUndoAdapter * undo = 0; +        if ((undo = image->undoAdapter()) && undo->undo()) { +            undo->beginMacro(i18n("Separate Image")); +        } + +        // Flatten the image if required +        switch(sourceOps) { +            case(ALL_LAYERS): +                image->flatten(); +                break; +            default: +                break; +        } + +        for (QValueVector<KisChannelInfo *>::const_iterator it = begin; it != end; ++it) +        { + +            KisChannelInfo * ch = (*it); + +            if (ch->channelType() == KisChannelInfo::ALPHA && alphaOps != CREATE_ALPHA_SEPARATION) { +            // Don't make an separate separation of the alpha channel if the user didn't ask for it. +                continue; +            } + +            if (outputOps == TO_LAYERS) { +                KisPaintLayerSP l = new KisPaintLayer( image, ch->name(), OPACITY_OPAQUE, *deviceIt); +                image->addLayer( dynamic_cast<KisLayer*>(l.data()), image->rootLayer(), 0); +            } +            else { +                QStringList listMimeFilter = KoFilterManager::mimeFilter("application/x-krita", KoFilterManager::Export); +                QString mimelist = listMimeFilter.join(" "); + +                KFileDialog fd (QString::null, mimelist, m_view, "Export Layer", true); +                fd.setCaption(i18n("Export Layer") + "(" + ch->name() + ")"); +                fd.setMimeFilter(listMimeFilter); +                fd.setOperationMode(KFileDialog::Saving); +                fd.setURL(KURL(ch->name())); +                if (!fd.exec()) return; + +                KURL url = fd.selectedURL(); +                QString mimefilter = fd.currentMimeFilter(); + +                if (url.isEmpty()) +                    return; + +                KisPaintLayerSP l = new KisPaintLayer( image, ch->name(), OPACITY_OPAQUE, *deviceIt); +                QRect r = l->exactBounds(); + +                KisDoc d; +                d.prepareForImport(); + +                KisImageSP dst = new KisImage(d.undoAdapter(), r.width(), r.height(), (*deviceIt)->colorSpace(), l->name()); +                d.setCurrentImage( dst ); +                dst->addLayer(l->clone(), dst->rootLayer(), 0); + +                d.setOutputMimeType(mimefilter.latin1()); +                d.exp0rt(url); + +            } + +            ++deviceIt; +        } + +        if (undo && undo->undo()) { +            undo->endMacro(); +        } + +        m_view->canvasSubject()->document()->setModified(true); +    } +} + + + + +#include "kis_channel_separator.moc" diff --git a/krita/plugins/viewplugins/separate_channels/kis_channel_separator.h b/krita/plugins/viewplugins/separate_channels/kis_channel_separator.h new file mode 100644 index 000000000..0c0d80c9f --- /dev/null +++ b/krita/plugins/viewplugins/separate_channels/kis_channel_separator.h @@ -0,0 +1,69 @@ +/* + * This file is part of the KDE project + * + * Copyright (c) Michael Thaler <michael.thaler@physik.tu-muenchen.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 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. + */ + +#ifndef _KIS_CHANNEL_SEPARATOR_H_ +#define _KIS_CHANNEL_SEPARATOR_H_ + +#include <kis_progress_subject.h> + +class KisView; +class KisProgressDisplayInterface; + + +enum enumSepAlphaOptions { +    COPY_ALPHA_TO_SEPARATIONS = 0, +    DISCARD_ALPHA = 1, +    CREATE_ALPHA_SEPARATION = 2 +}; + + +enum enumSepSource { +    CURRENT_LAYER = 0, +    ALL_LAYERS = 1, +    VISIBLE_LAYERS = 2 +}; + +enum enumSepOutput { +    TO_LAYERS = 0, +    TO_IMAGES = 1 +}; + +class KisChannelSeparator : public KisProgressSubject { + +    Q_OBJECT + +public: + +    KisChannelSeparator(KisView * view); +    virtual ~KisChannelSeparator() {}; + +    void separate(KisProgressDisplayInterface * progress, enumSepAlphaOptions alphaOps, enumSepSource sourceOps, enumSepOutput outputOps, bool downscale, bool toColor); + +public: // Implement KisProgressSubject +        virtual void cancel() { m_cancelRequested = true; } + +             +private: +    KisView * m_view; +    bool m_cancelRequested; + +}; + +#endif diff --git a/krita/plugins/viewplugins/separate_channels/kis_separate_channels_plugin.cc b/krita/plugins/viewplugins/separate_channels/kis_separate_channels_plugin.cc new file mode 100644 index 000000000..4f7134f85 --- /dev/null +++ b/krita/plugins/viewplugins/separate_channels/kis_separate_channels_plugin.cc @@ -0,0 +1,96 @@ +/* + * This file is part of the KDE project + * + * Copyright (c) 2005 Michael Thaler <michael.thaler@physik.tu-muenchen.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 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 <klocale.h> +#include <kiconloader.h> +#include <kinstance.h> +#include <kmessagebox.h> +#include <kstandarddirs.h> +#include <ktempfile.h> +#include <kdebug.h> +#include <kgenericfactory.h> + +#include <kis_view.h> +#include <kis_types.h> +#include <kis_image.h> +#include <kis_paint_device.h> +#include <kis_layer.h> + +#include "kis_separate_channels_plugin.h" +#include "kis_channel_separator.h" +#include "dlg_separate.h" + +K_EXPORT_COMPONENT_FACTORY( kritaseparatechannels, KGenericFactory<KisSeparateChannelsPlugin>( "krita" ) ) + +KisSeparateChannelsPlugin::KisSeparateChannelsPlugin(QObject *parent, const char *name, const QStringList &) +    : KParts::Plugin(parent, name) +{ + +    if ( parent->inherits("KisView") ) { +        setInstance(KGenericFactory<KisSeparateChannelsPlugin>::instance()); +        setXMLFile(locate("data","kritaplugins/imageseparate.rc"), true); +        m_view = (KisView*) parent; +        (void) new KAction(i18n("Separate Image..."), 0, 0, this, SLOT(slotSeparate()), actionCollection(), "separate"); +    } +} + +KisSeparateChannelsPlugin::~KisSeparateChannelsPlugin() +{ +} + +void KisSeparateChannelsPlugin::slotSeparate() +{ +    KisImageSP image = m_view->canvasSubject()->currentImg(); +    if (!image) return; + +    KisLayerSP l = image->activeLayer(); +    if (!l) return; + +    KisPaintDeviceSP dev = image->activeDevice(); +    if (!dev) return; + +    DlgSeparate * dlgSeparate = new DlgSeparate(dev->colorSpace()->id().name(), +                                                image->colorSpace()->id().name(), m_view, "Separate"); +    Q_CHECK_PTR(dlgSeparate); + +    dlgSeparate->setCaption(i18n("Separate Image")); + +    // If we're 8-bits, disable the downscale option +    if (dev->pixelSize() == dev->nChannels()) { +	dlgSeparate->enableDownscale(false); +    } + +    if (dlgSeparate->exec() == QDialog::Accepted) { + +        KisChannelSeparator separator(m_view); +        separator.separate(m_view->canvasSubject()->progressDisplay(), +                           dlgSeparate->getAlphaOptions(), +                           dlgSeparate->getSource(), +                           dlgSeparate->getOutput(), +                           dlgSeparate->getDownscale(), +                           dlgSeparate->getToColor()); + +    } + +    delete dlgSeparate; + +} + +#include "kis_separate_channels_plugin.moc" diff --git a/krita/plugins/viewplugins/separate_channels/kis_separate_channels_plugin.h b/krita/plugins/viewplugins/separate_channels/kis_separate_channels_plugin.h new file mode 100644 index 000000000..a4a4fd617 --- /dev/null +++ b/krita/plugins/viewplugins/separate_channels/kis_separate_channels_plugin.h @@ -0,0 +1,45 @@ +/* + * This file is part of Krita + * + * Copyright (c) Michael Thaler <michael.thaler@physik.tu-muenchen.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 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. */ + +#ifndef _KIS_SEPARATE_CHANNELS_PLUGIN_H_ +#define _KIS_SEPARATE_CHANNELS_PLUGIN_H_ + +#include <kparts/plugin.h> + +class KisView; + + + +class KisSeparateChannelsPlugin : public KParts::Plugin +{ +    Q_OBJECT +public: +    KisSeparateChannelsPlugin(QObject *parent, const char *name, const QStringList &); +    virtual ~KisSeparateChannelsPlugin(); + +private slots: + +    void slotSeparate(); + +private: + +    KisView * m_view; +}; + +#endif diff --git a/krita/plugins/viewplugins/separate_channels/kritaseparatechannels.desktop b/krita/plugins/viewplugins/separate_channels/kritaseparatechannels.desktop new file mode 100644 index 000000000..63da737f4 --- /dev/null +++ b/krita/plugins/viewplugins/separate_channels/kritaseparatechannels.desktop @@ -0,0 +1,42 @@ +[Desktop Entry] +Name=Separate Channels Plugin +Name[bg]=Приставка за отделен канал +Name[ca]=Connector de canals separats +Name[da]=Plugin for separate kanaler +Name[de]="Kanäle trennen"-Modul +Name[el]=Πρόσθετο διαχωρισμού καναλιών +Name[eo]=Apartkanal-kromaĵo +Name[es]=Complemento para canales separados +Name[et]=Kanalite lahutamise plugin +Name[fa]=جدا کردن وصلۀ مجراها +Name[fr]=Module de séparation des canaux +Name[fy]=Plugin foar aparte kanalen +Name[gl]=Plugin de Separación de Canais +Name[he]=תוסף לריבוי ערוצים +Name[hu]=Csatornaszétválasztó modul +Name[is]=Aðgreindar rásir íforrit +Name[it]=Plugin per la separazione dei canali +Name[ja]=チャンネル分離プラグイン +Name[km]=កម្មវិធីជំនួយដើម្បីបំបែកឆានែល +Name[nb]=Programtillegg for atskilte kanaler +Name[nds]=Kanaaltrenn-Moduul +Name[ne]=च्यानल प्लगइन छुट्याउनुहोस् +Name[nl]=Plugin voor aparte kanalen +Name[pl]=Wtyczka oddzielania kanałów +Name[pt]='Plugin' de Separação de Canais +Name[pt_BR]=Plugin de Separação de Canais +Name[ru]=Разбор изображения по каналам +Name[sk]=Modul oddelenie kanálov +Name[sl]=Vstavek za ločevanje kanalov +Name[sr]=Прикључак за раздвајање канала +Name[sr@Latn]=Priključak za razdvajanje kanala +Name[sv]=Insticksprogram för separata kanaler +Name[uk]=Втулок розділення каналів +Name[uz]=Kanallarni ajratish uchun plagin +Name[uz@cyrillic]=Каналларни ажратиш учун плагин +Name[zh_CN]=独立通道插件 +Name[zh_TW]=分離色頻外掛程式 +ServiceTypes=Krita/ViewPlugin +Type=Service +X-KDE-Library=kritaseparatechannels +X-Krita-Version=2 diff --git a/krita/plugins/viewplugins/separate_channels/wdg_separations.ui b/krita/plugins/viewplugins/separate_channels/wdg_separations.ui new file mode 100644 index 000000000..6c7a8cf7e --- /dev/null +++ b/krita/plugins/viewplugins/separate_channels/wdg_separations.ui @@ -0,0 +1,182 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>WdgSeparations</class> +<widget class="QWidget"> +    <property name="name"> +        <cstring>WdgSeparations</cstring> +    </property> +    <property name="geometry"> +        <rect> +            <x>0</x> +            <y>0</y> +            <width>570</width> +            <height>350</height> +        </rect> +    </property> +    <grid> +        <property name="name"> +            <cstring>unnamed</cstring> +        </property> +        <widget class="QCheckBox" row="4" column="0" rowspan="1" colspan="3"> +            <property name="name"> +                <cstring>chkColors</cstring> +            </property> +            <property name="text"> +                <string>Output to color, not grayscale</string> +            </property> +        </widget> +        <widget class="QCheckBox" row="3" column="0" rowspan="1" colspan="3"> +            <property name="name"> +                <cstring>chkDownscale</cstring> +            </property> +            <property name="text"> +                <string>Downscale to 8-bit before separating</string> +            </property> +        </widget> +        <widget class="QButtonGroup" row="2" column="0" rowspan="1" colspan="3"> +            <property name="name"> +                <cstring>grpAlpha</cstring> +            </property> +            <property name="title"> +                <string>Alpha Options</string> +            </property> +            <vbox> +                <property name="name"> +                    <cstring>unnamed</cstring> +                </property> +                <widget class="QRadioButton"> +                    <property name="name"> +                        <cstring>radioCopyAlpha</cstring> +                    </property> +                    <property name="text"> +                        <string>Copy alpha channel to each separated channel as an alpha channel</string> +                    </property> +                </widget> +                <widget class="QRadioButton"> +                    <property name="name"> +                        <cstring>radioDiscardAlpha</cstring> +                    </property> +                    <property name="text"> +                        <string>Discard alpha channel</string> +                    </property> +                    <property name="checked"> +                        <bool>true</bool> +                    </property> +                </widget> +                <widget class="QRadioButton"> +                    <property name="name"> +                        <cstring>radioSeparateAlpha</cstring> +                    </property> +                    <property name="text"> +                        <string>Create separate separation from alpha channel</string> +                    </property> +                </widget> +            </vbox> +        </widget> +        <spacer row="5" column="1"> +            <property name="name"> +                <cstring>spacer1</cstring> +            </property> +            <property name="orientation"> +                <enum>Vertical</enum> +            </property> +            <property name="sizeType"> +                <enum>Expanding</enum> +            </property> +            <property name="sizeHint"> +                <size> +                    <width>20</width> +                    <height>16</height> +                </size> +            </property> +        </spacer> +        <widget class="QButtonGroup" row="1" column="0" rowspan="1" colspan="2"> +            <property name="name"> +                <cstring>grpSource</cstring> +            </property> +            <property name="title"> +                <string>Source</string> +            </property> +            <grid> +                <property name="name"> +                    <cstring>unnamed</cstring> +                </property> +                <widget class="QRadioButton" row="0" column="0"> +                    <property name="name"> +                        <cstring>radioCurrentLayer</cstring> +                    </property> +                    <property name="text"> +                        <string>Current layer</string> +                    </property> +                    <property name="checked"> +                        <bool>true</bool> +                    </property> +                </widget> +                <widget class="QRadioButton" row="1" column="0"> +                    <property name="name"> +                        <cstring>radioAllLayers</cstring> +                    </property> +                    <property name="text"> +                        <string>Flatten all layers before separation</string> +                    </property> +                </widget> +            </grid> +        </widget> +        <widget class="QButtonGroup" row="1" column="2"> +            <property name="name"> +                <cstring>grpOutput</cstring> +            </property> +            <property name="title"> +                <string>Output</string> +            </property> +            <vbox> +                <property name="name"> +                    <cstring>unnamed</cstring> +                </property> +                <widget class="QRadioButton"> +                    <property name="name"> +                        <cstring>radioLayers</cstring> +                    </property> +                    <property name="text"> +                        <string>To layers</string> +                    </property> +                    <property name="checked"> +                        <bool>true</bool> +                    </property> +                </widget> +                <widget class="QRadioButton"> +                    <property name="name"> +                        <cstring>radioImages</cstring> +                    </property> +                    <property name="text"> +                        <string>To images</string> +                    </property> +                </widget> +            </vbox> +        </widget> +        <widget class="QLabel" row="0" column="1" rowspan="1" colspan="2"> +            <property name="name"> +                <cstring>lblColormodel</cstring> +            </property> +            <property name="text"> +                <string></string> +            </property> +        </widget> +        <widget class="QLabel" row="0" column="0"> +            <property name="name"> +                <cstring>textLabel1</cstring> +            </property> +            <property name="text"> +                <string>Current color model:</string> +            </property> +        </widget> +    </grid> +</widget> +<tabstops> +    <tabstop>radioCurrentLayer</tabstop> +    <tabstop>radioLayers</tabstop> +    <tabstop>radioDiscardAlpha</tabstop> +    <tabstop>chkDownscale</tabstop> +    <tabstop>chkColors</tabstop> +</tabstops> +<layoutdefaults spacing="6" margin="11"/> +</UI> diff --git a/krita/plugins/viewplugins/shearimage/Makefile.am b/krita/plugins/viewplugins/shearimage/Makefile.am new file mode 100644 index 000000000..3c085d45c --- /dev/null +++ b/krita/plugins/viewplugins/shearimage/Makefile.am @@ -0,0 +1,24 @@ +kritarcdir = $(kde_datadir)/kritaplugins +kritarc_DATA = shearimage.rc + +EXTRA_DIST = $(kritarc_DATA) + + +INCLUDES  =  -I$(srcdir)/../../../sdk \ +	-I$(srcdir)/../../../core \ +	-I$(srcdir)/../../../kritacolor/ \ +	-I$(srcdir)/../../../ui \ +	$(KOFFICE_INCLUDES) \ +	$(all_includes) + +kde_module_LTLIBRARIES = kritashearimage.la + +kde_services_DATA = kritashearimage.desktop + +kritashearimage_la_SOURCES = wdg_shearimage.ui shearimage.cc dlg_shearimage.cc +noinst_HEADERS = wdg_shearimage.h dlg_shearimage.h shearimage.h + +kritashearimage_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) +kritashearimage_la_LIBADD =  ../../../libkritacommon.la + +kritashearimage_la_METASOURCES = AUTO diff --git a/krita/plugins/viewplugins/shearimage/dlg_shearimage.cc b/krita/plugins/viewplugins/shearimage/dlg_shearimage.cc new file mode 100644 index 000000000..9a6a2f667 --- /dev/null +++ b/krita/plugins/viewplugins/shearimage/dlg_shearimage.cc @@ -0,0 +1,96 @@ +/* + *  dlg_shearimage.cc - part of KimageShop^WKrayon^WKrita + * + *  Copyright (c) 2004 Michael Thaler <michael.thaler@physik.tu-muenchen.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 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 <config.h> + +#include <math.h> + +#include <iostream> + +using namespace std; + +#include <qradiobutton.h> +#include <qcheckbox.h> +#include <qlabel.h> +#include <qlayout.h> + +#include <klocale.h> +#include <knuminput.h> +#include <kdebug.h> + +#include "dlg_shearimage.h" +#include "wdg_shearimage.h" + + +DlgShearImage::DlgShearImage( QWidget *  parent, +                const char * name) +    : super (parent, name, true, i18n("Shear Image"), Ok | Cancel, Ok) +{ +    m_lock = false; + +    m_page = new WdgShearImage(this, "shear_image"); +    m_page->layout()->setMargin(0); +    Q_CHECK_PTR(m_page); + +    setMainWidget(m_page); +    resize(m_page->sizeHint()); + +    connect(this, SIGNAL(okClicked()), +        this, SLOT(okClicked())); + +} + +DlgShearImage::~DlgShearImage() +{ +    delete m_page; +} + +void DlgShearImage::setAngleX(Q_UINT32 angle)  +{ +    m_page->shearAngleX->setValue(angle); +    m_oldAngle = angle; + +} + +void DlgShearImage::setAngleY(Q_UINT32 angle)  +{ +    m_page->shearAngleY->setValue(angle); +    m_oldAngle = angle; + +} + +Q_INT32 DlgShearImage::angleX() +{ +    return (Q_INT32)qRound(m_page->shearAngleX->value()); +} + +Q_INT32 DlgShearImage::angleY() +{ +    return (Q_INT32)qRound(m_page->shearAngleY->value()); +} + +// SLOTS + +void DlgShearImage::okClicked() +{ +    accept(); +} + +#include "dlg_shearimage.moc" diff --git a/krita/plugins/viewplugins/shearimage/dlg_shearimage.h b/krita/plugins/viewplugins/shearimage/dlg_shearimage.h new file mode 100644 index 000000000..183f166a9 --- /dev/null +++ b/krita/plugins/viewplugins/shearimage/dlg_shearimage.h @@ -0,0 +1,54 @@ +/* + *  dlg_shearimage.h -- part of KimageShop^WKrayon^WKrita + * + *  Copyright (c) 2004 Michael Thaler <michael.thaler@physik.tu-muenchen.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 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. + */ +#ifndef DLG_SHEARIMAGE +#define DLG_SHEARIMAGE + +#include <kdialogbase.h> + +class WdgShearImage; + +class DlgShearImage: public KDialogBase { +    typedef KDialogBase super; +    Q_OBJECT + +public: + +    DlgShearImage(QWidget * parent = 0, +             const char* name = 0); +    ~DlgShearImage(); + +    void setAngleX(Q_UINT32 w); +    void setAngleY(Q_UINT32 w); +        Q_INT32 angleX(); +        Q_INT32 angleY(); + +private slots: + +    void okClicked(); + +private: + +    WdgShearImage * m_page; +    double m_oldAngle; +    bool m_lock; + +}; + +#endif // DLG_SHEARIMAGE diff --git a/krita/plugins/viewplugins/shearimage/kritashearimage.desktop b/krita/plugins/viewplugins/shearimage/kritashearimage.desktop new file mode 100644 index 000000000..1b1e8ad09 --- /dev/null +++ b/krita/plugins/viewplugins/shearimage/kritashearimage.desktop @@ -0,0 +1,37 @@ +[Desktop Entry] +Name=Shear Image Plugin +Name[bg]=Приставка за отрязване на изображение +Name[ca]=Connector de tall d'imatge +Name[da]=Plugin for skævvrid billede +Name[de]="Bild scheren"-Modul +Name[el]=Πρόσθετο στρέβλωσης εικόνας +Name[es]=Complemento para cortar la imagen +Name[et]=Pildinihke plugin +Name[fa]=اشتراک وصلۀ تصویر +Name[fr]=Module de rognage d'images +Name[fy]=Ofbylding skeanlûke plugin +Name[gl]=Plugin de Inclinación da Imaxe +Name[hu]=Képnyíró modul +Name[is]=Klippa mynd íforrit +Name[it]=Plugin di distorsione delle immagini +Name[ja]=画像剪断変形プラグイン +Name[km]=កម្មវិធីជំនួយដើម្បីកាត់រូបភាព +Name[nb]=Programtillegg for bildeskjæring +Name[nds]=Bildscheer-Moduul +Name[ne]=छवि प्लगइन अपूर्ण गर्नुहोस् +Name[nl]=Afbeelding schuintrekken +Name[pl]=Wtyczka obcinania obrazków +Name[pt]='Plugin' de Inclinação da Imagem +Name[pt_BR]=Plugin de Inclinação da Imagem +Name[ru]=Сдвиг +Name[sk]=Modul roztrhnutie obrázku +Name[sl]=Vstavek Ostriži sliko +Name[sr]=Прикључак за смицање слике +Name[sr@Latn]=Priključak za smicanje slike +Name[sv]=Insticksprogram för skjuva bild +Name[uk]=Втулок перекошення зображення +Name[zh_TW]=修剪圖片外掛程式 +ServiceTypes=Krita/ViewPlugin +Type=Service +X-KDE-Library=kritashearimage +X-Krita-Version=2 diff --git a/krita/plugins/viewplugins/shearimage/shearimage.cc b/krita/plugins/viewplugins/shearimage/shearimage.cc new file mode 100644 index 000000000..d8c839cec --- /dev/null +++ b/krita/plugins/viewplugins/shearimage/shearimage.cc @@ -0,0 +1,113 @@ +/* + * shearimage.cc -- Part of Krita + * + * Copyright (c) 2004 Michael Thaler + * + *  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 <math.h> + +#include <stdlib.h> + +#include <qslider.h> +#include <qpoint.h> + +#include <klocale.h> +#include <kiconloader.h> +#include <kinstance.h> +#include <kmessagebox.h> +#include <kstandarddirs.h> +#include <ktempfile.h> +#include <kdebug.h> +#include <kgenericfactory.h> + +#include <kis_doc.h> +#include <kis_config.h> +#include <kis_image.h> +#include <kis_layer.h> +#include <kis_global.h> +#include <kis_types.h> +#include <kis_view.h> +#include <kis_selection.h> + +#include "shearimage.h" +#include "dlg_shearimage.h" + +typedef KGenericFactory<ShearImage> ShearImageFactory; +K_EXPORT_COMPONENT_FACTORY( kritashearimage, ShearImageFactory( "krita" ) ) + +// XXX: this plugin could also provide layer scaling/resizing +ShearImage::ShearImage(QObject *parent, const char *name, const QStringList &) +    : KParts::Plugin(parent, name) +{ +    if ( parent->inherits("KisView") ) +    { +        setInstance(ShearImageFactory::instance()); +        setXMLFile(locate("data","kritaplugins/shearimage.rc"), true); + +        (void) new KAction(i18n("&Shear Image..."), 0, 0, this, SLOT(slotShearImage()), actionCollection(), "shearimage"); +        (void) new KAction(i18n("&Shear Layer..."), 0, 0, this, SLOT(slotShearLayer()), actionCollection(), "shearlayer"); + +        m_view = (KisView*) parent; +    } +} + +ShearImage::~ShearImage() +{ +    m_view = 0; +} + +void ShearImage::slotShearImage() +{ +    KisImageSP image = m_view->canvasSubject()->currentImg(); + +    if (!image) return; + +    DlgShearImage * dlgShearImage = new DlgShearImage(m_view, "ShearImage"); +    Q_CHECK_PTR(dlgShearImage); + +    dlgShearImage->setCaption(i18n("Shear Image")); + +        if (dlgShearImage->exec() == QDialog::Accepted) { +        Q_INT32 angleX = dlgShearImage->angleX(); +                Q_INT32 angleY = dlgShearImage->angleY(); +                m_view->shearCurrentImage(angleX, angleY); +    } +        delete dlgShearImage; +} + +void ShearImage::slotShearLayer() +{ +    KisImageSP image = m_view->canvasSubject()->currentImg(); + +    if (!image) return; + +    DlgShearImage * dlgShearImage = new DlgShearImage(m_view, "ShearLayer"); +    Q_CHECK_PTR(dlgShearImage); + +    dlgShearImage->setCaption(i18n("Shear Layer")); + +    if (dlgShearImage->exec() == QDialog::Accepted) { +                Q_INT32 angleX = dlgShearImage->angleX(); +                Q_INT32 angleY = dlgShearImage->angleY(); +                m_view->shearLayer(angleX, angleY); + +    } +    delete dlgShearImage; +} + +#include "shearimage.moc" diff --git a/krita/plugins/viewplugins/shearimage/shearimage.h b/krita/plugins/viewplugins/shearimage/shearimage.h new file mode 100644 index 000000000..bfff2ac2c --- /dev/null +++ b/krita/plugins/viewplugins/shearimage/shearimage.h @@ -0,0 +1,46 @@ +/* + * shearimage.h -- Part of Krita + * + * Copyright (c) 2004 Michael Thaler (michael.thaler@physik.tu-muenchen.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 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. */ + +#ifndef SHEARIMAGE_H +#define SHEARIMAGE_H + +#include <kparts/plugin.h> + +class KisView; + +class ShearImage : public KParts::Plugin +{ +    Q_OBJECT +public: +    ShearImage(QObject *parent, const char *name, const QStringList &); +    virtual ~ShearImage(); + +private slots: + +    void slotShearImage(); +    void slotShearLayer(); + +private: + +    KisView * m_view; +    KisPainter * m_painter; + +}; + +#endif // SHEARIMAGE_H diff --git a/krita/plugins/viewplugins/shearimage/shearimage.rc b/krita/plugins/viewplugins/shearimage/shearimage.rc new file mode 100644 index 000000000..c13e341fb --- /dev/null +++ b/krita/plugins/viewplugins/shearimage/shearimage.rc @@ -0,0 +1,13 @@ +<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd"> +<kpartgui library="kritashearimage" version="6"> +<MenuBar> +    <Menu name="Image"><text>&Image</text> +	<Separator/> +	<Action name="shearimage"/> +    </Menu> +    <Menu name="Layer"><text>La&yer</text> +	<Separator/> +	<Action name="shearlayer"/> +    </Menu> +</MenuBar> +</kpartgui> diff --git a/krita/plugins/viewplugins/shearimage/wdg_shearimage.ui b/krita/plugins/viewplugins/shearimage/wdg_shearimage.ui new file mode 100644 index 000000000..20de0b6b5 --- /dev/null +++ b/krita/plugins/viewplugins/shearimage/wdg_shearimage.ui @@ -0,0 +1,102 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>WdgShearImage</class> +<widget class="QWidget"> +    <property name="name"> +        <cstring>WdgShearImage</cstring> +    </property> +    <property name="geometry"> +        <rect> +            <x>0</x> +            <y>0</y> +            <width>323</width> +            <height>114</height> +        </rect> +    </property> +    <property name="caption"> +        <string>Shear Image</string> +    </property> +    <grid> +        <property name="name"> +            <cstring>unnamed</cstring> +        </property> +        <widget class="QButtonGroup" row="0" column="0"> +            <property name="name"> +                <cstring>grpPixelDimensions</cstring> +            </property> +            <property name="title"> +                <string>&Shear Image</string> +            </property> +            <grid> +                <property name="name"> +                    <cstring>unnamed</cstring> +                </property> +                <widget class="KIntNumInput" row="0" column="1"> +                    <property name="name"> +                        <cstring>shearAngleX</cstring> +                    </property> +                    <property name="minValue"> +                        <number>-45</number> +                    </property> +                    <property name="maxValue"> +                        <number>45</number> +                    </property> +                    <property name="suffix"> +                        <string>°</string> +                    </property> +                </widget> +                <widget class="QLabel" row="1" column="0"> +                    <property name="name"> +                        <cstring>lblShearAngelY</cstring> +                    </property> +                    <property name="text"> +                        <string>Shear angle Y:</string> +                    </property> +                </widget> +                <widget class="KIntNumInput" row="1" column="1"> +                    <property name="name"> +                        <cstring>shearAngleY</cstring> +                    </property> +                    <property name="maximumSize"> +                        <size> +                            <width>32767</width> +                            <height>100</height> +                        </size> +                    </property> +                    <property name="minValue"> +                        <number>-45</number> +                    </property> +                    <property name="maxValue"> +                        <number>45</number> +                    </property> +                    <property name="suffix"> +                        <string>°</string> +                    </property> +                </widget> +                <widget class="QLabel" row="0" column="0"> +                    <property name="name"> +                        <cstring>lblShearAngleX</cstring> +                    </property> +                    <property name="text"> +                        <string>Shear angle X:</string> +                    </property> +                    <property name="buddy" stdset="0"> +                        <cstring>intWidth</cstring> +                    </property> +                </widget> +            </grid> +        </widget> +    </grid> +</widget> +<customwidgets> +</customwidgets> +<tabstops> +    <tabstop>shearAngleX</tabstop> +</tabstops> +<layoutdefaults spacing="6" margin="11"/> +<includehints> +    <includehint>knuminput.h</includehint> +    <includehint>knuminput.h</includehint> +    <includehint>knuminput.h</includehint> +    <includehint>knuminput.h</includehint> +</includehints> +</UI> diff --git a/krita/plugins/viewplugins/substrate/Makefile.am b/krita/plugins/viewplugins/substrate/Makefile.am new file mode 100644 index 000000000..5f86ea991 --- /dev/null +++ b/krita/plugins/viewplugins/substrate/Makefile.am @@ -0,0 +1,25 @@ +kritarcdir = $(kde_datadir)/kritaplugins +kritarc_DATA = substrate.rc + +EXTRA_DIST = $(kritarc_DATA) + + +INCLUDES  =  -I$(srcdir)/../../../sdk \ +	-I$(srcdir)/../../../core \ +	-I$(srcdir)/../../../kritacolor/ \ +	-I$(srcdir)/../../../ui \ +	-I$/../../../ui \ +	$(KOFFICE_INCLUDES) \ +	$(all_includes) + +kde_module_LTLIBRARIES = kritasubstrate.la + +kritasubstrate_la_SOURCES = substrate.cc dlg_substrate.cc wdgsubstrate.ui kis_repeating_substrate.cc +noinst_HEADERS = wdgsubstrate.h dlg_substrate.h kis_repeating_substrate.h substrate.h + +kritasubstrate_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) +kritasubstrate_la_LIBADD =  ../../../libkritacommon.la + +kde_services_DATA = kritasubstrate.desktop + +METASOURCES = AUTO diff --git a/krita/plugins/viewplugins/substrate/dlg_substrate.cc b/krita/plugins/viewplugins/substrate/dlg_substrate.cc new file mode 100644 index 000000000..d1bbe38f0 --- /dev/null +++ b/krita/plugins/viewplugins/substrate/dlg_substrate.cc @@ -0,0 +1,59 @@ +/* + *  dlg_substrate.cc - part of KimageShop^WKrayon^WKrita + * + *  Copyright (c) 2004 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 <klocale.h> + +#include "dlg_substrate.h" +#include "wdgsubstrate.h" + + +DlgSubstrate::DlgSubstrate( QWidget *  parent, +                    const char * name) +    : super (parent, name, true, i18n("Color Range"), Ok | Cancel, Ok) +{ +    m_previewPix = QPixmap(); +    m_page = new WdgSubstrate(this, "substrate"); +    Q_CHECK_PTR(m_page); +    setCaption(i18n("Substrate")); +    setMainWidget(m_page); +    resize(m_page -> size()); + +    connect(this, SIGNAL(okClicked()), +        this, SLOT(okClicked())); +} + +DlgSubstrate::~DlgSubstrate() +{ +    delete m_page; +} + +void DlgSubstrate::setPixmap(QPixmap pix) +{ +    m_previewPix = pix; +    m_previewPix.detach(); +} + +void DlgSubstrate::okClicked() +{ +    accept(); +} + +#include "dlg_substrate.moc" + diff --git a/krita/plugins/viewplugins/substrate/dlg_substrate.h b/krita/plugins/viewplugins/substrate/dlg_substrate.h new file mode 100644 index 000000000..0a566b11b --- /dev/null +++ b/krita/plugins/viewplugins/substrate/dlg_substrate.h @@ -0,0 +1,61 @@ +/* + *  dlg_substrate.h -- part of KimageShop^WKrayon^WKrita + * + *  Copyright (c) 2004 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. + */ +#ifndef DLG_SUBSTRATE +#define DLG_SUBSTRATE + +#include <qpixmap.h> + +#include <kdialogbase.h> + +#include "wdgsubstrate.h" + + +/** + * This dialog allows the user to modify a layer or a selection + * by adding more colour in a particular channel or lighten or + * darken an image. + */ +class DlgSubstrate: public KDialogBase { + +    typedef KDialogBase super; +    Q_OBJECT + +public: + +    DlgSubstrate(QWidget * parent = 0, +              const char* name = 0); +    ~DlgSubstrate(); + +    /** +     * Set the initial preview pixmap +     */ +    void setPixmap(QPixmap pix); + +private slots: + +    void okClicked(); + +private: + +    WdgSubstrate * m_page; +    QPixmap m_previewPix; +}; + +#endif // DLG_SUBSTRATE diff --git a/krita/plugins/viewplugins/substrate/kis_repeating_substrate.cc b/krita/plugins/viewplugins/substrate/kis_repeating_substrate.cc new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/krita/plugins/viewplugins/substrate/kis_repeating_substrate.cc diff --git a/krita/plugins/viewplugins/substrate/kis_repeating_substrate.h b/krita/plugins/viewplugins/substrate/kis_repeating_substrate.h new file mode 100644 index 000000000..9dc512d18 --- /dev/null +++ b/krita/plugins/viewplugins/substrate/kis_repeating_substrate.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2006 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. + */ +#ifndef KIS_SUBSTRATE_H +#define KIS_SUBSTRATE_H + +#include <qrect.h> +#include <ksharedptr.h> + +class KisImage; + +/// All values are normalized to a range between 0 and 1. +/// XXX: Do we need more? +struct KisSubstratePixel { +    float height;      // absolute height of the current position +    float smoothness;  // determines how easily the painting tool "slips" over the surface +    float absorbency;  // determines how much wetness the substrate can absorb. XXX: How about speed of absorbing? +    float r;           //.Red component of reflectivity +    float g;           // Green component of reflectivity +    float b;           // Blue component of reflectivity +    float transmittance; // Similar to alpha. XXX: Ask Leonardo about this. +}; + +/** + * This abstract class defines the properties of a substrate -- that is, the simulation + * of the paper or canvas for natural media. + * + * Subclass this interface to define a specific type of substrate: repeating, + * or full-size, with specific and cool ways of generating the surface, or + * maybe based on scans of real substrates. + */ +class KisSubstrate : public KShared { + +public: + +    KisSubstrate(KisImage * /*img*/) : KShared() {}; +    virtual ~KisSubstrate() {}; + + +    /** +     * Copy the pixel values in the specified rect into an array of Substrate. +     * Make sure the array is big enough! +     */  +    virtual void getPixels(KisSubstratePixel * /*substrate*/, const QRect & /*rc*/) = 0; + +    /** +     * Return a pointer to the substrate at the specified position. Note that +     * you cannot do pointe arithmetic with this value: the position of the +     * neighbouring pixels cannot be determined from this value +     */ +    virtual KisSubstratePixel * getPixel(uint x, uint y) = 0; + +}; + +#endif diff --git a/krita/plugins/viewplugins/substrate/kritasubstrate.desktop b/krita/plugins/viewplugins/substrate/kritasubstrate.desktop new file mode 100644 index 000000000..85e58263a --- /dev/null +++ b/krita/plugins/viewplugins/substrate/kritasubstrate.desktop @@ -0,0 +1,35 @@ +[Desktop Entry] +Name=Substrate +Name[bg]=Основа +Name[ca]=Substrat +Name[da]=Substrat +Name[de]=Träger +Name[el]=Υπόστρωμα +Name[es]=Sustrato +Name[et]=Substraat +Name[fa]=زیربنا +Name[fy]=Substraat +Name[ga]=Foshraith +Name[gl]=Substrato +Name[hu]=Szubsztrát +Name[it]=Substrato +Name[ja]=下地 +Name[nb]=Substrat +Name[nds]=Wassboden +Name[ne]=जीवाधार +Name[nl]=Substraat +Name[pl]=Wycięcie +Name[pt]=Substrato +Name[pt_BR]=Substrato +Name[ru]=Подложка +Name[sk]=Substrát +Name[sl]=Substrat +Name[sr]=Супстрат +Name[sr@Latn]=Supstrat +Name[sv]=Substrat +Name[uk]=Підложка +Name[zh_TW]=基底 +ServiceTypes=Krita/ViewPlugin +Type=Service +X-KDE-Library=kritasubstrate +X-Krita-Version=2 diff --git a/krita/plugins/viewplugins/substrate/substrate.cc b/krita/plugins/viewplugins/substrate/substrate.cc new file mode 100644 index 000000000..aac9ef944 --- /dev/null +++ b/krita/plugins/viewplugins/substrate/substrate.cc @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2006 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 <math.h> + +#include <stdlib.h> + +#include <qslider.h> +#include <qpoint.h> + +#include <klocale.h> +#include <kiconloader.h> +#include <kinstance.h> +#include <kmessagebox.h> +#include <kstandarddirs.h> +#include <ktempfile.h> +#include <kdebug.h> +#include <kgenericfactory.h> + +#include <kis_doc.h> +#include <kis_image.h> +#include <kis_layer.h> +#include <kis_global.h> +#include <kis_types.h> +#include <kis_view.h> + +#include "substrate.h" +#include "dlg_substrate.h" + +typedef KGenericFactory<SubstratePlugin> SubstrateFactory; +K_EXPORT_COMPONENT_FACTORY( kritasubstrate, SubstrateFactory( "krita" ) ) + +SubstratePlugin::SubstratePlugin(QObject *parent, const char *name, const QStringList &) +    : KParts::Plugin(parent, name) +{ + +    if ( parent->inherits("KisView") ) +    { +        setInstance(SubstrateFactory::instance()); +        setXMLFile(locate("data","kritaplugins/substrate.rc"), true); + +        (void) new KAction(i18n("&Substrate..."), 0, 0, this, SLOT(slotSubstrateActivated()), actionCollection(), "substrate"); + +         m_view = (KisView*) parent; +    } +} + +SubstratePlugin::~SubstratePlugin() +{ +} + +void SubstratePlugin::slotSubstrateActivated() +{ +    DlgSubstrate * dlgSubstrate = new DlgSubstrate(m_view, "Substrate"); +    Q_CHECK_PTR(dlgSubstrate); +    if (dlgSubstrate -> exec() == QDialog::Accepted) { +        // Retrieve changes made by dialog +        // Apply changes to layer (selection) +    } +    delete dlgSubstrate; +} + +#include "substrate.moc" + diff --git a/krita/plugins/viewplugins/substrate/substrate.h b/krita/plugins/viewplugins/substrate/substrate.h new file mode 100644 index 000000000..ebb9e48ed --- /dev/null +++ b/krita/plugins/viewplugins/substrate/substrate.h @@ -0,0 +1,44 @@ +/*  + * substrate.h -- Part of Krita + * + * Copyright (c) 2006 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. + */ + +#ifndef SUBSTATE_H +#define SUBSTATE_H + +#include <kparts/plugin.h> + +class KisView; + +class SubstratePlugin : public KParts::Plugin +{ +    Q_OBJECT +public: +    SubstratePlugin(QObject *parent, const char *name, const QStringList &); +    virtual ~SubstratePlugin(); +     +private slots: +    void slotSubstrateActivated(); + +private: +    KisView * m_view; +    KisPainter * m_painter; + +}; + +#endif // SUBSTATE_H diff --git a/krita/plugins/viewplugins/substrate/substrate.rc b/krita/plugins/viewplugins/substrate/substrate.rc new file mode 100644 index 000000000..4251e87fc --- /dev/null +++ b/krita/plugins/viewplugins/substrate/substrate.rc @@ -0,0 +1,8 @@ +<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd"> +<kpartgui library="kritasubstrate" version="1"> +<MenuBar> +    <Menu name="Image"><text>Image</text> +	<Action name="substrate"/> +    </Menu> +</MenuBar> +</kpartgui> diff --git a/krita/plugins/viewplugins/substrate/wdgsubstrate.ui b/krita/plugins/viewplugins/substrate/wdgsubstrate.ui new file mode 100644 index 000000000..846b43a78 --- /dev/null +++ b/krita/plugins/viewplugins/substrate/wdgsubstrate.ui @@ -0,0 +1,221 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>WdgSubstrate</class> +<widget class="QWidget"> +    <property name="name"> +        <cstring>Form1</cstring> +    </property> +    <property name="geometry"> +        <rect> +            <x>0</x> +            <y>0</y> +            <width>478</width> +            <height>358</height> +        </rect> +    </property> +    <grid> +        <property name="name"> +            <cstring>unnamed</cstring> +        </property> +        <widget class="QButtonGroup" row="0" column="0"> +            <property name="name"> +                <cstring>grpCustom</cstring> +            </property> +            <property name="title"> +                <string>Custom Canvas Definition</string> +            </property> +            <vbox> +                <property name="name"> +                    <cstring>unnamed</cstring> +                </property> +                <widget class="QLayoutWidget"> +                    <property name="name"> +                        <cstring>layout3</cstring> +                    </property> +                    <grid> +                        <property name="name"> +                            <cstring>unnamed</cstring> +                        </property> +                        <widget class="QComboBox" row="0" column="1" rowspan="1" colspan="2"> +                            <item> +                                <property name="text"> +                                    <string>Custom</string> +                                </property> +                            </item> +                            <property name="name"> +                                <cstring>cmbPredefinedCanvases</cstring> +                            </property> +                        </widget> +                        <widget class="KColorButton" row="2" column="2"> +                            <property name="name"> +                                <cstring>bnBackground</cstring> +                            </property> +                            <property name="text"> +                                <string></string> +                            </property> +                        </widget> +                        <widget class="QLabel" row="1" column="0"> +                            <property name="name"> +                                <cstring>textLabel1</cstring> +                            </property> +                            <property name="text"> +                                <string>Save custom substrate as:</string> +                            </property> +                        </widget> +                        <widget class="QLabel" row="0" column="0"> +                            <property name="name"> +                                <cstring>lblPredefined</cstring> +                            </property> +                            <property name="text"> +                                <string>&Pre-defined canvas types:</string> +                            </property> +                            <property name="buddy" stdset="0"> +                                <cstring>cmbPredefinedCanvases</cstring> +                            </property> +                        </widget> +                        <widget class="QLabel" row="2" column="0" rowspan="1" colspan="2"> +                            <property name="name"> +                                <cstring>lblColor</cstring> +                            </property> +                            <property name="text"> +                                <string>&Basic color:</string> +                            </property> +                            <property name="buddy" stdset="0"> +                                <cstring>bnBackground</cstring> +                            </property> +                        </widget> +                        <widget class="QLineEdit" row="1" column="1" rowspan="1" colspan="2"> +                            <property name="name"> +                                <cstring>lineEdit1</cstring> +                            </property> +                        </widget> +                    </grid> +                </widget> +                <widget class="QLayoutWidget"> +                    <property name="name"> +                        <cstring>layout2</cstring> +                    </property> +                    <grid> +                        <property name="name"> +                            <cstring>unnamed</cstring> +                        </property> +                        <widget class="QSlider" row="3" column="1"> +                            <property name="name"> +                                <cstring>slAbsorbency</cstring> +                            </property> +                            <property name="orientation"> +                                <enum>Horizontal</enum> +                            </property> +                        </widget> +                        <widget class="QSlider" row="2" column="1"> +                            <property name="name"> +                                <cstring>slFiber</cstring> +                            </property> +                            <property name="orientation"> +                                <enum>Horizontal</enum> +                            </property> +                        </widget> +                        <widget class="QLabel" row="1" column="2"> +                            <property name="name"> +                                <cstring>textLabel9</cstring> +                            </property> +                            <property name="text"> +                                <string>Grainy</string> +                            </property> +                        </widget> +                        <widget class="QLabel" row="0" column="0"> +                            <property name="name"> +                                <cstring>lblSmoothness</cstring> +                            </property> +                            <property name="text"> +                                <string>&Smooth:</string> +                            </property> +                            <property name="buddy" stdset="0"> +                                <cstring>slSlippery</cstring> +                            </property> +                        </widget> +                        <widget class="QLabel" row="3" column="0"> +                            <property name="name"> +                                <cstring>lblAbsorbency</cstring> +                            </property> +                            <property name="text"> +                                <string>&Water repellant:</string> +                            </property> +                            <property name="buddy" stdset="0"> +                                <cstring>slAbsorbency</cstring> +                            </property> +                        </widget> +                        <widget class="QSlider" row="0" column="1"> +                            <property name="name"> +                                <cstring>slSlippery</cstring> +                            </property> +                            <property name="orientation"> +                                <enum>Horizontal</enum> +                            </property> +                        </widget> +                        <widget class="QLabel" row="1" column="0"> +                            <property name="name"> +                                <cstring>lblHeight</cstring> +                            </property> +                            <property name="text"> +                                <string>&Flat:</string> +                            </property> +                            <property name="buddy" stdset="0"> +                                <cstring>slHeight</cstring> +                            </property> +                        </widget> +                        <widget class="QLabel" row="2" column="0"> +                            <property name="name"> +                                <cstring>lblFiber</cstring> +                            </property> +                            <property name="text"> +                                <string>Fine &fiber:</string> +                            </property> +                            <property name="buddy" stdset="0"> +                                <cstring>slFiber</cstring> +                            </property> +                        </widget> +                        <widget class="QLabel" row="0" column="2"> +                            <property name="name"> +                                <cstring>lblRough</cstring> +                            </property> +                            <property name="text"> +                                <string>Rough</string> +                            </property> +                        </widget> +                        <widget class="QSlider" row="1" column="1"> +                            <property name="name"> +                                <cstring>slHeight</cstring> +                            </property> +                            <property name="orientation"> +                                <enum>Horizontal</enum> +                            </property> +                        </widget> +                        <widget class="QLabel" row="3" column="2"> +                            <property name="name"> +                                <cstring>textLabel11</cstring> +                            </property> +                            <property name="text"> +                                <string>Absorbent</string> +                            </property> +                        </widget> +                        <widget class="QLabel" row="2" column="2"> +                            <property name="name"> +                                <cstring>textLabel10</cstring> +                            </property> +                            <property name="text"> +                                <string>Coarse</string> +                            </property> +                        </widget> +                    </grid> +                </widget> +            </vbox> +        </widget> +    </grid> +</widget> +<customwidgets> +</customwidgets> +<layoutdefaults spacing="6" margin="11"/> +<includehints> +    <includehint>kcolorbutton.h</includehint> +</includehints> +</UI> diff --git a/krita/plugins/viewplugins/variations/Makefile.am b/krita/plugins/viewplugins/variations/Makefile.am new file mode 100644 index 000000000..d4908aa63 --- /dev/null +++ b/krita/plugins/viewplugins/variations/Makefile.am @@ -0,0 +1,25 @@ +kritarcdir = $(kde_datadir)/kritaplugins +kritarc_DATA = variations.rc + +EXTRA_DIST = $(kritarc_DATA) + + +INCLUDES  =  -I$(srcdir)/../../../sdk \ +	-I$(srcdir)/../../../core \ +	-I$(srcdir)/../../../kritacolor/ \ +	-I$(srcdir)/../../../ui \ +	-I$/../../../ui \ +	$(KOFFICE_INCLUDES) \ +	$(all_includes) + +kde_module_LTLIBRARIES = kritavariations.la + +kritavariations_la_SOURCES = variations.cc dlg_variations.cc wdg_variations.ui  +noinst_HEADERS = wdg_variations.h + +kritavariations_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) +kritavariations_la_LIBADD =  ../../../libkritacommon.la + +kde_services_DATA = kritavariations.desktop + +kritavariations_la_METASOURCES = AUTO diff --git a/krita/plugins/viewplugins/variations/dlg_variations.cc b/krita/plugins/viewplugins/variations/dlg_variations.cc new file mode 100644 index 000000000..7d81b0787 --- /dev/null +++ b/krita/plugins/viewplugins/variations/dlg_variations.cc @@ -0,0 +1,58 @@ +/* + *  dlg_variations.cc - part of KimageShop^WKrayon^WKrita + * + *  Copyright (c) 2004 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 <klocale.h> + +#include "dlg_variations.h" +#include "wdg_variations.h" + + +DlgVariations::DlgVariations( QWidget *  parent, +                    const char * name) +    : super (parent, name, true, i18n("Color Range"), Ok | Cancel, Ok) +{ +    m_previewPix = QPixmap(); +    m_page = new WdgVariations(this, "variations"); +    Q_CHECK_PTR(m_page); +    setCaption(i18n("Variations")); +    setMainWidget(m_page); +    resize(m_page -> size()); + +    connect(this, SIGNAL(okClicked()), +        this, SLOT(okClicked())); +} + +DlgVariations::~DlgVariations() +{ +    delete m_page; +} + +void DlgVariations::setPixmap(QPixmap pix)  +{ +    m_previewPix = pix; +    m_previewPix.detach(); +} + +void DlgVariations::okClicked() +{ +    accept(); +} + +#include "dlg_variations.moc" diff --git a/krita/plugins/viewplugins/variations/dlg_variations.h b/krita/plugins/viewplugins/variations/dlg_variations.h new file mode 100644 index 000000000..48538687e --- /dev/null +++ b/krita/plugins/viewplugins/variations/dlg_variations.h @@ -0,0 +1,61 @@ +/* + *  dlg_variations.h -- part of KimageShop^WKrayon^WKrita + * + *  Copyright (c) 2004 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. + */ +#ifndef DLG_VARIATIONS +#define DLG_VARIATIONS + +#include <qpixmap.h> + +#include <kdialogbase.h> + +#include "wdg_variations.h" + + +/** + * This dialog allows the user to modify a layer or a selection + * by adding more colour in a particular channel or lighten or + * darken an image. + */ +class DlgVariations: public KDialogBase { + +    typedef KDialogBase super; +    Q_OBJECT + +public: + +    DlgVariations(QWidget * parent = 0, +              const char* name = 0); +    ~DlgVariations(); + +    /** +     * Set the initial preview pixmap +     */ +    void setPixmap(QPixmap pix); + +private slots: + +    void okClicked(); + +private: + +    WdgVariations * m_page; +    QPixmap m_previewPix; +}; + +#endif // DLG_VARIATIONS diff --git a/krita/plugins/viewplugins/variations/kritavariations.desktop b/krita/plugins/viewplugins/variations/kritavariations.desktop new file mode 100644 index 000000000..f0e066594 --- /dev/null +++ b/krita/plugins/viewplugins/variations/kritavariations.desktop @@ -0,0 +1,40 @@ +[Desktop Entry] +Name=Variations Plugin +Name[bg]=Приставка за вариации +Name[ca]=Connector de variacions +Name[da]=Plugin med variationer +Name[de]=Variationen-Modul +Name[el]=Πρόσθετο παραλλαγών +Name[eo]=Variaĵ-kromprogramo +Name[es]=Complemento para variaciones +Name[et]=Variatsioonide plugin +Name[fa]=وصلۀ تغییرات +Name[fr]=Module de variations +Name[fy]=Fariaasjeplugin +Name[gl]=Extensión de Variacións +Name[hu]=Variációk modul +Name[is]=Breytileika íforrit +Name[it]=Plugin delle variazioni +Name[ja]=バリエーションプラグイン +Name[km]=កម្មវិធីជំនួយភាពប្រែប្រួល +Name[nb]=Programtillegg for variasjoner +Name[nds]=Varianten-Moduul +Name[ne]=भिन्नता प्लगइन +Name[nl]=Variatieplugin +Name[pl]=Wtyczka wariacji +Name[pt]='Plugin' de Variações +Name[pt_BR]=Plugin de Variações +Name[ru]=Вариации +Name[sk]=Modul variácie +Name[sl]=Vstavek Variacije +Name[sr]=Прикључак за варијације +Name[sr@Latn]=Priključak za varijacije +Name[sv]=Insticksprogram med variationer +Name[uk]=Варіації +Name[uz]=Variatsiya plagini +Name[uz@cyrillic]=Вариация плагини +Name[zh_TW]=變動外掛程式 +ServiceTypes=Krita/ViewPlugin +Type=Service +X-KDE-Library=kritavariations +X-Krita-Version=2 diff --git a/krita/plugins/viewplugins/variations/variations.cc b/krita/plugins/viewplugins/variations/variations.cc new file mode 100644 index 000000000..eef4d6e5a --- /dev/null +++ b/krita/plugins/viewplugins/variations/variations.cc @@ -0,0 +1,88 @@ +/* + * variation.h -- Part of Krita + * + * Copyright (c) 2004 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 <math.h> + +#include <stdlib.h> + +#include <qslider.h> +#include <qpoint.h> + +#include <klocale.h> +#include <kiconloader.h> +#include <kinstance.h> +#include <kmessagebox.h> +#include <kstandarddirs.h> +#include <ktempfile.h> +#include <kdebug.h> +#include <kgenericfactory.h> + +#include <kis_doc.h> +#include <kis_image.h> +#include <kis_layer.h> +#include <kis_global.h> +#include <kis_types.h> +#include <kis_view.h> + +#include "variations.h" +#include "dlg_variations.h" + +typedef KGenericFactory<Variations> VariationsFactory; +K_EXPORT_COMPONENT_FACTORY( kritavariations, VariationsFactory( "krita" ) ) + +Variations::Variations(QObject *parent, const char *name, const QStringList &) +    : KParts::Plugin(parent, name) +{ + +    if ( parent->inherits("KisView") ) +    { +        setInstance(VariationsFactory::instance()); +        setXMLFile(locate("data","kritaplugins/variations.rc"), true); + +        (void) new KAction(i18n("&Variations..."), 0, 0, this, SLOT(slotVariationsActivated()), actionCollection(), "variations"); + +         m_view = (KisView*) parent; +    } +} + +Variations::~Variations() +{ +} + +void Variations::slotVariationsActivated() +{ +    DlgVariations * dlgVariations = new DlgVariations(m_view, "Variations"); +    Q_CHECK_PTR(dlgVariations); +    // Render layer to a QIMage -- keep in mind possibility of selection + +    // Scale QImage + +    // Set original QImage in dialog + +    if (dlgVariations -> exec() == QDialog::Accepted) { +        // Retrieve changes made by dialog +        // Apply changes to layer (selection) +    } +    delete dlgVariations; +} + +#include "variations.moc" + diff --git a/krita/plugins/viewplugins/variations/variations.h b/krita/plugins/viewplugins/variations/variations.h new file mode 100644 index 000000000..7aa40dafa --- /dev/null +++ b/krita/plugins/viewplugins/variations/variations.h @@ -0,0 +1,44 @@ +/*  + * variation.h -- Part of Krita + * + * Copyright (c) 2004 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. + */ + +#ifndef VARIATIONS_H +#define VARIATIONS_H + +#include <kparts/plugin.h> + +class KisView; + +class Variations : public KParts::Plugin +{ +    Q_OBJECT +public: +        Variations(QObject *parent, const char *name, const QStringList &); +    virtual ~Variations(); +     +private slots: +    void slotVariationsActivated(); + +private: +    KisView * m_view; +    KisPainter * m_painter; + +}; + +#endif // VARIATIONS_H diff --git a/krita/plugins/viewplugins/variations/variations.rc b/krita/plugins/viewplugins/variations/variations.rc new file mode 100644 index 000000000..9a3ac985e --- /dev/null +++ b/krita/plugins/viewplugins/variations/variations.rc @@ -0,0 +1,8 @@ +<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd"> +<kpartgui library="kritavariations" version="6"> +<MenuBar> +    <Menu name="Image"><text>Image</text> +	<Action name="variations"/> +    </Menu> +</MenuBar> +</kpartgui> diff --git a/krita/plugins/viewplugins/variations/wdg_variations.ui b/krita/plugins/viewplugins/variations/wdg_variations.ui new file mode 100644 index 000000000..e6d8336de --- /dev/null +++ b/krita/plugins/viewplugins/variations/wdg_variations.ui @@ -0,0 +1,897 @@ +<!DOCTYPE UI><UI version="3.2" stdsetdef="1"> +<class>WdgVariations</class> +<widget class="QWidget"> +    <property name="name"> +        <cstring>WdgVariations</cstring> +    </property> +    <property name="geometry"> +        <rect> +            <x>0</x> +            <y>0</y> +            <width>763</width> +            <height>852</height> +        </rect> +    </property> +    <property name="sizePolicy"> +        <sizepolicy> +            <hsizetype>5</hsizetype> +            <vsizetype>5</vsizetype> +            <horstretch>0</horstretch> +            <verstretch>0</verstretch> +        </sizepolicy> +    </property> +    <property name="caption"> +        <string>Variations</string> +    </property> +    <widget class="QFrame"> +        <property name="name"> +            <cstring>framePreview</cstring> +        </property> +        <property name="geometry"> +            <rect> +                <x>11</x> +                <y>11</y> +                <width>328</width> +                <height>255</height> +            </rect> +        </property> +        <property name="paletteBackgroundColor"> +            <color> +                <red>166</red> +                <green>188</green> +                <blue>153</blue> +            </color> +        </property> +        <property name="frameShape"> +            <enum>NoFrame</enum> +        </property> +        <property name="frameShadow"> +            <enum>Plain</enum> +        </property> +        <grid> +            <property name="name"> +                <cstring>unnamed</cstring> +            </property> +            <widget class="QLabel" row="0" column="0"> +                <property name="name"> +                    <cstring>lblOriginal</cstring> +                </property> +                <property name="sizePolicy"> +                    <sizepolicy> +                        <hsizetype>0</hsizetype> +                        <vsizetype>0</vsizetype> +                        <horstretch>0</horstretch> +                        <verstretch>0</verstretch> +                    </sizepolicy> +                </property> +                <property name="minimumSize"> +                    <size> +                        <width>150</width> +                        <height>150</height> +                    </size> +                </property> +                <property name="maximumSize"> +                    <size> +                        <width>150</width> +                        <height>150</height> +                    </size> +                </property> +                <property name="pixmap"> +                    <pixmap>image0</pixmap> +                </property> +                <property name="scaledContents"> +                    <bool>true</bool> +                </property> +            </widget> +            <widget class="QLabel" row="0" column="1"> +                <property name="name"> +                    <cstring>lblCurrentPick</cstring> +                </property> +                <property name="sizePolicy"> +                    <sizepolicy> +                        <hsizetype>0</hsizetype> +                        <vsizetype>0</vsizetype> +                        <horstretch>0</horstretch> +                        <verstretch>0</verstretch> +                    </sizepolicy> +                </property> +                <property name="minimumSize"> +                    <size> +                        <width>150</width> +                        <height>150</height> +                    </size> +                </property> +                <property name="maximumSize"> +                    <size> +                        <width>150</width> +                        <height>150</height> +                    </size> +                </property> +                <property name="pixmap"> +                    <pixmap>image0</pixmap> +                </property> +                <property name="scaledContents"> +                    <bool>true</bool> +                </property> +            </widget> +            <widget class="QLabel" row="1" column="1"> +                <property name="name"> +                    <cstring>textLabel4</cstring> +                </property> +                <property name="text"> +                    <string>Current Pick</string> +                </property> +                <property name="alignment"> +                    <set>AlignCenter</set> +                </property> +            </widget> +            <widget class="QLabel" row="1" column="0"> +                <property name="name"> +                    <cstring>textLabel3</cstring> +                </property> +                <property name="text"> +                    <string>Original</string> +                </property> +                <property name="alignment"> +                    <set>AlignCenter</set> +                </property> +            </widget> +        </grid> +    </widget> +    <widget class="QGroupBox"> +        <property name="name"> +            <cstring>grpOptions</cstring> +        </property> +        <property name="geometry"> +            <rect> +                <x>345</x> +                <y>11</y> +                <width>210</width> +                <height>250</height> +            </rect> +        </property> +        <property name="title"> +            <string>Options</string> +        </property> +        <grid> +            <property name="name"> +                <cstring>unnamed</cstring> +            </property> +            <widget class="QRadioButton" row="0" column="0" rowspan="1" colspan="2"> +                <property name="name"> +                    <cstring>radioShadows</cstring> +                </property> +                <property name="text"> +                    <string>&Shadows</string> +                </property> +            </widget> +            <widget class="QRadioButton" row="1" column="0" rowspan="1" colspan="2"> +                <property name="name"> +                    <cstring>radioMidtones</cstring> +                </property> +                <property name="text"> +                    <string>&Midtones</string> +                </property> +                <property name="checked"> +                    <bool>true</bool> +                </property> +            </widget> +            <widget class="QRadioButton" row="2" column="0" rowspan="1" colspan="2"> +                <property name="name"> +                    <cstring>radioHighlights</cstring> +                </property> +                <property name="text"> +                    <string>&Highlights</string> +                </property> +            </widget> +            <widget class="QRadioButton" row="3" column="0" rowspan="1" colspan="2"> +                <property name="name"> +                    <cstring>radioSaturation</cstring> +                </property> +                <property name="text"> +                    <string>&Saturation</string> +                </property> +            </widget> +            <widget class="QCheckBox" row="6" column="0" rowspan="1" colspan="2"> +                <property name="name"> +                    <cstring>chkClipping</cstring> +                </property> +                <property name="text"> +                    <string>Show &clipping</string> +                </property> +            </widget> +            <widget class="QSlider" row="5" column="0" rowspan="1" colspan="2"> +                <property name="name"> +                    <cstring>slider1</cstring> +                </property> +                <property name="orientation"> +                    <enum>Horizontal</enum> +                </property> +            </widget> +            <widget class="QLabel" row="4" column="0"> +                <property name="name"> +                    <cstring>lblFine</cstring> +                </property> +                <property name="text"> +                    <string>Fine</string> +                </property> +            </widget> +            <widget class="QLabel" row="4" column="1"> +                <property name="name"> +                    <cstring>lblCoars</cstring> +                </property> +                <property name="text"> +                    <string>Coarse</string> +                </property> +            </widget> +        </grid> +    </widget> +    <widget class="QLayoutWidget"> +        <property name="name"> +            <cstring>layout5</cstring> +        </property> +        <property name="geometry"> +            <rect> +                <x>570</x> +                <y>10</y> +                <width>174</width> +                <height>819</height> +            </rect> +        </property> +        <vbox> +            <property name="name"> +                <cstring>unnamed</cstring> +            </property> +            <widget class="QPushButton"> +                <property name="name"> +                    <cstring>bnLoad</cstring> +                </property> +                <property name="text"> +                    <string>&Load...</string> +                </property> +            </widget> +            <widget class="QPushButton"> +                <property name="name"> +                    <cstring>bnSave</cstring> +                </property> +                <property name="text"> +                    <string>&Save As...</string> +                </property> +            </widget> +            <spacer> +                <property name="name"> +                    <cstring>spacer1</cstring> +                </property> +                <property name="orientation"> +                    <enum>Vertical</enum> +                </property> +                <property name="sizeType"> +                    <enum>Expanding</enum> +                </property> +                <property name="sizeHint"> +                    <size> +                        <width>20</width> +                        <height>187</height> +                    </size> +                </property> +            </spacer> +            <widget class="QFrame"> +                <property name="name"> +                    <cstring>frameLight</cstring> +                </property> +                <property name="sizePolicy"> +                    <sizepolicy> +                        <hsizetype>1</hsizetype> +                        <vsizetype>0</vsizetype> +                        <horstretch>0</horstretch> +                        <verstretch>0</verstretch> +                    </sizepolicy> +                </property> +                <property name="maximumSize"> +                    <size> +                        <width>32767</width> +                        <height>556</height> +                    </size> +                </property> +                <property name="paletteBackgroundColor"> +                    <color> +                        <red>166</red> +                        <green>188</green> +                        <blue>153</blue> +                    </color> +                </property> +                <property name="frameShape"> +                    <enum>NoFrame</enum> +                </property> +                <property name="frameShadow"> +                    <enum>Plain</enum> +                </property> +                <grid> +                    <property name="name"> +                        <cstring>unnamed</cstring> +                    </property> +                    <widget class="QLabel" row="0" column="0"> +                        <property name="name"> +                            <cstring>lblLighter</cstring> +                        </property> +                        <property name="sizePolicy"> +                            <sizepolicy> +                                <hsizetype>0</hsizetype> +                                <vsizetype>0</vsizetype> +                                <horstretch>0</horstretch> +                                <verstretch>0</verstretch> +                            </sizepolicy> +                        </property> +                        <property name="minimumSize"> +                            <size> +                                <width>150</width> +                                <height>150</height> +                            </size> +                        </property> +                        <property name="maximumSize"> +                            <size> +                                <width>150</width> +                                <height>150</height> +                            </size> +                        </property> +                        <property name="pixmap"> +                            <pixmap>image0</pixmap> +                        </property> +                        <property name="scaledContents"> +                            <bool>true</bool> +                        </property> +                    </widget> +                    <widget class="QLabel" row="1" column="0"> +                        <property name="name"> +                            <cstring>textLabel12</cstring> +                        </property> +                        <property name="text"> +                            <string>Lighter</string> +                        </property> +                        <property name="alignment"> +                            <set>AlignCenter</set> +                        </property> +                    </widget> +                    <widget class="QLabel" row="2" column="0"> +                        <property name="name"> +                            <cstring>lblCurrentPick3</cstring> +                        </property> +                        <property name="sizePolicy"> +                            <sizepolicy> +                                <hsizetype>0</hsizetype> +                                <vsizetype>0</vsizetype> +                                <horstretch>0</horstretch> +                                <verstretch>0</verstretch> +                            </sizepolicy> +                        </property> +                        <property name="minimumSize"> +                            <size> +                                <width>150</width> +                                <height>150</height> +                            </size> +                        </property> +                        <property name="maximumSize"> +                            <size> +                                <width>150</width> +                                <height>150</height> +                            </size> +                        </property> +                        <property name="pixmap"> +                            <pixmap>image0</pixmap> +                        </property> +                        <property name="scaledContents"> +                            <bool>true</bool> +                        </property> +                    </widget> +                    <widget class="QLabel" row="3" column="0"> +                        <property name="name"> +                            <cstring>textLabel13</cstring> +                        </property> +                        <property name="text"> +                            <string>Current Pick</string> +                        </property> +                        <property name="alignment"> +                            <set>AlignCenter</set> +                        </property> +                    </widget> +                    <widget class="QLabel" row="4" column="0"> +                        <property name="name"> +                            <cstring>lblDarker</cstring> +                        </property> +                        <property name="sizePolicy"> +                            <sizepolicy> +                                <hsizetype>0</hsizetype> +                                <vsizetype>0</vsizetype> +                                <horstretch>0</horstretch> +                                <verstretch>0</verstretch> +                            </sizepolicy> +                        </property> +                        <property name="minimumSize"> +                            <size> +                                <width>150</width> +                                <height>150</height> +                            </size> +                        </property> +                        <property name="maximumSize"> +                            <size> +                                <width>150</width> +                                <height>150</height> +                            </size> +                        </property> +                        <property name="pixmap"> +                            <pixmap>image0</pixmap> +                        </property> +                        <property name="scaledContents"> +                            <bool>true</bool> +                        </property> +                    </widget> +                    <widget class="QLabel" row="5" column="0"> +                        <property name="name"> +                            <cstring>textLabel14</cstring> +                        </property> +                        <property name="text"> +                            <string>Darker</string> +                        </property> +                        <property name="alignment"> +                            <set>AlignCenter</set> +                        </property> +                    </widget> +                </grid> +            </widget> +        </vbox> +    </widget> +    <widget class="QFrame"> +        <property name="name"> +            <cstring>frameColor</cstring> +        </property> +        <property name="geometry"> +            <rect> +                <x>10</x> +                <y>270</y> +                <width>540</width> +                <height>556</height> +            </rect> +        </property> +        <property name="sizePolicy"> +            <sizepolicy> +                <hsizetype>0</hsizetype> +                <vsizetype>0</vsizetype> +                <horstretch>0</horstretch> +                <verstretch>0</verstretch> +            </sizepolicy> +        </property> +        <property name="minimumSize"> +            <size> +                <width>540</width> +                <height>556</height> +            </size> +        </property> +        <property name="maximumSize"> +            <size> +                <width>540</width> +                <height>556</height> +            </size> +        </property> +        <property name="paletteBackgroundColor"> +            <color> +                <red>166</red> +                <green>188</green> +                <blue>153</blue> +            </color> +        </property> +        <property name="frameShape"> +            <enum>NoFrame</enum> +        </property> +        <property name="frameShadow"> +            <enum>Plain</enum> +        </property> +        <widget class="QLabel"> +            <property name="name"> +                <cstring>lblMoreCyan</cstring> +            </property> +            <property name="geometry"> +                <rect> +                    <x>30</x> +                    <y>190</y> +                    <width>150</width> +                    <height>150</height> +                </rect> +            </property> +            <property name="minimumSize"> +                <size> +                    <width>150</width> +                    <height>150</height> +                </size> +            </property> +            <property name="maximumSize"> +                <size> +                    <width>150</width> +                    <height>150</height> +                </size> +            </property> +            <property name="pixmap"> +                <pixmap>image0</pixmap> +            </property> +            <property name="scaledContents"> +                <bool>true</bool> +            </property> +        </widget> +        <widget class="QLabel"> +            <property name="name"> +                <cstring>textLabel9</cstring> +            </property> +            <property name="geometry"> +                <rect> +                    <x>390</x> +                    <y>350</y> +                    <width>110</width> +                    <height>20</height> +                </rect> +            </property> +            <property name="text"> +                <string>More Red</string> +            </property> +            <property name="alignment"> +                <set>AlignCenter</set> +            </property> +        </widget> +        <widget class="QLabel"> +            <property name="name"> +                <cstring>textLabel7</cstring> +            </property> +            <property name="geometry"> +                <rect> +                    <x>50</x> +                    <y>350</y> +                    <width>120</width> +                    <height>20</height> +                </rect> +            </property> +            <property name="text"> +                <string>More Cyan</string> +            </property> +            <property name="alignment"> +                <set>AlignCenter</set> +            </property> +        </widget> +        <widget class="QLabel"> +            <property name="name"> +                <cstring>lblMoreBlue</cstring> +            </property> +            <property name="geometry"> +                <rect> +                    <x>110</x> +                    <y>380</y> +                    <width>150</width> +                    <height>150</height> +                </rect> +            </property> +            <property name="sizePolicy"> +                <sizepolicy> +                    <hsizetype>0</hsizetype> +                    <vsizetype>0</vsizetype> +                    <horstretch>0</horstretch> +                    <verstretch>0</verstretch> +                </sizepolicy> +            </property> +            <property name="minimumSize"> +                <size> +                    <width>150</width> +                    <height>150</height> +                </size> +            </property> +            <property name="maximumSize"> +                <size> +                    <width>150</width> +                    <height>150</height> +                </size> +            </property> +            <property name="pixmap"> +                <pixmap>image0</pixmap> +            </property> +            <property name="scaledContents"> +                <bool>true</bool> +            </property> +        </widget> +        <widget class="QLabel"> +            <property name="name"> +                <cstring>textLabel5</cstring> +            </property> +            <property name="geometry"> +                <rect> +                    <x>140</x> +                    <y>170</y> +                    <width>91</width> +                    <height>20</height> +                </rect> +            </property> +            <property name="text"> +                <string>More Green</string> +            </property> +            <property name="alignment"> +                <set>AlignCenter</set> +            </property> +        </widget> +        <widget class="QLabel"> +            <property name="name"> +                <cstring>lblMoreRed</cstring> +            </property> +            <property name="geometry"> +                <rect> +                    <x>370</x> +                    <y>190</y> +                    <width>150</width> +                    <height>150</height> +                </rect> +            </property> +            <property name="sizePolicy"> +                <sizepolicy> +                    <hsizetype>0</hsizetype> +                    <vsizetype>0</vsizetype> +                    <horstretch>0</horstretch> +                    <verstretch>0</verstretch> +                </sizepolicy> +            </property> +            <property name="minimumSize"> +                <size> +                    <width>150</width> +                    <height>150</height> +                </size> +            </property> +            <property name="maximumSize"> +                <size> +                    <width>150</width> +                    <height>150</height> +                </size> +            </property> +            <property name="pixmap"> +                <pixmap>image0</pixmap> +            </property> +            <property name="scaledContents"> +                <bool>true</bool> +            </property> +        </widget> +        <widget class="QLabel"> +            <property name="name"> +                <cstring>lblMoreYellow</cstring> +            </property> +            <property name="geometry"> +                <rect> +                    <x>280</x> +                    <y>10</y> +                    <width>150</width> +                    <height>150</height> +                </rect> +            </property> +            <property name="sizePolicy"> +                <sizepolicy> +                    <hsizetype>0</hsizetype> +                    <vsizetype>0</vsizetype> +                    <horstretch>0</horstretch> +                    <verstretch>0</verstretch> +                </sizepolicy> +            </property> +            <property name="minimumSize"> +                <size> +                    <width>150</width> +                    <height>150</height> +                </size> +            </property> +            <property name="maximumSize"> +                <size> +                    <width>150</width> +                    <height>150</height> +                </size> +            </property> +            <property name="pixmap"> +                <pixmap>image0</pixmap> +            </property> +            <property name="scaledContents"> +                <bool>true</bool> +            </property> +        </widget> +        <widget class="QLabel"> +            <property name="name"> +                <cstring>lblMoreMagenta</cstring> +            </property> +            <property name="geometry"> +                <rect> +                    <x>280</x> +                    <y>380</y> +                    <width>150</width> +                    <height>150</height> +                </rect> +            </property> +            <property name="sizePolicy"> +                <sizepolicy> +                    <hsizetype>0</hsizetype> +                    <vsizetype>0</vsizetype> +                    <horstretch>0</horstretch> +                    <verstretch>0</verstretch> +                </sizepolicy> +            </property> +            <property name="minimumSize"> +                <size> +                    <width>150</width> +                    <height>150</height> +                </size> +            </property> +            <property name="maximumSize"> +                <size> +                    <width>150</width> +                    <height>150</height> +                </size> +            </property> +            <property name="pixmap"> +                <pixmap>image0</pixmap> +            </property> +            <property name="scaledContents"> +                <bool>true</bool> +            </property> +        </widget> +        <widget class="QLabel"> +            <property name="name"> +                <cstring>textLabel8</cstring> +            </property> +            <property name="geometry"> +                <rect> +                    <x>210</x> +                    <y>350</y> +                    <width>128</width> +                    <height>20</height> +                </rect> +            </property> +            <property name="text"> +                <string>Current Pick</string> +            </property> +            <property name="alignment"> +                <set>AlignCenter</set> +            </property> +        </widget> +        <widget class="QLabel"> +            <property name="name"> +                <cstring>textLabel6</cstring> +            </property> +            <property name="geometry"> +                <rect> +                    <x>310</x> +                    <y>170</y> +                    <width>93</width> +                    <height>20</height> +                </rect> +            </property> +            <property name="text"> +                <string>More Yellow</string> +            </property> +            <property name="alignment"> +                <set>AlignCenter</set> +            </property> +        </widget> +        <widget class="QLabel"> +            <property name="name"> +                <cstring>lblCurrentPick2</cstring> +            </property> +            <property name="geometry"> +                <rect> +                    <x>200</x> +                    <y>190</y> +                    <width>150</width> +                    <height>150</height> +                </rect> +            </property> +            <property name="sizePolicy"> +                <sizepolicy> +                    <hsizetype>0</hsizetype> +                    <vsizetype>0</vsizetype> +                    <horstretch>0</horstretch> +                    <verstretch>0</verstretch> +                </sizepolicy> +            </property> +            <property name="minimumSize"> +                <size> +                    <width>150</width> +                    <height>150</height> +                </size> +            </property> +            <property name="maximumSize"> +                <size> +                    <width>150</width> +                    <height>150</height> +                </size> +            </property> +            <property name="frameShape"> +                <enum>Box</enum> +            </property> +            <property name="pixmap"> +                <pixmap>image0</pixmap> +            </property> +            <property name="scaledContents"> +                <bool>true</bool> +            </property> +        </widget> +        <widget class="QLabel"> +            <property name="name"> +                <cstring>lblMoreGreen</cstring> +            </property> +            <property name="geometry"> +                <rect> +                    <x>110</x> +                    <y>10</y> +                    <width>150</width> +                    <height>150</height> +                </rect> +            </property> +            <property name="sizePolicy"> +                <sizepolicy> +                    <hsizetype>0</hsizetype> +                    <vsizetype>0</vsizetype> +                    <horstretch>0</horstretch> +                    <verstretch>0</verstretch> +                </sizepolicy> +            </property> +            <property name="minimumSize"> +                <size> +                    <width>150</width> +                    <height>150</height> +                </size> +            </property> +            <property name="maximumSize"> +                <size> +                    <width>150</width> +                    <height>150</height> +                </size> +            </property> +            <property name="pixmap"> +                <pixmap>image0</pixmap> +            </property> +            <property name="scaledContents"> +                <bool>true</bool> +            </property> +        </widget> +        <widget class="QLabel"> +            <property name="name"> +                <cstring>textLabel11</cstring> +            </property> +            <property name="geometry"> +                <rect> +                    <x>290</x> +                    <y>540</y> +                    <width>128</width> +                    <height>20</height> +                </rect> +            </property> +            <property name="text"> +                <string>More Magenta</string> +            </property> +            <property name="alignment"> +                <set>AlignCenter</set> +            </property> +        </widget> +        <widget class="QLabel"> +            <property name="name"> +                <cstring>textLabel10</cstring> +            </property> +            <property name="geometry"> +                <rect> +                    <x>140</x> +                    <y>540</y> +                    <width>77</width> +                    <height>20</height> +                </rect> +            </property> +            <property name="text"> +                <string>More Blue</string> +            </property> +            <property name="alignment"> +                <set>AlignCenter</set> +            </property> +        </widget> +    </widget> +</widget> +<images> +    <image name="image0"> +        <data format="XPM.GZ" length="55092">789cccbd47b7eb38b2ef397f9fa2d6e5ecae5e7cf266d0035266cb6da7ed77af1ed07b2f1aa9bf7c83883f704c56d5cd7c75bb5f95d6c9ca5f8a22114044202200f0fccffffcdbe7d3fddffef37ffe8fea625c02eb6f966f947ffb4fbb4e92ebfff57fff9fffcffff88fe160f0b7fecf68389bfe6df41fffc7fff80febf96fd6df9401ff5fcff64232ffde36244f7a762ac953fefd56f29cf35cf2a267f3072ff9f733c906e7836493f35eb2c59fd74ab6797b1f243bfcfb46b2cb7fef0a1e72799c5af2907f7f94cce5732cc963fefd483297cf3a8387d43f992999ffde0c25f3dfb79a64de5f662099dfcfe924cf386f24f3fe4a44ff0fd17e5b327f9e772799dfcfb8078fa87d662499cbebbb9249de6fc9bcbd9d2f99dab795ccc7b31a48e6e3b71a4ae6e315ed25f3f1b04f82a93f0dc1636a9ff32999daf32599f757a54ae6fde17e48e6fae23892b97e78a2bd63ea1f438cef849e97e892f9f7652b99b76f3d91cce53763f0947e6f08fd9c1137b664de5e43c83fc7f53bf0022cf475499c8be719c4f113d824de5cc01671fd0eb6895dbaff50d8ab174ae6f2ad3ac9a47f63c924df4832d73f732a99f777f324998fb73993ccfb5f7f96ccc7df3a49e6e3514592b9bd3aa664ae1fd6bd646eaf9a2b98f4ddf52573fdb58e60d89f6d49e6df9b13c97c3c1d45326fbf634826ffb2934cfee40086fdf88164de7ff65232d9eb9b646e1fa607867e9bbe641a8f816092cf14f2423f4d070c7d8b9f25f3e7bbaf60e89fb791ccfb3b15df43ffe22f30f42f13f240ffea1b18fab716bf877ee967b043dc92bf1f0ea16fdd9af3a8f740bc3dbe64f2f70bc9bcbfcd2fc9bcbfbd4432f90b4730f5cff55e3297bfc9c0187f732899f4772099c6e35b321f7f6b0fc6f8daa6649aff7692f9f3724d32d7f7cb4932ef6ffb4e32e9b302c6f86723c9dcdefc50326f9ff32e99f7975382a10fd75c32d7e795906742fdd3bd49e6df67a2bdd09ff20886beb89164fefcd54932ef9ffa2c98fca72bda0b7d6a9f25f3feb0c4f842bf9a07b0d02fd13fd0afe2090cffd6c660e85b24ae87be05a40f63e1df8277c9bc7debab643e5e575732efef6e2799cb1bfcf89ecbdbed2573fd5cfd781e1fcf952d98fa3b91cf277f74cd24f3fe0f3ec08807ba8d64ae9fc54232e98f27993faff9f13df787ae680ff4d57995cce57103c95c7fac3bc97c7c7c5f308d67b8028bf9f72299cbd3dc49e6f2981f92797fd69664de5f7e2499dbb33b92ccdb6f2dc1d067772099fca72e99b7ff6a49a6f946f437f4b9bd48267934b0d0ef77c9bc7dad68df9cee9fee25f3fe69447fcc31df88f1843eaf6e92f9f3da89649a0fee25f3f1cb85be41ff0331bed07f5f8ca7f0a7d43f13a1df9d2a99f777f32899dfffea80111faeae92b93cee41f090f7effa0c463ce77f48a6f9ee51321fafeb4930f547bb01433fecb164fe7cff5b321f2f2f92ccfb3f93d793bd745b30f421ae2593bfd94be6fd1b2692b93cde4e32b79fda164ced8ddec1d017e74332f9dbb564de5e772899e299140c7dcaa692b93db8df92797fe61d18fe3117e303fd59b792e979b164de3f8918ff05f5cf46f40ff4c715e301fdb9bd80e13f57f792797fad4a30fce906bf17f3f51ae331c4fc19a13d43f89780e693a9f0a7ed028cebfd4e321fafe6198c7cc00b2473f9bc77c95cdf4a4ff0908fc75a5c8f78bfb52553fcf02999ebbfdf08a6f10e5ec1c2bfdc49a6f97c2b99e6ff27c9642f3fbee7fab416f2407fc299643efe912f99ec692099cbd3b492b9bc9ab8ff94c63711fd0bfdb2a792c93e2ac9140f689229df5125f3feed5660e85ffd2a99fce34432efdfee00867e5e14c9941f8ec0d0bfcc904cf9572a99b7a76e25f3fe73c760a1afaa646ebf99e85fe86f2ec61bfaea0b79e11f0ba12f2eda8bfb4b7d267b98897c64dd81a1cfeb503297afbd934cf1d45e30fc93f81ef363b896ccefbf3a4a26793dc1149fae7d30f247ff2a99ea1d3fbee7fed68b05a31eb1924cf9c2083ca5f6076bc9542fd948e6fa900e2473fdbbbc09463d630246be1a6692f9f84481643edef95532b73f5df01cfd7993ccdb7be92453beb5924cf3c14432efbf5cfc7e01fffa2999e6bfb1646e5f9b022ce2cba364de3e37114cfec132c0d047f74d32f9e37b30f26b2f05431f5763c9bc7f42c1d04797e6cf99d0c71be41fc21fa52a18fe24207d9f0bfd5a1d04d3f8570fe009d573dca3642e7fbb054f697ca237c1246f3a944cf53a5b32c5a72f60f81bd796ccaf4f2bc994af2d2593be6f2453bea682e7345eed4e32d5ff14c9bcbf2f57c95cff7dd15ef8a35097ccdb93cd25537e2bfa6b3124fffd055ec2bfcc24537c548045fe518331decda7647ebd2eda6ba37fc478c01f6d44ffb8d43e1ded17e3af3960cc97f5022cf481e257a6dd149fd96bf08cc6ffe64aa6f92604c35eec4032b7efab2799e2375b30e94b2aae5f50ff58aa642e6fe148a67ce1065e927fb80d2553bd2494cc9fdf3e49a6fc45c863c07e1dc97cfcd3a3606a5f7d05633e887682497faf4bb08df8e2030cfb2bc9de17a2ff4bf49f886762f4cf10f666bd80618f3e8dff92f5177f5e914be6ed2f36e005c91b5f24533cf22598ecafeec04be467ae64f28757b041bfaf5f040f29fe68c0268d9726da63917e14a2bdd0c7f424998f5f44fdb314fd91bf83a18f8105467fdc4660e86783e789fee94a30e215e3118c78a3a0f9dc60fd45fa34072f491fc329d8a0f685a964aae7dfc0265d5f2f05537f568f60d86bb091ccfbe36248e6fad988dfbba85f8e24533e48f66f88fe892b30fa67634ba6f97508467f6d1cb0a827435ed11f35fa6388f9c9a7f8c814f157fd065e92fe5f6e6083e42f5cb0897ac417d8227dca3fc036f55fb305431fba77c1747f3b02bba4df3ad9ab29e42f669229df46fb647fe460d8d3aa0243fecd2758d4bbefc0a21eb403a33f2a8a772c263f6fff35055ba827d1f85aa2bf2f1a58f4f70a8cfb252a18febdf1c0f02701f58f2dda7f5d48a6fe9b8071fff21d2cfc83603caf51c1b87fb106433f4b1a1f87fd17eebf1b17ec903efbd43e46b0f71a0c79cb2d58c4e72d18cf2f1bb078be0dc6f3339abf5cd11f8906c6f5de1a8cf846e3f6c1cbe724df068cf6548964ae3f1b130c7f9096608c7f7603a3bde90e8ce7bb2f60b4d77e00c39f075c9f98f639e47fa34832d7e7f84c2c9eb7ba80216ffb08c6f3cc042cd64f1a30e42f9760d88fe382d19e1ced19c11e42aebf0cf17cd306435ecb04a33d610e16f20b16f1470a16ed3981457cf9443c82bdae2660e19f79bc341c8be7d70e18cfd71ec022df8ac178feaa05e379d72bf108e3df70ff369cc8fe1d8345bc9c81d1fe60452cfaeb7a03c3be74ba7e2adbd382f1fbcb3b18e3910dc1689f4df24e657fd4603cafb2c168bffb0cc6f32b1ebf0c67e2fe01e9d34cdcef1283e12faa6f30ee67f860e1ffe660a1efdc7f0ee7e2fed58c58b6e70cc6ef8d002cd6173db0a83f2dc0d0b78edbf77021e5bd078bf6aec1f87d41fabd14f2155bb0f8fd108cdfeb2330da93de83f1fc8ac6d310f2ac1a309ed772ff3734c5fdb48d64ee0fb72e58d4e75ec0f87d7202a33f0d713df4a5237bb7e4782a60b11ee681d15eed112cee1782a1cf158f4f86b6b8bf6581c5fa2af5a733823f762d30eed7d2efdd11f2efcd1d18d76bdc5e468311f2a3c007e379f5082cea75f760e8fbfa8d782cf49dfba3d150fcbebc030b7bdc83a17f099faf472371ffe64c2ceed73460e883cefb6b3416f7ab4fc463e10f2c30e46b8927e279b94b2cee6f6cc1d087ec092cec4930c6f342f24f85fc46442caef75660e8cf85fb93d18cfd9ec783f1162ceaa37cfe19cdc5fd3ceabfb990d79d80d13eeb152cd64fe9fa85f8de7c05a33df9188cf66cbec0d0c7f50d0c7df3b8ff1f2d85bcce002ce227078ceb1d0f2cfca54e3c41fb6f74bd21ef5780f17c5d058bf53beeaf46e618ebd77a2299c77f5bba9f25c6b7f4c1c2bfbd80d19eeb07f104fda1933cb678de2603e37eba01c6ef6f57b0a8ff71ff3d72c6a8b7e8d47faee88fb507c6effd188cdf3bdc1ec67d38c739e2e3c5a63393e21723269e60fde4f22c99d677b93e307577285eb7b8fd8f27ecfe9cf50e0c7d8a79ff8ca7ec7bfefb6b412cc627db81c57e823730ead9eb1158d43fb8bce399b8fe7a0716eb5d7330c663c3fb733c67eda1fa484d2cc6c39a83a11fed193ca57a651282b13e16f3f96ebc9860bdc8d880c5fe810c2cf21bae8fe3e544d4cb23c93c5ed30a30ea071b170cff92d0f81813d443d71730eaed9a07c6f53eb7b7b1c9bee7fa117c49a6f5024b30c5b3760cb6b19ec9e3adb13331e8face93ccfbaf3883f13c23013ba8a72e05d3fd0d1b8c7c734df23b53d8df86facf9da03e7e1b80f1fc82f7e76430813e6d63e229fa3be5e333194e4cd40b52b04ded31b8fe4e4653110ff2fa0a73a736f28d9a788afd67fa180cfd6a1db0588fe3fe7f32610accfb77c3f59721f2c77c493cc5fe0aaf00e37eb731788afa4e059ed1f8361f60d48f6dde1f93d914ebc7460a46bd2fe4fd37994fc7940f6cbec1e89f98cf5f93a578def5013c433d86da6f4c51bf09b9bd4dcce982f2b39cebcbc49a22fff6b83e4dec29ea15d95932adb704c433acffebf43c776ad1fd039d7886f5d315bf3f5356f09acf77d3d1d4a5fa65734f3cc3fe035d134cf7372c30ec355b824dc413dc3fb0e9906574dcdf79c4e2f74501c6fa5b74104cdfb73c3e9d4ea6d6887f7fdb10b3e791bef1f9940ddf1ceb078fe005f5b7c5e7e3e96c86f58f8d0246fd3a76c1f311f9b377b043e31bf07c693a9fa1de19df816dec07f804bb584fa3fe5accc47a86069e517b82002cd6f775b043f39bc6e3dde9923d8eeb7332035bd47f3705ec60ff824d3cc7fecf84ebefd498c19e2faf609bfa2be6f9f0d49c2d51cff5c016e5fb2b176c8f78fb8b15d8a5fa99c9e7d7a93543fdab1b831dfafde6287844f5d10e8cf1af49bfac39c63bff024f499e98ee6fb3fb937f7d023bd4fed407bb435aafb124d37e2d5d30b53f03cf87d43eeb0d8cf5dd7803c67cb7e1f63d75587f707df1e9fece7c30a2fd5d7b30f6b3469f9269fdc792cce5594dc1587fba52ffb84c1edebecd5e326f7f41faebceb19f2cda8271bfa6133ca2e727e0118d4fb2164cfa9c2892f978af4c30eca1f1c19321d7bf2bff7e3660e34ff5e53bb043cfaf5dc174bf6c0076a97fdb929805acfcfb6d0446bdbee4ed9f0d857eddd660f89b6e2298da5f05c4ac3f687e6bc0c311ad87e07a263f9f0fda77f094da537f8067245fc5f569369a1963d29f2b31eb5fdabfe20ba6e7a777e0d188ff3eb9815906c29fa78227d04f053ca3f6b65c3f6663260fd553a93d2cfca4fec91bc95cfeea041e517f5fb8fece2662fcdd023c86ff33c1d31167cd06cf21cf5c308d679d8017d41f0df72fb3e9cc1ef3ebab14ec8c69bfc05432ed47d38885fe5d4cc9b4fe37028fc8fecb37c9649f25784cf6ebbf82e7f47dbc042fe87e05f5cf4ce8936b82e7f4fb36113ca6f17a002fe8f986b8de80fe8bef4dd28fc292cce52fa68269fc4d1effb0db2f49decd0c0c7fdc92fe2ce6131a3f6d2d98fcb7bf02cf49bf370330d68fea5a30fdde38831dfabea3fe59b2fea178b0009bd41e4f03db23aeff37713decb5f00593fc2df5a7c1ee47eb6f2330eadd17156c8ea87ff7609bfc45590b267f78d5c02e714bfa6ab2f1207ff80136c87ef22918f34dfe06c67cd186c48b018dafcee3cd99c5ee47faa48217647f99609bf4c7a0f1b2160392afa3f6da6cfc68bcd69279ff949f6093daef4ec1f067f5817831a4e76de8f70ebb9ece177c806d6abfb3235ec0dfba2bc9b4df9bc6d7ed1376ae5f5c3fe703263f6f4f520a1e53fc99102f66d4be8cf7cf7cc8e4e3d7673e784c7cdd82a7d4de5a03c3fe751e9f3265c2fca09be009d94fc2e397394b87c99f186bf08cfa4fe3fd3b9fb0e7717dacc792e97c0b8f5f58f8bb20d6793d613e5f2cc7b49fc5005bd49e35b56fb1c4fcecf1fe9e2fd9f7743dfdde582ca83f8267b049ed59f3f9686eb2eb69fd782699d62fa83de67244f67de1fa3eb79643b237ef2698f4ab9e8347d4feb0008fc99e1c6a8fbd70d05f4762261e6f9f46e3e730a6f3160618fdbbe6f9c6dc5d0ea8bd0df5bf6b88f89aebdfa25f00a5f8ff4e32edd749c0636aff66019ee17939780e7de2f92a73f643e8bb031e537b7c133c237bf5dec073ba7f44f71f1a225ea3e78f447f79dfe011ddcfe3f22dc68c29feff06e379ba0e9ed2ef0b1effb1747d44f3b1fd0d5ed2f78d0236c65cdf367c7e5fb0009858bf07cfd15f7bf082f4a3492473f96f19d8257b6df8f82e66cb05f55fbe223630ff6f797cbc98b3f67079527afe82319d17e1f6b7581a03fafdc693ccc7d7a0fb194b97da7bbb111b63f2af1bae9f0bd31810eb7cbd61612d1dd2bf94da671943c8cfe7af856d8c69be6e0563be594f2573fdd7b8bd2c1c763ded0f53c01392c7bb4ae6fdd3717d5db8c684fa4bbb134cdfa767f094e28180fba3e5c080fff15fc0b309f5ef9764d24ff13dfc43cae7a3e5d0807d6cf8782d47acbdfcfeed0b783ea1fad50ebca0ef6f3ed82079a32f30f2c5644f6c627f5acce7df655fd0e1e3930460a662dc3f1cc14beaaf40133ca178a8069bf47cdf90ccc74ff3c10e8de78dfa676c8afd09b564daff5982b1ff36a6f64c58ffd2fed40b7836a1fac504bc9c50fd6101c6fc97abc426e2b3700fc67911f3018cf33ac99d643e1edd198cf3176e07463da4fa0063bf8826be47bd53e7fe773965e345fded806db217eb1d8c78f29612b3f6923ea9603cbffb0663bf4949d7b38083c663b3022f68fceb7bb043f6118682a9ff8c02ec92bfcbe9fe7dba49f5c30d18fb636c9e2f2ce7ecf7144f2a6097e4bbe5c4ecf7140fcdc0b0b734018bfde03a784af3c53504cfb15f47dc0ffb0bbb8160ecbffc002fa95e58edc1d8bf1a4dc1163d2f36c1a8575495609c5f1a4aa6f3a134febd83e2ed2f376093faafa3e72fcc01f1f50b3c217ddd5660ac37ad63f00cfe5407cf69beef5230ea35c6026c60bfe55532e55b39d8a4eb6f73b0d8df20ee6f637fe04a32cdff03b043fd757b904cf9d9168c7ae7ed2299ce7b3692697fc898d8c2f99ddb128cf3b317f49f85fa6348f75f1a06d9afb604c37ff817b04dfa1c0ec10ee9bb4ef22ecd015d7fdd8047345eb5079e907e598e60d2d7b40363ffe3762598e2d5750e16e703d692297ffc128cf35768af897afb36108cfaee5c32d56b0f9269fe2e24f3f61731d880ff5125d37ed80558ac974c25d37ec09d64de7fe64132f73fea27d8a2f15732c9b4bea008a6f655a23fb1dfb28c24d3fe470d8c7ae1ed5132e95b2099cf8fa6e82fd4e3c32fc9b4bee3125b38ef7723ff641816d99b7d03dbe48fc22bd8a1f9f95a825d9adf4af28706eb1ede5eaf060fe97aaf133ca1fc5605237e6d8ee009e5bbd5198cf58b4efc1efb6fb71730f67bae66e025c5df8a09c6fecae020998fafd248a6f3ba909fd93b6f4f71025bb0af52329ddf9849e6cf533fc036e993924ba6f96726993f2fcec00ef57ff12e99e2c34a32ed7f0cc1f017d5bb649aef7cc9bc3f22f13c97fa4fc3f859388f5a6d25f3f69443c1d86f3b06e37c4be54ae6edd354c9bc7dd791643aefdc4aa67acf2b18e7f134f13dced325a4ef26d3379affc95f9826e2cb952a99c6f7153ca57835fd0463ff691108267fb579028b78c2001b34dee14532bf7f62814df88b4832d52f2ab085f59d0118eba3752899ecff2699eae307c9b43fb405431f9454329d2fbb97ccdb938cc02ee95b2adaebd2f8b590dfc279e448974ce3f12998e67b4d30ce074713c934ff403e0be72d2dba9fc5e607defeca014fc85f5413f094e2313b954cfea0114cfe467901233fd41792a99e6a49a6f527c198afd71bc9549fb9822dea8fba944cf9502799dad782b17e6d7592c9be6782495fea42321fdff8c7f77cbcb477b043fa1deb9229ff4904e37cc697641a7f0decd27828aa647abfc45032ade7b982495f13b25fcbc2fb0c944032d9cb93606abf5949a6f314cf60bc4fc00a24f3f6b79960d29f5a914cf11dfa53d87bf82999d6df303e16ceb755a4cf369b3fc8ff7660ec3f57de04933ff0f760ac5f665bc114df2b67c1a44f57156c507f5f1cc9b49ff3198cfdc69bab60aac7ac4f601be7fd22c1781fc95132ddaf95ccdbabd492b93e794f60e883229e87fd9ef959326fbf3a964cf9e00318fe5d9d4be6fda192fed916ce83a92f92a93dbe64ca8fd11f229e4c6f92f9f3938164ca1f4f82b1fe994ae6df871f60acf79a6bc9bc7f62f49785f3b1b75230d95775914cf30bfacfc279b22df90f47c413a621995f9f7be011f99b6d2b98e2136d021e4f683d63059e4cb83e7ae2fa19dd4f3b83e734df943118f581f22099cba33c8397549f592dc026d69b8f9279fb6f9f60e453d6156c537f5a63c9644f8160aa47695330fc8dee0aa6e7c5b964f28791648a6fe692297e580aa6fa6628da8bf8c3bc974cf9642118fa38954cf58f89649acf1692e93c27e9936361ffbdd149e6df2b9e609c1f7d96ccf549ad24d37974e887d0676721998f8fba924cf1fa9364b247713df687754f92e9fc672399ea45a23d581f35af92f9f7b9f81eef13885ac1181f4b32d5dfa10f16f6a3044bc974dee9158cfd3f892399fcbb2d993fff26fa6786fd3ba23f711ef146d7bbcc7e283f7b944ce7995ec0639aafab25784af671db0a9e52feb200cfc9fe320f2cec650f5e52beae7d49a6f319e2fe4bd457766083f453bf80b11fa878154cf6b2adc1585f37c4fde0af235530f251717fc45b9e90d7c17ca848a67add5530ad1f74a160aa8f76e279c8e7c34630f97f3b174cf2379a645abf247fe35a781f90ff2818f3c1443297571d49a67cfd4930cd87da1b58e8ff5630ece74b32cd1fa564aaef7982697dc87900633f73694ae6faa0be4aa6fd789a648aa724637fd25a32ed3f79924ceb3d3330f6f325ad64de1fd98364927f2598facbd42553fd3594ccafcf311e16cecbdf22c95c5e652a99de7f267e8ff3c9e1bb641a6f4732bf3efb008bfd812f92297eb32473794b31bec87fa30a2ccea3ee0493ff30f79269bfe23718f53e6b2099ea0377609c7f34be2453fc7b914cf91c1f2f63c0e6478a0fb6e019d58be207c1538aff8fe039e503712b99e6eb5c3297a750c04b1afff22618fb1922c1347fc73bc9b47f4630f2f9eda360b2efab2e98fcd1ea158cfd83452598f47f6b48e6cf8feec1a8b7a40bc1f05f3bc9bcffb61918f596f85d32d5e3447fbaa48ff94030f6ffdc24737bf267c416f6a7ac3f2453fe580bc67e99122cceeb9c24533d6b2299f4ad108cfce30773fd500cc9341f7792a9fe6b0ba6f5da6b2399ce372ec1d85f1d9d25f3efd59b60f89f3bc9bc3fd4a364f22f6f60ec97543792797fa8a960d8c74d32f9932918f61ed49269ff832d99e44d24f3f61a23c1d43f96fc1ef1fe1c8cf763448e645a3f16cfc3fe3d632899e2955832cdafd01f0be7d5ad4a32ad9f3792b9fcc64030ced3d792b93e9723c9b41feb02c6fe67732b99f68b7c4aa6faa3180f9c17f6499ffa032dc46bf098ec5d8f24d3fe08133ca1f530ed049e527eb7f50593ffb83c48a6fd570a7846f7d36b30e6fff25b32d5ab73c1145f28ef82299ed1e660d473b64f92a9def92698fcdd5a3cdf46fd24914cfbcd74c9b43e21e445fda611f7437cb1fe124cf65edcc02edd3f7225d3fb001e05d3fc5ebd108b7879bb93ccfbc72f05937e66a9605abf538e92493f56e021d99f6249a6fa5b2b98fc9f72914cedc3785a789f52f12698e42943c964ef17c9e40fe792697e1849e6f2648e60ac470660bc9f243b4aa6fd3fa1647ebda20826f9d24c32ef0ff55e32d5d7447f60fe2f9f25933f5a4aa6f8e62c18f9502299f40ffa61e1fd4b4a2899f6279492495ed19e29e297028cf795048d64dedef05530e29137c9e47fe4efb19f740cc6fed152134ced0f55c9fcfb488c17dedf74b9934cf64dfa3c326754ffab0cc1643f510ac67a78ba04633e77466083ecb309c026cdffa921998f476582b19fa7ba0aa6f93e5e0ba6fca6188051bf4b447bb1bf4aff00237ff60f92e9fd41f792e9bc7d2599e6f717c1d8cf247e8f7a5d160ba6fecf23c1b4bf21a0f86264e13c72f82499f2fd57c1f06727c954bfcec098df755b30d9ef7a2e98ecdf78974cf54cb447d47b3d5330e2cb0fc9b4df47dc0ffbd12ea9647a9fec1e2cde07f92e99f60b1c05239e3e4ba6f9df974cf9d74932ed9ffff17b2e5f70014f90ef288261df8664b25f5332bd6f0ae36be1fc4ef92499f22d4b3297ff593c0fefb7525dc9e4df3c30de5fa53a9229feb12553bc2ec66f46f2565f92c97f37609ca7b4df25d37e825a32adff89fba39eaafb92293fea24f3ebb7627cb13ebbfd944cfbadbf2453fe37154cf287a664d257d15e715e80fa6fcce673f2af117846f94076075e503d2188c1d88f9a9b82c91f2457c954cf38832df2279ba9647adfe70a8cfaecf62098e2ef6e2699ce27ed04533cb2d5c0d8efaa3c09a6fa46f12199ec5d3c0feba51dcd9f63517f5dbd0886bd3f4be6d76f7f30d59b62c164afde5432d5271f2453bdf0118c7abd77124ced4f1ac914afae2553bd5edc0ff3b9f32498ec6d1308a6f66c55c9341fdd83313f9ba23da8ef46a564dabf664aa6fd21f27b8a37e291643abfe249a6f9ce174cfb13a2028cf78b25b9647a1fd4a364f20fdf92c97f0c25d37a512599d607a03f22bf375ac994ffa49229ff78944cf94a2618fe48fe1ef59e4632bd3f270163becf2ac994bf8beb71fe4b0d2453bd27964cf552d13fa807da2f9269ff612499e627d13ed40f424330b55f13d763bfc6ed4332c50f37c1f0f78a64daff3d964cfb43c578637daf7a138cfd39429f719e6745fa30314df21f590ec6fedd32134cfbb10c5d30f98bcb8b64da2f3c01dbd87fbc174cf5c92001e37c4d25eee760fff1b7605a0fc8b792e9fc81b8bf43f149740263ff68fe2a989eb722fb9c8878201849a6f75f9e25d3f37cc974fee15532bdaf752898ecdd0904d37a475080512faf7e30e9432e18e7f56e82914f5482c91e0bf13ce4ff7e2698c627fb924cebcfe2f7d8ff1b3e80719eaa934cfaee3992491e717ff80f6f2699f22ff13dcecfa753c9e4bf0e92293f394aa6fd139660b2cfc8904cf9df4230e68b4a32add78bf1c0feda740ec6fbebcab3648a8f2792c95fd492299e1848a67ccd164cf25b2d58f887ab64f2379d64de3fea4132bd6f4efc7e8e7827944cfb7f1e2553bd4f134cfa6c799269ffb6781eea8df14432b57f2718ebe591645a2f8b05231f15bfc77e0f652699e229f13cbc7faa9a4ba6f361427fb03f5013fa8cf5e2c495ccbfd73dc924af180fec0fd33e24737922f17c9c6f6cc91ea626f69b5e13f082fccfe64d32d547bfc0385f565ec0886fba1cecd07a663394ccfb237b05633d627b144cf6779949a6f75fd682c93f06349f4dc5fa433d154cfaace982697d721b4aa6f3c11918f585742299fce5bd64aa67958229be5ac560ac27ac12c178bfd79b64da0ff1e37b7adf95fc3dcef70592a95ebb174cfe3a10cf47fda01c08c67e1b5f32bdcfb0134cfde12a92493ed17f585fc81f25d378dc49a6f8e253308d57249e3f417c7a904cfbcd7e30c5d382b11e982592797f24df82b1de954ba67aa6907f4af69baec138af6c8d24533d692f99ea733bc1e4ff3c0b2cde37be944cfe712499f2b1b964b2675732c52bd0670bfb45d54832e58fba64da0fb301e3fd8d4a2499d67f857ee0fc72f82d99be5f81713e3e194aa6fd49e27e588fb89ec1884fae13c9d4ffa27fb0bff0229e67537fae481f66e612fb2d776083ec3debc026eaa53618f18a3b0323fe580f04d3f5c98b64da7f63825df217852e99ce77907c33113f6c4dc134df6f1f24d37c9982b17ee04f05537b9a77c9148f88dfa3deb07a92ccfb7f73168cf365778229be48bf25537d19f28bf501e55e309d4fc94f92c97fcec158cf2b12c1e41fbb4fc9b43e3d104cf3f7f6158cf87ebb170cffe448267942c1e47fba05187f1f455049a6f5614330f4ff0d8cf3b88ab83fde3770d94ba6fafc12bca0f6a557c1c80f6dc9644fb964aa7f1492a99eb1934cf3f718bc44fd632199f2ab67c914bfd782518f16e389f78346a23dd8bfa58c25d379ba4030c95b5f2453fc5c824deacfec2299f6eb6c25d37ae74630e2b94632ad170bf9b13fb87b964cf514713df61bd4aa643a9f0f7bb31cecbf10fa28f6e3f89269bd83e2adb9399f52bd33032fa6fcfef9086cd07e8d95f81eeb1b97a964b2bf0dd8a2f958ff02dbb41fbbbb825d9a3f2eb5608a3fe28560caafb6141fcd45fdb11a83b11e180f05d37e5c5f114cfe669d8051ef6f3dc1a40fab108cf3d9e55a30ce3b1a60d4d78bab649a5fe5f7645f978364dededbb360f247452899ea616730d6e7d6779269fdfb4330f9bbd4148cf8e7058cf5b8e44932bdffe25e30f6835c24d3f9d1b964b27f713decdd16ed9b937fd2f792a99ed2082679a247b0380f33964cf3ab18af05c52f57d1df381f5baf2453bcff0046fcacfe60daaf6a4aa6f9ed4b30ce7fce25d3fedd1918f65f8af1c37e6d4f954cf9cf5a32c927fa17fbede254326faf22aec77c1bd582a9fd971d58ecef3524d3fe5ea1bfd84f97d1f82ec47a83be124cf5c8ca07dba4efbab8de9df2dffba44f0b51afeb5cc1747d32154cf61eecc043ccf74f9269ffd3098cf7495c1e25d3f9c14a30ad9f281f92693de2001ee3bcf34430e94f71114cfe259883f17ef6b52599de2f36144cfaa23c4aa6fafd188cfa79d60a267de832c1345f1786649a3f7e30cd97a2bdc86ff55232c54fb9648a6fc4f367e44fbaa1649a5f669269ffb7f87e4ef6915f2453beaf4ba6f9443c1feb655a2c99e47b944cfb532493ff6bef25d3f86ec1e2bc532318ef1712fa82f3cdc55e32b5ff1b0c7b5acd25d3df9fa04ba67ac25e32bd0f44b4cfc0f95ad13f787f759c08c6fb8f34c9141f6e2453fee80b46fe22fac7c2fbafef24933f17fa8efdf9590dc6fb8d4a8a079626ceb3d513b04bfa5a527cb664f645eb65067848f359fd8369bfec063cc27ae45532d5e31f25f3f15c3d83315f5d12c9544f740553fe1e6592a93f3dc158bfb88127145ffb9560b2873a96cce5d75f25537ce90ba6fa62f283a95e2ae49bd2f82b0f82c93ef385645a6f17ed453d39984aa6fac04c32fdfd5607c1a42ff14a30cdb7b74232e5a76f60e483fe5132cdafb960c4fb5f60c4aba52218ebaf7b30d69fb6e27b9c1f0ceec1d82f962b92c95f1d24537da7148cf93d05239f534f92e9bc8bb81fcefb1547c9544fabc1383fe68af1c67e92f807d3fe43213ff6af7662fcb19fdaa37cc410f5ebfc5e30cd1f6b07ecd2f85a347e06332faa8f1cc0d0efdb17784cf6e91a82499ff44ff004eb318f92693fdebd649adf5f05937efa67c1347fe91618e7bb6e7782112faa60ac8736a1601a8fac00a31ee98c05e37d155bc1347ff8aa647a1fc009bca0f1f21682c99f9ae2fe0b6acf360763fd62bb168cfcb0148cf7790879f1be9ad4954cf53cd17fd8bfe49f24533db1164cfdbd7d07e33cd346fc1efb17b789643a4f300423bf303760bcdfec42f669b27885ee47f38169e1bc977e124cf18d3706e3fd11fa163c22fdda9482a7b43e7805c3ff058660ba9f2b9e87f364d14632d5fb4792e9ef37fe02e33cd926028bf364efe039c9b712f747fdd9ad24d3f58231fee58b601affdb9b648a6f7230dedfe12d25d3fa760a467d3817f218145fd99f9269bda1924cefdf93df23fe7e009b349f98623c2c1a5ffb2298ee97d8609c3f32e6609c3f8b2cc9646f0bc914cf3f4aa6786607c6fe958ee20f8bcdafb43f81e20b165e93fe5c3e25d37e30f13dea3ddd093cc27ede2d18f5983804e3fd1d9a25989ed7168269ff61fa089e223f9e8167d47f862699d6f39e25d3fe68152ce2b70318e7c9ec67c9f4fe12138cf70f252918f1932b9e67507caf08f9f1be9938069b648fc15e308dbf32108cf7df88e7637f627c150cff7a0163ff42f000c6f99c88ec9b4d37a867d1fc62b3f1a3fd3c743f5b8c5ff102463cb2da82117fb4df9269bde12498ec510f25d3fef01c8cfcb8b425d37eaa5232bd5f2506235ed85a9269bda4154ce31d89f6cef17ea8037841f76b447b17d84fb6012fa9fd6b211fea49978b608a4f0c156c423f3bc9b49f3602c31e6f7bc1d0bf4a32c50fe44f6c1bfb3be22918e7e93a6287d907adb70ec063eacfd51b784afdb3d1c0c85f8a5232cd97afe0398ddf652d99fcf75130e5879d09c67c961482c97eae7bb049f74b3ac9349e86649a4f2692b93cb978be8df749b88229be509660eca7f39f24d3f922713dd6afaedf8269bcd690c7c6f9d755001e52bc5b533ceb5a63d29fab2199ce63edc1139a9f82083c25f9f5068cf745dd2cf082c6238d25d3fb1d378229bf503ec178dfce6a0946fce9bd0aa6fe5ccf04e37d0af27aca77ac1bd8a2e747df9229fe2dc136f98ffc4530e9f34a934cf9f10fa6e78be739387f48fde9daa8f7273c3e310716f67b260f9269ffde1318efefb91e24537dcd06e3fd79f6156ca0deb1904cf6a080d1fe6a2199e67b5f303d4fbb801dd8fb0a8cf8f9a611db78ff5dac8211df745f60d413133e7e2c389be17ccc183c27ff97459279ffac4b30de27947e0826f94c4532bd7f5d032fa9fd6d2a784af58e21d8a0f9e1aa48a6f53f5b30d58ffd6730de5f94ad89ed01d9ef86eb2b0b2eb0feac6fc04b92af7525d3fbcd8f6093fccde64532d9cb4d30c57fe1128cfd33eb77c1a41feb028cf7355a1f82e9f9ee1cec62ffea9b60f227892918e785f0bd8dfdafe9b3601a4f270463fda81980f17ea59adbbf3966fd41ef472dc14bf2075b1b6c60fdec4132d50f0bc9944f1cc126c693dad7bf5e9ff2075c6f63bd6b45fd33b1e6549fb8adc0580fdc7682c97fdd5ab035a5f74309c67961e50bec523c1de2f736eaf7f11c3ca4feaba8bfa6d664467fffdc080c7f53b492a97e6f08a6f686776013fab4964cf69982717ed224ff30b5b15fe81608c6fbd3ce60c48b2d8dd78cdd8ff2eb5430c5839b5730f2dff60086be74a4af33d6ff148fdd8391ff6a74bf390b30693de808b6917f64c436ce8fdf1230f6bfb7345e0b6b3a27fbe9c0f319bdaf8bfcc782a5f7e43f0f60cc4705f99f256b3fedf71c826d92ef3625b627349f68dcdf9b2c9f9b927f237d3458ffd1fc5b8327f007241f530f1aaf6b00467cad51ffb2f8674efd41fed5b6711ed0e4fac192cf39b57733022fe97ecf977feda32abf7d8c9f3e26ffa7827fa74fcf0afb9da5daaac3fe58ff6a0be8f3df21cb2f72b9ecf3bb5c0afe9b90afff77f7df5116d62247f5d81ffad87ddba87590cbfd87bfb3f1f9779605f20899fa6be8cfffb79fff167b71e9f393743ffadc1663f4e33aa96fbdedf8eccf3f18b9ffff65e16dfbc90e6009240d1fa9bf2b3bc9439ee0df4d1661eb3f64f9313a3f24f3e4e717cbfa7791e5379fecfefa91d758f05a8e94457a8a7f2b590235542335561335553335570b364ea55aa917b5669f86e951ab76ec7365b2de544dd5d99f15ff9dc67eb1fe379365a3aed827652391a85bf6b963d2ecd43dfbec982c07464726dd91fdfb4e3da9f74cce7bf5817d0c76e53ff4daff5b6479e43dfdc446e699fddb597d515fb94ebda9efea87faa906ec9a9449f8c524f85607ea501da96375a24ed5993a67d2fc1bc9c25a7a5637ec9f91ba607f02d8fd92c9f2cafe6929aafaa4284cc7be15431d2ba662b18fad380af31a8aa7f8ff3d92fcf7cc954aa0844aa4c44aa2a44aa6e44ccf5ca63d2dfbf4b6622a059b45064aa954ca45a9954669954eb92a3745537465a5acffe8b5ff37cab251b6ca9db253cf8aa2ec95036bf1513929f7ca83f2a83c29cfca5979515e9537e55df9503e952ff6dfbf9581325446ca589928d37f23596c65a6cc9505d3b393b26413cd83f261288661b044c0b00dc7700dcff08dc0088dc8888dc4488dccc88dc2288dcab8a87746fddf23c99f9345b58ca6ff23a390df6677a3353ae36adc0ccdd08d95b13636c6d6b83376c69efd391847e364dcb3cf897d8e8c1fd8e7d178329e8db3f162bc1a6fc6bbf1c1b4b0cf02685e757f9b797f9aadfe999ff8af6561527c1a5feccfb7313086c6c818315fd4186363624c8d194b9916c6b2370ad3304dd3326de3683aa68b8fc73ebe19b04f684666c465eaa53a9a31936a6726666a66666e16666956e6c5accdc66ccdcebc9a375333757365aecdcd2f33b1f2eb1cfcd764311a736bde3169becd9db9e7b21ccc8379344fe6bdf9603e9a4fe6b379365fcc57f3cd7c373fcc4ff38b7dbecd8139c467648ed967c23e63736aceccb9b960992a3334e3de322cd3b22cdb722cd7f22cdf0aacd08aacd84aacd4caacdc2aac12b9dc2f91c5ffaa2c56655dac4b3f2e566d0cad5a3d5b8dd55a9d75b56e9666e9d6ca5a5b1bd6d3f7ccd96ead3bd6522689b5b3f61677bfd6019f2393666a9dac7beb817d1ead27ebd93ab351da592fd6abf566bd5b1fd6274b98bf5884b0601e3d61b3e9c0faeea3cf1fd1d1bfa2634cb31a8bfe82f001fff74a89aca135b2c6d6c49a5a336b6e2d7acdb196cc74fa4a9ed18f85b5b34d48f2439643bf4c614e6ddb766cd77ab03ddbb7033bb42326cfc178b4633bb1533bb37336abda766197ea935dd997de92fecce74fc932307756cdc6646055aa67d77663b776675fed9badd9ba71303fec95bdb6376c249ef9676fed9924625414662bcc5e602bf766681bf6d6beb377f6de3eb0cfde3eda27fb9e8debde7eb01fed27fbd93eb319d7b35fec57656fbfb1d1b07efffcafc9f27cb16a66274cb78cc6f8b4df992c1ff6a7fd657fdb037bc8faf3c47a7864bbe6dc1edb137b6a2db924bb7e64fab161ff9cb1f6ce85fd9b91bdb0972c485698ddcc1dc3311d662c8eed384cd2bde33a9ee33b8113b218f5dd89545df17fcdecfe155954d7183ab113333bb1edda499cd4c9ec2f27778a5e0ea7640ff0ed3d6b55653d3b17361acf4cc706cc6216dc6ed8ff3b356b6be3b44ca6b9d3998173756e8e66f7938feeac9cb5b3b1b7ecf78eb365d21c8d9d73e7ec9cbd73708ecec9b9771e7ec9107ecb7a7eb6a03f234b2f09f3c683fe7ecea3f3e43c3b67e7c58cadb33db1ced6b33d6656cc3ece2b6b5dc5dab5c0a7f765ec63cfe9e374f8bc39efbd24f6d20e9d0f66fd47e7d3f9ea7fe954ce379366dffff5f6cec8e9ff5acca933b3eb9fe4f8576599ab9db3b05f9c25fba1e21a6ce2b08c23f34accd3bab6ebb8aebd702a73e17ab66b1f5d9ff9a8931b981fccdacfaca5f76ec86c2ae673e6d18ddcd84d98bde0e3746e6a7acc73b02b594fbcd93336be67377373b7704bb7722f6e6d176e63356e6b358ae67656f3afe8987a70afaaeddeecd6d55cdd5db96b3626cfeec6dd9a43f7ceddb97b3622dbde86dd837bb4576e6031ed331df7e4debb0feea3fbe43e1b817b765fdc472195fbeabeb9efec5707f7c3f9703fdd2ff7db1db84377c474f1c0fe7dec4edca93b73e7eec25daabd2f6091b8a7aa81f70fbdda9f91c533d8f46d79b6e778ae937b9e71b2179eef055ec8e4601fdbf0222ff612e6030eb6d1eb8c977a99977b85577a9577f16aaff15aaff3aedecdd33cdd5b796b36e7c7c6c9db785befce7a70471ebb0b1b5d9dfd3ff36fde8e59cec1db7b07efe89dbc7bb5f01e58467af31ebcc71f5af5bb1ff853b23c79cfded97bf15ebd37a730637362dbde3bd32f2e099368cbe6f229b39ae7de76bd0fefd3fbf2bebd8137f446ded89b78536fe6cdbd85b76441d7a3aff8866ffa966ffb8e71f45ddfb31e7c9ff9e8ad6df8811ff663e547ee8069e4831ffb899ffa198bd6be51bffd523c9189fe75599e2f7eee177ee957fec5af0d6603e6d46f7a49fc967d3aff6acead27ffd6cf77bee6ebfeca5ffb1b7febdff93b7fef1ffca37f62f966a2bef8f78aea3ff88ffe93ffec9ffd17ffd57ff3df8da3bdf03ffc4fff8bf9f485bd30c74ee57ffb037fe88f8cbd3ff627fed49ff9737fa1382c27fd6679f70f597ea97dfc99d8d25f066aa004060b112da65f6aff97c0f7fae5b7811d38fe3570cd0fe31478811f04411844411c24411a64411e14411954c14509839a7d1afb3d68838ee59af3e06a3f07b7400bf460c5fc48ef0d9560ddeb99ad30d906f6c27a0e36ecaedbe02ed8057ba50e0e4a191c8353708f0af54f35ab3f2d8b1d3c048fc153f01c9ccdd829ad73f012bcf6da15bc05ef81137c049fccf38c83afe03b1804c360148c8309fb330d66c19c49b47016c1325443253442d3188416fbc39c71e8865ee88741188651c86cc73a8709f3cb4698f29881c50f61d6fbfc300f8bb00cabf012d661e32fd421d3b41fb2387f94e5e77af6cf63d25f1db661175ec39b19875aa8b3bbafac636f27e13a5c33795e8c7b2f0d37e136bc0b77e13e3c84c7f014de870fe163f8143e8767f52d7c095fc337ab08dfc38ff033fc62d2982c22f6d97ff90e07e1301c8563e3184ed82cb40dd6e1943d63e6ee99fd7c9b53f6dfe7e1225c466aa428456444e68fcacdaf5a46b288ff862c28f1d4c8525fd5d7c88e1c7f19b9e673e41987c8376751c02375a61351c8e2f7cf88e524511c25511a65c62dca8347ab65f369cafe3c4645f01895aa1255d125aaa3266a5910d345d7e8166966678ccc75d4467ab48ad6d126da4677c629da452c82f0039ef778d68ecdb40bf6bc7d74888ed129ba77d2e8217aecefcdabed866af4d1eeaff6f2932c068fb043b77516ca2e7a8a9ea373f4629ea357f6a437e6750d16a79ca37773c2e6e8aad7eae823fa8cbea2ef68a0ce153f1a2aea8f2a2c7f9e1b8da27134096d2b8ca6d1cc8aa379b48896b11a2b56111b319bac629b85166eccbc3d9f73962c7f93b29843e33ef6e3200ea3fb388ae3f081f554cadbcafc5a1f25fe2c0b7ff68f7131d4f8f9e22cd4f73889d3388bf3b888cbb86277bcb0f87111d7d6dedd5b4f7c2639b959dcc46ddcc557ff515dfdb4f662cb3bbaca5875e25bacc5ba3f8b57f13adec4dbf82edec57ba5890fea323ec6a7f83e7e881fe327e3143fb3d866c9bc7380b86e689de373fc120ce2d76011bfc5effd88736b3055a38fdeff992c0ad34726cb6b9cb8adba8a3f4c23fe649db7641ec6b09ee3da665ed3fc0c33f6dcaff83b1ec4c378a456eaca7e51ee94713c862c3c1eecff9dfdb7493c55f57816cfe345bc4c54e3c17e4894c448ccc44aecc449dcc44bfc24484263efde9b3e8bd8d887e7a42c3b65f3d6d17c4da2244e92244db2a84872b1baf07765b1c886f8155b36bbb2fe65914fa2b8499194e69b71f26fd69e8dc9d9b998dff6c13ad953e39054c925a99326d6d5f7beea9db4ccca52f40d55c1d97d95bb385332bb4abae49adc12cd38252ceb4956c93ad924dbe42eba26bb641f1c9243724cd82c657a8ec272014364d94c9b4b2f4dee9387e4d158264f09b34ab146d2e722ff4c96e499f5e198e50e2bf6efe7e4257935dfad3e3f3f276f56ff8afa7df26ece8dfb709c7c249fc957f29d0c143d192a8b64c4abe3bdc7b4fbac8dc9c264b2df93713231de9269324be6c63159d8c76469c6a99a2aa9919aa995daa9e3dfa76eeaa5bef1603a2cbfe1b2f45910cb54b769601cd3308dd2384dd294cbc2d76dfa7cc4180aaff6932c96b0fe3453466e6b97cc8e9d344f8bb4343fd22a4c98f75a5afdfe8687f4621becee75daa46ddaa5d7d451f4a04b6fa996ea91c9fd3f978549c3644957e93adda4dbf42eddb15fedd3837d4c8fe9c9d8a7f7e943fa18fae953642b7a344c9fd373fa92bed2c8902c2ca7db4681719fbea5efe947fa997ef5feb197a56f7f9f5bfd2acb8f91e17a78607dbb5412ff2139a7dfce9069eb673ae86da5f7c54ee5fa696f8f553a4ac7e9249da6b3a4b50b65c3f42c5177fe23ef31361a7d0edad724d379ba4897999a29c63163f971b4efb3e3ccecb3e2649559999d39ea57ea0475e6665ee66781e9fa81a3a06ab0eb675096e1c5599845599c25ce23b3172e8b6af5b9d52fb2889a9add3f99d14efd4a064ccf952c553eb2cc74cc2fe61b077dcecbf477613d982316e37efaeb2ccf8aaccc2a61e7e45b98b34db24b56678d5dc763f53b6bb32ebb662c62f343d6df6ff6c2fd66de9c652c99661ce3a74ccf56d93adb306bd3b36d76e74efa5999c53363a603cf76bfcd8445369691edb23d93e5901db313d31d85db7491ddff268bf28b2ca67a973d3032b24743c99eb82ccc37f67d642ebcc4661146f69c9db397ec357bcbde852c1855577d4bdaec23fb8c9e93419a655fd97736c8d8e866a36cec8eb24936355da7cc66d9bcf7ebacbf17d93257734509552b377233b7723b77d8377d3d6dc29edad74398b7cedddccbfdec900779a828ff4496be024a7dabf8bd36f63edacc23c330ee982cbd97efed70c024619219f7799c27fe364ff32c3c30597eac4172bf95e779919779a556f925aff3266f8d63dee5d75eb7dc613f1ef9cdfdeeb3e25cb316f153aee7ab7cad9eed32dfe4dbfcced67396c1b09879c8729a4bafd9feb7719f29f93e3fe4c73cc88e4c9b1392c52afe812cbd0f559209d332db2ed5263f1926f32baed05ca6678eed5877ecbfbce6f7fe5dfe104cf347a3fd690d92d97afe943f671725cecff94bfe9abfe5ef7dd4937ff49909af719cddaf6cca73628dcd8871fe997fe5dff9404d9cc833f3613ecac7f1579ff1997dbc4c51b4cfee30c9a7f92cc9988e1d59a699f47e377c0bdffe200bb75792259fab7b854d65ea77be302c63cfd2fb1dd5bc481673943bf9b2500b8545f5b3e8814547b6dcabc0575793b1fa919f0ba33059b7d9ac557d2cbfe8f312ebaeb7e4c2e96b1785cb62ad53e1157e111461112923d52ee22229d22233f67d5ec365611ac6aecdd98cb92f8aa22caa3c2459faf6b398f5f597f9e5375958c6b34f6fcc62be8b0b7be4ce74a97227646177ae8ba6688b2e288a6b714bf25f7684303d53fc645268855eac8ab5710835e7b597a5d8b06cabaf6a7ef4d5be60cd243916dbe2aed815fbe2a0d8c5317b284ec57df1503c16cc3efa1a279764614e0b268f7128cec54bf15abcfd248b1aaa7f57164fcab22bde59fe742a3ed894b5efa33c5420875c9645f1597c15dfc5a01806398ba2c90bffd8555114a3625c4c8a692f4931ebd72c989ea8c5bc8f467b5b6677e03163b12cd5ecbb544287c540d7d250c2d22cadd22e9dd2354ebc22c2ae36c7f6a1f498cdc6a55f06e1ae64290dd731f7efc822d654c40cf3adb665c472b053191b2ecbef852cfb5e16f3cb3a9749999659996749745f163f564a7824669465599597b22e9b5e92b2cd34661b565f3b6371dc985bb4e10ffaaca7ecca6b79b3be4acd0a4a9d8d67c4a45995eb72536e992cbabdeda326368e5bebbecf64cabb7257ee7b591425cd7a6d28b552fb45961fd13ef773ea8dcd103b75c56439183e1bebc81c5b7d3d2cb0674e63cfcb63792aefcb87f2b17c6271ce86e527a398c594ca9d5d97cfe5b97c295fcbb7f29d79d12eef32adafee9bb3bebec13f337b5f7eb079bc2c3fcbaff2bb1c985d392c47e5b89c94d3c42d67e5bc5c944be3c45c7d156a7c4c0f665f1939564a655466d06746a7e0d4ef2ab2aadf62fedefb3059d8b7663f36c8d834bbaa2c26cbbd19b2deec97483a264b6b06c6a1b22bc79bc5e3a00996e5c4dc562e538ba86236cfa29545e5574115329fca66bb3ea736471513d73a313946fd9a4515dbdb2aa9d22aabf2aaa84a2bacaaea52d55553b5556745c1b1ba062b362e5ba7a355b57ebda3aff254b74aabf42467b21c83a36ad9f51f641151a5cf6571d488e9e246bd315559556b264bc4662c268b193269f64c96a37bf65a6fae2e2387e9eb5bb5a9b6d55db5abf6cab53a54c7ea54f575e17be6c717d681c5d5233e26a3fe2ebd3d570f4c96c7eaa97af646d5b97ab1aaead5dc556fd57bf5517d565ff128afabef5e966ac07ac2e5f5cf678bddb11a56a36a9ce4ce23c6c5339adf627e4bca6270efba60d1ee539ac5a36a524db98e912c51af654c965335f33a8f656bca3c34ccae9a87af9eaac6ac3f17d5f2a26637f7f5a25cb81fb615f38349d17f26b406c3ee7570377d7e75312fd6c5be38e1cbc5bd78179f8d897f092e6134b8449798c9d2b91fccbadefb159cde673059946a7449823e47f6d9c7fea32ca859283c96225912f549bdbfa4ec9e593fc6fdfa9c6df523d4af3d18a774e75d2fb9925e8ad0c8eefbbcfd525eaacbe5525f9a4b6b9c2edde56a6fcdd1e5165f98bd93244764f10773e445d68e5da55df4cbeab2b6c2cbe6b2bddc5d7655a7b697fde57039ba2fbd2c173633b1d8cde27fd5d684fde2fef27079e4b2a0adfd5add3f95256071f24d29c2faf27479eeb585d61bfb95a07ecd81e9d8a377f35545b3df7975c88ca6feec72bebc5c5ecdc4383afae58daf136d8235f75dbd7e8db92c7c3d96f5f196c5dd5333bebc5f3e2e9f97afcb777cbcf06a13d388e16578195dc66c869ddb6c66cd466c967db5ee7adbbf4c2ed3cb8ccba2f0bcc2fe5d16392f4096545373b5cdcf97f9657159f6eb90bdcdb2d8b85fd50accc08d8c83a7298f8a1fb4c620fca8d55a49b6b5519bc98ac9f9565bb56def1cc38bfaf99ecd8d336ef74cc7b8341e9b3146e6dcdef82cdeac9ddaadbddaaf83484b46e9ad0eeba88eeb84e5ca9fcce3796c6e9db008f4c9dd32590e755a67756e325990875bfd0aeaeff9cbcfb2287eaa2b6e5dd4a5f25557c68149c0bc0fb3dfa8978569716cc69eee2b6aa9cc422bfc8caa9a4590ec7f0d6b5beb7eb84347cdaf2c63af9cd73063f67faa22f6ebdeaff7d27875c746f9cbfc626d5cd6d7fa566bb55eafea35d36ca77c8af27a536fcdd8b9b23cdceb6318d6239bdec2eabb7a57efcb3d932515759e3fe695d8112074cc55efd44370523ae5b13e184cb3597e7f6fdbbc12cfda581f599b4ff57dfde0b6a1556d13b77eac9fea67e3549feb17a65b8bfab59f159cd728b02d1691ceeb37bfb1b7fe376fd994b220ca89acbdfb5abfd71ff56738a8bfeaef7a500fcba01e992ed3c27db17077aec3f29881cb324b63578feb493de5b2507ef20f7264f6a797a59ffb13f6ff0d9bfda7f5ac9ed70b9657b2fc8bc52e5b7b592f9d779bcdc98dda288de13f5a35f3ca1f8dd958c64363db47f6d9374e3f438693be6ed3fbb2c665ff34a2d0def09a9af1cb1ae0d074eb5be3357e1334a1f3d4444ddc244dcafae291e54977eeaec9ac2dfb158b429bbc299ab2a9b8bdd09ca8f42b763fcb42732397c5e4b364aa8cd2cc99c77a7369eaa6316377c3eefb7039352d0b8359d6e186c6aee99a6b738badd0b48a466b74fbc18c9b557aecc7c57c6fd64cdfc76c2c3efa5cbdd9345bebdcdcb9dbbe8283d53fac9c9b5ebfb3a4d935fbe6604d9a63736aee9b0726c363f3d43c3799bbeb6be64c2fe3e6dcbc34afcd9b948559c51f65a1d95ecaa2f1959bb5faa138cd7bf3c1a22ac7ff609e89d973bfa6686f9b4fe3e0dbcd57f31dbae167ad3483669828d60b7bde283359ae356bc66c961b46611f41369366dacc9ab971b296eeb6e1e3815566167d9b9ed3354b63efad5bb5555aa3355bcbe8ebd581396efb15c45d9f2b87ba71689dd66dbdd6ef63181e7719aadfaf09ff365752a5cfa4bdc2fdfa937a8bc76de03dc65d1b1afd4afdb658703fbbed6dba8d8c531bb7499b865ef5de666d9e9fdaa22ddbcad8370fed85595585fce4beaddba66ddbaebd5e5876dfded8bcf3ddd70ee4eabfefed5aaddf1de36baddeaeda755bb35f6dda6df0dede056f5ec89eb7734a63d7eedb437b6c4f52163f38fd41161bd97abff39945bc2c951e313ddbe5b9a2b7f7ed43fbc8b4f7686ffa9d05b5d53ef55adf326fdf9edb97f6d518861f4e5c44ed5bb269df59ccb3cf3b7bc9645ef5f949fbd17eb65fed773b6887eda865b3068b697aed123b19f67e906bf6b69db0acf8d44edb593b6751cb397875ed76d12e3bb59fdbeace38754a67746667c571922779af472c8e39fe4116e75759d84c99a94967770e93e6dab99d67192cd770d89cb063be56ef7c7b5b9f7d3753baa00bbba8da767197746997b1b0b8e8ca7e6dc8db75157bfea5abbbc6df756dd775d7eed6699ddeadfaac8e723b5ec95b326b687b8fe2fb4e65dce75db7ee36eeaedb76776c02d875fbe6397aef0eddb13b75f7dd43f7f8ab2cbfc563b40fdae2fbb87b59fabdb76ef7d43de7cfddb97be95e6bc738b9ae7de8ff1a4166c38eb3eddeba77964f9cba8feeb3fbeabe9d85fad80dba6137eac6d19d195b0b33f6b56ed24dbb5937ef16ddf2aa5e95ab71358d9dfbca7763f9bd1ce6d00ffa99fd6ad97bc7bada4cbe73b7bb322bb18ee1cadd5d5deffdea3109dfaffe35b886d7280fa302b66ffe1d1d13eb0b72bf196a7fdcef5de36b52b2d65d53ebe19ab119ef6c9dddcf7eb5f79ab3ff5a5ccb6bc5e29897ebe55a5bfeb5b9b6d7ee7acd27d7db55bb321d5533b30bdf8da69c5c57d7f57573dde6937efe655aa8f4750ce623a2be06c6f7638dd87c74ecfd38d515ade7de5aaa8171bcde5d77d7bdda3847b5edab2c5993353c07367f9c07f8afd7f89ca7ebe17a8cd953afa7eb3d3dddbf998b6641d1eef5e1fa787dba3e5fcfd797eb6bad3069deaeefd78febe7f5ebfa5d75d74139bc0eafa3eb987d26d7e975769d7b6bd60b8bcccccceb92dba2f5f327f2dd7d73c7fc1c27ebcc52c3a79b7263f955348c4c36f3b9aa6dbf33591cbebef31764b99937eb66df1cd6379ecb66877edf8bad140b2fb9b139d0b8f7b51b0b346f8152ddc25b748bd5db2db9a5b7ec96df8a68d025e15755df4a7377ab6e97f0e3c626c65b5bac6e9db1ef772df0fd16d6af1f5eafb0d86cc4246aee7236b3dcaeb7db4d4bc6d133cb2d44fefb87ddf3ffb52ce6e34dbfad6eeb86c5860d1b0d663515f3f8ecff6d8fc5eecc9fe593dbe6b6bdddd5a5fa62d7cae2b65386b7fdeda0d4ea58dd869f55773bde4eb7fbcbddede1f6787bba3ddfce51623f180fb71733643e7af24759983454afa4fbbfdede54f7f67efb48068a226ac97f7d7d3f2a6e9fb7afdbf76dc02b565f2cb35c58776c86d89a73162f6d6e43e3741bddc6b7c96d9abab759eadce6f1241ef77bf56f8bc80a5fa2eab6d4d4a8d394a85202f5ac199aa9599aadb1b16e5acdedade4e78fbbef3396c82759cc58f3345f0bb4508bf242d1d20ce3f287d3597fc25e1eb5584bb454cbfad981dd7b617e7a119385f624cdedad96f733a75668a5566917ad564325615ed0b65fe289b25322add15aadd3aedacdf84c1dd573979aa6e9da4a5b6b1b7ba16da99af0ebc8b03f2a8bb1ad7667dada9db653bba0b9bddbef2c7f37642dcfa1f8f22fc8926a7beda01db59376af3db008efce9cfa1f2c3bda71eb6451633568f92e43ed517bd29eb5b3f6a2bd46b935d2de8c85f61e4fb40f36269f2c216e94246ccb2767e999da97f6ad0d3436a6edeeefd98bf5dcee2c35f2b59136d6260a8bd955d72eed525db37111f562ef2fcbf2a84db59936d716da52578d7da8318f79673d9993b86e6fecb363518056b6bac26c79a71bbad92a9dab5bc64db77527327457c97596ee844e7fe622ce597e32d4033dd4233dd6133dedc7e0d74f98f5b2447e2f95bbd7333dcfebb2d20bf6fbfe0c84266b797c86ff2b3a16157aa957fa45aff5466ff5aedf11c3f2de39af8f322fa45ffb798faffbfaa6ebbe66817ed3355dd757fa5adfe85bfdcef850bff59dbe77c6d5413fe847fda4dfeb0ffaa3fe14bd07aece722db28dde4ef86e0bf3e78fe9e8e764adbfe8af4aa36ead86cdca34abf4f6eff075c43fbd8724c9f537fdbdb8ea1ffaa7fea57febcc07588affed6ed3ca56a3f7beea637afd3a561f4733895c33d687fa888dd0589fe8537da6cff585be5ca92b6565accc95e5eddd3c7ded778d38d5ca5e39b6e1eec90f0b0ff68b2cae7170dc95bbf2567e3c535f56415f310a4e2cdeea57df6a5a7bfb73b2048fab701505b355bc4a56e92a5be5ed78555807166b6efa5ccb3afe248bc9b28265dee5ceed8565b4b755b9aa5697555dcd568d3e5ab5b1c7f7c23129dcddaaeb76abab395e752c5bbbe3f66e626ef955166f7533e3b261f9d270a5b1f178e335567efeafaf2afd9571311f57fa6ab55a6bb362b8daacb6abbbcbc76ad75767d2a05f79b0b67d0ecf64796372ec983c0adfc570cff7819ef85efea3d8cf6bdcbbdf76e87ff8cd6abf3aac8ead1d7cb84edffa7e9e679aa6b63b6627bfcae2af4eab7b9643ad570fcdfbea919fce727f3a052c4f69fca971795a3dafceab176db67ad5ebd5dbea7df5b1fa8cbff26ef595f615a31fbbddf98749f7c177bc0f9d57f6795b7daf06d17e35147b2cfbbdbccd9339ee7739b58bd5a8d72e173b9358e3acdf65b1ceab717d67ec5693d574355bcd51c3b7708ec1fdf3314c92af16abe55a5d2b6b439badcdb5b5b6d7ceda5d7bc69e45cffb1f7bdefb489eaffb32097a7b62b3105fc7e3fba9f9beea7e36627e6318266b7f1dacc3c0091cbecb91452c6431bd17f85d967e7473dbd8d7efeb681dab77e20c2d9745f9b16be9cff8b1f03198af933c5d5bc1789daeb375be2ed6e5ba5a5fd6b5b5b437741601fbf7fbd5b30fbe57a25f6bb15a16fc34ceba757416dfb3e83e9ce9d77ecd807df6ebceefd6cc62bc50c8d2eeb411f366bfd90bd7d26374b7beadb53573e4b2fee5fed5793f628aba5eaf37ebedfa6ebd5befd787f5717d5adfaf1fd68feba790c5fdd69eef5ac1b8b04fbf9ef76a7e704b3e584bbedb9f5950bffba8f7e2eb7e97fcb1df83b63eaf5f02d736cc28effa73246c8e1feb193f73d2e7373edfafe4b23c69bb7e5dbf35cafa7dfdc1e617c8f2f7f78ffdf38ff3283f69566595d196e7f5e7fa6bfdbd1eac87eb11d335bea38c568b980e4db0afbf8fa6c6acc7cffc04c6b2dfadd7cbe90f7a7bea77569a43967505d5e0a69a713e6171d79d36d1f3f5b8f776eb49bfa3b61f93cb389f38de7aba9eade7eabdd8d32b674be7afc8f2d3d9621ecf798f6a11dcaf179774bdcc5f36ea46d9181bb37faead164ebf368979c230a77db5439cb4602336661ab91436d3dc39174ba1fd0a2caa7f6511e4ae0f0b36569fdfacc6cce59f8ce3c6c9271b77e36dfc4d607da94f56f35b9bfed2b8fc7eb6381a2a9ee2da55972acd26dc449b78936cd24db6c9f9aa0bcb6eac27ffdbf68bbc782effdf76ae6549552488eee733a6f615fdba7dbb6356a899203e5a6db51f3b4444f0c14b1489987f9faa8202a4bd37b457331113b9d010943a661645669d93b6d9e37b5a6207f5ce54d90a7b630ee6244ed8f3c2d4532060d9afca32ad349d280e4d481246103617866ae8b10a11c3b2b36c86248e1fe983506f36cb7bd7f59cde1344592e9dd23decc91c0e90c0115250a0014d680104cf80a691efb672cf7c667bc1191af13a6a6c8d2ed758790ea8a041fba8a546ca6681e23a2c67047dffd9b4a1130fb9e20cbad0833e2ce34747a706bc2c0e85fef98baee722bfd4f4404187dc51957668dcd0c2d0b660004318c12b8c61025378f3347fb13bb0acbe5df0f8ab3a31cdd0e01d3ee0136ee036e9c2ddb1ed7437f7e95459c13d7169c0bcfd003fe0117eb2bb700a4ff08c94def1b9eef5e9337dca1557dfc052a8ea8aefae6ed98c216b9d45ef4ffa485524aebeeaa181333471eeaa5edbb7f71bff47100423b4421517519a70a1686ff7106f632dbe471b97ebe0a027b3a4874ec8a276354cdffc603e255ca59dee228325a4b8c2354b719e8d29bbca113774bcb961e319c8f15c1f6327bd3884873ca043ee1bdcda7dce35430f7d0c30740718e10e636fed2f7ddd7f0cc2861b3aa1161991827b3cecfa8d66ec6112bce2115354f693204dfadb96d559cd6ccab25f967cd21655d61b3627a2d61336b0892d72a03dc20e53978ef868d8fa229f5faee75a7fe935c07eb745b764495b08ec7d0311d5f514356ca3bffd70224ff774bfb3f1822818bb5ad8461d3bd8c5de6e837df6fe0507fb088787258ef015c7d68bd0fa1a7cc79ef3f0a8623d21573237714a0f6bb636061dba66de58d0211dac1b76bfe293ef6039b59ad281736c393795d713791dceebf80ee712f96e3009ddd07544a5d179e13613e6e4967d435ca3ec245389a0cad56bfd58aad7bf7aee9fc122ff178e852391e3f3ba9c7d9399eff23a234758aeb7d96b869def6fe7fb0f468e60216ac18678a2378b9890bd31a42ee18c42f1d27b720dcf09969c1fb0909d7904e76ec356026184f0baafc89d66956e3da5fecbf6f6f369d67545d6b5c5d924df135a7ec542cb5e26e49a7cbfc201afa191da8093df3604f79408ae9ab0ad576031ca9ca3caca1635c83935653d22cfb448ce3bcf6adc752c32e62a9eb9443352aa19aaaae7e288acea1ab4729f2cb50e052bf5d4871cf952b02732ae47d9db635ea9689b453c57bc2062244752ad5f5e84c592fcc3e1ee4c949995795bc152fdbea830d827ffc84c20e9088f91d2fb395e4b665b520152c3422492ebf27dce3a1163b10a2cc60916c11710bad85b6ed69a7320cdc09db863ceee0a1533e20c1ccef6c814cd995eb334f9fc9ecf4b7ebda988b5c23b67b1108e04dff03d63da7fc32f8b9a5f4caeec2fc7c9c7e6f5bc5e154b795ce2e596e3679fca7dd222b624e3bc58134fe3a1e0bbcd199677fcb81c4b3d6a7ea7d6aeb0fb7e71ceb9a3f5738b7cbeda2ba7de3ba79caf57e52fff15fb1fcbbfd3fefcfbaf3ffe0193cc32fd</data> +    </image> +</images> +<layoutdefaults spacing="6" margin="11"/> +</UI>  | 
