Index: third_party/WebKit/Source/platform/fonts/opentype/OpenTypeCapsSupport.cpp |
diff --git a/third_party/WebKit/Source/platform/fonts/opentype/OpenTypeCapsSupport.cpp b/third_party/WebKit/Source/platform/fonts/opentype/OpenTypeCapsSupport.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..bba64a56b121b822bce37b935a2920e53cfb5971 |
--- /dev/null |
+++ b/third_party/WebKit/Source/platform/fonts/opentype/OpenTypeCapsSupport.cpp |
@@ -0,0 +1,173 @@ |
+// Copyright 2015 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 "platform/fonts/opentype/OpenTypeCapsSupport.h" |
+ |
+namespace blink { |
+ |
+OpenTypeCapsSupport::OpenTypeCapsSupport() |
+ : m_harfBuzzFace(nullptr) |
+ , m_requestedCaps(FontDescription::CapsNormal) |
+ , m_fontSupport(FontSupport::Full) |
+ , m_capsSynthesis(CapsSynthesis::None) |
+{ |
+} |
+ |
+OpenTypeCapsSupport::OpenTypeCapsSupport(const HarfBuzzFace* harfBuzzFace, |
+ FontDescription::FontVariantCaps requestedCaps, |
+ hb_script_t script) |
+ : m_harfBuzzFace(harfBuzzFace) |
+ , m_requestedCaps(requestedCaps) |
+ , m_fontSupport(FontSupport::Full) |
+ , m_capsSynthesis(CapsSynthesis::None) |
+{ |
+ if (requestedCaps != FontDescription::CapsNormal) |
+ determineFontSupport(script); |
+} |
+ |
+FontDescription::FontVariantCaps OpenTypeCapsSupport::fontFeatureToUse( |
+ SmallCapsIterator::SmallCapsBehavior sourceTextCase) |
+{ |
+ if (m_fontSupport == FontSupport::Full) |
+ return m_requestedCaps; |
+ |
+ if (m_fontSupport == FontSupport::Fallback) { |
+ if (m_requestedCaps == FontDescription::FontVariantCaps::AllPetiteCaps) |
+ return FontDescription::FontVariantCaps::AllSmallCaps; |
+ |
+ if (m_requestedCaps == FontDescription::FontVariantCaps::PetiteCaps |
+ || (m_requestedCaps == FontDescription::FontVariantCaps::Unicase |
+ && sourceTextCase == SmallCapsIterator::SmallCapsSameCase)) |
+ return FontDescription::FontVariantCaps::SmallCaps; |
+ } |
+ |
+ return FontDescription::FontVariantCaps::CapsNormal; |
+} |
+ |
+bool OpenTypeCapsSupport::needsRunCaseSplitting() |
+{ |
+ // Lack of titling case support is ignored, titling case is not synthesized. |
+ return m_fontSupport != FontSupport::Full |
+ && m_requestedCaps != FontDescription::TitlingCaps; |
+} |
+ |
+bool OpenTypeCapsSupport::needsSyntheticFont( |
+ SmallCapsIterator::SmallCapsBehavior runCase) |
+{ |
+ if (m_fontSupport == FontSupport::Full) |
+ return false; |
+ |
+ if (m_requestedCaps == FontDescription::TitlingCaps) |
+ return false; |
+ |
+ if (m_fontSupport == FontSupport::None) { |
+ if (runCase == SmallCapsIterator::SmallCapsUppercaseNeeded |
+ && (m_capsSynthesis == CapsSynthesis::LowerToSmallCaps |
+ || m_capsSynthesis == CapsSynthesis::BothToSmallCaps)) |
+ return true; |
+ |
+ if (runCase == SmallCapsIterator::SmallCapsSameCase |
+ && (m_capsSynthesis == CapsSynthesis::UpperToSmallCaps |
+ || m_capsSynthesis == CapsSynthesis::BothToSmallCaps)) { |
+ return true; |
+ } |
+ } |
+ |
+ return false; |
+} |
+ |
+CaseMapIntend OpenTypeCapsSupport::needsCaseChange( |
+ SmallCapsIterator::SmallCapsBehavior runCase) |
+{ |
+ CaseMapIntend caseMapIntend = CaseMapIntend::KeepSameCase; |
+ |
+ if (m_fontSupport == FontSupport::Full) |
+ return caseMapIntend; |
+ |
+ switch (runCase) { |
+ case SmallCapsIterator::SmallCapsSameCase: |
+ caseMapIntend = m_fontSupport == FontSupport::Fallback |
+ && (m_capsSynthesis == CapsSynthesis::BothToSmallCaps |
+ || m_capsSynthesis == CapsSynthesis::UpperToSmallCaps) |
+ ? CaseMapIntend::LowerCase |
+ : CaseMapIntend::KeepSameCase; |
+ break; |
+ case SmallCapsIterator::SmallCapsUppercaseNeeded: |
+ caseMapIntend = m_fontSupport != FontSupport::Fallback |
+ && (m_capsSynthesis == CapsSynthesis::LowerToSmallCaps |
+ || m_capsSynthesis == CapsSynthesis::BothToSmallCaps) |
+ ? CaseMapIntend::UpperCase |
+ : CaseMapIntend::KeepSameCase; |
+ break; |
+ default: |
+ break; |
+ } |
+ return caseMapIntend; |
+} |
+ |
+void OpenTypeCapsSupport::determineFontSupport(hb_script_t script) |
+{ |
+ switch (m_requestedCaps) { |
+ case FontDescription::SmallCaps: |
+ if (!supportsOpenTypeFeature(script, HB_TAG('s', 'm', 'c', 'p'))) { |
+ m_fontSupport = FontSupport::None; |
+ m_capsSynthesis = CapsSynthesis::LowerToSmallCaps; |
+ } |
+ break; |
+ case FontDescription::AllSmallCaps: |
+ if (!(supportsOpenTypeFeature(script, HB_TAG('s', 'm', 'c', 'p')) |
+ && supportsOpenTypeFeature( |
+ script, |
+ HB_TAG('c', '2', 's', 'c')))) { |
+ m_fontSupport = FontSupport::None; |
+ m_capsSynthesis = CapsSynthesis::BothToSmallCaps; |
+ } |
+ break; |
+ case FontDescription::PetiteCaps: |
+ if (!supportsOpenTypeFeature(script, HB_TAG('p', 'c', 'a', 'p'))) { |
+ if (supportsOpenTypeFeature(script, HB_TAG('s', 'm', 'c', 'p'))) { |
+ m_fontSupport = FontSupport::Fallback; |
+ } else { |
+ m_fontSupport = FontSupport::None; |
+ m_capsSynthesis = CapsSynthesis::LowerToSmallCaps; |
+ } |
+ } |
+ break; |
+ case FontDescription::AllPetiteCaps: |
+ if (!(supportsOpenTypeFeature(script, HB_TAG('p', 'c', 'a', 'p')) |
+ && supportsOpenTypeFeature( |
+ script, |
+ HB_TAG('c', '2', 'p', 'c')))) { |
+ if (supportsOpenTypeFeature(script, HB_TAG('s', 'm', 'c', 'p')) |
+ && supportsOpenTypeFeature( |
+ script, |
+ HB_TAG('c', '2', 's', 'c'))) { |
+ m_fontSupport = FontSupport::Fallback; |
+ } else { |
+ m_fontSupport = FontSupport::None; |
+ m_capsSynthesis = CapsSynthesis::BothToSmallCaps; |
+ } |
+ } |
+ break; |
+ case FontDescription::Unicase: |
+ if (!supportsOpenTypeFeature(script, HB_TAG('u', 'n', 'i', 'c'))) { |
+ m_capsSynthesis = CapsSynthesis::UpperToSmallCaps; |
+ if (supportsOpenTypeFeature(script, HB_TAG('s', 'm', 'c', 'p'))) { |
+ m_fontSupport = FontSupport::Fallback; |
+ } else { |
+ m_fontSupport = FontSupport::None; |
+ } |
+ } |
+ break; |
+ case FontDescription::TitlingCaps: |
+ if (!supportsOpenTypeFeature(script, HB_TAG('t', 'i', 't', 'l'))) { |
+ m_fontSupport = FontSupport::None; |
+ } |
+ break; |
+ default: |
+ ASSERT_NOT_REACHED(); |
+ } |
+} |
+ |
+} // namespace blink |