summaryrefslogtreecommitdiffstats
path: root/chromium/third_party/WebKit/Source/platform/fonts
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/WebKit/Source/platform/fonts')
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/AlternateFontFamily.h27
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/Character.cpp392
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/Character.h86
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/CustomFontData.h24
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/Font.cpp1093
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/Font.h154
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/FontCache.cpp70
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/FontCache.h39
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/FontCacheClient.h (renamed from chromium/third_party/WebKit/Source/platform/fonts/skia/SkiaFontWin.h)52
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/FontCacheTest.cpp46
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/FontCustomPlatformData.h19
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/FontData.h2
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/FontDataCache.cpp2
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/FontDescription.cpp138
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/FontDescription.h127
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/FontDescriptionTest.cpp121
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/FontFallbackList.cpp68
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/FontFallbackList.h9
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/FontFastPath.cpp621
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/FontMetrics.h12
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/FontPlatformData.cpp16
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/FontPlatformData.h23
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/FontPlatformFeatures.h (renamed from chromium/third_party/WebKit/Source/platform/fonts/skia/GlyphPageTreeNodeSkia.cpp)40
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/FontSelector.h20
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/FontTest.cpp291
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/FontTraits.h106
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/FontTraitsMask.h70
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/GenericFontFamilySettings.cpp12
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/GenericFontFamilySettings.h5
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/GlyphBuffer.h76
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/GlyphPage.h52
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/GlyphPageTreeNode.cpp66
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/GlyphPageTreeNodeTest.cpp226
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/SegmentedFontData.cpp29
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/SegmentedFontData.h13
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/SimpleFontData.cpp17
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/SimpleFontData.h22
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/WidthCache.h37
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/WidthIterator.cpp56
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/WidthIterator.h5
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/android/FontCacheAndroid.cpp7
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/android/FontCacheAndroidTest.cpp29
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/cocoa/FontPlatformDataCocoa.mm22
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/harfbuzz/FontHarfBuzz.cpp69
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/harfbuzz/FontPlatformDataHarfBuzz.cpp212
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/harfbuzz/FontPlatformDataHarfBuzz.h67
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/harfbuzz/HarfBuzzFace.cpp10
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/harfbuzz/HarfBuzzFaceCoreText.cpp5
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/harfbuzz/HarfBuzzFaceSkia.cpp57
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/harfbuzz/HarfBuzzShaper.cpp523
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/harfbuzz/HarfBuzzShaper.h36
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/linux/FontCacheLinux.cpp23
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/linux/FontPlatformDataLinuxHarfBuzz.cpp151
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/mac/ComplexTextController.cpp101
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/mac/ComplexTextController.h3
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/mac/ComplexTextControllerCoreText.mm8
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/mac/FontCacheMac.mm38
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/mac/FontComplexTextMac.cpp32
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/mac/FontMac.cpp39
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/mac/GlyphPageTreeNodeMac.cpp168
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/mac/MemoryActivatedFont.mm4
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/mac/SimpleFontDataCoreText.cpp137
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/mac/SimpleFontDataMac.mm54
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/opentype/OpenTypeSanitizer.cpp8
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/opentype/OpenTypeVerticalData.cpp7
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/skia/FontCacheSkia.cpp98
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/skia/FontCustomPlatformDataSkia.cpp43
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/skia/FontPlatformDataSkia.cpp4
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/skia/SimpleFontDataSkia.cpp120
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/skia/SkiaFontWin.cpp182
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/win/FontCacheSkiaWin.cpp (renamed from chromium/third_party/WebKit/Source/platform/fonts/skia/FontCacheSkiaWin.cpp)68
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/win/FontCacheWin.cpp594
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/win/FontCustomPlatformDataWin.cpp135
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/win/FontFallbackWin.cpp91
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/win/FontFallbackWin.h17
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/win/FontPlatformDataWin.cpp418
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/win/FontPlatformDataWin.h191
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/win/FontWin.cpp224
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/win/GlyphPageTreeNodeWin.cpp260
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/win/SimpleFontDataWin.cpp181
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/win/UniscribeHelper.cpp1208
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/win/UniscribeHelper.h449
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/win/UniscribeHelperTextRun.cpp151
-rw-r--r--chromium/third_party/WebKit/Source/platform/fonts/win/UniscribeHelperTextRun.h102
84 files changed, 3655 insertions, 6975 deletions
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/AlternateFontFamily.h b/chromium/third_party/WebKit/Source/platform/fonts/AlternateFontFamily.h
index f2648d2208c..2ff2121c02d 100644
--- a/chromium/third_party/WebKit/Source/platform/fonts/AlternateFontFamily.h
+++ b/chromium/third_party/WebKit/Source/platform/fonts/AlternateFontFamily.h
@@ -36,10 +36,9 @@
namespace WebCore {
-// We currently do not support bitmap fonts on windows (with GDI_FONTS_ON_WINDOWS enabled).
+// We currently do not support bitmap fonts on windows.
// Instead of trying to construct a bitmap font and then going down the fallback path map
-// certain common bitmap fonts to their truetype equivalent up front. This also allows the
-// GDI_FONTS_ON_WINDOWS disabled code path to match our current behavior.
+// certain common bitmap fonts to their truetype equivalent up front.
inline const AtomicString& adjustFamilyNameToAvoidUnsupportedFonts(const AtomicString& familyName)
{
#if OS(WIN)
@@ -60,10 +59,12 @@ inline const AtomicString& adjustFamilyNameToAvoidUnsupportedFonts(const AtomicS
return microsoftSans;
// Alias 'MS Serif' (bitmap) -> 'Times New Roman' (truetype font).
+ // Alias 'Times' -> 'Times New Roman' (truetype font).
// There's no 'Microsoft Sans Serif-equivalent' for Serif.
DEFINE_STATIC_LOCAL(AtomicString, msSerif, ("MS Serif", AtomicString::ConstructFromLiteral));
+ DEFINE_STATIC_LOCAL(AtomicString, times, ("Times", AtomicString::ConstructFromLiteral));
DEFINE_STATIC_LOCAL(AtomicString, timesNewRoman, ("Times New Roman", AtomicString::ConstructFromLiteral));
- if (equalIgnoringCase(familyName, msSerif))
+ if (equalIgnoringCase(familyName, msSerif) || equalIgnoringCase(familyName, times))
return timesNewRoman;
#endif
@@ -107,18 +108,26 @@ inline const AtomicString& alternateFamilyName(const AtomicString& familyName)
inline const AtomicString getFallbackFontFamily(const FontDescription& description)
{
- DEFINE_STATIC_LOCAL(const AtomicString, sansStr, ("Sans", AtomicString::ConstructFromLiteral));
- DEFINE_STATIC_LOCAL(const AtomicString, serifStr, ("Serif", AtomicString::ConstructFromLiteral));
- DEFINE_STATIC_LOCAL(const AtomicString, monospaceStr, ("Monospace", AtomicString::ConstructFromLiteral));
+ DEFINE_STATIC_LOCAL(const AtomicString, sansStr, ("sans-serif", AtomicString::ConstructFromLiteral));
+ DEFINE_STATIC_LOCAL(const AtomicString, serifStr, ("serif", AtomicString::ConstructFromLiteral));
+ DEFINE_STATIC_LOCAL(const AtomicString, monospaceStr, ("monospace", AtomicString::ConstructFromLiteral));
+ DEFINE_STATIC_LOCAL(const AtomicString, cursiveStr, ("cursive", AtomicString::ConstructFromLiteral));
+ DEFINE_STATIC_LOCAL(const AtomicString, fantasyStr, ("fantasy", AtomicString::ConstructFromLiteral));
switch (description.genericFamily()) {
+ case FontDescription::SansSerifFamily:
+ return sansStr;
case FontDescription::SerifFamily:
return serifStr;
case FontDescription::MonospaceFamily:
return monospaceStr;
- case FontDescription::SansSerifFamily:
+ case FontDescription::CursiveFamily:
+ return cursiveStr;
+ case FontDescription::FantasyFamily:
+ return fantasyStr;
default:
- return sansStr;
+ // Let the caller use the system default font.
+ return emptyAtom;
}
}
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/Character.cpp b/chromium/third_party/WebKit/Source/platform/fonts/Character.cpp
new file mode 100644
index 00000000000..a9898c953b1
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/platform/fonts/Character.cpp
@@ -0,0 +1,392 @@
+/*
+ * Copyright (C) 2014 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "platform/fonts/Character.h"
+
+#include "platform/fonts/FontPlatformFeatures.h"
+#include "wtf/StdLibExtras.h"
+#include "wtf/text/StringBuilder.h"
+
+using namespace WTF;
+using namespace Unicode;
+
+namespace WebCore {
+
+const uint8_t Character::s_roundingHackCharacterTable[256] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 /*\t*/, 1 /*\n*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1 /*space*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 /*-*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 /*?*/,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1 /*no-break space*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+static const UChar32 cjkIsolatedSymbolsArray[] = {
+ // 0x2C7 Caron, Mandarin Chinese 3rd Tone
+ 0x2C7,
+ // 0x2CA Modifier Letter Acute Accent, Mandarin Chinese 2nd Tone
+ 0x2CA,
+ // 0x2CB Modifier Letter Grave Access, Mandarin Chinese 4th Tone
+ 0x2CB,
+ // 0x2D9 Dot Above, Mandarin Chinese 5th Tone
+ 0x2D9,
+ 0x2020, 0x2021, 0x2030, 0x203B, 0x203C, 0x2042, 0x2047, 0x2048, 0x2049, 0x2051,
+ 0x20DD, 0x20DE, 0x2100, 0x2103, 0x2105, 0x2109, 0x210A, 0x2113, 0x2116, 0x2121,
+ 0x212B, 0x213B, 0x2150, 0x2151, 0x2152, 0x217F, 0x2189, 0x2307, 0x2312, 0x23CE,
+ 0x2423, 0x25A0, 0x25A1, 0x25A2, 0x25AA, 0x25AB, 0x25B1, 0x25B2, 0x25B3, 0x25B6,
+ 0x25B7, 0x25BC, 0x25BD, 0x25C0, 0x25C1, 0x25C6, 0x25C7, 0x25C9, 0x25CB, 0x25CC,
+ 0x25EF, 0x2605, 0x2606, 0x260E, 0x2616, 0x2617, 0x2640, 0x2642, 0x26A0, 0x26BD,
+ 0x26BE, 0x2713, 0x271A, 0x273F, 0x2740, 0x2756, 0x2B1A, 0xFE10, 0xFE11, 0xFE12,
+ 0xFE19, 0xFF1D,
+ // Emoji.
+ 0x1F100
+};
+
+// Takes a flattened list of closed intervals
+template <class T, size_t size>
+bool valueInIntervalList(const T (&intervalList)[size], const T& value)
+{
+ const T* bound = std::upper_bound(&intervalList[0], &intervalList[size], value);
+ if ((bound - intervalList) % 2 == 1)
+ return true;
+ return bound > intervalList && *(bound - 1) == value;
+}
+
+CodePath Character::characterRangeCodePath(const UChar* characters, unsigned len)
+{
+ static const UChar complexCodePathRanges[] = {
+ // U+02E5 through U+02E9 (Modifier Letters : Tone letters)
+ 0x2E5, 0x2E9,
+ // U+0300 through U+036F Combining diacritical marks
+ 0x300, 0x36F,
+ // U+0591 through U+05CF excluding U+05BE Hebrew combining marks, ...
+ 0x0591, 0x05BD,
+ // ... Hebrew punctuation Paseq, Sof Pasuq and Nun Hafukha
+ 0x05BF, 0x05CF,
+ // U+0600 through U+109F Arabic, Syriac, Thaana, NKo, Samaritan, Mandaic,
+ // Devanagari, Bengali, Gurmukhi, Gujarati, Oriya, Tamil, Telugu, Kannada,
+ // Malayalam, Sinhala, Thai, Lao, Tibetan, Myanmar
+ 0x0600, 0x109F,
+ // U+1100 through U+11FF Hangul Jamo (only Ancient Korean should be left
+ // here if you precompose; Modern Korean will be precomposed as a result of step A)
+ 0x1100, 0x11FF,
+ // U+135D through U+135F Ethiopic combining marks
+ 0x135D, 0x135F,
+ // U+1780 through U+18AF Tagalog, Hanunoo, Buhid, Taghanwa,Khmer, Mongolian
+ 0x1700, 0x18AF,
+ // U+1900 through U+194F Limbu (Unicode 4.0)
+ 0x1900, 0x194F,
+ // U+1980 through U+19DF New Tai Lue
+ 0x1980, 0x19DF,
+ // U+1A00 through U+1CFF Buginese, Tai Tham, Balinese, Batak, Lepcha, Vedic
+ 0x1A00, 0x1CFF,
+ // U+1DC0 through U+1DFF Comining diacritical mark supplement
+ 0x1DC0, 0x1DFF,
+ // RIGHT-TO-LEFT MARK
+ 0x200B, 0x200F,
+ // RIGHT-TO-LEFT OVERRIDE
+ 0x202A, 0x202E,
+ // Nominal Digit Shape
+ 0x2060, 0x206F,
+ // U+20D0 through U+20FF Combining marks for symbols
+ 0x20D0, 0x20FF,
+ // U+2CEF through U+2CF1 Combining marks for Coptic
+ 0x2CEF, 0x2CF1,
+ // U+302A through U+302F Ideographic and Hangul Tone marks
+ 0x302A, 0x302F,
+ // U+A67C through U+A67D Combining marks for old Cyrillic
+ 0xA67C, 0xA67D,
+ // U+A6F0 through U+A6F1 Combining mark for Bamum
+ 0xA6F0, 0xA6F1,
+ // U+A800 through U+ABFF Nagri, Phags-pa, Saurashtra, Devanagari Extended,
+ // Hangul Jamo Ext. A, Javanese, Myanmar Extended A, Tai Viet, Meetei Mayek
+ 0xA800, 0xABFF,
+ // U+D7B0 through U+D7FF Hangul Jamo Ext. B
+ 0xD7B0, 0xD7FF,
+ // U+FE00 through U+FE0F Unicode variation selectors
+ 0xFE00, 0xFE0F,
+ // U+FE20 through U+FE2F Combining half marks
+ 0xFE20, 0xFE2F
+ };
+
+ CodePath result = SimplePath;
+ for (unsigned i = 0; i < len; i++) {
+ const UChar c = characters[i];
+
+ // Shortcut for common case
+ if (c < 0x2E5)
+ continue;
+
+ // U+1E00 through U+2000 characters with diacritics and stacked diacritics
+ if (c >= 0x1E00 && c <= 0x2000) {
+ result = SimpleWithGlyphOverflowPath;
+ continue;
+ }
+
+ // Surrogate pairs
+ if (c > 0xD7FF && c <= 0xDBFF) {
+ if (i == len - 1)
+ continue;
+
+ UChar next = characters[++i];
+ if (!U16_IS_TRAIL(next))
+ continue;
+
+ UChar32 supplementaryCharacter = U16_GET_SUPPLEMENTARY(c, next);
+
+ if (supplementaryCharacter < 0x1F1E6) // U+1F1E6 through U+1F1FF Regional Indicator Symbols
+ continue;
+ if (supplementaryCharacter <= 0x1F1FF)
+ return ComplexPath;
+
+ if (supplementaryCharacter < 0xE0100) // U+E0100 through U+E01EF Unicode variation selectors.
+ continue;
+ if (supplementaryCharacter <= 0xE01EF)
+ return ComplexPath;
+
+ // FIXME: Check for Brahmi (U+11000 block), Kaithi (U+11080 block) and other complex scripts
+ // in plane 1 or higher.
+
+ continue;
+ }
+
+ // Search for other Complex cases
+ if (valueInIntervalList(complexCodePathRanges, c))
+ return ComplexPath;
+ }
+
+ return result;
+}
+
+bool Character::isCJKIdeograph(UChar32 c)
+{
+ static const UChar32 cjkIdeographRanges[] = {
+ // CJK Radicals Supplement and Kangxi Radicals.
+ 0x2E80, 0x2FDF,
+ // CJK Strokes.
+ 0x31C0, 0x31EF,
+ // CJK Unified Ideographs Extension A.
+ 0x3400, 0x4DBF,
+ // The basic CJK Unified Ideographs block.
+ 0x4E00, 0x9FFF,
+ // CJK Compatibility Ideographs.
+ 0xF900, 0xFAFF,
+ // CJK Unified Ideographs Extension B.
+ 0x20000, 0x2A6DF,
+ // CJK Unified Ideographs Extension C.
+ // CJK Unified Ideographs Extension D.
+ 0x2A700, 0x2B81F,
+ // CJK Compatibility Ideographs Supplement.
+ 0x2F800, 0x2FA1F
+ };
+ static size_t cjkIdeographRangesCount = WTF_ARRAY_LENGTH(cjkIdeographRanges);
+
+ // Early out
+ if (c < cjkIdeographRanges[0] || c > cjkIdeographRanges[cjkIdeographRangesCount - 1])
+ return false;
+
+ return valueInIntervalList(cjkIdeographRanges, c);
+}
+
+bool Character::isCJKIdeographOrSymbol(UChar32 c)
+{
+ // Likely common case
+ if (c < 0x2C7)
+ return false;
+
+ // Hash lookup for isolated symbols (those not part of a contiguous range)
+ static HashSet<UChar32>* cjkIsolatedSymbols = 0;
+ if (!cjkIsolatedSymbols) {
+ cjkIsolatedSymbols = new HashSet<UChar32>();
+ for (size_t i = 0; i < WTF_ARRAY_LENGTH(cjkIsolatedSymbolsArray); ++i)
+ cjkIsolatedSymbols->add(cjkIsolatedSymbolsArray[i]);
+ }
+ if (cjkIsolatedSymbols->contains(c))
+ return true;
+
+ if (isCJKIdeograph(c))
+ return true;
+
+ static const UChar32 cjkSymbolRanges[] = {
+ 0x2156, 0x215A,
+ 0x2160, 0x216B,
+ 0x2170, 0x217B,
+ 0x23BE, 0x23CC,
+ 0x2460, 0x2492,
+ 0x249C, 0x24FF,
+ 0x25CE, 0x25D3,
+ 0x25E2, 0x25E6,
+ 0x2600, 0x2603,
+ 0x2660, 0x266F,
+ 0x2672, 0x267D,
+ 0x2776, 0x277F,
+ // Ideographic Description Characters, with CJK Symbols and Punctuation, excluding 0x3030.
+ // Then Hiragana 0x3040 .. 0x309F, Katakana 0x30A0 .. 0x30FF, Bopomofo 0x3100 .. 0x312F
+ 0x2FF0, 0x302F,
+ 0x3031, 0x312F,
+ // More Bopomofo and Bopomofo Extended 0x31A0 .. 0x31BF
+ 0x3190, 0x31BF,
+ // Enclosed CJK Letters and Months (0x3200 .. 0x32FF).
+ // CJK Compatibility (0x3300 .. 0x33FF).
+ 0x3200, 0x33FF,
+ 0xF860, 0xF862,
+ // CJK Compatibility Forms.
+ 0xFE30, 0xFE4F,
+ // Halfwidth and Fullwidth Forms
+ // Usually only used in CJK
+ 0xFF00, 0xFF0C,
+ 0xFF0E, 0xFF1A,
+ 0xFF1F, 0xFFEF,
+ // Emoji.
+ 0x1F110, 0x1F129,
+ 0x1F130, 0x1F149,
+ 0x1F150, 0x1F169,
+ 0x1F170, 0x1F189,
+ 0x1F200, 0x1F6FF
+ };
+
+ return valueInIntervalList(cjkSymbolRanges, c);
+}
+
+unsigned Character::expansionOpportunityCount(const LChar* characters, size_t length, TextDirection direction, bool& isAfterExpansion)
+{
+ unsigned count = 0;
+ if (direction == LTR) {
+ for (size_t i = 0; i < length; ++i) {
+ if (treatAsSpace(characters[i])) {
+ count++;
+ isAfterExpansion = true;
+ } else {
+ isAfterExpansion = false;
+ }
+ }
+ } else {
+ for (size_t i = length; i > 0; --i) {
+ if (treatAsSpace(characters[i - 1])) {
+ count++;
+ isAfterExpansion = true;
+ } else {
+ isAfterExpansion = false;
+ }
+ }
+ }
+ return count;
+}
+
+unsigned Character::expansionOpportunityCount(const UChar* characters, size_t length, TextDirection direction, bool& isAfterExpansion)
+{
+ static bool expandAroundIdeographs = FontPlatformFeatures::canExpandAroundIdeographsInComplexText();
+ unsigned count = 0;
+ if (direction == LTR) {
+ for (size_t i = 0; i < length; ++i) {
+ UChar32 character = characters[i];
+ if (treatAsSpace(character)) {
+ count++;
+ isAfterExpansion = true;
+ continue;
+ }
+ if (U16_IS_LEAD(character) && i + 1 < length && U16_IS_TRAIL(characters[i + 1])) {
+ character = U16_GET_SUPPLEMENTARY(character, characters[i + 1]);
+ i++;
+ }
+ if (expandAroundIdeographs && isCJKIdeographOrSymbol(character)) {
+ if (!isAfterExpansion)
+ count++;
+ count++;
+ isAfterExpansion = true;
+ continue;
+ }
+ isAfterExpansion = false;
+ }
+ } else {
+ for (size_t i = length; i > 0; --i) {
+ UChar32 character = characters[i - 1];
+ if (treatAsSpace(character)) {
+ count++;
+ isAfterExpansion = true;
+ continue;
+ }
+ if (U16_IS_TRAIL(character) && i > 1 && U16_IS_LEAD(characters[i - 2])) {
+ character = U16_GET_SUPPLEMENTARY(characters[i - 2], character);
+ i--;
+ }
+ if (expandAroundIdeographs && isCJKIdeographOrSymbol(character)) {
+ if (!isAfterExpansion)
+ count++;
+ count++;
+ isAfterExpansion = true;
+ continue;
+ }
+ isAfterExpansion = false;
+ }
+ }
+ return count;
+}
+
+bool Character::canReceiveTextEmphasis(UChar32 c)
+{
+ CharCategory category = Unicode::category(c);
+ if (category & (Separator_Space | Separator_Line | Separator_Paragraph | Other_NotAssigned | Other_Control | Other_Format))
+ return false;
+
+ // Additional word-separator characters listed in CSS Text Level 3 Editor's Draft 3 November 2010.
+ if (c == ethiopicWordspace || c == aegeanWordSeparatorLine || c == aegeanWordSeparatorDot
+ || c == ugariticWordDivider || c == tibetanMarkIntersyllabicTsheg || c == tibetanMarkDelimiterTshegBstar)
+ return false;
+
+ return true;
+}
+
+template <typename CharacterType>
+static inline String normalizeSpacesInternal(const CharacterType* characters, unsigned length)
+{
+ StringBuilder normalized;
+ normalized.reserveCapacity(length);
+
+ for (unsigned i = 0; i < length; ++i)
+ normalized.append(Character::normalizeSpaces(characters[i]));
+
+ return normalized.toString();
+}
+
+String Character::normalizeSpaces(const LChar* characters, unsigned length)
+{
+ return normalizeSpacesInternal(characters, length);
+}
+
+String Character::normalizeSpaces(const UChar* characters, unsigned length)
+{
+ return normalizeSpacesInternal(characters, length);
+}
+
+}
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/Character.h b/chromium/third_party/WebKit/Source/platform/fonts/Character.h
new file mode 100644
index 00000000000..bbe0433f369
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/platform/fonts/Character.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2014 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef Character_h
+#define Character_h
+
+#include "platform/PlatformExport.h"
+#include "platform/text/TextDirection.h"
+#include "platform/text/TextPath.h"
+#include "wtf/HashSet.h"
+#include "wtf/text/WTFString.h"
+#include "wtf/unicode/CharacterNames.h"
+
+namespace WebCore {
+
+class PLATFORM_EXPORT Character {
+public:
+ static CodePath characterRangeCodePath(const LChar*, unsigned) { return SimplePath; }
+ static CodePath characterRangeCodePath(const UChar*, unsigned len);
+
+ static bool isCJKIdeograph(UChar32);
+ static bool isCJKIdeographOrSymbol(UChar32);
+
+ static unsigned expansionOpportunityCount(const LChar*, size_t length, TextDirection, bool& isAfterExpansion);
+ static unsigned expansionOpportunityCount(const UChar*, size_t length, TextDirection, bool& isAfterExpansion);
+
+ static bool treatAsSpace(UChar c) { return c == ' ' || c == '\t' || c == '\n' || c == noBreakSpace; }
+ static bool treatAsZeroWidthSpace(UChar c) { return treatAsZeroWidthSpaceInComplexScript(c) || c == 0x200c || c == 0x200d; }
+ static bool treatAsZeroWidthSpaceInComplexScript(UChar c) { return c < 0x20 || (c >= 0x7F && c < 0xA0) || c == softHyphen || c == zeroWidthSpace || (c >= 0x200e && c <= 0x200f) || (c >= 0x202a && c <= 0x202e) || c == zeroWidthNoBreakSpace || c == objectReplacementCharacter; }
+ static bool canReceiveTextEmphasis(UChar32);
+
+ static inline UChar normalizeSpaces(UChar character)
+ {
+ if (treatAsSpace(character))
+ return space;
+
+ if (treatAsZeroWidthSpace(character))
+ return zeroWidthSpace;
+
+ return character;
+ }
+
+ static String normalizeSpaces(const LChar*, unsigned length);
+ static String normalizeSpaces(const UChar*, unsigned length);
+
+ static bool isRoundingHackCharacter(UChar32 c)
+ {
+ return !(c & ~0xFF) && s_roundingHackCharacterTable[c];
+ }
+
+private:
+ Character();
+
+ static const uint8_t s_roundingHackCharacterTable[256];
+};
+
+}
+
+#endif
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/CustomFontData.h b/chromium/third_party/WebKit/Source/platform/fonts/CustomFontData.h
index cb69f5a0c41..f1b5ddaae8d 100644
--- a/chromium/third_party/WebKit/Source/platform/fonts/CustomFontData.h
+++ b/chromium/third_party/WebKit/Source/platform/fonts/CustomFontData.h
@@ -29,7 +29,6 @@
namespace WebCore {
-class CSSFontFaceSource;
struct GlyphData;
class GlyphPage;
class SimpleFontData;
@@ -37,16 +36,15 @@ struct WidthIterator;
class PLATFORM_EXPORT CustomFontData : public RefCounted<CustomFontData> {
public:
- static PassRefPtr<CustomFontData> create(bool isLoadingFallback = false)
- {
- return adoptRef(new CustomFontData(isLoadingFallback));
- }
+ static PassRefPtr<CustomFontData> create() { return adoptRef(new CustomFontData()); }
virtual ~CustomFontData() { }
virtual void beginLoadIfNeeded() const { };
- bool isLoading() const { return m_isLoadingFallback && m_isUsed; }
- bool isLoadingFallback() const { return m_isLoadingFallback; }
+ virtual bool isLoading() const { return false; }
+ virtual bool isLoadingFallback() const { return false; }
+ virtual bool shouldSkipDrawing() const { return false; }
+ virtual void clearFontFaceSource() { }
virtual bool isSVGFont() const { return false; }
virtual void initializeFontData(SimpleFontData*, float) { }
@@ -54,18 +52,8 @@ public:
virtual bool fillSVGGlyphPage(GlyphPage*, unsigned, unsigned, UChar*, unsigned, const SimpleFontData*) const { return false; }
virtual bool applySVGGlyphSelection(WidthIterator&, GlyphData&, bool, int, unsigned&) const { return false; }
- virtual void setCSSFontFaceSource(CSSFontFaceSource* source) { ASSERT_NOT_REACHED(); }
- virtual void clearCSSFontFaceSource() { }
-
protected:
- CustomFontData(bool isLoadingFallback)
- : m_isLoadingFallback(isLoadingFallback)
- , m_isUsed(false)
- {
- }
-
- bool m_isLoadingFallback; // Whether or not this is a temporary font data for a custom font which is not yet loaded.
- mutable bool m_isUsed;
+ CustomFontData() { }
};
}
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/Font.cpp b/chromium/third_party/WebKit/Source/platform/fonts/Font.cpp
index e0dfa3d0383..73a7d878c71 100644
--- a/chromium/third_party/WebKit/Source/platform/fonts/Font.cpp
+++ b/chromium/third_party/WebKit/Source/platform/fonts/Font.cpp
@@ -24,104 +24,46 @@
#include "config.h"
#include "platform/fonts/Font.h"
+#include "platform/LayoutUnit.h"
+#include "platform/fonts/Character.h"
+#include "platform/fonts/FontCache.h"
+#include "platform/fonts/FontFallbackList.h"
+#include "platform/fonts/FontPlatformFeatures.h"
+#include "platform/fonts/GlyphBuffer.h"
+#include "platform/fonts/GlyphPageTreeNode.h"
+#include "platform/fonts/SimpleFontData.h"
#include "platform/fonts/WidthIterator.h"
#include "platform/geometry/FloatRect.h"
#include "platform/text/TextRun.h"
#include "wtf/MainThread.h"
#include "wtf/StdLibExtras.h"
-#include "wtf/text/StringBuilder.h"
+#include "wtf/unicode/CharacterNames.h"
+#include "wtf/unicode/Unicode.h"
using namespace WTF;
using namespace Unicode;
-
-namespace WTF {
-
-// allow compilation of OwnPtr<TextLayout> in source files that don't have access to the TextLayout class definition
-void OwnedPtrDeleter<WebCore::TextLayout>::deletePtr(WebCore::TextLayout* ptr)
-{
- WebCore::Font::deleteLayout(ptr);
-}
-
-}
+using namespace std;
namespace WebCore {
-const uint8_t Font::s_roundingHackCharacterTable[256] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 /*\t*/, 1 /*\n*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 1 /*space*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 /*-*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 /*?*/,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 1 /*no-break space*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-};
-
-static const UChar32 cjkIsolatedSymbolsArray[] = {
- // 0x2C7 Caron, Mandarin Chinese 3rd Tone
- 0x2C7,
- // 0x2CA Modifier Letter Acute Accent, Mandarin Chinese 2nd Tone
- 0x2CA,
- // 0x2CB Modifier Letter Grave Access, Mandarin Chinese 4th Tone
- 0x2CB,
- // 0x2D9 Dot Above, Mandarin Chinese 5th Tone
- 0x2D9,
- 0x2020, 0x2021, 0x2030, 0x203B, 0x203C, 0x2042, 0x2047, 0x2048, 0x2049, 0x2051,
- 0x20DD, 0x20DE, 0x2100, 0x2103, 0x2105, 0x2109, 0x210A, 0x2113, 0x2116, 0x2121,
- 0x212B, 0x213B, 0x2150, 0x2151, 0x2152, 0x217F, 0x2189, 0x2307, 0x2312, 0x23CE,
- 0x2423, 0x25A0, 0x25A1, 0x25A2, 0x25AA, 0x25AB, 0x25B1, 0x25B2, 0x25B3, 0x25B6,
- 0x25B7, 0x25BC, 0x25BD, 0x25C0, 0x25C1, 0x25C6, 0x25C7, 0x25C9, 0x25CB, 0x25CC,
- 0x25EF, 0x2605, 0x2606, 0x260E, 0x2616, 0x2617, 0x2640, 0x2642, 0x26A0, 0x26BD,
- 0x26BE, 0x2713, 0x271A, 0x273F, 0x2740, 0x2756, 0x2B1A, 0xFE10, 0xFE11, 0xFE12,
- 0xFE19, 0xFF1D,
- // Emoji.
- 0x1F100
-};
-
-Font::CodePath Font::s_codePath = Auto;
-
-TypesettingFeatures Font::s_defaultTypesettingFeatures = 0;
+CodePath Font::s_codePath = AutoPath;
// ============================================================================================
// Font Implementation (Cross-Platform Portion)
// ============================================================================================
Font::Font()
- : m_letterSpacing(0)
- , m_wordSpacing(0)
- , m_isPlatformFont(false)
- , m_typesettingFeatures(0)
{
}
-Font::Font(const FontDescription& fd, float letterSpacing, float wordSpacing)
+Font::Font(const FontDescription& fd)
: m_fontDescription(fd)
- , m_letterSpacing(letterSpacing)
- , m_wordSpacing(wordSpacing)
- , m_isPlatformFont(false)
- , m_typesettingFeatures(computeTypesettingFeatures())
-{
-}
-
-Font::Font(const FontPlatformData& fontData, bool isPrinterFont, FontSmoothingMode fontSmoothingMode)
- : m_fontFallbackList(FontFallbackList::create())
- , m_letterSpacing(0)
- , m_wordSpacing(0)
- , m_isPlatformFont(true)
- , m_typesettingFeatures(computeTypesettingFeatures())
{
- m_fontDescription.setUsePrinterFont(isPrinterFont);
- m_fontDescription.setFontSmoothing(fontSmoothingMode);
- m_fontFallbackList->setPlatformFont(fontData);
}
Font::Font(const Font& other)
: m_fontDescription(other.m_fontDescription)
, m_fontFallbackList(other.m_fontFallbackList)
- , m_letterSpacing(other.m_letterSpacing)
- , m_wordSpacing(other.m_wordSpacing)
- , m_isPlatformFont(other.m_isPlatformFont)
- , m_typesettingFeatures(computeTypesettingFeatures())
{
}
@@ -129,10 +71,6 @@ Font& Font::operator=(const Font& other)
{
m_fontDescription = other.m_fontDescription;
m_fontFallbackList = other.m_fontFallbackList;
- m_letterSpacing = other.m_letterSpacing;
- m_wordSpacing = other.m_wordSpacing;
- m_isPlatformFont = other.m_isPlatformFont;
- m_typesettingFeatures = other.m_typesettingFeatures;
return *this;
}
@@ -148,13 +86,11 @@ bool Font::operator==(const Font& other) const
return first == second
&& m_fontDescription == other.m_fontDescription
- && m_letterSpacing == other.m_letterSpacing
- && m_wordSpacing == other.m_wordSpacing
&& (m_fontFallbackList ? m_fontFallbackList->fontSelectorVersion() : 0) == (other.m_fontFallbackList ? other.m_fontFallbackList->fontSelectorVersion() : 0)
&& (m_fontFallbackList ? m_fontFallbackList->generation() : 0) == (other.m_fontFallbackList ? other.m_fontFallbackList->generation() : 0);
}
-void Font::update(PassRefPtr<FontSelector> fontSelector) const
+void Font::update(PassRefPtrWillBeRawPtr<FontSelector> fontSelector) const
{
// FIXME: It is pretty crazy that we are willing to just poke into a RefPtr, but it ends up
// being reasonably safe (because inherited fonts in the render tree pick up the new
@@ -164,7 +100,6 @@ void Font::update(PassRefPtr<FontSelector> fontSelector) const
if (!m_fontFallbackList)
m_fontFallbackList = FontFallbackList::create();
m_fontFallbackList->invalidate(fontSelector);
- m_typesettingFeatures = computeTypesettingFeatures();
}
void Font::drawText(GraphicsContext* context, const TextRunPaintInfo& runInfo, const FloatPoint& point, CustomFontNotReadyAction customFontNotReadyAction) const
@@ -172,15 +107,15 @@ void Font::drawText(GraphicsContext* context, const TextRunPaintInfo& runInfo, c
// Don't draw anything while we are using custom fonts that are in the process of loading,
// except if the 'force' argument is set to true (in which case it will use a fallback
// font).
- if (loadingCustomFonts() && customFontNotReadyAction == DoNotPaintIfFontNotReady)
+ if (shouldSkipDrawing() && customFontNotReadyAction == DoNotPaintIfFontNotReady)
return;
CodePath codePathToUse = codePath(runInfo.run);
// FIXME: Use the fast code path once it handles partial runs with kerning and ligatures. See http://webkit.org/b/100050
- if (codePathToUse != Complex && typesettingFeatures() && (runInfo.from || runInfo.to != runInfo.run.length()))
- codePathToUse = Complex;
+ if (codePathToUse != ComplexPath && fontDescription().typesettingFeatures() && (runInfo.from || runInfo.to != runInfo.run.length()))
+ codePathToUse = ComplexPath;
- if (codePathToUse != Complex)
+ if (codePathToUse != ComplexPath)
return drawSimpleText(context, runInfo, point);
return drawComplexText(context, runInfo, point);
@@ -188,92 +123,100 @@ void Font::drawText(GraphicsContext* context, const TextRunPaintInfo& runInfo, c
void Font::drawEmphasisMarks(GraphicsContext* context, const TextRunPaintInfo& runInfo, const AtomicString& mark, const FloatPoint& point) const
{
- if (loadingCustomFonts())
+ if (shouldSkipDrawing())
return;
CodePath codePathToUse = codePath(runInfo.run);
// FIXME: Use the fast code path once it handles partial runs with kerning and ligatures. See http://webkit.org/b/100050
- if (codePathToUse != Complex && typesettingFeatures() && (runInfo.from || runInfo.to != runInfo.run.length()))
- codePathToUse = Complex;
+ if (codePathToUse != ComplexPath && fontDescription().typesettingFeatures() && (runInfo.from || runInfo.to != runInfo.run.length()))
+ codePathToUse = ComplexPath;
- if (codePathToUse != Complex)
+ if (codePathToUse != ComplexPath)
drawEmphasisMarksForSimpleText(context, runInfo, mark, point);
else
drawEmphasisMarksForComplexText(context, runInfo, mark, point);
}
+static inline void updateGlyphOverflowFromBounds(const IntRectExtent& glyphBounds,
+ const FontMetrics& fontMetrics, GlyphOverflow* glyphOverflow)
+{
+ glyphOverflow->top = max<int>(glyphOverflow->top,
+ glyphBounds.top() - (glyphOverflow->computeBounds ? 0 : fontMetrics.ascent()));
+ glyphOverflow->bottom = max<int>(glyphOverflow->bottom,
+ glyphBounds.bottom() - (glyphOverflow->computeBounds ? 0 : fontMetrics.descent()));
+ glyphOverflow->left = glyphBounds.left();
+ glyphOverflow->right = glyphBounds.right();
+}
+
float Font::width(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const
{
CodePath codePathToUse = codePath(run);
- if (codePathToUse != Complex) {
+ if (codePathToUse != ComplexPath) {
// The complex path is more restrictive about returning fallback fonts than the simple path, so we need an explicit test to make their behaviors match.
- if (!canReturnFallbackFontsForComplexText())
+ if (!FontPlatformFeatures::canReturnFallbackFontsForComplexText())
fallbackFonts = 0;
// The simple path can optimize the case where glyph overflow is not observable.
- if (codePathToUse != SimpleWithGlyphOverflow && (glyphOverflow && !glyphOverflow->computeBounds))
+ if (codePathToUse != SimpleWithGlyphOverflowPath && (glyphOverflow && !glyphOverflow->computeBounds))
glyphOverflow = 0;
}
- bool hasKerningOrLigatures = typesettingFeatures() & (Kerning | Ligatures);
- bool hasWordSpacingOrLetterSpacing = wordSpacing() || letterSpacing();
- float* cacheEntry = m_fontFallbackList->widthCache().add(run, std::numeric_limits<float>::quiet_NaN(), hasKerningOrLigatures, hasWordSpacingOrLetterSpacing, glyphOverflow);
- if (cacheEntry && !std::isnan(*cacheEntry))
- return *cacheEntry;
+ bool hasKerningOrLigatures = fontDescription().typesettingFeatures() & (Kerning | Ligatures);
+ bool hasWordSpacingOrLetterSpacing = fontDescription().wordSpacing() || fontDescription().letterSpacing();
+ bool isCacheable = (codePathToUse == ComplexPath || hasKerningOrLigatures)
+ && !hasWordSpacingOrLetterSpacing // Word spacing and letter spacing can change the width of a word.
+ && !run.allowTabs(); // If we allow tabs and a tab occurs inside a word, the width of the word varies based on its position on the line.
+
+ WidthCacheEntry* cacheEntry = isCacheable
+ ? m_fontFallbackList->widthCache().add(run, WidthCacheEntry())
+ : 0;
+ if (cacheEntry && cacheEntry->isValid()) {
+ if (glyphOverflow)
+ updateGlyphOverflowFromBounds(cacheEntry->glyphBounds, fontMetrics(), glyphOverflow);
+ return cacheEntry->width;
+ }
float result;
- if (codePathToUse == Complex)
- result = floatWidthForComplexText(run, fallbackFonts, glyphOverflow);
- else
- result = floatWidthForSimpleText(run, fallbackFonts, glyphOverflow);
+ IntRectExtent glyphBounds;
+ if (codePathToUse == ComplexPath) {
+ result = floatWidthForComplexText(run, fallbackFonts, &glyphBounds);
+ } else {
+ result = floatWidthForSimpleText(run, fallbackFonts,
+ glyphOverflow || isCacheable ? &glyphBounds : 0);
+ }
+
+ if (cacheEntry && (!fallbackFonts || fallbackFonts->isEmpty())) {
+ cacheEntry->glyphBounds = glyphBounds;
+ cacheEntry->width = result;
+ }
- if (cacheEntry && (!fallbackFonts || fallbackFonts->isEmpty()))
- *cacheEntry = result;
+ if (glyphOverflow)
+ updateGlyphOverflowFromBounds(glyphBounds, fontMetrics(), glyphOverflow);
return result;
}
-float Font::width(const TextRun& run, int& charsConsumed, String& glyphName) const
+float Font::width(const TextRun& run, int& charsConsumed, Glyph& glyphId) const
{
#if ENABLE(SVG_FONTS)
if (TextRun::RenderingContext* renderingContext = run.renderingContext())
- return renderingContext->floatWidthUsingSVGFont(*this, run, charsConsumed, glyphName);
+ return renderingContext->floatWidthUsingSVGFont(*this, run, charsConsumed, glyphId);
#endif
charsConsumed = run.length();
- glyphName = "";
+ glyphId = 0;
return width(run);
}
-#if !OS(MACOSX)
-
-PassOwnPtr<TextLayout> Font::createLayoutForMacComplexText(const TextRun&, unsigned, float, bool) const
-{
- ASSERT_NOT_REACHED();
- return nullptr;
-}
-
-void Font::deleteLayout(TextLayout*)
-{
-}
-
-float Font::width(TextLayout&, unsigned, unsigned, HashSet<const SimpleFontData*>*)
-{
- ASSERT_NOT_REACHED();
- return 0;
-}
-
-#endif
-
-FloatRect Font::selectionRectForText(const TextRun& run, const FloatPoint& point, int h, int from, int to) const
+FloatRect Font::selectionRectForText(const TextRun& run, const FloatPoint& point, int h, int from, int to, bool accountForGlyphBounds) const
{
to = (to == -1 ? run.length() : to);
CodePath codePathToUse = codePath(run);
// FIXME: Use the fast code path once it handles partial runs with kerning and ligatures. See http://webkit.org/b/100050
- if (codePathToUse != Complex && typesettingFeatures() && (from || to != run.length()))
- codePathToUse = Complex;
+ if (codePathToUse != ComplexPath && fontDescription().typesettingFeatures() && (from || to != run.length()))
+ codePathToUse = ComplexPath;
- if (codePathToUse != Complex)
- return selectionRectForSimpleText(run, point, h, from, to);
+ if (codePathToUse != ComplexPath)
+ return selectionRectForSimpleText(run, point, h, from, to, accountForGlyphBounds);
return selectionRectForComplexText(run, point, h, from, to);
}
@@ -281,417 +224,637 @@ FloatRect Font::selectionRectForText(const TextRun& run, const FloatPoint& point
int Font::offsetForPosition(const TextRun& run, float x, bool includePartialGlyphs) const
{
// FIXME: Use the fast code path once it handles partial runs with kerning and ligatures. See http://webkit.org/b/100050
- if (codePath(run) != Complex && !typesettingFeatures())
+ if (codePath(run) != ComplexPath && !fontDescription().typesettingFeatures())
return offsetForPositionForSimpleText(run, x, includePartialGlyphs);
return offsetForPositionForComplexText(run, x, includePartialGlyphs);
}
-template <typename CharacterType>
-static inline String normalizeSpacesInternal(const CharacterType* characters, unsigned length)
+void Font::setCodePath(CodePath p)
+{
+ s_codePath = p;
+}
+
+CodePath Font::codePath()
{
- StringBuilder normalized;
- normalized.reserveCapacity(length);
+ return s_codePath;
+}
- for (unsigned i = 0; i < length; ++i)
- normalized.append(Font::normalizeSpaces(characters[i]));
+CodePath Font::codePath(const TextRun& run) const
+{
+ if (s_codePath != AutoPath)
+ return s_codePath;
- return normalized.toString();
+#if ENABLE(SVG_FONTS)
+ if (run.renderingContext())
+ return SimplePath;
+#endif
+
+ if (m_fontDescription.featureSettings() && m_fontDescription.featureSettings()->size() > 0 && m_fontDescription.letterSpacing() == 0)
+ return ComplexPath;
+
+ if (run.length() > 1 && !WidthIterator::supportsTypesettingFeatures(*this))
+ return ComplexPath;
+
+ if (!run.characterScanForCodePath())
+ return SimplePath;
+
+ if (run.is8Bit())
+ return SimplePath;
+
+ // Start from 0 since drawing and highlighting also measure the characters before run->from.
+ return Character::characterRangeCodePath(run.characters16(), run.length());
}
-String Font::normalizeSpaces(const LChar* characters, unsigned length)
+void Font::willUseFontData(UChar32 character) const
{
- return normalizeSpacesInternal(characters, length);
+ const FontFamily& family = fontDescription().family();
+ if (m_fontFallbackList && m_fontFallbackList->fontSelector() && !family.familyIsEmpty())
+ m_fontFallbackList->fontSelector()->willUseFontData(fontDescription(), family.family(), character);
}
-String Font::normalizeSpaces(const UChar* characters, unsigned length)
+static inline bool isInRange(UChar32 character, UChar32 lowerBound, UChar32 upperBound)
{
- return normalizeSpacesInternal(characters, length);
+ return character >= lowerBound && character <= upperBound;
}
-static bool shouldUseFontSmoothing = true;
+static bool shouldIgnoreRotation(UChar32 character)
+{
+ if (character == 0x000A7 || character == 0x000A9 || character == 0x000AE)
+ return true;
-void Font::setShouldUseSmoothing(bool shouldUseSmoothing)
+ if (character == 0x000B6 || character == 0x000BC || character == 0x000BD || character == 0x000BE)
+ return true;
+
+ if (isInRange(character, 0x002E5, 0x002EB))
+ return true;
+
+ if (isInRange(character, 0x01100, 0x011FF) || isInRange(character, 0x01401, 0x0167F) || isInRange(character, 0x01800, 0x018FF))
+ return true;
+
+ if (character == 0x02016 || character == 0x02018 || character == 0x02019 || character == 0x02020 || character == 0x02021
+ || character == 0x2030 || character == 0x02031)
+ return true;
+
+ if (isInRange(character, 0x0203B, 0x0203D) || character == 0x02042 || character == 0x02044 || character == 0x02047
+ || character == 0x02048 || character == 0x02049 || character == 0x2051)
+ return true;
+
+ if (isInRange(character, 0x02065, 0x02069) || isInRange(character, 0x020DD, 0x020E0)
+ || isInRange(character, 0x020E2, 0x020E4) || isInRange(character, 0x02100, 0x02117)
+ || isInRange(character, 0x02119, 0x02131) || isInRange(character, 0x02133, 0x0213F))
+ return true;
+
+ if (isInRange(character, 0x02145, 0x0214A) || character == 0x0214C || character == 0x0214D
+ || isInRange(character, 0x0214F, 0x0218F))
+ return true;
+
+ if (isInRange(character, 0x02300, 0x02307) || isInRange(character, 0x0230C, 0x0231F)
+ || isInRange(character, 0x02322, 0x0232B) || isInRange(character, 0x0237D, 0x0239A)
+ || isInRange(character, 0x023B4, 0x023B6) || isInRange(character, 0x023BA, 0x023CF)
+ || isInRange(character, 0x023D1, 0x023DB) || isInRange(character, 0x023E2, 0x024FF))
+ return true;
+
+ if (isInRange(character, 0x025A0, 0x02619) || isInRange(character, 0x02620, 0x02767)
+ || isInRange(character, 0x02776, 0x02793) || isInRange(character, 0x02B12, 0x02B2F)
+ || isInRange(character, 0x02B4D, 0x02BFF) || isInRange(character, 0x02E80, 0x03007))
+ return true;
+
+ if (character == 0x03012 || character == 0x03013 || isInRange(character, 0x03020, 0x0302F)
+ || isInRange(character, 0x03031, 0x0309F) || isInRange(character, 0x030A1, 0x030FB)
+ || isInRange(character, 0x030FD, 0x0A4CF))
+ return true;
+
+ if (isInRange(character, 0x0A840, 0x0A87F) || isInRange(character, 0x0A960, 0x0A97F)
+ || isInRange(character, 0x0AC00, 0x0D7FF) || isInRange(character, 0x0E000, 0x0FAFF))
+ return true;
+
+ if (isInRange(character, 0x0FE10, 0x0FE1F) || isInRange(character, 0x0FE30, 0x0FE48)
+ || isInRange(character, 0x0FE50, 0x0FE57) || isInRange(character, 0x0FE5F, 0x0FE62)
+ || isInRange(character, 0x0FE67, 0x0FE6F))
+ return true;
+
+ if (isInRange(character, 0x0FF01, 0x0FF07) || isInRange(character, 0x0FF0A, 0x0FF0C)
+ || isInRange(character, 0x0FF0E, 0x0FF19) || isInRange(character, 0x0FF1F, 0x0FF3A))
+ return true;
+
+ if (character == 0x0FF3C || character == 0x0FF3E)
+ return true;
+
+ if (isInRange(character, 0x0FF40, 0x0FF5A) || isInRange(character, 0x0FFE0, 0x0FFE2)
+ || isInRange(character, 0x0FFE4, 0x0FFE7) || isInRange(character, 0x0FFF0, 0x0FFF8)
+ || character == 0x0FFFD)
+ return true;
+
+ if (isInRange(character, 0x13000, 0x1342F) || isInRange(character, 0x1B000, 0x1B0FF)
+ || isInRange(character, 0x1D000, 0x1D1FF) || isInRange(character, 0x1D300, 0x1D37F)
+ || isInRange(character, 0x1F000, 0x1F64F) || isInRange(character, 0x1F680, 0x1F77F))
+ return true;
+
+ if (isInRange(character, 0x20000, 0x2FFFD) || isInRange(character, 0x30000, 0x3FFFD))
+ return true;
+
+ return false;
+}
+
+static inline std::pair<GlyphData, GlyphPage*> glyphDataAndPageForNonCJKCharacterWithGlyphOrientation(UChar32 character, NonCJKGlyphOrientation orientation, GlyphData& data, GlyphPage* page, unsigned pageNumber)
+{
+ if (orientation == NonCJKGlyphOrientationUpright || shouldIgnoreRotation(character)) {
+ RefPtr<SimpleFontData> uprightFontData = data.fontData->uprightOrientationFontData();
+ GlyphPageTreeNode* uprightNode = GlyphPageTreeNode::getRootChild(uprightFontData.get(), pageNumber);
+ GlyphPage* uprightPage = uprightNode->page();
+ if (uprightPage) {
+ GlyphData uprightData = uprightPage->glyphDataForCharacter(character);
+ // If the glyphs are the same, then we know we can just use the horizontal glyph rotated vertically to be upright.
+ if (data.glyph == uprightData.glyph)
+ return make_pair(data, page);
+ // The glyphs are distinct, meaning that the font has a vertical-right glyph baked into it. We can't use that
+ // glyph, so we fall back to the upright data and use the horizontal glyph.
+ if (uprightData.fontData)
+ return make_pair(uprightData, uprightPage);
+ }
+ } else if (orientation == NonCJKGlyphOrientationVerticalRight) {
+ RefPtr<SimpleFontData> verticalRightFontData = data.fontData->verticalRightOrientationFontData();
+ GlyphPageTreeNode* verticalRightNode = GlyphPageTreeNode::getRootChild(verticalRightFontData.get(), pageNumber);
+ GlyphPage* verticalRightPage = verticalRightNode->page();
+ if (verticalRightPage) {
+ GlyphData verticalRightData = verticalRightPage->glyphDataForCharacter(character);
+ // If the glyphs are distinct, we will make the assumption that the font has a vertical-right glyph baked
+ // into it.
+ if (data.glyph != verticalRightData.glyph)
+ return make_pair(data, page);
+ // The glyphs are identical, meaning that we should just use the horizontal glyph.
+ if (verticalRightData.fontData)
+ return make_pair(verticalRightData, verticalRightPage);
+ }
+ }
+ return make_pair(data, page);
+}
+
+std::pair<GlyphData, GlyphPage*> Font::glyphDataAndPageForCharacter(UChar32 c, bool mirror, FontDataVariant variant) const
{
ASSERT(isMainThread());
- shouldUseFontSmoothing = shouldUseSmoothing;
+
+ if (variant == AutoVariant) {
+ if (m_fontDescription.variant() == FontVariantSmallCaps && !primaryFont()->isSVGFont()) {
+ UChar32 upperC = toUpper(c);
+ if (upperC != c) {
+ c = upperC;
+ variant = SmallCapsVariant;
+ } else {
+ variant = NormalVariant;
+ }
+ } else {
+ variant = NormalVariant;
+ }
+ }
+
+ if (mirror)
+ c = mirroredChar(c);
+
+ unsigned pageNumber = (c / GlyphPage::size);
+
+ GlyphPageTreeNode* node = pageNumber ? m_fontFallbackList->m_pages.get(pageNumber) : m_fontFallbackList->m_pageZero;
+ if (!node) {
+ node = GlyphPageTreeNode::getRootChild(fontDataAt(0), pageNumber);
+ if (pageNumber)
+ m_fontFallbackList->m_pages.set(pageNumber, node);
+ else
+ m_fontFallbackList->m_pageZero = node;
+ }
+
+ GlyphPage* page = 0;
+ if (variant == NormalVariant) {
+ // Fastest loop, for the common case (normal variant).
+ while (true) {
+ page = node->page();
+ if (page) {
+ GlyphData data = page->glyphDataForCharacter(c);
+ if (data.fontData && (data.fontData->platformData().orientation() == Horizontal || data.fontData->isTextOrientationFallback()))
+ return make_pair(data, page);
+
+ if (data.fontData) {
+ if (Character::isCJKIdeographOrSymbol(c)) {
+ if (!data.fontData->hasVerticalGlyphs()) {
+ // Use the broken ideograph font data. The broken ideograph font will use the horizontal width of glyphs
+ // to make sure you get a square (even for broken glyphs like symbols used for punctuation).
+ variant = BrokenIdeographVariant;
+ break;
+ }
+ } else {
+ return glyphDataAndPageForNonCJKCharacterWithGlyphOrientation(c, m_fontDescription.nonCJKGlyphOrientation(), data, page, pageNumber);
+ }
+
+ return make_pair(data, page);
+ }
+
+ if (node->isSystemFallback())
+ break;
+ }
+
+ // Proceed with the fallback list.
+ node = node->getChild(fontDataAt(node->level()), pageNumber);
+ if (pageNumber)
+ m_fontFallbackList->m_pages.set(pageNumber, node);
+ else
+ m_fontFallbackList->m_pageZero = node;
+ }
+ }
+ if (variant != NormalVariant) {
+ while (true) {
+ page = node->page();
+ if (page) {
+ GlyphData data = page->glyphDataForCharacter(c);
+ if (data.fontData) {
+ // The variantFontData function should not normally return 0.
+ // But if it does, we will just render the capital letter big.
+ RefPtr<SimpleFontData> variantFontData = data.fontData->variantFontData(m_fontDescription, variant);
+ if (!variantFontData)
+ return make_pair(data, page);
+
+ GlyphPageTreeNode* variantNode = GlyphPageTreeNode::getRootChild(variantFontData.get(), pageNumber);
+ GlyphPage* variantPage = variantNode->page();
+ if (variantPage) {
+ GlyphData data = variantPage->glyphDataForCharacter(c);
+ if (data.fontData)
+ return make_pair(data, variantPage);
+ }
+
+ // Do not attempt system fallback off the variantFontData. This is the very unlikely case that
+ // a font has the lowercase character but the small caps font does not have its uppercase version.
+ return make_pair(variantFontData->missingGlyphData(), page);
+ }
+
+ if (node->isSystemFallback())
+ break;
+ }
+
+ // Proceed with the fallback list.
+ node = node->getChild(fontDataAt(node->level()), pageNumber);
+ if (pageNumber)
+ m_fontFallbackList->m_pages.set(pageNumber, node);
+ else
+ m_fontFallbackList->m_pageZero = node;
+ }
+ }
+
+ ASSERT(page);
+ ASSERT(node->isSystemFallback());
+
+ // System fallback is character-dependent. When we get here, we
+ // know that the character in question isn't in the system fallback
+ // font's glyph page. Try to lazily create it here.
+
+ // FIXME: Unclear if this should normalizeSpaces above 0xFFFF.
+ // Doing so changes fast/text/international/plane2-diffs.html
+ UChar32 characterToRender = c;
+ if (characterToRender <= 0xFFFF)
+ characterToRender = Character::normalizeSpaces(characterToRender);
+ const SimpleFontData* fontDataToSubstitute = fontDataAt(0)->fontDataForCharacter(characterToRender);
+ RefPtr<SimpleFontData> characterFontData = FontCache::fontCache()->fallbackFontForCharacter(m_fontDescription, characterToRender, fontDataToSubstitute);
+ if (characterFontData) {
+ if (characterFontData->platformData().orientation() == Vertical && !characterFontData->hasVerticalGlyphs() && Character::isCJKIdeographOrSymbol(c))
+ variant = BrokenIdeographVariant;
+ if (variant != NormalVariant)
+ characterFontData = characterFontData->variantFontData(m_fontDescription, variant);
+ }
+ if (characterFontData) {
+ // Got the fallback glyph and font.
+ GlyphPage* fallbackPage = GlyphPageTreeNode::getRootChild(characterFontData.get(), pageNumber)->page();
+ GlyphData data = fallbackPage && fallbackPage->glyphForCharacter(c) ? fallbackPage->glyphDataForCharacter(c) : characterFontData->missingGlyphData();
+ // Cache it so we don't have to do system fallback again next time.
+ if (variant == NormalVariant) {
+ page->setGlyphDataForCharacter(c, data.glyph, data.fontData);
+ data.fontData->setMaxGlyphPageTreeLevel(max(data.fontData->maxGlyphPageTreeLevel(), node->level()));
+ if (!Character::isCJKIdeographOrSymbol(c) && data.fontData->platformData().orientation() != Horizontal && !data.fontData->isTextOrientationFallback())
+ return glyphDataAndPageForNonCJKCharacterWithGlyphOrientation(c, m_fontDescription.nonCJKGlyphOrientation(), data, page, pageNumber);
+ }
+ return make_pair(data, page);
+ }
+
+ // Even system fallback can fail; use the missing glyph in that case.
+ // FIXME: It would be nicer to use the missing glyph from the last resort font instead.
+ GlyphData data = primaryFont()->missingGlyphData();
+ if (variant == NormalVariant) {
+ page->setGlyphDataForCharacter(c, data.glyph, data.fontData);
+ data.fontData->setMaxGlyphPageTreeLevel(max(data.fontData->maxGlyphPageTreeLevel(), node->level()));
+ }
+ return make_pair(data, page);
}
-bool Font::shouldUseSmoothing()
+bool Font::primaryFontHasGlyphForCharacter(UChar32 character) const
{
- return shouldUseFontSmoothing;
+ unsigned pageNumber = (character / GlyphPage::size);
+
+ GlyphPageTreeNode* node = GlyphPageTreeNode::getRootChild(primaryFont(), pageNumber);
+ GlyphPage* page = node->page();
+
+ return page && page->glyphForCharacter(character);
}
-void Font::setCodePath(CodePath p)
+// FIXME: This function may not work if the emphasis mark uses a complex script, but none of the
+// standard emphasis marks do so.
+bool Font::getEmphasisMarkGlyphData(const AtomicString& mark, GlyphData& glyphData) const
{
- s_codePath = p;
+ if (mark.isEmpty())
+ return false;
+
+ UChar32 character = mark[0];
+
+ if (U16_IS_SURROGATE(character)) {
+ if (!U16_IS_SURROGATE_LEAD(character))
+ return false;
+
+ if (mark.length() < 2)
+ return false;
+
+ UChar low = mark[1];
+ if (!U16_IS_TRAIL(low))
+ return false;
+
+ character = U16_GET_SUPPLEMENTARY(character, low);
+ }
+
+ glyphData = glyphDataForCharacter(character, false, EmphasisMarkVariant);
+ return true;
}
-Font::CodePath Font::codePath()
+int Font::emphasisMarkAscent(const AtomicString& mark) const
{
- return s_codePath;
+ FontCachePurgePreventer purgePreventer;
+
+ GlyphData markGlyphData;
+ if (!getEmphasisMarkGlyphData(mark, markGlyphData))
+ return 0;
+
+ const SimpleFontData* markFontData = markGlyphData.fontData;
+ ASSERT(markFontData);
+ if (!markFontData)
+ return 0;
+
+ return markFontData->fontMetrics().ascent();
}
-void Font::setDefaultTypesettingFeatures(TypesettingFeatures typesettingFeatures)
+int Font::emphasisMarkDescent(const AtomicString& mark) const
{
- s_defaultTypesettingFeatures = typesettingFeatures;
+ FontCachePurgePreventer purgePreventer;
+
+ GlyphData markGlyphData;
+ if (!getEmphasisMarkGlyphData(mark, markGlyphData))
+ return 0;
+
+ const SimpleFontData* markFontData = markGlyphData.fontData;
+ ASSERT(markFontData);
+ if (!markFontData)
+ return 0;
+
+ return markFontData->fontMetrics().descent();
}
-TypesettingFeatures Font::defaultTypesettingFeatures()
+int Font::emphasisMarkHeight(const AtomicString& mark) const
{
- return s_defaultTypesettingFeatures;
+ FontCachePurgePreventer purgePreventer;
+
+ GlyphData markGlyphData;
+ if (!getEmphasisMarkGlyphData(mark, markGlyphData))
+ return 0;
+
+ const SimpleFontData* markFontData = markGlyphData.fontData;
+ ASSERT(markFontData);
+ if (!markFontData)
+ return 0;
+
+ return markFontData->fontMetrics().height();
}
-Font::CodePath Font::codePath(const TextRun& run) const
+float Font::getGlyphsAndAdvancesForSimpleText(const TextRunPaintInfo& runInfo, GlyphBuffer& glyphBuffer, ForTextEmphasisOrNot forTextEmphasis) const
{
- if (s_codePath != Auto)
- return s_codePath;
+ float initialAdvance;
-#if ENABLE(SVG_FONTS)
- if (run.renderingContext())
- return Simple;
-#endif
+ WidthIterator it(this, runInfo.run, 0, false, forTextEmphasis);
+ // FIXME: Using separate glyph buffers for the prefix and the suffix is incorrect when kerning or
+ // ligatures are enabled.
+ GlyphBuffer localGlyphBuffer;
+ it.advance(runInfo.from, &localGlyphBuffer);
+ float beforeWidth = it.m_runWidthSoFar;
+ it.advance(runInfo.to, &glyphBuffer);
- if (m_fontDescription.featureSettings() && m_fontDescription.featureSettings()->size() > 0)
- return Complex;
+ if (glyphBuffer.isEmpty())
+ return 0;
- if (run.length() > 1 && !WidthIterator::supportsTypesettingFeatures(*this))
- return Complex;
+ float afterWidth = it.m_runWidthSoFar;
- if (!run.characterScanForCodePath())
- return Simple;
+ if (runInfo.run.rtl()) {
+ float finalRoundingWidth = it.m_finalRoundingWidth;
+ it.advance(runInfo.run.length(), &localGlyphBuffer);
+ initialAdvance = finalRoundingWidth + it.m_runWidthSoFar - afterWidth;
+ glyphBuffer.reverse();
+ } else {
+ initialAdvance = beforeWidth;
+ }
- if (run.is8Bit())
- return Simple;
+ return initialAdvance;
+}
- // Start from 0 since drawing and highlighting also measure the characters before run->from.
- return characterRangeCodePath(run.characters16(), run.length());
-}
-
-static inline UChar keyExtractorUChar(const UChar* value)
-{
- return *value;
-}
-
-static inline UChar32 keyExtractorUChar32(const UChar32* value)
-{
- return *value;
-}
-
-Font::CodePath Font::characterRangeCodePath(const UChar* characters, unsigned len)
-{
- static const UChar complexCodePathRanges[] = {
- // U+02E5 through U+02E9 (Modifier Letters : Tone letters)
- 0x2E5, 0x2E9,
- // U+0300 through U+036F Combining diacritical marks
- 0x300, 0x36F,
- // U+0591 through U+05CF excluding U+05BE Hebrew combining marks, ...
- 0x0591, 0x05BD,
- // ... Hebrew punctuation Paseq, Sof Pasuq and Nun Hafukha
- 0x05BF, 0x05CF,
- // U+0600 through U+109F Arabic, Syriac, Thaana, NKo, Samaritan, Mandaic,
- // Devanagari, Bengali, Gurmukhi, Gujarati, Oriya, Tamil, Telugu, Kannada,
- // Malayalam, Sinhala, Thai, Lao, Tibetan, Myanmar
- 0x0600, 0x109F,
- // U+1100 through U+11FF Hangul Jamo (only Ancient Korean should be left
- // here if you precompose; Modern Korean will be precomposed as a result of step A)
- 0x1100, 0x11FF,
- // U+135D through U+135F Ethiopic combining marks
- 0x135D, 0x135F,
- // U+1780 through U+18AF Tagalog, Hanunoo, Buhid, Taghanwa,Khmer, Mongolian
- 0x1700, 0x18AF,
- // U+1900 through U+194F Limbu (Unicode 4.0)
- 0x1900, 0x194F,
- // U+1980 through U+19DF New Tai Lue
- 0x1980, 0x19DF,
- // U+1A00 through U+1CFF Buginese, Tai Tham, Balinese, Batak, Lepcha, Vedic
- 0x1A00, 0x1CFF,
- // U+1DC0 through U+1DFF Comining diacritical mark supplement
- 0x1DC0, 0x1DFF,
- // U+20D0 through U+20FF Combining marks for symbols
- 0x20D0, 0x20FF,
- // U+2CEF through U+2CF1 Combining marks for Coptic
- 0x2CEF, 0x2CF1,
- // U+302A through U+302F Ideographic and Hangul Tone marks
- 0x302A, 0x302F,
- // U+A67C through U+A67D Combining marks for old Cyrillic
- 0xA67C, 0xA67D,
- // U+A6F0 through U+A6F1 Combining mark for Bamum
- 0xA6F0, 0xA6F1,
- // U+A800 through U+ABFF Nagri, Phags-pa, Saurashtra, Devanagari Extended,
- // Hangul Jamo Ext. A, Javanese, Myanmar Extended A, Tai Viet, Meetei Mayek
- 0xA800, 0xABFF,
- // U+D7B0 through U+D7FF Hangul Jamo Ext. B
- 0xD7B0, 0xD7FF,
- // U+FE00 through U+FE0F Unicode variation selectors
- 0xFE00, 0xFE0F,
- // U+FE20 through U+FE2F Combining half marks
- 0xFE20, 0xFE2F
- };
- static size_t complexCodePathRangesCount = WTF_ARRAY_LENGTH(complexCodePathRanges);
-
- CodePath result = Simple;
- for (unsigned i = 0; i < len; i++) {
- const UChar c = characters[i];
-
- // Shortcut for common case
- if (c < 0x2E5)
- continue;
-
- // U+1E00 through U+2000 characters with diacritics and stacked diacritics
- if (c >= 0x1E00 && c <= 0x2000) {
- result = SimpleWithGlyphOverflow;
- continue;
- }
+void Font::drawSimpleText(GraphicsContext* context, const TextRunPaintInfo& runInfo, const FloatPoint& point) const
+{
+ // This glyph buffer holds our glyphs+advances+font data for each glyph.
+ GlyphBuffer glyphBuffer;
- // Surrogate pairs
- if (c > 0xD7FF && c <= 0xDBFF) {
- if (i == len - 1)
- continue;
+ float startX = point.x() + getGlyphsAndAdvancesForSimpleText(runInfo, glyphBuffer);
- UChar next = characters[++i];
- if (!U16_IS_TRAIL(next))
- continue;
+ if (glyphBuffer.isEmpty())
+ return;
- UChar32 supplementaryCharacter = U16_GET_SUPPLEMENTARY(c, next);
+ FloatPoint startPoint(startX, point.y());
+ drawGlyphBuffer(context, runInfo, glyphBuffer, startPoint);
+}
- if (supplementaryCharacter < 0x1F1E6) // U+1F1E6 through U+1F1FF Regional Indicator Symbols
- continue;
- if (supplementaryCharacter <= 0x1F1FF)
- return Complex;
+void Font::drawEmphasisMarksForSimpleText(GraphicsContext* context, const TextRunPaintInfo& runInfo, const AtomicString& mark, const FloatPoint& point) const
+{
+ GlyphBuffer glyphBuffer;
+ float initialAdvance = getGlyphsAndAdvancesForSimpleText(runInfo, glyphBuffer, ForTextEmphasis);
- if (supplementaryCharacter < 0xE0100) // U+E0100 through U+E01EF Unicode variation selectors.
- continue;
- if (supplementaryCharacter <= 0xE01EF)
- return Complex;
+ if (glyphBuffer.isEmpty())
+ return;
- // FIXME: Check for Brahmi (U+11000 block), Kaithi (U+11080 block) and other complex scripts
- // in plane 1 or higher.
+ drawEmphasisMarks(context, runInfo, glyphBuffer, mark, FloatPoint(point.x() + initialAdvance, point.y()));
+}
- continue;
- }
+void Font::drawGlyphBuffer(GraphicsContext* context, const TextRunPaintInfo& runInfo, const GlyphBuffer& glyphBuffer, const FloatPoint& point) const
+{
+ // Draw each contiguous run of glyphs that use the same font data.
+ const SimpleFontData* fontData = glyphBuffer.fontDataAt(0);
+ FloatPoint startPoint(point);
+ FloatPoint nextPoint = startPoint + glyphBuffer.advanceAt(0);
+ unsigned lastFrom = 0;
+ unsigned nextGlyph = 1;
+#if ENABLE(SVG_FONTS)
+ TextRun::RenderingContext* renderingContext = runInfo.run.renderingContext();
+#endif
+ while (nextGlyph < glyphBuffer.size()) {
+ const SimpleFontData* nextFontData = glyphBuffer.fontDataAt(nextGlyph);
- // Search for other Complex cases
- UChar* boundingCharacter = approximateBinarySearch<UChar, UChar>(
- (UChar*)complexCodePathRanges, complexCodePathRangesCount, c, keyExtractorUChar);
- // Exact matches are complex
- if (*boundingCharacter == c)
- return Complex;
- bool isEndOfRange = ((boundingCharacter - complexCodePathRanges) % 2);
- if (*boundingCharacter < c) {
- // Determine if we are in a range or out
- if (!isEndOfRange)
- return Complex;
- continue;
+ if (nextFontData != fontData) {
+#if ENABLE(SVG_FONTS)
+ if (renderingContext && fontData->isSVGFont())
+ renderingContext->drawSVGGlyphs(context, runInfo.run, fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, startPoint);
+ else
+#endif
+ drawGlyphs(context, fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, startPoint, runInfo.bounds);
+
+ lastFrom = nextGlyph;
+ fontData = nextFontData;
+ startPoint = nextPoint;
}
- ASSERT(*boundingCharacter > c);
- // Determine if we are in a range or out - opposite condition to above
- if (isEndOfRange)
- return Complex;
+ nextPoint += glyphBuffer.advanceAt(nextGlyph);
+ nextGlyph++;
}
- return result;
+#if ENABLE(SVG_FONTS)
+ if (renderingContext && fontData->isSVGFont())
+ renderingContext->drawSVGGlyphs(context, runInfo.run, fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, startPoint);
+ else
+#endif
+ drawGlyphs(context, fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, startPoint, runInfo.bounds);
}
-bool Font::isCJKIdeograph(UChar32 c)
-{
- static const UChar32 cjkIdeographRanges[] = {
- // CJK Radicals Supplement and Kangxi Radicals.
- 0x2E80, 0x2FDF,
- // CJK Strokes.
- 0x31C0, 0x31EF,
- // CJK Unified Ideographs Extension A.
- 0x3400, 0x4DBF,
- // The basic CJK Unified Ideographs block.
- 0x4E00, 0x9FFF,
- // CJK Compatibility Ideographs.
- 0xF900, 0xFAFF,
- // CJK Unified Ideographs Extension B.
- 0x20000, 0x2A6DF,
- // CJK Unified Ideographs Extension C.
- // CJK Unified Ideographs Extension D.
- 0x2A700, 0x2B81F,
- // CJK Compatibility Ideographs Supplement.
- 0x2F800, 0x2FA1F
- };
- static size_t cjkIdeographRangesCount = WTF_ARRAY_LENGTH(cjkIdeographRanges);
-
- // Early out
- if (c < cjkIdeographRanges[0] || c > cjkIdeographRanges[cjkIdeographRangesCount - 1])
- return false;
+inline static float offsetToMiddleOfGlyph(const SimpleFontData* fontData, Glyph glyph)
+{
+ if (fontData->platformData().orientation() == Horizontal) {
+ FloatRect bounds = fontData->boundsForGlyph(glyph);
+ return bounds.x() + bounds.width() / 2;
+ }
+ // FIXME: Use glyph bounds once they make sense for vertical fonts.
+ return fontData->widthForGlyph(glyph) / 2;
+}
- UChar32* boundingCharacter = approximateBinarySearch<UChar32, UChar32>(
- (UChar32*)cjkIdeographRanges, cjkIdeographRangesCount, c, keyExtractorUChar32);
- // Exact matches are CJK
- if (*boundingCharacter == c)
- return true;
- bool isEndOfRange = ((boundingCharacter - cjkIdeographRanges) % 2);
- if (*boundingCharacter < c)
- return !isEndOfRange;
- return isEndOfRange;
+inline static float offsetToMiddleOfAdvanceAtIndex(const GlyphBuffer& glyphBuffer, size_t i)
+{
+ return glyphBuffer.advanceAt(i).width() / 2;
}
-bool Font::isCJKIdeographOrSymbol(UChar32 c)
+void Font::drawEmphasisMarks(GraphicsContext* context, const TextRunPaintInfo& runInfo, const GlyphBuffer& glyphBuffer, const AtomicString& mark, const FloatPoint& point) const
{
- // Likely common case
- if (c < 0x2C7)
- return false;
+ FontCachePurgePreventer purgePreventer;
+
+ GlyphData markGlyphData;
+ if (!getEmphasisMarkGlyphData(mark, markGlyphData))
+ return;
+
+ const SimpleFontData* markFontData = markGlyphData.fontData;
+ ASSERT(markFontData);
+ if (!markFontData)
+ return;
+
+ Glyph markGlyph = markGlyphData.glyph;
+ Glyph spaceGlyph = markFontData->spaceGlyph();
- // Hash lookup for isolated symbols (those not part of a contiguous range)
- static HashSet<UChar32>* cjkIsolatedSymbols = 0;
- if (!cjkIsolatedSymbols) {
- cjkIsolatedSymbols = new HashSet<UChar32>();
- for (size_t i = 0; i < WTF_ARRAY_LENGTH(cjkIsolatedSymbolsArray); ++i)
- cjkIsolatedSymbols->add(cjkIsolatedSymbolsArray[i]);
+ float middleOfLastGlyph = offsetToMiddleOfAdvanceAtIndex(glyphBuffer, 0);
+ FloatPoint startPoint(point.x() + middleOfLastGlyph - offsetToMiddleOfGlyph(markFontData, markGlyph), point.y());
+
+ GlyphBuffer markBuffer;
+ for (unsigned i = 0; i + 1 < glyphBuffer.size(); ++i) {
+ float middleOfNextGlyph = offsetToMiddleOfAdvanceAtIndex(glyphBuffer, i + 1);
+ float advance = glyphBuffer.advanceAt(i).width() - middleOfLastGlyph + middleOfNextGlyph;
+ markBuffer.add(glyphBuffer.glyphAt(i) ? markGlyph : spaceGlyph, markFontData, advance);
+ middleOfLastGlyph = middleOfNextGlyph;
}
- if (cjkIsolatedSymbols->contains(c))
- return true;
+ markBuffer.add(glyphBuffer.glyphAt(glyphBuffer.size() - 1) ? markGlyph : spaceGlyph, markFontData, 0);
- if (isCJKIdeograph(c))
- return true;
+ drawGlyphBuffer(context, runInfo, markBuffer, startPoint);
+}
- static const UChar32 cjkSymbolRanges[] = {
- 0x2156, 0x215A,
- 0x2160, 0x216B,
- 0x2170, 0x217B,
- 0x23BE, 0x23CC,
- 0x2460, 0x2492,
- 0x249C, 0x24FF,
- 0x25CE, 0x25D3,
- 0x25E2, 0x25E6,
- 0x2600, 0x2603,
- 0x2660, 0x266F,
- 0x2672, 0x267D,
- 0x2776, 0x277F,
- // Ideographic Description Characters, with CJK Symbols and Punctuation, excluding 0x3030.
- // Then Hiragana 0x3040 .. 0x309F, Katakana 0x30A0 .. 0x30FF, Bopomofo 0x3100 .. 0x312F
- 0x2FF0, 0x302F,
- 0x3031, 0x312F,
- // More Bopomofo and Bopomofo Extended 0x31A0 .. 0x31BF
- 0x3190, 0x31BF,
- // Enclosed CJK Letters and Months (0x3200 .. 0x32FF).
- // CJK Compatibility (0x3300 .. 0x33FF).
- 0x3200, 0x33FF,
- 0xF860, 0xF862,
- // CJK Compatibility Forms.
- 0xFE30, 0xFE4F,
- // Halfwidth and Fullwidth Forms
- // Usually only used in CJK
- 0xFF00, 0xFF0C,
- 0xFF0E, 0xFF1A,
- 0xFF1F, 0xFFEF,
- // Emoji.
- 0x1F110, 0x1F129,
- 0x1F130, 0x1F149,
- 0x1F150, 0x1F169,
- 0x1F170, 0x1F189,
- 0x1F200, 0x1F6FF
- };
- static size_t cjkSymbolRangesCount = WTF_ARRAY_LENGTH(cjkSymbolRanges);
-
- UChar32* boundingCharacter = approximateBinarySearch<UChar32, UChar32>(
- (UChar32*)cjkSymbolRanges, cjkSymbolRangesCount, c, keyExtractorUChar32);
- // Exact matches are CJK Symbols
- if (*boundingCharacter == c)
- return true;
- bool isEndOfRange = ((boundingCharacter - cjkSymbolRanges) % 2);
- if (*boundingCharacter < c)
- return !isEndOfRange;
- return isEndOfRange;
-}
-
-unsigned Font::expansionOpportunityCount(const LChar* characters, size_t length, TextDirection direction, bool& isAfterExpansion)
-{
- unsigned count = 0;
- if (direction == LTR) {
- for (size_t i = 0; i < length; ++i) {
- if (treatAsSpace(characters[i])) {
- count++;
- isAfterExpansion = true;
- } else
- isAfterExpansion = false;
- }
- } else {
- for (size_t i = length; i > 0; --i) {
- if (treatAsSpace(characters[i - 1])) {
- count++;
- isAfterExpansion = true;
- } else
- isAfterExpansion = false;
- }
+float Font::floatWidthForSimpleText(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts, IntRectExtent* glyphBounds) const
+{
+ WidthIterator it(this, run, fallbackFonts, glyphBounds);
+ GlyphBuffer glyphBuffer;
+ it.advance(run.length(), (fontDescription().typesettingFeatures() & (Kerning | Ligatures)) ? &glyphBuffer : 0);
+
+ if (glyphBounds) {
+ glyphBounds->setTop(floorf(-it.minGlyphBoundingBoxY()));
+ glyphBounds->setBottom(ceilf(it.maxGlyphBoundingBoxY()));
+ glyphBounds->setLeft(floorf(it.firstGlyphOverflow()));
+ glyphBounds->setRight(ceilf(it.lastGlyphOverflow()));
}
- return count;
+
+ return it.m_runWidthSoFar;
}
-unsigned Font::expansionOpportunityCount(const UChar* characters, size_t length, TextDirection direction, bool& isAfterExpansion)
+FloatRect Font::pixelSnappedSelectionRect(float fromX, float toX, float y, float height)
{
- static bool expandAroundIdeographs = canExpandAroundIdeographsInComplexText();
- unsigned count = 0;
- if (direction == LTR) {
- for (size_t i = 0; i < length; ++i) {
- UChar32 character = characters[i];
- if (treatAsSpace(character)) {
- count++;
- isAfterExpansion = true;
- continue;
- }
- if (U16_IS_LEAD(character) && i + 1 < length && U16_IS_TRAIL(characters[i + 1])) {
- character = U16_GET_SUPPLEMENTARY(character, characters[i + 1]);
- i++;
- }
- if (expandAroundIdeographs && isCJKIdeographOrSymbol(character)) {
- if (!isAfterExpansion)
- count++;
- count++;
- isAfterExpansion = true;
- continue;
+ // Using roundf() rather than ceilf() for the right edge as a compromise to
+ // ensure correct caret positioning.
+ // Use LayoutUnit::epsilon() to ensure that values that cannot be stored as
+ // an integer are floored to n and not n-1 due to floating point imprecision.
+ float pixelAlignedX = floorf(fromX + LayoutUnit::epsilon());
+ return FloatRect(pixelAlignedX, y, roundf(toX) - pixelAlignedX, height);
+}
+
+FloatRect Font::selectionRectForSimpleText(const TextRun& run, const FloatPoint& point, int h, int from, int to, bool accountForGlyphBounds) const
+{
+ GlyphBuffer glyphBuffer;
+ WidthIterator it(this, run, 0, accountForGlyphBounds);
+ it.advance(from, &glyphBuffer);
+ float fromX = it.m_runWidthSoFar;
+ it.advance(to, &glyphBuffer);
+ float toX = it.m_runWidthSoFar;
+
+ if (run.rtl()) {
+ it.advance(run.length(), &glyphBuffer);
+ float totalWidth = it.m_runWidthSoFar;
+ float beforeWidth = fromX;
+ float afterWidth = toX;
+ fromX = totalWidth - afterWidth;
+ toX = totalWidth - beforeWidth;
+ }
+
+ return pixelSnappedSelectionRect(point.x() + fromX, point.x() + toX,
+ accountForGlyphBounds ? it.minGlyphBoundingBoxY() : point.y(),
+ accountForGlyphBounds ? it.maxGlyphBoundingBoxY() - it.minGlyphBoundingBoxY() : h);
+}
+
+int Font::offsetForPositionForSimpleText(const TextRun& run, float x, bool includePartialGlyphs) const
+{
+ float delta = x;
+
+ WidthIterator it(this, run);
+ GlyphBuffer localGlyphBuffer;
+ unsigned offset;
+ if (run.rtl()) {
+ delta -= floatWidthForSimpleText(run);
+ while (1) {
+ offset = it.m_currentCharacter;
+ float w;
+ if (!it.advanceOneCharacter(w, localGlyphBuffer))
+ break;
+ delta += w;
+ if (includePartialGlyphs) {
+ if (delta - w / 2 >= 0)
+ break;
+ } else {
+ if (delta >= 0)
+ break;
}
- isAfterExpansion = false;
}
} else {
- for (size_t i = length; i > 0; --i) {
- UChar32 character = characters[i - 1];
- if (treatAsSpace(character)) {
- count++;
- isAfterExpansion = true;
- continue;
- }
- if (U16_IS_TRAIL(character) && i > 1 && U16_IS_LEAD(characters[i - 2])) {
- character = U16_GET_SUPPLEMENTARY(characters[i - 2], character);
- i--;
+ while (1) {
+ offset = it.m_currentCharacter;
+ float w;
+ if (!it.advanceOneCharacter(w, localGlyphBuffer))
+ break;
+ delta -= w;
+ if (includePartialGlyphs) {
+ if (delta + w / 2 <= 0)
+ break;
+ } else {
+ if (delta <= 0)
+ break;
}
- if (expandAroundIdeographs && isCJKIdeographOrSymbol(character)) {
- if (!isAfterExpansion)
- count++;
- count++;
- isAfterExpansion = true;
- continue;
- }
- isAfterExpansion = false;
}
}
- return count;
-}
-
-bool Font::canReceiveTextEmphasis(UChar32 c)
-{
- CharCategory category = Unicode::category(c);
- if (category & (Separator_Space | Separator_Line | Separator_Paragraph | Other_NotAssigned | Other_Control | Other_Format))
- return false;
-
- // Additional word-separator characters listed in CSS Text Level 3 Editor's Draft 3 November 2010.
- if (c == ethiopicWordspace || c == aegeanWordSeparatorLine || c == aegeanWordSeparatorDot
- || c == ugariticWordDivider || c == tibetanMarkIntersyllabicTsheg || c == tibetanMarkDelimiterTshegBstar)
- return false;
- return true;
-}
-
-void Font::willUseFontData() const
-{
- const FontFamily& family = fontDescription().family();
- if (m_fontFallbackList && m_fontFallbackList->fontSelector() && !family.familyIsEmpty())
- m_fontFallbackList->fontSelector()->willUseFontData(fontDescription(), family.family());
+ return offset;
}
}
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/Font.h b/chromium/third_party/WebKit/Source/platform/fonts/Font.h
index 1e1e4961746..5396ffb6d59 100644
--- a/chromium/third_party/WebKit/Source/platform/fonts/Font.h
+++ b/chromium/third_party/WebKit/Source/platform/fonts/Font.h
@@ -29,8 +29,8 @@
#include "platform/fonts/FontDescription.h"
#include "platform/fonts/FontFallbackList.h"
#include "platform/fonts/SimpleFontData.h"
-#include "platform/fonts/TypesettingFeatures.h"
#include "platform/text/TextDirection.h"
+#include "platform/text/TextPath.h"
#include "wtf/HashMap.h"
#include "wtf/HashSet.h"
#include "wtf/MathExtras.h"
@@ -52,7 +52,6 @@ class FontPlatformData;
class FontSelector;
class GlyphBuffer;
class GraphicsContext;
-class TextLayout;
class TextRun;
struct TextRunPaintInfo;
@@ -79,9 +78,7 @@ struct GlyphOverflow {
class PLATFORM_EXPORT Font {
public:
Font();
- Font(const FontDescription&, float letterSpacing, float wordSpacing);
- // This constructor is only used if the platform wants to start with a native font.
- Font(const FontPlatformData&, bool isPrinting, FontSmoothingMode = AutoSmoothing);
+ Font(const FontDescription&);
~Font();
Font(const Font&);
@@ -92,48 +89,23 @@ public:
const FontDescription& fontDescription() const { return m_fontDescription; }
- int pixelSize() const { return fontDescription().computedPixelSize(); }
- float size() const { return fontDescription().computedSize(); }
-
- void update(PassRefPtr<FontSelector>) const;
+ void update(PassRefPtrWillBeRawPtr<FontSelector>) const;
enum CustomFontNotReadyAction { DoNotPaintIfFontNotReady, UseFallbackIfFontNotReady };
void drawText(GraphicsContext*, const TextRunPaintInfo&, const FloatPoint&, CustomFontNotReadyAction = DoNotPaintIfFontNotReady) const;
void drawEmphasisMarks(GraphicsContext*, const TextRunPaintInfo&, const AtomicString& mark, const FloatPoint&) const;
float width(const TextRun&, HashSet<const SimpleFontData*>* fallbackFonts = 0, GlyphOverflow* = 0) const;
- float width(const TextRun&, int& charsConsumed, String& glyphName) const;
-
- PassOwnPtr<TextLayout> createLayoutForMacComplexText(const TextRun&, unsigned textLength, float xPos, bool collapseWhiteSpace) const;
- static void deleteLayout(TextLayout*);
- static float width(TextLayout&, unsigned from, unsigned len, HashSet<const SimpleFontData*>* fallbackFonts = 0);
+ float width(const TextRun&, int& charsConsumed, Glyph& glyphId) const;
int offsetForPosition(const TextRun&, float position, bool includePartialGlyphs) const;
- FloatRect selectionRectForText(const TextRun&, const FloatPoint&, int h, int from = 0, int to = -1) const;
+ FloatRect selectionRectForText(const TextRun&, const FloatPoint&, int h, int from = 0, int to = -1, bool accountForGlyphBounds = false) const;
- bool isSmallCaps() const { return m_fontDescription.smallCaps(); }
-
- float wordSpacing() const { return m_wordSpacing; }
- float letterSpacing() const { return m_letterSpacing; }
- void setWordSpacing(float s) { m_wordSpacing = s; }
- void setLetterSpacing(float s) { m_letterSpacing = s; }
bool isFixedPitch() const;
- bool isPrinterFont() const { return m_fontDescription.usePrinterFont(); }
-
- TypesettingFeatures typesettingFeatures() const { return static_cast<TypesettingFeatures>(m_typesettingFeatures); }
-
- FontFamily& firstFamily() { return m_fontDescription.firstFamily(); }
- const FontFamily& family() const { return m_fontDescription.family(); }
-
- FontItalic italic() const { return m_fontDescription.italic(); }
- FontWeight weight() const { return m_fontDescription.weight(); }
- FontWidthVariant widthVariant() const { return m_fontDescription.widthVariant(); }
-
- bool isPlatformFont() const { return m_isPlatformFont; }
// Metrics that we query the FontFallbackList for.
const FontMetrics& fontMetrics() const { return primaryFont()->fontMetrics(); }
- float spaceWidth() const { return primaryFont()->spaceWidth() + m_letterSpacing; }
+ float spaceWidth() const { return primaryFont()->spaceWidth() + fontDescription().letterSpacing(); }
float tabWidth(const SimpleFontData&, unsigned tabSize, float position) const;
float tabWidth(unsigned tabSize, float position) const { return tabWidth(*primaryFont(), tabSize, position); }
@@ -153,44 +125,29 @@ public:
std::pair<GlyphData, GlyphPage*> glyphDataAndPageForCharacter(UChar32, bool mirror, FontDataVariant = AutoVariant) const;
bool primaryFontHasGlyphForCharacter(UChar32) const;
- static bool isCJKIdeograph(UChar32);
- static bool isCJKIdeographOrSymbol(UChar32);
-
- static unsigned expansionOpportunityCount(const LChar*, size_t length, TextDirection, bool& isAfterExpansion);
- static unsigned expansionOpportunityCount(const UChar*, size_t length, TextDirection, bool& isAfterExpansion);
-
- static void setShouldUseSmoothing(bool);
- static bool shouldUseSmoothing();
-
- enum CodePath { Auto, Simple, Complex, SimpleWithGlyphOverflow };
CodePath codePath(const TextRun&) const;
- static CodePath characterRangeCodePath(const LChar*, unsigned) { return Simple; }
- static CodePath characterRangeCodePath(const UChar*, unsigned len);
private:
enum ForTextEmphasisOrNot { NotForTextEmphasis, ForTextEmphasis };
// Returns the initial in-stream advance.
- float getGlyphsAndAdvancesForSimpleText(const TextRun&, int from, int to, GlyphBuffer&, ForTextEmphasisOrNot = NotForTextEmphasis) const;
+ float getGlyphsAndAdvancesForSimpleText(const TextRunPaintInfo&, GlyphBuffer&, ForTextEmphasisOrNot = NotForTextEmphasis) const;
void drawSimpleText(GraphicsContext*, const TextRunPaintInfo&, const FloatPoint&) const;
void drawEmphasisMarksForSimpleText(GraphicsContext*, const TextRunPaintInfo&, const AtomicString& mark, const FloatPoint&) const;
void drawGlyphs(GraphicsContext*, const SimpleFontData*, const GlyphBuffer&, unsigned from, unsigned numGlyphs, const FloatPoint&, const FloatRect& textRect) const;
void drawGlyphBuffer(GraphicsContext*, const TextRunPaintInfo&, const GlyphBuffer&, const FloatPoint&) const;
void drawEmphasisMarks(GraphicsContext*, const TextRunPaintInfo&, const GlyphBuffer&, const AtomicString&, const FloatPoint&) const;
- float floatWidthForSimpleText(const TextRun&, HashSet<const SimpleFontData*>* fallbackFonts = 0, GlyphOverflow* = 0) const;
+ float floatWidthForSimpleText(const TextRun&, HashSet<const SimpleFontData*>* fallbackFonts = 0, IntRectExtent* glyphBounds = 0) const;
int offsetForPositionForSimpleText(const TextRun&, float position, bool includePartialGlyphs) const;
- FloatRect selectionRectForSimpleText(const TextRun&, const FloatPoint&, int h, int from, int to) const;
+ FloatRect selectionRectForSimpleText(const TextRun&, const FloatPoint&, int h, int from, int to, bool accountForGlyphBounds) const;
bool getEmphasisMarkGlyphData(const AtomicString&, GlyphData&) const;
- static bool canReturnFallbackFontsForComplexText();
- static bool canExpandAroundIdeographsInComplexText();
-
// Returns the initial in-stream advance.
- float getGlyphsAndAdvancesForComplexText(const TextRun&, int from, int to, GlyphBuffer&, ForTextEmphasisOrNot = NotForTextEmphasis) const;
+ float getGlyphsAndAdvancesForComplexText(const TextRunPaintInfo&, GlyphBuffer&, ForTextEmphasisOrNot = NotForTextEmphasis) const;
void drawComplexText(GraphicsContext*, const TextRunPaintInfo&, const FloatPoint&) const;
void drawEmphasisMarksForComplexText(GraphicsContext*, const TextRunPaintInfo&, const AtomicString& mark, const FloatPoint&) const;
- float floatWidthForComplexText(const TextRun&, HashSet<const SimpleFontData*>* fallbackFonts = 0, GlyphOverflow* = 0) const;
+ float floatWidthForComplexText(const TextRun&, HashSet<const SimpleFontData*>* fallbackFonts, IntRectExtent* glyphBounds) const;
int offsetForPositionForComplexText(const TextRun&, float position, bool includePartialGlyphs) const;
FloatRect selectionRectForComplexText(const TextRun&, const FloatPoint&, int h, int from, int to) const;
@@ -203,95 +160,26 @@ public:
static CodePath codePath();
static CodePath s_codePath;
- static void setDefaultTypesettingFeatures(TypesettingFeatures);
- static TypesettingFeatures defaultTypesettingFeatures();
-
- static const uint8_t s_roundingHackCharacterTable[256];
- static bool isRoundingHackCharacter(UChar32 c)
- {
- return !(c & ~0xFF) && s_roundingHackCharacterTable[c];
- }
-
FontSelector* fontSelector() const;
- static bool treatAsSpace(UChar c) { return c == ' ' || c == '\t' || c == '\n' || c == noBreakSpace; }
- static bool treatAsZeroWidthSpace(UChar c) { return treatAsZeroWidthSpaceInComplexScript(c) || c == 0x200c || c == 0x200d; }
- static bool treatAsZeroWidthSpaceInComplexScript(UChar c) { return c < 0x20 || (c >= 0x7F && c < 0xA0) || c == softHyphen || c == zeroWidthSpace || (c >= 0x200e && c <= 0x200f) || (c >= 0x202a && c <= 0x202e) || c == zeroWidthNoBreakSpace || c == objectReplacementCharacter; }
- static bool canReceiveTextEmphasis(UChar32 c);
-
- static inline UChar normalizeSpaces(UChar character)
- {
- if (treatAsSpace(character))
- return space;
-
- if (treatAsZeroWidthSpace(character))
- return zeroWidthSpace;
-
- return character;
- }
-
- static String normalizeSpaces(const LChar*, unsigned length);
- static String normalizeSpaces(const UChar*, unsigned length);
FontFallbackList* fontList() const { return m_fontFallbackList.get(); }
- void willUseFontData() const;
+ void willUseFontData(UChar32) const;
+ static FloatRect pixelSnappedSelectionRect(float fromX, float toX, float y, float height);
private:
bool loadingCustomFonts() const
{
return m_fontFallbackList && m_fontFallbackList->loadingCustomFonts();
}
- TypesettingFeatures computeTypesettingFeatures() const
+ bool shouldSkipDrawing() const
{
- TextRenderingMode textRenderingMode = m_fontDescription.textRenderingMode();
- TypesettingFeatures features = s_defaultTypesettingFeatures;
-
- switch (textRenderingMode) {
- case AutoTextRendering:
- break;
- case OptimizeSpeed:
- features &= ~(Kerning | Ligatures);
- break;
- case GeometricPrecision:
- case OptimizeLegibility:
- features |= Kerning | Ligatures;
- break;
- }
-
- switch (m_fontDescription.kerning()) {
- case FontDescription::NoneKerning:
- features &= ~Kerning;
- break;
- case FontDescription::NormalKerning:
- features |= Kerning;
- break;
- case FontDescription::AutoKerning:
- break;
- }
-
- switch (m_fontDescription.commonLigaturesState()) {
- case FontDescription::DisabledLigaturesState:
- features &= ~Ligatures;
- break;
- case FontDescription::EnabledLigaturesState:
- features |= Ligatures;
- break;
- case FontDescription::NormalLigaturesState:
- break;
- }
-
- return features;
+ return m_fontFallbackList && m_fontFallbackList->shouldSkipDrawing();
}
- static TypesettingFeatures s_defaultTypesettingFeatures;
-
FontDescription m_fontDescription;
mutable RefPtr<FontFallbackList> m_fontFallbackList;
- float m_letterSpacing;
- float m_wordSpacing;
- bool m_isPlatformFont;
- mutable unsigned m_typesettingFeatures : 2; // (TypesettingFeatures) Caches values computed from m_fontDescription.
};
inline Font::~Font()
@@ -324,19 +212,11 @@ inline FontSelector* Font::fontSelector() const
inline float Font::tabWidth(const SimpleFontData& fontData, unsigned tabSize, float position) const
{
if (!tabSize)
- return letterSpacing();
- float tabWidth = tabSize * fontData.spaceWidth() + letterSpacing();
+ return fontDescription().letterSpacing();
+ float tabWidth = tabSize * fontData.spaceWidth() + fontDescription().letterSpacing();
return tabWidth - fmodf(position, tabWidth);
}
}
-namespace WTF {
-
-template <> struct PLATFORM_EXPORT OwnedPtrDeleter<WebCore::TextLayout> {
- static void deletePtr(WebCore::TextLayout*);
-};
-
-}
-
#endif
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/FontCache.cpp b/chromium/third_party/WebKit/Source/platform/fonts/FontCache.cpp
index 0e9b22a3b3f..f988027dd63 100644
--- a/chromium/third_party/WebKit/Source/platform/fonts/FontCache.cpp
+++ b/chromium/third_party/WebKit/Source/platform/fonts/FontCache.cpp
@@ -30,16 +30,16 @@
#include "config.h"
#include "platform/fonts/FontCache.h"
-#include "FontFamilyNames.h"
+#include "platform/FontFamilyNames.h"
-#include "RuntimeEnabledFeatures.h"
+#include "platform/RuntimeEnabledFeatures.h"
#include "platform/fonts/AlternateFontFamily.h"
+#include "platform/fonts/FontCacheClient.h"
#include "platform/fonts/FontCacheKey.h"
#include "platform/fonts/FontDataCache.h"
#include "platform/fonts/FontDescription.h"
#include "platform/fonts/FontFallbackList.h"
#include "platform/fonts/FontPlatformData.h"
-#include "platform/fonts/FontSelector.h"
#include "platform/fonts/FontSmoothingMode.h"
#include "platform/fonts/TextRenderingMode.h"
#include "platform/fonts/opentype/OpenTypeVerticalData.h"
@@ -53,17 +53,23 @@ using namespace WTF;
namespace WebCore {
-#if !OS(WIN) || ENABLE(GDI_FONTS_ON_WINDOWS)
+#if !OS(WIN)
FontCache::FontCache()
: m_purgePreventCount(0)
{
}
-#endif // !OS(WIN) || ENABLE(GDI_FONTS_ON_WINDOWS)
+#endif // !OS(WIN)
typedef HashMap<FontCacheKey, OwnPtr<FontPlatformData>, FontCacheKeyHash, FontCacheKeyTraits> FontPlatformDataCache;
static FontPlatformDataCache* gFontPlatformDataCache = 0;
+#if OS(WIN)
+bool FontCache::s_useDirectWrite = false;
+IDWriteFactory* FontCache::s_directWriteFactory = 0;
+bool FontCache::s_useSubpixelPositioning = false;
+#endif // OS(WIN)
+
FontCache* FontCache::fontCache()
{
DEFINE_STATIC_LOCAL(FontCache, globalFontCache, ());
@@ -145,7 +151,7 @@ PassRefPtr<SimpleFontData> FontCache::getFontData(const FontDescription& fontDes
if (FontPlatformData* platformData = getFontPlatformData(fontDescription, adjustFamilyNameToAvoidUnsupportedFonts(family), checkingAlternateName))
return fontDataFromFontPlatformData(platformData, shouldRetain);
- return 0;
+ return nullptr;
}
PassRefPtr<SimpleFontData> FontCache::fontDataFromFontPlatformData(const FontPlatformData* platformData, ShouldRetain shouldRetain)
@@ -153,7 +159,7 @@ PassRefPtr<SimpleFontData> FontCache::fontDataFromFontPlatformData(const FontPla
if (!gFontDataCache)
gFontDataCache = new FontDataCache;
-#if !ASSERT_DISABLED
+#if ASSERT_ENABLED
if (shouldRetain == DoNotRetain)
ASSERT(m_purgePreventCount);
#endif
@@ -164,7 +170,7 @@ PassRefPtr<SimpleFontData> FontCache::fontDataFromFontPlatformData(const FontPla
bool FontCache::isPlatformFontAvailable(const FontDescription& fontDescription, const AtomicString& family)
{
bool checkingAlternateName = true;
- return getFontPlatformData(fontDescription, family, checkingAlternateName);
+ return getFontPlatformData(fontDescription, adjustFamilyNameToAvoidUnsupportedFonts(family), checkingAlternateName);
}
SimpleFontData* FontCache::getNonRetainedLastResortFallbackFont(const FontDescription& fontDescription)
@@ -191,10 +197,7 @@ static inline void purgePlatformFontDataCache()
if (platformData->value && !gFontDataCache->contains(platformData->value.get()))
keysToRemove.append(platformData->key);
}
-
- size_t keysToRemoveCount = keysToRemove.size();
- for (size_t i = 0; i < keysToRemoveCount; ++i)
- gFontPlatformDataCache->remove(keysToRemove[i]);
+ gFontPlatformDataCache->removeAll(keysToRemove);
}
static inline void purgeFontVerticalDataCache()
@@ -217,8 +220,7 @@ static inline void purgeFontVerticalDataCache()
if (!verticalData->value || !verticalData->value->inFontCache())
keysToRemove.append(verticalData->key);
}
- for (size_t i = 0, count = keysToRemove.size(); i < count; ++i)
- fontVerticalDataCache.take(keysToRemove[i]);
+ fontVerticalDataCache.removeAll(keysToRemove);
}
#endif
}
@@ -237,24 +239,32 @@ void FontCache::purge(PurgeSeverity PurgeSeverity)
purgeFontVerticalDataCache();
}
-static HashSet<FontSelector*>* gClients;
+static bool invalidateFontCache = false;
-void FontCache::addClient(FontSelector* client)
+WillBeHeapHashSet<RawPtrWillBeWeakMember<FontCacheClient> >& fontCacheClients()
{
- if (!gClients)
- gClients = new HashSet<FontSelector*>;
-
- ASSERT(!gClients->contains(client));
- gClients->add(client);
+#if ENABLE(OILPAN)
+ DEFINE_STATIC_LOCAL(Persistent<HeapHashSet<WeakMember<FontCacheClient> > >, clients, (new HeapHashSet<WeakMember<FontCacheClient> >()));
+#else
+ DEFINE_STATIC_LOCAL(HashSet<RawPtr<FontCacheClient> >*, clients, (new HashSet<RawPtr<FontCacheClient> >()));
+#endif
+ invalidateFontCache = true;
+ return *clients;
}
-void FontCache::removeClient(FontSelector* client)
+void FontCache::addClient(FontCacheClient* client)
{
- ASSERT(gClients);
- ASSERT(gClients->contains(client));
+ ASSERT(!fontCacheClients().contains(client));
+ fontCacheClients().add(client);
+}
- gClients->remove(client);
+#if !ENABLE(OILPAN)
+void FontCache::removeClient(FontCacheClient* client)
+{
+ ASSERT(fontCacheClients().contains(client));
+ fontCacheClients().remove(client);
}
+#endif
static unsigned short gGeneration = 0;
@@ -265,7 +275,7 @@ unsigned short FontCache::generation()
void FontCache::invalidate()
{
- if (!gClients) {
+ if (!invalidateFontCache) {
ASSERT(!gFontPlatformDataCache);
return;
}
@@ -277,11 +287,11 @@ void FontCache::invalidate()
gGeneration++;
- Vector<RefPtr<FontSelector> > clients;
- size_t numClients = gClients->size();
+ WillBeHeapVector<RefPtrWillBeMember<FontCacheClient> > clients;
+ size_t numClients = fontCacheClients().size();
clients.reserveInitialCapacity(numClients);
- HashSet<FontSelector*>::iterator end = gClients->end();
- for (HashSet<FontSelector*>::iterator it = gClients->begin(); it != end; ++it)
+ WillBeHeapHashSet<RawPtrWillBeWeakMember<FontCacheClient> >::iterator end = fontCacheClients().end();
+ for (WillBeHeapHashSet<RawPtrWillBeWeakMember<FontCacheClient> >::iterator it = fontCacheClients().begin(); it != end; ++it)
clients.append(*it);
ASSERT(numClients == clients.size());
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/FontCache.h b/chromium/third_party/WebKit/Source/platform/fonts/FontCache.h
index 4fcfb3fd234..0aef86a8dbc 100644
--- a/chromium/third_party/WebKit/Source/platform/fonts/FontCache.h
+++ b/chromium/third_party/WebKit/Source/platform/fonts/FontCache.h
@@ -33,6 +33,7 @@
#include <limits.h>
#include "platform/PlatformExport.h"
#include "wtf/Forward.h"
+#include "wtf/HashMap.h"
#include "wtf/PassRefPtr.h"
#include "wtf/RefPtr.h"
#include "wtf/Vector.h"
@@ -41,23 +42,25 @@
#include "wtf/unicode/Unicode.h"
#if OS(WIN)
+#include "SkFontMgr.h"
#include <windows.h>
#include <objidl.h>
#include <mlang.h>
+struct IDWriteFactory;
#endif
-#if OS(WIN) && !ENABLE(GDI_FONTS_ON_WINDOWS)
-#include "SkFontMgr.h"
+#if OS(ANDROID)
+#include <unicode/uscript.h>
#endif
class SkTypeface;
namespace WebCore {
+class FontCacheClient;
class FontPlatformData;
class FontData;
class FontDescription;
-class FontSelector;
class OpenTypeVerticalData;
class SimpleFontData;
@@ -75,7 +78,7 @@ public:
// This method is implemented by the plaform and used by
// FontFastPath to lookup the font for a given character.
- PassRefPtr<SimpleFontData> platformFallbackForCharacter(const FontDescription&, UChar32, const SimpleFontData* fontDataToSubstitute, bool disallowSynthetics);
+ PassRefPtr<SimpleFontData> fallbackFontForCharacter(const FontDescription&, UChar32, const SimpleFontData* fontDataToSubstitute);
// Also implemented by the platform.
void platformInit();
@@ -85,8 +88,10 @@ public:
SimpleFontData* getNonRetainedLastResortFallbackFont(const FontDescription&);
bool isPlatformFontAvailable(const FontDescription&, const AtomicString&);
- void addClient(FontSelector*);
- void removeClient(FontSelector*);
+ void addClient(FontCacheClient*);
+#if !ENABLE(OILPAN)
+ void removeClient(FontCacheClient*);
+#endif
unsigned short generation();
void invalidate();
@@ -95,9 +100,14 @@ public:
PassRefPtr<SimpleFontData> fontDataFromDescriptionAndLogFont(const FontDescription&, ShouldRetain, const LOGFONT&, wchar_t* outFontFamilyName);
#endif
-#if OS(WIN) && !ENABLE(GDI_FONTS_ON_WINDOWS)
- bool useSubpixelPositioning() const { return m_useSubpixelPositioning; }
+#if OS(WIN)
+ bool useSubpixelPositioning() const { return s_useSubpixelPositioning; }
SkFontMgr* fontManager() { return m_fontManager.get(); }
+ static bool useDirectWrite() { return s_useDirectWrite; }
+ static void setUseDirectWrite(bool useDirectWrite) { s_useDirectWrite = useDirectWrite; }
+ static void setDirectWriteFactory(IDWriteFactory* factory) { s_directWriteFactory = factory; }
+ static void setUseSubpixelPositioning(bool useSubpixelPositioning) { s_useSubpixelPositioning = useSubpixelPositioning; }
+ static void addSideloadedFontForTesting(SkTypeface*);
#endif
#if ENABLE(OPENTYPE_VERTICAL)
@@ -108,12 +118,14 @@ public:
#if OS(ANDROID)
static AtomicString getGenericFamilyNameForScript(const AtomicString& familyName, UScriptCode);
#else
- struct SimpleFontFamily {
+ struct PlatformFallbackFont {
String name;
+ CString filename;
+ int ttcIndex;
bool isBold;
bool isItalic;
};
- static void getFontFamilyForCharacter(UChar32, const char* preferredLocale, SimpleFontFamily*);
+ static void getFontForCharacter(UChar32, const char* preferredLocale, PlatformFallbackFont*);
#endif
private:
@@ -144,9 +156,12 @@ private:
// Don't purge if this count is > 0;
int m_purgePreventCount;
-#if OS(WIN) && !ENABLE(GDI_FONTS_ON_WINDOWS)
+#if OS(WIN)
OwnPtr<SkFontMgr> m_fontManager;
- bool m_useSubpixelPositioning;
+ static bool s_useDirectWrite;
+ static IDWriteFactory* s_directWriteFactory;
+ static bool s_useSubpixelPositioning;
+ static HashMap<String, SkTypeface*>* s_sideloadedFonts;
#endif
#if OS(MACOSX) || OS(ANDROID)
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/skia/SkiaFontWin.h b/chromium/third_party/WebKit/Source/platform/fonts/FontCacheClient.h
index 977e6c022f6..2ee8682fc93 100644
--- a/chromium/third_party/WebKit/Source/platform/fonts/skia/SkiaFontWin.h
+++ b/chromium/third_party/WebKit/Source/platform/fonts/FontCacheClient.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, Google Inc. All rights reserved.
+ * Copyright (C) 2014 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -28,47 +28,23 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef SkiaFontWin_h
-#define SkiaFontWin_h
+#ifndef FontCacheClient_h
+#define FontCacheClient_h
-#include <windows.h>
-#include <usp10.h>
-
-struct SkPoint;
-struct SkRect;
+#include "platform/PlatformExport.h"
+#include "platform/heap/Handle.h"
+#include "wtf/RefCounted.h"
namespace WebCore {
-class FontPlatformData;
-class GraphicsContext;
-
-// Note that the offsets parameter is optional. If not null it represents a
-// per glyph offset (such as returned by ScriptPlace Windows API function).
-void paintSkiaText(GraphicsContext*,
- const FontPlatformData&,
- unsigned numGlyphs,
- const WORD* glyphs,
- const int* advances,
- const GOFFSET* offsets,
- const SkPoint& origin,
- const SkRect& textRect);
+class PLATFORM_EXPORT FontCacheClient : public RefCountedWillBeGarbageCollectedFinalized<FontCacheClient> {
+public:
+ virtual ~FontCacheClient() { }
-#if !USE(HARFBUZZ)
-// Note that the offsets parameter is optional. If not null it represents a
-// per glyph offset (such as returned by ScriptPlace Windows API function).
-// Note: this is less efficient than calling the version with FontPlatformData,
-// as that caches the SkTypeface object.
-void paintSkiaText(GraphicsContext*,
- const FontPlatformData&,
- HFONT,
- unsigned numGlyphs,
- const WORD* glyphs,
- const int* advances,
- const GOFFSET* offsets,
- const SkPoint& origin,
- const SkRect& textRect);
-#endif
+ virtual void fontCacheInvalidated() = 0;
+ virtual void trace(Visitor*) { }
+};
-} // namespace WebCore
+} // namespace WebCore
-#endif // SkiaFontWin_h
+#endif // FontCacheClient_h
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/FontCacheTest.cpp b/chromium/third_party/WebKit/Source/platform/fonts/FontCacheTest.cpp
new file mode 100644
index 00000000000..27fb1487fb6
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/platform/fonts/FontCacheTest.cpp
@@ -0,0 +1,46 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "config.h"
+#include "platform/fonts/FontCache.h"
+
+#include "platform/fonts/FontDescription.h"
+#include "platform/fonts/SimpleFontData.h"
+#include "public/platform/Platform.h"
+#include <gtest/gtest.h>
+
+namespace WebCore {
+
+class EmptyPlatform : public blink::Platform {
+public:
+ EmptyPlatform() { }
+ virtual ~EmptyPlatform() { }
+ virtual void cryptographicallyRandomValues(unsigned char* buffer, size_t length) OVERRIDE { }
+};
+
+TEST(FontCache, getLastResortFallbackFont)
+{
+ FontCache* fontCache = FontCache::fontCache();
+ ASSERT_TRUE(fontCache);
+
+ blink::Platform* oldPlatform = blink::Platform::current();
+ OwnPtr<EmptyPlatform> platform = adoptPtr(new EmptyPlatform);
+ blink::Platform::initialize(platform.get());
+
+ if (emptyAtom.isNull())
+ AtomicString::init();
+
+ FontDescription fontDescription;
+ fontDescription.setGenericFamily(FontDescription::StandardFamily);
+ RefPtr<SimpleFontData> fontData = fontCache->getLastResortFallbackFont(fontDescription, Retain);
+ EXPECT_TRUE(fontData);
+
+ fontDescription.setGenericFamily(FontDescription::SansSerifFamily);
+ fontData = fontCache->getLastResortFallbackFont(fontDescription, Retain);
+ EXPECT_TRUE(fontData);
+
+ blink::Platform::initialize(oldPlatform);
+}
+
+} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/FontCustomPlatformData.h b/chromium/third_party/WebKit/Source/platform/fonts/FontCustomPlatformData.h
index ae7d6b2ba9d..f11c2901261 100644
--- a/chromium/third_party/WebKit/Source/platform/fonts/FontCustomPlatformData.h
+++ b/chromium/third_party/WebKit/Source/platform/fonts/FontCustomPlatformData.h
@@ -37,22 +37,16 @@
#include "platform/fonts/FontWidthVariant.h"
#include "wtf/Forward.h"
#include "wtf/Noncopyable.h"
+#include "wtf/RefPtr.h"
#include "wtf/text/WTFString.h"
-#if OS(WIN) && ENABLE(GDI_FONTS_ON_WINDOWS)
-#include <windows.h>
-#endif
-
#if OS(MACOSX)
#include "wtf/RetainPtr.h"
#include <CoreFoundation/CFBase.h>
typedef struct CGFont* CGFontRef;
#endif
-#if OS(MACOSX) || OS(POSIX) || (OS(WIN) && !ENABLE(GDI_FONTS_ON_WINDOWS))
-#include "wtf/RefPtr.h"
class SkTypeface;
-#endif
namespace WebCore {
@@ -70,18 +64,13 @@ public:
static bool supportsFormat(const String&);
private:
-#if OS(WIN) && ENABLE(GDI_FONTS_ON_WINDOWS)
- FontCustomPlatformData(HANDLE fontReference, const String& name);
- HANDLE m_fontReference;
- String m_name;
-#elif OS(MACOSX)
+#if OS(MACOSX)
explicit FontCustomPlatformData(CGFontRef, PassRefPtr<SkTypeface>);
RetainPtr<CGFontRef> m_cgFont;
- RefPtr<SkTypeface> m_typeface;
-#elif OS(POSIX) || (OS(WIN) && !ENABLE(GDI_FONTS_ON_WINDOWS))
+#else
explicit FontCustomPlatformData(PassRefPtr<SkTypeface>);
- RefPtr<SkTypeface> m_typeface;
#endif
+ RefPtr<SkTypeface> m_typeface;
};
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/FontData.h b/chromium/third_party/WebKit/Source/platform/fonts/FontData.h
index 003100b3924..fb4a65441cb 100644
--- a/chromium/third_party/WebKit/Source/platform/fonts/FontData.h
+++ b/chromium/third_party/WebKit/Source/platform/fonts/FontData.h
@@ -49,12 +49,12 @@ public:
virtual ~FontData();
virtual const SimpleFontData* fontDataForCharacter(UChar32) const = 0;
- virtual bool containsCharacters(const UChar*, int length) const = 0;
virtual bool isCustomFont() const = 0;
virtual bool isLoading() const = 0;
// Returns whether this is a temporary font data for a custom font which is not yet loaded.
virtual bool isLoadingFallback() const = 0;
virtual bool isSegmented() const = 0;
+ virtual bool shouldSkipDrawing() const = 0;
void setMaxGlyphPageTreeLevel(unsigned level) const { m_maxGlyphPageTreeLevel = level; }
unsigned maxGlyphPageTreeLevel() const { return m_maxGlyphPageTreeLevel; }
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/FontDataCache.cpp b/chromium/third_party/WebKit/Source/platform/fonts/FontDataCache.cpp
index 0f5efe3d45e..5a1e933d380 100644
--- a/chromium/third_party/WebKit/Source/platform/fonts/FontDataCache.cpp
+++ b/chromium/third_party/WebKit/Source/platform/fonts/FontDataCache.cpp
@@ -48,7 +48,7 @@ const unsigned cTargetInactiveFontData = 200;
PassRefPtr<SimpleFontData> FontDataCache::get(const FontPlatformData* platformData, ShouldRetain shouldRetain)
{
if (!platformData)
- return 0;
+ return nullptr;
Cache::iterator result = m_cache.find(*platformData);
if (result == m_cache.end()) {
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/FontDescription.cpp b/chromium/third_party/WebKit/Source/platform/fonts/FontDescription.cpp
index 9f46bf339c2..4f84d9f0cc0 100644
--- a/chromium/third_party/WebKit/Source/platform/fonts/FontDescription.cpp
+++ b/chromium/third_party/WebKit/Source/platform/fonts/FontDescription.cpp
@@ -30,7 +30,7 @@
#include "config.h"
#include "platform/fonts/FontDescription.h"
-#include "RuntimeEnabledFeatures.h"
+#include "platform/RuntimeEnabledFeatures.h"
#include "wtf/text/AtomicStringHash.h"
#include "wtf/text/StringHash.h"
@@ -39,14 +39,17 @@ namespace WebCore {
struct SameSizeAsFontDescription {
FontFamily familyList;
RefPtr<FontFeatureSettings> m_featureSettings;
- float sizes[2];
+ String locale;
+ float sizes[4];
// FXIME: Make them fit into one word.
uint32_t bitfields;
- uint32_t bitfields2 : 8;
+ uint32_t bitfields2 : 7;
};
COMPILE_ASSERT(sizeof(FontDescription) == sizeof(SameSizeAsFontDescription), FontDescription_should_stay_small);
+TypesettingFeatures FontDescription::s_defaultTypesettingFeatures = 0;
+
bool FontDescription::s_useSubpixelTextPositioning = false;
FontWeight FontDescription::lighterWeight(void) const
@@ -93,55 +96,23 @@ FontWeight FontDescription::bolderWeight(void) const
return FontWeightNormal;
}
-FontTraitsMask FontDescription::traitsMask() const
+FontTraits FontDescription::traits() const
{
- return static_cast<FontTraitsMask>((m_italic ? FontStyleItalicMask : FontStyleNormalMask)
- | (m_smallCaps ? FontVariantSmallCapsMask : FontVariantNormalMask)
- | (FontWeight100Mask << (m_weight - FontWeight100)));
-
+ return FontTraits(style(), variant(), weight(), stretch());
}
-void FontDescription::setTraitsMask(FontTraitsMask traitsMask)
+void FontDescription::setTraits(FontTraits traits)
{
- switch (traitsMask & FontWeightMask) {
- case FontWeight100Mask:
- setWeight(FontWeight100);
- break;
- case FontWeight200Mask:
- setWeight(FontWeight200);
- break;
- case FontWeight300Mask:
- setWeight(FontWeight300);
- break;
- case FontWeight400Mask:
- setWeight(FontWeight400);
- break;
- case FontWeight500Mask:
- setWeight(FontWeight500);
- break;
- case FontWeight600Mask:
- setWeight(FontWeight600);
- break;
- case FontWeight700Mask:
- setWeight(FontWeight700);
- break;
- case FontWeight800Mask:
- setWeight(FontWeight800);
- break;
- case FontWeight900Mask:
- setWeight(FontWeight900);
- break;
- default:
- ASSERT_NOT_REACHED();
- }
- setItalic((traitsMask & FontStyleItalicMask) ? FontItalicOn : FontItalicOff);
- setSmallCaps((traitsMask & FontVariantSmallCapsMask) ? FontSmallCapsOn : FontSmallCapsOff);
+ setStyle(traits.style());
+ setVariant(traits.variant());
+ setWeight(traits.weight());
+ setStretch(traits.stretch());
}
FontDescription FontDescription::makeNormalFeatureSettings() const
{
FontDescription normalDescription(*this);
- normalDescription.setFeatureSettings(0);
+ normalDescription.setFeatureSettings(nullptr);
return normalDescription;
}
@@ -156,22 +127,83 @@ float FontDescription::effectiveFontSize() const
return floorf(size * FontCacheKey::precisionMultiplier()) / FontCacheKey::precisionMultiplier();
}
-FontCacheKey FontDescription::cacheKey(const AtomicString& familyName, FontTraitsMask desiredTraits) const
+FontCacheKey FontDescription::cacheKey(const AtomicString& familyName, FontTraits desiredTraits) const
{
- FontTraitsMask traits = desiredTraits
+ FontTraits fontTraits = desiredTraits.mask()
? desiredTraits
- : traitsMask();
+ : traits();
unsigned options =
- static_cast<unsigned>(m_syntheticItalic) << 8 | // bit 9
- static_cast<unsigned>(m_syntheticBold) << 7 | // bit 8
- static_cast<unsigned>(m_fontSmoothing) << 5 | // bits 6-7
- static_cast<unsigned>(m_textRendering) << 3 | // bits 4-5
- static_cast<unsigned>(m_orientation) << 2 | // bit 3
- static_cast<unsigned>(m_usePrinterFont) << 1 | // bit 2
+ static_cast<unsigned>(m_syntheticItalic) << 7 | // bit 8
+ static_cast<unsigned>(m_syntheticBold) << 6 | // bit 7
+ static_cast<unsigned>(m_fontSmoothing) << 4 | // bits 5-6
+ static_cast<unsigned>(m_textRendering) << 2 | // bits 3-4
+ static_cast<unsigned>(m_orientation) << 1 | // bit 2
static_cast<unsigned>(m_subpixelTextPosition); // bit 1
- return FontCacheKey(familyName, effectiveFontSize(), options | traits << 9);
+ return FontCacheKey(familyName, effectiveFontSize(), options | fontTraits.mask() << 8);
+}
+
+
+void FontDescription::setDefaultTypesettingFeatures(TypesettingFeatures typesettingFeatures)
+{
+ s_defaultTypesettingFeatures = typesettingFeatures;
+}
+
+TypesettingFeatures FontDescription::defaultTypesettingFeatures()
+{
+ return s_defaultTypesettingFeatures;
+}
+
+void FontDescription::updateTypesettingFeatures() const
+{
+ m_typesettingFeatures = s_defaultTypesettingFeatures;
+
+ switch (textRendering()) {
+ case AutoTextRendering:
+ break;
+ case OptimizeSpeed:
+ m_typesettingFeatures &= ~(WebCore::Kerning | Ligatures);
+ break;
+ case GeometricPrecision:
+ case OptimizeLegibility:
+ m_typesettingFeatures |= WebCore::Kerning | Ligatures;
+ break;
+ }
+
+ switch (kerning()) {
+ case FontDescription::NoneKerning:
+ m_typesettingFeatures &= ~WebCore::Kerning;
+ break;
+ case FontDescription::NormalKerning:
+ m_typesettingFeatures |= WebCore::Kerning;
+ break;
+ case FontDescription::AutoKerning:
+ break;
+ }
+
+ // As per CSS (http://dev.w3.org/csswg/css-text-3/#letter-spacing-property),
+ // When the effective letter-spacing between two characters is not zero (due to
+ // either justification or non-zero computed letter-spacing), user agents should
+ // not apply optional ligatures.
+ if (m_letterSpacing == 0) {
+ switch (commonLigaturesState()) {
+ case FontDescription::DisabledLigaturesState:
+ m_typesettingFeatures &= ~Ligatures;
+ break;
+ case FontDescription::EnabledLigaturesState:
+ m_typesettingFeatures |= Ligatures;
+ break;
+ case FontDescription::NormalLigaturesState:
+ break;
+ }
+
+ if (discretionaryLigaturesState() == FontDescription::EnabledLigaturesState
+ || historicalLigaturesState() == FontDescription::EnabledLigaturesState
+ || contextualLigaturesState() == FontDescription::EnabledLigaturesState) {
+ m_typesettingFeatures |= WebCore::Ligatures;
+ }
+ }
}
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/FontDescription.h b/chromium/third_party/WebKit/Source/platform/fonts/FontDescription.h
index 642c95b85ab..9cefae0436a 100644
--- a/chromium/third_party/WebKit/Source/platform/fonts/FontDescription.h
+++ b/chromium/third_party/WebKit/Source/platform/fonts/FontDescription.h
@@ -25,45 +25,24 @@
#ifndef FontDescription_h
#define FontDescription_h
-#include "FontFamilyNames.h"
+#include "platform/FontFamilyNames.h"
#include "platform/fonts/FontCacheKey.h"
#include "platform/fonts/FontFamily.h"
#include "platform/fonts/FontFeatureSettings.h"
#include "platform/fonts/FontOrientation.h"
#include "platform/fonts/FontSmoothingMode.h"
-#include "platform/fonts/FontTraitsMask.h"
+#include "platform/fonts/FontTraits.h"
#include "platform/fonts/FontWidthVariant.h"
#include "platform/fonts/TextRenderingMode.h"
+#include "platform/fonts/TypesettingFeatures.h"
#include "platform/text/NonCJKGlyphOrientation.h"
#include "wtf/MathExtras.h"
#include "wtf/RefPtr.h"
-namespace WebCore {
-
-enum FontWeight {
- FontWeight100,
- FontWeight200,
- FontWeight300,
- FontWeight400,
- FontWeight500,
- FontWeight600,
- FontWeight700,
- FontWeight800,
- FontWeight900,
- FontWeightNormal = FontWeight400,
- FontWeightBold = FontWeight700
-};
-
-enum FontItalic {
- FontItalicOff = 0,
- FontItalicOn = 1
-};
+#include <unicode/uscript.h>
-enum FontSmallCaps {
- FontSmallCapsOff = 0,
- FontSmallCapsOn = 1
-};
+namespace WebCore {
class PLATFORM_EXPORT FontDescription {
public:
@@ -75,29 +54,33 @@ public:
enum LigaturesState { NormalLigaturesState, DisabledLigaturesState, EnabledLigaturesState };
FontDescription()
- : m_specifiedSize(0)
+ : m_locale("en")
+ , m_specifiedSize(0)
, m_computedSize(0)
+ , m_letterSpacing(0)
+ , m_wordSpacing(0)
, m_orientation(Horizontal)
, m_nonCJKGlyphOrientation(NonCJKGlyphOrientationVerticalRight)
, m_widthVariant(RegularWidth)
- , m_italic(FontItalicOff)
- , m_smallCaps(FontSmallCapsOff)
+ , m_style(FontStyleNormal)
+ , m_variant(FontVariantNormal)
, m_isAbsoluteSize(false)
, m_weight(FontWeightNormal)
+ , m_stretch(FontStretchNormal)
, m_genericFamily(NoFamily)
- , m_usePrinterFont(false)
, m_kerning(AutoKerning)
, m_commonLigaturesState(NormalLigaturesState)
, m_discretionaryLigaturesState(NormalLigaturesState)
, m_historicalLigaturesState(NormalLigaturesState)
+ , m_contextualLigaturesState(NormalLigaturesState)
, m_keywordSize(0)
, m_fontSmoothing(AutoSmoothing)
, m_textRendering(AutoTextRendering)
- , m_isSpecifiedFont(false)
, m_script(USCRIPT_COMMON)
, m_syntheticBold(false)
, m_syntheticItalic(false)
, m_subpixelTextPosition(s_useSubpixelTextPositioning)
+ , m_typesettingFeatures(s_defaultTypesettingFeatures)
{
}
@@ -108,31 +91,35 @@ public:
FontFamily& firstFamily() { return m_familyList; }
float specifiedSize() const { return m_specifiedSize; }
float computedSize() const { return m_computedSize; }
- FontItalic italic() const { return static_cast<FontItalic>(m_italic); }
+ FontStyle style() const { return static_cast<FontStyle>(m_style); }
int computedPixelSize() const { return int(m_computedSize + 0.5f); }
- FontSmallCaps smallCaps() const { return static_cast<FontSmallCaps>(m_smallCaps); }
+ FontVariant variant() const { return static_cast<FontVariant>(m_variant); }
bool isAbsoluteSize() const { return m_isAbsoluteSize; }
FontWeight weight() const { return static_cast<FontWeight>(m_weight); }
+ FontStretch stretch() const { return static_cast<FontStretch>(m_stretch); }
FontWeight lighterWeight() const;
FontWeight bolderWeight() const;
GenericFamilyType genericFamily() const { return static_cast<GenericFamilyType>(m_genericFamily); }
- bool usePrinterFont() const { return m_usePrinterFont; }
+
// only use fixed default size when there is only one font family, and that family is "monospace"
bool useFixedDefaultSize() const { return genericFamily() == MonospaceFamily && !family().next() && family().family() == FontFamilyNames::webkit_monospace; }
Kerning kerning() const { return static_cast<Kerning>(m_kerning); }
LigaturesState commonLigaturesState() const { return static_cast<LigaturesState>(m_commonLigaturesState); }
LigaturesState discretionaryLigaturesState() const { return static_cast<LigaturesState>(m_discretionaryLigaturesState); }
LigaturesState historicalLigaturesState() const { return static_cast<LigaturesState>(m_historicalLigaturesState); }
+ LigaturesState contextualLigaturesState() const { return static_cast<LigaturesState>(m_contextualLigaturesState); }
unsigned keywordSize() const { return m_keywordSize; }
FontSmoothingMode fontSmoothing() const { return static_cast<FontSmoothingMode>(m_fontSmoothing); }
- TextRenderingMode textRenderingMode() const { return static_cast<TextRenderingMode>(m_textRendering); }
+ TextRenderingMode textRendering() const { return static_cast<TextRenderingMode>(m_textRendering); }
UScriptCode script() const { return static_cast<UScriptCode>(m_script); }
+ const String& locale() const { return m_locale; }
bool isSyntheticBold() const { return m_syntheticBold; }
bool isSyntheticItalic() const { return m_syntheticItalic; }
bool useSubpixelPositioning() const { return m_subpixelTextPosition; }
- FontTraitsMask traitsMask() const;
- bool isSpecifiedFont() const { return m_isSpecifiedFont; }
+ FontTraits traits() const;
+ float wordSpacing() const { return m_wordSpacing; }
+ float letterSpacing() const { return m_letterSpacing; }
FontOrientation orientation() const { return static_cast<FontOrientation>(m_orientation); }
NonCJKGlyphOrientation nonCJKGlyphOrientation() const { return static_cast<NonCJKGlyphOrientation>(m_nonCJKGlyphOrientation); }
FontWidthVariant widthVariant() const { return static_cast<FontWidthVariant>(m_widthVariant); }
@@ -140,69 +127,78 @@ public:
FontDescription makeNormalFeatureSettings() const;
float effectiveFontSize() const; // Returns either the computedSize or the computedPixelSize
- FontCacheKey cacheKey(const AtomicString& familyName, FontTraitsMask desiredTraits = static_cast<FontTraitsMask>(0)) const;
+ FontCacheKey cacheKey(const AtomicString& familyName, FontTraits desiredTraits = FontTraits(0)) const;
void setFamily(const FontFamily& family) { m_familyList = family; }
void setComputedSize(float s) { m_computedSize = clampToFloat(s); }
void setSpecifiedSize(float s) { m_specifiedSize = clampToFloat(s); }
- void setItalic(FontItalic i) { m_italic = i; }
- void setItalic(bool i) { setItalic(i ? FontItalicOn : FontItalicOff); }
- void setSmallCaps(FontSmallCaps c) { m_smallCaps = c; }
- void setSmallCaps(bool c) { setSmallCaps(c ? FontSmallCapsOn : FontSmallCapsOff); }
+ void setStyle(FontStyle i) { m_style = i; }
+ void setVariant(FontVariant c) { m_variant = c; }
void setIsAbsoluteSize(bool s) { m_isAbsoluteSize = s; }
void setWeight(FontWeight w) { m_weight = w; }
+ void setStretch(FontStretch s) { m_stretch = s; }
void setGenericFamily(GenericFamilyType genericFamily) { m_genericFamily = genericFamily; }
-#if OS(MACOSX)
- void setUsePrinterFont(bool) { }
-#else
- void setUsePrinterFont(bool p) { m_usePrinterFont = p; }
-#endif
- void setKerning(Kerning kerning) { m_kerning = kerning; }
- void setCommonLigaturesState(LigaturesState commonLigaturesState) { m_commonLigaturesState = commonLigaturesState; }
- void setDiscretionaryLigaturesState(LigaturesState discretionaryLigaturesState) { m_discretionaryLigaturesState = discretionaryLigaturesState; }
- void setHistoricalLigaturesState(LigaturesState historicalLigaturesState) { m_historicalLigaturesState = historicalLigaturesState; }
+ void setKerning(Kerning kerning) { m_kerning = kerning; updateTypesettingFeatures(); }
+ void setCommonLigaturesState(LigaturesState commonLigaturesState) { m_commonLigaturesState = commonLigaturesState; updateTypesettingFeatures(); }
+ void setDiscretionaryLigaturesState(LigaturesState discretionaryLigaturesState) { m_discretionaryLigaturesState = discretionaryLigaturesState; updateTypesettingFeatures(); }
+ void setHistoricalLigaturesState(LigaturesState historicalLigaturesState) { m_historicalLigaturesState = historicalLigaturesState; updateTypesettingFeatures(); }
+ void setContextualLigaturesState(LigaturesState contextualLigaturesState) { m_contextualLigaturesState = contextualLigaturesState; updateTypesettingFeatures(); }
void setKeywordSize(unsigned s) { m_keywordSize = s; }
void setFontSmoothing(FontSmoothingMode smoothing) { m_fontSmoothing = smoothing; }
- void setTextRenderingMode(TextRenderingMode rendering) { m_textRendering = rendering; }
- void setIsSpecifiedFont(bool isSpecifiedFont) { m_isSpecifiedFont = isSpecifiedFont; }
+ void setTextRendering(TextRenderingMode rendering) { m_textRendering = rendering; updateTypesettingFeatures(); }
void setOrientation(FontOrientation orientation) { m_orientation = orientation; }
void setNonCJKGlyphOrientation(NonCJKGlyphOrientation orientation) { m_nonCJKGlyphOrientation = orientation; }
void setWidthVariant(FontWidthVariant widthVariant) { m_widthVariant = widthVariant; }
void setScript(UScriptCode s) { m_script = s; }
+ void setLocale(const String& locale) { m_locale = locale; }
void setSyntheticBold(bool syntheticBold) { m_syntheticBold = syntheticBold; }
void setSyntheticItalic(bool syntheticItalic) { m_syntheticItalic = syntheticItalic; }
void setFeatureSettings(PassRefPtr<FontFeatureSettings> settings) { m_featureSettings = settings; }
- void setTraitsMask(FontTraitsMask);
+ void setTraits(FontTraits);
+ void setWordSpacing(float s) { m_wordSpacing = s; }
+ void setLetterSpacing(float s) { m_letterSpacing = s; }
+
+ TypesettingFeatures typesettingFeatures() const { return static_cast<TypesettingFeatures>(m_typesettingFeatures); }
static void setSubpixelPositioning(bool b) { s_useSubpixelTextPositioning = b; }
static bool subpixelPositioning() { return s_useSubpixelTextPositioning; }
+ static void setDefaultTypesettingFeatures(TypesettingFeatures);
+ static TypesettingFeatures defaultTypesettingFeatures();
+
private:
FontFamily m_familyList; // The list of font families to be used.
RefPtr<FontFeatureSettings> m_featureSettings;
+ String m_locale;
+
+ void updateTypesettingFeatures() const;
float m_specifiedSize; // Specified CSS value. Independent of rendering issues such as integer
// rounding, minimum font sizes, and zooming.
float m_computedSize; // Computed size adjusted for the minimum font size and the zoom factor.
+ float m_letterSpacing;
+ float m_wordSpacing;
+
unsigned m_orientation : 1; // FontOrientation - Whether the font is rendering on a horizontal line or a vertical line.
unsigned m_nonCJKGlyphOrientation : 1; // NonCJKGlyphOrientation - Only used by vertical text. Determines the default orientation for non-ideograph glyphs.
unsigned m_widthVariant : 2; // FontWidthVariant
- unsigned m_italic : 1; // FontItalic
- unsigned m_smallCaps : 1; // FontSmallCaps
+ unsigned m_style : 1; // FontStyle
+ unsigned m_variant : 1; // FontVariant
unsigned m_isAbsoluteSize : 1; // Whether or not CSS specified an explicit size
// (logical sizes like "medium" don't count).
- unsigned m_weight : 8; // FontWeight
+ unsigned m_weight : 4; // FontWeight
+ unsigned m_stretch : 4; // FontStretch
unsigned m_genericFamily : 3; // GenericFamilyType
- unsigned m_usePrinterFont : 1;
unsigned m_kerning : 2; // Kerning
unsigned m_commonLigaturesState : 2;
unsigned m_discretionaryLigaturesState : 2;
unsigned m_historicalLigaturesState : 2;
+ unsigned m_contextualLigaturesState : 2;
unsigned m_keywordSize : 4; // We cache whether or not a font is currently represented by a CSS keyword (e.g., medium). If so,
// then we can accurately translate across different generic families to adjust for different preference settings
@@ -210,12 +206,15 @@ private:
unsigned m_fontSmoothing : 2; // FontSmoothingMode
unsigned m_textRendering : 2; // TextRenderingMode
- unsigned m_isSpecifiedFont : 1; // True if a web page specifies a non-generic font family as the first font family.
unsigned m_script : 7; // Used to help choose an appropriate font for generic font families.
unsigned m_syntheticBold : 1;
unsigned m_syntheticItalic : 1;
unsigned m_subpixelTextPosition : 1;
+ mutable unsigned m_typesettingFeatures : 2; // TypesettingFeatures
+
+ static TypesettingFeatures s_defaultTypesettingFeatures;
+
static bool s_useSubpixelTextPositioning;
};
@@ -224,20 +223,22 @@ inline bool FontDescription::operator==(const FontDescription& other) const
return m_familyList == other.m_familyList
&& m_specifiedSize == other.m_specifiedSize
&& m_computedSize == other.m_computedSize
- && m_italic == other.m_italic
- && m_smallCaps == other.m_smallCaps
+ && m_letterSpacing == other.m_letterSpacing
+ && m_wordSpacing == other.m_wordSpacing
+ && m_style == other.m_style
+ && m_variant == other.m_variant
&& m_isAbsoluteSize == other.m_isAbsoluteSize
&& m_weight == other.m_weight
+ && m_stretch == other.m_stretch
&& m_genericFamily == other.m_genericFamily
- && m_usePrinterFont == other.m_usePrinterFont
&& m_kerning == other.m_kerning
&& m_commonLigaturesState == other.m_commonLigaturesState
&& m_discretionaryLigaturesState == other.m_discretionaryLigaturesState
&& m_historicalLigaturesState == other.m_historicalLigaturesState
+ && m_contextualLigaturesState == other.m_contextualLigaturesState
&& m_keywordSize == other.m_keywordSize
&& m_fontSmoothing == other.m_fontSmoothing
&& m_textRendering == other.m_textRendering
- && m_isSpecifiedFont == other.m_isSpecifiedFont
&& m_orientation == other.m_orientation
&& m_nonCJKGlyphOrientation == other.m_nonCJKGlyphOrientation
&& m_widthVariant == other.m_widthVariant
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/FontDescriptionTest.cpp b/chromium/third_party/WebKit/Source/platform/fonts/FontDescriptionTest.cpp
new file mode 100644
index 00000000000..c53c4ad2fe7
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/platform/fonts/FontDescriptionTest.cpp
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2014 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include "platform/fonts/FontDescription.h"
+
+#include <gtest/gtest.h>
+
+namespace WebCore {
+
+
+static inline void assertDescriptionMatchesMask(FontDescription& source, FontTraitsMask mask)
+{
+ FontDescription target;
+ target.setTraits(FontTraits(mask));
+ EXPECT_EQ(source.style(), target.style());
+ EXPECT_EQ(source.variant(), target.variant());
+ EXPECT_EQ(source.weight(), target.weight());
+ EXPECT_EQ(source.stretch(), target.stretch());
+}
+
+TEST(FontDescriptionTest, TestFontTraits)
+{
+ FontDescription source;
+ source.setStyle(FontStyleNormal);
+ source.setVariant(FontVariantNormal);
+ source.setWeight(FontWeightNormal);
+ source.setStretch(FontStretchNormal);
+ assertDescriptionMatchesMask(source, source.traits().mask());
+
+ source.setStyle(FontStyleNormal);
+ source.setVariant(FontVariantNormal);
+ source.setWeight(FontWeightNormal);
+ source.setStretch(FontStretchExtraCondensed);
+ assertDescriptionMatchesMask(source, source.traits().mask());
+
+ source.setStyle(FontStyleItalic);
+ source.setVariant(FontVariantNormal);
+ source.setWeight(FontWeight900);
+ source.setStretch(FontStretchUltraExpanded);
+ assertDescriptionMatchesMask(source, source.traits().mask());
+
+ source.setStyle(FontStyleItalic);
+ source.setVariant(FontVariantSmallCaps);
+ source.setWeight(FontWeight100);
+ source.setStretch(FontStretchExtraExpanded);
+ assertDescriptionMatchesMask(source, source.traits().mask());
+
+ source.setStyle(FontStyleItalic);
+ source.setVariant(FontVariantNormal);
+ source.setWeight(FontWeight900);
+ source.setStretch(FontStretchNormal);
+ assertDescriptionMatchesMask(source, source.traits().mask());
+
+ source.setStyle(FontStyleItalic);
+ source.setVariant(FontVariantNormal);
+ source.setWeight(FontWeight800);
+ source.setStretch(FontStretchNormal);
+ assertDescriptionMatchesMask(source, source.traits().mask());
+
+ source.setStyle(FontStyleItalic);
+ source.setVariant(FontVariantNormal);
+ source.setWeight(FontWeight700);
+ source.setStretch(FontStretchNormal);
+ assertDescriptionMatchesMask(source, source.traits().mask());
+
+ source.setStyle(FontStyleItalic);
+ source.setVariant(FontVariantNormal);
+ source.setWeight(FontWeight600);
+ source.setStretch(FontStretchNormal);
+ assertDescriptionMatchesMask(source, source.traits().mask());
+
+ source.setStyle(FontStyleItalic);
+ source.setVariant(FontVariantNormal);
+ source.setWeight(FontWeight500);
+ source.setStretch(FontStretchNormal);
+ assertDescriptionMatchesMask(source, source.traits().mask());
+
+ source.setStyle(FontStyleItalic);
+ source.setVariant(FontVariantNormal);
+ source.setWeight(FontWeight400);
+ source.setStretch(FontStretchNormal);
+ assertDescriptionMatchesMask(source, source.traits().mask());
+
+ source.setStyle(FontStyleItalic);
+ source.setVariant(FontVariantNormal);
+ source.setWeight(FontWeight300);
+ source.setStretch(FontStretchUltraExpanded);
+ assertDescriptionMatchesMask(source, source.traits().mask());
+
+ source.setStyle(FontStyleItalic);
+ source.setVariant(FontVariantNormal);
+ source.setWeight(FontWeight200);
+ source.setStretch(FontStretchNormal);
+ assertDescriptionMatchesMask(source, source.traits().mask());
+}
+
+} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/FontFallbackList.cpp b/chromium/third_party/WebKit/Source/platform/fonts/FontFallbackList.cpp
index c2169de65ad..e7dfc6ef6f3 100644
--- a/chromium/third_party/WebKit/Source/platform/fonts/FontFallbackList.cpp
+++ b/chromium/third_party/WebKit/Source/platform/fonts/FontFallbackList.cpp
@@ -29,7 +29,7 @@
#include "config.h"
#include "platform/fonts/FontFallbackList.h"
-#include "FontFamilyNames.h"
+#include "platform/FontFamilyNames.h"
#include "platform/fonts/FontCache.h"
#include "platform/fonts/FontDescription.h"
#include "platform/fonts/FontFamily.h"
@@ -40,16 +40,16 @@ namespace WebCore {
FontFallbackList::FontFallbackList()
: m_pageZero(0)
, m_cachedPrimarySimpleFontData(0)
- , m_fontSelector(0)
+ , m_fontSelector(nullptr)
, m_fontSelectorVersion(0)
, m_familyIndex(0)
, m_generation(FontCache::fontCache()->generation())
, m_pitch(UnknownPitch)
- , m_loadingCustomFonts(false)
+ , m_hasLoadingFallback(false)
{
}
-void FontFallbackList::invalidate(PassRefPtr<FontSelector> fontSelector)
+void FontFallbackList::invalidate(PassRefPtrWillBeRawPtr<FontSelector> fontSelector)
{
releaseFontData();
m_fontList.clear();
@@ -58,7 +58,7 @@ void FontFallbackList::invalidate(PassRefPtr<FontSelector> fontSelector)
m_cachedPrimarySimpleFontData = 0;
m_familyIndex = 0;
m_pitch = UnknownPitch;
- m_loadingCustomFonts = false;
+ m_hasLoadingFallback = false;
m_fontSelector = fontSelector;
m_fontSelectorVersion = m_fontSelector ? m_fontSelector->version() : 0;
m_generation = FontCache::fontCache()->generation();
@@ -93,39 +93,62 @@ void FontFallbackList::determinePitch(const FontDescription& fontDescription) co
bool FontFallbackList::loadingCustomFonts() const
{
- if (m_loadingCustomFonts)
- return true;
+ if (!m_hasLoadingFallback)
+ return false;
unsigned numFonts = m_fontList.size();
for (unsigned i = 0; i < numFonts; ++i) {
- if (m_fontList[i]->isCustomFont() && m_fontList[i]->isLoading()) {
- m_loadingCustomFonts = true;
+ if (m_fontList[i]->isLoading())
+ return true;
+ }
+ return false;
+}
+
+bool FontFallbackList::shouldSkipDrawing() const
+{
+ if (!m_hasLoadingFallback)
+ return false;
+
+ unsigned numFonts = m_fontList.size();
+ for (unsigned i = 0; i < numFonts; ++i) {
+ if (m_fontList[i]->shouldSkipDrawing())
return true;
- }
}
return false;
}
const FontData* FontFallbackList::primaryFontData(const FontDescription& fontDescription) const
{
+ bool shouldLoadCustomFont = true;
+
for (unsigned fontIndex = 0; ; ++fontIndex) {
const FontData* fontData = fontDataAt(fontDescription, fontIndex);
if (!fontData) {
// All fonts are custom fonts and are loading. Return the first FontData.
- // FIXME: Correct fallback to the default font.
- return fontDataAt(fontDescription, 0);
+ fontData = fontDataAt(fontDescription, 0);
+ if (fontData)
+ return fontData->fontDataForCharacter(' ');
+
+ SimpleFontData* lastResortFallback = FontCache::fontCache()->getLastResortFallbackFont(fontDescription).get();
+ ASSERT(lastResortFallback);
+ return lastResortFallback;
}
+ if (fontData->isSegmented() && !toSegmentedFontData(fontData)->containsCharacter(' '))
+ continue;
+
+ const SimpleFontData* simpleFontData = fontData->fontDataForCharacter(' ');
+ ASSERT(simpleFontData);
+
// When a custom font is loading, we should use the correct fallback font to layout the text.
// Here skip the temporary font for the loading custom font which may not act as the correct fallback font.
- if (!fontData->isLoadingFallback())
+ if (!simpleFontData->isLoadingFallback())
return fontData;
// Begin to load the first custom font if needed.
- if (!fontIndex) {
- const SimpleFontData* simpleFontData = fontData->fontDataForCharacter(' ');
- if (simpleFontData && simpleFontData->customFontData())
- simpleFontData->customFontData()->beginLoadIfNeeded();
+ if (shouldLoadCustomFont) {
+ shouldLoadCustomFont = false;
+ simpleFontData->customFontData()->beginLoadIfNeeded();
}
}
}
@@ -190,17 +213,10 @@ const FontData* FontFallbackList::fontDataAt(const FontDescription& fontDescript
RefPtr<FontData> result = getFontData(fontDescription, m_familyIndex);
if (result) {
m_fontList.append(result);
- if (result->isLoading())
- m_loadingCustomFonts = true;
+ if (result->isLoadingFallback())
+ m_hasLoadingFallback = true;
}
return result.get();
}
-void FontFallbackList::setPlatformFont(const FontPlatformData& platformData)
-{
- m_familyIndex = cAllFamiliesScanned;
- RefPtr<FontData> fontData = FontCache::fontCache()->fontDataFromFontPlatformData(&platformData);
- m_fontList.append(fontData);
-}
-
}
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/FontFallbackList.h b/chromium/third_party/WebKit/Source/platform/fonts/FontFallbackList.h
index 71fb526cc3e..162972fd786 100644
--- a/chromium/third_party/WebKit/Source/platform/fonts/FontFallbackList.h
+++ b/chromium/third_party/WebKit/Source/platform/fonts/FontFallbackList.h
@@ -67,7 +67,7 @@ public:
static PassRefPtr<FontFallbackList> create() { return adoptRef(new FontFallbackList()); }
~FontFallbackList() { releaseFontData(); }
- void invalidate(PassRefPtr<FontSelector>);
+ void invalidate(PassRefPtrWillBeRawPtr<FontSelector>);
bool isFixedPitch(const FontDescription& fontDescription) const
{
@@ -78,6 +78,7 @@ public:
void determinePitch(const FontDescription&) const;
bool loadingCustomFonts() const;
+ bool shouldSkipDrawing() const;
FontSelector* fontSelector() const { return m_fontSelector.get(); }
// FIXME: It should be possible to combine fontSelectorVersion and generation.
@@ -102,21 +103,19 @@ private:
const FontData* primaryFontData(const FontDescription&) const;
const FontData* fontDataAt(const FontDescription&, unsigned index) const;
- void setPlatformFont(const FontPlatformData&);
-
void releaseFontData();
mutable Vector<RefPtr<FontData>, 1> m_fontList;
mutable GlyphPages m_pages;
mutable GlyphPageTreeNode* m_pageZero;
mutable const SimpleFontData* m_cachedPrimarySimpleFontData;
- RefPtr<FontSelector> m_fontSelector;
+ RefPtrWillBePersistent<FontSelector> m_fontSelector;
mutable WidthCache m_widthCache;
unsigned m_fontSelectorVersion;
mutable int m_familyIndex;
unsigned short m_generation;
mutable unsigned m_pitch : 3; // Pitch
- mutable bool m_loadingCustomFonts : 1;
+ mutable bool m_hasLoadingFallback : 1;
friend class Font;
};
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/FontFastPath.cpp b/chromium/third_party/WebKit/Source/platform/fonts/FontFastPath.cpp
deleted file mode 100644
index 2d5e8ee29b7..00000000000
--- a/chromium/third_party/WebKit/Source/platform/fonts/FontFastPath.cpp
+++ /dev/null
@@ -1,621 +0,0 @@
-/**
- * Copyright (C) 2003, 2006, 2010 Apple Inc. All rights reserved.
- * Copyright (C) 2008 Holger Hans Peter Freyther
- * Copyright (C) 2009 Torch Mobile, Inc.
- *
- * 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 "config.h"
-#include "platform/fonts/Font.h"
-
-#include "platform/LayoutUnit.h"
-#include "platform/fonts/FontCache.h"
-#include "platform/fonts/FontFallbackList.h"
-#include "platform/fonts/GlyphPageTreeNode.h"
-#include "platform/fonts/SimpleFontData.h"
-#include "platform/fonts/WidthIterator.h"
-#include "platform/fonts/GlyphBuffer.h"
-#include "platform/geometry/FloatRect.h"
-#include "platform/text/TextRun.h"
-#include "wtf/MainThread.h"
-#include "wtf/MathExtras.h"
-#include "wtf/unicode/CharacterNames.h"
-#include "wtf/unicode/Unicode.h"
-
-using namespace WTF;
-using namespace Unicode;
-using namespace std;
-
-namespace WebCore {
-
-static inline bool isInRange(UChar32 character, UChar32 lowerBound, UChar32 upperBound)
-{
- return character >= lowerBound && character <= upperBound;
-}
-
-static bool shouldIgnoreRotation(UChar32 character)
-{
- if (character == 0x000A7 || character == 0x000A9 || character == 0x000AE)
- return true;
-
- if (character == 0x000B6 || character == 0x000BC || character == 0x000BD || character == 0x000BE)
- return true;
-
- if (isInRange(character, 0x002E5, 0x002EB))
- return true;
-
- if (isInRange(character, 0x01100, 0x011FF) || isInRange(character, 0x01401, 0x0167F) || isInRange(character, 0x01800, 0x018FF))
- return true;
-
- if (character == 0x02016 || character == 0x02018 || character == 0x02019 || character == 0x02020 || character == 0x02021
- || character == 0x2030 || character == 0x02031)
- return true;
-
- if (isInRange(character, 0x0203B, 0x0203D) || character == 0x02042 || character == 0x02044 || character == 0x02047
- || character == 0x02048 || character == 0x02049 || character == 0x2051)
- return true;
-
- if (isInRange(character, 0x02065, 0x02069) || isInRange(character, 0x020DD, 0x020E0)
- || isInRange(character, 0x020E2, 0x020E4) || isInRange(character, 0x02100, 0x02117)
- || isInRange(character, 0x02119, 0x02131) || isInRange(character, 0x02133, 0x0213F))
- return true;
-
- if (isInRange(character, 0x02145, 0x0214A) || character == 0x0214C || character == 0x0214D
- || isInRange(character, 0x0214F, 0x0218F))
- return true;
-
- if (isInRange(character, 0x02300, 0x02307) || isInRange(character, 0x0230C, 0x0231F)
- || isInRange(character, 0x02322, 0x0232B) || isInRange(character, 0x0237D, 0x0239A)
- || isInRange(character, 0x023B4, 0x023B6) || isInRange(character, 0x023BA, 0x023CF)
- || isInRange(character, 0x023D1, 0x023DB) || isInRange(character, 0x023E2, 0x024FF))
- return true;
-
- if (isInRange(character, 0x025A0, 0x02619) || isInRange(character, 0x02620, 0x02767)
- || isInRange(character, 0x02776, 0x02793) || isInRange(character, 0x02B12, 0x02B2F)
- || isInRange(character, 0x02B4D, 0x02BFF) || isInRange(character, 0x02E80, 0x03007))
- return true;
-
- if (character == 0x03012 || character == 0x03013 || isInRange(character, 0x03020, 0x0302F)
- || isInRange(character, 0x03031, 0x0309F) || isInRange(character, 0x030A1, 0x030FB)
- || isInRange(character, 0x030FD, 0x0A4CF))
- return true;
-
- if (isInRange(character, 0x0A840, 0x0A87F) || isInRange(character, 0x0A960, 0x0A97F)
- || isInRange(character, 0x0AC00, 0x0D7FF) || isInRange(character, 0x0E000, 0x0FAFF))
- return true;
-
- if (isInRange(character, 0x0FE10, 0x0FE1F) || isInRange(character, 0x0FE30, 0x0FE48)
- || isInRange(character, 0x0FE50, 0x0FE57) || isInRange(character, 0x0FE5F, 0x0FE62)
- || isInRange(character, 0x0FE67, 0x0FE6F))
- return true;
-
- if (isInRange(character, 0x0FF01, 0x0FF07) || isInRange(character, 0x0FF0A, 0x0FF0C)
- || isInRange(character, 0x0FF0E, 0x0FF19) ||isInRange (character, 0x0FF1F, 0x0FF3A))
- return true;
-
- if (character == 0x0FF3C || character == 0x0FF3E)
- return true;
-
- if (isInRange(character, 0x0FF40, 0x0FF5A) || isInRange(character, 0x0FFE0, 0x0FFE2)
- || isInRange(character, 0x0FFE4, 0x0FFE7) || isInRange(character, 0x0FFF0, 0x0FFF8)
- || character == 0x0FFFD)
- return true;
-
- if (isInRange(character, 0x13000, 0x1342F) || isInRange(character, 0x1B000, 0x1B0FF)
- || isInRange(character, 0x1D000, 0x1D1FF) || isInRange(character, 0x1D300, 0x1D37F)
- || isInRange(character, 0x1F000, 0x1F64F) || isInRange(character, 0x1F680, 0x1F77F))
- return true;
-
- if (isInRange(character, 0x20000, 0x2FFFD) || isInRange(character, 0x30000, 0x3FFFD))
- return true;
-
- return false;
-}
-
-static inline std::pair<GlyphData, GlyphPage*> glyphDataAndPageForNonCJKCharacterWithGlyphOrientation(UChar32 character, NonCJKGlyphOrientation orientation, GlyphData& data, GlyphPage* page, unsigned pageNumber)
-{
- if (orientation == NonCJKGlyphOrientationUpright || shouldIgnoreRotation(character)) {
- RefPtr<SimpleFontData> uprightFontData = data.fontData->uprightOrientationFontData();
- GlyphPageTreeNode* uprightNode = GlyphPageTreeNode::getRootChild(uprightFontData.get(), pageNumber);
- GlyphPage* uprightPage = uprightNode->page();
- if (uprightPage) {
- GlyphData uprightData = uprightPage->glyphDataForCharacter(character);
- // If the glyphs are the same, then we know we can just use the horizontal glyph rotated vertically to be upright.
- if (data.glyph == uprightData.glyph)
- return make_pair(data, page);
- // The glyphs are distinct, meaning that the font has a vertical-right glyph baked into it. We can't use that
- // glyph, so we fall back to the upright data and use the horizontal glyph.
- if (uprightData.fontData)
- return make_pair(uprightData, uprightPage);
- }
- } else if (orientation == NonCJKGlyphOrientationVerticalRight) {
- RefPtr<SimpleFontData> verticalRightFontData = data.fontData->verticalRightOrientationFontData();
- GlyphPageTreeNode* verticalRightNode = GlyphPageTreeNode::getRootChild(verticalRightFontData.get(), pageNumber);
- GlyphPage* verticalRightPage = verticalRightNode->page();
- if (verticalRightPage) {
- GlyphData verticalRightData = verticalRightPage->glyphDataForCharacter(character);
- // If the glyphs are distinct, we will make the assumption that the font has a vertical-right glyph baked
- // into it.
- if (data.glyph != verticalRightData.glyph)
- return make_pair(data, page);
- // The glyphs are identical, meaning that we should just use the horizontal glyph.
- if (verticalRightData.fontData)
- return make_pair(verticalRightData, verticalRightPage);
- }
- }
- return make_pair(data, page);
-}
-
-std::pair<GlyphData, GlyphPage*> Font::glyphDataAndPageForCharacter(UChar32 c, bool mirror, FontDataVariant variant) const
-{
- ASSERT(isMainThread());
-
- if (variant == AutoVariant) {
- if (m_fontDescription.smallCaps() && !primaryFont()->isSVGFont()) {
- UChar32 upperC = toUpper(c);
- if (upperC != c) {
- c = upperC;
- variant = SmallCapsVariant;
- } else
- variant = NormalVariant;
- } else
- variant = NormalVariant;
- }
-
- if (mirror)
- c = mirroredChar(c);
-
- unsigned pageNumber = (c / GlyphPage::size);
-
- GlyphPageTreeNode* node = pageNumber ? m_fontFallbackList->m_pages.get(pageNumber) : m_fontFallbackList->m_pageZero;
- if (!node) {
- node = GlyphPageTreeNode::getRootChild(fontDataAt(0), pageNumber);
- if (pageNumber)
- m_fontFallbackList->m_pages.set(pageNumber, node);
- else
- m_fontFallbackList->m_pageZero = node;
- }
-
- GlyphPage* page = 0;
- if (variant == NormalVariant) {
- // Fastest loop, for the common case (normal variant).
- while (true) {
- page = node->page();
- if (page) {
- GlyphData data = page->glyphDataForCharacter(c);
- if (data.fontData && (data.fontData->platformData().orientation() == Horizontal || data.fontData->isTextOrientationFallback()))
- return make_pair(data, page);
-
- if (data.fontData) {
- if (isCJKIdeographOrSymbol(c)) {
- if (!data.fontData->hasVerticalGlyphs()) {
- // Use the broken ideograph font data. The broken ideograph font will use the horizontal width of glyphs
- // to make sure you get a square (even for broken glyphs like symbols used for punctuation).
- variant = BrokenIdeographVariant;
- break;
- }
- } else
- return glyphDataAndPageForNonCJKCharacterWithGlyphOrientation(c, m_fontDescription.nonCJKGlyphOrientation(), data, page, pageNumber);
-
- return make_pair(data, page);
- }
-
- if (node->isSystemFallback())
- break;
- }
-
- // Proceed with the fallback list.
- node = node->getChild(fontDataAt(node->level()), pageNumber);
- if (pageNumber)
- m_fontFallbackList->m_pages.set(pageNumber, node);
- else
- m_fontFallbackList->m_pageZero = node;
- }
- }
- if (variant != NormalVariant) {
- while (true) {
- page = node->page();
- if (page) {
- GlyphData data = page->glyphDataForCharacter(c);
- if (data.fontData) {
- // The variantFontData function should not normally return 0.
- // But if it does, we will just render the capital letter big.
- RefPtr<SimpleFontData> variantFontData = data.fontData->variantFontData(m_fontDescription, variant);
- if (!variantFontData)
- return make_pair(data, page);
-
- GlyphPageTreeNode* variantNode = GlyphPageTreeNode::getRootChild(variantFontData.get(), pageNumber);
- GlyphPage* variantPage = variantNode->page();
- if (variantPage) {
- GlyphData data = variantPage->glyphDataForCharacter(c);
- if (data.fontData)
- return make_pair(data, variantPage);
- }
-
- // Do not attempt system fallback off the variantFontData. This is the very unlikely case that
- // a font has the lowercase character but the small caps font does not have its uppercase version.
- return make_pair(variantFontData->missingGlyphData(), page);
- }
-
- if (node->isSystemFallback())
- break;
- }
-
- // Proceed with the fallback list.
- node = node->getChild(fontDataAt(node->level()), pageNumber);
- if (pageNumber)
- m_fontFallbackList->m_pages.set(pageNumber, node);
- else
- m_fontFallbackList->m_pageZero = node;
- }
- }
-
- ASSERT(page);
- ASSERT(node->isSystemFallback());
-
- // System fallback is character-dependent. When we get here, we
- // know that the character in question isn't in the system fallback
- // font's glyph page. Try to lazily create it here.
-
- // FIXME: Unclear if this should normalizeSpaces above 0xFFFF.
- // Doing so changes fast/text/international/plane2-diffs.html
- UChar32 characterToRender = c;
- if (characterToRender <= 0xFFFF)
- characterToRender = Font::normalizeSpaces(characterToRender);
- const SimpleFontData* fontDataToSubstitute = fontDataAt(0)->fontDataForCharacter(characterToRender);
- RefPtr<SimpleFontData> characterFontData = FontCache::fontCache()->platformFallbackForCharacter(m_fontDescription, characterToRender, fontDataToSubstitute, isPlatformFont());
- if (characterFontData) {
- if (characterFontData->platformData().orientation() == Vertical && !characterFontData->hasVerticalGlyphs() && isCJKIdeographOrSymbol(c))
- variant = BrokenIdeographVariant;
- if (variant != NormalVariant)
- characterFontData = characterFontData->variantFontData(m_fontDescription, variant);
- }
- if (characterFontData) {
- // Got the fallback glyph and font.
- GlyphPage* fallbackPage = GlyphPageTreeNode::getRootChild(characterFontData.get(), pageNumber)->page();
- GlyphData data = fallbackPage && fallbackPage->fontDataForCharacter(c) ? fallbackPage->glyphDataForCharacter(c) : characterFontData->missingGlyphData();
- // Cache it so we don't have to do system fallback again next time.
- if (variant == NormalVariant) {
- page->setGlyphDataForCharacter(c, data.glyph, data.fontData);
- data.fontData->setMaxGlyphPageTreeLevel(max(data.fontData->maxGlyphPageTreeLevel(), node->level()));
- if (!isCJKIdeographOrSymbol(c) && data.fontData->platformData().orientation() != Horizontal && !data.fontData->isTextOrientationFallback())
- return glyphDataAndPageForNonCJKCharacterWithGlyphOrientation(c, m_fontDescription.nonCJKGlyphOrientation(), data, fallbackPage, pageNumber);
- }
- return make_pair(data, page);
- }
-
- // Even system fallback can fail; use the missing glyph in that case.
- // FIXME: It would be nicer to use the missing glyph from the last resort font instead.
- GlyphData data = primaryFont()->missingGlyphData();
- if (variant == NormalVariant) {
- page->setGlyphDataForCharacter(c, data.glyph, data.fontData);
- data.fontData->setMaxGlyphPageTreeLevel(max(data.fontData->maxGlyphPageTreeLevel(), node->level()));
- }
- return make_pair(data, page);
-}
-
-bool Font::primaryFontHasGlyphForCharacter(UChar32 character) const
-{
- unsigned pageNumber = (character / GlyphPage::size);
-
- GlyphPageTreeNode* node = GlyphPageTreeNode::getRootChild(primaryFont(), pageNumber);
- GlyphPage* page = node->page();
-
- return page && page->fontDataForCharacter(character);
-}
-
-// FIXME: This function may not work if the emphasis mark uses a complex script, but none of the
-// standard emphasis marks do so.
-bool Font::getEmphasisMarkGlyphData(const AtomicString& mark, GlyphData& glyphData) const
-{
- if (mark.isEmpty())
- return false;
-
- UChar32 character = mark[0];
-
- if (U16_IS_SURROGATE(character)) {
- if (!U16_IS_SURROGATE_LEAD(character))
- return false;
-
- if (mark.length() < 2)
- return false;
-
- UChar low = mark[1];
- if (!U16_IS_TRAIL(low))
- return false;
-
- character = U16_GET_SUPPLEMENTARY(character, low);
- }
-
- glyphData = glyphDataForCharacter(character, false, EmphasisMarkVariant);
- return true;
-}
-
-int Font::emphasisMarkAscent(const AtomicString& mark) const
-{
- FontCachePurgePreventer purgePreventer;
-
- GlyphData markGlyphData;
- if (!getEmphasisMarkGlyphData(mark, markGlyphData))
- return 0;
-
- const SimpleFontData* markFontData = markGlyphData.fontData;
- ASSERT(markFontData);
- if (!markFontData)
- return 0;
-
- return markFontData->fontMetrics().ascent();
-}
-
-int Font::emphasisMarkDescent(const AtomicString& mark) const
-{
- FontCachePurgePreventer purgePreventer;
-
- GlyphData markGlyphData;
- if (!getEmphasisMarkGlyphData(mark, markGlyphData))
- return 0;
-
- const SimpleFontData* markFontData = markGlyphData.fontData;
- ASSERT(markFontData);
- if (!markFontData)
- return 0;
-
- return markFontData->fontMetrics().descent();
-}
-
-int Font::emphasisMarkHeight(const AtomicString& mark) const
-{
- FontCachePurgePreventer purgePreventer;
-
- GlyphData markGlyphData;
- if (!getEmphasisMarkGlyphData(mark, markGlyphData))
- return 0;
-
- const SimpleFontData* markFontData = markGlyphData.fontData;
- ASSERT(markFontData);
- if (!markFontData)
- return 0;
-
- return markFontData->fontMetrics().height();
-}
-
-float Font::getGlyphsAndAdvancesForSimpleText(const TextRun& run, int from, int to, GlyphBuffer& glyphBuffer, ForTextEmphasisOrNot forTextEmphasis) const
-{
- float initialAdvance;
-
- WidthIterator it(this, run, 0, false, forTextEmphasis);
- // FIXME: Using separate glyph buffers for the prefix and the suffix is incorrect when kerning or
- // ligatures are enabled.
- GlyphBuffer localGlyphBuffer;
- it.advance(from, &localGlyphBuffer);
- float beforeWidth = it.m_runWidthSoFar;
- it.advance(to, &glyphBuffer);
-
- if (glyphBuffer.isEmpty())
- return 0;
-
- float afterWidth = it.m_runWidthSoFar;
-
- if (run.rtl()) {
- float finalRoundingWidth = it.m_finalRoundingWidth;
- it.advance(run.length(), &localGlyphBuffer);
- initialAdvance = finalRoundingWidth + it.m_runWidthSoFar - afterWidth;
- } else
- initialAdvance = beforeWidth;
-
- if (run.rtl())
- glyphBuffer.reverse(0, glyphBuffer.size());
-
- return initialAdvance;
-}
-
-void Font::drawSimpleText(GraphicsContext* context, const TextRunPaintInfo& runInfo, const FloatPoint& point) const
-{
- // This glyph buffer holds our glyphs+advances+font data for each glyph.
- GlyphBuffer glyphBuffer;
-
- float startX = point.x() + getGlyphsAndAdvancesForSimpleText(runInfo.run, runInfo.from, runInfo.to, glyphBuffer);
-
- if (glyphBuffer.isEmpty())
- return;
-
- FloatPoint startPoint(startX, point.y());
- drawGlyphBuffer(context, runInfo, glyphBuffer, startPoint);
-}
-
-void Font::drawEmphasisMarksForSimpleText(GraphicsContext* context, const TextRunPaintInfo& runInfo, const AtomicString& mark, const FloatPoint& point) const
-{
- GlyphBuffer glyphBuffer;
- float initialAdvance = getGlyphsAndAdvancesForSimpleText(runInfo.run, runInfo.from, runInfo.to, glyphBuffer, ForTextEmphasis);
-
- if (glyphBuffer.isEmpty())
- return;
-
- drawEmphasisMarks(context, runInfo, glyphBuffer, mark, FloatPoint(point.x() + initialAdvance, point.y()));
-}
-
-void Font::drawGlyphBuffer(GraphicsContext* context, const TextRunPaintInfo& runInfo, const GlyphBuffer& glyphBuffer, const FloatPoint& point) const
-{
- // Draw each contiguous run of glyphs that use the same font data.
- const SimpleFontData* fontData = glyphBuffer.fontDataAt(0);
- FloatPoint startPoint(point);
- float nextX = startPoint.x() + glyphBuffer.advanceAt(0);
- unsigned lastFrom = 0;
- unsigned nextGlyph = 1;
-#if ENABLE(SVG_FONTS)
- TextRun::RenderingContext* renderingContext = runInfo.run.renderingContext();
-#endif
- while (nextGlyph < glyphBuffer.size()) {
- const SimpleFontData* nextFontData = glyphBuffer.fontDataAt(nextGlyph);
-
- if (nextFontData != fontData) {
-#if ENABLE(SVG_FONTS)
- if (renderingContext && fontData->isSVGFont())
- renderingContext->drawSVGGlyphs(context, runInfo.run, fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, startPoint);
- else
-#endif
- drawGlyphs(context, fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, startPoint, runInfo.bounds);
-
- lastFrom = nextGlyph;
- fontData = nextFontData;
- startPoint.setX(nextX);
- }
- nextX += glyphBuffer.advanceAt(nextGlyph);
- nextGlyph++;
- }
-
-#if ENABLE(SVG_FONTS)
- if (renderingContext && fontData->isSVGFont())
- renderingContext->drawSVGGlyphs(context, runInfo.run, fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, startPoint);
- else
-#endif
- drawGlyphs(context, fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, startPoint, runInfo.bounds);
-}
-
-inline static float offsetToMiddleOfGlyph(const SimpleFontData* fontData, Glyph glyph)
-{
- if (fontData->platformData().orientation() == Horizontal) {
- FloatRect bounds = fontData->boundsForGlyph(glyph);
- return bounds.x() + bounds.width() / 2;
- }
- // FIXME: Use glyph bounds once they make sense for vertical fonts.
- return fontData->widthForGlyph(glyph) / 2;
-}
-
-inline static float offsetToMiddleOfGlyphAtIndex(const GlyphBuffer& glyphBuffer, size_t i)
-{
- return offsetToMiddleOfGlyph(glyphBuffer.fontDataAt(i), glyphBuffer.glyphAt(i));
-}
-
-void Font::drawEmphasisMarks(GraphicsContext* context, const TextRunPaintInfo& runInfo, const GlyphBuffer& glyphBuffer, const AtomicString& mark, const FloatPoint& point) const
-{
- FontCachePurgePreventer purgePreventer;
-
- GlyphData markGlyphData;
- if (!getEmphasisMarkGlyphData(mark, markGlyphData))
- return;
-
- const SimpleFontData* markFontData = markGlyphData.fontData;
- ASSERT(markFontData);
- if (!markFontData)
- return;
-
- Glyph markGlyph = markGlyphData.glyph;
- Glyph spaceGlyph = markFontData->spaceGlyph();
-
- float middleOfLastGlyph = offsetToMiddleOfGlyphAtIndex(glyphBuffer, 0);
- FloatPoint startPoint(point.x() + middleOfLastGlyph - offsetToMiddleOfGlyph(markFontData, markGlyph), point.y());
-
- GlyphBuffer markBuffer;
- for (unsigned i = 0; i + 1 < glyphBuffer.size(); ++i) {
- float middleOfNextGlyph = offsetToMiddleOfGlyphAtIndex(glyphBuffer, i + 1);
- float advance = glyphBuffer.advanceAt(i) - middleOfLastGlyph + middleOfNextGlyph;
- markBuffer.add(glyphBuffer.glyphAt(i) ? markGlyph : spaceGlyph, markFontData, advance);
- middleOfLastGlyph = middleOfNextGlyph;
- }
- markBuffer.add(glyphBuffer.glyphAt(glyphBuffer.size() - 1) ? markGlyph : spaceGlyph, markFontData, 0);
-
- drawGlyphBuffer(context, runInfo, markBuffer, startPoint);
-}
-
-float Font::floatWidthForSimpleText(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const
-{
- WidthIterator it(this, run, fallbackFonts, glyphOverflow);
- GlyphBuffer glyphBuffer;
- it.advance(run.length(), (typesettingFeatures() & (Kerning | Ligatures)) ? &glyphBuffer : 0);
-
- if (glyphOverflow) {
- glyphOverflow->top = max<int>(glyphOverflow->top, ceilf(-it.minGlyphBoundingBoxY()) - (glyphOverflow->computeBounds ? 0 : fontMetrics().ascent()));
- glyphOverflow->bottom = max<int>(glyphOverflow->bottom, ceilf(it.maxGlyphBoundingBoxY()) - (glyphOverflow->computeBounds ? 0 : fontMetrics().descent()));
- glyphOverflow->left = ceilf(it.firstGlyphOverflow());
- glyphOverflow->right = ceilf(it.lastGlyphOverflow());
- }
-
- return it.m_runWidthSoFar;
-}
-
-FloatRect Font::selectionRectForSimpleText(const TextRun& run, const FloatPoint& point, int h, int from, int to) const
-{
- GlyphBuffer glyphBuffer;
- WidthIterator it(this, run);
- it.advance(from, &glyphBuffer);
- float beforeWidth = it.m_runWidthSoFar;
- it.advance(to, &glyphBuffer);
- float afterWidth = it.m_runWidthSoFar;
-
- // Using roundf() rather than ceilf() for the right edge as a compromise to
- // ensure correct caret positioning.
- // Use LayoutUnit::epsilon() to ensure that values that cannot be stored as
- // an integer are floored to n and not n-1 due to floating point imprecision.
- if (run.rtl()) {
- it.advance(run.length(), &glyphBuffer);
- float totalWidth = it.m_runWidthSoFar;
- float pixelAlignedX = floorf(point.x() + totalWidth - afterWidth + LayoutUnit::epsilon());
- return FloatRect(pixelAlignedX, point.y(),
- roundf(point.x() + totalWidth - beforeWidth) - pixelAlignedX, h);
- }
-
- float pixelAlignedX = floorf(point.x() + beforeWidth + LayoutUnit::epsilon());
- return FloatRect(pixelAlignedX, point.y(),
- roundf(point.x() + afterWidth) - pixelAlignedX, h);
-}
-
-int Font::offsetForPositionForSimpleText(const TextRun& run, float x, bool includePartialGlyphs) const
-{
- float delta = x;
-
- WidthIterator it(this, run);
- GlyphBuffer localGlyphBuffer;
- unsigned offset;
- if (run.rtl()) {
- delta -= floatWidthForSimpleText(run);
- while (1) {
- offset = it.m_currentCharacter;
- float w;
- if (!it.advanceOneCharacter(w, localGlyphBuffer))
- break;
- delta += w;
- if (includePartialGlyphs) {
- if (delta - w / 2 >= 0)
- break;
- } else {
- if (delta >= 0)
- break;
- }
- }
- } else {
- while (1) {
- offset = it.m_currentCharacter;
- float w;
- if (!it.advanceOneCharacter(w, localGlyphBuffer))
- break;
- delta -= w;
- if (includePartialGlyphs) {
- if (delta + w / 2 <= 0)
- break;
- } else {
- if (delta <= 0)
- break;
- }
- }
- }
-
- return offset;
-}
-
-}
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/FontMetrics.h b/chromium/third_party/WebKit/Source/platform/fonts/FontMetrics.h
index dafed6a476f..1d4ff32593f 100644
--- a/chromium/third_party/WebKit/Source/platform/fonts/FontMetrics.h
+++ b/chromium/third_party/WebKit/Source/platform/fonts/FontMetrics.h
@@ -37,6 +37,8 @@ public:
, m_lineSpacing(0)
, m_xHeight(0)
, m_zeroWidth(0)
+ , m_underlinethickness(0)
+ , m_underlinePosition(0)
, m_hasXHeight(false)
, m_hasZeroWidth(false)
{
@@ -122,6 +124,12 @@ public:
bool hasZeroWidth() const { return m_hasZeroWidth; }
void setHasZeroWidth(bool hasZeroWidth) { m_hasZeroWidth = hasZeroWidth; }
+ float underlineThickness() const { return m_underlinethickness; }
+ void setUnderlineThickness(float underlineThickness) { m_underlinethickness = underlineThickness; }
+
+ float underlinePosition() const { return m_underlinePosition; }
+ void setUnderlinePosition(float underlinePosition) { m_underlinePosition = underlinePosition; }
+
private:
friend class SimpleFontData;
@@ -134,6 +142,8 @@ private:
m_lineSpacing = 0;
m_xHeight = 0;
m_hasXHeight = false;
+ m_underlinethickness = 0;
+ m_underlinePosition = 0;
}
unsigned m_unitsPerEm;
@@ -143,6 +153,8 @@ private:
float m_lineSpacing;
float m_xHeight;
float m_zeroWidth;
+ float m_underlinethickness;
+ float m_underlinePosition;
bool m_hasXHeight;
bool m_hasZeroWidth;
};
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/FontPlatformData.cpp b/chromium/third_party/WebKit/Source/platform/fonts/FontPlatformData.cpp
index 85667d93cb1..ab891966e16 100644
--- a/chromium/third_party/WebKit/Source/platform/fonts/FontPlatformData.cpp
+++ b/chromium/third_party/WebKit/Source/platform/fonts/FontPlatformData.cpp
@@ -45,9 +45,6 @@ FontPlatformData::FontPlatformData(WTF::HashTableDeletedValueType)
#endif
, m_isColorBitmapFont(false)
, m_isCompositeFontReference(false)
-#if OS(MACOSX)
- , m_isPrinterFont(false)
-#endif
{
}
@@ -62,9 +59,6 @@ FontPlatformData::FontPlatformData()
#endif
, m_isColorBitmapFont(false)
, m_isCompositeFontReference(false)
-#if OS(MACOSX)
- , m_isPrinterFont(false)
-#endif
{
}
@@ -79,9 +73,6 @@ FontPlatformData::FontPlatformData(float size, bool syntheticBold, bool syntheti
#endif
, m_isColorBitmapFont(false)
, m_isCompositeFontReference(false)
-#if OS(MACOSX)
- , m_isPrinterFont(false)
-#endif
{
}
@@ -96,7 +87,6 @@ FontPlatformData::FontPlatformData(CGFontRef cgFont, float size, bool syntheticB
, m_cgFont(cgFont)
, m_isColorBitmapFont(false)
, m_isCompositeFontReference(false)
- , m_isPrinterFont(false)
{
}
#endif
@@ -109,9 +99,6 @@ FontPlatformData::FontPlatformData(const FontPlatformData& source)
, m_widthVariant(source.m_widthVariant)
, m_isColorBitmapFont(source.m_isColorBitmapFont)
, m_isCompositeFontReference(source.m_isCompositeFontReference)
-#if OS(MACOSX)
- , m_isPrinterFont(source.m_isPrinterFont)
-#endif
{
platformDataInit(source);
}
@@ -129,9 +116,6 @@ const FontPlatformData& FontPlatformData::operator=(const FontPlatformData& othe
m_widthVariant = other.m_widthVariant;
m_isColorBitmapFont = other.m_isColorBitmapFont;
m_isCompositeFontReference = other.m_isCompositeFontReference;
-#if OS(MACOSX)
- m_isPrinterFont = other.m_isPrinterFont;
-#endif
return platformDataAssign(other);
}
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/FontPlatformData.h b/chromium/third_party/WebKit/Source/platform/fonts/FontPlatformData.h
index 062a67f85b3..f45b6bb0f87 100644
--- a/chromium/third_party/WebKit/Source/platform/fonts/FontPlatformData.h
+++ b/chromium/third_party/WebKit/Source/platform/fonts/FontPlatformData.h
@@ -22,10 +22,8 @@
*
*/
-// FIXME: This is temporary until all ports switch to using this file.
-#if OS(WIN)
-#include "platform/fonts/win/FontPlatformDataWin.h"
-#elif !OS(MACOSX)
+// FIXME: This is temporary until mac switch to using FontPlatformDataHarfBuzz.h and we merge it with this file.
+#if !OS(MACOSX)
#include "platform/fonts/harfbuzz/FontPlatformDataHarfBuzz.h"
#else
@@ -56,6 +54,7 @@ typedef const struct __CTFont* CTFontRef;
#if OS(MACOSX)
#include "platform/fonts/mac/MemoryActivatedFont.h"
+#include "third_party/skia/include/core/SkTypeface.h"
#endif
#if OS(MACOSX)
@@ -88,7 +87,7 @@ public:
FontPlatformData(float size, bool syntheticBold, bool syntheticOblique, FontOrientation = Horizontal, FontWidthVariant = RegularWidth);
#if OS(MACOSX)
- FontPlatformData(NSFont*, float size, bool isPrinterFont = false, bool syntheticBold = false, bool syntheticOblique = false,
+ FontPlatformData(NSFont*, float size, bool syntheticBold = false, bool syntheticOblique = false,
FontOrientation = Horizontal, FontWidthVariant = RegularWidth);
FontPlatformData(CGFontRef, float size, bool syntheticBold, bool syntheticOblique, FontOrientation, FontWidthVariant);
#endif
@@ -103,6 +102,7 @@ public:
#if OS(MACOSX)
CGFontRef cgFont() const { return m_cgFont.get(); }
CTFontRef ctFont() const;
+ SkTypeface* typeface() const;
bool roundsGlyphAdvances() const;
bool allowsLigatures() const;
@@ -116,9 +116,7 @@ public:
bool syntheticOblique() const { return m_syntheticOblique; }
bool isColorBitmapFont() const { return m_isColorBitmapFont; }
bool isCompositeFontReference() const { return m_isCompositeFontReference; }
-#if OS(MACOSX)
- bool isPrinterFont() const { return m_isPrinterFont; }
-#endif
+
FontOrientation orientation() const { return m_orientation; }
FontWidthVariant widthVariant() const { return m_widthVariant; }
@@ -132,7 +130,7 @@ public:
{
#if OS(MACOSX)
ASSERT(m_font || !m_cgFont);
- uintptr_t hashCodes[3] = { (uintptr_t)m_font, m_widthVariant, static_cast<uintptr_t>(m_isPrinterFont << 3 | m_orientation << 2 | m_syntheticBold << 1 | m_syntheticOblique) };
+ uintptr_t hashCodes[3] = { (uintptr_t)m_font, m_widthVariant, static_cast<uintptr_t>(m_orientation << 2 | m_syntheticBold << 1 | m_syntheticOblique) };
return StringHasher::hashMemory<sizeof(hashCodes)>(hashCodes);
#endif
}
@@ -147,9 +145,6 @@ public:
&& m_syntheticOblique == other.m_syntheticOblique
&& m_isColorBitmapFont == other.m_isColorBitmapFont
&& m_isCompositeFontReference == other.m_isCompositeFontReference
-#if OS(MACOSX)
- && m_isPrinterFont == other.m_isPrinterFont
-#endif
&& m_orientation == other.m_orientation
&& m_widthVariant == other.m_widthVariant;
}
@@ -198,13 +193,11 @@ private:
RefPtr<MemoryActivatedFont> m_inMemoryFont;
RefPtr<HarfBuzzFace> m_harfBuzzFace;
+ mutable RefPtr<SkTypeface> m_typeface;
#endif
bool m_isColorBitmapFont;
bool m_isCompositeFontReference;
-#if OS(MACOSX)
- bool m_isPrinterFont;
-#endif
};
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/skia/GlyphPageTreeNodeSkia.cpp b/chromium/third_party/WebKit/Source/platform/fonts/FontPlatformFeatures.h
index 72c20972fc9..da59bc740fe 100644
--- a/chromium/third_party/WebKit/Source/platform/fonts/skia/GlyphPageTreeNodeSkia.cpp
+++ b/chromium/third_party/WebKit/Source/platform/fonts/FontPlatformFeatures.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2009 Google Inc. All rights reserved.
+ * Copyright (C) 2014 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -28,38 +28,22 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "config.h"
-#include "platform/fonts/GlyphPageTreeNode.h"
+#ifndef FontPlatformFeatures_h
+#define FontPlatformFeatures_h
-#include "platform/fonts/SimpleFontData.h"
-
-#include "SkPaint.h"
-#include "SkTemplates.h"
-#include "SkTypeface.h"
-#include "SkUtils.h"
+#include "platform/PlatformExport.h"
namespace WebCore {
-bool GlyphPage::fill(unsigned offset, unsigned length, UChar* buffer, unsigned bufferLength, const SimpleFontData* fontData)
-{
- if (SkUTF16_IsHighSurrogate(buffer[bufferLength-1])) {
- SkDebugf("%s last char is high-surrogate", __FUNCTION__);
- return false;
- }
-
- SkAutoSTMalloc<GlyphPage::size, uint16_t> glyphStorage(length);
-
- uint16_t* glyphs = glyphStorage.get();
- SkTypeface* typeface = fontData->platformData().typeface();
- typeface->charsToGlyphs(buffer, SkTypeface::kUTF16_Encoding, glyphs, length);
+class FontPlatformFeatures {
+public:
+ static bool canReturnFallbackFontsForComplexText();
+ static bool canExpandAroundIdeographsInComplexText();
- unsigned allGlyphs = 0; // track if any of the glyphIDs are non-zero
- for (unsigned i = 0; i < length; i++) {
- setGlyphDataForIndex(offset + i, glyphs[i], glyphs[i] ? fontData : NULL);
- allGlyphs |= glyphs[i];
- }
+private:
+ FontPlatformFeatures();
+};
- return allGlyphs != 0;
}
-} // namespace WebCore
+#endif
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/FontSelector.h b/chromium/third_party/WebKit/Source/platform/fonts/FontSelector.h
index 1225ffc783c..5c0db42ad1d 100644
--- a/chromium/third_party/WebKit/Source/platform/fonts/FontSelector.h
+++ b/chromium/third_party/WebKit/Source/platform/fonts/FontSelector.h
@@ -26,37 +26,25 @@
#ifndef FontSelector_h
#define FontSelector_h
+#include "platform/fonts/FontCacheClient.h"
#include "wtf/Forward.h"
#include "wtf/PassRefPtr.h"
-#include "wtf/RefCounted.h"
+#include "wtf/text/AtomicString.h"
namespace WebCore {
class FontData;
class FontDescription;
-class FontSelectorClient;
-class FontSelector : public RefCounted<FontSelector> {
+class FontSelector : public FontCacheClient {
public:
virtual ~FontSelector() { }
virtual PassRefPtr<FontData> getFontData(const FontDescription&, const AtomicString& familyName) = 0;
- virtual void willUseFontData(const FontDescription&, const AtomicString& familyName) = 0;
-
- virtual void fontCacheInvalidated() { }
-
- virtual void registerForInvalidationCallbacks(FontSelectorClient*) = 0;
- virtual void unregisterForInvalidationCallbacks(FontSelectorClient*) = 0;
+ virtual void willUseFontData(const FontDescription&, const AtomicString& familyName, UChar32) = 0;
virtual unsigned version() const = 0;
};
-class FontSelectorClient {
-public:
- virtual ~FontSelectorClient() { }
-
- virtual void fontsNeedUpdate(FontSelector*) = 0;
-};
-
} // namespace WebCore
#endif // FontSelector_h
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/FontTest.cpp b/chromium/third_party/WebKit/Source/platform/fonts/FontTest.cpp
index e4b6e14c91e..e54c19fa6f4 100644
--- a/chromium/third_party/WebKit/Source/platform/fonts/FontTest.cpp
+++ b/chromium/third_party/WebKit/Source/platform/fonts/FontTest.cpp
@@ -27,6 +27,7 @@
#include "config.h"
+#include "platform/fonts/Character.h"
#include "platform/fonts/Font.h"
#include <gtest/gtest.h>
@@ -47,17 +48,17 @@ static void TestSpecificUCharRange(UChar rangeStart, UChar rangeEnd)
end[0] = rangeEnd;
above[0] = rangeEnd + 1;
- EXPECT_EQ(Font::Simple, Font::characterRangeCodePath(below, 1));
- EXPECT_EQ(Font::Complex, Font::characterRangeCodePath(start, 1));
- EXPECT_EQ(Font::Complex, Font::characterRangeCodePath(midway, 1));
- EXPECT_EQ(Font::Complex, Font::characterRangeCodePath(end, 1));
- EXPECT_EQ(Font::Simple, Font::characterRangeCodePath(above, 1));
+ EXPECT_EQ(SimplePath, Character::characterRangeCodePath(below, 1));
+ EXPECT_EQ(ComplexPath, Character::characterRangeCodePath(start, 1));
+ EXPECT_EQ(ComplexPath, Character::characterRangeCodePath(midway, 1));
+ EXPECT_EQ(ComplexPath, Character::characterRangeCodePath(end, 1));
+ EXPECT_EQ(SimplePath, Character::characterRangeCodePath(above, 1));
}
TEST(FontTest, TestCharacterRangeCodePath)
{
static UChar c1[] = { 0x0 };
- EXPECT_EQ(Font::Simple, Font::characterRangeCodePath(c1, 1));
+ EXPECT_EQ(SimplePath, Character::characterRangeCodePath(c1, 1));
TestSpecificUCharRange(0x2E5, 0x2E9);
TestSpecificUCharRange(0x300, 0x36F);
@@ -72,19 +73,19 @@ TEST(FontTest, TestCharacterRangeCodePath)
TestSpecificUCharRange(0x1A00, 0x1CFF);
static UChar c2[] = { 0x1DBF };
- EXPECT_EQ(Font::Simple, Font::characterRangeCodePath(c2, 1));
+ EXPECT_EQ(SimplePath, Character::characterRangeCodePath(c2, 1));
static UChar c3[] = { 0x1DC0 };
- EXPECT_EQ(Font::Complex, Font::characterRangeCodePath(c3, 1));
+ EXPECT_EQ(ComplexPath, Character::characterRangeCodePath(c3, 1));
static UChar c4[] = { 0x1DD0 };
- EXPECT_EQ(Font::Complex, Font::characterRangeCodePath(c4, 1));
+ EXPECT_EQ(ComplexPath, Character::characterRangeCodePath(c4, 1));
static UChar c5[] = { 0x1DFF };
- EXPECT_EQ(Font::Complex, Font::characterRangeCodePath(c5, 1));
+ EXPECT_EQ(ComplexPath, Character::characterRangeCodePath(c5, 1));
static UChar c6[] = { 0x1E00 };
- EXPECT_EQ(Font::SimpleWithGlyphOverflow, Font::characterRangeCodePath(c6, 1));
+ EXPECT_EQ(SimpleWithGlyphOverflowPath, Character::characterRangeCodePath(c6, 1));
static UChar c7[] = { 0x2000 };
- EXPECT_EQ(Font::SimpleWithGlyphOverflow, Font::characterRangeCodePath(c7, 1));
+ EXPECT_EQ(SimpleWithGlyphOverflowPath, Character::characterRangeCodePath(c7, 1));
static UChar c8[] = { 0x2001 };
- EXPECT_EQ(Font::Simple, Font::characterRangeCodePath(c8, 1));
+ EXPECT_EQ(SimplePath, Character::characterRangeCodePath(c8, 1));
TestSpecificUCharRange(0x20D0, 0x20FF);
TestSpecificUCharRange(0x2CEF, 0x2CF1);
@@ -107,84 +108,84 @@ TEST(FontTest, TestCharacterRangeCodePathSurrogate1)
/* The following 5 should all be Simple because they are not surrogate. */
static UChar c1[] = { 0xD800, 0xDBFE };
- EXPECT_EQ(Font::Simple, Font::characterRangeCodePath(c1, 2));
+ EXPECT_EQ(SimplePath, Character::characterRangeCodePath(c1, 2));
static UChar c2[] = { 0xD800, 0xE000 };
- EXPECT_EQ(Font::Simple, Font::characterRangeCodePath(c2, 2));
+ EXPECT_EQ(SimplePath, Character::characterRangeCodePath(c2, 2));
static UChar c3[] = { 0xDBFF, 0xDBFE };
- EXPECT_EQ(Font::Simple, Font::characterRangeCodePath(c3, 2));
+ EXPECT_EQ(SimplePath, Character::characterRangeCodePath(c3, 2));
static UChar c4[] = { 0xDBFF, 0xE000 };
- EXPECT_EQ(Font::Simple, Font::characterRangeCodePath(c4, 2));
+ EXPECT_EQ(SimplePath, Character::characterRangeCodePath(c4, 2));
static UChar c5[] = { 0xDC00, 0xDBFF };
- EXPECT_EQ(Font::Simple, Font::characterRangeCodePath(c5, 2));
+ EXPECT_EQ(SimplePath, Character::characterRangeCodePath(c5, 2));
/* To be Complex, the Supplementary Character must be in either */
/* U+1F1E6 through U+1F1FF or U+E0100 through U+E01EF. */
/* That is, a lead of 0xD83C with trail 0xDDE6 .. 0xDDFF or */
/* a lead of 0xDB40 with trail 0xDD00 .. 0xDDEF. */
static UChar c6[] = { 0xD83C, 0xDDE5 };
- EXPECT_EQ(Font::Simple, Font::characterRangeCodePath(c6, 2));
+ EXPECT_EQ(SimplePath, Character::characterRangeCodePath(c6, 2));
static UChar c7[] = { 0xD83C, 0xDDE6 };
- EXPECT_EQ(Font::Complex, Font::characterRangeCodePath(c7, 2));
+ EXPECT_EQ(ComplexPath, Character::characterRangeCodePath(c7, 2));
static UChar c8[] = { 0xD83C, 0xDDF0 };
- EXPECT_EQ(Font::Complex, Font::characterRangeCodePath(c8, 2));
+ EXPECT_EQ(ComplexPath, Character::characterRangeCodePath(c8, 2));
static UChar c9[] = { 0xD83C, 0xDDFF };
- EXPECT_EQ(Font::Complex, Font::characterRangeCodePath(c9, 2));
+ EXPECT_EQ(ComplexPath, Character::characterRangeCodePath(c9, 2));
static UChar c10[] = { 0xD83C, 0xDE00 };
- EXPECT_EQ(Font::Simple, Font::characterRangeCodePath(c10, 2));
+ EXPECT_EQ(SimplePath, Character::characterRangeCodePath(c10, 2));
static UChar c11[] = { 0xDB40, 0xDCFF };
- EXPECT_EQ(Font::Simple, Font::characterRangeCodePath(c11, 2));
+ EXPECT_EQ(SimplePath, Character::characterRangeCodePath(c11, 2));
static UChar c12[] = { 0xDB40, 0xDD00 };
- EXPECT_EQ(Font::Complex, Font::characterRangeCodePath(c12, 2));
+ EXPECT_EQ(ComplexPath, Character::characterRangeCodePath(c12, 2));
static UChar c13[] = { 0xDB40, 0xDDED };
- EXPECT_EQ(Font::Complex, Font::characterRangeCodePath(c13, 2));
+ EXPECT_EQ(ComplexPath, Character::characterRangeCodePath(c13, 2));
static UChar c14[] = { 0xDB40, 0xDDEF };
- EXPECT_EQ(Font::Complex, Font::characterRangeCodePath(c14, 2));
+ EXPECT_EQ(ComplexPath, Character::characterRangeCodePath(c14, 2));
static UChar c15[] = { 0xDB40, 0xDDF0 };
- EXPECT_EQ(Font::Simple, Font::characterRangeCodePath(c15, 2));
+ EXPECT_EQ(SimplePath, Character::characterRangeCodePath(c15, 2));
}
TEST(FontTest, TestCharacterRangeCodePathString)
{
// Simple-Simple is still simple
static UChar c1[] = { 0x2FF, 0x2FF };
- EXPECT_EQ(Font::Simple, Font::characterRangeCodePath(c1, 2));
+ EXPECT_EQ(SimplePath, Character::characterRangeCodePath(c1, 2));
// Complex-Simple is Complex
static UChar c2[] = { 0x300, 0x2FF };
- EXPECT_EQ(Font::Complex, Font::characterRangeCodePath(c2, 2));
+ EXPECT_EQ(ComplexPath, Character::characterRangeCodePath(c2, 2));
// Simple-Complex is Complex
static UChar c3[] = { 0x2FF, 0x330 };
- EXPECT_EQ(Font::Complex, Font::characterRangeCodePath(c3, 2));
+ EXPECT_EQ(ComplexPath, Character::characterRangeCodePath(c3, 2));
// Complex-Complex is Complex
static UChar c4[] = { 0x36F, 0x330 };
- EXPECT_EQ(Font::Complex, Font::characterRangeCodePath(c4, 2));
+ EXPECT_EQ(ComplexPath, Character::characterRangeCodePath(c4, 2));
// SimpleWithGlyphOverflow-Simple is SimpleWithGlyphOverflow
static UChar c5[] = { 0x1E00, 0x2FF };
- EXPECT_EQ(Font::SimpleWithGlyphOverflow, Font::characterRangeCodePath(c5, 2));
+ EXPECT_EQ(SimpleWithGlyphOverflowPath, Character::characterRangeCodePath(c5, 2));
// Simple-SimpleWithGlyphOverflow is SimpleWithGlyphOverflow
static UChar c6[] = { 0x2FF, 0x2000 };
- EXPECT_EQ(Font::SimpleWithGlyphOverflow, Font::characterRangeCodePath(c6, 2));
+ EXPECT_EQ(SimpleWithGlyphOverflowPath, Character::characterRangeCodePath(c6, 2));
// SimpleWithGlyphOverflow-Complex is Complex
static UChar c7[] = { 0x1E00, 0x330 };
- EXPECT_EQ(Font::Complex, Font::characterRangeCodePath(c7, 2));
+ EXPECT_EQ(ComplexPath, Character::characterRangeCodePath(c7, 2));
// Complex-SimpleWithGlyphOverflow is Complex
static UChar c8[] = { 0x330, 0x2000 };
- EXPECT_EQ(Font::Complex, Font::characterRangeCodePath(c8, 2));
+ EXPECT_EQ(ComplexPath, Character::characterRangeCodePath(c8, 2));
// Surrogate-Complex is Complex
static UChar c9[] = { 0xD83C, 0xDDE5, 0x330 };
- EXPECT_EQ(Font::Complex, Font::characterRangeCodePath(c9, 3));
+ EXPECT_EQ(ComplexPath, Character::characterRangeCodePath(c9, 3));
// Complex-Surrogate is Complex
static UChar c10[] = { 0x330, 0xD83C, 0xDDE5 };
- EXPECT_EQ(Font::Complex, Font::characterRangeCodePath(c10, 3));
+ EXPECT_EQ(ComplexPath, Character::characterRangeCodePath(c10, 3));
}
static void TestSpecificUChar32RangeIdeograph(UChar32 rangeStart, UChar32 rangeEnd)
{
- EXPECT_FALSE(Font::isCJKIdeograph(rangeStart - 1));
- EXPECT_TRUE(Font::isCJKIdeograph(rangeStart));
- EXPECT_TRUE(Font::isCJKIdeograph((UChar32)((uint64_t)rangeStart + (uint64_t)rangeEnd) / 2));
- EXPECT_TRUE(Font::isCJKIdeograph(rangeEnd));
- EXPECT_FALSE(Font::isCJKIdeograph(rangeEnd + 1));
+ EXPECT_FALSE(Character::isCJKIdeograph(rangeStart - 1));
+ EXPECT_TRUE(Character::isCJKIdeograph(rangeStart));
+ EXPECT_TRUE(Character::isCJKIdeograph((UChar32)((uint64_t)rangeStart + (uint64_t)rangeEnd) / 2));
+ EXPECT_TRUE(Character::isCJKIdeograph(rangeEnd));
+ EXPECT_FALSE(Character::isCJKIdeograph(rangeEnd + 1));
}
TEST(FontTest, TestIsCJKIdeograph)
@@ -210,149 +211,149 @@ TEST(FontTest, TestIsCJKIdeograph)
static void TestSpecificUChar32RangeIdeographSymbol(UChar32 rangeStart, UChar32 rangeEnd)
{
- EXPECT_FALSE(Font::isCJKIdeographOrSymbol(rangeStart - 1));
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(rangeStart));
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol((UChar32)((uint64_t)rangeStart + (uint64_t)rangeEnd) / 2));
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(rangeEnd));
- EXPECT_FALSE(Font::isCJKIdeographOrSymbol(rangeEnd + 1));
+ EXPECT_FALSE(Character::isCJKIdeographOrSymbol(rangeStart - 1));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(rangeStart));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol((UChar32)((uint64_t)rangeStart + (uint64_t)rangeEnd) / 2));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(rangeEnd));
+ EXPECT_FALSE(Character::isCJKIdeographOrSymbol(rangeEnd + 1));
}
TEST(FontTest, TestIsCJKIdeographOrSymbol)
{
// CJK Compatibility Ideographs Supplement.
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x2C7));
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x2CA));
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x2CB));
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x2D9));
-
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x2020));
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x2021));
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x2030));
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x203B));
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x203C));
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x2042));
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x2047));
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x2048));
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x2049));
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x2051));
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x20DD));
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x20DE));
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x2100));
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x2103));
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x2105));
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x2109));
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x210A));
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x2113));
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x2116));
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x2121));
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x212B));
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x213B));
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x2150));
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x2151));
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x2152));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x2C7));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x2CA));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x2CB));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x2D9));
+
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x2020));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x2021));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x2030));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x203B));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x203C));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x2042));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x2047));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x2048));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x2049));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x2051));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x20DD));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x20DE));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x2100));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x2103));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x2105));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x2109));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x210A));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x2113));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x2116));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x2121));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x212B));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x213B));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x2150));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x2151));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x2152));
TestSpecificUChar32RangeIdeographSymbol(0x2156, 0x215A);
TestSpecificUChar32RangeIdeographSymbol(0x2160, 0x216B);
TestSpecificUChar32RangeIdeographSymbol(0x2170, 0x217B);
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x217F));
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x2189));
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x2307));
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x2312));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x217F));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x2189));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x2307));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x2312));
- EXPECT_FALSE(Font::isCJKIdeographOrSymbol(0x23BD));
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x23BE));
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x23C4));
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x23CC));
- EXPECT_FALSE(Font::isCJKIdeographOrSymbol(0x23CD));
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x23CE));
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x2423));
+ EXPECT_FALSE(Character::isCJKIdeographOrSymbol(0x23BD));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x23BE));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x23C4));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x23CC));
+ EXPECT_FALSE(Character::isCJKIdeographOrSymbol(0x23CD));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x23CE));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x2423));
TestSpecificUChar32RangeIdeographSymbol(0x2460, 0x2492);
TestSpecificUChar32RangeIdeographSymbol(0x249C, 0x24FF);
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x25A0));
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x25A1));
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x25A2));
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x25AA));
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x25AB));
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x25B1));
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x25B2));
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x25B3));
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x25B6));
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x25B7));
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x25BC));
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x25BD));
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x25C0));
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x25C1));
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x25C6));
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x25C7));
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x25C9));
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x25CB));
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x25CC));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x25A0));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x25A1));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x25A2));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x25AA));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x25AB));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x25B1));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x25B2));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x25B3));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x25B6));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x25B7));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x25BC));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x25BD));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x25C0));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x25C1));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x25C6));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x25C7));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x25C9));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x25CB));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x25CC));
TestSpecificUChar32RangeIdeographSymbol(0x25CE, 0x25D3);
TestSpecificUChar32RangeIdeographSymbol(0x25E2, 0x25E6);
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x25EF));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x25EF));
TestSpecificUChar32RangeIdeographSymbol(0x2600, 0x2603);
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x2605));
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x2606));
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x260E));
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x2616));
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x2617));
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x2640));
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x2642));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x2605));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x2606));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x260E));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x2616));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x2617));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x2640));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x2642));
TestSpecificUChar32RangeIdeographSymbol(0x2660, 0x266F);
TestSpecificUChar32RangeIdeographSymbol(0x2672, 0x267D);
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x26A0));
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x26BD));
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x26BE));
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x2713));
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x271A));
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x273F));
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x2740));
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x2756));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x26A0));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x26BD));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x26BE));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x2713));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x271A));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x273F));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x2740));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x2756));
TestSpecificUChar32RangeIdeographSymbol(0x2776, 0x277F);
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x2B1A));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x2B1A));
TestSpecificUChar32RangeIdeographSymbol(0x2FF0, 0x302F);
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x3031));
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x312F));
- EXPECT_FALSE(Font::isCJKIdeographOrSymbol(0x3130));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x3031));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x312F));
+ EXPECT_FALSE(Character::isCJKIdeographOrSymbol(0x3130));
- EXPECT_FALSE(Font::isCJKIdeographOrSymbol(0x318F));
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x3190));
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x319F));
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x31BF));
+ EXPECT_FALSE(Character::isCJKIdeographOrSymbol(0x318F));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x3190));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x319F));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x31BF));
- EXPECT_FALSE(Font::isCJKIdeographOrSymbol(0x31FF));
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x3200));
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x3300));
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x33FF));
+ EXPECT_FALSE(Character::isCJKIdeographOrSymbol(0x31FF));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x3200));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x3300));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x33FF));
TestSpecificUChar32RangeIdeographSymbol(0xF860, 0xF862);
TestSpecificUChar32RangeIdeographSymbol(0xFE30, 0xFE4F);
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0xFE10));
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0xFE11));
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0xFE12));
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0xFE19));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0xFE10));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0xFE11));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0xFE12));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0xFE19));
- EXPECT_FALSE(Font::isCJKIdeographOrSymbol(0xFF0D));
- EXPECT_FALSE(Font::isCJKIdeographOrSymbol(0xFF1B));
- EXPECT_FALSE(Font::isCJKIdeographOrSymbol(0xFF1C));
- EXPECT_FALSE(Font::isCJKIdeographOrSymbol(0xFF1E));
+ EXPECT_FALSE(Character::isCJKIdeographOrSymbol(0xFF0D));
+ EXPECT_FALSE(Character::isCJKIdeographOrSymbol(0xFF1B));
+ EXPECT_FALSE(Character::isCJKIdeographOrSymbol(0xFF1C));
+ EXPECT_FALSE(Character::isCJKIdeographOrSymbol(0xFF1E));
TestSpecificUChar32RangeIdeographSymbol(0xFF00, 0xFFEF);
- EXPECT_TRUE(Font::isCJKIdeographOrSymbol(0x1F100));
+ EXPECT_TRUE(Character::isCJKIdeographOrSymbol(0x1F100));
TestSpecificUChar32RangeIdeographSymbol(0x1F110, 0x1F129);
TestSpecificUChar32RangeIdeographSymbol(0x1F130, 0x1F149);
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/FontTraits.h b/chromium/third_party/WebKit/Source/platform/fonts/FontTraits.h
new file mode 100644
index 00000000000..9f2e2f13f84
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/platform/fonts/FontTraits.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2014 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef FontTraits_h
+#define FontTraits_h
+
+#include "wtf/Assertions.h"
+
+namespace WebCore {
+
+enum FontWeight {
+ FontWeight100,
+ FontWeight200,
+ FontWeight300,
+ FontWeight400,
+ FontWeight500,
+ FontWeight600,
+ FontWeight700,
+ FontWeight800,
+ FontWeight900,
+ FontWeightNormal = FontWeight400,
+ FontWeightBold = FontWeight700
+};
+
+// Numeric values matching OS/2 & Windows Metrics usWidthClass table.
+// https://www.microsoft.com/typography/otspec/os2.htm
+enum FontStretch {
+ FontStretchUltraCondensed = 1,
+ FontStretchExtraCondensed = 2,
+ FontStretchCondensed = 3,
+ FontStretchSemiCondensed = 4,
+ FontStretchNormal = 5,
+ FontStretchSemiExpanded = 6,
+ FontStretchExpanded = 7,
+ FontStretchExtraExpanded = 8,
+ FontStretchUltraExpanded = 9
+};
+
+enum FontStyle {
+ FontStyleNormal = 0,
+ FontStyleItalic = 1
+};
+
+enum FontVariant {
+ FontVariantNormal = 0,
+ FontVariantSmallCaps = 1
+};
+
+typedef unsigned FontTraitsMask;
+
+struct FontTraits {
+ FontTraits(FontStyle style, FontVariant variant, FontWeight weight, FontStretch stretch)
+ : m_style(style), m_variant(variant), m_weight(weight), m_stretch(stretch), m_filler(0)
+ {
+ ASSERT(!m_filler);
+ ASSERT(!(m_mask >> 10));
+ }
+ FontTraits(FontTraitsMask mask)
+ : m_mask(mask)
+ {
+ ASSERT(!m_filler);
+ ASSERT(!(m_mask >> 10));
+ }
+ FontStyle style() const { return static_cast<FontStyle>(m_style); }
+ FontVariant variant() const { return static_cast<FontVariant>(m_variant); }
+ FontWeight weight() const { return static_cast<FontWeight>(m_weight); }
+ FontStretch stretch() const { return static_cast<FontStretch>(m_stretch); }
+ FontTraitsMask mask() const { return m_mask; }
+
+ union {
+ struct {
+ unsigned m_style : 1;
+ unsigned m_variant : 1;
+ unsigned m_weight : 4;
+ unsigned m_stretch : 4;
+ unsigned m_filler : 22;
+ };
+ unsigned m_mask;
+ };
+};
+
+} // namespace WebCore
+#endif // FontTraits_h
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/FontTraitsMask.h b/chromium/third_party/WebKit/Source/platform/fonts/FontTraitsMask.h
deleted file mode 100644
index b95d131ff5d..00000000000
--- a/chromium/third_party/WebKit/Source/platform/fonts/FontTraitsMask.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2008 Apple Inc. All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef FontTraitsMask_h
-#define FontTraitsMask_h
-
-namespace WebCore {
-
-enum {
- FontStyleNormalBit = 0,
- FontStyleItalicBit,
- FontVariantNormalBit,
- FontVariantSmallCapsBit,
- FontWeight100Bit,
- FontWeight200Bit,
- FontWeight300Bit,
- FontWeight400Bit,
- FontWeight500Bit,
- FontWeight600Bit,
- FontWeight700Bit,
- FontWeight800Bit,
- FontWeight900Bit,
- FontTraitsMaskWidth
-};
-
-enum FontTraitsMask {
- FontStyleNormalMask = 1 << FontStyleNormalBit,
- FontStyleItalicMask = 1 << FontStyleItalicBit,
- FontStyleMask = FontStyleNormalMask | FontStyleItalicMask,
-
- FontVariantNormalMask = 1 << FontVariantNormalBit,
- FontVariantSmallCapsMask = 1 << FontVariantSmallCapsBit,
- FontVariantMask = FontVariantNormalMask | FontVariantSmallCapsMask,
-
- FontWeight100Mask = 1 << FontWeight100Bit,
- FontWeight200Mask = 1 << FontWeight200Bit,
- FontWeight300Mask = 1 << FontWeight300Bit,
- FontWeight400Mask = 1 << FontWeight400Bit,
- FontWeight500Mask = 1 << FontWeight500Bit,
- FontWeight600Mask = 1 << FontWeight600Bit,
- FontWeight700Mask = 1 << FontWeight700Bit,
- FontWeight800Mask = 1 << FontWeight800Bit,
- FontWeight900Mask = 1 << FontWeight900Bit,
- FontWeightMask = FontWeight100Mask | FontWeight200Mask | FontWeight300Mask | FontWeight400Mask | FontWeight500Mask | FontWeight600Mask | FontWeight700Mask | FontWeight800Mask | FontWeight900Mask
-};
-
-} // namespace WebCore
-#endif // FontTraitsMask_h
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/GenericFontFamilySettings.cpp b/chromium/third_party/WebKit/Source/platform/fonts/GenericFontFamilySettings.cpp
index 7f436745e7a..27916d24ed6 100644
--- a/chromium/third_party/WebKit/Source/platform/fonts/GenericFontFamilySettings.cpp
+++ b/chromium/third_party/WebKit/Source/platform/fonts/GenericFontFamilySettings.cpp
@@ -44,6 +44,18 @@ GenericFontFamilySettings::GenericFontFamilySettings(const GenericFontFamilySett
{
}
+GenericFontFamilySettings& GenericFontFamilySettings::operator=(const GenericFontFamilySettings& other)
+{
+ m_standardFontFamilyMap = other.m_standardFontFamilyMap;
+ m_serifFontFamilyMap = other.m_serifFontFamilyMap;
+ m_fixedFontFamilyMap = other.m_fixedFontFamilyMap;
+ m_sansSerifFontFamilyMap = other.m_sansSerifFontFamilyMap;
+ m_cursiveFontFamilyMap = other.m_cursiveFontFamilyMap;
+ m_fantasyFontFamilyMap = other.m_fantasyFontFamilyMap;
+ m_pictographFontFamilyMap = other.m_pictographFontFamilyMap;
+ return *this;
+}
+
// Sets the entry in the font map for the given script. If family is the empty string, removes the entry instead.
void GenericFontFamilySettings::setGenericFontFamilyMap(ScriptFontFamilyMap& fontMap, const AtomicString& family, UScriptCode script)
{
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/GenericFontFamilySettings.h b/chromium/third_party/WebKit/Source/platform/fonts/GenericFontFamilySettings.h
index ac10e1f79d2..cb019ed8e9c 100644
--- a/chromium/third_party/WebKit/Source/platform/fonts/GenericFontFamilySettings.h
+++ b/chromium/third_party/WebKit/Source/platform/fonts/GenericFontFamilySettings.h
@@ -36,6 +36,7 @@
#include "wtf/text/AtomicString.h"
#include "wtf/text/AtomicStringHash.h"
+#include <unicode/uscript.h>
namespace WebCore {
@@ -73,9 +74,9 @@ public:
// Only called by InternalSettings to clear font family maps.
void reset();
-private:
- GenericFontFamilySettings& operator=(const GenericFontFamilySettings&) WTF_DELETED_FUNCTION;
+ GenericFontFamilySettings& operator=(const GenericFontFamilySettings&);
+private:
// UScriptCode uses -1 and 0 for UScriptInvalidCode and UScriptCommon.
// We need to use -2 and -3 for empty value and deleted value.
struct UScriptCodeHashTraits : WTF::GenericHashTraits<int> {
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/GlyphBuffer.h b/chromium/third_party/WebKit/Source/platform/fonts/GlyphBuffer.h
index 18bcd57ca9e..358ca5e80bc 100644
--- a/chromium/third_party/WebKit/Source/platform/fonts/GlyphBuffer.h
+++ b/chromium/third_party/WebKit/Source/platform/fonts/GlyphBuffer.h
@@ -31,37 +31,13 @@
#define GlyphBuffer_h
#include "platform/fonts/Glyph.h"
-#include "platform/fonts/GlyphBuffer.h"
#include "platform/geometry/FloatSize.h"
#include "wtf/Vector.h"
-#if OS(MACOSX)
-#include <ApplicationServices/ApplicationServices.h>
-#endif
-
namespace WebCore {
class SimpleFontData;
-typedef Glyph GlyphBufferGlyph;
-
-// CG uses CGSize instead of FloatSize so that the result of advances()
-// can be passed directly to CGContextShowGlyphsWithAdvances in FontMac.mm
-#if OS(MACOSX)
-struct GlyphBufferAdvance : CGSize {
-public:
- GlyphBufferAdvance(CGSize size) : CGSize(size)
- {
- }
-
- void setWidth(CGFloat width) { this->CGSize::width = width; }
- CGFloat width() const { return this->CGSize::width; }
- CGFloat height() const { return this->CGSize::height; }
-};
-#else
-typedef FloatSize GlyphBufferAdvance;
-#endif
-
class GlyphBuffer {
public:
bool isEmpty() const { return m_fontData.isEmpty(); }
@@ -74,10 +50,10 @@ public:
m_advances.clear();
}
- GlyphBufferGlyph* glyphs(unsigned from) { return m_glyphs.data() + from; }
- GlyphBufferAdvance* advances(unsigned from) { return m_advances.data() + from; }
- const GlyphBufferGlyph* glyphs(unsigned from) const { return m_glyphs.data() + from; }
- const GlyphBufferAdvance* advances(unsigned from) const { return m_advances.data() + from; }
+ Glyph* glyphs(unsigned from) { return m_glyphs.data() + from; }
+ FloatSize* advances(unsigned from) { return m_advances.data() + from; }
+ const Glyph* glyphs(unsigned from) const { return m_glyphs.data() + from; }
+ const FloatSize* advances(unsigned from) const { return m_advances.data() + from; }
const SimpleFontData* fontDataAt(unsigned index) const { return m_fontData[index]; }
@@ -86,63 +62,41 @@ public:
return m_glyphs[index];
}
- float advanceAt(unsigned index) const
+ FloatSize advanceAt(unsigned index) const
{
- return m_advances[index].width();
+ return m_advances[index];
}
void add(Glyph glyph, const SimpleFontData* font, float width)
{
- m_fontData.append(font);
- m_glyphs.append(glyph);
-
-#if OS(MACOSX)
- CGSize advance = { width, 0 };
- m_advances.append(advance);
-#else
- m_advances.append(FloatSize(width, 0));
-#endif
+ add(glyph, font, FloatSize(width, 0));
}
- void add(Glyph glyph, const SimpleFontData* font, GlyphBufferAdvance advance)
+ void add(Glyph glyph, const SimpleFontData* font, const FloatSize& advance)
{
m_fontData.append(font);
m_glyphs.append(glyph);
m_advances.append(advance);
}
- void reverse(unsigned from, unsigned length)
+ void reverse()
{
- for (unsigned i = from, end = from + length - 1; i < end; ++i, --end)
- swap(i, end);
+ m_fontData.reverse();
+ m_glyphs.reverse();
+ m_advances.reverse();
}
void expandLastAdvance(float width)
{
ASSERT(!isEmpty());
- GlyphBufferAdvance& lastAdvance = m_advances.last();
+ FloatSize& lastAdvance = m_advances.last();
lastAdvance.setWidth(lastAdvance.width() + width);
}
private:
- void swap(unsigned index1, unsigned index2)
- {
- const SimpleFontData* f = m_fontData[index1];
- m_fontData[index1] = m_fontData[index2];
- m_fontData[index2] = f;
-
- GlyphBufferGlyph g = m_glyphs[index1];
- m_glyphs[index1] = m_glyphs[index2];
- m_glyphs[index2] = g;
-
- GlyphBufferAdvance s = m_advances[index1];
- m_advances[index1] = m_advances[index2];
- m_advances[index2] = s;
- }
-
Vector<const SimpleFontData*, 2048> m_fontData;
- Vector<GlyphBufferGlyph, 2048> m_glyphs;
- Vector<GlyphBufferAdvance, 2048> m_advances;
+ Vector<Glyph, 2048> m_glyphs;
+ Vector<FloatSize, 2048> m_advances;
};
}
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/GlyphPage.h b/chromium/third_party/WebKit/Source/platform/fonts/GlyphPage.h
index 98812862bef..c32bf148d5a 100644
--- a/chromium/third_party/WebKit/Source/platform/fonts/GlyphPage.h
+++ b/chromium/third_party/WebKit/Source/platform/fonts/GlyphPage.h
@@ -31,6 +31,7 @@
#define GlyphPage_h
#include "platform/PlatformExport.h"
+#include "platform/fonts/CustomFontData.h"
#include "platform/fonts/Glyph.h"
#include <string.h>
#include "wtf/PassRefPtr.h"
@@ -93,17 +94,22 @@ public:
page->m_perGlyphFontData[i] = m_glyphs[i] ? m_fontDataForAllGlyphs : 0;
}
}
+ page->m_customFontToLoad = m_customFontToLoad;
return page.release();
}
~GlyphPage() { }
- static const size_t size = 256; // Covers Latin-1 in a single page.
- static unsigned indexForCharacter(UChar32 c) { return c % GlyphPage::size; }
+ static const unsigned char sizeBits = 8;
+ static const size_t size = (1 << GlyphPage::sizeBits); // Covers Latin-1 in a single page.
+ static unsigned indexForCharacter(UChar32 c) { return c & 0xFF; }
ALWAYS_INLINE GlyphData glyphDataForCharacter(UChar32 c) const
{
- return glyphDataForIndex(indexForCharacter(c));
+ unsigned index = indexForCharacter(c);
+ if (const CustomFontData* customData = customFontToLoadAt(index))
+ customData->beginLoadIfNeeded();
+ return glyphDataForIndex(index);
}
ALWAYS_INLINE GlyphData glyphDataForIndex(unsigned index) const
@@ -126,14 +132,6 @@ public:
return m_glyphs[index];
}
- ALWAYS_INLINE const SimpleFontData* fontDataForCharacter(UChar32 c) const
- {
- unsigned index = indexForCharacter(c);
- if (hasPerGlyphFontData())
- return m_perGlyphFontData[index];
- return m_glyphs[index] ? m_fontDataForAllGlyphs : 0;
- }
-
void setGlyphDataForCharacter(UChar32 c, Glyph g, const SimpleFontData* f)
{
setGlyphDataForIndex(indexForCharacter(c), g, f);
@@ -143,6 +141,7 @@ public:
{
ASSERT_WITH_SECURITY_IMPLICATION(index < size);
m_glyphs[index] = glyph;
+ setCustomFontToLoad(index, 0);
// GlyphPage getters will always return a null SimpleFontData* for glyph #0 if there's no per-glyph font array.
if (hasPerGlyphFontData()) {
@@ -159,6 +158,23 @@ public:
setGlyphDataForIndex(index, glyphData.glyph, glyphData.fontData);
}
+ const CustomFontData* customFontToLoadAt(unsigned index) const
+ {
+ ASSERT_WITH_SECURITY_IMPLICATION(index < size);
+ return m_customFontToLoad ? m_customFontToLoad->at(index) : 0;
+ }
+
+ void setCustomFontToLoad(unsigned index, const CustomFontData* customFontToLoad)
+ {
+ if (!m_customFontToLoad) {
+ if (!customFontToLoad)
+ return;
+ m_customFontToLoad = CustomDataPage::create();
+ }
+ ASSERT_WITH_SECURITY_IMPLICATION(index < size);
+ m_customFontToLoad->set(index, customFontToLoad);
+ }
+
void removeFontDataFromSystemFallbackPage(const SimpleFontData* fontData)
{
// This method should only be called on the system fallback page, which is never single-font.
@@ -173,9 +189,6 @@ public:
GlyphPageTreeNode* owner() const { return m_owner; }
- // Implemented by the platform.
- bool fill(unsigned offset, unsigned length, UChar* characterBuffer, unsigned bufferLength, const SimpleFontData*);
-
private:
explicit GlyphPage(GlyphPageTreeNode* owner, const SimpleFontData* fontDataForAllGlyphs = 0)
: m_fontDataForAllGlyphs(fontDataForAllGlyphs)
@@ -188,8 +201,19 @@ private:
bool hasPerGlyphFontData() const { return !m_fontDataForAllGlyphs; }
+ class CustomDataPage : public RefCounted<CustomDataPage> {
+ public:
+ static RefPtr<CustomDataPage> create() { return adoptRef(new CustomDataPage()); }
+ const CustomFontData* at(size_t index) const { return m_customData[index]; }
+ void set(size_t index, const CustomFontData* data) { m_customData[index] = data; }
+ private:
+ CustomDataPage() { memset(m_customData, 0, sizeof(m_customData)); }
+ const CustomFontData* m_customData[size];
+ };
+
const SimpleFontData* m_fontDataForAllGlyphs;
GlyphPageTreeNode* m_owner;
+ RefPtr<CustomDataPage> m_customFontToLoad;
Glyph m_glyphs[size];
// NOTE: This array has (GlyphPage::size) elements if m_fontDataForAllGlyphs is null.
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/GlyphPageTreeNode.cpp b/chromium/third_party/WebKit/Source/platform/fonts/GlyphPageTreeNode.cpp
index a81f23bf7ab..3f0537f32b5 100644
--- a/chromium/third_party/WebKit/Source/platform/fonts/GlyphPageTreeNode.cpp
+++ b/chromium/third_party/WebKit/Source/platform/fonts/GlyphPageTreeNode.cpp
@@ -124,7 +124,7 @@ static bool fill(GlyphPage* pageToFill, unsigned offset, unsigned length, UChar*
if (fontData->isSVGFont())
return fontData->customFontData()->fillSVGGlyphPage(pageToFill, offset, length, buffer, bufferLength, fontData);
#endif
- bool hasGlyphs = pageToFill->fill(offset, length, buffer, bufferLength, fontData);
+ bool hasGlyphs = fontData->fillGlyphPage(pageToFill, offset, length, buffer, bufferLength);
#if ENABLE(OPENTYPE_VERTICAL)
if (hasGlyphs && fontData->verticalData())
fontData->verticalData()->substituteWithVerticalGlyphs(fontData, pageToFill, offset, length);
@@ -214,52 +214,32 @@ void GlyphPageTreeNode::initializePage(const FontData* fontData, unsigned pageNu
haveGlyphs = false;
const SegmentedFontData* segmentedFontData = static_cast<const SegmentedFontData*>(fontData);
- unsigned numRanges = segmentedFontData->numRanges();
- bool zeroFilled = false;
- RefPtr<GlyphPage> scratchPage;
- GlyphPage* pageToFill = m_page.get();
- for (unsigned i = 0; i < numRanges; i++) {
+ for (int i = segmentedFontData->numRanges() - 1; i >= 0; i--) {
const FontDataRange& range = segmentedFontData->rangeAt(i);
// all this casting is to ensure all the parameters to min and max have the same type,
// to avoid ambiguous template parameter errors on Windows
int from = max(0, static_cast<int>(range.from()) - static_cast<int>(start));
int to = 1 + min(static_cast<int>(range.to()) - static_cast<int>(start), static_cast<int>(GlyphPage::size) - 1);
- if (from < static_cast<int>(GlyphPage::size) && to > 0) {
- // If this is a custom font needs to be loaded, kick off
- // the load here, and do not fill the page so that
- // font fallback is used while loading.
- RefPtr<CustomFontData> customData = range.fontData()->customFontData();
- if (customData && customData->isLoadingFallback()) {
- customData->beginLoadIfNeeded();
- continue;
- }
-
- if (haveGlyphs && !scratchPage) {
- scratchPage = GlyphPage::createForMixedFontData(this);
- pageToFill = scratchPage.get();
- }
-
- if (!zeroFilled) {
- if (from > 0 || to < static_cast<int>(GlyphPage::size)) {
- for (unsigned i = 0; i < GlyphPage::size; i++)
- pageToFill->setGlyphDataForIndex(i, 0, 0);
- }
- zeroFilled = true;
- }
- haveGlyphs |= fill(pageToFill, from, to - from, buffer + from * (start < 0x10000 ? 1 : 2), (to - from) * (start < 0x10000 ? 1 : 2), range.fontData().get());
- if (scratchPage) {
- ASSERT_WITH_SECURITY_IMPLICATION(to <= static_cast<int>(GlyphPage::size));
- for (int j = from; j < to; j++) {
- if (!m_page->glyphAt(j) && pageToFill->glyphAt(j))
- m_page->setGlyphDataForIndex(j, pageToFill->glyphDataForIndex(j));
- }
+ if (from >= static_cast<int>(GlyphPage::size) || to <= 0)
+ continue;
+
+ // If this is a custom font needs to be loaded, do not fill
+ // the page so that font fallback is used while loading.
+ RefPtr<CustomFontData> customData = range.fontData()->customFontData();
+ if (customData && customData->isLoadingFallback()) {
+ for (int j = from; j < to; j++) {
+ m_page->setCustomFontToLoad(j, customData.get());
+ haveGlyphs = true;
}
+ continue;
}
+
+ haveGlyphs |= fill(m_page.get(), from, to - from, buffer + from * (start < 0x10000 ? 1 : 2), (to - from) * (start < 0x10000 ? 1 : 2), range.fontData().get());
}
}
if (!haveGlyphs)
- m_page = 0;
+ m_page = nullptr;
} else if (parentPage && parentPage->owner() != m_parent) {
// The page we're overriding may not be owned by our parent node.
// This happens when our parent node provides no useful overrides
@@ -294,13 +274,19 @@ void GlyphPageTreeNode::initializePage(const FontData* fontData, unsigned pageNu
// has added anything.
bool newGlyphs = false;
for (unsigned i = 0; i < GlyphPage::size; i++) {
- if (parentPage->glyphAt(i))
+ if (parentPage->glyphAt(i)) {
m_page->setGlyphDataForIndex(i, parentPage->glyphDataForIndex(i));
- else if (fallbackPage->glyphAt(i)) {
+ } else if (fallbackPage->glyphAt(i)) {
m_page->setGlyphDataForIndex(i, fallbackPage->glyphDataForIndex(i));
newGlyphs = true;
- } else
- m_page->setGlyphDataForIndex(i, 0, 0);
+ }
+
+ if (parentPage->customFontToLoadAt(i)) {
+ m_page->setCustomFontToLoad(i, parentPage->customFontToLoadAt(i));
+ } else if (fallbackPage->customFontToLoadAt(i) && !parentPage->glyphAt(i)) {
+ m_page->setCustomFontToLoad(i, fallbackPage->customFontToLoadAt(i));
+ newGlyphs = true;
+ }
}
if (!newGlyphs)
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/GlyphPageTreeNodeTest.cpp b/chromium/third_party/WebKit/Source/platform/fonts/GlyphPageTreeNodeTest.cpp
new file mode 100644
index 00000000000..51cc356c44e
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/platform/fonts/GlyphPageTreeNodeTest.cpp
@@ -0,0 +1,226 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "config.h"
+#include "platform/fonts/GlyphPageTreeNode.h"
+
+#include "platform/fonts/SegmentedFontData.h"
+#include "platform/fonts/SimpleFontData.h"
+#include <gtest/gtest.h>
+
+namespace WebCore {
+
+class TestCustomFontData : public CustomFontData {
+public:
+ static PassRefPtr<TestCustomFontData> create() { return adoptRef(new TestCustomFontData()); }
+private:
+ TestCustomFontData() { }
+ virtual bool isLoadingFallback() const OVERRIDE { return true; }
+};
+
+class TestSimpleFontData : public SimpleFontData {
+public:
+ static PassRefPtr<TestSimpleFontData> create(UChar32 from, UChar32 to)
+ {
+ return adoptRef(new TestSimpleFontData(nullptr, from, to));
+ }
+
+ static PassRefPtr<TestSimpleFontData> createUnloaded(UChar32 from, UChar32 to)
+ {
+ return adoptRef(new TestSimpleFontData(TestCustomFontData::create(), from, to));
+ }
+
+private:
+ TestSimpleFontData(PassRefPtr<CustomFontData> customData, UChar32 from, UChar32 to)
+ : SimpleFontData(customData, 10, false, false)
+ , m_from(from)
+ , m_to(to)
+ {
+ }
+
+ bool fillGlyphPage(GlyphPage* pageToFill, unsigned offset, unsigned length, UChar* buffer, unsigned bufferLength) const OVERRIDE
+ {
+ const Glyph kGlyph = 1;
+ String bufferString(buffer, bufferLength);
+ unsigned bufferIndex = 0;
+ bool hasGlyphs = false;
+ for (unsigned i = 0; i < length; i++) {
+ UChar32 c = bufferString.characterStartingAt(bufferIndex);
+ bufferIndex += U16_LENGTH(c);
+ if (m_from <= c && c <= m_to) {
+ pageToFill->setGlyphDataForIndex(offset + i, kGlyph, this);
+ hasGlyphs = true;
+ }
+ }
+ return hasGlyphs;
+ }
+
+ UChar32 m_from;
+ UChar32 m_to;
+};
+
+TEST(GlyphPageTreeNode, rootChild)
+{
+ const unsigned kPageNumber = 0;
+ size_t pageCountBeforeTest = GlyphPageTreeNode::treeGlyphPageCount();
+ {
+ RefPtr<TestSimpleFontData> data = TestSimpleFontData::create('a', 'z');
+ GlyphPageTreeNode* node = GlyphPageTreeNode::getRootChild(data.get(), kPageNumber);
+ EXPECT_EQ(pageCountBeforeTest + 1, GlyphPageTreeNode::treeGlyphPageCount());
+ EXPECT_TRUE(node->page()->glyphAt('a'));
+ EXPECT_FALSE(node->page()->glyphAt('A'));
+ EXPECT_FALSE(node->isSystemFallback());
+ EXPECT_EQ(1u, node->level());
+ EXPECT_EQ(node, node->page()->owner());
+ }
+ EXPECT_EQ(pageCountBeforeTest, GlyphPageTreeNode::treeGlyphPageCount());
+}
+
+TEST(GlyphPageTreeNode, level2)
+{
+ const unsigned kPageNumber = 0;
+ size_t pageCountBeforeTest = GlyphPageTreeNode::treeGlyphPageCount();
+ {
+ RefPtr<TestSimpleFontData> dataAtoC = TestSimpleFontData::create('A', 'C');
+ RefPtr<TestSimpleFontData> dataCtoE = TestSimpleFontData::create('C', 'E');
+ GlyphPageTreeNode* node1 = GlyphPageTreeNode::getRootChild(dataAtoC.get(), kPageNumber);
+ GlyphPageTreeNode* node2 = node1->getChild(dataCtoE.get(), kPageNumber);
+ EXPECT_EQ(pageCountBeforeTest + 3, GlyphPageTreeNode::treeGlyphPageCount());
+
+ EXPECT_EQ(2u, node2->level());
+ EXPECT_EQ(dataAtoC, node2->page()->glyphDataForCharacter('A').fontData);
+ EXPECT_EQ(dataAtoC, node2->page()->glyphDataForCharacter('C').fontData);
+ EXPECT_EQ(dataCtoE, node2->page()->glyphDataForCharacter('E').fontData);
+ }
+ EXPECT_EQ(pageCountBeforeTest, GlyphPageTreeNode::treeGlyphPageCount());
+}
+
+TEST(GlyphPageTreeNode, segmentedData)
+{
+ const unsigned kPageNumber = 0;
+ size_t pageCountBeforeTest = GlyphPageTreeNode::treeGlyphPageCount();
+ {
+ RefPtr<TestSimpleFontData> dataBtoC = TestSimpleFontData::create('B', 'C');
+ RefPtr<TestSimpleFontData> dataCtoE = TestSimpleFontData::create('C', 'E');
+ RefPtr<SegmentedFontData> segmentedData = SegmentedFontData::create();
+ segmentedData->appendRange(FontDataRange('A', 'C', dataBtoC));
+ segmentedData->appendRange(FontDataRange('C', 'D', dataCtoE));
+ GlyphPageTreeNode* node = GlyphPageTreeNode::getRootChild(segmentedData.get(), kPageNumber);
+
+ EXPECT_EQ(0, node->page()->glyphDataForCharacter('A').fontData);
+ EXPECT_EQ(dataBtoC, node->page()->glyphDataForCharacter('B').fontData);
+ EXPECT_EQ(dataBtoC, node->page()->glyphDataForCharacter('C').fontData);
+ EXPECT_EQ(dataCtoE, node->page()->glyphDataForCharacter('D').fontData);
+ EXPECT_EQ(0, node->page()->glyphDataForCharacter('E').fontData);
+ }
+ EXPECT_EQ(pageCountBeforeTest, GlyphPageTreeNode::treeGlyphPageCount());
+}
+
+TEST(GlyphPageTreeNode, outsideBMP)
+{
+ const unsigned kPageNumber = 0x1f300 / GlyphPage::size;
+ size_t pageCountBeforeTest = GlyphPageTreeNode::treeGlyphPageCount();
+ {
+ RefPtr<TestSimpleFontData> data = TestSimpleFontData::create(0x1f310, 0x1f320);
+ GlyphPageTreeNode* node = GlyphPageTreeNode::getRootChild(data.get(), kPageNumber);
+ EXPECT_EQ(pageCountBeforeTest + 1, GlyphPageTreeNode::treeGlyphPageCount());
+ EXPECT_FALSE(node->page()->glyphForCharacter(0x1f30f));
+ EXPECT_TRUE(node->page()->glyphForCharacter(0x1f310));
+ EXPECT_TRUE(node->page()->glyphForCharacter(0x1f320));
+ EXPECT_FALSE(node->page()->glyphForCharacter(0x1f321));
+ }
+ EXPECT_EQ(pageCountBeforeTest, GlyphPageTreeNode::treeGlyphPageCount());
+}
+
+TEST(GlyphPageTreeNode, customData)
+{
+ const unsigned kPageNumber = 0;
+ size_t pageCountBeforeTest = GlyphPageTreeNode::treeGlyphPageCount();
+ {
+ RefPtr<TestSimpleFontData> dataAtoC = TestSimpleFontData::createUnloaded('A', 'C');
+ RefPtr<TestSimpleFontData> dataBtoD = TestSimpleFontData::create('B', 'D');
+ RefPtr<TestSimpleFontData> dataCtoE = TestSimpleFontData::createUnloaded('C', 'E');
+ RefPtr<SegmentedFontData> segmentedData = SegmentedFontData::create();
+ segmentedData->appendRange(FontDataRange('A', 'C', dataAtoC));
+ segmentedData->appendRange(FontDataRange('B', 'D', dataBtoD));
+ segmentedData->appendRange(FontDataRange('C', 'E', dataCtoE));
+ GlyphPageTreeNode* node = GlyphPageTreeNode::getRootChild(segmentedData.get(), kPageNumber);
+
+ EXPECT_EQ(0, node->page()->glyphDataForCharacter('A').fontData);
+ EXPECT_EQ(dataBtoD, node->page()->glyphDataForCharacter('B').fontData);
+ EXPECT_EQ(dataBtoD, node->page()->glyphDataForCharacter('C').fontData);
+ EXPECT_EQ(dataBtoD, node->page()->glyphDataForCharacter('D').fontData);
+ EXPECT_EQ(0, node->page()->glyphDataForCharacter('E').fontData);
+
+ EXPECT_EQ(dataAtoC->customFontData(), node->page()->customFontToLoadAt('A'));
+ EXPECT_EQ(dataAtoC->customFontData(), node->page()->customFontToLoadAt('B'));
+ EXPECT_EQ(dataAtoC->customFontData(), node->page()->customFontToLoadAt('C'));
+ EXPECT_EQ(0, node->page()->customFontToLoadAt('D'));
+ EXPECT_EQ(dataCtoE->customFontData(), node->page()->customFontToLoadAt('E'));
+ }
+ EXPECT_EQ(pageCountBeforeTest, GlyphPageTreeNode::treeGlyphPageCount());
+}
+
+TEST(GlyphPageTreeNode, customDataWithMultiplePages)
+{
+ const unsigned kPageNumber = 0;
+ size_t pageCountBeforeTest = GlyphPageTreeNode::treeGlyphPageCount();
+ {
+ RefPtr<TestSimpleFontData> dataAtoC = TestSimpleFontData::createUnloaded('A', 'C');
+ RefPtr<TestSimpleFontData> dataBtoD = TestSimpleFontData::create('B', 'D');
+ RefPtr<TestSimpleFontData> dataCtoE = TestSimpleFontData::createUnloaded('C', 'E');
+ RefPtr<SegmentedFontData> segmentedData1 = SegmentedFontData::create();
+ RefPtr<SegmentedFontData> segmentedData2 = SegmentedFontData::create();
+ RefPtr<SegmentedFontData> segmentedData3 = SegmentedFontData::create();
+ segmentedData1->appendRange(FontDataRange('A', 'C', dataAtoC));
+ segmentedData2->appendRange(FontDataRange('B', 'D', dataBtoD));
+ segmentedData3->appendRange(FontDataRange('C', 'E', dataCtoE));
+ GlyphPageTreeNode* node1 = GlyphPageTreeNode::getRootChild(segmentedData1.get(), kPageNumber);
+ GlyphPageTreeNode* node2 = node1->getChild(segmentedData2.get(), kPageNumber);
+ GlyphPageTreeNode* node3 = node2->getChild(segmentedData3.get(), kPageNumber);
+
+ EXPECT_EQ(0, node3->page()->glyphDataForCharacter('A').fontData);
+ EXPECT_EQ(dataBtoD, node3->page()->glyphDataForCharacter('B').fontData);
+ EXPECT_EQ(dataBtoD, node3->page()->glyphDataForCharacter('C').fontData);
+ EXPECT_EQ(dataBtoD, node3->page()->glyphDataForCharacter('D').fontData);
+ EXPECT_EQ(0, node3->page()->glyphDataForCharacter('E').fontData);
+
+ EXPECT_EQ(dataAtoC->customFontData(), node3->page()->customFontToLoadAt('A'));
+ EXPECT_EQ(dataAtoC->customFontData(), node3->page()->customFontToLoadAt('B'));
+ EXPECT_EQ(dataAtoC->customFontData(), node3->page()->customFontToLoadAt('C'));
+ EXPECT_EQ(0, node3->page()->customFontToLoadAt('D'));
+ EXPECT_EQ(dataCtoE->customFontData(), node3->page()->customFontToLoadAt('E'));
+ }
+ EXPECT_EQ(pageCountBeforeTest, GlyphPageTreeNode::treeGlyphPageCount());
+}
+
+TEST(GlyphPageTreeNode, systemFallback)
+{
+ const unsigned kPageNumber = 0;
+ size_t pageCountBeforeTest = GlyphPageTreeNode::treeGlyphPageCount();
+ {
+ RefPtr<TestSimpleFontData> dataAtoC = TestSimpleFontData::createUnloaded('A', 'C');
+ RefPtr<TestSimpleFontData> dataBtoD = TestSimpleFontData::create('B', 'D');
+ RefPtr<SegmentedFontData> segmentedData = SegmentedFontData::create();
+ segmentedData->appendRange(FontDataRange('A', 'C', dataAtoC));
+ GlyphPageTreeNode* node1 = GlyphPageTreeNode::getRootChild(segmentedData.get(), kPageNumber);
+ GlyphPageTreeNode* node2 = node1->getChild(dataBtoD.get(), kPageNumber);
+ GlyphPageTreeNode* node3 = node2->getChild(0, kPageNumber);
+
+ EXPECT_TRUE(node3->isSystemFallback());
+
+ EXPECT_EQ(0, node3->page()->glyphDataForCharacter('A').fontData);
+ EXPECT_EQ(dataBtoD, node3->page()->glyphDataForCharacter('B').fontData);
+ EXPECT_EQ(dataBtoD, node3->page()->glyphDataForCharacter('C').fontData);
+ EXPECT_EQ(dataBtoD, node3->page()->glyphDataForCharacter('D').fontData);
+
+ EXPECT_EQ(dataAtoC->customFontData(), node3->page()->customFontToLoadAt('A'));
+ EXPECT_EQ(dataAtoC->customFontData(), node3->page()->customFontToLoadAt('B'));
+ EXPECT_EQ(dataAtoC->customFontData(), node3->page()->customFontToLoadAt('C'));
+ EXPECT_EQ(0, node3->page()->customFontToLoadAt('D'));
+ }
+ EXPECT_EQ(pageCountBeforeTest, GlyphPageTreeNode::treeGlyphPageCount());
+}
+
+} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/SegmentedFontData.cpp b/chromium/third_party/WebKit/Source/platform/fonts/SegmentedFontData.cpp
index 451e5fe5d29..c81e5c80b9d 100644
--- a/chromium/third_party/WebKit/Source/platform/fonts/SegmentedFontData.cpp
+++ b/chromium/third_party/WebKit/Source/platform/fonts/SegmentedFontData.cpp
@@ -57,17 +57,6 @@ bool SegmentedFontData::containsCharacter(UChar32 c) const
return false;
}
-bool SegmentedFontData::containsCharacters(const UChar* characters, int length) const
-{
- UChar32 c;
- for (int i = 0; i < length; ) {
- U16_NEXT(characters, i, length, c)
- if (!containsCharacter(c))
- return false;
- }
- return true;
-}
-
bool SegmentedFontData::isCustomFont() const
{
// All segmented fonts are custom fonts.
@@ -84,15 +73,15 @@ bool SegmentedFontData::isLoading() const
return false;
}
-// Returns true only if all of the sub fonts are loadingFallback.
+// Returns true if any of the sub fonts are loadingFallback.
bool SegmentedFontData::isLoadingFallback() const
{
Vector<FontDataRange>::const_iterator end = m_ranges.end();
for (Vector<FontDataRange>::const_iterator it = m_ranges.begin(); it != end; ++it) {
- if (!it->fontData()->isLoadingFallback())
- return false;
+ if (it->fontData()->isLoadingFallback())
+ return true;
}
- return true;
+ return false;
}
bool SegmentedFontData::isSegmented() const
@@ -100,6 +89,16 @@ bool SegmentedFontData::isSegmented() const
return true;
}
+bool SegmentedFontData::shouldSkipDrawing() const
+{
+ Vector<FontDataRange>::const_iterator end = m_ranges.end();
+ for (Vector<FontDataRange>::const_iterator it = m_ranges.begin(); it != end; ++it) {
+ if (it->fontData()->shouldSkipDrawing())
+ return true;
+ }
+ return false;
+}
+
#ifndef NDEBUG
String SegmentedFontData::description() const
{
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/SegmentedFontData.h b/chromium/third_party/WebKit/Source/platform/fonts/SegmentedFontData.h
index ffc34e067e9..db828ad2c3c 100644
--- a/chromium/third_party/WebKit/Source/platform/fonts/SegmentedFontData.h
+++ b/chromium/third_party/WebKit/Source/platform/fonts/SegmentedFontData.h
@@ -62,32 +62,27 @@ public:
void appendRange(const FontDataRange& range) { m_ranges.append(range); }
unsigned numRanges() const { return m_ranges.size(); }
const FontDataRange& rangeAt(unsigned i) const { return m_ranges[i]; }
+ bool containsCharacter(UChar32) const;
#ifndef NDEBUG
- virtual String description() const;
+ virtual String description() const OVERRIDE;
#endif
private:
SegmentedFontData() { }
virtual const SimpleFontData* fontDataForCharacter(UChar32) const OVERRIDE;
- virtual bool containsCharacters(const UChar*, int length) const OVERRIDE;
virtual bool isCustomFont() const OVERRIDE;
virtual bool isLoading() const OVERRIDE;
virtual bool isLoadingFallback() const OVERRIDE;
virtual bool isSegmented() const OVERRIDE;
-
- bool containsCharacter(UChar32) const;
+ virtual bool shouldSkipDrawing() const OVERRIDE;
Vector<FontDataRange, 1> m_ranges;
};
-inline SegmentedFontData* toSegmentedFontData(FontData* fontData)
-{
- ASSERT_WITH_SECURITY_IMPLICATION(!fontData || fontData->isSegmented());
- return static_cast<SegmentedFontData*>(fontData);
-}
+DEFINE_TYPE_CASTS(SegmentedFontData, FontData, fontData, fontData->isSegmented(), fontData.isSegmented());
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/SimpleFontData.cpp b/chromium/third_party/WebKit/Source/platform/fonts/SimpleFontData.cpp
index b6846b2ac00..849e889a0c0 100644
--- a/chromium/third_party/WebKit/Source/platform/fonts/SimpleFontData.cpp
+++ b/chromium/third_party/WebKit/Source/platform/fonts/SimpleFontData.cpp
@@ -47,7 +47,7 @@ SimpleFontData::SimpleFontData(const FontPlatformData& platformData, PassRefPtr<
, m_isTextOrientationFallback(isTextOrientationFallback)
, m_isBrokenIdeographFallback(false)
#if ENABLE(OPENTYPE_VERTICAL)
- , m_verticalData(0)
+ , m_verticalData(nullptr)
#endif
, m_hasVerticalGlyphs(false)
, m_customFontData(customData)
@@ -69,7 +69,7 @@ SimpleFontData::SimpleFontData(PassRefPtr<CustomFontData> customData, float font
, m_isTextOrientationFallback(false)
, m_isBrokenIdeographFallback(false)
#if ENABLE(OPENTYPE_VERTICAL)
- , m_verticalData(0)
+ , m_verticalData(nullptr)
#endif
, m_hasVerticalGlyphs(false)
, m_customFontData(customData)
@@ -160,8 +160,9 @@ const SimpleFontData* SimpleFontData::fontDataForCharacter(UChar32) const
Glyph SimpleFontData::glyphForCharacter(UChar32 character) const
{
- GlyphPageTreeNode* node = GlyphPageTreeNode::getRootChild(this, character / GlyphPage::size);
- return node->page() ? node->page()->glyphAt(character % GlyphPage::size) : 0;
+ // As GlyphPage::size is power of 2 so shifting is valid
+ GlyphPageTreeNode* node = GlyphPageTreeNode::getRootChild(this, character >> GlyphPage::sizeBits);
+ return node->page() ? node->page()->glyphAt(character & 0xFF) : 0;
}
bool SimpleFontData::isSegmented() const
@@ -176,7 +177,7 @@ PassRefPtr<SimpleFontData> SimpleFontData::verticalRightOrientationFontData() co
if (!m_derivedFontData->verticalRightOrientation) {
FontPlatformData verticalRightPlatformData(m_platformData);
verticalRightPlatformData.setOrientation(Horizontal);
- m_derivedFontData->verticalRightOrientation = create(verticalRightPlatformData, isCustomFont() ? CustomFontData::create(false): 0, true);
+ m_derivedFontData->verticalRightOrientation = create(verticalRightPlatformData, isCustomFont() ? CustomFontData::create(): nullptr, true);
}
return m_derivedFontData->verticalRightOrientation;
}
@@ -186,7 +187,7 @@ PassRefPtr<SimpleFontData> SimpleFontData::uprightOrientationFontData() const
if (!m_derivedFontData)
m_derivedFontData = DerivedFontData::create(isCustomFont());
if (!m_derivedFontData->uprightOrientation)
- m_derivedFontData->uprightOrientation = create(m_platformData, isCustomFont() ? CustomFontData::create(false): 0, true);
+ m_derivedFontData->uprightOrientation = create(m_platformData, isCustomFont() ? CustomFontData::create(): nullptr, true);
return m_derivedFontData->uprightOrientation;
}
@@ -215,7 +216,7 @@ PassRefPtr<SimpleFontData> SimpleFontData::brokenIdeographFontData() const
if (!m_derivedFontData)
m_derivedFontData = DerivedFontData::create(isCustomFont());
if (!m_derivedFontData->brokenIdeograph) {
- m_derivedFontData->brokenIdeograph = create(m_platformData, isCustomFont() ? CustomFontData::create(false): 0);
+ m_derivedFontData->brokenIdeograph = create(m_platformData, isCustomFont() ? CustomFontData::create(): nullptr);
m_derivedFontData->brokenIdeograph->m_isBrokenIdeographFallback = true;
}
return m_derivedFontData->brokenIdeograph;
@@ -259,7 +260,7 @@ PassRefPtr<SimpleFontData> SimpleFontData::createScaledFontData(const FontDescri
{
// FIXME: Support scaled SVG fonts. Given that SVG is scalable in general this should be achievable.
if (isSVGFont())
- return 0;
+ return nullptr;
return platformCreateScaledFontData(fontDescription, scaleFactor);
}
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/SimpleFontData.h b/chromium/third_party/WebKit/Source/platform/fonts/SimpleFontData.h
index bd2201676d5..8768872d8b9 100644
--- a/chromium/third_party/WebKit/Source/platform/fonts/SimpleFontData.h
+++ b/chromium/third_party/WebKit/Source/platform/fonts/SimpleFontData.h
@@ -30,7 +30,6 @@
#include "platform/fonts/FontData.h"
#include "platform/fonts/FontMetrics.h"
#include "platform/fonts/FontPlatformData.h"
-#include "platform/fonts/GlyphBuffer.h"
#include "platform/fonts/GlyphMetricsMap.h"
#include "platform/fonts/GlyphPageTreeNode.h"
#include "platform/fonts/TypesettingFeatures.h"
@@ -57,7 +56,7 @@ enum Pitch { UnknownPitch, FixedPitch, VariablePitch };
class PLATFORM_EXPORT SimpleFontData : public FontData {
public:
// Used to create platform fonts.
- static PassRefPtr<SimpleFontData> create(const FontPlatformData& platformData, PassRefPtr<CustomFontData> customData = 0, bool isTextOrientationFallback = false)
+ static PassRefPtr<SimpleFontData> create(const FontPlatformData& platformData, PassRefPtr<CustomFontData> customData = nullptr, bool isTextOrientationFallback = false)
{
return adoptRef(new SimpleFontData(platformData, customData, isTextOrientationFallback));
}
@@ -136,7 +135,6 @@ public:
void setZeroGlyph(Glyph zeroGlyph) { m_zeroGlyph = zeroGlyph; }
virtual const SimpleFontData* fontDataForCharacter(UChar32) const OVERRIDE;
- virtual bool containsCharacters(const UChar*, int length) const OVERRIDE;
Glyph glyphForCharacter(UChar32) const;
@@ -148,12 +146,13 @@ public:
virtual bool isLoading() const OVERRIDE { return m_customFontData ? m_customFontData->isLoading() : false; }
virtual bool isLoadingFallback() const OVERRIDE { return m_customFontData ? m_customFontData->isLoadingFallback() : false; }
virtual bool isSegmented() const OVERRIDE;
+ virtual bool shouldSkipDrawing() const OVERRIDE { return m_customFontData && m_customFontData->shouldSkipDrawing(); }
const GlyphData& missingGlyphData() const { return m_missingGlyphData; }
void setMissingGlyphData(const GlyphData& glyphData) { m_missingGlyphData = glyphData; }
#ifndef NDEBUG
- virtual String description() const;
+ virtual String description() const OVERRIDE;
#endif
#if OS(MACOSX)
@@ -165,22 +164,19 @@ public:
CFDictionaryRef getCFStringAttributes(TypesettingFeatures, FontOrientation) const;
#endif
-#if OS(MACOSX) || USE(HARFBUZZ)
bool canRenderCombiningCharacterSequence(const UChar*, size_t) const;
-#endif
-
- bool applyTransforms(GlyphBufferGlyph*, GlyphBufferAdvance*, size_t, TypesettingFeatures) const
- {
- return false;
- }
PassRefPtr<CustomFontData> customFontData() const { return m_customFontData; }
-private:
+ // Implemented by the platform.
+ virtual bool fillGlyphPage(GlyphPage* pageToFill, unsigned offset, unsigned length, UChar* buffer, unsigned bufferLength) const;
+
+protected:
SimpleFontData(const FontPlatformData&, PassRefPtr<CustomFontData> customData, bool isTextOrientationFallback = false);
SimpleFontData(PassRefPtr<CustomFontData> customData, float fontSize, bool syntheticBold, bool syntheticItalic);
+private:
void platformInit();
void platformGlyphInit();
void platformCharWidthInit();
@@ -249,9 +245,7 @@ private:
mutable HashMap<unsigned, RetainPtr<CFDictionaryRef> > m_CFStringAttributes;
#endif
-#if OS(MACOSX) || USE(HARFBUZZ)
mutable OwnPtr<HashMap<String, bool> > m_combiningCharacterSequenceSupport;
-#endif
};
ALWAYS_INLINE FloatRect SimpleFontData::boundsForGlyph(Glyph glyph) const
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/WidthCache.h b/chromium/third_party/WebKit/Source/platform/fonts/WidthCache.h
index 82f1b1e3d6d..7c47babf978 100644
--- a/chromium/third_party/WebKit/Source/platform/fonts/WidthCache.h
+++ b/chromium/third_party/WebKit/Source/platform/fonts/WidthCache.h
@@ -26,6 +26,7 @@
#ifndef WidthCache_h
#define WidthCache_h
+#include "platform/geometry/IntRectExtent.h"
#include "platform/text/TextRun.h"
#include "wtf/Forward.h"
#include "wtf/HashFunctions.h"
@@ -37,6 +38,16 @@ namespace WebCore {
struct GlyphOverflow;
+struct WidthCacheEntry {
+ WidthCacheEntry()
+ {
+ width = std::numeric_limits<float>::quiet_NaN();
+ }
+ bool isValid() const { return !std::isnan(width); }
+ float width;
+ IntRectExtent glyphBounds;
+};
+
class WidthCache {
private:
// Used to optimize small strings as hash table keys. Avoids malloc'ing an out-of-line StringImpl.
@@ -119,20 +130,8 @@ public:
{
}
- float* add(const TextRun& run, float entry, bool hasKerningOrLigatures, bool hasWordSpacingOrLetterSpacing, GlyphOverflow* glyphOverflow)
+ WidthCacheEntry* add(const TextRun& run, WidthCacheEntry entry)
{
- // The width cache is not really profitable unless we're doing expensive glyph transformations.
- if (!hasKerningOrLigatures)
- return 0;
- // Word spacing and letter spacing can change the width of a word.
- if (hasWordSpacingOrLetterSpacing)
- return 0;
- // Since this is just a width cache, we don't have enough information to satisfy glyph queries.
- if (glyphOverflow)
- return 0;
- // If we allow tabs and a tab occurs inside a word, the width of the word varies based on its position on the line.
- if (run.allowTabs())
- return 0;
if (static_cast<unsigned>(run.length()) > SmallStringKey::capacity())
return 0;
@@ -151,15 +150,15 @@ public:
}
private:
- float* addSlowCase(const TextRun& run, float entry)
+ WidthCacheEntry* addSlowCase(const TextRun& run, WidthCacheEntry entry)
{
int length = run.length();
bool isNewEntry;
- float *value;
+ WidthCacheEntry *value;
if (length == 1) {
SingleCharMap::AddResult addResult = m_singleCharMap.add(run[0], entry);
isNewEntry = addResult.isNewEntry;
- value = &addResult.iterator->value;
+ value = &addResult.storedValue->value;
} else {
SmallStringKey smallStringKey;
if (run.is8Bit())
@@ -169,7 +168,7 @@ private:
Map::AddResult addResult = m_map.add(smallStringKey, entry);
isNewEntry = addResult.isNewEntry;
- value = &addResult.iterator->value;
+ value = &addResult.storedValue->value;
}
// Cache hit: ramp up by sampling the next few words.
@@ -192,8 +191,8 @@ private:
return 0;
}
- typedef HashMap<SmallStringKey, float, SmallStringKeyHash, SmallStringKeyHashTraits> Map;
- typedef HashMap<uint32_t, float, DefaultHash<uint32_t>::Hash, WTF::UnsignedWithZeroKeyHashTraits<uint32_t> > SingleCharMap;
+ typedef HashMap<SmallStringKey, WidthCacheEntry, SmallStringKeyHash, SmallStringKeyHashTraits> Map;
+ typedef HashMap<uint32_t, WidthCacheEntry, DefaultHash<uint32_t>::Hash, WTF::UnsignedWithZeroKeyHashTraits<uint32_t> > SingleCharMap;
static const int s_minInterval = -3; // A cache hit pays for about 3 cache misses.
static const int s_maxInterval = 20; // Sampling at this interval has almost no overhead.
static const unsigned s_maxSize = 500000; // Just enough to guard against pathological growth.
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/WidthIterator.cpp b/chromium/third_party/WebKit/Source/platform/fonts/WidthIterator.cpp
index b871cb95aa0..8816fd8158f 100644
--- a/chromium/third_party/WebKit/Source/platform/fonts/WidthIterator.cpp
+++ b/chromium/third_party/WebKit/Source/platform/fonts/WidthIterator.cpp
@@ -22,6 +22,8 @@
#include "config.h"
#include "platform/fonts/WidthIterator.h"
+#include "platform/fonts/Character.h"
+#include "platform/fonts/FontPlatformFeatures.h"
#include "platform/fonts/GlyphBuffer.h"
#include "platform/fonts/Latin1TextIterator.h"
#include "platform/fonts/SimpleFontData.h"
@@ -41,7 +43,7 @@ WidthIterator::WidthIterator(const Font* font, const TextRun& run, HashSet<const
, m_runWidthSoFar(0)
, m_isAfterExpansion(!run.allowsLeadingExpansion())
, m_finalRoundingWidth(0)
- , m_typesettingFeatures(font->typesettingFeatures())
+ , m_typesettingFeatures(font->fontDescription().typesettingFeatures())
, m_fallbackFonts(fallbackFonts)
, m_accountForGlyphBounds(accountForGlyphBounds)
, m_maxGlyphBoundingBoxY(numeric_limits<float>::min())
@@ -57,7 +59,7 @@ WidthIterator::WidthIterator(const Font* font, const TextRun& run, HashSet<const
m_expansionPerOpportunity = 0;
else {
bool isAfterExpansion = m_isAfterExpansion;
- unsigned expansionOpportunityCount = m_run.is8Bit() ? Font::expansionOpportunityCount(m_run.characters8(), m_run.length(), m_run.ltr() ? LTR : RTL, isAfterExpansion) : Font::expansionOpportunityCount(m_run.characters16(), m_run.length(), m_run.ltr() ? LTR : RTL, isAfterExpansion);
+ unsigned expansionOpportunityCount = m_run.is8Bit() ? Character::expansionOpportunityCount(m_run.characters8(), m_run.length(), m_run.direction(), isAfterExpansion) : Character::expansionOpportunityCount(m_run.characters16(), m_run.length(), m_run.direction(), isAfterExpansion);
if (isAfterExpansion && !m_run.allowsTrailingExpansion())
expansionOpportunityCount--;
@@ -96,7 +98,7 @@ public:
typedef Vector<pair<int, OriginalAdvancesForCharacterTreatedAsSpace>, 64> CharactersTreatedAsSpace;
-static inline float applyFontTransforms(GlyphBuffer* glyphBuffer, bool ltr, unsigned& lastGlyphCount, const SimpleFontData* fontData, TypesettingFeatures typesettingFeatures, CharactersTreatedAsSpace& charactersTreatedAsSpace)
+static inline float applyFontTransforms(GlyphBuffer* glyphBuffer, unsigned& lastGlyphCount, TypesettingFeatures typesettingFeatures, CharactersTreatedAsSpace& charactersTreatedAsSpace)
{
ASSERT(typesettingFeatures & (Kerning | Ligatures));
@@ -107,19 +109,11 @@ static inline float applyFontTransforms(GlyphBuffer* glyphBuffer, bool ltr, unsi
if (glyphBuffer->size() <= lastGlyphCount + 1)
return 0;
- GlyphBufferAdvance* advances = glyphBuffer->advances(0);
+ FloatSize* advances = glyphBuffer->advances(0);
float widthDifference = 0;
for (unsigned i = lastGlyphCount; i < glyphBufferSize; ++i)
widthDifference -= advances[i].width();
- if (!ltr)
- glyphBuffer->reverse(lastGlyphCount, glyphBufferSize - lastGlyphCount);
-
- fontData->applyTransforms(glyphBuffer->glyphs(lastGlyphCount), advances + lastGlyphCount, glyphBufferSize - lastGlyphCount, typesettingFeatures);
-
- if (!ltr)
- glyphBuffer->reverse(lastGlyphCount, glyphBufferSize - lastGlyphCount);
-
for (size_t i = 0; i < charactersTreatedAsSpace.size(); ++i) {
int spaceOffset = charactersTreatedAsSpace[i].first;
const OriginalAdvancesForCharacterTreatedAsSpace& originalAdvances = charactersTreatedAsSpace[i].second;
@@ -140,7 +134,7 @@ template <typename TextIterator>
inline unsigned WidthIterator::advanceInternal(TextIterator& textIterator, GlyphBuffer* glyphBuffer)
{
bool rtl = m_run.rtl();
- bool hasExtraSpacing = (m_font->letterSpacing() || m_font->wordSpacing() || m_expansion) && !m_run.spacingDisabled();
+ bool hasExtraSpacing = (m_font->fontDescription().letterSpacing() || m_font->fontDescription().wordSpacing() || m_expansion) && !m_run.spacingDisabled();
float widthSinceLastRounding = m_runWidthSoFar;
m_runWidthSoFar = floorf(m_runWidthSoFar);
@@ -184,15 +178,16 @@ inline unsigned WidthIterator::advanceInternal(TextIterator& textIterator, Glyph
if (fontData != lastFontData && width) {
if (shouldApplyFontTransforms())
- m_runWidthSoFar += applyFontTransforms(glyphBuffer, m_run.ltr(), lastGlyphCount, lastFontData, m_typesettingFeatures, charactersTreatedAsSpace);
+ m_runWidthSoFar += applyFontTransforms(glyphBuffer, lastGlyphCount, m_typesettingFeatures, charactersTreatedAsSpace);
lastFontData = fontData;
if (m_fallbackFonts && fontData != primaryFont) {
// FIXME: This does a little extra work that could be avoided if
// glyphDataForCharacter() returned whether it chose to use a small caps font.
- if (!m_font->isSmallCaps() || character == toUpper(character))
+ if (m_font->fontDescription().variant() == FontVariantNormal || character == toUpper(character))
m_fallbackFonts->add(fontData);
else {
+ ASSERT(m_font->fontDescription().variant() == FontVariantSmallCaps);
const GlyphData& uppercaseGlyphData = m_font->glyphDataForCharacter(toUpper(character), rtl);
if (uppercaseGlyphData.fontData != primaryFont)
m_fallbackFonts->add(uppercaseGlyphData.fontData);
@@ -202,12 +197,12 @@ inline unsigned WidthIterator::advanceInternal(TextIterator& textIterator, Glyph
if (hasExtraSpacing) {
// Account for letter-spacing.
- if (width && m_font->letterSpacing())
- width += m_font->letterSpacing();
+ if (width && m_font->fontDescription().letterSpacing())
+ width += m_font->fontDescription().letterSpacing();
- static bool expandAroundIdeographs = Font::canExpandAroundIdeographsInComplexText();
- bool treatAsSpace = Font::treatAsSpace(character);
- if (treatAsSpace || (expandAroundIdeographs && Font::isCJKIdeographOrSymbol(character))) {
+ static bool expandAroundIdeographs = FontPlatformFeatures::canExpandAroundIdeographsInComplexText();
+ bool treatAsSpace = Character::treatAsSpace(character);
+ if (treatAsSpace || (expandAroundIdeographs && Character::isCJKIdeographOrSymbol(character))) {
// Distribute the run's total expansion evenly over all expansion opportunities in the run.
if (m_expansion) {
float previousExpansion = m_expansion;
@@ -238,15 +233,18 @@ inline unsigned WidthIterator::advanceInternal(TextIterator& textIterator, Glyph
// Account for word spacing.
// We apply additional space between "words" by adding width to the space character.
- if (treatAsSpace && (character != '\t' || !m_run.allowTabs()) && (textIterator.currentCharacter() || character == noBreakSpace) && m_font->wordSpacing())
- width += m_font->wordSpacing();
+ if (treatAsSpace && (character != '\t' || !m_run.allowTabs()) && (textIterator.currentCharacter() || character == noBreakSpace) && m_font->fontDescription().wordSpacing())
+ width += m_font->fontDescription().wordSpacing();
} else
m_isAfterExpansion = false;
}
- if (shouldApplyFontTransforms() && glyphBuffer && Font::treatAsSpace(character))
+ if (shouldApplyFontTransforms() && glyphBuffer && Character::treatAsSpace(character)) {
charactersTreatedAsSpace.append(make_pair(glyphBuffer->size(),
- OriginalAdvancesForCharacterTreatedAsSpace(character == ' ', glyphBuffer->size() ? glyphBuffer->advanceAt(glyphBuffer->size() - 1) : 0, width)));
+ OriginalAdvancesForCharacterTreatedAsSpace(character == ' ',
+ glyphBuffer->size() ? glyphBuffer->advanceAt(glyphBuffer->size() - 1).width() : 0,
+ width)));
+ }
if (m_accountForGlyphBounds) {
bounds = fontData->boundsForGlyph(glyph);
@@ -254,7 +252,7 @@ inline unsigned WidthIterator::advanceInternal(TextIterator& textIterator, Glyph
m_firstGlyphOverflow = max<float>(0, -bounds.x());
}
- if (m_forTextEmphasis && !Font::canReceiveTextEmphasis(character))
+ if (m_forTextEmphasis && !Character::canReceiveTextEmphasis(character))
glyph = 0;
// Advance past the character we just dealt with.
@@ -264,7 +262,7 @@ inline unsigned WidthIterator::advanceInternal(TextIterator& textIterator, Glyph
// Force characters that are used to determine word boundaries for the rounding hack
// to be integer width, so following words will start on an integer boundary.
- if (m_run.applyWordRounding() && Font::isRoundingHackCharacter(character)) {
+ if (m_run.applyWordRounding() && Character::isRoundingHackCharacter(character)) {
width = ceilf(width);
// Since widthSinceLastRounding can lose precision if we include measurements for
@@ -277,7 +275,7 @@ inline unsigned WidthIterator::advanceInternal(TextIterator& textIterator, Glyph
} else {
// Check to see if the next character is a "rounding hack character", if so, adjust
// width so that the total run width will be on an integer boundary.
- if ((m_run.applyWordRounding() && textIterator.currentCharacter() < m_run.length() && Font::isRoundingHackCharacter(*(textIterator.characters())))
+ if ((m_run.applyWordRounding() && textIterator.currentCharacter() < m_run.length() && Character::isRoundingHackCharacter(*(textIterator.characters())))
|| (m_run.applyRunRounding() && textIterator.currentCharacter() >= m_run.length())) {
float totalWidth = widthSinceLastRounding + width;
widthSinceLastRounding = ceilf(totalWidth);
@@ -301,7 +299,7 @@ inline unsigned WidthIterator::advanceInternal(TextIterator& textIterator, Glyph
}
if (shouldApplyFontTransforms())
- m_runWidthSoFar += applyFontTransforms(glyphBuffer, m_run.ltr(), lastGlyphCount, lastFontData, m_typesettingFeatures, charactersTreatedAsSpace);
+ m_runWidthSoFar += applyFontTransforms(glyphBuffer, lastGlyphCount, m_typesettingFeatures, charactersTreatedAsSpace);
unsigned consumedCharacters = textIterator.currentCharacter() - m_currentCharacter;
m_currentCharacter = textIterator.currentCharacter();
@@ -335,7 +333,7 @@ bool WidthIterator::advanceOneCharacter(float& width, GlyphBuffer& glyphBuffer)
advance(m_currentCharacter + 1, &glyphBuffer);
float w = 0;
for (unsigned i = oldSize; i < glyphBuffer.size(); ++i)
- w += glyphBuffer.advanceAt(i);
+ w += glyphBuffer.advanceAt(i).width();
width = w;
return glyphBuffer.size() > oldSize;
}
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/WidthIterator.h b/chromium/third_party/WebKit/Source/platform/fonts/WidthIterator.h
index e8f94207845..bd54b164abf 100644
--- a/chromium/third_party/WebKit/Source/platform/fonts/WidthIterator.h
+++ b/chromium/third_party/WebKit/Source/platform/fonts/WidthIterator.h
@@ -55,15 +55,13 @@ public:
float runWidthSoFar() const { return m_runWidthSoFar; }
#if ENABLE(SVG_FONTS)
- String lastGlyphName() const { return m_lastGlyphName; }
- void setLastGlyphName(const String& name) { m_lastGlyphName = name; }
Vector<SVGGlyph::ArabicForm>& arabicForms() { return m_arabicForms; }
#endif
static bool supportsTypesettingFeatures(const Font& font)
{
- return !font.typesettingFeatures();
+ return !font.fontDescription().typesettingFeatures();
}
const Font* m_font;
@@ -78,7 +76,6 @@ public:
float m_finalRoundingWidth;
#if ENABLE(SVG_FONTS)
- String m_lastGlyphName;
Vector<SVGGlyph::ArabicForm> m_arabicForms;
#endif
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/android/FontCacheAndroid.cpp b/chromium/third_party/WebKit/Source/platform/fonts/android/FontCacheAndroid.cpp
index 58ca789213f..72c649d07ab 100644
--- a/chromium/third_party/WebKit/Source/platform/fonts/android/FontCacheAndroid.cpp
+++ b/chromium/third_party/WebKit/Source/platform/fonts/android/FontCacheAndroid.cpp
@@ -64,15 +64,16 @@ static AtomicString getFamilyNameForCharacter(UChar32 c, UScriptCode script)
SkString skiaFamilyName;
if (!SkGetFallbackFamilyNameForChar(c, locale, &skiaFamilyName) || skiaFamilyName.isEmpty())
- return AtomicString();
+ return emptyAtom;
+
return skiaFamilyName.c_str();
}
-PassRefPtr<SimpleFontData> FontCache::platformFallbackForCharacter(const FontDescription& fontDescription, UChar32 c, const SimpleFontData*, bool)
+PassRefPtr<SimpleFontData> FontCache::fallbackFontForCharacter(const FontDescription& fontDescription, UChar32 c, const SimpleFontData*)
{
AtomicString familyName = getFamilyNameForCharacter(c, fontDescription.script());
if (familyName.isEmpty())
- return 0;
+ return getLastResortFallbackFont(fontDescription, DoNotRetain);
return fontDataFromFontPlatformData(getFontPlatformData(fontDescription, familyName), DoNotRetain);
}
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/android/FontCacheAndroidTest.cpp b/chromium/third_party/WebKit/Source/platform/fonts/android/FontCacheAndroidTest.cpp
new file mode 100644
index 00000000000..db0f122bedd
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/platform/fonts/android/FontCacheAndroidTest.cpp
@@ -0,0 +1,29 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "config.h"
+#include "platform/fonts/FontCache.h"
+
+#include "platform/fonts/SimpleFontData.h"
+#include <gtest/gtest.h>
+
+namespace WebCore {
+
+TEST(FontCacheAndroid, fallbackFontForCharacter)
+{
+ // A Latin character in the common locale system font, but not in the
+ // Chinese locale-preferred font.
+ const UChar32 testChar = 228;
+
+ FontDescription fontDescription;
+ fontDescription.setScript(USCRIPT_SIMPLIFIED_HAN);
+ fontDescription.setGenericFamily(FontDescription::StandardFamily);
+
+ FontCache* fontCache = FontCache::fontCache();
+ ASSERT_TRUE(fontCache);
+ RefPtr<SimpleFontData> fontData = fontCache->fallbackFontForCharacter(fontDescription, testChar, 0);
+ EXPECT_TRUE(fontData);
+}
+
+} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/cocoa/FontPlatformDataCocoa.mm b/chromium/third_party/WebKit/Source/platform/fonts/cocoa/FontPlatformDataCocoa.mm
index 5d76c1a5b14..2d3a5da6a3d 100644
--- a/chromium/third_party/WebKit/Source/platform/fonts/cocoa/FontPlatformDataCocoa.mm
+++ b/chromium/third_party/WebKit/Source/platform/fonts/cocoa/FontPlatformDataCocoa.mm
@@ -30,6 +30,7 @@
#if OS(MACOSX)
#import "platform/fonts/harfbuzz/HarfBuzzFace.h"
+#include "third_party/skia/include/ports/SkTypeface_mac.h"
#endif
namespace WebCore {
@@ -37,7 +38,7 @@ namespace WebCore {
// These CoreText Text Spacing feature selectors are not defined in CoreText.
enum TextSpacingCTFeatureSelector { TextSpacingProportional, TextSpacingFullWidth, TextSpacingHalfWidth, TextSpacingThirdWidth, TextSpacingQuarterWidth };
-FontPlatformData::FontPlatformData(NSFont *nsFont, float size, bool isPrinterFont, bool syntheticBold, bool syntheticOblique, FontOrientation orientation, FontWidthVariant widthVariant)
+FontPlatformData::FontPlatformData(NSFont *nsFont, float size, bool syntheticBold, bool syntheticOblique, FontOrientation orientation, FontWidthVariant widthVariant)
: m_syntheticBold(syntheticBold)
, m_syntheticOblique(syntheticOblique)
, m_orientation(orientation)
@@ -46,13 +47,12 @@ FontPlatformData::FontPlatformData(NSFont *nsFont, float size, bool isPrinterFon
, m_font(nsFont)
, m_isColorBitmapFont(false)
, m_isCompositeFontReference(false)
- , m_isPrinterFont(isPrinterFont)
{
ASSERT_ARG(nsFont, nsFont);
CGFontRef cgFont = 0;
loadFont(nsFont, size, m_font, cgFont);
-
+
#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
// FIXME: Chromium: The following code isn't correct for the Chromium port since the sandbox might
// have blocked font loading, in which case we'll only have the real loaded font file after the call to loadFont().
@@ -87,6 +87,7 @@ void FontPlatformData::platformDataInit(const FontPlatformData& f)
#if OS(MACOSX)
m_inMemoryFont = f.m_inMemoryFont;
m_harfBuzzFace = f.m_harfBuzzFace;
+ m_typeface = f.m_typeface;
#endif
}
@@ -104,6 +105,7 @@ const FontPlatformData& FontPlatformData::platformDataAssign(const FontPlatformD
#if OS(MACOSX)
m_inMemoryFont = f.m_inMemoryFont;
m_harfBuzzFace = f.m_harfBuzzFace;
+ m_typeface = f.m_typeface;
#endif
return *this;
}
@@ -128,11 +130,11 @@ void FontPlatformData::setFont(NSFont *font)
CFRelease(m_font);
m_font = font;
m_size = [font pointSize];
-
+
CGFontRef cgFont = 0;
NSFont* loadedFont = 0;
loadFont(m_font, m_size, loadedFont, cgFont);
-
+
#if OS(MACOSX)
// If loadFont replaced m_font with a fallback font, then release the
// previous font to counter the retain above. Then retain the new font.
@@ -142,7 +144,7 @@ void FontPlatformData::setFont(NSFont *font)
m_font = loadedFont;
}
#endif
-
+
m_cgFont.adoptCF(cgFont);
#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
{
@@ -278,6 +280,14 @@ CTFontRef FontPlatformData::ctFont() const
return m_CTFont.get();
}
+SkTypeface* FontPlatformData::typeface() const{
+ if (m_typeface)
+ return m_typeface.get();
+
+ m_typeface = adoptRef(SkCreateTypefaceFromCTFont(ctFont()));
+ return m_typeface.get();
+}
+
#if OS(MACOSX)
static bool isAATFont(CTFontRef ctFont)
{
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/harfbuzz/FontHarfBuzz.cpp b/chromium/third_party/WebKit/Source/platform/fonts/harfbuzz/FontHarfBuzz.cpp
index f4ffeb69c83..d9d77dbc443 100644
--- a/chromium/third_party/WebKit/Source/platform/fonts/harfbuzz/FontHarfBuzz.cpp
+++ b/chromium/third_party/WebKit/Source/platform/fonts/harfbuzz/FontHarfBuzz.cpp
@@ -32,6 +32,7 @@
#include "platform/fonts/Font.h"
#include "platform/NotImplemented.h"
+#include "platform/fonts/FontPlatformFeatures.h"
#include "platform/fonts/SimpleFontData.h"
#include "platform/fonts/harfbuzz/HarfBuzzShaper.h"
#include "platform/fonts/GlyphBuffer.h"
@@ -45,52 +46,55 @@
namespace WebCore {
-bool Font::canReturnFallbackFontsForComplexText()
+bool FontPlatformFeatures::canReturnFallbackFontsForComplexText()
{
return false;
}
-bool Font::canExpandAroundIdeographsInComplexText()
+bool FontPlatformFeatures::canExpandAroundIdeographsInComplexText()
{
return false;
}
-
static void paintGlyphs(GraphicsContext* gc, const SimpleFontData* font,
- const GlyphBufferGlyph* glyphs, unsigned numGlyphs,
+ const Glyph* glyphs, unsigned numGlyphs,
SkPoint* pos, const FloatRect& textRect)
{
TextDrawingModeFlags textMode = gc->textDrawingMode();
// We draw text up to two times (once for fill, once for stroke).
if (textMode & TextModeFill) {
- SkPaint paint;
- gc->setupPaintForFilling(&paint);
+ SkPaint paint = gc->fillPaint();
font->platformData().setupPaint(&paint, gc);
gc->adjustTextRenderMode(&paint);
paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
- gc->drawPosText(glyphs, numGlyphs << 1, pos, textRect, paint);
+ gc->drawPosText(glyphs, numGlyphs * sizeof(Glyph), pos, textRect, paint);
}
if ((textMode & TextModeStroke)
&& gc->strokeStyle() != NoStroke
&& gc->strokeThickness() > 0) {
- SkPaint paint;
- gc->setupPaintForStroking(&paint);
+ SkPaint paint = gc->strokePaint();
font->platformData().setupPaint(&paint, gc);
gc->adjustTextRenderMode(&paint);
paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
if (textMode & TextModeFill) {
- // If we also filled, we don't want to draw shadows twice.
- // See comment in FontChromiumWin.cpp::paintSkiaText() for more details.
- // Since we use the looper for shadows, we remove it (if any) now.
+ // If there is a shadow and we filled above, there will already be
+ // a shadow. We don't want to draw it again or it will be too dark
+ // and it will go on top of the fill.
+ //
+ // Note that this isn't strictly correct, since the stroke could be
+ // very thick and the shadow wouldn't account for this. The "right"
+ // thing would be to draw to a new layer and then draw that layer
+ // with a shadow. But this is a lot of extra work for something
+ // that isn't normally an issue.
paint.setLooper(0);
}
- gc->drawPosText(glyphs, numGlyphs << 1, pos, textRect, paint);
+ gc->drawPosText(glyphs, numGlyphs * sizeof(Glyph), pos, textRect, paint);
}
}
@@ -98,8 +102,6 @@ void Font::drawGlyphs(GraphicsContext* gc, const SimpleFontData* font,
const GlyphBuffer& glyphBuffer, unsigned from, unsigned numGlyphs,
const FloatPoint& point, const FloatRect& textRect) const
{
- SkASSERT(sizeof(GlyphBufferGlyph) == sizeof(uint16_t)); // compile-time assert
-
SkScalar x = SkFloatToScalar(point.x());
SkScalar y = SkFloatToScalar(point.y());
@@ -123,7 +125,7 @@ void Font::drawGlyphs(GraphicsContext* gc, const SimpleFontData* font,
while (glyphIndex < numGlyphs) {
unsigned chunkLength = std::min(kMaxBufferLength, numGlyphs - glyphIndex);
- const GlyphBufferGlyph* glyphs = glyphBuffer.glyphs(from + glyphIndex);
+ const Glyph* glyphs = glyphBuffer.glyphs(from + glyphIndex);
translations.resize(chunkLength);
verticalData->getVerticalTranslationsForGlyphs(font, &glyphs[0], chunkLength, reinterpret_cast<float*>(&translations[0]));
@@ -135,7 +137,7 @@ void Font::drawGlyphs(GraphicsContext* gc, const SimpleFontData* font,
pos[i].set(
x + SkIntToScalar(lroundf(translations[i].x())),
y + -SkIntToScalar(-lroundf(currentWidth - translations[i].y())));
- currentWidth += glyphBuffer.advanceAt(from + glyphIndex);
+ currentWidth += glyphBuffer.advanceAt(from + glyphIndex).width();
}
horizontalOffset += currentWidth;
paintGlyphs(gc, font, glyphs, chunkLength, pos, textRect);
@@ -151,14 +153,14 @@ void Font::drawGlyphs(GraphicsContext* gc, const SimpleFontData* font,
// text drawing can proceed faster. However, it's unclear when those
// patches may be upstreamed to WebKit so we always use the slower path
// here.
- const GlyphBufferAdvance* adv = glyphBuffer.advances(from);
+ const FloatSize* adv = glyphBuffer.advances(from);
for (unsigned i = 0; i < numGlyphs; i++) {
pos[i].set(x, y);
x += SkFloatToScalar(adv[i].width());
y += SkFloatToScalar(adv[i].height());
}
- const GlyphBufferGlyph* glyphs = glyphBuffer.glyphs(from);
+ const Glyph* glyphs = glyphBuffer.glyphs(from);
paintGlyphs(gc, font, glyphs, numGlyphs, pos, textRect);
}
@@ -179,22 +181,43 @@ void Font::drawComplexText(GraphicsContext* gc, const TextRunPaintInfo& runInfo,
GlyphBuffer glyphBuffer;
HarfBuzzShaper shaper(this, runInfo.run);
shaper.setDrawRange(runInfo.from, runInfo.to);
- if (!shaper.shape(&glyphBuffer))
+ if (!shaper.shape(&glyphBuffer) || glyphBuffer.isEmpty())
return;
FloatPoint adjustedPoint = shaper.adjustStartPoint(point);
drawGlyphBuffer(gc, runInfo, glyphBuffer, adjustedPoint);
}
-void Font::drawEmphasisMarksForComplexText(GraphicsContext* /* context */, const TextRunPaintInfo& /* runInfo */, const AtomicString& /* mark */, const FloatPoint& /* point */) const
+void Font::drawEmphasisMarksForComplexText(GraphicsContext* context, const TextRunPaintInfo& runInfo, const AtomicString& mark, const FloatPoint& point) const
{
- notImplemented();
+ GlyphBuffer glyphBuffer;
+
+ float initialAdvance = getGlyphsAndAdvancesForComplexText(runInfo, glyphBuffer, ForTextEmphasis);
+
+ if (glyphBuffer.isEmpty())
+ return;
+
+ drawEmphasisMarks(context, runInfo, glyphBuffer, mark, FloatPoint(point.x() + initialAdvance, point.y()));
}
-float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* /* fallbackFonts */, GlyphOverflow* /* glyphOverflow */) const
+float Font::getGlyphsAndAdvancesForComplexText(const TextRunPaintInfo& runInfo, GlyphBuffer& glyphBuffer, ForTextEmphasisOrNot forTextEmphasis) const
+{
+ HarfBuzzShaper shaper(this, runInfo.run, HarfBuzzShaper::ForTextEmphasis);
+ shaper.setDrawRange(runInfo.from, runInfo.to);
+ shaper.shape(&glyphBuffer);
+ return 0;
+}
+
+float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* /* fallbackFonts */, IntRectExtent* glyphBounds) const
{
HarfBuzzShaper shaper(this, run);
if (!shaper.shape())
return 0;
+
+ glyphBounds->setTop(floorf(-shaper.glyphBoundingBox().top()));
+ glyphBounds->setBottom(ceilf(shaper.glyphBoundingBox().bottom()));
+ glyphBounds->setLeft(std::max<int>(0, floorf(-shaper.glyphBoundingBox().left())));
+ glyphBounds->setRight(std::max<int>(0, ceilf(shaper.glyphBoundingBox().right() - shaper.totalWidth())));
+
return shaper.totalWidth();
}
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/harfbuzz/FontPlatformDataHarfBuzz.cpp b/chromium/third_party/WebKit/Source/platform/fonts/harfbuzz/FontPlatformDataHarfBuzz.cpp
index 2c8ec376e57..5320c1bc907 100644
--- a/chromium/third_party/WebKit/Source/platform/fonts/harfbuzz/FontPlatformDataHarfBuzz.cpp
+++ b/chromium/third_party/WebKit/Source/platform/fonts/harfbuzz/FontPlatformDataHarfBuzz.cpp
@@ -31,119 +31,109 @@
#include "config.h"
#include "platform/fonts/harfbuzz/FontPlatformDataHarfBuzz.h"
-#include "RuntimeEnabledFeatures.h"
#include "SkTypeface.h"
-#include "platform/LayoutTestSupport.h"
-#include "platform/NotImplemented.h"
-#include "platform/fonts/FontCache.h"
#include "platform/fonts/harfbuzz/HarfBuzzFace.h"
-
-#include "public/platform/linux/WebFontInfo.h"
-#include "public/platform/linux/WebFontRenderStyle.h"
-#include "public/platform/linux/WebSandboxSupport.h"
-#include "public/platform/Platform.h"
#include "wtf/text/WTFString.h"
namespace WebCore {
-static SkPaint::Hinting skiaHinting = SkPaint::kNormal_Hinting;
-static bool useSkiaAutoHint = true;
-static bool useSkiaBitmaps = true;
-static bool useSkiaAntiAlias = true;
-static bool useSkiaSubpixelRendering = false;
-
-void FontPlatformData::setHinting(SkPaint::Hinting hinting)
-{
- skiaHinting = hinting;
-}
-
-void FontPlatformData::setAutoHint(bool useAutoHint)
-{
- useSkiaAutoHint = useAutoHint;
-}
-
-void FontPlatformData::setUseBitmaps(bool useBitmaps)
-{
- useSkiaBitmaps = useBitmaps;
-}
-
-void FontPlatformData::setAntiAlias(bool useAntiAlias)
-{
- useSkiaAntiAlias = useAntiAlias;
-}
-
-void FontPlatformData::setSubpixelRendering(bool useSubpixelRendering)
-{
- useSkiaSubpixelRendering = useSubpixelRendering;
-}
-
FontPlatformData::FontPlatformData(WTF::HashTableDeletedValueType)
: m_textSize(0)
- , m_emSizeInFontUnits(0)
- , m_fakeBold(false)
- , m_fakeItalic(false)
+ , m_syntheticBold(false)
+ , m_syntheticItalic(false)
, m_orientation(Horizontal)
, m_isHashTableDeletedValue(true)
+#if OS(WIN)
+ , m_paintTextFlags(0)
+ , m_minSizeForAntiAlias(0)
+ , m_useSubpixelPositioning(false)
+#endif
{
}
FontPlatformData::FontPlatformData()
: m_textSize(0)
- , m_emSizeInFontUnits(0)
- , m_fakeBold(false)
- , m_fakeItalic(false)
+ , m_syntheticBold(false)
+ , m_syntheticItalic(false)
, m_orientation(Horizontal)
, m_isHashTableDeletedValue(false)
+#if OS(WIN)
+ , m_paintTextFlags(0)
+ , m_minSizeForAntiAlias(0)
+ , m_useSubpixelPositioning(false)
+#endif
{
}
-FontPlatformData::FontPlatformData(float textSize, bool fakeBold, bool fakeItalic)
+FontPlatformData::FontPlatformData(float textSize, bool syntheticBold, bool syntheticItalic)
: m_textSize(textSize)
- , m_emSizeInFontUnits(0)
- , m_fakeBold(fakeBold)
- , m_fakeItalic(fakeItalic)
+ , m_syntheticBold(syntheticBold)
+ , m_syntheticItalic(syntheticItalic)
, m_orientation(Horizontal)
, m_isHashTableDeletedValue(false)
+#if OS(WIN)
+ , m_paintTextFlags(0)
+ , m_minSizeForAntiAlias(0)
+ , m_useSubpixelPositioning(false)
+#endif
{
}
FontPlatformData::FontPlatformData(const FontPlatformData& src)
: m_typeface(src.m_typeface)
+#if !OS(WIN)
, m_family(src.m_family)
+#endif
, m_textSize(src.m_textSize)
- , m_emSizeInFontUnits(src.m_emSizeInFontUnits)
- , m_fakeBold(src.m_fakeBold)
- , m_fakeItalic(src.m_fakeItalic)
+ , m_syntheticBold(src.m_syntheticBold)
+ , m_syntheticItalic(src.m_syntheticItalic)
, m_orientation(src.m_orientation)
, m_style(src.m_style)
- , m_harfBuzzFace(0)
+ , m_harfBuzzFace(nullptr)
, m_isHashTableDeletedValue(false)
+#if OS(WIN)
+ , m_paintTextFlags(src.m_paintTextFlags)
+ , m_minSizeForAntiAlias(src.m_minSizeForAntiAlias)
+ , m_useSubpixelPositioning(src.m_useSubpixelPositioning)
+#endif
{
}
-FontPlatformData::FontPlatformData(PassRefPtr<SkTypeface> tf, const char* family, float textSize, bool fakeBold, bool fakeItalic, FontOrientation orientation, bool subpixelTextPosition)
+FontPlatformData::FontPlatformData(PassRefPtr<SkTypeface> tf, const char* family, float textSize, bool syntheticBold, bool syntheticItalic, FontOrientation orientation, bool subpixelTextPosition)
: m_typeface(tf)
+#if !OS(WIN)
, m_family(family)
+#endif
, m_textSize(textSize)
- , m_emSizeInFontUnits(0)
- , m_fakeBold(fakeBold)
- , m_fakeItalic(fakeItalic)
+ , m_syntheticBold(syntheticBold)
+ , m_syntheticItalic(syntheticItalic)
, m_orientation(orientation)
, m_isHashTableDeletedValue(false)
+#if OS(WIN)
+ , m_paintTextFlags(0)
+ , m_minSizeForAntiAlias(0)
+ , m_useSubpixelPositioning(subpixelTextPosition)
+#endif
{
querySystemForRenderStyle(subpixelTextPosition);
}
FontPlatformData::FontPlatformData(const FontPlatformData& src, float textSize)
: m_typeface(src.m_typeface)
+#if !OS(WIN)
, m_family(src.m_family)
+#endif
, m_textSize(textSize)
- , m_emSizeInFontUnits(src.m_emSizeInFontUnits)
- , m_fakeBold(src.m_fakeBold)
- , m_fakeItalic(src.m_fakeItalic)
+ , m_syntheticBold(src.m_syntheticBold)
+ , m_syntheticItalic(src.m_syntheticItalic)
, m_orientation(src.m_orientation)
- , m_harfBuzzFace(0)
+ , m_harfBuzzFace(nullptr)
, m_isHashTableDeletedValue(false)
+#if OS(WIN)
+ , m_paintTextFlags(src.m_paintTextFlags)
+ , m_minSizeForAntiAlias(src.m_minSizeForAntiAlias)
+ , m_useSubpixelPositioning(src.m_useSubpixelPositioning)
+#endif
{
querySystemForRenderStyle(FontDescription::subpixelPositioning());
}
@@ -152,26 +142,23 @@ FontPlatformData::~FontPlatformData()
{
}
-int FontPlatformData::emSizeInFontUnits() const
-{
- if (m_emSizeInFontUnits)
- return m_emSizeInFontUnits;
-
- m_emSizeInFontUnits = m_typeface->getUnitsPerEm();
- return m_emSizeInFontUnits;
-}
-
FontPlatformData& FontPlatformData::operator=(const FontPlatformData& src)
{
m_typeface = src.m_typeface;
+#if !OS(WIN)
m_family = src.m_family;
+#endif
m_textSize = src.m_textSize;
- m_fakeBold = src.m_fakeBold;
- m_fakeItalic = src.m_fakeItalic;
- m_harfBuzzFace = 0;
+ m_syntheticBold = src.m_syntheticBold;
+ m_syntheticItalic = src.m_syntheticItalic;
+ m_harfBuzzFace = nullptr;
m_orientation = src.m_orientation;
m_style = src.m_style;
- m_emSizeInFontUnits = src.m_emSizeInFontUnits;
+#if OS(WIN)
+ m_paintTextFlags = 0;
+ m_minSizeForAntiAlias = src.m_minSizeForAntiAlias;
+ m_useSubpixelPositioning = src.m_useSubpixelPositioning;
+#endif
return *this;
}
@@ -183,28 +170,6 @@ String FontPlatformData::description() const
}
#endif
-void FontPlatformData::setupPaint(SkPaint* paint, GraphicsContext*) const
-{
- paint->setAntiAlias(m_style.useAntiAlias);
- paint->setHinting(static_cast<SkPaint::Hinting>(m_style.hintStyle));
- paint->setEmbeddedBitmapText(m_style.useBitmaps);
- paint->setAutohinted(m_style.useAutoHint);
- if (m_style.useAntiAlias)
- paint->setLCDRenderText(m_style.useSubpixelRendering);
-
- // TestRunner specifically toggles the subpixel positioning flag.
- if (RuntimeEnabledFeatures::subpixelFontScalingEnabled() && !isRunningLayoutTest())
- paint->setSubpixelText(true);
- else
- paint->setSubpixelText(m_style.useSubpixelPositioning);
-
- const float ts = m_textSize >= 0 ? m_textSize : 12;
- paint->setTextSize(SkFloatToScalar(ts));
- paint->setTypeface(m_typeface.get());
- paint->setFakeBoldText(m_fakeBold);
- paint->setTextSkewX(m_fakeItalic ? -SK_Scalar1 / 4 : 0);
-}
-
SkFontID FontPlatformData::uniqueID() const
{
return m_typeface->uniqueID();
@@ -234,8 +199,8 @@ bool FontPlatformData::operator==(const FontPlatformData& a) const
return typefacesEqual
&& m_textSize == a.m_textSize
- && m_fakeBold == a.m_fakeBold
- && m_fakeItalic == a.m_fakeItalic
+ && m_syntheticBold == a.m_syntheticBold
+ && m_syntheticItalic == a.m_syntheticItalic
&& m_orientation == a.m_orientation
&& m_style == a.m_style
&& m_isHashTableDeletedValue == a.m_isHashTableDeletedValue;
@@ -243,8 +208,7 @@ bool FontPlatformData::operator==(const FontPlatformData& a) const
bool FontPlatformData::isFixedPitch() const
{
- notImplemented();
- return false;
+ return typeface() && typeface()->isFixedPitch();
}
HarfBuzzFace* FontPlatformData::harfBuzzFace() const
@@ -255,50 +219,4 @@ HarfBuzzFace* FontPlatformData::harfBuzzFace() const
return m_harfBuzzFace.get();
}
-void FontPlatformData::getRenderStyleForStrike(const char* font, int sizeAndStyle)
-{
- blink::WebFontRenderStyle style;
-
-#if OS(ANDROID)
- style.setDefaults();
-#else
- if (!font || !*font)
- style.setDefaults(); // It's probably a webfont. Take the system defaults.
- else if (blink::Platform::current()->sandboxSupport())
- blink::Platform::current()->sandboxSupport()->getRenderStyleForStrike(font, sizeAndStyle, &style);
- else
- blink::WebFontInfo::renderStyleForStrike(font, sizeAndStyle, &style);
-#endif
-
- style.toFontRenderStyle(&m_style);
-}
-
-void FontPlatformData::querySystemForRenderStyle(bool useSkiaSubpixelPositioning)
-{
- getRenderStyleForStrike(m_family.data(), (((int)m_textSize) << 2) | (m_typeface->style() & 3));
-
- // Fix FontRenderStyle::NoPreference to actual styles.
- if (m_style.useAntiAlias == FontRenderStyle::NoPreference)
- m_style.useAntiAlias = useSkiaAntiAlias;
-
- if (!m_style.useHinting)
- m_style.hintStyle = SkPaint::kNo_Hinting;
- else if (m_style.useHinting == FontRenderStyle::NoPreference)
- m_style.hintStyle = skiaHinting;
-
- if (m_style.useBitmaps == FontRenderStyle::NoPreference)
- m_style.useBitmaps = useSkiaBitmaps;
- if (m_style.useAutoHint == FontRenderStyle::NoPreference)
- m_style.useAutoHint = useSkiaAutoHint;
- if (m_style.useAntiAlias == FontRenderStyle::NoPreference)
- m_style.useAntiAlias = useSkiaAntiAlias;
- if (m_style.useSubpixelRendering == FontRenderStyle::NoPreference)
- m_style.useSubpixelRendering = useSkiaSubpixelRendering;
-
- // TestRunner specifically toggles the subpixel positioning flag.
- if (m_style.useSubpixelPositioning == FontRenderStyle::NoPreference
- || isRunningLayoutTest())
- m_style.useSubpixelPositioning = useSkiaSubpixelPositioning;
-}
-
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/harfbuzz/FontPlatformDataHarfBuzz.h b/chromium/third_party/WebKit/Source/platform/fonts/harfbuzz/FontPlatformDataHarfBuzz.h
index 0ae633b9a82..2d875a8f789 100644
--- a/chromium/third_party/WebKit/Source/platform/fonts/harfbuzz/FontPlatformDataHarfBuzz.h
+++ b/chromium/third_party/WebKit/Source/platform/fonts/harfbuzz/FontPlatformDataHarfBuzz.h
@@ -51,11 +51,6 @@ namespace WebCore {
class GraphicsContext;
class HarfBuzzFace;
-// -----------------------------------------------------------------------------
-// FontPlatformData is the handle which WebKit has on a specific face. A face
-// is the tuple of (font, size, ...etc). Here we are just wrapping a Skia
-// SkTypeface pointer and dealing with the reference counting etc.
-// -----------------------------------------------------------------------------
class PLATFORM_EXPORT FontPlatformData {
public:
// Used for deleted values in the font cache's hash tables. The hash table
@@ -65,43 +60,37 @@ public:
// set everything to 0.
FontPlatformData(WTF::HashTableDeletedValueType);
FontPlatformData();
- FontPlatformData(float textSize, bool fakeBold, bool fakeItalic);
+ FontPlatformData(float textSize, bool syntheticBold, bool syntheticItalic);
FontPlatformData(const FontPlatformData&);
- FontPlatformData(PassRefPtr<SkTypeface>, const char* name, float textSize, bool fakeBold, bool fakeItalic, FontOrientation = Horizontal, bool subpixelTextPosition = FontDescription::subpixelPositioning());
+ FontPlatformData(PassRefPtr<SkTypeface>, const char* name, float textSize, bool syntheticBold, bool syntheticItalic, FontOrientation = Horizontal, bool subpixelTextPosition = defaultUseSubpixelPositioning());
FontPlatformData(const FontPlatformData& src, float textSize);
~FontPlatformData();
String fontFamilyName() const;
-
- // -------------------------------------------------------------------------
- // Return true iff this font is monospaced (i.e. every glyph has an equal x
- // advance)
- // -------------------------------------------------------------------------
+ float size() const { return m_textSize; }
bool isFixedPitch() const;
- // -------------------------------------------------------------------------
- // Setup a Skia painting context to use this font.
- // -------------------------------------------------------------------------
- void setupPaint(SkPaint*, GraphicsContext* = 0) const;
-
- // -------------------------------------------------------------------------
- // Return Skia's unique id for this font. This encodes both the style and
- // the font's file name so refers to a single face.
- // -------------------------------------------------------------------------
- SkFontID uniqueID() const;
SkTypeface* typeface() const { return m_typeface.get(); }
-
+ HarfBuzzFace* harfBuzzFace() const;
+ SkFontID uniqueID() const;
unsigned hash() const;
- float size() const { return m_textSize; }
- int emSizeInFontUnits() const;
FontOrientation orientation() const { return m_orientation; }
void setOrientation(FontOrientation orientation) { m_orientation = orientation; }
- void setFakeBold(bool fakeBold) { m_fakeBold = fakeBold; }
- void setFakeItalic(bool fakeItalic) { m_fakeItalic = fakeItalic; }
+ void setSyntheticBold(bool syntheticBold) { m_syntheticBold = syntheticBold; }
+ void setSyntheticItalic(bool syntheticItalic) { m_syntheticItalic = syntheticItalic; }
bool operator==(const FontPlatformData&) const;
FontPlatformData& operator=(const FontPlatformData&);
bool isHashTableDeletedValue() const { return m_isHashTableDeletedValue; }
+#if OS(WIN)
+ void setMinSizeForAntiAlias(unsigned size) { m_minSizeForAntiAlias = size; }
+ unsigned minSizeForAntiAlias() const { return m_minSizeForAntiAlias; }
+ void setHinting(SkPaint::Hinting style)
+ {
+ m_style.useAutoHint = 0;
+ m_style.hintStyle = style;
+ }
+#endif
#if ENABLE(OPENTYPE_VERTICAL)
PassRefPtr<OpenTypeVerticalData> verticalData() const;
@@ -112,34 +101,40 @@ public:
String description() const;
#endif
- HarfBuzzFace* harfBuzzFace() const;
-
// The returned styles are all actual styles without FontRenderStyle::NoPreference.
const FontRenderStyle& fontRenderStyle() const { return m_style; }
+ void setupPaint(SkPaint*, GraphicsContext* = 0) const;
- // -------------------------------------------------------------------------
- // Global font preferences...
-
+#if OS(WIN)
+ int paintTextFlags() const { return m_paintTextFlags; }
+#else
static void setHinting(SkPaint::Hinting);
static void setAutoHint(bool);
static void setUseBitmaps(bool);
static void setAntiAlias(bool);
static void setSubpixelRendering(bool);
+#endif
private:
- void getRenderStyleForStrike(const char*, int);
+ bool static defaultUseSubpixelPositioning();
void querySystemForRenderStyle(bool useSkiaSubpixelPositioning);
RefPtr<SkTypeface> m_typeface;
+#if !OS(WIN)
CString m_family;
+#endif
float m_textSize;
- mutable int m_emSizeInFontUnits;
- bool m_fakeBold;
- bool m_fakeItalic;
+ bool m_syntheticBold;
+ bool m_syntheticItalic;
FontOrientation m_orientation;
FontRenderStyle m_style;
mutable RefPtr<HarfBuzzFace> m_harfBuzzFace;
bool m_isHashTableDeletedValue;
+#if OS(WIN)
+ int m_paintTextFlags;
+ bool m_useSubpixelPositioning;
+ unsigned m_minSizeForAntiAlias;
+#endif
};
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/harfbuzz/HarfBuzzFace.cpp b/chromium/third_party/WebKit/Source/platform/fonts/harfbuzz/HarfBuzzFace.cpp
index b35f636353a..306ea2c5056 100644
--- a/chromium/third_party/WebKit/Source/platform/fonts/harfbuzz/HarfBuzzFace.cpp
+++ b/chromium/third_party/WebKit/Source/platform/fonts/harfbuzz/HarfBuzzFace.cpp
@@ -82,12 +82,12 @@ HarfBuzzFace::HarfBuzzFace(FontPlatformData* platformData, uint64_t uniqueID)
, m_uniqueID(uniqueID)
, m_scriptForVerticalText(HB_SCRIPT_INVALID)
{
- HarfBuzzFaceCache::AddResult result = harfBuzzFaceCache()->add(m_uniqueID, 0);
+ HarfBuzzFaceCache::AddResult result = harfBuzzFaceCache()->add(m_uniqueID, nullptr);
if (result.isNewEntry)
- result.iterator->value = FaceCacheEntry::create(createFace());
- result.iterator->value->ref();
- m_face = result.iterator->value->face();
- m_glyphCacheForFaceCacheEntry = result.iterator->value->glyphCache();
+ result.storedValue->value = FaceCacheEntry::create(createFace());
+ result.storedValue->value->ref();
+ m_face = result.storedValue->value->face();
+ m_glyphCacheForFaceCacheEntry = result.storedValue->value->glyphCache();
}
HarfBuzzFace::~HarfBuzzFace()
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/harfbuzz/HarfBuzzFaceCoreText.cpp b/chromium/third_party/WebKit/Source/platform/fonts/harfbuzz/HarfBuzzFaceCoreText.cpp
index 96b0285d4ec..afa73103f9f 100644
--- a/chromium/third_party/WebKit/Source/platform/fonts/harfbuzz/HarfBuzzFaceCoreText.cpp
+++ b/chromium/third_party/WebKit/Source/platform/fonts/harfbuzz/HarfBuzzFaceCoreText.cpp
@@ -141,9 +141,4 @@ hb_font_t* HarfBuzzFace::createFont()
return font;
}
-GlyphBufferAdvance HarfBuzzShaper::createGlyphBufferAdvance(float width, float height)
-{
- return CGSizeMake(width, height);
-}
-
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/harfbuzz/HarfBuzzFaceSkia.cpp b/chromium/third_party/WebKit/Source/platform/fonts/harfbuzz/HarfBuzzFaceSkia.cpp
index b0daf5323db..20a22e77a80 100644
--- a/chromium/third_party/WebKit/Source/platform/fonts/harfbuzz/HarfBuzzFaceSkia.cpp
+++ b/chromium/third_party/WebKit/Source/platform/fonts/harfbuzz/HarfBuzzFaceSkia.cpp
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2012 Google Inc. All rights reserved.
+ * Copyright (c) 2014 BlackBerry Limited. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -39,7 +40,6 @@
#include "SkUtils.h"
#include "platform/fonts/FontPlatformData.h"
#include "platform/fonts/SimpleFontData.h"
-#include "platform/fonts/GlyphBuffer.h"
#include "platform/fonts/harfbuzz/HarfBuzzShaper.h"
#include "hb.h"
@@ -94,10 +94,10 @@ static hb_bool_t harfBuzzGetGlyph(hb_font_t* hbFont, void* fontData, hb_codepoin
paint->setTextEncoding(SkPaint::kUTF32_TextEncoding);
uint16_t glyph16;
paint->textToGlyphs(&unicode, sizeof(hb_codepoint_t), &glyph16);
- result.iterator->value = glyph16;
+ result.storedValue->value = glyph16;
*glyph = glyph16;
}
- *glyph = result.iterator->value;
+ *glyph = result.storedValue->value;
return !!*glyph;
}
@@ -117,6 +117,50 @@ static hb_bool_t harfBuzzGetGlyphHorizontalOrigin(hb_font_t* hbFont, void* fontD
return true;
}
+static hb_position_t harfBuzzGetGlyphHorizontalKerning(hb_font_t*, void* fontData, hb_codepoint_t leftGlyph, hb_codepoint_t rightGlyph, void*)
+{
+ HarfBuzzFontData* hbFontData = reinterpret_cast<HarfBuzzFontData*>(fontData);
+ if (hbFontData->m_paint.isVerticalText()) {
+ // We don't support cross-stream kerning
+ return 0;
+ }
+
+ SkTypeface* typeface = hbFontData->m_paint.getTypeface();
+
+ const uint16_t glyphs[2] = { static_cast<uint16_t>(leftGlyph), static_cast<uint16_t>(rightGlyph) };
+ int32_t kerningAdjustments[1] = { 0 };
+
+ if (typeface->getKerningPairAdjustments(glyphs, 2, kerningAdjustments)) {
+ SkScalar upm = SkIntToScalar(typeface->getUnitsPerEm());
+ SkScalar size = hbFontData->m_paint.getTextSize();
+ return SkiaScalarToHarfBuzzPosition(SkScalarMulDiv(SkIntToScalar(kerningAdjustments[0]), size, upm));
+ }
+
+ return 0;
+}
+
+static hb_position_t harfBuzzGetGlyphVerticalKerning(hb_font_t*, void* fontData, hb_codepoint_t topGlyph, hb_codepoint_t bottomGlyph, void*)
+{
+ HarfBuzzFontData* hbFontData = reinterpret_cast<HarfBuzzFontData*>(fontData);
+ if (!hbFontData->m_paint.isVerticalText()) {
+ // We don't support cross-stream kerning
+ return 0;
+ }
+
+ SkTypeface* typeface = hbFontData->m_paint.getTypeface();
+
+ const uint16_t glyphs[2] = { static_cast<uint16_t>(topGlyph), static_cast<uint16_t>(bottomGlyph) };
+ int32_t kerningAdjustments[1] = { 0 };
+
+ if (typeface->getKerningPairAdjustments(glyphs, 2, kerningAdjustments)) {
+ SkScalar upm = SkIntToScalar(typeface->getUnitsPerEm());
+ SkScalar size = hbFontData->m_paint.getTextSize();
+ return SkiaScalarToHarfBuzzPosition(SkScalarMulDiv(SkIntToScalar(kerningAdjustments[0]), size, upm));
+ }
+
+ return 0;
+}
+
static hb_bool_t harfBuzzGetGlyphExtents(hb_font_t* hbFont, void* fontData, hb_codepoint_t glyph, hb_glyph_extents_t* extents, void* userData)
{
HarfBuzzFontData* hbFontData = reinterpret_cast<HarfBuzzFontData*>(fontData);
@@ -135,7 +179,9 @@ static hb_font_funcs_t* harfBuzzSkiaGetFontFuncs()
harfBuzzSkiaFontFuncs = hb_font_funcs_create();
hb_font_funcs_set_glyph_func(harfBuzzSkiaFontFuncs, harfBuzzGetGlyph, 0, 0);
hb_font_funcs_set_glyph_h_advance_func(harfBuzzSkiaFontFuncs, harfBuzzGetGlyphHorizontalAdvance, 0, 0);
+ hb_font_funcs_set_glyph_h_kerning_func(harfBuzzSkiaFontFuncs, harfBuzzGetGlyphHorizontalKerning, 0, 0);
hb_font_funcs_set_glyph_h_origin_func(harfBuzzSkiaFontFuncs, harfBuzzGetGlyphHorizontalOrigin, 0, 0);
+ hb_font_funcs_set_glyph_v_kerning_func(harfBuzzSkiaFontFuncs, harfBuzzGetGlyphVerticalKerning, 0, 0);
hb_font_funcs_set_glyph_extents_func(harfBuzzSkiaFontFuncs, harfBuzzGetGlyphExtents, 0, 0);
hb_font_funcs_make_immutable(harfBuzzSkiaFontFuncs);
}
@@ -188,9 +234,4 @@ hb_font_t* HarfBuzzFace::createFont()
return font;
}
-GlyphBufferAdvance HarfBuzzShaper::createGlyphBufferAdvance(float width, float height)
-{
- return GlyphBufferAdvance(width, height);
-}
-
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/harfbuzz/HarfBuzzShaper.cpp b/chromium/third_party/WebKit/Source/platform/fonts/harfbuzz/HarfBuzzShaper.cpp
index 77f482cce26..d27c200f3d9 100644
--- a/chromium/third_party/WebKit/Source/platform/fonts/harfbuzz/HarfBuzzShaper.cpp
+++ b/chromium/third_party/WebKit/Source/platform/fonts/harfbuzz/HarfBuzzShaper.cpp
@@ -32,15 +32,21 @@
#include "config.h"
#include "platform/fonts/harfbuzz/HarfBuzzShaper.h"
-#include "RuntimeEnabledFeatures.h"
-#include "hb-icu.h"
+#include "hb.h"
+#include "platform/LayoutUnit.h"
+#include "platform/RuntimeEnabledFeatures.h"
+#include "platform/fonts/Character.h"
#include "platform/fonts/Font.h"
+#include "platform/fonts/GlyphBuffer.h"
#include "platform/fonts/harfbuzz/HarfBuzzFace.h"
#include "platform/text/SurrogatePairAwareTextIterator.h"
+#include "platform/text/TextBreakIterator.h"
+#include "wtf/Compiler.h"
#include "wtf/MathExtras.h"
#include "wtf/unicode/Unicode.h"
#include <unicode/normlzr.h>
#include <unicode/uchar.h>
+#include <unicode/uscript.h>
#include <list>
#include <map>
@@ -81,12 +87,13 @@ typedef std::map<std::wstring, CachedShapingResults*> CachedShapingResultsMap;
typedef std::list<CachedShapingResultsLRUNode*> CachedShapingResultsLRU;
struct CachedShapingResults {
- CachedShapingResults(hb_buffer_t* harfBuzzBuffer, const Font* runFont, hb_direction_t runDir);
+ CachedShapingResults(hb_buffer_t* harfBuzzBuffer, const Font* runFont, hb_direction_t runDir, const String& newLocale);
~CachedShapingResults();
hb_buffer_t* buffer;
Font font;
hb_direction_t dir;
+ String locale;
CachedShapingResultsLRU::iterator lru;
};
@@ -97,10 +104,11 @@ struct CachedShapingResultsLRUNode {
CachedShapingResultsMap::iterator entry;
};
-CachedShapingResults::CachedShapingResults(hb_buffer_t* harfBuzzBuffer, const Font* fontData, hb_direction_t dirData)
+CachedShapingResults::CachedShapingResults(hb_buffer_t* harfBuzzBuffer, const Font* fontData, hb_direction_t dirData, const String& newLocale)
: buffer(harfBuzzBuffer)
, font(*fontData)
, dir(dirData)
+ , locale(newLocale)
{
}
@@ -207,6 +215,26 @@ static inline float harfBuzzPositionToFloat(hb_position_t value)
return static_cast<float>(value) / (1 << 16);
}
+static inline unsigned countGraphemesInCluster(const UChar* normalizedBuffer, unsigned normalizedBufferLength, uint16_t startIndex, uint16_t endIndex)
+{
+ if (startIndex > endIndex) {
+ uint16_t tempIndex = startIndex;
+ startIndex = endIndex;
+ endIndex = tempIndex;
+ }
+ uint16_t length = endIndex - startIndex;
+ ASSERT(static_cast<unsigned>(startIndex + length) <= normalizedBufferLength);
+ TextBreakIterator* cursorPosIterator = cursorMovementIterator(&normalizedBuffer[startIndex], length);
+
+ int cursorPos = cursorPosIterator->current();
+ int numGraphemes = -1;
+ while (0 <= cursorPos) {
+ cursorPos = cursorPosIterator->next();
+ numGraphemes++;
+ }
+ return numGraphemes < 0 ? 0 : numGraphemes;
+}
+
inline HarfBuzzShaper::HarfBuzzRun::HarfBuzzRun(const SimpleFontData* fontData, unsigned startIndex, unsigned numCharacters, TextDirection direction, hb_script_t script)
: m_fontData(fontData)
, m_startIndex(startIndex)
@@ -289,7 +317,6 @@ int HarfBuzzShaper::HarfBuzzRun::characterIndexForXPosition(float targetX)
if (currentX <= targetX && targetX <= nextX)
return rtl() ? prevCharacterIndex : m_glyphToCharacterIndexes[glyphIndex];
currentX = nextX;
- prevAdvance = currentAdvance;
++glyphIndex;
}
@@ -339,26 +366,28 @@ static void normalizeCharacters(const TextRun& run, unsigned length, UChar* dest
UChar32 character;
U16_NEXT(source, position, length, character);
// Don't normalize tabs as they are not treated as spaces for word-end.
- if (Font::treatAsSpace(character) && character != '\t')
+ if (Character::treatAsSpace(character) && character != '\t')
character = ' ';
- else if (Font::treatAsZeroWidthSpaceInComplexScript(character))
+ else if (Character::treatAsZeroWidthSpaceInComplexScript(character))
character = zeroWidthSpace;
U16_APPEND(destination, *destinationLength, length, character, error);
ASSERT_UNUSED(error, !error);
}
}
-HarfBuzzShaper::HarfBuzzShaper(const Font* font, const TextRun& run)
+HarfBuzzShaper::HarfBuzzShaper(const Font* font, const TextRun& run, ForTextEmphasisOrNot forTextEmphasis)
: m_font(font)
, m_normalizedBufferLength(0)
, m_run(run)
- , m_wordSpacingAdjustment(font->wordSpacing())
+ , m_wordSpacingAdjustment(font->fontDescription().wordSpacing())
, m_padding(0)
, m_padPerWordBreak(0)
, m_padError(0)
- , m_letterSpacing(font->letterSpacing())
+ , m_letterSpacing(font->fontDescription().letterSpacing())
, m_fromIndex(0)
, m_toIndex(m_run.length())
+ , m_forTextEmphasis(forTextEmphasis)
+ , m_glyphBoundingBox(std::numeric_limits<float>::max(), std::numeric_limits<float>::min(), std::numeric_limits<float>::min(), std::numeric_limits<float>::max())
{
m_normalizedBuffer = adoptArrayPtr(new UChar[m_run.length() + 1]);
normalizeCharacters(m_run, m_run.length(), m_normalizedBuffer.get(), &m_normalizedBufferLength);
@@ -366,81 +395,6 @@ HarfBuzzShaper::HarfBuzzShaper(const Font* font, const TextRun& run)
setFontFeatures();
}
-static void normalizeSpacesAndMirrorChars(const UChar* source, unsigned length, UChar* destination, unsigned* destinationLength, HarfBuzzShaper::NormalizeMode normalizeMode)
-{
- unsigned position = 0;
- bool error = false;
- // Iterate characters in source and mirror character if needed.
- *destinationLength = 0;
- while (position < length) {
- UChar32 character;
- U16_NEXT(source, position, length, character);
- // Don't normalize tabs as they are not treated as spaces for word-end
- if (Font::treatAsSpace(character) && character != '\t')
- character = ' ';
- else if (Font::treatAsZeroWidthSpace(character))
- character = zeroWidthSpace;
- else if (normalizeMode == HarfBuzzShaper::NormalizeMirrorChars)
- character = u_charMirror(character);
- U16_APPEND(destination, *destinationLength, length, character, error);
- ASSERT_UNUSED(error, !error);
- }
-}
-
-void HarfBuzzShaper::setNormalizedBuffer(NormalizeMode normalizeMode)
-{
- // Normalize the text run in three ways:
- // 1) Convert the |originalRun| to NFC normalized form if combining diacritical marks
- // (U+0300..) are used in the run. This conversion is necessary since most OpenType
- // fonts (e.g., Arial) don't have substitution rules for the diacritical marks in
- // their GSUB tables.
- //
- // Note that we don't use the icu::Normalizer::isNormalized(UNORM_NFC) API here since
- // the API returns FALSE (= not normalized) for complex runs that don't require NFC
- // normalization (e.g., Arabic text). Unless the run contains the diacritical marks,
- // HarfBuzz will do the same thing for us using the GSUB table.
- // 2) Convert spacing characters into plain spaces, as some fonts will provide glyphs
- // for characters like '\n' otherwise.
- // 3) Convert mirrored characters such as parenthesis for rtl text.
-
- // Convert to NFC form if the text has diacritical marks.
- icu::UnicodeString normalizedString;
- UErrorCode error = U_ZERO_ERROR;
-
- const UChar* runCharacters;
- String stringFor8BitRun;
- if (m_run.is8Bit()) {
- stringFor8BitRun = String::make16BitFrom8BitSource(m_run.characters8(), m_run.length());
- runCharacters = stringFor8BitRun.characters16();
- } else
- runCharacters = m_run.characters16();
-
- for (int i = 0; i < m_run.length(); ++i) {
- UChar ch = runCharacters[i];
- if (::ublock_getCode(ch) == UBLOCK_COMBINING_DIACRITICAL_MARKS) {
- icu::Normalizer::normalize(icu::UnicodeString(runCharacters,
- m_run.length()), UNORM_NFC, 0 /* no options */,
- normalizedString, error);
- if (U_FAILURE(error))
- normalizedString.remove();
- break;
- }
- }
-
- const UChar* sourceText;
- unsigned sourceLength;
- if (normalizedString.isEmpty()) {
- sourceLength = m_run.length();
- sourceText = runCharacters;
- } else {
- sourceLength = normalizedString.length();
- sourceText = normalizedString.getBuffer();
- }
-
- m_normalizedBuffer = adoptArrayPtr(new UChar[sourceLength + 1]);
- normalizeSpacesAndMirrorChars(sourceText, sourceLength, m_normalizedBuffer.get(), &m_normalizedBufferLength, normalizeMode);
-}
-
bool HarfBuzzShaper::isWordEnd(unsigned index)
{
// This could refer a high-surrogate, but should work.
@@ -520,6 +474,53 @@ void HarfBuzzShaper::setFontFeatures()
break;
}
+ static hb_feature_t noClig = { HB_TAG('c', 'l', 'i', 'g'), 0, 0, static_cast<unsigned>(-1) };
+ static hb_feature_t noLiga = { HB_TAG('l', 'i', 'g', 'a'), 0, 0, static_cast<unsigned>(-1) };
+ switch (description.commonLigaturesState()) {
+ case FontDescription::DisabledLigaturesState:
+ m_features.append(noLiga);
+ m_features.append(noClig);
+ break;
+ case FontDescription::EnabledLigaturesState:
+ // liga and clig are on by default
+ break;
+ case FontDescription::NormalLigaturesState:
+ break;
+ }
+ static hb_feature_t dlig = { HB_TAG('d', 'l', 'i', 'g'), 1, 0, static_cast<unsigned>(-1) };
+ switch (description.discretionaryLigaturesState()) {
+ case FontDescription::DisabledLigaturesState:
+ // dlig is off by default
+ break;
+ case FontDescription::EnabledLigaturesState:
+ m_features.append(dlig);
+ break;
+ case FontDescription::NormalLigaturesState:
+ break;
+ }
+ static hb_feature_t hlig = { HB_TAG('h', 'l', 'i', 'g'), 1, 0, static_cast<unsigned>(-1) };
+ switch (description.historicalLigaturesState()) {
+ case FontDescription::DisabledLigaturesState:
+ // hlig is off by default
+ break;
+ case FontDescription::EnabledLigaturesState:
+ m_features.append(hlig);
+ break;
+ case FontDescription::NormalLigaturesState:
+ break;
+ }
+ static hb_feature_t noCalt = { HB_TAG('c', 'a', 'l', 't'), 0, 0, static_cast<unsigned>(-1) };
+ switch (description.contextualLigaturesState()) {
+ case FontDescription::DisabledLigaturesState:
+ m_features.append(noCalt);
+ break;
+ case FontDescription::EnabledLigaturesState:
+ // calt is on by default
+ break;
+ case FontDescription::NormalLigaturesState:
+ break;
+ }
+
FontFeatureSettings* settings = description.featureSettings();
if (!settings)
return;
@@ -538,19 +539,18 @@ void HarfBuzzShaper::setFontFeatures()
bool HarfBuzzShaper::shape(GlyphBuffer* glyphBuffer)
{
- if (!collectHarfBuzzRuns())
+ if (!createHarfBuzzRuns())
return false;
m_totalWidth = 0;
- // WebKit doesn't set direction when calulating widths. Leave the direction setting to
- // HarfBuzz when we are calculating widths (except when directionalOverride() is set).
- if (!shapeHarfBuzzRuns(glyphBuffer || m_run.directionalOverride()))
+ if (!shapeHarfBuzzRuns())
return false;
if (!RuntimeEnabledFeatures::subpixelFontScalingEnabled())
m_totalWidth = roundf(m_totalWidth);
- if (glyphBuffer && !fillGlyphBuffer(glyphBuffer))
+ if (m_harfBuzzRuns.last()->hasGlyphToCharacterIndexes()
+ && glyphBuffer && !fillGlyphBuffer(glyphBuffer))
return false;
return true;
@@ -561,17 +561,53 @@ FloatPoint HarfBuzzShaper::adjustStartPoint(const FloatPoint& point)
return point + m_startOffset;
}
-bool HarfBuzzShaper::collectHarfBuzzRuns()
+static inline int handleMultipleUChar(
+ UChar32 character,
+ unsigned clusterLength,
+ const SimpleFontData* currentFontData,
+ const UChar* currentCharacterPosition,
+ const UChar* markCharactersEnd,
+ const UChar* normalizedBufferEnd)
{
- const UChar* normalizedBufferEnd = m_normalizedBuffer.get() + m_normalizedBufferLength;
- SurrogatePairAwareTextIterator iterator(m_normalizedBuffer.get(), 0, m_normalizedBufferLength, m_normalizedBufferLength);
+ if (U_GET_GC_MASK(character) & U_GC_M_MASK) {
+ int markLength = clusterLength;
+ while (markCharactersEnd < normalizedBufferEnd) {
+ UChar32 nextCharacter;
+ int nextCharacterLength = 0;
+ U16_NEXT(markCharactersEnd, nextCharacterLength, normalizedBufferEnd - markCharactersEnd, nextCharacter);
+ if (!(U_GET_GC_MASK(nextCharacter) & U_GC_M_MASK))
+ break;
+ markLength += nextCharacterLength;
+ markCharactersEnd += nextCharacterLength;
+ }
+
+ if (currentFontData->canRenderCombiningCharacterSequence(currentCharacterPosition, markCharactersEnd - currentCharacterPosition)) {
+ return markLength;
+ }
+ }
+ return 0;
+}
+
+struct CandidateRun {
+ UChar32 character;
+ unsigned start;
+ unsigned end;
+ const SimpleFontData* fontData;
+ UScriptCode script;
+};
+
+static inline bool collectCandidateRuns(const UChar* normalizedBuffer,
+ size_t bufferLength, const Font* font, Vector<CandidateRun>* runs)
+{
+ const UChar* normalizedBufferEnd = normalizedBuffer + bufferLength;
+ SurrogatePairAwareTextIterator iterator(normalizedBuffer, 0, bufferLength, bufferLength);
UChar32 character;
unsigned clusterLength = 0;
unsigned startIndexOfCurrentRun = 0;
if (!iterator.consume(character, clusterLength))
return false;
- const SimpleFontData* nextFontData = m_font->glyphDataForCharacter(character, false).fontData;
+ const SimpleFontData* nextFontData = font->glyphDataForCharacter(character, false).fontData;
UErrorCode errorCode = U_ZERO_ERROR;
UScriptCode nextScript = uscript_getScript(character, &errorCode);
if (U_FAILURE(errorCode))
@@ -582,49 +618,169 @@ bool HarfBuzzShaper::collectHarfBuzzRuns()
const SimpleFontData* currentFontData = nextFontData;
UScriptCode currentScript = nextScript;
+ UChar32 lastCharacter = character;
for (iterator.advance(clusterLength); iterator.consume(character, clusterLength); iterator.advance(clusterLength)) {
- if (Font::treatAsZeroWidthSpace(character))
+ if (Character::treatAsZeroWidthSpace(character))
continue;
- if (U_GET_GC_MASK(character) & U_GC_M_MASK) {
- int markLength = clusterLength;
- const UChar* markCharactersEnd = iterator.characters() + clusterLength;
- while (markCharactersEnd < normalizedBufferEnd) {
- UChar32 nextCharacter;
- int nextCharacterLength = 0;
- U16_NEXT(markCharactersEnd, nextCharacterLength, normalizedBufferEnd - markCharactersEnd, nextCharacter);
- if (!(U_GET_GC_MASK(nextCharacter) & U_GC_M_MASK))
- break;
- markLength += nextCharacterLength;
- markCharactersEnd += nextCharacterLength;
- }
-
- if (currentFontData->canRenderCombiningCharacterSequence(currentCharacterPosition, markCharactersEnd - currentCharacterPosition)) {
- clusterLength = markLength;
- continue;
- }
+ int length = handleMultipleUChar(character, clusterLength, currentFontData, currentCharacterPosition, iterator.characters() + clusterLength, normalizedBufferEnd);
+ if (length) {
+ clusterLength = length;
+ continue;
}
- nextFontData = m_font->glyphDataForCharacter(character, false).fontData;
+ nextFontData = font->glyphDataForCharacter(character, false).fontData;
nextScript = uscript_getScript(character, &errorCode);
if (U_FAILURE(errorCode))
return false;
+ if (lastCharacter == zeroWidthJoiner)
+ currentFontData = nextFontData;
if ((nextFontData != currentFontData) || ((currentScript != nextScript) && (nextScript != USCRIPT_INHERITED) && (!uscript_hasScript(character, currentScript))))
break;
- if (nextScript == USCRIPT_INHERITED)
- nextScript = currentScript;
currentCharacterPosition = iterator.characters();
+ lastCharacter = character;
}
- unsigned numCharactersOfCurrentRun = iterator.currentCharacter() - startIndexOfCurrentRun;
- hb_script_t script = hb_icu_script_to_script(currentScript);
- m_harfBuzzRuns.append(HarfBuzzRun::create(currentFontData, startIndexOfCurrentRun, numCharactersOfCurrentRun, m_run.direction(), script));
- currentFontData = nextFontData;
+
+ CandidateRun run = { character, startIndexOfCurrentRun, iterator.currentCharacter(), currentFontData, currentScript };
+ runs->append(run);
+
startIndexOfCurrentRun = iterator.currentCharacter();
} while (iterator.consume(character, clusterLength));
+ return true;
+}
+
+static inline bool matchesAdjacentRun(UScriptCode* scriptExtensions, int length,
+ CandidateRun& adjacentRun)
+{
+ for (int i = 0; i < length; i++) {
+ if (scriptExtensions[i] == adjacentRun.script)
+ return true;
+ }
+ return false;
+}
+
+static inline void resolveRunBasedOnScriptExtensions(Vector<CandidateRun>& runs,
+ CandidateRun& run, size_t i, size_t length, UScriptCode* scriptExtensions,
+ int extensionsLength, size_t& nextResolvedRun)
+{
+ // If uscript_getScriptExtensions returns 1 it only contains the script value,
+ // we only care about ScriptExtensions which is indicated by a value >= 2.
+ if (extensionsLength <= 1)
+ return;
+
+ if (i > 0 && matchesAdjacentRun(scriptExtensions, extensionsLength, runs[i - 1])) {
+ run.script = runs[i - 1].script;
+ return;
+ }
+
+ for (size_t j = i + 1; j < length; j++) {
+ if (runs[j].script != USCRIPT_COMMON
+ && runs[j].script != USCRIPT_INHERITED
+ && matchesAdjacentRun(scriptExtensions, extensionsLength, runs[j])) {
+ nextResolvedRun = j;
+ break;
+ }
+ }
+}
+
+static inline void resolveRunBasedOnScriptValue(Vector<CandidateRun>& runs,
+ CandidateRun& run, size_t i, size_t length, size_t& nextResolvedRun)
+{
+ if (run.script != USCRIPT_COMMON)
+ return;
+
+ if (i > 0 && runs[i - 1].script != USCRIPT_COMMON) {
+ run.script = runs[i - 1].script;
+ return;
+ }
+
+ for (size_t j = i + 1; j < length; j++) {
+ if (runs[j].script != USCRIPT_COMMON
+ && runs[j].script != USCRIPT_INHERITED) {
+ nextResolvedRun = j;
+ break;
+ }
+ }
+}
+
+static inline bool resolveCandidateRuns(Vector<CandidateRun>& runs)
+{
+ UScriptCode scriptExtensions[8];
+ UErrorCode errorCode = U_ZERO_ERROR;
+ size_t length = runs.size();
+ size_t nextResolvedRun = 0;
+ for (size_t i = 0; i < length; i++) {
+ CandidateRun& run = runs[i];
+ nextResolvedRun = 0;
+
+ if (run.script == USCRIPT_INHERITED)
+ run.script = i > 0 ? runs[i - 1].script : USCRIPT_COMMON;
+
+ int extensionsLength = uscript_getScriptExtensions(run.character,
+ scriptExtensions, sizeof(scriptExtensions), &errorCode);
+ if (U_FAILURE(errorCode))
+ return false;
+
+ resolveRunBasedOnScriptExtensions(runs, run, i, length,
+ scriptExtensions, extensionsLength, nextResolvedRun);
+ resolveRunBasedOnScriptValue(runs, run, i, length,
+ nextResolvedRun);
+ for (size_t j = i; j < nextResolvedRun; j++)
+ runs[j].script = runs[nextResolvedRun].script;
+
+ i = std::max(i, nextResolvedRun);
+ }
+ return true;
+}
+
+bool HarfBuzzShaper::createHarfBuzzRuns()
+{
+ Vector<CandidateRun> candidateRuns;
+ if (!collectCandidateRuns(m_normalizedBuffer.get(),
+ m_normalizedBufferLength, m_font, &candidateRuns))
+ return false;
+
+ if (!resolveCandidateRuns(candidateRuns))
+ return false;
+
+ size_t length = candidateRuns.size();
+ for (size_t i = 0; i < length; ) {
+ CandidateRun& run = candidateRuns[i];
+ CandidateRun lastMatchingRun = run;
+ for (i++; i < length; i++) {
+ if (candidateRuns[i].script != run.script
+ || candidateRuns[i].fontData != run.fontData)
+ break;
+ lastMatchingRun = candidateRuns[i];
+ }
+ addHarfBuzzRun(run.start, lastMatchingRun.end, run.fontData, run.script);
+ }
return !m_harfBuzzRuns.isEmpty();
}
+// A port of hb_icu_script_to_script because harfbuzz on CrOS is built
+// without hb-icu. See http://crbug.com/356929
+static inline hb_script_t ICUScriptToHBScript(UScriptCode script)
+{
+ if (UNLIKELY(script == USCRIPT_INVALID_CODE))
+ return HB_SCRIPT_INVALID;
+
+ return hb_script_from_string(uscript_getShortName(script), -1);
+}
+
+
+void HarfBuzzShaper::addHarfBuzzRun(unsigned startCharacter,
+ unsigned endCharacter, const SimpleFontData* fontData,
+ UScriptCode script)
+{
+ ASSERT(endCharacter > startCharacter);
+ ASSERT(script != USCRIPT_INVALID_CODE);
+ return m_harfBuzzRuns.append(HarfBuzzRun::create(fontData,
+ startCharacter, endCharacter - startCharacter,
+ m_run.direction(), ICUScriptToHBScript(script)));
+}
+
static const uint16_t* toUint16(const UChar* src)
{
// FIXME: This relies on undefined behavior however it works on the
@@ -634,12 +790,14 @@ static const uint16_t* toUint16(const UChar* src)
return reinterpret_cast<const uint16_t*>(src);
}
-bool HarfBuzzShaper::shapeHarfBuzzRuns(bool shouldSetDirection)
+bool HarfBuzzShaper::shapeHarfBuzzRuns()
{
HarfBuzzScopedPtr<hb_buffer_t> harfBuzzBuffer(hb_buffer_create(), hb_buffer_destroy);
- hb_buffer_set_unicode_funcs(harfBuzzBuffer.get(), hb_icu_get_unicode_funcs());
HarfBuzzRunCache& runCache = harfBuzzRunCache();
+ const FontDescription& fontDescription = m_font->fontDescription();
+ const String& localeString = fontDescription.locale();
+ CString locale = localeString.latin1();
for (unsigned i = 0; i < m_harfBuzzRuns.size(); ++i) {
unsigned runIndex = m_run.rtl() ? m_harfBuzzRuns.size() - i - 1 : i;
@@ -653,12 +811,9 @@ bool HarfBuzzShaper::shapeHarfBuzzRuns(bool shouldSetDirection)
if (!face)
return false;
+ hb_buffer_set_language(harfBuzzBuffer.get(), hb_language_from_string(locale.data(), locale.length()));
hb_buffer_set_script(harfBuzzBuffer.get(), currentRun->script());
- if (shouldSetDirection)
- hb_buffer_set_direction(harfBuzzBuffer.get(), currentRun->rtl() ? HB_DIRECTION_RTL : HB_DIRECTION_LTR);
- else
- // Leaving direction to HarfBuzz to guess is *really* bad, but will do for now.
- hb_buffer_guess_segment_properties(harfBuzzBuffer.get());
+ hb_buffer_set_direction(harfBuzzBuffer.get(), currentRun->rtl() ? HB_DIRECTION_RTL : HB_DIRECTION_LTR);
hb_segment_properties_t props;
hb_buffer_get_segment_properties(harfBuzzBuffer.get(), &props);
@@ -668,11 +823,11 @@ bool HarfBuzzShaper::shapeHarfBuzzRuns(bool shouldSetDirection)
CachedShapingResults* cachedResults = runCache.find(key);
if (cachedResults) {
- if (cachedResults->dir == props.direction && cachedResults->font == *m_font) {
+ if (cachedResults->dir == props.direction && cachedResults->font == *m_font && cachedResults->locale == localeString) {
currentRun->applyShapeResult(cachedResults->buffer);
setGlyphPositionsForHarfBuzzRun(currentRun, cachedResults->buffer);
- hb_buffer_reset(harfBuzzBuffer.get());
+ hb_buffer_clear_contents(harfBuzzBuffer.get());
runCache.moveToBack(cachedResults);
@@ -687,16 +842,15 @@ bool HarfBuzzShaper::shapeHarfBuzzRuns(bool shouldSetDirection)
static const uint16_t preContext = ' ';
hb_buffer_add_utf16(harfBuzzBuffer.get(), &preContext, 1, 1, 0);
- if (m_font->isSmallCaps() && u_islower(m_normalizedBuffer[currentRun->startIndex()])) {
+ if (fontDescription.variant() == FontVariantSmallCaps && u_islower(m_normalizedBuffer[currentRun->startIndex()])) {
String upperText = String(m_normalizedBuffer.get() + currentRun->startIndex(), currentRun->numCharacters()).upper();
- currentFontData = m_font->glyphDataForCharacter(upperText[0], false, SmallCapsVariant).fontData;
ASSERT(!upperText.is8Bit()); // m_normalizedBuffer is 16 bit, therefore upperText is 16 bit, even after we call makeUpper().
hb_buffer_add_utf16(harfBuzzBuffer.get(), toUint16(upperText.characters16()), currentRun->numCharacters(), 0, currentRun->numCharacters());
} else {
hb_buffer_add_utf16(harfBuzzBuffer.get(), toUint16(m_normalizedBuffer.get() + currentRun->startIndex()), currentRun->numCharacters(), 0, currentRun->numCharacters());
}
- if (m_font->fontDescription().orientation() == Vertical)
+ if (fontDescription.orientation() == Vertical)
face->setScriptForVerticalGlyphSubstitution(harfBuzzBuffer.get());
HarfBuzzScopedPtr<hb_font_t> harfBuzzFont(face->createFont(), hb_font_destroy);
@@ -705,10 +859,9 @@ bool HarfBuzzShaper::shapeHarfBuzzRuns(bool shouldSetDirection)
currentRun->applyShapeResult(harfBuzzBuffer.get());
setGlyphPositionsForHarfBuzzRun(currentRun, harfBuzzBuffer.get());
- runCache.insert(key, new CachedShapingResults(harfBuzzBuffer.get(), m_font, props.direction));
+ runCache.insert(key, new CachedShapingResults(harfBuzzBuffer.get(), m_font, props.direction, localeString));
harfBuzzBuffer.set(hb_buffer_create());
- hb_buffer_set_unicode_funcs(harfBuzzBuffer.get(), hb_icu_get_unicode_funcs());
}
return true;
@@ -720,9 +873,16 @@ void HarfBuzzShaper::setGlyphPositionsForHarfBuzzRun(HarfBuzzRun* currentRun, hb
hb_glyph_info_t* glyphInfos = hb_buffer_get_glyph_infos(harfBuzzBuffer, 0);
hb_glyph_position_t* glyphPositions = hb_buffer_get_glyph_positions(harfBuzzBuffer, 0);
+ if (!currentRun->hasGlyphToCharacterIndexes()) {
+ // FIXME: https://crbug.com/337886
+ ASSERT_NOT_REACHED();
+ return;
+ }
+
unsigned numGlyphs = currentRun->numGlyphs();
uint16_t* glyphToCharacterIndexes = currentRun->glyphToCharacterIndexes();
float totalAdvance = 0;
+ FloatPoint glyphOrigin;
// HarfBuzz returns the shaping result in visual order. We need not to flip for RTL.
for (size_t i = 0; i < numGlyphs; ++i) {
@@ -738,7 +898,7 @@ void HarfBuzzShaper::setGlyphPositionsForHarfBuzzRun(HarfBuzzRun* currentRun, hb
glyphToCharacterIndexes[i] = glyphInfos[i].cluster;
- if (isClusterEnd && !Font::treatAsZeroWidthSpace(m_normalizedBuffer[currentCharacterIndex]))
+ if (isClusterEnd && !Character::treatAsZeroWidthSpace(m_normalizedBuffer[currentCharacterIndex]))
spacing += m_letterSpacing;
if (isClusterEnd && isWordEnd(currentCharacterIndex))
@@ -759,6 +919,11 @@ void HarfBuzzShaper::setGlyphPositionsForHarfBuzzRun(HarfBuzzRun* currentRun, hb
currentRun->setGlyphAndPositions(i, glyph, advance, offsetX, offsetY);
+ FloatRect glyphBounds = currentFontData->boundsForGlyph(glyph);
+ glyphBounds.move(glyphOrigin.x(), glyphOrigin.y());
+ m_glyphBoundingBox.unite(glyphBounds);
+ glyphOrigin += FloatSize(advance + offsetX, offsetY);
+
totalAdvance += advance;
}
currentRun->setWidth(totalAdvance > 0.0 ? totalAdvance : 0.0);
@@ -772,7 +937,6 @@ void HarfBuzzShaper::fillGlyphBufferFromHarfBuzzRun(GlyphBuffer* glyphBuffer, Ha
float* advances = currentRun->advances();
unsigned numGlyphs = currentRun->numGlyphs();
uint16_t* glyphToCharacterIndexes = currentRun->glyphToCharacterIndexes();
-
for (unsigned i = 0; i < numGlyphs; ++i) {
uint16_t currentCharacterIndex = currentRun->startIndex() + glyphToCharacterIndexes[i];
FloatPoint& currentOffset = offsets[i];
@@ -783,12 +947,66 @@ void HarfBuzzShaper::fillGlyphBufferFromHarfBuzzRun(GlyphBuffer* glyphBuffer, Ha
if (currentCharacterIndex >= m_toIndex)
m_startOffset.move(glyphAdvanceX, glyphAdvanceY);
else if (currentCharacterIndex >= m_fromIndex)
- glyphBuffer->add(glyphs[i], currentRun->fontData(), createGlyphBufferAdvance(glyphAdvanceX, glyphAdvanceY));
+ glyphBuffer->add(glyphs[i], currentRun->fontData(), FloatSize(glyphAdvanceX, glyphAdvanceY));
} else {
if (currentCharacterIndex < m_fromIndex)
m_startOffset.move(glyphAdvanceX, glyphAdvanceY);
else if (currentCharacterIndex < m_toIndex)
- glyphBuffer->add(glyphs[i], currentRun->fontData(), createGlyphBufferAdvance(glyphAdvanceX, glyphAdvanceY));
+ glyphBuffer->add(glyphs[i], currentRun->fontData(), FloatSize(glyphAdvanceX, glyphAdvanceY));
+ }
+ }
+}
+
+void HarfBuzzShaper::fillGlyphBufferForTextEmphasis(GlyphBuffer* glyphBuffer, HarfBuzzRun* currentRun)
+{
+ // FIXME: Instead of generating a synthetic GlyphBuffer here which is then used by the
+ // drawEmphasisMarks method of FontFastPath, we should roll our own emphasis mark drawing function.
+
+ float* advances = currentRun->advances();
+ unsigned numGlyphs = currentRun->numGlyphs();
+ uint16_t* glyphToCharacterIndexes = currentRun->glyphToCharacterIndexes();
+ unsigned graphemesInCluster = 1;
+ float clusterAdvance = 0;
+ uint16_t clusterStart;
+
+ // A "cluster" in this context means a cluster as it is used by HarfBuzz:
+ // The minimal group of characters and corresponding glyphs, that cannot be broken
+ // down further from a text shaping point of view.
+ // A cluster can contain multiple glyphs and grapheme clusters, with mutually
+ // overlapping boundaries. Below we count grapheme clusters per HarfBuzz clusters,
+ // then linearly split the sum of corresponding glyph advances by the number of
+ // grapheme clusters in order to find positions for emphasis mark drawing.
+
+ if (m_run.rtl())
+ clusterStart = currentRun->startIndex() + currentRun->numCharacters();
+ else
+ clusterStart = currentRun->startIndex() + glyphToCharacterIndexes[0];
+
+ for (unsigned i = 0; i < numGlyphs; ++i) {
+ uint16_t currentCharacterIndex = currentRun->startIndex() + glyphToCharacterIndexes[i];
+ bool isRunEnd = (i + 1 == numGlyphs);
+ bool isClusterEnd = isRunEnd || (currentRun->startIndex() + glyphToCharacterIndexes[i + 1] != currentCharacterIndex);
+ clusterAdvance += advances[i];
+
+ if (isClusterEnd) {
+ uint16_t clusterEnd;
+ if (m_run.rtl())
+ clusterEnd = currentCharacterIndex;
+ else
+ clusterEnd = isRunEnd ? currentRun->startIndex() + currentRun->numCharacters() : currentRun->startIndex() + glyphToCharacterIndexes[i + 1];
+
+ graphemesInCluster = countGraphemesInCluster(m_normalizedBuffer.get(), m_normalizedBufferLength, clusterStart, clusterEnd);
+ if (!graphemesInCluster || !clusterAdvance)
+ continue;
+
+ float glyphAdvanceX = clusterAdvance / graphemesInCluster;
+ for (unsigned j = 0; j < graphemesInCluster; ++j) {
+ // Do not put emphasis marks on space, separator, and control characters.
+ Glyph glyphToAdd = Character::canReceiveTextEmphasis(m_run[currentCharacterIndex]) ? 1 : 0;
+ glyphBuffer->add(glyphToAdd, currentRun->fontData(), glyphAdvanceX);
+ }
+ clusterStart = clusterEnd;
+ clusterAdvance = 0;
}
}
}
@@ -800,15 +1018,29 @@ bool HarfBuzzShaper::fillGlyphBuffer(GlyphBuffer* glyphBuffer)
m_startOffset = m_harfBuzzRuns.last()->offsets()[0];
for (int runIndex = numRuns - 1; runIndex >= 0; --runIndex) {
HarfBuzzRun* currentRun = m_harfBuzzRuns[runIndex].get();
+ if (!currentRun->hasGlyphToCharacterIndexes()) {
+ // FIXME: bug 337886, 359664
+ continue;
+ }
FloatPoint firstOffsetOfNextRun = !runIndex ? FloatPoint() : m_harfBuzzRuns[runIndex - 1]->offsets()[0];
- fillGlyphBufferFromHarfBuzzRun(glyphBuffer, currentRun, firstOffsetOfNextRun);
+ if (m_forTextEmphasis == ForTextEmphasis)
+ fillGlyphBufferForTextEmphasis(glyphBuffer, currentRun);
+ else
+ fillGlyphBufferFromHarfBuzzRun(glyphBuffer, currentRun, firstOffsetOfNextRun);
}
} else {
m_startOffset = m_harfBuzzRuns.first()->offsets()[0];
for (unsigned runIndex = 0; runIndex < numRuns; ++runIndex) {
HarfBuzzRun* currentRun = m_harfBuzzRuns[runIndex].get();
+ if (!currentRun->hasGlyphToCharacterIndexes()) {
+ // FIXME: bug 337886, 359664
+ continue;
+ }
FloatPoint firstOffsetOfNextRun = runIndex == numRuns - 1 ? FloatPoint() : m_harfBuzzRuns[runIndex + 1]->offsets()[0];
- fillGlyphBufferFromHarfBuzzRun(glyphBuffer, currentRun, firstOffsetOfNextRun);
+ if (m_forTextEmphasis == ForTextEmphasis)
+ fillGlyphBufferForTextEmphasis(glyphBuffer, currentRun);
+ else
+ fillGlyphBufferFromHarfBuzzRun(glyphBuffer, currentRun, firstOffsetOfNextRun);
}
}
return glyphBuffer->size();
@@ -886,10 +1118,15 @@ FloatRect HarfBuzzShaper::selectionRect(const FloatPoint& point, int height, int
if (!foundToX)
toX = m_run.rtl() ? 0 : m_totalWidth;
- // Using floorf() and roundf() as the same as mac port.
- if (fromX < toX)
- return FloatRect(floorf(point.x() + fromX), point.y(), roundf(toX - fromX), height);
- return FloatRect(floorf(point.x() + toX), point.y(), roundf(fromX - toX), height);
+ if (fromX < toX) {
+ return Font::pixelSnappedSelectionRect(
+ point.x() + fromX, point.x() + toX,
+ point.y(), height);
+ }
+
+ return Font::pixelSnappedSelectionRect(
+ point.x() + toX, point.x() + fromX,
+ point.y(), height);
}
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/harfbuzz/HarfBuzzShaper.h b/chromium/third_party/WebKit/Source/platform/fonts/harfbuzz/HarfBuzzShaper.h
index c60d4213bbc..fd25d1ee01a 100644
--- a/chromium/third_party/WebKit/Source/platform/fonts/harfbuzz/HarfBuzzShaper.h
+++ b/chromium/third_party/WebKit/Source/platform/fonts/harfbuzz/HarfBuzzShaper.h
@@ -32,7 +32,7 @@
#define HarfBuzzShaper_h
#include "hb.h"
-#include "platform/fonts/GlyphBuffer.h"
+#include "platform/geometry/FloatBoxExtent.h"
#include "platform/geometry/FloatPoint.h"
#include "platform/text/TextRun.h"
#include "wtf/HashSet.h"
@@ -41,19 +41,22 @@
#include "wtf/unicode/CharacterNames.h"
#include "wtf/Vector.h"
+#include <unicode/uscript.h>
+
namespace WebCore {
class Font;
+class GlyphBuffer;
class SimpleFontData;
class HarfBuzzShaper FINAL {
public:
- enum NormalizeMode {
- DoNotNormalizeMirrorChars,
- NormalizeMirrorChars
+ enum ForTextEmphasisOrNot {
+ NotForTextEmphasis,
+ ForTextEmphasis
};
- HarfBuzzShaper(const Font*, const TextRun&);
+ HarfBuzzShaper(const Font*, const TextRun&, ForTextEmphasisOrNot = NotForTextEmphasis);
void setDrawRange(int from, int to);
bool shape(GlyphBuffer* = 0);
@@ -61,6 +64,7 @@ public:
float totalWidth() { return m_totalWidth; }
int offsetForPosition(float targetX);
FloatRect selectionRect(const FloatPoint&, int height, int from, int to);
+ FloatBoxExtent glyphBoundingBox() const { return m_glyphBoundingBox; }
private:
class HarfBuzzRun {
@@ -88,7 +92,14 @@ private:
uint16_t* glyphs() { return &m_glyphs[0]; }
float* advances() { return &m_advances[0]; }
FloatPoint* offsets() { return &m_offsets[0]; }
- uint16_t* glyphToCharacterIndexes() { return &m_glyphToCharacterIndexes[0]; }
+ bool hasGlyphToCharacterIndexes() const
+ {
+ return m_glyphToCharacterIndexes.size() > 0;
+ }
+ uint16_t* glyphToCharacterIndexes()
+ {
+ return &m_glyphToCharacterIndexes[0];
+ }
float width() { return m_width; }
bool rtl() { return m_direction == RTL; }
hb_script_t script() { return m_script; }
@@ -109,8 +120,6 @@ private:
float m_width;
};
- void setNormalizedBuffer(NormalizeMode = DoNotNormalizeMirrorChars);
-
bool isWordEnd(unsigned);
int determineWordBreakSpacing();
// setPadding sets a number of pixels to be distributed across the TextRun.
@@ -122,13 +131,13 @@ private:
void setFontFeatures();
- bool collectHarfBuzzRuns();
- bool shapeHarfBuzzRuns(bool shouldSetDirection);
+ bool createHarfBuzzRuns();
+ bool shapeHarfBuzzRuns();
bool fillGlyphBuffer(GlyphBuffer*);
void fillGlyphBufferFromHarfBuzzRun(GlyphBuffer*, HarfBuzzRun*, FloatPoint& firstOffsetOfNextRun);
+ void fillGlyphBufferForTextEmphasis(GlyphBuffer*, HarfBuzzRun* currentRun);
void setGlyphPositionsForHarfBuzzRun(HarfBuzzRun*, hb_buffer_t*);
-
- GlyphBufferAdvance createGlyphBufferAdvance(float, float);
+ void addHarfBuzzRun(unsigned startCharacter, unsigned endCharacter, const SimpleFontData*, UScriptCode);
const Font* m_font;
OwnPtr<UChar[]> m_normalizedBuffer;
@@ -149,7 +158,10 @@ private:
int m_fromIndex;
int m_toIndex;
+ ForTextEmphasisOrNot m_forTextEmphasis;
+
float m_totalWidth;
+ FloatBoxExtent m_glyphBoundingBox;
friend struct CachedShapingResults;
};
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/linux/FontCacheLinux.cpp b/chromium/third_party/WebKit/Source/platform/fonts/linux/FontCacheLinux.cpp
index 69e81b68174..358a3e13f47 100644
--- a/chromium/third_party/WebKit/Source/platform/fonts/linux/FontCacheLinux.cpp
+++ b/chromium/third_party/WebKit/Source/platform/fonts/linux/FontCacheLinux.cpp
@@ -26,7 +26,7 @@
#include "platform/fonts/FontCache.h"
-#include "public/platform/linux/WebFontFamily.h"
+#include "public/platform/linux/WebFallbackFont.h"
#include "public/platform/linux/WebFontInfo.h"
#include "public/platform/linux/WebSandboxSupport.h"
#include "public/platform/Platform.h"
@@ -34,16 +34,19 @@
namespace WebCore {
-void FontCache::getFontFamilyForCharacter(UChar32 c, const char* preferredLocale, FontCache::SimpleFontFamily* family)
+void FontCache::getFontForCharacter(UChar32 c, const char* preferredLocale, FontCache::PlatformFallbackFont* fallbackFont)
{
- blink::WebFontFamily webFamily;
- if (blink::Platform::current()->sandboxSupport())
- blink::Platform::current()->sandboxSupport()->getFontFamilyForCharacter(c, preferredLocale, &webFamily);
- else
- blink::WebFontInfo::familyForChar(c, preferredLocale, &webFamily);
- family->name = String::fromUTF8(CString(webFamily.name));
- family->isBold = webFamily.isBold;
- family->isItalic = webFamily.isItalic;
+ blink::WebFallbackFont webFallbackFont;
+ if (blink::Platform::current()->sandboxSupport()) {
+ blink::Platform::current()->sandboxSupport()->getFallbackFontForCharacter(c, preferredLocale, &webFallbackFont);
+ } else {
+ blink::WebFontInfo::fallbackFontForChar(c, preferredLocale, &webFallbackFont);
+ }
+ fallbackFont->name = String::fromUTF8(CString(webFallbackFont.name));
+ fallbackFont->filename = webFallbackFont.filename;
+ fallbackFont->ttcIndex = webFallbackFont.ttcIndex;
+ fallbackFont->isBold = webFallbackFont.isBold;
+ fallbackFont->isItalic = webFallbackFont.isItalic;
}
}
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/linux/FontPlatformDataLinuxHarfBuzz.cpp b/chromium/third_party/WebKit/Source/platform/fonts/linux/FontPlatformDataLinuxHarfBuzz.cpp
new file mode 100644
index 00000000000..c05fa20be98
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/platform/fonts/linux/FontPlatformDataLinuxHarfBuzz.cpp
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2006, 2007, 2008, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "public/platform/Platform.h"
+
+#include "SkTypeface.h"
+#include "platform/LayoutTestSupport.h"
+#include "platform/RuntimeEnabledFeatures.h"
+#include "platform/fonts/harfbuzz/FontPlatformDataHarfBuzz.h"
+#include "public/platform/linux/WebFontInfo.h"
+#include "public/platform/linux/WebFontRenderStyle.h"
+#include "public/platform/linux/WebSandboxSupport.h"
+
+namespace WebCore {
+
+static SkPaint::Hinting skiaHinting = SkPaint::kNormal_Hinting;
+static bool useSkiaAutoHint = true;
+static bool useSkiaBitmaps = true;
+static bool useSkiaAntiAlias = true;
+static bool useSkiaSubpixelRendering = false;
+
+void FontPlatformData::setHinting(SkPaint::Hinting hinting)
+{
+ skiaHinting = hinting;
+}
+
+void FontPlatformData::setAutoHint(bool useAutoHint)
+{
+ useSkiaAutoHint = useAutoHint;
+}
+
+void FontPlatformData::setUseBitmaps(bool useBitmaps)
+{
+ useSkiaBitmaps = useBitmaps;
+}
+
+void FontPlatformData::setAntiAlias(bool useAntiAlias)
+{
+ useSkiaAntiAlias = useAntiAlias;
+}
+
+void FontPlatformData::setSubpixelRendering(bool useSubpixelRendering)
+{
+ useSkiaSubpixelRendering = useSubpixelRendering;
+}
+
+void FontPlatformData::setupPaint(SkPaint* paint, GraphicsContext*) const
+{
+ paint->setAntiAlias(m_style.useAntiAlias);
+ paint->setHinting(static_cast<SkPaint::Hinting>(m_style.hintStyle));
+ paint->setEmbeddedBitmapText(m_style.useBitmaps);
+ paint->setAutohinted(m_style.useAutoHint);
+ if (m_style.useAntiAlias)
+ paint->setLCDRenderText(m_style.useSubpixelRendering);
+
+ // TestRunner specifically toggles the subpixel positioning flag.
+ if (RuntimeEnabledFeatures::subpixelFontScalingEnabled()
+ && paint->getHinting() != SkPaint::kFull_Hinting
+ && !isRunningLayoutTest())
+ paint->setSubpixelText(true);
+ else
+ paint->setSubpixelText(m_style.useSubpixelPositioning);
+
+ const float ts = m_textSize >= 0 ? m_textSize : 12;
+ paint->setTextSize(SkFloatToScalar(ts));
+ paint->setTypeface(m_typeface.get());
+ paint->setFakeBoldText(m_syntheticBold);
+ paint->setTextSkewX(m_syntheticItalic ? -SK_Scalar1 / 4 : 0);
+}
+
+
+static inline void getRenderStyleForStrike(FontRenderStyle& fontRenderStyle, const char* font, int sizeAndStyle)
+{
+ blink::WebFontRenderStyle style;
+
+#if OS(ANDROID)
+ style.setDefaults();
+#else
+ if (!font || !*font)
+ style.setDefaults(); // It's probably a webfont. Take the system defaults.
+ else if (blink::Platform::current()->sandboxSupport())
+ blink::Platform::current()->sandboxSupport()->getRenderStyleForStrike(font, sizeAndStyle, &style);
+ else
+ blink::WebFontInfo::renderStyleForStrike(font, sizeAndStyle, &style);
+#endif
+
+ style.toFontRenderStyle(&fontRenderStyle);
+}
+
+void FontPlatformData::querySystemForRenderStyle(bool useSkiaSubpixelPositioning)
+{
+ getRenderStyleForStrike(m_style, m_family.data(), (((int)m_textSize) << 2) | (m_typeface->style() & 3));
+
+ // Fix FontRenderStyle::NoPreference to actual styles.
+ if (m_style.useAntiAlias == FontRenderStyle::NoPreference)
+ m_style.useAntiAlias = useSkiaAntiAlias;
+
+ if (!m_style.useHinting)
+ m_style.hintStyle = SkPaint::kNo_Hinting;
+ else if (m_style.useHinting == FontRenderStyle::NoPreference)
+ m_style.hintStyle = skiaHinting;
+
+ if (m_style.useBitmaps == FontRenderStyle::NoPreference)
+ m_style.useBitmaps = useSkiaBitmaps;
+ if (m_style.useAutoHint == FontRenderStyle::NoPreference)
+ m_style.useAutoHint = useSkiaAutoHint;
+ if (m_style.useAntiAlias == FontRenderStyle::NoPreference)
+ m_style.useAntiAlias = useSkiaAntiAlias;
+ if (m_style.useSubpixelRendering == FontRenderStyle::NoPreference)
+ m_style.useSubpixelRendering = useSkiaSubpixelRendering;
+
+ // TestRunner specifically toggles the subpixel positioning flag.
+ if (m_style.useSubpixelPositioning == FontRenderStyle::NoPreference
+ || isRunningLayoutTest())
+ m_style.useSubpixelPositioning = useSkiaSubpixelPositioning;
+}
+
+bool FontPlatformData::defaultUseSubpixelPositioning()
+{
+ return FontDescription::subpixelPositioning();
+}
+
+} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/mac/ComplexTextController.cpp b/chromium/third_party/WebKit/Source/platform/fonts/mac/ComplexTextController.cpp
index 57855a55b5e..4ddf0e3e92e 100644
--- a/chromium/third_party/WebKit/Source/platform/fonts/mac/ComplexTextController.cpp
+++ b/chromium/third_party/WebKit/Source/platform/fonts/mac/ComplexTextController.cpp
@@ -25,77 +25,20 @@
#include "config.h"
#include "platform/fonts/mac/ComplexTextController.h"
-#include <ApplicationServices/ApplicationServices.h>
+#include "platform/fonts/Character.h"
#include "platform/fonts/Font.h"
+#include "platform/fonts/GlyphBuffer.h"
#include "platform/geometry/FloatSize.h"
#include "platform/text/TextBreakIterator.h"
#include "platform/text/TextRun.h"
#include "wtf/StdLibExtras.h"
#include "wtf/unicode/CharacterNames.h"
+#include <ApplicationServices/ApplicationServices.h>
using namespace std;
namespace WebCore {
-class TextLayout {
-public:
- static bool isNeeded(const TextRun& run, const Font& font)
- {
- return font.codePath(run) == Font::Complex;
- }
-
- TextLayout(const TextRun& run, unsigned textLength, const Font& font, float xPos)
- : m_font(font)
- , m_run(constructTextRun(run, textLength, font, xPos))
- , m_controller(adoptPtr(new ComplexTextController(&m_font, m_run, true)))
- {
- }
-
- float width(unsigned from, unsigned len, HashSet<const SimpleFontData*>* fallbackFonts)
- {
- m_controller->advance(from, 0, ByWholeGlyphs, fallbackFonts);
- float beforeWidth = m_controller->runWidthSoFar();
- if (m_font.wordSpacing() && from && Font::treatAsSpace(m_run[from]))
- beforeWidth += m_font.wordSpacing();
- m_controller->advance(from + len, 0, ByWholeGlyphs, fallbackFonts);
- float afterWidth = m_controller->runWidthSoFar();
- return afterWidth - beforeWidth;
- }
-
-private:
- static TextRun constructTextRun(const TextRun& textRun, unsigned textLength, const Font& font, float xPos)
- {
- TextRun run = textRun;
- run.setCharactersLength(textLength);
- ASSERT(run.charactersLength() >= run.length());
-
- run.setXPos(xPos);
- return run;
- }
-
- // ComplexTextController has only references to its Font and TextRun so they must be kept alive here.
- Font m_font;
- TextRun m_run;
- OwnPtr<ComplexTextController> m_controller;
-};
-
-PassOwnPtr<TextLayout> Font::createLayoutForMacComplexText(const TextRun& run, unsigned textLength, float xPos, bool collapseWhiteSpace) const
-{
- if (!collapseWhiteSpace || !TextLayout::isNeeded(run, *this))
- return nullptr;
- return adoptPtr(new TextLayout(run, textLength, *this, xPos));
-}
-
-void Font::deleteLayout(TextLayout* layout)
-{
- delete layout;
-}
-
-float Font::width(TextLayout& layout, unsigned from, unsigned len, HashSet<const SimpleFontData*>* fallbackFonts)
-{
- return layout.width(from, len, fallbackFonts);
-}
-
static inline CGFloat roundCGFloat(CGFloat f)
{
if (sizeof(CGFloat) == sizeof(float))
@@ -141,9 +84,9 @@ ComplexTextController::ComplexTextController(const Font* font, const TextRun& ru
bool isAfterExpansion = m_afterExpansion;
unsigned expansionOpportunityCount;
if (m_run.is8Bit())
- expansionOpportunityCount = Font::expansionOpportunityCount(m_run.characters8(), m_end, m_run.ltr() ? LTR : RTL, isAfterExpansion);
+ expansionOpportunityCount = Character::expansionOpportunityCount(m_run.characters8(), m_end, m_run.direction(), isAfterExpansion);
else
- expansionOpportunityCount = Font::expansionOpportunityCount(m_run.characters16(), m_end, m_run.ltr() ? LTR : RTL, isAfterExpansion);
+ expansionOpportunityCount = Character::expansionOpportunityCount(m_run.characters16(), m_end, m_run.direction(), isAfterExpansion);
if (isAfterExpansion && !m_run.allowsTrailingExpansion())
expansionOpportunityCount--;
@@ -302,7 +245,7 @@ void ComplexTextController::collectComplexTextRuns()
} else
cp = m_run.characters16();
- if (m_font.isSmallCaps())
+ if (m_font.fontDescription().variant() == FontVariantSmallCaps)
m_smallCapsBuffer.resize(m_end);
unsigned indexOfFontTransition = 0;
@@ -323,7 +266,7 @@ void ComplexTextController::collectComplexTextRuns()
UChar uppercaseCharacter = 0;
bool isSmallCaps;
- bool nextIsSmallCaps = m_font.isSmallCaps() && !(U_GET_GC_MASK(baseCharacter) & U_GC_M_MASK) && (uppercaseCharacter = u_toupper(baseCharacter)) != baseCharacter;
+ bool nextIsSmallCaps = m_font.fontDescription().variant() == FontVariantSmallCaps && !(U_GET_GC_MASK(baseCharacter) & U_GC_M_MASK) && (uppercaseCharacter = u_toupper(baseCharacter)) != baseCharacter;
if (nextIsSmallCaps) {
m_smallCapsBuffer[sequenceStart - cp] = uppercaseCharacter;
@@ -345,7 +288,7 @@ void ComplexTextController::collectComplexTextRuns()
if (!advanceByCombiningCharacterSequence(curr, end, baseCharacter, markCount))
return;
- if (m_font.isSmallCaps()) {
+ if (m_font.fontDescription().variant()) {
nextIsSmallCaps = (uppercaseCharacter = u_toupper(baseCharacter)) != baseCharacter;
if (nextIsSmallCaps) {
m_smallCapsBuffer[index] = uppercaseCharacter;
@@ -528,7 +471,7 @@ void ComplexTextController::advance(unsigned offset, GlyphBuffer* glyphBuffer, G
return;
if (glyphBuffer && !m_characterInCurrentGlyph)
- glyphBuffer->add(m_adjustedGlyphs[k], complexTextRun.fontData(), adjustedAdvance);
+ glyphBuffer->add(m_adjustedGlyphs[k], complexTextRun.fontData(), FloatSize(adjustedAdvance));
unsigned oldCharacterInCurrentGlyph = m_characterInCurrentGlyph;
m_characterInCurrentGlyph = min(m_currentCharacter - complexTextRun.stringLocation(), glyphEndOffset) - glyphStartOffset;
@@ -570,7 +513,7 @@ void ComplexTextController::adjustGlyphsAndAdvances()
{
CGFloat widthSinceLastCommit = 0;
size_t runCount = m_complexTextRuns.size();
- bool hasExtraSpacing = (m_font.letterSpacing() || m_font.wordSpacing() || m_expansion) && !m_run.spacingDisabled();
+ bool hasExtraSpacing = (m_font.fontDescription().letterSpacing() || m_font.fontDescription().wordSpacing() || m_expansion) && !m_run.spacingDisabled();
for (size_t r = 0; r < runCount; ++r) {
ComplexTextRun& complexTextRun = *m_complexTextRuns[r];
unsigned glyphCount = complexTextRun.glyphCount();
@@ -583,7 +526,7 @@ void ComplexTextController::adjustGlyphsAndAdvances()
const CGSize* advances = complexTextRun.advances();
bool lastRun = r + 1 == runCount;
- bool roundsAdvances = !m_font.isPrinterFont() && fontData->platformData().roundsGlyphAdvances();
+ bool roundsAdvances = fontData->platformData().roundsGlyphAdvances();
float spaceWidth = fontData->spaceWidth() - fontData->syntheticBoldOffset();
CGFloat roundedSpaceWidth = roundCGFloat(spaceWidth);
const UChar* cp = complexTextRun.characters();
@@ -610,13 +553,13 @@ void ComplexTextController::adjustGlyphsAndAdvances()
else
nextCh = *(m_complexTextRuns[r + 1]->characters() + m_complexTextRuns[r + 1]->indexAt(0));
- bool treatAsSpace = Font::treatAsSpace(ch);
+ bool treatAsSpace = Character::treatAsSpace(ch);
CGGlyph glyph = treatAsSpace ? fontData->spaceGlyph() : glyphs[i];
CGSize advance = treatAsSpace ? CGSizeMake(spaceWidth, advances[i].height) : advances[i];
- if (ch == '\t' && m_run.allowTabs())
+ if (ch == '\t' && m_run.allowTabs()) {
advance.width = m_font.tabWidth(*fontData, m_run.tabSize(), m_run.xPos() + m_totalWidth + widthSinceLastCommit);
- else if (Font::treatAsZeroWidthSpace(ch) && !treatAsSpace) {
+ } else if (Character::treatAsZeroWidthSpace(ch) && !treatAsSpace) {
advance.width = 0;
glyph = fontData->spaceGlyph();
}
@@ -638,11 +581,11 @@ void ComplexTextController::adjustGlyphsAndAdvances()
if (hasExtraSpacing) {
// If we're a glyph with an advance, go ahead and add in letter-spacing.
// That way we weed out zero width lurkers. This behavior matches the fast text code path.
- if (advance.width && m_font.letterSpacing())
- advance.width += m_font.letterSpacing();
+ if (advance.width && m_font.fontDescription().letterSpacing())
+ advance.width += m_font.fontDescription().letterSpacing();
// Handle justification and word-spacing.
- if (treatAsSpace || Font::isCJKIdeographOrSymbol(ch)) {
+ if (treatAsSpace || Character::isCJKIdeographOrSymbol(ch)) {
// Distribute the run's total expansion evenly over all expansion opportunities in the run.
if (m_expansion) {
float previousExpansion = m_expansion;
@@ -666,8 +609,8 @@ void ComplexTextController::adjustGlyphsAndAdvances()
m_afterExpansion = false;
// Account for word-spacing.
- if (treatAsSpace && (ch != '\t' || !m_run.allowTabs()) && (characterIndex > 0 || r > 0) && m_font.wordSpacing())
- advance.width += m_font.wordSpacing();
+ if (treatAsSpace && (ch != '\t' || !m_run.allowTabs()) && (characterIndex > 0 || r > 0) && m_font.fontDescription().wordSpacing())
+ advance.width += m_font.fontDescription().wordSpacing();
} else
m_afterExpansion = false;
}
@@ -676,12 +619,12 @@ void ComplexTextController::adjustGlyphsAndAdvances()
// We adjust the width of the last character of a "word" to ensure an integer width.
// Force characters that are used to determine word boundaries for the rounding hack
// to be integer width, so the following words will start on an integer boundary.
- if (m_run.applyWordRounding() && Font::isRoundingHackCharacter(ch))
+ if (m_run.applyWordRounding() && Character::isRoundingHackCharacter(ch))
advance.width = ceilCGFloat(advance.width);
// Check to see if the next character is a "rounding hack character", if so, adjust the
// width so that the total run width will be on an integer boundary.
- if ((m_run.applyWordRounding() && !lastGlyph && Font::isRoundingHackCharacter(nextCh)) || (m_run.applyRunRounding() && lastGlyph)) {
+ if ((m_run.applyWordRounding() && !lastGlyph && Character::isRoundingHackCharacter(nextCh)) || (m_run.applyRunRounding() && lastGlyph)) {
CGFloat totalWidth = widthSinceLastCommit + advance.width;
widthSinceLastCommit = ceilCGFloat(totalWidth);
CGFloat extraWidth = widthSinceLastCommit - totalWidth;
@@ -700,7 +643,7 @@ void ComplexTextController::adjustGlyphsAndAdvances()
widthSinceLastCommit += advance.width;
// FIXME: Combining marks should receive a text emphasis mark if they are combine with a space.
- if (m_forTextEmphasis && (!Font::canReceiveTextEmphasis(ch) || (U_GET_GC_MASK(ch) & U_GC_M_MASK)))
+ if (m_forTextEmphasis && (!Character::canReceiveTextEmphasis(ch) || (U_GET_GC_MASK(ch) & U_GC_M_MASK)))
glyph = 0;
advance.height *= -1;
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/mac/ComplexTextController.h b/chromium/third_party/WebKit/Source/platform/fonts/mac/ComplexTextController.h
index 06bd70ab036..e1eabfae80f 100644
--- a/chromium/third_party/WebKit/Source/platform/fonts/mac/ComplexTextController.h
+++ b/chromium/third_party/WebKit/Source/platform/fonts/mac/ComplexTextController.h
@@ -25,7 +25,6 @@
#ifndef ComplexTextController_h
#define ComplexTextController_h
-#include "platform/fonts/GlyphBuffer.h"
#include "wtf/HashSet.h"
#include "wtf/PassRefPtr.h"
#include "wtf/RefCounted.h"
@@ -33,6 +32,7 @@
#include "wtf/text/WTFString.h"
#include "wtf/unicode/Unicode.h"
#include "wtf/Vector.h"
+#include <ApplicationServices/ApplicationServices.h>
typedef unsigned short CGGlyph;
@@ -42,6 +42,7 @@ typedef const struct __CTLine * CTLineRef;
namespace WebCore {
class Font;
+class GlyphBuffer;
class SimpleFontData;
class TextRun;
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/mac/ComplexTextControllerCoreText.mm b/chromium/third_party/WebKit/Source/platform/fonts/mac/ComplexTextControllerCoreText.mm
index 822aa8cb8f0..98b062f328c 100644
--- a/chromium/third_party/WebKit/Source/platform/fonts/mac/ComplexTextControllerCoreText.mm
+++ b/chromium/third_party/WebKit/Source/platform/fonts/mac/ComplexTextControllerCoreText.mm
@@ -202,15 +202,15 @@ void ComplexTextController::collectComplexTextRunsForCharacters(const UChar* cp,
RetainPtr<WebCascadeList> cascadeList(AdoptNS, [[WebCascadeList alloc] initWithFont:&m_font character:baseCharacter]);
- stringAttributes.adoptCF(CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, fontData->getCFStringAttributes(m_font.typesettingFeatures(), fontData->platformData().orientation())));
+ stringAttributes.adoptCF(CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, fontData->getCFStringAttributes(m_font.fontDescription().typesettingFeatures(), fontData->platformData().orientation())));
static const void* attributeKeys[] = { kCTFontCascadeListAttribute };
const void* values[] = { cascadeList.get() };
RetainPtr<CFDictionaryRef> attributes(AdoptCF, CFDictionaryCreate(kCFAllocatorDefault, attributeKeys, values, sizeof(attributeKeys) / sizeof(*attributeKeys), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
RetainPtr<CTFontDescriptorRef> fontDescriptor(AdoptCF, CTFontDescriptorCreateWithAttributes(attributes.get()));
- RetainPtr<CTFontRef> fontWithCascadeList(AdoptCF, CTFontCreateCopyWithAttributes(fontData->platformData().ctFont(), m_font.pixelSize(), 0, fontDescriptor.get()));
+ RetainPtr<CTFontRef> fontWithCascadeList(AdoptCF, CTFontCreateCopyWithAttributes(fontData->platformData().ctFont(), m_font.fontDescription().computedPixelSize(), 0, fontDescriptor.get()));
CFDictionarySetValue(const_cast<CFMutableDictionaryRef>(stringAttributes.get()), kCTFontAttributeName, fontWithCascadeList.get());
} else
- stringAttributes = fontData->getCFStringAttributes(m_font.typesettingFeatures(), fontData->platformData().orientation());
+ stringAttributes = fontData->getCFStringAttributes(m_font.fontDescription().typesettingFeatures(), fontData->platformData().orientation());
RetainPtr<CTLineRef> line;
@@ -279,7 +279,7 @@ void ComplexTextController::collectComplexTextRunsForCharacters(const UChar* cp,
// Core Text may have used a font that is not known to NSFontManager. In that case, fall back on
// using the font as returned, even though it may not have the best NSFontRenderingMode.
if (!runFontData) {
- FontPlatformData runFontPlatformData((NSFont *)runFont, CTFontGetSize(runFont), m_font.fontDescription().usePrinterFont());
+ FontPlatformData runFontPlatformData((NSFont *)runFont, CTFontGetSize(runFont));
runFontData = FontCache::fontCache()->fontDataFromFontPlatformData(&runFontPlatformData, DoNotRetain).get();
}
}
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/mac/FontCacheMac.mm b/chromium/third_party/WebKit/Source/platform/fonts/mac/FontCacheMac.mm
index ef8862c1006..3f69c1002d8 100644
--- a/chromium/third_party/WebKit/Source/platform/fonts/mac/FontCacheMac.mm
+++ b/chromium/third_party/WebKit/Source/platform/fonts/mac/FontCacheMac.mm
@@ -31,6 +31,8 @@
#import "platform/fonts/FontCache.h"
#import <AppKit/AppKit.h>
+#import "platform/LayoutTestSupport.h"
+#import "platform/RuntimeEnabledFeatures.h"
#import "platform/fonts/FontDescription.h"
#import "platform/fonts/FontPlatformData.h"
#import "platform/fonts/SimpleFontData.h"
@@ -64,6 +66,14 @@ static void fontCacheRegisteredFontsChangedNotificationCallback(CFNotificationCe
invalidateFontCache(0);
}
+static bool useHinting()
+{
+ // Enable hinting when subpixel font scaling is disabled or
+ // when running the set of standard non-subpixel layout tests,
+ // otherwise use subpixel glyph positioning.
+ return (isRunningLayoutTest() && !isFontAntialiasingEnabledForTest()) || !RuntimeEnabledFeatures::subpixelFontScalingEnabled();
+}
+
void FontCache::platformInit()
{
CFNotificationCenterAddObserver(CFNotificationCenterGetLocalCenter(), this, fontCacheRegisteredFontsChangedNotificationCallback, kCTFontManagerRegisteredFontsChangedNotification, 0, CFNotificationSuspensionBehaviorDeliverImmediately);
@@ -90,7 +100,7 @@ static inline bool isAppKitFontWeightBold(NSInteger appKitFontWeight)
return appKitFontWeight >= 7;
}
-PassRefPtr<SimpleFontData> FontCache::platformFallbackForCharacter(const FontDescription& fontDescription, UChar32 character, const SimpleFontData* fontDataToSubstitute, bool disallowSynthetics)
+PassRefPtr<SimpleFontData> FontCache::fallbackFontForCharacter(const FontDescription& fontDescription, UChar32 character, const SimpleFontData* fontDataToSubstitute)
{
// FIXME: We should fix getFallbackFamily to take a UChar32
// and remove this split-to-UChar16 code.
@@ -116,11 +126,11 @@ PassRefPtr<SimpleFontData> FontCache::platformFallbackForCharacter(const FontDes
if (!substituteFont && codeUnitsLength == 1)
substituteFont = [NSFont findFontLike:nsFont forCharacter:codeUnits[0] inLanguage:nil];
if (!substituteFont)
- return 0;
+ return nullptr;
// Chromium can't render AppleColorEmoji.
if ([[substituteFont familyName] isEqual:@"Apple Color Emoji"])
- return 0;
+ return nullptr;
// Use the family name from the AppKit-supplied substitute font, requesting the
// traits, weight, and size we want. One way this does better than the original
@@ -144,7 +154,7 @@ PassRefPtr<SimpleFontData> FontCache::platformFallbackForCharacter(const FontDes
size = [nsFont pointSize];
} else {
// For custom fonts nsFont is nil.
- traits = fontDescription.italic() ? NSFontItalicTrait : 0;
+ traits = fontDescription.style() ? NSFontItalicTrait : 0;
weight = toAppKitFontWeight(fontDescription.weight());
size = fontDescription.computedPixelSize();
}
@@ -154,20 +164,20 @@ PassRefPtr<SimpleFontData> FontCache::platformFallbackForCharacter(const FontDes
if (traits != substituteFontTraits || weight != substituteFontWeight || !nsFont) {
if (NSFont *bestVariation = [fontManager fontWithFamily:[substituteFont familyName] traits:traits weight:weight size:size]) {
- if (!nsFont || (([fontManager traitsOfFont:bestVariation] != substituteFontTraits || [fontManager weightOfFont:bestVariation] != substituteFontWeight)
- && [[bestVariation coveredCharacterSet] longCharacterIsMember:character]))
+ if ((!nsFont || [fontManager traitsOfFont:bestVariation] != substituteFontTraits || [fontManager weightOfFont:bestVariation] != substituteFontWeight)
+ && [[bestVariation coveredCharacterSet] longCharacterIsMember:character])
substituteFont = bestVariation;
}
}
- substituteFont = fontDescription.usePrinterFont() ? [substituteFont printerFont] : [substituteFont screenFont];
+ substituteFont = useHinting() ? [substituteFont screenFont] : [substituteFont printerFont];
substituteFontTraits = [fontManager traitsOfFont:substituteFont];
substituteFontWeight = [fontManager weightOfFont:substituteFont];
- FontPlatformData alternateFont(substituteFont, platformData.size(), platformData.isPrinterFont(),
- !disallowSynthetics && isAppKitFontWeightBold(weight) && !isAppKitFontWeightBold(substituteFontWeight),
- !disallowSynthetics && (traits & NSFontItalicTrait) && !(substituteFontTraits & NSFontItalicTrait),
+ FontPlatformData alternateFont(substituteFont, platformData.size(),
+ isAppKitFontWeightBold(weight) && !isAppKitFontWeightBold(substituteFontWeight),
+ (traits & NSFontItalicTrait) && !(substituteFontTraits & NSFontItalicTrait),
platformData.m_orientation);
return fontDataFromFontPlatformData(&alternateFont, DoNotRetain);
@@ -193,7 +203,7 @@ PassRefPtr<SimpleFontData> FontCache::getLastResortFallbackFont(const FontDescri
FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontDescription, const AtomicString& family, float fontSize)
{
- NSFontTraitMask traits = fontDescription.italic() ? NSFontItalicTrait : 0;
+ NSFontTraitMask traits = fontDescription.style() ? NSFontItalicTrait : 0;
NSInteger weight = toAppKitFontWeight(fontDescription.weight());
float size = fontSize;
@@ -203,17 +213,17 @@ FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontD
NSFontManager *fontManager = [NSFontManager sharedFontManager];
NSFontTraitMask actualTraits = 0;
- if (fontDescription.italic())
+ if (fontDescription.style())
actualTraits = [fontManager traitsOfFont:nsFont];
NSInteger actualWeight = [fontManager weightOfFont:nsFont];
- NSFont *platformFont = fontDescription.usePrinterFont() ? [nsFont printerFont] : [nsFont screenFont];
+ NSFont *platformFont = useHinting() ? [nsFont screenFont] : [nsFont printerFont];
bool syntheticBold = (isAppKitFontWeightBold(weight) && !isAppKitFontWeightBold(actualWeight)) || fontDescription.isSyntheticBold();
bool syntheticOblique = ((traits & NSFontItalicTrait) && !(actualTraits & NSFontItalicTrait)) || fontDescription.isSyntheticItalic();
// FontPlatformData::font() can be null for the case of Chromium out-of-process font loading.
// In that case, we don't want to use the platformData.
- OwnPtr<FontPlatformData> platformData = adoptPtr(new FontPlatformData(platformFont, size, fontDescription.usePrinterFont(), syntheticBold, syntheticOblique, fontDescription.orientation(), fontDescription.widthVariant()));
+ OwnPtr<FontPlatformData> platformData = adoptPtr(new FontPlatformData(platformFont, size, syntheticBold, syntheticOblique, fontDescription.orientation(), fontDescription.widthVariant()));
if (!platformData->font())
return 0;
return platformData.leakPtr();
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/mac/FontComplexTextMac.cpp b/chromium/third_party/WebKit/Source/platform/fonts/mac/FontComplexTextMac.cpp
index 1626aaacb81..73eb52c1e6a 100644
--- a/chromium/third_party/WebKit/Source/platform/fonts/mac/FontComplexTextMac.cpp
+++ b/chromium/third_party/WebKit/Source/platform/fonts/mac/FontComplexTextMac.cpp
@@ -25,6 +25,7 @@
#include "config.h"
#include "platform/fonts/Font.h"
+#include "platform/fonts/Character.h"
#include "platform/fonts/FontFallbackList.h"
#include "platform/fonts/GlyphBuffer.h"
#include "platform/fonts/SimpleFontData.h"
@@ -68,23 +69,23 @@ FloatRect Font::selectionRectForComplexText(const TextRun& run, const FloatPoint
return FloatRect(floorf(point.x() + beforeWidth), point.y(), roundf(point.x() + afterWidth) - floorf(point.x() + beforeWidth), h);
}
-float Font::getGlyphsAndAdvancesForComplexText(const TextRun& run, int from, int to, GlyphBuffer& glyphBuffer, ForTextEmphasisOrNot forTextEmphasis) const
+float Font::getGlyphsAndAdvancesForComplexText(const TextRunPaintInfo& runInfo, GlyphBuffer& glyphBuffer, ForTextEmphasisOrNot forTextEmphasis) const
{
float initialAdvance;
- ComplexTextController controller(this, run, false, 0, forTextEmphasis);
- controller.advance(from);
+ ComplexTextController controller(this, runInfo.run, false, 0, forTextEmphasis);
+ controller.advance(runInfo.from);
float beforeWidth = controller.runWidthSoFar();
- controller.advance(to, &glyphBuffer);
+ controller.advance(runInfo.to, &glyphBuffer);
if (glyphBuffer.isEmpty())
return 0;
float afterWidth = controller.runWidthSoFar();
- if (run.rtl()) {
+ if (runInfo.run.rtl()) {
initialAdvance = controller.totalWidth() + controller.finalRoundingWidth() - afterWidth;
- glyphBuffer.reverse(0, glyphBuffer.size());
+ glyphBuffer.reverse();
} else
initialAdvance = beforeWidth;
@@ -105,7 +106,7 @@ void Font::drawComplexText(GraphicsContext* context, const TextRunPaintInfo& run
// This glyph buffer holds our glyphs + advances + font data for each glyph.
GlyphBuffer glyphBuffer;
- float startX = point.x() + getGlyphsAndAdvancesForComplexText(runInfo.run, runInfo.from, runInfo.to, glyphBuffer);
+ float startX = point.x() + getGlyphsAndAdvancesForComplexText(runInfo, glyphBuffer);
// We couldn't generate any glyphs for the run. Give up.
if (glyphBuffer.isEmpty())
@@ -119,7 +120,7 @@ void Font::drawComplexText(GraphicsContext* context, const TextRunPaintInfo& run
void Font::drawEmphasisMarksForComplexText(GraphicsContext* context, const TextRunPaintInfo& runInfo, const AtomicString& mark, const FloatPoint& point) const
{
GlyphBuffer glyphBuffer;
- float initialAdvance = getGlyphsAndAdvancesForComplexText(runInfo.run, runInfo.from, runInfo.to, glyphBuffer, ForTextEmphasis);
+ float initialAdvance = getGlyphsAndAdvancesForComplexText(runInfo, glyphBuffer, ForTextEmphasis);
if (glyphBuffer.isEmpty())
return;
@@ -127,7 +128,7 @@ void Font::drawEmphasisMarksForComplexText(GraphicsContext* context, const TextR
drawEmphasisMarks(context, runInfo, glyphBuffer, mark, FloatPoint(point.x() + initialAdvance, point.y()));
}
-float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const
+float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts, IntRectExtent* glyphBounds) const
{
if (preferHarfBuzz(this)) {
HarfBuzzShaper shaper(this, run);
@@ -135,12 +136,11 @@ float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFon
return shaper.totalWidth();
}
ComplexTextController controller(this, run, true, fallbackFonts);
- if (glyphOverflow) {
- glyphOverflow->top = max<int>(glyphOverflow->top, ceilf(-controller.minGlyphBoundingBoxY()) - (glyphOverflow->computeBounds ? 0 : fontMetrics().ascent()));
- glyphOverflow->bottom = max<int>(glyphOverflow->bottom, ceilf(controller.maxGlyphBoundingBoxY()) - (glyphOverflow->computeBounds ? 0 : fontMetrics().descent()));
- glyphOverflow->left = max<int>(0, ceilf(-controller.minGlyphBoundingBoxX()));
- glyphOverflow->right = max<int>(0, ceilf(controller.maxGlyphBoundingBoxX() - controller.totalWidth()));
- }
+ glyphBounds->setTop(floorf(-controller.minGlyphBoundingBoxY()));
+ glyphBounds->setBottom(ceilf(controller.maxGlyphBoundingBoxY()));
+ glyphBounds->setLeft(max<int>(0, floorf(-controller.minGlyphBoundingBoxX())));
+ glyphBounds->setRight(max<int>(0, ceilf(controller.maxGlyphBoundingBoxX() - controller.totalWidth())));
+
return controller.totalWidth();
}
@@ -176,7 +176,7 @@ const SimpleFontData* Font::fontDataForCombiningCharacterSequence(const UChar* c
const SimpleFontData* simpleFontData = fontData->fontDataForCharacter(baseCharacter);
if (variant == NormalVariant) {
if (simpleFontData->platformData().orientation() == Vertical) {
- if (isCJKIdeographOrSymbol(baseCharacter) && !simpleFontData->hasVerticalGlyphs()) {
+ if (Character::isCJKIdeographOrSymbol(baseCharacter) && !simpleFontData->hasVerticalGlyphs()) {
variant = BrokenIdeographVariant;
simpleFontData = simpleFontData->brokenIdeographFontData().get();
} else if (m_fontDescription.nonCJKGlyphOrientation() == NonCJKGlyphOrientationVerticalRight) {
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/mac/FontMac.cpp b/chromium/third_party/WebKit/Source/platform/fonts/mac/FontMac.cpp
index b0fd0274743..b140c463817 100644
--- a/chromium/third_party/WebKit/Source/platform/fonts/mac/FontMac.cpp
+++ b/chromium/third_party/WebKit/Source/platform/fonts/mac/FontMac.cpp
@@ -32,6 +32,7 @@
#include "platform/fonts/Font.h"
#include "platform/LayoutTestSupport.h"
+#include "platform/fonts/FontPlatformFeatures.h"
#include "platform/fonts/FontSmoothingMode.h"
#include "platform/fonts/GlyphBuffer.h"
#include "platform/fonts/SimpleFontData.h"
@@ -40,16 +41,15 @@
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkPaint.h"
#include "third_party/skia/include/core/SkTypeface.h"
-#include "third_party/skia/include/ports/SkTypeface_mac.h"
namespace WebCore {
-bool Font::canReturnFallbackFontsForComplexText()
+bool FontPlatformFeatures::canReturnFallbackFontsForComplexText()
{
return true;
}
-bool Font::canExpandAroundIdeographsInComplexText()
+bool FontPlatformFeatures::canExpandAroundIdeographsInComplexText()
{
return true;
}
@@ -63,23 +63,16 @@ static void setupPaint(SkPaint* paint, const SimpleFontData* fontData, const Fon
paint->setEmbeddedBitmapText(false);
paint->setTextSize(SkFloatToScalar(textSize));
paint->setVerticalText(platformData.orientation() == Vertical);
- SkTypeface* typeface = SkCreateTypefaceFromCTFont(platformData.ctFont());
- SkAutoUnref autoUnref(typeface);
- paint->setTypeface(typeface);
+ paint->setTypeface(platformData.typeface());
paint->setFakeBoldText(platformData.m_syntheticBold);
paint->setTextSkewX(platformData.m_syntheticOblique ? -SK_Scalar1 / 4 : 0);
paint->setAutohinted(false); // freetype specific
paint->setLCDRenderText(shouldSmoothFonts);
paint->setSubpixelText(true);
-#if OS(MACOSX)
// When using CoreGraphics, disable hinting when webkit-font-smoothing:antialiased is used.
// See crbug.com/152304
- if (font->fontDescription().fontSmoothing() == Antialiased)
- paint->setHinting(SkPaint::kNo_Hinting);
-#endif
-
- if (font->fontDescription().textRenderingMode() == GeometricPrecision)
+ if (font->fontDescription().fontSmoothing() == Antialiased || font->fontDescription().textRendering() == GeometricPrecision)
paint->setHinting(SkPaint::kNo_Hinting);
}
@@ -90,8 +83,6 @@ void Font::drawGlyphs(GraphicsContext* gc, const SimpleFontData* font,
const GlyphBuffer& glyphBuffer, unsigned from, unsigned numGlyphs,
const FloatPoint& point, const FloatRect& textRect) const
{
- COMPILE_ASSERT(sizeof(GlyphBufferGlyph) == sizeof(uint16_t), GlyphBufferGlyphSize_equals_uint16_t);
-
bool shouldSmoothFonts = true;
bool shouldAntialias = true;
@@ -110,12 +101,12 @@ void Font::drawGlyphs(GraphicsContext* gc, const SimpleFontData* font,
break;
}
- if (!shouldUseSmoothing() || isRunningLayoutTest()) {
+ if (isRunningLayoutTest()) {
shouldSmoothFonts = false;
- shouldAntialias = false;
+ shouldAntialias = shouldAntialias && isFontAntialiasingEnabledForTest();
}
- const GlyphBufferGlyph* glyphs = glyphBuffer.glyphs(from);
+ const Glyph* glyphs = glyphBuffer.glyphs(from);
SkScalar x = SkFloatToScalar(point.x());
SkScalar y = SkFloatToScalar(point.y());
@@ -127,7 +118,7 @@ void Font::drawGlyphs(GraphicsContext* gc, const SimpleFontData* font,
// text drawing can proceed faster. However, it's unclear when those
// patches may be upstreamed to WebKit so we always use the slower path
// here.
- const GlyphBufferAdvance* adv = glyphBuffer.advances(from);
+ const FloatSize* adv = glyphBuffer.advances(from);
SkAutoSTMalloc<32, SkPoint> storage(numGlyphs);
SkPoint* pos = storage.get();
@@ -149,32 +140,30 @@ void Font::drawGlyphs(GraphicsContext* gc, const SimpleFontData* font,
// We draw text up to two times (once for fill, once for stroke).
if (textMode & TextModeFill) {
- SkPaint paint;
- gc->setupPaintForFilling(&paint);
+ SkPaint paint = gc->fillPaint();
setupPaint(&paint, font, this, shouldAntialias, shouldSmoothFonts);
gc->adjustTextRenderMode(&paint);
paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
- gc->drawPosText(glyphs, numGlyphs * sizeof(uint16_t), pos, textRect, paint);
+ gc->drawPosText(glyphs, numGlyphs * sizeof(Glyph), pos, textRect, paint);
}
if ((textMode & TextModeStroke)
&& gc->strokeStyle() != NoStroke
&& gc->strokeThickness() > 0) {
- SkPaint paint;
- gc->setupPaintForStroking(&paint);
+ SkPaint paint = gc->strokePaint();
setupPaint(&paint, font, this, shouldAntialias, shouldSmoothFonts);
gc->adjustTextRenderMode(&paint);
paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
if (textMode & TextModeFill) {
// If we also filled, we don't want to draw shadows twice.
- // See comment in FontChromiumWin.cpp::paintSkiaText() for more details.
+ // See comment in FontHarfBuzz.cpp::paintGlyphs() for more details.
paint.setLooper(0);
}
- gc->drawPosText(glyphs, numGlyphs * sizeof(uint16_t), pos, textRect, paint);
+ gc->drawPosText(glyphs, numGlyphs * sizeof(Glyph), pos, textRect, paint);
}
if (font->platformData().orientation() == Vertical)
gc->restore();
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/mac/GlyphPageTreeNodeMac.cpp b/chromium/third_party/WebKit/Source/platform/fonts/mac/GlyphPageTreeNodeMac.cpp
deleted file mode 100644
index 704d10df799..00000000000
--- a/chromium/third_party/WebKit/Source/platform/fonts/mac/GlyphPageTreeNodeMac.cpp
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "platform/fonts/GlyphPageTreeNode.h"
-
-#include <ApplicationServices/ApplicationServices.h>
-#include "platform/fonts/Font.h"
-#include "platform/fonts/SimpleFontData.h"
-
-// Forward declare Mac SPIs.
-// Request for public API: rdar://13787589
-extern "C" {
-void CGFontGetGlyphsForUnichars(CGFontRef font, const UniChar chars[], CGGlyph glyphs[], size_t length);
-}
-
-namespace WebCore {
-
-static bool shouldUseCoreText(UChar* buffer, unsigned bufferLength, const SimpleFontData* fontData)
-{
- if (fontData->platformData().isCompositeFontReference())
- return true;
- if (fontData->platformData().widthVariant() != RegularWidth || fontData->hasVerticalGlyphs()) {
- // Ideographs don't have a vertical variant or width variants.
- for (unsigned i = 0; i < bufferLength; ++i) {
- if (!Font::isCJKIdeograph(buffer[i]))
- return true;
- }
- }
-
- return false;
-}
-
-bool GlyphPage::fill(unsigned offset, unsigned length, UChar* buffer, unsigned bufferLength, const SimpleFontData* fontData)
-{
- bool haveGlyphs = false;
-
- Vector<CGGlyph, 512> glyphs(bufferLength);
- if (!shouldUseCoreText(buffer, bufferLength, fontData)) {
- CGFontGetGlyphsForUnichars(fontData->platformData().cgFont(), buffer, glyphs.data(), bufferLength);
- for (unsigned i = 0; i < length; ++i) {
- if (!glyphs[i])
- setGlyphDataForIndex(offset + i, 0, 0);
- else {
- setGlyphDataForIndex(offset + i, glyphs[i], fontData);
- haveGlyphs = true;
- }
- }
- } else if (!fontData->platformData().isCompositeFontReference() && fontData->platformData().widthVariant() != RegularWidth
- && CTFontGetGlyphsForCharacters(fontData->platformData().ctFont(), buffer, glyphs.data(), bufferLength)) {
- // When buffer consists of surrogate pairs, CTFontGetGlyphsForCharacters
- // places the glyphs at indices corresponding to the first character of each pair.
- unsigned glyphStep = bufferLength / length;
- for (unsigned i = 0; i < length; ++i) {
- if (!glyphs[i * glyphStep])
- setGlyphDataForIndex(offset + i, 0, 0);
- else {
- setGlyphDataForIndex(offset + i, glyphs[i * glyphStep], fontData);
- haveGlyphs = true;
- }
- }
- } else {
- // We ask CoreText for possible vertical variant glyphs
- RetainPtr<CFStringRef> string(AdoptCF, CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault, buffer, bufferLength, kCFAllocatorNull));
- RetainPtr<CFAttributedStringRef> attributedString(AdoptCF, CFAttributedStringCreate(kCFAllocatorDefault, string.get(), fontData->getCFStringAttributes(0, fontData->hasVerticalGlyphs() ? Vertical : Horizontal)));
- RetainPtr<CTLineRef> line(AdoptCF, CTLineCreateWithAttributedString(attributedString.get()));
-
- CFArrayRef runArray = CTLineGetGlyphRuns(line.get());
- CFIndex runCount = CFArrayGetCount(runArray);
-
- // Initialize glyph entries
- for (unsigned index = 0; index < length; ++index)
- setGlyphDataForIndex(offset + index, 0, 0);
-
- Vector<CGGlyph, 512> glyphVector;
- Vector<CFIndex, 512> indexVector;
- bool done = false;
-
- // For the CGFont comparison in the loop, use the CGFont that Core Text assigns to the CTFont. This may
- // be non-CFEqual to fontData->platformData().cgFont().
- RetainPtr<CGFontRef> cgFont(AdoptCF, CTFontCopyGraphicsFont(fontData->platformData().ctFont(), 0));
-
- for (CFIndex r = 0; r < runCount && !done ; ++r) {
- // CTLine could map characters over multiple fonts using its own font fallback list.
- // We need to pick runs that use the exact font we need, i.e., fontData->platformData().ctFont().
- CTRunRef ctRun = static_cast<CTRunRef>(CFArrayGetValueAtIndex(runArray, r));
- ASSERT(CFGetTypeID(ctRun) == CTRunGetTypeID());
-
- CFDictionaryRef attributes = CTRunGetAttributes(ctRun);
- CTFontRef runFont = static_cast<CTFontRef>(CFDictionaryGetValue(attributes, kCTFontAttributeName));
- RetainPtr<CGFontRef> runCGFont(AdoptCF, CTFontCopyGraphicsFont(runFont, 0));
- // Use CGFont here as CFEqual for CTFont counts all attributes for font.
- bool gotBaseFont = CFEqual(cgFont.get(), runCGFont.get());
- if (gotBaseFont || fontData->platformData().isCompositeFontReference()) {
- // This run uses the font we want. Extract glyphs.
- CFIndex glyphCount = CTRunGetGlyphCount(ctRun);
- const CGGlyph* glyphs = CTRunGetGlyphsPtr(ctRun);
- if (!glyphs) {
- glyphVector.resize(glyphCount);
- CTRunGetGlyphs(ctRun, CFRangeMake(0, 0), glyphVector.data());
- glyphs = glyphVector.data();
- }
- const CFIndex* stringIndices = CTRunGetStringIndicesPtr(ctRun);
- if (!stringIndices) {
- indexVector.resize(glyphCount);
- CTRunGetStringIndices(ctRun, CFRangeMake(0, 0), indexVector.data());
- stringIndices = indexVector.data();
- }
-
- if (gotBaseFont) {
- for (CFIndex i = 0; i < glyphCount; ++i) {
- if (stringIndices[i] >= static_cast<CFIndex>(length)) {
- done = true;
- break;
- }
- if (glyphs[i]) {
- setGlyphDataForIndex(offset + stringIndices[i], glyphs[i], fontData);
- haveGlyphs = true;
- }
- }
- } else {
- const SimpleFontData* runSimple = fontData->getCompositeFontReferenceFontData((NSFont *)runFont);
- if (runSimple) {
- for (CFIndex i = 0; i < glyphCount; ++i) {
- if (stringIndices[i] >= static_cast<CFIndex>(length)) {
- done = true;
- break;
- }
- if (glyphs[i]) {
- setGlyphDataForIndex(offset + stringIndices[i], glyphs[i], runSimple);
- haveGlyphs = true;
- }
- }
- }
- }
- }
- }
- }
-
- return haveGlyphs;
-}
-
-} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/mac/MemoryActivatedFont.mm b/chromium/third_party/WebKit/Source/platform/fonts/mac/MemoryActivatedFont.mm
index 3f3bbef007d..c96fe1e1e58 100644
--- a/chromium/third_party/WebKit/Source/platform/fonts/mac/MemoryActivatedFont.mm
+++ b/chromium/third_party/WebKit/Source/platform/fonts/mac/MemoryActivatedFont.mm
@@ -118,10 +118,10 @@ PassRefPtr<MemoryActivatedFont> loadFontFromBrowserProcess(NSFont* nsFont)
// font due to being blocked by the sandbox.
// This by definition shouldn't happen if there is no sandbox support.
ASSERT_NOT_REACHED();
- return 0;
+ return nullptr;
}
if (!sandboxSupport->loadFont(nsFont, &tmpCGFont, &fontID))
- return 0;
+ return nullptr;
RetainPtr<CGFontRef> cgFont(tmpCGFont);
// Now that we have the fontID from the browser process, we can consult
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/mac/SimpleFontDataCoreText.cpp b/chromium/third_party/WebKit/Source/platform/fonts/mac/SimpleFontDataCoreText.cpp
index 80a146e1f48..e3b0b86a380 100644
--- a/chromium/third_party/WebKit/Source/platform/fonts/mac/SimpleFontDataCoreText.cpp
+++ b/chromium/third_party/WebKit/Source/platform/fonts/mac/SimpleFontDataCoreText.cpp
@@ -27,15 +27,24 @@
#include "config.h"
#include "platform/fonts/SimpleFontData.h"
+#include "platform/fonts/Character.h"
+#include "platform/fonts/Font.h"
+#include "platform/fonts/GlyphPage.h"
#include <ApplicationServices/ApplicationServices.h>
+// Forward declare Mac SPIs.
+// Request for public API: rdar://13787589
+extern "C" {
+void CGFontGetGlyphsForUnichars(CGFontRef, const UniChar chars[], CGGlyph glyphs[], size_t length);
+}
+
namespace WebCore {
CFDictionaryRef SimpleFontData::getCFStringAttributes(TypesettingFeatures typesettingFeatures, FontOrientation orientation) const
{
unsigned key = typesettingFeatures + 1;
HashMap<unsigned, RetainPtr<CFDictionaryRef> >::AddResult addResult = m_CFStringAttributes.add(key, RetainPtr<CFDictionaryRef>());
- RetainPtr<CFDictionaryRef>& attributesDictionary = addResult.iterator->value;
+ RetainPtr<CFDictionaryRef>& attributesDictionary = addResult.storedValue->value;
if (!addResult.isNewEntry)
return attributesDictionary.get();
@@ -63,4 +72,130 @@ CFDictionaryRef SimpleFontData::getCFStringAttributes(TypesettingFeatures typese
return attributesDictionary.get();
}
+static bool shouldUseCoreText(UChar* buffer, unsigned bufferLength, const SimpleFontData* fontData)
+{
+ if (fontData->platformData().isCompositeFontReference())
+ return true;
+
+ // CoreText doesn't have vertical glyphs of surrogate pair characters.
+ // Therefore, we should not use CoreText, but this always returns horizontal glyphs.
+ // FIXME: We should use vertical glyphs. https://code.google.com/p/chromium/issues/detail?id=340173
+ if (bufferLength >= 2 && U_IS_SURROGATE(buffer[0]) && fontData->hasVerticalGlyphs()) {
+ ASSERT(U_IS_SURROGATE_LEAD(buffer[0]));
+ ASSERT(U_IS_TRAIL(buffer[1]));
+ return false;
+ }
+
+ if (fontData->platformData().widthVariant() != RegularWidth || fontData->hasVerticalGlyphs()) {
+ // Ideographs don't have a vertical variant or width variants.
+ for (unsigned i = 0; i < bufferLength; ++i) {
+ if (!Character::isCJKIdeograph(buffer[i]))
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool SimpleFontData::fillGlyphPage(GlyphPage* pageToFill, unsigned offset, unsigned length, UChar* buffer, unsigned bufferLength) const
+{
+ bool haveGlyphs = false;
+
+ Vector<CGGlyph, 512> glyphs(bufferLength);
+ if (!shouldUseCoreText(buffer, bufferLength, this)) {
+ CGFontGetGlyphsForUnichars(platformData().cgFont(), buffer, glyphs.data(), bufferLength);
+ for (unsigned i = 0; i < length; ++i) {
+ if (glyphs[i]) {
+ pageToFill->setGlyphDataForIndex(offset + i, glyphs[i], this);
+ haveGlyphs = true;
+ }
+ }
+ } else if (!platformData().isCompositeFontReference() && platformData().widthVariant() != RegularWidth
+ && CTFontGetGlyphsForCharacters(platformData().ctFont(), buffer, glyphs.data(), bufferLength)) {
+ // When buffer consists of surrogate pairs, CTFontGetGlyphsForCharacters
+ // places the glyphs at indices corresponding to the first character of each pair.
+ unsigned glyphStep = bufferLength / length;
+ for (unsigned i = 0; i < length; ++i) {
+ if (glyphs[i * glyphStep]) {
+ pageToFill->setGlyphDataForIndex(offset + i, glyphs[i * glyphStep], this);
+ haveGlyphs = true;
+ }
+ }
+ } else {
+ // We ask CoreText for possible vertical variant glyphs
+ RetainPtr<CFStringRef> string(AdoptCF, CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault, buffer, bufferLength, kCFAllocatorNull));
+ RetainPtr<CFAttributedStringRef> attributedString(AdoptCF, CFAttributedStringCreate(kCFAllocatorDefault, string.get(), getCFStringAttributes(0, hasVerticalGlyphs() ? Vertical : Horizontal)));
+ RetainPtr<CTLineRef> line(AdoptCF, CTLineCreateWithAttributedString(attributedString.get()));
+
+ CFArrayRef runArray = CTLineGetGlyphRuns(line.get());
+ CFIndex runCount = CFArrayGetCount(runArray);
+
+ Vector<CGGlyph, 512> glyphVector;
+ Vector<CFIndex, 512> indexVector;
+ bool done = false;
+
+ // For the CGFont comparison in the loop, use the CGFont that Core Text assigns to the CTFont. This may
+ // be non-CFEqual to platformData().cgFont().
+ RetainPtr<CGFontRef> cgFont(AdoptCF, CTFontCopyGraphicsFont(platformData().ctFont(), 0));
+
+ for (CFIndex r = 0; r < runCount && !done ; ++r) {
+ // CTLine could map characters over multiple fonts using its own font fallback list.
+ // We need to pick runs that use the exact font we need, i.e., platformData().ctFont().
+ CTRunRef ctRun = static_cast<CTRunRef>(CFArrayGetValueAtIndex(runArray, r));
+ ASSERT(CFGetTypeID(ctRun) == CTRunGetTypeID());
+
+ CFDictionaryRef attributes = CTRunGetAttributes(ctRun);
+ CTFontRef runFont = static_cast<CTFontRef>(CFDictionaryGetValue(attributes, kCTFontAttributeName));
+ RetainPtr<CGFontRef> runCGFont(AdoptCF, CTFontCopyGraphicsFont(runFont, 0));
+ // Use CGFont here as CFEqual for CTFont counts all attributes for font.
+ bool gotBaseFont = CFEqual(cgFont.get(), runCGFont.get());
+ if (gotBaseFont || platformData().isCompositeFontReference()) {
+ // This run uses the font we want. Extract glyphs.
+ CFIndex glyphCount = CTRunGetGlyphCount(ctRun);
+ const CGGlyph* glyphs = CTRunGetGlyphsPtr(ctRun);
+ if (!glyphs) {
+ glyphVector.resize(glyphCount);
+ CTRunGetGlyphs(ctRun, CFRangeMake(0, 0), glyphVector.data());
+ glyphs = glyphVector.data();
+ }
+ const CFIndex* stringIndices = CTRunGetStringIndicesPtr(ctRun);
+ if (!stringIndices) {
+ indexVector.resize(glyphCount);
+ CTRunGetStringIndices(ctRun, CFRangeMake(0, 0), indexVector.data());
+ stringIndices = indexVector.data();
+ }
+
+ if (gotBaseFont) {
+ for (CFIndex i = 0; i < glyphCount; ++i) {
+ if (stringIndices[i] >= static_cast<CFIndex>(length)) {
+ done = true;
+ break;
+ }
+ if (glyphs[i]) {
+ pageToFill->setGlyphDataForIndex(offset + stringIndices[i], glyphs[i], this);
+ haveGlyphs = true;
+ }
+ }
+ } else {
+ const SimpleFontData* runSimple = getCompositeFontReferenceFontData((NSFont *)runFont);
+ if (runSimple) {
+ for (CFIndex i = 0; i < glyphCount; ++i) {
+ if (stringIndices[i] >= static_cast<CFIndex>(length)) {
+ done = true;
+ break;
+ }
+ if (glyphs[i]) {
+ pageToFill->setGlyphDataForIndex(offset + stringIndices[i], glyphs[i], runSimple);
+ haveGlyphs = true;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return haveGlyphs;
+}
+
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/mac/SimpleFontDataMac.mm b/chromium/third_party/WebKit/Source/platform/fonts/mac/SimpleFontDataMac.mm
index 4d5533eea80..1fce9b54549 100644
--- a/chromium/third_party/WebKit/Source/platform/fonts/mac/SimpleFontDataMac.mm
+++ b/chromium/third_party/WebKit/Source/platform/fonts/mac/SimpleFontDataMac.mm
@@ -31,6 +31,8 @@
#import <ApplicationServices/ApplicationServices.h>
#import <float.h>
#import <unicode/uchar.h>
+#import "platform/LayoutTestSupport.h"
+#import "platform/RuntimeEnabledFeatures.h"
#import "platform/SharedBuffer.h"
#import "platform/fonts/Font.h"
#import "platform/fonts/FontCache.h"
@@ -106,6 +108,14 @@ static NSString *webFallbackFontFamily(void)
return webFallbackFontFamily.get();
}
+static bool useHinting()
+{
+ // Enable hinting when subpixel font scaling is disabled or
+ // when running the set of standard non-subpixel layout tests,
+ // otherwise use subpixel glyph positioning.
+ return (isRunningLayoutTest() && !isFontAntialiasingEnabledForTest()) || !RuntimeEnabledFeatures::subpixelFontScalingEnabled();
+}
+
const SimpleFontData* SimpleFontData::getCompositeFontReferenceFontData(NSFont *key) const
{
if (key && !CFEqual(RetainPtr<CFStringRef>(AdoptCF, CTFontCopyPostScriptName(CTFontRef(key))).get(), CFSTR("LastResort"))) {
@@ -119,15 +129,14 @@ const SimpleFontData* SimpleFontData::getCompositeFontReferenceFontData(NSFont *
return found;
}
if (CFMutableDictionaryRef dictionary = m_derivedFontData->compositeFontReferences.get()) {
- bool isUsingPrinterFont = platformData().isPrinterFont();
- NSFont *substituteFont = isUsingPrinterFont ? [key printerFont] : [key screenFont];
+ NSFont *substituteFont = [key printerFont];
CTFontSymbolicTraits traits = CTFontGetSymbolicTraits(toCTFontRef(substituteFont));
bool syntheticBold = platformData().syntheticBold() && !(traits & kCTFontBoldTrait);
bool syntheticOblique = platformData().syntheticOblique() && !(traits & kCTFontItalicTrait);
- FontPlatformData substitutePlatform(substituteFont, platformData().size(), isUsingPrinterFont, syntheticBold, syntheticOblique, platformData().orientation(), platformData().widthVariant());
- SimpleFontData* value = new SimpleFontData(substitutePlatform, isCustomFont() ? CustomFontData::create(false) : 0);
+ FontPlatformData substitutePlatform(substituteFont, platformData().size(), syntheticBold, syntheticOblique, platformData().orientation(), platformData().widthVariant());
+ SimpleFontData* value = new SimpleFontData(substitutePlatform, isCustomFont() ? CustomFontData::create() : nullptr);
if (value) {
CFDictionaryAddValue(dictionary, key, value);
return value;
@@ -155,7 +164,7 @@ void SimpleFontData::platformInit()
fallbackFontFamily = @"Times New Roman";
else
fallbackFontFamily = webFallbackFontFamily();
-
+
// Try setting up the alternate font.
// This is a last ditch effort to use a substitute font when something has gone wrong.
#if !ERROR_DISABLED
@@ -195,11 +204,12 @@ void SimpleFontData::platformInit()
WTF_LOG_ERROR("failed to set up font, using system font %s", m_platformData.font());
initFontData(this);
}
-
+
int iAscent;
int iDescent;
int iLineGap;
unsigned unitsPerEm;
+
iAscent = CGFontGetAscent(m_platformData.cgFont());
// Some fonts erroneously specify a positive descender value. We follow Core Text in assuming that
// such fonts meant the same distance, but in the reverse direction.
@@ -211,6 +221,8 @@ void SimpleFontData::platformInit()
float ascent = scaleEmToUnits(iAscent, unitsPerEm) * pointSize;
float descent = -scaleEmToUnits(iDescent, unitsPerEm) * pointSize;
float lineGap = scaleEmToUnits(iLineGap, unitsPerEm) * pointSize;
+ float underlineThickness = CTFontGetUnderlineThickness(m_platformData.ctFont());
+ float underlinePosition = CTFontGetUnderlinePosition(m_platformData.ctFont());
// We need to adjust Times, Helvetica, and Courier to closely match the
// vertical metrics of their Microsoft counterparts that are the de facto
@@ -230,7 +242,7 @@ void SimpleFontData::platformInit()
lineGap -= 3 - descent;
descent = 3;
}
-
+
if (platformData().orientation() == Vertical && !isTextOrientationFallback())
m_hasVerticalGlyphs = fontHasVerticalGlyphs(m_platformData.ctFont());
@@ -253,6 +265,8 @@ void SimpleFontData::platformInit()
m_fontMetrics.setDescent(descent);
m_fontMetrics.setLineGap(lineGap);
m_fontMetrics.setXHeight(xHeight);
+ m_fontMetrics.setUnderlineThickness(underlineThickness);
+ m_fontMetrics.setUnderlinePosition(underlinePosition);
}
static CFDataRef copyFontTableForTag(FontPlatformData& platformData, FourCharCode tableName)
@@ -264,7 +278,7 @@ void SimpleFontData::platformCharWidthInit()
{
m_avgCharWidth = 0;
m_maxCharWidth = 0;
-
+
RetainPtr<CFDataRef> os2Table(AdoptCF, copyFontTableForTag(m_platformData, 'OS/2'));
if (os2Table && CFDataGetLength(os2Table.get()) >= 4) {
const UInt8* os2 = CFDataGetBytePtr(os2Table.get());
@@ -304,16 +318,15 @@ PassRefPtr<SimpleFontData> SimpleFontData::platformCreateScaledFontData(const Fo
if (isCustomFont()) {
FontPlatformData scaledFontData(m_platformData);
scaledFontData.m_size = scaledFontData.m_size * scaleFactor;
- return SimpleFontData::create(scaledFontData, CustomFontData::create(false));
+ return SimpleFontData::create(scaledFontData, CustomFontData::create());
}
BEGIN_BLOCK_OBJC_EXCEPTIONS;
float size = m_platformData.size() * scaleFactor;
- FontPlatformData scaledFontData([[NSFontManager sharedFontManager] convertFont:m_platformData.font() toSize:size], size, m_platformData.isPrinterFont(), false, false, m_platformData.orientation());
+ FontPlatformData scaledFontData([[NSFontManager sharedFontManager] convertFont:m_platformData.font() toSize:size], size, false, false, m_platformData.orientation());
- // AppKit resets the type information (screen/printer) when you convert a font to a different size.
- // We have to fix up the font that we're handed back.
- scaledFontData.setFont(fontDescription.usePrinterFont() ? [scaledFontData.font() printerFont] : [scaledFontData.font() screenFont]);
+ // AppKit forgets about hinting property when scaling, so we have to remind it.
+ scaledFontData.setFont(useHinting() ? [scaledFontData.font() screenFont] : [scaledFontData.font() printerFont]);
if (scaledFontData.font()) {
NSFontManager *fontManager = [NSFontManager sharedFontManager];
@@ -333,16 +346,7 @@ PassRefPtr<SimpleFontData> SimpleFontData::platformCreateScaledFontData(const Fo
}
END_BLOCK_OBJC_EXCEPTIONS;
- return 0;
-}
-
-bool SimpleFontData::containsCharacters(const UChar* characters, int length) const
-{
- NSString *string = [[NSString alloc] initWithCharactersNoCopy:const_cast<unichar*>(characters) length:length freeWhenDone:NO];
- NSCharacterSet *set = [[m_platformData.font() coveredCharacterSet] invertedSet];
- bool result = set && [string rangeOfCharacterFromSet:set].location == NSNotFound;
- [string release];
- return result;
+ return nullptr;
}
void SimpleFontData::determinePitch()
@@ -425,7 +429,7 @@ bool SimpleFontData::canRenderCombiningCharacterSequence(const UChar* characters
WTF::HashMap<String, bool>::AddResult addResult = m_combiningCharacterSequenceSupport->add(String(characters, length), false);
if (!addResult.isNewEntry)
- return addResult.iterator->value;
+ return addResult.storedValue->value;
RetainPtr<CGFontRef> cgFont(AdoptCF, CTFontCopyGraphicsFont(platformData().ctFont(), 0));
@@ -445,7 +449,7 @@ bool SimpleFontData::canRenderCombiningCharacterSequence(const UChar* characters
return false;
}
- addResult.iterator->value = true;
+ addResult.storedValue->value = true;
return true;
}
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/opentype/OpenTypeSanitizer.cpp b/chromium/third_party/WebKit/Source/platform/fonts/opentype/OpenTypeSanitizer.cpp
index 4829bd0fd0f..a66fec97067 100644
--- a/chromium/third_party/WebKit/Source/platform/fonts/opentype/OpenTypeSanitizer.cpp
+++ b/chromium/third_party/WebKit/Source/platform/fonts/opentype/OpenTypeSanitizer.cpp
@@ -31,7 +31,7 @@
#include "config.h"
#include "platform/fonts/opentype/OpenTypeSanitizer.h"
-#include "RuntimeEnabledFeatures.h"
+#include "platform/RuntimeEnabledFeatures.h"
#include "platform/SharedBuffer.h"
#include "opentype-sanitiser.h"
#include "ots-memory-stream.h"
@@ -41,12 +41,12 @@ namespace WebCore {
PassRefPtr<SharedBuffer> OpenTypeSanitizer::sanitize()
{
if (!m_buffer)
- return 0;
+ return nullptr;
// This is the largest web font size which we'll try to transcode.
static const size_t maxWebFontSize = 30 * 1024 * 1024; // 30 MB
if (m_buffer->size() > maxWebFontSize)
- return 0;
+ return nullptr;
if (RuntimeEnabledFeatures::woff2Enabled())
ots::EnableWOFF2();
@@ -60,7 +60,7 @@ PassRefPtr<SharedBuffer> OpenTypeSanitizer::sanitize()
ots::ExpandingMemoryStream output(m_buffer->size(), maxWebFontSize);
if (!ots::Process(&output, reinterpret_cast<const uint8_t*>(m_buffer->data()), m_buffer->size()))
- return 0;
+ return nullptr;
const size_t transcodeLen = output.Tell();
return SharedBuffer::create(static_cast<unsigned char*>(output.get()), transcodeLen);
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/opentype/OpenTypeVerticalData.cpp b/chromium/third_party/WebKit/Source/platform/fonts/opentype/OpenTypeVerticalData.cpp
index 7c8ab6ec5ce..c1df3abc0b6 100644
--- a/chromium/third_party/WebKit/Source/platform/fonts/opentype/OpenTypeVerticalData.cpp
+++ b/chromium/third_party/WebKit/Source/platform/fonts/opentype/OpenTypeVerticalData.cpp
@@ -560,10 +560,9 @@ void OpenTypeVerticalData::substituteWithVerticalGlyphs(const SimpleFontData* fo
return;
for (unsigned index = offset, end = offset + length; index < end; ++index) {
- Glyph glyph = glyphPage->glyphAt(index);
- if (glyph) {
- ASSERT(glyphPage->glyphDataForIndex(index).fontData == font);
- Glyph to = map.get(glyph);
+ GlyphData glyphData = glyphPage->glyphDataForIndex(index);
+ if (glyphData.glyph && glyphData.fontData == font) {
+ Glyph to = map.get(glyphData.glyph);
if (to)
glyphPage->setGlyphDataForIndex(index, to, font);
}
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/skia/FontCacheSkia.cpp b/chromium/third_party/WebKit/Source/platform/fonts/skia/FontCacheSkia.cpp
index 6498da1a56e..1dfc9c768e5 100644
--- a/chromium/third_party/WebKit/Source/platform/fonts/skia/FontCacheSkia.cpp
+++ b/chromium/third_party/WebKit/Source/platform/fonts/skia/FontCacheSkia.cpp
@@ -49,57 +49,70 @@ void FontCache::platformInit()
}
#if !OS(WIN) && !OS(ANDROID)
-PassRefPtr<SimpleFontData> FontCache::platformFallbackForCharacter(const FontDescription& fontDescription, UChar32 c, const SimpleFontData*, bool)
+PassRefPtr<SimpleFontData> FontCache::fallbackFontForCharacter(const FontDescription& fontDescription, UChar32 c, const SimpleFontData*)
{
icu::Locale locale = icu::Locale::getDefault();
- FontCache::SimpleFontFamily family;
- FontCache::getFontFamilyForCharacter(c, locale.getLanguage(), &family);
- if (family.name.isEmpty())
- return 0;
+ FontCache::PlatformFallbackFont fallbackFont;
+ FontCache::getFontForCharacter(c, locale.getLanguage(), &fallbackFont);
+ if (fallbackFont.name.isEmpty())
+ return nullptr;
- AtomicString atomicFamily(family.name);
+ AtomicString atomicFamily(fallbackFont.name);
// Changes weight and/or italic of given FontDescription depends on
// the result of fontconfig so that keeping the correct font mapping
// of the given character. See http://crbug.com/32109 for details.
- bool shouldSetFakeBold = false;
- bool shouldSetFakeItalic = false;
+ bool shouldSetSyntheticBold = false;
+ bool shouldSetSyntheticItalic = false;
FontDescription description(fontDescription);
- if (family.isBold && description.weight() < FontWeightBold)
+ if (fallbackFont.isBold && description.weight() < FontWeightBold)
description.setWeight(FontWeightBold);
- if (!family.isBold && description.weight() >= FontWeightBold) {
- shouldSetFakeBold = true;
+ if (!fallbackFont.isBold && description.weight() >= FontWeightBold) {
+ shouldSetSyntheticBold = true;
description.setWeight(FontWeightNormal);
}
- if (family.isItalic && description.italic() == FontItalicOff)
- description.setItalic(FontItalicOn);
- if (!family.isItalic && description.italic() == FontItalicOn) {
- shouldSetFakeItalic = true;
- description.setItalic(FontItalicOff);
+ if (fallbackFont.isItalic && description.style() == FontStyleNormal)
+ description.setStyle(FontStyleItalic);
+ if (!fallbackFont.isItalic && description.style() == FontStyleItalic) {
+ shouldSetSyntheticItalic = true;
+ description.setStyle(FontStyleNormal);
}
FontPlatformData* substitutePlatformData = getFontPlatformData(description, atomicFamily);
if (!substitutePlatformData)
- return 0;
+ return nullptr;
FontPlatformData platformData = FontPlatformData(*substitutePlatformData);
- platformData.setFakeBold(shouldSetFakeBold);
- platformData.setFakeItalic(shouldSetFakeItalic);
+ platformData.setSyntheticBold(shouldSetSyntheticBold);
+ platformData.setSyntheticItalic(shouldSetSyntheticItalic);
return fontDataFromFontPlatformData(&platformData, DoNotRetain);
}
-#endif // !OS(WINDOWNS) && !OS(ANDROID)
+#endif // !OS(WIN) && !OS(ANDROID)
PassRefPtr<SimpleFontData> FontCache::getLastResortFallbackFont(const FontDescription& description, ShouldRetain shouldRetain)
{
const AtomicString fallbackFontFamily = getFallbackFontFamily(description);
- const FontPlatformData* fontPlatformData = 0;
- if (!fallbackFontFamily.isEmpty())
- fontPlatformData = getFontPlatformData(description, fallbackFontFamily);
+ const FontPlatformData* fontPlatformData = getFontPlatformData(description, fallbackFontFamily);
+ // We should at least have Sans or Arial which is the last resort fallback of SkFontHost ports.
+ if (!fontPlatformData) {
+ DEFINE_STATIC_LOCAL(const AtomicString, sansStr, ("Sans", AtomicString::ConstructFromLiteral));
+ fontPlatformData = getFontPlatformData(description, sansStr);
+ }
if (!fontPlatformData) {
- // we should at least have Arial; this is the SkFontHost_fontconfig last resort fallback
DEFINE_STATIC_LOCAL(const AtomicString, arialStr, ("Arial", AtomicString::ConstructFromLiteral));
fontPlatformData = getFontPlatformData(description, arialStr);
}
+#if OS(WIN)
+ // Try some more Windows-specific fallbacks.
+ if (!fontPlatformData) {
+ DEFINE_STATIC_LOCAL(const AtomicString, msuigothicStr, ("MS UI Gothic", AtomicString::ConstructFromLiteral));
+ fontPlatformData = getFontPlatformData(description, msuigothicStr);
+ }
+ if (!fontPlatformData) {
+ DEFINE_STATIC_LOCAL(const AtomicString, mssansserifStr, ("Microsoft Sans Serif", AtomicString::ConstructFromLiteral));
+ fontPlatformData = getFontPlatformData(description, mssansserifStr);
+ }
+#endif
ASSERT(fontPlatformData);
return fontDataFromFontPlatformData(fontPlatformData, shouldRetain);
@@ -107,42 +120,29 @@ PassRefPtr<SimpleFontData> FontCache::getLastResortFallbackFont(const FontDescri
PassRefPtr<SkTypeface> FontCache::createTypeface(const FontDescription& fontDescription, const AtomicString& family, CString& name)
{
- name = "";
-
// If we're creating a fallback font (e.g. "-webkit-monospace"), convert the name into
// the fallback name (like "monospace") that fontconfig understands.
if (!family.length() || family.startsWith("-webkit-")) {
- static const struct {
- FontDescription::GenericFamilyType mType;
- const char* mName;
- } fontDescriptions[] = {
- { FontDescription::SerifFamily, "serif" },
- { FontDescription::SansSerifFamily, "sans-serif" },
- { FontDescription::MonospaceFamily, "monospace" },
- { FontDescription::CursiveFamily, "cursive" },
- { FontDescription::FantasyFamily, "fantasy" }
- };
-
- FontDescription::GenericFamilyType type = fontDescription.genericFamily();
- for (unsigned i = 0; i < SK_ARRAY_COUNT(fontDescriptions); i++) {
- if (type == fontDescriptions[i].mType) {
- name = fontDescriptions[i].mName;
- break;
- }
- }
+ name = getFallbackFontFamily(fontDescription).string().utf8();
} else {
// convert the name to utf8
- name = family.string().utf8();
+ name = family.utf8();
}
int style = SkTypeface::kNormal;
if (fontDescription.weight() >= FontWeightBold)
style |= SkTypeface::kBold;
- if (fontDescription.italic())
+ if (fontDescription.style())
style |= SkTypeface::kItalic;
+#if OS(WIN)
+ if (s_sideloadedFonts) {
+ HashMap<String, SkTypeface*>::iterator sideloadedFont = s_sideloadedFonts->find(name.data());
+ if (sideloadedFont != s_sideloadedFonts->end()) {
+ return adoptRef(sideloadedFont->value);
+ }
+ }
// FIXME: Use SkFontStyle and matchFamilyStyle instead of legacyCreateTypeface.
-#if OS(WIN) && !ENABLE(GDI_FONTS_ON_WINDOWS)
if (m_fontManager)
return adoptRef(m_fontManager->legacyCreateTypeface(name.data(), style));
#endif
@@ -162,11 +162,11 @@ FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontD
name.data(),
fontSize,
(fontDescription.weight() >= FontWeightBold && !tf->isBold()) || fontDescription.isSyntheticBold(),
- (fontDescription.italic() && !tf->isItalic()) || fontDescription.isSyntheticItalic(),
+ (fontDescription.style() && !tf->isItalic()) || fontDescription.isSyntheticItalic(),
fontDescription.orientation(),
fontDescription.useSubpixelPositioning());
return result;
}
-#endif // !OS(WINDOWNS)
+#endif // !OS(WIN)
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/skia/FontCustomPlatformDataSkia.cpp b/chromium/third_party/WebKit/Source/platform/fonts/skia/FontCustomPlatformDataSkia.cpp
index ecf42ef0664..3f552dc11e6 100644
--- a/chromium/third_party/WebKit/Source/platform/fonts/skia/FontCustomPlatformDataSkia.cpp
+++ b/chromium/third_party/WebKit/Source/platform/fonts/skia/FontCustomPlatformDataSkia.cpp
@@ -57,26 +57,31 @@ FontPlatformData FontCustomPlatformData::fontPlatformData(float size, bool bold,
{
ASSERT(m_typeface);
#if OS(WIN)
- // FIXME: Skia currently renders synthetic bold and italics with hinting and without
- // linear metrics on windows. Using CreateFromName and specifying the bold/italics
- // style allows for proper rendering of synthetic style. Once Skia has been updated
- // this workaround will no longer be needed. crbug.com/332958
- bool syntheticBold = bold && !m_typeface->isBold();
- bool syntheticItalic = italic && !m_typeface->isItalic();
- if (syntheticBold || syntheticItalic) {
- SkString name;
- m_typeface->getFamilyName(&name);
+ if (!FontCache::useDirectWrite()) {
+ // FIXME: Skia currently renders synthetic bold and italics with
+ // hinting and without linear metrics on the windows GDI backend
+ // while the DirectWrite backend does the right thing. Using
+ // CreateFromName and specifying the bold/italics style allows
+ // for proper rendering of synthetic style. Once Skia has been
+ // updated this workaround will no longer be needed.
+ // http://crbug.com/332958
+ bool syntheticBold = bold && !m_typeface->isBold();
+ bool syntheticItalic = italic && !m_typeface->isItalic();
+ if (syntheticBold || syntheticItalic) {
+ SkString name;
+ m_typeface->getFamilyName(&name);
- int style = SkTypeface::kNormal;
- if (syntheticBold)
- style |= SkTypeface::kBold;
- if (syntheticItalic)
- style |= SkTypeface::kItalic;
+ int style = SkTypeface::kNormal;
+ if (syntheticBold)
+ style |= SkTypeface::kBold;
+ if (syntheticItalic)
+ style |= SkTypeface::kItalic;
- RefPtr<SkTypeface> typeface = adoptRef(SkTypeface::CreateFromName(name.c_str(), static_cast<SkTypeface::Style>(style)));
- syntheticBold = false;
- syntheticItalic = false;
- return FontPlatformData(typeface.release(), "", size, syntheticBold, syntheticItalic, orientation);
+ RefPtr<SkTypeface> typeface = adoptRef(FontCache::fontCache()->fontManager()->legacyCreateTypeface(name.c_str(), static_cast<SkTypeface::Style>(style)));
+ syntheticBold = false;
+ syntheticItalic = false;
+ return FontPlatformData(typeface.release(), "", size, syntheticBold, syntheticItalic, orientation);
+ }
}
#endif
return FontPlatformData(m_typeface.get(), "", size, bold && !m_typeface->isBold(), italic && !m_typeface->isItalic(), orientation);
@@ -93,7 +98,7 @@ PassOwnPtr<FontCustomPlatformData> FontCustomPlatformData::create(SharedBuffer*
buffer = transcodeBuffer.get();
RefPtr<SkMemoryStream> stream = adoptRef(new SkMemoryStream(buffer->getAsSkData().get()));
-#if OS(WIN) && !ENABLE(GDI_FONTS_ON_WINDOWS)
+#if OS(WIN)
RefPtr<SkTypeface> typeface = adoptRef(FontCache::fontCache()->fontManager()->createFromStream(stream.get()));
#else
RefPtr<SkTypeface> typeface = adoptRef(SkTypeface::CreateFromStream(stream.get()));
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/skia/FontPlatformDataSkia.cpp b/chromium/third_party/WebKit/Source/platform/fonts/skia/FontPlatformDataSkia.cpp
index 3744cd2f233..ed0de7eab07 100644
--- a/chromium/third_party/WebKit/Source/platform/fonts/skia/FontPlatformDataSkia.cpp
+++ b/chromium/third_party/WebKit/Source/platform/fonts/skia/FontPlatformDataSkia.cpp
@@ -37,11 +37,11 @@
namespace WebCore {
-#if (!ENABLE(GDI_FONTS_ON_WINDOWS) || !OS(WIN)) && !OS(MACOSX)
+#if !OS(MACOSX)
unsigned FontPlatformData::hash() const
{
unsigned h = SkTypeface::UniqueID(m_typeface.get());
- h ^= 0x01010101 * ((static_cast<int>(m_orientation) << 2) | (static_cast<int>(m_fakeBold) << 1) | static_cast<int>(m_fakeItalic));
+ h ^= 0x01010101 * ((static_cast<int>(m_orientation) << 2) | (static_cast<int>(m_syntheticBold) << 1) | static_cast<int>(m_syntheticItalic));
// This memcpy is to avoid a reinterpret_cast that breaks strict-aliasing
// rules. Memcpy is generally optimized enough so that performance doesn't
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/skia/SimpleFontDataSkia.cpp b/chromium/third_party/WebKit/Source/platform/fonts/skia/SimpleFontDataSkia.cpp
index 7171bfb5a4a..0e20e86668f 100644
--- a/chromium/third_party/WebKit/Source/platform/fonts/skia/SimpleFontDataSkia.cpp
+++ b/chromium/third_party/WebKit/Source/platform/fonts/skia/SimpleFontDataSkia.cpp
@@ -36,15 +36,13 @@
#include "SkPath.h"
#include "SkTypeface.h"
#include "SkTypes.h"
+#include "SkUtils.h"
#include "platform/fonts/FontDescription.h"
+#include "platform/fonts/GlyphPage.h"
#include "platform/fonts/VDMXParser.h"
#include "platform/geometry/FloatRect.h"
#include "wtf/unicode/Unicode.h"
-#if OS(WIN)
-#include "platform/win/HWndDC.h"
-#endif
-
namespace WebCore {
// This is the largest VDMX table which we'll try to load and parse.
@@ -67,20 +65,31 @@ void SimpleFontData::platformInit()
SkTypeface* face = paint.getTypeface();
ASSERT(face);
- static const uint32_t vdmxTag = SkSetFourByteTag('V', 'D', 'M', 'X');
- int pixelSize = m_platformData.size() + 0.5;
- int vdmxAscent, vdmxDescent;
+ int vdmxAscent = 0, vdmxDescent = 0;
bool isVDMXValid = false;
- size_t vdmxSize = face->getTableSize(vdmxTag);
- if (vdmxSize && vdmxSize < maxVDMXTableSize) {
- uint8_t* vdmxTable = (uint8_t*) fastMalloc(vdmxSize);
- if (vdmxTable
- && face->getTableData(vdmxTag, 0, vdmxSize, vdmxTable) == vdmxSize
- && parseVDMX(&vdmxAscent, &vdmxDescent, vdmxTable, vdmxSize, pixelSize))
- isVDMXValid = true;
- fastFree(vdmxTable);
+#if OS(LINUX) || OS(ANDROID)
+ // Manually digging up VDMX metrics is only applicable when bytecode hinting using FreeType.
+ // With GDI, the metrics will already have taken this into account (as needed).
+ // With DirectWrite or CoreText, no bytecode hinting is ever done.
+ // This code should be pushed into FreeType (hinted font metrics).
+ static const uint32_t vdmxTag = SkSetFourByteTag('V', 'D', 'M', 'X');
+ int pixelSize = m_platformData.size() + 0.5;
+ if (!paint.isAutohinted()
+ && (paint.getHinting() == SkPaint::kFull_Hinting
+ || paint.getHinting() == SkPaint::kNormal_Hinting))
+ {
+ size_t vdmxSize = face->getTableSize(vdmxTag);
+ if (vdmxSize && vdmxSize < maxVDMXTableSize) {
+ uint8_t* vdmxTable = (uint8_t*) fastMalloc(vdmxSize);
+ if (vdmxTable
+ && face->getTableData(vdmxTag, 0, vdmxSize, vdmxTable) == vdmxSize
+ && parseVDMX(&vdmxAscent, &vdmxDescent, vdmxTable, vdmxSize, pixelSize))
+ isVDMXValid = true;
+ fastFree(vdmxTable);
+ }
}
+#endif
float ascent;
float descent;
@@ -91,8 +100,8 @@ void SimpleFontData::platformInit()
ascent = vdmxAscent;
descent = -vdmxDescent;
} else {
- ascent = SkScalarRound(-metrics.fAscent);
- descent = SkScalarRound(metrics.fDescent);
+ ascent = SkScalarRoundToInt(-metrics.fAscent);
+ descent = SkScalarRoundToInt(metrics.fDescent);
#if OS(LINUX) || OS(ANDROID)
// When subpixel positioning is enabled, if the descent is rounded down, the descent part
// of the glyph may be truncated when displayed in a 'overflow: hidden' container.
@@ -122,6 +131,13 @@ void SimpleFontData::platformInit()
m_fontMetrics.setLineGap(lineGap);
m_fontMetrics.setLineSpacing(lroundf(ascent) + lroundf(descent) + lroundf(lineGap));
+ SkScalar underlineThickness, underlinePosition;
+ if (metrics.hasUnderlineThickness(&underlineThickness)
+ && metrics.hasUnderlinePosition(&underlinePosition)) {
+ m_fontMetrics.setUnderlineThickness(SkScalarToFloat(underlineThickness));
+ m_fontMetrics.setUnderlinePosition(SkScalarToFloat(-underlinePosition));
+ }
+
if (platformData().orientation() == Vertical && !isTextOrientationFallback()) {
static const uint32_t vheaTag = SkSetFourByteTag('v', 'h', 'e', 'a');
static const uint32_t vorgTag = SkSetFourByteTag('V', 'O', 'R', 'G');
@@ -135,16 +151,16 @@ void SimpleFontData::platformInit()
// calculated for us, but we need to calculate m_maxCharWidth and
// m_avgCharWidth in order for text entry widgets to be sized correctly.
#if OS(WIN)
- m_maxCharWidth = SkScalarRound(metrics.fMaxCharWidth);
+ m_maxCharWidth = SkScalarRoundToInt(metrics.fMaxCharWidth);
#else
// FIXME: This seems incorrect and should probably use fMaxCharWidth as
// the code path above.
SkScalar xRange = metrics.fXMax - metrics.fXMin;
- m_maxCharWidth = SkScalarRound(xRange * SkScalarRound(m_platformData.size()));
+ m_maxCharWidth = SkScalarRoundToInt(xRange * SkScalarRoundToInt(m_platformData.size()));
#endif
if (metrics.fAvgCharWidth)
- m_avgCharWidth = SkScalarRound(metrics.fAvgCharWidth);
+ m_avgCharWidth = SkScalarRoundToInt(metrics.fAvgCharWidth);
else {
m_avgCharWidth = xHeight;
@@ -181,33 +197,7 @@ void SimpleFontData::platformDestroy()
PassRefPtr<SimpleFontData> SimpleFontData::platformCreateScaledFontData(const FontDescription& fontDescription, float scaleFactor) const
{
const float scaledSize = lroundf(fontDescription.computedSize() * scaleFactor);
- return SimpleFontData::create(FontPlatformData(m_platformData, scaledSize), isCustomFont() ? CustomFontData::create(false) : 0);
-}
-
-bool SimpleFontData::containsCharacters(const UChar* characters, int length) const
-{
- SkPaint paint;
- static const unsigned maxBufferCount = 64;
- uint16_t glyphs[maxBufferCount];
-
- m_platformData.setupPaint(&paint);
- paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
-
- while (length > 0) {
- int n = SkMin32(length, SK_ARRAY_COUNT(glyphs));
-
- // textToGlyphs takes a byte count so we double the character count.
- int count = paint.textToGlyphs(characters, n * 2, glyphs);
- for (int i = 0; i < count; i++) {
- if (!glyphs[i])
- return false; // missing glyph
- }
-
- characters += n;
- length -= n;
- }
-
- return true;
+ return SimpleFontData::create(FontPlatformData(m_platformData, scaledSize), isCustomFont() ? CustomFontData::create() : nullptr);
}
void SimpleFontData::determinePitch()
@@ -223,12 +213,6 @@ static inline void getSkiaBoundsForGlyph(SkPaint& paint, Glyph glyph, SkRect& bo
paint.getTextPath(&glyph, sizeof(glyph), 0, 0, &path);
bounds = path.getBounds();
- // FIXME(eae): getBounds currently returns an empty rect for bitmap
- // fonts so fall back on the old behavior. Once fixed in Skia this
- // fallback can go away.
- if (bounds.isEmpty())
- paint.measureText(&glyph, 2, &bounds);
-
if (!paint.isSubpixelText()) {
SkIRect ir;
bounds.round(&ir);
@@ -265,7 +249,7 @@ float SimpleFontData::platformWidthForGlyph(Glyph glyph) const
paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
SkScalar width = paint.measureText(&glyph, 2);
if (!paint.isSubpixelText())
- width = SkScalarRound(width);
+ width = SkScalarRoundToInt(width);
return SkScalarToFloat(width);
}
@@ -277,7 +261,7 @@ bool SimpleFontData::canRenderCombiningCharacterSequence(const UChar* characters
WTF::HashMap<String, bool>::AddResult addResult = m_combiningCharacterSequenceSupport->add(String(characters, length), false);
if (!addResult.isNewEntry)
- return addResult.iterator->value;
+ return addResult.storedValue->value;
UErrorCode error = U_ZERO_ERROR;
Vector<UChar, 4> normalizedCharacters(length);
@@ -290,11 +274,35 @@ bool SimpleFontData::canRenderCombiningCharacterSequence(const UChar* characters
m_platformData.setupPaint(&paint);
paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
if (paint.textToGlyphs(&normalizedCharacters[0], normalizedLength * 2, 0)) {
- addResult.iterator->value = true;
+ addResult.storedValue->value = true;
return true;
}
return false;
}
#endif
+bool SimpleFontData::fillGlyphPage(GlyphPage* pageToFill, unsigned offset, unsigned length, UChar* buffer, unsigned bufferLength) const
+{
+ if (SkUTF16_IsHighSurrogate(buffer[bufferLength-1])) {
+ SkDebugf("%s last char is high-surrogate", __FUNCTION__);
+ return false;
+ }
+
+ SkAutoSTMalloc<GlyphPage::size, uint16_t> glyphStorage(length);
+
+ uint16_t* glyphs = glyphStorage.get();
+ SkTypeface* typeface = platformData().typeface();
+ typeface->charsToGlyphs(buffer, SkTypeface::kUTF16_Encoding, glyphs, length);
+
+ bool haveGlyphs = false;
+ for (unsigned i = 0; i < length; i++) {
+ if (glyphs[i]) {
+ pageToFill->setGlyphDataForIndex(offset + i, glyphs[i], this);
+ haveGlyphs = true;
+ }
+ }
+
+ return haveGlyphs;
+}
+
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/skia/SkiaFontWin.cpp b/chromium/third_party/WebKit/Source/platform/fonts/skia/SkiaFontWin.cpp
deleted file mode 100644
index 7332e3566f8..00000000000
--- a/chromium/third_party/WebKit/Source/platform/fonts/skia/SkiaFontWin.cpp
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * Copyright (c) 2008, Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "platform/fonts/skia/SkiaFontWin.h"
-
-#include "platform/fonts/SimpleFontData.h"
-#include "platform/fonts/win/FontPlatformDataWin.h"
-#include "platform/graphics/Gradient.h"
-#include "platform/graphics/GraphicsContext.h"
-#include "platform/graphics/Pattern.h"
-#include "platform/transforms/AffineTransform.h"
-#include "third_party/skia/include/core/SkCanvas.h"
-#include "third_party/skia/include/core/SkDevice.h"
-#include "third_party/skia/include/core/SkPaint.h"
-#include "third_party/skia/include/core/SkShader.h"
-#include "third_party/skia/include/core/SkTemplates.h"
-#include "wtf/RefPtr.h"
-
-namespace WebCore {
-
-static void skiaDrawText(GraphicsContext* context,
- const SkPoint& point,
- const SkRect& textRect,
- SkPaint* paint,
- const WORD* glyphs,
- const int* advances,
- const GOFFSET* offsets,
- unsigned numGlyphs)
-{
- // Reserve space for 64 SkPoints on the stack. If numGlyphs is larger, the array
- // will dynamically allocate it space for numGlyph glyphs. This is used to store
- // the computed x,y locations. In the case where offsets==null, then we use it
- // to store (twice as many) SkScalars for x[]
- static const size_t kLocalGlyphMax = 64;
-
- SkScalar x = point.fX;
- SkScalar y = point.fY;
- if (offsets) {
- SkAutoSTArray<kLocalGlyphMax, SkPoint> storage(numGlyphs);
- SkPoint* pos = storage.get();
- for (unsigned i = 0; i < numGlyphs; i++) {
- // GDI has dv go up, so we negate it
- pos[i].set(x + SkIntToScalar(offsets[i].du),
- y + -SkIntToScalar(offsets[i].dv));
- x += SkIntToScalar(advances[i]);
- }
- context->drawPosText(glyphs, numGlyphs * sizeof(uint16_t), pos, textRect, *paint);
- } else {
- SkAutoSTArray<kLocalGlyphMax * 2, SkScalar> storage(numGlyphs);
- SkScalar* xpos = storage.get();
- for (unsigned i = 0; i < numGlyphs; i++) {
- xpos[i] = x;
- x += SkIntToScalar(advances[i]);
- }
- context->drawPosTextH(glyphs, numGlyphs * sizeof(uint16_t),
- xpos, y, textRect, *paint);
- }
-}
-
-static void paintSkiaText(GraphicsContext* context,
- const FontPlatformData& data,
- SkTypeface* face, float size, uint32_t textFlags,
- unsigned numGlyphs,
- const WORD* glyphs,
- const int* advances,
- const GOFFSET* offsets,
- const SkPoint& origin,
- const SkRect& textRect)
-{
- TextDrawingModeFlags textMode = context->textDrawingMode();
-
- // Filling (if necessary). This is the common case.
- SkPaint paint;
- context->setupPaintForFilling(&paint);
- paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
- data.setupPaint(&paint, context);
-
- // FIXME: Only needed to support the HFONT based paintSkiaText
- // version where a new typeface is created from the HFONT.
- // As such it can go away once the HFONT code path is removed.
- paint.setTypeface(face);
-
- bool didFill = false;
-
- if ((textMode & TextModeFill) && (SkColorGetA(paint.getColor()) || paint.getLooper())) {
- skiaDrawText(context, origin, textRect, &paint, &glyphs[0], &advances[0], &offsets[0], numGlyphs);
- didFill = true;
- }
-
- // Stroking on top (if necessary).
- if ((textMode & TextModeStroke)
- && context->strokeStyle() != NoStroke
- && context->strokeThickness() > 0) {
-
- paint.reset();
- context->setupPaintForStroking(&paint);
- paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
- data.setupPaint(&paint, context);
- paint.setTypeface(face);
-
- if (didFill) {
- // If there is a shadow and we filled above, there will already be
- // a shadow. We don't want to draw it again or it will be too dark
- // and it will go on top of the fill.
- //
- // Note that this isn't strictly correct, since the stroke could be
- // very thick and the shadow wouldn't account for this. The "right"
- // thing would be to draw to a new layer and then draw that layer
- // with a shadow. But this is a lot of extra work for something
- // that isn't normally an issue.
- paint.setLooper(0);
- }
-
- skiaDrawText(context, origin, textRect, &paint, &glyphs[0], &advances[0], &offsets[0], numGlyphs);
- }
-}
-
-///////////////////////////////////////////////////////////////////////////////////////////
-
-void paintSkiaText(GraphicsContext* context,
- const FontPlatformData& data,
- unsigned numGlyphs,
- const WORD* glyphs,
- const int* advances,
- const GOFFSET* offsets,
- const SkPoint& origin,
- const SkRect& textRect)
-{
- paintSkiaText(context, data, data.typeface(), data.size(), data.paintTextFlags(),
- numGlyphs, glyphs, advances, offsets, origin, textRect);
-}
-#if !USE(HARFBUZZ)
-void paintSkiaText(GraphicsContext* context,
- const FontPlatformData& data,
- HFONT hfont,
- unsigned numGlyphs,
- const WORD* glyphs,
- const int* advances,
- const GOFFSET* offsets,
- const SkPoint& origin,
- const SkRect& textRect)
-{
- int size;
- int paintTextFlags = data->paintTextFlags();
-
- // Ensure font load for printing, because PDF device needs it.
- if (context->isPrintingDevice())
- FontPlatformData::ensureFontLoaded(hfont);
-
- RefPtr<SkTypeface> face = CreateTypefaceFromHFont(hfont, &size, &paintTextFlags);
- paintSkiaText(context, data, face.get(), size, paintTextFlags, numGlyphs, glyphs, advances, offsets, origin, textRect);
-}
-#endif
-} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/skia/FontCacheSkiaWin.cpp b/chromium/third_party/WebKit/Source/platform/fonts/win/FontCacheSkiaWin.cpp
index d1b35b42ae7..dd088b96602 100644
--- a/chromium/third_party/WebKit/Source/platform/fonts/skia/FontCacheSkiaWin.cpp
+++ b/chromium/third_party/WebKit/Source/platform/fonts/win/FontCacheSkiaWin.cpp
@@ -32,34 +32,43 @@
#include "config.h"
#include "platform/fonts/FontCache.h"
-#include "RuntimeEnabledFeatures.h"
#include "SkFontMgr.h"
#include "SkTypeface_win.h"
+#include "platform/RuntimeEnabledFeatures.h"
#include "platform/fonts/FontDescription.h"
#include "platform/fonts/SimpleFontData.h"
+#include "platform/fonts/harfbuzz/FontPlatformDataHarfbuzz.h"
#include "platform/fonts/win/FontFallbackWin.h"
-#include "platform/fonts/win/FontPlatformDataWin.h"
namespace WebCore {
+HashMap<String, SkTypeface*>* FontCache::s_sideloadedFonts = 0;
+
+// static
+void FontCache::addSideloadedFontForTesting(SkTypeface* typeface)
+{
+ if (!s_sideloadedFonts)
+ s_sideloadedFonts = new HashMap<String, SkTypeface*>;
+ SkString name;
+ typeface->getFamilyName(&name);
+ s_sideloadedFonts->set(name.c_str(), typeface);
+}
+
FontCache::FontCache()
: m_purgePreventCount(0)
{
- SkFontMgr* fontManager = 0;
+ SkFontMgr* fontManager;
- // Prefer DirectWrite (if runtime feature is enabled) but fallback
- // to GDI on platforms where DirectWrite is not supported.
- if (RuntimeEnabledFeatures::directWriteEnabled())
- fontManager = SkFontMgr_New_DirectWrite();
-
- // Subpixel text positioning is not supported by the GDI backend.
- m_useSubpixelPositioning = fontManager
- ? RuntimeEnabledFeatures::subpixelFontScalingEnabled()
- : false;
-
- if (!fontManager)
+ if (s_useDirectWrite) {
+ fontManager = SkFontMgr_New_DirectWrite(s_directWriteFactory);
+ s_useSubpixelPositioning = RuntimeEnabledFeatures::subpixelFontScalingEnabled();
+ } else {
fontManager = SkFontMgr_New_GDI();
+ // Subpixel text positioning is not supported by the GDI backend.
+ s_useSubpixelPositioning = false;
+ }
+ ASSERT(fontManager);
m_fontManager = adoptPtr(fontManager);
}
@@ -76,14 +85,15 @@ static bool fontContainsCharacter(const FontPlatformData* fontData, const wchar_
// Given the desired base font, this will create a SimpleFontData for a specific
// font that can be used to render the given range of characters.
-PassRefPtr<SimpleFontData> FontCache::platformFallbackForCharacter(const FontDescription& fontDescription, UChar32 character, const SimpleFontData*, bool)
+PassRefPtr<SimpleFontData> FontCache::fallbackFontForCharacter(const FontDescription& fontDescription, UChar32 character, const SimpleFontData*)
{
// FIXME: Consider passing fontDescription.dominantScript()
// to GetFallbackFamily here.
UScriptCode script;
const wchar_t* family = getFallbackFamily(character,
fontDescription.genericFamily(),
- &script);
+ &script,
+ m_fontManager.get());
FontPlatformData* data = 0;
if (family)
data = getFontPlatformData(fontDescription, AtomicString(family, wcslen(family)));
@@ -147,6 +157,7 @@ PassRefPtr<SimpleFontData> FontCache::platformFallbackForCharacter(const FontDes
family = panUniFonts[i];
data = getFontPlatformData(fontDescription, AtomicString(family, wcslen(family)));
}
+
// When i-th font (0-base) in |panUniFonts| contains a character and
// we get out of the loop, |i| will be |i + 1|. That is, if only the
// last font in the array covers the character, |i| will be numFonts.
@@ -155,7 +166,7 @@ PassRefPtr<SimpleFontData> FontCache::platformFallbackForCharacter(const FontDes
if (i <= numFonts)
return fontDataFromFontPlatformData(data, DoNotRetain);
- return 0;
+ return nullptr;
}
static inline bool equalIgnoringCase(const AtomicString& a, const SkString& b)
@@ -210,9 +221,28 @@ FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontD
name.data(),
fontSize,
fontDescription.weight() >= FontWeightBold && !tf->isBold() || fontDescription.isSyntheticBold(),
- fontDescription.italic() && !tf->isItalic() || fontDescription.isSyntheticItalic(),
+ fontDescription.style() == FontStyleItalic && !tf->isItalic() || fontDescription.isSyntheticItalic(),
fontDescription.orientation(),
- m_useSubpixelPositioning);
+ s_useSubpixelPositioning);
+
+ struct FamilyMinSize {
+ const wchar_t* family;
+ unsigned minSize;
+ };
+ const static FamilyMinSize minAntiAliasSizeForFont[] = {
+ { L"simsun", 16 },
+ { L"dotum", 12 },
+ { L"gulim", 12 }
+ };
+ size_t numFonts = WTF_ARRAY_LENGTH(minAntiAliasSizeForFont);
+ for (size_t i = 0; i < numFonts; i++) {
+ FamilyMinSize entry = minAntiAliasSizeForFont[i];
+ if (typefacesMatchesFamily(tf.get(), entry.family)) {
+ result->setMinSizeForAntiAlias(entry.minSize);
+ break;
+ }
+ }
+
return result;
}
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/win/FontCacheWin.cpp b/chromium/third_party/WebKit/Source/platform/fonts/win/FontCacheWin.cpp
deleted file mode 100644
index c94f9ed71a8..00000000000
--- a/chromium/third_party/WebKit/Source/platform/fonts/win/FontCacheWin.cpp
+++ /dev/null
@@ -1,594 +0,0 @@
-/*
- * Copyright (C) 2006, 2007 Apple Computer, Inc.
- * Copyright (c) 2006, 2007, 2008, 2009, 2012 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-
-#include <unicode/uniset.h>
-#include "platform/fonts/FontDescription.h"
-#include "platform/LayoutTestSupport.h"
-#include "platform/fonts/FontCache.h"
-#include "platform/fonts/FontFallbackWin.h"
-#include "platform/fonts/SimpleFontData.h"
-#include "platform/fonts/win/FontPlatformDataWin.h"
-#include "platform/win/HWndDC.h"
-#include "wtf/HashMap.h"
-#include "wtf/text/StringHash.h"
-
-#include <windows.h>
-#include <mlang.h>
-#include <objidl.h>
-
-using std::min;
-
-namespace WebCore
-{
-
-// When asked for a CJK font with a native name under a non-CJK locale or
-// asked for a CJK font with a Romanized name under a CJK locale,
-// |GetTextFace| (after |CreateFont*|) returns a 'bogus' value (e.g. Arial).
-// This is not consistent with what MSDN says !!
-// Therefore, before we call |CreateFont*|, we have to map a Romanized name to
-// the corresponding native name under a CJK locale and vice versa
-// under a non-CJK locale.
-// See the corresponding gecko bugs at
-// https://bugzilla.mozilla.org/show_bug.cgi?id=373952
-// https://bugzilla.mozilla.org/show_bug.cgi?id=231426
-static bool LookupAltName(const String& name, String& altName)
-{
- struct FontCodepage {
- const WCHAR* name;
- int codePage;
- };
-
- struct NamePair {
- const WCHAR* name;
- FontCodepage altNameCodepage;
- };
-
- const int japaneseCodepage = 932;
- const int simplifiedChineseCodepage = 936;
- const int koreanCodepage = 949;
- const int traditionalChineseCodepage = 950;
-
- // FIXME(jungshik) : This list probably covers 99% of cases.
- // To cover the remaining 1% and cut down the file size,
- // consider accessing 'NAME' table of a truetype font
- // using |GetFontData| and caching the mapping.
- // In the table below, the ASCII keys are all lower-cased for
- // case-insensitive matching.
- static const NamePair namePairs[] = {
- // MS Pゴシック, MS PGothic
- {L"\xFF2D\xFF33 \xFF30\x30B4\x30B7\x30C3\x30AF", {L"MS PGothic", japaneseCodepage}},
- {L"ms pgothic", {L"\xFF2D\xFF33 \xFF30\x30B4\x30B7\x30C3\x30AF", japaneseCodepage}},
- // MS P明朝, MS PMincho
- {L"\xFF2D\xFF33 \xFF30\x660E\x671D", {L"MS PMincho", japaneseCodepage}},
- {L"ms pmincho", {L"\xFF2D\xFF33 \xFF30\x660E\x671D", japaneseCodepage}},
- // MSゴシック, MS Gothic
- {L"\xFF2D\xFF33 \x30B4\x30B7\x30C3\x30AF", {L"MS Gothic", japaneseCodepage}},
- {L"ms gothic", {L"\xFF2D\xFF33 \x30B4\x30B7\x30C3\x30AF", japaneseCodepage}},
- // MS 明朝, MS Mincho
- {L"\xFF2D\xFF33 \x660E\x671D", {L"MS Mincho", japaneseCodepage}},
- {L"ms mincho", {L"\xFF2D\xFF33 \x660E\x671D", japaneseCodepage}},
- // メイリオ, Meiryo
- {L"\x30E1\x30A4\x30EA\x30AA", {L"Meiryo", japaneseCodepage}},
- {L"meiryo", {L"\x30E1\x30A4\x30EA\x30AA", japaneseCodepage}},
- // 바탕, Batang
- {L"\xBC14\xD0D5", {L"Batang", koreanCodepage}},
- {L"batang", {L"\xBC14\xD0D5", koreanCodepage}},
- // 바탕체, Batangche
- {L"\xBC14\xD0D5\xCCB4", {L"Batangche", koreanCodepage}},
- {L"batangche", {L"\xBC14\xD0D5\xCCB4", koreanCodepage}},
- // 굴림, Gulim
- {L"\xAD74\xB9BC", {L"Gulim", koreanCodepage}},
- {L"gulim", {L"\xAD74\xB9BC", koreanCodepage}},
- // 굴림체, Gulimche
- {L"\xAD74\xB9BC\xCCB4", {L"Gulimche", koreanCodepage}},
- {L"gulimche", {L"\xAD74\xB9BC\xCCB4", koreanCodepage}},
- // 돋움, Dotum
- {L"\xB3CB\xC6C0", {L"Dotum", koreanCodepage}},
- {L"dotum", {L"\xB3CB\xC6C0", koreanCodepage}},
- // 돋움체, Dotumche
- {L"\xB3CB\xC6C0\xCCB4", {L"Dotumche", koreanCodepage}},
- {L"dotumche", {L"\xB3CB\xC6C0\xCCB4", koreanCodepage}},
- // 궁서, Gungsuh
- {L"\xAD81\xC11C", {L"Gungsuh", koreanCodepage}},
- {L"gungsuh", {L"\xAD81\xC11C", koreanCodepage}},
- // 궁서체, Gungsuhche
- {L"\xAD81\xC11C\xCCB4", {L"Gungsuhche", koreanCodepage}},
- {L"gungsuhche", {L"\xAD81\xC11C\xCCB4", koreanCodepage}},
- // 맑은 고딕, Malgun Gothic
- {L"\xB9D1\xC740 \xACE0\xB515", {L"Malgun Gothic", koreanCodepage}},
- {L"malgun gothic", {L"\xB9D1\xC740 \xACE0\xB515", koreanCodepage}},
- // 宋体, SimSun
- {L"\x5B8B\x4F53", {L"SimSun", simplifiedChineseCodepage}},
- {L"simsun", {L"\x5B8B\x4F53", simplifiedChineseCodepage}},
- // 宋体-ExtB, SimSun-ExtB
- {L"\x5B8B\x4F53-ExtB", {L"SimSun-ExtB", simplifiedChineseCodepage}},
- {L"simsun-extb", {L"\x5B8B\x4F53-extb", simplifiedChineseCodepage}},
- // 黑体, SimHei
- {L"\x9ED1\x4F53", {L"SimHei", simplifiedChineseCodepage}},
- {L"simhei", {L"\x9ED1\x4F53", simplifiedChineseCodepage}},
- // 新宋体, NSimSun
- {L"\x65B0\x5B8B\x4F53", {L"NSimSun", simplifiedChineseCodepage}},
- {L"nsimsun", {L"\x65B0\x5B8B\x4F53", simplifiedChineseCodepage}},
- // 微软雅黑, Microsoft Yahei
- {L"\x5FAE\x8F6F\x96C5\x9ED1", {L"Microsoft Yahei", simplifiedChineseCodepage}},
- {L"microsoft yahei", {L"\x5FAE\x8F6F\x96C5\x9ED1", simplifiedChineseCodepage}},
- // 仿宋, FangSong
- {L"\x4EFF\x5B8B", {L"FangSong", simplifiedChineseCodepage}},
- {L"fangsong", {L"\x4EFF\x5B8B", simplifiedChineseCodepage}},
- // 楷体, KaiTi
- {L"\x6977\x4F53", {L"KaiTi", simplifiedChineseCodepage}},
- {L"kaiti", {L"\x6977\x4F53", simplifiedChineseCodepage}},
- // 仿宋_GB2312, FangSong_GB2312
- {L"\x4EFF\x5B8B_GB2312", {L"FangSong_GB2312", simplifiedChineseCodepage}},
- {L"fangsong_gb2312", {L"\x4EFF\x5B8B_gb2312", simplifiedChineseCodepage}},
- // 楷体_GB2312, KaiTi_GB2312
- {L"\x6977\x4F53", {L"KaiTi_GB2312", simplifiedChineseCodepage}},
- {L"kaiti_gb2312", {L"\x6977\x4F53_gb2312", simplifiedChineseCodepage}},
- // 新細明體, PMingLiu
- {L"\x65B0\x7D30\x660E\x9AD4", {L"PMingLiu", traditionalChineseCodepage}},
- {L"pmingliu", {L"\x65B0\x7D30\x660E\x9AD4", traditionalChineseCodepage}},
- // 新細明體-ExtB, PMingLiu-ExtB
- {L"\x65B0\x7D30\x660E\x9AD4-ExtB", {L"PMingLiu-ExtB", traditionalChineseCodepage}},
- {L"pmingliu-extb", {L"\x65B0\x7D30\x660E\x9AD4-extb", traditionalChineseCodepage}},
- // 細明體, MingLiu
- {L"\x7D30\x660E\x9AD4", {L"MingLiu", traditionalChineseCodepage}},
- {L"mingliu", {L"\x7D30\x660E\x9AD4", traditionalChineseCodepage}},
- // 細明體-ExtB, MingLiu-ExtB
- {L"\x7D30\x660E\x9AD4-ExtB", {L"MingLiu-ExtB", traditionalChineseCodepage}},
- {L"mingliu-extb", {L"x65B0\x7D30\x660E\x9AD4-extb", traditionalChineseCodepage}},
- // 微軟正黑體, Microsoft JhengHei
- {L"\x5FAE\x8EDF\x6B63\x9ED1\x9AD4", {L"Microsoft JhengHei", traditionalChineseCodepage}},
- {L"microsoft jhengHei", {L"\x5FAE\x8EDF\x6B63\x9ED1\x9AD4", traditionalChineseCodepage}},
- // 標楷體, DFKai-SB
- {L"\x6A19\x6977\x9AD4", {L"DFKai-SB", traditionalChineseCodepage}},
- {L"dfkai-sb", {L"\x6A19\x6977\x9AD4", traditionalChineseCodepage}},
- // WenQuanYi Zen Hei
- {L"\x6587\x6cc9\x9a5b\x6b63\x9ed1", {L"WenQuanYi Zen Hei", traditionalChineseCodepage}},
- {L"wenquanyi zen hei", {L"\x6587\x6cc9\x9a5b\x6b63\x9ed1", traditionalChineseCodepage}},
- // WenQuanYi Zen Hei
- {L"\x6587\x6cc9\x9a7f\x6b63\x9ed1", {L"WenQuanYi Zen Hei", simplifiedChineseCodepage}},
- {L"wenquanyi zen hei", {L"\x6587\x6cc9\x9a7f\x6b63\x9ed1", simplifiedChineseCodepage}},
- // AR PL ShanHeiSun Uni,
- {L"\x6587\x9f0e\x0050\x004c\x7d30\x4e0a\x6d77\x5b8b\x0055\x006e\x0069",
- {L"AR PL ShanHeiSun Uni", traditionalChineseCodepage}},
- {L"ar pl shanheisun uni",
- {L"\x6587\x9f0e\x0050\x004c\x7d30\x4e0a\x6d77\x5b8b\x0055\x006e\x0069", traditionalChineseCodepage}},
- // AR PL ShanHeiSun Uni,
- {L"\x6587\x9f0e\x0050\x004c\x7ec6\x4e0a\x6d77\x5b8b\x0055\x006e\x0069",
- {L"AR PL ShanHeiSun Uni", simplifiedChineseCodepage}},
- {L"ar pl shanheisun uni",
- {L"\x6587\x9f0e\x0050\x004c\x7ec6\x4e0a\x6d77\x5b8b\x0055\x006e\x0069", simplifiedChineseCodepage}},
- // AR PL ZenKai Uni
- // Traditional Chinese and Simplified Chinese names are
- // identical.
- {L"\x6587\x0050\x004C\x4E2D\x6977\x0055\x006E\x0069", {L"AR PL ZenKai Uni", traditionalChineseCodepage}},
- {L"ar pl zenkai uni", {L"\x6587\x0050\x004C\x4E2D\x6977\x0055\x006E\x0069", traditionalChineseCodepage}},
- {L"\x6587\x0050\x004C\x4E2D\x6977\x0055\x006E\x0069", {L"AR PL ZenKai Uni", simplifiedChineseCodepage}},
- {L"ar pl zenkai uni", {L"\x6587\x0050\x004C\x4E2D\x6977\x0055\x006E\x0069", simplifiedChineseCodepage}},
- };
-
- typedef HashMap<String, const FontCodepage*> NameMap;
- static NameMap* fontNameMap = 0;
-
- if (!fontNameMap) {
- fontNameMap = new NameMap;
- for (size_t i = 0; i < WTF_ARRAY_LENGTH(namePairs); ++i)
- fontNameMap->set(String(namePairs[i].name), &(namePairs[i].altNameCodepage));
- }
-
- bool isAscii = false;
- String n;
- // use |lower| only for ASCII names
- // For non-ASCII names, we don't want to invoke an expensive
- // and unnecessary |lower|.
- if (name.containsOnlyASCII()) {
- isAscii = true;
- n = name.lower();
- } else
- n = name;
-
- NameMap::iterator iter = fontNameMap->find(n);
- if (iter == fontNameMap->end())
- return false;
-
- static int systemCp = ::GetACP();
- int fontCp = iter->value->codePage;
-
- if ((isAscii && systemCp == fontCp) || (!isAscii && systemCp != fontCp)) {
- altName = String(iter->value->name);
- return true;
- }
-
- return false;
-}
-
-static HFONT createFontIndirectAndGetWinName(const String& family, LOGFONT* winfont, String* winName)
-{
- unsigned len = family.copyTo(winfont->lfFaceName, 0, LF_FACESIZE - 1);
- winfont->lfFaceName[len] = '\0';
-
- HFONT hfont = CreateFontIndirect(winfont);
- if (!hfont)
- return 0;
-
- HWndDC dc(0);
- HGDIOBJ oldFont = static_cast<HFONT>(SelectObject(dc, hfont));
- WCHAR name[LF_FACESIZE];
- unsigned resultLength = GetTextFace(dc, LF_FACESIZE, name);
- if (resultLength > 0)
- resultLength--; // ignore the null terminator
-
- SelectObject(dc, oldFont);
- *winName = String(name, resultLength);
- return hfont;
-}
-
-// This maps font family names to their repertoires of supported Unicode
-// characters. Because it's family names rather than font faces we use
-// as keys, there might be edge cases where one face of a font family
-// has a different repertoire from another face of the same family.
-typedef HashMap<const wchar_t*, icu::UnicodeSet*> FontCmapCache;
-
-static bool fontContainsCharacter(const FontPlatformData* fontData,
- const wchar_t* family, UChar32 character)
-{
- // FIXME: For non-BMP characters, GetFontUnicodeRanges is of
- // no use. We have to read directly from the cmap table of a font.
- // Return true for now.
- if (character > 0xFFFF)
- return true;
-
- // This cache is just leaked on shutdown.
- static FontCmapCache* fontCmapCache = 0;
- if (!fontCmapCache)
- fontCmapCache = new FontCmapCache;
-
- HashMap<const wchar_t*, icu::UnicodeSet*>::iterator it = fontCmapCache->find(family);
- if (it != fontCmapCache->end())
- return it->value->contains(character);
-
- HFONT hfont = fontData->hfont();
- HWndDC hdc(0);
- HGDIOBJ oldFont = static_cast<HFONT>(SelectObject(hdc, hfont));
- int count = GetFontUnicodeRanges(hdc, 0);
- if (!count && FontPlatformData::ensureFontLoaded(hfont))
- count = GetFontUnicodeRanges(hdc, 0);
- if (!count) {
- WTF_LOG_ERROR("Unable to get the font unicode range after second attempt");
- SelectObject(hdc, oldFont);
- return true;
- }
-
- static Vector<char, 512>* gGlyphsetBuffer = 0;
- if (!gGlyphsetBuffer)
- gGlyphsetBuffer = new Vector<char, 512>();
- gGlyphsetBuffer->resize(GetFontUnicodeRanges(hdc, 0));
- GLYPHSET* glyphset = reinterpret_cast<GLYPHSET*>(gGlyphsetBuffer->data());
- // In addition, refering to the OS/2 table and converting the codepage list
- // to the coverage map might be faster.
- count = GetFontUnicodeRanges(hdc, glyphset);
- ASSERT(count > 0);
- SelectObject(hdc, oldFont);
-
- // FIXME: consider doing either of the following two:
- // 1) port back ICU 4.0's faster look-up code for UnicodeSet
- // 2) port Mozilla's CompressedCharMap or gfxSparseBitset
- unsigned i = 0;
- icu::UnicodeSet* cmap = new icu::UnicodeSet;
- while (i < glyphset->cRanges) {
- WCHAR start = glyphset->ranges[i].wcLow;
- cmap->add(start, start + glyphset->ranges[i].cGlyphs - 1);
- i++;
- }
- cmap->freeze();
- // We don't lowercase |family| because all of them are under our control
- // and they're already lowercased.
- fontCmapCache->set(family, cmap);
- return cmap->contains(character);
-}
-
-// Tries the given font and save it |outFontFamilyName| if it succeeds.
-PassRefPtr<SimpleFontData> FontCache::fontDataFromDescriptionAndLogFont(const FontDescription& fontDescription, ShouldRetain shouldRetain, const LOGFONT& font, wchar_t* outFontFamilyName)
-{
- RefPtr<SimpleFontData> fontData = getFontData(fontDescription, font.lfFaceName, false, shouldRetain);
- if (fontData)
- memcpy(outFontFamilyName, font.lfFaceName, sizeof(font.lfFaceName));
- return fontData.release();
-}
-
-static LONG toGDIFontWeight(FontWeight fontWeight)
-{
- static LONG gdiFontWeights[] = {
- FW_THIN, // FontWeight100
- FW_EXTRALIGHT, // FontWeight200
- FW_LIGHT, // FontWeight300
- FW_NORMAL, // FontWeight400
- FW_MEDIUM, // FontWeight500
- FW_SEMIBOLD, // FontWeight600
- FW_BOLD, // FontWeight700
- FW_EXTRABOLD, // FontWeight800
- FW_HEAVY // FontWeight900
- };
- return gdiFontWeights[fontWeight];
-}
-
-static void FillLogFont(const FontDescription& fontDescription, LOGFONT* winfont)
-{
- // The size here looks unusual. The negative number is intentional.
- // Unlike WebKit trunk, we don't multiply the size by 32. That seems to be
- // some kind of artifact of their CG backend, or something.
- winfont->lfHeight = -fontDescription.computedPixelSize();
- winfont->lfWidth = 0;
- winfont->lfEscapement = 0;
- winfont->lfOrientation = 0;
- winfont->lfUnderline = false;
- winfont->lfStrikeOut = false;
- winfont->lfCharSet = DEFAULT_CHARSET;
- winfont->lfOutPrecision = OUT_TT_ONLY_PRECIS;
- winfont->lfQuality = isRunningLayoutTest() ? NONANTIALIASED_QUALITY : DEFAULT_QUALITY; // Honor user's desktop settings.
- winfont->lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
- winfont->lfItalic = fontDescription.italic();
- winfont->lfWeight = toGDIFontWeight(fontDescription.weight());
-}
-
-struct GetLastResortFallbackFontProcData {
- GetLastResortFallbackFontProcData(FontCache* fontCache, const FontDescription* fontDescription, FontCache::ShouldRetain shouldRetain, wchar_t* fontName)
- : m_fontCache(fontCache)
- , m_fontDescription(fontDescription)
- , m_shouldRetain(shouldRetain)
- , m_fontName(fontName)
- , m_fontData(0)
- {
- }
-
- FontCache* m_fontCache;
- const FontDescription* m_fontDescription;
- FontCache::ShouldRetain m_shouldRetain;
- wchar_t* m_fontName;
- RefPtr<SimpleFontData> m_fontData;
-};
-
-static int CALLBACK getLastResortFallbackFontProc(const LOGFONT* logFont, const TEXTMETRIC* metrics, DWORD fontType, LPARAM lParam)
-{
- GetLastResortFallbackFontProcData* procData = reinterpret_cast<GetLastResortFallbackFontProcData*>(lParam);
- procData->m_fontData = procData->m_fontCache->fontDataFromDescriptionAndLogFont(*procData->m_fontDescription, procData->m_shouldRetain, *logFont, procData->m_fontName);
- return !procData->m_fontData;
-}
-
-void FontCache::platformInit()
-{
- // Not needed on Windows.
-}
-
-// Given the desired base font, this will create a SimpleFontData for a specific
-// font that can be used to render the given range of characters.
-PassRefPtr<SimpleFontData> FontCache::platformFallbackForCharacter(const FontDescription& fontDescription, UChar32 c, const SimpleFontData*, bool)
-{
- // FIXME: We should fix getFallbackFamily to take a UChar32
- // and remove this split-to-UChar16 code.
- UChar codeUnits[2];
- int codeUnitsLength;
- if (inputC <= 0xFFFF) {
- codeUnits[0] = inputC;
- codeUnitsLength = 1;
- } else {
- codeUnits[0] = U16_LEAD(inputC);
- codeUnits[1] = U16_TRAIL(inputC);
- codeUnitsLength = 2;
- }
-
- // FIXME: Consider passing fontDescription.dominantScript()
- // to GetFallbackFamily here.
- FontDescription fontDescription = fontDescription;
- UChar32 c;
- UScriptCode script;
- const wchar_t* family = getFallbackFamily(codeUnits, codeUnitsLength, fontDescription.genericFamily(), &c, &script);
- FontPlatformData* data = 0;
- if (family)
- data = getFontPlatformData(fontDescription, AtomicString(family, wcslen(family)));
-
- // Last resort font list : PanUnicode. CJK fonts have a pretty
- // large repertoire. Eventually, we need to scan all the fonts
- // on the system to have a Firefox-like coverage.
- // Make sure that all of them are lowercased.
- const static wchar_t* const cjkFonts[] = {
- L"arial unicode ms",
- L"ms pgothic",
- L"simsun",
- L"gulim",
- L"pmingliu",
- L"wenquanyi zen hei", // partial CJK Ext. A coverage but more
- // widely known to Chinese users.
- L"ar pl shanheisun uni",
- L"ar pl zenkai uni",
- L"han nom a", // Complete CJK Ext. A coverage
- L"code2000", // Complete CJK Ext. A coverage
- // CJK Ext. B fonts are not listed here because it's of no use
- // with our current non-BMP character handling because we use
- // Uniscribe for it and that code path does not go through here.
- };
-
- const static wchar_t* const commonFonts[] = {
- L"tahoma",
- L"arial unicode ms",
- L"lucida sans unicode",
- L"microsoft sans serif",
- L"palatino linotype",
- // Six fonts below (and code2000 at the end) are not from MS, but
- // once installed, cover a very wide range of characters.
- L"dejavu serif",
- L"dejavu sasns",
- L"freeserif",
- L"freesans",
- L"gentium",
- L"gentiumalt",
- L"ms pgothic",
- L"simsun",
- L"gulim",
- L"pmingliu",
- L"code2000",
- };
-
- const wchar_t* const* panUniFonts = 0;
- int numFonts = 0;
- if (script == USCRIPT_HAN) {
- panUniFonts = cjkFonts;
- numFonts = WTF_ARRAY_LENGTH(cjkFonts);
- } else {
- panUniFonts = commonFonts;
- numFonts = WTF_ARRAY_LENGTH(commonFonts);
- }
- // Font returned from GetFallbackFamily may not cover |characters|
- // because it's based on script to font mapping. This problem is
- // critical enough for non-Latin scripts (especially Han) to
- // warrant an additional (real coverage) check with fontCotainsCharacter.
- int i;
- for (i = 0; (!data || !fontContainsCharacter(data, family, c)) && i < numFonts; ++i) {
- family = panUniFonts[i];
- data = getFontPlatformData(fontDescription, AtomicString(family, wcslen(family)));
- }
- // When i-th font (0-base) in |panUniFonts| contains a character and
- // we get out of the loop, |i| will be |i + 1|. That is, if only the
- // last font in the array covers the character, |i| will be numFonts.
- // So, we have to use '<=" rather than '<' to see if we found a font
- // covering the character.
- if (i <= numFonts)
- return fontDataFromPlatformData(data, DoNotRetain);
-
- return 0;
-
-}
-
-PassRefPtr<SimpleFontData> FontCache::getLastResortFallbackFont(const FontDescription& description, ShouldRetain shouldRetain)
-{
- FontDescription::GenericFamilyType generic = description.genericFamily();
-
- // FIXME: Would be even better to somehow get the user's default font here.
- // For now we'll pick the default that the user would get without changing
- // any prefs.
- DEFINE_STATIC_LOCAL(AtomicString, timesStr, "Times New Roman");
- DEFINE_STATIC_LOCAL(AtomicString, courierStr, "Courier New");
- DEFINE_STATIC_LOCAL(AtomicString, arialStr, "Arial");
-
- AtomicString& fontStr = timesStr;
- if (generic == FontDescription::SansSerifFamily)
- fontStr = arialStr;
- else if (generic == FontDescription::MonospaceFamily)
- fontStr = courierStr;
-
- RefPtr<SimpleFontData> simpleFont = getFontData(description, fontStr, false, shouldRetain);
- if (simpleFont)
- return simpleFont.release();
-
- // Fall back to system fonts as Win Safari does because this function must
- // return a valid font. Once we find a valid system font, we save its name
- // to a static variable and use it to prevent trying system fonts again.
- static wchar_t fallbackFontName[LF_FACESIZE] = {0};
- if (fallbackFontName[0])
- return getFontData(description, fallbackFontName, false, shouldRetain);
-
- // Fall back to the DEFAULT_GUI_FONT if no known Unicode fonts are available.
- if (HFONT defaultGUIFont = static_cast<HFONT>(GetStockObject(DEFAULT_GUI_FONT))) {
- LOGFONT defaultGUILogFont;
- GetObject(defaultGUIFont, sizeof(defaultGUILogFont), &defaultGUILogFont);
- if (simpleFont = fontDataFromDescriptionAndLogFont(description, shouldRetain, defaultGUILogFont, fallbackFontName))
- return simpleFont.release();
- }
-
- // Fall back to Non-client metrics fonts.
- NONCLIENTMETRICS nonClientMetrics = {0};
- nonClientMetrics.cbSize = sizeof(nonClientMetrics);
- if (SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(nonClientMetrics), &nonClientMetrics, 0)) {
- if (simpleFont = fontDataFromDescriptionAndLogFont(description, shouldRetain, nonClientMetrics.lfMessageFont, fallbackFontName))
- return simpleFont.release();
- if (simpleFont = fontDataFromDescriptionAndLogFont(description, shouldRetain, nonClientMetrics.lfMenuFont, fallbackFontName))
- return simpleFont.release();
- if (simpleFont = fontDataFromDescriptionAndLogFont(description, shouldRetain, nonClientMetrics.lfStatusFont, fallbackFontName))
- return simpleFont.release();
- if (simpleFont = fontDataFromDescriptionAndLogFont(description, shouldRetain, nonClientMetrics.lfCaptionFont, fallbackFontName))
- return simpleFont.release();
- if (simpleFont = fontDataFromDescriptionAndLogFont(description, shouldRetain, nonClientMetrics.lfSmCaptionFont, fallbackFontName))
- return simpleFont.release();
- }
-
- // Fall back to all the fonts installed in this PC. When a font has a
- // localized name according to the system locale as well as an English name,
- // both GetTextFace() and EnumFontFamilies() return the localized name. So,
- // FontCache::createFontPlatformData() does not filter out the fonts
- // returned by this EnumFontFamilies() call.
- HWndDC dc(0);
- if (dc) {
- GetLastResortFallbackFontProcData procData(this, &description, shouldRetain, fallbackFontName);
- EnumFontFamilies(dc, 0, getLastResortFallbackFontProc, reinterpret_cast<LPARAM>(&procData));
-
- if (procData.m_fontData)
- return procData.m_fontData.release();
- }
-
- ASSERT_NOT_REACHED();
- return 0;
-}
-
-FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontDescription, const AtomicString& family, float fontSize)
-{
- LOGFONT winfont = {0};
- FillLogFont(fontDescription, &winfont);
-
- // Windows will always give us a valid pointer here, even if the face name
- // is non-existent. We have to double-check and see if the family name was
- // really used.
- String winName;
- HFONT hfont = createFontIndirectAndGetWinName(family, &winfont, &winName);
- if (!hfont)
- return 0;
-
- // FIXME: Do we need to use predefined fonts "guaranteed" to exist
- // when we're running in layout-test mode?
- if (!equalIgnoringCase(family, winName)) {
- // For CJK fonts with both English and native names,
- // GetTextFace returns a native name under the font's "locale"
- // and an English name under other locales regardless of
- // lfFaceName field of LOGFONT. As a result, we need to check
- // if a font has an alternate name. If there is, we need to
- // compare it with what's requested in the first place.
- String altName;
- if (!LookupAltName(family, altName) || !equalIgnoringCase(altName, winName)) {
- DeleteObject(hfont);
- return 0;
- }
- }
-
- return new FontPlatformData(hfont, fontSize, fontDescription.orientation());
-}
-
-}
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/win/FontCustomPlatformDataWin.cpp b/chromium/third_party/WebKit/Source/platform/fonts/win/FontCustomPlatformDataWin.cpp
deleted file mode 100644
index 43ae74c825e..00000000000
--- a/chromium/third_party/WebKit/Source/platform/fonts/win/FontCustomPlatformDataWin.cpp
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright (C) 2013 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "platform/fonts/FontCustomPlatformData.h"
-
-#include "platform/LayoutTestSupport.h"
-#include "platform/SharedBuffer.h"
-#include "platform/fonts/FontPlatformData.h"
-#include "platform/fonts/opentype/OpenTypeSanitizer.h"
-#include "platform/fonts/opentype/OpenTypeUtilities.h"
-#include "wtf/PassOwnPtr.h"
-#include "wtf/RefPtr.h"
-#include "wtf/text/Base64.h"
-
-#include <objbase.h>
-
-namespace {
-
-// Creates a unique and unpredictable font name, in order to avoid collisions and to
-// not allow access from CSS.
-String createUniqueFontName()
-{
- GUID fontUuid;
- CoCreateGuid(&fontUuid);
-
- String fontName = base64Encode(reinterpret_cast<char*>(&fontUuid), sizeof(fontUuid));
- ASSERT(fontName.length() < LF_FACESIZE);
- return fontName;
-}
-
-} // namespace
-
-namespace WebCore {
-
-FontCustomPlatformData::FontCustomPlatformData(HANDLE fontReference, const String& name)
- : m_fontReference(fontReference)
- , m_name(name)
-{
-}
-
-FontCustomPlatformData::~FontCustomPlatformData()
-{
- if (m_fontReference)
- RemoveFontMemResourceEx(m_fontReference);
-}
-
-FontPlatformData FontCustomPlatformData::fontPlatformData(float size, bool bold, bool italic, FontOrientation orientation, FontWidthVariant)
-{
- ASSERT(m_fontReference);
-
- LOGFONT logFont;
- // m_name comes from createUniqueFontName, which, in turn, gets
- // it from base64-encoded uuid (128-bit). So, m_name
- // can never be longer than LF_FACESIZE (32).
- if (m_name.length() + 1 >= LF_FACESIZE) {
- ASSERT_NOT_REACHED();
- return FontPlatformData();
- }
- unsigned len = m_name.copyTo(logFont.lfFaceName, 0, LF_FACESIZE - 1);
- logFont.lfFaceName[len] = '\0';
-
- // FIXME: almost identical to FillLogFont in FontCacheWin.cpp.
- // Need to refactor.
- logFont.lfHeight = -static_cast<int>(size);
- logFont.lfWidth = 0;
- logFont.lfEscapement = 0;
- logFont.lfOrientation = 0;
- logFont.lfUnderline = false;
- logFont.lfStrikeOut = false;
- logFont.lfCharSet = DEFAULT_CHARSET;
- logFont.lfOutPrecision = OUT_TT_ONLY_PRECIS;
- logFont.lfQuality = isRunningLayoutTest() ? NONANTIALIASED_QUALITY : DEFAULT_QUALITY; // Honor user's desktop settings.
- logFont.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
- logFont.lfItalic = italic;
- logFont.lfWeight = bold ? FW_BOLD : FW_DONTCARE;
-
- HFONT hfont = CreateFontIndirect(&logFont);
- return FontPlatformData(hfont, size, orientation);
-}
-
-PassOwnPtr<FontCustomPlatformData> FontCustomPlatformData::create(SharedBuffer* buffer)
-{
- ASSERT_ARG(buffer, buffer);
-
- OpenTypeSanitizer sanitizer(buffer);
- RefPtr<SharedBuffer> transcodeBuffer = sanitizer.sanitize();
- if (!transcodeBuffer)
- return nullptr; // validation failed.
- buffer = transcodeBuffer.get();
-
- // Introduce the font to GDI. AddFontMemResourceEx should be used with care, because it will pollute the process's
- // font namespace (Windows has no API for creating an HFONT from data without exposing the font to the
- // entire process first).
- String fontName = createUniqueFontName();
- HANDLE fontReference = renameAndActivateFont(buffer, fontName);
- if (!fontReference)
- return nullptr;
-
- return adoptPtr(new FontCustomPlatformData(fontReference, fontName));
-}
-
-bool FontCustomPlatformData::supportsFormat(const String& format)
-{
- return equalIgnoringCase(format, "truetype") || equalIgnoringCase(format, "opentype") || OpenTypeSanitizer::supportsFormat(format);
-}
-
-} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/win/FontFallbackWin.cpp b/chromium/third_party/WebKit/Source/platform/fonts/win/FontFallbackWin.cpp
index 6f4d91d6eb5..d8afcdc5155 100644
--- a/chromium/third_party/WebKit/Source/platform/fonts/win/FontFallbackWin.cpp
+++ b/chromium/third_party/WebKit/Source/platform/fonts/win/FontFallbackWin.cpp
@@ -31,7 +31,8 @@
#include "config.h"
#include "platform/fonts/win/FontFallbackWin.h"
-#include "platform/win/HWndDC.h"
+#include "SkFontMgr.h"
+#include "SkTypeface.h"
#include "wtf/HashMap.h"
#include "wtf/text/StringHash.h"
#include "wtf/text/WTFString.h"
@@ -43,29 +44,48 @@ namespace WebCore {
namespace {
-bool isFontPresent(const UChar* fontName)
+static inline bool isFontPresent(const UChar* fontName, SkFontMgr* fontManager)
{
- HFONT hfont = CreateFont(12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, fontName);
- if (!hfont)
+ String family = fontName;
+ RefPtr<SkTypeface> tf = adoptRef(fontManager->legacyCreateTypeface(family.utf8().data(), SkTypeface::kNormal));
+ if (!tf)
return false;
- HWndDC dc(0);
- HGDIOBJ oldFont = static_cast<HFONT>(SelectObject(dc, hfont));
- WCHAR actualFontName[LF_FACESIZE];
- GetTextFace(dc, LF_FACESIZE, actualFontName);
- actualFontName[LF_FACESIZE - 1] = 0;
- SelectObject(dc, oldFont);
- DeleteObject(hfont);
- // We don't have to worry about East Asian fonts with locale-dependent
- // names here for now.
- // FIXME: Why not?
- return !wcscmp(fontName, actualFontName);
+
+ SkTypeface::LocalizedStrings* actualFamilies = tf->createFamilyNameIterator();
+ bool matchesRequestedFamily = false;
+ SkTypeface::LocalizedString actualFamily;
+ while (actualFamilies->next(&actualFamily)) {
+ if (equalIgnoringCase(family, AtomicString::fromUTF8(actualFamily.fString.c_str()))) {
+ matchesRequestedFamily = true;
+ break;
+ }
+ }
+ actualFamilies->unref();
+
+ return matchesRequestedFamily;
}
// A simple mapping from UScriptCode to family name. This is a sparse array,
// which works well since the range of UScriptCode values is small.
typedef const UChar* ScriptToFontMap[USCRIPT_CODE_LIMIT];
-void initializeScriptFontMap(ScriptToFontMap& scriptFontMap)
+void initializeScriptMonospaceFontMap(ScriptToFontMap& scriptFontMap, SkFontMgr* fontManager)
+{
+ struct FontMap {
+ UScriptCode script;
+ const UChar* family;
+ };
+
+ static const FontMap fontMap[] = {
+ { USCRIPT_HEBREW, L"courier new" },
+ { USCRIPT_ARABIC, L"courier new" },
+ };
+
+ for (size_t i = 0; i < WTF_ARRAY_LENGTH(fontMap); ++i)
+ scriptFontMap[fontMap[i].script] = fontMap[i].family;
+}
+
+void initializeScriptFontMap(ScriptToFontMap& scriptFontMap, SkFontMgr* fontManager)
{
struct FontMap {
UScriptCode script;
@@ -160,7 +180,7 @@ void initializeScriptFontMap(ScriptToFontMap& scriptFontMap)
scriptFontMap[script] = 0;
const UChar** familyPtr = scriptToFontFamilies[i].families;
while (*familyPtr) {
- if (isFontPresent(*familyPtr)) {
+ if (isFontPresent(*familyPtr, fontManager)) {
scriptFontMap[script] = *familyPtr;
break;
}
@@ -251,17 +271,22 @@ UScriptCode getScript(int ucs4)
// - Update script_font_cache in response to WM_FONTCHANGE
const UChar* getFontFamilyForScript(UScriptCode script,
- FontDescription::GenericFamilyType generic)
+ FontDescription::GenericFamilyType generic,
+ SkFontMgr* fontManager)
{
static ScriptToFontMap scriptFontMap;
+ static ScriptToFontMap scriptMonospaceFontMap;
static bool initialized = false;
if (!initialized) {
- initializeScriptFontMap(scriptFontMap);
+ initializeScriptFontMap(scriptFontMap, fontManager);
+ initializeScriptMonospaceFontMap(scriptMonospaceFontMap, fontManager);
initialized = true;
}
if (script == USCRIPT_INVALID_CODE)
return 0;
ASSERT(script < USCRIPT_CODE_LIMIT);
+ if (generic == FontDescription::MonospaceFamily && scriptMonospaceFontMap[script])
+ return scriptMonospaceFontMap[script];
return scriptFontMap[script];
}
@@ -275,7 +300,8 @@ const UChar* getFontFamilyForScript(UScriptCode script,
// font can cover) need to be taken into account
const UChar* getFallbackFamily(UChar32 character,
FontDescription::GenericFamilyType generic,
- UScriptCode* scriptChecked)
+ UScriptCode* scriptChecked,
+ SkFontMgr* fontManager)
{
ASSERT(character);
UScriptCode script = getScript(character);
@@ -290,7 +316,7 @@ const UChar* getFallbackFamily(UChar32 character,
if (script == USCRIPT_COMMON)
script = getScriptBasedOnUnicodeBlock(character);
- const UChar* family = getFontFamilyForScript(script, generic);
+ const UChar* family = getFontFamilyForScript(script, generic, fontManager);
// Another lame work-around to cover non-BMP characters.
// If the font family for script is not found or the character is
// not in BMP (> U+FFFF), we resort to the hard-coded list of
@@ -322,27 +348,4 @@ const UChar* getFallbackFamily(UChar32 character,
return family;
}
-
-const UChar* getFallbackFamilyForFirstNonCommonCharacter(const UChar* characters,
- int length,
- FontDescription::GenericFamilyType generic)
-{
- ASSERT(characters && characters[0] && length > 0);
- UScriptCode script = USCRIPT_COMMON;
-
- // Sometimes characters common to script (e.g. space) is at
- // the beginning of a string so that we need to skip them
- // to get a font required to render the string.
- int i = 0;
- UChar32 ucs4 = 0;
- while (i < length && script == USCRIPT_COMMON) {
- U16_NEXT(characters, i, length, ucs4);
- script = getScript(ucs4);
- }
-
- const UChar* family = getFallbackFamily(ucs4, generic, 0);
-
- return family;
-}
-
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/win/FontFallbackWin.h b/chromium/third_party/WebKit/Source/platform/fonts/win/FontFallbackWin.h
index 232b2e2ee90..75e62187858 100644
--- a/chromium/third_party/WebKit/Source/platform/fonts/win/FontFallbackWin.h
+++ b/chromium/third_party/WebKit/Source/platform/fonts/win/FontFallbackWin.h
@@ -28,11 +28,6 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-// A collection of utilities for font handling.
-
-// FIXME: Move all methods to the files that have their callsites and remove this file.
-// *Utils files are not very WebKit-ty.
-
#ifndef FontFallbackWin_h
#define FontFallbackWin_h
@@ -43,14 +38,9 @@
#include <wchar.h>
#include <windows.h>
-namespace WebCore {
+class SkFontMgr;
-// Return a font family that can render |characters| based on
-// what script characters belong to.
-// FIXME: This function needs a total overhaul.
-PLATFORM_EXPORT const UChar* getFallbackFamilyForFirstNonCommonCharacter(const UChar* characters,
- int length,
- FontDescription::GenericFamilyType);
+namespace WebCore {
// Return a font family that can render |character| based on what script
// that characters belong to.
@@ -58,7 +48,8 @@ PLATFORM_EXPORT const UChar* getFallbackFamilyForFirstNonCommonCharacter(const U
// the family is returned.
PLATFORM_EXPORT const UChar* getFallbackFamily(UChar32 character,
FontDescription::GenericFamilyType,
- UScriptCode* scriptChecked);
+ UScriptCode* scriptChecked,
+ SkFontMgr* fontManager);
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/win/FontPlatformDataWin.cpp b/chromium/third_party/WebKit/Source/platform/fonts/win/FontPlatformDataWin.cpp
index e9eb7c1ab3a..a93e44c87bd 100644
--- a/chromium/third_party/WebKit/Source/platform/fonts/win/FontPlatformDataWin.cpp
+++ b/chromium/third_party/WebKit/Source/platform/fonts/win/FontPlatformDataWin.cpp
@@ -32,417 +32,123 @@
#include "config.h"
#include "platform/fonts/FontPlatformData.h"
+#include "SkTypeface.h"
#include "platform/LayoutTestSupport.h"
#include "platform/fonts/FontCache.h"
-#if USE(HARFBUZZ)
-#include "platform/fonts/harfbuzz/HarfBuzzFace.h"
-#endif
-#include "platform/fonts/skia/SkiaFontWin.h"
#include "platform/graphics/GraphicsContext.h"
-#include "platform/win/HWndDC.h"
-#include "public/platform/Platform.h"
-#include "public/platform/win/WebSandboxSupport.h"
-#include "wtf/PassOwnPtr.h"
-#include "wtf/StdLibExtras.h"
-#include <mlang.h>
-#include <objidl.h>
#include <windows.h>
namespace WebCore {
+// Maximum font size, in pixels, at which embedded bitmaps will be used
+// if available.
+const float kMaxSizeForEmbeddedBitmap = 24.0f;
+
void FontPlatformData::setupPaint(SkPaint* paint, GraphicsContext* context) const
{
const float ts = m_textSize >= 0 ? m_textSize : 12;
paint->setTextSize(SkFloatToScalar(m_textSize));
paint->setTypeface(typeface());
- paint->setFakeBoldText(m_fakeBold);
- paint->setTextSkewX(m_fakeItalic ? -SK_Scalar1 / 4 : 0);
- paint->setSubpixelText(m_useSubpixelPositioning);
-
- int textFlags = paintTextFlags();
- // Only set painting flags when we're actually painting.
- if (context && !context->couldUseLCDRenderedText()) {
- textFlags &= ~SkPaint::kLCDRenderText_Flag;
- // If we *just* clear our request for LCD, then GDI seems to
- // sometimes give us AA text, and sometimes give us BW text. Since the
- // original intent was LCD, we want to force AA (rather than BW), so we
- // add a special bit to tell Skia to do its best to avoid the BW: by
- // drawing LCD offscreen and downsampling that to AA.
- textFlags |= SkPaint::kGenA8FromLCD_Flag;
- }
+ paint->setFakeBoldText(m_syntheticBold);
+ paint->setTextSkewX(m_syntheticItalic ? -SK_Scalar1 / 4 : 0);
+ uint32_t textFlags = paintTextFlags();
+ uint32_t flags = paint->getFlags();
static const uint32_t textFlagsMask = SkPaint::kAntiAlias_Flag |
SkPaint::kLCDRenderText_Flag |
SkPaint::kGenA8FromLCD_Flag;
-
- SkASSERT(!(textFlags & ~textFlagsMask));
- uint32_t flags = paint->getFlags();
flags &= ~textFlagsMask;
- flags |= textFlags;
+
+ if (ts <= kMaxSizeForEmbeddedBitmap)
+ flags |= SkPaint::kEmbeddedBitmapText_Flag;
+
+ if (ts >= m_minSizeForAntiAlias) {
+ if (m_useSubpixelPositioning)
+ flags |= SkPaint::kSubpixelText_Flag;
+
+ // Only set painting flags when we're actually painting.
+ if (context && !context->couldUseLCDRenderedText()) {
+ textFlags &= ~SkPaint::kLCDRenderText_Flag;
+ // If we *just* clear our request for LCD, then GDI seems to
+ // sometimes give us AA text, and sometimes give us BW text. Since the
+ // original intent was LCD, we want to force AA (rather than BW), so we
+ // add a special bit to tell Skia to do its best to avoid the BW: by
+ // drawing LCD offscreen and downsampling that to AA.
+ textFlags |= SkPaint::kGenA8FromLCD_Flag;
+ }
+ SkASSERT(!(textFlags & ~textFlagsMask));
+ flags |= textFlags;
+ }
+
paint->setFlags(flags);
}
// Lookup the current system settings for font smoothing.
// We cache these values for performance, but if the browser has a way to be
// notified when these change, we could re-query them at that time.
-static uint32_t getDefaultGDITextFlags()
+static uint32_t getSystemTextFlags()
{
static bool gInited;
static uint32_t gFlags;
if (!gInited) {
BOOL enabled;
gFlags = 0;
- if (SystemParametersInfo(SPI_GETFONTSMOOTHING, 0, &enabled, 0) && enabled) {
- gFlags |= SkPaint::kAntiAlias_Flag;
-
- UINT smoothType;
- if (SystemParametersInfo(SPI_GETFONTSMOOTHINGTYPE, 0, &smoothType, 0)) {
- if (FE_FONTSMOOTHINGCLEARTYPE == smoothType)
- gFlags |= SkPaint::kLCDRenderText_Flag;
+ if (SystemParametersInfo(SPI_GETFONTSMOOTHING, 0, &enabled, 0)) {
+ if (enabled) {
+ gFlags |= SkPaint::kAntiAlias_Flag;
+
+ UINT smoothType;
+ if (SystemParametersInfo(SPI_GETFONTSMOOTHINGTYPE, 0, &smoothType, 0)) {
+ if (FE_FONTSMOOTHINGCLEARTYPE == smoothType)
+ gFlags |= SkPaint::kLCDRenderText_Flag;
+ }
}
+ } else {
+ // SystemParametersInfo will fail only under full sandbox lockdown on Win8+.
+ // So, we default to settings we know are supported and look good.
+ // FIXME(eae): We should be querying the DirectWrite settings directly
+ // so we can respect the settings for users who turn off smoothing.
+ gFlags = SkPaint::kAntiAlias_Flag | SkPaint::kLCDRenderText_Flag;
}
gInited = true;
}
return gFlags;
}
-static bool isWebFont(const LOGFONT& lf)
+static bool isWebFont(const String& familyName)
{
- // web-fonts have artifical names constructed to always be
+ // Web-fonts have artifical names constructed to always be:
// 1. 24 characters, followed by a '\0'
// 2. the last two characters are '=='
- return '=' == lf.lfFaceName[22] && '=' == lf.lfFaceName[23] && '\0' == lf.lfFaceName[24];
+ return familyName.length() == 24
+ && '=' == familyName[22] && '=' == familyName[23];
}
-static int computePaintTextFlags(const LOGFONT& lf)
+static int computePaintTextFlags(String fontFamilyName)
{
- int textFlags = 0;
- switch (lf.lfQuality) {
- case NONANTIALIASED_QUALITY:
- textFlags = 0;
- break;
- case ANTIALIASED_QUALITY:
- textFlags = SkPaint::kAntiAlias_Flag;
- break;
- case CLEARTYPE_QUALITY:
- textFlags = (SkPaint::kAntiAlias_Flag | SkPaint::kLCDRenderText_Flag);
- break;
- default:
- textFlags = getDefaultGDITextFlags();
- break;
- }
+ if (isRunningLayoutTest())
+ return isFontAntialiasingEnabledForTest() ? SkPaint::kAntiAlias_Flag : 0;
- // only allow features that SystemParametersInfo allows
- textFlags &= getDefaultGDITextFlags();
+ int textFlags = getSystemTextFlags();
- /*
- * FontPlatformData(...) will read our logfont, and try to honor the the lfQuality
- * setting (computing the corresponding SkPaint flags for AA and LCD). However, it
- * will limit the quality based on its query of SPI_GETFONTSMOOTHING. This could mean
- * we end up drawing the text in BW, even though our lfQuality requested antialiasing.
- *
- * Many web-fonts are so poorly hinted that they are terrible to read when drawn in BW.
- * In these cases, we have decided to FORCE these fonts to be drawn with at least grayscale AA,
- * even when the System (getDefaultGDITextFlags) tells us to draw only in BW.
- */
- if (isWebFont(lf) && !isRunningLayoutTest())
+ // Many web-fonts are so poorly hinted that they are terrible to read when drawn in BW.
+ // In these cases, we have decided to FORCE these fonts to be drawn with at least grayscale AA,
+ // even when the System (getSystemTextFlags) tells us to draw only in BW.
+ if (isWebFont(fontFamilyName))
textFlags |= SkPaint::kAntiAlias_Flag;
- return textFlags;
-}
-
-#if !USE(HARFBUZZ)
-PassRefPtr<SkTypeface> CreateTypefaceFromHFont(HFONT hfont, int* size, int* paintTextFlags)
-{
- LOGFONT info;
- GetObject(hfont, sizeof(info), &info);
- if (size) {
- int height = info.lfHeight;
- if (height < 0)
- height = -height;
- *size = height;
- }
- if (paintTextFlags)
- *paintTextFlags = computePaintTextFlags(info);
- return adoptRef(SkCreateTypefaceFromLOGFONT(info));
-}
-#endif
-
-FontPlatformData::FontPlatformData(WTF::HashTableDeletedValueType)
- : m_textSize(-1)
- , m_fakeBold(false)
- , m_fakeItalic(false)
- , m_orientation(Horizontal)
- , m_typeface(adoptRef(SkTypeface::RefDefault()))
- , m_paintTextFlags(0)
- , m_isHashTableDeletedValue(true)
- , m_useSubpixelPositioning(false)
-{
-#if !USE(HARFBUZZ)
- m_font = 0;
- m_scriptCache = 0;
-#endif
-}
-
-FontPlatformData::FontPlatformData()
- : m_textSize(0)
- , m_fakeBold(false)
- , m_fakeItalic(false)
- , m_orientation(Horizontal)
- , m_typeface(adoptRef(SkTypeface::RefDefault()))
- , m_paintTextFlags(0)
- , m_isHashTableDeletedValue(false)
- , m_useSubpixelPositioning(false)
-{
-#if !USE(HARFBUZZ)
- m_font = 0;
- m_scriptCache = 0;
-#endif
-}
-
-#if ENABLE(GDI_FONTS_ON_WINDOWS) && !USE(HARFBUZZ)
-FontPlatformData::FontPlatformData(HFONT font, float size, FontOrientation orientation)
- : m_font(RefCountedHFONT::create(font))
- , m_textSize(size)
- , m_fakeBold(false)
- , m_fakeItalic(false)
- , m_orientation(orientation)
- , m_scriptCache(0)
- , m_typeface(CreateTypefaceFromHFont(font, 0, &m_paintTextFlags))
- , m_isHashTableDeletedValue(false)
- , m_useSubpixelPositioning(false)
-{
-}
-#endif
-
-// FIXME: this constructor is needed for SVG fonts but doesn't seem to do much
-FontPlatformData::FontPlatformData(float size, bool bold, bool oblique)
- : m_textSize(size)
- , m_fakeBold(false)
- , m_fakeItalic(false)
- , m_orientation(Horizontal)
- , m_typeface(adoptRef(SkTypeface::RefDefault()))
- , m_paintTextFlags(0)
- , m_isHashTableDeletedValue(false)
- , m_useSubpixelPositioning(false)
-{
-#if !USE(HARFBUZZ)
- m_font = 0;
- m_scriptCache = 0;
-#endif
-}
-
-FontPlatformData::FontPlatformData(const FontPlatformData& data)
- : m_textSize(data.m_textSize)
- , m_fakeBold(data.m_fakeBold)
- , m_fakeItalic(data.m_fakeItalic)
- , m_orientation(data.m_orientation)
- , m_typeface(data.m_typeface)
- , m_paintTextFlags(data.m_paintTextFlags)
- , m_isHashTableDeletedValue(false)
- , m_useSubpixelPositioning(data.m_useSubpixelPositioning)
-{
-#if !USE(HARFBUZZ)
- m_font = data.m_font;
- m_scriptCache = 0;
-#endif
-}
-
-FontPlatformData::FontPlatformData(const FontPlatformData& data, float textSize)
- : m_textSize(textSize)
- , m_fakeBold(data.m_fakeBold)
- , m_fakeItalic(data.m_fakeItalic)
- , m_orientation(data.m_orientation)
- , m_typeface(data.m_typeface)
- , m_paintTextFlags(data.m_paintTextFlags)
- , m_isHashTableDeletedValue(false)
- , m_useSubpixelPositioning(data.m_useSubpixelPositioning)
-{
-#if !USE(HARFBUZZ)
- m_font = data.m_font;
- m_scriptCache = 0;
-#endif
-}
-
-FontPlatformData::FontPlatformData(PassRefPtr<SkTypeface> tf, const char* family,
- float textSize, bool fakeBold, bool fakeItalic, FontOrientation orientation,
- bool useSubpixelPositioning)
- : m_textSize(textSize)
- , m_fakeBold(fakeBold)
- , m_fakeItalic(fakeItalic)
- , m_orientation(orientation)
- , m_typeface(tf)
- , m_isHashTableDeletedValue(false)
- , m_useSubpixelPositioning(useSubpixelPositioning)
-{
- // FIXME: This can be removed together with m_font once the last few
- // uses of hfont() has been eliminated.
- LOGFONT logFont;
- SkLOGFONTFromTypeface(m_typeface.get(), &logFont);
- logFont.lfHeight = -textSize;
- m_paintTextFlags = computePaintTextFlags(logFont);
-
-#if !USE(HARFBUZZ)
- HFONT hFont = CreateFontIndirect(&logFont);
- m_font = hFont ? RefCountedHFONT::create(hFont) : 0;
- m_scriptCache = 0;
-#endif
-}
-
-FontPlatformData& FontPlatformData::operator=(const FontPlatformData& data)
-{
- if (this != &data) {
- m_textSize = data.m_textSize;
- m_fakeBold = data.m_fakeBold;
- m_fakeItalic = data.m_fakeItalic;
- m_orientation = data.m_orientation;
- m_typeface = data.m_typeface;
- m_paintTextFlags = data.m_paintTextFlags;
-
-#if !USE(HARFBUZZ)
- m_font = data.m_font;
- // The following fields will get re-computed if necessary.
- ScriptFreeCache(&m_scriptCache);
- m_scriptCache = 0;
- m_scriptFontProperties.clear();
-#endif
- }
- return *this;
-}
-
-FontPlatformData::~FontPlatformData()
-{
-#if !USE(HARFBUZZ)
- ScriptFreeCache(&m_scriptCache);
- m_scriptCache = 0;
-#endif
-}
-
-String FontPlatformData::fontFamilyName() const
-{
-#if ENABLE(GDI_FONTS_ON_WINDOWS)
- HWndDC dc(0);
- HGDIOBJ oldFont = static_cast<HFONT>(SelectObject(dc, hfont()));
- WCHAR name[LF_FACESIZE];
- unsigned resultLength = GetTextFace(dc, LF_FACESIZE, name);
- if (resultLength > 0)
- resultLength--; // ignore the null terminator
- SelectObject(dc, oldFont);
- return String(name, resultLength);
-#else
- // FIXME: This returns the requested name, perhaps a better solution would be to
- // return the list of names provided by SkTypeface::createFamilyNameIterator.
- ASSERT(typeface());
- SkString familyName;
- typeface()->getFamilyName(&familyName);
- return String::fromUTF8(familyName.c_str());
-#endif
-}
-
-bool FontPlatformData::isFixedPitch() const
-{
-#if ENABLE(GDI_FONTS_ON_WINDOWS)
- // TEXTMETRICS have this. Set m_treatAsFixedPitch based off that.
- HWndDC dc(0);
- HGDIOBJ oldFont = SelectObject(dc, hfont());
-
- // Yes, this looks backwards, but the fixed pitch bit is actually set if the font
- // is *not* fixed pitch. Unbelievable but true.
- TEXTMETRIC textMetric = { 0 };
- if (!GetTextMetrics(dc, &textMetric)) {
- if (ensureFontLoaded(hfont())) {
- // Retry GetTextMetrics.
- // FIXME: Handle gracefully the error if this call also fails.
- // See http://crbug.com/6401.
- if (!GetTextMetrics(dc, &textMetric))
- WTF_LOG_ERROR("Unable to get the text metrics after second attempt");
- }
- }
-
- bool treatAsFixedPitch = !(textMetric.tmPitchAndFamily & TMPF_FIXED_PITCH);
-
- SelectObject(dc, oldFont);
-
- return treatAsFixedPitch;
-#else
- return typeface() && typeface()->isFixedPitch();
-#endif
-}
-
-bool FontPlatformData::operator==(const FontPlatformData& a) const
-{
- return SkTypeface::Equal(m_typeface.get(), a.m_typeface.get())
- && m_textSize == a.m_textSize
- && m_fakeBold == a.m_fakeBold
- && m_fakeItalic == a.m_fakeItalic
- && m_orientation == a.m_orientation
- && m_isHashTableDeletedValue == a.m_isHashTableDeletedValue;
-}
-
-#if USE(HARFBUZZ)
-HarfBuzzFace* FontPlatformData::harfBuzzFace() const
-{
- if (!m_harfBuzzFace)
- m_harfBuzzFace = HarfBuzzFace::create(const_cast<FontPlatformData*>(this), uniqueID());
-
- return m_harfBuzzFace.get();
-}
-#else
-FontPlatformData::RefCountedHFONT::~RefCountedHFONT()
-{
- DeleteObject(m_hfont);
+ return textFlags;
}
-SCRIPT_FONTPROPERTIES* FontPlatformData::scriptFontProperties() const
-{
- if (!m_scriptFontProperties) {
- m_scriptFontProperties = adoptPtr(new SCRIPT_FONTPROPERTIES);
- memset(m_scriptFontProperties.get(), 0, sizeof(SCRIPT_FONTPROPERTIES));
- m_scriptFontProperties->cBytes = sizeof(SCRIPT_FONTPROPERTIES);
- HRESULT result = ScriptGetFontProperties(0, scriptCache(), m_scriptFontProperties.get());
- if (result == E_PENDING) {
- HWndDC dc(0);
- HGDIOBJ oldFont = SelectObject(dc, hfont());
- HRESULT hr = ScriptGetFontProperties(dc, scriptCache(), m_scriptFontProperties.get());
- if (S_OK != hr) {
- if (FontPlatformData::ensureFontLoaded(hfont())) {
- // FIXME: Handle gracefully the error if this call also fails.
- hr = ScriptGetFontProperties(dc, scriptCache(), m_scriptFontProperties.get());
- if (S_OK != hr) {
- WTF_LOG_ERROR("Unable to get the font properties after second attempt");
- }
- }
- }
-
- SelectObject(dc, oldFont);
- }
- }
- return m_scriptFontProperties.get();
-}
-bool FontPlatformData::ensureFontLoaded(HFONT font)
+void FontPlatformData::querySystemForRenderStyle(bool)
{
- blink::WebSandboxSupport* sandboxSupport = blink::Platform::current()->sandboxSupport();
- // if there is no sandbox, then we can assume the font
- // was able to be loaded successfully already
- return sandboxSupport ? sandboxSupport->ensureFontLoaded(font) : true;
+ m_paintTextFlags = computePaintTextFlags(fontFamilyName());
}
-#endif
bool FontPlatformData::defaultUseSubpixelPositioning()
{
-#if OS(WIN) && !ENABLE(GDI_FONTS_ON_WINDOWS)
return FontCache::fontCache()->useSubpixelPositioning();
-#else
- return false;
-#endif
-}
-
-#ifndef NDEBUG
-String FontPlatformData::description() const
-{
- return String();
}
-#endif
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/win/FontPlatformDataWin.h b/chromium/third_party/WebKit/Source/platform/fonts/win/FontPlatformDataWin.h
deleted file mode 100644
index 3b3e9736e1e..00000000000
--- a/chromium/third_party/WebKit/Source/platform/fonts/win/FontPlatformDataWin.h
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- * Copyright (C) 2006, 2007 Apple Computer, Inc.
- * Copyright (c) 2006, 2007, 2008, 2009, Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef FontPlatformDataChromiumWin_h
-#define FontPlatformDataChromiumWin_h
-
-#include "SkPaint.h"
-#include "SkTypeface.h"
-#include "SkTypeface_win.h"
-#include "platform/SharedBuffer.h"
-#include "platform/fonts/FontOrientation.h"
-#include "platform/fonts/opentype/OpenTypeVerticalData.h"
-#include "wtf/Forward.h"
-#include "wtf/HashTableDeletedValueType.h"
-#include "wtf/OwnPtr.h"
-#include "wtf/PassRefPtr.h"
-#include "wtf/RefCounted.h"
-#include "wtf/RefPtr.h"
-#include "wtf/text/StringImpl.h"
-
-#include <usp10.h>
-
-typedef struct HFONT__ *HFONT;
-
-namespace WebCore {
-
-// Return a typeface associated with the hfont, and return its size and
-// lfQuality from the hfont's LOGFONT.
-PassRefPtr<SkTypeface> CreateTypefaceFromHFont(HFONT, int* size, int* paintTextFlags);
-
-class FontDescription;
-class GraphicsContext;
-class HarfBuzzFace;
-
-class PLATFORM_EXPORT FontPlatformData {
-public:
- // Used for deleted values in the font cache's hash tables. The hash table
- // will create us with this structure, and it will compare other values
- // to this "Deleted" one. It expects the Deleted one to be differentiable
- // from the NULL one (created with the empty constructor), so we can't just
- // set everything to NULL.
- FontPlatformData(WTF::HashTableDeletedValueType);
- FontPlatformData();
-#if ENABLE(GDI_FONTS_ON_WINDOWS)
- // This constructor takes ownership of the HFONT
- FontPlatformData(HFONT, float size, FontOrientation);
-#endif
- FontPlatformData(float size, bool bold, bool oblique);
- FontPlatformData(const FontPlatformData&);
- FontPlatformData(const FontPlatformData&, float textSize);
- FontPlatformData(PassRefPtr<SkTypeface>, const char* name, float textSize, bool fakeBold, bool fakeItalic, FontOrientation = Horizontal, bool useSubpixelPositioning = defaultUseSubpixelPositioning());
-
- void setupPaint(SkPaint*, GraphicsContext* = 0) const;
-
- FontPlatformData& operator=(const FontPlatformData&);
-
- bool isHashTableDeletedValue() const { return m_isHashTableDeletedValue; }
-
- ~FontPlatformData();
-
- bool isFixedPitch() const;
- float size() const { return m_textSize; }
-#if USE(HARFBUZZ)
- HarfBuzzFace* harfBuzzFace() const;
-#else
- HFONT hfont() const { return m_font ? m_font->hfont() : 0; }
-#endif
- SkTypeface* typeface() const { return m_typeface.get(); }
- SkFontID uniqueID() const { return m_typeface->uniqueID(); }
- int paintTextFlags() const { return m_paintTextFlags; }
-
- String fontFamilyName() const;
-
- FontOrientation orientation() const { return m_orientation; }
- void setOrientation(FontOrientation orientation) { m_orientation = orientation; }
-
-#if ENABLE(GDI_FONTS_ON_WINDOWS)
- unsigned hash() const
- {
- return m_font ? m_font->hash() : NULL;
- }
-#else
- unsigned hash() const;
-#endif
-
- bool operator==(const FontPlatformData&) const;
-
-#if ENABLE(OPENTYPE_VERTICAL)
- PassRefPtr<OpenTypeVerticalData> verticalData() const;
- PassRefPtr<SharedBuffer> openTypeTable(uint32_t table) const;
-#endif
-
-#ifndef NDEBUG
- String description() const;
-#endif
-
-#if !USE(HARFBUZZ)
- SCRIPT_FONTPROPERTIES* scriptFontProperties() const;
- SCRIPT_CACHE* scriptCache() const { return &m_scriptCache; }
- static bool ensureFontLoaded(HFONT);
-#endif
-
-private:
- bool static defaultUseSubpixelPositioning();
-
-#if !USE(HARFBUZZ)
- // We refcount the internal HFONT so that FontPlatformData can be
- // efficiently copied. WebKit depends on being able to copy it, and we
- // don't really want to re-create the HFONT.
- class RefCountedHFONT : public RefCounted<RefCountedHFONT> {
- public:
- static PassRefPtr<RefCountedHFONT> create(HFONT hfont)
- {
- return adoptRef(new RefCountedHFONT(hfont));
- }
-
- ~RefCountedHFONT();
-
- HFONT hfont() const { return m_hfont; }
- unsigned hash() const
- {
- return StringHasher::hashMemory<sizeof(HFONT)>(&m_hfont);
- }
-
- bool operator==(const RefCountedHFONT& other) const
- {
- return m_hfont == other.m_hfont;
- }
-
- private:
- // The create() function assumes there is already a refcount of one
- // so it can do adoptRef.
- RefCountedHFONT(HFONT hfont) : m_hfont(hfont)
- {
- }
-
- HFONT m_hfont;
- };
-
- RefPtr<RefCountedHFONT> m_font;
-#endif // !USE(HARFBUZZ)
- float m_textSize; // Point size of the font in pixels.
- FontOrientation m_orientation;
- bool m_fakeBold;
- bool m_fakeItalic;
-
- RefPtr<SkTypeface> m_typeface;
- int m_paintTextFlags;
-
-#if USE(HARFBUZZ)
- mutable RefPtr<HarfBuzzFace> m_harfBuzzFace;
-#else
- mutable SCRIPT_CACHE m_scriptCache;
- mutable OwnPtr<SCRIPT_FONTPROPERTIES> m_scriptFontProperties;
-#endif
-
- bool m_isHashTableDeletedValue;
- bool m_useSubpixelPositioning;
-};
-
-} // WebCore
-
-#endif // FontPlatformDataChromiumWin_h
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/win/FontWin.cpp b/chromium/third_party/WebKit/Source/platform/fonts/win/FontWin.cpp
deleted file mode 100644
index 605d129ee89..00000000000
--- a/chromium/third_party/WebKit/Source/platform/fonts/win/FontWin.cpp
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
- * Copyright (C) 2006, 2007 Apple Computer, Inc.
- * Copyright (c) 2006, 2007, 2008, 2009, Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "platform/fonts/Font.h"
-
-#include "platform/NotImplemented.h"
-#include "platform/fonts/FontFallbackList.h"
-#include "platform/fonts/GlyphBuffer.h"
-#include "platform/fonts/SimpleFontData.h"
-#include "platform/fonts/skia/SkiaFontWin.h"
-#include "platform/fonts/win/FontPlatformDataWin.h"
-#include "platform/fonts/win/UniscribeHelperTextRun.h"
-#include "platform/graphics/GraphicsContext.h"
-
-#include <windows.h>
-
-using namespace std;
-
-namespace WebCore {
-
-bool Font::canReturnFallbackFontsForComplexText()
-{
- return false;
-}
-
-bool Font::canExpandAroundIdeographsInComplexText()
-{
- return false;
-}
-
-void Font::drawGlyphs(GraphicsContext* graphicsContext,
- const SimpleFontData* font, const GlyphBuffer& glyphBuffer,
- unsigned from, unsigned numGlyphs, const FloatPoint& point,
- const FloatRect& textRect) const
-{
- SkColor color = graphicsContext->effectiveFillColor();
- unsigned char alpha = SkColorGetA(color);
- // Skip 100% transparent text; no need to draw anything.
- if (!alpha && graphicsContext->strokeStyle() == NoStroke && !graphicsContext->hasShadow())
- return;
-
- // We draw the glyphs in chunks to avoid having to do a heap allocation for
- // the arrays of characters and advances.
- const unsigned kMaxBufferLength = 256;
- Vector<int, kMaxBufferLength> advances;
- unsigned glyphIndex = 0; // The starting glyph of the current chunk.
-
- float horizontalOffset = point.x(); // The floating point offset of the left side of the current glyph.
-
-#if ENABLE(OPENTYPE_VERTICAL)
- const OpenTypeVerticalData* verticalData = font->verticalData();
- if (verticalData) {
- Vector<FloatPoint, kMaxBufferLength> translations;
- Vector<GOFFSET, kMaxBufferLength> offsets;
-
- // Skia doesn't have matrix for glyph coordinate space, so we rotate back the CTM.
- AffineTransform savedMatrix = graphicsContext->getCTM();
- graphicsContext->concatCTM(AffineTransform(0, -1, 1, 0, point.x(), point.y()));
- graphicsContext->concatCTM(AffineTransform(1, 0, 0, 1, -point.x(), -point.y()));
-
- const FontMetrics& metrics = font->fontMetrics();
- SkScalar verticalOriginX = SkFloatToScalar(point.x() + metrics.floatAscent() - metrics.floatAscent(IdeographicBaseline));
- while (glyphIndex < numGlyphs) {
- // How many chars will be in this chunk?
- unsigned curLen = std::min(kMaxBufferLength, numGlyphs - glyphIndex);
-
- const Glyph* glyphs = glyphBuffer.glyphs(from + glyphIndex);
- translations.resize(curLen);
- verticalData->getVerticalTranslationsForGlyphs(font, &glyphs[0], curLen, reinterpret_cast<float*>(&translations[0]));
- // To position glyphs vertically, we use offsets instead of advances.
- advances.resize(curLen);
- advances.fill(0);
- offsets.resize(curLen);
- float currentWidth = 0;
- for (unsigned i = 0; i < curLen; ++i, ++glyphIndex) {
- offsets[i].du = lroundf(translations[i].x());
- offsets[i].dv = -lroundf(currentWidth - translations[i].y());
- currentWidth += glyphBuffer.advanceAt(from + glyphIndex);
- }
- SkPoint origin;
- origin.set(verticalOriginX, SkFloatToScalar(point.y() + horizontalOffset - point.x()));
- horizontalOffset += currentWidth;
- paintSkiaText(graphicsContext, font->platformData(), curLen, &glyphs[0], &advances[0], &offsets[0], origin, SkRect(textRect));
- }
-
- graphicsContext->setCTM(savedMatrix);
- return;
- }
-#endif
-
- // In order to round all offsets to the correct pixel boundary, this code keeps track of the absolute position
- // of each glyph in floating point units and rounds to integer advances at the last possible moment.
-
- int lastHorizontalOffsetRounded = lroundf(horizontalOffset); // The rounded offset of the left side of the last glyph rendered.
- Vector<WORD, kMaxBufferLength> glyphs;
- while (glyphIndex < numGlyphs) {
- // How many chars will be in this chunk?
- unsigned curLen = std::min(kMaxBufferLength, numGlyphs - glyphIndex);
- glyphs.resize(curLen);
- advances.resize(curLen);
-
- float currentWidth = 0;
- for (unsigned i = 0; i < curLen; ++i, ++glyphIndex) {
- glyphs[i] = glyphBuffer.glyphAt(from + glyphIndex);
- horizontalOffset += glyphBuffer.advanceAt(from + glyphIndex);
- advances[i] = lroundf(horizontalOffset) - lastHorizontalOffsetRounded;
- lastHorizontalOffsetRounded += advances[i];
- currentWidth += glyphBuffer.advanceAt(from + glyphIndex);
-
- // Bug 26088 - very large positive or negative runs can fail to
- // render so we clamp the size here. In the specs, negative
- // letter-spacing is implementation-defined, so this should be
- // fine, and it matches Safari's implementation. The call actually
- // seems to crash if kMaxNegativeRun is set to somewhere around
- // -32830, so we give ourselves a little breathing room.
- const int maxNegativeRun = -32768;
- const int maxPositiveRun = 32768;
- if ((currentWidth + advances[i] < maxNegativeRun) || (currentWidth + advances[i] > maxPositiveRun))
- advances[i] = 0;
- }
-
- SkPoint origin = point;
- origin.fX += SkFloatToScalar(horizontalOffset - point.x() - currentWidth);
- paintSkiaText(graphicsContext, font->platformData(), curLen, &glyphs[0], &advances[0], 0, origin, SkRect(textRect));
- }
-}
-
-FloatRect Font::selectionRectForComplexText(const TextRun& run,
- const FloatPoint& point,
- int h,
- int from,
- int to) const
-{
- UniscribeHelperTextRun state(run, *this);
- float left = static_cast<float>(point.x() + state.characterToX(from));
- float right = static_cast<float>(point.x() + state.characterToX(to));
-
- // If the text is RTL, left will actually be after right.
- if (left < right)
- return FloatRect(left, point.y(),
- right - left, static_cast<float>(h));
-
- return FloatRect(right, point.y(),
- left - right, static_cast<float>(h));
-}
-
-void Font::drawComplexText(GraphicsContext* graphicsContext,
- const TextRunPaintInfo& runInfo,
- const FloatPoint& point) const
-{
- UniscribeHelperTextRun state(runInfo.run, *this);
-
- SkColor color = graphicsContext->effectiveFillColor();
- unsigned char alpha = SkColorGetA(color);
- // Skip 100% transparent text; no need to draw anything.
- if (!alpha && graphicsContext->strokeStyle() == NoStroke)
- return;
-
- HDC hdc = 0;
- // Uniscribe counts the coordinates from the upper left, while WebKit uses
- // the baseline, so we have to subtract off the ascent.
- state.draw(graphicsContext, primaryFont()->platformData(), hdc, lroundf(point.x()), lroundf(point.y() - fontMetrics().ascent()), runInfo.bounds, runInfo.from, runInfo.to);
-}
-
-void Font::drawEmphasisMarksForComplexText(GraphicsContext* /* context */, const TextRunPaintInfo& /* runInfo */, const AtomicString& /* mark */, const FloatPoint& /* point */) const
-{
- notImplemented();
-}
-
-float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* /* fallbackFonts */, GlyphOverflow* /* glyphOverflow */) const
-{
- UniscribeHelperTextRun state(run, *this);
- return static_cast<float>(state.width());
-}
-
-int Font::offsetForPositionForComplexText(const TextRun& run, float xFloat,
- bool includePartialGlyphs) const
-{
- // FIXME: This truncation is not a problem for HTML, but only affects SVG, which passes floating-point numbers
- // to Font::offsetForPosition(). Bug http://webkit.org/b/40673 tracks fixing this problem.
- int x = static_cast<int>(xFloat);
-
- // Mac code ignores includePartialGlyphs, and they don't know what it's
- // supposed to do, so we just ignore it as well.
- UniscribeHelperTextRun state(run, *this);
- int charIndex = state.xToCharacter(x);
-
- // XToCharacter will return -1 if the position is before the first
- // character (we get called like this sometimes).
- if (charIndex < 0)
- charIndex = 0;
- return charIndex;
-}
-
-} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/win/GlyphPageTreeNodeWin.cpp b/chromium/third_party/WebKit/Source/platform/fonts/win/GlyphPageTreeNodeWin.cpp
deleted file mode 100644
index a33515f252a..00000000000
--- a/chromium/third_party/WebKit/Source/platform/fonts/win/GlyphPageTreeNodeWin.cpp
+++ /dev/null
@@ -1,260 +0,0 @@
-/*
- * Copyright (c) 2008, 2009, 2012 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <windows.h>
-#include "config.h"
-#include <vector>
-
-#include "platform/fonts/Font.h"
-#include "platform/fonts/GlyphPageTreeNode.h"
-#include "platform/fonts/SimpleFontData.h"
-#include "platform/fonts/win/FontPlatformDataWin.h"
-#include "platform/fonts/win/UniscribeHelperTextRun.h"
-#include "platform/win/HWndDC.h"
-#include "platform/win/SystemInfo.h"
-
-namespace WebCore {
-
-// Fills one page of font data pointers with 0 to indicate that there
-// are no glyphs for the characters.
-static void fillEmptyGlyphs(GlyphPage* page)
-{
- for (int i = 0; i < GlyphPage::size; ++i)
- page->setGlyphDataForIndex(i, 0, 0);
-}
-
-// Convert characters to glyph ids by GetGlyphIndices(), during which, we
-// ensure the font is loaded in memory to make it work in a sandboxed process.
-static bool getGlyphIndices(HFONT font, HDC dc, const UChar* characters, unsigned charactersLength, WORD* glyphBuffer, DWORD flag)
-{
- if (GetGlyphIndices(dc, characters, charactersLength, glyphBuffer, flag) != GDI_ERROR)
- return true;
- if (FontPlatformData::ensureFontLoaded(font)) {
- if (GetGlyphIndices(dc, characters, charactersLength, glyphBuffer, flag) != GDI_ERROR)
- return true;
- // FIXME: Handle gracefully the error if this call also fails.
- // See http://crbug.com/6401
- WTF_LOG_ERROR("Unable to get the glyph indices after second attempt");
- }
- return false;
-}
-
-// Initializes space glyph
-static bool initSpaceGlyph(HFONT font, HDC dc, Glyph* spaceGlyph)
-{
- static wchar_t space = ' ';
- return getGlyphIndices(font, dc, &space, 1, spaceGlyph, 0);
-}
-
-// Fills |length| glyphs starting at |offset| in a |page| in the Basic
-// Multilingual Plane (<= U+FFFF). The input buffer size should be the
-// same as |length|. We can use the standard Windows GDI functions here.
-// Returns true if any glyphs were found.
-static bool fillBMPGlyphs(unsigned offset,
- unsigned length,
- UChar* buffer,
- GlyphPage* page,
- const SimpleFontData* fontData)
-{
- HWndDC dc(0);
- HGDIOBJ oldFont = SelectObject(dc, fontData->platformData().hfont());
-
- TEXTMETRIC tm = {0};
- if (!GetTextMetrics(dc, &tm)) {
- if (FontPlatformData::ensureFontLoaded(fontData->platformData().hfont())) {
- if (!GetTextMetrics(dc, &tm)) {
- // FIXME: Handle gracefully the error if this call also fails.
- // See http://crbug.com/6401
- WTF_LOG_ERROR("Unable to get the text metrics after second attempt");
-
- SelectObject(dc, oldFont);
- fillEmptyGlyphs(page);
- return false;
- }
- } else {
- SelectObject(dc, oldFont);
- fillEmptyGlyphs(page);
- return false;
- }
- }
-
- // FIXME: GetGlyphIndices() sets each item of localGlyphBuffer[]
- // with the one of the values listed below.
- // * With the GGI_MARK_NONEXISTING_GLYPHS flag
- // + If the font has a glyph available for the character,
- // localGlyphBuffer[i] > 0x0.
- // + If the font does not have glyphs available for the character,
- // localGlyphBuffer[i] = 0x1F (TrueType Collection?) or
- // 0xFFFF (OpenType?).
- // * Without the GGI_MARK_NONEXISTING_GLYPHS flag
- // + If the font has a glyph available for the character,
- // localGlyphBuffer[i] > 0x0.
- // + If the font does not have glyphs available for the character,
- // localGlyphBuffer[i] = 0x80.
- // (Windows automatically assigns the glyph for a box character to
- // prevent ExtTextOut() from returning errors.)
- // To avoid from hurting the rendering performance, this code just
- // tells WebKit whether or not the all glyph indices for the given
- // characters are 0x80 (i.e. a possibly-invalid glyph) and let it
- // use alternative fonts for the characters.
- // Although this may cause a problem, it seems to work fine as far as I
- // have tested. (Obviously, I need more tests.)
- WORD localGlyphBuffer[GlyphPage::size];
-
- // FIXME: I find some Chinese characters can not be correctly displayed
- // when call GetGlyphIndices without flag GGI_MARK_NONEXISTING_GLYPHS,
- // because the corresponding glyph index is set as 0x20 when current font
- // does not have glyphs available for the character. According a blog post
- // http://blogs.msdn.com/michkap/archive/2006/06/28/649791.aspx
- // I think we should switch to the way about calling GetGlyphIndices with
- // flag GGI_MARK_NONEXISTING_GLYPHS, it should be OK according the
- // description of MSDN.
- // Also according to Jungshik and Hironori's suggestion and modification
- // we treat turetype and raster Font as different way when windows version
- // is less than Vista.
- if (!getGlyphIndices(fontData->platformData().hfont(), dc, buffer, length, localGlyphBuffer, GGI_MARK_NONEXISTING_GLYPHS)) {
- SelectObject(dc, oldFont);
- fillEmptyGlyphs(page);
- return false;
- }
-
- // Copy the output to the GlyphPage
- bool haveGlyphs = false;
- int invalidGlyph = 0xFFFF;
- const DWORD cffTableTag = 0x20464643; // 4-byte identifier for OpenType CFF table ('CFF ').
- if (!isWindowsVistaOrGreater() && !(tm.tmPitchAndFamily & TMPF_TRUETYPE) && (GetFontData(dc, cffTableTag, 0, 0, 0) == GDI_ERROR))
- invalidGlyph = 0x1F;
-
- Glyph spaceGlyph = 0; // Glyph for a space. Lazily filled.
- bool spaceGlyphInitialized = false;
-
- for (unsigned i = 0; i < length; i++) {
- UChar c = buffer[i];
- Glyph glyph = localGlyphBuffer[i];
- const SimpleFontData* glyphFontData = fontData;
- // When this character should be a space, we ignore whatever the font
- // says and use a space. Otherwise, if fonts don't map one of these
- // space or zero width glyphs, we will get a box.
- if (Font::treatAsSpace(c)) {
- // Hard code the glyph indices for characters that should be
- // treated like spaces.
- if (!spaceGlyphInitialized) {
- // If initSpaceGlyph fails, spaceGlyph stays 0 (= glyph is not present).
- initSpaceGlyph(fontData->platformData().hfont(), dc, &spaceGlyph);
- spaceGlyphInitialized = true;
- if (spaceGlyph)
- haveGlyphs = true;
- }
- glyph = spaceGlyph;
- } else if (glyph == invalidGlyph) {
- // WebKit expects both the glyph index and FontData
- // pointer to be 0 if the glyph is not present
- glyph = 0;
- glyphFontData = 0;
- } else
- haveGlyphs = true;
- page->setGlyphDataForCharacter(offset + i, glyph, glyphFontData);
- }
-
- SelectObject(dc, oldFont);
- return haveGlyphs;
-}
-
-// For non-BMP characters, each is two words (UTF-16) and the input buffer
-// size is 2 * |length|. Since GDI doesn't know how to handle non-BMP
-// characters, we must use Uniscribe to tell us the glyph indices.
-//
-// We don't want to call this in the case of "regular" characters since some
-// fonts may not have the correct combining rules for accents. See the notes
-// at the bottom of ScriptGetCMap. We can't use ScriptGetCMap, though, since
-// it doesn't seem to support UTF-16, despite what this blog post says:
-// http://blogs.msdn.com/michkap/archive/2006/06/29/650680.aspx
-//
-// So we fire up the full Uniscribe doohicky, give it our string, and it will
-// correctly handle the UTF-16 for us. The hard part is taking this and getting
-// the glyph indices back out that correspond to the correct input characters,
-// since they may be missing.
-//
-// Returns true if any glyphs were found.
-static bool fillNonBMPGlyphs(unsigned offset,
- unsigned length,
- UChar* buffer,
- GlyphPage* page,
- const SimpleFontData* fontData)
-{
- bool haveGlyphs = false;
-
- UniscribeHelperTextRun state(buffer, length * 2, false,
- fontData->platformData().hfont(),
- fontData->platformData().scriptCache(),
- fontData->platformData().scriptFontProperties());
- state.setInhibitLigate(true);
- state.setDisableFontFallback(true);
- state.init();
-
- for (unsigned i = 0; i < length; i++) {
- // Each character in this input buffer is a surrogate pair, which
- // consists of two UChars. So, the offset for its i-th character is
- // (i * 2).
- WORD glyph = state.firstGlyphForCharacter(i * 2);
- if (glyph) {
- haveGlyphs = true;
- page->setGlyphDataForIndex(offset + i, glyph, fontData);
- } else
- // Clear both glyph and fontData fields.
- page->setGlyphDataForIndex(offset + i, 0, 0);
- }
- return haveGlyphs;
-}
-
-// We're supposed to return true if there are any glyphs in the range
-// specified by |offset| and |length| in our font,
-// false if there are none.
-bool GlyphPage::fill(unsigned offset, unsigned length, UChar* characterBuffer,
- unsigned bufferLength, const SimpleFontData* fontData)
-{
- // We have to handle BMP and non-BMP characters differently.
- // FIXME: Add assertions to make sure that buffer is entirely in BMP
- // or entirely in non-BMP.
- if (bufferLength == length)
- return fillBMPGlyphs(offset, length, characterBuffer, this, fontData);
-
- if (bufferLength == 2 * length) {
- // A non-BMP input buffer will be twice as long as output glyph buffer
- // because each character in the non-BMP input buffer will be
- // represented by a surrogate pair (two UChar's).
- return fillNonBMPGlyphs(offset, length, characterBuffer, this, fontData);
- }
-
- ASSERT_NOT_REACHED();
- return false;
-}
-
-} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/win/SimpleFontDataWin.cpp b/chromium/third_party/WebKit/Source/platform/fonts/win/SimpleFontDataWin.cpp
deleted file mode 100644
index bc1d367140f..00000000000
--- a/chromium/third_party/WebKit/Source/platform/fonts/win/SimpleFontDataWin.cpp
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * Copyright (C) 2006, 2007 Apple Inc. All Rights Reserved.
- * Copyright (c) 2008, 2009, Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "platform/fonts/SimpleFontData.h"
-
-#include <mlang.h>
-#include <objidl.h>
-#include <unicode/uchar.h>
-#include <unicode/unorm.h>
-#include "platform/fonts/Font.h"
-#include "platform/fonts/FontCache.h"
-#include "platform/fonts/FontDescription.h"
-#include "platform/fonts/win/FontPlatformDataWin.h"
-#include "platform/geometry/FloatRect.h"
-#include "platform/win/HWndDC.h"
-#include "wtf/MathExtras.h"
-
-namespace WebCore {
-
-void SimpleFontData::platformInit()
-{
- if (!m_platformData.size()) {
- m_fontMetrics.reset();
- m_avgCharWidth = 0;
- m_maxCharWidth = 0;
- return;
- }
-
- HWndDC dc(0);
- HGDIOBJ oldFont = SelectObject(dc, m_platformData.hfont());
-
- TEXTMETRIC textMetric = {0};
- if (!GetTextMetrics(dc, &textMetric)) {
- if (FontPlatformData::ensureFontLoaded(m_platformData.hfont())) {
- // Retry GetTextMetrics.
- // FIXME: Handle gracefully the error if this call also fails.
- // See http://crbug.com/6401.
- if (!GetTextMetrics(dc, &textMetric))
- WTF_LOG_ERROR("Unable to get the text metrics after second attempt");
- }
- }
-
- m_avgCharWidth = textMetric.tmAveCharWidth;
- m_maxCharWidth = textMetric.tmMaxCharWidth;
-
- // FIXME: Access ascent/descent/lineGap with floating point precision.
- float ascent = textMetric.tmAscent;
- float descent = textMetric.tmDescent;
- float lineGap = textMetric.tmExternalLeading;
- float xHeight = ascent * 0.56f; // Best guess for xHeight for non-Truetype fonts.
-
- OUTLINETEXTMETRIC outlineTextMetric;
- if (GetOutlineTextMetrics(dc, sizeof(outlineTextMetric), &outlineTextMetric) > 0) {
- m_fontMetrics.setUnitsPerEm(outlineTextMetric.otmEMSquare);
-
- // This is a TrueType font. We might be able to get an accurate xHeight.
- GLYPHMETRICS glyphMetrics = {0};
- MAT2 identityMatrix = {{0, 1}, {0, 0}, {0, 0}, {0, 1}};
- DWORD len = GetGlyphOutlineW(dc, 'x', GGO_METRICS, &glyphMetrics, 0, 0, &identityMatrix);
- if (len != GDI_ERROR && glyphMetrics.gmBlackBoxY > 0)
- xHeight = static_cast<float>(glyphMetrics.gmBlackBoxY);
- }
-
- m_fontMetrics.setAscent(ascent);
- m_fontMetrics.setDescent(descent);
- m_fontMetrics.setLineGap(lineGap);
- m_fontMetrics.setXHeight(xHeight);
- m_fontMetrics.setLineSpacing(ascent + descent + lineGap);
-
- SelectObject(dc, oldFont);
-}
-
-void SimpleFontData::platformCharWidthInit()
-{
- // charwidths are set in platformInit.
-}
-
-void SimpleFontData::platformDestroy()
-{
-}
-
-PassRefPtr<SimpleFontData> SimpleFontData::platformCreateScaledFontData(const FontDescription& fontDescription, float scaleFactor) const
-{
- LOGFONT winFont;
- GetObject(m_platformData.hfont(), sizeof(LOGFONT), &winFont);
- float scaledSize = scaleFactor * fontDescription.computedSize();
- winFont.lfHeight = -lroundf(scaledSize);
- HFONT hfont = CreateFontIndirect(&winFont);
- return SimpleFontData::create(FontPlatformData(hfont, scaledSize, m_platformData.orientation()), isCustomFont() ? CustomFontData::create(false) : 0);
-}
-
-bool SimpleFontData::containsCharacters(const UChar* characters, int length) const
-{
- // This used to be implemented with IMLangFontLink2, but since that code has
- // been disabled, this would always return false anyway.
- return false;
-}
-
-void SimpleFontData::determinePitch()
-{
- m_treatAsFixedPitch = platformData().isFixedPitch();
-}
-
-FloatRect SimpleFontData::platformBoundsForGlyph(Glyph glyph) const
-{
- HWndDC hdc(0);
- SetGraphicsMode(hdc, GM_ADVANCED);
- HGDIOBJ oldFont = SelectObject(hdc, m_platformData.hfont());
-
- GLYPHMETRICS gdiMetrics;
- static const MAT2 identity = { 0, 1, 0, 0, 0, 0, 0, 1 };
- if (GetGlyphOutline(hdc, glyph, GGO_METRICS | GGO_GLYPH_INDEX, &gdiMetrics, 0, 0, &identity) == -1) {
- if (FontPlatformData::ensureFontLoaded(m_platformData.hfont())) {
- // Retry GetTextMetrics.
- // FIXME: Handle gracefully the error if this call also fails.
- // See http://crbug.com/6401.
- if (GetGlyphOutline(hdc, glyph, GGO_METRICS | GGO_GLYPH_INDEX, &gdiMetrics, 0, 0, &identity) == -1)
- WTF_LOG_ERROR("Unable to get the glyph metrics after second attempt");
- }
- }
-
- SelectObject(hdc, oldFont);
-
- return FloatRect(gdiMetrics.gmptGlyphOrigin.x, -gdiMetrics.gmptGlyphOrigin.y,
- gdiMetrics.gmBlackBoxX, gdiMetrics.gmBlackBoxY);
-}
-
-float SimpleFontData::platformWidthForGlyph(Glyph glyph) const
-{
- if (!m_platformData.size())
- return 0;
-
- HWndDC dc(0);
- HGDIOBJ oldFont = SelectObject(dc, m_platformData.hfont());
-
- int width = 0;
- if (!GetCharWidthI(dc, glyph, 1, 0, &width)) {
- // Ask the browser to preload the font and retry.
- if (FontPlatformData::ensureFontLoaded(m_platformData.hfont())) {
- // FIXME: Handle gracefully the error if this call also fails.
- // See http://crbug.com/6401.
- if (!GetCharWidthI(dc, glyph, 1, 0, &width))
- WTF_LOG_ERROR("Unable to get the char width after second attempt");
- }
- }
-
- SelectObject(dc, oldFont);
-
- return static_cast<float>(width);
-}
-
-} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/win/UniscribeHelper.cpp b/chromium/third_party/WebKit/Source/platform/fonts/win/UniscribeHelper.cpp
deleted file mode 100644
index f65ab128408..00000000000
--- a/chromium/third_party/WebKit/Source/platform/fonts/win/UniscribeHelper.cpp
+++ /dev/null
@@ -1,1208 +0,0 @@
-/*
- * Copyright (c) 2006, 2007, 2008, 2009, 2012 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "platform/fonts/win/UniscribeHelper.h"
-
-#include "platform/fonts/Font.h"
-#include "platform/fonts/skia/SkiaFontWin.h"
-#include "platform/fonts/FontFallbackWin.h"
-#include "platform/graphics/GraphicsContext.h"
-#include "platform/win/HWndDC.h"
-#include "third_party/skia/include/core/SkPoint.h"
-#include "wtf/Assertions.h"
-
-namespace WebCore {
-
-// The function types for ScriptItemizeOpenType() and ScriptShapeOpenType().
-// We want to use these functions for OpenType feature support, but we can't
-// call them directly because usp10.dll does not always have them.
-// Instead, we use GetProcAddress() to check whether we can actually use these
-// function. If we can't use these functions, we substitute ScriptItemze() and
-// ScriptShape().
-typedef HRESULT (WINAPI *ScriptItemizeOpenTypeFunc)(const WCHAR*, int, int,
- const SCRIPT_CONTROL*,
- const SCRIPT_STATE*,
- SCRIPT_ITEM*,
- OPENTYPE_TAG*, int*);
-typedef HRESULT (WINAPI *ScriptShapeOpenTypeFunc)(HDC, SCRIPT_CACHE*,
- SCRIPT_ANALYSIS*,
- OPENTYPE_TAG, OPENTYPE_TAG,
- int*, TEXTRANGE_PROPERTIES**,
- int, const WCHAR*, int, int,
- WORD*, SCRIPT_CHARPROP*,
- WORD*, SCRIPT_GLYPHPROP*,
- int*);
-
-static ScriptItemizeOpenTypeFunc gScriptItemizeOpenTypeFunc = 0;
-static ScriptShapeOpenTypeFunc gScriptShapeOpenTypeFunc = 0;
-static bool gOpenTypeFunctionsLoaded = false;
-
-static void loadOpenTypeFunctions()
-{
- HMODULE hModule = GetModuleHandle(L"usp10");
- if (hModule) {
- gScriptItemizeOpenTypeFunc = reinterpret_cast<ScriptItemizeOpenTypeFunc>(GetProcAddress(hModule, "ScriptItemizeOpenType"));
- gScriptShapeOpenTypeFunc = reinterpret_cast<ScriptShapeOpenTypeFunc>(GetProcAddress(hModule, "ScriptShapeOpenType"));
- }
- if (!gScriptItemizeOpenTypeFunc || !gScriptShapeOpenTypeFunc) {
- gScriptItemizeOpenTypeFunc = 0;
- gScriptShapeOpenTypeFunc = 0;
- }
- gOpenTypeFunctionsLoaded = true;
-}
-
-enum {
- FontStyleNormal = 0,
- FontStyleBold = 1,
- FontStyleItalic = 2,
- FontStyleUnderlined = 4
-};
-
-int getStyleFromLogfont(const LOGFONT* logfont)
-{
- // FIXME: consider defining UNDEFINED or INVALID for style and
- // returning it when logfont is 0
- if (!logfont) {
- ASSERT_NOT_REACHED();
- return FontStyleNormal;
- }
- return (logfont->lfItalic ? FontStyleItalic : FontStyleNormal) |
- (logfont->lfUnderline ? FontStyleUnderlined : FontStyleNormal) |
- (logfont->lfWeight >= 700 ? FontStyleBold : FontStyleNormal);
-}
-
-
-// HFONT is the 'incarnation' of 'everything' about font, but it's an opaque
-// handle and we can't directly query it to make a new HFONT sharing
-// its characteristics (height, style, etc) except for family name.
-// This function uses GetObject to convert HFONT back to LOGFONT,
-// resets the fields of LOGFONT and calculates style to use later
-// for the creation of a font identical to HFONT other than family name.
-static void setLogFontAndStyle(HFONT hfont, LOGFONT *logfont, int *style)
-{
- ASSERT(hfont && logfont);
- if (!hfont || !logfont)
- return;
-
- GetObject(hfont, sizeof(LOGFONT), logfont);
- // We reset these fields to values appropriate for CreateFontIndirect.
- // while keeping lfHeight, which is the most important value in creating
- // a new font similar to hfont.
- logfont->lfWidth = 0;
- logfont->lfEscapement = 0;
- logfont->lfOrientation = 0;
- logfont->lfCharSet = DEFAULT_CHARSET;
- logfont->lfOutPrecision = OUT_TT_ONLY_PRECIS;
- logfont->lfQuality = DEFAULT_QUALITY; // Honor user's desktop settings.
- logfont->lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
- if (style)
- *style = getStyleFromLogfont(logfont);
-}
-
-// This memory DC will NOT be released but it's OK
-// since we want to keep it for the whole life span of the process.
-HDC UniscribeHelper::m_cachedDC = 0;
-
-static bool canUseGlyphIndex(const SCRIPT_ITEM& run)
-{
- // On early version of Uniscribe, ScriptShape() sets run.a.fNoGlyphIndex
- // to TRUE when it can't shape the run with glyph indexes. This could
- // occur when we use CFF webfonts(See http://crbug.com/39017).
- // We don't use the font in that case and try to use fallback fonts.
- return !run.a.fNoGlyphIndex;
-}
-
-UniscribeHelper::UniscribeHelper(const UChar* input,
- int inputLength,
- bool isRtl,
- HFONT hfont,
- SCRIPT_CACHE* scriptCache,
- SCRIPT_FONTPROPERTIES* fontProperties,
- WORD spaceGlyph)
- : m_input(input)
- , m_inputLength(inputLength)
- , m_isRtl(isRtl)
- , m_hfont(hfont)
- , m_scriptCache(scriptCache)
- , m_fontProperties(fontProperties)
- , m_spaceGlyph(spaceGlyph)
- , m_directionalOverride(false)
- , m_inhibitLigate(false)
- , m_letterSpacing(0)
- , m_spaceWidth(0)
- , m_wordSpacing(0)
- , m_ascent(0)
- , m_disableFontFallback(false)
-
-{
- m_logfont.lfFaceName[0] = 0;
- if (!gOpenTypeFunctionsLoaded)
- loadOpenTypeFunctions();
-}
-
-UniscribeHelper::~UniscribeHelper()
-{
-}
-
-void UniscribeHelper::initWithOptionalLengthProtection(bool lengthProtection)
-{
- // We cap the input length and just don't do anything. We'll allocate a lot
- // of things of the size of the number of characters, so the allocated
- // memory will be several times the input length. Plus shaping such a large
- // buffer may be a form of denial of service. No legitimate text should be
- // this long. It also appears that Uniscribe flatly rejects very long
- // strings, so we don't lose anything by doing this.
- //
- // The input length protection may be disabled by the unit tests to cause
- // an error condition.
- static const int kMaxInputLength = 65535;
- if (m_inputLength == 0 || (lengthProtection && m_inputLength > kMaxInputLength))
- return;
-
- fillRuns();
- fillShapes();
- fillScreenOrder();
-}
-
-int UniscribeHelper::width() const
-{
- int width = 0;
- for (int itemIndex = 0; itemIndex < static_cast<int>(m_runs.size()); itemIndex++)
- width += advanceForItem(itemIndex);
- return width;
-}
-
-void UniscribeHelper::justify(int additionalSpace)
-{
- // Count the total number of glyphs we have so we know how big to make the
- // buffers below.
- int totalGlyphs = 0;
- for (size_t run = 0; run < m_runs.size(); run++) {
- int runIndex = m_screenOrder[run];
- totalGlyphs += static_cast<int>(m_shapes[runIndex].glyphLength());
- }
- if (totalGlyphs == 0)
- return; // Nothing to do.
-
- // We make one big buffer in screen order of all the glyphs we are drawing
- // across runs so that the justification function will adjust evenly across
- // all glyphs.
- Vector<SCRIPT_VISATTR, 64> visualAttributes;
- visualAttributes.resize(totalGlyphs);
- Vector<int, 64> advances;
- advances.resize(totalGlyphs);
- Vector<int, 64> justify;
- justify.resize(totalGlyphs);
-
- // Build the packed input.
- int destIndex = 0;
- for (size_t run = 0; run < m_runs.size(); run++) {
- int runIndex = m_screenOrder[run];
- const Shaping& shaping = m_shapes[runIndex];
-
- for (int i = 0; i < shaping.glyphLength(); i++, destIndex++) {
- memcpy(&visualAttributes[destIndex], &shaping.m_visualAttributes[i],
- sizeof(SCRIPT_VISATTR));
- advances[destIndex] = shaping.m_advance[i];
- }
- }
-
- // The documentation for Scriptjustify is wrong, the parameter is the space
- // to add and not the width of the column you want.
- int minKashida;
- // Disable kashida justification based on
- // http://blogs.msdn.com/b/michkap/archive/2010/08/31/10056140.aspx.
- for (int i = 0; i < totalGlyphs; ++i) {
- if (visualAttributes[i].uJustification == SCRIPT_JUSTIFY_ARABIC_KASHIDA)
- visualAttributes[i].uJustification = SCRIPT_JUSTIFY_NONE;
- }
- minKashida = 0;
- ScriptJustify(&visualAttributes[0], &advances[0], totalGlyphs,
- additionalSpace, minKashida, &justify[0]);
-
- // Now we have to unpack the justification amounts back into the runs so
- // the glyph indices match.
- int globalGlyphIndex = 0;
- for (size_t run = 0; run < m_runs.size(); run++) {
- int runIndex = m_screenOrder[run];
- Shaping& shaping = m_shapes[runIndex];
-
- shaping.m_justify.resize(shaping.glyphLength());
- for (int i = 0; i < shaping.glyphLength(); i++, globalGlyphIndex++)
- shaping.m_justify[i] = justify[globalGlyphIndex];
- }
-}
-
-int UniscribeHelper::characterToX(int offset) const
-{
- HRESULT hr;
- ASSERT(offset <= m_inputLength);
-
- // Our algorithm is to traverse the items in screen order from left to
- // right, adding in each item's screen width until we find the item with
- // the requested character in it.
- int width = 0;
- for (size_t screenIndex = 0; screenIndex < m_runs.size(); screenIndex++) {
- // Compute the length of this run.
- int itemIndex = m_screenOrder[screenIndex];
- const SCRIPT_ITEM& item = m_runs[itemIndex];
- const Shaping& shaping = m_shapes[itemIndex];
- int itemLength = shaping.charLength();
-
- if (offset >= item.iCharPos && offset <= item.iCharPos + itemLength) {
- // Character offset is in this run.
- int charLength = offset - item.iCharPos;
-
- int curX = 0;
- hr = ScriptCPtoX(charLength, FALSE, itemLength,
- shaping.glyphLength(),
- &shaping.m_logs[0], &shaping.m_visualAttributes[0],
- shaping.effectiveAdvances(), &item.a, &curX);
- if (FAILED(hr))
- return 0;
-
- width += curX + shaping.m_prePadding;
- ASSERT(width >= 0);
- return width;
- }
-
- // Move to the next item.
- width += advanceForItem(itemIndex);
- }
- ASSERT(width >= 0);
- return width;
-}
-
-int UniscribeHelper::xToCharacter(int x) const
-{
- // We iterate in screen order until we find the item with the given pixel
- // position in it. When we find that guy, we ask Uniscribe for the
- // character index.
- HRESULT hr;
- for (size_t screenIndex = 0; screenIndex < m_runs.size(); screenIndex++) {
- int itemIndex = m_screenOrder[screenIndex];
- int itemAdvance = advanceForItem(itemIndex);
-
- // Note that the run may be empty if shaping failed, so we want to skip
- // over it.
- const Shaping& shaping = m_shapes[itemIndex];
- int itemLength = shaping.charLength();
- if (x <= itemAdvance && itemLength > 0) {
- // The requested offset is within this item.
- const SCRIPT_ITEM& item = m_runs[itemIndex];
-
- // Account for the leading space we've added to this run that
- // Uniscribe doesn't know about.
- x -= shaping.m_prePadding;
-
- int charX = 0;
- int trailing;
- hr = ScriptXtoCP(x, itemLength, shaping.glyphLength(),
- &shaping.m_logs[0], &shaping.m_visualAttributes[0],
- shaping.effectiveAdvances(), &item.a, &charX,
- &trailing);
-
- // The character offset is within the item. We need to add the
- // item's offset to transform it into the space of the TextRun
- return charX + item.iCharPos;
- }
-
- // The offset is beyond this item, account for its length and move on.
- x -= itemAdvance;
- }
-
- // Error condition, we don't know what to do if we don't have that X
- // position in any of our items.
- return 0;
-}
-
-void UniscribeHelper::draw(GraphicsContext* graphicsContext,
- const FontPlatformData& fontPlatformData, HDC dc, int x, int y,
- const FloatRect& textRect, int from, int to)
-{
- HGDIOBJ oldFont = 0;
- int curX = x;
- bool firstRun = true;
-
- for (size_t screenIndex = 0; screenIndex < m_runs.size(); screenIndex++) {
- int itemIndex = m_screenOrder[screenIndex];
- const SCRIPT_ITEM& item = m_runs[itemIndex];
- const Shaping& shaping = m_shapes[itemIndex];
-
- // Character offsets within this run. THESE MAY NOT BE IN RANGE and may
- // be negative, etc. The code below handles this.
- int fromChar = from - item.iCharPos;
- int toChar = to - item.iCharPos;
-
- // See if we need to draw any characters in this item.
- if (shaping.charLength() == 0 ||
- fromChar >= shaping.charLength() || toChar <= 0) {
- // No chars in this item to display.
- curX += advanceForItem(itemIndex);
- continue;
- }
-
- // Compute the starting glyph within this span. |from| and |to| are
- // global offsets that may intersect arbitrarily with our local run.
- int fromGlyph, afterGlyph;
- if (item.a.fRTL) {
- // To compute the first glyph when going RTL, we use |to|.
- if (toChar >= shaping.charLength())
- // The end of the text is after (to the left) of us.
- fromGlyph = 0;
- else {
- // Since |to| is exclusive, the first character we draw on the
- // left is actually the one right before (to the right) of
- // |to|.
- fromGlyph = shaping.m_logs[toChar - 1];
- }
-
- // The last glyph is actually the first character in the range.
- if (fromChar <= 0) {
- // The first character to draw is before (to the right) of this
- // span, so draw all the way to the end.
- afterGlyph = shaping.glyphLength();
- } else {
- // We want to draw everything up until the character to the
- // right of |from|. To the right is - 1, so we look that up
- // (remember our character could be more than one glyph, so we
- // can't look up our glyph and add one).
- afterGlyph = shaping.m_logs[fromChar - 1];
- }
- } else {
- // Easy case, everybody agrees about directions. We only need to
- // handle boundary conditions to get a range inclusive at the
- // beginning, and exclusive at the ending. We have to do some
- // computation to see the glyph one past the end.
- fromGlyph = shaping.m_logs[fromChar < 0 ? 0 : fromChar];
- if (toChar >= shaping.charLength())
- afterGlyph = shaping.glyphLength();
- else
- afterGlyph = shaping.m_logs[toChar];
- }
-
- // Account for the characters that were skipped in this run. When
- // WebKit asks us to draw a subset of the run, it actually tells us
- // to draw at the X offset of the beginning of the run, since it
- // doesn't know the internal position of any of our characters.
- const int* effectiveAdvances = shaping.effectiveAdvances();
- int innerOffset = 0;
- for (int i = 0; i < fromGlyph; i++)
- innerOffset += effectiveAdvances[i];
-
- // Actually draw the glyphs we found.
- int glyphCount = afterGlyph - fromGlyph;
- if (fromGlyph >= 0 && glyphCount > 0) {
- // Account for the preceding space we need to add to this run. We
- // don't need to count for the following space because that will be
- // counted in advanceForItem below when we move to the next run.
- innerOffset += shaping.m_prePadding;
-
- // Pass 0 in when there is no justification.
- const int* justify = shaping.m_justify.size() == 0 ? 0 : &shaping.m_justify[fromGlyph];
-
- const int* advances = shaping.m_justify.size() ?
- &shaping.m_justify[fromGlyph]
- : &shaping.m_advance[fromGlyph];
-
- // Fonts with different ascents can be used to render different
- // runs. 'Across-runs' y-coordinate correction needs to be
- // adjusted for each font.
- bool textOutOk = false;
- for (int executions = 0; executions < 2; ++executions) {
- SkPoint origin;
- origin.fX = curX + + innerOffset;
- origin.fY = y + m_ascent;
- paintSkiaText(graphicsContext,
- fontPlatformData,
- shaping.m_hfont,
- glyphCount,
- &shaping.m_glyphs[fromGlyph],
- advances,
- &shaping.m_offsets[fromGlyph],
- origin,
- textRect);
- textOutOk = true;
-
- if (!textOutOk && 0 == executions) {
- // If TextOut is called from the renderer it might fail
- // because the sandbox is preventing it from opening the
- // font files. If we are running in the renderer,
- // TryToPreloadFont is overridden to ask the browser to
- // preload the font for us so we can access it.
- tryToPreloadFont(shaping.m_hfont);
- continue;
- }
- break;
- }
- }
-
- curX += advanceForItem(itemIndex);
- }
-
- if (oldFont)
- SelectObject(dc, oldFont);
-}
-
-WORD UniscribeHelper::firstGlyphForCharacter(int charOffset) const
-{
- // Find the run for the given character.
- for (int i = 0; i < static_cast<int>(m_runs.size()); i++) {
- int firstChar = m_runs[i].iCharPos;
- const Shaping& shaping = m_shapes[i];
- int localOffset = charOffset - firstChar;
- if (localOffset >= 0 && localOffset < shaping.charLength()) {
- // The character is in this run, return the first glyph for it
- // (should generally be the only glyph). It seems Uniscribe gives
- // glyph 0 for empty, which is what we want to return in the
- // "missing" case.
- size_t glyphIndex = shaping.m_logs[localOffset];
- if (glyphIndex >= shaping.m_glyphs.size()) {
- // The glyph should be in this run, but the run has too few
- // actual characters. This can happen when shaping the run
- // fails, in which case, we should have no data in the logs at
- // all.
- ASSERT(shaping.m_glyphs.size() == 0);
- return 0;
- }
- return shaping.m_glyphs[glyphIndex];
- }
- }
-
- return 0;
-}
-
-void UniscribeHelper::fillRuns()
-{
- HRESULT hr;
- m_runs.resize(cUniscribeHelperStackRuns);
- m_scriptTags.resize(cUniscribeHelperStackRuns);
-
- SCRIPT_STATE inputState;
- inputState.uBidiLevel = m_isRtl;
- inputState.fOverrideDirection = m_directionalOverride;
- inputState.fInhibitSymSwap = false;
- inputState.fCharShape = false; // Not implemented in Uniscribe
- inputState.fDigitSubstitute = false; // Do we want this for Arabic?
- inputState.fInhibitLigate = m_inhibitLigate;
- inputState.fDisplayZWG = false; // Don't draw control characters.
- inputState.fArabicNumContext = m_isRtl; // Do we want this for Arabic?
- inputState.fGcpClusters = false;
- inputState.fReserved = 0;
- inputState.fEngineReserved = 0;
- // The psControl argument to ScriptItemize should be non-0 for RTL text,
- // per http://msdn.microsoft.com/en-us/library/ms776532.aspx . So use a
- // SCRIPT_CONTROL that is set to all zeros. Zero as a locale ID means the
- // neutral locale per http://msdn.microsoft.com/en-us/library/ms776294.aspx
- static SCRIPT_CONTROL inputControl = {0, // uDefaultLanguage :16;
- 0, // fContextDigits :1;
- 0, // fInvertPreBoundDir :1;
- 0, // fInvertPostBoundDir :1;
- 0, // fLinkStringBefore :1;
- 0, // fLinkStringAfter :1;
- 0, // fNeutralOverride :1;
- 0, // fNumericOverride :1;
- 0, // fLegacyBidiClass :1;
- 0, // fMergeNeutralItems :1;
- 0};// fReserved :7;
- // Calling ScriptApplyDigitSubstitution( 0, &inputControl, &inputState)
- // here would be appropriate if we wanted to set the language ID, and get
- // local digit substitution behavior. For now, don't do it.
-
- while (true) {
- int numberOfItems = 0;
-
- // Ideally, we would have a way to know the runs before and after this
- // one, and put them into the control parameter of ScriptItemize. This
- // would allow us to shape characters properly that cross style
- // boundaries (WebKit bug 6148).
- //
- // We tell ScriptItemize that the output list of items is one smaller
- // than it actually is. According to Mozilla bug 366643, if there is
- // not enough room in the array on pre-SP2 systems, ScriptItemize will
- // write one past the end of the buffer.
- //
- // ScriptItemize is very strange. It will often require a much larger
- // ITEM buffer internally than it will give us as output. For example,
- // it will say a 16-item buffer is not big enough, and will write
- // interesting numbers into all those items. But when we give it a 32
- // item buffer and it succeeds, it only has one item output.
- //
- // It seems to be doing at least two passes, the first where it puts a
- // lot of intermediate data into our items, and the second where it
- // collates them.
- if (gScriptItemizeOpenTypeFunc) {
- hr = gScriptItemizeOpenTypeFunc(m_input, m_inputLength,
- static_cast<int>(m_runs.size()) - 1,
- &inputControl, &inputState,
- &m_runs[0], &m_scriptTags[0],
- &numberOfItems);
-
- if (SUCCEEDED(hr)) {
- // Pack consecutive runs, the script tag of which are
- // SCRIPT_TAG_UNKNOWN, to reduce the number of runs.
- for (int i = 0; i < numberOfItems; ++i) {
- // Do not pack with whitespace characters at the head.
- // Otherwise whole the run is rendered as a whitespace.
- WCHAR ch = m_input[m_runs[i].iCharPos];
- if (m_scriptTags[i] == SCRIPT_TAG_UNKNOWN && !Font::treatAsSpace(ch) && !Font::treatAsZeroWidthSpace(ch)) {
- int j = 1;
- while (i + j < numberOfItems && m_scriptTags[i + j] == SCRIPT_TAG_UNKNOWN)
- ++j;
- if (--j) {
- m_runs.remove(i + 1, j);
- m_scriptTags.remove(i + 1, j);
- numberOfItems -= j;
- }
- }
- }
- m_scriptTags.resize(numberOfItems);
- }
- } else {
- hr = ScriptItemize(m_input, m_inputLength,
- static_cast<int>(m_runs.size()) - 1,
- &inputControl, &inputState, &m_runs[0],
- &numberOfItems);
- }
- if (SUCCEEDED(hr)) {
- m_runs.resize(numberOfItems);
- break;
- }
- if (hr != E_OUTOFMEMORY) {
- // Some kind of unexpected error.
- m_runs.resize(0);
- break;
- }
- // There was not enough items for it to write into, expand.
- m_runs.resize(m_runs.size() * 2);
- m_scriptTags.resize(m_runs.size());
- }
-}
-
-const int kUndefinedAscent = std::numeric_limits<int>::min();
-
-// Given an HFONT, return the ascent. If GetTextMetrics fails,
-// kUndefinedAscent is returned, instead.
-int getAscent(HFONT hfont)
-{
- HWndDC dc(0);
- HGDIOBJ oldFont = SelectObject(dc, hfont);
- TEXTMETRIC tm;
- BOOL gotMetrics = GetTextMetrics(dc, &tm);
- SelectObject(dc, oldFont);
- return gotMetrics ? tm.tmAscent : kUndefinedAscent;
-}
-
-const WORD kUnsupportedGlyph = 0xffff;
-
-WORD getSpaceGlyph(HFONT hfont)
-{
- HWndDC dc(0);
- HGDIOBJ oldFont = SelectObject(dc, hfont);
- WCHAR space = L' ';
- WORD spaceGlyph = kUnsupportedGlyph;
- GetGlyphIndices(dc, &space, 1, &spaceGlyph, GGI_MARK_NONEXISTING_GLYPHS);
- SelectObject(dc, oldFont);
- return spaceGlyph;
-}
-
-struct ShaperFontData {
- ShaperFontData()
- : hfont(0)
- , ascent(kUndefinedAscent)
- , scriptCache(0)
- , spaceGlyph(0)
- {
- }
-
- HFONT hfont;
- int ascent;
- mutable SCRIPT_CACHE scriptCache;
- WORD spaceGlyph;
-};
-
-// Again, using hash_map does not earn us much here. page_cycler_test intl2
-// gave us a 'better' result with map than with hash_map even though they're
-// well-within 1-sigma of each other so that the difference is not significant.
-// On the other hand, some pages in intl2 seem to take longer to load with map
-// in the 1st pass. Need to experiment further.
-typedef HashMap<String, ShaperFontData> ShaperFontDataCache;
-
-// Derive a new HFONT by replacing lfFaceName of LOGFONT with |family|,
-// calculate the ascent for the derived HFONT, and initialize SCRIPT_CACHE
-// in ShaperFontData.
-// |style| is only used for cache key generation. |style| is
-// bit-wise OR of BOLD(1), UNDERLINED(2) and ITALIC(4) and
-// should match what's contained in LOGFONT. It should be calculated
-// by calling GetStyleFromLogFont.
-// Returns false if the font is not accessible, in which case |ascent| field
-// of |ShaperFontData| is set to kUndefinedAscent.
-// Be aware that this is not thread-safe.
-// FIXME: Instead of having three out params, we'd better have one
-// (|*ShaperFontData|), but somehow it mysteriously messes up the layout for
-// certain complex script pages (e.g. hi.wikipedia.org) and also crashes
-// at the start-up if recently visited page list includes pages with complex
-// scripts in their title. Moreover, somehow the very first-pass of
-// intl2 page-cycler test is noticeably slower with one out param than
-// the current version although the subsequent 9 passes take about the
-// same time.
-// Be aware that this is not thread-safe.
-static bool getDerivedFontData(const UChar* family, int style, LOGFONT* logfont,
- int* ascent, HFONT* hfont, SCRIPT_CACHE** scriptCache, WORD* spaceGlyph)
-{
- ASSERT(logfont);
- ASSERT(family);
- ASSERT(*family);
-
- // It does not matter that we leak font data when we exit.
- static ShaperFontDataCache* gFontDataCache = 0;
- if (!gFontDataCache)
- gFontDataCache = new ShaperFontDataCache();
-
- // FIXME: This comes up pretty high in the profile so that
- // we need to measure whether using SHA256 (after coercing all the
- // fields to char*) is faster than String::format.
- String fontKey = String::format("%1d:%d:%ls", style, logfont->lfHeight, family);
- ShaperFontDataCache::iterator iter = gFontDataCache->find(fontKey);
- ShaperFontData* derived;
- if (iter == gFontDataCache->end()) {
- ASSERT(wcslen(family) < LF_FACESIZE);
- wcscpy_s(logfont->lfFaceName, LF_FACESIZE, family);
- // FIXME: CreateFontIndirect always comes up with
- // a font even if there's no font matching the name. Need to
- // check it against what we actually want (as is done in
- // FontCacheWin.cpp)
- ShaperFontDataCache::AddResult entry = gFontDataCache->add(fontKey, ShaperFontData());
- derived = &entry.iterator->value;
- derived->hfont = CreateFontIndirect(logfont);
- // GetAscent may return kUndefinedAscent, but we still want to
- // cache it so that we won't have to call CreateFontIndirect once
- // more for HFONT next time.
- derived->ascent = getAscent(derived->hfont);
- derived->spaceGlyph = getSpaceGlyph(derived->hfont);
- } else {
- derived = &iter->value;
- // Last time, getAscent or getSpaceGlyph failed so that only HFONT was
- // cached. Try once more assuming that TryPreloadFont
- // was called by a caller between calls.
- if (kUndefinedAscent == derived->ascent)
- derived->ascent = getAscent(derived->hfont);
- if (kUnsupportedGlyph == derived->spaceGlyph)
- derived->spaceGlyph = getSpaceGlyph(derived->hfont);
- }
- *hfont = derived->hfont;
- *ascent = derived->ascent;
- *scriptCache = &(derived->scriptCache);
- *spaceGlyph = derived->spaceGlyph;
- return *ascent != kUndefinedAscent && *spaceGlyph != kUnsupportedGlyph;
-}
-
-bool UniscribeHelper::shape(const UChar* input,
- int itemLength,
- int numGlyphs,
- SCRIPT_ITEM& run,
- OPENTYPE_TAG scriptTag,
- Shaping& shaping)
-{
- HFONT hfont = m_hfont;
- SCRIPT_CACHE* scriptCache = m_scriptCache;
- SCRIPT_FONTPROPERTIES* fontProperties = m_fontProperties;
- Vector<SCRIPT_CHARPROP, cUniscribeHelperStackChars> charProps;
- Vector<SCRIPT_GLYPHPROP, cUniscribeHelperStackChars> glyphProps;
- int ascent = m_ascent;
- WORD spaceGlyph = m_spaceGlyph;
- HRESULT hr;
- // When used to fill up glyph pages for simple scripts in non-BMP,
- // we don't want any font fallback in this class. The simple script
- // font path can take care of font fallback.
- bool lastFallbackTried = m_disableFontFallback;
- bool result;
-
- int generatedGlyphs = 0;
-
- // In case HFONT passed in ctor cannot render this run, we have to scan
- // other fonts from the beginning of the font list.
- resetFontIndex();
-
- // Compute shapes.
- while (true) {
- shaping.m_logs.resize(itemLength);
- shaping.m_glyphs.resize(numGlyphs);
- shaping.m_visualAttributes.resize(numGlyphs);
- charProps.resize(itemLength);
- glyphProps.resize(numGlyphs);
- run.a.fNoGlyphIndex = FALSE;
-
-#ifdef PURIFY
- // http://code.google.com/p/chromium/issues/detail?id=5309
- // Purify isn't able to track the assignments that ScriptShape makes to
- // shaping.m_glyphs. Consequently, any bytes with value 0xCD that it
- // writes, will be considered un-initialized data.
- //
- // This hack avoid the false-positive UMRs by marking the buffer as
- // initialized.
- //
- // FIXME: A better solution would be to use Purify's API and mark only
- // the populated range as initialized:
- //
- // PurifyMarkAsInitialized(
- // &shaping.m_glyphs[0],
- // sizeof(shaping.m_glyphs[0] * generatedGlyphs);
-
- ZeroMemory(&shaping.m_glyphs[0],
- sizeof(shaping.m_glyphs[0]) * shaping.m_glyphs.size());
-#endif
- // If our DC is already created, select the font in it so we can use it now.
- // Otherwise, we'll create it as needed afterward...
- if (m_cachedDC)
- SelectObject(m_cachedDC, hfont);
-
- // Firefox sets SCRIPT_ANALYSIS.SCRIPT_STATE.fDisplayZWG to true
- // here. Is that what we want? It will display control characters.
- if (gScriptShapeOpenTypeFunc) {
- TEXTRANGE_PROPERTIES* rangeProps = m_featureRecords.size() ? &m_rangeProperties : 0;
- hr = gScriptShapeOpenTypeFunc(m_cachedDC, scriptCache, &run.a,
- scriptTag, 0, &itemLength,
- &rangeProps, rangeProps ? 1 : 0,
- input, itemLength, numGlyphs,
- &shaping.m_logs[0], &charProps[0],
- &shaping.m_glyphs[0], &glyphProps[0],
- &generatedGlyphs);
- if (SUCCEEDED(hr)) {
- // If we use ScriptShapeOpenType(), visual attributes
- // information for each characters are stored in
- // |glyphProps[i].sva|.
- for (int i = 0; i < generatedGlyphs; ++i)
- memcpy(&shaping.m_visualAttributes[i], &glyphProps[i].sva, sizeof(SCRIPT_VISATTR));
- }
- } else {
- hr = ScriptShape(m_cachedDC, scriptCache, input, itemLength,
- numGlyphs, &run.a,
- &shaping.m_glyphs[0], &shaping.m_logs[0],
- &shaping.m_visualAttributes[0], &generatedGlyphs);
- }
- // We receive E_PENDING when we need to try again with a Drawing Context,
- // but we don't want to retry again if we already tried with non-zero DC.
- if (hr == E_PENDING && !m_cachedDC) {
- EnsureCachedDCCreated();
- continue;
- }
- if (hr == E_OUTOFMEMORY) {
- numGlyphs *= 2;
- continue;
- }
- if (SUCCEEDED(hr) && (lastFallbackTried || !containsMissingGlyphs(shaping, run, fontProperties) && canUseGlyphIndex(run)))
- break;
-
- // The current font can't render this run, try next font.
- if (!m_disableFontFallback &&
- nextWinFontData(hfont, scriptCache, fontProperties, ascent, spaceGlyph)) {
- // The primary font does not support this run. Try next font.
- // In case of web page rendering, they come from fonts specified in
- // CSS stylesheets.
- continue;
- } else if (!lastFallbackTried) {
- lastFallbackTried = true;
-
- // Generate a last fallback font based on the script of
- // a character to draw while inheriting size and styles
- // from the primary font
- if (!m_logfont.lfFaceName[0])
- setLogFontAndStyle(m_hfont, &m_logfont, &m_style);
-
- // TODO(jungshik): generic type should come from webkit for
- // UniscribeHelperTextRun (a derived class used in webkit).
- const UChar *family = getFallbackFamilyForFirstNonCommonCharacter(input, itemLength,
- FontDescription::StandardFamily);
- bool fontOk = getDerivedFontData(family, m_style, &m_logfont,
- &ascent, &hfont, &scriptCache,
- &spaceGlyph);
-
-
- if (!fontOk) {
- // If this GetDerivedFontData is called from the renderer it
- // might fail because the sandbox is preventing it from opening
- // the font files. If we are running in the renderer,
- // TryToPreloadFont is overridden to ask the browser to preload
- // the font for us so we can access it.
- tryToPreloadFont(hfont);
-
- // Try again.
- fontOk = getDerivedFontData(family, m_style, &m_logfont,
- &ascent, &hfont, &scriptCache,
- &spaceGlyph);
- ASSERT(fontOk);
- }
-
- // TODO(jungshik) : Currently GetDerivedHFont always returns a
- // a valid HFONT, but in the future, I may change it to return 0.
- ASSERT(hfont);
-
- // We don't need a font_properties for the last resort fallback font
- // because we don't have anything more to try and are forced to
- // accept empty glyph boxes. If we tried a series of fonts as
- // 'last-resort fallback', we'd need it, but currently, we don't.
- continue;
- } else if (hr == USP_E_SCRIPT_NOT_IN_FONT) {
- run.a.eScript = SCRIPT_UNDEFINED;
- continue;
- } else if (FAILED(hr)) {
- // Error shaping.
- generatedGlyphs = 0;
- result = false;
- goto cleanup;
- }
- }
-
- // Sets Windows font data for this run to those corresponding to
- // a font supporting this run. we don't need to store font_properties
- // because it's not used elsewhere.
- shaping.m_hfont = hfont;
- shaping.m_scriptCache = scriptCache;
- shaping.m_spaceGlyph = spaceGlyph;
-
- // The ascent of a font for this run can be different from
- // that of the primary font so that we need to keep track of
- // the difference per run and take that into account when calling
- // ScriptTextOut in |draw|. Otherwise, different runs rendered by
- // different fonts would not be aligned vertically.
- shaping.m_ascentOffset = m_ascent ? ascent - m_ascent : 0;
- result = true;
-
- cleanup:
- shaping.m_glyphs.resize(generatedGlyphs);
- shaping.m_visualAttributes.resize(generatedGlyphs);
- shaping.m_advance.resize(generatedGlyphs);
- shaping.m_offsets.resize(generatedGlyphs);
-
- // On failure, our logs don't mean anything, so zero those out.
- if (!result)
- shaping.m_logs.clear();
-
- return result;
-}
-
-void UniscribeHelper::EnsureCachedDCCreated()
-{
- if (m_cachedDC)
- return;
- // Allocate a memory DC that is compatible with the Desktop DC since we don't have any window,
- // and we don't want to use the Desktop DC directly since it can have nasty side effects
- // as identified in Chrome Issue http://crbug.com/59315.
- HWndDC screenDC(0);
- m_cachedDC = ::CreateCompatibleDC(screenDC);
- ASSERT(m_cachedDC);
-}
-
-void UniscribeHelper::fillShapes()
-{
- m_shapes.resize(m_runs.size());
- for (size_t i = 0; i < m_runs.size(); i++) {
- int startItem = m_runs[i].iCharPos;
- int itemLength = m_inputLength - startItem;
- if (i < m_runs.size() - 1)
- itemLength = m_runs[i + 1].iCharPos - startItem;
-
- int numGlyphs;
- if (itemLength < cUniscribeHelperStackChars) {
- // We'll start our buffer sizes with the current stack space
- // available in our buffers if the current input fits. As long as
- // it doesn't expand past that we'll save a lot of time mallocing.
- numGlyphs = cUniscribeHelperStackChars;
- } else {
- // When the input doesn't fit, give up with the stack since it will
- // almost surely not be enough room (unless the input actually
- // shrinks, which is unlikely) and just start with the length
- // recommended by the Uniscribe documentation as a "usually fits"
- // size.
- numGlyphs = itemLength * 3 / 2 + 16;
- }
-
- // Convert a string to a glyph string trying the primary font, fonts in
- // the fallback list and then script-specific last resort font.
- Shaping& shaping = m_shapes[i];
- if (!shape(&m_input[startItem], itemLength, numGlyphs, m_runs[i], m_scriptTags[i], shaping))
- continue;
-
- // At the moment, the only time m_disableFontFallback is set is
- // when we look up glyph indices for non-BMP code ranges. So,
- // we can skip the glyph placement. When that becomes not the case
- // any more, we have to add a new flag to control glyph placement.
- if (m_disableFontFallback)
- continue;
-
- // Compute placements. Note that offsets is documented incorrectly
- // and is actually an array.
- EnsureCachedDCCreated();
- SelectObject(m_cachedDC, shaping.m_hfont);
- shaping.m_prePadding = 0;
- if (FAILED(ScriptPlace(m_cachedDC, shaping.m_scriptCache,
- &shaping.m_glyphs[0],
- static_cast<int>(shaping.m_glyphs.size()),
- &shaping.m_visualAttributes[0], &m_runs[i].a,
- &shaping.m_advance[0], &shaping.m_offsets[0],
- &shaping.m_abc))) {
- // Some error we don't know how to handle. Nuke all of our data
- // since we can't deal with partially valid data later.
- m_runs.clear();
- m_scriptTags.clear();
- m_shapes.clear();
- m_screenOrder.clear();
- }
- }
-
- adjustSpaceAdvances();
-
- if (m_letterSpacing != 0 || m_wordSpacing != 0)
- applySpacing();
-}
-
-void UniscribeHelper::fillScreenOrder()
-{
- m_screenOrder.resize(m_runs.size());
-
- // We assume that the input has only one text direction in it.
- // TODO(brettw) are we sure we want to keep this restriction?
- if (m_isRtl) {
- for (int i = 0; i < static_cast<int>(m_screenOrder.size()); i++)
- m_screenOrder[static_cast<int>(m_screenOrder.size()) - i - 1] = i;
- } else {
- for (int i = 0; i < static_cast<int>(m_screenOrder.size()); i++)
- m_screenOrder[i] = i;
- }
-}
-
-void UniscribeHelper::adjustSpaceAdvances()
-{
- if (m_spaceWidth == 0)
- return;
-
- int spaceWidthWithoutLetterSpacing = m_spaceWidth - m_letterSpacing;
-
- // This mostly matches what WebKit's UniscribeController::shapeAndPlaceItem.
- for (size_t run = 0; run < m_runs.size(); run++) {
- Shaping& shaping = m_shapes[run];
-
- // FIXME: This loop is not UTF-16-safe. Unicode 6.0 has a couple
- // of complex script blocks in Plane 1.
- for (int i = 0; i < shaping.charLength(); i++) {
- UChar c = m_input[m_runs[run].iCharPos + i];
- bool treatAsSpace = Font::treatAsSpace(c);
- if (!treatAsSpace && !Font::treatAsZeroWidthSpaceInComplexScript(c))
- continue;
-
- int glyphIndex = shaping.m_logs[i];
- int currentAdvance = shaping.m_advance[glyphIndex];
-
- shaping.m_glyphs[glyphIndex] = shaping.m_spaceGlyph;
-
- if (treatAsSpace) {
- // currentAdvance does not include additional letter-spacing,
- // but m_spaceWidth does. Here we find out how off we are from
- // the correct width (spaceWidthWithoutLetterSpacing) and
- // just subtract that diff.
- int diff = currentAdvance - spaceWidthWithoutLetterSpacing;
- // The shaping can consist of a run of text, so only subtract
- // the difference in the width of the glyph.
- shaping.m_advance[glyphIndex] -= diff;
- shaping.m_abc.abcB -= diff;
- continue;
- }
-
- // For characters treated as zero-width space in complex
- // scripts, set the advance width to zero, adjust
- // |abcB| of the current run accordingly and set
- // the glyph to m_spaceGlyph (invisible).
- shaping.m_advance[glyphIndex] = 0;
- shaping.m_abc.abcB -= currentAdvance;
- shaping.m_offsets[glyphIndex].du = 0;
- shaping.m_offsets[glyphIndex].dv = 0;
- }
- }
-}
-
-void UniscribeHelper::applySpacing()
-{
- for (size_t run = 0; run < m_runs.size(); run++) {
- Shaping& shaping = m_shapes[run];
- bool isRtl = m_runs[run].a.fRTL;
-
- if (m_letterSpacing != 0) {
- // RTL text gets padded to the left of each character. We increment
- // the run's advance to make this happen. This will be balanced out
- // by NOT adding additional advance to the last glyph in the run.
- if (isRtl)
- shaping.m_prePadding += m_letterSpacing;
-
- // Go through all the glyphs in this run and increase the "advance"
- // to account for letter spacing. We adjust letter spacing only on
- // cluster boundaries.
- //
- // This works for most scripts, but may have problems with some
- // indic scripts. This behavior is better than Firefox or IE for
- // Hebrew.
- for (int i = 0; i < shaping.glyphLength(); i++) {
- if (shaping.m_visualAttributes[i].fClusterStart) {
- // Ick, we need to assign the extra space so that the glyph
- // comes first, then is followed by the space. This is
- // opposite for RTL.
- if (isRtl) {
- if (i != shaping.glyphLength() - 1) {
- // All but the last character just get the spacing
- // applied to their advance. The last character
- // doesn't get anything,
- shaping.m_advance[i] += m_letterSpacing;
- shaping.m_abc.abcB += m_letterSpacing;
- }
- } else {
- // LTR case is easier, we just add to the advance.
- shaping.m_advance[i] += m_letterSpacing;
- shaping.m_abc.abcB += m_letterSpacing;
- }
- }
- }
- }
-
- // Go through all the characters to find whitespace and insert the
- // extra wordspacing amount for the glyphs they correspond to.
- if (m_wordSpacing != 0) {
- for (int i = 0; i < shaping.charLength(); i++) {
- if (!Font::treatAsSpace(m_input[m_runs[run].iCharPos + i]))
- continue;
-
- // The char in question is a word separator...
- int glyphIndex = shaping.m_logs[i];
-
- // Spaces will not have a glyph in Uniscribe, it will just add
- // additional advance to the character to the left of the
- // space. The space's corresponding glyph will be the character
- // following it in reading order.
- if (isRtl) {
- // In RTL, the glyph to the left of the space is the same
- // as the first glyph of the following character, so we can
- // just increment it.
- shaping.m_advance[glyphIndex] += m_wordSpacing;
- shaping.m_abc.abcB += m_wordSpacing;
- } else {
- // LTR is actually more complex here, we apply it to the
- // previous character if there is one, otherwise we have to
- // apply it to the leading space of the run.
- if (glyphIndex == 0)
- shaping.m_prePadding += m_wordSpacing;
- else {
- shaping.m_advance[glyphIndex - 1] += m_wordSpacing;
- shaping.m_abc.abcB += m_wordSpacing;
- }
- }
- }
- } // m_wordSpacing != 0
-
- // Loop for next run...
- }
-}
-
-// The advance is the ABC width of the run
-int UniscribeHelper::advanceForItem(int itemIndex) const
-{
- int accum = 0;
- const Shaping& shaping = m_shapes[itemIndex];
-
- if (shaping.m_justify.size() == 0) {
- // Easy case with no justification, the width is just the ABC width of
- // the run. (The ABC width is the sum of the advances).
- return shaping.m_abc.abcA + shaping.m_abc.abcB +
- shaping.m_abc.abcC + shaping.m_prePadding;
- }
-
- // With justification, we use the justified amounts instead. The
- // justification array contains both the advance and the extra space
- // added for justification, so is the width we want.
- int justification = 0;
- for (size_t i = 0; i < shaping.m_justify.size(); i++)
- justification += shaping.m_justify[i];
-
- return shaping.m_prePadding + justification;
-}
-
-// SCRIPT_FONTPROPERTIES contains glyph indices for default, invalid
-// and blank glyphs. Just because ScriptShape succeeds does not mean
-// that a text run is rendered correctly. Some characters may be rendered
-// with default/invalid/blank glyphs. Therefore, we need to check if the glyph
-// array returned by ScriptShape contains any of those glyphs to make
-// sure that the text run is rendered successfully.
-// However, we should not subject zero-width characters to this test.
-
-bool UniscribeHelper::containsMissingGlyphs(const Shaping& shaping,
- const SCRIPT_ITEM& run,
- const SCRIPT_FONTPROPERTIES* properties) const
-{
- for (int i = 0; i < shaping.charLength(); i++) {
- UChar c = m_input[run.iCharPos + i];
- // Skip zero-width space characters because they're not considered to
- // be missing in a font.
- if (Font::treatAsZeroWidthSpaceInComplexScript(c))
- continue;
- int glyphIndex = shaping.m_logs[i];
- WORD glyph = shaping.m_glyphs[glyphIndex];
- // Note on the thrid condition: Windows Vista sometimes returns glyphs
- // equal to wgBlank (instead of wgDefault), with fZeroWidth set. Treat
- // such cases as having missing glyphs if the corresponding character
- // is not a zero width whitespace.
- if (glyph == properties->wgDefault
- || (glyph == properties->wgInvalid && glyph != properties->wgBlank)
- || (glyph == properties->wgBlank && shaping.m_visualAttributes[glyphIndex].fZeroWidth && !Font::treatAsZeroWidthSpace(c)))
- return true;
- }
- return false;
-}
-
-static OPENTYPE_TAG convertFeatureTag(const String& tag)
-{
- return ((tag[0] & 0xFF) | ((tag[1] & 0xFF) << 8) | ((tag[2] & 0xFF) << 16) | ((tag[3] & 0xFF) << 24));
-}
-
-void UniscribeHelper::setRangeProperties(const FontFeatureSettings* featureSettings)
-{
- if (!featureSettings || !featureSettings->size()) {
- m_featureRecords.resize(0);
- return;
- }
-
- m_featureRecords.resize(featureSettings->size());
- for (unsigned i = 0; i < featureSettings->size(); ++i) {
- m_featureRecords[i].lParameter = featureSettings->at(i).value();
- m_featureRecords[i].tagFeature = convertFeatureTag(featureSettings->at(i).tag());
- }
- m_rangeProperties.potfRecords = &m_featureRecords[0];
- m_rangeProperties.cotfRecords = m_featureRecords.size();
-}
-
-} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/win/UniscribeHelper.h b/chromium/third_party/WebKit/Source/platform/fonts/win/UniscribeHelper.h
deleted file mode 100644
index 8a724c6d608..00000000000
--- a/chromium/third_party/WebKit/Source/platform/fonts/win/UniscribeHelper.h
+++ /dev/null
@@ -1,449 +0,0 @@
-/*
- * Copyright (c) 2006, 2007, 2008, 2009, Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-// A wrapper around Uniscribe that provides a reasonable API.
-
-#ifndef UniscribeHelper_h
-#define UniscribeHelper_h
-
-#include <windows.h>
-#include <usp10.h>
-#include <map>
-
-#include <unicode/uchar.h>
-#include "wtf/Vector.h"
-
-class UniscribeTest_TooBig_Test; // A gunit test for UniscribeHelper.
-
-namespace WebCore {
-
-class FloatRect;
-class FontFeatureSettings;
-class FontPlatformData;
-class GraphicsContext;
-
-const unsigned cUniscribeHelperStackRuns = 8;
-const unsigned cUniscribeHelperStackChars = 32;
-const unsigned cUniscribeHelperFeatures = 4;
-
-// This object should be safe to create & destroy frequently, as long as the
-// caller preserves the script_cache when possible (this data may be slow to
-// compute).
-//
-// This object is "kind of large" (~1K) because it reserves a lot of space for
-// working with to avoid expensive heap operations. Therefore, not only should
-// you not worry about creating and destroying it, you should try to not keep
-// them around.
-class UniscribeHelper {
-public:
- // Initializes this Uniscribe run with the text pointed to by |run| with
- // |length|. The input is NOT null terminated.
- //
- // The is_rtl flag should be set if the input script is RTL. It is assumed
- // that the caller has already divided up the input text (using ICU, for
- // example) into runs of the same direction of script. This avoids
- // disagreements between the caller and Uniscribe later (see FillItems).
- //
- // A script cache should be provided by the caller that is initialized to
- // NULL. When the caller is done with the cache (it may be stored between
- // runs as long as it is used consistently with the same HFONT), it should
- // call ScriptFreeCache().
- UniscribeHelper(const UChar* input,
- int inputLength,
- bool isRtl,
- HFONT,
- SCRIPT_CACHE*,
- SCRIPT_FONTPROPERTIES*,
- WORD);
-
- virtual ~UniscribeHelper();
-
- // Sets Uniscribe's directional override flag. False by default.
- bool directionalOverride() const
- {
- return m_directionalOverride;
- }
- void setDirectionalOverride(bool override)
- {
- m_directionalOverride = override;
- }
-
- // Set's Uniscribe's no-ligate override flag. False by default.
- bool inhibitLigate() const
- {
- return m_inhibitLigate;
- }
- void setInhibitLigate(bool inhibit)
- {
- m_inhibitLigate = inhibit;
- }
-
- // Set letter spacing. We will try to insert this much space between
- // graphemes (one or more glyphs perceived as a single unit by ordinary
- // users of a script). Positive values increase letter spacing, negative
- // values decrease it. 0 by default.
- int letterSpacing() const
- {
- return m_letterSpacing;
- }
- void setLetterSpacing(int letterSpacing)
- {
- m_letterSpacing = letterSpacing;
- }
-
- // Set the width of a standard space character. We use this to normalize
- // space widths. Windows will make spaces after Hindi characters larger than
- // other spaces. A space_width of 0 means to use the default space width.
- //
- // Must be set before Init() is called.
- int spaceWidth() const
- {
- return m_spaceWidth;
- }
- void setSpaceWidth(int spaceWidth)
- {
- m_spaceWidth = spaceWidth;
- }
-
- // Set word spacing. We will try to insert this much extra space between
- // each word in the input (beyond whatever whitespace character separates
- // words). Positive values lead to increased letter spacing, negative values
- // decrease it. 0 by default.
- //
- // Must be set before Init() is called.
- int wordSpacing() const
- {
- return m_wordSpacing;
- }
- void setWordSpacing(int wordSpacing)
- {
- m_wordSpacing = wordSpacing;
- }
-
- void setAscent(int ascent)
- {
- m_ascent = ascent;
- }
-
- // When set to true, this class is used only to look up glyph
- // indices for a range of Unicode characters without glyph placement.
- // By default, it's false. This should be set to true when this
- // class is used for glyph index look-up for non-BMP characters
- // in GlyphPageNodeChromiumWin.cpp.
- void setDisableFontFallback(bool disableFontFallback)
- {
- m_disableFontFallback = true;
- }
-
- // Set TEXTRANGE_PROPERTIES structure which contains
- // OpenType feature records generated from FontFeatureSettings.
- void setRangeProperties(const FontFeatureSettings*);
-
- // You must call this after setting any options but before doing any
- // other calls like asking for widths or drawing.
- void init()
- {
- initWithOptionalLengthProtection(true);
- }
-
- // Returns the total width in pixels of the text run.
- int width() const;
-
- // Call to justify the text, with the amount of space that should be ADDED
- // to get the desired width that the column should be justified to.
- // Normally, spaces are inserted, but for Arabic there will be kashidas
- // (extra strokes) inserted instead.
- //
- // This function MUST be called AFTER Init().
- void justify(int additionalSpace);
-
- // Computes the given character offset into a pixel offset of the beginning
- // of that character.
- int characterToX(int offset) const;
-
- // Converts the given pixel X position into a logical character offset into
- // the run. For positions appearing before the first character, this will
- // return -1.
- int xToCharacter(int x) const;
-
- // Draws the given characters to (x, y) in the given DC. The font will be
- // handled by this function, but the font color and other attributes should
- // be pre-set.
- //
- // The y position is the upper left corner, NOT the baseline.
- void draw(GraphicsContext*, const FontPlatformData&, HDC,
- int x, int y, const FloatRect& textRect,
- int from, int to);
-
- // Returns the first glyph assigned to the character at the given offset.
- // This function is used to retrieve glyph information when Uniscribe is
- // being used to generate glyphs for non-complex, non-BMP (above U+FFFF)
- // characters. These characters are not otherwise special and have no
- // complex shaping rules, so we don't otherwise need Uniscribe, except
- // Uniscribe is the only way to get glyphs for non-BMP characters.
- //
- // Returns 0 if there is no glyph for the given character.
- WORD firstGlyphForCharacter(int charOffset) const;
-
-protected:
- // Backend for init. The flag allows the unit test to specify whether we
- // should fail early for very long strings like normal, or try to pass the
- // long string to Uniscribe. The latter provides a way to force failure of
- // shaping.
- void initWithOptionalLengthProtection(bool lengthProtection);
-
- // Tries to preload the font when the it is not accessible.
- // This is the default implementation and it does not do anything.
- virtual void tryToPreloadFont(HFONT) {}
-
- // Let our subclasses provide the input lazily in case they can't compute
- // it in their constructors. Once we have input, however, we don't let
- // our subclasses change it.
- void setInput(const UChar* input) { ASSERT(!m_input); m_input = input; }
-
-private:
- friend class UniscribeTest_TooBig_Test;
-
- // An array corresponding to each item in runs_ containing information
- // on each of the glyphs that were generated. Like runs_, this is in
- // reading order. However, for rtl text, the characters within each
- // item will be reversed.
- struct Shaping {
- Shaping()
- : m_prePadding(0)
- , m_hfont(NULL)
- , m_scriptCache(NULL)
- , m_ascentOffset(0)
- , m_spaceGlyph(0)
- {
- m_abc.abcA = 0;
- m_abc.abcB = 0;
- m_abc.abcC = 0;
- }
-
- // Returns the number of glyphs (which will be drawn to the screen)
- // in this run.
- int glyphLength() const
- {
- return static_cast<int>(m_glyphs.size());
- }
-
- // Returns the number of characters (that we started with) in this run.
- int charLength() const
- {
- return static_cast<int>(m_logs.size());
- }
-
- // Returns the advance array that should be used when measuring glyphs.
- // The returned pointer will indicate an array with glyph_length()
- // elements and the advance that should be used for each one. This is
- // either the real advance, or the justified advances if there is one,
- // and is the array we want to use for measurement.
- const int* effectiveAdvances() const
- {
- if (m_advance.size() == 0)
- return 0;
- if (m_justify.size() == 0)
- return &m_advance[0];
- return &m_justify[0];
- }
-
- // This is the advance amount of space that we have added to the
- // beginning of the run. It is like the ABC's |A| advance but one that
- // we create and must handle internally whenever computing with pixel
- // offsets.
- int m_prePadding;
-
- // Glyph indices in the font used to display this item. These indices
- // are in screen order.
- Vector<WORD, cUniscribeHelperStackChars> m_glyphs;
-
- // For each input character, this tells us the first glyph index it
- // generated. This is the only array with size of the input chars.
- //
- // All offsets are from the beginning of this run. Multiple characters
- // can generate one glyph, in which case there will be adjacent
- // duplicates in this list. One character can also generate multiple
- // glyphs, in which case there will be skipped indices in this list.
- Vector<WORD, cUniscribeHelperStackChars> m_logs;
-
- // Flags and such for each glyph.
- Vector<SCRIPT_VISATTR, cUniscribeHelperStackChars> m_visualAttributes;
-
- // Horizontal advances for each glyph listed above, this is basically
- // how wide each glyph is.
- Vector<int, cUniscribeHelperStackChars> m_advance;
-
- // This contains glyph offsets, from the nominal position of a glyph.
- // It is used to adjust the positions of multiple combining characters
- // around/above/below base characters in a context-sensitive manner so
- // that they don't bump against each other and the base character.
- Vector<GOFFSET, cUniscribeHelperStackChars> m_offsets;
-
- // Filled by a call to Justify, this is empty for nonjustified text.
- // If nonempty, this contains the array of justify characters for each
- // character as returned by ScriptJustify.
- //
- // This is the same as the advance array, but with extra space added
- // for some characters. The difference between a glyph's |justify|
- // width and it's |advance| width is the extra space added.
- Vector<int, cUniscribeHelperStackChars> m_justify;
-
- // Sizing information for this run. This treats the entire run as a
- // character with a preceeding advance, width, and ending advance. The
- // B width is the sum of the |advance| array, and the A and C widths
- // are any extra spacing applied to each end.
- //
- // It is unclear from the documentation what this actually means. From
- // experimentation, it seems that the sum of the character advances is
- // always the sum of the ABC values, and I'm not sure what you're
- // supposed to do with the ABC values.
- ABC m_abc;
-
- // Pointers to windows font data used to render this run.
- HFONT m_hfont;
- SCRIPT_CACHE* m_scriptCache;
-
- // Ascent offset between the ascent of the primary font
- // and that of the fallback font. The offset needs to be applied,
- // when drawing a string, to align multiple runs rendered with
- // different fonts.
- int m_ascentOffset;
-
- WORD m_spaceGlyph;
- };
-
- // Computes the runs_ array from the text run.
- void fillRuns();
-
- // Computes the shapes_ array given an runs_ array already filled in.
- void fillShapes();
-
- // Fills in the screen_order_ array (see below).
- void fillScreenOrder();
-
- // Called to update the glyph positions based on the current spacing
- // options that are set.
- void applySpacing();
-
- // Normalizes all advances for spaces to the same width. This keeps windows
- // from making spaces after Hindi characters larger, which is then
- // inconsistent with our meaure of the width since WebKit doesn't include
- // spaces in text-runs sent to uniscribe unless white-space:pre.
- void adjustSpaceAdvances();
-
- // Returns the total width of a single item.
- int advanceForItem(int) const;
-
- bool containsMissingGlyphs(const Shaping&,
- const SCRIPT_ITEM&,
- const SCRIPT_FONTPROPERTIES*) const;
-
- // Shapes a run (pointed to by |input|) using |hfont| first.
- // Tries a series of fonts specified retrieved with NextWinFontData
- // and finally a font covering characters in |*input|. A string pointed
- // by |input| comes from ScriptItemize and is supposed to contain
- // characters belonging to a single script aside from characters common to
- // all scripts (e.g. space).
- bool shape(const UChar* input, int itemLength, int numGlyphs, SCRIPT_ITEM& run, OPENTYPE_TAG, Shaping&);
-
- // Gets Windows font data for the next best font to try in the list
- // of fonts. When there's no more font available, returns false
- // without touching any of out params. Need to call ResetFontIndex
- // to start scanning of the font list from the beginning.
- virtual bool nextWinFontData(HFONT&, SCRIPT_CACHE*&, SCRIPT_FONTPROPERTIES*&, int&, WORD&)
- {
- return false;
- }
-
- // Resets the font index to the first in the list of fonts to try after the
- // primaryFont turns out not to work. With fontIndex reset,
- // NextWinFontData scans fallback fonts from the beginning.
- virtual void resetFontIndex() {}
-
- // If m_cachedDC is 0, creates one that is compatible with the screen DC.
- void EnsureCachedDCCreated();
-
- // The input data for this run of Uniscribe. See the constructor.
- const UChar* m_input;
- const int m_inputLength;
- const bool m_isRtl;
-
- // Windows font data for the primary font. In a sense, m_logfont and m_style
- // are redundant because m_hfont contains all the information. However,
- // invoking GetObject, everytime we need the height and the style, is rather
- // expensive so that we cache them. Would it be better to add getter and
- // (virtual) setter for the height and the style of the primary font,
- // instead of m_logfont? Then, a derived class ctor can set m_ascent,
- // m_height and m_style if they're known. Getters for them would have to
- // 'infer' their values from m_hfont ONLY when they're not set.
- HFONT m_hfont;
- // We cache the DC to use with ScriptShape/ScriptPlace.
- static HDC m_cachedDC;
- SCRIPT_CACHE* m_scriptCache;
- SCRIPT_FONTPROPERTIES* m_fontProperties;
- int m_ascent;
- LOGFONT m_logfont;
- int m_style;
- WORD m_spaceGlyph;
-
- // Options, see the getters/setters above.
- bool m_directionalOverride;
- bool m_inhibitLigate;
- int m_letterSpacing;
- int m_spaceWidth;
- int m_wordSpacing;
- bool m_disableFontFallback;
-
- // Uniscribe breaks the text into Runs. These are one length of text that is
- // in one script and one direction. This array is in reading order.
- Vector<SCRIPT_ITEM, cUniscribeHelperStackRuns> m_runs;
-
- Vector<Shaping, cUniscribeHelperStackRuns> m_shapes;
- Vector<OPENTYPE_TAG, cUniscribeHelperStackRuns> m_scriptTags;
-
- // This is a mapping between reading order and screen order for the items.
- // Uniscribe's items array are in reading order. For right-to-left text,
- // or mixed (although WebKit's |TextRun| should really be only one
- // direction), this makes it very difficult to compute character offsets
- // and positions. This list is in screen order from left to right, and
- // gives the index into the |m_runs| and |m_shapes| arrays of each
- // subsequent item.
- Vector<int, cUniscribeHelperStackRuns> m_screenOrder;
-
- // This contains Uniscribe's OpenType feature settings. This structure
- // is filled by using WebKit's |FontFeatureSettings|.
- TEXTRANGE_PROPERTIES m_rangeProperties;
- Vector<OPENTYPE_FEATURE_RECORD, cUniscribeHelperFeatures> m_featureRecords;
-};
-
-} // namespace WebCore
-
-#endif // UniscribeHelper_h
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/win/UniscribeHelperTextRun.cpp b/chromium/third_party/WebKit/Source/platform/fonts/win/UniscribeHelperTextRun.cpp
deleted file mode 100644
index 9ae1680992d..00000000000
--- a/chromium/third_party/WebKit/Source/platform/fonts/win/UniscribeHelperTextRun.cpp
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * Copyright (c) 2006, 2007, 2008, 2009, Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "platform/fonts/win/UniscribeHelperTextRun.h"
-
-#include "platform/fonts/Font.h"
-#include "platform/fonts/SimpleFontData.h"
-#include "platform/fonts/win/FontPlatformDataWin.h"
-#include "platform/text/TextRun.h"
-
-namespace WebCore {
-
-UniscribeHelperTextRun::UniscribeHelperTextRun(const TextRun& run,
- const Font& font)
- : UniscribeHelper(0, run.length(), run.rtl(),
- font.primaryFont()->platformData().hfont(),
- font.primaryFont()->platformData().scriptCache(),
- font.primaryFont()->platformData().scriptFontProperties(),
- font.primaryFont()->spaceGlyph())
- , m_font(&font)
- , m_fontIndex(0)
-{
- if (run.is8Bit()) {
- m_stringFor8BitRun = String::make16BitFrom8BitSource(run.characters8(), run.length());
- setInput(m_stringFor8BitRun.characters16());
- } else {
- setInput(run.characters16());
- }
-
- setDirectionalOverride(run.directionalOverride());
- setLetterSpacing(font.letterSpacing());
- setSpaceWidth(font.spaceWidth());
- setWordSpacing(font.wordSpacing());
- setAscent(font.fontMetrics().ascent());
- setRangeProperties(font.fontDescription().featureSettings());
-
- init();
-
- // Expansion is the amount to add to make justification happen. This
- // should be done after Init() so all the runs are already measured.
- if (run.expansion() > 0)
- justify(run.expansion());
-}
-
-UniscribeHelperTextRun::UniscribeHelperTextRun(
- const wchar_t* input,
- int inputLength,
- bool isRtl,
- HFONT hfont,
- SCRIPT_CACHE* scriptCache,
- SCRIPT_FONTPROPERTIES* fontProperties)
- : UniscribeHelper(input, inputLength, isRtl, hfont,
- scriptCache, fontProperties, 0)
- , m_font(0)
- , m_fontIndex(-1)
-{
-}
-
-void UniscribeHelperTextRun::tryToPreloadFont(HFONT font)
-{
- // Ask the browser to get the font metrics for this font.
- // That will preload the font and it should now be accessible
- // from the renderer.
- FontPlatformData::ensureFontLoaded(font);
-}
-
-bool UniscribeHelperTextRun::nextWinFontData(
- HFONT& hfont,
- SCRIPT_CACHE*& scriptCache,
- SCRIPT_FONTPROPERTIES*& fontProperties,
- int& ascent,
- WORD& spaceGlyph)
-{
- // This check is necessary because NextWinFontData can be called again
- // after we already ran out of fonts. fontDataAt behaves in a strange
- // manner when the difference between param passed and # of fonts stored in
- // blink::Font is larger than one. We can avoid this check by setting
- // font_index_ to # of elements in hfonts_ when we run out of font. In that
- // case, we'd have to go through a couple of more checks before returning
- // false.
- if (m_fontIndex == -1 || !m_font)
- return false;
-
- // If the font data for a fallback font requested is not yet retrieved, add
- // them to our vectors. Note that '>' rather than '>=' is used to test that
- // condition. primaryFont is not stored in hfonts_, and friends so that
- // indices for fontDataAt and our vectors for font data are 1 off from each
- // other. That is, when fully populated, hfonts_ and friends have one font
- // fewer than what's contained in font_.
- if (static_cast<size_t>(++m_fontIndex) > m_hfonts.size()) {
- const FontData *fontData = m_font->fontDataAt(m_fontIndex);
- if (!fontData) {
- // Ran out of fonts.
- m_fontIndex = -1;
- return false;
- }
-
- // FIXME: this won't work for SegmentedFontData
- // http://crbug.com/6425
- const SimpleFontData* simpleFontData =
- fontData->fontDataForCharacter(' ');
-
- m_hfonts.append(simpleFontData->platformData().hfont());
- m_scriptCaches.append(simpleFontData->platformData().scriptCache());
- m_fontProperties.append(simpleFontData->platformData().scriptFontProperties());
- m_ascents.append(simpleFontData->fontMetrics().ascent());
- m_spaceGlyphs.append(simpleFontData->spaceGlyph());
- }
-
- hfont = m_hfonts[m_fontIndex - 1];
- scriptCache = m_scriptCaches[m_fontIndex - 1];
- fontProperties = m_fontProperties[m_fontIndex - 1];
- ascent = m_ascents[m_fontIndex - 1];
- spaceGlyph = m_spaceGlyphs[m_fontIndex - 1];
- return true;
-}
-
-void UniscribeHelperTextRun::resetFontIndex()
-{
- m_fontIndex = 0;
-}
-
-} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/platform/fonts/win/UniscribeHelperTextRun.h b/chromium/third_party/WebKit/Source/platform/fonts/win/UniscribeHelperTextRun.h
deleted file mode 100644
index f033f3431c7..00000000000
--- a/chromium/third_party/WebKit/Source/platform/fonts/win/UniscribeHelperTextRun.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright (c) 2006, 2007, 2008, 2009, Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef UniscribeHelperTextRun_h
-#define UniscribeHelperTextRun_h
-
-#include "platform/fonts/win/UniscribeHelper.h"
-#include "wtf/text/WTFString.h"
-
-namespace WebCore {
-
-class Font;
-class TextRun;
-
-// Wrapper around the Uniscribe helper that automatically sets it up with the
-// WebKit types we supply.
-class UniscribeHelperTextRun : public UniscribeHelper {
-public:
- // Regular constructor used for WebCore text run processing.
- UniscribeHelperTextRun(const TextRun&, const Font&);
-
- // Constructor with the same interface as the gfx::UniscribeState. Using
- // this constructor will not give you font fallback, but it will provide
- // the ability to load fonts that may not be in the OS cache
- // ("TryToPreloadFont") if the caller does not have a TextRun/Font.
- UniscribeHelperTextRun(const wchar_t* input,
- int inputLength,
- bool isRtl,
- HFONT hfont,
- SCRIPT_CACHE*,
- SCRIPT_FONTPROPERTIES*);
-
-protected:
- virtual void tryToPreloadFont(HFONT);
-
-private:
- // This function retrieves the Windows font data (HFONT, etc) for the next
- // WebKit font in the list. If the font data corresponding to font_index_
- // has been obtained before, returns the values stored in our internal
- // vectors (hfonts_, etc). Otherwise, it gets next SimpleFontData from
- // WebKit and adds them to in hfonts_ and friends so that font data can be
- // returned quickly next time they're requested.
- virtual bool nextWinFontData(HFONT&, SCRIPT_CACHE*&, SCRIPT_FONTPROPERTIES*&, int& ascent, WORD& spaceGlyph);
- virtual void resetFontIndex();
-
- // Reference to blink::Font that contains all the information about fonts
- // we can use to render this input run of text. It is used in
- // NextWinFontData to retrieve Windows font data for a series of
- // non-primary fonts.
- //
- // This pointer can be NULL for no font fallback handling.
- const Font* m_font;
-
- // When we have an 8 bit TestRun, we store the buffer of upconverted characters
- // in this string.
- String m_stringFor8BitRun;
-
- // It's rare that many fonts are listed in stylesheets.
- // Four would be large enough in most cases.
- const static size_t kNumberOfFonts = 4;
-
- // These vectors are used to store Windows font data for non-primary fonts.
- Vector<HFONT, kNumberOfFonts> m_hfonts;
- Vector<SCRIPT_CACHE*, kNumberOfFonts> m_scriptCaches;
- Vector<SCRIPT_FONTPROPERTIES*, kNumberOfFonts> m_fontProperties;
- Vector<int, kNumberOfFonts> m_ascents;
- Vector<WORD> m_spaceGlyphs;
-
- // Index of the fallback font we're currently using for NextWinFontData.
- int m_fontIndex;
-};
-
-} // namespace WebCore
-
-#endif // UniscribeHelperTextRun_h