summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/core/css/font_size_functions.cc
blob: 29f44c40e45ec892a0ca0459efc1cab176dd2b40 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
/*
 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
 *           (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com)
 * Copyright (C) 2006, 2007 Nicholas Shanks (webkit@nickshanks.com)
 * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc.
 * All rights reserved.
 * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org>
 * Copyright (C) 2007, 2008 Eric Seidel <eric@webkit.org>
 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved.
 * (http://www.torchmobile.com/)
 * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
 * Copyright (C) Research In Motion Limited 2011. All rights reserved.
 * Copyright (C) 2012 Google Inc. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#include "third_party/blink/renderer/core/css/font_size_functions.h"

#include "third_party/blink/renderer/core/css_value_keywords.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/frame/settings.h"

namespace blink {

float FontSizeFunctions::GetComputedSizeFromSpecifiedSize(
    const Document* document,
    float zoom_factor,
    bool is_absolute_size,
    float specified_size,
    ApplyMinimumFontSize apply_minimum_font_size) {
  // Text with a 0px font size should not be visible and therefore needs to be
  // exempt from minimum font size rules. Acid3 relies on this for pixel-perfect
  // rendering. This is also compatible with other browsers that have minimum
  // font size settings (e.g. Firefox).
  if (fabsf(specified_size) < std::numeric_limits<float>::epsilon())
    return 0.0f;

  Settings* settings = document->GetSettings();
  if (apply_minimum_font_size && settings) {
    // We support two types of minimum font size. The first is a hard override
    // that applies to all fonts. This is "min_size." The second type of minimum
    // font size is a "smart minimum" that is applied only when the Web page
    // can't know what size it really asked for, e.g., when it uses logical
    // sizes like "small" or expresses the font-size as a percentage of the
    // user's default font setting.

    // With the smart minimum, we never want to get smaller than the minimum
    // font size to keep fonts readable. However we always allow the page to set
    // an explicit pixel size that is smaller, since sites will mis-render
    // otherwise (e.g., http://www.gamespot.com with a 9px minimum).

    int min_size = settings->GetMinimumFontSize();
    int min_logical_size = settings->GetMinimumLogicalFontSize();

    // Apply the hard minimum first.
    if (specified_size < min_size)
      specified_size = min_size;

    // Now apply the "smart minimum". The font size must either be relative to
    // the user default or the original size must have been acceptable. In other
    // words, we only apply the smart minimum whenever we're positive doing so
    // won't disrupt the layout.
    if (specified_size < min_logical_size && !is_absolute_size)
      specified_size = min_logical_size;
  }
  // Also clamp to a reasonable maximum to prevent insane font sizes from
  // causing crashes on various platforms (I'm looking at you, Windows.)
  return std::min(kMaximumAllowedFontSize, specified_size * zoom_factor);
}

const int kFontSizeTableMax = 16;
const int kDefaultMediumFontSize = 12;
const int kFontSizeTableMin = 9;
const int kTotalKeywords = 8;

// WinIE/Nav4 table for font sizes. Designed to match the legacy font mapping
// system of HTML.
static const int kQuirksFontSizeTable[kFontSizeTableMax - kFontSizeTableMin +
                                      1][kTotalKeywords] = {
    {9, 9, 9, 9, 11, 14, 18, 28},   {9, 9, 9, 10, 12, 15, 20, 31},
    {9, 9, 9, 11, 13, 17, 22, 34},  {9, 9, 10, 12, 14, 18, 24, 37},
    {9, 9, 10, 13, 16, 20, 26, 40},  // fixed font default (13)
    {9, 9, 11, 14, 17, 21, 28, 42}, {9, 10, 12, 15, 17, 23, 30, 45},
    {9, 10, 13, 16, 18, 24, 32, 48}  // proportional font default (16)
};
// HTML       1      2      3      4      5      6      7
// CSS  xxs   xs     s      m      l     xl     xxl
//                          |
//                      user pref

// Strict mode table matches MacIE and Mozilla's settings exactly.
static const int kStrictFontSizeTable[kFontSizeTableMax - kFontSizeTableMin +
                                      1][kTotalKeywords] = {
    {9, 9, 9, 9, 11, 14, 18, 27},    {9, 9, 9, 10, 12, 15, 20, 30},
    {9, 9, 10, 11, 13, 17, 22, 33},  {9, 9, 10, 12, 14, 18, 24, 36},
    {9, 10, 12, 13, 16, 20, 26, 39},  // fixed font default (13)
    {9, 10, 12, 14, 17, 21, 28, 42}, {9, 10, 13, 15, 18, 23, 30, 45},
    {9, 10, 13, 16, 18, 24, 32, 48}  // proportional font default (16)
};
// HTML       1      2      3      4      5      6      7
// CSS  xxs   xs     s      m      l     xl     xxl
//                          |
//                      user pref

// For values outside the range of the table, we use Todd Fahrner's suggested
// scale factors for each keyword value.
static const float kFontSizeFactors[kTotalKeywords] = {
    0.60f, 0.75f, 0.89f, 1.0f, 1.2f, 1.5f, 2.0f, 3.0f};

static int inline RowFromMediumFontSizeInRange(const Settings* settings,
                                               bool quirks_mode,
                                               bool is_monospace,
                                               int& medium_size) {
  medium_size = settings ? (is_monospace ? settings->GetDefaultFixedFontSize()
                                         : settings->GetDefaultFontSize())
                         : kDefaultMediumFontSize;
  if (medium_size >= kFontSizeTableMin && medium_size <= kFontSizeTableMax)
    return medium_size - kFontSizeTableMin;
  return -1;
}

float FontSizeFunctions::FontSizeForKeyword(const Document* document,
                                            unsigned keyword,
                                            bool is_monospace) {
  DCHECK_GE(keyword, 1u);
  DCHECK_LE(keyword, 8u);
  const Settings* settings = document ? document->GetSettings() : nullptr;
  bool quirks_mode = document ? document->InQuirksMode() : false;

  int medium_size = 0;
  int row = RowFromMediumFontSizeInRange(settings, quirks_mode, is_monospace,
                                         medium_size);
  if (row >= 0) {
    int col = (keyword - 1);
    return quirks_mode ? kQuirksFontSizeTable[row][col]
                       : kStrictFontSizeTable[row][col];
  }

  // Value is outside the range of the table. Apply the scale factor instead.
  float min_logical_size =
      settings ? std::max(settings->GetMinimumLogicalFontSize(), 1) : 1;
  return std::max(kFontSizeFactors[keyword - 1] * medium_size,
                  min_logical_size);
}

template <typename T>
static int FindNearestLegacyFontSize(int pixel_font_size,
                                     const T* table,
                                     int multiplier) {
  // Ignore table[0] because xx-small does not correspond to any legacy font
  // size.
  for (int i = 1; i < kTotalKeywords - 1; i++) {
    if (pixel_font_size * 2 < (table[i] + table[i + 1]) * multiplier)
      return i;
  }
  return kTotalKeywords - 1;
}

int FontSizeFunctions::LegacyFontSize(const Document* document,
                                      int pixel_font_size,
                                      bool is_monospace) {
  const Settings* settings = document->GetSettings();
  if (!settings)
    return 1;

  bool quirks_mode = document->InQuirksMode();
  int medium_size = 0;
  int row = RowFromMediumFontSizeInRange(settings, quirks_mode, is_monospace,
                                         medium_size);
  if (row >= 0) {
    return FindNearestLegacyFontSize<int>(
        pixel_font_size,
        quirks_mode ? kQuirksFontSizeTable[row] : kStrictFontSizeTable[row], 1);
  }

  return FindNearestLegacyFontSize<float>(pixel_font_size, kFontSizeFactors,
                                          medium_size);
}

}  // namespace blink