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/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:
FontDescriptionChangeScope(FontBuilder * fontBuilder)42 FontDescriptionChangeScope(FontBuilder* fontBuilder)
43 : m_fontBuilder(fontBuilder)
44 , m_fontDescription(fontBuilder->m_style->fontDescription())
45 {
46 }
47
reset()48 void reset() { m_fontDescription = FontDescription(); }
set(const FontDescription & fontDescription)49 void set(const FontDescription& fontDescription) { m_fontDescription = fontDescription; }
fontDescription()50 FontDescription& fontDescription() { return m_fontDescription; }
51
~FontDescriptionChangeScope()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
FontBuilder()62 FontBuilder::FontBuilder()
63 : m_document(0)
64 , m_useSVGZoomRules(false)
65 , m_fontDirty(false)
66 {
67 }
68
initForStyleResolve(const Document & document,RenderStyle * style,bool useSVGZoomRules)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
setInitial(float effectiveZoom)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
inheritFrom(const FontDescription & fontDescription)101 void FontBuilder::inheritFrom(const FontDescription& fontDescription)
102 {
103 FontDescriptionChangeScope scope(this);
104
105 scope.set(fontDescription);
106 }
107
didChangeFontParameters(bool changed)108 void FontBuilder::didChangeFontParameters(bool changed)
109 {
110 m_fontDirty |= changed;
111 }
112
fromSystemFont(CSSValueID valueId,float effectiveZoom)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
setFontFamilyInitial(float effectiveZoom)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
setFontFamilyInherit(const FontDescription & parentFontDescription)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.
setFontFamilyValue(CSSValue * value,float effectiveZoom)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
setFontSizeInitial(float effectiveZoom)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
setFontSizeInherit(const FontDescription & parentFontDescription,float effectiveZoom)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.
largerFontSize(float size)270 static float largerFontSize(float size)
271 {
272 return size * 1.2f;
273 }
274
smallerFontSize(float size)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.
setFontSizeValue(CSSValue * value,RenderStyle * parentStyle,const RenderStyle * rootElementStyle,float effectiveZoom)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
setWeight(FontWeight fontWeight)349 void FontBuilder::setWeight(FontWeight fontWeight)
350 {
351 FontDescriptionChangeScope scope(this);
352
353 scope.fontDescription().setWeight(fontWeight);
354 }
355
setWeightBolder()356 void FontBuilder::setWeightBolder()
357 {
358 FontDescriptionChangeScope scope(this);
359
360 scope.fontDescription().setWeight(scope.fontDescription().bolderWeight());
361 }
362
setWeightLighter()363 void FontBuilder::setWeightLighter()
364 {
365 FontDescriptionChangeScope scope(this);
366
367 scope.fontDescription().setWeight(scope.fontDescription().lighterWeight());
368 }
369
setFontVariantLigaturesInitial()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
setFontVariantLigaturesInherit(const FontDescription & parentFontDescription)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
setFontVariantLigaturesValue(CSSValue * value)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
setScript(const String & locale)441 void FontBuilder::setScript(const String& locale)
442 {
443 FontDescriptionChangeScope scope(this);
444
445 scope.fontDescription().setScript(localeToScriptCodeForFontSelection(locale));
446 }
447
setItalic(FontItalic italic)448 void FontBuilder::setItalic(FontItalic italic)
449 {
450 FontDescriptionChangeScope scope(this);
451
452 scope.fontDescription().setItalic(italic);
453 }
454
setSmallCaps(FontSmallCaps smallCaps)455 void FontBuilder::setSmallCaps(FontSmallCaps smallCaps)
456 {
457 FontDescriptionChangeScope scope(this);
458
459 scope.fontDescription().setSmallCaps(smallCaps);
460 }
461
setTextRenderingMode(TextRenderingMode textRenderingMode)462 void FontBuilder::setTextRenderingMode(TextRenderingMode textRenderingMode)
463 {
464 FontDescriptionChangeScope scope(this);
465
466 scope.fontDescription().setTextRenderingMode(textRenderingMode);
467 }
468
setKerning(FontDescription::Kerning kerning)469 void FontBuilder::setKerning(FontDescription::Kerning kerning)
470 {
471 FontDescriptionChangeScope scope(this);
472
473 scope.fontDescription().setKerning(kerning);
474 }
475
setFontSmoothing(FontSmoothingMode foontSmoothingMode)476 void FontBuilder::setFontSmoothing(FontSmoothingMode foontSmoothingMode)
477 {
478 FontDescriptionChangeScope scope(this);
479
480 scope.fontDescription().setFontSmoothing(foontSmoothingMode);
481 }
482
setFeatureSettingsNormal()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
setFeatureSettingsValue(CSSValue * value)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
setSize(FontDescription & fontDescription,float effectiveZoom,float size)508 void FontBuilder::setSize(FontDescription& fontDescription, float effectiveZoom, float size)
509 {
510 fontDescription.setSpecifiedSize(size);
511 fontDescription.setComputedSize(getComputedSizeFromSpecifiedSize(fontDescription, effectiveZoom, size));
512 }
513
getComputedSizeFromSpecifiedSize(FontDescription & fontDescription,float effectiveZoom,float specifiedSize)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
getFontAndGlyphOrientation(const RenderStyle * style,FontOrientation & fontOrientation,NonCJKGlyphOrientation & glyphOrientation)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
checkForOrientationChange(RenderStyle * style)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
checkForGenericFamilyChange(RenderStyle * style,const RenderStyle * parentStyle)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
checkForZoomChange(RenderStyle * style,const RenderStyle * parentStyle)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
createFont(PassRefPtr<FontSelector> fontSelector,const RenderStyle * parentStyle,RenderStyle * style)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
createFontForDocument(PassRefPtr<FontSelector> fontSelector,RenderStyle * documentStyle)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