⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 qpainterpath.cpp

📁 qt-x11-opensource-src-4.1.4.tar.gz源码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
        if (bounds.width() < lower_bound && bounds.height() < lower_bound) {            // We make the assumption here that the curve starts to            // approximate a line after while (i.e. that it doesn't            // change direction drastically during its slope)            if (bezier.pt1().x() <= x) {                (*winding) += (bezier.pt4().y() > bezier.pt1().y() ? 1 : -1);            }            return;        }        // split curve and try again...        QBezier first_half, second_half;        bezier.split(&first_half, &second_half);        qt_painterpath_isect_curve(first_half, pt, winding);        qt_painterpath_isect_curve(second_half, pt, winding);    }}/*!    \fn bool QPainterPath::contains(const QPointF &point) const    Returns true if the given \a point is inside the path, otherwise    returns false.    \sa intersects()*/bool QPainterPath::contains(const QPointF &pt) const{    if (isEmpty())        return false;    QPainterPathData *d = d_func();    int winding_number = 0;    QPointF last_pt;    QPointF last_start;    for (int i=0; i<d->elements.size(); ++i) {        const Element &e = d->elements.at(i);        switch (e.type) {        case MoveToElement:            if (i > 0) // implicitly close all paths.                qt_painterpath_isect_line(last_pt, last_start, pt, &winding_number);            last_start = last_pt = e;            break;        case LineToElement:            qt_painterpath_isect_line(last_pt, e, pt, &winding_number);            last_pt = e;            break;        case CurveToElement:            {                const QPainterPath::Element &cp2 = d->elements.at(++i);                const QPainterPath::Element &ep = d->elements.at(++i);                qt_painterpath_isect_curve(QBezier::fromPoints(last_pt, e, cp2, ep),                                           pt, &winding_number);                last_pt = ep;            }            break;        default:            break;        }    }    // implicitly close last subpath    if (last_pt != last_start)        qt_painterpath_isect_line(last_pt, last_start, pt, &winding_number);    return (d->fillRule == Qt::WindingFill            ? (winding_number != 0)            : ((winding_number % 2) != 0));}static bool qt_painterpath_isect_line_rect(qreal x1, qreal y1, qreal x2, qreal y2,                                           const QRectF &rect){    qreal left = rect.left();    qreal right = rect.right();    qreal top = rect.top();    qreal bottom = rect.bottom();    enum { Left, Right, Top, Bottom };    // clip the lines, after cohen-sutherland, see e.g. http://www.nondot.org/~sabre/graphpro/line6.html    int p1 = ((x1 < left) << Left)             | ((x1 > right) << Right)             | ((y1 < top) << Top)             | ((y1 > bottom) << Bottom);    int p2 = ((x2 < left) << Left)             | ((x2 > right) << Right)             | ((y2 < top) << Top)             | ((y2 > bottom) << Bottom);    if (p1 & p2)        // completely inside        return false;    if (p1 | p2) {        qreal dx = x2 - x1;        qreal dy = y2 - y1;        // clip x coordinates        if (x1 < left) {            y1 += dy/dx * (left - x1);            x1 = left;        } else if (x1 > right) {            y1 -= dy/dx * (x1 - right);            x1 = right;        }        if (x2 < left) {            y2 += dy/dx * (left - x2);            x2 = left;        } else if (x2 > right) {            y2 -= dy/dx * (x2 - right);            x2 = right;        }        p1 = ((y1 < top) << Top)             | ((y1 > bottom) << Bottom);        p2 = ((y2 < top) << Top)             | ((y2 > bottom) << Bottom);        if (p1 & p2)            return false;        // clip y coordinates        if (y1 < top) {            x1 += dx/dy * (top - y1);            y1 = top;        } else if (y1 > bottom) {            x1 -= dx/dy * (y1 - bottom);            y1 = bottom;        }        if (y2 < top) {            x2 += dx/dy * (top - y2);            y2 = top;        } else if (y2 > bottom) {            x2 -= dx/dy * (y2 - bottom);            y2 = bottom;        }        p1 = ((x1 < left) << Left)             | ((x1 > right) << Right);        p2 = ((x2 < left) << Left)             | ((x2 > right) << Right);        if (p1 & p2)            return false;        return true;    }    return false;}static bool qt_isect_curve_horizontal(const QBezier &bezier, qreal y, qreal x1, qreal x2){    QRectF bounds = bezier.bounds();    if (y >= bounds.top() && y < bounds.bottom()        && bounds.right() >= x1 && bounds.left() < x2) {        const qreal lower_bound = .01;        if (bounds.width() < lower_bound && bounds.height() < lower_bound)            return true;        QBezier first_half, second_half;        bezier.split(&first_half, &second_half);        qreal midpoint = x1 + (x2 - x1) / 2;        if (qt_isect_curve_horizontal(first_half, y, x1, midpoint)            || qt_isect_curve_horizontal(first_half, y, midpoint, x2)            || qt_isect_curve_horizontal(second_half, y, x1, midpoint)            || qt_isect_curve_horizontal(second_half, y, midpoint, x2))            return true;    }    return false;}static bool qt_isect_curve_vertical(const QBezier &bezier, qreal x, qreal y1, qreal y2){    QRectF bounds = bezier.bounds();    if (x >= bounds.left() && x < bounds.right()        && bounds.top() >= y1 && bounds.bottom() < y2) {        const qreal lower_bound = .01;        if (bounds.width() < lower_bound && bounds.height() < lower_bound)            return true;        QBezier first_half, second_half;        bezier.split(&first_half, &second_half);        qreal midpoint = y1 + (y2 - y1) / 2;        if (qt_isect_curve_horizontal(first_half, x, y1, midpoint)            || qt_isect_curve_horizontal(first_half, x, midpoint, y2)            || qt_isect_curve_horizontal(second_half, x, y1, midpoint)            || qt_isect_curve_horizontal(second_half, x, midpoint, y2))            return true;    }    return false;}/*    Returns true if any lines or curves cross the four edges in of rect*/static bool qt_painterpath_check_crossing(const QPainterPath *path, const QRectF &rect){    QPointF last_pt;    QPointF last_start;    for (int i=0; i<path->elementCount(); ++i) {        const QPainterPath::Element &e = path->elementAt(i);        switch (e.type) {        case QPainterPath::MoveToElement:            if (i > 0                && qFuzzyCompare(last_pt.x(), last_start.y())                && qFuzzyCompare(last_pt.y(), last_start.y())                && qt_painterpath_isect_line_rect(last_pt.x(), last_pt.y(),                                                  last_start.x(), last_start.y(), rect))                return true;            last_start = last_pt = e;            break;        case QPainterPath::LineToElement:            if (qt_painterpath_isect_line_rect(last_pt.x(), last_pt.y(), e.x, e.y, rect))                return true;            last_pt = e;            break;        case QPainterPath::CurveToElement:            {                QPointF cp2 = path->elementAt(++i);                QPointF ep = path->elementAt(++i);                QBezier bezier = QBezier::fromPoints(last_pt, e, cp2, ep);                if (qt_isect_curve_horizontal(bezier, rect.top(), rect.left(), rect.right())                    || qt_isect_curve_horizontal(bezier, rect.bottom(), rect.left(), rect.right())                    || qt_isect_curve_vertical(bezier, rect.left(), rect.top(), rect.bottom())                    || qt_isect_curve_vertical(bezier, rect.right(), rect.top(), rect.bottom()))                    return true;                last_pt = ep;            }            break;        default:            break;        }    }    // implicitly close last subpath    if (last_pt != last_start        && qt_painterpath_isect_line_rect(last_pt.x(), last_pt.y(),                                          last_start.x(), last_start.y(), rect))        return true;    return false;}/*!    \fn bool QPainterPath::intersects(const QRectF &rectangle) const    Returns true if any point in the given \a rectangle is inside the    path; otherwise returns false.    \sa contains()*/bool QPainterPath::intersects(const QRectF &rect) const{    if (isEmpty() || !controlPointRect().intersects(rect))        return false;    // If any path element cross the rect its bound to be an intersection    if (qt_painterpath_check_crossing(this, rect))        return true;    if (contains(rect.center()))        return true;    Q_D(QPainterPath);    // Check if the rectangle surounds any subpath...    for (int i=0; i<d->elements.size(); ++i) {        const Element &e = d->elements.at(i);        if (e.type == QPainterPath::MoveToElement && rect.contains(e))            return true;    }    return false;}/*!    \fn bool QPainterPath::contains(const QRectF &rectangle) const    \overload    Returns true if the given \a rectangle is inside the path,    otherwise returns false.*/bool QPainterPath::contains(const QRectF &rect) const{    Q_D(QPainterPath);    // the path is empty or the control point rect doesn't completly    // cover the rectangle we abort stratight away.    if (isEmpty() || !controlPointRect().contains(rect))        return false;    // if there are intersections, chances are that the rect is not    // contained, except if we have winding rule, in which case it    // still might.    if (qt_painterpath_check_crossing(this, rect)) {        if (fillRule() == Qt::OddEvenFill) {            return false;        } else {            // Do some wague sampling in the winding case. This is not            // precise but it should mostly be good enough.            if (!contains(rect.topLeft()) ||                !contains(rect.topRight()) ||                !contains(rect.bottomRight()) ||                !contains(rect.bottomLeft()))                return false;        }    }    // If there exists a point inside that is not part of the path its    // because: rectangle lies completly outside path or a subpath    // excludes parts of the rectangle. Both cases mean that the rect    // is not contained    if (!contains(rect.center()))        return false;    // If there are any subpaths inside this rectangle we need to    // check if they are still contained as a result of the fill    // rule. This can only be the case for WindingFill though. For    // OddEvenFill the rect will never be contained if it surrounds a    // subpath. (the case where two subpaths are completly identical    // can be argued but we choose to neglect it).    for (int i=0; i<d->elements.size(); ++i) {        const Element &e = d->elements.at(i);        if (e.type == QPainterPath::MoveToElement && rect.contains(e)) {            if (fillRule() == Qt::OddEvenFill)                return false;            bool stop = false;            for (; !stop && i<d->elements.size(); ++i) {                const Element &el = d->elements.at(i);                switch (el.type) {                case MoveToElement:                    stop = true;                    break;                case LineToElement:                    if (!contains(el))                        return false;                    break;                case CurveToElement:                    if (!contains(d->elements.at(i+2)))                        return false;                    i += 2;                    break;                default:                    break;                }            }            // compensate for the last ++i in the inner for            --i;        }    }    return true;}/*!    Returns true if this painterpath is equal to the given \a path.    Note that comparing paths may involve a per element comparison    which can be slow for complex paths.    \sa operator!=()*/bool QPainterPath::operator==(const QPainterPath &path) const{    QPainterPathData *d = reinterpret_cast<QPainterPathData *>(d_func());    if (path.d_func() == d)        return true;    else if (!d || !path.d_func())        return false;    bool equal = d->fillRule == path.d_func()->fillRule && d->elements.size() == path.d_func()->elements.size();    for (int i = 0; i < d->elements.size() && equal; ++i)        equal = d->elements.at(i) == path.d_func()->elements.at(i);    return equal;}/*!    Returns true if this painter path differs from the given \a path.    Note that comparing paths may involve a per element comparison    which can be slow for complex paths.    \sa operator==()*/bool QPainterPath::operator!=(const QPainterPath &path) const{    return !(*this==path);}#ifndef QT_NO_DATASTREAM/*!    \fn QDataStream &operator<<(QDataStream &stream, const QPainterPath &path)    \relates QPainterPath    Writes the given painter \a path to the given \a stream, and    returns a reference to the \a stream.    \sa {Format of the QDataStream Operators}*/QDataStream &operator<<(QDataStream &s, const QPainterPath &p){    if (p.isEmpty()) { 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -