|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#include "tools/rasterselection.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tools/tool.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tools/toolutils.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tools/toolhandle.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tpaletteutil.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "trop.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "drawutil.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tconvert.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "timagecache.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tpixelutils.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "toonzqt/rasterimagedata.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "toonzqt/strokesdata.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "toonzqt/selectioncommandids.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "toonzqt/tselectionhandle.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "toonzqt/dvdialog.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "toonz/stage.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "toonz/toonzimageutils.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "toonz/txshlevelhandle.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "toonz/txshsimplelevel.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "toonz/tpalettehandle.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "toonz/palettecontroller.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "toonz/toonzscene.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "toonz/tcamera.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "toonz/trasterimageutils.h"
|
|
manongjohn |
6939a3 |
#include "toonz/tcolumnhandle.h"
|
|
manongjohn |
6939a3 |
#include "toonz/tframehandle.h"
|
|
manongjohn |
6939a3 |
#include "toonz/txsheethandle.h"
|
|
manongjohn |
6939a3 |
#include "toonz/tstageobject.h"
|
|
justburner |
2975e1 |
#include "toonzqt/gutil.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#include <qapplication></qapplication>
|
|
Toshihiro Shimizu |
890ddd |
#include <qclipboard></qclipboard>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#include "timage_io.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tropcm.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//=============================================================================
|
|
Shinya Kitaoka |
120a6e |
namespace {
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TRasterP getRaster(const TImageP image) {
|
|
Shinya Kitaoka |
120a6e |
if (TToonzImageP ti = (TToonzImageP)(image)) return ti->getRaster();
|
|
Shinya Kitaoka |
120a6e |
if (TRasterImageP ri = (TRasterImageP)(image)) return ri->getRaster();
|
|
Shinya Kitaoka |
120a6e |
return (TRasterP)(0);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TRect convertWorldToRaster(const TRectD area, const TRasterP ras) {
|
|
Shinya Kitaoka |
120a6e |
if (area.isEmpty()) return TRect();
|
|
Shinya Kitaoka |
120a6e |
if (!ras)
|
|
Shinya Kitaoka |
120a6e |
return TRect(tfloor(area.x0), tfloor(area.y0), tfloor(area.x1) - 1,
|
|
Shinya Kitaoka |
120a6e |
tfloor(area.y1) - 1);
|
|
Shinya Kitaoka |
120a6e |
TRectD rect(area + ras->getCenterD());
|
|
Shinya Kitaoka |
120a6e |
return TRect(tfloor(rect.x0), tfloor(rect.y0), tceil(rect.x1) - 1,
|
|
Shinya Kitaoka |
120a6e |
tceil(rect.y1) - 1);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TRect convertWorldToRaster(const TRectD area, const TImageP image) {
|
|
Shinya Kitaoka |
120a6e |
TRasterImageP ri(image);
|
|
Shinya Kitaoka |
120a6e |
TToonzImageP ti(image);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
// Watch out! TToonzImage::getRaster() returns a TRasterCM32P, while
|
|
Shinya Kitaoka |
120a6e |
// TRasterImage::getRaster() returns a TRasterP!
|
|
Shinya Kitaoka |
120a6e |
TRasterP ras = (ri) ? ri->getRaster() : (TRasterP)ti->getRaster();
|
|
Shinya Kitaoka |
120a6e |
return convertWorldToRaster(area, ras);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TRectD convertRasterToWorld(const TRect area, const TImageP image) {
|
|
Shinya Kitaoka |
120a6e |
TToonzImageP ti(image);
|
|
Shinya Kitaoka |
120a6e |
if (ti) return ToonzImageUtils::convertRasterToWorld(area, image);
|
|
Shinya Kitaoka |
120a6e |
return TRasterImageUtils::convertRasterToWorld(area, image);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TRectD intersection(const TRectD &area, const TImageP image) {
|
|
Shinya Kitaoka |
120a6e |
TToonzImageP ti(image);
|
|
Shinya Kitaoka |
120a6e |
if (ti)
|
|
Shinya Kitaoka |
120a6e |
return area * ToonzImageUtils::convertRasterToWorld(
|
|
Shinya Kitaoka |
120a6e |
ti->getRaster()->getBounds(), image);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TRasterImageP ri(image);
|
|
Shinya Kitaoka |
120a6e |
if (ri)
|
|
Shinya Kitaoka |
120a6e |
return area * TRasterImageUtils::convertRasterToWorld(
|
|
Shinya Kitaoka |
120a6e |
ri->getRaster()->getBounds(), ri);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
return area;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
// The stroke is in raster coordinates
|
|
Toshihiro Shimizu |
890ddd |
template <class class="" pixel1,="" pixel2=""></class>
|
|
Shinya Kitaoka |
120a6e |
TRasterPT<pixel1> getImageFromStroke(TRasterPT<pixel2> ras,</pixel2></pixel1>
|
|
Shinya Kitaoka |
120a6e |
const TStroke &stroke) {
|
|
Shinya Kitaoka |
120a6e |
TRectD regionsBoxD = stroke.getBBox();
|
|
Shinya Kitaoka |
120a6e |
// E' volutamente allargato di un pixel!
|
|
Shinya Kitaoka |
120a6e |
TRect regionsBox(tfloor(regionsBoxD.x0), tfloor(regionsBoxD.y0),
|
|
Shinya Kitaoka |
120a6e |
tceil(regionsBoxD.x1), tceil(regionsBoxD.y1));
|
|
Shinya Kitaoka |
120a6e |
regionsBox *= ras->getBounds();
|
|
Shinya Kitaoka |
120a6e |
if (regionsBox.isEmpty()) return (TRasterPT<pixel1>)0;</pixel1>
|
|
Shinya Kitaoka |
120a6e |
TRasterPT<pixel1> buffer(regionsBox.getSize());</pixel1>
|
|
Shinya Kitaoka |
120a6e |
buffer->clear();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// Compute regions created by the std::vector
|
|
Shinya Kitaoka |
120a6e |
TVectorImage app;
|
|
Shinya Kitaoka |
120a6e |
app.addStroke(new TStroke(stroke));
|
|
Shinya Kitaoka |
120a6e |
app.findRegions();
|
|
Shinya Kitaoka |
120a6e |
int reg, j, k, y;
|
|
Shinya Kitaoka |
120a6e |
ras->lock();
|
|
Shinya Kitaoka |
120a6e |
for (reg = 0; reg < (int)app.getRegionCount(); reg++) {
|
|
Shinya Kitaoka |
120a6e |
// For each region, pixels inside the region are copied in buffer!
|
|
Shinya Kitaoka |
120a6e |
TRectD bBoxD = stroke.getBBox();
|
|
Shinya Kitaoka |
120a6e |
TRect bBox(tfloor(bBoxD.x0), tfloor(bBoxD.y0), tceil(bBoxD.x1) - 1,
|
|
Shinya Kitaoka |
120a6e |
tceil(bBoxD.y1) - 1);
|
|
Shinya Kitaoka |
120a6e |
bBox *= ras->getBounds();
|
|
Shinya Kitaoka |
120a6e |
for (y = bBox.y0; y <= bBox.y1; y++) {
|
|
Shinya Kitaoka |
120a6e |
PIXEL2 *selectedLine = ras->pixels(y);
|
|
Shinya Kitaoka |
120a6e |
int startY = y - regionsBox.y0;
|
|
Shinya Kitaoka |
120a6e |
PIXEL1 *bufferLine = buffer->pixels(startY >= 0 ? startY : 0);
|
|
Shinya Kitaoka |
120a6e |
std::vector<double> intersections;</double>
|
|
Shinya Kitaoka |
120a6e |
app.getRegion(reg)->computeScanlineIntersections(y, intersections);
|
|
Shinya Kitaoka |
120a6e |
if (intersections.empty())
|
|
Shinya Kitaoka |
120a6e |
app.getRegion(reg)->computeScanlineIntersections(y + 0.9,
|
|
Shinya Kitaoka |
120a6e |
intersections);
|
|
Shinya Kitaoka |
120a6e |
for (j = 0; j < (int)intersections.size(); j += 2) {
|
|
Shinya Kitaoka |
120a6e |
if (intersections[j] == intersections[j + 1]) continue;
|
|
Shinya Kitaoka |
120a6e |
int from = std::max(tfloor(intersections[j]), bBox.x0);
|
|
Shinya Kitaoka |
120a6e |
int to = std::min(tceil(intersections[j + 1]), bBox.x1);
|
|
Shinya Kitaoka |
120a6e |
for (k = from; k <= to; k++) {
|
|
Shinya Kitaoka |
120a6e |
TRasterCM32P bufferCM(buffer);
|
|
Shinya Kitaoka |
120a6e |
TRaster32P buffer32(buffer);
|
|
Shinya Kitaoka |
120a6e |
TRasterCM32P rasCM(ras);
|
|
Shinya Kitaoka |
120a6e |
TRaster32P ras32(ras);
|
|
Shinya Kitaoka |
120a6e |
TRasterGR8P rasGR8(ras);
|
|
Shinya Kitaoka |
120a6e |
if (bufferCM && rasCM) {
|
|
Shinya Kitaoka |
120a6e |
TPixelCM32 *bottomPix =
|
|
Shinya Kitaoka |
120a6e |
(TPixelCM32 *)bufferLine + k - regionsBox.x0;
|
|
Shinya Kitaoka |
120a6e |
TPixelCM32 *topPix = (TPixelCM32 *)selectedLine + k;
|
|
Shinya Kitaoka |
120a6e |
*bottomPix = *topPix;
|
|
Shinya Kitaoka |
120a6e |
} else if (buffer32 && ras32) {
|
|
Shinya Kitaoka |
120a6e |
TPixel32 *bottomPix = (TPixel32 *)bufferLine + k - regionsBox.x0;
|
|
Shinya Kitaoka |
120a6e |
TPixel32 *topPix = (TPixel32 *)selectedLine + k;
|
|
Shinya Kitaoka |
120a6e |
*bottomPix = *topPix;
|
|
Shinya Kitaoka |
120a6e |
} else if (buffer32 && rasGR8) {
|
|
Shinya Kitaoka |
120a6e |
TPixel32 *bottomPix = (TPixel32 *)bufferLine + k - regionsBox.x0;
|
|
Shinya Kitaoka |
120a6e |
TPixelGR8 *topPix = (TPixelGR8 *)selectedLine + k;
|
|
Shinya Kitaoka |
120a6e |
*bottomPix =
|
|
Shinya Kitaoka |
120a6e |
TPixel32(topPix->value, topPix->value, topPix->value, 255);
|
|
Shinya Kitaoka |
120a6e |
} else
|
|
Shinya Kitaoka |
120a6e |
assert(0);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
ras->unlock();
|
|
Shinya Kitaoka |
120a6e |
return buffer;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <class class="" pixel1,="" pixel2=""></class>
|
|
Shinya Kitaoka |
120a6e |
TRasterPT<pixel1> getImageFromSelection(TRasterPT<pixel2> &ras,</pixel2></pixel1>
|
|
Shinya Kitaoka |
120a6e |
RasterSelection &selection) {
|
|
Shinya Kitaoka |
120a6e |
if (selection.isEmpty()) return (TRasterPT<pixel1>)0;</pixel1>
|
|
Shinya Kitaoka |
120a6e |
TRectD wSelectionBound = selection.getSelectionBbox();
|
|
Shinya Kitaoka |
120a6e |
TRect rSelectionBound = convertWorldToRaster(wSelectionBound, ras);
|
|
Shinya Kitaoka |
120a6e |
rSelectionBound *= ras->getBounds();
|
|
Shinya Kitaoka |
120a6e |
TRasterPT<pixel1> selectedRaster(rSelectionBound.getSize());</pixel1>
|
|
Shinya Kitaoka |
120a6e |
selectedRaster->clear();
|
|
Shinya Kitaoka |
120a6e |
std::vector<tstroke> strokes = selection.getStrokes();</tstroke>
|
|
Shinya Kitaoka |
120a6e |
TPoint startPosition = rSelectionBound.getP00();
|
|
Shinya Kitaoka |
120a6e |
unsigned int i;
|
|
Shinya Kitaoka |
120a6e |
for (i = 0; i < strokes.size(); i++) {
|
|
Shinya Kitaoka |
120a6e |
TStroke stroke = strokes[i];
|
|
Shinya Kitaoka |
120a6e |
stroke.transform(TTranslation(ras->getCenterD()));
|
|
Shinya Kitaoka |
120a6e |
TRasterPT<pixel1> app = getImageFromStroke<pixel1, pixel2="">(ras, stroke);</pixel1,></pixel1>
|
|
Shinya Kitaoka |
120a6e |
if (!app) continue;
|
|
Shinya Kitaoka |
120a6e |
TRectD strokeRectD = stroke.getBBox();
|
|
Shinya Kitaoka |
120a6e |
TRect strokeRect(tfloor(strokeRectD.x0), tfloor(strokeRectD.y0),
|
|
Shinya Kitaoka |
120a6e |
tceil(strokeRectD.x1) - 1, tceil(strokeRectD.y1) - 1);
|
|
Shinya Kitaoka |
120a6e |
TPoint offset((strokeRect * rSelectionBound).getP00() -
|
|
Shinya Kitaoka |
120a6e |
rSelectionBound.getP00());
|
|
Shinya Kitaoka |
120a6e |
TPoint startP = rSelectionBound.getP00() + offset;
|
|
Shinya Kitaoka |
120a6e |
startPosition = TPoint(std::min(startPosition.x, startP.x),
|
|
Shinya Kitaoka |
120a6e |
std::min(startPosition.y, startP.y));
|
|
Shinya Kitaoka |
120a6e |
TRop::over(selectedRaster, app, offset);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
selection.setStartPosition(startPosition);
|
|
Shinya Kitaoka |
120a6e |
return selectedRaster;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TRasterP getImageFromSelection(const TImageP &image,
|
|
Shinya Kitaoka |
120a6e |
RasterSelection &selection) {
|
|
Shinya Kitaoka |
120a6e |
if (TToonzImageP toonzImage = (TToonzImageP)image) {
|
|
Shinya Kitaoka |
120a6e |
TRasterPT<tpixelcm32> ras = toonzImage->getRaster();</tpixelcm32>
|
|
Shinya Kitaoka |
120a6e |
return getImageFromSelection<tpixelcm32, tpixelcm32="">(ras, selection);</tpixelcm32,>
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
if (TRasterImageP rasterImage = (TRasterImageP)image) {
|
|
Shinya Kitaoka |
120a6e |
TRasterP ras = rasterImage->getRaster();
|
|
Shinya Kitaoka |
120a6e |
if (TRaster32P ras32 = (TRaster32P)ras)
|
|
Shinya Kitaoka |
120a6e |
return getImageFromSelection<tpixel32, tpixel32="">(ras32, selection);</tpixel32,>
|
|
Shinya Kitaoka |
120a6e |
if (TRasterGR8P rasGR8 = (TRasterGR8P)ras)
|
|
Shinya Kitaoka |
120a6e |
return getImageFromSelection<tpixel32, tpixelgr8="">(rasGR8, selection);</tpixel32,>
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
return (TRasterP)0;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename pixel=""></typename>
|
|
Shinya Kitaoka |
120a6e |
void deleteSelectionWithoutUndo(TRasterPT<pixel> &ras,</pixel>
|
|
Shinya Kitaoka |
120a6e |
const std::vector<tstroke> &strokes,</tstroke>
|
|
Shinya Kitaoka |
120a6e |
PIXEL emptyValue) {
|
|
Shinya Kitaoka |
120a6e |
if (!ras) return;
|
|
Shinya Kitaoka |
120a6e |
unsigned int i;
|
|
Shinya Kitaoka |
120a6e |
for (i = 0; i < strokes.size(); i++) {
|
|
Shinya Kitaoka |
120a6e |
TStroke s = strokes[i];
|
|
Shinya Kitaoka |
120a6e |
s.transform(TTranslation(ras->getCenterD()));
|
|
Shinya Kitaoka |
120a6e |
TRectD strokeRectD = s.getBBox();
|
|
Shinya Kitaoka |
120a6e |
// E' volutamente allargato di un pixel!
|
|
Shinya Kitaoka |
120a6e |
TRect strokeRect(tfloor(strokeRectD.x0), tfloor(strokeRectD.y0),
|
|
Shinya Kitaoka |
120a6e |
tceil(strokeRectD.x1), tceil(strokeRectD.y1));
|
|
Shinya Kitaoka |
120a6e |
if (!strokeRect.overlaps(ras->getBounds())) continue;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// Compute regions created by the std::vector
|
|
Shinya Kitaoka |
120a6e |
TVectorImage app;
|
|
Shinya Kitaoka |
120a6e |
app.addStroke(new TStroke(s));
|
|
Shinya Kitaoka |
120a6e |
app.findRegions();
|
|
Shinya Kitaoka |
120a6e |
int reg, j, k, y;
|
|
Shinya Kitaoka |
120a6e |
ras->lock();
|
|
Shinya Kitaoka |
120a6e |
TRect rasRect(ras->getBounds());
|
|
Shinya Kitaoka |
120a6e |
for (reg = 0; reg < (int)app.getRegionCount(); reg++) {
|
|
Shinya Kitaoka |
120a6e |
// For each region, pixels inside the region are erased!
|
|
Shinya Kitaoka |
120a6e |
TRectD bBoxD = app.getRegion(reg)->getBBox();
|
|
Shinya Kitaoka |
120a6e |
TRect bBox(tfloor(bBoxD.x0), tfloor(bBoxD.y0), tceil(bBoxD.x1) - 1,
|
|
Shinya Kitaoka |
120a6e |
tceil(bBoxD.y1) - 1);
|
|
Shinya Kitaoka |
120a6e |
bBox *= rasRect;
|
|
Shinya Kitaoka |
120a6e |
for (y = bBox.y0; y <= bBox.y1; y++) {
|
|
Shinya Kitaoka |
120a6e |
PIXEL *selectedLine = ras->pixels(y);
|
|
Shinya Kitaoka |
120a6e |
int startY = y - strokeRect.y0;
|
|
Shinya Kitaoka |
120a6e |
std::vector<double> intersections;</double>
|
|
Shinya Kitaoka |
120a6e |
app.getRegion(reg)->computeScanlineIntersections(y, intersections);
|
|
Shinya Kitaoka |
120a6e |
if (intersections.empty())
|
|
Shinya Kitaoka |
120a6e |
app.getRegion(reg)->computeScanlineIntersections(y + 0.9,
|
|
Shinya Kitaoka |
120a6e |
intersections);
|
|
Shinya Kitaoka |
120a6e |
for (j = 0; j < (int)intersections.size(); j += 2) {
|
|
Shinya Kitaoka |
120a6e |
if (intersections[j] == intersections[j + 1]) continue;
|
|
Shinya Kitaoka |
120a6e |
int from = std::max(tfloor(intersections[j]), bBox.x0);
|
|
Shinya Kitaoka |
120a6e |
int to = std::min(tceil(intersections[j + 1]), bBox.x1);
|
|
Shinya Kitaoka |
120a6e |
for (k = from; k <= to; k++) *(selectedLine + k) = emptyValue;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
ras->unlock();
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void deleteSelectionWithoutUndo(const TImageP &image,
|
|
Shinya Kitaoka |
120a6e |
const std::vector<tstroke> &strokes) {</tstroke>
|
|
Shinya Kitaoka |
120a6e |
if (TToonzImageP toonzImage = (TToonzImageP)image) {
|
|
Shinya Kitaoka |
120a6e |
TRasterPT<tpixelcm32> ras = toonzImage->getRaster();</tpixelcm32>
|
|
Shinya Kitaoka |
120a6e |
deleteSelectionWithoutUndo<tpixelcm32>(ras, strokes, TPixelCM32());</tpixelcm32>
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
if (TRasterImageP rasterImage = (TRasterImageP)image) {
|
|
Shinya Kitaoka |
120a6e |
TRasterP ras = rasterImage->getRaster();
|
|
Shinya Kitaoka |
120a6e |
if (TRaster32P ras32 = (TRaster32P)ras)
|
|
Shinya Kitaoka |
120a6e |
deleteSelectionWithoutUndo<tpixel32>(ras32, strokes,</tpixel32>
|
|
Shinya Kitaoka |
120a6e |
TPixel32::Transparent);
|
|
Shinya Kitaoka |
120a6e |
if (TRasterGR8P rasGR8 = (TRasterGR8P)ras)
|
|
Shinya Kitaoka |
120a6e |
deleteSelectionWithoutUndo<tpixelgr8>(rasGR8, strokes, TPixelGR8::White);</tpixelgr8>
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void pasteFloatingSelectionWithoutUndo(const TImageP &image,
|
|
Shinya Kitaoka |
120a6e |
const TRasterP &floatingSelection,
|
|
Shinya Kitaoka |
120a6e |
const TAffine &transformation,
|
|
Shinya Kitaoka |
120a6e |
const TRectD &wSelectionBound,
|
|
Shinya Kitaoka |
120a6e |
bool noAntialiasing) {
|
|
Shinya Kitaoka |
120a6e |
TRasterImageP ri = (TRasterImageP)image;
|
|
Shinya Kitaoka |
120a6e |
TToonzImageP ti = (TToonzImageP)image;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TRasterP targetRaster = (ri) ? ri->getRaster() : (TRasterP)ti->getRaster();
|
|
Shinya Kitaoka |
120a6e |
if (!targetRaster || !floatingSelection) return;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TRect rSelectionBound = convertWorldToRaster(wSelectionBound, targetRaster);
|
|
Shinya Kitaoka |
120a6e |
TRop::over(targetRaster, floatingSelection, rSelectionBound.getP00(),
|
|
Shinya Kitaoka |
120a6e |
transformation,
|
|
Shinya Kitaoka |
120a6e |
noAntialiasing ? TRop::ClosestPixel : TRop::Triangle);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//=============================================================================
|
|
Toshihiro Shimizu |
890ddd |
// UndoDeleteSelection
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
d1f6c4 |
class UndoDeleteSelection final : public TUndo {
|
|
Shinya Kitaoka |
120a6e |
static int m_id;
|
|
Shinya Kitaoka |
120a6e |
TXshSimpleLevelP m_level;
|
|
Shinya Kitaoka |
120a6e |
TFrameId m_frameId;
|
|
Shinya Kitaoka |
120a6e |
std::string m_erasedImageId;
|
|
Shinya Kitaoka |
120a6e |
TPoint m_erasePoint;
|
|
Shinya Kitaoka |
120a6e |
std::vector<tstroke> m_strokes;</tstroke>
|
|
Shinya Kitaoka |
120a6e |
TTool *m_tool;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Shinya Kitaoka |
120a6e |
UndoDeleteSelection(RasterSelection *selection, TXshSimpleLevel *level)
|
|
Shinya Kitaoka |
120a6e |
: TUndo()
|
|
Shinya Kitaoka |
120a6e |
, m_level(level)
|
|
Shinya Kitaoka |
120a6e |
, m_frameId(selection->getFrameId())
|
|
Shinya Kitaoka |
120a6e |
, m_strokes(selection->getOriginalStrokes()) {
|
|
Shinya Kitaoka |
120a6e |
TImageP image = m_level->getFrame(m_frameId, true);
|
|
Shinya Kitaoka |
120a6e |
m_erasedImageId = "UndoDeleteSelection" + std::to_string(m_id++);
|
|
Shinya Kitaoka |
120a6e |
TRasterP ras = getRaster(image);
|
|
Shinya Kitaoka |
120a6e |
TRasterP erasedRas;
|
|
Shinya Kitaoka |
120a6e |
if (!selection->isFloating())
|
|
Shinya Kitaoka |
120a6e |
erasedRas = TRasterP(getImageFromSelection(image, *selection));
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
erasedRas = TRasterP(selection->getOriginalFloatingSelection());
|
|
Shinya Kitaoka |
120a6e |
TImageP erasedImage;
|
|
Shinya Kitaoka |
120a6e |
if (TRasterCM32P toonzRas = (TRasterCM32P)(erasedRas))
|
|
Shinya Kitaoka |
120a6e |
erasedImage = TToonzImageP(toonzRas, toonzRas->getBounds());
|
|
Shinya Kitaoka |
120a6e |
else if (TRaster32P fullColorRas = (TRaster32P)(erasedRas))
|
|
Shinya Kitaoka |
120a6e |
erasedImage = TRasterImageP(fullColorRas);
|
|
Shinya Kitaoka |
120a6e |
TImageCache::instance()->add(m_erasedImageId, erasedImage, false);
|
|
Shinya Kitaoka |
120a6e |
m_erasePoint = selection->getStartPosition();
|
|
Shinya Kitaoka |
120a6e |
m_tool = TTool::getApplication()->getCurrentTool()->getTool();
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
~UndoDeleteSelection() {
|
|
Shinya Kitaoka |
120a6e |
if (TImageCache::instance()->isCached(m_erasedImageId))
|
|
Shinya Kitaoka |
120a6e |
TImageCache::instance()->remove(m_erasedImageId);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
473e70 |
void undo() const override {
|
|
Shinya Kitaoka |
120a6e |
TImageP image = m_level->getFrame(m_frameId, true);
|
|
Shinya Kitaoka |
120a6e |
if (!image) return;
|
|
Shinya Kitaoka |
120a6e |
TRasterP ras = getRaster(image);
|
|
Shinya Kitaoka |
120a6e |
if (!ras) return;
|
|
Shinya Kitaoka |
120a6e |
TImageP erasedImage = TImageCache::instance()->get(m_erasedImageId, false);
|
|
Shinya Kitaoka |
120a6e |
if (!erasedImage) return;
|
|
Shinya Kitaoka |
120a6e |
TRasterP erasedRaster = getRaster(erasedImage);
|
|
Shinya Kitaoka |
120a6e |
TRop::over(ras, erasedRaster, m_erasePoint);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
ToolUtils::updateSaveBox(m_level, m_frameId);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (!m_tool) return;
|
|
Shinya Kitaoka |
120a6e |
m_tool->notifyImageChanged(m_frameId);
|
|
Shinya Kitaoka |
120a6e |
m_tool->invalidate();
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
473e70 |
void redo() const override {
|
|
Shinya Kitaoka |
120a6e |
TImageP image = m_level->getFrame(m_frameId, true);
|
|
Shinya Kitaoka |
120a6e |
TImageP erasedImage = TImageCache::instance()->get(m_erasedImageId, false);
|
|
Shinya Kitaoka |
120a6e |
if (!erasedImage) return;
|
|
Shinya Kitaoka |
120a6e |
deleteSelectionWithoutUndo(image, m_strokes);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
ToolUtils::updateSaveBox(m_level, m_frameId);
|
|
Shinya Kitaoka |
120a6e |
if (!m_tool) return;
|
|
Shinya Kitaoka |
120a6e |
m_tool->notifyImageChanged(m_frameId);
|
|
Shinya Kitaoka |
120a6e |
m_tool->invalidate();
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
473e70 |
int getSize() const override { return sizeof(*this); }
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int UndoDeleteSelection::m_id = 0;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//=============================================================================
|
|
Toshihiro Shimizu |
890ddd |
// UndoPasteSelection
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
d1f6c4 |
class UndoPasteSelection final : public TUndo {
|
|
Shinya Kitaoka |
120a6e |
RasterSelection *m_currentSelection, m_newSelection;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Shinya Kitaoka |
120a6e |
UndoPasteSelection(RasterSelection *currentSelection)
|
|
Shinya Kitaoka |
120a6e |
: TUndo()
|
|
Shinya Kitaoka |
120a6e |
, m_currentSelection(currentSelection)
|
|
Shinya Kitaoka |
120a6e |
, m_newSelection(*currentSelection) {}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
~UndoPasteSelection() {}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
473e70 |
void undo() const override {
|
|
Shinya Kitaoka |
120a6e |
m_currentSelection->setFloatingSeletion(TRasterP());
|
|
Shinya Kitaoka |
120a6e |
m_currentSelection->selectNone();
|
|
Shinya Kitaoka |
120a6e |
m_currentSelection->notify();
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
473e70 |
void redo() const override {
|
|
Shinya Kitaoka |
120a6e |
*m_currentSelection = m_newSelection;
|
|
Shinya Kitaoka |
120a6e |
m_currentSelection->notify();
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
473e70 |
int getSize() const override { return sizeof(*this); }
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
473e70 |
QString getHistoryString() override { return QObject::tr("Paste"); }
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//=============================================================================
|
|
Toshihiro Shimizu |
890ddd |
// UndoPasteFloatingSelection
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
d1f6c4 |
class UndoPasteFloatingSelection final : public TUndo {
|
|
Shinya Kitaoka |
120a6e |
static int m_id;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TXshCell m_imageCell; //!< Level/frame pair to the pasted-to image
|
|
Shinya Kitaoka |
120a6e |
//!< (seemingly cached as m_imageId)
|
|
Shinya Kitaoka |
120a6e |
TPaletteP m_oldPalette, m_newPalette;
|
|
Shinya Kitaoka |
120a6e |
std::string m_imageId, m_floatingImageId, m_undoImageId, m_oldFloatingImageId;
|
|
Shinya Kitaoka |
120a6e |
std::vector<tstroke> m_strokes;</tstroke>
|
|
Shinya Kitaoka |
120a6e |
TRectD m_selectionRect;
|
|
Shinya Kitaoka |
120a6e |
TAffine m_transformation;
|
|
Shinya Kitaoka |
120a6e |
TPoint m_startPos;
|
|
Shinya Kitaoka |
120a6e |
bool m_isPastedSelection;
|
|
Shinya Kitaoka |
120a6e |
bool m_noAntialiasing;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TTool *m_tool;
|
|
Shinya Kitaoka |
120a6e |
TFrameId m_frameId;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Shinya Kitaoka |
120a6e |
UndoPasteFloatingSelection(RasterSelection *currentSelection,
|
|
Shinya Kitaoka |
120a6e |
TPalette *oldPalette, bool noAntialiasing)
|
|
Shinya Kitaoka |
120a6e |
: TUndo()
|
|
Shinya Kitaoka |
120a6e |
, m_imageCell(currentSelection->getCurrentImageCell())
|
|
Shinya Kitaoka |
120a6e |
, m_oldPalette(oldPalette ? oldPalette->clone() : 0)
|
|
Shinya Kitaoka |
120a6e |
, m_strokes(currentSelection->getOriginalStrokes())
|
|
Shinya Kitaoka |
120a6e |
, m_selectionRect(currentSelection->getSelectionBbox())
|
|
Shinya Kitaoka |
120a6e |
, m_transformation(currentSelection->getTransformation())
|
|
Shinya Kitaoka |
120a6e |
, m_isPastedSelection(currentSelection->isPastedSelection())
|
|
Shinya Kitaoka |
120a6e |
, m_noAntialiasing(noAntialiasing)
|
|
Shinya Kitaoka |
120a6e |
, m_undoImageId("")
|
|
Shinya Kitaoka |
120a6e |
, m_frameId(currentSelection->getFrameId()) {
|
|
Shinya Kitaoka |
120a6e |
TImageP image(currentSelection->getCurrentImage());
|
|
Shinya Kitaoka |
120a6e |
if (!image) return;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
m_imageId = "UndoPasteImage_" + std::to_string(m_id);
|
|
Shinya Kitaoka |
120a6e |
TImageCache::instance()->add(m_imageId, image, false);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
m_floatingImageId =
|
|
Shinya Kitaoka |
120a6e |
"UndoPasteFloatingSelection_floating_" + std::to_string(m_id);
|
|
Shinya Kitaoka |
120a6e |
TRasterP floatingRas = currentSelection->getFloatingSelection();
|
|
Shinya Kitaoka |
120a6e |
TImageP floatingImage;
|
|
Shinya Kitaoka |
120a6e |
if (TRasterCM32P toonzRas = (TRasterCM32P)(floatingRas))
|
|
Shinya Kitaoka |
120a6e |
floatingImage = TToonzImageP(toonzRas, toonzRas->getBounds());
|
|
Shinya Kitaoka |
120a6e |
else if (TRaster32P fullColorRas = (TRaster32P)(floatingRas))
|
|
Shinya Kitaoka |
120a6e |
floatingImage = TRasterImageP(fullColorRas);
|
|
Shinya Kitaoka |
120a6e |
else if (TRasterGR8P grRas = (TRasterGR8P)(floatingRas))
|
|
Shinya Kitaoka |
120a6e |
floatingImage = TRasterImageP(grRas);
|
|
Shinya Kitaoka |
120a6e |
TImageCache::instance()->add(m_floatingImageId, floatingImage, false);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
m_oldFloatingImageId =
|
|
Shinya Kitaoka |
120a6e |
"UndoPasteFloatingSelection_oldFloating_" + std::to_string(m_id);
|
|
Shinya Kitaoka |
120a6e |
TRasterP oldFloatingRas = currentSelection->getOriginalFloatingSelection();
|
|
Shinya Kitaoka |
120a6e |
TImageP olfFloatingImage;
|
|
Shinya Kitaoka |
120a6e |
if (TRasterCM32P toonzRas = (TRasterCM32P)(oldFloatingRas))
|
|
Shinya Kitaoka |
120a6e |
olfFloatingImage = TToonzImageP(toonzRas, toonzRas->getBounds());
|
|
Shinya Kitaoka |
120a6e |
else if (TRaster32P fullColorRas = (TRaster32P)(oldFloatingRas))
|
|
Shinya Kitaoka |
120a6e |
olfFloatingImage = TRasterImageP(fullColorRas);
|
|
Shinya Kitaoka |
120a6e |
else if (TRasterGR8P grRas = (TRasterGR8P)(oldFloatingRas))
|
|
Shinya Kitaoka |
120a6e |
olfFloatingImage = TRasterImageP(grRas);
|
|
Shinya Kitaoka |
120a6e |
TImageCache::instance()->add(m_oldFloatingImageId, olfFloatingImage, false);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TPaletteP imgPalette = image->getPalette();
|
|
Shinya Kitaoka |
120a6e |
m_newPalette = imgPalette ? imgPalette->clone() : 0;
|
|
Shinya Kitaoka |
120a6e |
TRasterP rasImage = getRaster(image);
|
|
Shinya Kitaoka |
120a6e |
TRectD wRect = m_selectionRect.enlarge(2);
|
|
Shinya Kitaoka |
120a6e |
TRect rRect = convertWorldToRaster(wRect, image);
|
|
Shinya Kitaoka |
120a6e |
rRect *= rasImage->getBounds();
|
|
Shinya Kitaoka |
120a6e |
if (!rRect.isEmpty()) {
|
|
Shinya Kitaoka |
120a6e |
m_undoImageId = "UndoPasteFloatingSelection_undo" + std::to_string(m_id);
|
|
Shinya Kitaoka |
120a6e |
TRasterP undoRas = rasImage->extract(rRect)->clone();
|
|
Shinya Kitaoka |
120a6e |
TImageP undoImage;
|
|
Shinya Kitaoka |
120a6e |
if (TRasterCM32P toonzRas = (TRasterCM32P)(undoRas))
|
|
Shinya Kitaoka |
120a6e |
undoImage = TToonzImageP(toonzRas, toonzRas->getBounds());
|
|
Shinya Kitaoka |
120a6e |
else if (TRaster32P fullColorRas = (TRaster32P)(undoRas))
|
|
Shinya Kitaoka |
120a6e |
undoImage = TRasterImageP(fullColorRas);
|
|
Shinya Kitaoka |
120a6e |
else if (TRasterGR8P grRas = (TRasterGR8P)(undoRas))
|
|
Shinya Kitaoka |
120a6e |
undoImage = TRasterImageP(grRas);
|
|
Shinya Kitaoka |
120a6e |
TImageCache::instance()->add(m_undoImageId, undoImage, false);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
m_startPos = currentSelection->getStartPosition();
|
|
Shinya Kitaoka |
120a6e |
m_id++;
|
|
Shinya Kitaoka |
120a6e |
m_tool = TTool::getApplication()->getCurrentTool()->getTool();
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
~UndoPasteFloatingSelection() {
|
|
Shinya Kitaoka |
120a6e |
if (TImageCache::instance()->isCached(m_imageId))
|
|
Shinya Kitaoka |
120a6e |
TImageCache::instance()->remove(m_imageId);
|
|
Shinya Kitaoka |
120a6e |
if (TImageCache::instance()->isCached(m_floatingImageId))
|
|
Shinya Kitaoka |
120a6e |
TImageCache::instance()->remove(m_floatingImageId);
|
|
Shinya Kitaoka |
120a6e |
if (TImageCache::instance()->isCached(m_undoImageId))
|
|
Shinya Kitaoka |
120a6e |
TImageCache::instance()->remove(m_undoImageId);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
473e70 |
void undo() const override {
|
|
Shinya Kitaoka |
120a6e |
TImageP image = TImageCache::instance()->get(m_imageId, false);
|
|
Shinya Kitaoka |
120a6e |
if (!image) return;
|
|
Shinya Kitaoka |
120a6e |
TRasterP rasImage = getRaster(image);
|
|
Shinya Kitaoka |
120a6e |
TRectD wRect = m_selectionRect.enlarge(2);
|
|
Shinya Kitaoka |
120a6e |
TRect rRect = convertWorldToRaster(wRect, image);
|
|
Shinya Kitaoka |
120a6e |
rRect *= rasImage->getBounds();
|
|
Shinya Kitaoka |
120a6e |
if (!m_undoImageId.empty()) {
|
|
Shinya Kitaoka |
120a6e |
TImageP undoImage = TImageCache::instance()->get(m_undoImageId, false);
|
|
Shinya Kitaoka |
120a6e |
if (!undoImage) return;
|
|
Shinya Kitaoka |
120a6e |
rasImage->copy(getRaster(undoImage), rRect.getP00());
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TXshSimpleLevelP sl(m_imageCell.getSimpleLevel());
|
|
Shinya Kitaoka |
120a6e |
const TFrameId &fid = m_imageCell.m_frameId;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (!m_isPastedSelection) {
|
|
Shinya Kitaoka |
120a6e |
TImageP floatingImage =
|
|
Shinya Kitaoka |
120a6e |
TImageCache::instance()->get(m_oldFloatingImageId, false);
|
|
Shinya Kitaoka |
120a6e |
if (!floatingImage) return;
|
|
Shinya Kitaoka |
120a6e |
TRasterP floatingRaster = getRaster(floatingImage);
|
|
Shinya Kitaoka |
120a6e |
TRop::over(rasImage, floatingRaster, m_startPos);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
ToolUtils::updateSaveBox(sl, fid);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (m_oldPalette) image->getPalette()->assign(m_oldPalette->clone());
|
|
Shinya Kitaoka |
120a6e |
TTool::Application *app = TTool::getApplication();
|
|
Shinya Kitaoka |
120a6e |
app->getPaletteController()
|
|
Shinya Kitaoka |
120a6e |
->getCurrentLevelPalette()
|
|
Shinya Kitaoka |
120a6e |
->notifyPaletteChanged();
|
|
Shinya Kitaoka |
120a6e |
if (!m_tool) return;
|
|
Shinya Kitaoka |
120a6e |
m_tool->notifyImageChanged(m_frameId);
|
|
Shinya Kitaoka |
120a6e |
m_tool->invalidate();
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
473e70 |
void redo() const override {
|
|
Shinya Kitaoka |
120a6e |
TImageP image = TImageCache::instance()->get(m_imageId, false);
|
|
Shinya Kitaoka |
120a6e |
TImageP floatingImage =
|
|
Shinya Kitaoka |
120a6e |
TImageCache::instance()->get(m_floatingImageId, false);
|
|
Shinya Kitaoka |
120a6e |
if (!floatingImage || !image) return;
|
|
Shinya Kitaoka |
120a6e |
TRasterP floatingRas = getRaster(floatingImage);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TXshSimpleLevelP sl(m_imageCell.getSimpleLevel());
|
|
Shinya Kitaoka |
120a6e |
const TFrameId &fid = m_imageCell.m_frameId;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (!m_isPastedSelection) deleteSelectionWithoutUndo(image, m_strokes);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TRasterP ras = getRaster(image);
|
|
Shinya Kitaoka |
120a6e |
pasteFloatingSelectionWithoutUndo(image, floatingRas, m_transformation,
|
|
Shinya Kitaoka |
120a6e |
m_selectionRect, m_noAntialiasing);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
ToolUtils::updateSaveBox(sl, fid);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (m_newPalette) image->getPalette()->assign(m_newPalette->clone());
|
|
Shinya Kitaoka |
120a6e |
TTool::Application *app = TTool::getApplication();
|
|
Shinya Kitaoka |
120a6e |
app->getPaletteController()
|
|
Shinya Kitaoka |
120a6e |
->getCurrentLevelPalette()
|
|
Shinya Kitaoka |
120a6e |
->notifyPaletteChanged();
|
|
Shinya Kitaoka |
120a6e |
if (!m_tool) return;
|
|
Shinya Kitaoka |
120a6e |
m_tool->notifyImageChanged(m_frameId);
|
|
Shinya Kitaoka |
120a6e |
m_tool->invalidate();
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
473e70 |
int getSize() const override { return sizeof(*this); }
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
473e70 |
QString getHistoryString() override { return QObject::tr("Paste"); }
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int UndoPasteFloatingSelection::m_id = 0;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//=============================================================================
|
|
Shinya Kitaoka |
120a6e |
// Next methods are used to compute intersection between selected stroke and
|
|
Shinya Kitaoka |
120a6e |
// image box
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
/*! Help function.*/
|
|
Shinya Kitaoka |
120a6e |
TSegment getSegmentByIndex(TRectD rect, int index) {
|
|
Shinya Kitaoka |
120a6e |
if (index == 0) return TSegment(rect.getP00(), rect.getP01());
|
|
Shinya Kitaoka |
120a6e |
if (index == 1) return TSegment(rect.getP01(), rect.getP11());
|
|
Shinya Kitaoka |
120a6e |
if (index == 2) return TSegment(rect.getP11(), rect.getP10());
|
|
Shinya Kitaoka |
120a6e |
if (index == 3) return TSegment(rect.getP10(), rect.getP00());
|
|
Shinya Kitaoka |
120a6e |
return TSegment();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
/*! Help function. precPoint -> point */
|
|
Shinya Kitaoka |
120a6e |
bool isClockwise(TRectD bbox, int segmentIndex, TThickPoint precPoint,
|
|
Shinya Kitaoka |
120a6e |
TThickPoint point) {
|
|
Shinya Kitaoka |
120a6e |
if (segmentIndex == 0) return precPoint.y > point.y;
|
|
Shinya Kitaoka |
120a6e |
if (segmentIndex == 1) return precPoint.x > point.x;
|
|
Shinya Kitaoka |
120a6e |
if (segmentIndex == 2) return precPoint.y < point.y;
|
|
Shinya Kitaoka |
120a6e |
if (segmentIndex == 3) return precPoint.x < point.x;
|
|
Shinya Kitaoka |
120a6e |
return true;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
/*! Help function.*/
|
|
Shinya Kitaoka |
120a6e |
void addPointToVector(TThickPoint point, std::vector<tthickpoint> &points,</tthickpoint>
|
|
Shinya Kitaoka |
120a6e |
bool insertMiddlePoint) {
|
|
Shinya Kitaoka |
120a6e |
if (insertMiddlePoint)
|
|
Shinya Kitaoka |
120a6e |
points.push_back((points[points.size() - 1] + point) * 0.5);
|
|
Shinya Kitaoka |
120a6e |
points.push_back(point);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
/*! Return intersection between \b bbox and \b chuck;
|
|
Toshihiro Shimizu |
890ddd |
set segmentIndex to index of segment that contains intersection. */
|
|
Toshihiro Shimizu |
890ddd |
TThickPoint getIntersectionPoint(TRectD bbox, const TThickQuadratic *chunk,
|
|
Shinya Kitaoka |
120a6e |
int &segmentIndex,
|
|
Shinya Kitaoka |
120a6e |
bool secondChunkIntersection) {
|
|
Shinya Kitaoka |
120a6e |
TStroke stroke;
|
|
Shinya Kitaoka |
120a6e |
std::vector<tthickpoint> points;</tthickpoint>
|
|
Shinya Kitaoka |
120a6e |
points.push_back(chunk->getThickP0());
|
|
Shinya Kitaoka |
120a6e |
points.push_back(chunk->getThickP1());
|
|
Shinya Kitaoka |
120a6e |
points.push_back(chunk->getThickP2());
|
|
Shinya Kitaoka |
120a6e |
stroke.reshape(&points[0], points.size());
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
std::vector<doublepair> intersectionInfo;</doublepair>
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
std::vector<doublepair> intersections;</doublepair>
|
|
Shinya Kitaoka |
120a6e |
TSegment segment0(bbox.getP00(), bbox.getP01());
|
|
Shinya Kitaoka |
120a6e |
int count0 = intersect(stroke, segment0, intersections);
|
|
Shinya Kitaoka |
120a6e |
if (count0 > 0) {
|
|
Shinya Kitaoka |
120a6e |
DoublePair pair;
|
|
Shinya Kitaoka |
120a6e |
pair.first = intersections[0].first;
|
|
Shinya Kitaoka |
120a6e |
pair.second = 0;
|
|
Shinya Kitaoka |
120a6e |
intersectionInfo.push_back(pair);
|
|
Shinya Kitaoka |
120a6e |
intersections.clear();
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
TSegment segment1(bbox.getP01(), bbox.getP11());
|
|
Shinya Kitaoka |
120a6e |
int count1 = intersect(stroke, segment1, intersections);
|
|
Shinya Kitaoka |
120a6e |
if (count1 > 0) {
|
|
Shinya Kitaoka |
120a6e |
DoublePair pair;
|
|
Shinya Kitaoka |
120a6e |
pair.first = intersections[0].first;
|
|
Shinya Kitaoka |
120a6e |
pair.second = 1;
|
|
Shinya Kitaoka |
120a6e |
intersectionInfo.push_back(pair);
|
|
Shinya Kitaoka |
120a6e |
intersections.clear();
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
TSegment segment2(bbox.getP11(), bbox.getP10());
|
|
Shinya Kitaoka |
120a6e |
int count2 = intersect(stroke, segment2, intersections);
|
|
Shinya Kitaoka |
120a6e |
if (count2 > 0) {
|
|
Shinya Kitaoka |
120a6e |
DoublePair pair;
|
|
Shinya Kitaoka |
120a6e |
pair.first = intersections[0].first;
|
|
Shinya Kitaoka |
120a6e |
pair.second = 2;
|
|
Shinya Kitaoka |
120a6e |
intersectionInfo.push_back(pair);
|
|
Shinya Kitaoka |
120a6e |
intersections.clear();
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
TSegment segment3(bbox.getP10(), bbox.getP00());
|
|
Shinya Kitaoka |
120a6e |
int count3 = intersect(stroke, segment3, intersections);
|
|
Shinya Kitaoka |
120a6e |
if (count3 > 0) {
|
|
Shinya Kitaoka |
120a6e |
DoublePair pair;
|
|
Shinya Kitaoka |
120a6e |
pair.first = intersections[0].first;
|
|
Shinya Kitaoka |
120a6e |
pair.second = 3;
|
|
Shinya Kitaoka |
120a6e |
intersectionInfo.push_back(pair);
|
|
Shinya Kitaoka |
120a6e |
intersections.clear();
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
int infoSize = intersectionInfo.size();
|
|
Shinya Kitaoka |
120a6e |
assert(infoSize <= 2);
|
|
Shinya Kitaoka |
120a6e |
if (infoSize == 1) {
|
|
Shinya Kitaoka |
120a6e |
segmentIndex = intersectionInfo[0].second;
|
|
Shinya Kitaoka |
120a6e |
return stroke.getPoint(intersectionInfo[0].first);
|
|
Shinya Kitaoka |
120a6e |
} else if (infoSize == 2) {
|
|
Shinya Kitaoka |
120a6e |
double firstT = intersectionInfo[0].first;
|
|
Shinya Kitaoka |
120a6e |
double secondT = intersectionInfo[1].first;
|
|
Shinya Kitaoka |
120a6e |
if (!secondChunkIntersection) {
|
|
Shinya Kitaoka |
120a6e |
if (firstT < secondT) {
|
|
Shinya Kitaoka |
120a6e |
segmentIndex = intersectionInfo[0].second;
|
|
Shinya Kitaoka |
120a6e |
return stroke.getPoint(intersectionInfo[0].first);
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
segmentIndex = intersectionInfo[1].second;
|
|
Shinya Kitaoka |
120a6e |
return stroke.getPoint(intersectionInfo[1].first);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
if (firstT > secondT) {
|
|
Shinya Kitaoka |
120a6e |
segmentIndex = intersectionInfo[0].second;
|
|
Shinya Kitaoka |
120a6e |
return stroke.getPoint(intersectionInfo[0].first);
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
segmentIndex = intersectionInfo[1].second;
|
|
Shinya Kitaoka |
120a6e |
return stroke.getPoint(intersectionInfo[1].first);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
segmentIndex = -1;
|
|
Shinya Kitaoka |
120a6e |
return TThickPoint();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Shinya Kitaoka |
120a6e |
/*! Insert \b bbox corners in \b points if \b bbox corners are contained in \b
|
|
Shinya Kitaoka |
120a6e |
* outPoints stroke. */
|
|
Shinya Kitaoka |
120a6e |
void insertBoxCorners(TRectD bbox, std::vector<tthickpoint> &points,</tthickpoint>
|
|
Shinya Kitaoka |
120a6e |
std::vector<tthickpoint> outPoints,</tthickpoint>
|
|
Shinya Kitaoka |
120a6e |
int currentSegmentIndex, int precSegmentIndex) {
|
|
Shinya Kitaoka |
120a6e |
if (outPoints[0] != outPoints[(int)outPoints.size() - 1])
|
|
Shinya Kitaoka |
120a6e |
addPointToVector(outPoints[0], outPoints, true);
|
|
Shinya Kitaoka |
120a6e |
assert((int)outPoints.size() % 2 == 1);
|
|
Shinya Kitaoka |
120a6e |
TStroke *outPointsStroke = new TStroke();
|
|
Shinya Kitaoka |
120a6e |
outPointsStroke->reshape(&(outPoints[0]), outPoints.size());
|
|
Shinya Kitaoka |
120a6e |
TVectorImageP vi(new TVectorImage());
|
|
Shinya Kitaoka |
120a6e |
vi->addStroke(outPointsStroke);
|
|
Shinya Kitaoka |
120a6e |
vi->findRegions();
|
|
Shinya Kitaoka |
120a6e |
assert((int)vi->getRegionCount() > 0);
|
|
Shinya Kitaoka |
120a6e |
bool sameIndex = (precSegmentIndex == currentSegmentIndex);
|
|
Shinya Kitaoka |
120a6e |
if (currentSegmentIndex == -1) return;
|
|
Shinya Kitaoka |
120a6e |
int j;
|
|
Shinya Kitaoka |
120a6e |
for (j = sameIndex ? 1 : 0; j < 2; j++) {
|
|
Shinya Kitaoka |
120a6e |
bool clockwise = j;
|
|
Shinya Kitaoka |
120a6e |
if (sameIndex)
|
|
Shinya Kitaoka |
120a6e |
clockwise = isClockwise(bbox, currentSegmentIndex,
|
|
Shinya Kitaoka |
120a6e |
outPoints[outPoints.size() - 2],
|
|
Shinya Kitaoka |
120a6e |
outPoints[outPoints.size() - 1]);
|
|
Shinya Kitaoka |
120a6e |
int segmentIndex = precSegmentIndex;
|
|
Shinya Kitaoka |
120a6e |
if (sameIndex)
|
|
Shinya Kitaoka |
120a6e |
segmentIndex =
|
|
Shinya Kitaoka |
120a6e |
clockwise ? currentSegmentIndex - 1 : currentSegmentIndex + 1;
|
|
Shinya Kitaoka |
120a6e |
if (segmentIndex < 0) segmentIndex = 3;
|
|
Shinya Kitaoka |
120a6e |
if (segmentIndex > 3) segmentIndex = 0;
|
|
Shinya Kitaoka |
120a6e |
while (segmentIndex != currentSegmentIndex) {
|
|
Shinya Kitaoka |
120a6e |
if (sameIndex) // controllo anche il segmento di partenza.
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
segmentIndex = currentSegmentIndex;
|
|
Shinya Kitaoka |
120a6e |
sameIndex = false;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
TSegment s = getSegmentByIndex(bbox, segmentIndex);
|
|
Shinya Kitaoka |
120a6e |
TThickPoint corner = clockwise ? s.getP0() : s.getP1();
|
|
Shinya Kitaoka |
120a6e |
int i;
|
|
Shinya Kitaoka |
120a6e |
for (i = 0; i < (int)vi->getRegionCount(); i++)
|
|
Shinya Kitaoka |
120a6e |
if (vi->getRegion(i)->contains(corner)) {
|
|
Shinya Kitaoka |
120a6e |
if ((int)points.size() % 2 == 1)
|
|
Shinya Kitaoka |
120a6e |
points.push_back((points[points.size() - 1] + corner) * 0.5);
|
|
Shinya Kitaoka |
120a6e |
points.push_back(corner);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
segmentIndex = clockwise ? segmentIndex - 1 : segmentIndex + 1;
|
|
Shinya Kitaoka |
120a6e |
if (segmentIndex < 0) segmentIndex = 3;
|
|
Shinya Kitaoka |
120a6e |
if (segmentIndex > 3) segmentIndex = 0;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TStroke getStrokeByRect(TRectD r) {
|
|
Shinya Kitaoka |
120a6e |
TStroke stroke;
|
|
Shinya Kitaoka |
120a6e |
if (r.isEmpty()) return stroke;
|
|
Shinya Kitaoka |
120a6e |
std::vector<tthickpoint> points;</tthickpoint>
|
|
Shinya Kitaoka |
120a6e |
points.push_back(r.getP00());
|
|
Shinya Kitaoka |
120a6e |
points.push_back((r.getP00() + r.getP01()) * 0.5);
|
|
Shinya Kitaoka |
120a6e |
points.push_back(r.getP01());
|
|
Shinya Kitaoka |
120a6e |
points.push_back((r.getP01() + r.getP11()) * 0.5);
|
|
Shinya Kitaoka |
120a6e |
points.push_back(r.getP11());
|
|
Shinya Kitaoka |
120a6e |
points.push_back((r.getP11() + r.getP10()) * 0.5);
|
|
Shinya Kitaoka |
120a6e |
points.push_back(r.getP10());
|
|
Shinya Kitaoka |
120a6e |
points.push_back((r.getP10() + r.getP00()) * 0.5);
|
|
Shinya Kitaoka |
120a6e |
points.push_back(r.getP00());
|
|
Shinya Kitaoka |
120a6e |
stroke.reshape(&(points[0]), points.size());
|
|
Shinya Kitaoka |
120a6e |
stroke.setSelfLoop(true);
|
|
Shinya Kitaoka |
120a6e |
return stroke;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TStroke getIntersectedStroke(TStroke &stroke, TRectD bbox) {
|
|
Shinya Kitaoka |
120a6e |
int cpCount = stroke.getControlPointCount();
|
|
Shinya Kitaoka |
120a6e |
if (cpCount == 0) return stroke;
|
|
Shinya Kitaoka |
120a6e |
// isFirstTime, startSegmentIndex e startOutPoints sono usati nel il caso in
|
|
Shinya Kitaoka |
120a6e |
// cui lo stroke inizia fuori dalla bbox.
|
|
Shinya Kitaoka |
120a6e |
bool isFirstTime = true;
|
|
Shinya Kitaoka |
120a6e |
std::vector<tthickpoint> points, outPoints, startOutPoints;</tthickpoint>
|
|
Shinya Kitaoka |
120a6e |
TThickPoint precPoint = stroke.getControlPoint(0);
|
|
Shinya Kitaoka |
120a6e |
bool isPrecPointInternal = bbox.contains(precPoint);
|
|
Shinya Kitaoka |
120a6e |
if (isPrecPointInternal)
|
|
Shinya Kitaoka |
120a6e |
points.push_back(precPoint);
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
outPoints.push_back(precPoint);
|
|
Shinya Kitaoka |
120a6e |
int i;
|
|
Shinya Kitaoka |
120a6e |
int precSegmentIndex, currentSegmentIndex, startSegmentIndex,
|
|
Shinya Kitaoka |
120a6e |
precChunkIndex = -1;
|
|
Shinya Kitaoka |
120a6e |
for (i = 1; i < stroke.getControlPointCount(); i++) {
|
|
Shinya Kitaoka |
120a6e |
TThickPoint point = stroke.getControlPoint(i);
|
|
Shinya Kitaoka |
120a6e |
bool isPointInternal = bbox.contains(point);
|
|
Shinya Kitaoka |
120a6e |
if (isPointInternal && isPrecPointInternal)
|
|
Shinya Kitaoka |
120a6e |
addPointToVector(point, points, (int)points.size() % 2 != i % 2);
|
|
Shinya Kitaoka |
120a6e |
if (!isPointInternal && !isPrecPointInternal)
|
|
Shinya Kitaoka |
120a6e |
addPointToVector(
|
|
Shinya Kitaoka |
120a6e |
point, outPoints,
|
|
Shinya Kitaoka |
120a6e |
(int)outPoints.size() > 0 && (int)outPoints.size() % 2 != i % 2);
|
|
Shinya Kitaoka |
120a6e |
if (isPointInternal != isPrecPointInternal) {
|
|
Shinya Kitaoka |
120a6e |
// Devo trovare l'intersezione
|
|
Shinya Kitaoka |
120a6e |
int chunkIndex = (i % 2 == 0) ? (i * 0.5) - 1 : i * 0.5;
|
|
Shinya Kitaoka |
120a6e |
TThickPoint p = getIntersectionPoint(bbox, stroke.getChunk(chunkIndex),
|
|
Shinya Kitaoka |
120a6e |
currentSegmentIndex,
|
|
Shinya Kitaoka |
120a6e |
chunkIndex == precChunkIndex);
|
|
shun-iwasawa |
63eb15 |
|
|
shun-iwasawa |
63eb15 |
// exactly match the position with the edge of bbox
|
|
shun-iwasawa |
63eb15 |
// or the pasted raster may offset by 1pixel due to truncation in
|
|
shun-iwasawa |
63eb15 |
// ToonzImageUtils::convertWorldToRaster()
|
|
shun-iwasawa |
63eb15 |
if (areAlmostEqual(p.x, bbox.getP00().x, 1e-6))
|
|
shun-iwasawa |
63eb15 |
p.x = bbox.getP00().x;
|
|
shun-iwasawa |
63eb15 |
else if (areAlmostEqual(p.x, bbox.getP11().x, 1e-6))
|
|
shun-iwasawa |
63eb15 |
p.x = bbox.getP11().x;
|
|
shun-iwasawa |
63eb15 |
if (areAlmostEqual(p.y, bbox.getP00().y, 1e-6))
|
|
shun-iwasawa |
63eb15 |
p.y = bbox.getP00().y;
|
|
shun-iwasawa |
63eb15 |
else if (areAlmostEqual(p.y, bbox.getP11().y, 1e-6))
|
|
shun-iwasawa |
63eb15 |
p.y = bbox.getP11().y;
|
|
shun-iwasawa |
63eb15 |
|
|
Shinya Kitaoka |
120a6e |
precChunkIndex = chunkIndex;
|
|
Shinya Kitaoka |
120a6e |
addPointToVector(p, outPoints, (int)outPoints.size() % 2 == 1);
|
|
Shinya Kitaoka |
120a6e |
if (!isPrecPointInternal && points.size() > 0 && outPoints.size() > 0) {
|
|
Shinya Kitaoka |
120a6e |
insertBoxCorners(bbox, points, outPoints, currentSegmentIndex,
|
|
Shinya Kitaoka |
120a6e |
precSegmentIndex);
|
|
Shinya Kitaoka |
120a6e |
outPoints.clear();
|
|
Shinya Kitaoka |
120a6e |
} else if (outPoints.size() > 0 && isFirstTime) {
|
|
Shinya Kitaoka |
120a6e |
startSegmentIndex = currentSegmentIndex;
|
|
Shinya Kitaoka |
120a6e |
startOutPoints = outPoints;
|
|
Shinya Kitaoka |
120a6e |
outPoints.clear();
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
isFirstTime = false;
|
|
Shinya Kitaoka |
120a6e |
precSegmentIndex = currentSegmentIndex;
|
|
Shinya Kitaoka |
120a6e |
addPointToVector(p, points, (int)points.size() % 2 == 1);
|
|
Shinya Kitaoka |
120a6e |
addPointToVector(p, outPoints, (int)outPoints.size() % 2 == 1);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
if (isPointInternal && !isPrecPointInternal)
|
|
Shinya Kitaoka |
120a6e |
addPointToVector(point, points, (int)points.size() % 2 != i % 2);
|
|
Shinya Kitaoka |
120a6e |
if (!isPointInternal && isPrecPointInternal)
|
|
Shinya Kitaoka |
120a6e |
addPointToVector(
|
|
Shinya Kitaoka |
120a6e |
point, outPoints,
|
|
Shinya Kitaoka |
120a6e |
(int)outPoints.size() > 0 && (int)outPoints.size() % 2 != i % 2);
|
|
Shinya Kitaoka |
120a6e |
isPrecPointInternal = isPointInternal;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
// Caso in cui lo stroke aveva il primo punto fuori dalla bbox
|
|
Shinya Kitaoka |
120a6e |
if (!isPrecPointInternal && points.size() > 0 && outPoints.size() > 0) {
|
|
Shinya Kitaoka |
120a6e |
int t;
|
|
Shinya Kitaoka |
120a6e |
for (t = 0; t < (int)outPoints.size(); t++)
|
|
Shinya Kitaoka |
120a6e |
addPointToVector(outPoints[t], startOutPoints,
|
|
Shinya Kitaoka |
120a6e |
(int)startOutPoints.size() % 2 != 2);
|
|
Shinya Kitaoka |
120a6e |
insertBoxCorners(bbox, points, startOutPoints, startSegmentIndex,
|
|
Shinya Kitaoka |
120a6e |
currentSegmentIndex);
|
|
Shinya Kitaoka |
120a6e |
outPoints.clear();
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// Caso particolare in cui lo stroke non ha intersezione con la bbox
|
|
Shinya Kitaoka |
120a6e |
if (points.size() == 0) { // Lo stroke e' completamente contenuto nella bbox
|
|
Shinya Kitaoka |
120a6e |
if (bbox.contains(precPoint))
|
|
Shinya Kitaoka |
120a6e |
return stroke;
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
return getStrokeByRect(bbox);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
if (points[0] != points[(int)points.size() - 1])
|
|
Shinya Kitaoka |
120a6e |
addPointToVector(points[0], points, true);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
assert((int)points.size() % 2 == 1);
|
|
Shinya Kitaoka |
120a6e |
TStroke intersectedStroke;
|
|
Shinya Kitaoka |
120a6e |
intersectedStroke.reshape(&(points[0]), points.size());
|
|
Shinya Kitaoka |
120a6e |
intersectedStroke.setSelfLoop(true);
|
|
Shinya Kitaoka |
120a6e |
return intersectedStroke;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
} // namespace
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//=============================================================================
|
|
Toshihiro Shimizu |
890ddd |
// RasterSelection
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
RasterSelection::RasterSelection()
|
|
Shinya Kitaoka |
120a6e |
: TSelection()
|
|
Shinya Kitaoka |
120a6e |
, m_currentImage()
|
|
Shinya Kitaoka |
120a6e |
, m_oldPalette(0)
|
|
Shinya Kitaoka |
120a6e |
, m_selectionBbox()
|
|
Shinya Kitaoka |
120a6e |
, m_affine()
|
|
Shinya Kitaoka |
120a6e |
, m_startPosition()
|
|
Shinya Kitaoka |
120a6e |
, m_floatingSelection()
|
|
Shinya Kitaoka |
120a6e |
, m_originalfloatingSelection()
|
|
Shinya Kitaoka |
120a6e |
, m_fid()
|
|
Shinya Kitaoka |
120a6e |
, m_transformationCount(0)
|
|
Shinya Kitaoka |
120a6e |
, m_isPastedSelection(false)
|
|
Shinya Kitaoka |
120a6e |
, m_noAntialiasing(false) {
|
|
Shinya Kitaoka |
120a6e |
m_strokes.clear();
|
|
Shinya Kitaoka |
120a6e |
m_originalStrokes.clear();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
RasterSelection::RasterSelection(const RasterSelection &src)
|
|
Shinya Kitaoka |
120a6e |
: TSelection()
|
|
Shinya Kitaoka |
120a6e |
, m_currentImage(src.m_currentImage)
|
|
Shinya Kitaoka |
120a6e |
, m_oldPalette(src.m_oldPalette)
|
|
Shinya Kitaoka |
120a6e |
, m_selectionBbox(src.m_selectionBbox)
|
|
Shinya Kitaoka |
120a6e |
, m_strokes(src.m_strokes)
|
|
Shinya Kitaoka |
120a6e |
, m_originalStrokes(src.m_originalStrokes)
|
|
Shinya Kitaoka |
120a6e |
, m_affine(src.m_affine)
|
|
Shinya Kitaoka |
120a6e |
, m_startPosition(src.m_startPosition)
|
|
Shinya Kitaoka |
120a6e |
, m_fid(src.m_fid)
|
|
Shinya Kitaoka |
120a6e |
, m_transformationCount(src.m_transformationCount)
|
|
Shinya Kitaoka |
120a6e |
, m_isPastedSelection(src.m_isPastedSelection)
|
|
Shinya Kitaoka |
120a6e |
, m_noAntialiasing(src.m_noAntialiasing)
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Shinya Kitaoka |
120a6e |
setView(src.getView());
|
|
Shinya Kitaoka |
120a6e |
if (src.isFloating()) {
|
|
Shinya Kitaoka |
120a6e |
m_floatingSelection = src.m_floatingSelection->clone();
|
|
Shinya Kitaoka |
120a6e |
if (src.m_originalfloatingSelection)
|
|
Shinya Kitaoka |
120a6e |
m_originalfloatingSelection = src.m_originalfloatingSelection->clone();
|
|
Shinya Kitaoka |
120a6e |
assert(isFloating());
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
//! Returns the clone of this selection
|
|
Shinya Kitaoka |
120a6e |
TSelection *RasterSelection::clone() const {
|
|
Shinya Kitaoka |
120a6e |
RasterSelection *rs = new RasterSelection(*this);
|
|
Shinya Kitaoka |
120a6e |
return rs;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//! Notify to the viewer that the selection is changed.
|
|
Shinya Kitaoka |
120a6e |
void RasterSelection::notify() {
|
|
Shinya Kitaoka |
120a6e |
RasterSelection *selection = dynamic_cast<rasterselection *="">(</rasterselection>
|
|
Shinya Kitaoka |
120a6e |
TTool::getApplication()->getCurrentSelection()->getSelection());
|
|
Shinya Kitaoka |
120a6e |
if (selection) selection->notifyView();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
//! Empty the selection.
|
|
Shinya Kitaoka |
120a6e |
//! If the selection is floating, the floating image is pasted using the current
|
|
luz paz |
6454c4 |
//! transformation.
|
|
Shinya Kitaoka |
120a6e |
void RasterSelection::selectNone() {
|
|
Shinya Kitaoka |
120a6e |
if (isFloating()) {
|
|
Shinya Kitaoka |
120a6e |
pasteFloatingSelection();
|
|
Shinya Kitaoka |
120a6e |
notify();
|
|
Shinya Kitaoka |
120a6e |
return;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
m_selectionBbox = TRectD();
|
|
Shinya Kitaoka |
120a6e |
m_strokes.clear();
|
|
Shinya Kitaoka |
120a6e |
m_originalStrokes.clear();
|
|
Shinya Kitaoka |
120a6e |
m_affine = TAffine();
|
|
Shinya Kitaoka |
120a6e |
m_startPosition = TPoint();
|
|
Shinya Kitaoka |
120a6e |
m_floatingSelection = TRasterP();
|
|
Shinya Kitaoka |
120a6e |
m_originalfloatingSelection = TRasterP();
|
|
Shinya Kitaoka |
120a6e |
m_transformationCount = 0;
|
|
Shinya Kitaoka |
120a6e |
m_isPastedSelection = false;
|
|
Shinya Kitaoka |
120a6e |
m_oldPalette = 0;
|
|
Shinya Kitaoka |
120a6e |
notify();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void RasterSelection::select(TStroke &stroke) {
|
|
Shinya Kitaoka |
120a6e |
TRect box = getRaster(m_currentImage)->getBounds();
|
|
Shinya Kitaoka |
120a6e |
TRectD rasterBbox = convertRasterToWorld(box, m_currentImage);
|
|
Shinya Kitaoka |
120a6e |
TStroke intersectedStroke = getIntersectedStroke(stroke, rasterBbox);
|
|
Shinya Kitaoka |
120a6e |
if ((int)intersectedStroke.getControlPointCount() == 0) return;
|
|
Shinya Kitaoka |
120a6e |
m_strokes.push_back(intersectedStroke);
|
|
Shinya Kitaoka |
120a6e |
m_originalStrokes.push_back(intersectedStroke);
|
|
Shinya Kitaoka |
120a6e |
notify();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void RasterSelection::select(const TRectD &rect) {
|
|
Shinya Kitaoka |
120a6e |
assert(!!m_currentImage);
|
|
Shinya Kitaoka |
120a6e |
TRectD r = rect;
|
|
Shinya Kitaoka |
120a6e |
TRect box = getRaster(m_currentImage)->getBounds();
|
|
Shinya Kitaoka |
120a6e |
r *= convertRasterToWorld(box, m_currentImage);
|
|
Shinya Kitaoka |
120a6e |
if (!r.isEmpty()) {
|
|
Shinya Kitaoka |
120a6e |
TStroke stroke = getStrokeByRect(r);
|
|
Shinya Kitaoka |
120a6e |
if ((int)stroke.getControlPointCount() == 0) return;
|
|
Shinya Kitaoka |
120a6e |
m_strokes.push_back(stroke);
|
|
Shinya Kitaoka |
120a6e |
m_originalStrokes.push_back(stroke);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
notify();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void RasterSelection::selectAll() {
|
|
Shinya Kitaoka |
120a6e |
if (!m_currentImage) return;
|
|
Shinya Kitaoka |
120a6e |
selectNone();
|
|
Shinya Kitaoka |
120a6e |
TRectD wRect = convertRasterToWorld(getRaster(m_currentImage)->getBounds(),
|
|
Shinya Kitaoka |
120a6e |
m_currentImage);
|
|
Shinya Kitaoka |
120a6e |
select(wRect);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
bool RasterSelection::isEmpty() const {
|
|
Shinya Kitaoka |
120a6e |
return getStrokesBound(m_strokes).isEmpty();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void RasterSelection::enableCommands() {
|
|
Shinya Kitaoka |
120a6e |
enableCommand(this, MI_Clear, &RasterSelection::deleteSelection);
|
|
Shinya Kitaoka |
120a6e |
enableCommand(this, MI_Cut, &RasterSelection::cutSelection);
|
|
Shinya Kitaoka |
120a6e |
enableCommand(this, MI_Copy, &RasterSelection::copySelection);
|
|
Shinya Kitaoka |
120a6e |
enableCommand(this, MI_Paste, &RasterSelection::pasteSelection);
|
|
Shinya Kitaoka |
120a6e |
enableCommand(this, MI_SelectAll, &RasterSelection::selectAll);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
bool RasterSelection::isFloating() const { return m_floatingSelection; }
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void RasterSelection::transform(const TAffine &affine) {
|
|
Shinya Kitaoka |
120a6e |
m_affine = affine * m_affine;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void RasterSelection::makeFloating() {
|
|
Shinya Kitaoka |
120a6e |
if (isEmpty()) return;
|
|
Shinya Kitaoka |
120a6e |
if (!m_currentImage) return;
|
|
manongjohn |
6939a3 |
|
|
manongjohn |
6939a3 |
if (!isEditable()) return;
|
|
manongjohn |
6939a3 |
|
|
Shinya Kitaoka |
120a6e |
m_floatingSelection = getImageFromSelection(m_currentImage, *this);
|
|
Shinya Kitaoka |
120a6e |
m_originalfloatingSelection = m_floatingSelection->clone();
|
|
Shinya Kitaoka |
120a6e |
deleteSelectionWithoutUndo(m_currentImage, m_strokes);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
ToolUtils::updateSaveBox();
|
|
Shinya Kitaoka |
120a6e |
TTool *tool = TTool::getApplication()->getCurrentTool()->getTool();
|
|
Shinya Kitaoka |
120a6e |
tool->notifyImageChanged(m_fid);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void RasterSelection::pasteFloatingSelection() {
|
|
Shinya Kitaoka |
120a6e |
if (!isFloating()) return;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
assert(m_transformationCount != -1 && m_transformationCount != -2);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
if (m_isPastedSelection)
|
|
Shinya Kitaoka |
120a6e |
TUndoManager::manager()->popUndo(m_transformationCount + 1);
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
TUndoManager::manager()->popUndo(m_transformationCount);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
if (m_transformationCount > 0 || m_isPastedSelection)
|
|
Shinya Kitaoka |
120a6e |
TUndoManager::manager()->add(new UndoPasteFloatingSelection(
|
|
Shinya Kitaoka |
120a6e |
this, m_oldPalette.getPointer(), m_noAntialiasing));
|
|
Shinya Kitaoka |
120a6e |
else if (m_transformationCount == 0)
|
|
Shinya Kitaoka |
120a6e |
TUndoManager::manager()->popUndo(-1, true);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TRectD wRect = getSelectionBbox();
|
|
Shinya Kitaoka |
120a6e |
pasteFloatingSelectionWithoutUndo(m_currentImage, m_floatingSelection,
|
|
Shinya Kitaoka |
120a6e |
m_affine, wRect, m_noAntialiasing);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
ToolUtils::updateSaveBox(m_currentImageCell.getSimpleLevel(),
|
|
Shinya Kitaoka |
120a6e |
m_currentImageCell.getFrameId());
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
setFloatingSeletion(TRasterP());
|
|
Shinya Kitaoka |
120a6e |
selectNone();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TTool *tool = TTool::getApplication()->getCurrentTool()->getTool();
|
|
Shinya Kitaoka |
120a6e |
tool->notifyImageChanged(m_fid);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void RasterSelection::deleteSelection() {
|
|
Shinya Kitaoka |
120a6e |
if (!m_currentImage) return;
|
|
Shinya Kitaoka |
120a6e |
TTool::Application *app = TTool::getApplication();
|
|
Shinya Kitaoka |
120a6e |
TXshSimpleLevel *level = app->getCurrentLevel()->getSimpleLevel();
|
|
manongjohn |
6939a3 |
if (!isEditable()) {
|
|
manongjohn |
6939a3 |
DVGui::error(
|
|
manongjohn |
6939a3 |
QObject::tr("The selection cannot be deleted. It is not editable."));
|
|
manongjohn |
6939a3 |
return;
|
|
manongjohn |
6939a3 |
}
|
|
manongjohn |
6939a3 |
|
|
Shinya Kitaoka |
120a6e |
// we have to remove all undo transformation and the undo for the makeFloating
|
|
Shinya Kitaoka |
120a6e |
// operation!
|
|
Shinya Kitaoka |
120a6e |
if (isFloating()) {
|
|
Shinya Kitaoka |
120a6e |
assert(m_transformationCount != -1 && m_transformationCount != -2);
|
|
Shinya Kitaoka |
120a6e |
if (m_isPastedSelection)
|
|
Shinya Kitaoka |
120a6e |
TUndoManager::manager()->popUndo(m_transformationCount + 1);
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
TUndoManager::manager()->popUndo(m_transformationCount);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
if (!isPastedSelection() && !isEmpty())
|
|
Shinya Kitaoka |
120a6e |
TUndoManager::manager()->add(new UndoDeleteSelection(this, level));
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (!isFloating())
|
|
Shinya Kitaoka |
120a6e |
deleteSelectionWithoutUndo(m_currentImage, m_strokes);
|
|
Shinya Kitaoka |
120a6e |
else if (m_oldPalette)
|
|
Shinya Kitaoka |
120a6e |
m_currentImage->getPalette()->assign(m_oldPalette.getPointer());
|
|
Shinya Kitaoka |
120a6e |
m_floatingSelection = TRasterP();
|
|
Shinya Kitaoka |
120a6e |
m_originalfloatingSelection = TRasterP();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
ToolUtils::updateSaveBox();
|
|
Shinya Kitaoka |
120a6e |
selectNone();
|
|
Shinya Kitaoka |
120a6e |
app->getPaletteController()->getCurrentLevelPalette()->notifyPaletteChanged();
|
|
Shinya Kitaoka |
120a6e |
TTool *tool = app->getCurrentTool()->getTool();
|
|
Shinya Kitaoka |
120a6e |
tool->notifyImageChanged(m_fid);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void RasterSelection::copySelection() {
|
|
Shinya Kitaoka |
120a6e |
if (isEmpty() || !m_currentImage) return;
|
|
Shinya Kitaoka |
120a6e |
TRasterP ras;
|
|
Shinya Kitaoka |
120a6e |
if (!isFloating())
|
|
Shinya Kitaoka |
120a6e |
ras = getImageFromSelection(m_currentImage, *this);
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
ras = m_floatingSelection;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
double dpix, dpiy;
|
|
Shinya Kitaoka |
120a6e |
std::vector<trectd> rect;</trectd>
|
|
Shinya Kitaoka |
120a6e |
if (TToonzImageP ti = (TToonzImageP)(m_currentImage)) {
|
|
Shinya Kitaoka |
120a6e |
ToonzImageData *data = new ToonzImageData();
|
|
Shinya Kitaoka |
120a6e |
ti->getDpi(dpix, dpiy);
|
|
Shinya Kitaoka |
120a6e |
data->setData(ras, ti->getPalette(), dpix, dpiy, ti->getSize(), rect,
|
|
Shinya Kitaoka |
120a6e |
m_strokes, m_originalStrokes, m_affine);
|
|
Shinya Kitaoka |
120a6e |
QApplication::clipboard()->setMimeData(cloneData(data));
|
|
Shinya Kitaoka |
120a6e |
} else if (TRasterImageP ri = (TRasterImageP)(m_currentImage)) {
|
|
Shinya Kitaoka |
120a6e |
FullColorImageData *data = new FullColorImageData();
|
|
Shinya Kitaoka |
120a6e |
ri->getDpi(dpix, dpiy);
|
|
Shinya Kitaoka |
120a6e |
data->setData(ras, ri->getPalette(), dpix, dpiy, ri->getRaster()->getSize(),
|
|
Shinya Kitaoka |
120a6e |
rect, m_strokes, m_originalStrokes, m_affine);
|
|
Shinya Kitaoka |
120a6e |
QApplication::clipboard()->setMimeData(cloneData(data));
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void RasterSelection::cutSelection() {
|
|
Shinya Kitaoka |
120a6e |
copySelection();
|
|
Shinya Kitaoka |
120a6e |
deleteSelection();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
justburner |
2975e1 |
bool RasterSelection::pasteSelection(const RasterImageData *riData) {
|
|
Shinya Kitaoka |
120a6e |
std::vector<trectd> rect;</trectd>
|
|
Shinya Kitaoka |
120a6e |
double currentDpiX, currentDpiY;
|
|
Shinya Kitaoka |
120a6e |
double dpiX, dpiY;
|
|
Shinya Kitaoka |
120a6e |
const ToonzImageData *toonzImageData =
|
|
Shinya Kitaoka |
120a6e |
dynamic_cast<const *="" toonzimagedata="">(riData);</const>
|
|
Shinya Kitaoka |
120a6e |
const FullColorImageData *fullColorData =
|
|
Shinya Kitaoka |
120a6e |
dynamic_cast<const *="" fullcolorimagedata="">(riData);</const>
|
|
Shinya Kitaoka |
120a6e |
if (TToonzImageP ti = (TToonzImageP)m_currentImage) {
|
|
Shinya Kitaoka |
120a6e |
ti->getDpi(currentDpiX, currentDpiY);
|
|
Shinya Kitaoka |
120a6e |
TRasterP cmRas;
|
|
Shinya Kitaoka |
120a6e |
if (fullColorData) {
|
|
Shinya Kitaoka |
120a6e |
DVGui::error(QObject::tr(
|
|
Shinya Kitaoka |
120a6e |
"The copied selection cannot be pasted in the current drawing."));
|
|
justburner |
2975e1 |
return false;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
riData->getData(cmRas, dpiX, dpiY, rect, m_strokes, m_originalStrokes,
|
|
Shinya Kitaoka |
120a6e |
m_affine, m_currentImage->getPalette());
|
|
justburner |
2975e1 |
if (!cmRas) return false;
|
|
Shinya Kitaoka |
120a6e |
m_floatingSelection = cmRas;
|
|
Shinya Kitaoka |
120a6e |
} else if (TRasterImageP ri = (TRasterImageP)m_currentImage) {
|
|
Shinya Kitaoka |
120a6e |
ri->getDpi(currentDpiX, currentDpiY);
|
|
Shinya Kitaoka |
120a6e |
TRasterP ras;
|
|
Shinya Kitaoka |
120a6e |
riData->getData(ras, dpiX, dpiY, rect, m_strokes, m_originalStrokes,
|
|
Shinya Kitaoka |
120a6e |
m_affine, ri->getPalette());
|
|
justburner |
2975e1 |
if (!ras) return false;
|
|
Shinya Kitaoka |
120a6e |
if (TRasterCM32P rasCM = ras) {
|
|
Shinya Kitaoka |
120a6e |
TDimension dim = rasCM->getSize();
|
|
Shinya Kitaoka |
120a6e |
TRaster32P app = TRaster32P(dim.lx, dim.ly);
|
|
Shinya Kitaoka |
120a6e |
TRop::convert(app, rasCM, ri->getPalette());
|
|
Shinya Kitaoka |
120a6e |
ras = app;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
m_floatingSelection = ras;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
if (m_floatingSelection)
|
|
Shinya Kitaoka |
120a6e |
m_originalfloatingSelection = m_floatingSelection->clone();
|
|
Shinya Kitaoka |
120a6e |
TScale sc;
|
|
Shinya Kitaoka |
120a6e |
if (dpiX != 0 && dpiY != 0 && currentDpiX != 0 && currentDpiY != 0)
|
|
shun-iwasawa |
63eb15 |
sc = TScale(currentDpiX / dpiX, currentDpiY / dpiY);
|
|
Shinya Kitaoka |
120a6e |
m_affine = m_affine * sc;
|
|
justburner |
2975e1 |
return true;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void RasterSelection::pasteSelection() {
|
|
Shinya Kitaoka |
120a6e |
TTool::Application *app = TTool::getApplication();
|
|
Shinya Kitaoka |
120a6e |
TTool *tool = app->getCurrentTool()->getTool();
|
|
manongjohn |
6dad4e |
TImageP image = tool->touchImage();
|
|
manongjohn |
6dad4e |
|
|
manongjohn |
6dad4e |
if (!image) return;
|
|
manongjohn |
6dad4e |
|
|
manongjohn |
6939a3 |
if (!isEditable()) {
|
|
manongjohn |
6939a3 |
DVGui::error(
|
|
manongjohn |
6939a3 |
QObject::tr("The selection cannot be pasted. It is not editable."));
|
|
manongjohn |
6939a3 |
return;
|
|
manongjohn |
6939a3 |
}
|
|
manongjohn |
6939a3 |
|
|
justburner |
2975e1 |
TXshLevel *xl = app->getCurrentLevel()->getLevel();
|
|
justburner |
2975e1 |
TXshSimpleLevel *sl = xl ? xl->getSimpleLevel() : nullptr;
|
|
justburner |
2975e1 |
int levelType = sl ? sl->getType() : NO_XSHLEVEL;
|
|
justburner |
2975e1 |
|
|
manongjohn |
6dad4e |
m_currentImage = image;
|
|
manongjohn |
6dad4e |
m_fid = tool->getCurrentFid();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
QClipboard *clipboard = QApplication::clipboard();
|
|
Shinya Kitaoka |
120a6e |
const RasterImageData *riData =
|
|
Shinya Kitaoka |
120a6e |
dynamic_cast<const *="" rasterimagedata="">(clipboard->mimeData());</const>
|
|
Shinya Kitaoka |
120a6e |
const StrokesData *stData =
|
|
Shinya Kitaoka |
120a6e |
dynamic_cast<const *="" strokesdata="">(clipboard->mimeData());</const>
|
|
justburner |
2975e1 |
QImage clipImage = clipboard->image();
|
|
justburner |
2975e1 |
if (!riData && !stData && clipImage.height() == 0) return;
|
|
Shinya Kitaoka |
120a6e |
if (isFloating()) pasteFloatingSelection();
|
|
Shinya Kitaoka |
120a6e |
selectNone();
|
|
Shinya Kitaoka |
120a6e |
m_isPastedSelection = true;
|
|
justburner |
2975e1 |
if (!m_currentImageCell.getSimpleLevel()) {
|
|
justburner |
2975e1 |
const TXshCell &imageCell = TTool::getImageCell();
|
|
justburner |
2975e1 |
|
|
justburner |
2975e1 |
TImageP image =
|
|
justburner |
2975e1 |
imageCell.getImage(false, 1); // => See the onImageChanged() warning !
|
|
justburner |
2975e1 |
|
|
justburner |
2975e1 |
TToonzImageP ti = (TToonzImageP)image;
|
|
justburner |
2975e1 |
TRasterImageP ri = (TRasterImageP)image;
|
|
justburner |
2975e1 |
if (!ti && !ri) return;
|
|
justburner |
2975e1 |
|
|
justburner |
2975e1 |
makeCurrent();
|
|
justburner |
2975e1 |
setCurrentImage(image, imageCell);
|
|
justburner |
2975e1 |
}
|
|
justburner |
2975e1 |
if (m_currentImage->getPalette())
|
|
justburner |
2975e1 |
m_oldPalette = m_currentImage->getPalette()->clone();
|
|
Shinya Kitaoka |
120a6e |
if (stData) {
|
|
Shinya Kitaoka |
120a6e |
if (TToonzImageP ti = m_currentImage)
|
|
Shinya Kitaoka |
120a6e |
riData = stData->toToonzImageData(ti);
|
|
Shinya Kitaoka |
120a6e |
else {
|
|
Shinya Kitaoka |
120a6e |
TRasterImageP ri = m_currentImage;
|
|
Shinya Kitaoka |
120a6e |
assert(ri);
|
|
Shinya Kitaoka |
120a6e |
double dpix, dpiy;
|
|
Shinya Kitaoka |
120a6e |
ri->getDpi(dpix, dpiy);
|
|
Shinya Kitaoka |
120a6e |
if (dpix == 0 || dpiy == 0) {
|
|
Shinya Kitaoka |
120a6e |
TPointD dpi =
|
|
Shinya Kitaoka |
120a6e |
tool->getXsheet()->getScene()->getCurrentCamera()->getDpi();
|
|
Shinya Kitaoka |
120a6e |
dpix = dpi.x;
|
|
Shinya Kitaoka |
120a6e |
dpiy = dpi.y;
|
|
Shinya Kitaoka |
120a6e |
ri->setDpi(dpix, dpiy);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
riData = stData->toFullColorImageData(ri);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
justburner |
2975e1 |
if (clipImage.height() > 0 && (levelType == OVL_XSHLEVEL ||
|
|
justburner |
2975e1 |
m_currentImage->getType() == OVL_XSHLEVEL)) {
|
|
justburner |
2975e1 |
// An image was pasted from outside OpenToonz
|
|
justburner |
2975e1 |
|
|
justburner |
2975e1 |
// Set up variables
|
|
justburner |
2975e1 |
std::vector<trectd> rects;</trectd>
|
|
justburner |
2975e1 |
const std::vector<tstroke> strokes;</tstroke>
|
|
justburner |
2975e1 |
const std::vector<tstroke> originalStrokes;</tstroke>
|
|
justburner |
2975e1 |
TRasterImageP ri = m_currentImage;
|
|
justburner |
2975e1 |
TAffine aff;
|
|
justburner |
2975e1 |
TRasterP ras = rasterFromQImage(clipImage);
|
|
justburner |
2975e1 |
// center the image in the viewer
|
|
justburner |
2975e1 |
rects.push_back(TRectD(0.0 - clipImage.width() / 2,
|
|
justburner |
2975e1 |
0.0 - clipImage.height() / 2, clipImage.width() / 2,
|
|
justburner |
2975e1 |
clipImage.height() / 2));
|
|
justburner |
2975e1 |
|
|
justburner |
2975e1 |
TRectD r =
|
|
justburner |
2975e1 |
TRectD(0.0 - (clipImage.width() / 2), 0.0 - (clipImage.height() / 2),
|
|
justburner |
2975e1 |
clipImage.width() / 2, clipImage.height() / 2);
|
|
justburner |
2975e1 |
TRect box = getRaster(m_currentImage)->getBounds();
|
|
justburner |
2975e1 |
r *= convertRasterToWorld(box, m_currentImage);
|
|
justburner |
2975e1 |
if (!r.isEmpty()) {
|
|
justburner |
2975e1 |
TStroke stroke = getStrokeByRect(r);
|
|
justburner |
2975e1 |
if ((int)stroke.getControlPointCount() == 0) return;
|
|
justburner |
2975e1 |
m_strokes.push_back(stroke);
|
|
justburner |
2975e1 |
m_originalStrokes.push_back(stroke);
|
|
justburner |
2975e1 |
}
|
|
justburner |
2975e1 |
// pack up the data to send to the next pasteSelection
|
|
justburner |
2975e1 |
FullColorImageData *qimageData = new FullColorImageData();
|
|
justburner |
2975e1 |
|
|
justburner |
2975e1 |
qimageData->setData(ras, ri->getPalette(), 120.0, 120.0,
|
|
justburner |
2975e1 |
ri->getRaster()->getSize(), rects, m_strokes,
|
|
justburner |
2975e1 |
m_originalStrokes, aff);
|
|
justburner |
2975e1 |
setSelectionBbox(TRectD(0.0 - clipImage.width() / 2,
|
|
justburner |
2975e1 |
0.0 - clipImage.height() / 2, clipImage.width() / 2,
|
|
justburner |
2975e1 |
clipImage.height() / 2));
|
|
justburner |
2975e1 |
|
|
justburner |
2975e1 |
riData = qimageData;
|
|
justburner |
2975e1 |
}
|
|
justburner |
2975e1 |
|
|
Shinya Kitaoka |
120a6e |
if (!riData) return;
|
|
justburner |
2975e1 |
if (!pasteSelection(riData)) return;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
app->getPaletteController()->getCurrentLevelPalette()->notifyPaletteChanged();
|
|
Shinya Kitaoka |
120a6e |
notify();
|
|
Shinya Kitaoka |
120a6e |
TUndoManager::manager()->add(new UndoPasteSelection(this));
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
bool RasterSelection::isTransformed() { return !m_affine.isIdentity(); }
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
manongjohn |
6939a3 |
bool RasterSelection::isEditable() {
|
|
manongjohn |
6939a3 |
TTool::Application *app = TTool::getApplication();
|
|
manongjohn |
6939a3 |
TXshSimpleLevel *level = app->getCurrentLevel()->getSimpleLevel();
|
|
manongjohn |
6939a3 |
|
|
manongjohn |
6939a3 |
TFrameHandle *frame = app->getCurrentFrame();
|
|
manongjohn |
6939a3 |
bool filmstrip = frame->isEditingLevel();
|
|
manongjohn |
6939a3 |
|
|
manongjohn |
6939a3 |
if (level) {
|
|
manongjohn |
6939a3 |
if (level->isReadOnly()) return false;
|
|
manongjohn |
6939a3 |
|
|
manongjohn |
6939a3 |
TFrameId frameId = app->getCurrentTool()->getTool()->getCurrentFid();
|
|
manongjohn |
6939a3 |
if (level->isFrameReadOnly(frameId)) return false;
|
|
manongjohn |
6939a3 |
}
|
|
manongjohn |
6939a3 |
|
|
manongjohn |
6939a3 |
if (!filmstrip) {
|
|
manongjohn |
6939a3 |
int colIndex = app->getCurrentTool()->getTool()->getColumnIndex();
|
|
manongjohn |
6939a3 |
int rowIndex = frame->getFrame();
|
|
manongjohn |
6939a3 |
if (app->getCurrentTool()->getTool()->isColumnLocked(colIndex))
|
|
manongjohn |
6939a3 |
return false;
|
|
manongjohn |
6939a3 |
|
|
manongjohn |
6939a3 |
TXsheet *xsh = app->getCurrentXsheet()->getXsheet();
|
|
manongjohn |
6939a3 |
TStageObject *obj = xsh->getStageObject(TStageObjectId::ColumnId(colIndex));
|
|
manongjohn |
6939a3 |
// Test for Mesh-deformed levels
|
|
manongjohn |
6939a3 |
const TStageObjectId &parentId = obj->getParent();
|
|
manongjohn |
6939a3 |
if (parentId.isColumn() && obj->getParentHandle()[0] != 'H') {
|
|
manongjohn |
6939a3 |
TXshSimpleLevel *parentSl =
|
|
manongjohn |
6939a3 |
xsh->getCell(rowIndex, parentId.getIndex()).getSimpleLevel();
|
|
manongjohn |
6939a3 |
if (parentSl && parentSl->getType() == MESH_XSHLEVEL) return false;
|
|
manongjohn |
6939a3 |
}
|
|
manongjohn |
6939a3 |
}
|
|
manongjohn |
6939a3 |
|
|
manongjohn |
6939a3 |
return true;
|
|
manongjohn |
6939a3 |
}
|
|
manongjohn |
6939a3 |
|
|
manongjohn |
6939a3 |
//-----------------------------------------------------------------------------
|
|
manongjohn |
6939a3 |
|
|
Shinya Kitaoka |
120a6e |
TRectD RasterSelection::getStrokesBound(std::vector<tstroke> strokes) const {</tstroke>
|
|
Shinya Kitaoka |
120a6e |
int i;
|
|
Shinya Kitaoka |
120a6e |
TRectD box = TRectD();
|
|
Shinya Kitaoka |
120a6e |
for (i = 0; i < (int)strokes.size(); i++) box += strokes[i].getBBox();
|
|
Shinya Kitaoka |
120a6e |
return box;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TRectD RasterSelection::getSelectionBound() const {
|
|
Shinya Kitaoka |
120a6e |
if (m_strokes.size() == 0) return TRectD();
|
|
shun-iwasawa |
63eb15 |
TRectD selectionBox = getStrokesBound(m_strokes);
|
|
Shinya Kitaoka |
120a6e |
if (isFloating()) selectionBox = m_affine * selectionBox;
|
|
Shinya Kitaoka |
120a6e |
return selectionBox;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TRectD RasterSelection::getOriginalSelectionBound() const {
|
|
Shinya Kitaoka |
120a6e |
if (m_originalStrokes.size() == 0) return TRectD();
|
|
Shinya Kitaoka |
120a6e |
return getStrokesBound(m_originalStrokes);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TRectD RasterSelection::getSelectionBbox() const {
|
|
shun-iwasawa |
63eb15 |
TRectD rect = m_selectionBbox;
|
|
Shinya Kitaoka |
120a6e |
if (isFloating()) rect = m_affine * m_selectionBbox;
|
|
Shinya Kitaoka |
120a6e |
return rect;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void RasterSelection::setSelectionBbox(const TRectD &rect) {
|
|
Shinya Kitaoka |
120a6e |
m_selectionBbox = rect;
|
|
Toshihiro Shimizu |
890ddd |
}
|