int findBreak(int A[], int n, int p, int q) {
     int len = q - p + 1;
     if(len == 1 || A[p] < A[q]) return p;
     if(len == 2) return q;
     int m = (p + q) / 2;
     if(A[m] > A[p]) return findBreak(A, n, m, q);
     return findBreak(A, n, p, m);
 }
 int search(int A[], int n, int target) {
     if(n == 0) return -1;
     if(n == 1) return A[0] == target ? 0 : -1;
     
     int breakpos = findBreak(A, n);
     breakpos = (breakpos == 0 ? n-1 : breakpos - 1);
     
     if(breakpos >= n - 1) {
         return searchInSortedArray(A, n, 0, n - 1, target);
     } else if(target > A[breakpos] || target < A[breakpos + 1]) {
         return -1;
     } else if(target >= A[0]) {
         return searchInSortedArray(A, n, 0, breakpos, target);
     } else {
         return searchInSortedArray(A, n, breakpos + 1, n - 1, target);
     }
 }
示例#3
0
文件: drawparams.cpp 项目: KDE/kdesvn
bool RectDrawing::drawField(QPainter *p, int f, DrawParams *dp)
{
    if (!dp) {
        dp = drawParams();
    }

    if (!_fm) {
        _fm = new QFontMetrics(dp->font());
        _fontHeight = _fm->height();
    }

    QRect r = _rect;

    int h = _fontHeight;
    bool rotate = dp->rotated();
    int width   = (rotate ? r.height() : r.width()) - 4;
    int height  = (rotate ? r.width() : r.height());
    int lines   = height / h;

    // stop if there is no space available
    if (lines < 1) {
        return false;
    }

    // calculate free space in first line (<unused>)
    int pos = dp->position(f);
    if (pos == DrawParams::Default) {
        switch (f % 4) {
        case 0: pos = DrawParams::TopLeft; break;
        case 1: pos = DrawParams::TopRight; break;
        case 2: pos = DrawParams::BottomRight; break;
        case 3: pos = DrawParams::BottomLeft; break;
        }
    }

    int unused = 0;
    bool isBottom = false;
    bool isCenter = false;
    bool isRight = false;
    int *used = 0;
    switch (pos) {
    case DrawParams::TopLeft:
        used = &_usedTopLeft;
        if (_usedTopLeft == 0) {
            if (_usedTopCenter) {
                unused = (width - _usedTopCenter) / 2;
            } else {
                unused = width - _usedTopRight;
            }
        }
        break;

    case DrawParams::TopCenter:
        isCenter = true;
        used = &_usedTopCenter;
        if (_usedTopCenter == 0) {
            if (_usedTopLeft > _usedTopRight) {
                unused = width - 2 * _usedTopLeft;
            } else {
                unused = width - 2 * _usedTopRight;
            }
        }
        break;

    case DrawParams::TopRight:
        isRight = true;
        used = &_usedTopRight;
        if (_usedTopRight == 0) {
            if (_usedTopCenter) {
                unused = (width - _usedTopCenter) / 2;
            } else {
                unused = width - _usedTopLeft;
            }
        }
        break;

    case DrawParams::BottomLeft:
        isBottom = true;
        used = &_usedBottomLeft;
        if (_usedBottomLeft == 0) {
            if (_usedBottomCenter) {
                unused = (width - _usedBottomCenter) / 2;
            } else {
                unused = width - _usedBottomRight;
            }
        }
        break;

    case DrawParams::BottomCenter:
        isCenter = true;
        isBottom = true;
        used = &_usedBottomCenter;
        if (_usedBottomCenter == 0) {
            if (_usedBottomLeft > _usedBottomRight) {
                unused = width - 2 * _usedBottomLeft;
            } else {
                unused = width - 2 * _usedBottomRight;
            }
        }
        break;

    case DrawParams::BottomRight:
        isRight = true;
        isBottom = true;
        used = &_usedBottomRight;
        if (_usedBottomRight == 0) {
            if (_usedBottomCenter) {
                unused = (width - _usedBottomCenter) / 2;
            } else {
                unused = width - _usedBottomLeft;
            }
        }
        break;
    }
    if (isBottom) {
        if ((_usedTopLeft > 0) ||
                (_usedTopCenter > 0) ||
                (_usedTopRight > 0)) {
            lines--;
        }
    } else if (!isBottom) {
        if ((_usedBottomLeft > 0) ||
                (_usedBottomCenter > 0) ||
                (_usedBottomRight > 0)) {
            lines--;
        }
    }
    if (lines < 1) {
        return false;
    }

    int y = isBottom ? height - h : 0;

    if (unused < 0) {
        unused = 0;
    }
    if (unused == 0) {
        // no space available in last line at this position
        y = isBottom ? (y - h) : (y + h);
        lines--;

        if (lines < 1) {
            return false;
        }

        // new line: reset used space
        if (isBottom) {
            _usedBottomLeft = _usedBottomCenter = _usedBottomRight = 0;
        } else {
            _usedTopLeft = _usedTopCenter = _usedTopRight = 0;
        }

        unused = width;
    }

    // stop as soon as possible when there is no space for "..."
    static int dotW = 0;
    if (!dotW) {
        dotW = _fm->width("...");
    }
    if (width < dotW) {
        return false;
    }

    // get text and pixmap now, only if we need to, because it is possible
    // that they are calculated on demand (and this can take some time)
    QString name = dp->text(f);
    if (name.isEmpty()) {
        return 0;
    }
    QPixmap pix = dp->pixmap(f);

    // check if pixmap can be drawn
    int pixW = pix.width();
    int pixH = pix.height();
    int pixY = 0;
    bool pixDrawn = true;
    if (pixW > 0) {
        pixW += 2; // X distance from pix
        if ((width < pixW + dotW) || (height < pixH)) {
            // do not draw
            pixW = 0;
        } else {
            pixDrawn = false;
        }
    }

    // width of text and pixmap to be drawn
    int w = pixW + _fm->width(name);

    // if we have limited space at 1st line:
    // use it only if whole name does fit in last line...
    if ((unused < width) && (w > unused)) {
        y = isBottom ? (y - h) : (y + h);
        lines--;

        if (lines < 1) {
            return false;
        }

        // new line: reset used space
        if (isBottom) {
            _usedBottomLeft = _usedBottomCenter = _usedBottomRight = 0;
        } else {
            _usedTopLeft = _usedTopCenter = _usedTopRight = 0;
        }
    }

    p->save();
    p->setPen((qGray(dp->backColor().rgb()) > 100) ? Qt::black : Qt::white);
    p->setFont(dp->font());
    if (rotate) {
        //p->translate(r.x()+2, r.y()+r.height());
        p->translate(r.x(), r.y() + r.height() - 2);
        p->rotate(270);
    } else {
        p->translate(r.x() + 2, r.y());
    }
    // adjust available lines according to maxLines
    int max = dp->maxLines(f);
    if ((max > 0) && (lines > max)) {
        lines = max;
    }
    /* loop over name parts to break up string depending on available width.
     * every char category change is supposed a possible break,
     * with the exception Uppercase=>Lowercase.
     * It is good enough for numbers, Symbols...
     *
     * If the text is to be written at the bottom, we start with the
     * end of the string (so everything is reverted)
    */
    QString remaining;
    int origLines = lines;
    while (lines > 0) {

        // more than one line: search for line break
        if (w > width && lines > 1) {
            int breakPos;

            if (!isBottom) {
                w = pixW + findBreak(breakPos, name, _fm, width - pixW);

                remaining = name.mid(breakPos);
                // remove space on break point
                if (name[breakPos - 1].category() == QChar::Separator_Space) {
                    name = name.left(breakPos - 1);
                } else {
                    name = name.left(breakPos);
                }
            } else { // bottom
                w = pixW + findBreakBackwards(breakPos, name, _fm, width - pixW);

                remaining = name.left(breakPos);
                // remove space on break point
                if (name[breakPos].category() == QChar::Separator_Space) {
                    name = name.mid(breakPos + 1);
                } else {
                    name = name.mid(breakPos);
                }
            }
        } else {
            remaining.clear();
        }
        /* truncate and add ... if needed */
        if (w > width) {
            name = _fm->elidedText(name, Qt::ElideRight, width - pixW);
            w = _fm->width(name) + pixW;
        }

        int x = 0;
        if (isCenter) {
            x = (width - w) / 2;
        } else if (isRight) {
            x = width - w;
        }
        if (!pixDrawn) {
            pixY = y + (h - pixH) / 2; // default: center vertically
            if (pixH > h) {
                pixY = isBottom ? y - (pixH - h) : y;
            }

            p->drawPixmap(x, pixY, pix);

            // for distance to next text
            pixY = isBottom ? (pixY - h - 2) : (pixY + pixH + 2);
            pixDrawn = true;
        }
        p->drawText(x + pixW, y,
                    width - pixW, h,
                    Qt::AlignLeft, name);
        y = isBottom ? (y - h) : (y + h);
        lines--;

        if (remaining.isEmpty()) {
            break;
        }
        name = remaining;
        w = pixW + _fm->width(name);
    }

    // make sure the pix stays visible
    if (pixDrawn && (pixY > 0)) {
        if (isBottom && (pixY < y)) {
            y = pixY;
        }
        if (!isBottom && (pixY > y)) {
            y = pixY;
        }
    }

    if (origLines > lines) {
        // if only 1 line written, do not reset _used* vars
        if (lines - origLines > 1) {
            if (isBottom) {
                _usedBottomLeft = _usedBottomCenter = _usedBottomRight = 0;
            } else {
                _usedTopLeft = _usedTopCenter = _usedTopRight = 0;
            }
        }

        // take back one line
        y = isBottom ? (y + h) : (y - h);
        if (used) {
            *used = w;
        }
    }

    // update free space
    if (!isBottom) {
        if (rotate) {
            _rect.setRect(r.x() + y, r.y(), r.width() - y, r.height());
        } else {
            _rect.setRect(r.x(), r.y() + y, r.width(), r.height() - y);
        }
    } else {
        if (rotate) {
            _rect.setRect(r.x(), r.y(), y + h, r.height());
        } else {
            _rect.setRect(r.x(), r.y(), r.width(), y + h);
        }
    }

    p->restore();

    return true;
}
 int findBreak(int A[], int n) {
     return findBreak(A, n, 0, n - 1);
 }