void RenderMathMLSquareRoot::layout() { int maxHeight = 0; RenderObject* current = firstChild(); while (current) { if (current->isBoxModelObject()) { RenderBoxModelObject* box = toRenderBoxModelObject(current); if (box->pixelSnappedOffsetHeight() > maxHeight) maxHeight = box->pixelSnappedOffsetHeight(); box->style()->setVerticalAlign(BASELINE); } current = current->nextSibling(); } if (!maxHeight) maxHeight = style()->fontSize(); if (maxHeight > static_cast<int>(gThresholdBaseHeight * style()->fontSize())) style()->setPaddingBottom(Length(static_cast<int>(gRootBottomPadding * style()->fontSize()), Fixed)); RenderBlock::layout(); }
void RenderMathMLRoot::layout() { RenderBlock::layout(); if (!firstChild() || !lastChild()) return; int baseHeight = toRenderBoxModelObject(lastChild())->pixelSnappedOffsetHeight(); if (!baseHeight) baseHeight = style()->fontSize(); RenderObject* base = lastChild()->firstChild(); if (base) base->style()->setVerticalAlign(BASELINE); // FIXME: Can this style be modified? // Base height above which the shape of the root changes int thresholdHeight = static_cast<int>(gThresholdBaseHeightEms * style()->fontSize()); int overbarLeftPointShift = 0; // FIXME: Can style() and indexBox->style() be modified (4 times below)? if (baseHeight > thresholdHeight && thresholdHeight) { float shift = (baseHeight - thresholdHeight) / static_cast<float>(thresholdHeight); if (shift > 1.) shift = 1.0f; int frontWidth = static_cast<int>(style()->fontSize() * gFrontWidthEms); overbarLeftPointShift = static_cast<int>(gRadicalBottomPointXFront * frontWidth * shift); style()->setPaddingBottom(Length(static_cast<int>(gBigRootBottomPaddingEms * style()->fontSize()), Fixed)); } // Positioning of the index RenderObject* possibleIndex = firstChild()->firstChild(); while (possibleIndex && !possibleIndex->isBoxModelObject()) possibleIndex = possibleIndex->nextSibling(); RenderBoxModelObject* indexBox = toRenderBoxModelObject(possibleIndex); if (!indexBox) return; int shiftForIndex = indexBox->pixelSnappedOffsetWidth() + overbarLeftPointShift; int partDipHeight = static_cast<int>((1 - gRadicalDipLeftPointYPos) * baseHeight); int rootExtraTop = partDipHeight + style()->paddingBottom().value() + indexBox->pixelSnappedOffsetHeight() - (baseHeight + static_cast<int>(gRootPaddingEms * style()->fontSize())); style()->setPaddingLeft(Length(shiftForIndex, Fixed)); if (rootExtraTop > 0) style()->setPaddingTop(Length(rootExtraTop + static_cast<int>(gRootPaddingEms * style()->fontSize()), Fixed)); setNeedsLayout(true); setPreferredLogicalWidthsDirty(true, MarkOnlyThis); // FIXME: Can this really be right? RenderBlock::layout(); indexBox->style()->setBottom(Length(partDipHeight + style()->paddingBottom().value(), Fixed)); // Now that we've potentially changed its position, we need layout the index again. indexBox->setNeedsLayout(true); indexBox->layout(); }
inline int getOffsetHeight(RenderObject* obj) { if (obj->isBoxModelObject()) { RenderBoxModelObject* box = toRenderBoxModelObject(obj); return box->pixelSnappedOffsetHeight(); } return 0; }
void RenderMathMLRow::layout() { RenderBlock::layout(); int maxHeight = 0; // Calculate the non-operator max height of the row. for (RenderObject* current = firstChild(); current; current = current->nextSibling()) { if (current->isRenderMathMLBlock()) { RenderMathMLBlock* block = toRenderMathMLBlock(current); if (!block->unembellishedOperator() && block->offsetHeight() > maxHeight) maxHeight = block->offsetHeight(); } else if (current->isBoxModelObject()) { RenderBoxModelObject* box = toRenderBoxModelObject(current); // Check to see if this box has a larger height. if (box->pixelSnappedOffsetHeight() > maxHeight) maxHeight = box->pixelSnappedOffsetHeight(); } } if (!maxHeight) maxHeight = style()->fontSize(); // Stretch everything to the same height (blocks can ignore the request). if (maxHeight > 0) { bool didStretch = false; for (RenderObject* current = firstChild(); current; current = current->nextSibling()) { if (current->isRenderMathMLBlock()) { RenderMathMLBlock* block = toRenderMathMLBlock(current); block->stretchToHeight(maxHeight); didStretch = true; } } if (didStretch) { setNeedsLayout(true); setPreferredLogicalWidthsDirty(true, false); RenderBlock::layout(); } } }
static PassRefPtr<InspectorObject> buildObjectForElementInfo(Node* node) { if (!node->isElementNode() || !node->document().frame()) return nullptr; RefPtr<InspectorObject> elementInfo = InspectorObject::create(); Element* element = toElement(node); bool isXHTML = element->document().isXHTMLDocument(); elementInfo->setString("tagName", isXHTML ? element->nodeName() : element->nodeName().lower()); elementInfo->setString("idValue", element->getIdAttribute()); HashSet<AtomicString> usedClassNames; if (element->hasClass() && element->isStyledElement()) { StringBuilder classNames; const SpaceSplitString& classNamesString = toStyledElement(element)->classNames(); size_t classNameCount = classNamesString.size(); for (size_t i = 0; i < classNameCount; ++i) { const AtomicString& className = classNamesString[i]; if (usedClassNames.contains(className)) continue; usedClassNames.add(className); classNames.append('.'); classNames.append(className); } elementInfo->setString("className", classNames.toString()); } RenderElement* renderer = element->renderer(); Frame* containingFrame = node->document().frame(); FrameView* containingView = containingFrame->view(); IntRect boundingBox = pixelSnappedIntRect(containingView->contentsToRootView(renderer->absoluteBoundingBoxRect())); RenderBoxModelObject* modelObject = renderer->isBoxModelObject() ? toRenderBoxModelObject(renderer) : nullptr; elementInfo->setString("nodeWidth", String::number(modelObject ? adjustForAbsoluteZoom(modelObject->pixelSnappedOffsetWidth(), *modelObject) : boundingBox.width())); elementInfo->setString("nodeHeight", String::number(modelObject ? adjustForAbsoluteZoom(modelObject->pixelSnappedOffsetHeight(), *modelObject) : boundingBox.height())); if (renderer->isRenderNamedFlowFragmentContainer()) { RenderNamedFlowFragment* region = toRenderBlockFlow(renderer)->renderNamedFlowFragment(); if (region->isValid()) { RenderFlowThread* flowThread = region->flowThread(); ASSERT(flowThread && flowThread->isRenderNamedFlowThread()); RefPtr<InspectorObject> regionFlowInfo = InspectorObject::create(); regionFlowInfo->setString("name", toRenderNamedFlowThread(flowThread)->flowThreadName()); regionFlowInfo->setArray("regions", buildObjectForCSSRegionsHighlight(region, flowThread)); elementInfo->setObject("regionFlowInfo", regionFlowInfo.release()); } } RenderFlowThread* containingFlowThread = renderer->flowThreadContainingBlock(); if (containingFlowThread && containingFlowThread->isRenderNamedFlowThread()) { RefPtr<InspectorObject> contentFlowInfo = InspectorObject::create(); contentFlowInfo->setString("name", toRenderNamedFlowThread(containingFlowThread)->flowThreadName()); elementInfo->setObject("contentFlowInfo", contentFlowInfo.release()); } #if ENABLE(CSS_SHAPES) if (renderer->isBox()) { RenderBox* renderBox = toRenderBox(renderer); if (RefPtr<InspectorObject> shapeObject = buildObjectForShapeOutside(containingFrame, renderBox)) elementInfo->setObject("shapeOutsideInfo", shapeObject.release()); } #endif // Need to enable AX to get the computed role. if (!WebCore::AXObjectCache::accessibilityEnabled()) WebCore::AXObjectCache::enableAccessibility(); if (AXObjectCache* axObjectCache = node->document().axObjectCache()) { if (AccessibilityObject* axObject = axObjectCache->getOrCreate(node)) elementInfo->setString("role", axObject->computedRoleString()); } return elementInfo.release(); }
void InspectorOverlay::drawNodeHighlight() { if (!m_highlightNode) return; Highlight highlight; buildNodeHighlight(m_highlightNode.get(), m_nodeHighlightConfig, &highlight); RefPtr<InspectorObject> highlightObject = buildObjectForHighlight(m_page->mainFrame()->view(), highlight); Node* node = m_highlightNode.get(); if (node->isElementNode() && m_nodeHighlightConfig.showInfo && node->renderer() && node->document()->frame()) { RefPtr<InspectorObject> elementInfo = InspectorObject::create(); Element* element = toElement(node); bool isXHTML = element->document()->isXHTMLDocument(); elementInfo->setString("tagName", isXHTML ? element->nodeName() : element->nodeName().lower()); elementInfo->setString("idValue", element->getIdAttribute()); HashSet<AtomicString> usedClassNames; if (element->hasClass() && element->isStyledElement()) { StringBuilder classNames; const SpaceSplitString& classNamesString = static_cast<StyledElement*>(element)->classNames(); size_t classNameCount = classNamesString.size(); for (size_t i = 0; i < classNameCount; ++i) { const AtomicString& className = classNamesString[i]; if (usedClassNames.contains(className)) continue; usedClassNames.add(className); classNames.append('.'); classNames.append(className); } elementInfo->setString("className", classNames.toString()); } RenderObject* renderer = node->renderer(); Frame* containingFrame = node->document()->frame(); FrameView* containingView = containingFrame->view(); IntRect boundingBox = pixelSnappedIntRect(containingView->contentsToRootView(renderer->absoluteBoundingBoxRect())); RenderBoxModelObject* modelObject = renderer->isBoxModelObject() ? toRenderBoxModelObject(renderer) : 0; elementInfo->setString("nodeWidth", String::number(modelObject ? adjustForAbsoluteZoom(modelObject->pixelSnappedOffsetWidth(), modelObject) : boundingBox.width())); elementInfo->setString("nodeHeight", String::number(modelObject ? adjustForAbsoluteZoom(modelObject->pixelSnappedOffsetHeight(), modelObject) : boundingBox.height())); highlightObject->setObject("elementInfo", elementInfo.release()); } evaluateInOverlay("drawNodeHighlight", highlightObject); }
void RenderMathMLSquareRoot::paint(PaintInfo& info, const LayoutPoint& paintOffset) { RenderMathMLBlock::paint(info, paintOffset); if (info.context->paintingDisabled()) return; IntPoint adjustedPaintOffset = roundedIntPoint(paintOffset + location()); int maxHeight = 0; int width = 0; RenderObject* current = firstChild(); while (current) { if (current->isBoxModelObject()) { RenderBoxModelObject* box = toRenderBoxModelObject(current); // Check to see if this box has a larger height if (box->pixelSnappedOffsetHeight() > maxHeight) maxHeight = box->pixelSnappedOffsetHeight(); width += box->pixelSnappedOffsetWidth(); } current = current->nextSibling(); } // default to the font size in pixels if we're empty if (!maxHeight) maxHeight = style()->fontSize(); int frontWidth = static_cast<int>(style()->fontSize() * gRadicalWidth); int topStartShift = 0; // Base height above which the shape of the root changes int thresholdHeight = static_cast<int>(gThresholdBaseHeight * style()->fontSize()); if (maxHeight > thresholdHeight && thresholdHeight) { float shift = (maxHeight - thresholdHeight) / static_cast<float>(thresholdHeight); if (shift > 1.) shift = 1.0f; topStartShift = static_cast<int>(gRadicalBottomPointXPos * frontWidth * shift); } width += topStartShift; FloatPoint topStart(adjustedPaintOffset.x() + frontWidth - topStartShift, adjustedPaintOffset.y()); FloatPoint bottomLeft(adjustedPaintOffset.x() + frontWidth * gRadicalBottomPointXPos , adjustedPaintOffset.y() + maxHeight + gRadicalBasePad); FloatPoint topLeft(adjustedPaintOffset.x() + frontWidth * gRadicalTopLeftPointXPos , adjustedPaintOffset.y() + gRadicalTopLeftPointYPos * maxHeight); FloatPoint leftEnd(adjustedPaintOffset.x() , topLeft.y() + gRadicalLeftEndYShift * style()->fontSize()); GraphicsContextStateSaver stateSaver(*info.context); info.context->setStrokeThickness(gRadicalLineThickness * style()->fontSize()); info.context->setStrokeStyle(SolidStroke); info.context->setStrokeColor(style()->visitedDependentColor(CSSPropertyColor), ColorSpaceDeviceRGB); info.context->setLineJoin(MiterJoin); info.context->setMiterLimit(style()->fontSize()); Path root; root.moveTo(FloatPoint(topStart.x() + width , adjustedPaintOffset.y())); // draw top root.addLineTo(topStart); // draw from top left corner to bottom point of radical root.addLineTo(bottomLeft); // draw from bottom point to top of left part of radical base "pocket" root.addLineTo(topLeft); // draw to end root.addLineTo(leftEnd); info.context->strokePath(root); GraphicsContextStateSaver maskStateSaver(*info.context); // Build a mask to draw the thick part of the root. Path mask; mask.moveTo(topStart); mask.addLineTo(bottomLeft); mask.addLineTo(topLeft); mask.addLineTo(FloatPoint(2 * topLeft.x() - leftEnd.x(), 2 * topLeft.y() - leftEnd.y())); info.context->clip(mask); // Draw the thick part of the root. info.context->setStrokeThickness(gRadicalThickLineThickness * style()->fontSize()); info.context->setLineCap(SquareCap); Path line; line.moveTo(bottomLeft); line.addLineTo(topLeft); info.context->strokePath(line); }
void RenderMathMLRoot::paint(PaintInfo& info, const LayoutPoint& paintOffset) { RenderMathMLBlock::paint(info, paintOffset); if (info.context->paintingDisabled()) return; if (!firstChild() || !lastChild()) return; IntPoint adjustedPaintOffset = roundedIntPoint(paintOffset + location()); RenderBoxModelObject* baseWrapper = toRenderBoxModelObject(lastChild()); int baseHeight = baseWrapper->pixelSnappedOffsetHeight(); // default to the font size in pixels if we're empty if (!baseHeight) baseHeight = style()->fontSize(); int overbarWidth = baseWrapper->pixelSnappedOffsetWidth(); int indexWidth = 0; RenderObject* current = firstChild(); while (current != lastChild()) { if (current->isBoxModelObject()) { RenderBoxModelObject* box = toRenderBoxModelObject(current); indexWidth += box->pixelSnappedOffsetWidth(); } current = current->nextSibling(); } int frontWidth = static_cast<int>(style()->fontSize() * gFrontWidthEms); int overbarLeftPointShift = 0; // Base height above which the shape of the root changes int thresholdHeight = static_cast<int>(gThresholdBaseHeightEms * style()->fontSize()); if (baseHeight > thresholdHeight && thresholdHeight) { float shift = (baseHeight - thresholdHeight) / static_cast<float>(thresholdHeight); if (shift > 1.) shift = 1.0f; overbarLeftPointShift = static_cast<int>(gRadicalBottomPointXFront * frontWidth * shift); } overbarWidth += overbarLeftPointShift; int rootPad = static_cast<int>(gRootPaddingEms * style()->fontSize()); int startX = adjustedPaintOffset.x() + indexWidth + gRadicalLeftExtra + style()->paddingLeft().value() - rootPad; adjustedPaintOffset.setY(adjustedPaintOffset.y() + style()->paddingTop().value() - rootPad); FloatPoint overbarLeftPoint(startX - overbarLeftPointShift, adjustedPaintOffset.y()); FloatPoint bottomPoint(startX - gRadicalBottomPointXFront * frontWidth, adjustedPaintOffset.y() + baseHeight + gRadicalBottomPointLower); FloatPoint dipLeftPoint(startX - gRadicalDipLeftPointXFront * frontWidth, adjustedPaintOffset.y() + gRadicalDipLeftPointYPos * baseHeight); FloatPoint leftEnd(startX - frontWidth, dipLeftPoint.y() + gRadicalLeftEndYShiftEms * style()->fontSize()); GraphicsContextStateSaver stateSaver(*info.context); info.context->setStrokeThickness(gRadicalLineThicknessEms * style()->fontSize()); info.context->setStrokeStyle(SolidStroke); info.context->setStrokeColor(style()->visitedDependentColor(CSSPropertyColor), ColorSpaceDeviceRGB); info.context->setLineJoin(MiterJoin); info.context->setMiterLimit(style()->fontSize()); Path root; root.moveTo(FloatPoint(overbarLeftPoint.x() + overbarWidth, adjustedPaintOffset.y())); // draw top root.addLineTo(overbarLeftPoint); // draw from top left corner to bottom point of radical root.addLineTo(bottomPoint); // draw from bottom point to top of left part of radical base "dip" root.addLineTo(dipLeftPoint); // draw to end root.addLineTo(leftEnd); info.context->strokePath(root); GraphicsContextStateSaver maskStateSaver(*info.context); // Build a mask to draw the thick part of the root. Path mask; mask.moveTo(overbarLeftPoint); mask.addLineTo(bottomPoint); mask.addLineTo(dipLeftPoint); mask.addLineTo(FloatPoint(2 * dipLeftPoint.x() - leftEnd.x(), 2 * dipLeftPoint.y() - leftEnd.y())); info.context->clip(mask); // Draw the thick part of the root. info.context->setStrokeThickness(gRadicalThickLineThicknessEms * style()->fontSize()); info.context->setLineCap(SquareCap); Path line; line.moveTo(bottomPoint); line.addLineTo(dipLeftPoint); info.context->strokePath(line); }