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

📄 khtml_caret.cpp

📁 konqueror3 embedded版本, KDE环境下的当家浏览器的嵌入式版本源码包.
💻 CPP
📖 第 1 页 / 共 5 页
字号:
#endif      // must be an inline-block, inline-table, or any RenderReplaced      bool rtl = ps->direction() == RTL;      const QFontMetrics &pfm = ps->fontMetrics();      if (coalesceOutsideBoxes) {        if (sbp.equalsBox(box, true, false)) {          sbp.it = lastCoalescedBox;          Q_ASSERT(!sbp.found);          sbp.found = true;        }      } else {        addCreatedInlineBoxEdge(box, pfm, true, rtl);        sbp.check(preEnd());      }      caret_boxes.append(new CaretBox(box, false, false));      sbp.check(preEnd());      addCreatedInlineBoxEdge(box, pfm, false, rtl);      lastCoalescedBox = preEnd();      sbp.check(lastCoalescedBox);      coalesceOutsideBoxes = true;    }/*end if*/  }/*next box*/}#undef DEBUG_ACIBvoid CaretBoxLine::addCreatedFlowBoxInside(InlineFlowBox *flowBox, const QFontMetrics &fm) /*KDE_NO_EXPORT*/{  CaretBox *caretBox = new CaretBox(flowBox, false, false);  caret_boxes.append(caretBox);  // afaik an inner flow box can only have the width 0, therefore we don't  // have to care for rtl or alignment  // ### can empty inline elements have a width? css 2 spec isn't verbose about it  caretBox->_y += flowBox->baseline() - fm.ascent();  caretBox->_h = fm.height();}void CaretBoxLine::addCreatedFlowBoxEdge(InlineFlowBox *flowBox, const QFontMetrics &fm, bool left, bool rtl) /*KDE_NO_EXPORT*/{  CaretBox *caretBox = new CaretBox(flowBox, true, !left);  caret_boxes.append(caretBox);  if (left ^ rtl) caretBox->_x -= flowBox->paddingLeft() + flowBox->borderLeft() + 1;  else caretBox->_x += caretBox->_w + flowBox->paddingRight() + flowBox->borderRight();  caretBox->_y += flowBox->baseline() - fm.ascent();  caretBox->_h = fm.height();  caretBox->_w = 1;}void CaretBoxLine::addCreatedInlineBoxEdge(InlineBox *box, const QFontMetrics &fm, bool left, bool rtl) /*KDE_NO_EXPORT*/{  CaretBox *caretBox = new CaretBox(box, true, !left);  caret_boxes.append(caretBox);  if (left ^ rtl) caretBox->_x--;  else caretBox->_x += caretBox->_w;  caretBox->_y += box->baseline() - fm.ascent();  caretBox->_h = fm.height();  caretBox->_w = 1;}CaretBoxLine *CaretBoxLine::constructCaretBoxLine(CaretBoxLineDeleter *deleter,	InlineFlowBox *basicFlowBox, InlineBox *seekBox, bool seekOutside,        bool seekOutsideEnd, CaretBoxIterator &iter, RenderObject *seekObject)// 	KDE_NO_EXPORT{  // Iterate all inline boxes within this inline flow box.  // Caret boxes will be created for each  // - outside begin of an inline flow box (except for the basic inline flow box)  // - outside end of an inline flow box (except for the basic inline flow box)  // - inside of an empty inline flow box  // - outside begin of an inline box resembling a replaced element  // - outside end of an inline box resembling a replaced element  // - inline text box  // - inline replaced box  CaretBoxLine *result = new CaretBoxLine(basicFlowBox);  deleter->append(result);  SeekBoxParams sbp(seekBox, seekOutside, seekOutsideEnd, seekObject, iter);  // iterate recursively, I'm too lazy to do it iteratively  result->addConvertedInlineBox(basicFlowBox, sbp);  if (!sbp.found) sbp.it = result->end();  return result;}CaretBoxLine *CaretBoxLine::constructCaretBoxLine(CaretBoxLineDeleter *deleter,	RenderBox *cb, bool outside, bool outsideEnd, CaretBoxIterator &iter) /*KDE_NO_EXPORT*/{  int _x = cb->xPos();  int _y = cb->yPos();  int height;  int width = 1;		// no override is indicated in boxes  if (outside) {    RenderStyle *s = cb->element() && cb->element()->parent()			&& cb->element()->parent()->renderer()			? cb->element()->parent()->renderer()->style()			: cb->style();    bool rtl = s->direction() == RTL;    const QFontMetrics &fm = s->fontMetrics();    height = fm.height();    if (!outsideEnd) {        _x--;    } else {        _x += cb->width();    }    int hl = fm.leading() / 2;    int baseline = cb->baselinePosition(false);    if (!cb->isReplaced() || cb->style()->display() == BLOCK) {        if (!outsideEnd ^ rtl)            _y -= fm.leading() / 2;        else            _y += kMax(cb->height() - fm.ascent() - hl, 0);    } else {        _y += baseline - fm.ascent() - hl;    }  } else {		// !outside    RenderStyle *s = cb->style();    const QFontMetrics &fm = s->fontMetrics();    height = fm.height();    _x += cb->borderLeft() + cb->paddingLeft();    _y += cb->borderTop() + cb->paddingTop();    // ### regard direction    switch (s->textAlign()) {      case LEFT:      case KHTML_LEFT:      case TAAUTO:	// ### find out what this does      case JUSTIFY:        break;      case CENTER:      case KHTML_CENTER:        _x += cb->contentWidth() / 2;        break;      case KHTML_RIGHT:      case RIGHT:        _x += cb->contentWidth();        break;    }/*end switch*/  }/*end if*/  CaretBoxLine *result = new CaretBoxLine;  deleter->append(result);  result->caret_boxes.append(new CaretBox(_x, _y, width, height, cb,  			outside, outsideEnd));  iter = result->begin();  return result;}#if DEBUG_CARETMODE > 0void CaretBoxLine::dump(QTextStream &ts, const QString &ind) const{  ts << ind << "cbl: baseFlowBox@" << basefb << endl;  QString ind2 = ind + "  ";  for (size_t i = 0; i < caret_boxes.size(); i++) {    if (i > 0) ts << endl;    caret_boxes[i]->dump(ts, ind2);  }}#endif// == caret mode related helper functions/** seeks the root line box that is the parent of the given inline box. * @param b given inline box * @param base base render object which not to step over. If \c base's *	inline flow box is hit before the root line box, the flow box *	is returned instead. * @return the root line box or the base flow box. */inline InlineFlowBox *seekBaseFlowBox(InlineBox *b, RenderObject *base = 0){  // Seek root line box or base inline flow box, if \c base is interfering.  while (b->parent() && b->object() != base) {    b = b->parent();  }/*wend*/  Q_ASSERT(b->isInlineFlowBox());  return static_cast<InlineFlowBox *>(b);}/** determines whether the given element is a block level replaced element. */inline bool isBlockRenderReplaced(RenderObject *r){  return r->isRenderReplaced() && r->style()->display() == BLOCK;}/** determines the caret line box that contains the given position. * * If the node does not map to a render object, the function will snap to * the next suitable render object following it. * * @param node node to begin with * @param offset zero-based offset within node. * @param cblDeleter deleter for caret box lines * @param base base render object which the caret must not be placed beyond. * @param r_ofs adjusted offset within render object * @param caretBoxIt returns an iterator to the caret box that contains the *	given position. * @return the determined caret box lineor 0 if either the node is 0 or *	there is no inline flow box containing this node. The containing block *	will still be set. If it is 0 too, @p node was invalid. */static CaretBoxLine* findCaretBoxLine(DOM::NodeImpl *node, long offset,		CaretBoxLineDeleter *cblDeleter, RenderObject *base,                long &r_ofs, CaretBoxIterator &caretBoxIt){  bool outside, outsideEnd;  RenderObject *r = findRenderer(node, offset, base, r_ofs, outside, outsideEnd);  if (!r) { return 0; }#if DEBUG_CARETMODE > 0  kdDebug(6200) << "=================== findCaretBoxLine" << endl;  kdDebug(6200) << "node " << node << " offset: " << offset << " r " << r->renderName() << "[" << r << "].node " << r->element()->nodeName().string() << "[" << r->element() << "]" << " r_ofs " << r_ofs << " outside " << outside << " outsideEnd " << outsideEnd << endl;#endif  // There are two strategies to find the correct line box. (The third is failsafe)  // (A) First, if node's renderer is a RenderText, we only traverse its text  // runs and return the root line box (saves much time for long blocks).  // This should be the case 99% of the time.  // (B) Second, we derive the inline flow box directly when the renderer is  // a RenderBlock, RenderInline, or blocked RenderReplaced.  // (C) Otherwise, we iterate linearly through all line boxes in order to find  // the renderer.  // (A)  if (r->isText()) do {    RenderText *t = static_cast<RenderText *>(r);    int dummy;    InlineBox *b = t->findInlineTextBox(offset, dummy, true);    // Actually b should never be 0, but some render texts don't have text    // boxes, so we insert the last run as an error correction.    // If there is no last run, we resort to (B)    if (!b) {      if (t->m_lines.count() > 0)        b = t->m_lines[t->m_lines.count() - 1];      else        break;    }/*end if*/    Q_ASSERT(b);    outside = false;	// text boxes cannot have outside positions    InlineFlowBox *baseFlowBox = seekBaseFlowBox(b, base);#if DEBUG_CARETMODE > 2  kdDebug(6200) << "text-box b: " << b << " baseFlowBox: " << baseFlowBox << (b && b->object() ? QString(" contains \"%1\"").arg(QConstString(static_cast<RenderText *>(b->object())->str->s+b->minOffset(), kMin(b->maxOffset() - b->minOffset(), 15L)).string()) : QString::null) << endl;#endif#if 0    if (t->containingBlock()->isListItem()) dumpLineBoxes(static_cast<RenderFlow *>(t->containingBlock()));#endif#if DEBUG_CARETMODE > 0  kdDebug(6200) << "=================== end findCaretBoxLine (renderText)" << endl;#endif    return CaretBoxLine::constructCaretBoxLine(cblDeleter, baseFlowBox,        b, outside, outsideEnd, caretBoxIt);  } while(false);/*end if*/  // (B)  bool isrepl = isBlockRenderReplaced(r);  if (r->isRenderBlock() || r->isRenderInline() || isrepl) {    RenderFlow *flow = static_cast<RenderFlow *>(r);    InlineFlowBox *firstLineBox = isrepl ? 0 : flow->firstLineBox();    // On render blocks, if we are outside, or have a totally empty render    // block, we simply construct a special caret box line.    // The latter case happens only when the render block is a leaf object itself.    if (isrepl || r->isRenderBlock() && (outside || !firstLineBox)    		|| r->isRenderInline() && !firstLineBox) {  #if DEBUG_CARETMODE > 0    kdDebug(6200) << "=================== end findCaretBoxLine (box " << (outside ? (outsideEnd ? "outside end" : "outside begin") : "inside") << ")" << endl;  #endif      Q_ASSERT(r->isBox());      return CaretBoxLine::constructCaretBoxLine(cblDeleter,      		static_cast<RenderBox *>(r), outside, outsideEnd, caretBoxIt);    }/*end if*/  kdDebug(6200) << "firstlinebox " << firstLineBox << endl;    InlineFlowBox *baseFlowBox = seekBaseFlowBox(firstLineBox, base);    return CaretBoxLine::constructCaretBoxLine(cblDeleter, baseFlowBox,        firstLineBox, outside, outsideEnd, caretBoxIt);  }/*end if*/  RenderBlock *cb = r->containingBlock();  //if ( !cb ) return 0L;  Q_ASSERT(cb);  // ### which element doesn't have a block as its containing block?  // Is it still possible after the RenderBlock/RenderInline merge?  if (!cb->isRenderBlock()) {    kdWarning() << "containing block is no render block!!! crash imminent" << endl;  }/*end if*/  InlineFlowBox *flowBox = cb->firstLineBox();  // (C)  // This case strikes when the element is replaced, but neither a  // RenderBlock nor a RenderInline  if (!flowBox) {	// ### utter emergency (why is this possible at all?)//    flowBox = generateDummyFlowBox(arena, cb, r);//    if (ibox) *ibox = flowBox->firstChild();//    outside = outside_end = true;//    kdWarning() << "containing block contains no inline flow boxes!!! crash imminent" << endl;#if DEBUG_CARETMODE > 0   kdDebug(6200) << "=================== end findCaretBoxLine (2)" << endl;#endif    return CaretBoxLine::constructCaretBoxLine(cblDeleter, cb,			outside, outsideEnd, caretBoxIt);  }/*end if*/  // We iterate the inline flow boxes of the containing block until  // we find the given node. This has one major flaw: it is linear, and therefore  // painfully slow for really large blocks.  for (; flowBox; flowBox = static_cast<InlineFlowBox *>(flowBox->nextLineBox())) {#if DEBUG_CARETMODE > 0    kdDebug(6200) << "[scan line]" << endl;#endif    // construct a caret line box and stop when the element is contained within    InlineFlowBox *baseFlowBox = seekBaseFlowBox(flowBox, base);    CaretBoxLine *cbl = CaretBoxLine::constructCaretBoxLine(cblDeleter,        baseFlowBox, 0, outside, outsideEnd, caretBoxIt, r);#if DEBUG_CARETMODE > 5    kdDebug(6200) << cbl->information() << endl;#endif    if (caretBoxIt != cbl->end()) {#if DEBUG_CARETMODE > 0   kdDebug(6200) << "=================== end findCaretBoxLine (3)" << endl;#endif      return cbl;    }  }/*next flowBox*/  // no inline flow box found, approximate to nearest following node.  // Danger: this is O(n^2). It's only called to recover from  // errors, that means, theoretically, never. (Practically, far too often :-( )  Q_ASSERT(!flowBox);  CaretBoxLine *cbl = findCaretBoxLine(nextLeafNode(node, base ? base->element() : 0), 0, cblDeleter, base, r_ofs, caretBoxIt);#if DEBUG_CARETMODE > 0  kdDebug(6200) << "=================== end findCaretBoxLine" << endl;#endif  return cbl;}/** finds the innermost table object @p r is contained within, but no * farther than @p cb. * @param r leaf element to begin with * @param cb bottom element where to stop search at least. * @return the table object or 0 if none found. */static inline RenderTable *findTableUpTo(RenderObject *r, RenderFlow *cb){  while (r && r != cb && !r->isTable()) r = r->parent();  return r && r->isTable() ? static_cast<RenderTable *>(r) : 0;}/** checks whether @p r is a descendant of @p cb, or r == cb

⌨️ 快捷键说明

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