diff --git a/libs/flake/KoShapeController.h b/libs/flake/KoShapeController.h index 0c2c0104fa..9e60ff550a 100644 --- a/libs/flake/KoShapeController.h +++ b/libs/flake/KoShapeController.h @@ -1,171 +1,173 @@ /* This file is part of the KDE project * * Copyright (C) 2006-2007, 2010 Thomas Zander * Copyright (C) 2006-2008 Thorsten Zachmann * * 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 Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef KOSHAPECONTROLLER_H #define KOSHAPECONTROLLER_H #include "kritaflake_export.h" #include #include #include class KoCanvasBase; class KoShape; class KoShapeContainer; class KoShapeControllerBase; class KUndo2Command; class KoDocumentResourceManager; /** * Class used by tools to maintain the list of shapes. * All applications have some sort of list of all shapes that belong to the document. * The applications implement the KoShapeControllerBase interface (all pure virtuals) * to add and remove shapes from the document. To ensure that an application can expect * a certain protocol to be adhered to when adding/removing shapes, all tools use the API * from this class for maintaining the list of shapes in the document. So no tool gets * to access the application directly. */ class KRITAFLAKE_EXPORT KoShapeController : public QObject { Q_OBJECT public: /** * Create a new Controller; typically not called by applications, only * by the KonCanvasBase constructor. * @param canvas the canvas this controller works for. The canvas can be 0 * @param shapeController the application provided shapeController that we can call. */ KoShapeController(KoCanvasBase *canvas, KoShapeControllerBase *shapeController); /// destructor ~KoShapeController() override; /** * @brief reset sets the canvas and shapebased document to 0. */ void reset(); /** * @brief Add a shape to the document. * If the shape has no parent, the active layer will become its parent. * * @param shape to add to the document + * @param parentShape the parent shape * @param parent the parent command if the resulting command is a compound undo command. * * @return command which will insert the shape into the document or 0 if the * insertion was cancelled. The command is not yet executed. */ KUndo2Command* addShape(KoShape *shape, KoShapeContainer *parentShape, KUndo2Command *parent = 0); /** * @brief Add a shape to the document, skipping any dialogs or other user interaction. * * @param shape to add to the document + * @param parentShape the parent shape * @param parent the parent command if the resulting command is a compound undo command. * * @return command which will insert the shape into the document. The command is not yet executed. */ KUndo2Command* addShapeDirect(KoShape *shape, KoShapeContainer *parentShape, KUndo2Command *parent = 0); /** * @brief Add shapes to the document, skipping any dialogs or other user interaction. * * @param shape the shape to add to the document * @param parentShape the parent shape * @param parent the parent command if the resulting command is a compound undo command. * * @return command which will insert the shapes into the document. The command is not yet executed. */ KUndo2Command* addShapesDirect(const QList shape, KoShapeContainer *parentShape, KUndo2Command *parent = 0); /** * @brief Remove a shape from the document. * * @param shape to remove from the document * @param parent the parent command if the resulting command is a compound undo command. * * @return command which will remove the shape from the document. * The command is not yet executed. */ KUndo2Command* removeShape(KoShape *shape, KUndo2Command *parent = 0); /** * Remove a shape from the document. * * @param shapes the set of shapes to remove from the document * @param parent the parent command if the resulting command is a compound undo command. * * @return command which will remove the shape from the document. * The command is not yet executed. */ KUndo2Command* removeShapes(const QList &shapes, KUndo2Command *parent = 0); /** * @brief Set the KoShapeControllerBase used to add/remove shapes. * * NOTE: only Sheets uses this method. Do not use it in your application. Sheets * has to also call: * KoToolManager::instance()->updateShapeControllerBase(shapeController, canvas->canvasController()); * * @param shapeController the new shapeController. */ void setShapeControllerBase(KoShapeControllerBase *shapeController); /** * The size of the document measured in rasterized pixels. This information is needed for loading * SVG documents that use 'px' as the default unit. */ QRectF documentRectInPixels() const; /** * Resolution of the rasterized representation of the document. Used to load SVG documents correctly. */ qreal pixelsPerInch() const; /** * Document rect measured in 'pt' */ QRectF documentRect() const; /** * Return a pointer to the resource manager associated with the * shape-set (typically a document). The resource manager contains * document wide resources * such as variable managers, the image * collection and others. */ KoDocumentResourceManager *resourceManager() const; /** * @brief Returns the KoShapeControllerBase used to add/remove shapes. * * @return the KoShapeControllerBase */ KoShapeControllerBase *documentBase() const; private: class Private; Private * const d; }; Q_DECLARE_METATYPE(KoShapeController *) #endif diff --git a/libs/flake/KoShapeManager.h b/libs/flake/KoShapeManager.h index 8b9600658d..9b21d5af37 100644 --- a/libs/flake/KoShapeManager.h +++ b/libs/flake/KoShapeManager.h @@ -1,212 +1,214 @@ /* This file is part of the KDE project Copyright (C) 2006-2008 Thorsten Zachmann Copyright (C) 2007, 2009 Thomas Zander 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 Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef KOSHAPEMANAGER_H #define KOSHAPEMANAGER_H #include #include #include #include "KoFlake.h" #include "kritaflake_export.h" class KoShape; class KoSelection; class KoViewConverter; class KoCanvasBase; class KoPointerEvent; class KoShapePaintingContext; class QPainter; class QPointF; class QRectF; /** * The shape manager hold a list of all shape which are in scope. * There is one shape manager per canvas. This makes the shape manager * different from QGraphicsScene, which contains the datamodel for all * graphics items: KoShapeManager only contains the subset of shapes * that are shown in its canvas. * * The selection in the different views can be different. */ class KRITAFLAKE_EXPORT KoShapeManager : public QObject { Q_OBJECT public: /// enum for add() enum Repaint { PaintShapeOnAdd, ///< Causes each shapes 'update()' to be called after being added to the shapeManager AddWithoutRepaint ///< Avoids each shapes 'update()' to be called for faster addition when its possible. }; /** * Constructor. */ explicit KoShapeManager(KoCanvasBase *canvas); /** * Constructor that takes a list of shapes, convenience version. * @param shapes the shapes to start out with, see also setShapes() * @param canvas the canvas this shape manager is working on. */ KoShapeManager(KoCanvasBase *canvas, const QList &shapes); ~KoShapeManager() override; /** * Remove all previously owned shapes and make the argument list the new shapes * to be managed by this manager. * @param shapes the new shapes to manage. * @param repaint if true it will trigger a repaint of the shapes */ void setShapes(const QList &shapes, Repaint repaint = PaintShapeOnAdd); /// returns the list of maintained shapes QList shapes() const; /** * Get a list of all shapes that don't have a parent. */ QList topLevelShapes() const; public Q_SLOTS: /** * Add a KoShape to be displayed and managed by this manager. * This will trigger a repaint of the shape. * @param shape the shape to add * @param repaint if true it will trigger a repaint of the shape */ void addShape(KoShape *shape, KoShapeManager::Repaint repaint = PaintShapeOnAdd); /** * Remove a KoShape from this manager * @param shape the shape to remove */ void remove(KoShape *shape); public: /// return the selection shapes for this shapeManager KoSelection *selection() const; /** * Paint all shapes and their selection handles etc. * @param painter the painter to paint to. * @param forPrint if true, make sure only actual content is drawn and no decorations. * @param converter to convert between document and view coordinates. */ void paint(QPainter &painter, const KoViewConverter &converter, bool forPrint); /** * Returns the shape located at a specific point in the document. * If more than one shape is located at the specific point, the given selection type * controls which of them is returned. * @param position the position in the document coordinate system. * @param selection controls which shape is returned when more than one shape is at the specific point * @param omitHiddenShapes if true, only visible shapes are considered */ KoShape *shapeAt(const QPointF &position, KoFlake::ShapeSelection selection = KoFlake::ShapeOnTop, bool omitHiddenShapes = true); /** * Returns the shapes which intersects the specific rect in the document. * @param rect the rectangle in the document coordinate system. - * @param omitHiddenShapes if true, only visible shapes are considered + * @param omitHiddenShapes if @c true, only visible shapes are considered + * @param containedMode if @c true use contained mode */ QList shapesAt(const QRectF &rect, bool omitHiddenShapes = true, bool containedMode = false); /** * Request a repaint to be queued. * The repaint will be restricted to the parameters rectangle, which is expected to be * in points (the document coordinates system of KoShape) and it is expected to be * normalized and based in the global coordinates, not any local coordinates. *

This method will return immediately and only request a repaint. Successive calls * will be merged into an appropriate repaint action. * @param rect the rectangle (in pt) to queue for repaint. * @param shape the shape that is going to be redrawn; only needed when selectionHandles=true * @param selectionHandles if true; find out if the shape is selected and repaint its * selection handles at the same time. */ void update(const QRectF &rect, const KoShape *shape = 0, bool selectionHandles = false); /** * Update the tree for finding the shapes. * This will remove the shape from the tree and will reinsert it again. * The update to the tree will be posponed until it is needed so that successive calls * will be merged into one. * @param shape the shape to updated its position in the tree. */ void notifyShapeChanged(KoShape *shape); /** * Paint a shape * * @param shape the shape to paint * @param painter the painter to paint to. * @param converter to convert between document and view coordinates. + * @param paintContext the painting context */ static void paintShape(KoShape *shape, QPainter &painter, const KoViewConverter &converter, KoShapePaintingContext &paintContext); /** * @brief renderSingleShape renders a shape on \p painter. This method includes all the * needed steps for painting a single shape: setting transformations, clipping and masking. */ static void renderSingleShape(KoShape *shape, QPainter &painter, const KoViewConverter &converter, KoShapePaintingContext &paintContext); /** * A special interface for KoShape to use during shape destruction. Don't use this * interface directly unless you are KoShape. */ struct ShapeInterface { ShapeInterface(KoShapeManager *_q); /** * Called by a shape when it is destructed. Please note that you cannot access * any shape's method type or information during this call because the shape might be * semi-destroyed. */ void notifyShapeDestructed(KoShape *shape); protected: KoShapeManager *q; }; ShapeInterface* shapeInterface(); Q_SIGNALS: /// emitted when the selection is changed void selectionChanged(); /// emitted when an object in the selection is changed (moved/rotated etc) void selectionContentChanged(); /// emitted when any object changed (moved/rotated etc) void contentChanged(); private: KoCanvasBase *canvas(); class Private; Private * const d; Q_PRIVATE_SLOT(d, void updateTree()) }; #endif diff --git a/libs/flake/KoToolManager.h b/libs/flake/KoToolManager.h index 9d17239db9..77dbe4edd1 100644 --- a/libs/flake/KoToolManager.h +++ b/libs/flake/KoToolManager.h @@ -1,334 +1,335 @@ /* This file is part of the KDE project * Copyright (c) 2005-2006 Boudewijn Rempt * Copyright (C) 2006, 2008 Thomas Zander * Copyright (C) 2006 Thorsten Zachmann * * 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 Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef KO_TOOL_MANAGER #define KO_TOOL_MANAGER #include "KoInputDevice.h" #include "kritaflake_export.h" #include #include class KoCanvasController; class KoShapeControllerBase; class KoToolFactoryBase; class KoCanvasBase; class KoToolBase; class KoCreateShapesTool; class KActionCollection; class KoShape; class KoInputDeviceHandlerEvent; class KoShapeLayer; class ToolHelper; class QKeySequence; class QCursor; /** * This class serves as a QAction-like control object for activation of a tool. * * It allows to implement a custom UI to control the activation of tools. * See KoToolBox & KoModeBox in the kowidgets library. * * KoToolAction objects are indirectly owned by the KoToolManager singleton * and live until the end of its lifetime. */ class KRITAFLAKE_EXPORT KoToolAction : public QObject { Q_OBJECT public: // toolHelper takes over ownership, and those live till the end of KoToolManager. explicit KoToolAction(ToolHelper *toolHelper); ~KoToolAction() override; public: QString id() const; ///< The id of the tool QString iconText() const; ///< The icontext of the tool QString toolTip() const; ///< The tooltip of the tool QString iconName() const; ///< The icon name of the tool QKeySequence shortcut() const; ///< The shortcut to activate the tool QString section() const; ///< The section the tool wants to be in. int priority() const; ///< Lower number (higher priority) means coming first in the section. int buttonGroupId() const; ///< A unique ID for this tool as passed by changedTool(), >= 0 QString visibilityCode() const; ///< This tool should become visible when we emit this string in toolCodesSelected() public Q_SLOTS: void trigger(); ///< Request the activation of the tool Q_SIGNALS: void changed(); ///< Emitted when a property changes (shortcut ATM) private: friend class ToolHelper; class Private; Private *const d; }; /** * This class manages the activation and deactivation of tools for * each input device. * * Managing the active tool and switching tool based on various variables. * * The state of the toolbox will be the same for all views in the process so practically * you can say we have one toolbox per application instance (process). Implementation * does not allow one widget to be in more then one view, so we just make sure the toolbox * is hidden in not-in-focus views. * * The ToolManager is a singleton and will manage all views in all applications that * are loaded in this process. This means you will have to register and unregister your view. * When creating your new view you should use a KoCanvasController() and register that * with the ToolManager like this: @code MyGuiWidget::MyGuiWidget() { m_canvasController = new KoCanvasController(this); m_canvasController->setCanvas(m_canvas); KoToolManager::instance()->addControllers(m_canvasController)); } MyGuiWidget::~MyGuiWidget() { KoToolManager::instance()->removeCanvasController(m_canvasController); } @endcode * * For a new view that extends KoView all you need to do is implement KoView::createToolBox() * * KoToolManager also keeps track of the current tool based on a complex set of conditions and heuristics: - there is one active tool per KoCanvasController (and there is one KoCanvasController per view, because this is a class with scrollbars and a zoomlevel and so on) - for every pointing device (determined by the unique id of tablet, or 0 for mice -- you may have more than one mouse attached, but Qt cannot distinguish between them, there is an associated tool. - depending on things like tablet leave/enter proximity, incoming mouse or tablet events and a little timer (that gets stopped when we know what is what), the active pointing device is determined, and the active tool is set accordingly. Nota bene: if you use KoToolManager and register your canvases with it you no longer have to manually implement methods to route mouse, tablet, key or wheel events to the active tool. In fact, it's no longer interesting to you which tool is active; you can safely route the paint event through KoToolProxy::paint(). (The reason the input events are handled completely by the toolmanager and the paint events not is that, generally speaking, it's okay if the tools get the input events first, but you want to paint your shapes or other canvas stuff first and only then paint the tool stuff.) */ class KRITAFLAKE_EXPORT KoToolManager : public QObject { Q_OBJECT public: KoToolManager(); /// Return the toolmanager singleton static KoToolManager* instance(); ~KoToolManager() override; /** * Register actions for switching to tools at the actionCollection parameter. * The actions will have the text / shortcut as stated by the toolFactory. * If the application calls this in their KoView extending class they will have all the benefits * from allowing this in the menus and to allow the use to configure the shortcuts used. * @param ac the actionCollection that will be the parent of the actions. * @param controller tools registered with this controller will have all their actions added as well. */ void registerToolActions(KActionCollection *ac, KoCanvasController *controller); /** * Register a new canvas controller * @param controller the view controller that this toolmanager will manage the tools for */ void addController(KoCanvasController *controller); /** * Remove a set of controllers * When the controller is no longer used it should be removed so all tools can be * deleted and stop eating memory. * @param controller the controller that is removed */ void removeCanvasController(KoCanvasController *controller); /** * Attempt to remove a controller. * This is automatically called when a controller's proxy object is deleted, and * it ensures that the controller is, in fact, removed, even if the creator forgot * to do so. * @param controller the proxy object of the controller to be removed */ Q_SLOT void attemptCanvasControllerRemoval(QObject *controller); /// @return the active canvas controller KoCanvasController *activeCanvasController() const; /** * Return the tool that is able to create shapes for this param canvas. * This is typically used by the KoShapeSelector to set which shape to create next. * @param canvas the canvas that is a child of a previously registered controller * who's tool you want. * @see addController() */ KoCreateShapesTool *shapeCreatorTool(KoCanvasBase *canvas) const; /** * Returns the tool for the given tool id. The tool may be 0 * @param canvas the canvas that is a child of a previously registered controller * who's tool you want. + * @param id the tool identifier * @see addController() */ KoToolBase *toolById(KoCanvasBase *canvas, const QString &id) const; /// @return the currently active pointing device KoInputDevice currentInputDevice() const; /** * For the list of shapes find out which tool is the highest priority tool that can handle it. * @returns the toolId for the shapes. * @param shapes a list of shapes, a selection for example, that is used to look for the tool. */ QString preferredToolForSelection(const QList &shapes); /** * Returns the list of toolActions for the current tools. * @returns lists of toolActions for the current tools. */ QList toolActionList() const; /// Request tool activation for the given canvas controller void requestToolActivation(KoCanvasController *controller); /// Returns the toolId of the currently active tool QString activeToolId() const; void initializeCurrentToolForCanvas(); class Private; /** * \internal return the private object for the toolmanager. */ KoToolManager::Private *priv(); public Q_SLOTS: /** * Request switching tool * @param id the id of the tool */ void switchToolRequested(const QString &id); /** * Request change input device * @param id the id of the input device */ void switchInputDeviceRequested(const KoInputDevice &id); /** * Request for temporary switching the tools. * This switch can be later reverted with switchBackRequested(). * @param id the id of the tool * * @see switchBackRequested() */ void switchToolTemporaryRequested(const QString &id); /** * Switches back to the original tool after the temporary switch * has been done. It the user changed the tool manually on the way, * then it switches to the interaction tool */ void switchBackRequested(); Q_SIGNALS: /** * Emitted when a new tool is going to override the current tool * @param canvas the currently active canvas. */ void aboutToChangeTool(KoCanvasController *canvas); /** * Emitted when a new tool was selected or became active. * @param canvas the currently active canvas. * @param uniqueToolId a random but unique code for the new tool. */ void changedTool(KoCanvasController *canvas, int uniqueToolId); /** * Emitted after the selection changed to state which unique shape-types are now * in the selection. * @param types a list of string that are the shape types of the selected objects. */ void toolCodesSelected(const QList &types); /** * Emitted after the current layer changed either its properties or to a new layer. * @param canvas the currently active canvas. * @param layer the layer that is selected. */ void currentLayerChanged(const KoCanvasController *canvas, const KoShapeLayer *layer); /** * Every time a new input device gets used by a tool, this event is emitted. * @param device the new input device that the user picked up. */ void inputDeviceChanged(const KoInputDevice &device); /** * Emitted whenever the active canvas changed. * @param canvas the new activated canvas (might be 0) */ void changedCanvas(const KoCanvasBase *canvas); /** * Emitted whenever the active tool changes the status text. * @param statusText the new status text */ void changedStatusText(const QString &statusText); /** * emitted whenever a new tool is dynamically added for the given canvas */ void addedTool(KoToolAction *toolAction, KoCanvasController *canvas); /** * Emit the new tool option widgets to be used with this canvas. */ void toolOptionWidgetsChanged(KoCanvasController *controller, const QList > &widgets); private: KoToolManager(const KoToolManager&); KoToolManager operator=(const KoToolManager&); Q_PRIVATE_SLOT(d, void toolActivated(ToolHelper *tool)) Q_PRIVATE_SLOT(d, void detachCanvas(KoCanvasController *controller)) Q_PRIVATE_SLOT(d, void attachCanvas(KoCanvasController *controller)) Q_PRIVATE_SLOT(d, void movedFocus(QWidget *from, QWidget *to)) Q_PRIVATE_SLOT(d, void updateCursor(const QCursor &cursor)) Q_PRIVATE_SLOT(d, void selectionChanged(const QList &shapes)) Q_PRIVATE_SLOT(d, void currentLayerChanged(const KoShapeLayer *layer)) QPair createTools(KoCanvasController *controller, ToolHelper *tool); Private *const d; }; #endif diff --git a/libs/image/brushengine/kis_paintop_factory.h b/libs/image/brushengine/kis_paintop_factory.h index d726da9856..7c62545621 100644 --- a/libs/image/brushengine/kis_paintop_factory.h +++ b/libs/image/brushengine/kis_paintop_factory.h @@ -1,117 +1,118 @@ /* * Copyright (c) 2008 Boudewijn Rempt * Copyright (c) 2010 Lukáš Tvrdý * 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_PAINTOP_FACTORY_H_ #define KIS_PAINTOP_FACTORY_H_ #include "kis_types.h" #include "kritaimage_export.h" #include #include #include #include #include class KisPainter; class KisPaintOp; class QWidget; class KisPaintOpConfigWidget; /** * The paintop factory is responsible for creating paintops of the specified class. * If there is an optionWidget, the derived paintop itself must support settings, * and it's up to the factory to do that. */ class KRITAIMAGE_EXPORT KisPaintOpFactory : public QObject { Q_OBJECT public: enum PaintopVisibility { AUTO, ALWAYS, NEVER }; /** * @param whiteListedCompositeOps list of compositeops that don't work with this paintop */ KisPaintOpFactory(const QStringList & whiteListedCompositeOps = QStringList()); ~KisPaintOpFactory() override {} static QString categoryStable(); #ifdef HAVE_THREADED_TEXT_RENDERING_WORKAROUND virtual void preinitializePaintOpIfNeeded(const KisPaintOpSettingsSP settings); #endif /* HAVE_THREADED_TEXT_RENDERING_WORKAROUND */ /** * Create a KisPaintOp with the given settings and painter. * @param settings the settings associated with the input device * @param painter the painter used to draw + * @param node the node used to draw * @param image the image used to draw */ virtual KisPaintOp * createOp(const KisPaintOpSettingsSP settings, KisPainter * painter, KisNodeSP node, KisImageSP image) = 0; virtual QString id() const = 0; virtual QString name() const = 0; virtual QString category() const = 0; /** * List of usually hidden compositeops that are useful for this paintop. */ QStringList whiteListedCompositeOps() const; /** * @brief icon * @return the icon to represent this paintop. */ virtual QIcon icon(); /** * Create and return an settings object for this paintop. */ virtual KisPaintOpSettingsSP settings() = 0; /** * create a widget that can display paintop settings */ virtual KisPaintOpConfigWidget* createConfigWidget(QWidget* parent) = 0; /** * Set the priority of this paintop, as it is shown in the UI; lower number means * it will be show more to the front of the list. * @param newPriority the priority */ void setPriority(int newPriority); int priority() const; /** * This method will be called by the registry after all paintops are loaded * Overwrite to let the factory do something. */ virtual void processAfterLoading() {} private: QStringList m_whiteListedCompositeOps; int m_priority; PaintopVisibility m_visibility; }; #endif diff --git a/libs/image/kis_edge_detection_kernel.h b/libs/image/kis_edge_detection_kernel.h index e435aac95d..f5c4d6b7d2 100644 --- a/libs/image/kis_edge_detection_kernel.h +++ b/libs/image/kis_edge_detection_kernel.h @@ -1,130 +1,131 @@ /* * Copyright (c) 2017 Wolthera van Hövell tot Westerflier * * 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_EDGE_DETECTION_KERNEL_H #define KIS_EDGE_DETECTION_KERNEL_H #include "kritaimage_export.h" #include "kis_types.h" #include class QRect; class KRITAIMAGE_EXPORT KisEdgeDetectionKernel { public: KisEdgeDetectionKernel(); enum FilterType { Simple, //A weird simple method used in our old sobel filter Prewit, //The simpler prewitt detection, which doesn't smooth. SobelVector //Sobel does smooth. The creation of bigger kernels is based on an approach regarding vectors. }; enum FilterOutput { pythagorean, xGrowth, xFall, yGrowth, yFall, radian }; /** * @brief createHorizontalMatrix * @param radius the radius. 1 makes a 3x3 kernel. * @param type One of the entries in the enum Filtertype * @param reverse which direction the gradient goes. * The horizontal gradient by default detects the rightmost edges. * Reversed it selects the leftmost edges. * @return */ static Eigen::Matrix createHorizontalMatrix(qreal radius, FilterType type, bool reverse = false); /** * @brief createVerticalMatrix * @param radius the radius. 1 makes a 3x3 kernel. * @param type One of the entries in the enum Filtertype * @param reverse which direction the gradient goes. * The vertical gradient by default detects the topmost edges. * Reversed it selects the bottommost edges. * @return */ static Eigen::Matrix createVerticalMatrix(qreal radius, FilterType type, bool reverse = false); static KisConvolutionKernelSP createHorizontalKernel(qreal radius, FilterType type, bool denormalize = true, bool reverse = false); static KisConvolutionKernelSP createVerticalKernel(qreal radius, FilterType type, bool denormalize = true, bool reverse = false); static int kernelSizeFromRadius(qreal radius); static qreal sigmaFromRadius(qreal radius); /** * @brief applyEdgeDetection * This applies the edge detection filter to the device. * @param device the device to apply to. * @param rect the affected rect. * @param xRadius the radius of the horizontal sampling, radius of 0 is effectively disabling it. * @param yRadius the radius of the vertical sampling, refius of 0 is effectively disabling it. * @param type the type can be prewitt, sobel or simple, each of which * have a different sampling for the eventual edge detection. * @param channelFlags the affected channels. * @param progressUpdater the progress updater if it exists. * @param output the output mode. * @param writeToAlpha whether or not to have the result applied to the transparency than the color channels, * this is useful for fringe effects. */ static void applyEdgeDetection(KisPaintDeviceSP device, const QRect& rect, qreal xRadius, qreal yRadius, FilterType type, const QBitArray &channelFlags, KoUpdater *progressUpdater, FilterOutput output = pythagorean, bool writeToAlpha = false); /** * @brief converToNormalMap * Convert a channel of the device to a normal map. The channel will be interpreted as a heightmap. * @param device the device * @param rect the rectangle to apply this to. * @param xRadius the xradius * @param yRadius the yradius * @param type the edge detection filter. * @param channelToConvert the channel to use as a grayscale. * @param channelOrder the order in which the xyz coordinates ought to be written to the pixels. - * @param channelFlags + * @param channelFlip whether to flip the channels + * @param channelFlags the channel flags * @param progressUpdater */ static void convertToNormalMap(KisPaintDeviceSP device, const QRect & rect, qreal xRadius, qreal yRadius, FilterType type, int channelToConvert, QVector channelOrder, QVector channelFlip, const QBitArray &channelFlags, KoUpdater *progressUpdater); }; #endif // KIS_EDGE_DETECTION_KERNEL_H diff --git a/libs/image/kis_fixed_paint_device.h b/libs/image/kis_fixed_paint_device.h index b9d3d510e0..78462501f1 100644 --- a/libs/image/kis_fixed_paint_device.h +++ b/libs/image/kis_fixed_paint_device.h @@ -1,205 +1,207 @@ /* * Copyright (c) 2009 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_FIXED_PAINT_DEVICE_H #define KIS_FIXED_PAINT_DEVICE_H #include #include #include "kis_shared.h" #include #include #include #include "KisOptimizedByteArray.h" class KoColor; /** * A fixed paint device is a simple paint device that consists of an array * of bytes and a rectangle. It cannot grow, it cannot shrink, all you can * do is fill the paint device with the right bytes and use it as an argument * to KisPainter or use the bytes as an argument to KoColorSpace functions. */ class KRITAIMAGE_EXPORT KisFixedPaintDevice : public KisShared { public: KisFixedPaintDevice(const KoColorSpace* colorSpace, KisOptimizedByteArray::MemoryAllocatorSP allocator = KisOptimizedByteArray::MemoryAllocatorSP()); virtual ~KisFixedPaintDevice(); /** * Deep copy the fixed paint device, including the data. */ KisFixedPaintDevice(const KisFixedPaintDevice& rhs); /** * Deep copy the fixed paint device, including the data. */ KisFixedPaintDevice& operator=(const KisFixedPaintDevice& rhs); /** * setRect sets the rect of the fixed paint device to rect. * This will _not_ create the associated data area. * * @param rc the bounds in pixels. The x,y of the rect represent the origin * of the fixed paint device. */ void setRect(const QRect& rc); /** * @return the rect that the data represents */ QRect bounds() const; /** * @return the amount of allocated pixels (you can fake the size with setRect/bounds) * It is useful to know the accumulated memory size in pixels (not in bytes) for optimizations to avoid re-allocation. */ int allocatedPixels() const; /** * @return the pixelSize associated with this fixed paint device. */ quint32 pixelSize() const; const KoColorSpace* colorSpace() const { return m_colorSpace; } /** * initializes the paint device. * * @param defaultValue the default byte with which all pixels will be filled. * @return false if the allocation failed. */ bool initialize(quint8 defaultValue = 0); /** * Changed the size of the internal buffer to accommodate the exact number of bytes * needed to store area bounds(). The allocated data is *not* initialized! */ void reallocateBufferWithoutInitialization(); /** * If the size of the internal buffer is smaller than the one needed to accommodate * bounds(), resize the buffer. Otherwise, do nothing. The allocated data is neither * copying or initialized! */ void lazyGrowBufferWithoutInitialization(); /** * @return a pointer to the beginning of the data associated with this fixed paint device. */ quint8* data(); const quint8* constData() const; quint8* data() const; /** * Read the bytes representing the rectangle described by x, y, w, h into * data. If data is not big enough, Krita will gladly overwrite the rest * of your precious memory. * * Since this is a copy, you need to make sure you have enough memory. * * The reading is done only if the rectangular area x,y,w,h is inside the bounds of the device * and the device is not empty */ void readBytes(quint8 * dstData, qint32 x, qint32 y, qint32 w, qint32 h) const; /** * Converts the paint device to a different colorspace */ void convertTo(const KoColorSpace * dstColorSpace = 0, KoColorConversionTransformation::Intent renderingIntent = KoColorConversionTransformation::internalRenderingIntent(), KoColorConversionTransformation::ConversionFlags conversionFlags = KoColorConversionTransformation::internalConversionFlags()); /** * Fill this paint device with the data from image * * @param image the image * @param srcProfileName name of the RGB profile to interpret the image as. 0 is interpreted as sRGB */ virtual void convertFromQImage(const QImage& image, const QString &srcProfileName); /** * Create an RGBA QImage from a rectangle in the paint device. * * @param dstProfile RGB profile to use in conversion. May be 0, in which * case it's up to the color strategy to choose a profile (most * like sRGB). * @param x Left coordinate of the rectangle * @param y Top coordinate of the rectangle * @param w Width of the rectangle in pixels * @param h Height of the rectangle in pixels * @param renderingIntent Rendering intent * @param conversionFlags Conversion flags */ virtual QImage convertToQImage(const KoColorProfile *dstProfile, qint32 x, qint32 y, qint32 w, qint32 h, KoColorConversionTransformation::Intent renderingIntent = KoColorConversionTransformation::internalRenderingIntent(), KoColorConversionTransformation::ConversionFlags conversionFlags = KoColorConversionTransformation::internalConversionFlags()) const; /** * Create an RGBA QImage from a rectangle in the paint device. The * rectangle is defined by the parent image's bounds. * * @param dstProfile RGB profile to use in conversion. May be 0, in which * case it's up to the color strategy to choose a profile (most * like sRGB). + * @param renderingIntent The rendering intent of conversion. + * @param conversionFlags The conversion flags. */ virtual QImage convertToQImage(const KoColorProfile *dstProfile, KoColorConversionTransformation::Intent renderingIntent = KoColorConversionTransformation::internalRenderingIntent(), KoColorConversionTransformation::ConversionFlags conversionFlags = KoColorConversionTransformation::internalConversionFlags()) const; /** * Clear the given rectangle to transparent black. * * XXX: this will not (yet) expand the paint device to contain the specified rect * but if the paintdevice has not been initialized, it will be. */ void clear(const QRect & rc); /** * Fill the given rectangle with the given pixel. This does not take the * selection into account. * * XXX: this will not (yet) expand the paint device to contain the specified rect * but if the paintdevice has not been initialized, it will be. */ void fill(qint32 x, qint32 y, qint32 w, qint32 h, const quint8 *fillPixel); void fill(const QRect &rc, const KoColor &color); /** * Mirrors the device. */ void mirror(bool horizontal, bool vertical); private: const KoColorSpace* m_colorSpace; QRect m_bounds; KisOptimizedByteArray m_data; }; #endif diff --git a/libs/image/kis_paint_device.h b/libs/image/kis_paint_device.h index 055d67c27e..969a1181f4 100644 --- a/libs/image/kis_paint_device.h +++ b/libs/image/kis_paint_device.h @@ -1,882 +1,894 @@ /* * Copyright (c) 2002 patrick julien * Copyright (c) 2006 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_PAINT_DEVICE_IMPL_H_ #define KIS_PAINT_DEVICE_IMPL_H_ #include #include #include #include "kis_debug.h" #include #include "kis_types.h" #include "kis_shared.h" #include "kis_default_bounds_base.h" #include class KUndo2Command; class QRect; class QImage; class QPoint; class QString; class QColor; class QIODevice; class KoColor; class KoColorSpace; class KoColorProfile; class KisDataManager; class KisPaintDeviceWriter; class KisKeyframe; class KisRasterKeyframeChannel; class KisPaintDeviceFramesInterface; typedef KisSharedPtr KisDataManagerSP; namespace KritaUtils { enum DeviceCopyMode { CopySnapshot = 0, CopyAllFrames }; } /** * A paint device contains the actual pixel data and offers methods * to read and write pixels. A paint device has an integer x, y position * (it is not positioned on the image with sub-pixel accuracy). * A KisPaintDevice doesn't have any fixed size, the size changes dynamically * when pixels are accessed by an iterator. */ class KRITAIMAGE_EXPORT KisPaintDevice : public QObject , public KisShared { Q_OBJECT public: /** * Create a new paint device with the specified colorspace. * * @param colorSpace the colorspace of this paint device * @param name for debugging purposes */ explicit KisPaintDevice(const KoColorSpace * colorSpace, const QString& name = QString()); /** * Create a new paint device with the specified colorspace. The * parent node will be notified of changes to this paint device. * * @param parent the node that contains this paint device * @param colorSpace the colorspace of this paint device * @param defaultBounds boundaries of the device in case it is empty * @param name for debugging purposes */ KisPaintDevice(KisNodeWSP parent, const KoColorSpace * colorSpace, KisDefaultBoundsBaseSP defaultBounds = KisDefaultBoundsBaseSP(), const QString& name = QString()); /** * Creates a copy of this device. * * If \p copyMode is CopySnapshot, the newly created device clones the * current frame of \p rhs only (default and efficient * behavior). If \p copyFrames is CopyAllFrames, the new device is a deep * copy of the source with all the frames included. */ KisPaintDevice(const KisPaintDevice& rhs, KritaUtils::DeviceCopyMode copyMode = KritaUtils::CopySnapshot, KisNode *newParentNode = 0); ~KisPaintDevice() override; protected: /** * A special constructor for usage in KisPixelSelection. It allows * two paint devices to share a data manager. * * @param explicitDataManager data manager to use inside paint device * @param src source paint device to copy parameters from * @param name for debugging purposes */ KisPaintDevice(KisDataManagerSP explicitDataManager, KisPaintDeviceSP src, const QString& name = QString()); public: /** * Write the pixels of this paint device into the specified file store. */ bool write(KisPaintDeviceWriter &store); /** * Fill this paint device with the pixels from the specified file store. */ bool read(QIODevice *stream); public: /** * set the parent node of the paint device */ void setParentNode(KisNodeWSP parent); /** * set the default bounds for the paint device when * the default pixel is not completely transparent */ void setDefaultBounds(KisDefaultBoundsBaseSP bounds); /** * the default bounds rect of the paint device */ KisDefaultBoundsBaseSP defaultBounds() const; /** * Moves the device to these new coordinates (no incremental move) */ void moveTo(qint32 x, qint32 y); /** * Convenience method for the above. */ virtual void moveTo(const QPoint& pt); /** * Return an X,Y offset of the device in a convenient form */ QPoint offset() const; /** * The X offset of the paint device */ qint32 x() const; /** * The Y offset of the paint device */ qint32 y() const; /** * set the X offset of the paint device */ void setX(qint32 x); /** * set the Y offset of the paint device */ void setY(qint32 y); /** * Retrieve the bounds of the paint device. The size is not exact, * but may be larger if the underlying datamanager works that way. * For instance, the tiled datamanager keeps the extent to the nearest * multiple of 64. * * If default pixel is not transparent, then the actual extent * rect is united with the defaultBounds()->bounds() value * (the size of the image, usually). */ QRect extent() const; /// Convenience method for the above void extent(qint32 &x, qint32 &y, qint32 &w, qint32 &h) const; /** * Get the exact bounds of this paint device. The real solution is * very slow because it does a linear scanline search, but it * uses caching, so calling to this function without changing * the device is quite cheap. * * Exactbounds follows these rules: * *

    *
  • if default pixel is transparent, then exact bounds * of actual pixel data are returned *
  • if default pixel is not transparent, then the union * (defaultBounds()->bounds() | nonDefaultPixelArea()) is * returned *
* \see calculateExactBounds() */ QRect exactBounds() const; /** * Relaxed version of the exactBounds() that can be used in tight * loops. If the exact bounds value is present in the paint * device cache, returns this value. If the cache is invalidated, * returns extent() and tries to recalculate the exact bounds not * faster than once in 1000 ms. */ QRect exactBoundsAmortized() const; /** * Returns exact rectangle of the paint device that contains * non-default pixels. For paint devices with fully transparent * default pixel is equivalent to exactBounds(). * * nonDefaultPixelArea() follows these rules: * *
    *
  • if default pixel is transparent, then exact bounds * of actual pixel data are returned. The same as exactBounds() *
  • if default pixel is not transparent, then calculates the * rectangle of non-default pixels. May be smaller or greater * than image bounds *
* \see calculateExactBounds() */ QRect nonDefaultPixelArea() const; /** * Returns a rough approximation of region covered by device. * For tiled data manager, it region will consist of a number * of rects each corresponding to a tile. */ QRegion region() const; /** * The slow version of region() that searches for exact bounds of * each rectangle in the region */ QRegion regionExact() const; /** * Cut the paint device down to the specified rect. If the crop * area is bigger than the paint device, nothing will happen. */ void crop(qint32 x, qint32 y, qint32 w, qint32 h); /// Convenience method for the above void crop(const QRect & r); /** * Complete erase the current paint device. Its size will become 0. This * does not take the selection into account. */ virtual void clear(); /** * Clear the given rectangle to transparent black. The paint device will expand to * contain the given rect. */ void clear(const QRect & rc); /** * Frees the memory occupied by the pixels containing default * values. The extents() and exactBounds() of the image will * probably also shrink */ void purgeDefaultPixels(); /** * Sets the default pixel. New data will be initialised with this pixel. The pixel is copied: the * caller still owns the pointer and needs to delete it to avoid memory leaks. * If frame ID is given, set default pixel for that frame. Otherwise use active frame. */ void setDefaultPixel(const KoColor &defPixel); /** * Get a pointer to the default pixel. * If the frame parameter is given, get the default pixel of * specified frame. Otherwise use currently active frame. */ KoColor defaultPixel() const; /** * Fill the given rectangle with the given pixel. The paint device will expand to * contain the given rect. */ void fill(const QRect & rc, const KoColor &color); /** * Overloaded function. For legacy purposes only. * Please use fill(const QRect & rc, const KoColor &color) instead */ void fill(qint32 x, qint32 y, qint32 w, qint32 h, const quint8 *fillPixel); public: /** * Prepares the device for fastBitBlt operation. It clears * the device, switches x,y shifts and colorspace if needed. * After this call fastBitBltPossible will return true. * May be used for initialization of temporary devices. */ void prepareClone(KisPaintDeviceSP src); /** * Make this device to become a clone of \a src. It will have the same * x,y shifts, colorspace and will share pixels inside \a rect. * After calling this function: * (this->extent() >= this->exactBounds() == rect). * * Rule of thumb: * * "Use makeCloneFrom() or makeCloneFromRough() if and only if you * are the only owner of the destination paint device and you are * 100% sure no other thread has access to it" */ void makeCloneFrom(KisPaintDeviceSP src, const QRect &rect); /** * Make this device to become a clone of \a src. It will have the same * x,y shifts, colorspace and will share pixels inside \a rect. * Be careful, this function will copy *at least* \a rect * of pixels. Actual copy area will be a bigger - it will * be aligned by tiles borders. So after calling this function: * (this->extent() == this->exactBounds() >= rect). * * Rule of thumb: * * "Use makeCloneFrom() or makeCloneFromRough() if and only if you * are the only owner of the destination paint device and you are * 100% sure no other thread has access to it" */ void makeCloneFromRough(KisPaintDeviceSP src, const QRect &minimalRect); protected: friend class KisPaintDeviceTest; friend class DataReaderThread; /** * Checks whether a src paint device can be used as source * of fast bitBlt operation. The result of the check may * depend on whether color spaces coincide, whether there is * any shift of tiles between the devices and etc. * * WARNING: This check must be done before performing any * fast bitBlt operation! * * \see fastBitBlt * \see fastBitBltRough */ bool fastBitBltPossible(KisPaintDeviceSP src); /** * Clones rect from another paint device. The cloned area will be * shared between both paint devices as much as possible using * copy-on-write. Parts of the rect that cannot be shared * (cross tiles) are deep-copied, * * \see fastBitBltPossible * \see fastBitBltRough */ void fastBitBlt(KisPaintDeviceSP src, const QRect &rect); /** * The same as \ref fastBitBlt() but reads old data */ void fastBitBltOldData(KisPaintDeviceSP src, const QRect &rect); /** * Clones rect from another paint device in a rough and fast way. * All the tiles touched by rect will be shared, between both * devices, that means it will copy a bigger area than was * requested. This method is supposed to be used for bitBlt'ing * into temporary paint devices. * * \see fastBitBltPossible * \see fastBitBlt */ void fastBitBltRough(KisPaintDeviceSP src, const QRect &rect); /** * The same as \ref fastBitBltRough() but reads old data */ void fastBitBltRoughOldData(KisPaintDeviceSP src, const QRect &rect); public: /** * Read the bytes representing the rectangle described by x, y, w, h into * data. If data is not big enough, Krita will gladly overwrite the rest * of your precious memory. * * Since this is a copy, you need to make sure you have enough memory. * * Reading from areas not previously initialized will read the default * pixel value into data but not initialize that region. */ void readBytes(quint8 * data, qint32 x, qint32 y, qint32 w, qint32 h) const; /** * Read the bytes representing the rectangle rect into * data. If data is not big enough, Krita will gladly overwrite the rest * of your precious memory. * * Since this is a copy, you need to make sure you have enough memory. * * Reading from areas not previously initialized will read the default * pixel value into data but not initialize that region. * @param data The address of the memory to receive the bytes read * @param rect The rectangle in the paint device to read from */ void readBytes(quint8 * data, const QRect &rect) const; /** * Copy the bytes in data into the rect specified by x, y, w, h. If the * data is too small or uninitialized, Krita will happily read parts of * memory you never wanted to be read. * * If the data is written to areas of the paint device not previously initialized, * the paint device will grow. */ void writeBytes(const quint8 * data, qint32 x, qint32 y, qint32 w, qint32 h); /** * Copy the bytes in data into the rectangle rect. If the * data is too small or uninitialized, Krita will happily read parts of * memory you never wanted to be read. * * If the data is written to areas of the paint device not previously initialized, * the paint device will grow. * @param data The address of the memory to write bytes from * @param rect The rectangle in the paint device to write to */ void writeBytes(const quint8 * data, const QRect &rect); /** * Copy the bytes in the paint device into a vector of arrays of bytes, * where the number of arrays is the number of channels in the * paint device. If the specified area is larger than the paint * device's extent, the default pixel will be read. */ QVector readPlanarBytes(qint32 x, qint32 y, qint32 w, qint32 h) const; /** * Write the data in the separate arrays to the channes. If there * are less vectors than channels, the remaining channels will not * be copied. If any of the arrays points to 0, the channel in * that location will not be touched. If the specified area is * larger than the paint device, the paint device will be * extended. There are no guards: if the area covers more pixels * than there are bytes in the arrays, krita will happily fill * your paint device with areas of memory you never wanted to be * read. Krita may also crash. * * XXX: what about undo? */ void writePlanarBytes(QVector planes, qint32 x, qint32 y, qint32 w, qint32 h); /** * Converts the paint device to a different colorspace * * @return a command that can be used to undo the conversion. */ KUndo2Command* convertTo(const KoColorSpace * dstColorSpace, KoColorConversionTransformation::Intent renderingIntent = KoColorConversionTransformation::internalRenderingIntent(), KoColorConversionTransformation::ConversionFlags conversionFlags = KoColorConversionTransformation::internalConversionFlags()); /** * Changes the profile of the colorspace of this paint device to the given * profile. If the given profile is 0, nothing happens. */ bool setProfile(const KoColorProfile * profile); /** * Fill this paint device with the data from image; starting at (offsetX, offsetY) * @param image the image * @param profile name of the RGB profile to interpret the image as. 0 is interpreted as sRGB * @param offsetX x offset * @param offsetY y offset */ void convertFromQImage(const QImage& image, const KoColorProfile *profile, qint32 offsetX = 0, qint32 offsetY = 0); /** * Create an RGBA QImage from a rectangle in the paint device. * + * @param dstProfile RGB profile to use in conversion. May be 0, in which + * case it's up to the color strategy to choose a profile (most + * like sRGB). * @param x Left coordinate of the rectangle * @param y Top coordinate of the rectangle * @param w Width of the rectangle in pixels * @param h Height of the rectangle in pixels - * @param dstProfile RGB profile to use in conversion. May be 0, in which - * case it's up to the color strategy to choose a profile (most - * like sRGB). + * @param renderingIntent Rendering intent + * @param conversionFlags Conversion flags */ QImage convertToQImage(const KoColorProfile *dstProfile, qint32 x, qint32 y, qint32 w, qint32 h, KoColorConversionTransformation::Intent renderingIntent = KoColorConversionTransformation::internalRenderingIntent(), KoColorConversionTransformation::ConversionFlags conversionFlags = KoColorConversionTransformation::internalConversionFlags()) const; /** * Overridden method for convenience */ QImage convertToQImage(const KoColorProfile *dstProfile, const QRect &rc, KoColorConversionTransformation::Intent renderingIntent = KoColorConversionTransformation::internalRenderingIntent(), KoColorConversionTransformation::ConversionFlags conversionFlags = KoColorConversionTransformation::internalConversionFlags()) const; /** * Create an RGBA QImage from a rectangle in the paint device. The * rectangle is defined by the parent image's bounds. * * @param dstProfile RGB profile to use in conversion. May be 0, in which * case it's up to the color strategy to choose a profile (most * like sRGB). + * @param renderingIntent Rendering intent + * @param conversionFlags Conversion flags */ QImage convertToQImage(const KoColorProfile * dstProfile, KoColorConversionTransformation::Intent renderingIntent = KoColorConversionTransformation::internalRenderingIntent(), KoColorConversionTransformation::ConversionFlags conversionFlags = KoColorConversionTransformation::internalConversionFlags()) const; /** * Creates a paint device thumbnail of the paint device, retaining * the aspect ratio. The width and height of the returned device * won't exceed \p maxw and \p maxw, but they may be smaller. * * @param w maximum width * @param h maximum height * @param rect only this rect will be used for the thumbnail * @param outputRect output rectangle * */ KisPaintDeviceSP createThumbnailDevice(qint32 w, qint32 h, QRect rect = QRect(), QRect outputRect = QRect()) const; KisPaintDeviceSP createThumbnailDeviceOversampled(qint32 w, qint32 h, qreal oversample, QRect rect = QRect(), QRect outputRect = QRect()) const; /** * Creates a thumbnail of the paint device, retaining the aspect ratio. * The width and height of the returned QImage won't exceed \p maxw and \p maxw, but they may be smaller. * The colors are not corrected for display! * * @param maxw: maximum width * @param maxh: maximum height * @param rect: only this rect will be used for the thumbnail * @param oversample: ratio used for antialiasing + * @param renderingIntent Rendering intent + * @param conversionFlags Conversion flags */ QImage createThumbnail(qint32 maxw, qint32 maxh, QRect rect, qreal oversample = 1, KoColorConversionTransformation::Intent renderingIntent = KoColorConversionTransformation::internalRenderingIntent(), KoColorConversionTransformation::ConversionFlags conversionFlags = KoColorConversionTransformation::internalConversionFlags()); /** * Cached version of createThumbnail(qint32 maxw, qint32 maxh, const KisSelection *selection, QRect rect) */ QImage createThumbnail(qint32 maxw, qint32 maxh, qreal oversample = 1, KoColorConversionTransformation::Intent renderingIntent = KoColorConversionTransformation::internalRenderingIntent(), KoColorConversionTransformation::ConversionFlags conversionFlags = KoColorConversionTransformation::internalConversionFlags()); /** * Fill c and opacity with the values found at x and y. * * The color values will be transformed from the profile of * this paint device to the display profile. * * @return true if the operation was successful. */ bool pixel(qint32 x, qint32 y, QColor *c) const; /** * Fill kc with the values found at x and y. This method differs * from the above in using KoColor, which can be of any colorspace * * The color values will be transformed from the profile of * this paint device to the display profile. * * @return true if the operation was successful. */ bool pixel(qint32 x, qint32 y, KoColor * kc) const; /** * Set the specified pixel to the specified color. Note that this * bypasses KisPainter. the PaintDevice is here used as an equivalent * to QImage, not QPixmap. This means that this is not undoable; also, * there is no compositing with an existing value at this location. * * The color values will be transformed from the display profile to * the paint device profile. * * Note that this will use 8-bit values and may cause a significant * degradation when used on 16-bit or hdr quality images. * * @return true if the operation was successful */ bool setPixel(qint32 x, qint32 y, const QColor& c); /// Convenience method for the above bool setPixel(qint32 x, qint32 y, const KoColor& kc); /** * @return the colorspace of the pixels in this paint device */ const KoColorSpace* colorSpace() const; /** * There is quite a common technique in Krita. It is used in * cases, when we want to paint something over a paint device * using the composition, opacity or selection. E.g. painting a * dab in a paint op, filling the selection in the Fill Tool. * Such work is usually done in the following way: * * 1) Create a paint device * * 2) Fill it with the desired color or data * * 3) Create a KisPainter and set all the properties of the * transaction: selection, compositeOp, opacity and etc. * * 4) Paint a newly created paint device over the destination * device. * * The following two methods (createCompositionSourceDevice() or * createCompositionSourceDeviceFixed())should be used for the * accomplishing the step 1). The point is that the desired color * space of the temporary device may not coincide with the color * space of the destination. That is the case, for example, for * the alpha8() colorspace used in the selections. So for such * devices the temporary target would have a different (grayscale) * color space. * * So there are two rules of thumb: * * 1) If you need a temporary device which you are going to fill * with some data and then paint over the paint device, create * it with either createCompositionSourceDevice() or * createCompositionSourceDeviceFixed(). * * 2) Do *not* expect that the color spaces of the destination and * the temporary device would coincide. If you need to copy a * single pixel from one device to another, you can use * KisCrossDeviceColorPicker class, that will handle all the * necessary conversions for you. * * \see createCompositionSourceDeviceFixed() * \see compositionSourceColorSpace() * \see KisCrossDeviceColorPicker * \see KisCrossDeviceColorPickerInt */ KisPaintDeviceSP createCompositionSourceDevice() const; /** * The same as createCompositionSourceDevice(), but initializes the * newly created device with the content of \p cloneSource * * \see createCompositionSourceDevice() */ KisPaintDeviceSP createCompositionSourceDevice(KisPaintDeviceSP cloneSource) const; /** * The same as createCompositionSourceDevice(), but initializes * the newly created device with the *rough* \p roughRect of * \p cloneSource. * * "Rough rect" means that it may copy a bit more than * requested. It is expected that the caller will not use the area * outside \p roughRect. * * \see createCompositionSourceDevice() */ KisPaintDeviceSP createCompositionSourceDevice(KisPaintDeviceSP cloneSource, const QRect roughRect) const; /** * This is a convenience method for createCompositionSourceDevice() * * \see createCompositionSourceDevice() */ KisFixedPaintDeviceSP createCompositionSourceDeviceFixed() const; /** * This is a lowlevel method for the principle used in * createCompositionSourceDevice(). In most of the cases the paint * device creation methods should be used instead of this function. * * \see createCompositionSourceDevice() * \see createCompositionSourceDeviceFixed() */ virtual const KoColorSpace* compositionSourceColorSpace() const; /** * @return the internal datamanager that keeps the pixels. */ KisDataManagerSP dataManager() const; /** * Replace the pixel data, color strategy, and profile. */ void setDataManager(KisDataManagerSP data, const KoColorSpace * colorSpace = 0); /** * Return the number of bytes a pixel takes. */ quint32 pixelSize() const; /** * Return the number of channels a pixel takes */ quint32 channelCount() const; /** * Create a keyframe channel for the content on this device. * @param id identifier for the channel * @return keyframe channel or 0 if there is not one */ KisRasterKeyframeChannel *createKeyframeChannel(const KoID &id); KisRasterKeyframeChannel* keyframeChannel() const; /** * An interface to modify/load/save frames stored inside this device */ KisPaintDeviceFramesInterface* framesInterface(); public: /** * Add the specified rect to the parent layer's set of dirty rects * (if there is a parent layer) */ void setDirty(const QRect & rc); /** * Add the specified region to the parent layer's dirty region * (if there is a parent layer) */ void setDirty(const QRegion & region); /** * Set the parent layer completely dirty, if this paint device has * as parent layer. */ void setDirty(); void setDirty(const QVector rects); /** * Called by KisTransactionData when it thinks current time should * be changed. And the requests is forwarded to the image if * needed. */ void requestTimeSwitch(int time); /** * \return a sequence number corresponding to the current paint * device state. Every time the paint device is changed, * the sequence number is increased */ int sequenceNumber() const; void estimateMemoryStats(qint64 &imageData, qint64 &temporaryData, qint64 &lodData) const; public: KisHLineIteratorSP createHLineIteratorNG(qint32 x, qint32 y, qint32 w); KisHLineConstIteratorSP createHLineConstIteratorNG(qint32 x, qint32 y, qint32 w) const; KisVLineIteratorSP createVLineIteratorNG(qint32 x, qint32 y, qint32 h); KisVLineConstIteratorSP createVLineConstIteratorNG(qint32 x, qint32 y, qint32 h) const; KisRandomAccessorSP createRandomAccessorNG(qint32 x, qint32 y); KisRandomConstAccessorSP createRandomConstAccessorNG(qint32 x, qint32 y) const; /** * Create an iterator that will "artificially" extend the paint device with the * value of the border when trying to access values outside the range of data. * + * @param x x of top left corner + * @param y y of top left corner + * @param w width of the border * @param _dataWidth indicates the rectangle that truly contains data */ KisRepeatHLineConstIteratorSP createRepeatHLineConstIterator(qint32 x, qint32 y, qint32 w, const QRect& _dataWidth) const; /** * Create an iterator that will "artificially" extend the paint device with the * value of the border when trying to access values outside the range of data. * + * @param x x of top left corner + * @param y y of top left corner + * @param h height of the border * @param _dataWidth indicates the rectangle that truly contains data */ KisRepeatVLineConstIteratorSP createRepeatVLineConstIterator(qint32 x, qint32 y, qint32 h, const QRect& _dataWidth) const; /** * This function create a random accessor which can easily access to sub pixel values. */ KisRandomSubAccessorSP createRandomSubAccessor() const; /** Clear the selected pixels from the paint device */ void clearSelection(KisSelectionSP selection); Q_SIGNALS: void profileChanged(const KoColorProfile * profile); void colorSpaceChanged(const KoColorSpace *colorspace); public: friend class PaintDeviceCache; /** * Caclculates exact bounds of the device. Used internally * by a transparent caching system. The solution is very slow * because it does a linear scanline search. So the complexity * is n*n at worst. * * \see exactBounds(), nonDefaultPixelArea() */ QRect calculateExactBounds(bool nonDefaultOnly) const; public: struct MemoryReleaseObject : public QObject { ~MemoryReleaseObject() override; }; static MemoryReleaseObject* createMemoryReleaseObject(); public: struct LodDataStruct { virtual ~LodDataStruct(); }; QRegion regionForLodSyncing() const; LodDataStruct* createLodDataStruct(int lod); void updateLodDataStruct(LodDataStruct *dst, const QRect &srcRect); void uploadLodDataStruct(LodDataStruct *dst); void generateLodCloneDevice(KisPaintDeviceSP dst, const QRect &originalRect, int lod); void setProjectionDevice(bool value); void tesingFetchLodDevice(KisPaintDeviceSP targetDevice); private: KisPaintDevice& operator=(const KisPaintDevice&); void init(const KoColorSpace *colorSpace, KisDefaultBoundsBaseSP defaultBounds, KisNodeWSP parent, const QString& name); // Only KisPainter is allowed to have access to these low-level methods friend class KisPainter; /** * Return a vector with in order the size in bytes of the channels * in the colorspace of this paint device. */ QVector channelSizes() const; void emitColorSpaceChanged(); void emitProfileChanged(); private: friend class KisPaintDeviceFramesInterface; protected: friend class KisSelectionTest; KisNodeWSP parentNode() const; private: struct Private; Private * const m_d; }; #endif // KIS_PAINT_DEVICE_IMPL_H_ diff --git a/libs/image/kis_repeat_iterators_pixel.h b/libs/image/kis_repeat_iterators_pixel.h index 1132185fae..acc6289ddf 100644 --- a/libs/image/kis_repeat_iterators_pixel.h +++ b/libs/image/kis_repeat_iterators_pixel.h @@ -1,268 +1,280 @@ /* * Copyright (c) 2008 Cyrille Berger * * 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_REPEAT_ITERATORS_PIXEL_H_ #define _KIS_REPEAT_ITERATORS_PIXEL_H_ #include #include "kis_shared.h" #include "tiles3/kis_hline_iterator.h" #include "tiles3/kis_vline_iterator.h" template class KisRepeatHLineIteratorPixelBase; template class KisRepeatVLineIteratorPixelBase; /** * This iterator is an iterator that will "artificially" extend the paint device with the * value of the border when trying to access values outside the range of data. */ template class KisRepeatLineIteratorPixelBase : public KisShared { Q_DISABLE_COPY(KisRepeatLineIteratorPixelBase) public: friend class KisRepeatHLineIteratorPixelBase; friend class KisRepeatVLineIteratorPixelBase; /** + * @param dm data manager + * @param x x of top left corner + * @param y y of top left corner + * @param offsetx x offset + * @param offsety y offset * @param _rc indicates the rectangle that truly contains data + * @param completeListener completion listener */ inline KisRepeatLineIteratorPixelBase(KisDataManager *dm, qint32 x, qint32 y, qint32 offsetx, qint32 offsety, const QRect& _rc, KisIteratorCompleteListener *completeListener); virtual inline ~KisRepeatLineIteratorPixelBase(); public: inline qint32 x() const { return m_realX; } inline qint32 y() const { return m_realY; } inline const quint8 * oldRawData() const { return m_iterator->oldRawData(); } private: KisDataManager* m_dm; qint32 m_realX, m_realY; qint32 m_offsetX, m_offsetY; QRect m_dataRect; T* m_iterator; KisIteratorCompleteListener *m_completeListener; }; /** * This iterator is an iterator that will "artificially" extend the paint device with the * value of the border when trying to access values outside the range of data. */ template class KisRepeatHLineIteratorPixelBase : public KisRepeatLineIteratorPixelBase { public: /** + * @param dm data manager + * @param x x of top left corner + * @param y y of top left corner + * @param offsetx x offset + * @param offsety y offset * @param _rc indicates the rectangle that truly contains data + * @param completeListener completion listener */ inline KisRepeatHLineIteratorPixelBase(KisDataManager *dm, qint32 x, qint32 y, qint32 w, qint32 offsetx, qint32 offsety, const QRect& _rc, KisIteratorCompleteListener *completeListener); inline ~KisRepeatHLineIteratorPixelBase() override; inline bool nextPixel(); /** * Reach next row. */ inline void nextRow(); private: void createIterator(); private: qint32 m_startX; qint32 m_startIteratorX; qint32 m_width; }; /** * This iterator is an iterator that will "artificially" extend the paint device with the * value of the border when trying to access values outside the range of data. */ template class KisRepeatVLineIteratorPixelBase : public KisRepeatLineIteratorPixelBase { public: /** * @param _rc indicates the rectangle that truly contains data */ inline KisRepeatVLineIteratorPixelBase(KisDataManager *dm, qint32 x, qint32 y, qint32 h, qint32 offsetx, qint32 offsety, const QRect& _rc, KisIteratorCompleteListener *completeListener); inline ~KisRepeatVLineIteratorPixelBase() override; inline KisRepeatVLineIteratorPixelBase & operator ++(); inline bool nextPixel(); /** * Reach next row. */ inline void nextColumn(); private: void createIterator(); private: qint32 m_startY; qint32 m_startIteratorY; qint32 m_height; }; //------------------------ Implementations ------------------------// //---------------- KisRepeatLineIteratorPixelBase -----------------// template KisRepeatLineIteratorPixelBase::KisRepeatLineIteratorPixelBase(KisDataManager *dm, qint32 x, qint32 y, qint32 offsetx, qint32 offsety, const QRect& _rc, KisIteratorCompleteListener *completeListener) : m_dm(dm), m_realX(x), m_realY(y), m_offsetX(offsetx), m_offsetY(offsety), m_dataRect(_rc), m_iterator(0), m_completeListener(completeListener) { } template KisRepeatLineIteratorPixelBase::~KisRepeatLineIteratorPixelBase() { delete m_iterator; } //---------------- KisRepeatHLineIteratorPixelBase ----------------// template KisRepeatHLineIteratorPixelBase::KisRepeatHLineIteratorPixelBase(KisDataManager *dm, qint32 x, qint32 y, qint32 w, qint32 offsetx, qint32 offsety, const QRect& _rc, KisIteratorCompleteListener *completeListener) : KisRepeatLineIteratorPixelBase(dm, x, y, offsetx, offsety , _rc, completeListener), m_startX(x), m_startIteratorX(x), m_width(w) { // Compute the startx value of the iterator if (m_startIteratorX < _rc.left()) { m_startIteratorX = _rc.left(); } createIterator(); } template KisRepeatHLineIteratorPixelBase::~KisRepeatHLineIteratorPixelBase() { } template inline bool KisRepeatHLineIteratorPixelBase::nextPixel() { Q_ASSERT(this->m_iterator); if (this->m_realX >= this->m_dataRect.x() && this->m_realX < this->m_dataRect.x() + this->m_dataRect.width() - 1) { this->m_iterator->nextPixel(); } ++this->m_realX; return (this->m_realX < m_startX + m_width); } template inline void KisRepeatHLineIteratorPixelBase::nextRow() { if (this->m_realY >= this->m_dataRect.y() && this->m_realY < this->m_dataRect.y() + this->m_dataRect.height() - 1) { this->m_iterator->nextRow(); } else { createIterator(); } this->m_realX = this->m_startX; ++this->m_realY; } template void KisRepeatHLineIteratorPixelBase::createIterator() { // Cleanup delete this->m_iterator; qint32 startY = this->m_realY; if (startY < this->m_dataRect.y()) { startY = this->m_dataRect.top(); } if (startY > (this->m_dataRect.y() + this->m_dataRect.height() - 1)) { startY = (this->m_dataRect.y() + this->m_dataRect.height() - 1); } int width = this->m_dataRect.x() + this->m_dataRect.width() - this->m_startIteratorX; this->m_iterator = new T(this->m_dm, this->m_startIteratorX, startY, width, this->m_offsetX, this->m_offsetY, false, this->m_completeListener); this->m_realX = this->m_startX; } //---------------- KisRepeatVLineIteratorPixelBase ----------------// template KisRepeatVLineIteratorPixelBase::KisRepeatVLineIteratorPixelBase(KisDataManager *dm, qint32 x, qint32 y, qint32 h, qint32 offsetx, qint32 offsety, const QRect& _rc, KisIteratorCompleteListener *completeListener) : KisRepeatLineIteratorPixelBase(dm, x, y, offsetx, offsety , _rc, completeListener), m_startY(y), m_startIteratorY(y), m_height(h) { // Compute the startx value of the iterator if (m_startIteratorY < _rc.top()) { m_startIteratorY = _rc.top(); } createIterator(); } template KisRepeatVLineIteratorPixelBase::~KisRepeatVLineIteratorPixelBase() { } template inline bool KisRepeatVLineIteratorPixelBase::nextPixel() { Q_ASSERT(this->m_iterator); if (this->m_realY >= this->m_dataRect.y() && this->m_realY < this->m_dataRect.y() + this->m_dataRect.height() - 1) { this->m_iterator->nextPixel(); } ++this->m_realY; return (this->m_realY < m_startY + m_height); } template inline void KisRepeatVLineIteratorPixelBase::nextColumn() { if (this->m_realX >= this->m_dataRect.x() && this->m_realX < this->m_dataRect.x() + this->m_dataRect.width() - 1) { this->m_iterator->nextColumn(); } else { createIterator(); } this->m_realY = this->m_startY; ++this->m_realX; } template void KisRepeatVLineIteratorPixelBase::createIterator() { // Cleanup delete this->m_iterator; qint32 startX = this->m_realX; if (startX < this->m_dataRect.x()) { startX = this->m_dataRect.x(); } if (startX > (this->m_dataRect.x() + this->m_dataRect.width() - 1)) { startX = (this->m_dataRect.x() + this->m_dataRect.width() - 1); } int height = this->m_dataRect.y() + this->m_dataRect.height() - this->m_startIteratorY; this->m_iterator = new T(this->m_dm, startX, this->m_startIteratorY, height, this->m_offsetX, this->m_offsetY, false, this->m_completeListener); this->m_realY = this->m_startY; } #endif diff --git a/libs/image/tiles3/kis_tiled_data_manager.h b/libs/image/tiles3/kis_tiled_data_manager.h index b6f8384d17..0ddb815456 100644 --- a/libs/image/tiles3/kis_tiled_data_manager.h +++ b/libs/image/tiles3/kis_tiled_data_manager.h @@ -1,420 +1,430 @@ /* * Copyright (c) 2004 Boudewijn Rempt * (c) 2009 Dmitry Kazakov * * 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_TILEDDATAMANAGER_H_ #define KIS_TILEDDATAMANAGER_H_ #include #include #include #include #include #include "config-hash-table-implementaion.h" //#include "kis_debug.h" #include "kritaimage_export.h" #ifdef USE_LOCK_FREE_HASH_TABLE #include "kis_tile_hash_table2.h" #else #include "kis_tile_hash_table.h" #endif // USE_LOCK_FREE_HASH_TABLE #include "kis_memento_manager.h" #include "kis_memento.h" #include "KisTiledExtentManager.h" class KisTiledDataManager; typedef KisSharedPtr KisTiledDataManagerSP; class KisTiledIterator; class KisTiledRandomAccessor; class KisPaintDeviceWriter; class QIODevice; /** * KisTiledDataManager implements the interface that KisDataManager defines * * The interface definition is enforced by KisDataManager calling all the methods * which must also be defined in KisTiledDataManager. It is not allowed to change the interface * as other datamangers may also rely on the same interface. * * * Storing undo/redo data * * Offering ordered and unordered iterators over rects of pixels * * (eventually) efficiently loading and saving data in a format * that may allow deferred loading. * * A datamanager knows nothing about the type of pixel data except * how many quint8's a single pixel takes. */ class KRITAIMAGE_EXPORT KisTiledDataManager : public KisShared { private: static const qint32 LEGACY_VERSION = 1; static const qint32 CURRENT_VERSION = 2; protected: /*FIXME:*/ public: KisTiledDataManager(quint32 pixelSize, const quint8 *defPixel); virtual ~KisTiledDataManager(); KisTiledDataManager(const KisTiledDataManager &dm); KisTiledDataManager & operator=(const KisTiledDataManager &dm); protected: // Allow the baseclass of iterators access to the interior // derived iterator classes must go through KisTiledIterator friend class KisTiledIterator; friend class KisBaseIterator; friend class KisTiledRandomAccessor; friend class KisRandomAccessor2; friend class KisStressJob; public: void setDefaultPixel(const quint8 *defPixel); const quint8 *defaultPixel() const { return m_defaultPixel; } /** * Every iterator fetches both types of tiles all the time: old and new. * For projection devices these tiles are **always** the same, but doing * two distinct calls makes double pressure on the read-write lock in the * hash table. * * Merging two calls into one allows us to avoid additional tile fetch from * the hash table and therefore reduce waiting time. */ inline void getTilesPair(qint32 col, qint32 row, bool writable, KisTileSP *tile, KisTileSP *oldTile) { *tile = getTile(col, row, writable); bool unused; *oldTile = m_mementoManager->getCommitedTile(col, row, unused); if (!*oldTile) { *oldTile = *tile; } } inline KisTileSP getTile(qint32 col, qint32 row, bool writable) { if (writable) { bool newTile; KisTileSP tile = m_hashTable->getTileLazy(col, row, newTile); if (newTile) { m_extentManager.notifyTileAdded(col, row); } return tile; } else { bool unused; return m_hashTable->getReadOnlyTileLazy(col, row, unused); } } inline KisTileSP getReadOnlyTileLazy(qint32 col, qint32 row, bool &existingTile) { return m_hashTable->getReadOnlyTileLazy(col, row, existingTile); } inline KisTileSP getOldTile(qint32 col, qint32 row, bool &existingTile) { KisTileSP tile = m_mementoManager->getCommitedTile(col, row, existingTile); return tile ? tile : getReadOnlyTileLazy(col, row, existingTile); } inline KisTileSP getOldTile(qint32 col, qint32 row) { bool unused; return getOldTile(col, row, unused); } KisMementoSP getMemento() { QWriteLocker locker(&m_lock); KisMementoSP memento = m_mementoManager->getMemento(); memento->saveOldDefaultPixel(m_defaultPixel, m_pixelSize); return memento; } /** * Finishes having already started transaction */ void commit() { QWriteLocker locker(&m_lock); KisMementoSP memento = m_mementoManager->currentMemento(); if(memento) { memento->saveNewDefaultPixel(m_defaultPixel, m_pixelSize); } m_mementoManager->commit(); } void rollback(KisMementoSP memento) { commit(); QWriteLocker locker(&m_lock); m_mementoManager->rollback(m_hashTable); const quint8 *defaultPixel = memento->oldDefaultPixel(); if(memcmp(m_defaultPixel, defaultPixel, m_pixelSize)) { setDefaultPixelImpl(defaultPixel); } recalculateExtent(); } void rollforward(KisMementoSP memento) { commit(); QWriteLocker locker(&m_lock); m_mementoManager->rollforward(m_hashTable); const quint8 *defaultPixel = memento->newDefaultPixel(); if(memcmp(m_defaultPixel, defaultPixel, m_pixelSize)) { setDefaultPixelImpl(defaultPixel); } recalculateExtent(); } bool hasCurrentMemento() const { return m_mementoManager->hasCurrentMemento(); //return true; } /** * Removes all the history that preceds the revision * pointed by oldestMemento. That is after calling to * purgeHistory(someMemento) you won't be able to do * rollback(someMemento) anymore. */ void purgeHistory(KisMementoSP oldestMemento) { QWriteLocker locker(&m_lock); m_mementoManager->purgeHistory(oldestMemento); } static void releaseInternalPools(); protected: /** * Reads and writes the tiles */ bool write(KisPaintDeviceWriter &store); bool read(QIODevice *stream); void purge(const QRect& area); inline quint32 pixelSize() const { return m_pixelSize; } /* FIXME:*/ public: void extent(qint32 &x, qint32 &y, qint32 &w, qint32 &h) const; void setExtent(qint32 x, qint32 y, qint32 w, qint32 h); QRect extent() const; void setExtent(QRect newRect); QRegion region() const; void clear(QRect clearRect, quint8 clearValue); void clear(QRect clearRect, const quint8 *clearPixel); void clear(qint32 x, qint32 y, qint32 w, qint32 h, quint8 clearValue); void clear(qint32 x, qint32 y, qint32 w, qint32 h, const quint8 *clearPixel); void clear(); /** * Clones rect from another datamanager. The cloned area will be * shared between both datamanagers as much as possible using * copy-on-write. Parts of the rect that cannot be shared * (cross tiles) are deep-copied, */ void bitBlt(KisTiledDataManager *srcDM, const QRect &rect); /** * The same as \ref bitBlt(), but reads old data */ void bitBltOldData(KisTiledDataManager *srcDM, const QRect &rect); /** * Clones rect from another datamanager in a rough and fast way. * All the tiles touched by rect will be shared, between both * managers, that means it will copy a bigger area than was * requested. This method is supposed to be used for bitBlt'ing * into temporary paint devices. */ void bitBltRough(KisTiledDataManager *srcDM, const QRect &rect); /** * The same as \ref bitBltRough(), but reads old data */ void bitBltRoughOldData(KisTiledDataManager *srcDM, const QRect &rect); /** * write the specified data to x, y. There is no checking on pixelSize! */ void setPixel(qint32 x, qint32 y, const quint8 * data); /** * Copy the bytes in the specified rect to a vector. The caller is responsible * for managing the vector. * + * \param bytes the bytes + * \param x x of top left corner + * \param y y of top left corner + * \param w width + * \param h height * \param dataRowStride is the step (in bytes) which should be * added to \p bytes pointer to get to the * next row */ void readBytes(quint8 * bytes, qint32 x, qint32 y, qint32 w, qint32 h, qint32 dataRowStride = -1) const; /** * Copy the bytes in the vector to the specified rect. If there are bytes left * in the vector after filling the rect, they will be ignored. If there are * not enough bytes, the rest of the rect will be filled with the default value * given (by default, 0); * + * \param bytes the bytes + * \param x x of top left corner + * \param y y of top left corner + * \param w width + * \param h height * \param dataRowStride is the step (in bytes) which should be * added to \p bytes pointer to get to the * next row */ void writeBytes(const quint8 * bytes, qint32 x, qint32 y, qint32 w, qint32 h, qint32 dataRowStride = -1); /** * Copy the bytes in the paint device into a vector of arrays of bytes, * where the number of arrays is the number of channels in the * paint device. If the specified area is larger than the paint * device's extent, the default pixel will be read. */ QVector readPlanarBytes(QVector channelsizes, qint32 x, qint32 y, qint32 w, qint32 h) const; /** * Write the data in the separate arrays to the channels. If there * are less vectors than channels, the remaining channels will not * be copied. If any of the arrays points to 0, the channel in * that location will not be touched. If the specified area is * larger than the paint device, the paint device will be * extended. There are no guards: if the area covers more pixels * than there are bytes in the arrays, krita will happily fill * your paint device with areas of memory you never wanted to be * read. Krita may also crash. */ void writePlanarBytes(QVector planes, QVector channelsizes, qint32 x, qint32 y, qint32 w, qint32 h); /** * Get the number of contiguous columns starting at x, valid for all values * of y between minY and maxY. */ qint32 numContiguousColumns(qint32 x, qint32 minY, qint32 maxY) const; /** * Get the number of contiguous rows starting at y, valid for all values * of x between minX and maxX. */ qint32 numContiguousRows(qint32 y, qint32 minX, qint32 maxX) const; /** * Get the row stride at pixel (x, y). This is the number of bytes to add to a * pointer to pixel (x, y) to access (x, y + 1). */ qint32 rowStride(qint32 x, qint32 y) const; private: KisTileHashTable *m_hashTable; KisMementoManager *m_mementoManager; quint8* m_defaultPixel; qint32 m_pixelSize; KisTiledExtentManager m_extentManager; mutable QReadWriteLock m_lock; private: // Allow compression routines to calculate (col,row) coordinates // and pixel size friend class KisAbstractTileCompressor; friend class KisTileDataWrapper; qint32 xToCol(qint32 x) const; qint32 yToRow(qint32 y) const; private: void setDefaultPixelImpl(const quint8 *defPixel); bool writeTilesHeader(KisPaintDeviceWriter &store, quint32 numTiles); bool processTilesHeader(QIODevice *stream, quint32 &numTiles); qint32 divideRoundDown(qint32 x, const qint32 y) const; void recalculateExtent(); quint8* duplicatePixel(qint32 num, const quint8 *pixel); template void bitBltImpl(KisTiledDataManager *srcDM, const QRect &rect); template void bitBltRoughImpl(KisTiledDataManager *srcDM, const QRect &rect); void writeBytesBody(const quint8 *data, qint32 x, qint32 y, qint32 width, qint32 height, qint32 dataRowStride = -1); void readBytesBody(quint8 *data, qint32 x, qint32 y, qint32 width, qint32 height, qint32 dataRowStride = -1) const; template void writePlanarBytesBody(QVector planes, QVector channelsizes, qint32 x, qint32 y, qint32 w, qint32 h); QVector readPlanarBytesBody(QVector channelsizes, qint32 x, qint32 y, qint32 w, qint32 h) const; public: void debugPrintInfo() { m_mementoManager->debugPrintInfo(); } }; inline qint32 KisTiledDataManager::divideRoundDown(qint32 x, const qint32 y) const { /** * Equivalent to the following: * -(( -x + (y-1) ) / y) */ return x >= 0 ? x / y : -(((-x - 1) / y) + 1); } inline qint32 KisTiledDataManager::xToCol(qint32 x) const { return divideRoundDown(x, KisTileData::WIDTH); } inline qint32 KisTiledDataManager::yToRow(qint32 y) const { return divideRoundDown(y, KisTileData::HEIGHT); } // during development the following line helps to check the interface is correct // it should be safe to keep it here even during normal compilation //#include "kis_datamanager.h" #endif // KIS_TILEDDATAMANAGER_H_ diff --git a/libs/image/tiles3/swap/kis_abstract_compression.h b/libs/image/tiles3/swap/kis_abstract_compression.h index 31e7ca0a73..c34eb7ed37 100644 --- a/libs/image/tiles3/swap/kis_abstract_compression.h +++ b/libs/image/tiles3/swap/kis_abstract_compression.h @@ -1,88 +1,94 @@ /* * Copyright (c) 2010 Dmitry Kazakov * * 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_ABSTRACT_COMPRESSION_H #define __KIS_ABSTRACT_COMPRESSION_H #include "kritaimage_export.h" #include /** * Base class for compression operations */ class KRITAIMAGE_EXPORT KisAbstractCompression { public: KisAbstractCompression(); virtual ~KisAbstractCompression(); /** - * Compresses \a input buffer into \a output buffer. + * Compresses \p input buffer into \p output buffer. * WARNING: Be careful, output buffer must be at least * outputBufferSize(inputLength) size! + * \param input the input + * \param inputLength the input length + * \param output the output * \param outputLength is not used! * \return number of bytes written to the output buffer * and 0 if error occurred. * * \see outputBufferSize() */ virtual qint32 compress(const quint8* input, qint32 inputLength, quint8* output, qint32 outputLength) = 0; /** - * Decompresses \a input buffer into \a output buffer. + * Decompresses \p input buffer into \p output buffer. * WARNING: output buffer must be able to fit the input data + * \param input the input + * \param inputLength the input length + * \param output the output * \param outputLength is not used! * \return number of bytes written to the output buffer * and 0 if error occurred. */ virtual qint32 decompress(const quint8* input, qint32 inputLength, quint8* output, qint32 outputLength) = 0; /** * Returns minimal allowed size of output buffer for compression */ virtual qint32 outputBufferSize(qint32 dataSize) = 0; /** * Some algorithms may decide to optimize them work depending on * the usual size of the data. * Default implementation of KisAbstractCompression class does nothing. */ virtual void adjustForDataSize(qint32 dataSize); public: /** * Additional interface for jumbling color channels order */ /** * e.g. RGBARGBARGBA -> RRRGGGBBBAAA * NOTE: performs mixing of bytes, not channels! */ static void linearizeColors(quint8 *input, quint8 *output, qint32 dataSize, qint32 pixelSize); /** * e.g. RRRGGGBBBAAA -> RGBARGBARGBA * NOTE: performs mixing of bytes, not channels! */ static void delinearizeColors(quint8 *input, quint8 *output, qint32 dataSize, qint32 pixelSize); }; #endif /* __KIS_ABSTRACT_COMPRESSION_H */ diff --git a/libs/image/tiles3/swap/kis_abstract_tile_compressor.h b/libs/image/tiles3/swap/kis_abstract_tile_compressor.h index d5cbdfb6cd..1acd1eb847 100644 --- a/libs/image/tiles3/swap/kis_abstract_tile_compressor.h +++ b/libs/image/tiles3/swap/kis_abstract_tile_compressor.h @@ -1,103 +1,108 @@ /* * Copyright (c) 2010 Dmitry Kazakov * * 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_ABSTRACT_TILE_COMPRESSOR_H #define __KIS_ABSTRACT_TILE_COMPRESSOR_H #include "kritaimage_export.h" #include "../kis_tile.h" #include "../kis_tiled_data_manager.h" class KisPaintDeviceWriter; /** * Base class for compressing a tile and wrapping it with a header */ class KisAbstractTileCompressor; typedef KisSharedPtr KisAbstractTileCompressorSP; class KRITAIMAGE_EXPORT KisAbstractTileCompressor : public KisShared { public: KisAbstractTileCompressor(); virtual ~KisAbstractTileCompressor(); public: /** * Compresses the \a tile and writes it into the \a stream. * Used by datamanager in load/save routines * * \see compressTile() */ virtual bool writeTile(KisTileSP tile, KisPaintDeviceWriter &store) = 0; /** * Decompresses the \a tile from the \a stream. * Used by datamanager in load/save routines * * \see decompressTile() */ virtual bool readTile(QIODevice *stream, KisTiledDataManager *dm) = 0; /** - * Compresses a \a tileData and writes it into the \a buffer. + * Compresses a \p tileData and writes it into the \p buffer. * The buffer must be at least tileDataBufferSize() bytes long. * Actual number of bytes written is returned using out-parameter - * \a bytesWritten + * \p bytesWritten * * \param tileData an existing tile data. It should be created * and acquired by the caller. + * \param buffer the buffer + * \param bufferSize the size of the buffer + * \param bytesWritten the number of written bytes * * \see tileDataBufferSize() */ virtual void compressTileData(KisTileData *tileData,quint8 *buffer, qint32 bufferSize, qint32 &bytesWritten) = 0; /** - * Decompresses a \a tileData from a given \a buffer. + * Decompresses a \p tileData from a given \p buffer. * - * \param tileData an existing tile data wrere the result + * \param buffer the buffer + * \param bufferSize the size of the buffer + * \param tileData an existing tile data where the result * will be written to. It should be created and acquired * by the caller. * */ virtual bool decompressTileData(quint8 *buffer, qint32 bufferSize, KisTileData *tileData) = 0; /** * Return the number of bytes needed for compressing one tile */ virtual qint32 tileDataBufferSize(KisTileData *tileData) = 0; protected: inline qint32 xToCol(KisTiledDataManager *dm, qint32 x) { return dm->xToCol(x); } inline qint32 yToRow(KisTiledDataManager *dm, qint32 y) { return dm->yToRow(y); } inline qint32 pixelSize(KisTiledDataManager *dm) { return dm->pixelSize(); } }; #endif /* __KIS_ABSTRACT_TILE_COMPRESSOR_H */ diff --git a/libs/image/tiles3/swap/kis_memory_window.h b/libs/image/tiles3/swap/kis_memory_window.h index 7fa7689851..4f54a4e3bb 100644 --- a/libs/image/tiles3/swap/kis_memory_window.h +++ b/libs/image/tiles3/swap/kis_memory_window.h @@ -1,82 +1,83 @@ /* * Copyright (c) 2010 Dmitry Kazakov * * 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_MEMORY_WINDOW_H #define __KIS_MEMORY_WINDOW_H #include #include "kis_chunk_allocator.h" #define DEFAULT_WINDOW_SIZE (16*MiB) class KRITAIMAGE_EXPORT KisMemoryWindow { public: /** * @param swapDir If the dir doesn't exist, it'll be created, if it's empty QDir::tempPath will be used. + * @param writeWindowSize write window size. */ KisMemoryWindow(const QString &swapDir, quint64 writeWindowSize = DEFAULT_WINDOW_SIZE); ~KisMemoryWindow(); inline quint8* getReadChunkPtr(KisChunk readChunk) { return getReadChunkPtr(readChunk.data()); } inline quint8* getWriteChunkPtr(KisChunk writeChunk) { return getWriteChunkPtr(writeChunk.data()); } quint8* getReadChunkPtr(const KisChunkData &readChunk); quint8* getWriteChunkPtr(const KisChunkData &writeChunk); private: struct MappingWindow { MappingWindow(quint64 _defaultSize) : chunk(0,0), window(0), defaultSize(_defaultSize) { } quint8* calculatePointer(const KisChunkData &other) const { return window + other.m_begin - chunk.m_begin; } KisChunkData chunk; quint8 *window; const quint64 defaultSize; }; private: bool adjustWindow(const KisChunkData &requestedChunk, MappingWindow *adjustingWindow, MappingWindow *otherWindow); private: QTemporaryFile m_file; bool m_valid; MappingWindow m_readWindowEx; MappingWindow m_writeWindowEx; }; #endif /* __KIS_MEMORY_WINDOW_H */ diff --git a/libs/pigment/KoChannelInfo.h b/libs/pigment/KoChannelInfo.h index 8c3a80d359..d56723f380 100644 --- a/libs/pigment/KoChannelInfo.h +++ b/libs/pigment/KoChannelInfo.h @@ -1,276 +1,277 @@ /* * Copyright (c) 2004 Boudewijn Rempt * * 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 Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef KOCHANNELINFO_H_ #define KOCHANNELINFO_H_ #include #include #include #include /** * This class gives some basic information about a channel, * that is, one of the components that makes up a particular * pixel. */ class KoChannelInfo { public: /** * Used to represent a min and max range. */ struct DoubleRange { public: double minVal, maxVal; public: /// creates an invalid range of 0,0 DoubleRange(void) : minVal(0), maxVal(0) { } /// creates DoubleRange(qreal _minVal, qreal _maxVal) : minVal(_minVal), maxVal(_maxVal) { Q_ASSERT(minVal <= maxVal); } /// true if this range is usable bool isValid(void) const { return minVal < maxVal; } }; public: /// enum to define the type of the channel enum enumChannelType { COLOR, ///< The channel represents a color ALPHA ///< The channel represents the opacity of a pixel //SUBSTANCE, ///< The channel represents a real-world substance like pigments or medium //SUBSTRATE ///< The channel represents a real-world painting substrate like a canvas }; /// enum to define the value of the channel enum enumChannelValueType { UINT8, ///< use this for an unsigned integer 8bits channel UINT16, ///< use this for an integer 16bits channel UINT32, ///< use this for an unsigned integer 21bits channel FLOAT16, ///< use this for a float 16bits channel FLOAT32, ///< use this for a float 32bits channel FLOAT64, ///< use this for a float 64bits channel INT8, ///< use this for an integer 8bits channel INT16, ///< use this for an integer 16bits channel OTHER ///< Use this if the channel is neither an integer or a float }; public: KoChannelInfo() { } /** * @param name of the channel * @param npos position of the channel in the pixel (in bytes) * @param displayPosition the position of the channel in the user-visible order * @param channelType type of the channel * @param channelValueType type of the numerical data used by the channel * @param size number of bytes (not bits) of the channel (if -1, it is deduced from the channelType) * @param color a color to represent that channel (for instance in an histogram) + * @param uiMinMax the UI range */ KoChannelInfo(const QString & name, qint32 npos, qint32 displayPosition, enumChannelType channelType, enumChannelValueType channelValueType, qint32 size = -1, const QColor &color = QColor(0, 0, 0), const DoubleRange &uiMinMax = DoubleRange()) : m_name(name) , m_pos(npos) , m_displayPosition(displayPosition) , m_channelType(channelType) , m_channelValueType(channelValueType) , m_size(size) , m_color(color) , m_uiMinMax(uiMinMax) { switch(m_channelValueType) { case UINT8: case INT8: Q_ASSERT(m_size == -1 || m_size == 1); m_size = 1; break; case UINT16: case INT16: Q_ASSERT(m_size == -1 || m_size == 2); m_size = 2; break; case UINT32: Q_ASSERT(m_size == -1 || m_size == 4); m_size = 4; break; case FLOAT16: Q_ASSERT(m_size == -1 || m_size == 2); m_size = 2; break; case FLOAT32: Q_ASSERT(m_size == -1 || m_size == 4); m_size = 4; break; case FLOAT64: Q_ASSERT(m_size == -1 || m_size == 8); m_size = 8; break; case OTHER: Q_ASSERT(m_size != -1); } if (!uiMinMax.isValid()) { switch (m_channelValueType) { case UINT8: m_uiMinMax.minVal = std::numeric_limits::min(); m_uiMinMax.maxVal = std::numeric_limits::max(); break; case INT8: m_uiMinMax.minVal = std::numeric_limits::min(); m_uiMinMax.maxVal = std::numeric_limits::max(); break; case UINT16: m_uiMinMax.minVal = std::numeric_limits::min(); m_uiMinMax.maxVal = std::numeric_limits::max(); break; case INT16: m_uiMinMax.minVal = std::numeric_limits::min(); m_uiMinMax.maxVal = std::numeric_limits::max(); break; case UINT32: m_uiMinMax.minVal = std::numeric_limits::min(); m_uiMinMax.maxVal = std::numeric_limits::max(); break; default: // assume real otherwise, which is 0..1 by default m_uiMinMax.minVal = 0.0; m_uiMinMax.maxVal = 1.0; break; } } Q_ASSERT(m_uiMinMax.isValid()); } public: /** * converts the display position to the pixel-order index in the channels vector. */ static int displayPositionToChannelIndex(int displayPosition, const QList &channels) { for (int i = 0; i < channels.size(); ++i) { if (channels.at(i)->displayPosition() == displayPosition) { return i; } } return -1; } static QList displayOrderSorted(const QList &channels) { QList sortedChannels; for (int i = 0; i < channels.size(); ++i) { Q_FOREACH (KoChannelInfo* channel, channels) { if (channel->displayPosition() == i) { sortedChannels << channel; break; } } } Q_ASSERT(channels.size() == sortedChannels.size()); return sortedChannels; } /** * User-friendly name for this channel for presentation purposes in the gui */ inline QString name() const { return m_name; } /** * @return the position of the first byte of the channel in the pixel */ inline qint32 pos() const { return m_pos; } /** * @return the displayPosition of the channel in the pixel */ inline qint32 displayPosition() const { return m_displayPosition; } /** * @return the number of bytes this channel takes */ inline qint32 size() const { return m_size; } /** * @return the type of the channel */ inline enumChannelType channelType() const { return m_channelType; } /** * @return the type of the value of the channel (float, uint8 or uint16) */ inline enumChannelValueType channelValueType() const { return m_channelValueType; } /** * This is a color that can be used to represent this channel in histograms and so. * By default this is black, so keep in mind that many channels might look the same */ inline QColor color() const { return m_color; } /** * A channel is less than another channel if its pos is smaller. */ inline bool operator<(const KoChannelInfo & info) { return m_pos < info.m_pos; } /** * Gets the minimum value that this channel should have. * This is suitable for UI use. */ inline double getUIMin(void) const { return m_uiMinMax.minVal; } /** * Gets the minimum value that this channel should have. * This is suitable for UI use. */ inline double getUIMax(void) const { return m_uiMinMax.maxVal; } private: QString m_name; qint32 m_pos; qint32 m_displayPosition; enumChannelType m_channelType; enumChannelValueType m_channelValueType; qint32 m_size; QColor m_color; DoubleRange m_uiMinMax; }; #endif // KOCHANNELINFO_H_