Home | History | Annotate | Download | only in css
      1 /*
      2  * Copyright (C) 1999 Lars Knoll (knoll (at) kde.org)
      3  *           (C) 2004-2005 Allan Sandfeld Jensen (kde (at) carewolf.com)
      4  * Copyright (C) 2006, 2007 Nicholas Shanks (webkit (at) nickshanks.com)
      5  * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc. All rights reserved.
      6  * Copyright (C) 2007 Alexey Proskuryakov <ap (at) webkit.org>
      7  * Copyright (C) 2007, 2008 Eric Seidel <eric (at) webkit.org>
      8  * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
      9  * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
     10  * Copyright (C) Research In Motion Limited 2011. All rights reserved.
     11  * Copyright (C) 2012 Google Inc. All rights reserved.
     12  *
     13  * This library is free software; you can redistribute it and/or
     14  * modify it under the terms of the GNU Library General Public
     15  * License as published by the Free Software Foundation; either
     16  * version 2 of the License, or (at your option) any later version.
     17  *
     18  * This library is distributed in the hope that it will be useful,
     19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     21  * Library General Public License for more details.
     22  *
     23  * You should have received a copy of the GNU Library General Public License
     24  * along with this library; see the file COPYING.LIB.  If not, write to
     25  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     26  * Boston, MA 02110-1301, USA.
     27  */
     28 
     29 #include "config.h"
     30 #include "core/css/FontSize.h"
     31 
     32 #include "core/CSSValueKeywords.h"
     33 #include "core/dom/Document.h"
     34 #include "core/frame/Settings.h"
     35 
     36 namespace blink {
     37 
     38 float FontSize::getComputedSizeFromSpecifiedSize(const Document* document, float zoomFactor, bool isAbsoluteSize, float specifiedSize, ESmartMinimumForFontSize useSmartMinimumForFontSize)
     39 {
     40     // Text with a 0px font size should not be visible and therefore needs to be
     41     // exempt from minimum font size rules. Acid3 relies on this for pixel-perfect
     42     // rendering. This is also compatible with other browsers that have minimum
     43     // font size settings (e.g. Firefox).
     44     if (fabsf(specifiedSize) < std::numeric_limits<float>::epsilon())
     45         return 0.0f;
     46 
     47     // We support two types of minimum font size. The first is a hard override that applies to
     48     // all fonts. This is "minSize." The second type of minimum font size is a "smart minimum"
     49     // that is applied only when the Web page can't know what size it really asked for, e.g.,
     50     // when it uses logical sizes like "small" or expresses the font-size as a percentage of
     51     // the user's default font setting.
     52 
     53     // With the smart minimum, we never want to get smaller than the minimum font size to keep fonts readable.
     54     // However we always allow the page to set an explicit pixel size that is smaller,
     55     // since sites will mis-render otherwise (e.g., http://www.gamespot.com with a 9px minimum).
     56 
     57     Settings* settings = document->settings();
     58     if (!settings)
     59         return 1.0f;
     60 
     61     int minSize = settings->minimumFontSize();
     62     int minLogicalSize = settings->minimumLogicalFontSize();
     63     float zoomedSize = specifiedSize * zoomFactor;
     64 
     65     // Apply the hard minimum first. We only apply the hard minimum if after zooming we're still too small.
     66     if (zoomedSize < minSize)
     67         zoomedSize = minSize;
     68 
     69     // Now apply the "smart minimum." This minimum is also only applied if we're still too small
     70     // after zooming. The font size must either be relative to the user default or the original size
     71     // must have been acceptable. In other words, we only apply the smart minimum whenever we're positive
     72     // doing so won't disrupt the layout.
     73     if (useSmartMinimumForFontSize && zoomedSize < minLogicalSize && (specifiedSize >= minLogicalSize || !isAbsoluteSize))
     74         zoomedSize = minLogicalSize;
     75 
     76     // Also clamp to a reasonable maximum to prevent insane font sizes from causing crashes on various
     77     // platforms (I'm looking at you, Windows.)
     78     return std::min(maximumAllowedFontSize, zoomedSize);
     79 }
     80 
     81 const int fontSizeTableMax = 16;
     82 const int fontSizeTableMin = 9;
     83 const int totalKeywords = 8;
     84 
     85 // WinIE/Nav4 table for font sizes. Designed to match the legacy font mapping system of HTML.
     86 static const int quirksFontSizeTable[fontSizeTableMax - fontSizeTableMin + 1][totalKeywords] =
     87 {
     88     { 9,    9,     9,     9,    11,    14,    18,    28 },
     89     { 9,    9,     9,    10,    12,    15,    20,    31 },
     90     { 9,    9,     9,    11,    13,    17,    22,    34 },
     91     { 9,    9,    10,    12,    14,    18,    24,    37 },
     92     { 9,    9,    10,    13,    16,    20,    26,    40 }, // fixed font default (13)
     93     { 9,    9,    11,    14,    17,    21,    28,    42 },
     94     { 9,   10,    12,    15,    17,    23,    30,    45 },
     95     { 9,   10,    13,    16,    18,    24,    32,    48 } // proportional font default (16)
     96 };
     97 // HTML       1      2      3      4      5      6      7
     98 // CSS  xxs   xs     s      m      l     xl     xxl
     99 //                          |
    100 //                      user pref
    101 
    102 // Strict mode table matches MacIE and Mozilla's settings exactly.
    103 static const int strictFontSizeTable[fontSizeTableMax - fontSizeTableMin + 1][totalKeywords] =
    104 {
    105     { 9,    9,     9,     9,    11,    14,    18,    27 },
    106     { 9,    9,     9,    10,    12,    15,    20,    30 },
    107     { 9,    9,    10,    11,    13,    17,    22,    33 },
    108     { 9,    9,    10,    12,    14,    18,    24,    36 },
    109     { 9,   10,    12,    13,    16,    20,    26,    39 }, // fixed font default (13)
    110     { 9,   10,    12,    14,    17,    21,    28,    42 },
    111     { 9,   10,    13,    15,    18,    23,    30,    45 },
    112     { 9,   10,    13,    16,    18,    24,    32,    48 } // proportional font default (16)
    113 };
    114 // HTML       1      2      3      4      5      6      7
    115 // CSS  xxs   xs     s      m      l     xl     xxl
    116 //                          |
    117 //                      user pref
    118 
    119 // For values outside the range of the table, we use Todd Fahrner's suggested scale
    120 // factors for each keyword value.
    121 static const float fontSizeFactors[totalKeywords] = { 0.60f, 0.75f, 0.89f, 1.0f, 1.2f, 1.5f, 2.0f, 3.0f };
    122 
    123 static int inline rowFromMediumFontSizeInRange(const Settings* settings, bool quirksMode, FixedPitchFontType fixedPitchFontType, int& mediumSize)
    124 {
    125     mediumSize = fixedPitchFontType == FixedPitchFont ? settings->defaultFixedFontSize() : settings->defaultFontSize();
    126     if (mediumSize >= fontSizeTableMin && mediumSize <= fontSizeTableMax)
    127         return mediumSize - fontSizeTableMin;
    128     return -1;
    129 }
    130 
    131 float FontSize::fontSizeForKeyword(const Document* document, unsigned keyword, FixedPitchFontType fixedPitchFontType)
    132 {
    133     ASSERT(keyword >= 1 && keyword <= 8);
    134     const Settings* settings = document->settings();
    135     if (!settings)
    136         return 1.0f;
    137 
    138     bool quirksMode = document->inQuirksMode();
    139     int mediumSize = 0;
    140     int row = rowFromMediumFontSizeInRange(settings, quirksMode, fixedPitchFontType, mediumSize);
    141     if (row >= 0) {
    142         int col = (keyword - 1);
    143         return quirksMode ? quirksFontSizeTable[row][col] : strictFontSizeTable[row][col];
    144     }
    145 
    146     // Value is outside the range of the table. Apply the scale factor instead.
    147     float minLogicalSize = std::max(settings->minimumLogicalFontSize(), 1);
    148     return std::max(fontSizeFactors[keyword - 1] * mediumSize, minLogicalSize);
    149 }
    150 
    151 
    152 
    153 template<typename T>
    154 static int findNearestLegacyFontSize(int pixelFontSize, const T* table, int multiplier)
    155 {
    156     // Ignore table[0] because xx-small does not correspond to any legacy font size.
    157     for (int i = 1; i < totalKeywords - 1; i++) {
    158         if (pixelFontSize * 2 < (table[i] + table[i + 1]) * multiplier)
    159             return i;
    160     }
    161     return totalKeywords - 1;
    162 }
    163 
    164 int FontSize::legacyFontSize(const Document* document, int pixelFontSize, FixedPitchFontType fixedPitchFontType)
    165 {
    166     const Settings* settings = document->settings();
    167     if (!settings)
    168         return 1;
    169 
    170     bool quirksMode = document->inQuirksMode();
    171     int mediumSize = 0;
    172     int row = rowFromMediumFontSizeInRange(settings, quirksMode, fixedPitchFontType, mediumSize);
    173     if (row >= 0)
    174         return findNearestLegacyFontSize<int>(pixelFontSize, quirksMode ? quirksFontSizeTable[row] : strictFontSizeTable[row], 1);
    175 
    176     return findNearestLegacyFontSize<float>(pixelFontSize, fontSizeFactors, mediumSize);
    177 }
    178 
    179 } // namespace blink
    180