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);
}
PassRefPtr<SimpleFontData> SimpleFontData::createScaledFontData(const FontDescription& fontDescription, float scaleFactor) const
{
    FontDescription desc = FontDescription(fontDescription);
    desc.setSpecifiedSize(scaleFactor * fontDescription.computedSize());
    FontPlatformData platformData(desc, desc.family().family());
    return SimpleFontData::create(platformData, isCustomFont(), false);
}
Example #3
0
HRESULT STDMETHODCALLTYPE DOMElement::font(WebFontDescription* webFontDescription)
{
    if (!webFontDescription) {
        ASSERT_NOT_REACHED();
        return E_POINTER;
    }

    ASSERT(m_element);

    WebCore::RenderElement* renderer = m_element->renderer();
    if (!renderer)
        return E_FAIL;

    FontDescription fontDescription = renderer->style().fontCascade().fontDescription();
    AtomicString family = fontDescription.firstFamily();

    // FIXME: This leaks. Delete this whole function to get rid of the leak.
    UChar* familyCharactersBuffer = new UChar[family.length()];
    StringView(family.string()).getCharactersWithUpconvert(familyCharactersBuffer);

    webFontDescription->family = familyCharactersBuffer;
    webFontDescription->familyLength = family.length();
    webFontDescription->size = fontDescription.computedSize();
    webFontDescription->bold = fontDescription.weight() >= WebCore::FontWeight600;
    webFontDescription->italic = fontDescription.italic();

    return S_OK;
}
Example #4
0
PassRefPtr<SimpleFontData> SimpleFontData::platformCreateScaledFontData(const FontDescription& fontDescription, float scaleFactor) const
{
    ASSERT(m_platformData.scaledFont());
    return SimpleFontData::create(FontPlatformData(cairo_scaled_font_get_font_face(m_platformData.scaledFont()),
                                                        scaleFactor * fontDescription.computedSize(),
                                                        m_platformData.syntheticBold(),
                                                        m_platformData.syntheticOblique()), isCustomFont(), false);
}
Example #5
0
PassOwnPtr<SimpleFontData> SimpleFontData::createScaledFontData(const FontDescription& fontDescription, float scaleFactor) const
{
    return adoptPtr(new SimpleFontData(FontPlatformData(m_platformData.m_font.get(),
                                                        scaleFactor * fontDescription.computedSize(),
                                                        m_platformData.syntheticBold(),
                                                        m_platformData.syntheticOblique()),
                                       isCustomFont(), false));
}
PassOwnPtr<SimpleFontData> SimpleFontData::createScaledFontData(const FontDescription& fontDescription, float scaleFactor) const
{
    LOGFONT winFont;
    GetObject(m_platformData.hfont(), sizeof(LOGFONT), &winFont);
    float scaledSize = scaleFactor * fontDescription.computedSize();
    winFont.lfHeight = -lroundf(scaledSize);
    HFONT hfont = CreateFontIndirect(&winFont);
    return adoptPtr(new SimpleFontData(FontPlatformData(hfont, scaledSize), isCustomFont(), false));
}
Example #7
0
PassRefPtr<SimpleFontData> SimpleFontData::platformCreateScaledFontData(const FontDescription& fontDescription, float scaleFactor) const
{
    LOGFONT winFont;
    GetObject(m_platformData.hfont(), sizeof(LOGFONT), &winFont);
    float scaledSize = scaleFactor * fontDescription.computedSize();
    winFont.lfHeight = -lroundf(scaledSize);
    HFONT hfont = CreateFontIndirect(&winFont);
    return SimpleFontData::create(FontPlatformData(hfont, scaledSize, m_platformData.orientation()), isCustomFont() ? CustomFontData::create(false) : 0);
}
Example #8
0
PassRefPtr<SimpleFontData> SimpleFontData::createScaledFontData(
    const FontDescription& fontDescription,
    float scaleFactor) const {
  const float scaledSize =
      lroundf(fontDescription.computedSize() * scaleFactor);
  return SimpleFontData::create(
      FontPlatformData(m_platformData, scaledSize),
      isCustomFont() ? CustomFontData::create() : nullptr);
}
Example #9
0
void RenderCombineText::combineText()
{
    if (!m_needsFontUpdate)
        return;

    m_isCombined = false;
    m_needsFontUpdate = false;

    // CSS3 spec says text-combine works only in vertical writing mode.
    if (style()->isHorizontalWritingMode())
        return;

    TextRun run = RenderBlock::constructTextRun(this, originalFont(), this, *style());
    FontDescription description = originalFont().fontDescription();
    float emWidth = description.computedSize() * textCombineMargin;
    bool shouldUpdateFont = false;

    description.setOrientation(Horizontal); // We are going to draw combined text horizontally.
    m_combinedTextWidth = originalFont().width(run);
    m_isCombined = m_combinedTextWidth <= emWidth;

    FontSelector* fontSelector = style()->font().fontSelector();

    if (m_isCombined)
        shouldUpdateFont = m_combineFontStyle->setFontDescription(description); // Need to change font orientation to horizontal.
    else {
        // Need to try compressed glyphs.
        static const FontWidthVariant widthVariants[] = { HalfWidth, ThirdWidth, QuarterWidth };
        for (size_t i = 0 ; i < WTF_ARRAY_LENGTH(widthVariants) ; ++i) {
            description.setWidthVariant(widthVariants[i]);
            Font compressedFont = Font(description, style()->font().letterSpacing(), style()->font().wordSpacing());
            compressedFont.update(fontSelector);
            float runWidth = compressedFont.width(run);
            if (runWidth <= emWidth) {
                m_combinedTextWidth = runWidth;
                m_isCombined = true;

                // Replace my font with the new one.
                shouldUpdateFont = m_combineFontStyle->setFontDescription(description);
                break;
            }
        }
    }

    if (!m_isCombined)
        shouldUpdateFont = m_combineFontStyle->setFontDescription(originalFont().fontDescription());

    if (shouldUpdateFont)
        m_combineFontStyle->font().update(fontSelector);

    if (m_isCombined) {
        DEFINE_STATIC_LOCAL(String, objectReplacementCharacterString, (&objectReplacementCharacter, 1));
        RenderText::setTextInternal(objectReplacementCharacterString.impl());
    }
}
PassRefPtr<SimpleFontData> SimpleFontData::platformCreateScaledFontData(const FontDescription& fontDescription, float scaleFactor) const
{
    const float scaledSize = lroundf(fontDescription.computedSize() * scaleFactor);
    return adoptRef(new SimpleFontData(
        FontPlatformData(m_platformData.font()->cur_lfnt->name,
            scaledSize,
            m_platformData.syntheticBold(),
            m_platformData.syntheticOblique(),
            m_platformData.orientation(),
            m_platformData.widthVariant()),
        isCustomFont(), false));
}
Example #11
0
FontPlatformData::FontPlatformData(const FontDescription& fontDescription, const AtomicString& familyName)
    : m_font(new QFont("Times New Roman", 12))
{
    m_font->setFamily(familyName.domString());
    m_font->setPixelSize(qRound(fontDescription.computedSize()));
    m_font->setItalic(fontDescription.italic());
    if (fontDescription.bold()) {
        // Qt's Bold is 75, Webkit is 63.
        m_font->setWeight(QFont::Bold);
    } else {
        m_font->setWeight(fontDescription.weight());
    }
}
Example #12
0
PassRefPtr<Font>
Font::platformCreateScaledFont(const FontDescription& orig, float scaleFactor) const
{
    FontDescription d(orig);
    d.setComputedSize(orig.computedSize() * scaleFactor);
    d.setSpecifiedSize(orig.specifiedSize() * scaleFactor);
    FontPlatformData* ret = new FontPlatformData(d, m_platformData.font()->familyName().data());

    if (!ret || !ret->font() || !ret->font()->font()) {
        delete ret;
        return adoptRef((Font *)0);
    }

    return Font::create(*ret);
}
FontPlatformData::FontPlatformData(const FontDescription& fontDescription, const AtomicString& familyName)
    : m_pattern(0)
    , m_size(fontDescription.computedSize())
    , m_syntheticBold(false)
    , m_syntheticOblique(false)
    , m_scaledFont(0)
{
    if (fontDescription.italic()) {
        m_pixelFont = &NormalItalicPixelFont;
        m_syntheticOblique = true;
    } else if (fontDescription.weight() >= FontWeightBold) {
        m_pixelFont = &NormalBoldPixelFont;
        m_syntheticBold = true;
    } else 
        m_pixelFont = &NormalPixelFont;
    FontPlatformData::init();
}
FontPlatformData::FontPlatformData(const FontDescription& description, const AtomicString& familyName, int wordSpacing, int letterSpacing)
    : m_data(new FontPlatformDataPrivate())
{
    QFont& font = m_data->font;
    font.setFamily(familyName);
    font.setPixelSize(qRound(description.computedSize()));
    font.setItalic(description.italic());
    font.setWeight(toQFontWeight(description.weight()));
    font.setWordSpacing(wordSpacing);
    font.setLetterSpacing(QFont::AbsoluteSpacing, letterSpacing);
    const bool smallCaps = description.smallCaps();
    font.setCapitalization(smallCaps ? QFont::SmallCaps : QFont::MixedCase);
#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)
    font.setStyleStrategy(QFont::ForceIntegerMetrics);
#endif

    m_data->bold = font.bold();
    m_data->size = font.pointSizeF();
}
Example #15
0
HRESULT STDMETHODCALLTYPE DOMElement::font(WebFontDescription* webFontDescription)
{
    if (!webFontDescription) {
        ASSERT_NOT_REACHED();
        return E_POINTER;
    }

    ASSERT(m_element);

    WebCore::RenderElement* renderer = m_element->renderer();
    if (!renderer)
        return E_FAIL;

    FontDescription fontDescription = renderer->style().font().fontDescription();
    AtomicString family = fontDescription.firstFamily();
    webFontDescription->family = family.characters();
    webFontDescription->familyLength = family.length();
    webFontDescription->size = fontDescription.computedSize();
    webFontDescription->bold = fontDescription.weight() >= WebCore::FontWeight600;
    webFontDescription->italic = fontDescription.italic();

    return S_OK;
}
Example #16
0
void TextAutoSizingValue::reset()
{
    HashSet<RefPtr<Node> >::iterator end = m_autoSizedNodes.end();
    for (HashSet<RefPtr<Node> >::iterator i = m_autoSizedNodes.begin(); i != end; ++i) {
        const RefPtr<Node>& autoSizingNode = *i;
        RenderText* text = static_cast<RenderText*>(autoSizingNode->renderer());
        if (!text)
            continue;
        // Reset the font size back to the original specified size
        FontDescription fontDescription = text->style().fontDescription();
        float originalSize = fontDescription.specifiedSize();
        if (fontDescription.computedSize() != originalSize) {
            fontDescription.setComputedSize(originalSize);
            RefPtr<RenderStyle> style = cloneRenderStyleWithState(text->style());
            style->setFontDescription(fontDescription);
            style->font().update(autoSizingNode->document().ensureStyleResolver().fontSelector());
            text->parent()->setStyle(style.releaseNonNull());
        }
        // Reset the line height of the parent.
        RenderElement* parentRenderer = text->parent();
        if (!parentRenderer)
            continue;
        
        if (parentRenderer->isAnonymousBlock())
            parentRenderer = parentRenderer->parent();
        
        const RenderStyle& parentStyle = parentRenderer->style();
        Length originalLineHeight = parentStyle.specifiedLineHeight();
        if (originalLineHeight != parentStyle.lineHeight()) {
            RefPtr<RenderStyle> newParentStyle = cloneRenderStyleWithState(parentStyle);
            newParentStyle->setLineHeight(originalLineHeight);
            newParentStyle->setFontDescription(fontDescription);
            newParentStyle->font().update(autoSizingNode->document().ensureStyleResolver().fontSelector());
            parentRenderer->setStyle(newParentStyle.releaseNonNull());
        }
    }
}
Example #17
0
void RenderCombineText::combineText()
{
    if (!m_needsFontUpdate)
        return;

    m_isCombined = false;
    m_needsFontUpdate = false;

    // CSS3 spec says text-combine works only in vertical writing mode.
    if (style().isHorizontalWritingMode())
        return;

    FontDescription description = originalFont().fontDescription();
    float emWidth = description.computedSize() * textCombineMargin;
    bool shouldUpdateFont = false;

    description.setOrientation(Horizontal); // We are going to draw combined text horizontally.
    
    GlyphOverflow glyphOverflow;
    glyphOverflow.computeBounds = true;
    
    float combinedTextWidth = width(0, textLength(), originalFont(), 0, nullptr, &glyphOverflow);
    m_isCombined = combinedTextWidth <= emWidth;
    
    FontSelector* fontSelector = style().fontCascade().fontSelector();

    if (m_isCombined)
        shouldUpdateFont = m_combineFontStyle->setFontDescription(description); // Need to change font orientation to horizontal.
    else {
        // Need to try compressed glyphs.
        static const FontWidthVariant widthVariants[] = { HalfWidth, ThirdWidth, QuarterWidth };
        for (size_t i = 0 ; i < WTF_ARRAY_LENGTH(widthVariants) ; ++i) {
            description.setWidthVariant(widthVariants[i]);

            FontCascade compressedFont(description, style().fontCascade().letterSpacing(), style().fontCascade().wordSpacing());
            compressedFont.update(fontSelector);
            
            float runWidth = RenderText::width(0, textLength(), compressedFont, 0, nullptr, &glyphOverflow);
            if (runWidth <= emWidth) {
                combinedTextWidth = runWidth;
                m_isCombined = true;

                // Replace my font with the new one.
                shouldUpdateFont = m_combineFontStyle->setFontDescription(description);
                break;
            }
        }
    }

    if (!m_isCombined)
        shouldUpdateFont = m_combineFontStyle->setFontDescription(originalFont().fontDescription());

    if (shouldUpdateFont)
        m_combineFontStyle->fontCascade().update(fontSelector);

    if (m_isCombined) {
        DEPRECATED_DEFINE_STATIC_LOCAL(String, objectReplacementCharacterString, (&objectReplacementCharacter, 1));
        RenderText::setRenderedText(objectReplacementCharacterString.impl());
        m_combinedTextSize = FloatSize(combinedTextWidth, glyphOverflow.bottom + glyphOverflow.top);
    }
}
PassOwnPtr<SimpleFontData> SimpleFontData::createScaledFontData(const FontDescription& fontDescription, float scaleFactor) const
{
    const float scaledSize = lroundf(fontDescription.computedSize() * scaleFactor);
    return adoptPtr(new SimpleFontData(FontPlatformData(m_platformData, scaledSize), isCustomFont(), false));
}
FontPlatformData::FontPlatformData(const FontDescription& fontDescription, const AtomicString& familyName)
    : m_pattern(0)
    , m_fallbacks(0)
    , m_size(fontDescription.computedSize())
    , m_syntheticBold(false)
    , m_syntheticOblique(false)
    , m_scaledFont(0)
    , m_face(0)
{
    FontPlatformData::init();

    CString familyNameString = familyName.string().utf8();
    const char* fcfamily = familyNameString.data();

    int fcslant = FC_SLANT_ROMAN;
    // FIXME: Map all FontWeight values to fontconfig weights.
    int fcweight = FC_WEIGHT_NORMAL;
    float fcsize = fontDescription.computedSize();
    if (fontDescription.italic())
        fcslant = FC_SLANT_ITALIC;
    if (fontDescription.weight() >= FontWeight600)
        fcweight = FC_WEIGHT_BOLD;

    FcConfig *config = FcConfigGetCurrent();

    //printf("family = %s\n", fcfamily);

    int type = fontDescription.genericFamily();

    FcPattern* pattern = FcPatternCreate();
    
    if (!FcPatternAddString(pattern, FC_FAMILY, reinterpret_cast<const FcChar8*>(fcfamily)))
        goto freePattern;

    switch (type) {
        case FontDescription::SerifFamily:
            fcfamily = "serif";
            break;
        case FontDescription::SansSerifFamily:
            fcfamily = "sans-serif";
            break;
        case FontDescription::MonospaceFamily:
            fcfamily = "monospace";
            break;
        case FontDescription::NoFamily:
        case FontDescription::StandardFamily:
        default:
            fcfamily = "sans-serif";
    }

    if (!FcPatternAddString(pattern, FC_FAMILY, reinterpret_cast<const FcChar8*>(fcfamily)))
        goto freePattern;
    if (!FcPatternAddInteger(pattern, FC_SLANT, fcslant))
        goto freePattern;
    if (!FcPatternAddInteger(pattern, FC_WEIGHT, fcweight))
        goto freePattern;
    if (!FcPatternAddDouble(pattern, FC_PIXEL_SIZE, fcsize))
        goto freePattern;

    FcConfigSubstitute(config, pattern, FcMatchPattern);
    FcDefaultSubstitute(pattern);

    FcResult fcresult;
    m_pattern = FcFontMatch(config, pattern, &fcresult);
    FcPatternReference(m_pattern);
    // FIXME: should we set some default font?
    if (!m_pattern)
        goto freePattern;

    FcChar8 *fc_filename;
    char *filename;
    int id;
    id = 0;

    if (FcPatternGetString(m_pattern, FC_FILE, 0, &fc_filename) != FcResultMatch) {
        LOG(FontEngine, "cannot retrieve font\n");
        goto freePattern;
    }

    filename = (char *) fc_filename; //use C cast as FcChar is a fontconfig type
    //printf("filename = %s\n", filename);

    if (FcPatternGetInteger(m_pattern, FC_INDEX, 0, &id) != FcResultMatch) {
        LOG(FontEngine, "cannot retrieve font index\n");
        goto freePattern;
    }
    
    if (FT_Error error = FT_New_Face(m_library, filename, id, &m_face)) {
    //if (FT_Error error = FT_New_Face(m_library, too, id, &m_face)) {
        LOG(FontEngine, "fail to open fonti %s with index %d (error = 0x%x)\n", filename, id, error);
        m_face = 0;
        goto freePattern;
    }

    FT_Set_Pixel_Sizes(m_face, 0, static_cast<uint> (fontDescription.computedSize()));
    //DBGML(MODULE_FONTS, LEVEL_INFO, "open font %s with size %d\n", filename, static_cast<uint> (fontDescription.specifiedSize()));

freePattern:
    FcPatternDestroy(pattern);
    FcConfigDestroy(config);
}
Example #20
0
void PopupListBox::paintRow(GraphicsContext* gc, const IntRect& rect, int rowIndex)
{
    // This code is based largely on RenderListBox::paint* methods.

    IntRect rowRect = getRowBounds(rowIndex);
    if (!rowRect.intersects(rect))
        return;

    PopupMenuStyle style = m_popupClient->itemStyle(rowIndex);

    // Paint background
    Color backColor, textColor, labelColor;
    if (rowIndex == m_selectedIndex) {
        backColor = RenderTheme::theme().activeListBoxSelectionBackgroundColor();
        textColor = RenderTheme::theme().activeListBoxSelectionForegroundColor();
        labelColor = textColor;
    } else {
        backColor = style.backgroundColor();
        textColor = style.foregroundColor();

#if OS(LINUX) || OS(ANDROID)
        // On other platforms, the <option> background color is the same as the
        // <select> background color. On Linux, that makes the <option>
        // background color very dark, so by default, try to use a lighter
        // background color for <option>s.
        if (style.backgroundColorType() == PopupMenuStyle::DefaultBackgroundColor && RenderTheme::theme().systemColor(CSSValueButtonface) == backColor)
            backColor = RenderTheme::theme().systemColor(CSSValueMenu);
#endif

        // FIXME: for now the label color is hard-coded. It should be added to
        // the PopupMenuStyle.
        labelColor = Color(115, 115, 115);
    }

    // If we have a transparent background, make sure it has a color to blend
    // against.
    if (backColor.hasAlpha())
        gc->fillRect(rowRect, Color::white);

    gc->fillRect(rowRect, backColor);

    // It doesn't look good but Autofill requires special style for separator.
    // Autofill doesn't have padding and #dcdcdc color.
    if (m_popupClient->itemIsSeparator(rowIndex)) {
        int padding = style.menuType() == PopupMenuStyle::AutofillPopup ? 0 : separatorPadding;
        IntRect separatorRect(
            rowRect.x() + padding,
            rowRect.y() + (rowRect.height() - separatorHeight) / 2,
            rowRect.width() - 2 * padding, separatorHeight);
        gc->fillRect(separatorRect, style.menuType() == PopupMenuStyle::AutofillPopup ? Color(0xdc, 0xdc, 0xdc) : textColor);
        return;
    }

    if (!style.isVisible())
        return;

    gc->setFillColor(textColor);

    FontCachePurgePreventer fontCachePurgePreventer;

    Font itemFont = getRowFont(rowIndex);
    // FIXME: http://crbug.com/19872 We should get the padding of individual option
    // elements. This probably implies changes to PopupMenuClient.
    bool rightAligned = m_popupClient->menuStyle().textDirection() == RTL;
    int textX = 0;
    int maxWidth = 0;
    if (rightAligned)
        maxWidth = rowRect.width() - max<int>(0, m_popupClient->clientPaddingRight() - m_popupClient->clientInsetRight());
    else {
        textX = max<int>(0, m_popupClient->clientPaddingLeft() - m_popupClient->clientInsetLeft());
        maxWidth = rowRect.width() - textX;
    }
    // Prepare text to be drawn.
    String itemText = m_popupClient->itemText(rowIndex);
    String itemLabel = m_popupClient->itemLabel(rowIndex);
    String itemIcon = m_popupClient->itemIcon(rowIndex);
    if (m_settings.restrictWidthOfListBox) { // Truncate strings to fit in.
        // FIXME: We should leftTruncate for the rtl case.
        // StringTruncator::leftTruncate would have to be implemented.
        String str = StringTruncator::rightTruncate(itemText, maxWidth, itemFont);
        if (str != itemText) {
            itemText = str;
            // Don't display the label or icon, we already don't have enough
            // room for the item text.
            itemLabel = "";
            itemIcon = "";
        } else if (!itemLabel.isEmpty()) {
            int availableWidth = maxWidth - textToLabelPadding - StringTruncator::width(itemText, itemFont);
            itemLabel = StringTruncator::rightTruncate(itemLabel, availableWidth, itemFont);
        }
    }

    // Prepare the directionality to draw text.
    TextRun textRun(itemText, 0, 0, TextRun::AllowTrailingExpansion, style.textDirection(), style.hasTextDirectionOverride());
    // If the text is right-to-left, make it right-aligned by adjusting its
    // beginning position.
    if (rightAligned)
        textX += maxWidth - itemFont.width(textRun);

    // Draw the item text.
    int textY = rowRect.y() + itemFont.fontMetrics().ascent() + (rowRect.height() - itemFont.fontMetrics().height()) / 2;
    TextRunPaintInfo textRunPaintInfo(textRun);
    textRunPaintInfo.bounds = rowRect;
    gc->drawBidiText(itemFont, textRunPaintInfo, IntPoint(textX, textY));

    // We are using the left padding as the right padding includes room for the scroll-bar which
    // does not show in this case.
    int rightPadding = max<int>(0, m_popupClient->clientPaddingLeft() - m_popupClient->clientInsetLeft());
    int remainingWidth = rowRect.width() - rightPadding;

    // Draw the icon if applicable.
    RefPtr<Image> image(Image::loadPlatformResource(itemIcon.utf8().data()));
    if (image && !image->isNull()) {
        IntRect imageRect = image->rect();
        remainingWidth -= (imageRect.width() + labelToIconPadding);
        imageRect.setX(rowRect.width() - rightPadding - imageRect.width());
        imageRect.setY(rowRect.y() + (rowRect.height() - imageRect.height()) / 2);
        gc->drawImage(image.get(), imageRect);
    }

    // Draw the the label if applicable.
    if (itemLabel.isEmpty())
        return;

    // Autofill label is 0.9 smaller than regular font size.
    if (style.menuType() == PopupMenuStyle::AutofillPopup) {
        itemFont = m_popupClient->itemStyle(rowIndex).font();
        FontDescription d = itemFont.fontDescription();
        d.setComputedSize(d.computedSize() * 0.9);
        itemFont = Font(d, itemFont.letterSpacing(), itemFont.wordSpacing());
        itemFont.update(0);
    }

    TextRun labelTextRun(itemLabel, 0, 0, TextRun::AllowTrailingExpansion, style.textDirection(), style.hasTextDirectionOverride());
    if (rightAligned)
        textX = max<int>(0, m_popupClient->clientPaddingLeft() - m_popupClient->clientInsetLeft());
    else
        textX = remainingWidth - itemFont.width(labelTextRun);
    TextRunPaintInfo labelTextRunPaintInfo(labelTextRun);
    labelTextRunPaintInfo.bounds = rowRect;

    gc->setFillColor(labelColor);
    gc->drawBidiText(itemFont, labelTextRunPaintInfo, IntPoint(textX, textY));
}
FontPlatformData::FontPlatformData(const FontDescription& fontDescription, const AtomicString& familyName)
    : m_context(0)
    , m_font(0)
    , m_size(fontDescription.computedSize())
    , m_syntheticBold(false)
    , m_syntheticOblique(false)
    , m_scaledFont(0)
{
    FontPlatformData::init();

    CString stored_family = familyName.string().utf8();
    char const* families[] = {
      stored_family.data(),
      NULL
    };

    switch (fontDescription.genericFamily()) {
    case FontDescription::SerifFamily:
        families[1] = "serif";
        break;
    case FontDescription::SansSerifFamily:
        families[1] = "sans";
        break;
    case FontDescription::MonospaceFamily:
        families[1] = "monospace";
        break;
    case FontDescription::NoFamily:
    case FontDescription::StandardFamily:
    default:
        families[1] = "sans";
        break;
    }

    PangoFontDescription* description = pango_font_description_new();
    pango_font_description_set_absolute_size(description, fontDescription.computedSize() * PANGO_SCALE);

    // FIXME: Map all FontWeight values to Pango font weights.
    if (fontDescription.weight() >= FontWeight600)
        pango_font_description_set_weight(description, PANGO_WEIGHT_BOLD);
    if (fontDescription.italic())
        pango_font_description_set_style(description, PANGO_STYLE_ITALIC);

#if PANGO_VERSION_CHECK(1,21,5)   // deprecated in 1.21
    m_context = pango_font_map_create_context(m_fontMap);
#else
    m_context = pango_cairo_font_map_create_context(PANGO_CAIRO_FONT_MAP(m_fontMap));
#endif
    for (unsigned int i = 0; !m_font && i < G_N_ELEMENTS(families); i++) {
        pango_font_description_set_family(description, families[i]);
        pango_context_set_font_description(m_context, description);
        m_font = pango_font_map_load_font(m_fontMap, m_context, description);
    }

#if PANGO_VERSION_CHECK(1,18,0)
    if (m_font)
        m_scaledFont = cairo_scaled_font_reference(pango_cairo_font_get_scaled_font(PANGO_CAIRO_FONT(m_font)));
#else
    // This compatibility code for older versions of Pango is not well-tested.
    if (m_font) {
        PangoFcFont* fcfont = PANGO_FC_FONT(m_font);
        cairo_font_face_t* face = cairo_ft_font_face_create_for_pattern(fcfont->font_pattern);
        double size;
        if (FcPatternGetDouble(fcfont->font_pattern, FC_PIXEL_SIZE, 0, &size) != FcResultMatch)
            size = 12.0;
        cairo_matrix_t fontMatrix;
        cairo_matrix_init_scale(&fontMatrix, size, size);
        cairo_font_options_t* fontOptions;
        if (pango_cairo_context_get_font_options(m_context))
            fontOptions = cairo_font_options_copy(pango_cairo_context_get_font_options(m_context));
        else
            fontOptions = cairo_font_options_create();
        cairo_matrix_t ctm;
        cairo_matrix_init_identity(&ctm);
        m_scaledFont = cairo_scaled_font_create(face, &fontMatrix, &ctm, fontOptions);
        cairo_font_options_destroy(fontOptions);
        cairo_font_face_destroy(face);
    }
#endif
    pango_font_description_free(description);
}
FontPlatformData::FontPlatformData(const FontDescription& fontDescription, const UChar *characters, int length)
    : m_context(0)
    , m_font(0)
    , m_size(fontDescription.computedSize())
    , m_syntheticBold(false)
    , m_syntheticOblique(false)
    , m_scaledFont(0)
{
    FontPlatformData::init();

    const UChar character = characters[0];

    char const *family;
    switch (fontDescription.genericFamily()) {
        case FontDescription::SerifFamily:
            family = "serif";
            break;
        case FontDescription::SansSerifFamily:
            family = "sans";
            break;
        case FontDescription::MonospaceFamily:
            family = "monospace";
            break;
        case FontDescription::NoFamily:
        case FontDescription::StandardFamily:
        default:
            family = "sans";
            break;
    }

    m_context = pango_cairo_font_map_create_context(PANGO_CAIRO_FONT_MAP(m_fontMap));

    PangoFontDescription* description = pango_font_description_new();

    pango_font_description_set_absolute_size(description, fontDescription.computedSize() * PANGO_SCALE);
    if (fontDescription.weight() >= FontWeight600)
        pango_font_description_set_weight(description, PANGO_WEIGHT_BOLD);
    if (fontDescription.italic())
        pango_font_description_set_style(description, PANGO_STYLE_ITALIC);

    pango_font_description_set_family(description, family);
    pango_context_set_font_description(m_context, description);

    PangoFontset *fset = pango_font_map_load_fontset (m_fontMap, m_context, description, NULL); 

    // Get the font from the fontset which contains the best glyph for this character
    m_font = pango_fontset_get_font(fset, (guint)character);

#if PANGO_VERSION_CHECK(1,18,0)
    if (m_font)
        m_scaledFont = cairo_scaled_font_reference(pango_cairo_font_get_scaled_font(PANGO_CAIRO_FONT(m_font)));
#else
    // This compatibility code for older versions of Pango is not well-tested.
    if (m_font) {
        PangoFcFont* fcfont = PANGO_FC_FONT(m_font);
        cairo_font_face_t* face = cairo_ft_font_face_create_for_pattern(fcfont->font_pattern);
        double size;
        if (FcPatternGetDouble(fcfont->font_pattern, FC_PIXEL_SIZE, 0, &size) != FcResultMatch)
          size = 12.0;
        cairo_matrix_t fontMatrix;
        cairo_matrix_init_scale(&fontMatrix, size, size);
        cairo_font_options_t* fontOptions;
        if (pango_cairo_context_get_font_options(m_context))
          fontOptions = cairo_font_options_copy(pango_cairo_context_get_font_options(m_context));
        else
          fontOptions = cairo_font_options_create();
        cairo_matrix_t ctm;
        cairo_matrix_init_identity(&ctm);
        m_scaledFont = cairo_scaled_font_create(face, &fontMatrix, &ctm, fontOptions);
        cairo_font_options_destroy(fontOptions);
        cairo_font_face_destroy(face);
    }
#endif

    pango_font_description_free(description);
}
FontPlatformData::FontPlatformData(const FontDescription& description, const AtomicString& familyName, const UChar* characters, int length, int wordSpacing, int letterSpacing)
    : m_data(new FontPlatformDataPrivate())
{
    using namespace EA::WebKit;

    EA::WebKit::TextStyle textStyle;  // We rather use the textStyle so we can pass in the spacing and the fx info directly. 
    InitTextStyle(textStyle);
    
	// Note by Arpit Baldeva:
	// The way WebCore expects us to handle creation of FontPlatformData is to take the familyName
	// in FontCacheEA.cpp and return a valid pointer only if that particular font can be created.
	// In CSS, one can specify multiple font families in order of preference. If you return NULL,
	// WebCore sends the next highest priority font. Note that it also converts generic font family
	// name (such as serif) to the one you specify as your default in the Settings (For example,
	// Times New Roman for us). So the system is supposed to be pretty simple.
	
	// The problem we have is that EAText wants to builds a priority array in one shot. Also, if you
	// request a font and it is not found, it may return one of the fallback fonts even though you may
	// have something down the priority order available in EAText.
	
	// So what we do here is build up that array.
	
	//-- Build FamilyName array ---
	ITextSystem* pTextSystem = GetTextSystem();
	const uint32_t familyNameArrayCapacity = pTextSystem->GetFamilyNameArrayCapacity();

	uint32_t i = 0;
	EAW_ASSERT_MSG(!familyName.isEmpty(), "Family name can never be empty");
	CopyFontFamilyName(textStyle.mFamilyNameArray[i],familyName);
    
	const FontFamily* pfontFamily = &(description.family());
	pfontFamily = pfontFamily->next();
	++i;

	const EA::WebKit::Parameters& params = EA::WebKit::GetParameters();
	
	// Here, we iterate through the list and copy the fonts to the destination array in the order of priority.
	// If we come across a generic font, we read it from the Params based on the generic family set in the description. 
	bool genericFontAdded = false;
	while(pfontFamily && i < familyNameArrayCapacity)
	{
		if(pfontFamily->family().startsWith("-webkit",true)) // A generic font family 
		{
			genericFontAdded = true;
			const char16_t* type = 0;
			switch(description.genericFamily())
			{
			case FontDescription::SerifFamily:
				type = params.mFontFamilySerif;
				break;

			case FontDescription::SansSerifFamily:
				type = params.mFontFamilySansSerif;
				break;

			case FontDescription::MonospaceFamily:
				type = params.mFontFamilyMonospace;
				break;

			case FontDescription::CursiveFamily:
				type = params.mFontFamilyCursive;
				break;

			case FontDescription::FantasyFamily:
				type = params.mFontFamilyFantasy;
				break;

			default:
			case FontDescription::NoFamily:
			case FontDescription::StandardFamily:
				type = params.mFontFamilyStandard;
				break;
			}

			if(type)
			{
				EA::Internal::Strcpy(textStyle.mFamilyNameArray[i],type);
				++i;
			}
			break;
		}

		CopyFontFamilyName(textStyle.mFamilyNameArray[i], pfontFamily->family());
		++i;
		pfontFamily = pfontFamily->next();
	}
	
	// If we went through all the fonts specified but a generic font was not added, we add the standard font as a fallback.
	// It is probably not a good practice to not specify a generic font family for any font but we deal with that situation here.
	if( i < familyNameArrayCapacity && !genericFontAdded)
	{
		EA::Internal::Strcpy(textStyle.mFamilyNameArray[i],params.mFontFamilyStandard);
		++i;
	}

	if(i < familyNameArrayCapacity)
		*textStyle.mFamilyNameArray[i] = 0;

	// verify that spacing can be used raw without size adjustments. 
    textStyle.mfLetterSpacing =  static_cast<float> (letterSpacing);   
    textStyle.mfWordSpacing =  static_cast<float> (wordSpacing);   

     // Size
    const float fFontSize = description.computedSize();
    const float fAdjustedFontSize = GetFontAdjustedSize(fFontSize); 
    textStyle.mfSize = fAdjustedFontSize;   
    
    // Italic
    const bool bItalic = description.italic();
    if(bItalic)
        textStyle.mStyle = EA::WebKit::kStyleItalic; 
      
    // Weight
    const WebCore::FontWeight fontWeight = description.weight();
    textStyle.mfWeight = GetFontAdjustedWeight(fontWeight);
    
    // Variant
    if(description.smallCaps())
        textStyle.mVariant = EA::WebKit::kVariantSmallCaps;

    // Smooth
    // We act like FireFox under Windows does with respect to sizes and weights.
    bool smooth = IsFontSmooth(fFontSize, description.fontSmoothing());
    if(smooth)
        textStyle.mSmooth = EA::WebKit::kSmoothEnabled;    

    // Effects.  
    const EA::WebKit::TextEffectData& effectData = description.getTextEffectData();
    textStyle.mTextEffectData = effectData;

    // Now get the requested font 
    if(pTextSystem)      
    { 
        IFont* pFont = pTextSystem->GetFont(textStyle, length ? characters[0] : ' ');
        EAW_ASSERT(pFont);
        m_data->mpFont = pFont;
    }
}
FontPlatformData::FontPlatformData(const FontDescription& in_desc, const AtomicString& in_family)
    : m_orientation(in_desc.orientation())
    , m_size(in_desc.computedSize())
{
    m_font = _createWKCFont(in_desc, in_family.string().utf8().data());
}