void AnalysisPlotView::drawBackground(QPainter* painter, const QRectF& rect) { FrequencyPlotView::drawBackground(painter, rect); painter->setRenderHint(QPainter::Antialiasing, true); AnalysisPlotScene* s = qobject_cast<AnalysisPlotScene*>(scene()); std::vector<FilterNode>& nodes = s->getNodes(); GainIterator gainIterator(nodes); QPainterPath path; bool first = true; double lastDb = -1000; for (int x = rect.left() - 1; x <= rect.right() + 1; x++) { double hz = s->xToHz(x); double db = gainIterator.gainAt(hz); double y = s->dbToY(db); if (y == -1) { if (db < 0) y = sceneRect().bottom() + 1; else y = sceneRect().top() - 1; } if (db == lastDb) y = floor(y) + 0.5; lastDb = db; if (first) { path.moveTo(x, y); first = false; } else { path.lineTo(x, y); } } path.lineTo(rect.right() + 1, rect.bottom() + 1); path.lineTo(rect.left() - 1, rect.bottom() + 1); double thresholdY = s->dbToY(0); if (rect.top() < thresholdY) { QPainterPath rectPath; rectPath.addRect(rect.left(), rect.top(), rect.width(), min(thresholdY - rect.top(), rect.height())); QPainterPath clippingPath = path.intersected(rectPath); painter->setPen(Qt::NoPen); painter->setBrush(Qt::red); painter->drawPath(clippingPath); painter->setBrush(Qt::NoBrush); } painter->setPen(Qt::black); painter->drawPath(path); }
void KarbonBooleanCommand::redo() { if (! d->resultingPath) { // transform input pathes to global coordinates QPainterPath pa = d->pathA->absoluteTransformation(0).map(d->pathA->outline()); QPainterPath pb = d->pathB->absoluteTransformation(0).map(d->pathB->outline()); QPainterPath pr; switch (d->operation) { case Intersection: pr = pa.intersected(pb); break; case Subtraction: pr = pa.subtracted(pb); break; case Exclusion: pr = pa.subtracted(pb); pr.addPath(pb.subtracted(pa)); break; case Union: pr = pa.united(pb); break; } QTransform transformationA = d->pathA->absoluteTransformation(0); // transform resulting path to local coordinate system of input path A pr = transformationA.inverted().map(pr); // create a path shape from the resulting path in local coordinates d->resultingPath = KoPathShape::createShapeFromPainterPath(pr); d->resultingPath->setStroke(d->pathA->stroke()); d->resultingPath->setBackground(d->pathA->background()); d->resultingPath->setShapeId(d->pathA->shapeId()); // the created shape has a transformation applied so we have to // apply the original transformation instead of replacing with it d->resultingPath->applyAbsoluteTransformation(transformationA); d->resultingPath->setName(d->pathA->name()); d->resultingPath->setZIndex(d->pathA->zIndex()); d->resultingPath->setFillRule(d->pathA->fillRule()); KoShapeGroup * group = dynamic_cast<KoShapeGroup*>(d->pathA->parent()); if (group) { QList<KoShape*> children; d->resultParentCmd = new KoShapeGroupCommand(group, children << d->resultingPath, this); } } if (d->shapeBasedDocument) { if (d->resultParent) d->resultParent->addShape(d->resultingPath); d->shapeBasedDocument->addShape(d->resultingPath); } KUndo2Command::redo(); d->isExecuted = true; }
void QOutlineMapper::clipElements(const QPointF *elements, const QPainterPath::ElementType *types, int element_count) { // We could save a bit of time by actually implementing them fully // instead of going through convenience functionallity, but since // this part of code hardly every used, it shouldn't matter. m_in_clip_elements = true; QPainterPath path; if (!(m_outline.flags & QT_FT_OUTLINE_EVEN_ODD_FILL)) path.setFillRule(Qt::WindingFill); if (types) { for (int i=0; i<element_count; ++i) { switch (types[i]) { case QPainterPath::MoveToElement: path.moveTo(elements[i]); break; case QPainterPath::LineToElement: path.lineTo(elements[i]); break; case QPainterPath::CurveToElement: path.cubicTo(elements[i], elements[i+1], elements[i+2]); i += 2; break; default: break; } } } else { path.moveTo(elements[0]); for (int i=1; i<element_count; ++i) path.lineTo(elements[i]); } QPainterPath clipPath; clipPath.addRect(m_clip_rect); QPainterPath clippedPath = path.intersected(clipPath); uint old_txop = m_txop; m_txop = QTransform::TxNone; if (clippedPath.isEmpty()) m_valid = false; else convertPath(clippedPath); m_txop = old_txop; m_in_clip_elements = false; }
void KarbonBooleanCommand::redo() { if (! d->resultingPath) { QPainterPath pa = d->pathA->absoluteTransformation(0).map(d->pathA->outline()); QPainterPath pb = d->pathB->absoluteTransformation(0).map(d->pathB->outline()); QPainterPath pr; switch (d->operation) { case Intersection: pr = pa.intersected(pb); break; case Subtraction: pr = pa.subtracted(pb); break; case Exclusion: pr = pa.subtracted(pb); pr.addPath(pb.subtracted(pa)); break; case Union: pr = pa.united(pb); break; } QTransform transformation = d->pathA->transformation(); pr = transformation.inverted().map(pr); d->resultingPath = KoPathShape::createShapeFromPainterPath(pr); d->resultingPath->setBorder(d->pathA->border()); d->resultingPath->setBackground(d->pathA->background()); d->resultingPath->setShapeId(d->pathA->shapeId()); d->resultingPath->setTransformation(transformation); d->resultingPath->setName(d->pathA->name()); d->resultingPath->setZIndex(d->pathA->zIndex()); d->resultingPath->setFillRule(d->pathA->fillRule()); KoShapeGroup * group = dynamic_cast<KoShapeGroup*>(d->pathA->parent()); if (group) { QList<KoShape*> children; d->resultParentCmd = new KoShapeGroupCommand(group, children << d->resultingPath, this); } } if (d->controller) { if (d->resultParent) d->resultParent->addShape(d->resultingPath); d->controller->addShape(d->resultingPath); } QUndoCommand::redo(); d->isExecuted = true; }
void tst_QPainterPath::operators_data() { QTest::addColumn<QPainterPath>("test"); QTest::addColumn<QPainterPath>("expected"); QPainterPath a; QPainterPath b; a.addRect(0, 0, 100, 100); b.addRect(50, 50, 100, 100); QTest::newRow("a & b") << (a & b) << a.intersected(b); QTest::newRow("a | b") << (a | b) << a.united(b); QTest::newRow("a + b") << (a + b) << a.united(b); QTest::newRow("a - b") << (a - b) << a.subtracted(b); QPainterPath c = a; QTest::newRow("a &= b") << (a &= b) << a.intersected(b); c = a; QTest::newRow("a |= b") << (a |= b) << a.united(b); c = a; QTest::newRow("a += b") << (a += b) << a.united(b); c = a; QTest::newRow("a -= b") << (a -= b) << a.subtracted(b); }
void Transition::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget */*widget*/) { const QRectF exposed = painter->worldTransform().mapRect(option->exposedRect); const QRectF br = rect(); QPen framePen; framePen.setWidthF(1.2); const QRectF mapped = painter->worldTransform().mapRect(br); QPointF p1(br.x(), br.y() + br.height() / 2 - 7); painter->setWorldTransform(QTransform()); QPainterPath p; p.addRect(exposed); QPainterPath q; q.addRoundedRect(mapped, 3, 3); painter->setClipPath(p.intersected(q)); painter->fillRect(exposed, brush()); const QString text = m_name + (m_forceTransitionTrack ? QStringLiteral("|>") : QString()); // Draw clip name if (isSelected() || (parentItem() && parentItem()->isSelected())) { framePen.setColor(scene()->palette().highlight().color()); framePen.setColor(Qt::red); } else { framePen.setColor(brush().color().darker()); } const QRectF txtBounding = painter->boundingRect(mapped, Qt::AlignHCenter | Qt::AlignVCenter, ' ' + text + ' '); painter->setBrush(framePen.color()); painter->setPen(framePen.color()); painter->drawRoundedRect(txtBounding, 3, 3); painter->setBrush(QBrush(Qt::NoBrush)); painter->setPen(Qt::white); painter->drawText(txtBounding, Qt::AlignCenter, text); // Draw frame painter->setPen(framePen); painter->setClipping(false); painter->setRenderHint(QPainter::Antialiasing, true); painter->drawRoundedRect(mapped.adjusted(0, 0, -0.5, -0.5), 3, 3); }
//virtual QVariant AbstractGroupItem::itemChange(GraphicsItemChange change, const QVariant &value) { if (change == ItemPositionChange && scene()) { // calculate new position. const int trackHeight = KdenliveSettings::trackheight(); QPointF start = sceneBoundingRect().topLeft(); QPointF newPos = value.toPointF(); //kDebug()<<"REAL:"<<start.x()<<", PROPOSED:"<<(int)(start.x() - pos().x() + newPos.x()); int xpos = projectScene()->getSnapPointForPos((int)(start.x() + newPos.x() - pos().x()), KdenliveSettings::snaptopoints()); xpos = qMax(xpos, 0); //kDebug()<<"GRP XPOS:"<<xpos<<", START:"<<start.x()<<",NEW:"<<newPos.x()<<"; SCENE:"<<scenePos().x()<<",POS:"<<pos().x(); newPos.setX((int)(pos().x() + xpos - (int) start.x())); //int startTrack = (start.y() + trackHeight / 2) / trackHeight; int realTrack = (start.y() + newPos.y() - pos().y()) / trackHeight; int proposedTrack = newPos.y() / trackHeight; int correctedTrack = qMin(realTrack, projectScene()->tracksCount() - (int)(boundingRect().height() + 5) / trackHeight); correctedTrack = qMax(correctedTrack, 0); proposedTrack += (correctedTrack - realTrack); // Check if top item is a clip or a transition int offset = 0; int topTrack = -1; QList<QGraphicsItem *> children = childItems(); for (int i = 0; i < children.count(); i++) { int currentTrack = (int)(children.at(i)->scenePos().y() / trackHeight); if (children.at(i)->type() == AVWIDGET) { if (topTrack == -1 || currentTrack <= topTrack) { offset = 0; topTrack = currentTrack; } } else if (children.at(i)->type() == TRANSITIONWIDGET) { if (topTrack == -1 || currentTrack < topTrack) { offset = (int)(trackHeight / 3 * 2 - 1); topTrack = currentTrack; } } } newPos.setY((int)((proposedTrack) * trackHeight) + offset); //if (newPos == start) return start; /*if (newPos.x() < 0) { // If group goes below 0, adjust position to 0 return QPointF(pos().x() - start.x(), pos().y()); }*/ QPainterPath shape = groupShape(newPos - pos()); QList<QGraphicsItem*> collindingItems = scene()->items(shape, Qt::IntersectsItemShape); for (int i = 0; i < children.count(); i++) { collindingItems.removeAll(children.at(i)); } if (collindingItems.isEmpty()) return newPos; else { bool forwardMove = xpos > start.x(); int offset = 0; for (int i = 0; i < collindingItems.count(); i++) { QGraphicsItem *collision = collindingItems.at(i); if (collision->type() == AVWIDGET) { // Collision //kDebug()<<"// COLLISION WIT:"<<collision->sceneBoundingRect(); if (newPos.y() != pos().y()) { // Track change results in collision, restore original position return pos(); } AbstractClipItem *item = static_cast <AbstractClipItem *>(collision); if (forwardMove) { // Moving forward, determine best pos QPainterPath clipPath; clipPath.addRect(item->sceneBoundingRect()); QPainterPath res = shape.intersected(clipPath); offset = qMax(offset, (int)(res.boundingRect().width() + 0.5)); } else { // Moving backward, determine best pos QPainterPath clipPath; clipPath.addRect(item->sceneBoundingRect()); QPainterPath res = shape.intersected(clipPath); offset = qMax(offset, (int)(res.boundingRect().width() + 0.5)); } } } if (offset > 0) { if (forwardMove) { newPos.setX(newPos.x() - offset); } else { newPos.setX(newPos.x() + offset); } // If there is still a collision after our position adjust, restore original pos collindingItems = scene()->items(groupShape(newPos - pos()), Qt::IntersectsItemShape); for (int i = 0; i < children.count(); i++) { collindingItems.removeAll(children.at(i)); } for (int i = 0; i < collindingItems.count(); i++) if (collindingItems.at(i)->type() == AVWIDGET) return pos(); } return newPos; } } return QGraphicsItemGroup::itemChange(change, value); }
//virtual QVariant AbstractGroupItem::itemChange(GraphicsItemChange change, const QVariant &value) { if (change == QGraphicsItem::ItemSelectedChange) { if (value.toBool()) setZValue(3); else setZValue(1); } CustomTrackScene *scene = NULL; if (change == ItemPositionChange && parentItem() == 0) { scene = projectScene(); } if (scene) { // calculate new position. if (scene->isZooming) { // For some reason, mouse wheel on selected itm sometimes triggered // a position change event corrupting timeline, so discard it return pos(); } // calculate new position. const int trackHeight = KdenliveSettings::trackheight(); QPointF start = sceneBoundingRect().topLeft(); QPointF newPos = value.toPointF(); int xpos = projectScene()->getSnapPointForPos((int)(start.x() + newPos.x() - pos().x()), KdenliveSettings::snaptopoints()); xpos = qMax(xpos, 0); ////qDebug()<<"GRP XPOS:"<<xpos<<", START:"<<start.x()<<",NEW:"<<newPos.x()<<"; SCENE:"<<scenePos().x()<<",POS:"<<pos().x(); newPos.setX((int)(pos().x() + xpos - (int) start.x())); QStringList lockedTracks = property("locked_tracks").toStringList(); int proposedTrack = trackForPos(property("y_absolute").toInt() + newPos.y()); // Check if top item is a clip or a transition int offset = 0; int topTrack = -1; QList<int> groupTracks; QList<QGraphicsItem *> children = childItems(); for (int i = 0; i < children.count(); ++i) { int currentTrack = 0; if (children.at(i)->type() == AVWidget || children.at(i)->type() == TransitionWidget) { currentTrack = static_cast <AbstractClipItem*> (children.at(i))->track(); if (!groupTracks.contains(currentTrack)) groupTracks.append(currentTrack); } else if (children.at(i)->type() == GroupWidget) { currentTrack = static_cast <AbstractGroupItem*> (children.at(i))->track(); } else continue; if (children.at(i)->type() == AVWidget) { if (topTrack == -1 || currentTrack >= topTrack) { offset = 0; topTrack = currentTrack; } } else if (children.at(i)->type() == TransitionWidget) { if (topTrack == -1 || currentTrack > topTrack) { offset = (int)(trackHeight / 3 * 2 - 1); topTrack = currentTrack; } } else if (children.at(i)->type() == GroupWidget) { QList<QGraphicsItem *> subchildren = children.at(i)->childItems(); bool clipGroup = false; for (int j = 0; j < subchildren.count(); ++j) { if (subchildren.at(j)->type() == AVWidget || subchildren.at(j)->type() == TransitionWidget) { int subTrack = static_cast <AbstractClipItem*> (subchildren.at(j))->track(); if (!groupTracks.contains(subTrack)) groupTracks.append(subTrack); clipGroup = true; } } if (clipGroup) { if (topTrack == -1 || currentTrack >= topTrack) { offset = 0; topTrack = currentTrack; } } else { if (topTrack == -1 || currentTrack > topTrack) { offset = (int)(trackHeight / 3 * 2 - 1); topTrack = currentTrack; } } } } // Check no clip in the group goes outside of existing tracks int maximumTrack = projectScene()->tracksCount(); int groupHeight = 0; for (int i = 0; i < groupTracks.count(); ++i) { int offset = groupTracks.at(i) - topTrack; if (offset > groupHeight) groupHeight = offset; } maximumTrack -= groupHeight; proposedTrack = qMin(proposedTrack, maximumTrack); proposedTrack = qMax(proposedTrack, groupTracks.count()); int groupOffset = proposedTrack - topTrack; if (!lockedTracks.isEmpty()) { for (int i = 0; i < groupTracks.count(); ++i) { if (lockedTracks.contains(QString::number(groupTracks.at(i) + groupOffset))) { return pos(); } } } newPos.setY(posForTrack(proposedTrack) + offset); //if (newPos == start) return start; /*if (newPos.x() < 0) { // If group goes below 0, adjust position to 0 return QPointF(pos().x() - start.x(), pos().y()); }*/ QList<QGraphicsItem*> collidingItems; QPainterPath shape; if (projectScene()->editMode() == NormalEdit) { shape = clipGroupShape(newPos - pos()); collidingItems = scene->items(shape, Qt::IntersectsItemShape); collidingItems.removeAll(this); for (int i = 0; i < children.count(); ++i) { if (children.at(i)->type() == GroupWidget) { QList<QGraphicsItem *> subchildren = children.at(i)->childItems(); for (int j = 0; j < subchildren.count(); ++j) { collidingItems.removeAll(subchildren.at(j)); } } collidingItems.removeAll(children.at(i)); } } if (!collidingItems.isEmpty()) { bool forwardMove = xpos > start.x(); int offset = 0; for (int i = 0; i < collidingItems.count(); ++i) { QGraphicsItem *collision = collidingItems.at(i); if (collision->type() == AVWidget) { // Collision if (newPos.y() != pos().y()) { // Track change results in collision, restore original position return pos(); } AbstractClipItem *item = static_cast <AbstractClipItem *>(collision); // Determine best pos QPainterPath clipPath; clipPath.addRect(item->sceneBoundingRect()); QPainterPath res = shape.intersected(clipPath); offset = qMax(offset, (int)(res.boundingRect().width() + 0.5)); } } if (offset > 0) { if (forwardMove) { newPos.setX(newPos.x() - offset); } else { newPos.setX(newPos.x() + offset); } // If there is still a collision after our position adjust, restore original pos collidingItems = scene->items(clipGroupShape(newPos - pos()), Qt::IntersectsItemShape); collidingItems.removeAll(this); for (int i = 0; i < children.count(); ++i) { if (children.at(i)->type() == GroupWidget) { QList<QGraphicsItem *> subchildren = children.at(i)->childItems(); for (int j = 0; j < subchildren.count(); ++j) { collidingItems.removeAll(subchildren.at(j)); } } collidingItems.removeAll(children.at(i)); } for (int i = 0; i < collidingItems.count(); ++i) if (collidingItems.at(i)->type() == AVWidget) return pos(); } } if (projectScene()->editMode() == NormalEdit) { shape = transitionGroupShape(newPos - pos()); collidingItems = scene->items(shape, Qt::IntersectsItemShape); collidingItems.removeAll(this); for (int i = 0; i < children.count(); ++i) { if (children.at(i)->type() == GroupWidget) { QList<QGraphicsItem *> subchildren = children.at(i)->childItems(); for (int j = 0; j < subchildren.count(); ++j) { collidingItems.removeAll(subchildren.at(j)); } } collidingItems.removeAll(children.at(i)); } } if (collidingItems.isEmpty()) return newPos; else { bool forwardMove = xpos > start.x(); int offset = 0; for (int i = 0; i < collidingItems.count(); ++i) { QGraphicsItem *collision = collidingItems.at(i); if (collision->type() == TransitionWidget) { // Collision if (newPos.y() != pos().y()) { // Track change results in collision, restore original position return pos(); } AbstractClipItem *item = static_cast <AbstractClipItem *>(collision); // Determine best pos QPainterPath clipPath; clipPath.addRect(item->sceneBoundingRect()); QPainterPath res = shape.intersected(clipPath); offset = qMax(offset, (int)(res.boundingRect().width() + 0.5)); } } if (offset > 0) { if (forwardMove) { newPos.setX(newPos.x() - offset); } else { newPos.setX(newPos.x() + offset); } // If there is still a collision after our position adjust, restore original pos collidingItems = scene->items(transitionGroupShape(newPos - pos()), Qt::IntersectsItemShape); for (int i = 0; i < children.count(); ++i) { collidingItems.removeAll(children.at(i)); } for (int i = 0; i < collidingItems.count(); ++i) if (collidingItems.at(i)->type() == TransitionWidget) return pos(); } } return newPos; } return QGraphicsItemGroup::itemChange(change, value); }
void MovableWidget::paintEvent(QPaintEvent*) { int shadow = 3; QPoint centerCard = rect().center(); QPainterPath arrow; QPointF arrowTarget = rect().bottomRight(); qreal arrowSize = 100; QRectF internalCard(QPointF(0, 0), QSizeF(rect().size() - QSizeF(arrowSize, arrowSize))); qreal arrowGuideX1 = arrowTarget.x(); qreal arrowGuideY1 = arrowTarget.y(); qreal arrowGuideX2 = centerCard.x(); qreal arrowGuideY2 = centerCard.y(); qreal a = 90; if (arrowGuideX1 != arrowGuideX2) { qreal k = (arrowGuideY1 - arrowGuideY2) / (arrowGuideX1 - arrowGuideX2); a = atan(k) * 180 / M_PI; } arrow.moveTo(arrowTarget); arrow.lineTo( arrowGuideX2 + 100 * cos((a - 90) * (M_PI / 180)), arrowGuideY2 + 100 * sin((a - 90) * (M_PI / 180))); arrow.lineTo( arrowGuideX2 + 100 * cos((a + 90) * (M_PI / 180)), arrowGuideY2 + 100 * sin((a + 90) * (M_PI / 180))); arrow.lineTo(arrowTarget); QPainterPath path; path.setFillRule(Qt::WindingFill); path.addRoundedRect(internalCard.x(), internalCard.y(), internalCard.width() - shadow, internalCard.height() - shadow, 5, 5, Qt::AbsoluteSize); QPainterPath cardPath = path.united(arrow); QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing, true); painter.setRenderHint(QPainter::TextAntialiasing, true); painter.setRenderHint(QPainter::SmoothPixmapTransform, false); painter.setRenderHint(QPainter::NonCosmeticDefaultPen, false); painter.setCompositionMode(QPainter::CompositionMode_SourceOver); // shadow cardPath.translate(shadow, shadow); painter.fillPath(cardPath, QColor(255, 0, 0)); cardPath.translate(-shadow, -shadow); painter.setPen(QColor(0, 0, 0)); painter.fillPath(cardPath, QColor(255, 255, 255)); QPainterPath topPath; topPath.addRect(internalCard.x(), internalCard.y(), internalCard.width() - shadow, 19); topPath = path.intersected(topPath); painter.fillPath(topPath, QColor(127, 127, 127)); QLinearGradient gradient(internalCard.x(), internalCard.y() + 19, internalCard.x(), internalCard.y() + 19 + 23); gradient.setColorAt(0, GRADIENT_0); gradient.setColorAt(1, GRADIENT_1); QPainterPath top2Path; top2Path.addRect(internalCard.x(), internalCard.y() + 19, internalCard.width() - shadow, 23); top2Path = path.intersected(top2Path); painter.fillPath(top2Path, QBrush(gradient)); painter.drawPath(cardPath); }