Commit 16681d2a authored by Boudewijn Rempt's avatar Boudewijn Rempt

* Add pressure sensitivity setting -- this should be tested since my tablet doesn't

quite work here...
* Move at least one method to XYZ as a fallback from the abstract colorspace. (This
is a free-for-all, feel free start implementing either xyz fallback methods or 
specialized implementations for functions in the other colorspaces, the architecture
is now done for now.
* Add my presentation to our documentation directory.

svn path=/trunk/koffice/; revision=455021
parent 2018036f
Bugs
* Save separations as grayscale
* On opening a second image after loading first image but not changing it,
the second image should be loaded in a second view and not replace the
first image in the first view.
......@@ -34,6 +34,26 @@ Integration
kimgio.
* Hack koMainWindow so the save warning doesn't happen for Krita (BSAR)
* pressure curve
Option "PressCurve" "x1,y1,x2,y2"
sets pressure curve by control points x1, y1, x2, and y2.
Their values are in range from 0..100. The input for
linear curve (default) is "0,0,100,100";
slightly depressed curve (firmer) might be "5,0,100,95";
slightly raised curve (softer) might be "0,5,95,100".
Waarde van 0 - 100
0 => 20, 0, 80, 100
50 => 10, 10, 90, 90 --> 0, 0, 100, 100 BSAR
100 => 0, 20, 100, 80
Colorspace independence (found with the test colorstrategy)
......@@ -92,6 +112,8 @@ Import/Export
User Interface
* Add a cheatsheet widget that integrates with knewstuff to have tutorials that people
can download and follow from Krita.
* Add opacity widget (One that grows more white or transparent (showing those gray blocks) based on the
input)
* Add out-of-gamut selection
......
......@@ -219,15 +219,31 @@ void KisAbstractColorSpace::applyAdjustment(const Q_UINT8 */*src*/, Q_UINT8 */*d
// BC: should this default be HSV-based?
Q_INT8 KisAbstractColorSpace::difference(const Q_UINT8* src1, const Q_UINT8* src2)
{
QColor color1, color2;
toQColor(src1, &color1);
toQColor(src2, &color2);
if ( m_defaultToXYZ != 0 && m_defaultFromXYZ != 0 ) {
Q_INT32 psize = pixelSize();
int h1, s1, v1, h2, s2, v2;
rgb_to_hsv(color1.red(), color1.green(), color1.blue(), &h1, &s1, &v1);
rgb_to_hsv(color2.red(), color2.green(), color2.blue(), &h2, &s2, &v2);
return QMAX(QABS(v1 - v2), QMAX(QABS(s1 - s2), QABS(h1 - h2)));
if ( m_conversionCache.size() < 2 * psize ) {
m_conversionCache.resize( 2 * psize, QGArray::SpeedOptim );
}
cmsDoTransform( m_defaultToXYZ, const_cast<Q_UINT8*>( src1 ), m_conversionCache.data(), 1);
cmsDoTransform( m_defaultToXYZ, const_cast<Q_UINT8*>( src2 ), m_conversionCache.data() + psize, 1);
return KisColorSpaceRegistry::getXYZ16()->difference( m_conversionCache.data(), m_conversionCache.data() + psize );
}
else {
QColor color1, color2;
toQColor(src1, &color1);
toQColor(src2, &color2);
int h1, s1, v1, h2, s2, v2;
rgb_to_hsv(color1.red(), color1.green(), color1.blue(), &h1, &s1, &v1);
rgb_to_hsv(color2.red(), color2.green(), color2.blue(), &h2, &s2, &v2);
return QMAX(QABS(v1 - v2), QMAX(QABS(s1 - s2), QABS(h1 - h2)));
}
}
void KisAbstractColorSpace::mixColors(const Q_UINT8 **colors, const Q_UINT8 *weights, Q_UINT32 nColors, Q_UINT8 *dst) const
......
......@@ -24,8 +24,6 @@
#include <qstringlist.h>
#include <qpair.h>
#include <ksharedptr.h>
#include "kis_global.h"
#include "kis_types.h"
#include "kis_channelinfo.h"
......
......@@ -31,6 +31,9 @@
#include "kis_pixel_op.h"
KisColorSpaceRegistry *KisColorSpaceRegistry::m_singleton = 0;
KisAbstractColorSpace * KisColorSpaceRegistry::m_rgb = 0;
KisAbstractColorSpace * KisColorSpaceRegistry::m_alpha = 0;
KisAbstractColorSpace * KisColorSpaceRegistry::m_xyz = 0;
KisColorSpaceRegistry::KisColorSpaceRegistry()
{
......@@ -48,13 +51,47 @@ KisColorSpaceRegistry* KisColorSpaceRegistry::instance()
{
KisColorSpaceRegistry::m_singleton = new KisColorSpaceRegistry();
Q_CHECK_PTR(KisColorSpaceRegistry::m_singleton);
m_singleton->add(new KisXyzColorSpace());
m_singleton->add(new KisAlphaColorSpace());
if ( !m_xyz ) {
m_xyz = new KisXyzColorSpace();
m_singleton->add(m_xyz);
}
if ( !m_alpha ) {
m_alpha = new KisAlphaColorSpace();
}
m_singleton->resetProfiles();
}
return KisColorSpaceRegistry::m_singleton;
}
KisAbstractColorSpace * KisColorSpaceRegistry::getRGB8()
{
if ( m_rgb == 0 ) {
m_rgb = m_singleton->get( "RGBA" );
}
return m_rgb;
}
KisAbstractColorSpace * KisColorSpaceRegistry::getAlpha8()
{
if ( m_alpha == 0 ) {
m_alpha = new KisAlphaColorSpace();
}
return m_alpha;
}
KisAbstractColorSpace * KisColorSpaceRegistry::getXYZ16()
{
if ( m_xyz == 0 ) {
m_xyz = new KisXyzColorSpace();
m_singleton->add( m_xyz );
}
return m_xyz;
}
KisProfileSP KisColorSpaceRegistry::getProfileByName(const QString & name)
{
if (m_profileMap.find(name) == m_profileMap.end()) {
......@@ -67,7 +104,7 @@ KisProfileSP KisColorSpaceRegistry::getProfileByName(const QString & name)
vKisProfileSP KisColorSpaceRegistry::profilesFor(KisAbstractColorSpace * cs)
{
vKisProfileSP profiles;
QMap<QString, KisProfileSP>::Iterator it;
for (it = m_profileMap.begin(); it != m_profileMap.end(); ++it) {
KisProfileSP profile = it.data();
......@@ -88,15 +125,15 @@ void KisColorSpaceRegistry::resetProfiles()
profileFilenames += KisFactory::global() -> dirs() -> findAllResources("kis_profiles", "*.ICM");
profileFilenames += KisFactory::global() -> dirs() -> findAllResources("kis_profiles", "*.ICC");
profileFilenames += KisFactory::global() -> dirs() -> findAllResources("kis_profiles", "*.icc");
QDir d("/usr/share/color/icc/", "*.icc");
profileFilenames += d.entryList();
d.setCurrent("/usr/share/color/icc/");
d.setNameFilter("*.icm");
profileFilenames += d.entryList();
if (!profileFilenames.empty()) {
KisProfile * profile = 0;
for ( QStringList::Iterator it = profileFilenames.begin(); it != profileFilenames.end(); ++it ) {
......@@ -118,15 +155,15 @@ void KisColorSpaceRegistry::addFallbackPixelOp(KisPixelOp * pixelop)
if (!pixelop) {
return;
}
if (!pixelop->isValid()) {
kdDebug() << "Cannot add invalid pixel operation " << pixelop->id().id() << "\n";
return;
}
m_defaultPixelOps[pixelop->id()] = pixelop;
}
KisPixelOp * KisColorSpaceRegistry::getFallbackPixelOp(KisID pixelop)
......@@ -137,3 +174,4 @@ KisPixelOp * KisColorSpaceRegistry::getFallbackPixelOp(KisID pixelop)
return 0;
}
......@@ -45,6 +45,21 @@ public:
*/
static KisColorSpaceRegistry* instance();
/**
* Convenience method to get the often used rgb8 colorspace
*/
static KisAbstractColorSpace * getRGB8();
/**
* Convenience method to get the often used alpha colorspace
*/
static KisAbstractColorSpace * getAlpha8();
/**
* Convenience method to get the often used xyz16 colorspace
*/
static KisAbstractColorSpace * getXYZ16();
/**
* Reload the profiles from disk
*/
......@@ -74,7 +89,7 @@ public:
* returned.
*/
KisPixelOp * getFallbackPixelOp(KisID pixelop);
private:
KisColorSpaceRegistry();
KisColorSpaceRegistry(const KisColorSpaceRegistry&);
......@@ -82,6 +97,10 @@ private:
private:
static KisColorSpaceRegistry *m_singleton;
static KisAbstractColorSpace * m_rgb;
static KisAbstractColorSpace * m_alpha;
static KisAbstractColorSpace * m_xyz;
QMap<QString, KisProfileSP> m_profileMap;
QMap<KisID, KisPixelOp*> m_defaultPixelOps;
};
......
......@@ -104,9 +104,12 @@ void KisXyzColorSpace::applyAdjustment(const Q_UINT8 *src, Q_UINT8 *dst, KisColo
{
}
Q_INT8 KisXyzColorSpace::difference(const Q_UINT8 *src1, const Q_UINT8 *src2)
Q_INT8 KisXyzColorSpace::difference(const Q_UINT8 *src1U8, const Q_UINT8 *src2U8)
{
return 0;
const Pixel *src1 = reinterpret_cast<const Pixel *>(src1U8);
const Pixel *src2 = reinterpret_cast<const Pixel *>(src2U8);
return QMAX(QABS(src1->X - src2->X), QMAX(QABS(src1->Y - src2->Y), QABS(src1->Z - src2->Z)));
}
void KisXyzColorSpace::mixColors(const Q_UINT8 **colors, const Q_UINT8 *weights, Q_UINT32 nColors, Q_UINT8 *dst) const
......
......@@ -45,7 +45,7 @@ KAboutData * newKritaAboutData()
aboutData->addAuthor("Clarence Dang", 0, "dang@kde.org");
aboutData->addAuthor("Cyrille Berger", 0, "cyb@lepi.org");
aboutData->addAuthor("Dirk Schoenberger", 0, "dirk.schoenberger@sz-online.de");
aboutData->addAuthor("Danny Allen", 0 , "danny@dannyallen.co.uk");
aboutData->addAuthor("Danny Allen", 0 , "danny@dannyallen.co.uk");
aboutData->addAuthor("John Califf",0, "jcaliff@compuzone.net");
aboutData->addAuthor("Laurent Montel",0, "lmontel@mandrakesoft.com");
aboutData->addAuthor("Matthias Elter", 0, "me@kde.org");
......@@ -57,6 +57,7 @@ KAboutData * newKritaAboutData()
aboutData->addAuthor("Sven Langkamp", 0, "longamp@reallygood.de");
aboutData->addAuthor("Toshitaka Fujioka", 0, "fujioka@kde.org");
aboutData->addAuthor("Thomas Zander", 0, "zander@kde.org");
aboutData->addAuthor("Sander Koning", 0, "sanderkoning@kde.nl");
return aboutData;
}
......
......@@ -36,6 +36,7 @@ namespace {
const Q_INT32 DEFAULT_MAX_THREADS = 4;
const Q_INT32 DEFAULT_MAX_TILES_MEM = 500; // 8192 kilobytes given 64x64 tiles with 32bpp
const Q_INT32 DEFAULT_SWAPPINESS = 100;
const Q_INT32 DEFAULT_PRESSURE_CORRECTION = 50;
}
KisConfig::KisConfig()
......@@ -253,3 +254,18 @@ void KisConfig::setSwappiness(Q_INT32 swappiness)
{
m_cfg -> writeEntry("swappiness", swappiness);
}
Q_INT32 KisConfig::getPressureCorrection()
{
return m_cfg->readNumEntry( "pressurecorrection", DEFAULT_PRESSURE_CORRECTION );
}
void KisConfig::setPressureCorrection( Q_INT32 correction )
{
m_cfg->writeEntry( "pressurecorrection", correction );
}
Q_INT32 KisConfig::getDefaultPressureCorrection()
{
return DEFAULT_PRESSURE_CORRECTION;
}
......@@ -85,6 +85,9 @@ public:
Q_INT32 swappiness() const;
void setSwappiness(Q_INT32 swappiness);
Q_INT32 getPressureCorrection();
void setPressureCorrection( Q_INT32 correction);
Q_INT32 getDefaultPressureCorrection();
private:
KisConfig(const KisConfig&);
KisConfig& operator=(const KisConfig&);
......
......@@ -32,11 +32,6 @@ KisImageIface::KisImageIface( KisImage * img )
m_img = img;
}
QString KisImageIface::name()const
{
return m_img->name();
}
int KisImageIface::height() const
{
return m_img->height();
......@@ -65,7 +60,7 @@ DCOPRef KisImageIface::activeDevice()
return DCOPRef();
else
return DCOPRef( kapp->dcopClient()->appId(),
dev->dcopObject()->objId(),
"KisPaintDeviceIface");
dev->dcopObject()->objId(),
"KisPaintDeviceIface");
}
......@@ -35,7 +35,7 @@ class KisImageIface : virtual public DCOPObject
public:
KisImageIface( KisImage *img_ );
k_dcop:
QString name()const;
int height() const;
int width() const;
bool empty() const;
......@@ -46,7 +46,7 @@ k_dcop:
* Get the active painting device.
*/
DCOPRef activeDevice();
private:
......
......@@ -35,7 +35,7 @@
KisSelection::KisSelection(KisPaintDeviceSP layer, const QString& name)
: super(
layer -> image(),
KisColorSpaceRegistry::instance()->get("ALPHA"),
KisColorSpaceRegistry::getAlpha8(),
name)
{
m_parentLayer = layer;
......
......@@ -4,10 +4,10 @@ kritapics_DATA = deletelayer.png lowerlayer.png newlayer.png raiselayer.png \
rectangle.png ellipse.png \
visible.png novisible.png linked.png unlinked.png \
tool_pan.png \
tool_freehand.png tool_text.png \
tool_star.png tool_screenshot.png \
tool_freehand.png tool_text.png \
tool_star.png tool_screenshot.png tablet.png \
openhand_cursor.xpm \
closedhand_cursor.xpm locked.png unlocked.png rotate_cursor.xpm
closedhand_cursor.xpm locked.png unlocked.png rotate_cursor.xpm
# directory for pixmaps
kritapicsdir = $(kde_datadir)/krita/pics
......
<!DOCTYPE UI><UI version="3.2" stdsetdef="1">
<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
<class>WdgResolution</class>
<widget class="QWidget">
<property name="name">
......@@ -9,7 +9,7 @@
<x>0</x>
<y>0</y>
<width>487</width>
<height>382</height>
<height>265</height>
</rect>
</property>
<property name="caption">
......@@ -19,32 +19,6 @@
<property name="name">
<cstring>unnamed</cstring>
</property>
<widget class="QLabel" row="2" column="0">
<property name="name">
<cstring>lblMetric</cstring>
</property>
<property name="text">
<string>&amp;Metric system:</string>
</property>
<property name="buddy" stdset="0">
<cstring>cmbMetrics</cstring>
</property>
</widget>
<widget class="QComboBox" row="2" column="1">
<item>
<property name="text">
<string>Dots per Inch</string>
</property>
</item>
<item>
<property name="text">
<string>Dots per Centimeter</string>
</property>
</item>
<property name="name">
<cstring>cmbMetrics</cstring>
</property>
</widget>
<widget class="QGroupBox" row="1" column="0" rowspan="1" colspan="2">
<property name="name">
<cstring>grpSize</cstring>
......@@ -82,17 +56,6 @@
<cstring>intHeight</cstring>
</property>
</widget>
<widget class="QLabel" row="2" column="0" rowspan="1" colspan="2">
<property name="name">
<cstring>lblWarning</cstring>
</property>
<property name="text">
<string>The print size of an image is determined by the size in pixels and the image resolution shown above. Most images do not have a resolution set by default. Changing width and height here will change the resolution, not the number of pixels.</string>
</property>
<property name="alignment">
<set>WordBreak|AlignVCenter</set>
</property>
</widget>
</grid>
</widget>
<widget class="QGroupBox" row="0" column="0" rowspan="1" colspan="2">
......
......@@ -47,7 +47,8 @@ libkisui_la_SOURCES = \
wdgcolorsettings.ui \
wdgapplyprofile.ui \
wdglayerbox.ui \
wdgperformancesettings.ui
wdgperformancesettings.ui \
wdgpressuresettings.ui
noinst_HEADERS = kis_dlg_preferences.h \
......@@ -82,7 +83,8 @@ noinst_HEADERS = kis_dlg_preferences.h \
wdgapplyprofile.h \
wdglayerbox.h \
wdglayerproperties.h \
wdgperformancesettings.h
wdgperformancesettings.h \
wdgpressuresettings.h
libkisui_la_METASOURCES = AUTO
......
......@@ -17,12 +17,12 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
The X11-specific event handling code is based upon code from
The X11-specific event handling code is based upon code from
src/kernel/qapplication_x11.cpp from the Qt GUI Toolkit and is subject
to the following license and copyright:
****************************************************************************
**
**
**
** Implementation of X11 startup routines and event handling
**
......@@ -64,6 +64,7 @@
#include "kis_button_press_event.h"
#include "kis_button_release_event.h"
#include "kis_double_click_event.h"
#include "kis_config.h"
#ifdef Q_WS_X11
......@@ -89,6 +90,47 @@ std::map<XID, KisCanvas::X11TabletDevice> KisCanvas::X11TabletDeviceMap;
#endif // Q_WS_X11
namespace {
static Q_INT32 correctPressureScale( Q_INT32 inPressure )
{
KisConfig cfg;
Q_INT32 correction = cfg.getPressureCorrection();
Q_INT32 x1, y1, x2, y2;
if ( correction == 0 ) {
x1 = 20;
y1 = 0;
x2 = 80;
y2 = 100;
} else if ( correction < 50 ) {
x1 = 20 - ( correction / 50 * 20 );
y1 = 0;
x2 = 80 + ( correction / 50 * 20 );
y2 = 100;
} else if ( correction == 50 ) {
x1 = 0;
y1 = 0;
x2 = 100;
y2 = 100;
} else if ( correction > 50 && correction < 100 ){
x1 = 0;
y1 = correction / 50 * 20;
x2 = 100;
y2 = 100 - ( correction / 50 * 20 );
} else {
x1 = 0;
y1 = 20;
x2 = 100;
y2 = 80;
}
return inPressure;
}
}
KisCanvas::KisCanvas(QWidget *parent, const char *name) : super(parent, name)
{
setBackgroundMode(QWidget::NoBackground);
......@@ -167,7 +209,7 @@ void KisCanvas::tabletEvent(QTabletEvent *e)
break;
}
double pressure = e -> pressure() / 255.0;
double pressure = correctPressureScale( e -> pressure() ) / 255.0;
if (e -> type() == QEvent::TabletPress) {
KisButtonPressEvent ke(device, e -> pos(), e -> globalPos(), pressure, e -> xTilt(), e -> yTilt(), Qt::LeftButton, Qt::NoButton);
......@@ -183,18 +225,18 @@ void KisCanvas::tabletEvent(QTabletEvent *e)
translateTabletEvent(&ke);
#ifdef Q_WS_X11
// Fix the problem that when you change from using a tablet device to the mouse,
// the first mouse button event is not recognised. This is because we handle
// the first mouse button event is not recognised. This is because we handle
// X11 core mouse move events directly so Qt does not get to see them. This breaks
// the tablet event accept/ignore mechanism, causing Qt to consume the first
// mouse button event it sees, instead of a mouse move. 'Ignoring' tablet move events
// stops Qt from stealing the next mouse button event. This does not affect the
// stops Qt from stealing the next mouse button event. This does not affect the
// tablet aware tools as they do not care about mouse moves while the tablet device is
// drawing.
e -> ignore();
#endif
}
}
void KisCanvas::enterEvent(QEvent *e)
{
emit gotEnterEvent(e);
......@@ -624,7 +666,7 @@ bool KisCanvas::x11Event(XEvent *event)
buttonState = translateX11ButtonState(buttonReleased -> state);
XEvent mouseEvent;
// Look for an accompanying core event.
if (XCheckTypedWindowEvent(x11Display(), winId(), ButtonRelease, &mouseEvent)) {
if (buttonReleased -> time == mouseEvent.xbutton.time) {
......
......@@ -189,9 +189,9 @@ ColorSettingsTab::ColorSettingsTab(QWidget *parent, const char *name )
refillPrintProfiles(KisID(cfg.printerColorSpace(), ""));
refillImportProfiles(KisID(cfg.workingColorSpace(), ""));
m_page -> cmbMonitorProfile -> setCurrentText(cfg.monitorProfile());
m_page -> cmbImportProfile -> setCurrentText(cfg.importProfile());
m_page -> cmbPrintProfile -> setCurrentText(cfg.printerProfile());
m_page -> cmbMonitorProfile -> setCurrentText(cfg.monitorProfile());
m_page -> cmbImportProfile -> setCurrentText(cfg.importProfile());
m_page -> cmbPrintProfile -> setCurrentText(cfg.printerProfile());
m_page -> chkBlackpoint -> setChecked(cfg.useBlackPointCompensation());
m_page -> chkDither8Bit -> setChecked(cfg.dither8Bit());
m_page -> chkAskOpen -> setChecked(cfg.askProfileOnOpen());
......@@ -200,13 +200,13 @@ ColorSettingsTab::ColorSettingsTab(QWidget *parent, const char *name )
m_page -> grpIntent -> setButton(cfg.renderIntent());
connect(m_page -> cmbWorkingColorSpace, SIGNAL(activated(const KisID &)),
this, SLOT(refillMonitorProfiles(const KisID &)));
this, SLOT(refillMonitorProfiles(const KisID &)));
connect(m_page -> cmbWorkingColorSpace, SIGNAL(activated(const KisID &)),
this, SLOT(refillImportProfiles(const KisID &)));
this, SLOT(refillImportProfiles(const KisID &)));
connect(m_page -> cmbPrintingColorSpace, SIGNAL(activated(const KisID &)),
this, SLOT(refillPrintProfiles(const KisID &)));
this, SLOT(refillPrintProfiles(const KisID &)));
}
......@@ -303,6 +303,23 @@ void PerformanceTab::setDefault()
m_page -> m_maxTiles -> setValue(500);
}
PressureSettingsTab::PressureSettingsTab( QWidget *parent, const char *name)
: WdgPressureSettings( parent, name )
{
KisConfig cfg;
slPressure->setValue( cfg.getPressureCorrection() );
}
void PressureSettingsTab::setDefault()
{
KisConfig cfg;
slPressure->setValue(cfg.getDefaultPressureCorrection());
}
PreferencesDialog::PreferencesDialog( QWidget* parent, const char* name )
: KDialogBase( IconList, i18n("Preferences"), Ok | Cancel | Help | Default | Apply, Ok, parent, name, true, true )
{
......@@ -322,6 +339,10 @@ PreferencesDialog::PreferencesDialog( QWidget* parent, const char* name )
vbox = addVBoxPage( i18n( "Performance Settings"), i18n( "Performance Settings"), BarIcon( "fork", KIcon::SizeMedium ));
m_performanceSettings = new PerformanceTab ( vbox );
vbox = addVBoxPage ( i18n( "Pressure Settings" ), i18n( "Pressure Settings" ), BarIcon( "tablet", KIcon::SizeMedium ));
m_pressureSettings = new PressureSettingsTab( vbox );