void FontBuilder::updateAdjustedSize(FontDescription& fontDescription, const ComputedStyle& style, FontSelector* fontSelector) { const float specifiedSize = fontDescription.specifiedSize(); if (!fontDescription.hasSizeAdjust() || !specifiedSize) return; // We need to create a temporal Font to get xHeight of a primary font. // The aspect value is based on the xHeight of the font for the computed font size, // so we need to reset the adjustedSize to computedSize. See FontDescription::effectiveFontSize. fontDescription.setAdjustedSize(fontDescription.computedSize()); Font font(fontDescription); font.update(fontSelector); if (!font.fontMetrics().hasXHeight()) return; const float sizeAdjust = fontDescription.sizeAdjust(); float aspectValue = font.fontMetrics().xHeight() / specifiedSize; float adjustedSize = (sizeAdjust / aspectValue) * specifiedSize; adjustedSize = getComputedSizeFromSpecifiedSize(fontDescription, style.effectiveZoom(), adjustedSize); float multiplier = style.textAutosizingMultiplier(); if (multiplier > 1) adjustedSize = TextAutosizer::computeAutosizedFontSize(adjustedSize, multiplier); fontDescription.setAdjustedSize(adjustedSize); }
bool CompositingReasonFinder::requiresCompositingForAnimation(const ComputedStyle& style) const { if (style.subtreeWillChangeContents()) return style.isRunningAnimationOnCompositor(); return style.shouldCompositeForCurrentAnimations(); }
void LayoutListMarker::styleWillChange(StyleDifference diff, const ComputedStyle& newStyle) { if (style() && (newStyle.listStylePosition() != style()->listStylePosition() || newStyle.listStyleType() != style()->listStyleType())) setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation(LayoutInvalidationReason::StyleChange); LayoutBox::styleWillChange(diff, newStyle); }
void MediaControlsPainter::adjustMediaSliderThumbSize(ComputedStyle& style) { static Image* mediaSliderThumb = platformResource("mediaplayerSliderThumb", "mediaplayerSliderThumbNew"); static Image* mediaVolumeSliderThumb = platformResource( "mediaplayerVolumeSliderThumb", "mediaplayerVolumeSliderThumbNew"); int width = 0; int height = 0; Image* thumbImage = 0; if (RuntimeEnabledFeatures::newMediaPlaybackUiEnabled()) { // Volume and time sliders are the same. thumbImage = mediaSliderThumb; width = mediaSliderThumbTouchWidthNew; height = mediaSliderThumbTouchHeightNew; } else if (style.appearance() == MediaSliderThumbPart) { thumbImage = mediaSliderThumb; width = mediaSliderThumbWidth; height = mediaSliderThumbHeight; } else if (style.appearance() == MediaVolumeSliderThumbPart) { thumbImage = mediaVolumeSliderThumb; width = mediaVolumeSliderThumbWidth; height = mediaVolumeSliderThumbHeight; } float zoomLevel = style.effectiveZoom(); if (thumbImage) { style.setWidth(Length(static_cast<int>(width * zoomLevel), Fixed)); style.setHeight(Length(static_cast<int>(height * zoomLevel), Fixed)); } }
bool LayoutTheme::isControlStyled(const ComputedStyle& style, const AuthorStyleInfo& authorStyle) const { switch (style.appearance()) { case PushButtonPart: case SquareButtonPart: case ButtonPart: case ProgressBarPart: case MeterPart: case RelevancyLevelIndicatorPart: case ContinuousCapacityLevelIndicatorPart: case DiscreteCapacityLevelIndicatorPart: case RatingLevelIndicatorPart: return authorStyle.specifiesBackground() || authorStyle.specifiesBorder(); case MenulistPart: case SearchFieldPart: case TextAreaPart: case TextFieldPart: return authorStyle.specifiesBackground() || authorStyle.specifiesBorder() || style.boxShadow(); case SliderHorizontalPart: case SliderVerticalPart: return style.boxShadow(); default: return false; } }
static bool hasWillChangeThatCreatesStackingContext(const ComputedStyle& style) { for (size_t i = 0; i < style.willChangeProperties().size(); ++i) { switch (style.willChangeProperties()[i]) { case CSSPropertyOpacity: case CSSPropertyTransform: case CSSPropertyAliasWebkitTransform: case CSSPropertyTransformStyle: case CSSPropertyAliasWebkitTransformStyle: case CSSPropertyPerspective: case CSSPropertyAliasWebkitPerspective: case CSSPropertyWebkitMask: case CSSPropertyWebkitMaskBoxImage: case CSSPropertyWebkitClipPath: case CSSPropertyWebkitBoxReflect: case CSSPropertyWebkitFilter: case CSSPropertyBackdropFilter: case CSSPropertyZIndex: case CSSPropertyPosition: return true; case CSSPropertyMixBlendMode: case CSSPropertyIsolation: if (RuntimeEnabledFeatures::cssCompositingEnabled()) return true; break; default: break; } } return false; }
bool SVGLayoutSupport::willIsolateBlendingDescendantsForStyle(const ComputedStyle& style) { const SVGComputedStyle& svgStyle = style.svgStyle(); return style.hasIsolation() || style.opacity() < 1 || style.hasBlendMode() || svgStyle.hasFilter() || svgStyle.hasMasker() || svgStyle.hasClipper(); }
PassRefPtr<AnimatableValue> CSSAnimatableValueFactory::createFromColor( CSSPropertyID property, const ComputedStyle& style) { Color color = style.colorIncludingFallback(property, false); Color visitedLinkColor = style.colorIncludingFallback(property, true); return AnimatableColor::create(color, visitedLinkColor); }
void LayoutThemeDefault::adjustInnerSpinButtonStyle(ComputedStyle& style) const { IntSize size = Platform::current()->themeEngine()->getSize(WebThemeEngine::PartInnerSpinButton); style.setWidth(Length(size.width(), Fixed)); style.setMinWidth(Length(size.width(), Fixed)); }
void LayoutThemeDefault::adjustButtonStyle(ComputedStyle& style) const { if (style.appearance() == PushButtonPart) { // Ignore line-height. style.setLineHeight(ComputedStyle::initialLineHeight()); } }
TextRun InlineTextBox::constructTextRun( const ComputedStyle& style, StringView string, int maximumLength, StringBuilder* charactersWithHyphen) const { if (charactersWithHyphen) { const AtomicString& hyphenString = style.hyphenString(); charactersWithHyphen->reserveCapacity(string.length() + hyphenString.length()); charactersWithHyphen->append(string); charactersWithHyphen->append(hyphenString); string = charactersWithHyphen->toString(); maximumLength = string.length(); } ASSERT(maximumLength >= static_cast<int>(string.length())); TextRun run(string, textPos().toFloat(), expansion(), expansionBehavior(), direction(), dirOverride() || style.rtlOrdering() == EOrder::Visual); run.setTabSize(!style.collapseWhiteSpace(), style.getTabSize()); run.setTextJustify(style.getTextJustify()); // Propagate the maximum length of the characters buffer to the TextRun, even // when we're only processing a substring. run.setCharactersLength(maximumLength); ASSERT(run.charactersLength() >= run.length()); return run; }
bool InlineTextBox::getEmphasisMarkPosition( const ComputedStyle& style, TextEmphasisPosition& emphasisPosition) const { // This function returns true if there are text emphasis marks and they are // suppressed by ruby text. if (style.getTextEmphasisMark() == TextEmphasisMarkNone) return false; emphasisPosition = style.getTextEmphasisPosition(); // Ruby text is always over, so it cannot suppress emphasis marks under. if (emphasisPosition == TextEmphasisPositionUnder) return true; LineLayoutBox containingBlock = getLineLayoutItem().containingBlock(); // This text is not inside a ruby base, so it does not have ruby text over it. if (!containingBlock.isRubyBase()) return true; // Cannot get the ruby text. if (!containingBlock.parent().isRubyRun()) return true; LineLayoutRubyText rubyText = LineLayoutRubyRun(containingBlock.parent()).rubyText(); // The emphasis marks over are suppressed only if there is a ruby text box and // it not empty. return !rubyText || !rubyText.firstLineBox(); }
Length ViewportStyleResolver::viewportLengthValue(CSSPropertyID id) const { ASSERT(id == CSSPropertyMaxHeight || id == CSSPropertyMinHeight || id == CSSPropertyMaxWidth || id == CSSPropertyMinWidth); CSSValue* value = m_propertySet->getPropertyCSSValue(id); if (!value || !value->isPrimitiveValue()) return Length(); // auto CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); if (primitiveValue->getValueID() == CSSValueInternalExtendToZoom) return Length(ExtendToZoom); ComputedStyle* documentStyle = m_document->mutableComputedStyle(); // If we have viewport units the conversion will mark the document style as having viewport units. bool documentStyleHasViewportUnits = documentStyle->hasViewportUnits(); documentStyle->setHasViewportUnits(false); CSSToLengthConversionData::FontSizes fontSizes(documentStyle, documentStyle); CSSToLengthConversionData::ViewportSize viewportSize(m_document->layoutView()); if (primitiveValue->getValueID() == CSSValueAuto) return Length(Auto); Length result = primitiveValue->convertToLength(CSSToLengthConversionData(documentStyle, fontSizes, viewportSize, 1.0f)); if (documentStyle->hasViewportUnits()) m_document->setHasViewportUnits(); documentStyle->setHasViewportUnits(documentStyleHasViewportUnits); return result; }
bool Text::textLayoutObjectIsNeeded(const ComputedStyle& style, const LayoutObject& parent) { if (!parent.canHaveChildren()) return false; if (isEditingText()) return true; if (!length()) return false; if (style.display() == NONE) return false; if (!containsOnlyWhitespace()) return true; if (!canHaveWhitespaceChildren(parent, this)) return false; // pre-wrap in SVG never makes layoutObject. if (style.whiteSpace() == PRE_WRAP && parent.isSVG()) return false; // pre/pre-wrap/-bb-pre-wrap-text/pre-line always make layoutObjects. if (style.preserveNewline()) return true; // childNeedsDistributionRecalc() here is rare, only happens JS calling surroundContents() etc. from DOMNodeInsertedIntoDocument etc. if (document().childNeedsDistributionRecalc()) return true; const LayoutObject* prev = LayoutTreeBuilderTraversal::previousSiblingLayoutObject(*this); if (prev && prev->isBR()) // <span><br/> <br/></span> return false; if (parent.isLayoutInline()) { // <span><div/> <div/></span> if (prev && !prev->isInline() && !prev->isOutOfFlowPositioned()) return false; } else { if (parent.isLayoutBlock() && !parent.childrenInline() && (!prev || !prev->isInline())) return false; // Avoiding creation of a layoutObject for the text node is a non-essential memory optimization. // So to avoid blowing up on very wide DOMs, we limit the number of siblings to visit. unsigned maxSiblingsToVisit = 50; LayoutObject* first = parent.slowFirstChild(); while (first && first->isFloatingOrOutOfFlowPositioned() && maxSiblingsToVisit--) first = first->nextSibling(); if (!first || first == layoutObject() || LayoutTreeBuilderTraversal::nextSiblingLayoutObject(*this) == first) { // Whitespace at the start of a block just goes away. Don't even // make a layout object for this text. return false; } } return true; }
static bool hasReferenceFilterOnly(const ComputedStyle& style) { if (!style.hasFilter()) return false; const FilterOperations& operations = style.filter(); if (operations.size() != 1) return false; return operations.at(0)->type() == FilterOperation::REFERENCE; }
void LayoutThemeDefault::adjustSearchFieldCancelButtonStyle(ComputedStyle& style) const { // Scale the button size based on the font size float fontScale = style.fontSize() / defaultControlFontPixelSize; int cancelButtonSize = lroundf(std::min(std::max(minCancelButtonSize, defaultCancelButtonSize * fontScale), maxCancelButtonSize)); style.setWidth(Length(cancelButtonSize, Fixed)); style.setHeight(Length(cancelButtonSize, Fixed)); }
void FontBuilder::updateComputedSize(FontDescription& fontDescription, const ComputedStyle& style) { float computedSize = getComputedSizeFromSpecifiedSize(fontDescription, style.effectiveZoom(), fontDescription.specifiedSize()); float multiplier = style.textAutosizingMultiplier(); if (multiplier > 1) computedSize = TextAutosizer::computeAutosizedFontSize(computedSize, multiplier); fontDescription.setComputedSize(computedSize); }
void LayoutThemeDefault::adjustSearchFieldResultsDecorationStyle(ComputedStyle& style) const { // Scale the decoration size based on the font size float fontScale = style.fontSize() / defaultControlFontPixelSize; int magnifierSize = lroundf(std::min(std::max(minSearchFieldResultsDecorationSize, defaultSearchFieldResultsDecorationSize * fontScale), maxSearchFieldResultsDecorationSize)); style.setWidth(Length(magnifierSize, Fixed)); style.setHeight(Length(magnifierSize, Fixed)); }
void LayoutTextControl::adjustInnerEditorStyle(ComputedStyle& textBlockStyle) const { // The inner block, if present, always has its direction set to LTR, // so we need to inherit the direction and unicode-bidi style from the element. textBlockStyle.setDirection(style()->direction()); textBlockStyle.setUnicodeBidi(style()->unicodeBidi()); updateUserModifyProperty(*textFormControlElement(), textBlockStyle); }
BoxReflection boxReflectionForPaintLayer(const PaintLayer& layer, const ComputedStyle& style) { const StyleReflection* reflectStyle = style.boxReflect(); LayoutRect frameLayoutRect = toLayoutBox(layer.layoutObject())->frameRect(); FloatRect frameRect(frameLayoutRect); BoxReflection::ReflectionDirection direction = BoxReflection::VerticalReflection; float offset = 0; switch (reflectStyle->direction()) { case ReflectionAbove: direction = BoxReflection::VerticalReflection; offset = -floatValueForLength(reflectStyle->offset(), frameRect.height()); break; case ReflectionBelow: direction = BoxReflection::VerticalReflection; offset = 2 * frameRect.height() + floatValueForLength(reflectStyle->offset(), frameRect.height()); break; case ReflectionLeft: direction = BoxReflection::HorizontalReflection; offset = -floatValueForLength(reflectStyle->offset(), frameRect.width()); break; case ReflectionRight: direction = BoxReflection::HorizontalReflection; offset = 2 * frameRect.width() + floatValueForLength(reflectStyle->offset(), frameRect.width()); break; } sk_sp<SkPicture> mask; const NinePieceImage& maskNinePiece = reflectStyle->mask(); if (maskNinePiece.hasImage()) { LayoutRect maskRect(LayoutPoint(), frameLayoutRect.size()); LayoutRect maskBoundingRect(maskRect); maskBoundingRect.expand(style.imageOutsets(maskNinePiece)); FloatRect maskBoundingFloatRect(maskBoundingRect); // TODO(jbroman): SkPictureBuilder + DrawingRecorder seems excessive. // If NinePieceImagePainter operated on SkCanvas, we'd only need an // SkPictureRecorder here. SkPictureBuilder recorder(maskBoundingFloatRect); { GraphicsContext& context = recorder.context(); DrawingRecorder drawingRecorder(context, *layer.layoutObject(), DisplayItem::kReflectionMask, maskBoundingFloatRect); NinePieceImagePainter(*layer.layoutObject()) .paint(recorder.context(), maskRect, style, maskNinePiece, SkXfermode::kSrcOver_Mode); } mask = recorder.endRecording(); } return BoxReflection(direction, offset, std::move(mask)); }
static inline LayoutUnit columnLogicalHeightRequirementForLine(const ComputedStyle& style, const RootInlineBox& lastLine) { // We may require a certain minimum number of lines per page in order to satisfy // orphans and widows, and that may affect the minimum page height. unsigned minimumLineCount = std::max<unsigned>(style.hasAutoOrphans() ? 1 : style.orphans(), style.widows()); const RootInlineBox* firstLine = &lastLine; for (unsigned i = 1; i < minimumLineCount && firstLine->prevRootBox(); i++) firstLine = firstLine->prevRootBox(); return lastLine.lineBottomWithLeading() - firstLine->lineTopWithLeading(); }
bool LayoutThemeDefault::shouldUseFallbackTheme(const ComputedStyle& style) const { if (useMockTheme()) { // The mock theme can't handle zoomed controls, so we fall back to the "fallback" theme. ControlPart part = style.appearance(); if (part == CheckboxPart || part == RadioPart) return style.effectiveZoom() != 1; } return LayoutTheme::shouldUseFallbackTheme(style); }
static ClipAutos getClipAutos(const ComputedStyle& style) { if (style.hasAutoClip()) return ClipAutos(); return ClipAutos( style.clipTop().isAuto(), style.clipRight().isAuto(), style.clipBottom().isAuto(), style.clipLeft().isAuto()); }
void ElementAnimations::updateAnimationFlags(ComputedStyle& style) { for (const auto& entry : m_animations) { const Animation& animation = *entry.key; ASSERT(animation.effect()); // FIXME: Needs to consider AnimationGroup once added. ASSERT(animation.effect()->isAnimation()); const KeyframeEffect& effect = *toKeyframeEffect(animation.effect()); if (effect.isCurrent()) { if (effect.affects(PropertyHandle(CSSPropertyOpacity))) style.setHasCurrentOpacityAnimation(true); if (effect.affects(PropertyHandle(CSSPropertyTransform)) || effect.affects(PropertyHandle(CSSPropertyRotate)) || effect.affects(PropertyHandle(CSSPropertyScale)) || effect.affects(PropertyHandle(CSSPropertyTranslate))) style.setHasCurrentTransformAnimation(true); if (effect.affects(PropertyHandle(CSSPropertyWebkitFilter))) style.setHasCurrentFilterAnimation(true); } } if (style.hasCurrentOpacityAnimation()) style.setIsRunningOpacityAnimationOnCompositor(m_defaultStack.hasActiveAnimationsOnCompositor(CSSPropertyOpacity)); if (style.hasCurrentTransformAnimation()) style.setIsRunningTransformAnimationOnCompositor(m_defaultStack.hasActiveAnimationsOnCompositor(CSSPropertyTransform)); if (style.hasCurrentFilterAnimation()) style.setIsRunningFilterAnimationOnCompositor(m_defaultStack.hasActiveAnimationsOnCompositor(CSSPropertyWebkitFilter)); }
void StyleAdjuster::adjustStyleForFirstLetter(ComputedStyle& style) { if (style.styleType() != FIRST_LETTER) return; // Force inline display (except for floating first-letters). style.setDisplay(style.isFloating() ? BLOCK : INLINE); // CSS2 says first-letter can't be positioned. style.setPosition(StaticPosition); }
void LayoutThemeMobile::adjustInnerSpinButtonStyle(ComputedStyle& style) const { if (LayoutTestSupport::isRunningLayoutTest()) { // Match Linux spin button style in layout tests. // FIXME: Consider removing the conditional if a future Android theme matches this. IntSize size = Platform::current()->themeEngine()->getSize(WebThemeEngine::PartInnerSpinButton); style.setWidth(Length(size.width(), Fixed)); style.setMinWidth(Length(size.width(), Fixed)); } }
void LayoutThemeDefault::setRadioSize(ComputedStyle& style) const { // If the width and height are both specified, then we have nothing to do. if (!style.width().isIntrinsicOrAuto() && !style.height().isAuto()) return; IntSize size = Platform::current()->themeEngine()->getSize(WebThemeEngine::PartRadio); float zoomLevel = style.effectiveZoom(); size.setWidth(size.width() * zoomLevel); size.setHeight(size.height() * zoomLevel); setSizeIfAuto(style, size); }
bool LayoutThemeDefault::themeDrawsFocusRing(const ComputedStyle& style) const { if (useMockTheme()) { // Don't use focus rings for buttons when mocking controls. return style.appearance() == ButtonPart || style.appearance() == PushButtonPart || style.appearance() == SquareButtonPart; } // This causes Blink to draw the focus rings for us. return false; }
void FontBuilder::createFont(PassRefPtrWillBeRawPtr<FontSelector> fontSelector, ComputedStyle& style) { if (!m_flags) return; FontDescription description = style.fontDescription(); if (isSet(PropertySetFlag::Family)) { description.setGenericFamily(m_fontDescription.genericFamily()); description.setFamily(m_fontDescription.family()); } if (isSet(PropertySetFlag::Size)) { description.setKeywordSize(m_fontDescription.keywordSize()); description.setSpecifiedSize(m_fontDescription.specifiedSize()); description.setIsAbsoluteSize(m_fontDescription.isAbsoluteSize()); } if (isSet(PropertySetFlag::SizeAdjust)) description.setSizeAdjust(m_fontDescription.sizeAdjust()); if (isSet(PropertySetFlag::Weight)) description.setWeight(m_fontDescription.weight()); if (isSet(PropertySetFlag::Stretch)) description.setStretch(m_fontDescription.stretch()); if (isSet(PropertySetFlag::FeatureSettings)) description.setFeatureSettings(m_fontDescription.featureSettings()); if (isSet(PropertySetFlag::Script)) { description.setLocale(m_fontDescription.locale()); description.setScript(m_fontDescription.script()); } if (isSet(PropertySetFlag::Style)) description.setStyle(m_fontDescription.style()); if (isSet(PropertySetFlag::Variant)) description.setVariant(m_fontDescription.variant()); if (isSet(PropertySetFlag::VariantLigatures)) description.setVariantLigatures(m_fontDescription.variantLigatures()); if (isSet(PropertySetFlag::TextRendering)) description.setTextRendering(m_fontDescription.textRendering()); if (isSet(PropertySetFlag::Kerning)) description.setKerning(m_fontDescription.kerning()); if (isSet(PropertySetFlag::FontSmoothing)) description.setFontSmoothing(m_fontDescription.fontSmoothing()); if (isSet(PropertySetFlag::TextOrientation) || isSet(PropertySetFlag::WritingMode)) updateOrientation(description, style); updateSpecifiedSize(description, style); updateComputedSize(description, style); updateAdjustedSize(description, style, fontSelector.get()); style.setFontDescription(description); style.font().update(fontSelector); m_flags = 0; }
void LayoutSliderThumb::updateAppearance(const ComputedStyle& parentStyle) { if (parentStyle.appearance() == SliderVerticalPart) mutableStyleRef().setAppearance(SliderThumbVerticalPart); else if (parentStyle.appearance() == SliderHorizontalPart) mutableStyleRef().setAppearance(SliderThumbHorizontalPart); else if (parentStyle.appearance() == MediaSliderPart) mutableStyleRef().setAppearance(MediaSliderThumbPart); else if (parentStyle.appearance() == MediaVolumeSliderPart) mutableStyleRef().setAppearance(MediaVolumeSliderThumbPart); else if (parentStyle.appearance() == MediaFullscreenVolumeSliderPart) mutableStyleRef().setAppearance(MediaFullscreenVolumeSliderThumbPart); if (styleRef().hasAppearance()) LayoutTheme::theme().adjustSliderThumbSize(mutableStyleRef()); }