TVectorImageP MyInbetweener::tween(double t)
{
	TVectorImageP vi = m_vi0->clone();
	int n = tmin(m_vi0->getStrokeCount(), m_vi1->getStrokeCount());
	for (int i = 0; i < n; i++) {
		TStroke *stroke0 = m_vi0->getStroke(i);
		TStroke *stroke1 = m_vi1->getStroke(i);
		TStroke *stroke = vi->getStroke(i);
		int m = tmin(stroke0->getControlPointCount(), stroke1->getControlPointCount());
		for (int j = 0; j < m; j++) {
			TThickPoint p0 = stroke0->getControlPoint(j);
			TThickPoint p1 = stroke1->getControlPoint(j);
			TThickPoint p = (1 - t) * p0 + t * p1;
			stroke->setControlPoint(j, p);
		}
		/*
    for(int j=2;j+2<m;j+=2)
    {
      TThickPoint p0 = stroke0->getControlPoint(j-2);
      TThickPoint p1 = stroke0->getControlPoint(j-1);
      TThickPoint p2 = stroke0->getControlPoint(j);
      TThickPoint p3 = stroke0->getControlPoint(j+1);
      TThickPoint p4 = stroke0->getControlPoint(j+2);
      if(tdistance2(p0,p1)<0.001 && tdistance2(p3,p4)<0.001)
      {
        p2 = 0.5*(p1+p2);
        stroke->setControlPoint(j,p2);
      }
    }
    */
	}
	return vi;
}
 void doClose(double t, const TImageP &img, const TVectorImageP &firstImage,
              const TVectorImageP &lastImage) {
   if (t == 0)
     applyAutoclose(img, TRectD(), firstImage->getStroke(0));
   else if (t == 1)
     applyAutoclose(img, TRectD(), lastImage->getStroke(0));
   else {
     assert(firstImage->getStrokeCount() == 1);
     assert(lastImage->getStrokeCount() == 1);
     TVectorImageP vi = TInbetween(firstImage, lastImage).tween(t);
     assert(vi->getStrokeCount() == 1);
     applyAutoclose(img, TRectD(), vi->getStroke(0));
   }
 }
Beispiel #3
0
TStroke *PinchTool::getClosestStroke(const TPointD &pos, double &w) const
{
	TVectorImageP vi = TImageP(getImage(false));
	if (!vi)
		return 0;
	double dist = 0;
	UINT index;
	if (vi->getNearestStroke(pos, w, index, dist, true))
		return vi->getStroke(index);
	else
		return 0;
}
Beispiel #4
0
void StrokeSelection::paste() {
  TTool *tool = TTool::getApplication()->getCurrentTool()->getTool();
  if (!tool) return;
  if (TTool::getApplication()->getCurrentObject()->isSpline()) {
    const StrokesData *stData = dynamic_cast<const StrokesData *>(
        QApplication::clipboard()->mimeData());
    if (!stData) return;
    TVectorImageP splineImg = tool->getImage(true);
    TVectorImageP img       = stData->m_image;
    if (!splineImg || !img) return;

    QMutexLocker lock(splineImg->getMutex());
    TUndo *undo = new ToolUtils::UndoPath(
        tool->getXsheet()->getStageObject(tool->getObjectId())->getSpline());
    while (splineImg->getStrokeCount() > 0) splineImg->deleteStroke(0);

    TStroke *stroke = img->getStroke(0);
    splineImg->addStroke(new TStroke(*stroke), false);
    TUndoManager::manager()->add(undo);
    tool->notifyImageChanged();
    tool->invalidate();
    return;
  }

  TVectorImageP tarImg = tool->touchImage();
  if (!tarImg) return;
  TPaletteP palette       = tarImg->getPalette();
  TPaletteP oldPalette    = new TPalette();
  if (palette) oldPalette = palette->clone();
  bool isPaste = pasteStrokesWithoutUndo(tarImg, m_indexes, m_sceneHandle);
  if (isPaste) {
    TXshSimpleLevel *level =
        TTool::getApplication()->getCurrentLevel()->getSimpleLevel();
    TUndoManager::manager()->add(new PasteStrokesUndo(
        level, tool->getCurrentFid(), m_indexes, oldPalette, m_sceneHandle));
    m_updateSelectionBBox = isPaste;
  }
  tool->notifyImageChanged();
  tool->getApplication()
      ->getPaletteController()
      ->getCurrentLevelPalette()
      ->notifyPaletteChanged();
  m_updateSelectionBBox = false;
  tool->invalidate();
}
//!Converts a TVectorImage into a TRasterImage. The input vector image
//!is transformed through the passed affine \b aff, and put into a
//!TRasterImage strictly covering the bounding box of the transformed
//!vector image. The output image has its lower-left position in the
//!world reference specified by the \b pos parameter, which is granted to
//!be an integer displacement of the passed value. Additional parameters
//!include an integer \b enlarge by which the output image is enlarged with
//!respect to the transformed image's bbox, and the bool \b transformThickness
//!to specify whether the transformation should involve strokes' thickensses
//!or not.
TRasterImageP TRasterImageUtils::vectorToFullColorImage(
	const TVectorImageP &vimage, const TAffine &aff, TPalette *palette,
	const TPointD &outputPos, const TDimension &outputSize,
	const std::vector<TRasterFxRenderDataP> *fxs, bool transformThickness)
{
	if (!vimage || !palette)
		return 0;

	//Transform the vector image through aff
	TVectorImageP vi = vimage->clone();
	vi->transform(aff, transformThickness);

	//Allocate the output ToonzImage
	TRaster32P raster(outputSize.lx, outputSize.ly);
	raster->clear();
	TRasterImageP ri(raster);
	ri->setPalette(palette->clone());

	//Shift outputPos to the origin
	vi->transform(TTranslation(-outputPos));

	int strokeCount = vi->getStrokeCount();
	std::vector<int> strokeIndex(strokeCount);
	std::vector<TStroke *> strokes(strokeCount);
	int i;
	for (i = 0; i < strokeCount; ++i) {
		strokeIndex[i] = i;
		strokes[i] = vi->getStroke(i);
	}
	vi->notifyChangedStrokes(strokeIndex, strokes);

	int maxStyleId = palette->getStyleCount() - 1;
	for (i = 0; i < (int)vi->getRegionCount(); ++i) {
		TRegion *region = vi->getRegion(i);
		fastAddPaintRegion(ri, region, tmin(maxStyleId, region->getStyle()), maxStyleId);
	}

	set<int> colors;
	if (fxs) {
		for (i = 0; i < (int)fxs->size(); i++) {
			SandorFxRenderData *sandorData = dynamic_cast<SandorFxRenderData *>((*fxs)[i].getPointer());
			if (sandorData && sandorData->m_type == BlendTz) {
				std::string indexes = toString(sandorData->m_blendParams.m_colorIndex);
				std::vector<std::string> items;
				parseIndexes(indexes, items);
				PaletteFilterFxRenderData paletteFilterData;
				insertIndexes(items, &paletteFilterData);
				colors = paletteFilterData.m_colors;
				break;
			}
		}
	}

	for (i = 0; i < strokeCount; ++i) {
		TStroke *stroke = vi->getStroke(i);

		bool visible = false;
		int styleId = stroke->getStyle();
		TColorStyleP style = palette->getStyle(styleId);
		assert(style);
		int colorCount = style->getColorParamCount();
		if (colorCount == 0)
			visible = true;
		else {
			visible = false;
			for (int j = 0; j < style->getColorParamCount() && !visible; j++) {
				TPixel32 color = style->getColorParamValue(j);
				if (color.m != 0)
					visible = true;
			}
		}
		if (visible)
			fastAddInkStroke(ri, stroke, TRectD(), 1, true);
	}
	return ri;
}
void MyInbetweener::stabilizeSegments(TVectorImageP &image)
{
	for (int i = 0; i < image->getStrokeCount(); i++)
		stabilizeSegments(image->getStroke(i));
}
void VectorBrushProp::draw(const TVectorRenderData &rd)
{
	//Ensure that the stroke overlaps our clipping rect
	if (rd.m_clippingRect != TRect() && !rd.m_is3dView &&
		!convert(rd.m_aff * m_stroke->getBBox()).overlaps(rd.m_clippingRect))
		return;

	TPaletteP palette(m_brush->getPalette());
	if (!palette)
		return;

	static TOutlineUtil::OutlineParameter param; //unused, but requested

	//Build a solid color style to draw each m_vi's stroke with.
	TSolidColorStyle colorStyle;

	//Push the specified rd affine before drawing
	glPushMatrix();
	tglMultMatrix(rd.m_aff);

	//1. If necessary, build the outlines
	double currentPixelSize = sqrt(tglGetPixelSize2());
	bool differentPixelSize = !isAlmostZero(currentPixelSize - m_pixelSize, 1e-5);
	m_pixelSize = currentPixelSize;

	int i, viRegionsCount = m_brush->getRegionCount(), viStrokesCount = m_brush->getStrokeCount();
	if (differentPixelSize || m_strokeChanged) {
		m_strokeChanged = false;

		//1a. First, the regions
		m_regionOutlines.resize(viRegionsCount);

		for (i = 0; i < viRegionsCount; ++i) {
			TRegionOutline &outline = m_regionOutlines[i];
			const TRegion *brushRegion = m_brush->getRegion(i);

			//Build the outline
			outline.clear();
			TOutlineUtil::makeOutline(*getStroke(), *brushRegion, m_brushBox,
									  outline);
		}

		//1b. Then, the strokes
		m_strokeOutlines.resize(viStrokesCount);

		for (i = 0; i < viStrokesCount; ++i) {
			TStrokeOutline &outline = m_strokeOutlines[i];
			const TStroke *brushStroke = m_brush->getStroke(i);

			outline.getArray().clear();
			TOutlineUtil::makeOutline(*getStroke(), *brushStroke, m_brushBox,
									  outline, param);
		}
	}

	//2. Draw the outlines

	UINT s, t, r,
		strokesCount = m_brush->getStrokeCount(),
		regionCount = m_brush->getRegionCount();

	for (s = 0; s < strokesCount; s = t) //Each cycle draws a group
	{
		//A vector image stores group strokes with consecutive indices.

		//2a. First, draw regions in the strokeIdx-th stroke's group
		for (r = 0; r < regionCount; ++r) {
			if (m_brush->sameGroupStrokeAndRegion(s, r)) {
				const TRegion *brushRegion = m_brush->getRegion(r);
				const TColorStyle *brushStyle =
					palette->getStyle(brushRegion->getStyle());
				assert(brushStyle);

				//Draw the outline
				colorStyle.setMainColor(brushStyle->getMainColor());
				colorStyle.drawRegion(0, false, m_regionOutlines[r]);
			}
		}

		//2b. Then, draw all strokes in strokeIdx-th stroke's group
		for (t = s; t < strokesCount && m_brush->sameGroup(s, t); ++t) {
			const TStroke *brushStroke = m_brush->getStroke(t);
			const TColorStyle *brushStyle =
				palette->getStyle(brushStroke->getStyle());
			if (!brushStyle)
				continue;

			colorStyle.setMainColor(brushStyle->getMainColor());
			colorStyle.drawStroke(0, &m_strokeOutlines[t], brushStroke); //brushStroke unused but requested
		}
	}

	glPopMatrix();
}
Beispiel #8
0
	void leftButtonUp(const TPointD &, const TMouseEvent &)
	{
		if (!m_active)
			return;

		m_active = false;
		m_pointAtMouseDown = m_pointAtMove = TConsts::napd;

		TStroke *ref;

		TVectorImageP vi = TImageP(getImage(true));
		if (!vi)
			return;
		QMutexLocker lock(vi->getMutex());
		UINT i, j;

		for (i = 0; i < m_strokeHit.size(); ++i) {
			ref = m_strokeHit[i];
			ref->enableComputeOfCaches();
			ref->reduceControlPoints(getPixelSize() * ReduceControlPointCorrection, *(m_hitStrokeCorners[i]));
			// vi->validateRegionEdges(ref, false);
		}
		clearPointerContainer(m_hitStrokeCorners);
		m_hitStrokeCorners.clear();

		UINT count = 0;
		for (i = 0; i < m_strokeToModify.size(); ++i) {
			// recupero la stroke collection
			MagnetTool::strokeCollection &sc = m_strokeToModify[i];

			for (j = 0; j < sc.m_splittedToMove.size(); ++j) {
				ref = sc.m_splittedToMove[j];
				ref->enableComputeOfCaches();
				ref->reduceControlPoints(getPixelSize() * ReduceControlPointCorrection, *(m_strokeToModifyCorners[count++]));
			}

			// ricostruisco una stroke con quella data
			ref = merge(sc.m_splitted);

			if (sc.m_parent->isSelfLoop()) {
				int cpCount = ref->getControlPointCount();
				TThickPoint p1 = ref->getControlPoint(0);
				TThickPoint p2 = ref->getControlPoint(cpCount - 1);
				TThickPoint midP = (p1 + p2) * 0.5;
				ref->setControlPoint(0, midP);
				ref->setControlPoint(cpCount - 1, midP);
				ref->setSelfLoop(true);
			}

			sc.m_parent->swapGeometry(*ref);

			delete ref;							  // elimino la curva temporanea
			clearPointerContainer(sc.m_splitted); // pulisco le stroke trovate con lo split
			sc.m_splittedToMove.clear();		  // pulisco il contenitore ( le stroke
												  // che erano contenute qua sono state
												  // eliminate nella clearPointer....
		}
		clearPointerContainer(m_strokeToModifyCorners);
		m_strokeToModifyCorners.clear();

		for (i = 0; i < vi->getStrokeCount(); ++i) {
			ref = vi->getStroke(i);
			ref->invalidate();
		}

		vi->notifyChangedStrokes(m_changedStrokes, m_oldStrokesArray);
		notifyImageChanged();
		if (m_undo)
			TUndoManager::manager()->add(m_undo);
		m_undo = 0;
		clearPointerContainer(m_oldStrokesArray);
		m_oldStrokesArray.clear();
		invalidate();
	};
Beispiel #9
0
	void leftButtonDown(const TPointD &pos, const TMouseEvent &e)
	{
		TPointD p(pos);

		m_oldPos = pos;

		m_pointAtMouseDown = p;
		m_startingPos = p;
		m_active = false;
		TVectorImageP vi = TImageP(getImage(true));
		if (!vi)
			return;
		QMutexLocker lock(vi->getMutex());
		m_active = true;

		m_pointAtMove = m_pointAtMouseDown = p;
		m_strokeHit.clear();
		m_changedStrokes.clear();
		m_strokeToModify.clear();

		std::vector<TStroke *> strokeUndo;

		TStroke *ref;

		m_hitStrokeCorners.clear();
		m_strokeToModifyCorners.clear();

		UINT i = 0;
		for (; i < vi->getStrokeCount(); ++i) {
			if (!vi->inCurrentGroup(i))
				continue;

			TStroke *stroke = vi->getStroke(i);
			ref = stroke;
			//  calcola le intersezioni
			std::vector<double> intersections;
			intersect(*ref, p, m_pointSize, intersections);

			if (intersections.empty()) {
				if (increaseControlPoints(*ref,
										  TStrokePointDeformation(p, m_pointSize))) {
					m_changedStrokes.push_back(i);
					m_strokeHit.push_back(ref);

					std::vector<int> *corners = new std::vector<int>;
					corners->push_back(0);
					detectCorners(ref, 20, *corners);
					corners->push_back(ref->getChunkCount());
					m_hitStrokeCorners.push_back(corners);

					ref->disableComputeOfCaches();

					strokeUndo.push_back(ref);
				}
			} else {
				strokeUndo.push_back(ref);

				MagnetTool::strokeCollection sc;

				sc.m_parent = ref;

				splitStroke(*sc.m_parent, intersections, sc.m_splitted);

				selectStrokeToMove(sc.m_splitted,
								   p,
								   m_pointSize,
								   sc.m_splittedToMove);
				for (UINT ii = 0; ii < sc.m_splittedToMove.size(); ++ii) {
					TStroke *temp = sc.m_splittedToMove[ii];
					bool test = increaseControlPoints(*temp, TStrokePointDeformation(p, m_pointSize));
					assert(test);

					std::vector<int> *corners = new std::vector<int>;
					corners->push_back(0);
					detectCorners(temp, 20, *corners);
					corners->push_back(temp->getChunkCount());
					m_strokeToModifyCorners.push_back(corners);
				}

				m_strokeToModify.push_back(sc);
				m_changedStrokes.push_back(i);
			}
		}

		m_oldStrokesArray.resize(m_changedStrokes.size());
		for (i = 0; i < m_changedStrokes.size(); i++)
			m_oldStrokesArray[i] = new TStroke(*(vi->getStroke(m_changedStrokes[i])));

		if (!strokeUndo.empty()) {
			if (TTool::getApplication()->getCurrentObject()->isSpline())
				m_undo = new UndoPath(getXsheet()->getStageObject(getObjectId())->getSpline());
			else {
				TXshSimpleLevel *sl = TTool::getApplication()->getCurrentLevel()->getSimpleLevel();
				assert(sl);
				TFrameId id = getCurrentFid();
				m_undo = new UndoModifyListStroke(sl, id, strokeUndo);
			}
		}

		invalidate();
		// vi->validateRegionEdges(ref, true);
	};
Beispiel #10
0
void PinchTool::leftButtonDown(const TPointD &pos,
							   const TMouseEvent &event)
{
	m_curr = m_down = pos;

	if (!m_active &&
		!m_selector.isSelected()) {
		m_active = false;

		assert(m_undo == 0);

		StrokeDeformation *
			deformation = m_deformation;

		TVectorImageP
			vi = TImageP(getImage(true));

		if (!vi)
			return;

		m_active = true;

		ContextStatus
			*status = &m_status;

		// reset status
		status->init();

		double
			w,
			dist2;

		// find nearest stroke
		if (vi->getNearestStroke(m_down,
								 w,
								 m_n,
								 dist2, true)) {

			TStroke
				*stroke = vi->getStroke(m_n);
			assert(stroke && "Not valid stroke found!!!");
			if (!stroke)
				return;

			updateStrokeStatus(stroke,
							   w);

			// set parameters from sliders
			updateInterfaceStatus(event);

			deformation->activate(status);

			// stroke can be changed (replaced by another) during deformation activate
			if (TTool::getApplication()->getCurrentObject()->isSpline())
				m_undo = new ToolUtils::UndoPath(getXsheet()->getStageObject(getObjectId())->getSpline());
			else {
				TXshSimpleLevel *sl = TTool::getApplication()->getCurrentLevel()->getSimpleLevel();
				assert(sl);
				TFrameId id = getCurrentFid();
				m_undo = new UndoModifyStrokeAndPaint(sl, id, m_n);
			}
		}
	}

	m_selector.mouseDown(m_curr);
	m_prev = m_curr;

	invalidate();
}