예제 #1
0
	void updateLevel()
	{
		TTool::Application *app = TTool::getApplication();
		if (!app->getCurrentLevel()->getLevel())
			return;
		TXshSimpleLevelP xl = app->getCurrentLevel()->getLevel()->getSimpleLevel();
		if (app->getCurrentFrame()->getFrameType() != TFrameHandle::LevelFrame)
			return;

		TFrameId fid = app->getCurrentFrame()->getFid();
		TVectorImageP src = xl->getFrame(fid, true);
		int count = src->getStrokeCount();

		for (int i = 1; i < 10; i++) {
			++fid;
			if (!xl->isFid(fid)) {
				TVectorImageP vi = new TVectorImage();
				xl->setFrame(fid, vi);
			}
			TVectorImageP vi = xl->getFrame(fid, true);
			TVectorImageP dst = src->clone();
			deform(dst.getPointer(), src.getPointer(), (double)i / (double)9);
			count = dst->getStrokeCount();
			vi->mergeImage(dst, TAffine());
			app->getCurrentTool()->getTool()->notifyImageChanged(fid);
		}
	}
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;
}
예제 #3
0
 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));
   }
 }
예제 #4
0
StrokesData *FullColorImageData::toStrokesData(ToonzScene *scene) const
{
	assert(scene);
	TRectD rect;
	if (!m_rects.empty())
		rect = m_rects[0];
	else if (!m_strokes.empty())
		rect = m_strokes[0].getBBox();
	unsigned int i;
	for (i = 0; i < m_rects.size(); i++)
		rect += m_rects[i];
	for (i = 0; i < m_strokes.size(); i++)
		rect += m_strokes[i].getBBox();
	TRasterImageP image(m_copiedRaster);
	image->setPalette(FullColorPalette::instance()->getPalette(scene));
	image->setDpi(m_dpiX, m_dpiY);

	const VectorizerParameters *vParams = scene->getProperties()->getVectorizerParameters();
	assert(vParams);

	std::auto_ptr<VectorizerConfiguration> config(vParams->getCurrentConfiguration(0.0));
	TVectorImageP vi = vectorize(image, rect, *config, m_transformation);

	StrokesData *sd = new StrokesData();

	std::set<int> indexes;
	for (i = 0; i < vi->getStrokeCount(); i++)
		indexes.insert(i);

	sd->setImage(vi, indexes);
	return sd;
}
예제 #5
0
StrokesData *ToonzImageData::toStrokesData(ToonzScene *scene) const
{
	assert(scene);
	TRectD rect;
	if (!m_rects.empty())
		rect = m_rects[0];
	else if (!m_strokes.empty())
		rect = m_strokes[0].getBBox();
	unsigned int i;
	for (i = 0; i < m_rects.size(); i++)
		rect += m_rects[i];
	for (i = 0; i < m_strokes.size(); i++)
		rect += m_strokes[i].getBBox();
	TToonzImageP image(m_copiedRaster, m_copiedRaster->getBounds());
	image->setPalette(m_palette.getPointer());
	image->setDpi(m_dpiX, m_dpiY);

	const VectorizerParameters &vParams = *scene->getProperties()->getVectorizerParameters();

	CenterlineConfiguration cConf = vParams.getCenterlineConfiguration(0.0);
	NewOutlineConfiguration oConf = vParams.getOutlineConfiguration(0.0);

	const VectorizerConfiguration &config = vParams.m_isOutline ? static_cast<const VectorizerConfiguration &>(oConf) : static_cast<const VectorizerConfiguration &>(cConf);

	TVectorImageP vi = vectorize(image, rect, config, m_transformation);

	StrokesData *sd = new StrokesData();

	std::set<int> indexes;
	for (i = 0; i < vi->getStrokeCount(); i++)
		indexes.insert(i);

	sd->setImage(vi, indexes);
	return sd;
}
예제 #6
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();
}
예제 #7
0
void SceneViewerContextMenu::addEnterGroupCommands(const TPointD &pos) {
  bool ret         = true;
  TVectorImageP vi = (TVectorImageP)TTool::getImage(false);
  if (!vi) return;

  if (vi->isInsideGroup() > 0) {
    addAction(CommandManager::instance()->getAction(MI_ExitGroup));
  }

  StrokeSelection *ss =
      dynamic_cast<StrokeSelection *>(TSelection::getCurrent());
  if (!ss) return;

  for (int i = 0; i < vi->getStrokeCount(); i++)
    if (ss->isSelected(i) && vi->canEnterGroup(i)) {
      m_groupIndexToBeEntered = i;
      addAction(CommandManager::instance()->getAction(MI_EnterGroup));
      return;
    }

  assert(ret);
}
예제 #8
0
//!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));
}
예제 #10
0
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();
}
예제 #11
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();
	};
예제 #12
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);
	};
예제 #13
0
TPoint TFont::drawChar(TVectorImageP &image, wchar_t charcode, wchar_t nextCharCode) const

{

	GLYPHMETRICS gm;
	MAT2 mat2;
	mat2.eM11.fract = 0;
	mat2.eM12.fract = 0;
	mat2.eM21.fract = 0;
	mat2.eM22.fract = 0;
	mat2.eM11.value = 1;
	mat2.eM12.value = 0;
	mat2.eM21.value = 0;
	mat2.eM22.value = 1;

	vector<TThickPoint> points;

	UINT j = 0;

	DWORD charMemorySize = GetGlyphOutlineW(m_pimpl->m_hdc, charcode, GGO_NATIVE, &gm, 0, 0, &mat2);
	if (charMemorySize == GDI_ERROR) {
		assert(0);
		return TPoint();
	}

	LPVOID lpvBuffer = new char[charMemorySize];

	charMemorySize = GetGlyphOutlineW(m_pimpl->m_hdc, charcode, GGO_NATIVE, &gm, charMemorySize, lpvBuffer, &mat2);
	if (charMemorySize == GDI_ERROR) {
		assert(0);
		return TPoint();
	}

	TTPOLYGONHEADER *header = (TTPOLYGONHEADER *)lpvBuffer;

	while ((char *)header < (char *)lpvBuffer + charMemorySize) {
		points.clear();
		TThickPoint startPoint = toThickPoint(header->pfxStart);
		points.push_back(startPoint);

		if (header->dwType != TT_POLYGON_TYPE) {
			assert(0);
		}
		int memorySize = header->cb;

		TTPOLYCURVE *curve = (TTPOLYCURVE *)(header + 1);

		while ((char *)curve < (char *)header + memorySize) {
			switch (curve->wType) {
			case TT_PRIM_LINE:

				for (j = 0; j < curve->cpfx; j++) {
					TThickPoint p0 = points.back();
					TThickPoint p1 = toThickPoint(((*curve).apfx[j]));
					points.push_back((p0 + p1) * 0.5);
					points.push_back(p1);
				}

				break;

			case TT_PRIM_QSPLINE:

				for (j = 0; (int)j + 2 < curve->cpfx; j++) {
					TThickPoint p1 = toThickPoint(((*curve).apfx[j]));
					TThickPoint p2 = toThickPoint(((*curve).apfx[j + 1]));

					points.push_back(p1);
					points.push_back((p1 + p2) * 0.5);
				}
				points.push_back(toThickPoint(((*curve).apfx[j++])));
				points.push_back(toThickPoint(((*curve).apfx[j++])));

				break;
			case TT_PRIM_CSPLINE:
				assert(0);
				break;
			default:
				assert(0);
			}

			curve = (TTPOLYCURVE *)(&(curve->apfx)[j]);
		}

		TThickPoint p0 = points.back();
		if (!isAlmostZero(p0.x - startPoint.x) || !isAlmostZero(p0.y - startPoint.y)) {
			points.push_back((p0 + startPoint) * 0.5);
			points.push_back(startPoint);
		}

		TStroke *stroke = new TStroke();
		stroke->reshape(&(points[0]), points.size());
		stroke->setSelfLoop(true);
		image->addStroke(stroke);

		header = (TTPOLYGONHEADER *)curve;
	}

	delete[] lpvBuffer;

	image->group(0, image->getStrokeCount());

	return getDistance(charcode, nextCharCode);
}