LayoutUnit toUserUnits(const MathMLElement::Length& length, const RenderStyle& style, const LayoutUnit& referenceValue) { switch (length.type) { case MathMLElement::LengthType::Cm: return length.value * cssPixelsPerInch / 2.54f; case MathMLElement::LengthType::Em: return length.value * style.fontCascade().size(); case MathMLElement::LengthType::Ex: return length.value * style.fontMetrics().xHeight(); case MathMLElement::LengthType::In: return length.value * cssPixelsPerInch; case MathMLElement::LengthType::MathUnit: return length.value * style.fontCascade().size() / 18; case MathMLElement::LengthType::Mm: return length.value * cssPixelsPerInch / 25.4f; case MathMLElement::LengthType::Pc: return length.value * cssPixelsPerInch / 6; case MathMLElement::LengthType::Percentage: return referenceValue * length.value / 100; case MathMLElement::LengthType::Pt: return length.value * cssPixelsPerInch / 72; case MathMLElement::LengthType::Px: return length.value; case MathMLElement::LengthType::UnitLess: return referenceValue * length.value; case MathMLElement::LengthType::ParsingFailed: return referenceValue; default: ASSERT_NOT_REACHED(); return referenceValue; } }
GlyphOverflow visualOverflowForDecorations(const RenderStyle& lineStyle, const InlineTextBox* inlineTextBox) { ASSERT(!inlineTextBox || inlineTextBox->lineStyle() == lineStyle); TextDecoration decoration = lineStyle.textDecorationsInEffect(); if (decoration == TextDecorationNone) return GlyphOverflow(); float strokeThickness = textDecorationStrokeThickness(lineStyle.fontSize()); float controlPointDistance; float step; float wavyOffset; TextDecorationStyle decorationStyle = lineStyle.textDecorationStyle(); float height = lineStyle.fontCascade().fontMetrics().floatHeight(); GlyphOverflow overflowResult; if (decorationStyle == TextDecorationStyleWavy) { getWavyStrokeParameters(strokeThickness, controlPointDistance, step); wavyOffset = wavyOffsetFromDecoration(); overflowResult.left = strokeThickness; overflowResult.right = strokeThickness; } // These metrics must match where underlines get drawn. if (decoration & TextDecorationUnderline) { // Compensate for the integral ceiling in GraphicsContext::computeLineBoundsAndAntialiasingModeForText() int underlineOffset = 1; underlineOffset += computeUnderlineOffset(lineStyle.textUnderlinePosition(), lineStyle.fontMetrics(), inlineTextBox, strokeThickness); if (decorationStyle == TextDecorationStyleWavy) { extendIntToFloat(overflowResult.bottom, underlineOffset + wavyOffset + controlPointDistance + strokeThickness - height); extendIntToFloat(overflowResult.top, -(underlineOffset + wavyOffset - controlPointDistance - strokeThickness)); } else { extendIntToFloat(overflowResult.bottom, underlineOffset + strokeThickness - height); extendIntToFloat(overflowResult.top, -underlineOffset); } } if (decoration & TextDecorationOverline) { if (decorationStyle == TextDecorationStyleWavy) { extendIntToFloat(overflowResult.bottom, -wavyOffset + controlPointDistance + strokeThickness - height); extendIntToFloat(overflowResult.top, wavyOffset + controlPointDistance + strokeThickness); } else { extendIntToFloat(overflowResult.bottom, strokeThickness - height); // top is untouched } } if (decoration & TextDecorationLineThrough) { float baseline = lineStyle.fontMetrics().floatAscent(); if (decorationStyle == TextDecorationStyleWavy) { extendIntToFloat(overflowResult.bottom, 2 * baseline / 3 + controlPointDistance + strokeThickness - height); extendIntToFloat(overflowResult.top, -(2 * baseline / 3 - controlPointDistance - strokeThickness)); } else { extendIntToFloat(overflowResult.bottom, 2 * baseline / 3 + strokeThickness - height); extendIntToFloat(overflowResult.top, -(2 * baseline / 3)); } } return overflowResult; }
static LayoutUnit axisHeight(const RenderStyle& style) { // If we have a MATH table we just return the AxisHeight constant. const auto& primaryFont = style.fontCascade().primaryFont(); if (auto* mathData = primaryFont.mathData()) return mathData->getMathConstant(primaryFont, OpenTypeMathData::AxisHeight); // Otherwise, the idea is to try and use the middle of operators as the math axis which we thus approximate by "half of the x-height". // Note that Gecko has a slower but more accurate version that measures half of the height of U+2212 MINUS SIGN. return style.fontMetrics().xHeight() / 2; }
TextFragmentIterator::Style::Style(const RenderStyle& style) : font(style.fontCascade()) , textAlign(style.textAlign()) , collapseWhitespace(style.collapseWhiteSpace()) , preserveNewline(style.preserveNewline()) , wrapLines(style.autoWrap()) , breakWordOnOverflow(style.overflowWrap() == BreakOverflowWrap && (wrapLines || preserveNewline)) , spaceWidth(font.width(TextRun(StringView(&space, 1)))) , tabWidth(collapseWhitespace ? 0 : style.tabSize()) , locale(style.locale()) { }
TextFragmentIterator::Style::Style(const RenderStyle& style) : font(style.fontCascade()) , textAlign(style.textAlign()) , collapseWhitespace(style.collapseWhiteSpace()) , preserveNewline(style.preserveNewline()) , wrapLines(style.autoWrap()) , breakAnyWordOnOverflow(style.wordBreak() == BreakAllWordBreak && wrapLines) , breakFirstWordOnOverflow(breakAnyWordOnOverflow || (style.breakWords() && (wrapLines || preserveNewline))) , breakNBSP(wrapLines && style.nbspMode() == SPACE) , keepAllWordsForCJK(style.wordBreak() == KeepAllWordBreak) , spaceWidth(font.width(TextRun(StringView(&space, 1)))) , wordSpacing(font.wordSpacing()) , tabWidth(collapseWhitespace ? 0 : style.tabSize()) , locale(style.locale()) { }
void RenderThemeSafari::setFontFromControlSize(StyleResolver& styleResolver, RenderStyle& style, NSControlSize controlSize) const { FontDescription fontDescription; fontDescription.setIsAbsoluteSize(true); float fontSize = systemFontSizeForControlSize(controlSize); fontDescription.setOneFamily("Lucida Grande"); fontDescription.setComputedSize(fontSize); fontDescription.setSpecifiedSize(fontSize); // Reset line height style.setLineHeight(RenderStyle::initialLineHeight()); if (style.setFontDescription(fontDescription)) style.fontCascade().update(&styleResolver.document().fontSelector()); }
void RenderSVGInlineText::computeNewScaledFontForStyle(const RenderObject& renderer, const RenderStyle& style, float& scalingFactor, FontCascade& scaledFont) { // Alter font-size to the right on-screen value to avoid scaling the glyphs themselves, except when GeometricPrecision is specified scalingFactor = SVGRenderingContext::calculateScreenFontSizeScalingFactor(renderer); if (scalingFactor == 1 || !scalingFactor || style.fontDescription().textRenderingMode() == GeometricPrecision) { scalingFactor = 1; scaledFont = style.fontCascade(); return; } FontDescription fontDescription(style.fontDescription()); // FIXME: We need to better handle the case when we compute very small fonts below (below 1pt). fontDescription.setComputedSize(Style::computedFontSizeFromSpecifiedSizeForSVGInlineText(fontDescription.computedSize(), fontDescription.isAbsoluteSize(), scalingFactor, renderer.document())); scaledFont = FontCascade(fontDescription, 0, 0); scaledFont.update(&renderer.document().fontSelector()); }
void RenderTheme::adjustStyle(StyleResolver& styleResolver, RenderStyle& style, Element* element, bool UAHasAppearance, const BorderData& border, const FillLayer& background, const Color& backgroundColor) { // Force inline and table display styles to be inline-block (except for table- which is block) ControlPart part = style.appearance(); if (style.display() == INLINE || style.display() == INLINE_TABLE || style.display() == TABLE_ROW_GROUP || style.display() == TABLE_HEADER_GROUP || style.display() == TABLE_FOOTER_GROUP || style.display() == TABLE_ROW || style.display() == TABLE_COLUMN_GROUP || style.display() == TABLE_COLUMN || style.display() == TABLE_CELL || style.display() == TABLE_CAPTION) style.setDisplay(INLINE_BLOCK); else if (style.display() == COMPACT || style.display() == LIST_ITEM || style.display() == TABLE) style.setDisplay(BLOCK); if (UAHasAppearance && isControlStyled(style, border, background, backgroundColor)) { if (part == MenulistPart) { style.setAppearance(MenulistButtonPart); part = MenulistButtonPart; } else style.setAppearance(NoControlPart); } if (!style.hasAppearance()) return; // Never support box-shadow on native controls. style.setBoxShadow(nullptr); #if USE(NEW_THEME) switch (part) { case CheckboxPart: case InnerSpinButtonPart: case RadioPart: case PushButtonPart: case SquareButtonPart: case DefaultButtonPart: case ButtonPart: { // Border LengthBox borderBox(style.borderTopWidth(), style.borderRightWidth(), style.borderBottomWidth(), style.borderLeftWidth()); borderBox = m_theme->controlBorder(part, style.fontCascade(), borderBox, style.effectiveZoom()); if (borderBox.top().value() != static_cast<int>(style.borderTopWidth())) { if (borderBox.top().value()) style.setBorderTopWidth(borderBox.top().value()); else style.resetBorderTop(); } if (borderBox.right().value() != static_cast<int>(style.borderRightWidth())) { if (borderBox.right().value()) style.setBorderRightWidth(borderBox.right().value()); else style.resetBorderRight(); } if (borderBox.bottom().value() != static_cast<int>(style.borderBottomWidth())) { style.setBorderBottomWidth(borderBox.bottom().value()); if (borderBox.bottom().value()) style.setBorderBottomWidth(borderBox.bottom().value()); else style.resetBorderBottom(); } if (borderBox.left().value() != static_cast<int>(style.borderLeftWidth())) { style.setBorderLeftWidth(borderBox.left().value()); if (borderBox.left().value()) style.setBorderLeftWidth(borderBox.left().value()); else style.resetBorderLeft(); } // Padding LengthBox paddingBox = m_theme->controlPadding(part, style.fontCascade(), style.paddingBox(), style.effectiveZoom()); if (paddingBox != style.paddingBox()) style.setPaddingBox(paddingBox); // Whitespace if (m_theme->controlRequiresPreWhiteSpace(part)) style.setWhiteSpace(PRE); // Width / Height // The width and height here are affected by the zoom. // FIXME: Check is flawed, since it doesn't take min-width/max-width into account. LengthSize controlSize = m_theme->controlSize(part, style.fontCascade(), LengthSize(style.width(), style.height()), style.effectiveZoom()); if (controlSize.width() != style.width()) style.setWidth(controlSize.width()); if (controlSize.height() != style.height()) style.setHeight(controlSize.height()); // Min-Width / Min-Height LengthSize minControlSize = m_theme->minimumControlSize(part, style.fontCascade(), style.effectiveZoom()); if (minControlSize.width() != style.minWidth()) style.setMinWidth(minControlSize.width()); if (minControlSize.height() != style.minHeight()) style.setMinHeight(minControlSize.height()); // Font if (auto themeFont = m_theme->controlFont(part, style.fontCascade(), style.effectiveZoom())) { // If overriding the specified font with the theme font, also override the line height with the standard line height. style.setLineHeight(RenderStyle::initialLineHeight()); if (style.setFontDescription(themeFont.value())) style.fontCascade().update(nullptr); } // Special style that tells enabled default buttons in active windows to use the ActiveButtonText color. // The active window part of the test has to be done at paint time since it's not triggered by a style change. style.setInsideDefaultButton(part == DefaultButtonPart && element && !element->isDisabledFormControl()); break; } default: break; } #endif // Call the appropriate style adjustment method based off the appearance value. switch (style.appearance()) { #if !USE(NEW_THEME) case CheckboxPart: return adjustCheckboxStyle(styleResolver, style, element); case RadioPart: return adjustRadioStyle(styleResolver, style, element); case PushButtonPart: case SquareButtonPart: case DefaultButtonPart: case ButtonPart: return adjustButtonStyle(styleResolver, style, element); case InnerSpinButtonPart: return adjustInnerSpinButtonStyle(styleResolver, style, element); #endif case TextFieldPart: return adjustTextFieldStyle(styleResolver, style, element); case TextAreaPart: return adjustTextAreaStyle(styleResolver, style, element); case MenulistPart: return adjustMenuListStyle(styleResolver, style, element); case MenulistButtonPart: return adjustMenuListButtonStyle(styleResolver, style, element); case MediaPlayButtonPart: case MediaCurrentTimePart: case MediaTimeRemainingPart: case MediaEnterFullscreenButtonPart: case MediaExitFullscreenButtonPart: case MediaMuteButtonPart: case MediaVolumeSliderContainerPart: return adjustMediaControlStyle(styleResolver, style, element); case MediaSliderPart: case MediaVolumeSliderPart: case MediaFullScreenVolumeSliderPart: case SliderHorizontalPart: case SliderVerticalPart: return adjustSliderTrackStyle(styleResolver, style, element); case SliderThumbHorizontalPart: case SliderThumbVerticalPart: return adjustSliderThumbStyle(styleResolver, style, element); case SearchFieldPart: return adjustSearchFieldStyle(styleResolver, style, element); case SearchFieldCancelButtonPart: return adjustSearchFieldCancelButtonStyle(styleResolver, style, element); case SearchFieldDecorationPart: return adjustSearchFieldDecorationPartStyle(styleResolver, style, element); case SearchFieldResultsDecorationPart: return adjustSearchFieldResultsDecorationPartStyle(styleResolver, style, element); case SearchFieldResultsButtonPart: return adjustSearchFieldResultsButtonStyle(styleResolver, style, element); case ProgressBarPart: return adjustProgressBarStyle(styleResolver, style, element); #if ENABLE(METER_ELEMENT) case MeterPart: case RelevancyLevelIndicatorPart: case ContinuousCapacityLevelIndicatorPart: case DiscreteCapacityLevelIndicatorPart: case RatingLevelIndicatorPart: return adjustMeterStyle(styleResolver, style, element); #endif #if ENABLE(SERVICE_CONTROLS) case ImageControlsButtonPart: break; #endif case CapsLockIndicatorPart: return adjustCapsLockIndicatorStyle(styleResolver, style, element); #if ENABLE(ATTACHMENT_ELEMENT) case AttachmentPart: return adjustAttachmentStyle(styleResolver, style, element); #endif default: break; } }