static FontRanges realizeNextFallback(const FontCascadeDescription& description, unsigned& index, FontSelector* fontSelector) { ASSERT(index < description.familyCount()); auto& fontCache = FontCache::singleton(); while (index < description.familyCount()) { const AtomicString& family = description.familyAt(index++); if (family.isEmpty()) continue; if (fontSelector) { auto ranges = fontSelector->fontRangesForFamily(description, family); if (!ranges.isNull()) return ranges; } if (auto font = fontCache.fontForFamily(description, family)) return FontRanges(WTFMove(font)); } // We didn't find a font. Try to find a similar font using our own specific knowledge about our platform. // For example on OS X, we know to map any families containing the words Arabic, Pashto, or Urdu to the // Geeza Pro font. for (auto& family : description.families()) { if (auto font = fontCache.similarFont(description, family)) return FontRanges(WTFMove(font)); } return { }; }
bool RenderEmbeddedObject::getReplacementTextGeometry(const LayoutPoint& accumulatedOffset, FloatRect& contentRect, FloatRect& indicatorRect, FloatRect& replacementTextRect, FloatRect& arrowRect, FontCascade& font, TextRun& run, float& textWidth) const { bool includesArrow = shouldUnavailablePluginMessageBeButton(document(), m_pluginUnavailabilityReason); contentRect = contentBoxRect(); contentRect.moveBy(roundedIntPoint(accumulatedOffset)); FontCascadeDescription fontDescription; RenderTheme::defaultTheme()->systemFont(CSSValueWebkitSmallControl, fontDescription); fontDescription.setWeight(FontWeightBold); fontDescription.setRenderingMode(frame().settings().fontRenderingMode()); fontDescription.setComputedSize(12); font = FontCascade(fontDescription, 0, 0); font.update(0); run = TextRun(m_unavailablePluginReplacementText); textWidth = font.width(run); replacementTextRect.setSize(FloatSize(textWidth + replacementTextRoundedRectLeftTextMargin + (includesArrow ? replacementTextRoundedRectRightTextMarginWithArrow : replacementTextRoundedRectRightTextMargin), replacementTextRoundedRectHeight)); float x = (contentRect.size().width() / 2 - replacementTextRect.size().width() / 2) + contentRect.location().x(); float y = (contentRect.size().height() / 2 - replacementTextRect.size().height() / 2) + contentRect.location().y(); replacementTextRect.setLocation(FloatPoint(x, y)); indicatorRect = replacementTextRect; // Expand the background rect to include the arrow, if it will be used. if (includesArrow) { arrowRect = indicatorRect; arrowRect.setX(ceilf(arrowRect.maxX() + replacementArrowLeftMargin)); arrowRect.setWidth(arrowRect.height()); indicatorRect.unite(arrowRect); } return true; }
bool CSSFontSelector::resolvesFamilyFor(const FontCascadeDescription& description) const { for (unsigned i = 0; i < description.familyCount(); ++i) { const AtomicString& familyName = description.familyAt(i); if (familyName.isEmpty()) continue; if (m_fontFaces.contains(familyName)) return true; static NeverDestroyed<String> webkitPrefix("-webkit-"); if (familyName.startsWith(webkitPrefix.get())) return true; } return false; }
bool FontCascadeDescription::familiesEqualForTextAutoSizing(const FontCascadeDescription& other) const { unsigned thisFamilyCount = familyCount(); unsigned otherFamilyCount = other.familyCount(); if (thisFamilyCount != otherFamilyCount) return false; for (unsigned i = 0; i < thisFamilyCount; ++i) { if (!equalIgnoringCase(familyAt(i), other.familyAt(i))) return false; } return true; }
GlyphData FontCascadeFonts::glyphDataForNormalVariant(UChar32 c, const FontCascadeDescription& description) { for (unsigned fallbackIndex = 0; ; ++fallbackIndex) { auto& fontRanges = realizeFallbackRangesAt(description, fallbackIndex); if (fontRanges.isNull()) break; GlyphData data = fontRanges.glyphDataForCharacter(c); if (!data.font) continue; if (data.font->platformData().orientation() == Vertical && !data.font->isTextOrientationFallback()) { if (!FontCascade::isCJKIdeographOrSymbol(c)) return glyphDataForNonCJKCharacterWithGlyphOrientation(c, description.nonCJKGlyphOrientation(), data); if (!data.font->hasVerticalGlyphs()) { // Use the broken ideograph font data. The broken ideograph font will use the horizontal width of glyphs // to make sure you get a square (even for broken glyphs like symbols used for punctuation). return glyphDataForVariant(c, description, BrokenIdeographVariant, fallbackIndex); } #if PLATFORM(COCOA) || USE(CAIRO) if (data.font->platformData().syntheticOblique()) return glyphDataForCJKCharacterWithoutSyntheticItalic(c, data); #endif } return data; } return glyphDataForSystemFallback(c, description, NormalVariant); }
void RenderTheme::systemFont(CSSValueID systemFontID, FontCascadeDescription& fontDescription) const { fontDescription = cachedSystemFontDescription(systemFontID); if (fontDescription.isAbsoluteSize()) return; updateCachedSystemFontDescription(systemFontID, fontDescription); }
void PlatformCALayerWin::drawTextAtPoint(CGContextRef context, CGFloat x, CGFloat y, CGSize scale, CGFloat fontSize, const char* message, size_t length) const { String text(message, length); FontCascadeDescription desc; NONCLIENTMETRICS metrics; metrics.cbSize = sizeof(metrics); SystemParametersInfo(SPI_GETNONCLIENTMETRICS, metrics.cbSize, &metrics, 0); desc.setOneFamily(metrics.lfSmCaptionFont.lfFaceName); desc.setComputedSize(scale.width * fontSize); FontCascade font = FontCascade(desc, 0, 0); font.update(nullptr); GraphicsContext cg(context); cg.setFillColor(Color::black, ColorSpaceDeviceRGB); cg.drawText(font, TextRun(text), IntPoint(x, y)); }
static FontCascade makeFont(const WebFontDescription& description) { AtomicString::init(); String fontFamilyString(description.family, description.familyLength); FontCascadeDescription f; f.setOneFamily(fontFamilyString); f.setSpecifiedSize(description.size); f.setComputedSize(description.size); f.setIsItalic(description.italic); f.setWeight(description.bold ? FontWeightBold : FontWeightNormal); f.setIsAbsoluteSize(true); FontSmoothingType smoothingType; if (SUCCEEDED(WebPreferences::sharedStandardPreferences()->fontSmoothing(&smoothingType))) f.setRenderingMode(smoothingType == FontSmoothingTypeWindows ? AlternateRenderingMode : NormalRenderingMode); FontCascade font(f, 0, 0); font.update(0); return font; }
static FontCascade dragLabelFont(int size, bool bold, FontRenderingMode renderingMode) { FontCascade result; NONCLIENTMETRICS metrics; metrics.cbSize = sizeof(metrics); SystemParametersInfo(SPI_GETNONCLIENTMETRICS, metrics.cbSize, &metrics, 0); FontCascadeDescription description; description.setWeight(bold ? FontWeightBold : FontWeightNormal); description.setOneFamily(metrics.lfSmCaptionFont.lfFaceName); description.setSpecifiedSize((float)size); description.setComputedSize((float)size); description.setRenderingMode(renderingMode); result = FontCascade(description, 0, 0); result.update(0); return result; }
GlyphData FontCascadeFonts::glyphDataForSystemFallback(UChar32 c, const FontCascadeDescription& description, FontVariant variant) { // System fallback is character-dependent. auto& primaryRanges = realizeFallbackRangesAt(description, 0); auto* originalFont = primaryRanges.fontForCharacter(c); if (!originalFont) originalFont = &primaryRanges.fontForFirstRange(); auto systemFallbackFont = originalFont->systemFallbackFontForCharacter(c, description, m_isForPlatformFont); if (!systemFallbackFont) return GlyphData(); if (systemFallbackFont->platformData().orientation() == Vertical && !systemFallbackFont->hasVerticalGlyphs() && FontCascade::isCJKIdeographOrSymbol(c)) variant = BrokenIdeographVariant; GlyphData fallbackGlyphData; if (variant == NormalVariant) fallbackGlyphData = systemFallbackFont->glyphDataForCharacter(c); else fallbackGlyphData = systemFallbackFont->variantFont(description, variant)->glyphDataForCharacter(c); if (fallbackGlyphData.font && fallbackGlyphData.font->platformData().orientation() == Vertical && !fallbackGlyphData.font->isTextOrientationFallback()) { if (variant == NormalVariant && !FontCascade::isCJKIdeographOrSymbol(c)) fallbackGlyphData = glyphDataForNonCJKCharacterWithGlyphOrientation(c, description.nonCJKGlyphOrientation(), fallbackGlyphData); #if PLATFORM(COCOA) || USE(CAIRO) if (fallbackGlyphData.font->platformData().syntheticOblique() && FontCascade::isCJKIdeographOrSymbol(c)) fallbackGlyphData = glyphDataForCJKCharacterWithoutSyntheticItalic(c, fallbackGlyphData); #endif } // Keep the system fallback fonts we use alive. if (fallbackGlyphData.glyph) m_systemFallbackFontSet.add(WTFMove(systemFallbackFont)); return fallbackGlyphData; }
void FullscreenVideoController::draw() { auto bitmapDC = adoptGDIObject(::CreateCompatibleDC(HWndDC(m_hudWindow))); HGDIOBJ oldBitmap = SelectObject(bitmapDC.get(), m_bitmap.get()); GraphicsContext context(bitmapDC.get(), true); context.save(); // Draw the background IntSize outerRadius(borderRadius, borderRadius); IntRect outerRect(0, 0, windowWidth, windowHeight); IntSize innerRadius(borderRadius - borderThickness, borderRadius - borderThickness); IntRect innerRect(borderThickness, borderThickness, windowWidth - borderThickness * 2, windowHeight - borderThickness * 2); context.fillRoundedRect(FloatRoundedRect(outerRect, outerRadius, outerRadius, outerRadius, outerRadius), Color(borderColor)); context.setCompositeOperation(CompositeCopy); context.fillRoundedRect(FloatRoundedRect(innerRect, innerRadius, innerRadius, innerRadius, innerRadius), Color(backgroundColor)); // Draw the widgets m_playPauseButton.draw(context); m_volumeUpButton.draw(context); m_volumeSliderButton.draw(context); m_volumeDownButton.draw(context); m_timeSliderButton.draw(context); m_exitFullscreenButton.draw(context); m_volumeSlider.draw(context); m_timeSlider.draw(context); // Draw the text strings FontCascadeDescription desc; NONCLIENTMETRICS metrics; metrics.cbSize = sizeof(metrics); SystemParametersInfo(SPI_GETNONCLIENTMETRICS, metrics.cbSize, &metrics, 0); desc.setOneFamily(metrics.lfSmCaptionFont.lfFaceName); desc.setComputedSize(textSize); FontCascade font = FontCascade(desc, 0, 0); font.update(0); String s; // The y positioning of these two text strings is tricky because they are so small. They // are currently positioned relative to the center of the slider and then down the font // height / 4 (which is actually half of font height /2), which positions the center of // the text at the center of the slider. // Left string s = timeToString(currentTime()); int fontHeight = font.fontMetrics().height(); TextRun leftText(s); context.setFillColor(Color(textColor)); context.drawText(font, leftText, IntPoint(windowWidth / 2 - timeSliderWidth / 2 - margin - font.width(leftText), windowHeight - margin - sliderHeight / 2 + fontHeight / 4)); // Right string s = timeToString(currentTime() - duration()); TextRun rightText(s); context.setFillColor(Color(textColor)); context.drawText(font, rightText, IntPoint(windowWidth / 2 + timeSliderWidth / 2 + margin, windowHeight - margin - sliderHeight / 2 + fontHeight / 4)); // Copy to the window BLENDFUNCTION blendFunction = {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA}; SIZE size = { windowWidth, windowHeight }; POINT sourcePoint = {0, 0}; POINT destPoint = { m_hudPosition.x(), m_hudPosition.y() }; BOOL result = UpdateLayeredWindow(m_hudWindow, 0, &destPoint, &size, bitmapDC.get(), &sourcePoint, 0, &blendFunction, ULW_ALPHA); context.restore(); ::SelectObject(bitmapDC.get(), oldBitmap); }