Home | History | Annotate | Download | only in resolver
      1 /*
      2  * Copyright (C) 1999 Lars Knoll (knoll (at) kde.org)
      3  * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
      4  * Copyright (C) 2013 Google Inc. All rights reserved.
      5  *
      6  * This library is free software; you can redistribute it and/or
      7  * modify it under the terms of the GNU Library General Public
      8  * License as published by the Free Software Foundation; either
      9  * version 2 of the License, or (at your option) any later version.
     10  *
     11  * This library is distributed in the hope that it will be useful,
     12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     14  * Library General Public License for more details.
     15  *
     16  * You should have received a copy of the GNU Library General Public License
     17  * along with this library; see the file COPYING.LIB.  If not, write to
     18  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     19  * Boston, MA 02110-1301, USA.
     20  *
     21  */
     22 
     23 #include "config.h"
     24 #include "core/css/resolver/FontBuilder.h"
     25 
     26 #include "core/css/CSSCalculationValue.h"
     27 #include "core/css/CSSFontFeatureValue.h"
     28 #include "core/css/CSSToLengthConversionData.h"
     29 #include "core/css/FontSize.h"
     30 #include "core/frame/LocalFrame.h"
     31 #include "core/frame/Settings.h"
     32 #include "core/rendering/RenderTheme.h"
     33 #include "core/rendering/RenderView.h"
     34 #include "platform/fonts/FontDescription.h"
     35 #include "platform/text/LocaleToScriptMapping.h"
     36 
     37 namespace WebCore {
     38 
     39 // FIXME: This scoping class is a short-term fix to minimize the changes in
     40 // Font-constructing logic.
     41 class FontDescriptionChangeScope {
     42 public:
     43     FontDescriptionChangeScope(FontBuilder* fontBuilder)
     44         : m_fontBuilder(fontBuilder)
     45         , m_fontDescription(fontBuilder->m_style->fontDescription())
     46     {
     47     }
     48 
     49     void reset() { m_fontDescription = FontDescription(); }
     50     void set(const FontDescription& fontDescription) { m_fontDescription = fontDescription; }
     51     FontDescription& fontDescription() { return m_fontDescription; }
     52 
     53     ~FontDescriptionChangeScope()
     54     {
     55         m_fontBuilder->didChangeFontParameters(m_fontBuilder->m_style->setFontDescription(m_fontDescription));
     56     }
     57 
     58 private:
     59     FontBuilder* m_fontBuilder;
     60     FontDescription m_fontDescription;
     61 };
     62 
     63 FontBuilder::FontBuilder()
     64     : m_document(0)
     65     , m_fontSizehasViewportUnits(false)
     66     , m_style(0)
     67     , m_fontDirty(false)
     68 {
     69 }
     70 
     71 void FontBuilder::initForStyleResolve(const Document& document, RenderStyle* style)
     72 {
     73     ASSERT(document.frame());
     74     m_document = &document;
     75     m_style = style;
     76     m_fontDirty = false;
     77 }
     78 
     79 inline static void setFontFamilyToStandard(FontDescription& fontDescription, const Document* document)
     80 {
     81     if (!document || !document->settings())
     82         return;
     83 
     84     fontDescription.setGenericFamily(FontDescription::StandardFamily);
     85     const AtomicString& standardFontFamily = document->settings()->genericFontFamilySettings().standard();
     86     if (standardFontFamily.isEmpty())
     87         return;
     88 
     89     fontDescription.firstFamily().setFamily(standardFontFamily);
     90     // FIXME: Why is this needed here?
     91     fontDescription.firstFamily().appendFamily(nullptr);
     92 }
     93 
     94 void FontBuilder::setInitial(float effectiveZoom)
     95 {
     96     ASSERT(m_document && m_document->settings());
     97     if (!m_document || !m_document->settings())
     98         return;
     99 
    100     FontDescriptionChangeScope scope(this);
    101 
    102     scope.reset();
    103     setFontFamilyToStandard(scope.fontDescription(), m_document);
    104     scope.fontDescription().setKeywordSize(CSSValueMedium - CSSValueXxSmall + 1);
    105     setSize(scope.fontDescription(), effectiveZoom, FontSize::fontSizeForKeyword(m_document, CSSValueMedium, false));
    106 }
    107 
    108 void FontBuilder::inheritFrom(const FontDescription& fontDescription)
    109 {
    110     FontDescriptionChangeScope scope(this);
    111 
    112     scope.set(fontDescription);
    113 }
    114 
    115 void FontBuilder::didChangeFontParameters(bool changed)
    116 {
    117     m_fontDirty |= changed;
    118 }
    119 
    120 void FontBuilder::fromSystemFont(CSSValueID valueId, float effectiveZoom)
    121 {
    122     FontDescriptionChangeScope scope(this);
    123 
    124     FontDescription fontDescription;
    125     RenderTheme::theme().systemFont(valueId, fontDescription);
    126 
    127     // Double-check and see if the theme did anything. If not, don't bother updating the font.
    128     if (!fontDescription.isAbsoluteSize())
    129         return;
    130 
    131     // Make sure the rendering mode and printer font settings are updated.
    132     const Settings* settings = m_document->settings();
    133     ASSERT(settings); // If we're doing style resolution, this document should always be in a frame and thus have settings
    134     if (!settings)
    135         return;
    136 
    137     // Handle the zoom factor.
    138     fontDescription.setComputedSize(getComputedSizeFromSpecifiedSize(fontDescription, effectiveZoom, fontDescription.specifiedSize()));
    139     scope.set(fontDescription);
    140 }
    141 
    142 void FontBuilder::setFontFamilyInitial()
    143 {
    144     FontDescriptionChangeScope scope(this);
    145 
    146     setFontFamilyToStandard(scope.fontDescription(), m_document);
    147 }
    148 
    149 void FontBuilder::setFontFamilyInherit(const FontDescription& parentFontDescription)
    150 {
    151     FontDescriptionChangeScope scope(this);
    152 
    153     scope.fontDescription().setGenericFamily(parentFontDescription.genericFamily());
    154     scope.fontDescription().setFamily(parentFontDescription.family());
    155 }
    156 
    157 // FIXME: I am not convinced FontBuilder needs to know anything about CSSValues.
    158 void FontBuilder::setFontFamilyValue(CSSValue* value)
    159 {
    160     FontDescriptionChangeScope scope(this);
    161 
    162     if (!value->isValueList())
    163         return;
    164 
    165     FontFamily& firstFamily = scope.fontDescription().firstFamily();
    166     FontFamily* currFamily = 0;
    167 
    168     // Before mapping in a new font-family property, we should reset the generic family.
    169     bool oldFamilyUsedFixedDefaultSize = scope.fontDescription().useFixedDefaultSize();
    170     scope.fontDescription().setGenericFamily(FontDescription::NoFamily);
    171 
    172     for (CSSValueListIterator i = value; i.hasMore(); i.advance()) {
    173         CSSValue* item = i.value();
    174         if (!item->isPrimitiveValue())
    175             continue;
    176         CSSPrimitiveValue* contentValue = toCSSPrimitiveValue(item);
    177         AtomicString face;
    178         Settings* settings = m_document->settings();
    179         if (contentValue->isString()) {
    180             face = AtomicString(contentValue->getStringValue());
    181         } else if (settings) {
    182             switch (contentValue->getValueID()) {
    183             case CSSValueWebkitBody:
    184                 face = settings->genericFontFamilySettings().standard();
    185                 break;
    186             case CSSValueSerif:
    187                 face = FontFamilyNames::webkit_serif;
    188                 scope.fontDescription().setGenericFamily(FontDescription::SerifFamily);
    189                 break;
    190             case CSSValueSansSerif:
    191                 face = FontFamilyNames::webkit_sans_serif;
    192                 scope.fontDescription().setGenericFamily(FontDescription::SansSerifFamily);
    193                 break;
    194             case CSSValueCursive:
    195                 face = FontFamilyNames::webkit_cursive;
    196                 scope.fontDescription().setGenericFamily(FontDescription::CursiveFamily);
    197                 break;
    198             case CSSValueFantasy:
    199                 face = FontFamilyNames::webkit_fantasy;
    200                 scope.fontDescription().setGenericFamily(FontDescription::FantasyFamily);
    201                 break;
    202             case CSSValueMonospace:
    203                 face = FontFamilyNames::webkit_monospace;
    204                 scope.fontDescription().setGenericFamily(FontDescription::MonospaceFamily);
    205                 break;
    206             case CSSValueWebkitPictograph:
    207                 face = FontFamilyNames::webkit_pictograph;
    208                 scope.fontDescription().setGenericFamily(FontDescription::PictographFamily);
    209                 break;
    210             default:
    211                 break;
    212             }
    213         }
    214 
    215         if (!face.isEmpty()) {
    216             if (!currFamily) {
    217                 // Filling in the first family.
    218                 firstFamily.setFamily(face);
    219                 firstFamily.appendFamily(nullptr); // Remove any inherited family-fallback list.
    220                 currFamily = &firstFamily;
    221             } else {
    222                 RefPtr<SharedFontFamily> newFamily = SharedFontFamily::create();
    223                 newFamily->setFamily(face);
    224                 currFamily->appendFamily(newFamily);
    225                 currFamily = newFamily.get();
    226             }
    227         }
    228     }
    229 
    230     // We can't call useFixedDefaultSize() until all new font families have been added
    231     // If currFamily is non-zero then we set at least one family on this description.
    232     if (!currFamily)
    233         return;
    234 
    235     if (scope.fontDescription().keywordSize() && scope.fontDescription().useFixedDefaultSize() != oldFamilyUsedFixedDefaultSize)
    236         scope.fontDescription().setSpecifiedSize(FontSize::fontSizeForKeyword(m_document, CSSValueXxSmall + scope.fontDescription().keywordSize() - 1, !oldFamilyUsedFixedDefaultSize));
    237 }
    238 
    239 void FontBuilder::setFontSizeInitial()
    240 {
    241     FontDescriptionChangeScope scope(this);
    242 
    243     float size = FontSize::fontSizeForKeyword(m_document, CSSValueMedium, scope.fontDescription().useFixedDefaultSize());
    244 
    245     if (size < 0)
    246         return;
    247 
    248     scope.fontDescription().setKeywordSize(CSSValueMedium - CSSValueXxSmall + 1);
    249     scope.fontDescription().setSpecifiedSize(size);
    250 }
    251 
    252 void FontBuilder::setFontSizeInherit(const FontDescription& parentFontDescription)
    253 {
    254     FontDescriptionChangeScope scope(this);
    255 
    256     float size = parentFontDescription.specifiedSize();
    257 
    258     if (size < 0)
    259         return;
    260 
    261     scope.fontDescription().setKeywordSize(parentFontDescription.keywordSize());
    262     scope.fontDescription().setSpecifiedSize(size);
    263 }
    264 
    265 // FIXME: Figure out where we fall in the size ranges (xx-small to xxx-large)
    266 // and scale down/up to the next size level.
    267 static float largerFontSize(float size)
    268 {
    269     return size * 1.2f;
    270 }
    271 
    272 static float smallerFontSize(float size)
    273 {
    274     return size / 1.2f;
    275 }
    276 
    277 // FIXME: Have to pass RenderStyles here for calc/computed values. This shouldn't be neecessary.
    278 void FontBuilder::setFontSizeValue(CSSValue* value, RenderStyle* parentStyle, const RenderStyle* rootElementStyle)
    279 {
    280     if (!value->isPrimitiveValue())
    281         return;
    282 
    283     CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
    284 
    285     FontDescriptionChangeScope scope(this);
    286 
    287     scope.fontDescription().setKeywordSize(0);
    288     float parentSize = 0;
    289     bool parentIsAbsoluteSize = false;
    290     float size = 0;
    291 
    292     // FIXME: Find out when parentStyle could be 0?
    293     if (parentStyle) {
    294         parentSize = parentStyle->fontDescription().specifiedSize();
    295         parentIsAbsoluteSize = parentStyle->fontDescription().isAbsoluteSize();
    296     }
    297 
    298     if (CSSValueID valueID = primitiveValue->getValueID()) {
    299         switch (valueID) {
    300         case CSSValueXxSmall:
    301         case CSSValueXSmall:
    302         case CSSValueSmall:
    303         case CSSValueMedium:
    304         case CSSValueLarge:
    305         case CSSValueXLarge:
    306         case CSSValueXxLarge:
    307         case CSSValueWebkitXxxLarge:
    308             size = FontSize::fontSizeForKeyword(m_document, valueID, scope.fontDescription().useFixedDefaultSize());
    309             scope.fontDescription().setKeywordSize(valueID - CSSValueXxSmall + 1);
    310             break;
    311         case CSSValueLarger:
    312             size = largerFontSize(parentSize);
    313             break;
    314         case CSSValueSmaller:
    315             size = smallerFontSize(parentSize);
    316             break;
    317         default:
    318             return;
    319         }
    320 
    321         scope.fontDescription().setIsAbsoluteSize(parentIsAbsoluteSize && (valueID == CSSValueLarger || valueID == CSSValueSmaller));
    322     } else {
    323         scope.fontDescription().setIsAbsoluteSize(parentIsAbsoluteSize || !(primitiveValue->isPercentage() || primitiveValue->isFontRelativeLength()));
    324         if (primitiveValue->isPercentage()) {
    325             size = (primitiveValue->getFloatValue() * parentSize) / 100.0f;
    326         } else {
    327             // If we have viewport units the conversion will mark the parent style as having viewport units.
    328             bool parentHasViewportUnits = parentStyle->hasViewportUnits();
    329             parentStyle->setHasViewportUnits(false);
    330             CSSToLengthConversionData conversionData(parentStyle, rootElementStyle, m_document->renderView(), 1.0f, true);
    331             if (primitiveValue->isLength())
    332                 size = primitiveValue->computeLength<float>(conversionData);
    333             else if (primitiveValue->isCalculatedPercentageWithLength())
    334                 size = primitiveValue->cssCalcValue()->toCalcValue(conversionData)->evaluate(parentSize);
    335             else
    336                 ASSERT_NOT_REACHED();
    337             m_fontSizehasViewportUnits = parentStyle->hasViewportUnits();
    338             parentStyle->setHasViewportUnits(parentHasViewportUnits);
    339         }
    340     }
    341 
    342     if (size < 0)
    343         return;
    344 
    345     // Overly large font sizes will cause crashes on some platforms (such as Windows).
    346     // Cap font size here to make sure that doesn't happen.
    347     size = std::min(maximumAllowedFontSize, size);
    348 
    349 
    350     scope.fontDescription().setSpecifiedSize(size);
    351 }
    352 
    353 void FontBuilder::setWeight(FontWeight fontWeight)
    354 {
    355     FontDescriptionChangeScope scope(this);
    356 
    357     scope.fontDescription().setWeight(fontWeight);
    358 }
    359 
    360 void FontBuilder::setWeightBolder()
    361 {
    362     FontDescriptionChangeScope scope(this);
    363 
    364     scope.fontDescription().setWeight(scope.fontDescription().bolderWeight());
    365 }
    366 
    367 void FontBuilder::setWeightLighter()
    368 {
    369     FontDescriptionChangeScope scope(this);
    370 
    371     scope.fontDescription().setWeight(scope.fontDescription().lighterWeight());
    372 }
    373 
    374 void FontBuilder::setFontVariantLigaturesInitial()
    375 {
    376     FontDescriptionChangeScope scope(this);
    377 
    378     scope.fontDescription().setCommonLigaturesState(FontDescription::NormalLigaturesState);
    379     scope.fontDescription().setDiscretionaryLigaturesState(FontDescription::NormalLigaturesState);
    380     scope.fontDescription().setHistoricalLigaturesState(FontDescription::NormalLigaturesState);
    381     scope.fontDescription().setContextualLigaturesState(FontDescription::NormalLigaturesState);
    382 }
    383 
    384 void FontBuilder::setFontVariantLigaturesInherit(const FontDescription& parentFontDescription)
    385 {
    386     FontDescriptionChangeScope scope(this);
    387 
    388     scope.fontDescription().setCommonLigaturesState(parentFontDescription.commonLigaturesState());
    389     scope.fontDescription().setDiscretionaryLigaturesState(parentFontDescription.discretionaryLigaturesState());
    390     scope.fontDescription().setHistoricalLigaturesState(parentFontDescription.historicalLigaturesState());
    391     scope.fontDescription().setContextualLigaturesState(parentFontDescription.historicalLigaturesState());
    392 }
    393 
    394 void FontBuilder::setFontVariantLigaturesValue(CSSValue* value)
    395 {
    396     FontDescriptionChangeScope scope(this);
    397 
    398     FontDescription::LigaturesState commonLigaturesState = FontDescription::NormalLigaturesState;
    399     FontDescription::LigaturesState discretionaryLigaturesState = FontDescription::NormalLigaturesState;
    400     FontDescription::LigaturesState historicalLigaturesState = FontDescription::NormalLigaturesState;
    401     FontDescription::LigaturesState contextualLigaturesState = FontDescription::NormalLigaturesState;
    402 
    403     if (value->isValueList()) {
    404         CSSValueList* valueList = toCSSValueList(value);
    405         for (size_t i = 0; i < valueList->length(); ++i) {
    406             CSSValue* item = valueList->itemWithoutBoundsCheck(i);
    407             ASSERT(item->isPrimitiveValue());
    408             if (item->isPrimitiveValue()) {
    409                 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(item);
    410                 switch (primitiveValue->getValueID()) {
    411                 case CSSValueNoCommonLigatures:
    412                     commonLigaturesState = FontDescription::DisabledLigaturesState;
    413                     break;
    414                 case CSSValueCommonLigatures:
    415                     commonLigaturesState = FontDescription::EnabledLigaturesState;
    416                     break;
    417                 case CSSValueNoDiscretionaryLigatures:
    418                     discretionaryLigaturesState = FontDescription::DisabledLigaturesState;
    419                     break;
    420                 case CSSValueDiscretionaryLigatures:
    421                     discretionaryLigaturesState = FontDescription::EnabledLigaturesState;
    422                     break;
    423                 case CSSValueNoHistoricalLigatures:
    424                     historicalLigaturesState = FontDescription::DisabledLigaturesState;
    425                     break;
    426                 case CSSValueHistoricalLigatures:
    427                     historicalLigaturesState = FontDescription::EnabledLigaturesState;
    428                     break;
    429                 case CSSValueNoContextual:
    430                     contextualLigaturesState = FontDescription::DisabledLigaturesState;
    431                     break;
    432                 case CSSValueContextual:
    433                     contextualLigaturesState = FontDescription::EnabledLigaturesState;
    434                     break;
    435                 default:
    436                     ASSERT_NOT_REACHED();
    437                     break;
    438                 }
    439             }
    440         }
    441     }
    442 #if ASSERT_ENABLED
    443     else {
    444         ASSERT_WITH_SECURITY_IMPLICATION(value->isPrimitiveValue());
    445         ASSERT(toCSSPrimitiveValue(value)->getValueID() == CSSValueNormal);
    446     }
    447 #endif
    448 
    449     scope.fontDescription().setCommonLigaturesState(commonLigaturesState);
    450     scope.fontDescription().setDiscretionaryLigaturesState(discretionaryLigaturesState);
    451     scope.fontDescription().setHistoricalLigaturesState(historicalLigaturesState);
    452     scope.fontDescription().setContextualLigaturesState(contextualLigaturesState);
    453 }
    454 
    455 void FontBuilder::setScript(const String& locale)
    456 {
    457     FontDescriptionChangeScope scope(this);
    458 
    459     scope.fontDescription().setLocale(locale);
    460     scope.fontDescription().setScript(localeToScriptCodeForFontSelection(locale));
    461 }
    462 
    463 void FontBuilder::setStyle(FontStyle italic)
    464 {
    465     FontDescriptionChangeScope scope(this);
    466 
    467     scope.fontDescription().setStyle(italic);
    468 }
    469 
    470 void FontBuilder::setVariant(FontVariant smallCaps)
    471 {
    472     FontDescriptionChangeScope scope(this);
    473 
    474     scope.fontDescription().setVariant(smallCaps);
    475 }
    476 
    477 void FontBuilder::setTextRendering(TextRenderingMode textRenderingMode)
    478 {
    479     FontDescriptionChangeScope scope(this);
    480 
    481     scope.fontDescription().setTextRendering(textRenderingMode);
    482 }
    483 
    484 void FontBuilder::setKerning(FontDescription::Kerning kerning)
    485 {
    486     FontDescriptionChangeScope scope(this);
    487 
    488     scope.fontDescription().setKerning(kerning);
    489 }
    490 
    491 void FontBuilder::setFontSmoothing(FontSmoothingMode foontSmoothingMode)
    492 {
    493     FontDescriptionChangeScope scope(this);
    494 
    495     scope.fontDescription().setFontSmoothing(foontSmoothingMode);
    496 }
    497 
    498 void FontBuilder::setFeatureSettingsNormal()
    499 {
    500     FontDescriptionChangeScope scope(this);
    501 
    502     // FIXME: Eliminate FontDescription::makeNormalFeatureSettings. It's useless.
    503     scope.set(scope.fontDescription().makeNormalFeatureSettings());
    504 }
    505 
    506 void FontBuilder::setFeatureSettingsValue(CSSValue* value)
    507 {
    508     FontDescriptionChangeScope scope(this);
    509 
    510     CSSValueList* list = toCSSValueList(value);
    511     RefPtr<FontFeatureSettings> settings = FontFeatureSettings::create();
    512     int len = list->length();
    513     for (int i = 0; i < len; ++i) {
    514         CSSValue* item = list->itemWithoutBoundsCheck(i);
    515         if (!item->isFontFeatureValue())
    516             continue;
    517         CSSFontFeatureValue* feature = toCSSFontFeatureValue(item);
    518         settings->append(FontFeature(feature->tag(), feature->value()));
    519     }
    520     scope.fontDescription().setFeatureSettings(settings.release());
    521 }
    522 
    523 void FontBuilder::setSize(FontDescription& fontDescription, float effectiveZoom, float size)
    524 {
    525     fontDescription.setSpecifiedSize(size);
    526     fontDescription.setComputedSize(getComputedSizeFromSpecifiedSize(fontDescription, effectiveZoom, size));
    527 }
    528 
    529 float FontBuilder::getComputedSizeFromSpecifiedSize(FontDescription& fontDescription, float effectiveZoom, float specifiedSize)
    530 {
    531     float zoomFactor = effectiveZoom;
    532     // FIXME: Why is this here!!!!?!
    533     if (LocalFrame* frame = m_document->frame())
    534         zoomFactor *= frame->textZoomFactor();
    535 
    536     return FontSize::getComputedSizeFromSpecifiedSize(m_document, zoomFactor, fontDescription.isAbsoluteSize(), specifiedSize);
    537 }
    538 
    539 static void getFontAndGlyphOrientation(const RenderStyle* style, FontOrientation& fontOrientation, NonCJKGlyphOrientation& glyphOrientation)
    540 {
    541     if (style->isHorizontalWritingMode()) {
    542         fontOrientation = Horizontal;
    543         glyphOrientation = NonCJKGlyphOrientationVerticalRight;
    544         return;
    545     }
    546 
    547     switch (style->textOrientation()) {
    548     case TextOrientationVerticalRight:
    549         fontOrientation = Vertical;
    550         glyphOrientation = NonCJKGlyphOrientationVerticalRight;
    551         return;
    552     case TextOrientationUpright:
    553         fontOrientation = Vertical;
    554         glyphOrientation = NonCJKGlyphOrientationUpright;
    555         return;
    556     case TextOrientationSideways:
    557         if (style->writingMode() == LeftToRightWritingMode) {
    558             // FIXME: This should map to sideways-left, which is not supported yet.
    559             fontOrientation = Vertical;
    560             glyphOrientation = NonCJKGlyphOrientationVerticalRight;
    561             return;
    562         }
    563         fontOrientation = Horizontal;
    564         glyphOrientation = NonCJKGlyphOrientationVerticalRight;
    565         return;
    566     case TextOrientationSidewaysRight:
    567         fontOrientation = Horizontal;
    568         glyphOrientation = NonCJKGlyphOrientationVerticalRight;
    569         return;
    570     default:
    571         ASSERT_NOT_REACHED();
    572         fontOrientation = Horizontal;
    573         glyphOrientation = NonCJKGlyphOrientationVerticalRight;
    574         return;
    575     }
    576 }
    577 
    578 void FontBuilder::checkForOrientationChange(RenderStyle* style)
    579 {
    580     FontOrientation fontOrientation;
    581     NonCJKGlyphOrientation glyphOrientation;
    582     getFontAndGlyphOrientation(style, fontOrientation, glyphOrientation);
    583 
    584     FontDescriptionChangeScope scope(this);
    585 
    586     if (scope.fontDescription().orientation() == fontOrientation && scope.fontDescription().nonCJKGlyphOrientation() == glyphOrientation)
    587         return;
    588 
    589     scope.fontDescription().setNonCJKGlyphOrientation(glyphOrientation);
    590     scope.fontDescription().setOrientation(fontOrientation);
    591 }
    592 
    593 void FontBuilder::checkForGenericFamilyChange(RenderStyle* style, const RenderStyle* parentStyle)
    594 {
    595     FontDescriptionChangeScope scope(this);
    596 
    597     if (scope.fontDescription().isAbsoluteSize() || !parentStyle)
    598         return;
    599 
    600     const FontDescription& parentFontDescription = parentStyle->fontDescription();
    601     if (scope.fontDescription().useFixedDefaultSize() == parentFontDescription.useFixedDefaultSize())
    602         return;
    603 
    604     // For now, lump all families but monospace together.
    605     if (scope.fontDescription().genericFamily() != FontDescription::MonospaceFamily
    606         && parentFontDescription.genericFamily() != FontDescription::MonospaceFamily)
    607         return;
    608 
    609     // We know the parent is monospace or the child is monospace, and that font
    610     // size was unspecified. We want to scale our font size as appropriate.
    611     // If the font uses a keyword size, then we refetch from the table rather than
    612     // multiplying by our scale factor.
    613     float size;
    614     if (scope.fontDescription().keywordSize()) {
    615         size = FontSize::fontSizeForKeyword(m_document, CSSValueXxSmall + scope.fontDescription().keywordSize() - 1, scope.fontDescription().useFixedDefaultSize());
    616     } else {
    617         Settings* settings = m_document->settings();
    618         float fixedScaleFactor = (settings && settings->defaultFixedFontSize() && settings->defaultFontSize())
    619             ? static_cast<float>(settings->defaultFixedFontSize()) / settings->defaultFontSize()
    620             : 1;
    621         size = parentFontDescription.useFixedDefaultSize() ?
    622             scope.fontDescription().specifiedSize() / fixedScaleFactor :
    623             scope.fontDescription().specifiedSize() * fixedScaleFactor;
    624     }
    625 
    626     setSize(scope.fontDescription(), style->effectiveZoom(), size);
    627 }
    628 
    629 void FontBuilder::updateComputedSize(RenderStyle* style, const RenderStyle* parentStyle)
    630 {
    631     FontDescriptionChangeScope scope(this);
    632 
    633     scope.fontDescription().setComputedSize(getComputedSizeFromSpecifiedSize(scope.fontDescription(), style->effectiveZoom(), scope.fontDescription().specifiedSize()));
    634 }
    635 
    636 // FIXME: style param should come first
    637 void FontBuilder::createFont(PassRefPtrWillBeRawPtr<FontSelector> fontSelector, const RenderStyle* parentStyle, RenderStyle* style)
    638 {
    639     if (!m_fontDirty)
    640         return;
    641 
    642     updateComputedSize(style, parentStyle);
    643     checkForGenericFamilyChange(style, parentStyle);
    644     checkForOrientationChange(style);
    645     style->font().update(fontSelector);
    646     m_fontDirty = false;
    647 }
    648 
    649 void FontBuilder::createFontForDocument(PassRefPtrWillBeRawPtr<FontSelector> fontSelector, RenderStyle* documentStyle)
    650 {
    651     FontDescription fontDescription = FontDescription();
    652     fontDescription.setScript(localeToScriptCodeForFontSelection(documentStyle->locale()));
    653 
    654     setFontFamilyToStandard(fontDescription, m_document);
    655     fontDescription.setKeywordSize(CSSValueMedium - CSSValueXxSmall + 1);
    656     int size = FontSize::fontSizeForKeyword(m_document, CSSValueMedium, false);
    657     fontDescription.setSpecifiedSize(size);
    658     fontDescription.setComputedSize(getComputedSizeFromSpecifiedSize(fontDescription, documentStyle->effectiveZoom(), size));
    659 
    660     FontOrientation fontOrientation;
    661     NonCJKGlyphOrientation glyphOrientation;
    662     getFontAndGlyphOrientation(documentStyle, fontOrientation, glyphOrientation);
    663     fontDescription.setOrientation(fontOrientation);
    664     fontDescription.setNonCJKGlyphOrientation(glyphOrientation);
    665     documentStyle->setFontDescription(fontDescription);
    666     documentStyle->font().update(fontSelector);
    667 }
    668 
    669 }
    670