📄 render_inline.cpp
字号:
{ if (pointArray.size() < 3) return false; QValueVector<QPoint>::Iterator it = pointArray.end(); QPoint p0 = *--it; QPoint p1 = *--it; QPoint p2 = *--it; bool elide = false; if (p0.x() == p1.x() && p1.x() == p2.x() && (p1.y() < p0.y() && p0.y() < p2.y() || p2.y() < p0.y() && p0.y() < p1.y() || p1.y() < p2.y() && p2.y() < p0.y() || p0.y() < p2.y() && p2.y() < p1.y() || (elide = p2.y() == p0.y() && p0.y() < p1.y()) || (elide = p1.y() < p0.y() && p0.y() == p2.y())) || p0.y() == p1.y() && p1.y() == p2.y() && (p1.x() < p0.x() && p0.x() < p2.x() || p2.x() < p0.x() && p0.x() < p1.x() || p1.x() < p2.x() && p2.x() < p0.x() || p0.x() < p2.x() && p2.x() < p1.x() || (elide = p2.x() == p0.x() && p0.x() < p1.x()) || (elide = p1.x() < p0.x() && p0.x() == p2.x()))) {// kdDebug(6040) << "spikered p2" << (elide ? " (elide)" : "") << ": " << p2 << " p1: " << p1 << " p0: " << p0 << endl; pointArray.pop_back(); pointArray.pop_back(); if (!elide) pointArray.push_back(p0); return true; } return false;}/** * Reduces segment separators. * * A segment separator separates a segment into two segments, thus causing * two adjacent segment with the same orientation. * * 2 1 0 * x-------x---->x * (0 means stack-top) * * Here, 1 is a segment separator. As segment separators not only make * the line drawing algorithm inefficient, but also make the spike-reduction * fail, they must be eliminated: * * 1 0 * x------------>x * * Preconditions: * - No other segment separators exist in the whole point-array except * at most one at the end * - No two succeeding points are ever equal * - For each two succeeding points either p1.x == p2.x or p1.y == p2.y holds * true * - No such spike exists where 2 is situated between 0 and 1. * * Postcondition: * - No segment separators exist in the whole point-array * * If no segment separator is found at the end of the point-array, it is * left unchanged. * @return \c true if a segment separator was actually reduced. */inline static bool reduceSegmentSeparator(QValueVector<QPoint> &pointArray){ if (pointArray.size() < 3) return false; QValueVector<QPoint>::Iterator it = pointArray.end(); QPoint p0 = *--it; QPoint p1 = *--it; QPoint p2 = *--it;// kdDebug(6040) << "checking p2: " << p2 << " p1: " << p1 << " p0: " << p0 << endl; if (p0.x() == p1.x() && p1.x() == p2.x() && (p2.y() < p1.y() && p1.y() < p0.y() || p0.y() < p1.y() && p1.y() < p2.y()) || p0.y() == p1.y() && p1.y() == p2.y() && (p2.x() < p1.x() && p1.x() < p0.x() || p0.x() < p1.x() && p1.x() < p2.x())) {// kdDebug(6040) << "segred p2: " << p2 << " p1: " << p1 << " p0: " << p0 << endl; pointArray.pop_back(); pointArray.pop_back(); pointArray.push_back(p0); return true; } return false;}/** * Appends the given point to the point-array, doing necessary reductions to * produce a path without spikes and segment separators. */static void appendPoint(QValueVector<QPoint> &pointArray, QPoint &pnt){ if (!appendIfNew(pointArray, pnt)) return;// kdDebug(6040) << "appendPoint: appended " << pnt << endl; reduceSegmentSeparator(pointArray) || reduceSpike(pointArray);}/** * Traverses the horizontal inline boxes and appends the point coordinates to * the given array. * @param box inline box * @param pointArray array collecting coordinates * @param bottom \c true, collect bottom coordinates, \c false, collect top * coordinates. * @param limit lower limit that an y-coordinate must at least reach. Note * that limit designates the highest y-coordinate for \c bottom, and * the lowest for !\c bottom. */static void collectHorizontalBoxCoordinates(InlineBox *box, QValueVector<QPoint> &pointArray, bool bottom, int limit = -500000){// kdDebug(6000) << "collectHorizontalBoxCoordinates: " << endl; int y = box->yPos() + bottom*box->height(); if (limit != -500000 && (bottom ? y < limit : y > limit)) y = limit; int x = box->xPos() + bottom*box->width(); QPoint newPnt(x, y); // Add intersection point if point-array not empty. if (!pointArray.isEmpty()) { QPoint lastPnt = pointArray.back(); QPoint insPnt(newPnt.x(), lastPnt.y());// kdDebug(6040) << "left: " << lastPnt << " == " << insPnt << ": " << (insPnt == lastPnt) << endl; appendPoint(pointArray, insPnt); } // Insert starting point of box appendPoint(pointArray, newPnt); newPnt.rx() += bottom ? -box->width() : box->width(); if (box->isInlineFlowBox()) { InlineFlowBox *flowBox = static_cast<InlineFlowBox *>(box); for (InlineBox *b = bottom ? flowBox->lastChild() : flowBox->firstChild(); b; b = bottom ? b->prevOnLine() : b->nextOnLine()) { // Don't let boxes smaller than this flow box' height influence // the vertical position of the outline if they have a different // x-coordinate int l2; if (b->xPos() != box->xPos() && b->xPos() + b->width() != box->xPos() + box->width()) l2 = y; else l2 = limit; collectHorizontalBoxCoordinates(b, pointArray, bottom, l2); } // Add intersection point if flow box contained any children if (flowBox->firstChild()) { QPoint lastPnt = pointArray.back(); QPoint insPnt(lastPnt.x(), newPnt.y());// kdDebug(6040) << "right: " << lastPnt << " == " << insPnt << ": " << (insPnt == lastPnt) << endl; appendPoint(pointArray, insPnt); } } // Insert ending point of box appendPoint(pointArray, newPnt);// kdDebug(6000) << "collectHorizontalBoxCoordinates: " << "ende" << endl;}/** * Checks whether the given line box' extents and the following line box' * extents are disjount (i. e. do not share the same x-coordinate range). * @param line line box * @param toBegin \c true, compare with preceding line box, \c false, with * succeeding * @return \c true if this and the next box are disjoint */inline static bool lineBoxesDisjoint(InlineRunBox *line, bool toBegin){ InlineRunBox *next = toBegin ? line->prevLineBox() : line->nextLineBox(); return !next || next->xPos() + next->width() < line->xPos() || next->xPos() > line->xPos() + line->width();}/** * Traverses the vertical outer borders of the given render flow's line * boxes and appends the point coordinates to the given point array. * @param line line box to begin traversal * @param pointArray point array * @param left \c true, traverse the left vertical coordinates, * \c false, traverse the right vertical coordinates. * @param lastline if not 0, returns the pointer to the last line box traversed */static void collectVerticalBoxCoordinates(InlineRunBox *line, QValueVector<QPoint> &pointArray, bool left, InlineRunBox **lastline = 0){ InlineRunBox *last = 0; for (InlineRunBox* curr = line; curr && !last; curr = left ? curr->prevLineBox() : curr->nextLineBox()) { InlineBox *root = curr; bool isLast = lineBoxesDisjoint(curr, left); if (isLast) last = curr; if (root != line && !isLast) while (root->parent()) root = root->parent(); QPoint newPnt(curr->xPos() + !left*curr->width(), left ? root->topOverflow() : root->bottomOverflow()); if (!pointArray.isEmpty()) { QPoint lastPnt = pointArray.back(); if (newPnt.x()>lastPnt.x() && !left) pointArray.back().setY( kMin(lastPnt.y(), root->topOverflow()) ); else if (newPnt.x()<lastPnt.x() && left) pointArray.back().setY( kMax(lastPnt.y(), root->bottomOverflow()) ); QPoint insPnt(newPnt.x(), pointArray.back().y());// kdDebug(6040) << "left: " << lastPnt << " == " << insPnt << ": " << (insPnt == lastPnt) << endl; appendPoint(pointArray, insPnt); } appendPoint(pointArray, newPnt); } if (lastline) *lastline = last;}/** * Links up the end of the given point-array such that the starting point * is not a segment separator. * * To achieve this, improper points are removed from the beginning of * the point-array (by changing the array's starting iterator), and * proper ones appended to the point-array's back. * * @param pointArray point-array * @return actual begin of point array */static QPoint *linkEndToBegin(QValueVector<QPoint> &pointArray){ uint index = 0; Q_ASSERT(pointArray.size() >= 3); // if first and last points match, ignore the last one. bool linkup = false; QPoint linkupPnt; if (pointArray.front() == pointArray.back()) { linkupPnt = pointArray.back(); pointArray.pop_back(); linkup = true; } const QPoint *it = pointArray.begin() + index; QPoint pfirst = *it; QPoint pnext = *++it; QPoint plast = pointArray.back();// kdDebug(6040) << "linkcheck plast: " << plast << " pfirst: " << pfirst << " pnext: " << pnext << endl; if (plast.x() == pfirst.x() && pfirst.x() == pnext.x() || plast.y() == pfirst.y() && pfirst.y() == pnext.y()) { ++index; appendPoint(pointArray, pfirst); appendPoint(pointArray, pnext); } else if (linkup) pointArray.push_back(linkupPnt); return pointArray.begin() + index;}void RenderInline::paintOutlines(QPainter *p, int _tx, int _ty){ if (style()->outlineWidth() == 0 || style()->outlineStyle() <= BHIDDEN) return; // We may have to draw more than one outline path as they may be // disjoint. for (InlineRunBox *curr = firstLineBox(); curr; curr = curr->nextLineBox()) { QValueVector<QPoint> path; // collect topmost outline collectHorizontalBoxCoordinates(curr, path, false); // collect right outline collectVerticalBoxCoordinates(curr, path, false, &curr); // collect bottommost outline collectHorizontalBoxCoordinates(curr, path, true); // collect left outline collectVerticalBoxCoordinates(curr, path, true); const QPoint *begin = linkEndToBegin(path); // paint the outline paintOutlinePath(p, _tx, _ty, begin, path.end(), BSLeft, -1, BSTop); }}template<class T> inline void kSwap(T &a1, T &a2){ T tmp = a2; a2 = a1; a1 = tmp;}enum BSOrientation { BSHorizontal, BSVertical };/** * Returns the orientation of the given border side. */inline BSOrientation bsOrientation(RenderObject::BorderSide bs){ switch (bs) { case RenderObject::BSTop: case RenderObject::BSBottom: return BSHorizontal; case RenderObject::BSLeft: case RenderObject::BSRight: return BSVertical; } return BSHorizontal; // make gcc happy (sigh)}/** * Determines the new border side by evaluating the new direction as determined * by the given coordinates, the old border side, and the relative direction. * * The relative direction specifies whether the old border side meets with the * straight given by the coordinates from below (negative), or above (positive). */inline RenderObject::BorderSide newBorderSide(RenderObject::BorderSide oldBS, int direction, const QPoint &last, const QPoint &cur){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -