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