예제 #1
0
static void stringToWCharArray(QVarLengthArray<wchar_t> &ret, const QString &string)
{
    ret.resize(string.length());
    int len = string.toWCharArray(ret.data());
    ret.resize(len+1);
    ret[len] = 0;
}
예제 #2
0
파일: FX.cpp 프로젝트: luebking/virtuality
static float ratioFor(int step, int maxSteps) {
#if 1
    static QVarLengthArray<float> table;
    const int n = maxSteps + 1;
    if (table.size() != n) {
        table.resize(n);
        const float accel = 0.5f;
        const float factor = pow(0.5f, accel);
        for (int i = (n+1)/2; i < n; ++i) {
            float ratio = i/float(maxSteps);
            if (ratio == 0.5f)
                table[i] = 0.f;
            else
                table[i] = (pow(ratio - 0.5f, accel) + factor) / (2.0f*factor);
        }
        for (int i = 0; i <= n/2; ++i) {
            table[i] = 1.0f - table[maxSteps-i];
        }
    }

    return table.at(step);
#else
    return step/float(MAX_STEPS);
#endif
}
예제 #3
0
QByteArray QBBSystemLocaleData::readPpsValue(const char *ppsObject, int ppsFd)
{
    QByteArray result;
    if (!ppsObject || ppsFd == -1)
        return result;


    // PPS objects are of unknown size, but must be read all at once.
    // Relying on the file size may not be a good idea since the size may change before reading.
    // Let's try with an initial size (512), and if the buffer is too small try with bigger one,
    // until we succeed or until other non buffer-size-related error occurs.
    // Using QVarLengthArray means the first try (of size == 512) uses a buffer on the stack - no allocation necessary.
     // Hopefully that covers most use cases.
    int bytes;
    QVarLengthArray<char, 512> buffer;
    for (;;) {
        errno = 0;
        bytes = qt_safe_read(ppsFd, buffer.data(), buffer.capacity() - 1);
        const bool bufferIsTooSmall = (bytes == -1 && errno == EMSGSIZE && buffer.capacity() < MAX_PPS_SIZE);
        if (!bufferIsTooSmall)
            break;

        buffer.resize(qMin(buffer.capacity()*2, MAX_PPS_SIZE));
    }

    // This method is called in the ctor(), so do not use qWarning to log warnings
    // if qt_safe_read fails to read the pps file
    // since the user code may install a message handler that invokes QLocale API again
    // (i.e QDate, QDateTime, ...) which will cause a infinite loop.
    if (bytes == -1) {
        fprintf(stderr, "Failed to read pps object:%s, errno=%d\n", ppsObject, errno);
        return result;
    }
    // ensure data is null terminated
    buffer[bytes] = '\0';

    pps_decoder_t ppsDecoder;
    pps_decoder_initialize(&ppsDecoder, 0);
    if (pps_decoder_parse_pps_str(&ppsDecoder, buffer.data()) == PPS_DECODER_OK) {
        pps_decoder_push(&ppsDecoder, 0);
        const char *ppsBuff;
        if (pps_decoder_get_string(&ppsDecoder, ppsObject, &ppsBuff) == PPS_DECODER_OK) {
            result = ppsBuff;
        } else {
            int val;
            if (pps_decoder_get_int(&ppsDecoder, ppsObject, &val) == PPS_DECODER_OK)
                result = QByteArray::number(val);
        }
    }

    pps_decoder_cleanup(&ppsDecoder);

    return result;
}
예제 #4
0
static inline QString qSystemDirectory()
{
    QVarLengthArray<wchar_t, MAX_PATH> fullPath;

    UINT retLen = ::GetSystemDirectory(fullPath.data(), MAX_PATH);
    if (retLen > MAX_PATH) {
        fullPath.resize(retLen);
        retLen = ::GetSystemDirectory(fullPath.data(), retLen);
    }
    // in some rare cases retLen might be 0
    return QString::fromWCharArray(fullPath.constData(), int(retLen));
}
예제 #5
0
NATRON_NAMESPACE_ANONYMOUS_ENTER

#if defined(Q_OS_WIN)
static QString
qSystemDirectory()
{
    QVarLengthArray<wchar_t, MAX_PATH> fullPath;
    UINT retLen = ::GetSystemDirectoryW(fullPath.data(), MAX_PATH);
    if (retLen > MAX_PATH) {
        fullPath.resize(retLen);
        retLen = ::GetSystemDirectoryW(fullPath.data(), retLen);
    }
    if (!fullPath.constData()) {
        return QString();
    }
    std::wstring ws(fullPath.constData(), retLen);
    return QString::fromStdWString(ws);
}
예제 #6
0
void QTriangulatingStroker::arcPoints(float cx, float cy, float fromX, float fromY, float toX, float toY, QVarLengthArray<float> &points)
{
    float dx1 = fromX - cx;
    float dy1 = fromY - cy;
    float dx2 = toX - cx;
    float dy2 = toY - cy;

    // while more than 180 degrees left:
    while (dx1 * dy2 - dx2 * dy1 < 0) {
        float tmpx = dx1 * m_cos_theta - dy1 * m_sin_theta;
        float tmpy = dx1 * m_sin_theta + dy1 * m_cos_theta;
        dx1 = tmpx;
        dy1 = tmpy;
        points.append(cx + dx1);
        points.append(cy + dy1);
    }

    // while more than 90 degrees left:
    while (dx1 * dx2 + dy1 * dy2 < 0) {
        float tmpx = dx1 * m_cos_theta - dy1 * m_sin_theta;
        float tmpy = dx1 * m_sin_theta + dy1 * m_cos_theta;
        dx1 = tmpx;
        dy1 = tmpy;
        points.append(cx + dx1);
        points.append(cy + dy1);
    }

    // while more than 0 degrees left:
    while (dx1 * dy2 - dx2 * dy1 > 0) {
        float tmpx = dx1 * m_cos_theta - dy1 * m_sin_theta;
        float tmpy = dx1 * m_sin_theta + dy1 * m_cos_theta;
        dx1 = tmpx;
        dy1 = tmpy;
        points.append(cx + dx1);
        points.append(cy + dy1);
    }

    // remove last point which was rotated beyond [toX, toY].
    if (!points.isEmpty())
        points.resize(points.size() - 2);
}
void tst_QVarLengthArray::squeeze()
{
    QVarLengthArray<int> list;
    int sizeOnStack = list.capacity();
    int sizeOnHeap = sizeOnStack * 2;
    list.resize(0);
    QCOMPARE(list.capacity(), sizeOnStack);
    list.resize(sizeOnHeap);
    QCOMPARE(list.capacity(), sizeOnHeap);
    list.resize(sizeOnStack);
    QCOMPARE(list.capacity(), sizeOnHeap);
    list.resize(0);
    QCOMPARE(list.capacity(), sizeOnHeap);
    list.squeeze();
    QCOMPARE(list.capacity(), sizeOnStack);
    list.resize(sizeOnStack);
    list.squeeze();
    QCOMPARE(list.capacity(), sizeOnStack);
    list.resize(sizeOnHeap);
    list.squeeze();
    QCOMPARE(list.capacity(), sizeOnHeap);
}
예제 #8
0
void QDBusMetaObjectGenerator::write(QDBusMetaObject *obj)
{
    // this code here is mostly copied from qaxbase.cpp
    // with a few modifications to make it cleaner
    
    QString className = interface;
    className.replace(QLatin1Char('.'), QLatin1String("::"));
    if (className.isEmpty())
        className = QLatin1String("QDBusInterface");

    QVarLengthArray<int> idata;
    idata.resize(sizeof(QDBusMetaObjectPrivate) / sizeof(int));

    QDBusMetaObjectPrivate *header = reinterpret_cast<QDBusMetaObjectPrivate *>(idata.data());
    header->revision = 1;
    header->className = 0;
    header->classInfoCount = 0;
    header->classInfoData = 0;
    header->methodCount = methods.count();
    header->methodData = idata.size();
    header->propertyCount = properties.count();
    header->propertyData = header->methodData + header->methodCount * 5;
    header->enumeratorCount = 0;
    header->enumeratorData = 0;
    header->propertyDBusData = header->propertyData + header->propertyCount * 3;
    header->methodDBusData = header->propertyDBusData + header->propertyCount * intsPerProperty;

    int data_size = idata.size() +
                    (header->methodCount * (5+intsPerMethod)) +
                    (header->propertyCount * (3+intsPerProperty));
    foreach (const Method &mm, methods)
        data_size += 2 + mm.inputTypes.count() + mm.outputTypes.count();
    idata.resize(data_size + 1);

    char null('\0');
    QByteArray stringdata = className.toLatin1();
    stringdata += null;
    stringdata.reserve(8192);

    int offset = header->methodData;
    int signatureOffset = header->methodDBusData;
    int typeidOffset = header->methodDBusData + header->methodCount * intsPerMethod;
    idata[typeidOffset++] = 0;                           // eod

    // add each method:
    for (QMap<QByteArray, Method>::ConstIterator it = methods.constBegin();
         it != methods.constEnd(); ++it) {
        // form "prototype\0parameters\0typeName\0tag\0methodname\0inputSignature\0outputSignature"
        const Method &mm = it.value();

        idata[offset++] = stringdata.length();
        stringdata += it.key();                 // prototype
        stringdata += null;
        idata[offset++] = stringdata.length();
        stringdata += mm.parameters;
        stringdata += null;
        idata[offset++] = stringdata.length();
        stringdata += mm.typeName;
        stringdata += null;
        idata[offset++] = stringdata.length();
        stringdata += mm.tag;
        stringdata += null;
        idata[offset++] = mm.flags;

        idata[signatureOffset++] = stringdata.length();
        stringdata += mm.name;
        stringdata += null;
        idata[signatureOffset++] = stringdata.length();
        stringdata += mm.inputSignature;
        stringdata += null;
        idata[signatureOffset++] = stringdata.length();
        stringdata += mm.outputSignature;
        stringdata += null;

        idata[signatureOffset++] = typeidOffset;
        idata[typeidOffset++] = mm.inputTypes.count();
        memcpy(idata.data() + typeidOffset, mm.inputTypes.data(), mm.inputTypes.count() * sizeof(int));
        typeidOffset += mm.inputTypes.count();

        idata[signatureOffset++] = typeidOffset;
        idata[typeidOffset++] = mm.outputTypes.count();
        memcpy(idata.data() + typeidOffset, mm.outputTypes.data(), mm.outputTypes.count() * sizeof(int));
        typeidOffset += mm.outputTypes.count();
    }

    Q_ASSERT(offset == header->propertyData);
    Q_ASSERT(signatureOffset == header->methodDBusData + header->methodCount * intsPerMethod);
    Q_ASSERT(typeidOffset == idata.size());

    // add each property
    signatureOffset = header->propertyDBusData;
    for (QMap<QByteArray, Property>::ConstIterator it = properties.constBegin();
         it != properties.constEnd(); ++it) {
        const Property &mp = it.value();

        // form is "name\0typeName\0signature\0"
        idata[offset++] = stringdata.length();
        stringdata += it.key();                 // name
        stringdata += null;
        idata[offset++] = stringdata.length();
        stringdata += mp.typeName;
        stringdata += null;
        idata[offset++] = mp.flags;

        idata[signatureOffset++] = stringdata.length();
        stringdata += mp.signature;
        stringdata += null;
        idata[signatureOffset++] = mp.type;
    }

    Q_ASSERT(offset == header->propertyDBusData);
    Q_ASSERT(signatureOffset == header->methodDBusData);

    char *string_data = new char[stringdata.length()];
    memcpy(string_data, stringdata, stringdata.length());

    uint *uint_data = new uint[idata.size()];
    memcpy(uint_data, idata.data(), idata.size() * sizeof(int));

    // put the metaobject together
    obj->d.data = uint_data;
    obj->d.extradata = 0;
    obj->d.stringdata = string_data;
    obj->d.superdata = &QDBusAbstractInterface::staticMetaObject;
}
예제 #9
0
void qDrawBorderPixmap(QPainter *painter, const QRect &targetRect, const QMargins &targetMargins,
                       const QPixmap &pixmap, const QRect &sourceRect,const QMargins &sourceMargins,
                       const QTileRules &rules, QDrawBorderPixmap::DrawingHints hints)
{
    QPainter::PixmapFragment d;
    d.opacity = 1.0;
    d.rotation = 0.0;

    QPixmapFragmentsArray opaqueData;
    QPixmapFragmentsArray translucentData;

    // source center
    const int sourceCenterTop = sourceRect.top() + sourceMargins.top();
    const int sourceCenterLeft = sourceRect.left() + sourceMargins.left();
    const int sourceCenterBottom = sourceRect.bottom() - sourceMargins.bottom() + 1;
    const int sourceCenterRight = sourceRect.right() - sourceMargins.right() + 1;
    const int sourceCenterWidth = sourceCenterRight - sourceCenterLeft;
    const int sourceCenterHeight = sourceCenterBottom - sourceCenterTop;
    // target center
    const int targetCenterTop = targetRect.top() + targetMargins.top();
    const int targetCenterLeft = targetRect.left() + targetMargins.left();
    const int targetCenterBottom = targetRect.bottom() - targetMargins.bottom() + 1;
    const int targetCenterRight = targetRect.right() - targetMargins.right() + 1;
    const int targetCenterWidth = targetCenterRight - targetCenterLeft;
    const int targetCenterHeight = targetCenterBottom - targetCenterTop;

    QVarLengthArray<qreal, 16> xTarget; // x-coordinates of target rectangles
    QVarLengthArray<qreal, 16> yTarget; // y-coordinates of target rectangles

    int columns = 3;
    int rows = 3;
    if (rules.horizontal != Qt::StretchTile && sourceCenterWidth != 0)
        columns = qMax(3, 2 + qCeil(targetCenterWidth / qreal(sourceCenterWidth)));
    if (rules.vertical != Qt::StretchTile && sourceCenterHeight != 0)
        rows = qMax(3, 2 + qCeil(targetCenterHeight / qreal(sourceCenterHeight)));

    xTarget.resize(columns + 1);
    yTarget.resize(rows + 1);

    bool oldAA = painter->testRenderHint(QPainter::Antialiasing);
    if (painter->paintEngine()->type() != QPaintEngine::OpenGL
        && painter->paintEngine()->type() != QPaintEngine::OpenGL2
        && oldAA && painter->combinedTransform().type() != QTransform::TxNone) {
        painter->setRenderHint(QPainter::Antialiasing, false);
    }

    xTarget[0] = targetRect.left();
    xTarget[1] = targetCenterLeft;
    xTarget[columns - 1] = targetCenterRight;
    xTarget[columns] = targetRect.left() + targetRect.width();

    yTarget[0] = targetRect.top();
    yTarget[1] = targetCenterTop;
    yTarget[rows - 1] = targetCenterBottom;
    yTarget[rows] = targetRect.top() + targetRect.height();

    qreal dx = targetCenterWidth;
    qreal dy = targetCenterHeight;

    switch (rules.horizontal) {
    case Qt::StretchTile:
        dx = targetCenterWidth;
        break;
    case Qt::RepeatTile:
        dx = sourceCenterWidth;
        break;
    case Qt::RoundTile:
        dx = targetCenterWidth / qreal(columns - 2);
        break;
    }

    for (int i = 2; i < columns - 1; ++i)
        xTarget[i] = xTarget[i - 1] + dx;

    switch (rules.vertical) {
    case Qt::StretchTile:
        dy = targetCenterHeight;
        break;
    case Qt::RepeatTile:
        dy = sourceCenterHeight;
        break;
    case Qt::RoundTile:
        dy = targetCenterHeight / qreal(rows - 2);
        break;
    }

    for (int i = 2; i < rows - 1; ++i)
        yTarget[i] = yTarget[i - 1] + dy;

    // corners
    if (targetMargins.top() > 0 && targetMargins.left() > 0 && sourceMargins.top() > 0 && sourceMargins.left() > 0) { // top left
        d.x = (0.5 * (xTarget[1] + xTarget[0]));
        d.y = (0.5 * (yTarget[1] + yTarget[0]));
        d.sourceLeft = sourceRect.left();
        d.sourceTop = sourceRect.top();
        d.width = sourceMargins.left();
        d.height = sourceMargins.top();
        d.scaleX = qreal(xTarget[1] - xTarget[0]) / d.width;
        d.scaleY = qreal(yTarget[1] - yTarget[0]) / d.height;
        if (hints & QDrawBorderPixmap::OpaqueTopLeft)
            opaqueData.append(d);
        else
            translucentData.append(d);
    }
    if (targetMargins.top() > 0 && targetMargins.right() > 0 && sourceMargins.top() > 0 && sourceMargins.right() > 0) { // top right
        d.x = (0.5 * (xTarget[columns] + xTarget[columns - 1]));
        d.y = (0.5 * (yTarget[1] + yTarget[0]));
        d.sourceLeft = sourceCenterRight;
        d.sourceTop = sourceRect.top();
        d.width = sourceMargins.right();
        d.height = sourceMargins.top();
        d.scaleX = qreal(xTarget[columns] - xTarget[columns - 1]) / d.width;
        d.scaleY = qreal(yTarget[1] - yTarget[0]) / d.height;
        if (hints & QDrawBorderPixmap::OpaqueTopRight)
            opaqueData.append(d);
        else
            translucentData.append(d);
    }
    if (targetMargins.bottom() > 0 && targetMargins.left() > 0 && sourceMargins.bottom() > 0 && sourceMargins.left() > 0) { // bottom left
        d.x = (0.5 * (xTarget[1] + xTarget[0]));
        d.y =(0.5 * (yTarget[rows] + yTarget[rows - 1]));
        d.sourceLeft = sourceRect.left();
        d.sourceTop = sourceCenterBottom;
        d.width = sourceMargins.left();
        d.height = sourceMargins.bottom();
        d.scaleX = qreal(xTarget[1] - xTarget[0]) / d.width;
        d.scaleY = qreal(yTarget[rows] - yTarget[rows - 1]) / d.height;
        if (hints & QDrawBorderPixmap::OpaqueBottomLeft)
            opaqueData.append(d);
        else
            translucentData.append(d);
    }
    if (targetMargins.bottom() > 0 && targetMargins.right() > 0 && sourceMargins.bottom() > 0 && sourceMargins.right() > 0) { // bottom right
        d.x = (0.5 * (xTarget[columns] + xTarget[columns - 1]));
        d.y = (0.5 * (yTarget[rows] + yTarget[rows - 1]));
        d.sourceLeft = sourceCenterRight;
        d.sourceTop = sourceCenterBottom;
        d.width = sourceMargins.right();
        d.height = sourceMargins.bottom();
        d.scaleX = qreal(xTarget[columns] - xTarget[columns - 1]) / d.width;
        d.scaleY = qreal(yTarget[rows] - yTarget[rows - 1]) / d.height;
        if (hints & QDrawBorderPixmap::OpaqueBottomRight)
            opaqueData.append(d);
        else
            translucentData.append(d);
    }

    // horizontal edges
    if (targetCenterWidth > 0 && sourceCenterWidth > 0) {
        if (targetMargins.top() > 0 && sourceMargins.top() > 0) { // top
            QPixmapFragmentsArray &data = hints & QDrawBorderPixmap::OpaqueTop ? opaqueData : translucentData;
            d.sourceLeft = sourceCenterLeft;
            d.sourceTop = sourceRect.top();
            d.width = sourceCenterWidth;
            d.height = sourceMargins.top();
            d.y = (0.5 * (yTarget[1] + yTarget[0]));
            d.scaleX = dx / d.width;
            d.scaleY = qreal(yTarget[1] - yTarget[0]) / d.height;
            for (int i = 1; i < columns - 1; ++i) {
                d.x = (0.5 * (xTarget[i + 1] + xTarget[i]));
                data.append(d);
            }
            if (rules.horizontal == Qt::RepeatTile)
                data[data.size() - 1].width = ((xTarget[columns - 1] - xTarget[columns - 2]) / d.scaleX);
        }
        if (targetMargins.bottom() > 0 && sourceMargins.bottom() > 0) { // bottom
            QPixmapFragmentsArray &data = hints & QDrawBorderPixmap::OpaqueBottom ? opaqueData : translucentData;
            d.sourceLeft = sourceCenterLeft;
            d.sourceTop = sourceCenterBottom;
            d.width = sourceCenterWidth;
            d.height = sourceMargins.bottom();
            d.y = (0.5 * (yTarget[rows] + yTarget[rows - 1]));
            d.scaleX = dx / d.width;
            d.scaleY = qreal(yTarget[rows] - yTarget[rows - 1]) / d.height;
            for (int i = 1; i < columns - 1; ++i) {
                d.x = (0.5 * (xTarget[i + 1] + xTarget[i]));
                data.append(d);
            }
            if (rules.horizontal == Qt::RepeatTile)
                data[data.size() - 1].width = ((xTarget[columns - 1] - xTarget[columns - 2]) / d.scaleX);
        }
    }

    // vertical edges
    if (targetCenterHeight > 0 && sourceCenterHeight > 0) {
        if (targetMargins.left() > 0 && sourceMargins.left() > 0) { // left
            QPixmapFragmentsArray &data = hints & QDrawBorderPixmap::OpaqueLeft ? opaqueData : translucentData;
            d.sourceLeft = sourceRect.left();
            d.sourceTop = sourceCenterTop;
            d.width = sourceMargins.left();
            d.height = sourceCenterHeight;
            d.x = (0.5 * (xTarget[1] + xTarget[0]));
            d.scaleX = qreal(xTarget[1] - xTarget[0]) / d.width;
            d.scaleY = dy / d.height;
            for (int i = 1; i < rows - 1; ++i) {
                d.y = (0.5 * (yTarget[i + 1] + yTarget[i]));
                data.append(d);
            }
            if (rules.vertical == Qt::RepeatTile)
                data[data.size() - 1].height = ((yTarget[rows - 1] - yTarget[rows - 2]) / d.scaleY);
        }
        if (targetMargins.right() > 0 && sourceMargins.right() > 0) { // right
            QPixmapFragmentsArray &data = hints & QDrawBorderPixmap::OpaqueRight ? opaqueData : translucentData;
            d.sourceLeft = sourceCenterRight;
            d.sourceTop = sourceCenterTop;
            d.width = sourceMargins.right();
            d.height = sourceCenterHeight;
            d.x = (0.5 * (xTarget[columns] + xTarget[columns - 1]));
            d.scaleX = qreal(xTarget[columns] - xTarget[columns - 1]) / d.width;
            d.scaleY = dy / d.height;
            for (int i = 1; i < rows - 1; ++i) {
                d.y = (0.5 * (yTarget[i + 1] + yTarget[i]));
                data.append(d);
            }
            if (rules.vertical == Qt::RepeatTile)
                data[data.size() - 1].height = ((yTarget[rows - 1] - yTarget[rows - 2]) / d.scaleY);
        }
    }

    // center
    if (targetCenterWidth > 0 && targetCenterHeight > 0 && sourceCenterWidth > 0 && sourceCenterHeight > 0) {
        QPixmapFragmentsArray &data = hints & QDrawBorderPixmap::OpaqueCenter ? opaqueData : translucentData;
        d.sourceLeft = sourceCenterLeft;
        d.sourceTop = sourceCenterTop;
        d.width = sourceCenterWidth;
        d.height = sourceCenterHeight;
        d.scaleX = dx / d.width;
        d.scaleY = dy / d.height;

        qreal repeatWidth = (xTarget[columns - 1] - xTarget[columns - 2]) / d.scaleX;
        qreal repeatHeight = (yTarget[rows - 1] - yTarget[rows - 2]) / d.scaleY;

        for (int j = 1; j < rows - 1; ++j) {
            d.y = (0.5 * (yTarget[j + 1] + yTarget[j]));
            for (int i = 1; i < columns - 1; ++i) {
                d.x = (0.5 * (xTarget[i + 1] + xTarget[i]));
                data.append(d);
            }
            if (rules.horizontal == Qt::RepeatTile)
                data[data.size() - 1].width = repeatWidth;
        }
        if (rules.vertical == Qt::RepeatTile) {
            for (int i = 1; i < columns - 1; ++i)
                data[data.size() - i].height = repeatHeight;
        }
    }

    if (opaqueData.size())
        painter->drawPixmapFragments(opaqueData.data(), opaqueData.size(), pixmap, QPainter::OpaqueHint);
    if (translucentData.size())
        painter->drawPixmapFragments(translucentData.data(), translucentData.size(), pixmap);

    if (oldAA)
        painter->setRenderHint(QPainter::Antialiasing, true);
}
예제 #10
0
/*! \internal

Draws a trigon (polygon with three corners \a pa, \a pb and \a pc
    and three edges), using \a painter.

    Fills the trigon with a gradient, where the \a pa point has the
    color \a color, \a pb is black and \a bc is white. Bilinear
    gradient.
*/
void QtColorTriangle::drawTrigon(QImage *buf, const QPointF &pa,
			       const QPointF &pb, const QPointF &pc,
			       const QColor &color)
{
    // Create three Vertex objects. A Vertex contains a double-point
    // coordinate and a color.
    // pa is the tip of the arrow
    // pb is the black corner
    // pc is the white corner
    Vertex aa(color, pa);
    Vertex bb(Qt::black, pb);
    Vertex cc(Qt::white, pc);

    // Sort. Make p1 above p2, which is above p3 (using y coordinate).
    // Bubble sorting is fastest here.
    Vertex *p1 = &aa;
    Vertex *p2 = &bb;
    Vertex *p3 = &cc;
    if (p1->point.y() > p2->point.y()) swap(&p1, &p2);
    if (p1->point.y() > p3->point.y()) swap(&p1, &p3);
    if (p2->point.y() > p3->point.y()) swap(&p2, &p3);

    // All the three y deltas are >= 0
    double p1p2ydist = p2->point.y() - p1->point.y();
    double p1p3ydist = p3->point.y() - p1->point.y();
    double p2p3ydist = p3->point.y() - p2->point.y();
    double p1p2xdist = p2->point.x() - p1->point.x();
    double p1p3xdist = p3->point.x() - p1->point.x();
    double p2p3xdist = p3->point.x() - p2->point.x();

    // The first x delta decides wether we have a lefty or a righty
    // trigon.
    bool lefty = p1p2xdist < 0;

    // Left and right colors and X values. The key in this map is the
    // y values. Our goal is to fill these structures with all the
    // information needed to do a single pass top-to-bottom,
    // left-to-right drawing of the trigon.
    QVarLengthArray<DoubleColor, 2000> leftColors;
    QVarLengthArray<DoubleColor, 2000> rightColors;
    QVarLengthArray<double, 2000> leftX; 
    QVarLengthArray<double, 2000> rightX; 

    leftColors.resize(int(floor(p3->point.y() + 1)));
    rightColors.resize(int(floor(p3->point.y() + 1)));
    leftX.resize(int(floor(p3->point.y() + 1)));
    rightX.resize(int(floor(p3->point.y() + 1)));

     // Scan longy - find all left and right colors and X-values for
    // the tallest edge (p1-p3).
    DoubleColor source;
    DoubleColor dest;
    double r, g, b;
    double rdelta, gdelta, bdelta;
    double x;
    double xdelta;
    int y1, y2;

    // Initialize with known values
    x = p1->point.x();
    source = p1->color;
    dest = p3->color;
    r = source.r;
    g = source.g;
    b = source.b;
    y1 = (int) floor(p1->point.y());
    y2 = (int) floor(p3->point.y());

    // Find slopes (notice that if the y dists are 0, we don't care
    // about the slopes)
    xdelta = p1p3ydist == 0.0 ? 0.0 : p1p3xdist / p1p3ydist;
    rdelta = p1p3ydist == 0.0 ? 0.0 : (dest.r - r) / p1p3ydist;
    gdelta = p1p3ydist == 0.0 ? 0.0 : (dest.g - g) / p1p3ydist;
    bdelta = p1p3ydist == 0.0 ? 0.0 : (dest.b - b) / p1p3ydist;

    // Calculate gradients using linear approximation
    int y;
    for (y = y1; y < y2; ++y) {
	if (lefty) {
	    rightColors[y] = DoubleColor(r, g, b);
	    rightX[y] = x;
	} else {
	    leftColors[y] = DoubleColor(r, g, b);
	    leftX[y] = x;
	}

	r += rdelta;
	g += gdelta;
	b += bdelta;
	x += xdelta;
    }

    // Scan top shorty - find all left and right colors and x-values
    // for the topmost of the two not-tallest short edges.
    x = p1->point.x();
    source = p1->color;
    dest = p2->color;
    r = source.r;
    g = source.g;
    b = source.b;
    y1 = (int) floor(p1->point.y());
    y2 = (int) floor(p2->point.y());

    // Find slopes (notice that if the y dists are 0, we don't care
    // about the slopes)
    xdelta = p1p2ydist == 0.0 ? 0.0 : p1p2xdist / p1p2ydist;
    rdelta = p1p2ydist == 0.0 ? 0.0 : (dest.r - r) / p1p2ydist;
    gdelta = p1p2ydist == 0.0 ? 0.0 : (dest.g - g) / p1p2ydist;
    bdelta = p1p2ydist == 0.0 ? 0.0 : (dest.b - b) / p1p2ydist;

    // Calculate gradients using linear approximation
    for (y = y1; y < y2; ++y) {
	if (lefty) {
	    leftColors[y] = DoubleColor(r, g, b);
	    leftX[y] = x;
	} else {
	    rightColors[y] = DoubleColor(r, g, b);
	    rightX[y] = x;
	}

	r += rdelta;
	g += gdelta;
	b += bdelta;
	x += xdelta;
    }

    // Scan bottom shorty - find all left and right colors and
    // x-values for the bottommost of the two not-tallest short edges.
    x = p2->point.x();
    source = p2->color;
    dest = p3->color;
    r = source.r;
    g = source.g;
    b = source.b;
    y1 = (int) floor(p2->point.y());
    y2 = (int) floor(p3->point.y());

    // Find slopes (notice that if the y dists are 0, we don't care
    // about the slopes)
    xdelta = p2p3ydist == 0.0 ? 0.0 : p2p3xdist / p2p3ydist;
    rdelta = p2p3ydist == 0.0 ? 0.0 : (dest.r - r) / p2p3ydist;
    gdelta = p2p3ydist == 0.0 ? 0.0 : (dest.g - g) / p2p3ydist;
    bdelta = p2p3ydist == 0.0 ? 0.0 : (dest.b - b) / p2p3ydist;

    // Calculate gradients using linear approximation
    for (y = y1; y < y2; ++y) {
	if (lefty) {
	    leftColors[y] = DoubleColor(r, g, b);
	    leftX[y] = x;
	} else {
	    rightColors[y] = DoubleColor(r, g, b);
	    rightX[y] = x;
	}

	r += rdelta;
	g += gdelta;
	b += bdelta;
	x += xdelta;
    }

    // Inner loop. For each y in the left map of x-values, draw one
    // line from left to right.
    const int p3yfloor = int(floor(p3->point.y()));
    for (int y = int(floor(p1->point.y())); y < p3yfloor; ++y) {
	double lx = leftX[y];
	double rx = rightX[y];

	int lxi = (int) floor(lx);
	int rxi = (int) floor(rx);
	DoubleColor rc = rightColors[y];
	DoubleColor lc = leftColors[y];

        // if the xdist is 0, don't draw anything.
	double xdist = rx - lx;
	if (xdist != 0.0) {
            double r = lc.r;
            double g = lc.g;
            double b = lc.b;
            double rdelta = (rc.r - r) / xdist;
            double gdelta = (rc.g - g) / xdist;
            double bdelta = (rc.b - b) / xdist;

            QRgb *scanline = reinterpret_cast<QRgb *>(buf->scanLine(y));
            scanline += lxi;

            // Inner loop 2. Draws the line from left to right.
            for (int i = lxi; i < rxi; ++i) {
                *scanline++ = qRgb((int) r, (int) g, (int) b);
                r += rdelta;
                g += gdelta;
                b += bdelta;
            }
        }
    }
}
void tst_QVarLengthArray::oldTests()
{
    {
	QVarLengthArray<int, 256> sa(128);
	QVERIFY(sa.data() == &sa[0]);
	sa[0] = 0xfee;
	sa[10] = 0xff;
	QVERIFY(sa[0] == 0xfee);
	QVERIFY(sa[10] == 0xff);
	sa.resize(512);
	QVERIFY(sa.data() == &sa[0]);
	QVERIFY(sa[0] == 0xfee);
	QVERIFY(sa[10] == 0xff);
        QVERIFY(sa.at(0) == 0xfee);
        QVERIFY(sa.at(10) == 0xff);
        QVERIFY(sa.value(0) == 0xfee);
        QVERIFY(sa.value(10) == 0xff);
        QVERIFY(sa.value(1000) == 0);
        QVERIFY(sa.value(1000, 12) == 12);
	QVERIFY(sa.size() == 512);
	sa.reserve(1024);
	QVERIFY(sa.capacity() == 1024);
	QVERIFY(sa.size() == 512);
    }
    {
	QVarLengthArray<QString> sa(10);
	sa[0] = "Hello";
	sa[9] = "World";
	QVERIFY(*sa.data() == "Hello");
	QVERIFY(sa[9] == "World");
	sa.reserve(512);
	QVERIFY(*sa.data() == "Hello");
	QVERIFY(sa[9] == "World");
	sa.resize(512);
	QVERIFY(*sa.data() == "Hello");
	QVERIFY(sa[9] == "World");
    }
    {
        int arr[2] = {1, 2};
        QVarLengthArray<int> sa(10);
        QCOMPARE(sa.size(), 10);
        sa.append(arr, 2);
        QCOMPARE(sa.size(), 12);
        QCOMPARE(sa[10], 1);
        QCOMPARE(sa[11], 2);
    }
    {
        QString arr[2] = { QString("hello"), QString("world") };
        QVarLengthArray<QString> sa(10);
        QCOMPARE(sa.size(), 10);
        sa.append(arr, 2);
        QCOMPARE(sa.size(), 12);
        QCOMPARE(sa[10], QString("hello"));
        QCOMPARE(sa[11], QString("world"));
        QCOMPARE(sa.at(10), QString("hello"));
        QCOMPARE(sa.at(11), QString("world"));
        QCOMPARE(sa.value(10), QString("hello"));
        QCOMPARE(sa.value(11), QString("world"));
        QCOMPARE(sa.value(10000), QString());
        QCOMPARE(sa.value(1212112, QString("none")), QString("none"));
        QCOMPARE(sa.value(-12, QString("neg")), QString("neg"));

        sa.append(arr, 1);
        QCOMPARE(sa.size(), 13);
        QCOMPARE(sa[12], QString("hello"));

        sa.append(arr, 0);
        QCOMPARE(sa.size(), 13);
    }
    {
        // assignment operator and copy constructor

        QVarLengthArray<int> sa(10);
        sa[5] = 5;

        QVarLengthArray<int> sa2(10);
        sa2[5] = 6;
        sa2 = sa;
        QCOMPARE(sa2[5], 5);

        QVarLengthArray<int> sa3(sa);
        QCOMPARE(sa3[5], 5);
    }

    QSKIP("This test causes the machine to crash when allocating too much memory.", SkipSingle);
    {
        QVarLengthArray<Foo> a;
        const int N = 0x7fffffff / sizeof(Foo);
        const int Prealloc = a.capacity();
        const Foo *data0 = a.constData();

        a.resize(N);
        if (a.size() == N) {
            QVERIFY(a.capacity() >= N);
            QCOMPARE(fooCtor, N);
            QCOMPARE(fooDtor, 0);

            for (int i = 0; i < N; i += 35000)
                a[i] = Foo();
        } else {
            // this is the case we're actually testing
            QCOMPARE(a.size(), 0);
            QCOMPARE(a.capacity(), Prealloc);
            QCOMPARE(a.constData(), data0);
            QCOMPARE(fooCtor, 0);
            QCOMPARE(fooDtor, 0);

            a.resize(5);
            QCOMPARE(a.size(), 5);
            QCOMPARE(a.capacity(), Prealloc);
            QCOMPARE(a.constData(), data0);
            QCOMPARE(fooCtor, 5);
            QCOMPARE(fooDtor, 0);

            a.resize(Prealloc + 1);
            QCOMPARE(a.size(), Prealloc + 1);
            QVERIFY(a.capacity() >= Prealloc + 1);
            QVERIFY(a.constData() != data0);
            QCOMPARE(fooCtor, Prealloc + 6);
            QCOMPARE(fooDtor, 5);

            const Foo *data1 = a.constData();

            a.resize(0x10000000);
            QCOMPARE(a.size(), 0);
            QVERIFY(a.capacity() >= Prealloc + 1);
            QVERIFY(a.constData() == data1);
            QCOMPARE(fooCtor, Prealloc + 6);
            QCOMPARE(fooDtor, Prealloc + 6);
        }
    }
}
예제 #12
0
void QDBusMetaObjectGenerator::write(QDBusMetaObject *obj)
{
    // this code here is mostly copied from qaxbase.cpp
    // with a few modifications to make it cleaner

    QString className = interface;
    className.replace(QLatin1Char('.'), QLatin1String("::"));
    if (className.isEmpty())
        className = QLatin1String("QDBusInterface");

    QVarLengthArray<int> idata;
    idata.resize(sizeof(QDBusMetaObjectPrivate) / sizeof(int));

    int methodParametersDataSize =
            ((aggregateParameterCount(signals_)
             + aggregateParameterCount(methods)) * 2) // types and parameter names
            - signals_.count() // return "parameters" don't have names
            - methods.count(); // ditto

    QDBusMetaObjectPrivate *header = reinterpret_cast<QDBusMetaObjectPrivate *>(idata.data());
    Q_STATIC_ASSERT_X(QMetaObjectPrivate::OutputRevision == 7, "QtDBus meta-object generator should generate the same version as moc");
    header->revision = QMetaObjectPrivate::OutputRevision;
    header->className = 0;
    header->classInfoCount = 0;
    header->classInfoData = 0;
    header->methodCount = signals_.count() + methods.count();
    header->methodData = idata.size();
    header->propertyCount = properties.count();
    header->propertyData = header->methodData + header->methodCount * 5 + methodParametersDataSize;
    header->enumeratorCount = 0;
    header->enumeratorData = 0;
    header->constructorCount = 0;
    header->constructorData = 0;
    header->flags = RequiresVariantMetaObject;
    header->signalCount = signals_.count();
    // These are specific to QDBusMetaObject:
    header->propertyDBusData = header->propertyData + header->propertyCount * 3;
    header->methodDBusData = header->propertyDBusData + header->propertyCount * intsPerProperty;

    int data_size = idata.size() +
                    (header->methodCount * (5+intsPerMethod)) + methodParametersDataSize +
                    (header->propertyCount * (3+intsPerProperty));
    foreach (const Method &mm, signals_)
        data_size += 2 + mm.inputTypes.count() + mm.outputTypes.count();
    foreach (const Method &mm, methods)
        data_size += 2 + mm.inputTypes.count() + mm.outputTypes.count();
    idata.resize(data_size + 1);

    QMetaStringTable strings(className.toLatin1());

    int offset = header->methodData;
    int parametersOffset = offset + header->methodCount * 5;
    int signatureOffset = header->methodDBusData;
    int typeidOffset = header->methodDBusData + header->methodCount * intsPerMethod;
    idata[typeidOffset++] = 0;                           // eod

    // add each method:
    for (int x = 0; x < 2; ++x) {
        // Signals must be added before other methods, to match moc.
        QMap<QByteArray, Method> &map = (x == 0) ? signals_ : methods;
        for (QMap<QByteArray, Method>::ConstIterator it = map.constBegin();
             it != map.constEnd(); ++it) {
            const Method &mm = it.value();

            int argc = mm.inputTypes.size() + qMax(0, mm.outputTypes.size() - 1);

            idata[offset++] = strings.enter(mm.name);
            idata[offset++] = argc;
            idata[offset++] = parametersOffset;
            idata[offset++] = strings.enter(mm.tag);
            idata[offset++] = mm.flags;

            // Parameter types
            for (int i = -1; i < argc; ++i) {
                int type;
                QByteArray typeName;
                if (i < 0) { // Return type
                    if (!mm.outputTypes.isEmpty()) {
                        type = mm.outputTypes.first();
                        if (type == -1) {
                            type = IsUnresolvedType | strings.enter(mm.rawReturnType);
                        }
                    } else {
                        type = QMetaType::Void;
                    }
                } else if (i < mm.inputTypes.size()) {
                    type = mm.inputTypes.at(i);
                } else {
                    Q_ASSERT(mm.outputTypes.size() > 1);
                    type = mm.outputTypes.at(i - mm.inputTypes.size() + 1);
                    // Output parameters are references; type id not available
                    typeName = QMetaType::typeName(type);
                    typeName.append('&');
                }
                Q_ASSERT(type != QMetaType::UnknownType);
                int typeInfo;
                if (!typeName.isEmpty())
                    typeInfo = IsUnresolvedType | strings.enter(typeName);
                else
                    typeInfo = type;
                idata[parametersOffset++] = typeInfo;
            }
            // Parameter names
            for (int i = 0; i < argc; ++i)
                idata[parametersOffset++] = strings.enter(mm.parameterNames.at(i));

            idata[signatureOffset++] = typeidOffset;
            idata[typeidOffset++] = mm.inputTypes.count();
            memcpy(idata.data() + typeidOffset, mm.inputTypes.data(), mm.inputTypes.count() * sizeof(int));
            typeidOffset += mm.inputTypes.count();

            idata[signatureOffset++] = typeidOffset;
            idata[typeidOffset++] = mm.outputTypes.count();
            memcpy(idata.data() + typeidOffset, mm.outputTypes.data(), mm.outputTypes.count() * sizeof(int));
            typeidOffset += mm.outputTypes.count();
        }
    }

    Q_ASSERT(offset == header->methodData + header->methodCount * 5);
    Q_ASSERT(parametersOffset == header->propertyData);
    Q_ASSERT(signatureOffset == header->methodDBusData + header->methodCount * intsPerMethod);
    Q_ASSERT(typeidOffset == idata.size());
    offset += methodParametersDataSize;
    Q_ASSERT(offset == header->propertyData);

    // add each property
    signatureOffset = header->propertyDBusData;
    for (QMap<QByteArray, Property>::ConstIterator it = properties.constBegin();
         it != properties.constEnd(); ++it) {
        const Property &mp = it.value();

        // form is name, typeinfo, flags
        idata[offset++] = strings.enter(it.key()); // name
        Q_ASSERT(mp.type != QMetaType::UnknownType);
        idata[offset++] = mp.type;
        idata[offset++] = mp.flags;

        idata[signatureOffset++] = strings.enter(mp.signature);
        idata[signatureOffset++] = mp.type;
    }

    Q_ASSERT(offset == header->propertyDBusData);
    Q_ASSERT(signatureOffset == header->methodDBusData);

    char *string_data = new char[strings.blobSize()];
    strings.writeBlob(string_data);

    uint *uint_data = new uint[idata.size()];
    memcpy(uint_data, idata.data(), idata.size() * sizeof(int));

    // put the metaobject together
    obj->d.data = uint_data;
    obj->d.relatedMetaObjects = 0;
    obj->d.static_metacall = 0;
    obj->d.extradata = 0;
    obj->d.stringdata = reinterpret_cast<const QByteArrayData *>(string_data);
    obj->d.superdata = &QDBusAbstractInterface::staticMetaObject;
}
예제 #13
0
/*!
    Creates an OpenCL context that is compatible with the current
    QGLContext and \a platform.  Returns false if there is no OpenGL
    context current or the OpenCL context could not be created for
    some reason.

    This function will first try to create a QCLDevice::GPU device,
    and will then fall back to QCLDevice::Default if a GPU is not found.

    If \a platform is null, then the first platform that has a GPU
    will be used.  If there is no GPU, then the first platform with a
    default device will be used.

    \sa supportsObjectSharing()
*/
bool QCLContextGL::create(const QCLPlatform &platform)
{
    Q_D(QCLContextGL);

    // Bail out if the context already exists.
    if (isCreated())
        return true;

    // Bail out if we don't have an OpenGL context.
    if (!QGLContext::currentContext()) {
        qWarning() << "QCLContextGL::create: needs a current GL context";
        setLastError(CL_INVALID_CONTEXT);
        return false;
    }

    // Find the first gpu device.
    QList<QCLDevice> devices;
    cl_device_type deviceType = CL_DEVICE_TYPE_GPU;
    devices = QCLDevice::devices(QCLDevice::GPU, platform);
    if (devices.isEmpty()) {
        // Find the first default device.
        devices = QCLDevice::devices(QCLDevice::Default, platform);
        deviceType = CL_DEVICE_TYPE_DEFAULT;
    }
    if (devices.isEmpty()) {
        qWarning() << "QCLContextGL::create: no gpu devices found";
        setLastError(CL_DEVICE_NOT_FOUND);
        return false;
    }
    QCLDevice gpu = devices[0];
    QVarLengthArray<cl_device_id> devs;
    foreach (QCLDevice dev, devices)
        devs.append(dev.deviceId());

    // Add the platform identifier to the properties.
    QVarLengthArray<cl_context_properties> properties;
    properties.append(CL_CONTEXT_PLATFORM);
    properties.append(cl_context_properties(gpu.platform().platformId()));

    bool hasSharing = false;
#ifndef QT_NO_CL_OPENGL
    // Determine what kind of OpenCL-OpenGL sharing we have and enable it.
#if defined(__APPLE__) || defined(__MACOSX)
    bool appleSharing = gpu.hasExtension("cl_apple_gl_sharing");
    if (appleSharing) {
        CGLContextObj cglContext = CGLGetCurrentContext();
        CGLShareGroupObj cglShareGroup = CGLGetShareGroup(cglContext);
        properties.append(CL_CGL_SHAREGROUP_KHR);
        properties.append(cl_context_properties(cglShareGroup));
        hasSharing = true;
    }
#else
    bool khrSharing = gpu.hasExtension("cl_khr_gl_sharing");
#if defined(QT_OPENGL_ES_2) || defined(QT_OPENGL_ES)
    if (khrSharing) {
        properties.append(CL_EGL_DISPLAY_KHR);
        properties.append(cl_context_properties(eglGetCurrentDisplay()));
#ifdef EGL_OPENGL_ES_API
        eglBindAPI(EGL_OPENGL_ES_API);
#endif
        properties.append(CL_GL_CONTEXT_KHR);
        properties.append(cl_context_properties(eglGetCurrentContext()));
        hasSharing = true;
    }
#elif defined(Q_WS_X11)
    if (khrSharing) {
        properties.append(CL_GLX_DISPLAY_KHR);
        properties.append(cl_context_properties(glXGetCurrentDisplay()));
        properties.append(CL_GL_CONTEXT_KHR);
        properties.append(cl_context_properties(glXGetCurrentContext()));
        hasSharing = true;
    }
#else
    // Needs to be ported to other platforms.
    if (khrSharing)
        qWarning() << "QCLContextGL::create: do not know how to enable sharing";
#endif
#endif
#endif // !QT_NO_CL_OPENGL
    properties.append(0);

#ifndef QT_NO_CL_OPENGL
    // Query the actual OpenCL devices we should use with the OpenGL context.
    typedef cl_int (*q_PFNCLGETGLCONTEXTINFOKHR)
        (const cl_context_properties *, cl_uint, size_t, void *, size_t *);
    q_PFNCLGETGLCONTEXTINFOKHR getGLContextInfo =
        (q_PFNCLGETGLCONTEXTINFOKHR)clGetExtensionFunctionAddress
            ("clGetGLContextInfoKHR");
    if (getGLContextInfo && hasSharing) {
        size_t size;
        cl_device_id currentDev;
        if(getGLContextInfo(properties.data(),
                            CL_DEVICES_FOR_GL_CONTEXT_KHR,
                            0, 0, &size) == CL_SUCCESS && size > 0) {
            QVarLengthArray<cl_device_id> buf(size / sizeof(cl_device_id));
            getGLContextInfo(properties.data(),
                             CL_DEVICES_FOR_GL_CONTEXT_KHR,
                             size, buf.data(), 0);
            devs = buf;
            gpu = QCLDevice(devs[0]);
        }
        if (getGLContextInfo(properties.data(),
                             CL_CURRENT_DEVICE_FOR_GL_CONTEXT_KHR,
                             sizeof(currentDev), &currentDev, 0)
                == CL_SUCCESS) {
            gpu = QCLDevice(currentDev);
        }
    }
#endif

    // Create the OpenCL context.
    cl_context id;
    cl_int error;
    id = clCreateContext
        (properties.data(), devs.size(), devs.data(),
         qt_clgl_context_notify, 0, &error);
    if (!id && hasSharing) {
        // Try again without the sharing parameters.
        properties.resize(2);
        properties.append(0);
        hasSharing = false;
        id = clCreateContext
            (properties.data(), devs.size(), devs.data(),
             qt_clgl_context_notify, 0, &error);
    }
    setLastError(error);
    if (id == 0) {
        qWarning() << "QCLContextGL::create:" << errorName(error);
        d->supportsSharing = false;
    } else {
        setContextId(id);
        clReleaseContext(id);   // setContextId() adds an extra reference.
        setDefaultDevice(gpu);
        d->supportsSharing = hasSharing;
    }
    return id != 0;
}
예제 #14
0
Kst::Object::UpdateType AsciiSource::internalDataSourceUpdate() 
{
  if (!_haveHeader) {
    _haveHeader = initRowIndex();
    if (!_haveHeader) {
      return NoChange;
    }
    // Re-update the field list since we have one now
    _fieldList = fieldListFor(_filename, &_config);
    _fieldListComplete = _fieldList.count() > 1;

    // Re-update the scalar list since we have one now
    _scalarList = scalarListFor(_filename, &_config);
    _stringList = stringListFor(_filename, &_config);
  }

  QFile file(_filename);
  if (!openValidFile(file)) {
    // Qt: If the device is closed, the size returned will not reflect the actual size of the device.
    return NoChange;
  }
  
  bool forceUpdate;
  if (_byteLength == file.size()) {
    forceUpdate = false;
  } else {
    forceUpdate = true;
    _byteLength = file.size();
  }

  int bufread;
  bool new_data = false;
  //bool first_read = (_numFrames == 0);

  QByteArray delbytes = _config._delimiters.value().toLatin1();
  const char *del = delbytes.constData();

  do {
    // Read the tmpbuffer, starting at row_index[_numFrames]
    QVarLengthArray<char, MAXBUFREADLEN + 1> varBuffer;
    varBuffer.resize(varBuffer.capacity());
    int bufstart = _rowIndex[_numFrames];
    bufread = readFromFile(file, varBuffer, bufstart, _byteLength - bufstart, MAXBUFREADLEN);    

#ifdef KST_DONT_CHECK_INDEX_IN_DEBUG
  const char* buffer = varBuffer.constData();
  const char* bufferData = buffer;
#else
  QVarLengthArray<char, MAXBUFREADLEN + 1>& buffer = varBuffer;
  const char* bufferData = buffer.data();
#endif

    bool is_comment = false, has_dat = false;
    char *comment = strpbrk(const_cast<char*>(bufferData), del);
    for (int i = 0; i < bufread; i++) {
      if (comment == &(buffer[i])) {
        is_comment = true;
      } else if (buffer[i] == '\n' || buffer[i] == '\r') {
        if (has_dat) {
          ++_numFrames;
          if (_numFrames >= _rowIndex.size()) {
            _rowIndex.resize(_rowIndex.size() + 32768);
            if (_numFrames >= _rowIndex.size()) {
              // TODO where could we report an error;
              return NoChange;
            }
          }
          new_data = true;
        }
        _rowIndex[_numFrames] = bufstart + i + 1;
        has_dat = is_comment = false;
        if (comment && comment < &(buffer[i])) {
          comment = strpbrk(const_cast<char*>(&(buffer[i])), del);
        }
      } else if (!is_comment && !isspace((unsigned char)buffer[i])) {
        // FIXME: this breaks custom delimiters
        has_dat = true;
      }
    }
  } while ((bufread == MAXBUFREADLEN)); // && (!first_read));

  return (forceUpdate ? Updated : (new_data ? Updated : NoChange));
}