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

📄 svginlinetextbox.cpp

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 CPP
📖 第 1 页 / 共 2 页
字号:
    // If we are past the last glyph of this box, don't mark it as 'hit'    if (x >= charAtPos.x + glyphRect.width() && closestOffsetInBox == (int) end())        return false;    return true;}int SVGInlineTextBox::offsetForPosition(int, bool) const{    // SVG doesn't use the offset <-> position selection system.     ASSERT_NOT_REACHED();    return 0;}int SVGInlineTextBox::positionForOffset(int) const{    // SVG doesn't use the offset <-> position selection system.     ASSERT_NOT_REACHED();    return 0;}bool SVGInlineTextBox::nodeAtPoint(const HitTestRequest&, HitTestResult& result, int x, int y, int tx, int ty){    ASSERT(!isLineBreak());    IntRect rect = selectionRect(0, 0, 0, len());    if (renderer()->style()->visibility() == VISIBLE && rect.contains(x, y)) {        renderer()->updateHitTestResult(result, IntPoint(x - tx, y - ty));        return true;    }    return false;}IntRect SVGInlineTextBox::selectionRect(int, int, int startPos, int endPos){    if (startPos >= endPos)        return IntRect();    // TODO: Actually respect startPos/endPos - we're returning the _full_ selectionRect    // here. This won't lead to visible bugs, but to extra work being done. Investigate.    SVGRootInlineBox* rootBox = svgRootInlineBox();    if (!rootBox)        return IntRect();    SVGInlineTextBoxSelectionRectWalker walkerCallback;    SVGTextChunkWalker<SVGInlineTextBoxSelectionRectWalker> walker(&walkerCallback, &SVGInlineTextBoxSelectionRectWalker::chunkPortionCallback);    rootBox->walkTextChunks(&walker, this);    return enclosingIntRect(walkerCallback.selectionRect());}void SVGInlineTextBox::paintCharacters(RenderObject::PaintInfo& paintInfo, int tx, int ty, const SVGChar& svgChar, const UChar* chars, int length, SVGPaintServer* activePaintServer){    if (renderer()->style()->visibility() != VISIBLE || paintInfo.phase == PaintPhaseOutline)        return;    ASSERT(paintInfo.phase != PaintPhaseSelfOutline && paintInfo.phase != PaintPhaseChildOutlines);    RenderText* text = textRenderer();    ASSERT(text);    bool isPrinting = text->document()->printing();    // Determine whether or not we're selected.    bool haveSelection = !isPrinting && selectionState() != RenderObject::SelectionNone;    if (!haveSelection && paintInfo.phase == PaintPhaseSelection)        // When only painting the selection, don't bother to paint if there is none.        return;    // Determine whether or not we have a composition.    bool containsComposition = text->document()->frame()->editor()->compositionNode() == text->node();    bool useCustomUnderlines = containsComposition && text->document()->frame()->editor()->compositionUsesCustomUnderlines();    // Set our font    RenderStyle* styleToUse = text->style(isFirstLineStyle());    const Font& font = styleToUse->font();    TransformationMatrix ctm = svgChar.characterTransform();    if (!ctm.isIdentity())        paintInfo.context->concatCTM(ctm);    // 1. Paint backgrounds behind text if needed.  Examples of such backgrounds include selection    // and marked text.    if (paintInfo.phase != PaintPhaseSelection && !isPrinting) {#if PLATFORM(MAC)        // Custom highlighters go behind everything else.        if (styleToUse->highlight() != nullAtom && !paintInfo.context->paintingDisabled())            paintCustomHighlight(tx, ty, styleToUse->highlight());#endif        if (containsComposition && !useCustomUnderlines)            paintCompositionBackground(paintInfo.context, tx, ty, styleToUse, font,                                        text->document()->frame()->editor()->compositionStart(),                                       text->document()->frame()->editor()->compositionEnd());                paintDocumentMarkers(paintInfo.context, tx, ty, styleToUse, font, true);        if (haveSelection && !useCustomUnderlines) {            int boxStartOffset = chars - text->characters() - start();            paintSelection(boxStartOffset, svgChar, chars, length, paintInfo.context, styleToUse, font);        }    }    // Set a text shadow if we have one.    // FIXME: Support multiple shadow effects.  Need more from the CG API before    // we can do this.    bool setShadow = false;    if (styleToUse->textShadow()) {        paintInfo.context->setShadow(IntSize(styleToUse->textShadow()->x, styleToUse->textShadow()->y),                                     styleToUse->textShadow()->blur, styleToUse->textShadow()->color);        setShadow = true;    }    IntPoint origin((int) svgChar.x, (int) svgChar.y);    TextRun run = svgTextRunForInlineTextBox(chars, length, styleToUse, this, svgChar.x);#if ENABLE(SVG_FONTS)    // SVG Fonts need access to the paint server used to draw the current text chunk.    // They need to be able to call renderPath() on a SVGPaintServer object.    run.setActivePaintServer(activePaintServer);#endif    paintInfo.context->drawText(font, run, origin);    if (paintInfo.phase != PaintPhaseSelection) {        paintDocumentMarkers(paintInfo.context, tx, ty, styleToUse, font, false);        if (useCustomUnderlines) {            const Vector<CompositionUnderline>& underlines = text->document()->frame()->editor()->customCompositionUnderlines();            size_t numUnderlines = underlines.size();                        for (size_t index = 0; index < numUnderlines; ++index) {                const CompositionUnderline& underline = underlines[index];                                if (underline.endOffset <= start())                    // underline is completely before this run.  This might be an underline that sits                    // before the first run we draw, or underlines that were within runs we skipped                     // due to truncation.                    continue;                                if (underline.startOffset <= end()) {                    // underline intersects this run.  Paint it.                    paintCompositionUnderline(paintInfo.context, tx, ty, underline);                    if (underline.endOffset > end() + 1)                        // underline also runs into the next run. Bail now, no more marker advancement.                        break;                } else                    // underline is completely after this run, bail.  A later run will paint it.                    break;            }        }            }    if (setShadow)        paintInfo.context->clearShadow();    if (!ctm.isIdentity())        paintInfo.context->concatCTM(ctm.inverse());}void SVGInlineTextBox::paintSelection(int boxStartOffset, const SVGChar& svgChar, const UChar*, int length, GraphicsContext* p, RenderStyle* style, const Font& font){    if (selectionState() == RenderObject::SelectionNone)        return;    int startPos, endPos;    selectionStartEnd(startPos, endPos);    if (startPos >= endPos)        return;    Color textColor = style->color();    Color color = renderer()->selectionBackgroundColor();    if (!color.isValid() || color.alpha() == 0)        return;    // If the text color ends up being the same as the selection background, invert the selection    // background.  This should basically never happen, since the selection has transparency.    if (textColor == color)        color = Color(0xff - color.red(), 0xff - color.green(), 0xff - color.blue());    // Map from text box positions and a given start offset to chunk positions    // 'boxStartOffset' represents the beginning of the text chunk.    if ((startPos > boxStartOffset && endPos > boxStartOffset + length) || boxStartOffset >= endPos)        return;    if (endPos > boxStartOffset + length)        endPos = boxStartOffset + length;    if (startPos < boxStartOffset)        startPos = boxStartOffset;    ASSERT(startPos >= boxStartOffset);    ASSERT(endPos <= boxStartOffset + length);    ASSERT(startPos < endPos);    p->save();    int adjust = startPos >= boxStartOffset ? boxStartOffset : 0;    p->drawHighlightForText(font, svgTextRunForInlineTextBox(textRenderer()->text()->characters() + start() + boxStartOffset, length, style, this, svgChar.x),                            IntPoint((int) svgChar.x, (int) svgChar.y - font.ascent()),                            font.ascent() + font.descent(), color, startPos - adjust, endPos - adjust);    p->restore();}static inline Path pathForDecoration(ETextDecoration decoration, RenderObject* object, float x, float y, float width){    float thickness = SVGRenderStyle::cssPrimitiveToLength(object, object->style()->svgStyle()->strokeWidth(), 1.0f);    const Font& font = object->style()->font();    thickness = max(thickness * powf(font.size(), 2.0f) / font.unitsPerEm(), 1.0f);    if (decoration == UNDERLINE)        y += thickness * 1.5f; // For compatibility with Batik/Opera    else if (decoration == OVERLINE)        y += thickness;    float halfThickness = thickness / 2.0f;    return Path::createRectangle(FloatRect(x + halfThickness, y, width - 2.0f * halfThickness, thickness));}void SVGInlineTextBox::paintDecoration(ETextDecoration decoration, GraphicsContext* context, int tx, int ty, int width, const SVGChar& svgChar, const SVGTextDecorationInfo& info){    if (renderer()->style()->visibility() != VISIBLE)        return;    // This function does NOT accept combinated text decorations. It's meant to be invoked for just one.    ASSERT(decoration == TDNONE || decoration == UNDERLINE || decoration == OVERLINE || decoration == LINE_THROUGH || decoration == BLINK);    bool isFilled = info.fillServerMap.contains(decoration);    bool isStroked = info.strokeServerMap.contains(decoration);    if (!isFilled && !isStroked)        return;    int baseline = renderer()->style(m_firstLine)->font().ascent();    if (decoration == UNDERLINE)        ty += baseline;    else if (decoration == LINE_THROUGH)        ty += 2 * baseline / 3;    context->save();    context->beginPath();    TransformationMatrix ctm = svgChar.characterTransform();    if (!ctm.isIdentity())        context->concatCTM(ctm);    if (isFilled) {        if (RenderObject* fillObject = info.fillServerMap.get(decoration)) {            if (SVGPaintServer* fillPaintServer = SVGPaintServer::fillPaintServer(fillObject->style(), fillObject)) {                context->addPath(pathForDecoration(decoration, fillObject, tx, ty, width));                fillPaintServer->draw(context, fillObject, ApplyToFillTargetType);            }        }    }    if (isStroked) {        if (RenderObject* strokeObject = info.strokeServerMap.get(decoration)) {            if (SVGPaintServer* strokePaintServer = SVGPaintServer::strokePaintServer(strokeObject->style(), strokeObject)) {                context->addPath(pathForDecoration(decoration, strokeObject, tx, ty, width));                strokePaintServer->draw(context, strokeObject, ApplyToStrokeTargetType);            }        }    }    context->restore();}} // namespace WebCore#endif

⌨️ 快捷键说明

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