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