Exemple #1
0
void BlurItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
  QGraphicsRectItem::mouseMoveEvent(event);

  const QPointF pos = event->scenePos();
  QRectF r;

  r.setTopLeft(m_point);
  r.setBottomRight(event->scenePos());

  if (r.width() < 0) {
    r.setLeft(pos.x());
    r.setRight(m_point.x());
  }

  if (r.height() < 0) {
    r.setTop(pos.y());
    r.setBottom(m_point.y());
  }

  r = r.intersected(m_item->scene()->sceneRect());

  setRect(r);
  setSelected(true);
  m_item->setOffset(r.topLeft());

  reload(m_pixmap);
}
Exemple #2
0
void PDF::render(const QRectF& texCoords)
{
    if (!pdfPage_)
        return;

    // get on-screen and full rectangle corresponding to the window
    const QRectF screenRect = GLWindow::getProjectedPixelRect(true);
    const QRectF fullRect = GLWindow::getProjectedPixelRect(false);

    // if we're not visible or we don't have a valid SVG, we're done...
    if(screenRect.isEmpty())
    {
        // TODO clear existing FBO for this OpenGL window
        return;
    }

    // generate texture corresponding to the visible part of these texture coordinates
    generateTexture(screenRect, fullRect, texCoords);

    if(!texture_.isValid())
        return;

    // figure out what visible region is for screenRect, a subregion of [0, 0, 1, 1]
    const float xp = (screenRect.x() - fullRect.x()) / fullRect.width();
    const float yp = (screenRect.y() - fullRect.y()) / fullRect.height();
    const float wp = screenRect.width() / fullRect.width();
    const float hp = screenRect.height() / fullRect.height();

    // Render the entire texture on a (scaled) unit textured quad
    glPushMatrix();

    glTranslatef(xp, yp, 0);
    glScalef(wp, hp, 1.f);

    drawUnitTexturedQuad();

    glPopMatrix();
}
Exemple #3
0
void renderCode128(OROPage * page, const QRectF & r, const QString & _str, ORBarcodeData * bc)
{
  QVector<int> str;
  int i = 0;

  // create the list.. if the list is empty then just set a start code and move on
  if(_str.isEmpty())
    str.push_back(104);
  else
  {
    int rank_a = 0;
    int rank_b = 0;
    int rank_c = 0;

    QChar c;
    for(i = 0; i < _str.length(); i++)
    {
      c = _str.at(i);
      rank_a += (code128Index(c, SETA) != -1 ? 1 : 0);
      rank_b += (code128Index(c, SETB) != -1 ? 1 : 0);
      rank_c += (c >= '0' && c <= '9' ? 1 : 0);
    }
    if(rank_c == _str.length() && ((rank_c % 2) == 0 || rank_c > 4))
    {
      // every value in the is a digit so we are going to go with mode C
      // and we have an even number or we have more than 4 values
      i = 0;
      if((rank_c % 2) == 1)
      {
        str.push_back(104); // START B
        c = _str.at(0);
        str.push_back(code128Index(c, SETB));
        str.push_back(99); // MODE C
        i = 1;
      }
      else
        str.push_back(105); // START C

      for(i = i; i < _str.length(); i+=2)
      {
        char a, b;
        c = _str.at(i);
        a = c.toLatin1();
        a -= 48;
        c = _str.at(i+1);
        b = c.toLatin1();
        b -= 48;
        str.push_back(int((a * 10) + b));
      }
    }
    else
    {
      // start in the mode that had the higher number of hits and then
      // just shift into the opposite mode as needed
      int set = ( rank_a > rank_b ? SETA : SETB );
      str.push_back(( rank_a > rank_b ? 103 : 104 ));
      int v = -1;
      for(i = 0; i < _str.length(); i++)
      {
        c = _str.at(i);
        v = code128Index(c, set);
        if(v == -1)
        {
          v = code128Index(c, (set == SETA ? SETB : SETA));
          if(v != -1)
          {
            str.push_back(98); // SHIFT
            str.push_back(v);
          }
        }
        else
          str.push_back(v);
      }
    }
  }

  // calculate and append the checksum value to the list
  int checksum = str.at(0);
  for(i = 1; i < str.size(); i++)
    checksum += (str.at(i) * i);
  checksum = checksum % 103;
  str.push_back(checksum);

  // lets determine some core attributes about this barcode
  qreal bar_width = bc->narrowBarWidth; 

  // this is are mandatory minimum quiet zone
  qreal quiet_zone = bar_width * 10;
  if(quiet_zone < 0.1)
    quiet_zone = 0.1;

  // what kind of area do we have to work with
  qreal draw_width = r.width();
  qreal draw_height = r.height();

  // how long is the value we need to encode?
  int val_length = str.size() - 2; // we include start and checksum in are list so
                                   // subtract them out for our calculations

  // L = (11C + 35)X 
  // L length of barcode (excluding quite zone) in units same as X and I
  // C the number of characters in the value excluding the start/stop and checksum characters
  // X the width of a bar (pixels in our case)
  qreal L;

  qreal C = val_length;
  qreal X = bar_width;

  L = (((11.0 * C) + 35.0) * X);

  // now we have the actual width the barcode will be so can determine the actual
  // size of the quiet zone (we assume we center the barcode in the given area
  // what should we do if the area is too small????
  // At the moment the way the code is written is we will always start at the minimum
  // required quiet zone if we don't have enough space.... I guess we'll just have over-run
  // to the right
  //
  // calculate the starting position based on the alignment option
  // for left align we don't need to do anything as the values are already setup for it
  if(bc->align == 1) // center
  {
    qreal nqz = (draw_width - L) / 2.0;
    if(nqz > quiet_zone)
      quiet_zone = nqz;
  }
  else if(bc->align > 1) // right
    quiet_zone = draw_width - (L + quiet_zone);
  // else if(align < 1) {} // left : do nothing

  qreal pos = r.left() + quiet_zone;
  qreal top = r.top();

  QPen pen(Qt::NoPen);
  QBrush brush(QColor("black"));

  bool space = false;
  int idx = 0, b = 0;
  qreal w = 0.0;
  for(i = 0; i < str.size(); i++)
  {
    // loop through each value and render the barcode
    idx = str.at(i);
    if(idx < 0 || idx > 105)
    {
      qDebug("Encountered a non-compliant element while rendering a 3of9 barcode -- skipping");
      continue;
    }
    space = false;
    for(b = 0; b < 6; b++, space = !space)
    {
      w = _128codes[idx].values[b] * bar_width;
      if(!space)
      {
        ORORect * rect = new ORORect(bc);
        rect->setPen(pen);
        rect->setBrush(brush);
        rect->setRect(QRectF(pos,top, w,draw_height));
		rect->setRotationAxis(r.topLeft());
        page->addPrimitive(rect);
      }
      pos += w;
    }
  }

  // we have to do the stop character seperatly like this because it has
  // 7 elements in it's bar sequence rather than 6 like the others
  int STOP_CHARACTER[]={ 2, 3, 3, 1, 1, 1, 2 };
  space = false;
  for(b = 0; b < 7; b++, space = !space)
  {
    w = STOP_CHARACTER[b] * bar_width;
    if(!space)
    {
      ORORect * rect = new ORORect(bc);
      rect->setPen(pen);
      rect->setBrush(brush);
      rect->setRect(QRectF(pos,top, w,draw_height));
	  rect->setRotationAxis(r.topLeft());
      page->addPrimitive(rect);
    }
    pos += w;
  }

  return;
} 
void HighlightItem::reposition(const QRectF & rect)
{
    QRectF pr = rect.isNull() ? parentRect() : rect;
    QGraphicsItem::setPos((int)(pr.left() + m_xn * pr.width()), (int)(pr.top() + m_yn * pr.height()));
}
Exemple #5
0
void TimelineGL::paintGL() {
    glReady = true;

    if(!Global::viewerGL->glReady) {
        Global::viewerSortChanged = true;
        Global::viewerGL->glReady = true;
    }

    //Efface
    GLbitfield clearFlag = GL_COLOR_BUFFER_BIT;
    if(format().stencil())  clearFlag |= GL_STENCIL_BUFFER_BIT;
    if(format().depth())    clearFlag |= GL_DEPTH_BUFFER_BIT;
    glClear(clearFlag);
    qglClearColor(Global::colorTextBlack);

    QRectF _drawingBoundingRect;
    scroll            = scroll            + (       scrollDest            - scroll)            / (Global::inertie);
    showLegend        = showLegend        + ((qreal)showLegendDest        - showLegend)        / (Global::inertie);
    showLinkedRenders = showLinkedRenders + ((qreal)showLinkedRendersDest - showLinkedRenders) / (Global::inertie);
    showLinkedTags    = showLinkedTags    + ((qreal)showLinkedTagsDest    - showLinkedTags)    / (Global::inertie);
    showHashedTags    = showHashedTags    + ((qreal)showHashedTagsDest    - showHashedTags)    / (Global::inertie);
    tagSnap           = tagSnap           + ((qreal)tagSnapDest           - tagSnap)           / (Global::inertie);
    tagSnapSlow       = tagSnapSlow       + ((qreal)tagSnapSlowDest       - tagSnapSlow)       / (Global::inertie * 2);

    visibleRect = QRectF(scroll, size());
    glScissor(Global::timelineHeaderSize.width(), 0, width() - Global::timelineHeaderSize.width(), height());
    glPushMatrix();
    glTranslatef(qRound(-scroll.x()), qRound(-scroll.y()), 0);
    if(Global::timeline)        _drawingBoundingRect = _drawingBoundingRect.united(Global::timeline      ->paintTimeline(true));
    if(Global::currentProject)  _drawingBoundingRect = _drawingBoundingRect.united(Global::currentProject->paintTimeline(true));
    if(Global::timeline)        _drawingBoundingRect = _drawingBoundingRect.united(Global::timeline      ->paintTimeline());
    if(Global::currentProject)  _drawingBoundingRect = _drawingBoundingRect.united(Global::currentProject->paintTimeline());
    glPopMatrix();
    drawingBoundingRect = _drawingBoundingRect;


    Global::breathing = Global::breathing + (Global::breathingDest - Global::breathing) / 50.;
    if((     Global::breathing > 0.90) && (Global::breathingDest == 1))    Global::breathingDest = 0;
    else if((Global::breathing < 0.10) && (Global::breathingDest == 0))    Global::breathingDest = 1;
    Global::breathingFast = Global::breathingFast + (Global::breathingFastDest - Global::breathingFast) / 20.;
    if((     Global::breathingFast > 0.90) && (Global::breathingFastDest == 1))    Global::breathingFastDest = 0;
    else if((Global::breathingFast < 0.10) && (Global::breathingFastDest == 0))    Global::breathingFastDest = 1;
    Global::breathingPics = Global::breathingPics + (Global::breathingPicsDest - Global::breathingPics) / 200.;
    if((     Global::breathingPics > 0.90) && (Global::breathingPicsDest == 1))    Global::breathingPicsDest = 0;
    else if((Global::breathingPics < 0.10) && (Global::breathingPicsDest == 0))    Global::breathingPicsDest = 1;

    if(showLegend > 0.01) {
        //Background
        qreal legendBaseSize = qBound(200., height() * 0.75, 400.);
        QRectF legendRect = QRectF(width() - legendBaseSize * 1.2, height() - showLegend * legendBaseSize, legendBaseSize * 1.2, legendBaseSize);
        qglColor(Global::colorAlternateStrong);
        GlRect::drawRect(legendRect);

        //Circles
        legendBaseSize *= 0.8;
        glPushMatrix();
        glTranslatef(qRound(legendRect.center().x()), qRound(legendRect.center().y()), 0);
        qreal angle = -M_PI/2, angleStep = 0;
        glBegin(GL_QUAD_STRIP);
        QMapIterator<QString, QPair<QColor, qreal> > colorForMetaIterator(Global::colorForMeta);
        while(colorForMetaIterator.hasNext()) {
            colorForMetaIterator.next();
            angleStep = 2 * M_PI * colorForMetaIterator.value().second * showLegend;

            qreal legendRadiusL = legendBaseSize;
            qreal legendRadiusS = legendBaseSize * 0.8;

            qglColor(colorForMetaIterator.value().first);
            for(qreal angleSmooth = angle ; angleSmooth <= angle + angleStep ; angleSmooth += 0.01) {
                glVertex2f(qCos(angleSmooth) * legendRadiusL/2, qSin(angleSmooth) * legendRadiusL/2);
                glVertex2f(qCos(angleSmooth) * legendRadiusS/2, qSin(angleSmooth) * legendRadiusS/2);
            }
            angle += angleStep;
        }
        glEnd();

        //Text
        legendBaseSize *= 1.1;
        angle = -M_PI/2;
        QMapIterator<QString, QPair<QColor, qreal> > colorForMetaIteratorText(Global::colorForMeta);
        while(colorForMetaIteratorText.hasNext()) {
            colorForMetaIteratorText.next();
            angleStep = 2*M_PI * colorForMetaIteratorText.value().second * showLegend;
            angle += angleStep/2;

            QString tagCategory = QString("%1 (%2%)").arg(colorForMetaIteratorText.key().toUpper()).arg(qFloor(colorForMetaIteratorText.value().second * 100));
            QPoint pt(qCos(angle) * legendBaseSize/2, qSin(angle) * legendBaseSize/2);

            QColor color = Qt::white;
            color.setAlpha(colorForMetaIteratorText.value().first.alpha());

            //Draw text
            qglColor(color);
            bool textFound = false;
            if(categories.count() > 1000)
                categories.clear();
            foreach(GlText category, categories) {
                if(category.text == tagCategory) {
                    category.drawText(pt - QPoint(category.size.width() / 2, 0));
                    textFound = true;
                }
            }
            if(!textFound) {
                GlText category;
                category.setStyle(QFontMetrics(Global::font).boundingRect(tagCategory).size(), Qt::AlignLeft, Global::font);
                category.drawText(tagCategory, pt - QPoint(category.size.width() / 2, 0));
                categories << category;
            }
            angle += angleStep/2;
        }
        glPopMatrix();
    }
Exemple #6
0
// Apply a simple variant type to a DOM property
static bool applySimpleProperty(const QVariant &v, bool translateString, DomProperty *dom_prop)
{
    switch (v.type()) {
    case QVariant::String: {
        DomString *str = new DomString();
        str->setText(v.toString());
        if (!translateString)
            str->setAttributeNotr(QLatin1String("true"));
        dom_prop->setElementString(str);
    }
        return true;

    case QVariant::ByteArray:
        dom_prop->setElementCstring(QString::fromUtf8(v.toByteArray()));
        return true;

    case QVariant::Int:
        dom_prop->setElementNumber(v.toInt());
        return true;

    case QVariant::UInt:
        dom_prop->setElementUInt(v.toUInt());
        return true;

    case QVariant::LongLong:
        dom_prop->setElementLongLong(v.toLongLong());
        return true;

    case QVariant::ULongLong:
        dom_prop->setElementULongLong(v.toULongLong());
        return true;

    case QVariant::Double:
        dom_prop->setElementDouble(v.toDouble());
        return true;

    case QVariant::Bool:
        dom_prop->setElementBool(v.toBool() ? QFormBuilderStrings::instance().trueValue : QFormBuilderStrings::instance().falseValue);
        return true;

    case QVariant::Char: {
        DomChar *ch = new DomChar();
        const QChar character = v.toChar();
        ch->setElementUnicode(character.unicode());
        dom_prop->setElementChar(ch);
    }
        return true;

    case QVariant::Point: {
        DomPoint *pt = new DomPoint();
        const QPoint point = v.toPoint();
        pt->setElementX(point.x());
        pt->setElementY(point.y());
        dom_prop->setElementPoint(pt);
    }
        return true;

    case QVariant::PointF: {
        DomPointF *ptf = new DomPointF();
        const QPointF pointf = v.toPointF();
        ptf->setElementX(pointf.x());
        ptf->setElementY(pointf.y());
        dom_prop->setElementPointF(ptf);
    }
        return true;

    case QVariant::Color: {
        DomColor *clr = new DomColor();
        const QColor color = qvariant_cast<QColor>(v);
        clr->setElementRed(color.red());
        clr->setElementGreen(color.green());
        clr->setElementBlue(color.blue());
        const int alphaChannel = color.alpha();
        if (alphaChannel != 255)
            clr->setAttributeAlpha(alphaChannel);
        dom_prop->setElementColor(clr);
    }
        return true;

    case QVariant::Size: {
        DomSize *sz = new DomSize();
        const QSize size = v.toSize();
        sz->setElementWidth(size.width());
        sz->setElementHeight(size.height());
        dom_prop->setElementSize(sz);
    }
        return true;

    case QVariant::SizeF: {
        DomSizeF *szf = new DomSizeF();
        const QSizeF sizef = v.toSizeF();
        szf->setElementWidth(sizef.width());
        szf->setElementHeight(sizef.height());
        dom_prop->setElementSizeF(szf);
    }
        return true;

    case QVariant::Rect: {
        DomRect *rc = new DomRect();
        const QRect rect = v.toRect();
        rc->setElementX(rect.x());
        rc->setElementY(rect.y());
        rc->setElementWidth(rect.width());
        rc->setElementHeight(rect.height());
        dom_prop->setElementRect(rc);
    }
        return true;

    case QVariant::RectF: {
        DomRectF *rcf = new DomRectF();
        const QRectF rectf = v.toRectF();
        rcf->setElementX(rectf.x());
        rcf->setElementY(rectf.y());
        rcf->setElementWidth(rectf.width());
        rcf->setElementHeight(rectf.height());
        dom_prop->setElementRectF(rcf);
    }
        return true;

    case QVariant::Font: {
        DomFont *fnt = new DomFont();
        const QFont font = qvariant_cast<QFont>(v);
        const uint mask = font.resolve();
        if (mask & QFont::WeightResolved) {
            fnt->setElementBold(font.bold());
            fnt->setElementWeight(font.weight());
        }
        if (mask & QFont::FamilyResolved)
            fnt->setElementFamily(font.family());
        if (mask & QFont::StyleResolved)
            fnt->setElementItalic(font.italic());
        if (mask & QFont::SizeResolved)
            fnt->setElementPointSize(font.pointSize());
        if (mask & QFont::StrikeOutResolved)
            fnt->setElementStrikeOut(font.strikeOut());
        if (mask & QFont::UnderlineResolved)
            fnt->setElementUnderline(font.underline());
        if (mask & QFont::KerningResolved)
            fnt->setElementKerning(font.kerning());
        if (mask & QFont::StyleStrategyResolved) {
            const QMetaEnum styleStrategy_enum = metaEnum<QAbstractFormBuilderGadget>("styleStrategy");
            fnt->setElementStyleStrategy(QLatin1String(styleStrategy_enum.valueToKey(font.styleStrategy())));
        }
        dom_prop->setElementFont(fnt);
    }
        return true;

#ifndef QT_NO_CURSOR
    case QVariant::Cursor: {
        const QMetaEnum cursorShape_enum = metaEnum<QAbstractFormBuilderGadget>("cursorShape");
        dom_prop->setElementCursorShape(QLatin1String(cursorShape_enum.valueToKey(qvariant_cast<QCursor>(v).shape())));
        }
        return true;
#endif

    case QVariant::KeySequence: {
        DomString *s = new DomString();
        s->setText(qvariant_cast<QKeySequence>(v).toString(QKeySequence::PortableText));
        dom_prop->setElementString(s);
        }
        return true;

    case QVariant::Locale: {
        DomLocale *dom = new DomLocale();
        const QLocale locale = qvariant_cast<QLocale>(v);

        const QMetaEnum language_enum = metaEnum<QAbstractFormBuilderGadget>("language");
        const QMetaEnum country_enum = metaEnum<QAbstractFormBuilderGadget>("country");

        dom->setAttributeLanguage(QLatin1String(language_enum.valueToKey(locale.language())));
        dom->setAttributeCountry(QLatin1String(country_enum.valueToKey(locale.country())));

        dom_prop->setElementLocale(dom);
        }
        return true;

    case QVariant::SizePolicy: {
        DomSizePolicy *dom = new DomSizePolicy();
        const QSizePolicy sizePolicy = qvariant_cast<QSizePolicy>(v);

        dom->setElementHorStretch(sizePolicy.horizontalStretch());
        dom->setElementVerStretch(sizePolicy.verticalStretch());

        const QMetaEnum sizeType_enum = metaEnum<QAbstractFormBuilderGadget>("sizeType");

        dom->setAttributeHSizeType(QLatin1String(sizeType_enum.valueToKey(sizePolicy.horizontalPolicy())));
        dom->setAttributeVSizeType(QLatin1String(sizeType_enum.valueToKey(sizePolicy.verticalPolicy())));

        dom_prop->setElementSizePolicy(dom);
    }
        return true;

    case QVariant::Date: {
        DomDate *dom = new DomDate();
        const QDate date = qvariant_cast<QDate>(v);

        dom->setElementYear(date.year());
        dom->setElementMonth(date.month());
        dom->setElementDay(date.day());

        dom_prop->setElementDate(dom);
        }
        return true;

    case QVariant::Time: {
        DomTime *dom = new DomTime();
        const QTime time = qvariant_cast<QTime>(v);

        dom->setElementHour(time.hour());
        dom->setElementMinute(time.minute());
        dom->setElementSecond(time.second());

        dom_prop->setElementTime(dom);
        }
        return true;

    case QVariant::DateTime: {
        DomDateTime *dom = new DomDateTime();
        const QDateTime dateTime = qvariant_cast<QDateTime>(v);

        dom->setElementHour(dateTime.time().hour());
        dom->setElementMinute(dateTime.time().minute());
        dom->setElementSecond(dateTime.time().second());
        dom->setElementYear(dateTime.date().year());
        dom->setElementMonth(dateTime.date().month());
        dom->setElementDay(dateTime.date().day());

        dom_prop->setElementDateTime(dom);
    }
        return true;

    case QVariant::Url: {
        DomUrl *dom = new DomUrl();
        const QUrl url = v.toUrl();

        DomString *str = new DomString();
        str->setText(url.toString());
        dom->setElementString(str);

        dom_prop->setElementUrl(dom);
    }
        return true;

    case QVariant::StringList: {
        DomStringList *sl = new DomStringList;
        sl->setElementString(qvariant_cast<QStringList>(v));
        dom_prop->setElementStringList(sl);
    }
        return true;

    default:
        break;
    }

    return false;
}
Exemple #7
0
//! [4]
void LayoutItem::setGeometry(const QRectF &geom)
{
    prepareGeometryChange();
    QGraphicsLayoutItem::setGeometry(geom);
    setPos(geom.topLeft());
}
Exemple #8
0
QImage * GroundPlaneGenerator::generateGroundPlaneAux(const QString & boardSvg, QSizeF boardImageSize, const QString & svg, QSizeF copperImageSize, 
													QStringList & exceptions, QGraphicsItem * board, double res, double & bWidth, double & bHeight, double blurBy) 
{
	QByteArray boardByteArray;
    QString tempColor("#ffffff");
    if (!SvgFileSplitter::changeColors(boardSvg, tempColor, exceptions, boardByteArray)) {
		return NULL;
	}

	/*
	QFile file0("testGroundFillBoard.svg");
	file0.open(QIODevice::WriteOnly);
	QTextStream out0(&file0);
	out0 << boardByteArray;
	file0.close();
	*/


	QByteArray copperByteArray;
	if (!SvgFileSplitter::changeStrokeWidth(svg, 50, false, copperByteArray)) {
		return NULL;
	}

	/*
	QFile file1("testGroundFillCopper.svg");
	file1.open(QIODevice::WriteOnly);
	QTextStream out1(&file1);
	out1 << copperByteArray;
	file1.close();
	*/

	double svgWidth = res * qMax(boardImageSize.width(), copperImageSize.width()) / FSvgRenderer::printerScale();
	double svgHeight = res * qMax(boardImageSize.height(), copperImageSize.height()) / FSvgRenderer::printerScale();

	QRectF br =  board->sceneBoundingRect();
	bWidth = res * br.width() / FSvgRenderer::printerScale();
	bHeight = res * br.height() / FSvgRenderer::printerScale();
	QImage * image = new QImage(qMax(svgWidth, bWidth), qMax(svgHeight, bHeight), QImage::Format_Mono); //
	image->setDotsPerMeterX(res * GraphicsUtils::InchesPerMeter);
	image->setDotsPerMeterY(res * GraphicsUtils::InchesPerMeter);
	image->fill(0x0);

	QSvgRenderer renderer(boardByteArray);
	QPainter painter;
	painter.begin(image);
	painter.setRenderHint(QPainter::Antialiasing, false);
	renderer.render(&painter, QRectF(0, 0, res * boardImageSize.width() / FSvgRenderer::printerScale(), res * boardImageSize.height() / FSvgRenderer::printerScale()));
	painter.end();

#ifndef QT_NO_DEBUG
	image->save("testGroundFillBoard.png");
#endif

	for (double m = 0; m < .004; m += (1.0 / res)) {
		QList<QPoint> points;
		collectBorderPoints(*image, points);

#ifndef QT_NO_DEBUG
		// for debugging
		double pixelFactor = GraphicsUtils::StandardFritzingDPI / res;
		QPolygon polygon;
		foreach(QPoint p, points) {
			polygon.append(QPoint(p.x() * pixelFactor, p.y() * pixelFactor));
		}

		QList<QPolygon> polygons;
		polygons.append(polygon);
		QPointF offset;
		QString pSvg = makePolySvg(polygons, res, bWidth, bHeight, pixelFactor, "#ffffff", "debug", false,  NULL, QSizeF(0,0), 0, QPointF(0, 0));
#endif

		foreach (QPoint p, points) image->setPixel(p, 0);
	}
Exemple #9
0
bool GroundPlaneGenerator::getBoardRects(const QString & boardSvg, QGraphicsItem * board, double res, double keepoutSpace, QList<QRect> & rects)
{
	QByteArray boardByteArray;
    QString tempColor("#000000");
	QStringList exceptions;
	exceptions << "none" << "";
    if (!SvgFileSplitter::changeColors(boardSvg, tempColor, exceptions, boardByteArray)) {
		return false;
	}

	QRectF br = board->sceneBoundingRect();
	double bWidth = res * br.width() / FSvgRenderer::printerScale();
	double bHeight = res * br.height() / FSvgRenderer::printerScale();
	QImage image(bWidth, bHeight, QImage::Format_Mono);  // Format_RGB32
	image.setDotsPerMeterX(res * GraphicsUtils::InchesPerMeter);
	image.setDotsPerMeterY(res * GraphicsUtils::InchesPerMeter);
	image.fill(0xffffffff);

	QSvgRenderer renderer(boardByteArray);
	QPainter painter;
	painter.begin(&image);
	painter.setRenderHint(QPainter::Antialiasing, false);
	renderer.render(&painter);
	painter.end();

#ifndef QT_NO_DEBUG
	//image.save("getBoardRects.png");
#endif

	QColor keepaway(255,255,255);
	int threshold = 1;

	// now add keepout area to the border
	QImage image2 = image.copy();
	painter.begin(&image2);
	painter.setRenderHint(QPainter::Antialiasing, false);
	painter.fillRect(0, 0, image2.width(), keepoutSpace, keepaway);
	painter.fillRect(0, image2.height() - keepoutSpace, image2.width(), keepoutSpace, keepaway);
	painter.fillRect(0, 0, keepoutSpace, image2.height(), keepaway);
	painter.fillRect(image2.width() - keepoutSpace, 0, keepoutSpace, image2.height(), keepaway);

	for (int y = 0; y < image.height(); y++) {
		for (int x = 0; x < image.width(); x++) {
			QRgb current = image.pixel(x, y);
			int gray = QGRAY(current);
			if (gray <= threshold) {			
				continue;
			}

			painter.fillRect(x - keepoutSpace, y - keepoutSpace, keepoutSpace + keepoutSpace, keepoutSpace + keepoutSpace, keepaway);
		}
	}
	painter.end();

#ifndef QT_NO_DEBUG
	//image2.save("getBoardRects2.png");
#endif

	scanLines(image2, bWidth, bHeight, rects, threshold, 1);

	// combine parallel equal-sized rects
	int ix = 0;
	while (ix < rects.count()) {
		QRect r = rects.at(ix++);
		for (int j = ix; j < rects.count(); j++) {
			QRect s = rects.at(j);
			if (s.bottom() == r.bottom()) {
				// on same row; keep going
				continue;
			}

			if (s.top() > r.bottom() + 1) {
				// skipped row, can't join
				break;
			}

			if (s.left() == r.left() && s.right() == r.right()) {
				// join these
				r.setBottom(s.bottom());
				rects.removeAt(j);
				ix--;
				rects.replace(ix, r);
				break;
			}
		}
	}

	return true;
}
Exemple #10
0
QPainterPath OrthogonalRenderer::shape(const MapObject *object) const
{
    QPainterPath path;

    if (!object->cell().isEmpty()) {
        path.addRect(boundingRect(object));
    } else {
        switch (object->shape()) {
        case MapObject::Rectangle: {
            const QRectF bounds = object->bounds();
            const QRectF rect(tileToPixelCoords(bounds.topLeft()),
                              tileToPixelCoords(bounds.bottomRight()));

            if (rect.isNull()) {
                path.addEllipse(rect.topLeft(), 20, 20);
            } else {
                path.addRoundedRect(rect, 10, 10);
            }
            break;
        }
        case MapObject::Polygon:
        case MapObject::Polyline: {
            const QPointF &pos = object->position();
            const QPolygonF polygon = object->polygon().translated(pos);
            const QPolygonF screenPolygon = tileToPixelCoords(polygon);
            if (object->shape() == MapObject::Polygon) {
                path.addPolygon(screenPolygon);
            } else {
                for (int i = 1; i < screenPolygon.size(); ++i) {
                    path.addPolygon(lineToPolygon(screenPolygon[i - 1],
                                                  screenPolygon[i]));
                }
                path.setFillRule(Qt::WindingFill);
            }
            break;
        }
        case MapObject::Ellipse: {
            const QRectF bounds = object->bounds();
            const QRectF rect(tileToPixelCoords(bounds.topLeft()),
                              tileToPixelCoords(bounds.bottomRight()));

            if (rect.isNull()) {
                path.addEllipse(rect.topLeft(), 20, 20);
            } else {
                path.addEllipse(rect);
            }
            break;
        }
        }
    }

    return path;
}
Exemple #11
0
void OrthogonalRenderer::drawMapObject(QPainter *painter,
                                       const MapObject *object,
                                       const QColor &color) const
{
    painter->save();

    const QRectF bounds = object->bounds();
    QRectF rect(tileToPixelCoords(bounds.topLeft()),
                tileToPixelCoords(bounds.bottomRight()));

    painter->translate(rect.topLeft());
    rect.moveTopLeft(QPointF(0, 0));

    if (!object->cell().isEmpty()) {
        const Cell &cell = object->cell();

        CellRenderer(painter).render(cell, QPointF(),
                                     CellRenderer::BottomLeft);

        if (testFlag(ShowTileObjectOutlines)) {
            const QRect rect = cell.tile->image().rect();
            QPen pen(Qt::SolidLine);
            pen.setCosmetic(true);
            painter->setPen(pen);
            painter->drawRect(rect);
            pen.setStyle(Qt::DotLine);
            pen.setColor(color);
            painter->setPen(pen);
            painter->drawRect(rect);
        }
    } else {
        const qreal lineWidth = objectLineWidth();
        const qreal scale = painterScale();
        const qreal shadowDist = (lineWidth == 0 ? 1 : lineWidth) / scale;
        const QPointF shadowOffset = QPointF(shadowDist * 0.5,
                                             shadowDist * 0.5);

        QPen linePen(color, lineWidth, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin);
        linePen.setCosmetic(true);
        QPen shadowPen(linePen);
        shadowPen.setColor(Qt::black);

        QColor brushColor = color;
        brushColor.setAlpha(50);
        const QBrush fillBrush(brushColor);

        painter->setRenderHint(QPainter::Antialiasing);

        switch (object->shape()) {
        case MapObject::Rectangle: {
            if (rect.isNull())
                rect = QRectF(QPointF(-10, -10), QSizeF(20, 20));

            const QFontMetrics fm = painter->fontMetrics();
            QString name = fm.elidedText(object->name(), Qt::ElideRight,
                                         rect.width() + 2);

            // Draw the shadow
            painter->setPen(shadowPen);
            painter->drawRect(rect.translated(shadowOffset));
            if (!name.isEmpty())
                painter->drawText(QPointF(0, -4 - lineWidth / 2) + shadowOffset, name);

            painter->setPen(linePen);
            painter->setBrush(fillBrush);
            painter->drawRect(rect);
            if (!name.isEmpty())
                painter->drawText(QPointF(0, -4 - lineWidth / 2), name);

            break;
        }

        case MapObject::Polyline: {
            QPolygonF screenPolygon = tileToPixelCoords(object->polygon());

            painter->setPen(shadowPen);
            painter->drawPolyline(screenPolygon.translated(shadowOffset));

            painter->setPen(linePen);
            painter->setBrush(fillBrush);
            painter->drawPolyline(screenPolygon);
            break;
        }

        case MapObject::Polygon: {
            QPolygonF screenPolygon = tileToPixelCoords(object->polygon());

            painter->setPen(shadowPen);
            painter->drawPolygon(screenPolygon.translated(shadowOffset));

            painter->setPen(linePen);
            painter->setBrush(fillBrush);
            painter->drawPolygon(screenPolygon);
            break;
        }

        case MapObject::Ellipse: {
            if (rect.isNull())
                rect = QRectF(QPointF(-10, -10), QSizeF(20, 20));

            const QFontMetrics fm = painter->fontMetrics();
            QString name = fm.elidedText(object->name(), Qt::ElideRight,
                                         rect.width() + 2);

            // Draw the shadow
            painter->setPen(shadowPen);
            painter->drawEllipse(rect.translated(shadowOffset));
            if (!name.isEmpty())
                painter->drawText(QPoint(1, -5 + 1), name);

            painter->setPen(linePen);
            painter->setBrush(fillBrush);
            painter->drawEllipse(rect);
            if (!name.isEmpty())
                painter->drawText(QPoint(0, -5), name);

            break;
        }
        }
    }

    painter->restore();
}
QSizeF QgsLayoutItemPicture::applyItemSizeConstraint( const QSizeF &targetSize )
{
  QSizeF currentPictureSize = pictureSize();
  QSizeF newSize = targetSize;
  if ( mResizeMode == QgsLayoutItemPicture::Clip )
  {
    mPictureWidth = targetSize.width();
    mPictureHeight = targetSize.height();
  }
  else
  {
    if ( mResizeMode == ZoomResizeFrame && !rect().isEmpty() && !( currentPictureSize.isEmpty() ) )
    {
      QSizeF targetImageSize;
      if ( qgsDoubleNear( mPictureRotation, 0.0 ) )
      {
        targetImageSize = currentPictureSize;
      }
      else
      {
        //calculate aspect ratio of bounds of rotated image
        QTransform tr;
        tr.rotate( mPictureRotation );
        QRectF rotatedBounds = tr.mapRect( QRectF( 0, 0, currentPictureSize.width(), currentPictureSize.height() ) );
        targetImageSize = QSizeF( rotatedBounds.width(), rotatedBounds.height() );
      }

      //if height has changed more than width, then fix width and set height correspondingly
      //else, do the opposite
      if ( std::fabs( rect().width() - targetSize.width() ) <
           std::fabs( rect().height() - targetSize.height() ) )
      {
        newSize.setHeight( targetImageSize.height() * newSize.width() / targetImageSize.width() );
      }
      else
      {
        newSize.setWidth( targetImageSize.width() * newSize.height() / targetImageSize.height() );
      }
    }
    else if ( mResizeMode == FrameToImageSize )
    {
      if ( !( currentPictureSize.isEmpty() ) )
      {
        QgsLayoutSize sizeMM = mLayout->convertFromLayoutUnits( currentPictureSize, QgsUnitTypes::LayoutMillimeters );
        newSize.setWidth( sizeMM.width() * 25.4 / mLayout->context().dpi() );
        newSize.setHeight( sizeMM.height() * 25.4 / mLayout->context().dpi() );
      }
    }

    //find largest scaling of picture with this rotation which fits in item
    if ( mResizeMode == Zoom || mResizeMode == ZoomResizeFrame )
    {
      QRectF rotatedImageRect = QgsLayoutUtils::largestRotatedRectWithinBounds( QRectF( 0, 0, currentPictureSize.width(), currentPictureSize.height() ),
                                QRectF( 0, 0, newSize.width(), newSize.height() ), mPictureRotation );
      mPictureWidth = rotatedImageRect.width();
      mPictureHeight = rotatedImageRect.height();
    }
    else
    {
      mPictureWidth = newSize.width();
      mPictureHeight = newSize.height();
    }

    if ( newSize != targetSize )
    {
      emit changed();
    }
  }

  return newSize;
}
//protected
void MapGraphicsView::doTileLayout()
{
    //Calculate the center point and polygon of the viewport in QGraphicsScene coordinates
    const QPointF centerPointQGS = _childView->mapToScene(_childView->width()/2.0,
                                                          _childView->height()/2.0);
    QPolygon viewportPolygonQGV;
    viewportPolygonQGV << QPoint(0,0) << QPoint(0,_childView->height()) << QPoint(_childView->width(),_childView->height()) << QPoint(_childView->width(),0);

    const QPolygonF viewportPolygonQGS = _childView->mapToScene(viewportPolygonQGV);
    const QRectF boundingRect = viewportPolygonQGS.boundingRect();

    //We exaggerate the bounding rect for some purposes!
    QRectF exaggeratedBoundingRect = boundingRect;
    exaggeratedBoundingRect.setSize(boundingRect.size()*2.0);
    exaggeratedBoundingRect.moveCenter(boundingRect.center());

    //We'll mark tiles that aren't being displayed as free so we can use them
    QQueue<MapTileGraphicsObject *> freeTiles;

    QSet<QPointF> placesWhereTilesAre;
    foreach(MapTileGraphicsObject * tileObject, _tileObjects)
    {
        if (!tileObject->isVisible() || !exaggeratedBoundingRect.contains(tileObject->pos()))
        {
            freeTiles.enqueue(tileObject);
            tileObject->setVisible(false);
        }
        else
            placesWhereTilesAre.insert(tileObject->pos());
    }

    const quint16 tileSize = _tileSource->tileSize();
    const quint32 tilesPerRow = sqrt((long double)_tileSource->tilesOnZoomLevel(this->zoomLevel()));
    const quint32 tilesPerCol = tilesPerRow;

    const qint32 perSide = qMax(boundingRect.width()/tileSize,
                       boundingRect.height()/tileSize) + 3;
    const qint32 xc = qMax((qint32)0,
                     (qint32)(centerPointQGS.x() / tileSize) - perSide/2);
    const qint32 yc = qMax((qint32)0,
                     (qint32)(centerPointQGS.y() / tileSize) - perSide/2);
    const qint32 xMax = qMin((qint32)tilesPerRow,
                              xc + perSide);
    const qint32 yMax = qMin(yc + perSide,
                              (qint32)tilesPerCol);

    for (qint32 x = xc; x < xMax; x++)
    {
        for (qint32 y = yc; y < yMax; y++)
        {
            const QPointF scenePos(x*tileSize + tileSize/2,
                                   y*tileSize + tileSize/2);


            bool tileIsThere = false;
            if (placesWhereTilesAre.contains(scenePos))
                tileIsThere = true;

            if (tileIsThere)
                continue;

            //Just in case we're running low on free tiles, add one
            if (freeTiles.isEmpty())
            {
                MapTileGraphicsObject * tileObject = new MapTileGraphicsObject(tileSize);
                tileObject->setTileSource(_tileSource);
                _tileObjects.insert(tileObject);
                _childScene->addItem(tileObject);
                freeTiles.enqueue(tileObject);
            }
            //Get the first free tile and make it do its thing
            MapTileGraphicsObject * tileObject = freeTiles.dequeue();
            if (tileObject->pos() != scenePos)
                tileObject->setPos(scenePos);
            if (tileObject->isVisible() != true)
                tileObject->setVisible(true);
            tileObject->setTile(x,y,this->zoomLevel());
        }
    }

    //If we've got a lot of free tiles left over, delete some of them
    while (freeTiles.size() > 2)
    {
        MapTileGraphicsObject * tileObject = freeTiles.dequeue();
        _tileObjects.remove(tileObject);
        _childScene->removeItem(tileObject);
        delete tileObject;
    }

}
void StartScene::adjustItems()
{
    QRectF startSceneRect = sceneRect();

    QRectF logoPixmapRect = logo->boundingRect();
    logo->setPos(startSceneRect.width() / 2 - logoPixmapRect.width() * 0.5,
        startSceneRect.height() / 2 - logoPixmapRect.height() * 1.05);

    for (int i = 0, n = buttons.length(); i < n; ++i) {
        Button *const &button = buttons.at(i);
        QRectF btnRect = button->boundingRect();
        if (i < 4) {
            button->setPos(startSceneRect.width() / 2 - btnRect.width() - 7,
                (i - 1) * (btnRect.height() * 1.2) + startSceneRect.height() / 2 + 40);
        }
        else {
            button->setPos(startSceneRect.width() / 2 + 7,
                (i - 5) * (btnRect.height() * 1.2) + startSceneRect.height() / 2 + 40);
        }
    }

    QRectF websiteTextRect = website_text->boundingRect();
    website_text->setPos(startSceneRect.width() / 2 + websiteTextRect.width(),
        startSceneRect.height() / 2 + 8.5 * websiteTextRect.height());

    if (server_log) {
        server_log->move(startSceneRect.width() / 2 - server_log->width() / 2,
            startSceneRect.height() / 2 - server_log->height() / 2 + logo->boundingRect().height() / 4);
    }
}
QRectF ObjectLayer::objectsBoundingRect() const {
    QRectF boundingRect;
    foreach (const MapObject *object, mObjects) {
        boundingRect = boundingRect.united(object->bounds());
    }
Exemple #16
0
KoShapeAlignCommand::KoShapeAlignCommand(const QList<KoShape*> &shapes, Align align, const QRectF &boundingRect, KUndo2Command *parent)
        : KUndo2Command(parent),
        d(new Private())
{
    QList<QPointF> previousPositions;
    QList<QPointF> newPositions;
    QPointF position;
    QPointF delta;
    QRectF bRect;
    foreach(KoShape *shape, shapes) {
//   if (dynamic_cast<KoShapeGroup*> (shape))
//       kDebug(30006) <<"Found Group";
//   else if (dynamic_cast<KoShapeContainer*> (shape))
//       kDebug(30006) <<"Found Container";
//   else
//       kDebug(30006) <<"Found shape";
        position = shape->position();
        previousPositions  << position;
        bRect = shape->boundingRect();
        switch (align) {
        case HorizontalLeftAlignment:
            delta = QPointF(boundingRect.left(), bRect.y()) - bRect.topLeft();
            break;
        case HorizontalCenterAlignment:
            delta = QPointF(boundingRect.center().x() - bRect.width() / 2, bRect.y()) - bRect.topLeft();
            break;
        case HorizontalRightAlignment:
            delta = QPointF(boundingRect.right() - bRect.width(), bRect.y()) - bRect.topLeft();
            break;
        case VerticalTopAlignment:
            delta = QPointF(bRect.x(), boundingRect.top()) - bRect.topLeft();
            break;
        case VerticalCenterAlignment:
            delta = QPointF(bRect.x(), boundingRect.center().y() - bRect.height() / 2) - bRect.topLeft();
            break;
        case VerticalBottomAlignment:
            delta = QPointF(bRect.x(), boundingRect.bottom() - bRect.height()) - bRect.topLeft();
            break;
        };
        newPositions  << position + delta;
//kDebug(30006) <<"-> moving" <<  position.x() <<"," << position.y() <<" to" <<
//        (position + delta).x() << ", " << (position+delta).y() << endl;
    }
Exemple #17
0
void QGIView::dumpRect(char* text, QRectF r) {
    Base::Console().Message("DUMP - %s - rect: (%.3f,%.3f) x (%.3f,%.3f)\n",text,
                            r.left(),r.top(),r.right(),r.bottom());
}
Exemple #18
0
/*!
   Set a the "rectangle of interest"

   QwtPlotSeriesItem defines the current area of the plot canvas
   as "rect of interest" ( QwtPlotSeriesItem::updateScaleDiv() ).

   If interval().isValid() == false the x values are calculated
   in the interval rect.left() -> rect.right().

   \sa rectOfInterest()
*/
void QwtSyntheticPointData::setRectOfInterest( const QRectF &rect )
{
    d_rectOfInterest = rect;
    d_intervalOfInterest = QwtInterval(
        rect.left(), rect.right() ).normalized();
}
void QxrdHistogramDialog::recalculateHistogram()
{
  QxrdHistogramDialogSettingsPtr set(m_HistogramDialogSettings);

  if (set && m_Image) {
    QxrdExperimentPtr expt(m_Experiment);

    if (expt) {
      QTime tic;
      tic.start();

      QRectF rect = set->get_HistogramRect();

      int nsum = m_Image->get_SummedExposures();

      if (nsum < 1) {
        nsum = 1;
      }

      QxrdAcquisitionPtr acq(expt->acquisition());

      double satlev = 60000;

      if (acq) {
        satlev = acq->get_OverflowLevel();
      }

      double min = 0, max = satlev*nsum;

      const int nbins=1000;

      QcepDoubleVector x0(nbins), h0(nbins), h1(nbins);

      for (int i=0; i<nbins; i++) {
//        double x = min+i*(max-min)/1000.0;
        x0[i] = i*100.0/(double)nbins;
        h0[i] = 0;
        h1[i] = 0;
      }

      int width = m_Image->get_Width();
      int height= m_Image->get_Height();

      double *data = m_Image->data();

      for (int i=0; i<width; i++) {
        for (int j=0; j<height; j++) {
          double v = *data++;

          int n;

          if (v<min) {
            n=0;
          } else if (v>max) {
            n=nbins-1;
          } else {
            n=(nbins-1)*(v-min)/(max-min);
          }

          if (n<0) {
            n=0;
          }

          if (n>=nbins) {
            n=nbins-1;
          }

          h0[n]++;

          if (rect.contains(i,j)) {
            h1[n]++;
          }
        }
      }

      m_HistogramPlot->detachItems();

      QwtPlotPiecewiseCurve *pc0 = new QwtPlotPiecewiseCurve(m_HistogramPlot, "Entire Image");

      pc0->setSamples(x0, h0);
      pc0->setPen(QPen(Qt::red));

      pc0->attach(m_HistogramPlot);

      QwtPlotPiecewiseCurve *pc1 = new QwtPlotPiecewiseCurve(m_HistogramPlot,
                                                             tr("[%1,%2]-[%3,%4]")
                                                             .arg(rect.left()).arg(rect.bottom())
                                                             .arg(rect.right()).arg(rect.top()));

      pc1->setSamples(x0, h1);
      pc1->setPen(QPen(Qt::darkRed));

      pc1->attach(m_HistogramPlot);

      m_HistogramPlot->replot();

      if (qcepDebug(DEBUG_HISTOGRAM)) {
        expt -> printMessage(tr("Histogram of data took %1 msec").arg(tic.elapsed()));
      }
    }
  }
}
void ColumnHandleItem::sceneRectChanged(const QRectF &rect) {
  prepareGeometryChange();
  _boundingRect = QRectF(-_width/2, rect.y(), _width, rect.height());
}
Exemple #21
0
void Tweener::release(const TupInputDeviceInformation *input, TupBrushManager *brushManager, TupGraphicsScene *scene)
{
    #ifdef K_DEBUG
        #ifdef Q_OS_WIN
            qDebug() << "[Tweener::release()]";
        #else
            T_FUNCINFO;
        #endif
    #endif

    Q_UNUSED(input);
    Q_UNUSED(brushManager);

    if (scene->currentFrameIndex() == k->initFrame) {
        if (k->editMode == TupToolPlugin::Properties) {
            if (k->nodesGroup) {
                k->nodesGroup->createNodes(k->path);
                k->nodesGroup->show();
                k->nodesGroup->expandAllNodes();
                k->configurator->updateSteps(k->path);
                QPainterPath::Element e = k->path->path().elementAt(0);
                QPointF begin = QPointF(e.x, e.y);

                if (begin != k->firstNode) {
                    QPointF oldPos = k->firstNode;
                    QPointF newPos = begin;

                    int distanceX = newPos.x() - oldPos.x();
                    int distanceY = newPos.y() - oldPos.y();

                    if (k->objects.size() > 0) {
                        foreach (QGraphicsItem *item, k->objects)
                                 item->moveBy(distanceX, distanceY);
                        QGraphicsItem *item = k->objects.at(0);
                        QRectF rect = item->sceneBoundingRect();
                        k->itemObjectReference = rect.center();
                    }

                    k->firstNode = newPos;
                }

                updateTweenPoints();
            }
        } else {
            if (scene->selectedItems().size() > 0) {
                k->objects = scene->selectedItems();
                k->configurator->notifySelection(true);

                QGraphicsItem *item = k->objects.at(0);
                QRectF rect = item->sceneBoundingRect();
                QPointF newPos = rect.center();
                QPointF oldPos = k->itemObjectReference;
                k->itemObjectReference = newPos;

                if (!k->path) {
                    k->path = new QGraphicsPathItem;
                    k->path->setZValue(k->baseZValue);

                    QColor color(55, 155, 55, 200);
                    QPen pen(QBrush(color), 2, Qt::DashDotLine, Qt::RoundCap, Qt::RoundJoin);
                    k->path->setPen(pen);

                    QPainterPath path;
                    path.moveTo(newPos);
                    k->firstNode = newPos;
                    k->path->setPath(path);
                    scene->addItem(k->path);
                    k->isPathInScene = true;

                    k->pathOffset = QPointF(0, 0);
                } else {
                    int distanceX = newPos.x() - oldPos.x();
                    int distanceY = newPos.y() - oldPos.y();
                    k->path->moveBy(distanceX, distanceY);
                    k->pathOffset = QPointF(distanceX, distanceY);

                    // k->firstNode = newPos;
                }
            } 
        }
    } 
}
void IsometricRenderer::drawTileLayer(QPainter *painter,
                                      const TileLayer *layer,
                                      const QRectF &exposed) const
{
    const int tileWidth = map()->tileWidth();
    const int tileHeight = map()->tileHeight();

    if (tileWidth <= 0 || tileHeight <= 1)
        return;

    QRect rect = exposed.toAlignedRect();
    if (rect.isNull())
        rect = boundingRect(layer->bounds());

    QMargins drawMargins = layer->drawMargins();
    drawMargins.setTop(drawMargins.top() - tileHeight);
    drawMargins.setRight(drawMargins.right() - tileWidth);

    rect.adjust(-drawMargins.right(),
                -drawMargins.bottom(),
                drawMargins.left(),
                drawMargins.top());

    // Determine the tile and pixel coordinates to start at
    QPointF tilePos = pixelToTileCoords(rect.x(), rect.y());
    QPoint rowItr = QPoint((int) std::floor(tilePos.x()),
                           (int) std::floor(tilePos.y()));
    QPointF startPos = tileToPixelCoords(rowItr);
    startPos.rx() -= tileWidth / 2;
    startPos.ry() += tileHeight;

    // Compensate for the layer position
    rowItr -= QPoint(layer->x(), layer->y());

    /* Determine in which half of the tile the top-left corner of the area we
     * need to draw is. If we're in the upper half, we need to start one row
     * up due to those tiles being visible as well. How we go up one row
     * depends on whether we're in the left or right half of the tile.
     */
    const bool inUpperHalf = startPos.y() - rect.y() > tileHeight / 2;
    const bool inLeftHalf = rect.x() - startPos.x() < tileWidth / 2;

    if (inUpperHalf) {
        if (inLeftHalf) {
            --rowItr.rx();
            startPos.rx() -= tileWidth / 2;
        } else {
            --rowItr.ry();
            startPos.rx() += tileWidth / 2;
        }
        startPos.ry() -= tileHeight / 2;
    }

    // Determine whether the current row is shifted half a tile to the right
    bool shifted = inUpperHalf ^ inLeftHalf;

    CellRenderer renderer(painter);

    for (int y = startPos.y(); y - tileHeight < rect.bottom();
         y += tileHeight / 2)
    {
        QPoint columnItr = rowItr;

        for (int x = startPos.x(); x < rect.right(); x += tileWidth) {
            if (layer->contains(columnItr)) {
                const Cell &cell = layer->cellAt(columnItr);
                if (!cell.isEmpty()) {
                    renderer.render(cell, QPointF(x, y),
                                    CellRenderer::BottomLeft);
                }
            }

            // Advance to the next column
            ++columnItr.rx();
            --columnItr.ry();
        }

        // Advance to the next row
        if (!shifted) {
            ++rowItr.rx();
            startPos.rx() += tileWidth / 2;
            shifted = true;
        } else {
            ++rowItr.ry();
            startPos.rx() -= tileWidth / 2;
            shifted = false;
        }
    }
}
bool MapGraphicsObject::contains(const QPointF &geoPos) const
{
    QRectF geoRect = this->boundingRect();
    return geoRect.contains(geoPos);
}
void IsometricRenderer::drawMapObject(QPainter *painter,
                                      const MapObject *object,
                                      const QColor &color) const
{
    painter->save();

    QPen pen(Qt::black, 0);

    if (!object->cell().isEmpty()) {
        const Tile *tile = object->cell().tile;
        const QSize imgSize = tile->size();
        const QPointF pos = tileToPixelCoords(object->position());

        // Draw the name before the transform is applied
        const QFontMetrics fm = painter->fontMetrics();
        QString name = fm.elidedText(object->name(), Qt::ElideRight,
                                     imgSize.width() + 2);
        if (!name.isEmpty()) {
            const QPointF tileOffset = tile->tileset()->tileOffset();
            const QPointF textPos = pos + tileOffset -
                    QPointF(imgSize.width() / 2, 5 + imgSize.height());

            painter->drawText(textPos + QPointF(1, 1), name);
            painter->setPen(color);
            painter->drawText(textPos, name);
        }

        CellRenderer(painter).render(object->cell(), pos,
                                     CellRenderer::BottomCenter);

        if (testFlag(ShowTileObjectOutlines)) {
            pen.setStyle(Qt::SolidLine);
            painter->setPen(pen);
            painter->drawRect(QRectF(QPointF(), imgSize));
            pen.setStyle(Qt::DotLine);
            pen.setColor(color);
            painter->setPen(pen);
            painter->drawRect(QRectF(QPointF(), imgSize));
        }
    } else {
        const qreal lineWidth = objectLineWidth();
        const qreal shadowOffset = lineWidth == 0 ? (1 / painter->transform().m11()) :
                                                    qMin(qreal(1), lineWidth);

        QColor brushColor = color;
        brushColor.setAlpha(50);
        QBrush brush(brushColor);

        pen.setJoinStyle(Qt::RoundJoin);
        pen.setCapStyle(Qt::RoundCap);
        pen.setWidth(lineWidth);

        painter->setPen(pen);
        painter->setRenderHint(QPainter::Antialiasing);

        // TODO: Draw the object name
        // TODO: Do something sensible to make null-sized objects usable

        switch (object->shape()) {
        case MapObject::Ellipse: {
            QPointF topLeft(tileToPixelCoords(object->bounds().topLeft()));
            QPointF bottomLeft(tileToPixelCoords(object->bounds().bottomLeft()));
            QPointF topRight(tileToPixelCoords(object->bounds().topRight()));

            const qreal headerX = bottomLeft.x();
            const qreal headerY = topLeft.y();

            QRectF rect(bottomLeft, topRight);

            const QFontMetrics fm = painter->fontMetrics();
            QString name = fm.elidedText(object->name(), Qt::ElideRight,
                                         rect.width() + 2);

            QPolygonF polygon = tileRectToPolygon(object->bounds());

            float tw = map()->tileWidth();
            float th = map()->tileHeight();
            QPointF transformScale(1, 1);
            if (tw > th)
                transformScale = QPointF(1, th/tw);
            else
                transformScale = QPointF(tw/th, 1);

            QPointF l1 = polygon.at(1) - polygon.at(0);
            QPointF l2 = polygon.at(3) - polygon.at(0);
            QTransform trans;
            trans.scale(transformScale.x(), transformScale.y());
            trans.rotate(45);
            QTransform iTrans = trans.inverted();
            QPointF l1x = iTrans.map(l1);
            QPointF l2x = iTrans.map(l2);
            QSizeF ellipseSize(l1x.manhattanLength(), l2x.manhattanLength());

            painter->save();
            painter->setPen(pen);
            painter->translate(polygon.at(0));
            painter->scale(transformScale.x(), transformScale.y());
            painter->rotate(45);
            painter->drawEllipse(QRectF(QPointF(0, 0), ellipseSize));
            painter->restore();

            painter->setBrush(Qt::NoBrush);
            painter->drawPolygon(polygon);

            if (!name.isEmpty())
                painter->drawText(QPoint(headerX, headerY - 5), name);

            pen.setColor(color);
            painter->setPen(pen);
            painter->setBrush(Qt::NoBrush);
            painter->translate(QPointF(0, -shadowOffset));
            painter->drawPolygon(polygon);

            painter->setBrush(brush);
            painter->save();
            painter->translate(polygon.at(0));
            painter->scale(transformScale.x(), transformScale.y());
            painter->rotate(45);
            painter->drawEllipse(QRectF(QPointF(0, 0), ellipseSize));
            painter->restore();

            if (!name.isEmpty())
                painter->drawText(QPoint(headerX, headerY - 5), name);
            break;
        }
        case MapObject::Rectangle: {

            QPointF topLeft(tileToPixelCoords(object->bounds().topLeft()));
            QPointF bottomLeft(tileToPixelCoords(object->bounds().bottomLeft()));
            QPointF topRight(tileToPixelCoords(object->bounds().topRight()));

            const qreal headerX = bottomLeft.x();
            const qreal headerY = topLeft.y();

            QRectF rect(bottomLeft, topRight);

            const QFontMetrics fm = painter->fontMetrics();
            QString name = fm.elidedText(object->name(), Qt::ElideRight,
                                         rect.width() + 2);

            QPolygonF polygon = tileRectToPolygon(object->bounds());
            painter->drawPolygon(polygon);
            if (!name.isEmpty())
                painter->drawText(QPointF(headerX, headerY - 5 + shadowOffset), name);

            pen.setColor(color);
            painter->setPen(pen);
            painter->setBrush(brush);
            polygon.translate(0, -shadowOffset);

            painter->drawPolygon(polygon);
            if (!name.isEmpty())
                painter->drawText(QPointF(headerX, headerY - 5), name);
            break;
        }
        case MapObject::Polygon: {
            const QPointF &pos = object->position();
            const QPolygonF polygon = object->polygon().translated(pos);
            QPolygonF screenPolygon = tileToPixelCoords(polygon);

            const QRectF polygonBoundingRect = screenPolygon.boundingRect();

            const QFontMetrics fm = painter->fontMetrics();
            QString name = fm.elidedText(object->name(), Qt::ElideRight,
                                         polygonBoundingRect.width() + 2);

            if (!name.isEmpty())
                painter->drawText(QPointF(polygonBoundingRect.left(), polygonBoundingRect.top() - 5 + shadowOffset), name);

            painter->drawPolygon(screenPolygon);

            pen.setColor(color);
            painter->setPen(pen);
            painter->setBrush(brush);
            screenPolygon.translate(0, -shadowOffset);

            painter->drawPolygon(screenPolygon);

            if (!name.isEmpty())
                painter->drawText(QPointF(polygonBoundingRect.left(), polygonBoundingRect.top() - 5), name);

            break;
        }
        case MapObject::Polyline: {
            const QPointF &pos = object->position();
            const QPolygonF polygon = object->polygon().translated(pos);
            QPolygonF screenPolygon = tileToPixelCoords(polygon);

            painter->drawPolyline(screenPolygon);

            pen.setColor(color);
            painter->setPen(pen);
            screenPolygon.translate(0, -shadowOffset);

            painter->drawPolyline(screenPolygon);
            break;
        }
        }
    }

    painter->restore();
}
Exemple #25
0
/*!
    Reimplement this function to draw the \a pixmap in the given \a
    rect, starting at the given \a p. The pixmap will be
    drawn repeatedly until the \a rect is filled.
*/
void QPaintEngine::drawTiledPixmap(const QRectF &rect, const QPixmap &pixmap, const QPointF &p)
{
    int sw = pixmap.width();
    int sh = pixmap.height();

    if (sw*sh < 8192 && sw*sh < 16*rect.width()*rect.height()) {
        int tw = sw, th = sh;
        while (tw*th < 32678 && tw < rect.width()/2)
            tw *= 2;
        while (tw*th < 32678 && th < rect.height()/2)
            th *= 2;
        QPixmap tile;
        if (pixmap.depth() == 1) {
            tile = QBitmap(tw, th);
        } else {
            tile = QPixmap(tw, th);
            if (pixmap.hasAlphaChannel())
                tile.fill(Qt::transparent);
        }
        qt_fill_tile(&tile, pixmap);
        qt_draw_tile(this, rect.x(), rect.y(), rect.width(), rect.height(), tile, p.x(), p.y());
    } else {
        qt_draw_tile(this, rect.x(), rect.y(), rect.width(), rect.height(), pixmap, p.x(), p.y());
    }
}
Exemple #26
0
void HexagonalRenderer::drawGrid(QPainter *painter, const QRectF &exposed,
                                 QColor gridColor) const
{
    QRect rect = exposed.toAlignedRect();
    if (rect.isNull())
        return;

    const RenderParams p(map());

    // Determine the tile and pixel coordinates to start at
    QPoint startTile = screenToTileCoords(rect.topLeft()).toPoint();
    QPoint startPos = tileToScreenCoords(startTile).toPoint();

    /* Determine in which half of the tile the top-left corner of the area we
     * need to draw is. If we're in the upper half, we need to start one row
     * up due to those tiles being visible as well. How we go up one row
     * depends on whether we're in the left or right half of the tile.
     */
    const bool inUpperHalf = rect.y() - startPos.y() < p.sideOffsetY;
    const bool inLeftHalf = rect.x() - startPos.x() < p.sideOffsetX;

    if (inUpperHalf)
        startTile.ry()--;
    if (inLeftHalf)
        startTile.rx()--;

    startTile.setX(qMax(0, startTile.x()));
    startTile.setY(qMax(0, startTile.y()));

    startPos = tileToScreenCoords(startTile).toPoint();

    const QPoint oct[8] = {
        QPoint(0,                           p.tileHeight - p.sideOffsetY),
        QPoint(0,                           p.sideOffsetY),
        QPoint(p.sideOffsetX,               0),
        QPoint(p.tileWidth - p.sideOffsetX, 0),
        QPoint(p.tileWidth,                 p.sideOffsetY),
        QPoint(p.tileWidth,                 p.tileHeight - p.sideOffsetY),
        QPoint(p.tileWidth - p.sideOffsetX, p.tileHeight),
        QPoint(p.sideOffsetX,               p.tileHeight)
    };

    QVector<QLine> lines;
    lines.reserve(8);

    gridColor.setAlpha(128);

    QPen gridPen(gridColor);
    gridPen.setCosmetic(true);
    gridPen.setDashPattern(QVector<qreal>() << 2 << 2);
    painter->setPen(gridPen);

    if (p.staggerX) {
        // Odd row shifting is applied in the rendering loop, so un-apply it here
        if (p.doStaggerX(startTile.x()))
            startPos.ry() -= p.rowHeight;

        for (; startPos.x() <= rect.right() && startTile.x() < map()->width(); startTile.rx()++) {
            QPoint rowTile = startTile;
            QPoint rowPos = startPos;

            if (p.doStaggerX(startTile.x()))
                rowPos.ry() += p.rowHeight;

            for (; rowPos.y() <= rect.bottom() && rowTile.y() < map()->height(); rowTile.ry()++) {
                lines.append(QLine(rowPos + oct[1], rowPos + oct[2]));
                lines.append(QLine(rowPos + oct[2], rowPos + oct[3]));
                lines.append(QLine(rowPos + oct[3], rowPos + oct[4]));

                const bool isStaggered = p.doStaggerX(startTile.x());
                const bool lastRow = rowTile.y() == map()->height() - 1;
                const bool lastColumn = rowTile.x() == map()->width() - 1;
                const bool bottomLeft = rowTile.x() == 0 || (lastRow && isStaggered);
                const bool bottomRight = lastColumn || (lastRow && isStaggered);

                if (bottomRight)
                    lines.append(QLine(rowPos + oct[5], rowPos + oct[6]));
                if (lastRow)
                    lines.append(QLine(rowPos + oct[6], rowPos + oct[7]));
                if (bottomLeft)
                    lines.append(QLine(rowPos + oct[7], rowPos + oct[0]));

                painter->drawLines(lines);
                lines.resize(0);

                rowPos.ry() += p.tileHeight + p.sideLengthY;
            }

            startPos.rx() += p.columnWidth;
        }
    } else {
        // Odd row shifting is applied in the rendering loop, so un-apply it here
        if (p.doStaggerY(startTile.y()))
            startPos.rx() -= p.columnWidth;

        for (; startPos.y() <= rect.bottom() && startTile.y() < map()->height(); startTile.ry()++) {
            QPoint rowTile = startTile;
            QPoint rowPos = startPos;

            if (p.doStaggerY(startTile.y()))
                rowPos.rx() += p.columnWidth;

            for (; rowPos.x() <= rect.right() && rowTile.x() < map()->width(); rowTile.rx()++) {
                lines.append(QLine(rowPos + oct[0], rowPos + oct[1]));
                lines.append(QLine(rowPos + oct[1], rowPos + oct[2]));
                lines.append(QLine(rowPos + oct[3], rowPos + oct[4]));

                const bool isStaggered = p.doStaggerY(startTile.y());
                const bool lastRow = rowTile.y() == map()->height() - 1;
                const bool lastColumn = rowTile.x() == map()->width() - 1;
                const bool bottomLeft = lastRow || (rowTile.x() == 0 && !isStaggered);
                const bool bottomRight = lastRow || (lastColumn && isStaggered);

                if (lastColumn)
                    lines.append(QLine(rowPos + oct[4], rowPos + oct[5]));
                if (bottomRight)
                    lines.append(QLine(rowPos + oct[5], rowPos + oct[6]));
                if (bottomLeft)
                    lines.append(QLine(rowPos + oct[7], rowPos + oct[0]));

                painter->drawLines(lines);
                lines.resize(0);

                rowPos.rx() += p.tileWidth + p.sideLengthX;
            }

            startPos.ry() += p.rowHeight;
        }
    }
}
Exemple #27
0
void PDF::generateTexture(const QRectF& screenRect, const QRectF& fullRect, const QRectF& texCoords)
{
    // figure out the coordinates of the topLeft corner of the texture in the PDF page
    const double tXp = texCoords.x()/texCoords.width()*fullRect.width()  + (screenRect.x() - fullRect.x());
    const double tYp = texCoords.y()/texCoords.height()*fullRect.height() + (screenRect.y() - fullRect.y());

    // Compute the actual texture dimensions
    const QRect textureRect(tXp, tYp, screenRect.width(), screenRect.height());

    // TODO The instance of this class is shared between GLWindows, so the
    // texture is constantly regenerated because the size changes...
    if(textureRect == textureRect_)
        return; // no need to regenerate texture

    // Adjust the quality to match the actual displayed size
    // Multiply resolution by the zoom factor (1/t[W,H])
    const double resFactorX = fullRect.width() / pdfPage_->pageSize().width() / texCoords.width();
    const double resFactorY = fullRect.height() / pdfPage_->pageSize().height() / texCoords.height();

    // Generate a QImage of the rendered page
    QImage image = pdfPage_->renderToImage(72.0*resFactorX , 72.0*resFactorY,
                                            textureRect.x(), textureRect.y(),
                                            textureRect.width(), textureRect.height()
                                            );

    if (image.isNull())
    {
        put_flog(LOG_DEBUG, "Could not render pdf to image");
        return;
    }

    texture_.update(image, GL_BGRA);
    textureRect_ = textureRect; // keep rendered texture information so we know when to rerender

}
Exemple #28
0
void HexagonalRenderer::drawTileLayer(QPainter *painter,
                                      const TileLayer *layer,
                                      const QRectF &exposed) const
{
    const RenderParams p(map());

    QRect rect = exposed.toAlignedRect();

    if (rect.isNull())
        rect = boundingRect(layer->bounds());

    QMargins drawMargins = layer->drawMargins();
    drawMargins.setBottom(drawMargins.bottom() + p.tileHeight);
    drawMargins.setRight(drawMargins.right() - p.tileWidth);

    rect.adjust(-drawMargins.right(),
                -drawMargins.bottom(),
                drawMargins.left(),
                drawMargins.top());

    // Determine the tile and pixel coordinates to start at
    QPoint startTile = screenToTileCoords(rect.topLeft()).toPoint();

    // Compensate for the layer position
    startTile -= layer->position();

    QPoint startPos = tileToScreenCoords(startTile + layer->position()).toPoint();

    /* Determine in which half of the tile the top-left corner of the area we
     * need to draw is. If we're in the upper half, we need to start one row
     * up due to those tiles being visible as well. How we go up one row
     * depends on whether we're in the left or right half of the tile.
     */
    const bool inUpperHalf = rect.y() - startPos.y() < p.sideOffsetY;
    const bool inLeftHalf = rect.x() - startPos.x() < p.sideOffsetX;

    if (inUpperHalf)
        startTile.ry()--;
    if (inLeftHalf)
        startTile.rx()--;

    CellRenderer renderer(painter);

    if (p.staggerX) {
        startTile.setX(qMax(-1, startTile.x()));
        startTile.setY(qMax(-1, startTile.y()));

        startPos = tileToScreenCoords(startTile + layer->position()).toPoint();
        startPos.ry() += p.tileHeight;

        bool staggeredRow = p.doStaggerX(startTile.x() + layer->x());

        for (; startPos.y() < rect.bottom() && startTile.y() < layer->height();) {
            QPoint rowTile = startTile;
            QPoint rowPos = startPos;

            for (; rowPos.x() < rect.right() && rowTile.x() < layer->width(); rowTile.rx() += 2) {
                if (layer->contains(rowTile)) {
                    const Cell &cell = layer->cellAt(rowTile);

                    if (!cell.isEmpty())
                        renderer.render(cell, rowPos, QSizeF(0, 0), CellRenderer::BottomLeft);
                }

                rowPos.rx() += p.tileWidth + p.sideLengthX;
            }

            if (staggeredRow) {
                startTile.rx() -= 1;
                startTile.ry() += 1;
                startPos.rx() -= p.columnWidth;
                staggeredRow = false;
            } else {
                startTile.rx() += 1;
                startPos.rx() += p.columnWidth;
                staggeredRow = true;
            }

            startPos.ry() += p.rowHeight;
        }
    } else {
        startTile.setX(qMax(0, startTile.x()));
        startTile.setY(qMax(0, startTile.y()));

        startPos = tileToScreenCoords(startTile + layer->position()).toPoint();
        startPos.ry() += p.tileHeight;

        // Odd row shifting is applied in the rendering loop, so un-apply it here
        if (p.doStaggerY(startTile.y() + layer->y()))
            startPos.rx() -= p.columnWidth;

        for (; startPos.y() < rect.bottom() && startTile.y() < layer->height(); startTile.ry()++) {
            QPoint rowTile = startTile;
            QPoint rowPos = startPos;

            if (p.doStaggerY(startTile.y() + layer->y()))
                rowPos.rx() += p.columnWidth;

            for (; rowPos.x() < rect.right() && rowTile.x() < layer->width(); rowTile.rx()++) {
                const Cell &cell = layer->cellAt(rowTile);

                if (!cell.isEmpty())
                    renderer.render(cell, rowPos, QSizeF(0, 0), CellRenderer::BottomLeft);

                rowPos.rx() += p.tileWidth + p.sideLengthX;
            }

            startPos.ry() += p.rowHeight;
        }
    }
}
Exemple #29
0
QPainterPath TextEditorOverlay::createSelectionPath(const QTextCursor &begin, const QTextCursor &end,
                                                    const QRect &clip)
{
    if (begin.isNull() || end.isNull() || begin.position() > end.position())
        return QPainterPath();

    QPointF offset = m_editor->contentOffset();
    QRect viewportRect = rect();
    QTextDocument *document = m_editor->document();

    if (m_editor->blockBoundingGeometry(begin.block()).translated(offset).top() > clip.bottom() + 10
        || m_editor->blockBoundingGeometry(end.block()).translated(offset).bottom() < clip.top() - 10
        )
        return QPainterPath(); // nothing of the selection is visible


    QTextBlock block = begin.block();

    if (block.blockNumber() < m_editor->firstVisibleBlock().blockNumber() - 4)
        block = m_editor->document()->findBlockByNumber(m_editor->firstVisibleBlock().blockNumber() - 4);

    bool inSelection = false;

    QVector<QRectF> selection;

    if (begin.position() == end.position()) {
        // special case empty selections
        const QRectF blockGeometry = m_editor->blockBoundingGeometry(block);
        QTextLayout *blockLayout = block.layout();
        int pos = begin.position() - begin.block().position();
        QTextLine line = blockLayout->lineForTextPosition(pos);
        QRectF lineRect = line.naturalTextRect();
        int x = line.cursorToX(pos);
        lineRect.setLeft(x - m_borderWidth);
        lineRect.setRight(x + m_borderWidth);
        selection += lineRect.translated(blockGeometry.topLeft());
    } else {
        for (; block.isValid() && block.blockNumber() <= end.blockNumber(); block = block.next()) {
            if (! block.isVisible())
                continue;

            const QRectF blockGeometry = m_editor->blockBoundingGeometry(block);
            QTextLayout *blockLayout = block.layout();

            QTextLine line = blockLayout->lineAt(0);
            bool firstOrLastBlock = false;

            int beginChar = 0;
            if (!inSelection) {
                if (block == begin.block()) {
                    beginChar = begin.positionInBlock();
                    line = blockLayout->lineForTextPosition(beginChar);
                    firstOrLastBlock = true;
                }
                inSelection = true;
            } else {
//                while (beginChar < block.length() && document->characterAt(block.position() + beginChar).isSpace())
//                    ++beginChar;
//                if (beginChar == block.length())
//                    beginChar = 0;
            }

            int lastLine = blockLayout->lineCount()-1;
            int endChar = -1;
            if (block == end.block()) {
                endChar = end.positionInBlock();
                lastLine = blockLayout->lineForTextPosition(endChar).lineNumber();
                inSelection = false;
                firstOrLastBlock = true;
            } else {
                endChar = block.length();
                while (endChar > beginChar && document->characterAt(block.position() + endChar - 1).isSpace())
                    --endChar;
            }

            QRectF lineRect = line.naturalTextRect();
            if (beginChar < endChar) {
                lineRect.setLeft(line.cursorToX(beginChar));
                if (line.lineNumber() == lastLine)
                    lineRect.setRight(line.cursorToX(endChar));
                selection += lineRect.translated(blockGeometry.topLeft());

                for (int lineIndex = line.lineNumber()+1; lineIndex <= lastLine; ++lineIndex) {
                    line = blockLayout->lineAt(lineIndex);
                    lineRect = line.naturalTextRect();
                    if (lineIndex == lastLine)
                        lineRect.setRight(line.cursorToX(endChar));
                    selection += lineRect.translated(blockGeometry.topLeft());
                }
            } else { // empty lines
                const int emptyLineSelectionSize = 16;
                if (!firstOrLastBlock && !selection.isEmpty()) { // middle
                    lineRect.setLeft(selection.last().left());
                } else if (inSelection) { // first line
                    lineRect.setLeft(line.cursorToX(beginChar));
                } else { // last line
                    if (endChar == 0)
                        break;
                    lineRect.setLeft(line.cursorToX(endChar) - emptyLineSelectionSize);
                }
                lineRect.setRight(lineRect.left() + emptyLineSelectionSize);
                selection += lineRect.translated(blockGeometry.topLeft());
            }

            if (!inSelection)
                break;

            if (blockGeometry.translated(offset).y() > 2*viewportRect.height())
                break;
        }
    }


    if (selection.isEmpty())
        return QPainterPath();

    QVector<QPointF> points;

    const int margin = m_borderWidth/2;
    const int extra = 0;

    points += (selection.at(0).topLeft() + selection.at(0).topRight()) / 2 + QPointF(0, -margin);
    points += selection.at(0).topRight() + QPointF(margin+1, -margin);
    points += selection.at(0).bottomRight() + QPointF(margin+1, 0);


    for(int i = 1; i < selection.count()-1; ++i) {

#define MAX3(a,b,c) qMax(a, qMax(b,c))
        qreal x = MAX3(selection.at(i-1).right(),
                       selection.at(i).right(),
                       selection.at(i+1).right()) + margin;

        points += QPointF(x+1, selection.at(i).top());
        points += QPointF(x+1, selection.at(i).bottom());

    }

    points += selection.at(selection.count()-1).topRight() + QPointF(margin+1, 0);
    points += selection.at(selection.count()-1).bottomRight() + QPointF(margin+1, margin+extra);
    points += selection.at(selection.count()-1).bottomLeft() + QPointF(-margin, margin+extra);
    points += selection.at(selection.count()-1).topLeft() + QPointF(-margin, 0);

    for(int i = selection.count()-2; i > 0; --i) {
#define MIN3(a,b,c) qMin(a, qMin(b,c))
        qreal x = MIN3(selection.at(i-1).left(),
                       selection.at(i).left(),
                       selection.at(i+1).left()) - margin;

        points += QPointF(x, selection.at(i).bottom()+extra);
        points += QPointF(x, selection.at(i).top());
    }

    points += selection.at(0).bottomLeft() + QPointF(-margin, extra);
    points += selection.at(0).topLeft() + QPointF(-margin, -margin);


    QPainterPath path;
    const int corner = 4;
    path.moveTo(points.at(0));
    points += points.at(0);
    QPointF previous = points.at(0);
    for (int i = 1; i < points.size(); ++i) {
        QPointF point = points.at(i);
        if (point.y() == previous.y() && qAbs(point.x() - previous.x()) > 2*corner) {
            QPointF tmp = QPointF(previous.x() + corner * ((point.x() > previous.x())?1:-1), previous.y());
            path.quadTo(previous, tmp);
            previous = tmp;
            i--;
            continue;
        } else if (point.x() == previous.x() && qAbs(point.y() - previous.y()) > 2*corner) {
            QPointF tmp = QPointF(previous.x(), previous.y() + corner * ((point.y() > previous.y())?1:-1));
            path.quadTo(previous, tmp);
            previous = tmp;
            i--;
            continue;
        }


        QPointF target = (previous + point) / 2;
        path.quadTo(previous, target);
        previous = points.at(i);
    }
    path.closeSubpath();
    path.translate(offset);
    return path;
}
Exemple #30
0
void KeyWidget::paintEvent(QPaintEvent*){
    const QColor bgColor(68, 64, 64);
    const QColor keyColor(112, 110, 110);
    const QColor highlightColor(136, 176, 240);
    const QColor highlightAnimColor(136, 200, 240);
    const QColor animColor(112, 200, 110);

    // Determine which keys to highlight
    QBitArray highlight;
    switch(mouseDownMode){
    case SET:
        highlight = newSelection;
        break;
    case ADD:
        highlight = selection | newSelection;
        break;
    case SUBTRACT:
        highlight = selection & ~newSelection;
        break;
    case TOGGLE:
        highlight = selection ^ newSelection;
        break;
    default:
        highlight = selection;
    }

    QPainter painter(this);
#if QT_VERSION >= QT_VERSION_CHECK(5, 3, 0)
    int ratio = painter.device()->devicePixelRatio();
#else
    int ratio = 1;
#endif
    float xScale = (float)width() / (keyMap.width() + KEY_SIZE) * ratio;
    float yScale = (float)height() / (keyMap.height() + KEY_SIZE) * ratio;
    // Draw background
    painter.setPen(Qt::NoPen);
    painter.setRenderHint(QPainter::Antialiasing, true);
    painter.setBrush(QBrush(bgColor));
    painter.drawRect(0, 0, width(), height());

    // Draw mouse highlight (if any)
    if(mouseDownMode != NONE && (mouseDownX != mouseCurrentX || mouseDownY != mouseCurrentY)){
        int x1 = (mouseDownX > mouseCurrentX) ? mouseCurrentX : mouseDownX;
        int x2 = (mouseDownX > mouseCurrentX) ? mouseDownX : mouseCurrentX;
        int y1 = (mouseDownY > mouseCurrentY) ? mouseCurrentY : mouseDownY;
        int y2 = (mouseDownY > mouseCurrentY) ? mouseDownY : mouseCurrentY;
        painter.setPen(QPen(highlightColor, 0.5));
        QColor bColor = highlightColor;
        bColor.setAlpha(128);
        painter.setBrush(QBrush(bColor));
        painter.drawRect(x1, y1, x2 - x1, y2 - y1);
    }

    // Draw key backgrounds on a separate pixmap so that a drop shadow can be applied to them.
    int wWidth = width(), wHeight = height();
    KeyMap::Model model = keyMap.model();
    QPixmap keyBG(wWidth * ratio, wHeight * ratio);
    keyBG.fill(QColor(0, 0, 0, 0));
    QPainter bgPainter(&keyBG);
    bgPainter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
    bgPainter.setPen(Qt::NoPen);
    QHashIterator<QString, Key> k(keyMap);
    uint i = -1;
    while(k.hasNext()){
        k.next();
        i++;
        const Key& key = k.value();
        float x = key.x + 6.f - key.width / 2.f + 1.f;
        float y = key.y + 6.f - key.height / 2.f + 1.f;
        float w = key.width - 2.f;
        float h = key.height - 2.f;
        // In RGB mode, ignore keys without LEDs
        if(_rgbMode && !key.hasLed)
            continue;
        // Set color based on key highlight
        if(highlight.testBit(i)){
            if(animation.testBit(i))
                bgPainter.setBrush(QBrush(highlightAnimColor));
            else
                bgPainter.setBrush(QBrush(highlightColor));
        } else if(animation.testBit(i))
            bgPainter.setBrush(QBrush(animColor));
        else
            bgPainter.setBrush(QBrush(keyColor));
        if(!strcmp(key.name, "mr") || !strcmp(key.name, "m1") || !strcmp(key.name, "m2") || !strcmp(key.name, "m3")
                || !strcmp(key.name, "light") || !strcmp(key.name, "lock") || (model == KeyMap::K65 && !strcmp(key.name, "mute"))){
            // Switch keys are circular
            x += w / 8.f;
            y += h / 8.f;
            w *= 0.75f;
            h *= 0.75f;
            bgPainter.drawEllipse(QRectF(x * xScale, y * yScale, w * xScale, h * yScale));
        } else {
            if(!strcmp(key.name, "enter")){
                if(key.height == 24){
                    // ISO enter key isn't rectangular
                    y = key.y + 1.f;
                    h = 10.f;
                    bgPainter.drawRect(QRectF((x + w - 13.f) * xScale, y * yScale, 13.f * xScale, 22.f * yScale));
                } else {
                    // US enter key isn't perfectly centered, needs an extra pixel on the left to appear correctly
                    x -= 1.f;
                    w += 1.f;
                }
            } else if(!strcmp(key.name, "rshift") || !strcmp(key.name, "stop")){
                // A few other keys also need extra pixels
                x -= 1.f;
                w += 1.f;
            } else if(!strcmp(key.name, "caps") || !strcmp(key.name, "lshift") || !strcmp(key.name, "next")){
                w += 1.f;
            }
            bgPainter.drawRect(QRectF(x * xScale, y * yScale, w * xScale, h * yScale));
        }
    }

    // Render the key decorations (RGB -> light circles, binding -> key names) on yet another layer
    QPixmap decoration(wWidth * ratio, wHeight * ratio);
    decoration.fill(QColor(0, 0, 0, 0));
    QPainter decPainter(&decoration);
    decPainter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
    if(_rgbMode){
        // Draw key colors (RGB mode)
        decPainter.setPen(QPen(QColor(255, 255, 255), 1.5));
        QHashIterator<QString, Key> k(keyMap);
        uint i = -1;
        while(k.hasNext()){
            k.next();
            i++;
            const Key& key = k.value();
            if(!key.hasLed)
                continue;
            float x = key.x + 6.f - 1.8f;
            float y = key.y + 6.f - 1.8f;
            float w = 3.6f;
            float h = 3.6f;
            if(_displayColorMap.contains(key.name))
                decPainter.setBrush(QBrush(_displayColorMap.value(key.name)));
            else
                decPainter.setBrush(QBrush(_colorMap.value(key.name)));
            decPainter.drawEllipse(QRectF(x * xScale, y * yScale, w * xScale, h * yScale));
        }
    } else {
        // Draw key names
        decPainter.setBrush(Qt::NoBrush);
        QFont font = painter.font();
        font.setBold(true);
        font.setPixelSize(5.25f * yScale);
        QFont font0 = font;
        QHashIterator<QString, Key> k(keyMap);
        uint i = -1;
        while(k.hasNext()){
            k.next();
            i++;
            const Key& key = k.value();
            float x = key.x + 6.f - key.width / 2.f + 1.f;
            float y = key.y + 6.f - key.height / 2.f;
            float w = key.width - 2.f;
            float h = key.height;
            // Print the key's friendly name (with some exceptions)
            QString keyName = KbBind::globalRemap(key.name);
            QString name = key.friendlyName(false);
            name = name.split(" ").last();
            struct {
                const char* keyName, *displayName;
            } names[] = {
                {"light", "☼"}, {"lock", "☒"}, {"mute", "◖⊘"}, {"volup", keyMap.model() == KeyMap::K65 ? "◖))" : "▲"}, {"voldn", keyMap.model() == KeyMap::K65 ? "◖)" : "▼"},
                {"prtscn",  "PrtScn\nSysRq"}, {"scroll", "Scroll\nLock"}, {"pause", "Pause\nBreak"}, {"stop", "▪"}, {"prev", "|◂◂"}, {"play", "▸||"}, {"next", "▸▸|"},
                {"pgup", "Page\nUp"}, {"pgdn", "Page\nDown"}, {"numlock", "Num\nLock"},
                {"caps", "Caps"}, {"lshift", "Shift"}, {"rshift", "Shift"},
#ifdef Q_OS_MACX
                {"lctrl", "⌃"}, {"rctrl", "⌃"}, {"lwin", "⌘"}, {"rwin", "⌘"}, {"lalt", "⌥"}, {"ralt", "⌥"},
#else
                {"lctrl", "Ctrl"}, {"rctrl", "Ctrl"}, {"lwin", "❖"}, {"rwin", "❖"}, {"lalt", "Alt"}, {"ralt", "Alt"},
#endif
                {"rmenu", "▤"}, {"up", "▲"}, {"left", "◀"}, {"down", "▼"}, {"right", "▶"},
                {"mousel", ""}, {"mouser", ""}, {"mousem", "-"}, {"dpiup", "▲"}, {"dpidn", "▼"}, {"dpi", "◉"}, {"mouses1", "▲"}, {"mouses2", "▼"}, {"sniper", "☀"}
            };
            for(uint k = 0; k < sizeof(names) / sizeof(names[0]); k++){
                if(keyName == names[k].keyName){
                    name = names[k].displayName;
                    break;
                }
            }
            if(keyName == "mr" || keyName == "m1" || keyName == "m2" || keyName == "m3" || keyName == "up" || keyName == "down" || keyName == "left" || keyName == "right")
                // Use a smaller size for MR, M1 - M3, and arrow keys
                font.setPixelSize(font.pixelSize() * 0.75);
            else if(keyName == "end")
                // Use a smaller size for "End" to match everything else in that area
                font.setPixelSize(font.pixelSize() * 0.65);
            else if(keyName == "light"
#ifndef Q_OS_MACX
                    || keyName == "lwin" || keyName == "rwin"
#endif
                    )
                // Use a larger font size for Super (Linux only) and Brightness to compensate for the unicode symbols looking smaller
                font.setPixelSize(font.pixelSize() * 1.3);
            // Determine the appropriate size to draw the text at
            decPainter.setFont(font);
            QRectF rect(x * xScale, y * yScale - 1, w * xScale, h * yScale);
            int flags = Qt::AlignHCenter | Qt::AlignVCenter | Qt::TextWordWrap;
            QRectF bounds = decPainter.boundingRect(rect, flags, name);
            while((bounds.height() >= rect.height() - 8. || bounds.width() >= rect.width() - 2.) && font.pixelSize() >= 5){
                // Scale font size down until it fits inside the key
                font.setPixelSize(font.pixelSize() - 2);
                decPainter.setFont(font);
                bounds = decPainter.boundingRect(rect, flags, name);
            }
            // Pick color based on key function
            QString bind = _bindMap.value(key.name);
            QString def = KbBind::defaultAction(key.name);
            if(bind.isEmpty())
                // Unbound - red
                decPainter.setPen(QColor(255, 136, 136));
            else if(KbBind::isProgram(bind))
                // Custom program - orange
                decPainter.setPen(QColor(255, 224, 192));
            else if(KbBind::isSpecial(bind) && (bind == def || !KbBind::isSpecial(def)))
                // Special function - blue (only if not mapped to a different function - if a special function is remapped, color it yellow)
                decPainter.setPen(QColor(128, 224, 255));
            else if(KbBind::isMedia(bind) && (bind == def || !KbBind::isMedia(def)))
                // Media key - green
                decPainter.setPen(QColor(160, 255, 168));
            else if(bind == def)
                // Standard key - white
                decPainter.setPen(QColor(255, 255, 255));
            else
                // Remapped key - yellow
                decPainter.setPen(QColor(255, 248, 128));
            decPainter.drawText(rect, flags, name);
            font = font0;
        }
    }
    // Create drop shadow effects
    QGraphicsDropShadowEffect* bgEffect = new QGraphicsDropShadowEffect;  // Have to use "new", creating these on the stack causes a crash...
    bgEffect->setBlurRadius(2.);
    bgEffect->setColor(QColor(0, 0, 0, 32));
    bgEffect->setOffset(0, 1);
    QGraphicsDropShadowEffect* decEffect = new QGraphicsDropShadowEffect;
    decEffect->setBlurRadius(4.);
    decEffect->setColor(QColor(0, 0, 0, 104));
    decEffect->setOffset(0, 1);
    // Apply them to the pixmaps
    QGraphicsPixmapItem* bgItem = new QGraphicsPixmapItem(keyBG);
    bgItem->setGraphicsEffect(bgEffect);
    QGraphicsPixmapItem* decItem = new QGraphicsPixmapItem(decoration);
    decItem->setGraphicsEffect(decEffect);
    // Render everything
    QGraphicsScene* scene = new QGraphicsScene;
    scene->addItem(bgItem);
    scene->addItem(decItem);
    // It has to be rendered onto yet another pixmap or else DPI scaling will look terrible...
    QPixmap final(wWidth * ratio, wHeight * ratio);
    final.fill(QColor(0, 0, 0, 0));