示例#1
0
void QTessellatorPrivate::removeEdges()
{
    int cv = currentVertex;
    while (cv < vertices.nPoints) {
        const Vertex *v = vertices.sorted[cv];
        if (v->y > y)
            break;
        if (v->flags & LineBeforeEnds) {
            QDEBUG() << "    removing edge" << vertices.prevPos(v);
            int pos = scanline.findEdge(vertices.prevPos(v));
            if (pos == -1)
                continue;
            scanline.edges[pos]->mark = true;
            if (pos > 0)
                scanline.edges[pos - 1]->intersect_right = true;
            if (pos < scanline.size - 1)
                scanline.edges[pos + 1]->intersect_left = true;
            scanline.removeAt(pos);
        }
        if (v->flags & LineAfterEnds) {
            QDEBUG() << "    removing edge" << vertices.position(v);
            int pos = scanline.findEdge(vertices.position(v));
            if (pos == -1)
                continue;
            scanline.edges[pos]->mark = true;
            if (pos > 0)
                scanline.edges[pos - 1]->intersect_right = true;
            if (pos < scanline.size - 1)
                scanline.edges[pos + 1]->intersect_left = true;
            scanline.removeAt(pos);
        }
        ++cv;
    }
}
示例#2
0
文件: qemu-test.c 项目: stweil/qemu
static int verify (uint8_t * truth_buf, uint8_t * test_buf,
                   int64_t sector_num, int nb_sectors)
{
    int i;
    for (i = 0; i < nb_sectors; i++) {
        int64_t offset = i * 512;
        if (memcmp (&truth_buf[offset], &test_buf[offset], 512) != 0) {
            int j;
            printf ("Sector %" PRId64 " differs\n", sector_num + i);
            QDEBUG ("Sector %" PRId64 " differs\n", sector_num + i);
            for (j = 0; j < 512; j++) {
                if (truth_buf[offset + j] == test_buf[offset + j]) {
                    QDEBUG ("%02d: %02X  %02X\n", j, truth_buf[offset + j],
                            test_buf[offset + j]);
                } else {
                    QDEBUG ("%02d: %02X  %02X   ***\n", j,
                            truth_buf[offset + j], test_buf[offset + j]);
                }
            }

            fprintf (stderr, "Pause process %d for debugging...\n", getpid ());
            fgetc (stdin);

            return -1;
        }
    }

    return 0;
}
示例#3
0
/**
 * @brief No incoming parameters. Get data from RCHAN. Creating the stream file. If BASS_StreamCreateFile is failure colled BASS_Free().
 * @param No params
 */
void Widget::stopRecording()
{
    if (BASS_ChannelGetData(rchan, this->fft, BASS_DATA_FFT1024 | BASS_DATA_FFT_COMPLEX) == -1) {
        QDEBUG("Cannot get recbuf from rchan");
        QDEBUG(BASS_ErrorGetCode());
    }

    BASS_ChannelStop(rchan);
    rchan=0;
    ui->pushButton->setText(tr("Record"));
    // complete the WAVE header
    *(DWORD*)(recbuf+4)=reclen-8;
    *(DWORD*)(recbuf+40)=reclen-44;
    // enable "save" button
    ui->pushButton_3->setEnabled(true);
    // setup output device (using default device)
    if (!BASS_Init(-1,44100,0,NULL,NULL)) {
        QDEBUG(BASS_ErrorGetCode());
        QDEBUG("Can't initialize output device");
        return;
    }
    // create a stream from the recording
    if (chan=BASS_StreamCreateFile(TRUE,recbuf,0,reclen,BASS_SAMPLE_FLOAT)) {
        //ui->pushButton_2->setEnabled(true); // enable "play" button
    }
    else
        BASS_Free();
    ui->pushButton->setEnabled(true);
}
示例#4
0
void QTessellatorPrivate::addIntersections()
{
    if (scanline.size) {
        QDEBUG() << "INTERSECTIONS";
        // check marked edges for intersections
#ifdef DEBUG
        for (int i = 0; i < scanline.size; ++i) {
            Edge *e = scanline.edges[i];
            QDEBUG() << "    " << i << e->edge << "isect=(" << e->intersect_left << e->intersect_right
                     << ')';
        }
#endif

        for (int i = 0; i < scanline.size - 1; ++i) {
            Edge *e1 = scanline.edges[i];
            Edge *e2 = scanline.edges[i + 1];
            // check for intersection
            if (e1->intersect_right || e2->intersect_left)
                addIntersection(e1, e2);
        }
    }
#if 0
    if (intersections.constBegin().key().y == y) {
        QDEBUG() << "----------------> intersection on same line";
        scanline.clearMarks();
        scanline.processIntersections(y, &intersections);
        goto redo;
    }
#endif
}
示例#5
0
void Widget::on_pushButton_2_clicked()
{
    QDEBUG(freq.size() << "freq size");
    for (std::int32_t i = 0; i < freq.size(); i++) {
        one.push_back(freq[i]);
    }
    QDEBUG(one.size() << "one size");
}
示例#6
0
void QTessellatorPrivate::addEdges()
{
    while (currentVertex < vertices.nPoints) {
        const Vertex *v = vertices.sorted[currentVertex];
        if (v->y > y)
            break;
        if (v->flags & LineBeforeStarts) {
            // add new edge
            int start = vertices.prevPos(v);
            Edge e(vertices, start);
            int pos = scanline.findEdgePosition(e);
            QDEBUG() << "    adding edge" << start << "at position" << pos;
            scanline.insert(pos, e);
            if (!mark_clever || !(v->flags & LineAfterEnds)) {
                if (pos > 0)
                    scanline.edges[pos - 1]->mark = true;
                if (pos < scanline.size - 1)
                    scanline.edges[pos + 1]->mark = true;
            }
        }
        if (v->flags & LineAfterStarts) {
            Edge e(vertices, vertices.position(v));
            int pos = scanline.findEdgePosition(e);
            QDEBUG() << "    adding edge" << vertices.position(v) << "at position" << pos;
            scanline.insert(pos, e);
            if (!mark_clever || !(v->flags & LineBeforeEnds)) {
                if (pos > 0)
                    scanline.edges[pos - 1]->mark = true;
                if (pos < scanline.size - 1)
                    scanline.edges[pos + 1]->mark = true;
            }
        }
        if (v->flags & LineAfterHorizontal) {
            int pos1 = scanline.findEdgePosition(v->x, v->y);
            const Vertex *next = vertices.next(v);
            Q_ASSERT(v->y == next->y);
            int pos2 = scanline.findEdgePosition(next->x, next->y);
            if (pos2 < pos1)
                qSwap(pos1, pos2);
            if (pos1 > 0)
                --pos1;
            if (pos2 == scanline.size)
                --pos2;
            //QDEBUG() << "marking horizontal edge from " << pos1 << "to" << pos2;
            scanline.markEdges(pos1, pos2);
        }
        ++currentVertex;
    }
}
示例#7
0
Logbook::~Logbook() {
   QDEBUG("Logbook::~Logbook()");
   deleteExpiredHistories();
   m_query.clear();
   m_db.close();
   if ( m_dbHelper ) delete m_dbHelper;
}
void PersistentConnection::statusReceiver(QString message)
{
    QDEBUGVAR(message);
    ui->topLabel->setText(message);

    if(message.startsWith("Connected")) {
        wasConnected = true;
    }

    if(message.toLower().startsWith("not connected")) {

        QDEBUG() << "Setting style sheet";
        ui->trafficViewEdit->setStyleSheet("QTextEdit { background-color: #EEEEEE }");
        ui->asciiSendButton->setEnabled(false);
        ui->asciiLineEdit->setEnabled(false);
        ui->packetComboBox->setEnabled(false);
        ui->appendCRcheck->setEnabled(false);
        ui->searchEdit->setEnabled(false);
        ui->packetComboBox->setEnabled(false);
        ui->LoadButton->setEnabled(false);

        stopTimer = true;
    }


}
示例#9
0
void Widget::on_pushButton_7_clicked()
{
    for (std::int32_t i = 0; i < freq.size(); i++) {
        four.push_back(freq[i]);
    }
    QDEBUG(two.size() << "two size");
}
示例#10
0
/**
 * @brief Starts the record and set default confuration for audio file. If start record is failure free RECBUF is comming.
 */
void Widget::startRecording() {
    WAVEFORMATEX *wf;
    if (recbuf) { // free old recording;
        BASS_StreamFree(chan);
        chan=0;
        free(recbuf);
        recbuf=NULL;
        //ui->pushButton_2->setEnabled(false);
        ui->pushButton_3->setEnabled(false);
        // close output device before recording incase of half-duplex device;
        BASS_Free();
    }
    // allocate initial buffer and make space for WAVE header;
    recbuf=(char*)malloc(BUFSTEP);
    reclen=44;
    // fill the WAVE header;
    memcpy(recbuf,"RIFF\0\0\0\0WAVEfmt \20\0\0\0",20);
    memcpy(recbuf+36,"data\0\0\0\0",8);
    wf=(WAVEFORMATEX*)(recbuf+20);
    wf->wFormatTag=1;
    wf->nChannels=2;
    wf->wBitsPerSample=16;
    wf->nSamplesPerSec=44100;
    wf->nBlockAlign=wf->nChannels*wf->wBitsPerSample/8;
    wf->nAvgBytesPerSec=wf->nSamplesPerSec*wf->nBlockAlign;
    // start recording @ 44100hz 32-bit stereo;
    if (!(rchan=BASS_RecordStart(44100,2,0,&RecordingCallback,0))) {
        QDEBUG(BASS_ErrorGetCode());
        Error("Couldn't start recording");
        free(recbuf);
        recbuf=0;
        return;
    }
    ui->pushButton->setEnabled(false);
}
void PersistentConnection::on_buttonBox_rejected()
{

    QDEBUG() << "Stopping timer";
    refreshTimer.stop();

}
示例#12
0
void GameLogger::networkError(QString errorStr)
{
    QDEBUG("[GameLogger::networkError()] called with error %s", qPrintable(errorStr));

    // Propagate error to UI
    emit error(errorStr);
}
示例#13
0
bool QTessellatorPrivate::Edge::intersect(const Edge &other, Q27Dot5 *y, bool *det_positive) const
{
    qint64 a1 = v1->y - v0->y;
    qint64 b1 = v0->x - v1->x;

    qint64 a2 = other.v1->y - other.v0->y;
    qint64 b2 = other.v0->x - other.v1->x;

    qint64 det = a1 * b2 - a2 * b1;
    if (det == 0)
        return false;

    qint64 c1 = qint64(v1->x) * v0->y - qint64(v0->x) * v1->y;

    qint64 r3 = a1 * other.v0->x + b1 * other.v0->y + c1;
    qint64 r4 = a1 * other.v1->x + b1 * other.v1->y + c1;

    // Check signs of r3 and r4.  If both point 3 and point 4 lie on
    // same side of line 1, the line segments do not intersect.
    QDEBUG() << "        " << r3 << r4;
    if (r3 != 0 && r4 != 0 && sameSign( r3, r4 ))
        return false;

    qint64 c2 = qint64(other.v1->x) * other.v0->y - qint64(other.v0->x) * other.v1->y;

    qint64 r1 = a2 * v0->x + b2 * v0->y + c2;
    qint64 r2 = a2 * v1->x + b2 * v1->y + c2;

    // Check signs of r1 and r2.  If both point 1 and point 2 lie
    // on same side of second line segment, the line segments do not intersect.
    QDEBUG() << "        " << r1 << r2;
    if (r1 != 0 && r2 != 0 && sameSign( r1, r2 ))
        return false;

    // The det/2 is to get rounding instead of truncating.  It
    // is added or subtracted to the numerator, depending upon the
    // sign of the numerator.
    qint64 offset = det < 0 ? -det : det;
    offset >>= 1;

    qint64 num = a2 * c1 - a1 * c2;
    *y = ( num < 0 ? num - offset : num + offset ) / det;

    *det_positive = (det > 0);

    return true;
}
示例#14
0
void Logbook::deleteBookmarks() {
   QDEBUG("Logbook::deleteBookmarks()");
   if ( !m_query.exec(DELETE_BOOKMARK_ALL_SQL) ) {
      QWARNING_EXP("Logbook::deleteBookmarks()", "Query exec error: " << m_query.lastError().text());
   } else {
      emit bookmarksChanged();
   }
}
示例#15
0
void Logbook::deleteHistories() {
   QDEBUG("Logbook::deleteHistories()");
   if ( !m_query.exec(DELETE_HISTORY_ALL_SQL) ) {
      QWARNING_EXP("Logbook::deleteHistories()", "Query exec error: " << m_query.lastError().text());
   } else {
      emit historiesChanged();
   }
}
示例#16
0
void MainWindow::onLogoutCompleted()
{
	if(isShuttingDown)
	{
		QDEBUG("MainWindow::onLogoutCompleted() - shutting down, forcing quit");
		forceQuit();
	}
}
示例#17
0
void SendPacketButton::sendClicked()
{

    QDEBUG() << " Emit clicked: " << name;

    emit sendPacket(name);

}
 foreach(loopPkt, trafficList) {
     QDEBUG() << "Packet Loop:" << count++ << loopPkt.asciiString();
     if(loopPkt.fromIP.toLower() == "you") {
         out << "<p style='color:blue'>";
     } else {
         out << "<p>";
     }
     out << loopPkt.asciiString().toHtmlEscaped();
     out << "</p>";
 }
示例#19
0
void Logbook::deleteExpiredHistories() {
   QDEBUG("Logbook::deleteExpiredHistories()");
   m_query.prepare(DELETE_EXPIRED_HISTORY_SQL);
   m_query.addBindValue( QString("-%1 days").arg( m_settings.value(SETTINGS_KEY_HISTORY_LENGTH_DAYS).toString() ) );
   if ( !m_query.exec() ) {
      QWARNING_EXP("Logbook::deleteExpiredHistories()", "Query exec error: " << m_query.lastError().text());
   } else {
      QDEBUG_EXP("Logbook::deleteExpiredHistories()", "Expired Histories deleted: " << m_query.numRowsAffected());
   }
}
示例#20
0
void GameLogger::querySettings() {
    QDEBUG("[GameLogger::querySettings()] called");
    networkHandler->querySettings();
    waitedForSettings = 0;

    // The first timeout in timer was to get the settings
    disconnect(updateTimer, SIGNAL(timeout()), this, SLOT(querySettings()));
    updateTimer->setInterval(1000-QTime::currentTime().msec()); // Baseline 1 second interval/resolution
    metronome.start();
    connect(updateTimer, SIGNAL(timeout()), this, SLOT(update()));
}
void PersistentConnection::init() {

    QDEBUG();
    setWindowTitle("TCP://"+sendPacket.toIP + ":" + QString::number(sendPacket.port));
    QDEBUG();

    thread = new TCPThread(sendPacket, this);

    QDEBUG() << ": thread Connection attempt " <<
             connect ( this , SIGNAL ( persistentPacketSend(Packet) ) , thread, SLOT ( sendPersistant(Packet) ) )
             << connect ( this , SIGNAL ( closeConnection() ) , thread, SLOT ( closeConnection() ) )
             << connect ( thread , SIGNAL ( connectStatus(QString) ) , this, SLOT ( statusReceiver(QString) ) )
             << connect ( thread , SIGNAL ( packetSent(Packet)), this, SLOT(packetSentSlot(Packet)));

    QApplication::processEvents();

    thread->start();


    QApplication::processEvents();

}
void DraggableLabel::dragPixmap()
{
	const QPixmap *currentPixmap = pixmap();

	if (currentPixmap == NULL)
		return;
	
	// Make temp file
	QTemporaryFile *tempFile = new QTemporaryFile(AppTools::addPathSeparator(QDir::tempPath()) + DRAG_LABEL_FILENAME_TEMPLATE);
	tempFile->setAutoRemove(false);

	if (!tempFile->open())
	{
		delete tempFile;
		return;
	}
	
	// Arrange data
	QMimeData *data = new QMimeData;
	data->setImageData(currentPixmap->toImage());

	// Save pixmap
	QString tempFileName = tempFile->fileName();
	currentPixmap->save(tempFileName);
	delete tempFile;

	QDEBUG("Dragged file saved to " << tempFileName);

	// Keep its name
	QList <QUrl> urls;
	urls.append(QUrl::fromLocalFile(tempFileName));
	data->setUrls(urls);

	QPixmap preview = currentPixmap->scaled(DRAG_LABEL_PREVIEW_WIDTH, DRAG_LABEL_PREVIEW_HEIGHT, Qt::KeepAspectRatio);

	QPixmap preview2(preview.width(), preview.height());
	preview2.fill(QColor(180, 180, 180));

	preview.setAlphaChannel(preview2);

	// Go drag
	QDrag *drag = new QDrag(this);

	drag->setPixmap(preview);
    drag->setMimeData(data);
	drag->setHotSpot(QPoint(preview.width() / 2, preview.height() / 2));

    // Let's go!
	drag->exec(Qt::MoveAction);
}
PersistentConnection::PersistentConnection(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::PersistentConnection)
{
    ui->setupUi(this);

    setWindowFlags(this->windowFlags() & ~Qt::WindowContextHelpButtonHint);

    suppressSlot = true;

    QDEBUG();
    sendPacket.clear();
    QDEBUG() << ": refreshTimer Connection attempt " <<
             connect ( &refreshTimer , SIGNAL ( timeout() ) , this, SLOT ( refreshTimerTimeout (  ) ) )
             << connect ( this , SIGNAL ( rejected() ) , this, SLOT ( aboutToClose (  ) ) )
             << connect ( this , SIGNAL ( accepted() ) , this, SLOT ( aboutToClose (  ) ) )
             << connect ( this , SIGNAL ( dialogIsClosing() ) , this, SLOT ( aboutToClose (  ) ) );
    QDEBUG() << "Setup timer";
    refreshTimer.setInterval(200);
    refreshTimer.start();
    trafficList.clear();
    startTime = QDateTime::currentDateTime();
    wasConnected = false;
    stopTimer = false;

    ui->searchEdit->setText("");

    loadComboBox();

    useraw = true;

    ui->asciiLineEdit->setFocus();
    suppressSlot = false;


}
FtuFirstTimeUse::FtuFirstTimeUse(QObject* aParent) : 
    QObject(aParent),
    mRuntime(NULL)
{  
    QDEBUG("FTU::FtuFirstTimeUse::FtuFirstTimeUse");
    
    registerServicePlugins();

    QServiceManager manager;
    QServiceFilter filter(ftuRuntimeUri);
    QList<QServiceInterfaceDescriptor> interfaces = manager.findInterfaces(
                                                                    filter);
    
    QDEBUG("ftu: found " << interfaces.count() 
             << " instances of runtime";)
    
    if(interfaces.count() > 0){
void AuthorizationRequest::onGetAuthorizationResponseResult(QVariant state, Fault fault, AuthorizationResultCode::AuthorizationResultCodeEnum result)
{
	Q_UNUSED(state)
	
	QDEBUG("AuthorizationReseponse result come");

	if (fault.isNull() && (result == AuthorizationResultCode::Ok || AuthorizationResultCode::AlreadyAuthorized) )
	{
		if (INFOMANAGER->isUserOnline())
		{
			if (approve)
				INFOMANAGER->authorizeContact(contactId);
			else
				INFOMANAGER->removeFromContactList(contactId);
		}
	}

	if (active)
		emit authorizationResponseCompleted(fault, result, approve);

	deleteLater();
}
示例#26
0
void MainWindow::shutDown()
{
	bool isOnline = INFOMANAGER->isUserOnline();

	if (isShuttingDown || !logout(true))
		return;

	if (isOnline)
	{
		// wait a little for logoutCompleted
		QTimer::singleShot(2000, this, SLOT(forceQuit()));
	}
	else
	{
		QDEBUG("MainWindow::shutDown() - not online, quit immediately");
		forceQuit();
	}
    
#ifdef Q_WS_MAC
    macCleanup();
#endif
}
示例#27
0
/**
 * @brief It is a one-parameter family of window functions used for digital signal processing.
 */
void Widget::kaiser_window() {
    std::float_t iI0b = 0, h = 0;
    std::int32_t k = 0;
    std::float_t b = 1.8;
    std::float_t L = 0.54;
    std::float_t w = 0.0;
    try {
        k = -512;
        //QDEBUG(k << "k");
        iI0b =  1.0 / this->I0(b);
        //QDEBUG(iI0b << "iI0b");

        for (std::int32_t i = 1; i < freq.size() - 1; i++) {
            k++;
            h = std::abs(this->I0(b*std::sqrt(1 - std::pow(2.0*k/(1023),2)))) * iI0b;
            //QDEBUG(h << "h");
            this->freq[i] *= h;

            //this->freq[256 - 1 - i] *= h;
            QDEBUG(freq[i]);
        }



        for (std::int32_t i = 1; i <freq.size() - 1; i++) {
            w = L - (1 - L)*std::cos(2*M_PI*(i+1)/(freq.size()-1));
            w /= 4;
            freq.at(i) *= w;
        }


        emit this->plotKaiserWindow();
    }
    catch (std::exception &ex) {
        std::cerr << ex.what();
        std::cerr << "Kaiser windwow";
    }
}
示例#28
0
static uint32_t allocate_chunk (BlockDriverState * bs)
{
    BDRVFvdState *s = bs->opaque;

    /* Check if there is sufficient storage space. */
    if (s->used_storage + s->chunk_size > s->data_storage) {
        if (s->add_storage_cmd) {
            if (system (s->add_storage_cmd)) {
                fprintf (stderr, "Error in executing %s\n", s->add_storage_cmd);
            }
        } else {
            /* If the image is stored on a file system, the image file size
             * can be increased by bdrv_truncate. */
            int64_t new_size = (s->data_offset + s->used_storage +
                                s->storage_grow_unit) * 512;
            bdrv_truncate (s->fvd_data, new_size);
        }

        /* Check how much storage is available now. */
        int64_t size = bdrv_getlength (s->fvd_data);
        if (size < 0) {
            fprintf (stderr, "Error in bdrv_getlength(%s)\n", bs->filename);
            return EMPTY_TABLE;
        }
        s->data_storage = size / 512 - s->data_offset;
        if (s->used_storage + s->chunk_size > s->data_storage) {
            fprintf (stderr, "Could not allocate more storage space.\n");
            return EMPTY_TABLE;
        }

        QDEBUG ("Increased storage to %" PRId64 " bytes.\n", size);
    }

    uint32_t allocated_chunk_id = s->used_storage / s->chunk_size;
    s->used_storage += s->chunk_size;
    return allocated_chunk_id;
}
示例#29
0
void QTessellatorPrivate::processIntersections()
{
    QDEBUG() << "PROCESS INTERSECTIONS";
    // process intersections
    while (!intersections.isEmpty()) {
        Intersections::iterator it = intersections.begin();
        if (it.key().y != y)
            break;

        // swap edges
        QDEBUG() << "    swapping intersecting edges ";
        int min = scanline.size;
        int max = 0;
        Q27Dot5 xmin = INT_MAX;
        Q27Dot5 xmax = INT_MIN;
        int num = 0;
        while (1) {
            const Intersection &i = it.key();
            int next = it->next;

            int edgePos = scanline.findEdge(i.edge);
            if (edgePos >= 0) {
                ++num;
                min = qMin(edgePos, min);
                max = qMax(edgePos, max);
                Edge *edge = scanline.edges[edgePos];
                xmin = qMin(xmin, edge->positionAt(y));
                xmax = qMax(xmax, edge->positionAt(y));
            }
            Intersection key;
            key.y = y;
            key.edge = next;
            it = intersections.find(key);
            intersections.remove(i);
            if (it == intersections.end())
                break;
        }
        if (num < 2)
            continue;

        Q_ASSERT(min != max);
        QDEBUG() << "sorting between" << min << "and" << max << "xpos=" << xmin << xmax;
        while (min > 0 && scanline.edges[min - 1]->positionAt(y) >= xmin) {
            QDEBUG() << "    adding edge on left";
            --min;
        }
        while (max + 1 < scanline.size && scanline.edges[max + 1]->positionAt(y) <=  xmax) {
            QDEBUG() << "    adding edge on right";
            ++max;
        }

        qSort(scanline.edges + min, scanline.edges + max + 1, EdgeSorter(y));
#ifdef DEBUG
        for (int i = min; i <= max; ++i)
            QDEBUG() << "        " << scanline.edges[i]->edge << "at pos" << i;
#endif
        for (int i = min; i <= max; ++i) {
            Edge *edge = scanline.edges[i];
            edge->intersect_left = true;
            edge->intersect_right = true;
            edge->mark = true;
        }
    }
}
示例#30
0
QRectF QTessellatorPrivate::collectAndSortVertices(const QPointF *points, int *maxActiveEdges)
{
    *maxActiveEdges = 0;
    Vertex *v = vertices.storage;
    Vertex **vv = vertices.sorted;

    qreal xmin(points[0].x());
    qreal xmax(points[0].x());
    qreal ymin(points[0].y());
    qreal ymax(points[0].y());

    // collect vertex data
    Q27Dot5 y_prev = FloatToQ27Dot5(points[vertices.nPoints-1].y());
    Q27Dot5 x_next = FloatToQ27Dot5(points[0].x());
    Q27Dot5 y_next = FloatToQ27Dot5(points[0].y());
    int j = 0;
    int i = 0;
    while (i < vertices.nPoints) {
        Q27Dot5 y_curr = y_next;

        *vv = v;

        v->x = x_next;
        v->y = y_next;
        v->flags = 0;

    next_point:

        xmin = qMin(xmin, points[i+1].x());
        xmax = qMax(xmax, points[i+1].x());
        ymin = qMin(ymin, points[i+1].y());
        ymax = qMax(ymax, points[i+1].y());

        y_next = FloatToQ27Dot5(points[i+1].y());
        x_next = FloatToQ27Dot5(points[i+1].x());

        // skip vertices on top of each other
        if (v->x == x_next && v->y == y_next) {
            ++i;
            if (i < vertices.nPoints)
                goto next_point;
            Vertex *v0 = vertices.storage;
            v0->flags &= ~(LineBeforeStarts|LineBeforeEnds|LineBeforeHorizontal);
            if (y_prev < y_curr)
                v0->flags |= LineBeforeEnds;
            else if (y_prev > y_curr)
                v0->flags |= LineBeforeStarts;
            else
                v0->flags |= LineBeforeHorizontal;
            if ((v0->flags & (LineBeforeStarts|LineAfterStarts))
                && !(v0->flags & (LineAfterEnds|LineBeforeEnds)))
                *maxActiveEdges += 2;
            break;
        }

        if (y_prev < y_curr)
            v->flags |= LineBeforeEnds;
        else if (y_prev > y_curr)
            v->flags |= LineBeforeStarts;
        else
            v->flags |= LineBeforeHorizontal;


        if (y_curr < y_next)
            v->flags |= LineAfterStarts;
        else if (y_curr > y_next)
            v->flags |= LineAfterEnds;
        else
            v->flags |= LineAfterHorizontal;
        // ### could probably get better limit by looping over sorted list and counting down on ending edges
        if ((v->flags & (LineBeforeStarts|LineAfterStarts))
            && !(v->flags & (LineAfterEnds|LineBeforeEnds)))
            *maxActiveEdges += 2;
        y_prev = y_curr;
        ++v;
        ++vv;
        ++j;
        ++i;
    }
    vertices.nPoints = j;

    QDEBUG() << "maxActiveEdges=" << *maxActiveEdges;
    vv = vertices.sorted;
    qSort(vv, vv + vertices.nPoints, compareVertex);

    return QRectF(xmin, ymin, xmax-xmin, ymax-ymin);
}