void Intertwine::doPointshapePoint(int x, int y, ToolLoop* loop) { Symmetry* symmetry = loop->getSymmetry(); if (symmetry) { Point origin(loop->getCelOrigin()); // Convert the point to the sprite position so we can apply the // symmetry transformation. Stroke main_stroke; main_stroke.addPoint(Point(x, y) + origin); Strokes strokes; symmetry->generateStrokes(main_stroke, strokes, loop); for (const auto& stroke : strokes) { // We call transformPoint() moving back each point to the cel // origin. loop->getPointShape()->transformPoint( loop, stroke[0].x - origin.x, stroke[0].y - origin.y); } } else { loop->getPointShape()->transformPoint(loop, x, y); } }
void Intertwine::doPointshapePoint(int x, int y, ToolLoop* loop) { Symmetry* symmetry = loop->getSymmetry(); if (symmetry) { Stroke main_stroke; main_stroke.addPoint(gfx::Point(x, y)); Strokes strokes; symmetry->generateStrokes(main_stroke, strokes); for (const auto& stroke : strokes) loop->getPointShape()->transformPoint( loop, stroke[0].x, stroke[0].y); } else { loop->getPointShape()->transformPoint(loop, x, y); } }
void ToolLoopManager::doLoopStep(bool last_step) { // Original set of points to interwine (original user stroke, // relative to sprite origin). Stroke main_stroke; if (!last_step) m_toolLoop->getController()->getStrokeToInterwine(m_stroke, main_stroke); else main_stroke = m_stroke; // Calculate the area to be updated in all document observers. Symmetry* symmetry = m_toolLoop->getSymmetry(); Strokes strokes; if (symmetry) symmetry->generateStrokes(main_stroke, strokes, m_toolLoop); else strokes.push_back(main_stroke); calculateDirtyArea(strokes); // Validate source image area. if (m_toolLoop->getInk()->needsSpecialSourceArea()) { gfx::Region srcArea; m_toolLoop->getInk()->createSpecialSourceArea(m_dirtyArea, srcArea); m_toolLoop->validateSrcImage(srcArea); } else { m_toolLoop->validateSrcImage(m_dirtyArea); } m_toolLoop->getInk()->prepareForStrokes(m_toolLoop, strokes); // Invalidate destionation image areas. if (m_toolLoop->getTracePolicy() == TracePolicy::Last) { // Copy source to destination (reset the previous trace). Useful // for tools like Line and Ellipse (we kept the last trace only). m_toolLoop->invalidateDstImage(); } else if (m_toolLoop->getTracePolicy() == TracePolicy::AccumulateUpdateLast) { // Revalidate only this last dirty area (e.g. pixel-perfect // freehand algorithm needs this trace policy to redraw only the // last dirty area, which can vary in one pixel from the previous // tool loop cycle). m_toolLoop->invalidateDstImage(m_dirtyArea); } m_toolLoop->validateDstImage(m_dirtyArea); // Join or fill user points if (!m_toolLoop->getFilled() || (!last_step && !m_toolLoop->getPreviewFilled())) m_toolLoop->getIntertwine()->joinStroke(m_toolLoop, main_stroke); else m_toolLoop->getIntertwine()->fillStroke(m_toolLoop, main_stroke); if (m_toolLoop->getTracePolicy() == TracePolicy::Overlap) { // Copy destination to source (yes, destination to source). In // this way each new trace overlaps the previous one. m_toolLoop->copyValidDstToSrcImage(m_dirtyArea); } if (!m_dirtyArea.isEmpty()) m_toolLoop->updateDirtyArea(); }