QTransform RectMapTransform( QRectF source, QRectF target ) { qreal x1 = source.left(); qreal y1 = source.top(); qreal x2 = source.right(); qreal y2 = source.bottom(); qreal x1P = target.left(); qreal y1P = target.top(); qreal x2P = target.right(); qreal y2P = target.bottom(); QTransform matrix; if ( ( x1 != x2 ) && ( y1 != y2 ) ) { matrix = QTransform( ( x2P - x1P ) / ( x2 - x1 ), // scale x 0, 0, ( y2P - y1P ) / ( y2 - y1 ), // scale y ( x1P * x2 - x2P * x1 ) / ( x2 - x1 ), // dx ( y1P * y2 - y2P * y1 ) / ( y2 - y1 ) ); // dy } else { matrix.reset(); } return matrix; }
void SprayBrush::paintRectangle(KisPainter& painter, qreal x, qreal y, int width, int height, qreal angle, int steps) { QVector <QPointF> points; QTransform transform; qreal halfWidth = width / 2.0; qreal halfHeight = height / 2.0; qreal tx, ty; transform.reset(); transform.rotateRadians( angle ); // top left transform.map( - halfWidth, - halfHeight, &tx, &ty); points.append(QPointF(tx + x,ty + y)); // top right transform.map( + halfWidth, - halfHeight, &tx, &ty); points.append(QPointF(tx + x,ty + y)); // bottom right transform.map( + halfWidth, + halfHeight, &tx, &ty); points.append(QPointF(tx + x,ty + y)); // botom left transform.map( - halfWidth, + halfHeight, &tx, &ty); points.append(QPointF(tx + x,ty + y)); painter.setOpacity( int( ( 255 * drand48() ) + 0.5 ) ); painter.setFillStyle(KisPainter::FillStyleForegroundColor); painter.paintPolygon( points ); }
void SprayBrush::paintRectangle(KisPainter* painter, qreal x, qreal y, int width, int height, qreal angle) { QPainterPath path; QTransform transform; qreal halfWidth = width * 0.5; qreal halfHeight = height * 0.5; qreal tx, ty; transform.reset(); transform.rotateRadians(angle); // top left transform.map(- halfWidth, - halfHeight, &tx, &ty); path.moveTo(QPointF(tx + x, ty + y)); // top right transform.map(+ halfWidth, - halfHeight, &tx, &ty); path.lineTo(QPointF(tx + x, ty + y)); // bottom right transform.map(+ halfWidth, + halfHeight, &tx, &ty); path.lineTo(QPointF(tx + x, ty + y)); // botom left transform.map(- halfWidth, + halfHeight, &tx, &ty); path.lineTo(QPointF(tx + x, ty + y)); path.closeSubpath(); painter->fillPainterPath(path); }
bool ReAnimEntityWidget::GetTransformAt( int _cursor, QTransform& _result, bool _allowExterpolate ) { bool isOk = false; QPointF translation; qreal rotation = 0.0f; QPointF scale; bool hasTranslation = GetTranslationAt( _cursor, translation, _allowExterpolate ); bool hasRotation = GetRotationAt( _cursor, rotation, _allowExterpolate ); bool hasScale = GetScaleAt( _cursor, scale, _allowExterpolate ); if( hasTranslation || hasRotation || hasScale ) { _result.reset(); if( hasScale ) _result.scale( scale.x(), scale.y() ); if( hasRotation ) _result.rotate( rotation ); if( hasTranslation ) _result.translate( translation.x(), translation.y() ); isOk = true; } return isOk; }
void QGraphicsCompositeImageItem::setFlipLR(bool flip) { const int w = boundingRect().width(); QTransform xform; xform.reset(); xform.setMatrix(-1, 0, 0, 0, 1, 0, w, 0, 1); setTransform(xform, true); }
void QGraphicsCompositeImageItem::setFlipUD(bool flip) { const int h = boundingRect().height(); QTransform xform; xform.reset(); xform.setMatrix(1, 0, 0, 0, -1, 0, 0, h, 1); setTransform(xform, true); }
QImage Rotater::HideRollOutCorners(const QImage image) { QImage destImage = QImage( image); QLine hline, vlineR, vlineL; int x0, y0, x1, y1; if (m_sign < 0) { x0 = 0, y0 = 0, x1 = m_width, y1 = 0; } else { x0 = 0, y0 = m_height, x1 = m_width, y1 = m_height; } hline = QLine(x0, y0, x1, y1); vlineR = QLine(m_width, 0, m_width, m_height); vlineL = QLine(0, 0, 0, m_height); QLine rvline = m_transform.map(vlineR); QPoint pa = get_line_cross_point(hline, rvline); QPoint pb = get_line_cross_point(vlineR, rvline); QLine rhline = m_transform.map(hline); QPoint pc = get_line_cross_point(vlineL, rhline); QPoint pd = get_line_cross_point(hline, rhline); // destImage = markOnImage( image, pa.x(), pa.y(), MarkType::CrossLines); // destImage = markOnImage( destImage, pb.x(), pb.y(), MarkType::CrossLines); // destImage = markOnImage( destImage, pc.x(), pc.y(), MarkType::CrossLines); // destImage = markOnImage( destImage, pd.x(), pd.y(), MarkType::CrossLines); QPolygonF triagle1, triagle2; triagle1 << pa << pb << QPointF(x1, y1); triagle2 << pc << pd << QPointF(x0, y0); QPainterPath myPath; myPath.addPolygon(triagle1); myPath.addPolygon(triagle2); QTransform transform; transform.translate(0, m_height * 0.5); transform.rotate(180, Qt::XAxis); transform.translate(0, -m_height * 0.5); QPainterPath myPath1 = transform.map(myPath); transform.reset(); transform.translate(m_width * 0.5, 0); transform.rotate(180, Qt::YAxis); transform.translate(-m_width * 0.5, 0); myPath = transform.map(myPath); myPath.addPath(myPath1); QPainter painter(&destImage); painter.setBrush(Qt::SolidPattern); painter.drawPath(myPath); return destImage; }
QPainterPath KisPaintOpSettings::ellipseOutline(qreal width, qreal height, qreal scale, qreal rotation) const { QPainterPath path; QRectF ellipse(0,0,width * scale,height * scale); ellipse.translate(-ellipse.center()); path.addEllipse(ellipse); QTransform m; m.reset(); m.rotate( rotation ); path = m.map(path); return path; }
QPainterPath KisPaintOpSettings::brushOutline(const QPointF& pos, OutlineMode mode, qreal scale, qreal rotation) const { QPainterPath path; if (mode == CursorIsOutline){ QRectF rc(-5,-5, 10, 10); path.moveTo(rc.topLeft()); path.lineTo(rc.bottomRight()); path.moveTo(rc.topRight()); path.lineTo(rc.bottomLeft()); QTransform m; m.reset(); m.scale(scale,scale); m.rotateRadians(rotation); path = m.map(path); path.translate(pos); } return path; }
QPainterPath KisGridPaintOpSettings::brushOutline(const QPointF& pos, KisPaintOpSettings::OutlineMode mode, qreal scale, qreal rotation) const { QPainterPath path; if (mode == CursorIsOutline) { qreal sizex = getInt(GRID_WIDTH) * getDouble(GRID_SCALE) * scale; qreal sizey = getInt(GRID_HEIGHT) * getDouble(GRID_SCALE) * scale; QRectF rc(0, 0, sizex, sizey); rc.translate(-rc.center()); QTransform m; m.reset(); m.rotate(rotation); path = m.map(path); path.addRect(rc); path.translate(pos); } return path; }
void CurveBrush::strokePens(QPointF pi1, QPointF pi2, KisPainter &/*painter*/) { if (m_pens.isEmpty()) { m_pens.append(Pen(pi1, 0.0, 1.0)); } qreal dx = pi2.x() - pi1.x(); qreal dy = pi2.y() - pi1.y(); for (int i = 0; i < m_pens.length(); i++) { Pen &pen = m_pens[i]; QPointF endPoint(dx, dy); QPainterPath path; path.moveTo(0, 0); path.lineTo(dx, dy); QTransform transform; transform.reset(); transform.translate(pen.pos.x(), pen.pos.y()); transform.scale(pen.scale, pen.scale); transform.rotate(pen.rotation); path = transform.map(path); //m_painter->drawPainterPath(path, QPen(Qt::white, 1.0)); endPoint = transform.map(endPoint); m_painter->drawThickLine(pen.pos, endPoint, 1.0, 1.0); pen.pos = endPoint; } qreal branchThreshold = 0.5; if ((m_branch * drand48() > branchThreshold) && (m_pens.length() < 1024)) { int index = floor(drand48() * (m_pens.length() - 1)); m_newPen.pos = m_pens.at(index).pos; m_newPen.rotation = drand48() * M_PI / 32; //atan(dy/dx) + (drand48() - 0.5) * M_PI/32; m_newPen.scale = drand48() * m_pens.at(index).scale; m_pens.append(m_newPen); dbgKrita << m_pens.length(); m_branch = 0; } else { m_branch++; } }
void converDemo::drawOnGDIplus(const HDC &hdc) { Q_ASSERT(hdc); Graphics graphics(hdc); Matrix matrix; QTransform transform; transform.translate(0, 20); converQTransform2GpMatrix(transform, &matrix); graphics.SetTransform(&matrix); drawOnNativeGdi(graphics); transform.reset(); transform.translate(210, 20); converQTransform2GpMatrix(transform, &matrix); graphics.SetTransform(&matrix); drawOnTranslateQT(graphics); }
void CWhiteBoardView::updateSize(const QSize &size) { if(size.width() <= 0 && size.height() <= 0) { return; } QSize adjustSize = size; if(m_data->m_needScale) { QRectF sceneRect = m_data->m_baseRect; if(sceneRect.width() < 0.001 && sceneRect.height() < 0.001) { return; } qreal sx = size.width() / sceneRect.width(); qreal sy = size.height() / sceneRect.height(); QTransform form = this->transform(); form.setMatrix(sx,form.m12(),form.m13(),form.m21(),sy,form.m23(),form.m31(),form.m32(),form.m33()); this->setTransform(form); adjustSize = sceneRect.size().toSize(); } else { QTransform form = this->transform(); form.reset(); this->setTransform(form); m_data->m_scene->setSceneRect(QRect(0,0,adjustSize.width(),adjustSize.height())); } if(m_data->m_backgroundColor.alpha() == 0) { m_data->m_backgroundColor.setAlpha(1); } QPixmap pixmap(adjustSize); pixmap.fill(m_data->m_backgroundColor); m_data->m_whiteBoardItem->setPixmap(pixmap); }
void SCgView::setScale(const QString& sc) { QTransform t = transform(); //Default transform t.reset(); //Getting percent value QString str = sc; str.remove("%"); double d = str.toDouble()/100.0; //Checking if value d in proper range if (d < SCgWindow::minScale) d = SCgWindow::minScale; else if (d > SCgWindow::maxScale) d = SCgWindow::maxScale; //Setting transformation setTransform(t.scale(d,d),false); emit(scaleChanged(transform().mapRect(QRectF(0, 0, 1, 1)).width())); }
void Box2DRobot::reinitSensor(const twoDModel::view::SensorItem &sensor) { // box2d doesn't rotate or shift elements, which are connected to main robot body via joints in case // when we manually use method SetTransform. // So we need to handle elements such as sensors by hand. // We use this method in case when user shifts or rotates sensor(s). auto box2dSensor = mSensors[&sensor]; box2dSensor->getBody()->SetLinearVelocity({0, 0}); box2dSensor->getBody()->SetAngularVelocity(0); if (const b2JointEdge *jointList = box2dSensor->getBody()->GetJointList()) { auto joint = jointList->joint; mJoints.removeAll(joint); mWorld.DestroyJoint(joint); } QPolygonF collidingPolygon = sensor.collidingPolygon(); QPointF localCenter = collidingPolygon.boundingRect().center(); QPointF deltaToCenter = mModel->rotationCenter() - mModel->position(); QPointF localPos = sensor.pos() - deltaToCenter; QTransform transform; QPointF dif = mModel->rotationCenter(); transform.translate(-dif.x(), -dif.y()); transform.rotate(mModel->rotation()); localPos = transform.map(localPos); transform.reset(); transform.translate(dif.x(), dif.y()); localPos = transform.map(localPos); const b2Vec2 pos = mEngine->positionToBox2D(localPos - localCenter + mModel->rotationCenter()); // IMPORTANT: we connect every sensor with box2d circle item. // So rotation of sensor doesn't matter, we set rotation corresponding to robot. // if in future it will be changed, you'll see some strange behavior, because of joints. See connectSensor method. mSensors[&sensor]->getBody()->SetTransform(pos, mBody->GetAngle()); connectSensor(*mSensors[&sensor]); }
/*! Reimplementation of QGraphicsItem::paint(). This function does the actual painting of the legend. \sa QGraphicsItem::paint(). */ void CartesianPlotLegendPrivate::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) { Q_UNUSED(option); Q_UNUSED(widget); if (!isVisible()) return; painter->save(); //draw the area painter->setOpacity(backgroundOpacity); painter->setPen(Qt::NoPen); if (backgroundType == PlotArea::Color){ switch (backgroundColorStyle){ case PlotArea::SingleColor:{ painter->setBrush(QBrush(backgroundFirstColor)); break; } case PlotArea::HorizontalLinearGradient:{ QLinearGradient linearGrad(rect.topLeft(), rect.topRight()); linearGrad.setColorAt(0, backgroundFirstColor); linearGrad.setColorAt(1, backgroundSecondColor); painter->setBrush(QBrush(linearGrad)); break; } case PlotArea::VerticalLinearGradient:{ QLinearGradient linearGrad(rect.topLeft(), rect.bottomLeft()); linearGrad.setColorAt(0, backgroundFirstColor); linearGrad.setColorAt(1, backgroundSecondColor); painter->setBrush(QBrush(linearGrad)); break; } case PlotArea::TopLeftDiagonalLinearGradient:{ QLinearGradient linearGrad(rect.topLeft(), rect.bottomRight()); linearGrad.setColorAt(0, backgroundFirstColor); linearGrad.setColorAt(1, backgroundSecondColor); painter->setBrush(QBrush(linearGrad)); break; } case PlotArea::BottomLeftDiagonalLinearGradient:{ QLinearGradient linearGrad(rect.bottomLeft(), rect.topRight()); linearGrad.setColorAt(0, backgroundFirstColor); linearGrad.setColorAt(1, backgroundSecondColor); painter->setBrush(QBrush(linearGrad)); break; } case PlotArea::RadialGradient:{ QRadialGradient radialGrad(rect.center(), rect.width()/2); radialGrad.setColorAt(0, backgroundFirstColor); radialGrad.setColorAt(1, backgroundSecondColor); painter->setBrush(QBrush(radialGrad)); break; } } }else if (backgroundType == PlotArea::Image){ if ( !backgroundFileName.trimmed().isEmpty() ) { QPixmap pix(backgroundFileName); switch (backgroundImageStyle){ case PlotArea::ScaledCropped: pix = pix.scaled(rect.size().toSize(),Qt::KeepAspectRatioByExpanding,Qt::SmoothTransformation); painter->drawPixmap(rect.topLeft(),pix); break; case PlotArea::Scaled: pix = pix.scaled(rect.size().toSize(),Qt::IgnoreAspectRatio,Qt::SmoothTransformation); painter->drawPixmap(rect.topLeft(),pix); break; case PlotArea::ScaledAspectRatio: pix = pix.scaled(rect.size().toSize(),Qt::KeepAspectRatio,Qt::SmoothTransformation); painter->drawPixmap(rect.topLeft(),pix); break; case PlotArea::Centered: painter->drawPixmap(QPointF(rect.center().x()-pix.size().width()/2,rect.center().y()-pix.size().height()/2),pix); break; case PlotArea::Tiled: painter->drawTiledPixmap(rect,pix); break; case PlotArea::CenterTiled: painter->drawTiledPixmap(rect,pix,QPoint(rect.size().width()/2,rect.size().height()/2)); } } } else if (backgroundType == PlotArea::Pattern){ painter->setBrush(QBrush(backgroundFirstColor,backgroundBrushStyle)); } if ( qFuzzyIsNull(borderCornerRadius) ) painter->drawRect(rect); else painter->drawRoundedRect(rect, borderCornerRadius, borderCornerRadius); //draw the border if (borderPen.style() != Qt::NoPen){ painter->setPen(borderPen); painter->setBrush(Qt::NoBrush); painter->setOpacity(borderOpacity); if ( qFuzzyIsNull(borderCornerRadius) ) painter->drawRect(rect); else painter->drawRoundedRect(rect, borderCornerRadius, borderCornerRadius); } //draw curve's line+symbol and the names int curveCount = curvesList.size(); QFontMetrics fm(labelFont); float h=fm.ascent(); XYCurve* curve; painter->setFont(labelFont); //translate to left upper conner of the bounding rect plus the layout offset and the height of the title painter->translate(-rect.width()/2+layoutLeftMargin, -rect.height()/2+layoutTopMargin); if (title->isVisible() && !title->text().text.isEmpty()) painter->translate(0, title->graphicsItem()->boundingRect().height()); painter->save(); int index; for (int c=0; c<columnCount; ++c) { for (int r=0; r<rowCount; ++r) { if (labelColumnMajor) index = c*rowCount + r; else index = r*columnCount + c; if ( index >= curveCount ) break; curve = curvesList.at(index); //curve's line (painted at the half of the ascent size) if (curve->lineType() != XYCurve::NoLine){ painter->setPen(curve->linePen()); painter->setOpacity(curve->lineOpacity()); painter->drawLine(0, h/2, lineSymbolWidth, h/2); } //error bars if ( (curve->xErrorType() != XYCurve::NoError) || (curve->yErrorType() != XYCurve::NoError) ) { painter->setOpacity(curve->errorBarsOpacity()); painter->setPen(curve->errorBarsPen()); //curve's error bars for x float errorBarsSize = Worksheet::convertToSceneUnits(10, Worksheet::Point); if (curve->symbolsStyle()!=Symbol::NoSymbols && errorBarsSize<curve->symbolsSize()*1.4) errorBarsSize = curve->symbolsSize()*1.4; switch(curve->errorBarsType()) { case XYCurve::ErrorBarsSimple: //horiz. line painter->drawLine(lineSymbolWidth/2-errorBarsSize/2, h/2, lineSymbolWidth/2+errorBarsSize/2, h/2); //vert. line painter->drawLine(lineSymbolWidth/2, h/2-errorBarsSize/2, lineSymbolWidth/2, h/2+errorBarsSize/2); break; case XYCurve::ErrorBarsWithEnds: { //horiz. line painter->drawLine(lineSymbolWidth/2-errorBarsSize/2, h/2, lineSymbolWidth/2+errorBarsSize/2, h/2); //vert. line painter->drawLine(lineSymbolWidth/2, h/2-errorBarsSize/2, lineSymbolWidth/2, h/2+errorBarsSize/2); //caps for the horiz. line painter->drawLine(lineSymbolWidth/2-errorBarsSize/2, h/2-errorBarsSize/4, lineSymbolWidth/2-errorBarsSize/2, h/2+errorBarsSize/4); painter->drawLine(lineSymbolWidth/2+errorBarsSize/2, h/2-errorBarsSize/4, lineSymbolWidth/2+errorBarsSize/2, h/2+errorBarsSize/4); //caps for the vert. line painter->drawLine(lineSymbolWidth/2-errorBarsSize/4, h/2-errorBarsSize/2, lineSymbolWidth/2+errorBarsSize/4, h/2-errorBarsSize/2); painter->drawLine(lineSymbolWidth/2-errorBarsSize/4, h/2+errorBarsSize/2, lineSymbolWidth/2+errorBarsSize/4, h/2+errorBarsSize/2); break; } } } //curve's symbol if (curve->symbolsStyle()!=Symbol::NoSymbols){ painter->setOpacity(curve->symbolsOpacity()); painter->setBrush(curve->symbolsBrush()); painter->setPen(curve->symbolsPen()); QPainterPath path = Symbol::pathFromStyle(curve->symbolsStyle()); QTransform trafo; trafo.scale(curve->symbolsSize(), curve->symbolsSize()); path = trafo.map(path); if (curve->symbolsRotationAngle() != 0) { trafo.reset(); trafo.rotate(curve->symbolsRotationAngle()); path = trafo.map(path); } painter->translate(QPointF(lineSymbolWidth/2, h/2)); painter->drawPath(path); painter->translate(-QPointF(lineSymbolWidth/2, h/2)); } //curve's name painter->setPen(QPen(labelColor)); painter->setOpacity(1.0); painter->drawText(QPoint(lineSymbolWidth+layoutHorizontalSpacing, h), curve->name()); painter->translate(0,layoutVerticalSpacing+h); } //translate to the beginning of the next column painter->restore(); int deltaX = lineSymbolWidth+layoutHorizontalSpacing+maxColumnTextWidths.at(c); //the width of the current columns deltaX += 2*layoutHorizontalSpacing; //spacing between two columns painter->translate(deltaX,0); painter->save(); } painter->restore(); painter->restore(); if (m_hovered && !isSelected() && !m_printing){ painter->setPen(q->hoveredPen); painter->setOpacity(q->hoveredOpacity); painter->drawPath(shape()); } if (isSelected() && !m_printing){ painter->setPen(q->selectedPen); painter->setOpacity(q->selectedOpacity); painter->drawPath(shape()); } }
void grabFramesLoop(bool &streaming, framebufferinfo &info, QQueue<QByteArray> &queue, QOrientationReading::Orientation &orientation) { QImage img(info.scrinfo.xres, info.scrinfo.yres, QImage::Format_RGBA8888); QBuffer imgBuffer; QElapsedTimer timer; timer.start(); int frames = 0; int old = 0; int now = 0; int line = info.fix_scrinfo.line_length / 4; QByteArray ba; QTransform transform; while(streaming) { for (unsigned int y = 0; y < info.scrinfo.yres; ++y) { QRgb *rowData = (QRgb*)img.scanLine(y); for (unsigned int x = 0; x < info.scrinfo.xres; ++x) { rowData[x] = *((unsigned int *)info.fbmmap + ((x + info.scrinfo.xoffset) + (y + info.scrinfo.yoffset) * line)); } } imgBuffer.setBuffer(&ba); imgBuffer.open(QIODevice::WriteOnly); if(orientation != QOrientationReading::TopUp) { switch (orientation) { case QOrientationReading::TopDown: img = img.transformed(transform.rotate(180)); break; case QOrientationReading::LeftUp: img = img.transformed(transform.rotate(90)); break; case QOrientationReading::RightUp: img = img.transformed(transform.rotate(-90)); break; default: break; } img.save(&imgBuffer, "JPG", info.compression); transform.reset(); // reset to original (correct width x height) img = QImage(info.scrinfo.xres, info.scrinfo.yres, QImage::Format_RGBA8888); } else { img.save(&imgBuffer, "JPG", info.compression); } queue.enqueue(ba); imgBuffer.close(); ++frames; now = timer.elapsed(); if(now > old) { info.frametime = now - old; } old = now; // get average fps over the last 50 frames if(frames == 50) { info.fps = round(50.0 / (timer.restart() / 1000.0)); frames = 0; } } return; }
QImage Rotater::shiftImage( const QImage image) { QImage outImage = QImage( image); QPainter painter( &outImage); painter.setRenderHint( QPainter::SmoothPixmapTransform); // using new method to calculate shift int move1 = m_sign < 0 ? 1 : 0, move2 = move1 ? 0 : 1; // Transformer: pan each half of original image outwards QRect rect_half(0, 0, m_width/2, m_height/2); QTransform transform; // quater-1: top-left transform.scale( move1 > 0 ? m_scale : 1, move2 > 0 ? m_scale : 1); transform.translate( -m_dx[1], -m_dy[1]); // (-,-) painter.setTransform ( transform); // as shift may deamage previous quater, configure the rect carefully // so pan only 3/4 of half image (1 + move2/2.0) rect_half.setRect( 0, 0, m_width/2 * (1 + move1), m_height/2 * (1 + move2/2.0)); painter.drawImage( rect_half, image, rect_half); // qDebug() << "##### 1:" << rect_half; // quater-2: top-right transform.reset(); transform.scale( move2 > 0 ? m_scale : 1, move1 > 0 ? m_scale : 1); transform.translate( (1-m_scale) * m_width * move2, 0); transform.translate(m_dx[2], -m_dy[2]); // (+,-) painter.setTransform ( transform); // as shift may deamage previous quater, configure the rect carefully // so pan only 3/4 of half image (move1 + move2/2.0) rect_half.setRect( m_width/2 * (move1 + move2/2.0), 0, m_width/2 * (1 + move2), m_height/2 * (1 + move1)); painter.drawImage( rect_half, image, rect_half); // qDebug() << "##### 2:" << rect_half; // quater-3: bottom-right transform.reset(); transform.scale( move1 > 0 ? m_scale : 1, move2 > 0 ? m_scale : 1); transform.translate( (1-m_scale) * m_width * move1, (1-m_scale) * m_height * move2); transform.translate( m_dx[3], m_dy[3]); // (+,+) painter.setTransform ( transform); // as shift may deamage previous quater, configure the rect carefully // so pan only 3/4 of half image (move1 + move2/2.0) rect_half.setRect( m_width/2 * move2, m_height/2 * (move1 + move2/2.0), m_width/2 * (1 + move1), m_height/2 * (1 + move2)); painter.drawImage( rect_half, image, rect_half); // qDebug() << "##### 3:" << rect_half; // quater-4: bottom-left transform.reset(); // the order of transform makes sense. if sequence was 2+(3.1+3,2), // then the 3-combined transform steps should be (3.1+3.2)+2 transform.scale( move2 > 0 ? m_scale : 1, move1 > 0 ? m_scale : 1); // 3.1 scale transform.translate( 0, (1-m_scale) * m_height * move1); // 3.2 compensate to scale transform.translate( -m_dx[4], m_dy[4]); // (-,+) // 2 original shift painter.setTransform ( transform); // as shift may deamage the 3rd quater, configure the rect carefully // so pan only 3/4 of a half (move2 + move2/2.0), (1 + move2/2.0) rect_half.setRect( 0, m_height/2 * (move2 + move1/2.0), m_width/2 * (1 + move2/2.0), m_height/2 * (1 + move1)); painter.drawImage( rect_half, image, rect_half); // qDebug() << "##### 4:" << rect_half; return outImage; }
QPainterPath ArtisticTextToolSelection::outline() { if (!hasSelection()) return QPainterPath(); CharIndex charPos = m_currentShape->indexOfChar(m_selectionStart); if (charPos.first < 0) return QPainterPath(); QPainterPath outline; QPolygonF polygon; QList<ArtisticTextRange> ranges = m_currentShape->text(); if (ranges.size() == 0) return outline; int globalCharIndex = m_selectionStart; int remainingChars = m_selectionCount; while (remainingChars) { const ArtisticTextRange ¤tRange = ranges[charPos.first]; int currentTextLength = currentRange.text().length(); while (charPos.second < currentTextLength && remainingChars > 0) { const QPointF pos = m_currentShape->charPositionAt(globalCharIndex); const qreal angle = m_currentShape->charAngleAt(globalCharIndex); QTransform charTransform; charTransform.translate( pos.x() - 1, pos.y() ); charTransform.rotate( 360. - angle ); QFontMetricsF metrics(currentRange.font()); polygon.prepend(charTransform.map(QPointF(0.0, -metrics.ascent()))); polygon.append(charTransform.map(QPointF(0.0, metrics.descent()))); // advance to next character charPos.second++; globalCharIndex++; remainingChars--; // next character has y-offset or we are at the end of this text range const bool hasYOffset = currentRange.hasYOffset(charPos.second); const bool atRangeEnd = charPos.second == currentTextLength; const bool atSelectionEnd = remainingChars == 0; if (hasYOffset || atRangeEnd || atSelectionEnd) { if (hasYOffset || atRangeEnd) { const QChar c = currentRange.text().at(charPos.second-1); const qreal w = metrics.width(c); polygon.prepend(charTransform.map(QPointF(w, -metrics.ascent()))); polygon.append(charTransform.map(QPointF(w, metrics.descent()))); } else { const QPointF pos = m_currentShape->charPositionAt(globalCharIndex); const qreal angle = m_currentShape->charAngleAt(globalCharIndex); charTransform.reset(); charTransform.translate( pos.x() - 1, pos.y() ); charTransform.rotate( 360. - angle ); polygon.prepend(charTransform.map(QPointF(0.0, -metrics.ascent()))); polygon.append(charTransform.map(QPointF(0.0, metrics.descent()))); } QPainterPath p; p.addPolygon(polygon); outline = outline.united(p); polygon.clear(); } } // go to first character of next text range charPos.first++; charPos.second = 0; } // transform to document coordinates return m_currentShape->absoluteTransformation(0).map(outline); }
void SprayBrush::paint(KisPaintDeviceSP dab, KisPaintDeviceSP source, const KisPaintInformation& info, qreal rotation, qreal scale, const KoColor &color, const KoColor &bgColor) { // initializing painter if (!m_painter) { m_painter = new KisPainter(dab); m_painter->setFillStyle(KisPainter::FillStyleForegroundColor); m_painter->setMaskImageSize(m_shapeProperties->width, m_shapeProperties->height); m_dabPixelSize = dab->colorSpace()->pixelSize(); if (m_colorProperties->useRandomHSV) { m_transfo = dab->colorSpace()->createColorTransformation("hsv_adjustment", QHash<QString, QVariant>()); } m_brushQImage = m_shapeProperties->image; if (!m_brushQImage.isNull()) { m_brushQImage = m_brushQImage.scaled(m_shapeProperties->width, m_shapeProperties->height); } m_imageDevice = new KisPaintDevice(dab->colorSpace()); } qreal x = info.pos().x(); qreal y = info.pos().y(); KisRandomAccessorSP accessor = dab->createRandomAccessorNG(qRound(x), qRound(y)); Q_ASSERT(color.colorSpace()->pixelSize() == dab->pixelSize()); m_inkColor = color; KisCrossDeviceColorPicker colorPicker(source, m_inkColor); // apply size sensor m_radius = m_properties->radius * scale; // jitter movement if (m_properties->jitterMovement) { x = x + ((2 * m_radius * drand48()) - m_radius) * m_properties->amount; y = y + ((2 * m_radius * drand48()) - m_radius) * m_properties->amount; } // this is wrong for every shape except pixel and anti-aliased pixel if (m_properties->useDensity) { m_particlesCount = (m_properties->coverage * (M_PI * m_radius * m_radius)); } else { m_particlesCount = m_properties->particleCount; } QHash<QString, QVariant> params; qreal nx, ny; int ix, iy; qreal angle; qreal length; qreal rotationZ = 0.0; qreal particleScale = 1.0; bool shouldColor = true; if (m_colorProperties->fillBackground) { m_painter->setPaintColor(bgColor); paintCircle(m_painter, x, y, m_radius); } QTransform m; m.reset(); m.rotateRadians(-rotation + deg2rad(m_properties->brushRotation)); m.scale(m_properties->scale, m_properties->scale); for (quint32 i = 0; i < m_particlesCount; i++) { // generate random angle angle = drand48() * M_PI * 2; // generate random length if (m_properties->gaussian) { length = qBound<qreal>(0.0, m_rand->nextGaussian(0.0, 0.50) , 1.0); } else { length = drand48(); } if (m_shapeDynamicsProperties->enabled) { // rotation rotationZ = rotationAngle(); if (m_shapeDynamicsProperties->followCursor) { rotationZ = linearInterpolation(rotationZ, angle, m_shapeDynamicsProperties->followCursorWeigth); } if (m_shapeDynamicsProperties->followDrawingAngle) { rotationZ = linearInterpolation(rotationZ, info.drawingAngle(), m_shapeDynamicsProperties->followDrawingAngleWeight); } // random size - scale if (m_shapeDynamicsProperties->randomSize) { particleScale = drand48(); } } // generate polar coordinate nx = (m_radius * cos(angle) * length); ny = (m_radius * sin(angle) * length); // compute the height of the ellipse ny *= m_properties->aspect; // transform m.map(nx, ny, &nx, &ny); // color transformation if (shouldColor) { if (m_colorProperties->sampleInputColor) { colorPicker.pickOldColor(nx + x, ny + y, m_inkColor.data()); } // mix the color with background color if (m_colorProperties->mixBgColor) { KoMixColorsOp * mixOp = dab->colorSpace()->mixColorsOp(); const quint8 *colors[2]; colors[0] = m_inkColor.data(); colors[1] = bgColor.data(); qint16 colorWeights[2]; int MAX_16BIT = 255; qreal blend = info.pressure(); colorWeights[0] = static_cast<quint16>(blend * MAX_16BIT); colorWeights[1] = static_cast<quint16>((1.0 - blend) * MAX_16BIT); mixOp->mixColors(colors, colorWeights, 2, m_inkColor.data()); } if (m_colorProperties->useRandomHSV && m_transfo) { params["h"] = (m_colorProperties->hue / 180.0) * drand48(); params["s"] = (m_colorProperties->saturation / 100.0) * drand48(); params["v"] = (m_colorProperties->value / 100.0) * drand48(); m_transfo->setParameters(params); m_transfo->transform(m_inkColor.data(), m_inkColor.data() , 1); } if (m_colorProperties->useRandomOpacity) { quint8 alpha = qRound(drand48() * OPACITY_OPAQUE_U8); m_inkColor.setOpacity(alpha); m_painter->setOpacity(alpha); } if (!m_colorProperties->colorPerParticle) { shouldColor = false; } m_painter->setPaintColor(m_inkColor); } qreal jitteredWidth = qMax(qreal(1.0), m_shapeProperties->width * particleScale); qreal jitteredHeight = qMax(qreal(1.0), m_shapeProperties->height * particleScale); if (m_shapeProperties->enabled){ switch (m_shapeProperties->shape){ // ellipse case 0: { if (m_shapeProperties->width == m_shapeProperties->height){ paintCircle(m_painter, nx + x, ny + y, qRound(jitteredWidth * 0.5)); } else { paintEllipse(m_painter, nx + x, ny + y, qRound(jitteredWidth * 0.5) , qRound(jitteredHeight * 0.5), rotationZ); } break; } // rectangle case 1: { paintRectangle(m_painter, nx + x, ny + y, qRound(jitteredWidth) , qRound(jitteredHeight), rotationZ); break; } // wu-particle case 2: { paintParticle(accessor, m_inkColor, nx + x, ny + y); break; } // pixel case 3: { ix = qRound(nx + x); iy = qRound(ny + y); accessor->moveTo(ix, iy); memcpy(accessor->rawData(), m_inkColor.data(), m_dabPixelSize); break; } case 4: { if (!m_brushQImage.isNull()) { QTransform m; m.rotate(rad2deg(rotationZ)); if (m_shapeDynamicsProperties->randomSize) { m.scale(particleScale, particleScale); } m_transformed = m_brushQImage.transformed(m, Qt::SmoothTransformation); m_imageDevice->convertFromQImage(m_transformed, 0); KisRandomAccessorSP ac = m_imageDevice->createRandomAccessorNG(0, 0); QRect rc = m_transformed.rect(); if (m_colorProperties->useRandomHSV && m_transfo) { for (int y = rc.y(); y < rc.y() + rc.height(); y++) { for (int x = rc.x(); x < rc.x() + rc.width(); x++) { ac->moveTo(x, y); m_transfo->transform(ac->rawData(), ac->rawData() , 1); } } } ix = qRound(nx + x - rc.width() * 0.5); iy = qRound(ny + y - rc.height() * 0.5); m_painter->bitBlt(QPoint(ix, iy), m_imageDevice, rc); m_imageDevice->clear(); break; } } } // Auto-brush } else { QPointF hotSpot = m_brush->hotSpot(particleScale, particleScale, -rotationZ, info); QPointF pos(nx + x, ny + y); QPointF pt = pos - hotSpot; qint32 ix; qreal xFraction; qint32 iy; qreal yFraction; KisPaintOp::splitCoordinate(pt.x(), &ix, &xFraction); KisPaintOp::splitCoordinate(pt.y(), &iy, &yFraction); //KisFixedPaintDeviceSP dab; if (m_brush->brushType() == IMAGE || m_brush->brushType() == PIPE_IMAGE) { m_fixedDab = m_brush->paintDevice(m_fixedDab->colorSpace(), particleScale, -rotationZ, info, xFraction, yFraction); if (m_colorProperties->useRandomHSV && m_transfo) { quint8 * dabPointer = m_fixedDab->data(); int pixelCount = m_fixedDab->bounds().width() * m_fixedDab->bounds().height(); m_transfo->transform(dabPointer, dabPointer, pixelCount); } } else { m_brush->mask(m_fixedDab, m_inkColor, particleScale, particleScale, -rotationZ, info, xFraction, yFraction); } m_painter->bltFixed(QPoint(ix, iy), m_fixedDab, m_fixedDab->bounds()); } } // recover from jittering of color, // m_inkColor.opacity is recovered with every paint }
void GpsSnrWidget::drawSat(int index) { if (index >= MAX_SATTELITES) { // A bit of error checking never hurts. return; } const int prn = satellites[index][0]; const int snr = satellites[index][3]; if (prn && snr) { boxes[index]->show(); // When using integer values, width and height are the // box width and height, but the left and bottom borders are drawn on the box, // and the top and right borders are drawn just next to the box. // So the box seems one pixel wider and higher with a border. // I'm sure there's a good explanation for that :) // Casting to int rounds down, which is what I want. // Minus 2 to allow a pixel of white left and right. int availableWidth = (int)((scene->width() - 2) / MAX_SATTELITES); // 2 pixels, one on each side. qreal width = availableWidth - 2; // SNR = 1-99 (0 is special).. qreal height = int((scene->height() / 99) * snr + 0.5); // 1 for showing a pixel of white to the left. qreal x = availableWidth * index + 1; // Rember, 0 is at the top. qreal y = scene->height() - height; // Compensate for the extra pixel for the border. boxes[index]->setRect(0, 0, width - 1, height - 1); boxes[index]->setPos(x, y); QRectF boxRect = boxes[index]->boundingRect(); // Change color for SBAS & QZSS 120-158, 193-197 range // GLONASS range 65-96 or 255, BeiDou 33-64 or 159-163 if ((prn > 119 && prn < 159) || (prn > 192 && prn < 198)) { boxes[index]->setBrush(QColor("#fd700b")); } else if ((prn > 64 && prn < 97) || 255 == prn) { boxes[index]->setBrush(QColor("Cyan")); } else if ((prn > 32 && prn < 65) || (prn > 158 && prn < 164)) { boxes[index]->setBrush(QColor("Red")); } else { boxes[index]->setBrush(QColor("Green")); } QString prnString = QString().number(prn); if (prnString.length() == 1) { prnString = "0" + prnString; } satTexts[index]->setText(prnString); QRectF textRect = satTexts[index]->boundingRect(); QTransform matrix; qreal scale = 0.85 * (boxRect.width() / textRect.width()); matrix.translate(boxRect.width() / 2, boxRect.height()); matrix.scale(scale, scale); matrix.translate(-textRect.width() / 2, -textRect.height()); satTexts[index]->setTransform(matrix, false); QString snrString = QString().number(snr); if (snrString.length() == 1) { // Will probably never happen! snrString = "0" + snrString; } satSNRs[index]->setText(snrString); textRect = satSNRs[index]->boundingRect(); matrix.reset(); scale = 0.85 * (boxRect.width() / textRect.width()); matrix.translate(boxRect.width() / 2, 0); matrix.scale(scale, scale); matrix.translate(-textRect.width() / 2, -textRect.height()); satSNRs[index]->setTransform(matrix, false); } else { boxes[index]->hide(); } }
void KeyboardLayoutWidget::drawKeyLabelHelper(QPainter* painter, int keysym, int angle, int glp, int x, int y, int width, int height, int padding, bool is_pressed) { if (keysym == 0) return; if (keysym == XK_VoidSymbol) return; if (padding >= height / 2) padding = 0; if (padding >= width / 2) padding = 0; Qt::Alignment align; QRectF rect(padding, padding, (width - 2 * padding), (height - 2 * padding)); switch (glp) { case KEYBOARD_DRAWING_POS_TOPLEFT: align = Qt::AlignTop | Qt::AlignLeft; break; case KEYBOARD_DRAWING_POS_BOTTOMLEFT: align = Qt::AlignBottom | Qt::AlignLeft; break; case KEYBOARD_DRAWING_POS_TOPRIGHT: align = Qt::AlignTop | Qt::AlignRight; break; case KEYBOARD_DRAWING_POS_BOTTOMRIGHT: align = Qt::AlignBottom | Qt::AlignRight; break; default: return; } if (keysym == XK_ISO_Left_Tab) keysym = XK_Tab; keysym = (int) FcitxHotkeyPadToMain((FcitxKeySym) keysym); uint32_t unicode = FcitxKeySymToUnicode((FcitxKeySym) keysym); if (deadMap.contains(keysym)) { unicode = deadMap[keysym]; } QString text; if (unicode && QChar(unicode).category() != QChar::Other_Control && !QChar(unicode).isSpace()) text.append(QChar(unicode)); else { if (keysym == XK_Prior) { text = "PgUp"; } else if (keysym == XK_Next) { text = "PgDn"; } else { text = QString(XKeysymToString(keysym)); } } if (text != "_") { if (text.endsWith("_L") || text.endsWith("_R")) text = text.replace('_', ' '); else text = text.replace('_', '\n'); } painter->save(); QTransform trans; trans.translate(x + padding / 2, y + padding / 2); trans.rotate(angle / 10); painter->setTransform(trans); //painter->fillRect(QRectF(0, 0, width - padding, height - padding), QBrush(Qt::blue)); // painter->setClipRect(QRect(x + padding / 2, y + padding / 2, width - padding, height - padding)); trans.reset(); trans.translate(x, y); trans.rotate(angle / 10); QFont font = painter->font(); font.setPixelSize(TEXT_SIZE * (height / 2 - padding)); QFontMetricsF fm(font); QStringList lines = text.split('\n'); foreach(const QString& line, lines) { qreal w = fm.width(line); if (w > (width - padding * 2) * TEXT_SIZE) { double sz = font.pixelSize() / w * (width - padding * 2) * TEXT_SIZE; if (sz < 1) sz = 1; font.setPixelSize(font.pixelSize() / w * (width - padding * 2) * TEXT_SIZE); } }
void Slur::computeBezier(SlurSegment* ss, QPointF p6o) { qreal _spatium = spatium(); qreal shoulderW; // height as fraction of slur-length qreal shoulderH; // // p1 and p2 are the end points of the slur // QPointF pp1 = ss->ups[GRIP_START].p + ss->ups[GRIP_START].off * _spatium; QPointF pp2 = ss->ups[GRIP_END].p + ss->ups[GRIP_END].off * _spatium; QPointF p2 = pp2 - pp1; if (p2.x() == 0.0) { qDebug("zero slur"); Measure* m1 = startChord()->segment()->measure(); Measure* m2 = endChord()->segment()->measure(); Page* page = m1->system()->page(); qDebug(" at tick %d in measure %d-%d page %d", m1->tick(), m1->no(), m2->no(), page->no()); return; } qreal sinb = atan(p2.y() / p2.x()); QTransform t; t.rotateRadians(-sinb); p2 = t.map(p2); p6o = t.map(p6o); double smallH = 0.5; qreal d = p2.x() / _spatium; if (d <= 2.0) { shoulderH = d * 0.5 * smallH * _spatium; shoulderW = .6; } else { qreal dd = log10(1.0 + (d - 2.0) * .5) * 2.0; if (dd > 3.0) dd = 3.0; shoulderH = (dd + smallH) * _spatium; if (d > 18.0) shoulderW = 0.8; else if (d > 10) shoulderW = 0.7; else shoulderW = 0.6; } if (!up()) shoulderH = -shoulderH; // shoulderH -= p6o.y(); qreal c = p2.x(); qreal c1 = (c - c * shoulderW) * .5 + p6o.x(); qreal c2 = c1 + c * shoulderW + p6o.x(); QPointF p5 = QPointF(c * .5, 0.0); QPointF p3(c1, -shoulderH); QPointF p4(c2, -shoulderH); qreal w = (score()->styleS(ST_SlurMidWidth).val() - score()->styleS(ST_SlurEndWidth).val()) * _spatium; if (((c2 - c1) / _spatium) <= _spatium) w *= .5; QPointF th(0.0, w); // thickness of slur QPointF p3o = p6o + t.map(ss->ups[GRIP_BEZIER1].off * _spatium); QPointF p4o = p6o + t.map(ss->ups[GRIP_BEZIER2].off * _spatium); //?? ss->ups[GRIP_BEZIER1].off = t.inverted().map(p3o) / _spatium; //?? ss->ups[GRIP_BEZIER2].off = t.inverted().map(p4o) / _spatium; //-----------------------------------calculate p6 QPointF pp3 = p3 + p3o; QPointF pp4 = p4 + p4o; QPointF ppp4 = pp4 - pp3; qreal r2 = atan(ppp4.y() / ppp4.x()); t.reset(); t.rotateRadians(-r2); QPointF p6 = QPointF(t.map(ppp4).x() * .5, 0.0); t.rotateRadians(2 * r2); p6 = t.map(p6) + pp3; // - p6o; //----------------------------------- ss->path = QPainterPath(); ss->path.moveTo(QPointF()); ss->path.cubicTo(p3 + p3o - th, p4 + p4o - th, p2); if (lineType() == 0) ss->path.cubicTo(p4 +p4o + th, p3 + p3o + th, QPointF()); th = QPointF(0.0, 3.0 * w); ss->shapePath = QPainterPath(); ss->shapePath.moveTo(QPointF()); ss->shapePath.cubicTo(p3 + p3o - th, p4 + p4o - th, p2); ss->shapePath.cubicTo(p4 +p4o + th, p3 + p3o + th, QPointF()); // translate back t.reset(); t.translate(pp1.x(), pp1.y()); t.rotateRadians(sinb); ss->path = t.map(ss->path); ss->shapePath = t.map(ss->shapePath); ss->ups[GRIP_BEZIER1].p = t.map(p3); ss->ups[GRIP_BEZIER2].p = t.map(p4); ss->ups[GRIP_END].p = t.map(p2) - ss->ups[GRIP_END].off * _spatium; ss->ups[GRIP_DRAG].p = t.map(p5); ss->ups[GRIP_SHOULDER].p = t.map(p6); }
void KisToolMultihand::initTransformations() { QVector<QTransform> transformations; QTransform m; if(m_transformMode == SYMMETRY) { qreal angle = 0; qreal angleStep = (2 * M_PI) / m_handsCount; for(int i = 0; i < m_handsCount; i++) { m.translate(m_axesPoint.x(), m_axesPoint.y()); m.rotateRadians(angle); m.translate(-m_axesPoint.x(), -m_axesPoint.y()); transformations << m; m.reset(); angle += angleStep; } } else if(m_transformMode == MIRROR) { transformations << m; if (m_mirrorHorizontally) { m.translate(m_axesPoint.x(),m_axesPoint.y()); m.rotateRadians(m_angle); m.scale(-1,1); m.rotateRadians(-m_angle); m.translate(-m_axesPoint.x(), -m_axesPoint.y()); transformations << m; m.reset(); } if (m_mirrorVertically) { m.translate(m_axesPoint.x(),m_axesPoint.y()); m.rotateRadians(m_angle); m.scale(1,-1); m.rotateRadians(-m_angle); m.translate(-m_axesPoint.x(), -m_axesPoint.y()); transformations << m; m.reset(); } if (m_mirrorVertically && m_mirrorHorizontally){ m.translate(m_axesPoint.x(),m_axesPoint.y()); m.rotateRadians(m_angle); m.scale(-1,-1); m.rotateRadians(-m_angle); m.translate(-m_axesPoint.x(), -m_axesPoint.y()); transformations << m; m.reset(); } } else if(m_transformMode == SNOWFLAKE) { qreal angle = 0; qreal angleStep = (2 * M_PI) / m_handsCount/4; for(int i = 0; i < m_handsCount*4; i++) { if ((i%2)==1) { m.translate(m_axesPoint.x(), m_axesPoint.y()); m.rotateRadians(m_angle-angleStep); m.rotateRadians(angle); m.scale(-1,1); m.rotateRadians(-m_angle+angleStep); m.translate(-m_axesPoint.x(), -m_axesPoint.y()); transformations << m; m.reset(); angle += angleStep*2; } else { m.translate(m_axesPoint.x(), m_axesPoint.y()); m.rotateRadians(m_angle-angleStep); m.rotateRadians(angle); m.rotateRadians(-m_angle+angleStep); m.translate(-m_axesPoint.x(), -m_axesPoint.y()); transformations << m; m.reset(); angle += angleStep*2; } } } else /* if(m_transformationNode == TRANSLATE) */ { /** * TODO: currently, the seed is the same for all the * strokes */ for (int i = 0; i < m_handsCount; i++){ qreal angle = drand48() * M_PI * 2; qreal length = drand48(); // convert the Polar coordinates to Cartesian coordinates qreal nx = (m_translateRadius * cos(angle) * length); qreal ny = (m_translateRadius * sin(angle) * length); m.translate(m_axesPoint.x(),m_axesPoint.y()); m.rotateRadians(m_angle); m.translate(nx,ny); m.rotateRadians(-m_angle); m.translate(-m_axesPoint.x(), -m_axesPoint.y()); transformations << m; m.reset(); } } m_helper->setupTransformations(transformations); }
void FGWCondition::paintEvent(QPaintEvent *) { QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing); QFontMetrics fm = painter.fontMetrics(); if (fm.ascent() + fm.descent() != m_fontHeight) { m_fontHeight = fm.ascent() + fm.descent(); updateTransforms(); } // Y-Axis label QTransform transform; transform.rotate(270); transform.translate(-(height() + fm.width(m_yAxisLabel)) / 2, fm.ascent()); painter.setTransform(transform); painter.drawText(QPointF(0, 0), m_yAxisLabel); // X-Axis label transform.reset(); painter.setTransform(transform); painter.drawText(QPointF((width() - fm.width(m_xAxisLabel)) / 2, height() - fm.descent()), m_xAxisLabel); // The actual graph if (m_forceCondition) { QPointF startPos(-1.0, 0.0); QPointF startViewPos = m_model2View.map(startPos); QPointF endPos(1.0, 0.0); QPointF endViewPos = m_model2View.map(endPos); double negativeSaturation = m_forceCondition->negativeSaturation(); if (m_forceCondition->negativeCoefficient() < 0.0) { negativeSaturation = -negativeSaturation; } double positiveSaturation = m_forceCondition->positiveSaturation(); if (m_forceCondition->positiveCoefficient() < 0.0) { positiveSaturation = -positiveSaturation; } double negativeDeadBandValue = CLIP11(m_forceCondition->offset() - m_forceCondition->deadBand()); double positiveDeadBandValue = CLIP11(m_forceCondition->offset() + m_forceCondition->deadBand()); double negCoeff = m_forceCondition->negativeCoefficient(); double negCoeffValue = 1000.0; if (0.001 < fabs(negCoeff)) { negCoeffValue = (1.0 / fabs(negCoeff)) - 1.0; } negCoeffValue *= m_forceCondition->negativeSaturation(); double negativeSaturationValue = negativeDeadBandValue - negCoeffValue; if (negativeSaturationValue < -1.0) { double negCoeffVisible = negativeDeadBandValue + 1.0; double ratio = negCoeffVisible / negCoeffValue; negativeSaturation *= ratio; negativeSaturationValue = -1.0; } double posCoeff = m_forceCondition->positiveCoefficient(); double posCoeffValue = 1000.0; if (0.001 < fabs(posCoeff)) { posCoeffValue = (1.0 / fabs(posCoeff)) - 1.0; } posCoeffValue *= m_forceCondition->positiveSaturation(); double positiveSaturationValue = positiveDeadBandValue + posCoeffValue; if (1.0 < positiveSaturationValue) { double posCoeffVisible = 1.0 - positiveDeadBandValue; double ratio = posCoeffVisible / posCoeffValue; positiveSaturation *= ratio; positiveSaturationValue = 1.0; } QPointF offsetPos(m_forceCondition->offset(), 0.0); QPointF offsetViewPos = m_model2View.map(offsetPos); QPointF negativeSaturationPos(-1.0, negativeSaturation); QPointF negativeSaturationViewPos = m_model2View.map(negativeSaturationPos); QPointF negativeCoefficientPos(negativeSaturationValue, negativeSaturation); QPointF negativeCoefficientViewPos = m_model2View.map(negativeCoefficientPos); QPointF negativeDeadBandPos(negativeDeadBandValue, 0.0); QPointF negativeDeadBandViewPos = m_model2View.map(negativeDeadBandPos); QPointF positiveDeadBandPos(positiveDeadBandValue, 0.0); QPointF positiveDeadBandViewPos = m_model2View.map(positiveDeadBandPos); QPointF positiveCoefficientPos(positiveSaturationValue, positiveSaturation); QPointF positiveCoefficientViewPos = m_model2View.map(positiveCoefficientPos); QPointF positiveSaturationPos(1.0, positiveSaturation); QPointF positiveSaturationViewPos = m_model2View.map(positiveSaturationPos); painter.setPen(Qt::black); painter.setBrush(Qt::green); QPolygon envelope; envelope << startViewPos.toPoint() << negativeSaturationViewPos.toPoint() << negativeCoefficientViewPos.toPoint() << negativeDeadBandViewPos.toPoint() << positiveDeadBandViewPos.toPoint() << positiveCoefficientViewPos.toPoint() << positiveSaturationViewPos.toPoint() << endViewPos.toPoint(); painter.drawPolygon(envelope); painter.setBrush(QBrush(Qt::red)); painter.drawEllipse(negativeCoefficientViewPos, m_handleRadius, m_handleRadius); painter.drawEllipse(negativeDeadBandViewPos, m_handleRadius, m_handleRadius); painter.drawEllipse(positiveDeadBandViewPos, m_handleRadius, m_handleRadius); painter.drawEllipse(positiveCoefficientViewPos, m_handleRadius, m_handleRadius); if (!m_dragHandler->isDragging()) { double negSatHalfWidth = (negativeCoefficientViewPos.x() - startViewPos.x()) / 2.0; m_dragHandler->setHitAreaView(NegativeSaturation, QPointF(startViewPos.x() + negSatHalfWidth, negativeSaturationViewPos.y()), negSatHalfWidth, m_handleRadius); m_dragHandler->setHitAreaView(NegativeCoefficient, negativeCoefficientViewPos); m_dragHandler->setHitAreaView(NegativeDeadBand, negativeDeadBandViewPos); double offsetHalfWidth = (positiveDeadBandViewPos.x() - negativeDeadBandViewPos.x()) / 2.0; m_dragHandler->setHitAreaView(Offset, offsetViewPos, offsetHalfWidth, m_handleRadius); m_dragHandler->setHitAreaView(PositiveDeadBand, positiveDeadBandViewPos); m_dragHandler->setHitAreaView(PositiveCoefficient, positiveCoefficientViewPos); double posSatHalfWidth = (endViewPos.x() - positiveCoefficientViewPos.x()) / 2.0; m_dragHandler->setHitAreaView(PositiveSaturation, QPointF(endViewPos.x() - posSatHalfWidth, positiveSaturationViewPos.y()), posSatHalfWidth, m_handleRadius); } } }
void Tie::computeBezier(SlurSegment* ss, QPointF p6o) { qreal _spatium = spatium(); qreal shoulderW; // height as fraction of slur-length qreal shoulderH; // // pp1 start of slur // pp2 end of slur // pp3 bezier 1 // pp4 bezier 2 // pp5 drag // pp6 shoulder // QPointF pp1 = ss->ups[GRIP_START].p + ss->ups[GRIP_START].off * _spatium; QPointF pp2 = ss->ups[GRIP_END].p + ss->ups[GRIP_END].off * _spatium; QPointF p2 = pp2 - pp1; // normalize to zero if (p2.x() == 0.0) { qDebug("zero tie"); return; } qreal sinb = atan(p2.y() / p2.x()); QTransform t; t.rotateRadians(-sinb); p2 = t.map(p2); p6o = t.map(p6o); double smallH = 0.38; qreal d = p2.x() / _spatium; shoulderH = d * 0.4 * smallH; if (shoulderH > 1.3) // maximum tie shoulder height shoulderH = 1.3; shoulderH *= _spatium; shoulderW = .6; if (!up()) shoulderH = -shoulderH; qreal c = p2.x(); qreal c1 = (c - c * shoulderW) * .5 + p6o.x(); qreal c2 = c1 + c * shoulderW + p6o.x(); QPointF p5 = QPointF(c * .5, 0.0); QPointF p3(c1, -shoulderH); QPointF p4(c2, -shoulderH); qreal w = (score()->styleS(ST_SlurMidWidth).val() - score()->styleS(ST_SlurEndWidth).val()) * _spatium; QPointF th(0.0, w); // thickness of slur QPointF p3o = p6o + t.map(ss->ups[GRIP_BEZIER1].off * _spatium); QPointF p4o = p6o + t.map(ss->ups[GRIP_BEZIER2].off * _spatium); // ss->ups[GRIP_BEZIER1].off = t.inverted().map(p3o) / _spatium; // ss->ups[GRIP_BEZIER2].off = t.inverted().map(p4o) / _spatium; //-----------------------------------calculate p6 QPointF pp3 = p3 + p3o; QPointF pp4 = p4 + p4o; QPointF ppp4 = pp4 - pp3; qreal r2 = atan(ppp4.y() / ppp4.x()); t.reset(); t.rotateRadians(-r2); QPointF p6 = QPointF(t.map(ppp4).x() * .5, 0.0); t.rotateRadians(2 * r2); p6 = t.map(p6) + pp3; // - p6o; //----------------------------------- ss->path = QPainterPath(); ss->path.moveTo(QPointF()); ss->path.cubicTo(p3 + p3o - th, p4 + p4o - th, p2); if (lineType() == 0) ss->path.cubicTo(p4 +p4o + th, p3 + p3o + th, QPointF()); th = QPointF(0.0, 3.0 * w); ss->shapePath = QPainterPath(); ss->shapePath.moveTo(QPointF()); ss->shapePath.cubicTo(p3 + p3o - th, p4 + p4o - th, p2); ss->shapePath.cubicTo(p4 +p4o + th, p3 + p3o + th, QPointF()); // translate back t.reset(); t.translate(pp1.x(), pp1.y()); t.rotateRadians(sinb); ss->path = t.map(ss->path); ss->shapePath = t.map(ss->shapePath); ss->ups[GRIP_BEZIER1].p = t.map(p3); ss->ups[GRIP_BEZIER2].p = t.map(p4); ss->ups[GRIP_END].p = t.map(p2) - ss->ups[GRIP_END].off * _spatium; ss->ups[GRIP_DRAG].p = t.map(p5); ss->ups[GRIP_SHOULDER].p = t.map(p6); }
void Tie::computeBezier(SlurSegment* ss, QPointF p6o) { qreal _spatium = spatium(); qreal shoulderW; // height as fraction of slur-length qreal shoulderH; // // pp1 start of slur // pp2 end of slur // pp3 bezier 1 // pp4 bezier 2 // pp5 drag // pp6 shoulder // QPointF pp1 = ss->ups(Grip::START).p + ss->ups(Grip::START).off * _spatium; QPointF pp2 = ss->ups(Grip::END).p + ss->ups(Grip::END).off * _spatium; QPointF p2 = pp2 - pp1; // normalize to zero if (p2.x() == 0.0) { qDebug("zero tie"); return; } qreal sinb = atan(p2.y() / p2.x()); QTransform t; t.rotateRadians(-sinb); p2 = t.map(p2); p6o = t.map(p6o); double smallH = 0.38; qreal d = p2.x() / _spatium; shoulderH = d * 0.4 * smallH; shoulderH = qBound(0.4, shoulderH, 1.3); shoulderH *= _spatium; shoulderW = .6; shoulderH -= p6o.y(); if (!up()) shoulderH = -shoulderH; qreal c = p2.x(); qreal c1 = (c - c * shoulderW) * .5 + p6o.x(); qreal c2 = c1 + c * shoulderW + p6o.x(); QPointF p5 = QPointF(c * .5, 0.0); QPointF p3(c1, -shoulderH); QPointF p4(c2, -shoulderH); qreal w = (score()->styleS(StyleIdx::SlurMidWidth).val() - score()->styleS(StyleIdx::SlurEndWidth).val()) * _spatium; QPointF th(0.0, w); // thickness of slur QPointF p3o = p6o + t.map(ss->ups(Grip::BEZIER1).off * _spatium); QPointF p4o = p6o + t.map(ss->ups(Grip::BEZIER2).off * _spatium); if(!p6o.isNull()) { QPointF p6i = t.inverted().map(p6o) / _spatium; ss->ups(Grip::BEZIER1).off += p6i ; ss->ups(Grip::BEZIER2).off += p6i; } //-----------------------------------calculate p6 QPointF pp3 = p3 + p3o; QPointF pp4 = p4 + p4o; QPointF ppp4 = pp4 - pp3; qreal r2 = atan(ppp4.y() / ppp4.x()); t.reset(); t.rotateRadians(-r2); QPointF p6 = QPointF(t.map(ppp4).x() * .5, 0.0); t.rotateRadians(2 * r2); p6 = t.map(p6) + pp3 - p6o; //----------------------------------- ss->path = QPainterPath(); ss->path.moveTo(QPointF()); ss->path.cubicTo(p3 + p3o - th, p4 + p4o - th, p2); if (lineType() == 0) ss->path.cubicTo(p4 +p4o + th, p3 + p3o + th, QPointF()); th = QPointF(0.0, 3.0 * w); ss->shapePath = QPainterPath(); ss->shapePath.moveTo(QPointF()); ss->shapePath.cubicTo(p3 + p3o - th, p4 + p4o - th, p2); ss->shapePath.cubicTo(p4 +p4o + th, p3 + p3o + th, QPointF()); // translate back t.reset(); t.translate(pp1.x(), pp1.y()); t.rotateRadians(sinb); ss->path = t.map(ss->path); ss->shapePath = t.map(ss->shapePath); ss->ups(Grip::BEZIER1).p = t.map(p3); ss->ups(Grip::BEZIER2).p = t.map(p4); ss->ups(Grip::END).p = t.map(p2) - ss->ups(Grip::END).off * _spatium; ss->ups(Grip::DRAG).p = t.map(p5); ss->ups(Grip::SHOULDER).p = t.map(p6); QPointF staffOffset; if (ss->system() && ss->track() >= 0) staffOffset = QPointF(0.0, -ss->system()->staff(ss->staffIdx())->y()); ss->path.translate(staffOffset); ss->shapePath.translate(staffOffset); }