font-variant-caps does not work if the font does not support font features
https://bugs.webkit.org/show_bug.cgi?id=149774

Reviewed by Antti Koivisto.

Source/WebCore:

This test implements synthesis for small-caps and all-small-caps. It does so by
moving font variant selection into a higher level (ComplexTextController).
In general, the approach is to use the pure font feature until we encounter
a character which needs to be uppercased, and which the font feature does not
support uppercasing. In this situation, we try again with synthesis. In this
case, synthesis means artificially uppercasing letters and rendering them with
a smaller font.

We require system support to know which glyphs a particular font feature supports.
Therefore, on operating systems which do not include this support, we will simply
say that the font feature does not support any glyphs.

Test: css3/font-variant-small-caps-synthesis.html
      css3/font-variant-petite-caps-synthesis.html

* platform/graphics/Font.cpp:
(WebCore::Font::noSmallCapsFont): Return the same font, but without smcp or c2sc.
This function utilizes a cache.
* platform/graphics/Font.h:
(WebCore::Font::variantFont): Small caps should never go through this function
anymore.
* platform/graphics/FontCascade.h: Because we're moving variant selection into
a higher level, we remove the FontVariant argument from the lower-level call.
* platform/graphics/FontCascadeFonts.cpp:
(WebCore::FontCascadeFonts::glyphDataForVariant): Use early-return style.
(WebCore::FontCascadeFonts::glyphDataForNormalVariant): Ditto.
* platform/graphics/cocoa/FontCascadeCocoa.mm:
(WebCore::FontCascade::fontForCombiningCharacterSequence): Because we're moving
variant selection into a higher level, we remove the FontVariant argument from
the lower-level call.
* platform/graphics/cocoa/FontCocoa.mm:
(WebCore::Font::smallCapsSupportsCharacter):
(WebCore::Font::allSmallCapsSupportsCharacter):
(WebCore::smallCapsOpenTypeDictionary): Helper function for
smallCapsSupportsCharacter().
(WebCore::smallCapsTrueTypeDictionary): Ditto.
(WebCore::unionBitVectors):
(WebCore::Font::glyphsSupportedBySmallCaps): Compute a bit vector of supported
glyphs.
(WebCore::Font::glyphsSupportedByAllSmallCaps): Ditto.
(WebCore::createDerivativeFont): Moving common code into its own helper function.
(WebCore::Font::createFontWithoutSmallCaps):
(WebCore::Font::platformCreateScaledFont): Use the common code.
* platform/graphics/mac/ComplexTextController.cpp:
(WebCore::capitalized): What is the capitalized form of a character?
(WebCore::ComplexTextController::collectComplexTextRuns): Implement the core
logic of this patch. This includes the retry when we encounter a character which
is not supported by the font feature.
* platform/spi/cocoa/CoreTextSPI.h:

LayoutTests:

Adding two new font which include lowercase characters which respond to 'smcp' and 'c2sc'.

The character mappings are:

OpenType:
'smcp': f
'c2sc': g

TrueType:
kLowerCaseType / kLowerCaseSmallCapsSelector: r
kUpperCaseType / kUpperCaseSmallCapsSelector: u

* css3/font-variant-all-expected.html:
* css3/font-variant-all.html:
* css3/font-variant-small-caps-synthesis-expected.html: Added.
* css3/font-variant-small-caps-synthesis.html: Added.
* css3/font-variant-petite-caps-synthesis-expected.html: Added.
* css3/font-variant-petite-caps-synthesis.html: Added.
* css3/resources/FontWithFeaturesLowercaseSmallCaps.otf: Added.
* css3/resources/FontWithFeaturesLowercaseSmallCaps.ttf: Added.
* platform/mac/TestExpectations:
* platform/mac/fast/writing-mode/broken-ideograph-small-caps-expected.txt:


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@193894 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/LayoutTests/css3/font-variant-small-caps-synthesis-coverage-expected.html b/LayoutTests/css3/font-variant-small-caps-synthesis-coverage-expected.html
new file mode 100644
index 0000000..d9b6a58
--- /dev/null
+++ b/LayoutTests/css3/font-variant-small-caps-synthesis-coverage-expected.html
@@ -0,0 +1,91 @@
+<!DOCTYPE html>
+<html>
+<head>
+<style>
+@font-face {
+    font-family: "testfont";
+    src: url("resources/FontWithFeatures.otf") format("opentype");
+}
+.test {
+    font-size: 20px;
+    display: inline-block;
+}
+</style>
+</head>
+<body>
+This test makes sure that font-variant synthesis is correctly applied. The test passes when a particular pattern of Xs and checks appear below. Also note that the correct size of the character is required.
+<div style="border: solid black 1px;">
+<div class="test">ASDF</div>
+<div class="test"><span style="font-size: 14px;">ASDF</span></div>
+<div class="test"><span style="font-size: 14px;">AS</span>DF</div>
+<div class="test">AS<span style="font-size: 14px;">DF</span></div>
+<div class="test"><span style="font-size: 14px;">ASDF</span></div>
+<div class="test"><span style="font-size: 14px;">ASDF</span></div>
+<div class="test"><span style="font-size: 14px;">ASDF</span></div>
+<div class="test"><span style="font-size: 14px;">ASDF</span></div>
+</div>
+<div style="font-family: testfont; border: solid black 1px; margin: 5px;">
+<div class="test">AB</div>
+<div class="test">B</div>
+<div class="test">B</div>
+<div class="test">B</div>
+<div class="test"><span style="font-size: 14px;">A</span></div>
+<div class="test">A</div>
+<div class="test"><span style="font-size: 14px;">A</span>B</div>
+<div class="test">B<span style="font-size: 14px;">A</span></div>
+<div class="test">AA</div>
+<div class="test">AA</div>
+<div class="test">B</div>
+<div class="test"><span style="font-size: 14px;">A</span>K</div>
+<div class="test">K<span style="font-size: 14px;">A</span></div>
+<div class="test">AB</div>
+<div class="test">BA</div>
+</div>
+<div style="font-family: testfont; border: solid red 1px; margin: 5px;">
+<div class="test"style="">AB</div>
+<div class="test">B</div>
+<div class="test">B</div>
+<div class="test">B</div>
+<div class="test">B</div>
+<div class="test">A</div>
+<div class="test"><span style="font-size: 14px;">A</span></div>
+<div class="test">A</div>
+<div class="test"><span style="font-size: 14px;">A</span><span style="font-size: 14px;">B</span></div>
+<div class="test"><span style="font-size: 14px;">B</span><span style="font-size: 14px;">A</span></div>
+<div class="test">AA</div>
+<div class="test">AA</div>
+<div class="test"><span style="font-size: 14px;">A</span></div>
+<div class="test"><span style="font-size: 14px;">A</span><span style="font-size: 14px;">A</span></div>
+<div class="test"><span style="font-size: 14px;">A</span><span style="font-size: 14px;">A</span></div>
+<div class="test">A<span style="font-size: 14px;">A</span></div>
+<div class="test"><span style="font-size: 14px;">A</span>A</div>
+</div>
+<div style="font-family: testfont; border: solid blue 1px; margin: 5px;">
+<div class="test"><span style="font-size: 14px;">A</span></div>
+<div class="test">A</div>
+<div class="test"><span style="font-size: 14px;">A</span><span style="font-size: 14px;">B</span></div>
+<div class="test"><span style="font-size: 14px;">B</span><span style="font-size: 14px;">A</span></div>
+<div class="test"><span style="font-size: 14px;">A</span><span style="font-size: 14px;">B</span></div>
+<div class="test"><span style="font-size: 14px;">B</span><span style="font-size: 14px;">A</span></div>
+<div class="test">A</div>
+<div class="test"><span style="font-size: 14px;">A</span><span style="font-size: 14px;">B</span></div>
+<div class="test"><span style="font-size: 14px;">B</span><span style="font-size: 14px;">A</span></div>
+<div class="test"><span style="font-size: 14px;">A</span><span style="font-size: 14px;">B</span></div>
+<div class="test"><span style="font-size: 14px;">B</span><span style="font-size: 14px;">A</span></div>
+</div>
+<div style="font-family: testfont; border: solid green 1px; margin: 5px;">
+<div class="test"><span style="font-size: 14px;">A</span></div>
+<div class="test">A</div>
+<div class="test"><span style="font-size: 14px;">A</span><span style="font-size: 14px;">B</span></div>
+<div class="test"><span style="font-size: 14px;">B</span><span style="font-size: 14px;">A</span></div>
+<div class="test"><span style="font-size: 14px;">A</span><span style="font-size: 14px;">B</span></div>
+<div class="test"><span style="font-size: 14px;">B</span><span style="font-size: 14px;">A</span></div>
+<div class="test">A</div>
+<div class="test"><span style="font-size: 14px;">A</span><span style="font-size: 14px;">A</span></div>
+<div class="test"><span style="font-size: 14px;">A</span><span style="font-size: 14px;">A</span></div>
+<div class="test"><span style="font-size: 14px;">A</span><span style="font-size: 14px;">A</span></div>
+<div class="test"><span style="font-size: 14px;">A</span><span style="font-size: 14px;">A</span></div>
+</div>
+</div>
+</body>
+</html>