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