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; }
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)); } }
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; }
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; }
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(); }
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); }
//!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(); }
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(); };
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); };
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); }