12bde8e466a4451c7319e3a072d118917957d6554Steve Block/*
22bde8e466a4451c7319e3a072d118917957d6554Steve Block * Copyright (C) 2011 Google Inc. All rights reserved.
32bde8e466a4451c7319e3a072d118917957d6554Steve Block *
42bde8e466a4451c7319e3a072d118917957d6554Steve Block * Redistribution and use in source and binary forms, with or without
52bde8e466a4451c7319e3a072d118917957d6554Steve Block * modification, are permitted provided that the following conditions
62bde8e466a4451c7319e3a072d118917957d6554Steve Block * are met:
72bde8e466a4451c7319e3a072d118917957d6554Steve Block *
82bde8e466a4451c7319e3a072d118917957d6554Steve Block * 1.  Redistributions of source code must retain the above copyright
92bde8e466a4451c7319e3a072d118917957d6554Steve Block *     notice, this list of conditions and the following disclaimer.
102bde8e466a4451c7319e3a072d118917957d6554Steve Block * 2.  Redistributions in binary form must reproduce the above copyright
112bde8e466a4451c7319e3a072d118917957d6554Steve Block *     notice, this list of conditions and the following disclaimer in the
122bde8e466a4451c7319e3a072d118917957d6554Steve Block *     documentation and/or other materials provided with the distribution.
132bde8e466a4451c7319e3a072d118917957d6554Steve Block * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
142bde8e466a4451c7319e3a072d118917957d6554Steve Block *     its contributors may be used to endorse or promote products derived
152bde8e466a4451c7319e3a072d118917957d6554Steve Block *     from this software without specific prior written permission.
162bde8e466a4451c7319e3a072d118917957d6554Steve Block *
172bde8e466a4451c7319e3a072d118917957d6554Steve Block * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
182bde8e466a4451c7319e3a072d118917957d6554Steve Block * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
192bde8e466a4451c7319e3a072d118917957d6554Steve Block * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
202bde8e466a4451c7319e3a072d118917957d6554Steve Block * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
212bde8e466a4451c7319e3a072d118917957d6554Steve Block * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
222bde8e466a4451c7319e3a072d118917957d6554Steve Block * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
232bde8e466a4451c7319e3a072d118917957d6554Steve Block * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
242bde8e466a4451c7319e3a072d118917957d6554Steve Block * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
252bde8e466a4451c7319e3a072d118917957d6554Steve Block * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
262bde8e466a4451c7319e3a072d118917957d6554Steve Block * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272bde8e466a4451c7319e3a072d118917957d6554Steve Block */
282bde8e466a4451c7319e3a072d118917957d6554Steve Block
292bde8e466a4451c7319e3a072d118917957d6554Steve Block#include "config.h"
302bde8e466a4451c7319e3a072d118917957d6554Steve Block#include "DOMNodeHighlighter.h"
312bde8e466a4451c7319e3a072d118917957d6554Steve Block
322bde8e466a4451c7319e3a072d118917957d6554Steve Block#if ENABLE(INSPECTOR)
332bde8e466a4451c7319e3a072d118917957d6554Steve Block
342bde8e466a4451c7319e3a072d118917957d6554Steve Block#include "Element.h"
352bde8e466a4451c7319e3a072d118917957d6554Steve Block#include "Frame.h"
362bde8e466a4451c7319e3a072d118917957d6554Steve Block#include "FrameView.h"
372bde8e466a4451c7319e3a072d118917957d6554Steve Block#include "GraphicsContext.h"
382bde8e466a4451c7319e3a072d118917957d6554Steve Block#include "Page.h"
392bde8e466a4451c7319e3a072d118917957d6554Steve Block#include "Range.h"
402bde8e466a4451c7319e3a072d118917957d6554Steve Block#include "RenderInline.h"
412bde8e466a4451c7319e3a072d118917957d6554Steve Block#include "Settings.h"
422bde8e466a4451c7319e3a072d118917957d6554Steve Block#include "StyledElement.h"
432bde8e466a4451c7319e3a072d118917957d6554Steve Block#include "TextRun.h"
442bde8e466a4451c7319e3a072d118917957d6554Steve Block
452bde8e466a4451c7319e3a072d118917957d6554Steve Blocknamespace WebCore {
462bde8e466a4451c7319e3a072d118917957d6554Steve Block
472bde8e466a4451c7319e3a072d118917957d6554Steve Blocknamespace {
482bde8e466a4451c7319e3a072d118917957d6554Steve Block
492bde8e466a4451c7319e3a072d118917957d6554Steve BlockPath quadToPath(const FloatQuad& quad)
502bde8e466a4451c7319e3a072d118917957d6554Steve Block{
512bde8e466a4451c7319e3a072d118917957d6554Steve Block    Path quadPath;
522bde8e466a4451c7319e3a072d118917957d6554Steve Block    quadPath.moveTo(quad.p1());
532bde8e466a4451c7319e3a072d118917957d6554Steve Block    quadPath.addLineTo(quad.p2());
542bde8e466a4451c7319e3a072d118917957d6554Steve Block    quadPath.addLineTo(quad.p3());
552bde8e466a4451c7319e3a072d118917957d6554Steve Block    quadPath.addLineTo(quad.p4());
562bde8e466a4451c7319e3a072d118917957d6554Steve Block    quadPath.closeSubpath();
572bde8e466a4451c7319e3a072d118917957d6554Steve Block    return quadPath;
582bde8e466a4451c7319e3a072d118917957d6554Steve Block}
592bde8e466a4451c7319e3a072d118917957d6554Steve Block
602bde8e466a4451c7319e3a072d118917957d6554Steve Blockvoid drawOutlinedQuad(GraphicsContext& context, const FloatQuad& quad, const Color& fillColor)
612bde8e466a4451c7319e3a072d118917957d6554Steve Block{
622bde8e466a4451c7319e3a072d118917957d6554Steve Block    static const int outlineThickness = 2;
632bde8e466a4451c7319e3a072d118917957d6554Steve Block    static const Color outlineColor(62, 86, 180, 228);
642bde8e466a4451c7319e3a072d118917957d6554Steve Block
652bde8e466a4451c7319e3a072d118917957d6554Steve Block    Path quadPath = quadToPath(quad);
662bde8e466a4451c7319e3a072d118917957d6554Steve Block
672bde8e466a4451c7319e3a072d118917957d6554Steve Block    // Clip out the quad, then draw with a 2px stroke to get a pixel
682bde8e466a4451c7319e3a072d118917957d6554Steve Block    // of outline (because inflating a quad is hard)
692bde8e466a4451c7319e3a072d118917957d6554Steve Block    {
702bde8e466a4451c7319e3a072d118917957d6554Steve Block        context.save();
712bde8e466a4451c7319e3a072d118917957d6554Steve Block        context.clipOut(quadPath);
722bde8e466a4451c7319e3a072d118917957d6554Steve Block
732bde8e466a4451c7319e3a072d118917957d6554Steve Block        context.setStrokeThickness(outlineThickness);
742bde8e466a4451c7319e3a072d118917957d6554Steve Block        context.setStrokeColor(outlineColor, ColorSpaceDeviceRGB);
752bde8e466a4451c7319e3a072d118917957d6554Steve Block        context.strokePath(quadPath);
762bde8e466a4451c7319e3a072d118917957d6554Steve Block
772bde8e466a4451c7319e3a072d118917957d6554Steve Block        context.restore();
782bde8e466a4451c7319e3a072d118917957d6554Steve Block    }
792bde8e466a4451c7319e3a072d118917957d6554Steve Block
802bde8e466a4451c7319e3a072d118917957d6554Steve Block    // Now do the fill
812bde8e466a4451c7319e3a072d118917957d6554Steve Block    context.setFillColor(fillColor, ColorSpaceDeviceRGB);
822bde8e466a4451c7319e3a072d118917957d6554Steve Block    context.fillPath(quadPath);
832bde8e466a4451c7319e3a072d118917957d6554Steve Block}
842bde8e466a4451c7319e3a072d118917957d6554Steve Block
852bde8e466a4451c7319e3a072d118917957d6554Steve Blockvoid drawOutlinedQuadWithClip(GraphicsContext& context, const FloatQuad& quad, const FloatQuad& clipQuad, const Color& fillColor)
862bde8e466a4451c7319e3a072d118917957d6554Steve Block{
872bde8e466a4451c7319e3a072d118917957d6554Steve Block    context.save();
882bde8e466a4451c7319e3a072d118917957d6554Steve Block    Path clipQuadPath = quadToPath(clipQuad);
892bde8e466a4451c7319e3a072d118917957d6554Steve Block    context.clipOut(clipQuadPath);
902bde8e466a4451c7319e3a072d118917957d6554Steve Block    drawOutlinedQuad(context, quad, fillColor);
912bde8e466a4451c7319e3a072d118917957d6554Steve Block    context.restore();
922bde8e466a4451c7319e3a072d118917957d6554Steve Block}
932bde8e466a4451c7319e3a072d118917957d6554Steve Block
942bde8e466a4451c7319e3a072d118917957d6554Steve Blockvoid drawHighlightForBox(GraphicsContext& context, const FloatQuad& contentQuad, const FloatQuad& paddingQuad, const FloatQuad& borderQuad, const FloatQuad& marginQuad)
952bde8e466a4451c7319e3a072d118917957d6554Steve Block{
962bde8e466a4451c7319e3a072d118917957d6554Steve Block    static const Color contentBoxColor(125, 173, 217, 128);
972bde8e466a4451c7319e3a072d118917957d6554Steve Block    static const Color paddingBoxColor(125, 173, 217, 160);
982bde8e466a4451c7319e3a072d118917957d6554Steve Block    static const Color borderBoxColor(125, 173, 217, 192);
992bde8e466a4451c7319e3a072d118917957d6554Steve Block    static const Color marginBoxColor(125, 173, 217, 228);
1002bde8e466a4451c7319e3a072d118917957d6554Steve Block
1012bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (marginQuad != borderQuad)
1022bde8e466a4451c7319e3a072d118917957d6554Steve Block        drawOutlinedQuadWithClip(context, marginQuad, borderQuad, marginBoxColor);
1032bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (borderQuad != paddingQuad)
1042bde8e466a4451c7319e3a072d118917957d6554Steve Block        drawOutlinedQuadWithClip(context, borderQuad, paddingQuad, borderBoxColor);
1052bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (paddingQuad != contentQuad)
1062bde8e466a4451c7319e3a072d118917957d6554Steve Block        drawOutlinedQuadWithClip(context, paddingQuad, contentQuad, paddingBoxColor);
1072bde8e466a4451c7319e3a072d118917957d6554Steve Block
1082bde8e466a4451c7319e3a072d118917957d6554Steve Block    drawOutlinedQuad(context, contentQuad, contentBoxColor);
1092bde8e466a4451c7319e3a072d118917957d6554Steve Block}
1102bde8e466a4451c7319e3a072d118917957d6554Steve Block
1112bde8e466a4451c7319e3a072d118917957d6554Steve Blockvoid drawHighlightForLineBoxesOrSVGRenderer(GraphicsContext& context, const Vector<FloatQuad>& lineBoxQuads)
1122bde8e466a4451c7319e3a072d118917957d6554Steve Block{
1132bde8e466a4451c7319e3a072d118917957d6554Steve Block    static const Color lineBoxColor(125, 173, 217, 128);
1142bde8e466a4451c7319e3a072d118917957d6554Steve Block
1152bde8e466a4451c7319e3a072d118917957d6554Steve Block    for (size_t i = 0; i < lineBoxQuads.size(); ++i)
1162bde8e466a4451c7319e3a072d118917957d6554Steve Block        drawOutlinedQuad(context, lineBoxQuads[i], lineBoxColor);
1172bde8e466a4451c7319e3a072d118917957d6554Steve Block}
1182bde8e466a4451c7319e3a072d118917957d6554Steve Block
1192bde8e466a4451c7319e3a072d118917957d6554Steve Blockinline IntSize frameToMainFrameOffset(Frame* frame)
1202bde8e466a4451c7319e3a072d118917957d6554Steve Block{
1212bde8e466a4451c7319e3a072d118917957d6554Steve Block    IntPoint mainFramePoint = frame->page()->mainFrame()->view()->windowToContents(frame->view()->contentsToWindow(IntPoint()));
1222bde8e466a4451c7319e3a072d118917957d6554Steve Block    return mainFramePoint - IntPoint();
1232bde8e466a4451c7319e3a072d118917957d6554Steve Block}
1242bde8e466a4451c7319e3a072d118917957d6554Steve Block
1252bde8e466a4451c7319e3a072d118917957d6554Steve Blockvoid drawElementTitle(GraphicsContext& context, Node* node, const IntRect& boundingBox, const IntRect& anchorBox, const FloatRect& overlayRect, WebCore::Settings* settings)
1262bde8e466a4451c7319e3a072d118917957d6554Steve Block{
1272bde8e466a4451c7319e3a072d118917957d6554Steve Block    static const int rectInflatePx = 4;
1282bde8e466a4451c7319e3a072d118917957d6554Steve Block    static const int fontHeightPx = 12;
1292bde8e466a4451c7319e3a072d118917957d6554Steve Block    static const int borderWidthPx = 1;
1302bde8e466a4451c7319e3a072d118917957d6554Steve Block    static const Color tooltipBackgroundColor(255, 255, 194, 255);
1312bde8e466a4451c7319e3a072d118917957d6554Steve Block    static const Color tooltipBorderColor(Color::black);
1322bde8e466a4451c7319e3a072d118917957d6554Steve Block    static const Color tooltipFontColor(Color::black);
1332bde8e466a4451c7319e3a072d118917957d6554Steve Block
1342bde8e466a4451c7319e3a072d118917957d6554Steve Block    Element* element = static_cast<Element*>(node);
1352bde8e466a4451c7319e3a072d118917957d6554Steve Block    bool isXHTML = element->document()->isXHTMLDocument();
1362bde8e466a4451c7319e3a072d118917957d6554Steve Block    String nodeTitle = isXHTML ? element->nodeName() : element->nodeName().lower();
1372bde8e466a4451c7319e3a072d118917957d6554Steve Block    const AtomicString& idValue = element->getIdAttribute();
1382bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (!idValue.isNull() && !idValue.isEmpty()) {
1392bde8e466a4451c7319e3a072d118917957d6554Steve Block        nodeTitle += "#";
1402bde8e466a4451c7319e3a072d118917957d6554Steve Block        nodeTitle += idValue;
1412bde8e466a4451c7319e3a072d118917957d6554Steve Block    }
1422bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (element->hasClass() && element->isStyledElement()) {
1432bde8e466a4451c7319e3a072d118917957d6554Steve Block        const SpaceSplitString& classNamesString = static_cast<StyledElement*>(element)->classNames();
1442bde8e466a4451c7319e3a072d118917957d6554Steve Block        size_t classNameCount = classNamesString.size();
1452bde8e466a4451c7319e3a072d118917957d6554Steve Block        if (classNameCount) {
1462bde8e466a4451c7319e3a072d118917957d6554Steve Block            HashSet<AtomicString> usedClassNames;
1472bde8e466a4451c7319e3a072d118917957d6554Steve Block            for (size_t i = 0; i < classNameCount; ++i) {
1482bde8e466a4451c7319e3a072d118917957d6554Steve Block                const AtomicString& className = classNamesString[i];
1492bde8e466a4451c7319e3a072d118917957d6554Steve Block                if (usedClassNames.contains(className))
1502bde8e466a4451c7319e3a072d118917957d6554Steve Block                    continue;
1512bde8e466a4451c7319e3a072d118917957d6554Steve Block                usedClassNames.add(className);
1522bde8e466a4451c7319e3a072d118917957d6554Steve Block                nodeTitle += ".";
1532bde8e466a4451c7319e3a072d118917957d6554Steve Block                nodeTitle += className;
1542bde8e466a4451c7319e3a072d118917957d6554Steve Block            }
1552bde8e466a4451c7319e3a072d118917957d6554Steve Block        }
1562bde8e466a4451c7319e3a072d118917957d6554Steve Block    }
1572bde8e466a4451c7319e3a072d118917957d6554Steve Block
1582bde8e466a4451c7319e3a072d118917957d6554Steve Block    nodeTitle += " [";
1592bde8e466a4451c7319e3a072d118917957d6554Steve Block    nodeTitle += String::number(boundingBox.width());
1602bde8e466a4451c7319e3a072d118917957d6554Steve Block    nodeTitle.append(static_cast<UChar>(0x00D7)); // &times;
1612bde8e466a4451c7319e3a072d118917957d6554Steve Block    nodeTitle += String::number(boundingBox.height());
1622bde8e466a4451c7319e3a072d118917957d6554Steve Block    nodeTitle += "]";
1632bde8e466a4451c7319e3a072d118917957d6554Steve Block
1642bde8e466a4451c7319e3a072d118917957d6554Steve Block    FontDescription desc;
1652bde8e466a4451c7319e3a072d118917957d6554Steve Block    FontFamily family;
1662bde8e466a4451c7319e3a072d118917957d6554Steve Block    family.setFamily(settings->fixedFontFamily());
1672bde8e466a4451c7319e3a072d118917957d6554Steve Block    desc.setFamily(family);
1682bde8e466a4451c7319e3a072d118917957d6554Steve Block    desc.setComputedSize(fontHeightPx);
1692bde8e466a4451c7319e3a072d118917957d6554Steve Block    Font font = Font(desc, 0, 0);
1702bde8e466a4451c7319e3a072d118917957d6554Steve Block    font.update(0);
1712bde8e466a4451c7319e3a072d118917957d6554Steve Block
1722bde8e466a4451c7319e3a072d118917957d6554Steve Block    TextRun nodeTitleRun(nodeTitle);
1732bde8e466a4451c7319e3a072d118917957d6554Steve Block    IntPoint titleBasePoint = IntPoint(anchorBox.x(), anchorBox.maxY() - 1);
1742bde8e466a4451c7319e3a072d118917957d6554Steve Block    titleBasePoint.move(rectInflatePx, rectInflatePx);
1752bde8e466a4451c7319e3a072d118917957d6554Steve Block    IntRect titleRect = enclosingIntRect(font.selectionRectForText(nodeTitleRun, titleBasePoint, fontHeightPx));
1762bde8e466a4451c7319e3a072d118917957d6554Steve Block    titleRect.inflate(rectInflatePx);
1772bde8e466a4451c7319e3a072d118917957d6554Steve Block
1782bde8e466a4451c7319e3a072d118917957d6554Steve Block    // The initial offsets needed to compensate for a 1px-thick border stroke (which is not a part of the rectangle).
1792bde8e466a4451c7319e3a072d118917957d6554Steve Block    int dx = -borderWidthPx;
1802bde8e466a4451c7319e3a072d118917957d6554Steve Block    int dy = borderWidthPx;
1812bde8e466a4451c7319e3a072d118917957d6554Steve Block
1822bde8e466a4451c7319e3a072d118917957d6554Steve Block    // If the tip sticks beyond the right of overlayRect, right-align the tip with the said boundary.
1832bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (titleRect.maxX() > overlayRect.maxX())
1842bde8e466a4451c7319e3a072d118917957d6554Steve Block        dx = overlayRect.maxX() - titleRect.maxX();
1852bde8e466a4451c7319e3a072d118917957d6554Steve Block
1862bde8e466a4451c7319e3a072d118917957d6554Steve Block    // If the tip sticks beyond the left of overlayRect, left-align the tip with the said boundary.
1872bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (titleRect.x() + dx < overlayRect.x())
1882bde8e466a4451c7319e3a072d118917957d6554Steve Block        dx = overlayRect.x() - titleRect.x() - borderWidthPx;
1892bde8e466a4451c7319e3a072d118917957d6554Steve Block
1902bde8e466a4451c7319e3a072d118917957d6554Steve Block    // If the tip sticks beyond the bottom of overlayRect, show the tip at top of bounding box.
1912bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (titleRect.maxY() > overlayRect.maxY()) {
1922bde8e466a4451c7319e3a072d118917957d6554Steve Block        dy = anchorBox.y() - titleRect.maxY() - borderWidthPx;
1932bde8e466a4451c7319e3a072d118917957d6554Steve Block        // If the tip still sticks beyond the bottom of overlayRect, bottom-align the tip with the said boundary.
1942bde8e466a4451c7319e3a072d118917957d6554Steve Block        if (titleRect.maxY() + dy > overlayRect.maxY())
1952bde8e466a4451c7319e3a072d118917957d6554Steve Block            dy = overlayRect.maxY() - titleRect.maxY();
1962bde8e466a4451c7319e3a072d118917957d6554Steve Block    }
1972bde8e466a4451c7319e3a072d118917957d6554Steve Block
1982bde8e466a4451c7319e3a072d118917957d6554Steve Block    // If the tip sticks beyond the top of overlayRect, show the tip at top of overlayRect.
1992bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (titleRect.y() + dy < overlayRect.y())
2002bde8e466a4451c7319e3a072d118917957d6554Steve Block        dy = overlayRect.y() - titleRect.y() + borderWidthPx;
2012bde8e466a4451c7319e3a072d118917957d6554Steve Block
2022bde8e466a4451c7319e3a072d118917957d6554Steve Block    titleRect.move(dx, dy);
2032bde8e466a4451c7319e3a072d118917957d6554Steve Block    context.setStrokeColor(tooltipBorderColor, ColorSpaceDeviceRGB);
2042bde8e466a4451c7319e3a072d118917957d6554Steve Block    context.setStrokeThickness(borderWidthPx);
2052bde8e466a4451c7319e3a072d118917957d6554Steve Block    context.setFillColor(tooltipBackgroundColor, ColorSpaceDeviceRGB);
2062bde8e466a4451c7319e3a072d118917957d6554Steve Block    context.drawRect(titleRect);
2072bde8e466a4451c7319e3a072d118917957d6554Steve Block    context.setFillColor(tooltipFontColor, ColorSpaceDeviceRGB);
2082bde8e466a4451c7319e3a072d118917957d6554Steve Block    context.drawText(font, nodeTitleRun, IntPoint(titleRect.x() + rectInflatePx, titleRect.y() + font.fontMetrics().height()));
2092bde8e466a4451c7319e3a072d118917957d6554Steve Block}
2102bde8e466a4451c7319e3a072d118917957d6554Steve Block
2112bde8e466a4451c7319e3a072d118917957d6554Steve Block} // anonymous namespace
2122bde8e466a4451c7319e3a072d118917957d6554Steve Block
2132bde8e466a4451c7319e3a072d118917957d6554Steve Blocknamespace DOMNodeHighlighter {
2142bde8e466a4451c7319e3a072d118917957d6554Steve Block
2152bde8e466a4451c7319e3a072d118917957d6554Steve Blockvoid DrawNodeHighlight(GraphicsContext& context, Node* node)
2162bde8e466a4451c7319e3a072d118917957d6554Steve Block{
2172bde8e466a4451c7319e3a072d118917957d6554Steve Block    RenderObject* renderer = node->renderer();
2182bde8e466a4451c7319e3a072d118917957d6554Steve Block    Frame* containingFrame = node->document()->frame();
2192bde8e466a4451c7319e3a072d118917957d6554Steve Block
2202bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (!renderer || !containingFrame)
2212bde8e466a4451c7319e3a072d118917957d6554Steve Block        return;
2222bde8e466a4451c7319e3a072d118917957d6554Steve Block
2232bde8e466a4451c7319e3a072d118917957d6554Steve Block    IntSize mainFrameOffset = frameToMainFrameOffset(containingFrame);
2242bde8e466a4451c7319e3a072d118917957d6554Steve Block    IntRect boundingBox = renderer->absoluteBoundingBoxRect(true);
2252bde8e466a4451c7319e3a072d118917957d6554Steve Block
2262bde8e466a4451c7319e3a072d118917957d6554Steve Block    boundingBox.move(mainFrameOffset);
2272bde8e466a4451c7319e3a072d118917957d6554Steve Block
2282bde8e466a4451c7319e3a072d118917957d6554Steve Block    IntRect titleAnchorBox = boundingBox;
2292bde8e466a4451c7319e3a072d118917957d6554Steve Block
2302bde8e466a4451c7319e3a072d118917957d6554Steve Block    FrameView* view = containingFrame->page()->mainFrame()->view();
2312bde8e466a4451c7319e3a072d118917957d6554Steve Block    FloatRect overlayRect = view->visibleContentRect();
2322bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (!overlayRect.contains(boundingBox) && !boundingBox.contains(enclosingIntRect(overlayRect)))
2332bde8e466a4451c7319e3a072d118917957d6554Steve Block        overlayRect = view->visibleContentRect();
2342bde8e466a4451c7319e3a072d118917957d6554Steve Block    context.translate(-overlayRect.x(), -overlayRect.y());
2352bde8e466a4451c7319e3a072d118917957d6554Steve Block
2362bde8e466a4451c7319e3a072d118917957d6554Steve Block    // RenderSVGRoot should be highlighted through the isBox() code path, all other SVG elements should just dump their absoluteQuads().
2372bde8e466a4451c7319e3a072d118917957d6554Steve Block#if ENABLE(SVG)
2382bde8e466a4451c7319e3a072d118917957d6554Steve Block    bool isSVGRenderer = renderer->node() && renderer->node()->isSVGElement() && !renderer->isSVGRoot();
2392bde8e466a4451c7319e3a072d118917957d6554Steve Block#else
2402bde8e466a4451c7319e3a072d118917957d6554Steve Block    bool isSVGRenderer = false;
2412bde8e466a4451c7319e3a072d118917957d6554Steve Block#endif
2422bde8e466a4451c7319e3a072d118917957d6554Steve Block
2432bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (renderer->isBox() && !isSVGRenderer) {
2442bde8e466a4451c7319e3a072d118917957d6554Steve Block        RenderBox* renderBox = toRenderBox(renderer);
2452bde8e466a4451c7319e3a072d118917957d6554Steve Block
2462daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        // RenderBox returns the "pure" content area box, exclusive of the scrollbars (if present), which also count towards the content area in CSS.
2472bde8e466a4451c7319e3a072d118917957d6554Steve Block        IntRect contentBox = renderBox->contentBoxRect();
2482daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        contentBox.setWidth(contentBox.width() + renderBox->verticalScrollbarWidth());
2492daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        contentBox.setHeight(contentBox.height() + renderBox->horizontalScrollbarHeight());
2502bde8e466a4451c7319e3a072d118917957d6554Steve Block
2512bde8e466a4451c7319e3a072d118917957d6554Steve Block        IntRect paddingBox(contentBox.x() - renderBox->paddingLeft(), contentBox.y() - renderBox->paddingTop(),
2522bde8e466a4451c7319e3a072d118917957d6554Steve Block                           contentBox.width() + renderBox->paddingLeft() + renderBox->paddingRight(), contentBox.height() + renderBox->paddingTop() + renderBox->paddingBottom());
2532bde8e466a4451c7319e3a072d118917957d6554Steve Block        IntRect borderBox(paddingBox.x() - renderBox->borderLeft(), paddingBox.y() - renderBox->borderTop(),
2542bde8e466a4451c7319e3a072d118917957d6554Steve Block                          paddingBox.width() + renderBox->borderLeft() + renderBox->borderRight(), paddingBox.height() + renderBox->borderTop() + renderBox->borderBottom());
2552bde8e466a4451c7319e3a072d118917957d6554Steve Block        IntRect marginBox(borderBox.x() - renderBox->marginLeft(), borderBox.y() - renderBox->marginTop(),
2562bde8e466a4451c7319e3a072d118917957d6554Steve Block                          borderBox.width() + renderBox->marginLeft() + renderBox->marginRight(), borderBox.height() + renderBox->marginTop() + renderBox->marginBottom());
2572bde8e466a4451c7319e3a072d118917957d6554Steve Block
2582bde8e466a4451c7319e3a072d118917957d6554Steve Block
2592bde8e466a4451c7319e3a072d118917957d6554Steve Block        FloatQuad absContentQuad = renderBox->localToAbsoluteQuad(FloatRect(contentBox));
2602bde8e466a4451c7319e3a072d118917957d6554Steve Block        FloatQuad absPaddingQuad = renderBox->localToAbsoluteQuad(FloatRect(paddingBox));
2612bde8e466a4451c7319e3a072d118917957d6554Steve Block        FloatQuad absBorderQuad = renderBox->localToAbsoluteQuad(FloatRect(borderBox));
2622bde8e466a4451c7319e3a072d118917957d6554Steve Block        FloatQuad absMarginQuad = renderBox->localToAbsoluteQuad(FloatRect(marginBox));
2632bde8e466a4451c7319e3a072d118917957d6554Steve Block
2642bde8e466a4451c7319e3a072d118917957d6554Steve Block        absContentQuad.move(mainFrameOffset);
2652bde8e466a4451c7319e3a072d118917957d6554Steve Block        absPaddingQuad.move(mainFrameOffset);
2662bde8e466a4451c7319e3a072d118917957d6554Steve Block        absBorderQuad.move(mainFrameOffset);
2672bde8e466a4451c7319e3a072d118917957d6554Steve Block        absMarginQuad.move(mainFrameOffset);
2682bde8e466a4451c7319e3a072d118917957d6554Steve Block
2692bde8e466a4451c7319e3a072d118917957d6554Steve Block        titleAnchorBox = absMarginQuad.enclosingBoundingBox();
2702bde8e466a4451c7319e3a072d118917957d6554Steve Block
2712bde8e466a4451c7319e3a072d118917957d6554Steve Block        drawHighlightForBox(context, absContentQuad, absPaddingQuad, absBorderQuad, absMarginQuad);
2722bde8e466a4451c7319e3a072d118917957d6554Steve Block    } else if (renderer->isRenderInline() || isSVGRenderer) {
2732bde8e466a4451c7319e3a072d118917957d6554Steve Block        // FIXME: We should show margins/padding/border for inlines.
2742bde8e466a4451c7319e3a072d118917957d6554Steve Block        Vector<FloatQuad> lineBoxQuads;
2752bde8e466a4451c7319e3a072d118917957d6554Steve Block        renderer->absoluteQuads(lineBoxQuads);
2762bde8e466a4451c7319e3a072d118917957d6554Steve Block        for (unsigned i = 0; i < lineBoxQuads.size(); ++i)
2772bde8e466a4451c7319e3a072d118917957d6554Steve Block            lineBoxQuads[i] += mainFrameOffset;
2782bde8e466a4451c7319e3a072d118917957d6554Steve Block
2792bde8e466a4451c7319e3a072d118917957d6554Steve Block        drawHighlightForLineBoxesOrSVGRenderer(context, lineBoxQuads);
2802bde8e466a4451c7319e3a072d118917957d6554Steve Block    }
2812bde8e466a4451c7319e3a072d118917957d6554Steve Block
2822bde8e466a4451c7319e3a072d118917957d6554Steve Block    // Draw node title if necessary.
2832bde8e466a4451c7319e3a072d118917957d6554Steve Block
2842bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (!node->isElementNode())
2852bde8e466a4451c7319e3a072d118917957d6554Steve Block        return;
2862bde8e466a4451c7319e3a072d118917957d6554Steve Block
2872bde8e466a4451c7319e3a072d118917957d6554Steve Block    WebCore::Settings* settings = containingFrame->settings();
2882bde8e466a4451c7319e3a072d118917957d6554Steve Block    drawElementTitle(context, node, boundingBox, titleAnchorBox, overlayRect, settings);
2892bde8e466a4451c7319e3a072d118917957d6554Steve Block}
2902bde8e466a4451c7319e3a072d118917957d6554Steve Block
2912bde8e466a4451c7319e3a072d118917957d6554Steve Block} // namespace DOMNodeHighlighter
2922bde8e466a4451c7319e3a072d118917957d6554Steve Block
2932bde8e466a4451c7319e3a072d118917957d6554Steve Block} // namespace WebCore
2942bde8e466a4451c7319e3a072d118917957d6554Steve Block
2952bde8e466a4451c7319e3a072d118917957d6554Steve Block#endif // ENABLE(INSPECTOR)
296