2017-08-04 15:31:50 +12:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#ifndef MYPAINTTOONZBRUSH_H
|
|
|
|
#define MYPAINTTOONZBRUSH_H
|
|
|
|
|
|
|
|
#include <toonz/mypaint.h>
|
|
|
|
#include "traster.h"
|
|
|
|
#include "trastercm.h"
|
|
|
|
#include "tcurves.h"
|
2023-02-04 15:05:42 +13:00
|
|
|
#include "symmetrytool.h"
|
2017-08-04 15:31:50 +12:00
|
|
|
#include <QPainter>
|
|
|
|
#include <QImage>
|
|
|
|
|
|
|
|
class RasterController {
|
|
|
|
public:
|
2018-09-12 13:37:07 +12:00
|
|
|
virtual ~RasterController() {}
|
2017-08-04 15:31:50 +12:00
|
|
|
virtual bool askRead(const TRect &rect) { return true; }
|
|
|
|
virtual bool askWrite(const TRect &rect) { return true; }
|
|
|
|
};
|
|
|
|
|
|
|
|
//=======================================================
|
|
|
|
//
|
|
|
|
// Raster32PMyPaintSurface
|
|
|
|
//
|
|
|
|
//=======================================================
|
|
|
|
|
2018-09-12 13:37:07 +12:00
|
|
|
class Raster32PMyPaintSurface : public mypaint::Surface {
|
2017-08-04 15:31:50 +12:00
|
|
|
private:
|
|
|
|
class Internal;
|
|
|
|
|
|
|
|
TRaster32P m_ras;
|
|
|
|
RasterController *controller;
|
|
|
|
Internal *internal;
|
|
|
|
|
2018-09-12 13:37:07 +12:00
|
|
|
inline static void readPixel(const void *pixelPtr, float &colorR,
|
|
|
|
float &colorG, float &colorB, float &colorA) {
|
|
|
|
const TPixel32 &pixel = *(const TPixel32 *)pixelPtr;
|
|
|
|
colorR = (float)pixel.r / (float)TPixel32::maxChannelValue;
|
|
|
|
colorG = (float)pixel.g / (float)TPixel32::maxChannelValue;
|
|
|
|
colorB = (float)pixel.b / (float)TPixel32::maxChannelValue;
|
|
|
|
colorA = (float)pixel.m / (float)TPixel32::maxChannelValue;
|
2017-08-04 15:31:50 +12:00
|
|
|
}
|
|
|
|
|
2018-09-12 13:37:07 +12:00
|
|
|
inline static void writePixel(void *pixelPtr, float colorR, float colorG,
|
|
|
|
float colorB, float colorA) {
|
|
|
|
TPixel32 &pixel = *(TPixel32 *)pixelPtr;
|
2017-08-04 15:31:50 +12:00
|
|
|
pixel.r = (TPixel32::Channel)roundf(colorR * TPixel32::maxChannelValue);
|
|
|
|
pixel.g = (TPixel32::Channel)roundf(colorG * TPixel32::maxChannelValue);
|
|
|
|
pixel.b = (TPixel32::Channel)roundf(colorB * TPixel32::maxChannelValue);
|
|
|
|
pixel.m = (TPixel32::Channel)roundf(colorA * TPixel32::maxChannelValue);
|
|
|
|
}
|
|
|
|
|
2018-09-12 13:37:07 +12:00
|
|
|
inline static bool askRead(void *surfaceController,
|
|
|
|
const void * /* surfacePointer */, int x0, int y0,
|
|
|
|
int x1, int y1) {
|
|
|
|
Raster32PMyPaintSurface &owner =
|
|
|
|
*((Raster32PMyPaintSurface *)surfaceController);
|
|
|
|
return !owner.controller ||
|
|
|
|
owner.controller->askRead(TRect(x0, y0, x1, y1));
|
2017-08-04 15:31:50 +12:00
|
|
|
}
|
|
|
|
|
2018-09-12 13:37:07 +12:00
|
|
|
inline static bool askWrite(void *surfaceController,
|
|
|
|
const void * /* surfacePointer */, int x0, int y0,
|
|
|
|
int x1, int y1) {
|
|
|
|
Raster32PMyPaintSurface &owner =
|
|
|
|
*((Raster32PMyPaintSurface *)surfaceController);
|
|
|
|
return !owner.controller ||
|
|
|
|
owner.controller->askWrite(TRect(x0, y0, x1, y1));
|
2017-08-04 15:31:50 +12:00
|
|
|
}
|
|
|
|
|
|
|
|
public:
|
|
|
|
explicit Raster32PMyPaintSurface(const TRaster32P &ras);
|
2018-09-12 13:37:07 +12:00
|
|
|
explicit Raster32PMyPaintSurface(const TRaster32P &ras,
|
|
|
|
RasterController &controller);
|
2017-08-04 15:31:50 +12:00
|
|
|
~Raster32PMyPaintSurface();
|
|
|
|
|
2018-09-12 13:37:07 +12:00
|
|
|
bool getColor(float x, float y, float radius, float &colorR, float &colorG,
|
|
|
|
float &colorB, float &colorA) override;
|
2017-08-04 15:31:50 +12:00
|
|
|
|
|
|
|
bool drawDab(const mypaint::Dab &dab) override;
|
|
|
|
|
|
|
|
bool getAntialiasing() const;
|
|
|
|
void setAntialiasing(bool value);
|
|
|
|
};
|
|
|
|
|
|
|
|
//=======================================================
|
|
|
|
//
|
|
|
|
// MyPaintToonzBrush
|
|
|
|
//
|
|
|
|
//=======================================================
|
|
|
|
|
|
|
|
class MyPaintToonzBrush {
|
|
|
|
private:
|
|
|
|
struct Params {
|
|
|
|
union {
|
2018-09-12 13:37:07 +12:00
|
|
|
struct {
|
|
|
|
double x, y, pressure, time;
|
|
|
|
};
|
|
|
|
struct {
|
|
|
|
double values[4];
|
|
|
|
};
|
2017-08-04 15:31:50 +12:00
|
|
|
};
|
|
|
|
|
2018-09-12 13:37:07 +12:00
|
|
|
inline explicit Params(double x = 0.0, double y = 0.0,
|
|
|
|
double pressure = 0.0, double time = 0.0)
|
|
|
|
: x(x), y(y), pressure(pressure), time(time) {}
|
2017-08-04 15:31:50 +12:00
|
|
|
|
|
|
|
inline void setMedian(Params &a, Params &b) {
|
2018-09-12 13:37:07 +12:00
|
|
|
for (int i = 0; i < (int)sizeof(values) / sizeof(values[0]); ++i)
|
|
|
|
values[i] = 0.5 * (a.values[i] + b.values[i]);
|
2017-08-04 15:31:50 +12:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
struct Segment {
|
|
|
|
Params p1, p2;
|
|
|
|
};
|
|
|
|
|
|
|
|
TRaster32P m_ras;
|
|
|
|
Raster32PMyPaintSurface m_mypaintSurface;
|
2023-02-04 15:05:42 +13:00
|
|
|
|
|
|
|
// Symmetry tool
|
|
|
|
mypaint::Brush brushes[MAX_SYMMETRY];
|
|
|
|
int m_brushCount;
|
|
|
|
double m_rotation;
|
|
|
|
TPointD m_centerPoint;
|
|
|
|
bool m_useLineSymmetry;
|
|
|
|
TPointD m_dpiScale;
|
|
|
|
TPointD m_rasCenter;
|
2017-08-04 15:31:50 +12:00
|
|
|
|
|
|
|
bool reset;
|
|
|
|
Params previous, current;
|
|
|
|
|
|
|
|
public:
|
2018-09-12 13:37:07 +12:00
|
|
|
MyPaintToonzBrush(const TRaster32P &ras, RasterController &controller,
|
|
|
|
const mypaint::Brush &brush);
|
2017-08-04 15:31:50 +12:00
|
|
|
void beginStroke();
|
|
|
|
void endStroke();
|
|
|
|
void strokeTo(const TPointD &p, double pressure, double dtime);
|
2018-09-12 13:37:07 +12:00
|
|
|
|
|
|
|
// colormapped
|
|
|
|
void updateDrawing(const TRasterCM32P rasCM, const TRasterCM32P rasBackupCM,
|
2021-06-04 10:18:35 +12:00
|
|
|
const TRect &bbox, int styleId, bool lockAlpha) const;
|
2023-02-04 15:05:42 +13:00
|
|
|
|
|
|
|
void addSymmetryBrushes(double lines, double rotation, TPointD centerPoint,
|
|
|
|
bool useLineSymmetry, TPointD dpiScale);
|
|
|
|
bool hasSymmetryBrushes() { return m_brushCount > 1; }
|
2017-08-04 15:31:50 +12:00
|
|
|
};
|
|
|
|
|
|
|
|
#endif // T_BLUREDBRUSH
|