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