• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/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:
FontDescriptionChangeScope(FontBuilder * fontBuilder)43     FontDescriptionChangeScope(FontBuilder* fontBuilder)
44         : m_fontBuilder(fontBuilder)
45         , m_fontDescription(fontBuilder->m_style->fontDescription())
46     {
47     }
48 
reset()49     void reset() { m_fontDescription = FontDescription(); }
set(const FontDescription & fontDescription)50     void set(const FontDescription& fontDescription) { m_fontDescription = fontDescription; }
fontDescription()51     FontDescription& fontDescription() { return m_fontDescription; }
52 
~FontDescriptionChangeScope()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 
FontBuilder()63 FontBuilder::FontBuilder()
64     : m_document(0)
65     , m_fontSizehasViewportUnits(false)
66     , m_style(0)
67     , m_fontDirty(false)
68 {
69 }
70 
initForStyleResolve(const Document & document,RenderStyle * style)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 
setFontFamilyToStandard(FontDescription & fontDescription,const Document * document)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 
setInitial(float effectiveZoom)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 
inheritFrom(const FontDescription & fontDescription)108 void FontBuilder::inheritFrom(const FontDescription& fontDescription)
109 {
110     FontDescriptionChangeScope scope(this);
111 
112     scope.set(fontDescription);
113 }
114 
didChangeFontParameters(bool changed)115 void FontBuilder::didChangeFontParameters(bool changed)
116 {
117     m_fontDirty |= changed;
118 }
119 
fromSystemFont(CSSValueID valueId,float effectiveZoom)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 
setFontFamilyInitial()142 void FontBuilder::setFontFamilyInitial()
143 {
144     FontDescriptionChangeScope scope(this);
145 
146     setFontFamilyToStandard(scope.fontDescription(), m_document);
147 }
148 
setFontFamilyInherit(const FontDescription & parentFontDescription)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.
setFontFamilyValue(CSSValue * value)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 
setFontSizeInitial()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 
setFontSizeInherit(const FontDescription & parentFontDescription)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.
largerFontSize(float size)267 static float largerFontSize(float size)
268 {
269     return size * 1.2f;
270 }
271 
smallerFontSize(float size)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.
setFontSizeValue(CSSValue * value,RenderStyle * parentStyle,const RenderStyle * rootElementStyle)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 
setWeight(FontWeight fontWeight)353 void FontBuilder::setWeight(FontWeight fontWeight)
354 {
355     FontDescriptionChangeScope scope(this);
356 
357     scope.fontDescription().setWeight(fontWeight);
358 }
359 
setWeightBolder()360 void FontBuilder::setWeightBolder()
361 {
362     FontDescriptionChangeScope scope(this);
363 
364     scope.fontDescription().setWeight(scope.fontDescription().bolderWeight());
365 }
366 
setWeightLighter()367 void FontBuilder::setWeightLighter()
368 {
369     FontDescriptionChangeScope scope(this);
370 
371     scope.fontDescription().setWeight(scope.fontDescription().lighterWeight());
372 }
373 
setFontVariantLigaturesInitial()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 
setFontVariantLigaturesInherit(const FontDescription & parentFontDescription)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 
setFontVariantLigaturesValue(CSSValue * value)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 
setScript(const String & locale)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 
setStyle(FontStyle italic)463 void FontBuilder::setStyle(FontStyle italic)
464 {
465     FontDescriptionChangeScope scope(this);
466 
467     scope.fontDescription().setStyle(italic);
468 }
469 
setVariant(FontVariant smallCaps)470 void FontBuilder::setVariant(FontVariant smallCaps)
471 {
472     FontDescriptionChangeScope scope(this);
473 
474     scope.fontDescription().setVariant(smallCaps);
475 }
476 
setTextRendering(TextRenderingMode textRenderingMode)477 void FontBuilder::setTextRendering(TextRenderingMode textRenderingMode)
478 {
479     FontDescriptionChangeScope scope(this);
480 
481     scope.fontDescription().setTextRendering(textRenderingMode);
482 }
483 
setKerning(FontDescription::Kerning kerning)484 void FontBuilder::setKerning(FontDescription::Kerning kerning)
485 {
486     FontDescriptionChangeScope scope(this);
487 
488     scope.fontDescription().setKerning(kerning);
489 }
490 
setFontSmoothing(FontSmoothingMode foontSmoothingMode)491 void FontBuilder::setFontSmoothing(FontSmoothingMode foontSmoothingMode)
492 {
493     FontDescriptionChangeScope scope(this);
494 
495     scope.fontDescription().setFontSmoothing(foontSmoothingMode);
496 }
497 
setFeatureSettingsNormal()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 
setFeatureSettingsValue(CSSValue * value)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 
setSize(FontDescription & fontDescription,float effectiveZoom,float size)523 void FontBuilder::setSize(FontDescription& fontDescription, float effectiveZoom, float size)
524 {
525     fontDescription.setSpecifiedSize(size);
526     fontDescription.setComputedSize(getComputedSizeFromSpecifiedSize(fontDescription, effectiveZoom, size));
527 }
528 
getComputedSizeFromSpecifiedSize(FontDescription & fontDescription,float effectiveZoom,float specifiedSize)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 
getFontAndGlyphOrientation(const RenderStyle * style,FontOrientation & fontOrientation,NonCJKGlyphOrientation & glyphOrientation)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 
checkForOrientationChange(RenderStyle * style)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 
checkForGenericFamilyChange(RenderStyle * style,const RenderStyle * parentStyle)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 
updateComputedSize(RenderStyle * style,const RenderStyle * parentStyle)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
createFont(PassRefPtrWillBeRawPtr<FontSelector> fontSelector,const RenderStyle * parentStyle,RenderStyle * style)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 
createFontForDocument(PassRefPtrWillBeRawPtr<FontSelector> fontSelector,RenderStyle * documentStyle)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