<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[178518] trunk/Source/WebCore</title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/178518">178518</a></dd>
<dt>Author</dt> <dd>antti@apple.com</dd>
<dt>Date</dt> <dd>2015-01-15 11:29:05 -0800 (Thu, 15 Jan 2015)</dd>
</dl>
<h3>Log Message</h3>
<pre>Try to fix windows build.
* platform/graphics/Font.cpp: Copied from Source/WebCore/platform/graphics/SimpleFontData.cpp.
* platform/graphics/Font.h: Copied from Source/WebCore/platform/graphics/SimpleFontData.h.
* platform/graphics/FontCascadeFastPath.cpp: Copied from Source/WebCore/platform/graphics/FontFastPath.cpp.
* platform/graphics/ca/win/PlatformCALayerWin.cpp:
* platform/graphics/ca/win/PlatformCALayerWinInternal.cpp:
(PlatformCALayerWinInternal::displayCallback):
* platform/graphics/ios/FontIOS.mm: Copied from Source/WebCore/platform/graphics/ios/SimpleFontDataIOS.mm.
* platform/graphics/mac/FontCascadeComplexTextMac.cpp: Copied from Source/WebCore/platform/graphics/mac/FontComplexTextMac.cpp.
* platform/graphics/mac/FontCascadeMac.mm: Copied from Source/WebCore/platform/graphics/mac/FontMac.mm.
* platform/graphics/mac/FontCoreText.cpp: Copied from Source/WebCore/platform/graphics/mac/SimpleFontDataCoreText.cpp.
* platform/graphics/mac/FontMac.mm: Replaced with Source/WebCore/platform/graphics/mac/SimpleFontDataMac.mm.
* platform/win/DragImageWin.cpp:
(WebCore::dragLabelFont):
(WebCore::createDragImageForLink):
* platform/win/PopupMenuWin.cpp:
(WebCore::PopupMenuWin::calculatePositionAndSize):
(WebCore::PopupMenuWin::paint):
* platform/win/WebCoreTextRenderer.cpp:
(WebCore::doDrawTextAtPoint):
(WebCore::WebCoreDrawDoubledTextAtPoint):
(WebCore::WebCoreTextFloatWidth):
(WebCore::WebCoreSetAlwaysUsesComplexTextCodePath):
(WebCore::WebCoreAlwaysUsesComplexTextCodePath):
* rendering/RenderThemeSafari.cpp:
(WebCore::RenderThemeSafari::setFontFromControlSize):</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicscawinPlatformCALayerWincpp">trunk/Source/WebCore/platform/graphics/ca/win/PlatformCALayerWin.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicscawinPlatformCALayerWinInternalcpp">trunk/Source/WebCore/platform/graphics/ca/win/PlatformCALayerWinInternal.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformwinDragImageWincpp">trunk/Source/WebCore/platform/win/DragImageWin.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformwinPopupMenuWincpp">trunk/Source/WebCore/platform/win/PopupMenuWin.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformwinWebCoreTextRenderercpp">trunk/Source/WebCore/platform/win/WebCoreTextRenderer.cpp</a></li>
<li><a href="#trunkSourceWebCorerenderingRenderThemeSafaricpp">trunk/Source/WebCore/rendering/RenderThemeSafari.cpp</a></li>
</ul>
<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreplatformgraphicsFontcpp">trunk/Source/WebCore/platform/graphics/Font.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsFonth">trunk/Source/WebCore/platform/graphics/Font.h</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsFontCascadeFastPathcpp">trunk/Source/WebCore/platform/graphics/FontCascadeFastPath.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsiosFontIOSmm">trunk/Source/WebCore/platform/graphics/ios/FontIOS.mm</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsmacFontCascadeComplexTextMaccpp">trunk/Source/WebCore/platform/graphics/mac/FontCascadeComplexTextMac.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsmacFontCascadeMacmm">trunk/Source/WebCore/platform/graphics/mac/FontCascadeMac.mm</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsmacFontCoreTextcpp">trunk/Source/WebCore/platform/graphics/mac/FontCoreText.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsmacFontMacmm">trunk/Source/WebCore/platform/graphics/mac/FontMac.mm</a></li>
</ul>
<h3>Removed Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreplatformgraphicsmacFontMacmm">trunk/Source/WebCore/platform/graphics/mac/FontMac.mm</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (178517 => 178518)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2015-01-15 19:20:03 UTC (rev 178517)
+++ trunk/Source/WebCore/ChangeLog        2015-01-15 19:29:05 UTC (rev 178518)
</span><span class="lines">@@ -1,3 +1,33 @@
</span><ins>+2015-01-15 Antti Koivisto <antti@apple.com>
+
+ Try to fix windows build.
+
+ * platform/graphics/Font.cpp: Copied from Source/WebCore/platform/graphics/SimpleFontData.cpp.
+ * platform/graphics/Font.h: Copied from Source/WebCore/platform/graphics/SimpleFontData.h.
+ * platform/graphics/FontCascadeFastPath.cpp: Copied from Source/WebCore/platform/graphics/FontFastPath.cpp.
+ * platform/graphics/ca/win/PlatformCALayerWin.cpp:
+ * platform/graphics/ca/win/PlatformCALayerWinInternal.cpp:
+ (PlatformCALayerWinInternal::displayCallback):
+ * platform/graphics/ios/FontIOS.mm: Copied from Source/WebCore/platform/graphics/ios/SimpleFontDataIOS.mm.
+ * platform/graphics/mac/FontCascadeComplexTextMac.cpp: Copied from Source/WebCore/platform/graphics/mac/FontComplexTextMac.cpp.
+ * platform/graphics/mac/FontCascadeMac.mm: Copied from Source/WebCore/platform/graphics/mac/FontMac.mm.
+ * platform/graphics/mac/FontCoreText.cpp: Copied from Source/WebCore/platform/graphics/mac/SimpleFontDataCoreText.cpp.
+ * platform/graphics/mac/FontMac.mm: Replaced with Source/WebCore/platform/graphics/mac/SimpleFontDataMac.mm.
+ * platform/win/DragImageWin.cpp:
+ (WebCore::dragLabelFont):
+ (WebCore::createDragImageForLink):
+ * platform/win/PopupMenuWin.cpp:
+ (WebCore::PopupMenuWin::calculatePositionAndSize):
+ (WebCore::PopupMenuWin::paint):
+ * platform/win/WebCoreTextRenderer.cpp:
+ (WebCore::doDrawTextAtPoint):
+ (WebCore::WebCoreDrawDoubledTextAtPoint):
+ (WebCore::WebCoreTextFloatWidth):
+ (WebCore::WebCoreSetAlwaysUsesComplexTextCodePath):
+ (WebCore::WebCoreAlwaysUsesComplexTextCodePath):
+ * rendering/RenderThemeSafari.cpp:
+ (WebCore::RenderThemeSafari::setFontFromControlSize):
+
</ins><span class="cx"> 2015-01-15 Myles C. Maxfield <mmaxfield@apple.com>
</span><span class="cx">
</span><span class="cx"> http/tests/misc/acid3.html is flakey on Mavericks
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsFontcppfromrev178515trunkSourceWebCoreplatformgraphicsSimpleFontDatacpp"></a>
<div class="copfile"><h4>Copied: trunk/Source/WebCore/platform/graphics/Font.cpp (from rev 178515, trunk/Source/WebCore/platform/graphics/SimpleFontData.cpp) (0 => 178518)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/Font.cpp         (rev 0)
+++ trunk/Source/WebCore/platform/graphics/Font.cpp        2015-01-15 19:29:05 UTC (rev 178518)
</span><span class="lines">@@ -0,0 +1,456 @@
</span><ins>+/*
+ * Copyright (C) 2005, 2008, 2010, 2015 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Alexey Proskuryakov
+ *
+ * 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 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 "SimpleFontData.h"
+
+#if PLATFORM(IOS) || (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED > 1080)
+#include "CoreTextSPI.h"
+#endif
+#include "FontCache.h"
+#include "FontCascade.h"
+#include "OpenTypeMathData.h"
+#include <wtf/MathExtras.h>
+#include <wtf/NeverDestroyed.h>
+
+#if ENABLE(OPENTYPE_VERTICAL)
+#include "OpenTypeVerticalData.h"
+#endif
+
+namespace WebCore {
+
+unsigned GlyphPage::s_count = 0;
+
+const float smallCapsFontSizeMultiplier = 0.7f;
+const float emphasisMarkFontSizeMultiplier = 0.5f;
+
+SimpleFontData::SimpleFontData(const FontPlatformData& platformData, bool isCustomFont, bool isLoading, bool isTextOrientationFallback)
+ : m_maxCharWidth(-1)
+ , m_avgCharWidth(-1)
+ , m_platformData(platformData)
+ , m_treatAsFixedPitch(false)
+ , m_isCustomFont(isCustomFont)
+ , m_isLoading(isLoading)
+ , m_isTextOrientationFallback(isTextOrientationFallback)
+ , m_isBrokenIdeographFallback(false)
+ , m_mathData(nullptr)
+#if ENABLE(OPENTYPE_VERTICAL)
+ , m_verticalData(0)
+#endif
+ , m_hasVerticalGlyphs(false)
+{
+ platformInit();
+ platformGlyphInit();
+ platformCharWidthInit();
+#if ENABLE(OPENTYPE_VERTICAL)
+ if (platformData.orientation() == Vertical && !isTextOrientationFallback) {
+ m_verticalData = platformData.verticalData();
+ m_hasVerticalGlyphs = m_verticalData.get() && m_verticalData->hasVerticalMetrics();
+ }
+#endif
+}
+
+SimpleFontData::SimpleFontData(std::unique_ptr<SVGData> svgData, float fontSize, bool syntheticBold, bool syntheticItalic)
+ : m_platformData(FontPlatformData(fontSize, syntheticBold, syntheticItalic))
+ , m_svgData(WTF::move(svgData))
+ , m_treatAsFixedPitch(false)
+ , m_isCustomFont(true)
+ , m_isLoading(false)
+ , m_isTextOrientationFallback(false)
+ , m_isBrokenIdeographFallback(false)
+ , m_mathData(nullptr)
+#if ENABLE(OPENTYPE_VERTICAL)
+ , m_verticalData(0)
+#endif
+ , m_hasVerticalGlyphs(false)
+#if PLATFORM(IOS)
+ , m_shouldNotBeUsedForArabic(false)
+#endif
+{
+ m_svgData->initializeFontData(this, fontSize);
+}
+
+// Estimates of avgCharWidth and maxCharWidth for platforms that don't support accessing these values from the font.
+void SimpleFontData::initCharWidths()
+{
+ auto* glyphPageZero = glyphPage(0);
+
+ // Treat the width of a '0' as the avgCharWidth.
+ if (m_avgCharWidth <= 0.f && glyphPageZero) {
+ static const UChar32 digitZeroChar = '0';
+ Glyph digitZeroGlyph = glyphPageZero->glyphDataForCharacter(digitZeroChar).glyph;
+ if (digitZeroGlyph)
+ m_avgCharWidth = widthForGlyph(digitZeroGlyph);
+ }
+
+ // If we can't retrieve the width of a '0', fall back to the x height.
+ if (m_avgCharWidth <= 0.f)
+ m_avgCharWidth = m_fontMetrics.xHeight();
+
+ if (m_maxCharWidth <= 0.f)
+ m_maxCharWidth = std::max(m_avgCharWidth, m_fontMetrics.floatAscent());
+}
+
+void SimpleFontData::platformGlyphInit()
+{
+ auto* glyphPageZero = glyphPage(0);
+ if (!glyphPageZero) {
+ m_spaceGlyph = 0;
+ m_spaceWidth = 0;
+ m_zeroGlyph = 0;
+ m_adjustedSpaceWidth = 0;
+ determinePitch();
+ m_zeroWidthSpaceGlyph = 0;
+ return;
+ }
+
+ // Ask for the glyph for 0 to avoid paging in ZERO WIDTH SPACE. Control characters, including 0,
+ // are mapped to the ZERO WIDTH SPACE glyph.
+ m_zeroWidthSpaceGlyph = glyphPageZero->glyphDataForCharacter(0).glyph;
+
+ // Nasty hack to determine if we should round or ceil space widths.
+ // If the font is monospace or fake monospace we ceil to ensure that
+ // every character and the space are the same width. Otherwise we round.
+ m_spaceGlyph = glyphPageZero->glyphDataForCharacter(' ').glyph;
+ float width = widthForGlyph(m_spaceGlyph);
+ m_spaceWidth = width;
+ m_zeroGlyph = glyphPageZero->glyphDataForCharacter('0').glyph;
+ m_fontMetrics.setZeroWidth(widthForGlyph(m_zeroGlyph));
+ determinePitch();
+ m_adjustedSpaceWidth = m_treatAsFixedPitch ? ceilf(width) : roundf(width);
+
+ // Force the glyph for ZERO WIDTH SPACE to have zero width, unless it is shared with SPACE.
+ // Helvetica is an example of a non-zero width ZERO WIDTH SPACE glyph.
+ // See <http://bugs.webkit.org/show_bug.cgi?id=13178> and SimpleFontData::isZeroWidthSpaceGlyph()
+ if (m_zeroWidthSpaceGlyph == m_spaceGlyph)
+ m_zeroWidthSpaceGlyph = 0;
+}
+
+SimpleFontData::~SimpleFontData()
+{
+ removeFromSystemFallbackCache();
+}
+
+static bool fillGlyphPage(GlyphPage& pageToFill, unsigned offset, unsigned length, UChar* buffer, unsigned bufferLength, const SimpleFontData* fontData)
+{
+#if ENABLE(SVG_FONTS)
+ if (auto* svgData = fontData->svgData())
+ return svgData->fillSVGGlyphPage(&pageToFill, offset, length, buffer, bufferLength, fontData);
+#endif
+ bool hasGlyphs = pageToFill.fill(offset, length, buffer, bufferLength, fontData);
+#if ENABLE(OPENTYPE_VERTICAL)
+ if (hasGlyphs && fontData->verticalData())
+ fontData->verticalData()->substituteWithVerticalGlyphs(fontData, &pageToFill, offset, length);
+#endif
+ return hasGlyphs;
+}
+
+static RefPtr<GlyphPage> createAndFillGlyphPage(unsigned pageNumber, const SimpleFontData* fontData)
+{
+#if PLATFORM(IOS)
+ // FIXME: Times New Roman contains Arabic glyphs, but Core Text doesn't know how to shape them. See <rdar://problem/9823975>.
+ // Once we have the fix for <rdar://problem/9823975> then remove this code together with SimpleFontData::shouldNotBeUsedForArabic()
+ // in <rdar://problem/12096835>.
+ if (pageNumber == 6 && fontData->shouldNotBeUsedForArabic())
+ return nullptr;
+#endif
+
+ unsigned start = pageNumber * GlyphPage::size;
+ UChar buffer[GlyphPage::size * 2 + 2];
+ unsigned bufferLength;
+ // Fill in a buffer with the entire "page" of characters that we want to look up glyphs for.
+ if (U_IS_BMP(start)) {
+ bufferLength = GlyphPage::size;
+ for (unsigned i = 0; i < GlyphPage::size; i++)
+ buffer[i] = start + i;
+
+ if (start == 0) {
+ // Control characters must not render at all.
+ for (unsigned i = 0; i < 0x20; ++i)
+ buffer[i] = zeroWidthSpace;
+ for (unsigned i = 0x7F; i < 0xA0; i++)
+ buffer[i] = zeroWidthSpace;
+ buffer[softHyphen] = zeroWidthSpace;
+
+ // \n, \t, and nonbreaking space must render as a space.
+ buffer[(int)'\n'] = ' ';
+ buffer[(int)'\t'] = ' ';
+ buffer[noBreakSpace] = ' ';
+ } else if (start == (leftToRightMark & ~(GlyphPage::size - 1))) {
+ // LRM, RLM, LRE, RLE, ZWNJ, ZWJ, and PDF must not render at all.
+ buffer[leftToRightMark - start] = zeroWidthSpace;
+ buffer[rightToLeftMark - start] = zeroWidthSpace;
+ buffer[leftToRightEmbed - start] = zeroWidthSpace;
+ buffer[rightToLeftEmbed - start] = zeroWidthSpace;
+ buffer[leftToRightOverride - start] = zeroWidthSpace;
+ buffer[rightToLeftOverride - start] = zeroWidthSpace;
+ buffer[zeroWidthNonJoiner - start] = zeroWidthSpace;
+ buffer[zeroWidthJoiner - start] = zeroWidthSpace;
+ buffer[popDirectionalFormatting - start] = zeroWidthSpace;
+ } else if (start == (objectReplacementCharacter & ~(GlyphPage::size - 1))) {
+ // Object replacement character must not render at all.
+ buffer[objectReplacementCharacter - start] = zeroWidthSpace;
+ } else if (start == (zeroWidthNoBreakSpace & ~(GlyphPage::size - 1))) {
+ // ZWNBS/BOM must not render at all.
+ buffer[zeroWidthNoBreakSpace - start] = zeroWidthSpace;
+ }
+ } else {
+ bufferLength = GlyphPage::size * 2;
+ for (unsigned i = 0; i < GlyphPage::size; i++) {
+ int c = i + start;
+ buffer[i * 2] = U16_LEAD(c);
+ buffer[i * 2 + 1] = U16_TRAIL(c);
+ }
+ }
+
+ // Now that we have a buffer full of characters, we want to get back an array
+ // of glyph indices. This part involves calling into the platform-specific
+ // routine of our glyph map for actually filling in the page with the glyphs.
+ // Success is not guaranteed. For example, Times fails to fill page 260, giving glyph data
+ // for only 128 out of 256 characters.
+ RefPtr<GlyphPage> glyphPage;
+ if (GlyphPage::mayUseMixedFontDataWhenFilling(buffer, bufferLength, fontData))
+ glyphPage = GlyphPage::createForMixedFontData();
+ else
+ glyphPage = GlyphPage::createForSingleFontData(fontData);
+
+ bool haveGlyphs = fillGlyphPage(*glyphPage, 0, GlyphPage::size, buffer, bufferLength, fontData);
+ if (!haveGlyphs)
+ return nullptr;
+
+ glyphPage->setImmutable();
+ return glyphPage;
+}
+
+const GlyphPage* SimpleFontData::glyphPage(unsigned pageNumber) const
+{
+ if (pageNumber == 0) {
+ if (!m_glyphPageZero)
+ m_glyphPageZero = createAndFillGlyphPage(0, this);
+ return m_glyphPageZero.get();
+ }
+ auto addResult = m_glyphPages.add(pageNumber, nullptr);
+ if (addResult.isNewEntry)
+ addResult.iterator->value = createAndFillGlyphPage(pageNumber, this);
+
+ return addResult.iterator->value.get();
+}
+
+Glyph SimpleFontData::glyphForCharacter(UChar32 character) const
+{
+ auto* page = glyphPage(character / GlyphPage::size);
+ if (!page)
+ return 0;
+ return page->glyphAt(character % GlyphPage::size);
+}
+
+GlyphData SimpleFontData::glyphDataForCharacter(UChar32 character) const
+{
+ auto* page = glyphPage(character / GlyphPage::size);
+ if (!page)
+ return GlyphData();
+ return page->glyphDataForCharacter(character);
+}
+
+PassRefPtr<SimpleFontData> SimpleFontData::verticalRightOrientationFontData() const
+{
+ if (!m_derivedFontData)
+ m_derivedFontData = std::make_unique<DerivedFontData>(isCustomFont());
+ if (!m_derivedFontData->verticalRightOrientation) {
+ FontPlatformData verticalRightPlatformData(m_platformData);
+ verticalRightPlatformData.setOrientation(Horizontal);
+ m_derivedFontData->verticalRightOrientation = create(verticalRightPlatformData, isCustomFont(), false, true);
+ }
+ return m_derivedFontData->verticalRightOrientation;
+}
+
+PassRefPtr<SimpleFontData> SimpleFontData::uprightOrientationFontData() const
+{
+ if (!m_derivedFontData)
+ m_derivedFontData = std::make_unique<DerivedFontData>(isCustomFont());
+ if (!m_derivedFontData->uprightOrientation)
+ m_derivedFontData->uprightOrientation = create(m_platformData, isCustomFont(), false, true);
+ return m_derivedFontData->uprightOrientation;
+}
+
+PassRefPtr<SimpleFontData> SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const
+{
+ if (!m_derivedFontData)
+ m_derivedFontData = std::make_unique<DerivedFontData>(isCustomFont());
+ if (!m_derivedFontData->smallCaps)
+ m_derivedFontData->smallCaps = createScaledFontData(fontDescription, smallCapsFontSizeMultiplier);
+
+ return m_derivedFontData->smallCaps;
+}
+
+PassRefPtr<SimpleFontData> SimpleFontData::emphasisMarkFontData(const FontDescription& fontDescription) const
+{
+ if (!m_derivedFontData)
+ m_derivedFontData = std::make_unique<DerivedFontData>(isCustomFont());
+ if (!m_derivedFontData->emphasisMark)
+ m_derivedFontData->emphasisMark = createScaledFontData(fontDescription, emphasisMarkFontSizeMultiplier);
+
+ return m_derivedFontData->emphasisMark;
+}
+
+PassRefPtr<SimpleFontData> SimpleFontData::brokenIdeographFontData() const
+{
+ if (!m_derivedFontData)
+ m_derivedFontData = std::make_unique<DerivedFontData>(isCustomFont());
+ if (!m_derivedFontData->brokenIdeograph) {
+ m_derivedFontData->brokenIdeograph = create(m_platformData, isCustomFont(), false);
+ m_derivedFontData->brokenIdeograph->m_isBrokenIdeographFallback = true;
+ }
+ return m_derivedFontData->brokenIdeograph;
+}
+
+PassRefPtr<SimpleFontData> SimpleFontData::nonSyntheticItalicFontData() const
+{
+ if (!m_derivedFontData)
+ m_derivedFontData = std::make_unique<DerivedFontData>(isCustomFont());
+ if (!m_derivedFontData->nonSyntheticItalic) {
+ FontPlatformData nonSyntheticItalicFontPlatformData(m_platformData);
+#if PLATFORM(COCOA)
+ nonSyntheticItalicFontPlatformData.m_syntheticOblique = false;
+#endif
+ m_derivedFontData->nonSyntheticItalic = create(nonSyntheticItalicFontPlatformData, isCustomFont());
+ }
+ return m_derivedFontData->nonSyntheticItalic;
+}
+
+#ifndef NDEBUG
+String SimpleFontData::description() const
+{
+ if (isSVGFont())
+ return "[SVG font]";
+ if (isCustomFont())
+ return "[custom font]";
+
+ return platformData().description();
+}
+#endif
+
+const OpenTypeMathData* SimpleFontData::mathData() const
+{
+ if (m_isLoading)
+ return nullptr;
+ if (!m_mathData) {
+ m_mathData = OpenTypeMathData::create(m_platformData);
+ if (!m_mathData->hasMathData())
+ m_mathData.clear();
+ }
+ return m_mathData.get();
+}
+
+SimpleFontData::DerivedFontData::~DerivedFontData()
+{
+}
+
+PassRefPtr<SimpleFontData> SimpleFontData::createScaledFontData(const FontDescription& fontDescription, float scaleFactor) const
+{
+ if (isSVGFont())
+ return nullptr;
+
+ return platformCreateScaledFontData(fontDescription, scaleFactor);
+}
+
+bool SimpleFontData::applyTransforms(GlyphBufferGlyph* glyphs, GlyphBufferAdvance* advances, size_t glyphCount, TypesettingFeatures typesettingFeatures) const
+{
+ // We need to handle transforms on SVG fonts internally, since they are rendered internally.
+ ASSERT(!isSVGFont());
+#if PLATFORM(IOS) || (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED > 1080)
+ CTFontTransformOptions options = (typesettingFeatures & Kerning ? kCTFontTransformApplyPositioning : 0) | (typesettingFeatures & Ligatures ? kCTFontTransformApplyShaping : 0);
+ return CTFontTransformGlyphs(m_platformData.ctFont(), glyphs, reinterpret_cast<CGSize*>(advances), glyphCount, options);
+#else
+ UNUSED_PARAM(glyphs);
+ UNUSED_PARAM(advances);
+ UNUSED_PARAM(glyphCount);
+ UNUSED_PARAM(typesettingFeatures);
+ return false;
+#endif
+}
+
+// FontDatas are not refcounted to avoid cycles.
+typedef HashMap<std::pair<UChar32, unsigned>, SimpleFontData*> CharacterFallbackMap;
+typedef HashMap<const SimpleFontData*, CharacterFallbackMap> SystemFallbackCache;
+
+static SystemFallbackCache& systemFallbackCache()
+{
+ static NeverDestroyed<SystemFallbackCache> map;
+ return map.get();
+}
+
+RefPtr<SimpleFontData> SimpleFontData::systemFallbackFontDataForCharacter(UChar32 character, const FontDescription& description, bool isForPlatformFont) const
+{
+ auto fontAddResult = systemFallbackCache().add(this, CharacterFallbackMap());
+
+ auto key = std::make_pair(character, isForPlatformFont);
+ auto characterAddResult = fontAddResult.iterator->value.add(key, nullptr);
+
+ SimpleFontData*& fallbackFontData = characterAddResult.iterator->value;
+
+ if (!fallbackFontData) {
+ UChar codeUnits[2];
+ int codeUnitsLength;
+ if (U_IS_BMP(character)) {
+ codeUnits[0] = FontCascade::normalizeSpaces(character);
+ codeUnitsLength = 1;
+ } else {
+ codeUnits[0] = U16_LEAD(character);
+ codeUnits[1] = U16_TRAIL(character);
+ codeUnitsLength = 2;
+ }
+
+ fallbackFontData = fontCache().systemFallbackForCharacters(description, this, isForPlatformFont, codeUnits, codeUnitsLength).get();
+ if (fallbackFontData)
+ fallbackFontData->m_isUsedInSystemFallbackCache = true;
+ }
+
+ return fallbackFontData;
+}
+
+void SimpleFontData::removeFromSystemFallbackCache()
+{
+ systemFallbackCache().remove(this);
+
+ if (!m_isUsedInSystemFallbackCache)
+ return;
+
+ for (auto& characterMap : systemFallbackCache().values()) {
+ Vector<std::pair<UChar32, unsigned>, 512> toRemove;
+ for (auto& entry : characterMap) {
+ if (entry.value == this)
+ toRemove.append(entry.key);
+ }
+ for (auto& key : toRemove)
+ characterMap.remove(key);
+ }
+}
+
+} // namespace WebCore
</ins></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsFonthfromrev178515trunkSourceWebCoreplatformgraphicsSimpleFontDatah"></a>
<div class="copfile"><h4>Copied: trunk/Source/WebCore/platform/graphics/Font.h (from rev 178515, trunk/Source/WebCore/platform/graphics/SimpleFontData.h) (0 => 178518)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/Font.h         (rev 0)
+++ trunk/Source/WebCore/platform/graphics/Font.h        2015-01-15 19:29:05 UTC (rev 178518)
</span><span class="lines">@@ -0,0 +1,369 @@
</span><ins>+/*
+ * This file is part of the internal font implementation.
+ *
+ * Copyright (C) 2006, 2008, 2010, 2015 Apple Inc. All rights reserved.
+ * Copyright (C) 2007-2008 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.
+ *
+ */
+
+#ifndef SimpleFontData_h
+#define SimpleFontData_h
+
+#include "FontBaseline.h"
+#include "FontMetrics.h"
+#include "FontPlatformData.h"
+#include "FloatRect.h"
+#include "GlyphBuffer.h"
+#include "GlyphMetricsMap.h"
+#include "GlyphPage.h"
+#include "OpenTypeMathData.h"
+#if ENABLE(OPENTYPE_VERTICAL)
+#include "OpenTypeVerticalData.h"
+#endif
+#include "TypesettingFeatures.h"
+#include <wtf/TypeCasts.h>
+#include <wtf/text/StringHash.h>
+
+#if PLATFORM(COCOA)
+#include "WebCoreSystemInterface.h"
+#include <wtf/RetainPtr.h>
+#endif
+
+#if PLATFORM(WIN)
+#include <usp10.h>
+#endif
+
+#if USE(CAIRO)
+#include <cairo.h>
+#endif
+
+#if USE(CG)
+#include <WebCore/CoreGraphicsSPI.h>
+#endif
+
+namespace WebCore {
+
+class GlyphPage;
+class FontDescription;
+class SharedBuffer;
+struct GlyphData;
+struct WidthIterator;
+
+enum FontDataVariant { AutoVariant, NormalVariant, SmallCapsVariant, EmphasisMarkVariant, BrokenIdeographVariant };
+enum Pitch { UnknownPitch, FixedPitch, VariablePitch };
+
+class SimpleFontData : public RefCounted<SimpleFontData> {
+public:
+ class SVGData {
+ WTF_MAKE_FAST_ALLOCATED;
+ public:
+ virtual ~SVGData() { }
+
+ virtual void initializeFontData(SimpleFontData*, float fontSize) = 0;
+ virtual float widthForSVGGlyph(Glyph, float fontSize) const = 0;
+ virtual bool fillSVGGlyphPage(GlyphPage*, unsigned offset, unsigned length, UChar* buffer, unsigned bufferLength, const SimpleFontData*) const = 0;
+ };
+
+ // Used to create platform fonts.
+ static Ref<SimpleFontData> create(const FontPlatformData& platformData, bool isCustomFont = false, bool isLoading = false, bool isTextOrientationFallback = false)
+ {
+ return adoptRef(*new SimpleFontData(platformData, isCustomFont, isLoading, isTextOrientationFallback));
+ }
+
+ // Used to create SVG Fonts.
+ static Ref<SimpleFontData> create(std::unique_ptr<SVGData> svgData, float fontSize, bool syntheticBold, bool syntheticItalic)
+ {
+ return adoptRef(*new SimpleFontData(WTF::move(svgData), fontSize, syntheticBold, syntheticItalic));
+ }
+
+ ~SimpleFontData();
+
+ static const SimpleFontData* systemFallback() { return reinterpret_cast<const SimpleFontData*>(-1); }
+
+ const FontPlatformData& platformData() const { return m_platformData; }
+ const OpenTypeMathData* mathData() const;
+#if ENABLE(OPENTYPE_VERTICAL)
+ const OpenTypeVerticalData* verticalData() const { return m_verticalData.get(); }
+#endif
+
+ PassRefPtr<SimpleFontData> smallCapsFontData(const FontDescription&) const;
+ PassRefPtr<SimpleFontData> emphasisMarkFontData(const FontDescription&) const;
+ PassRefPtr<SimpleFontData> brokenIdeographFontData() const;
+ PassRefPtr<SimpleFontData> nonSyntheticItalicFontData() const;
+
+ PassRefPtr<SimpleFontData> variantFontData(const FontDescription& description, FontDataVariant variant) const
+ {
+ switch (variant) {
+ case SmallCapsVariant:
+ return smallCapsFontData(description);
+ case EmphasisMarkVariant:
+ return emphasisMarkFontData(description);
+ case BrokenIdeographVariant:
+ return brokenIdeographFontData();
+ case AutoVariant:
+ case NormalVariant:
+ break;
+ }
+ ASSERT_NOT_REACHED();
+ return const_cast<SimpleFontData*>(this);
+ }
+
+ PassRefPtr<SimpleFontData> verticalRightOrientationFontData() const;
+ PassRefPtr<SimpleFontData> uprightOrientationFontData() const;
+
+ bool hasVerticalGlyphs() const { return m_hasVerticalGlyphs; }
+ bool isTextOrientationFallback() const { return m_isTextOrientationFallback; }
+
+ FontMetrics& fontMetrics() { return m_fontMetrics; }
+ const FontMetrics& fontMetrics() const { return m_fontMetrics; }
+ float sizePerUnit() const { return platformData().size() / (fontMetrics().unitsPerEm() ? fontMetrics().unitsPerEm() : 1); }
+
+ float maxCharWidth() const { return m_maxCharWidth; }
+ void setMaxCharWidth(float maxCharWidth) { m_maxCharWidth = maxCharWidth; }
+
+ float avgCharWidth() const { return m_avgCharWidth; }
+ void setAvgCharWidth(float avgCharWidth) { m_avgCharWidth = avgCharWidth; }
+
+ FloatRect boundsForGlyph(Glyph) const;
+ float widthForGlyph(Glyph glyph) const;
+ FloatRect platformBoundsForGlyph(Glyph) const;
+ float platformWidthForGlyph(Glyph) const;
+
+ float spaceWidth() const { return m_spaceWidth; }
+ float adjustedSpaceWidth() const { return m_adjustedSpaceWidth; }
+ void setSpaceWidths(float spaceWidth)
+ {
+ m_spaceWidth = spaceWidth;
+ m_adjustedSpaceWidth = spaceWidth;
+ }
+
+#if USE(CG) || USE(CAIRO)
+ float syntheticBoldOffset() const { return m_syntheticBoldOffset; }
+#endif
+
+ Glyph spaceGlyph() const { return m_spaceGlyph; }
+ void setSpaceGlyph(Glyph spaceGlyph) { m_spaceGlyph = spaceGlyph; }
+ Glyph zeroWidthSpaceGlyph() const { return m_zeroWidthSpaceGlyph; }
+ void setZeroWidthSpaceGlyph(Glyph spaceGlyph) { m_zeroWidthSpaceGlyph = spaceGlyph; }
+ bool isZeroWidthSpaceGlyph(Glyph glyph) const { return glyph == m_zeroWidthSpaceGlyph && glyph; }
+ Glyph zeroGlyph() const { return m_zeroGlyph; }
+ void setZeroGlyph(Glyph zeroGlyph) { m_zeroGlyph = zeroGlyph; }
+
+ GlyphData glyphDataForCharacter(UChar32) const;
+ Glyph glyphForCharacter(UChar32) const;
+
+ RefPtr<SimpleFontData> systemFallbackFontDataForCharacter(UChar32, const FontDescription&, bool isForPlatformFont) const;
+
+ const GlyphPage* glyphPage(unsigned pageNumber) const;
+
+ void determinePitch();
+ Pitch pitch() const { return m_treatAsFixedPitch ? FixedPitch : VariablePitch; }
+
+ const SVGData* svgData() const { return m_svgData.get(); }
+ bool isSVGFont() const { return !!m_svgData; }
+
+ bool isCustomFont() const { return m_isCustomFont; }
+ bool isLoading() const { return m_isLoading; }
+
+#ifndef NDEBUG
+ String description() const;
+#endif
+
+#if USE(APPKIT)
+ const SimpleFontData* compositeFontReferenceFontData(NSFont *key) const;
+ NSFont* getNSFont() const { return m_platformData.nsFont(); }
+#endif
+
+#if PLATFORM(IOS)
+ CTFontRef getCTFont() const { return m_platformData.font(); }
+ bool shouldNotBeUsedForArabic() const { return m_shouldNotBeUsedForArabic; };
+#endif
+#if PLATFORM(COCOA)
+ CFDictionaryRef getCFStringAttributes(TypesettingFeatures, FontOrientation) const;
+#endif
+
+#if PLATFORM(COCOA) || USE(HARFBUZZ)
+ bool canRenderCombiningCharacterSequence(const UChar*, size_t) const;
+#endif
+
+ bool applyTransforms(GlyphBufferGlyph*, GlyphBufferAdvance*, size_t glyphCount, TypesettingFeatures) const;
+
+#if PLATFORM(WIN)
+ bool isSystemFont() const { return m_isSystemFont; }
+ SCRIPT_FONTPROPERTIES* scriptFontProperties() const;
+ SCRIPT_CACHE* scriptCache() const { return &m_scriptCache; }
+ static void setShouldApplyMacAscentHack(bool);
+ static bool shouldApplyMacAscentHack();
+ static float ascentConsideringMacAscentHack(const WCHAR*, float ascent, float descent);
+#endif
+
+private:
+ SimpleFontData(const FontPlatformData&, bool isCustomFont = false, bool isLoading = false, bool isTextOrientationFallback = false);
+
+ SimpleFontData(std::unique_ptr<SVGData>, float fontSize, bool syntheticBold, bool syntheticItalic);
+
+ void platformInit();
+ void platformGlyphInit();
+ void platformCharWidthInit();
+ void platformDestroy();
+
+ void initCharWidths();
+
+ PassRefPtr<SimpleFontData> createScaledFontData(const FontDescription&, float scaleFactor) const;
+ PassRefPtr<SimpleFontData> platformCreateScaledFontData(const FontDescription&, float scaleFactor) const;
+
+ void removeFromSystemFallbackCache();
+
+#if PLATFORM(WIN)
+ void initGDIFont();
+ void platformCommonDestroy();
+ FloatRect boundsForGDIGlyph(Glyph glyph) const;
+ float widthForGDIGlyph(Glyph glyph) const;
+#endif
+
+#if USE(CG)
+ bool canUseFastGlyphAdvanceGetter(Glyph glyph, CGSize& advance, bool& populatedAdvance) const;
+ CGFontRenderingStyle renderingStyle() const;
+ bool advanceForColorBitmapFont(Glyph, CGSize& result) const; // Returns true if the font is a color bitmap font
+#endif
+
+ FontMetrics m_fontMetrics;
+ float m_maxCharWidth;
+ float m_avgCharWidth;
+
+ FontPlatformData m_platformData;
+ std::unique_ptr<SVGData> m_svgData;
+
+ mutable RefPtr<GlyphPage> m_glyphPageZero;
+ mutable HashMap<unsigned, RefPtr<GlyphPage>> m_glyphPages;
+ mutable std::unique_ptr<GlyphMetricsMap<FloatRect>> m_glyphToBoundsMap;
+ mutable GlyphMetricsMap<float> m_glyphToWidthMap;
+
+ bool m_treatAsFixedPitch;
+ bool m_isCustomFont; // Whether or not we are custom font loaded via @font-face
+ bool m_isLoading; // Whether or not this custom font is still in the act of loading.
+
+ bool m_isTextOrientationFallback;
+ bool m_isBrokenIdeographFallback;
+
+ bool m_isUsedInSystemFallbackCache { false };
+
+ mutable RefPtr<OpenTypeMathData> m_mathData;
+#if ENABLE(OPENTYPE_VERTICAL)
+ RefPtr<OpenTypeVerticalData> m_verticalData;
+#endif
+ bool m_hasVerticalGlyphs;
+
+ Glyph m_spaceGlyph;
+ float m_spaceWidth;
+ Glyph m_zeroGlyph;
+ float m_adjustedSpaceWidth;
+
+ Glyph m_zeroWidthSpaceGlyph;
+
+ struct DerivedFontData {
+ explicit DerivedFontData(bool custom)
+ : forCustomFont(custom)
+ {
+ }
+ ~DerivedFontData();
+
+ bool forCustomFont;
+ RefPtr<SimpleFontData> smallCaps;
+ RefPtr<SimpleFontData> emphasisMark;
+ RefPtr<SimpleFontData> brokenIdeograph;
+ RefPtr<SimpleFontData> verticalRightOrientation;
+ RefPtr<SimpleFontData> uprightOrientation;
+ RefPtr<SimpleFontData> nonSyntheticItalic;
+#if USE(APPKIT)
+ HashMap<NSFont*, RefPtr<SimpleFontData>> compositeFontReferences;
+#endif
+ };
+
+ mutable std::unique_ptr<DerivedFontData> m_derivedFontData;
+
+#if USE(CG) || USE(CAIRO)
+ float m_syntheticBoldOffset;
+#endif
+
+#if PLATFORM(COCOA)
+ mutable HashMap<unsigned, RetainPtr<CFDictionaryRef>> m_CFStringAttributes;
+#endif
+
+#if PLATFORM(COCOA) || USE(HARFBUZZ)
+ mutable std::unique_ptr<HashMap<String, bool>> m_combiningCharacterSequenceSupport;
+#endif
+
+#if PLATFORM(WIN)
+ bool m_isSystemFont;
+ mutable SCRIPT_CACHE m_scriptCache;
+ mutable SCRIPT_FONTPROPERTIES* m_scriptFontProperties;
+#endif
+#if PLATFORM(IOS)
+ bool m_shouldNotBeUsedForArabic;
+#endif
+};
+
+ALWAYS_INLINE FloatRect SimpleFontData::boundsForGlyph(Glyph glyph) const
+{
+ if (isZeroWidthSpaceGlyph(glyph))
+ return FloatRect();
+
+ FloatRect bounds;
+ if (m_glyphToBoundsMap) {
+ bounds = m_glyphToBoundsMap->metricsForGlyph(glyph);
+ if (bounds.width() != cGlyphSizeUnknown)
+ return bounds;
+ }
+
+ bounds = platformBoundsForGlyph(glyph);
+ if (!m_glyphToBoundsMap)
+ m_glyphToBoundsMap = std::make_unique<GlyphMetricsMap<FloatRect>>();
+ m_glyphToBoundsMap->setMetricsForGlyph(glyph, bounds);
+ return bounds;
+}
+
+ALWAYS_INLINE float SimpleFontData::widthForGlyph(Glyph glyph) const
+{
+ if (isZeroWidthSpaceGlyph(glyph))
+ return 0;
+
+ float width = m_glyphToWidthMap.metricsForGlyph(glyph);
+ if (width != cGlyphSizeUnknown)
+ return width;
+
+ if (isSVGFont())
+ width = m_svgData->widthForSVGGlyph(glyph, m_platformData.size());
+#if ENABLE(OPENTYPE_VERTICAL)
+ else if (m_verticalData)
+#if USE(CG) || USE(CAIRO)
+ width = m_verticalData->advanceHeight(this, glyph) + m_syntheticBoldOffset;
+#else
+ width = m_verticalData->advanceHeight(this, glyph);
+#endif
+#endif
+ else
+ width = platformWidthForGlyph(glyph);
+
+ m_glyphToWidthMap.setMetricsForGlyph(glyph, width);
+ return width;
+}
+
+} // namespace WebCore
+
+#endif // SimpleFontData_h
</ins></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsFontCascadeFastPathcppfromrev178510trunkSourceWebCoreplatformgraphicsFontFastPathcpp"></a>
<div class="copfile"><h4>Copied: trunk/Source/WebCore/platform/graphics/FontCascadeFastPath.cpp (from rev 178510, trunk/Source/WebCore/platform/graphics/FontFastPath.cpp) (0 => 178518)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/FontCascadeFastPath.cpp         (rev 0)
+++ trunk/Source/WebCore/platform/graphics/FontCascadeFastPath.cpp        2015-01-15 19:29:05 UTC (rev 178518)
</span><span class="lines">@@ -0,0 +1,341 @@
</span><ins>+/**
+ * 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 "FontCascade.h"
+
+#include "FloatRect.h"
+#include "FontGlyphs.h"
+#include "GlyphBuffer.h"
+#include "LayoutRect.h"
+#include "SimpleFontData.h"
+#include "TextRun.h"
+#include "WidthIterator.h"
+#include <wtf/MainThread.h>
+#include <wtf/MathExtras.h>
+#include <wtf/unicode/CharacterNames.h>
+
+using namespace WTF;
+using namespace Unicode;
+
+namespace WebCore {
+
+// FIXME: This function may not work if the emphasis mark uses a complex script, but none of the
+// standard emphasis marks do so.
+bool FontCascade::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 FontCascade::emphasisMarkAscent(const AtomicString& mark) const
+{
+ GlyphData markGlyphData;
+ if (!getEmphasisMarkGlyphData(mark, markGlyphData))
+ return 0;
+
+ const SimpleFontData* markFontData = markGlyphData.fontData;
+ ASSERT(markFontData);
+ if (!markFontData)
+ return 0;
+
+ return markFontData->fontMetrics().ascent();
+}
+
+int FontCascade::emphasisMarkDescent(const AtomicString& mark) const
+{
+ GlyphData markGlyphData;
+ if (!getEmphasisMarkGlyphData(mark, markGlyphData))
+ return 0;
+
+ const SimpleFontData* markFontData = markGlyphData.fontData;
+ ASSERT(markFontData);
+ if (!markFontData)
+ return 0;
+
+ return markFontData->fontMetrics().descent();
+}
+
+int FontCascade::emphasisMarkHeight(const AtomicString& mark) const
+{
+ GlyphData markGlyphData;
+ if (!getEmphasisMarkGlyphData(mark, markGlyphData))
+ return 0;
+
+ const SimpleFontData* markFontData = markGlyphData.fontData;
+ ASSERT(markFontData);
+ if (!markFontData)
+ return 0;
+
+ return markFontData->fontMetrics().height();
+}
+
+float FontCascade::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;
+}
+
+float FontCascade::drawSimpleText(GraphicsContext* context, const TextRun& run, const FloatPoint& point, int from, int to) const
+{
+ // This glyph buffer holds our glyphs+advances+font data for each glyph.
+ GlyphBuffer glyphBuffer;
+
+ float startX = point.x() + getGlyphsAndAdvancesForSimpleText(run, from, to, glyphBuffer);
+
+ if (glyphBuffer.isEmpty())
+ return 0;
+
+ FloatPoint startPoint(startX, point.y());
+ drawGlyphBuffer(context, run, glyphBuffer, startPoint);
+
+ return startPoint.x() - startX;
+}
+
+void FontCascade::drawEmphasisMarksForSimpleText(GraphicsContext* context, const TextRun& run, const AtomicString& mark, const FloatPoint& point, int from, int to) const
+{
+ GlyphBuffer glyphBuffer;
+ float initialAdvance = getGlyphsAndAdvancesForSimpleText(run, from, to, glyphBuffer, ForTextEmphasis);
+
+ if (glyphBuffer.isEmpty())
+ return;
+
+ drawEmphasisMarks(context, run, glyphBuffer, mark, FloatPoint(point.x() + initialAdvance, point.y()));
+}
+
+void FontCascade::drawGlyphBuffer(GraphicsContext* context, const TextRun& run, const GlyphBuffer& glyphBuffer, FloatPoint& point) const
+{
+#if !ENABLE(SVG_FONTS)
+ UNUSED_PARAM(run);
+#endif
+
+ // Draw each contiguous run of glyphs that use the same font data.
+ const SimpleFontData* fontData = glyphBuffer.fontDataAt(0);
+ FloatSize offset = glyphBuffer.offsetAt(0);
+ FloatPoint startPoint(point.x(), point.y() - glyphBuffer.initialAdvance().height());
+ float nextX = startPoint.x() + glyphBuffer.advanceAt(0).width();
+ float nextY = startPoint.y() + glyphBuffer.advanceAt(0).height();
+ int lastFrom = 0;
+ int nextGlyph = 1;
+#if ENABLE(SVG_FONTS)
+ TextRun::RenderingContext* renderingContext = run.renderingContext();
+#endif
+ while (nextGlyph < glyphBuffer.size()) {
+ const SimpleFontData* nextFontData = glyphBuffer.fontDataAt(nextGlyph);
+ FloatSize nextOffset = glyphBuffer.offsetAt(nextGlyph);
+
+ if (nextFontData != fontData || nextOffset != offset) {
+#if ENABLE(SVG_FONTS)
+ if (renderingContext && fontData->isSVGFont())
+ renderingContext->drawSVGGlyphs(context, fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, startPoint);
+ else
+#endif
+ drawGlyphs(context, fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, startPoint);
+
+ lastFrom = nextGlyph;
+ fontData = nextFontData;
+ offset = nextOffset;
+ startPoint.setX(nextX);
+ startPoint.setY(nextY);
+ }
+ nextX += glyphBuffer.advanceAt(nextGlyph).width();
+ nextY += glyphBuffer.advanceAt(nextGlyph).height();
+ nextGlyph++;
+ }
+
+#if ENABLE(SVG_FONTS)
+ if (renderingContext && fontData->isSVGFont())
+ renderingContext->drawSVGGlyphs(context, fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, startPoint);
+ else
+#endif
+ {
+ drawGlyphs(context, fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, startPoint);
+ point.setX(nextX);
+ }
+}
+
+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 FontCascade::drawEmphasisMarks(GraphicsContext* context, const TextRun& run, const GlyphBuffer& glyphBuffer, const AtomicString& mark, const FloatPoint& point) const
+{
+ 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 (int i = 0; i + 1 < glyphBuffer.size(); ++i) {
+ float middleOfNextGlyph = offsetToMiddleOfGlyphAtIndex(glyphBuffer, i + 1);
+ float advance = glyphBuffer.advanceAt(i).width() - 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, run, markBuffer, startPoint);
+}
+
+float FontCascade::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 = std::max<int>(glyphOverflow->top, ceilf(-it.minGlyphBoundingBoxY()) - (glyphOverflow->computeBounds ? 0 : fontMetrics().ascent()));
+ glyphOverflow->bottom = std::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;
+}
+
+void FontCascade::adjustSelectionRectForSimpleText(const TextRun& run, LayoutRect& selectionRect, 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;
+ float totalWidth = -1;
+
+ if (run.rtl()) {
+ it.advance(run.length(), &glyphBuffer);
+ totalWidth = it.m_runWidthSoFar;
+ selectionRect.move(totalWidth - afterWidth, 0);
+ } else
+ selectionRect.move(beforeWidth, 0);
+ selectionRect.setWidth(afterWidth - beforeWidth);
+}
+
+int FontCascade::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;
+}
+
+}
</ins></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicscawinPlatformCALayerWincpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/ca/win/PlatformCALayerWin.cpp (178517 => 178518)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/ca/win/PlatformCALayerWin.cpp        2015-01-15 19:20:03 UTC (rev 178517)
+++ trunk/Source/WebCore/platform/graphics/ca/win/PlatformCALayerWin.cpp        2015-01-15 19:29:05 UTC (rev 178518)
</span><span class="lines">@@ -28,7 +28,7 @@
</span><span class="cx"> #include "PlatformCALayerWin.h"
</span><span class="cx">
</span><span class="cx"> #include "AbstractCACFLayerTreeHost.h"
</span><del>-#include "Font.h"
</del><ins>+#include "FontCascade.h"
</ins><span class="cx"> #include "GraphicsContext.h"
</span><span class="cx"> #include "PlatformCAAnimationWin.h"
</span><span class="cx"> #include "PlatformCALayerWinInternal.h"
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicscawinPlatformCALayerWinInternalcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/ca/win/PlatformCALayerWinInternal.cpp (178517 => 178518)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/ca/win/PlatformCALayerWinInternal.cpp        2015-01-15 19:20:03 UTC (rev 178517)
+++ trunk/Source/WebCore/platform/graphics/ca/win/PlatformCALayerWinInternal.cpp        2015-01-15 19:29:05 UTC (rev 178518)
</span><span class="lines">@@ -27,7 +27,7 @@
</span><span class="cx">
</span><span class="cx"> #include "PlatformCALayerWinInternal.h"
</span><span class="cx">
</span><del>-#include "Font.h"
</del><ins>+#include "FontCascade.h"
</ins><span class="cx"> #include "GraphicsContext.h"
</span><span class="cx"> #include "PlatformCALayer.h"
</span><span class="cx"> #include "TextRun.h"
</span><span class="lines">@@ -159,7 +159,7 @@
</span><span class="cx">
</span><span class="cx"> desc.setComputedSize(18);
</span><span class="cx">
</span><del>- Font font = Font(desc, 0, 0);
</del><ins>+ FontCascade font = FontCascade(desc, 0, 0);
</ins><span class="cx"> font.update(0);
</span><span class="cx">
</span><span class="cx"> GraphicsContext cg(context);
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsiosFontIOSmmfromrev178510trunkSourceWebCoreplatformgraphicsiosSimpleFontDataIOSmm"></a>
<div class="copfile"><h4>Copied: trunk/Source/WebCore/platform/graphics/ios/FontIOS.mm (from rev 178510, trunk/Source/WebCore/platform/graphics/ios/SimpleFontDataIOS.mm) (0 => 178518)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/ios/FontIOS.mm         (rev 0)
+++ trunk/Source/WebCore/platform/graphics/ios/FontIOS.mm        2015-01-15 19:29:05 UTC (rev 178518)
</span><span class="lines">@@ -0,0 +1,197 @@
</span><ins>+/*
+ * Copyright (C) 2005, 2006, 2010, 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Alexey Proskuryakov
+ *
+ * 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. 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 INC. 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.
+ */
+
+#import "config.h"
+#import "SimpleFontData.h"
+
+#import "BlockExceptions.h"
+#import "CoreGraphicsSPI.h"
+#import "FontCache.h"
+#import "FontCascade.h"
+#import "FontDescription.h"
+#import "FontServicesIOS.h"
+#import <CoreText/CoreText.h>
+#import <float.h>
+#import <unicode/uchar.h>
+#import <wtf/Assertions.h>
+#import <wtf/StdLibExtras.h>
+
+namespace WebCore {
+
+static bool fontFamilyShouldNotBeUsedForArabic(CFStringRef fontFamilyName)
+{
+ if (!fontFamilyName)
+ return false;
+
+ // Times New Roman contains Arabic glyphs, but Core Text doesn't know how to shape them. <rdar://problem/9823975>
+ // FIXME <rdar://problem/12096835> remove this function once the above bug is fixed.
+ // Arial and Tahoma are have performance issues so don't use them as well.
+ return (CFStringCompare(CFSTR("Times New Roman"), fontFamilyName, 0) == kCFCompareEqualTo)
+ || (CFStringCompare(CFSTR("Arial"), fontFamilyName, 0) == kCFCompareEqualTo)
+ || (CFStringCompare(CFSTR("Tahoma"), fontFamilyName, 0) == kCFCompareEqualTo);
+}
+
+static bool fontHasVerticalGlyphs(CTFontRef ctFont)
+{
+ // The check doesn't look neat but this is what AppKit does for vertical writing...
+ RetainPtr<CFArrayRef> tableTags = adoptCF(CTFontCopyAvailableTables(ctFont, kCTFontTableOptionNoOptions));
+ CFIndex numTables = CFArrayGetCount(tableTags.get());
+ for (CFIndex index = 0; index < numTables; ++index) {
+ CTFontTableTag tag = (CTFontTableTag)(uintptr_t)CFArrayGetValueAtIndex(tableTags.get(), index);
+ if (tag == kCTFontTableVhea || tag == kCTFontTableVORG)
+ return true;
+ }
+ return false;
+}
+
+void SimpleFontData::platformInit()
+{
+ m_syntheticBoldOffset = m_platformData.m_syntheticBold ? ceilf(m_platformData.size() / 24.0f) : 0.f;
+ m_spaceGlyph = 0;
+ m_spaceWidth = 0;
+ unsigned unitsPerEm;
+ float ascent;
+ float descent;
+ float capHeight;
+ float lineGap;
+ float lineSpacing;
+ float xHeight;
+ RetainPtr<CFStringRef> familyName;
+ if (CTFontRef ctFont = m_platformData.font()) {
+ FontServicesIOS fontService(ctFont);
+ ascent = ceilf(fontService.ascent());
+ descent = ceilf(fontService.descent());
+ lineSpacing = fontService.lineSpacing();
+ lineGap = fontService.lineGap();
+ xHeight = fontService.xHeight();
+ capHeight = fontService.capHeight();
+ unitsPerEm = fontService.unitsPerEm();
+ familyName = adoptCF(CTFontCopyFamilyName(ctFont));
+ } else {
+ CGFontRef cgFont = m_platformData.cgFont();
+
+ unitsPerEm = CGFontGetUnitsPerEm(cgFont);
+
+ float pointSize = m_platformData.size();
+ ascent = lroundf(scaleEmToUnits(CGFontGetAscent(cgFont), unitsPerEm) * pointSize);
+ descent = lroundf(-scaleEmToUnits(-abs(CGFontGetDescent(cgFont)), unitsPerEm) * pointSize);
+ lineGap = lroundf(scaleEmToUnits(CGFontGetLeading(cgFont), unitsPerEm) * pointSize);
+ xHeight = scaleEmToUnits(CGFontGetXHeight(cgFont), unitsPerEm) * pointSize;
+ capHeight = scaleEmToUnits(CGFontGetCapHeight(cgFont), unitsPerEm) * pointSize;
+
+ lineSpacing = ascent + descent + lineGap;
+ familyName = adoptCF(CGFontCopyFamilyName(cgFont));
+ }
+
+ m_fontMetrics.setUnitsPerEm(unitsPerEm);
+ m_fontMetrics.setAscent(ascent);
+ m_fontMetrics.setDescent(descent);
+ m_fontMetrics.setLineGap(lineGap);
+ m_fontMetrics.setLineSpacing(lineSpacing);
+ m_fontMetrics.setXHeight(xHeight);
+ m_fontMetrics.setCapHeight(capHeight);
+ m_shouldNotBeUsedForArabic = fontFamilyShouldNotBeUsedForArabic(familyName.get());
+
+ if (platformData().orientation() == Vertical && !isTextOrientationFallback())
+ m_hasVerticalGlyphs = fontHasVerticalGlyphs(m_platformData.ctFont());
+
+ if (!m_platformData.m_isEmoji)
+ return;
+
+ int thirdOfSize = m_platformData.size() / 3;
+ m_fontMetrics.setAscent(thirdOfSize);
+ m_fontMetrics.setDescent(thirdOfSize);
+ m_fontMetrics.setLineGap(thirdOfSize);
+ m_fontMetrics.setLineSpacing(0);
+}
+
+void SimpleFontData::platformCharWidthInit()
+{
+ m_avgCharWidth = 0;
+ m_maxCharWidth = 0;
+
+ // Fallback to a cross-platform estimate, which will populate these values if they are non-positive.
+ initCharWidths();
+}
+
+PassRefPtr<SimpleFontData> SimpleFontData::platformCreateScaledFontData(const FontDescription&, float scaleFactor) const
+{
+ if (isCustomFont()) {
+ FontPlatformData scaledFontData(m_platformData);
+ scaledFontData.m_size = scaledFontData.m_size * scaleFactor;
+ return SimpleFontData::create(scaledFontData, true, false);
+ }
+
+ float size = m_platformData.size() * scaleFactor;
+ CTFontSymbolicTraits fontTraits = CTFontGetSymbolicTraits(m_platformData.font());
+ RetainPtr<CTFontDescriptorRef> fontDescriptor = adoptCF(CTFontCopyFontDescriptor(m_platformData.font()));
+ RetainPtr<CTFontRef> scaledFont = adoptCF(CTFontCreateWithFontDescriptor(fontDescriptor.get(), size, nullptr));
+ FontPlatformData scaledFontData(scaledFont.get(), size, m_platformData.isPrinterFont(), false, false, m_platformData.orientation());
+
+ if (scaledFontData.font()) {
+ if (m_platformData.m_syntheticBold)
+ fontTraits |= kCTFontBoldTrait;
+ if (m_platformData.m_syntheticOblique)
+ fontTraits |= kCTFontItalicTrait;
+
+ CTFontSymbolicTraits scaledFontTraits = CTFontGetSymbolicTraits(scaledFontData.font());
+ scaledFontData.m_syntheticBold = (fontTraits & kCTFontBoldTrait) && !(scaledFontTraits & kCTFontTraitBold);
+ scaledFontData.m_syntheticOblique = (fontTraits & kCTFontItalicTrait) && !(scaledFontTraits & kCTFontTraitItalic);
+
+ return fontCache().fontForPlatformData(scaledFontData);
+ }
+
+ return nullptr;
+}
+
+void SimpleFontData::determinePitch()
+{
+ CTFontRef ctFont = m_platformData.font();
+ m_treatAsFixedPitch = false;
+ if (!ctFont)
+ return; // CTFont is null in the case of SVG fonts for example.
+
+ RetainPtr<CFStringRef> fullName = adoptCF(CTFontCopyFullName(ctFont));
+ RetainPtr<CFStringRef> familyName = adoptCF(CTFontCopyFamilyName(ctFont));
+
+ m_treatAsFixedPitch = CGFontIsFixedPitch(m_platformData.cgFont()) || (fullName && (CFStringCompare(fullName.get(), CFSTR("Osaka-Mono"), kCFCompareCaseInsensitive) == kCFCompareEqualTo || CFStringCompare(fullName.get(), CFSTR("MS-PGothic"), kCFCompareCaseInsensitive) == kCFCompareEqualTo));
+ if (familyName && CFStringCompare(familyName.get(), CFSTR("Courier New"), kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
+ // Special case Courier New to not be treated as fixed pitch, as this will make use of a hacked space width which is undesireable for iPhone (see rdar://6269783).
+ m_treatAsFixedPitch = false;
+ }
+}
+
+CGFontRenderingStyle SimpleFontData::renderingStyle() const
+{
+ return kCGFontRenderingStyleAntialiasing | kCGFontRenderingStyleSubpixelPositioning | kCGFontRenderingStyleSubpixelQuantization | kCGFontAntialiasingStyleUnfiltered;
+}
+
+bool SimpleFontData::advanceForColorBitmapFont(Glyph, CGSize&) const
+{
+ return false;
+}
+
+} // namespace WebCore
</ins></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsmacFontCascadeComplexTextMaccppfromrev178510trunkSourceWebCoreplatformgraphicsmacFontComplexTextMaccpp"></a>
<div class="copfile"><h4>Copied: trunk/Source/WebCore/platform/graphics/mac/FontCascadeComplexTextMac.cpp (from rev 178510, trunk/Source/WebCore/platform/graphics/mac/FontComplexTextMac.cpp) (0 => 178518)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/mac/FontCascadeComplexTextMac.cpp         (rev 0)
+++ trunk/Source/WebCore/platform/graphics/mac/FontCascadeComplexTextMac.cpp        2015-01-15 19:29:05 UTC (rev 178518)
</span><span class="lines">@@ -0,0 +1,184 @@
</span><ins>+/*
+ * Copyright (C) 2006, 2007, 2008, 2009 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. 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 INC. 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 "FontCascade.h"
+
+#include "ComplexTextController.h"
+#include "FontGlyphs.h"
+#include "GlyphBuffer.h"
+#include "GraphicsContext.h"
+#include "IntRect.h"
+#include "LayoutRect.h"
+#include "SimpleFontData.h"
+#include "TextRun.h"
+#include <wtf/MathExtras.h>
+
+namespace WebCore {
+
+void FontCascade::adjustSelectionRectForComplexText(const TextRun& run, LayoutRect& selectionRect, int from, int to) const
+{
+ ComplexTextController controller(this, run);
+ controller.advance(from);
+ float beforeWidth = controller.runWidthSoFar();
+ controller.advance(to);
+ float afterWidth = controller.runWidthSoFar();
+
+ if (run.rtl())
+ selectionRect.move(controller.totalWidth() - afterWidth, 0);
+ else
+ selectionRect.move(beforeWidth, 0);
+ selectionRect.setWidth(afterWidth - beforeWidth);
+}
+
+float FontCascade::getGlyphsAndAdvancesForComplexText(const TextRun& run, int from, int to, GlyphBuffer& glyphBuffer, ForTextEmphasisOrNot forTextEmphasis) const
+{
+ float initialAdvance;
+
+ ComplexTextController controller(this, run, false, 0, forTextEmphasis);
+ controller.advance(from);
+ float beforeWidth = controller.runWidthSoFar();
+ controller.advance(to, &glyphBuffer);
+
+ if (glyphBuffer.isEmpty())
+ return 0;
+
+ float afterWidth = controller.runWidthSoFar();
+
+ if (run.rtl()) {
+ initialAdvance = controller.totalWidth() + controller.finalRoundingWidth() - afterWidth;
+ glyphBuffer.reverse(0, glyphBuffer.size());
+ } else
+ initialAdvance = beforeWidth;
+
+ return initialAdvance;
+}
+
+float FontCascade::drawComplexText(GraphicsContext* context, const TextRun& run, const FloatPoint& point, int from, int to) const
+{
+ // This glyph buffer holds our glyphs + advances + font data for each glyph.
+ GlyphBuffer glyphBuffer;
+
+ float startX = point.x() + getGlyphsAndAdvancesForComplexText(run, from, to, glyphBuffer);
+
+ // We couldn't generate any glyphs for the run. Give up.
+ if (glyphBuffer.isEmpty())
+ return 0;
+
+ // Draw the glyph buffer now at the starting point returned in startX.
+ FloatPoint startPoint(startX, point.y());
+ drawGlyphBuffer(context, run, glyphBuffer, startPoint);
+
+ return startPoint.x() - startX;
+}
+
+void FontCascade::drawEmphasisMarksForComplexText(GraphicsContext* context, const TextRun& run, const AtomicString& mark, const FloatPoint& point, int from, int to) const
+{
+ GlyphBuffer glyphBuffer;
+ float initialAdvance = getGlyphsAndAdvancesForComplexText(run, from, to, glyphBuffer, ForTextEmphasis);
+
+ if (glyphBuffer.isEmpty())
+ return;
+
+ drawEmphasisMarks(context, run, glyphBuffer, mark, FloatPoint(point.x() + initialAdvance, point.y()));
+}
+
+float FontCascade::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const
+{
+ ComplexTextController controller(this, run, true, fallbackFonts);
+ if (glyphOverflow) {
+ glyphOverflow->top = std::max<int>(glyphOverflow->top, ceilf(-controller.minGlyphBoundingBoxY()) - (glyphOverflow->computeBounds ? 0 : fontMetrics().ascent()));
+ glyphOverflow->bottom = std::max<int>(glyphOverflow->bottom, ceilf(controller.maxGlyphBoundingBoxY()) - (glyphOverflow->computeBounds ? 0 : fontMetrics().descent()));
+ glyphOverflow->left = std::max<int>(0, ceilf(-controller.minGlyphBoundingBoxX()));
+ glyphOverflow->right = std::max<int>(0, ceilf(controller.maxGlyphBoundingBoxX() - controller.totalWidth()));
+ }
+ return controller.totalWidth();
+}
+
+int FontCascade::offsetForPositionForComplexText(const TextRun& run, float x, bool includePartialGlyphs) const
+{
+ ComplexTextController controller(this, run);
+ return controller.offsetForPosition(x, includePartialGlyphs);
+}
+
+const SimpleFontData* FontCascade::fontDataForCombiningCharacterSequence(const UChar* characters, size_t length, FontDataVariant variant) const
+{
+ UChar32 baseCharacter;
+ size_t baseCharacterLength = 0;
+ U16_NEXT(characters, baseCharacterLength, length, baseCharacter);
+
+ GlyphData baseCharacterGlyphData = glyphDataForCharacter(baseCharacter, false, variant);
+
+ if (!baseCharacterGlyphData.glyph)
+ return 0;
+
+ if (length == baseCharacterLength)
+ return baseCharacterGlyphData.fontData;
+
+ bool triedBaseCharacterFontData = false;
+
+ for (unsigned i = 0; !fallbackRangesAt(i).isNull(); ++i) {
+ const SimpleFontData* simpleFontData = fallbackRangesAt(i).fontDataForCharacter(baseCharacter);
+ if (!simpleFontData)
+ continue;
+#if PLATFORM(IOS)
+ if (baseCharacter >= 0x0600 && baseCharacter <= 0x06ff && simpleFontData->shouldNotBeUsedForArabic())
+ continue;
+#endif
+ if (variant == NormalVariant) {
+ if (simpleFontData->platformData().orientation() == Vertical) {
+ if (isCJKIdeographOrSymbol(baseCharacter) && !simpleFontData->hasVerticalGlyphs()) {
+ variant = BrokenIdeographVariant;
+ simpleFontData = simpleFontData->brokenIdeographFontData().get();
+ } else if (m_fontDescription.nonCJKGlyphOrientation() == NonCJKGlyphOrientationVerticalRight) {
+ SimpleFontData* verticalRightFontData = simpleFontData->verticalRightOrientationFontData().get();
+ Glyph verticalRightGlyph = verticalRightFontData->glyphForCharacter(baseCharacter);
+ if (verticalRightGlyph == baseCharacterGlyphData.glyph)
+ simpleFontData = verticalRightFontData;
+ } else {
+ SimpleFontData* uprightFontData = simpleFontData->uprightOrientationFontData().get();
+ Glyph uprightGlyph = uprightFontData->glyphForCharacter(baseCharacter);
+ if (uprightGlyph != baseCharacterGlyphData.glyph)
+ simpleFontData = uprightFontData;
+ }
+ }
+ } else {
+ if (const SimpleFontData* variantFontData = simpleFontData->variantFontData(m_fontDescription, variant).get())
+ simpleFontData = variantFontData;
+ }
+
+ if (simpleFontData == baseCharacterGlyphData.fontData)
+ triedBaseCharacterFontData = true;
+
+ if (simpleFontData->canRenderCombiningCharacterSequence(characters, length))
+ return simpleFontData;
+ }
+
+ if (!triedBaseCharacterFontData && baseCharacterGlyphData.fontData && baseCharacterGlyphData.fontData->canRenderCombiningCharacterSequence(characters, length))
+ return baseCharacterGlyphData.fontData;
+
+ return SimpleFontData::systemFallback();
+}
+
+} // namespace WebCore
</ins></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsmacFontCascadeMacmmfromrev178510trunkSourceWebCoreplatformgraphicsmacFontMacmm"></a>
<div class="copfile"><h4>Copied: trunk/Source/WebCore/platform/graphics/mac/FontCascadeMac.mm (from rev 178510, trunk/Source/WebCore/platform/graphics/mac/FontMac.mm) (0 => 178518)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/mac/FontCascadeMac.mm         (rev 0)
+++ trunk/Source/WebCore/platform/graphics/mac/FontCascadeMac.mm        2015-01-15 19:29:05 UTC (rev 178518)
</span><span class="lines">@@ -0,0 +1,605 @@
</span><ins>+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ * (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * (C) 2000 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2003, 2006, 2007, 2008, 2009, 2010, 2011 Apple 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.
+ */
+
+#import "config.h"
+#import "FontCascade.h"
+
+#import "CoreGraphicsSPI.h"
+#import "CoreTextSPI.h"
+#import "DashArray.h"
+#import "GlyphBuffer.h"
+#import "GraphicsContext.h"
+#import "Logging.h"
+#import "SimpleFontData.h"
+#import "WebCoreSystemInterface.h"
+#if USE(APPKIT)
+#import <AppKit/AppKit.h>
+#endif
+#import <wtf/MathExtras.h>
+
+#if ENABLE(LETTERPRESS)
+#import "CoreUISPI.h"
+#import "SoftLinking.h"
+
+SOFT_LINK_PRIVATE_FRAMEWORK(CoreUI)
+SOFT_LINK_CLASS(CoreUI, CUICatalog)
+SOFT_LINK_CLASS(CoreUI, CUIStyleEffectConfiguration)
+
+SOFT_LINK_FRAMEWORK(UIKit)
+SOFT_LINK(UIKit, _UIKitGetTextEffectsCatalog, CUICatalog *, (void), ())
+#endif
+
+#define SYNTHETIC_OBLIQUE_ANGLE 14
+
+#ifdef __LP64__
+#define URefCon void*
+#else
+#define URefCon UInt32
+#endif
+
+namespace WebCore {
+
+bool FontCascade::canReturnFallbackFontsForComplexText()
+{
+ return true;
+}
+
+bool FontCascade::canExpandAroundIdeographsInComplexText()
+{
+ return true;
+}
+
+static inline void fillVectorWithHorizontalGlyphPositions(Vector<CGPoint, 256>& positions, CGContextRef context, const CGSize* advances, size_t count)
+{
+ CGAffineTransform matrix = CGAffineTransformInvert(CGContextGetTextMatrix(context));
+ positions[0] = CGPointZero;
+ for (size_t i = 1; i < count; ++i) {
+ CGSize advance = CGSizeApplyAffineTransform(advances[i - 1], matrix);
+ positions[i].x = positions[i - 1].x + advance.width;
+ positions[i].y = positions[i - 1].y + advance.height;
+ }
+}
+
+static inline bool shouldUseLetterpressEffect(const GraphicsContext& context)
+{
+#if ENABLE(LETTERPRESS)
+ return context.textDrawingMode() & TextModeLetterpress;
+#else
+ UNUSED_PARAM(context);
+ return false;
+#endif
+}
+
+static void showLetterpressedGlyphsWithAdvances(const FloatPoint& point, const SimpleFontData* font, CGContextRef context, const CGGlyph* glyphs, const CGSize* advances, size_t count)
+{
+#if ENABLE(LETTERPRESS)
+ if (!count)
+ return;
+
+ const FontPlatformData& platformData = font->platformData();
+ if (platformData.orientation() == Vertical) {
+ // FIXME: Implement support for vertical text. See <rdar://problem/13737298>.
+ return;
+ }
+
+ CGContextSetTextPosition(context, point.x(), point.y());
+ Vector<CGPoint, 256> positions(count);
+ fillVectorWithHorizontalGlyphPositions(positions, context, advances, count);
+
+ CTFontRef ctFont = platformData.ctFont();
+ CGContextSetFontSize(context, CTFontGetSize(ctFont));
+
+ static CUICatalog *catalog = _UIKitGetTextEffectsCatalog();
+ if (!catalog)
+ return;
+
+ static CUIStyleEffectConfiguration *styleConfiguration;
+ if (!styleConfiguration) {
+ styleConfiguration = [allocCUIStyleEffectConfigurationInstance() init];
+ styleConfiguration.useSimplifiedEffect = YES;
+ }
+
+ [catalog drawGlyphs:glyphs atPositions:positions.data() inContext:context withFont:ctFont count:count stylePresetName:@"_UIKitNewLetterpressStyle" styleConfiguration:styleConfiguration foregroundColor:CGContextGetFillColorAsColor(context)];
+#else
+ UNUSED_PARAM(point);
+ UNUSED_PARAM(font);
+ UNUSED_PARAM(context);
+ UNUSED_PARAM(glyphs);
+ UNUSED_PARAM(advances);
+ UNUSED_PARAM(count);
+#endif
+}
+
+static void showGlyphsWithAdvances(const FloatPoint& point, const SimpleFontData* font, CGContextRef context, const CGGlyph* glyphs, const CGSize* advances, size_t count)
+{
+ if (!count)
+ return;
+
+ CGContextSetTextPosition(context, point.x(), point.y());
+
+ const FontPlatformData& platformData = font->platformData();
+ Vector<CGPoint, 256> positions(count);
+ if (platformData.isColorBitmapFont())
+ fillVectorWithHorizontalGlyphPositions(positions, context, advances, count);
+ if (platformData.orientation() == Vertical) {
+ CGAffineTransform savedMatrix;
+ CGAffineTransform rotateLeftTransform = CGAffineTransformMake(0, -1, 1, 0, 0, 0);
+ savedMatrix = CGContextGetTextMatrix(context);
+ CGAffineTransform runMatrix = CGAffineTransformConcat(savedMatrix, rotateLeftTransform);
+ CGContextSetTextMatrix(context, runMatrix);
+
+ Vector<CGSize, 256> translations(count);
+ CTFontGetVerticalTranslationsForGlyphs(platformData.ctFont(), glyphs, translations.data(), count);
+
+ CGAffineTransform transform = CGAffineTransformInvert(CGContextGetTextMatrix(context));
+
+ CGPoint position = FloatPoint(point.x(), point.y() + font->fontMetrics().floatAscent(IdeographicBaseline) - font->fontMetrics().floatAscent());
+ for (size_t i = 0; i < count; ++i) {
+ CGSize translation = CGSizeApplyAffineTransform(translations[i], rotateLeftTransform);
+ positions[i] = CGPointApplyAffineTransform(CGPointMake(position.x - translation.width, position.y + translation.height), transform);
+ position.x += advances[i].width;
+ position.y += advances[i].height;
+ }
+ if (!platformData.isColorBitmapFont())
+ CGContextShowGlyphsAtPositions(context, glyphs, positions.data(), count);
+ else
+ CTFontDrawGlyphs(platformData.ctFont(), glyphs, positions.data(), count, context);
+ CGContextSetTextMatrix(context, savedMatrix);
+ } else {
+ if (!platformData.isColorBitmapFont())
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+ CGContextShowGlyphsWithAdvances(context, glyphs, advances, count);
+#pragma clang diagnostic pop
+ else
+ CTFontDrawGlyphs(platformData.ctFont(), glyphs, positions.data(), count, context);
+ }
+}
+
+#if PLATFORM(MAC)
+static void setCGFontRenderingMode(CGContextRef cgContext, NSFontRenderingMode renderingMode, BOOL shouldSubpixelQuantize)
+{
+ if (renderingMode == NSFontIntegerAdvancementsRenderingMode) {
+ CGContextSetShouldAntialiasFonts(cgContext, false);
+ return;
+ }
+
+ CGContextSetShouldAntialiasFonts(cgContext, true);
+
+ CGAffineTransform contextTransform = CGContextGetCTM(cgContext);
+ BOOL isTranslationOrIntegralScale = WTF::isIntegral(contextTransform.a) && WTF::isIntegral(contextTransform.d) && contextTransform.b == 0.f && contextTransform.c == 0.f;
+ BOOL isRotated = ((contextTransform.b || contextTransform.c) && (contextTransform.a || contextTransform.d));
+ BOOL doSubpixelQuantization = isTranslationOrIntegralScale || (!isRotated && shouldSubpixelQuantize);
+
+ CGContextSetShouldSubpixelPositionFonts(cgContext, renderingMode != NSFontAntialiasedIntegerAdvancementsRenderingMode || !isTranslationOrIntegralScale);
+ CGContextSetShouldSubpixelQuantizeFonts(cgContext, doSubpixelQuantization);
+}
+#endif
+
+void FontCascade::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, const GlyphBuffer& glyphBuffer, int from, int numGlyphs, const FloatPoint& anchorPoint) const
+{
+ const FontPlatformData& platformData = font->platformData();
+ if (!platformData.size())
+ return;
+
+ CGContextRef cgContext = context->platformContext();
+
+ bool shouldSmoothFonts;
+ bool changeFontSmoothing;
+
+ switch(fontDescription().fontSmoothing()) {
+ case Antialiased: {
+ context->setShouldAntialias(true);
+ shouldSmoothFonts = false;
+ changeFontSmoothing = true;
+ break;
+ }
+ case SubpixelAntialiased: {
+ context->setShouldAntialias(true);
+ shouldSmoothFonts = true;
+ changeFontSmoothing = true;
+ break;
+ }
+ case NoSmoothing: {
+ context->setShouldAntialias(false);
+ shouldSmoothFonts = false;
+ changeFontSmoothing = true;
+ break;
+ }
+ case AutoSmoothing: {
+ shouldSmoothFonts = true;
+ changeFontSmoothing = false;
+ break;
+ }
+ }
+
+ if (!shouldUseSmoothing()) {
+ shouldSmoothFonts = false;
+ changeFontSmoothing = true;
+ }
+
+#if !PLATFORM(IOS)
+ bool originalShouldUseFontSmoothing = false;
+ if (changeFontSmoothing) {
+ originalShouldUseFontSmoothing = CGContextGetShouldSmoothFonts(cgContext);
+ CGContextSetShouldSmoothFonts(cgContext, shouldSmoothFonts);
+ }
+#endif
+
+#if !PLATFORM(IOS)
+ NSFont* drawFont;
+ if (!isPrinterFont()) {
+ drawFont = [platformData.nsFont() screenFont];
+ if (drawFont != platformData.nsFont()) {
+ // We are getting this in too many places (3406411); use ERROR so it only prints on debug versions for now. (We should debug this also, eventually).
+ LOG_ERROR("Attempting to set non-screen font (%@) when drawing to screen. Using screen font anyway, may result in incorrect metrics.",
+ [[[platformData.nsFont() fontDescriptor] fontAttributes] objectForKey:NSFontNameAttribute]);
+ }
+ } else {
+ drawFont = [platformData.nsFont() printerFont];
+ if (drawFont != platformData.nsFont()) {
+ NSLog(@"Attempting to set non-printer font (%@) when printing. Using printer font anyway, may result in incorrect metrics.",
+ [[[platformData.nsFont() fontDescriptor] fontAttributes] objectForKey:NSFontNameAttribute]);
+ }
+ }
+#endif
+
+ CGContextSetFont(cgContext, platformData.cgFont());
+
+ bool useLetterpressEffect = shouldUseLetterpressEffect(*context);
+ FloatPoint point = anchorPoint;
+#if PLATFORM(IOS)
+ float fontSize = platformData.size();
+ CGAffineTransform matrix = useLetterpressEffect || platformData.isColorBitmapFont() ? CGAffineTransformIdentity : CGAffineTransformMakeScale(fontSize, fontSize);
+ if (platformData.m_isEmoji) {
+ if (!context->emojiDrawingEnabled())
+ return;
+
+ // Mimic the positioining of non-bitmap glyphs, which are not subpixel-positioned.
+ point.setY(ceilf(point.y()));
+
+ // Emoji glyphs snap to the CSS pixel grid.
+ point.setX(floorf(point.x()));
+
+ // Emoji glyphs are offset one CSS pixel to the right.
+ point.move(1, 0);
+
+ // Emoji glyphs are offset vertically based on font size.
+ float y = point.y();
+ if (fontSize <= 15) {
+ // Undo Core Text's y adjustment.
+ static float yAdjustmentFactor = iosExecutableWasLinkedOnOrAfterVersion(wkIOSSystemVersion_6_0) ? .19 : .1;
+ point.setY(floorf(y - yAdjustmentFactor * (fontSize + 2) + 2));
+ } else {
+ if (fontSize < 26)
+ y -= .35f * fontSize - 10;
+
+ // Undo Core Text's y adjustment.
+ static float yAdjustment = iosExecutableWasLinkedOnOrAfterVersion(wkIOSSystemVersion_6_0) ? 3.8 : 2;
+ point.setY(floorf(y - yAdjustment));
+ }
+ }
+#else
+ CGAffineTransform matrix = CGAffineTransformIdentity;
+ if (drawFont && !platformData.isColorBitmapFont())
+ memcpy(&matrix, [drawFont matrix], sizeof(matrix));
+#endif
+ matrix.b = -matrix.b;
+ matrix.d = -matrix.d;
+ if (platformData.m_syntheticOblique) {
+ static float obliqueSkew = tanf(SYNTHETIC_OBLIQUE_ANGLE * piFloat / 180);
+ if (platformData.orientation() == Vertical)
+ matrix = CGAffineTransformConcat(matrix, CGAffineTransformMake(1, obliqueSkew, 0, 1, 0, 0));
+ else
+ matrix = CGAffineTransformConcat(matrix, CGAffineTransformMake(1, 0, -obliqueSkew, 1, 0, 0));
+ }
+ CGContextSetTextMatrix(cgContext, matrix);
+
+#if PLATFORM(IOS)
+ CGContextSetFontSize(cgContext, 1);
+ CGContextSetShouldSubpixelQuantizeFonts(cgContext, context->shouldSubpixelQuantizeFonts());
+#else
+ setCGFontRenderingMode(cgContext, [drawFont renderingMode], context->shouldSubpixelQuantizeFonts());
+ if (drawFont)
+ CGContextSetFontSize(cgContext, 1);
+ else
+ CGContextSetFontSize(cgContext, platformData.m_size);
+#endif
+
+
+ FloatSize shadowOffset;
+ float shadowBlur;
+ Color shadowColor;
+ ColorSpace shadowColorSpace;
+ ColorSpace fillColorSpace = context->fillColorSpace();
+ context->getShadow(shadowOffset, shadowBlur, shadowColor, shadowColorSpace);
+
+ AffineTransform contextCTM = context->getCTM();
+ float syntheticBoldOffset = font->syntheticBoldOffset();
+ if (syntheticBoldOffset && !contextCTM.isIdentityOrTranslationOrFlipped()) {
+ FloatSize horizontalUnitSizeInDevicePixels = contextCTM.mapSize(FloatSize(1, 0));
+ float horizontalUnitLengthInDevicePixels = sqrtf(horizontalUnitSizeInDevicePixels.width() * horizontalUnitSizeInDevicePixels.width() + horizontalUnitSizeInDevicePixels.height() * horizontalUnitSizeInDevicePixels.height());
+ if (horizontalUnitLengthInDevicePixels)
+ syntheticBoldOffset /= horizontalUnitLengthInDevicePixels;
+ };
+
+ bool hasSimpleShadow = context->textDrawingMode() == TextModeFill && shadowColor.isValid() && !shadowBlur && !platformData.isColorBitmapFont() && (!context->shadowsIgnoreTransforms() || contextCTM.isIdentityOrTranslationOrFlipped()) && !context->isInTransparencyLayer();
+ if (hasSimpleShadow) {
+ // Paint simple shadows ourselves instead of relying on CG shadows, to avoid losing subpixel antialiasing.
+ context->clearShadow();
+ Color fillColor = context->fillColor();
+ Color shadowFillColor(shadowColor.red(), shadowColor.green(), shadowColor.blue(), shadowColor.alpha() * fillColor.alpha() / 255);
+ context->setFillColor(shadowFillColor, shadowColorSpace);
+ float shadowTextX = point.x() + shadowOffset.width();
+ // If shadows are ignoring transforms, then we haven't applied the Y coordinate flip yet, so down is negative.
+ float shadowTextY = point.y() + shadowOffset.height() * (context->shadowsIgnoreTransforms() ? -1 : 1);
+ showGlyphsWithAdvances(FloatPoint(shadowTextX, shadowTextY), font, cgContext, glyphBuffer.glyphs(from), static_cast<const CGSize*>(glyphBuffer.advances(from)), numGlyphs);
+#if !PLATFORM(IOS)
+ if (syntheticBoldOffset)
+#else
+ if (syntheticBoldOffset && !platformData.m_isEmoji)
+#endif
+ showGlyphsWithAdvances(FloatPoint(shadowTextX + syntheticBoldOffset, shadowTextY), font, cgContext, glyphBuffer.glyphs(from), static_cast<const CGSize*>(glyphBuffer.advances(from)), numGlyphs);
+ context->setFillColor(fillColor, fillColorSpace);
+ }
+
+ if (useLetterpressEffect)
+ showLetterpressedGlyphsWithAdvances(point, font, cgContext, glyphBuffer.glyphs(from), static_cast<const CGSize*>(glyphBuffer.advances(from)), numGlyphs);
+ else
+ showGlyphsWithAdvances(point, font, cgContext, glyphBuffer.glyphs(from), static_cast<const CGSize*>(glyphBuffer.advances(from)), numGlyphs);
+#if !PLATFORM(IOS)
+ if (syntheticBoldOffset)
+#else
+ if (syntheticBoldOffset && !platformData.m_isEmoji)
+#endif
+ showGlyphsWithAdvances(FloatPoint(point.x() + syntheticBoldOffset, point.y()), font, cgContext, glyphBuffer.glyphs(from), static_cast<const CGSize*>(glyphBuffer.advances(from)), numGlyphs);
+
+ if (hasSimpleShadow)
+ context->setShadow(shadowOffset, shadowBlur, shadowColor, shadowColorSpace);
+
+#if !PLATFORM(IOS)
+ if (changeFontSmoothing)
+ CGContextSetShouldSmoothFonts(cgContext, originalShouldUseFontSmoothing);
+#endif
+}
+
+#if ENABLE(CSS3_TEXT_DECORATION_SKIP_INK)
+struct GlyphIterationState {
+ GlyphIterationState(CGPoint startingPoint, CGPoint currentPoint, CGFloat y1, CGFloat y2, CGFloat minX, CGFloat maxX)
+ : startingPoint(startingPoint)
+ , currentPoint(currentPoint)
+ , y1(y1)
+ , y2(y2)
+ , minX(minX)
+ , maxX(maxX)
+ {
+ }
+ CGPoint startingPoint;
+ CGPoint currentPoint;
+ CGFloat y1;
+ CGFloat y2;
+ CGFloat minX;
+ CGFloat maxX;
+};
+
+static bool findIntersectionPoint(float y, CGPoint p1, CGPoint p2, CGFloat& x)
+{
+ x = p1.x + (y - p1.y) * (p2.x - p1.x) / (p2.y - p1.y);
+ return (p1.y < y && p2.y > y) || (p1.y > y && p2.y < y);
+}
+
+static void updateX(GlyphIterationState& state, CGFloat x)
+{
+ state.minX = std::min(state.minX, x);
+ state.maxX = std::max(state.maxX, x);
+}
+
+// This function is called by CGPathApply and is therefore invoked for each
+// contour in a glyph. This function models each contours as a straight line
+// and calculates the intersections between each pseudo-contour and
+// two horizontal lines (the upper and lower bounds of an underline) found in
+// GlyphIterationState::y1 and GlyphIterationState::y2. It keeps track of the
+// leftmost and rightmost intersection in GlyphIterationState::minX and
+// GlyphIterationState::maxX.
+static void findPathIntersections(void* stateAsVoidPointer, const CGPathElement* e)
+{
+ auto& state = *static_cast<GlyphIterationState*>(stateAsVoidPointer);
+ bool doIntersection = false;
+ CGPoint point = CGPointZero;
+ switch (e->type) {
+ case kCGPathElementMoveToPoint:
+ state.startingPoint = e->points[0];
+ state.currentPoint = e->points[0];
+ break;
+ case kCGPathElementAddLineToPoint:
+ doIntersection = true;
+ point = e->points[0];
+ break;
+ case kCGPathElementAddQuadCurveToPoint:
+ doIntersection = true;
+ point = e->points[1];
+ break;
+ case kCGPathElementAddCurveToPoint:
+ doIntersection = true;
+ point = e->points[2];
+ break;
+ case kCGPathElementCloseSubpath:
+ doIntersection = true;
+ point = state.startingPoint;
+ break;
+ }
+ if (!doIntersection)
+ return;
+ CGFloat x;
+ if (findIntersectionPoint(state.y1, state.currentPoint, point, x))
+ updateX(state, x);
+ if (findIntersectionPoint(state.y2, state.currentPoint, point, x))
+ updateX(state, x);
+ if ((state.currentPoint.y >= state.y1 && state.currentPoint.y <= state.y2)
+ || (state.currentPoint.y <= state.y1 && state.currentPoint.y >= state.y2))
+ updateX(state, state.currentPoint.x);
+ state.currentPoint = point;
+}
+
+class MacGlyphToPathTranslator final : public GlyphToPathTranslator {
+public:
+ MacGlyphToPathTranslator(const TextRun& textRun, const GlyphBuffer& glyphBuffer, const FloatPoint& textOrigin)
+ : m_index(0)
+ , m_textRun(textRun)
+ , m_glyphBuffer(glyphBuffer)
+ , m_fontData(glyphBuffer.fontDataAt(m_index))
+ , m_translation(CGAffineTransformScale(CGAffineTransformMakeTranslation(textOrigin.x(), textOrigin.y()), 1, -1))
+ {
+ moveToNextValidGlyph();
+ }
+private:
+ virtual bool containsMorePaths() override
+ {
+ return m_index != m_glyphBuffer.size();
+ }
+ virtual Path path() override;
+ virtual std::pair<float, float> extents() override;
+ virtual GlyphUnderlineType underlineType() override;
+ virtual void advance() override;
+ void moveToNextValidGlyph();
+
+ int m_index;
+ const TextRun& m_textRun;
+ const GlyphBuffer& m_glyphBuffer;
+ const SimpleFontData* m_fontData;
+ CGAffineTransform m_translation;
+};
+
+Path MacGlyphToPathTranslator::path()
+{
+ RetainPtr<CGPathRef> result = adoptCF(CTFontCreatePathForGlyph(m_fontData->platformData().ctFont(), m_glyphBuffer.glyphAt(m_index), &m_translation));
+ return adoptCF(CGPathCreateMutableCopy(result.get()));
+}
+
+std::pair<float, float> MacGlyphToPathTranslator::extents()
+{
+ CGPoint beginning = CGPointApplyAffineTransform(CGPointMake(0, 0), m_translation);
+ CGSize end = CGSizeApplyAffineTransform(m_glyphBuffer.advanceAt(m_index), m_translation);
+ return std::make_pair(static_cast<float>(beginning.x), static_cast<float>(beginning.x + end.width));
+}
+
+auto MacGlyphToPathTranslator::underlineType() -> GlyphUnderlineType
+{
+ return computeUnderlineType(m_textRun, m_glyphBuffer, m_index);
+}
+
+void MacGlyphToPathTranslator::moveToNextValidGlyph()
+{
+ if (!m_fontData->isSVGFont())
+ return;
+ advance();
+}
+
+void MacGlyphToPathTranslator::advance()
+{
+ do {
+ GlyphBufferAdvance advance = m_glyphBuffer.advanceAt(m_index);
+ m_translation = CGAffineTransformTranslate(m_translation, advance.width(), advance.height());
+ ++m_index;
+ if (m_index >= m_glyphBuffer.size())
+ break;
+ m_fontData = m_glyphBuffer.fontDataAt(m_index);
+ } while (m_fontData->isSVGFont() && m_index < m_glyphBuffer.size());
+}
+
+DashArray FontCascade::dashesForIntersectionsWithRect(const TextRun& run, const FloatPoint& textOrigin, const FloatRect& lineExtents) const
+{
+ if (isLoadingCustomFonts())
+ return DashArray();
+
+ GlyphBuffer glyphBuffer;
+ glyphBuffer.saveOffsetsInString();
+ float deltaX;
+ if (codePath(run) != FontCascade::Complex)
+ deltaX = getGlyphsAndAdvancesForSimpleText(run, 0, run.length(), glyphBuffer);
+ else
+ deltaX = getGlyphsAndAdvancesForComplexText(run, 0, run.length(), glyphBuffer);
+
+ if (!glyphBuffer.size())
+ return DashArray();
+
+ // FIXME: Handle SVG + non-SVG interleaved runs. https://bugs.webkit.org/show_bug.cgi?id=133778
+ const SimpleFontData* fontData = glyphBuffer.fontDataAt(0);
+ std::unique_ptr<GlyphToPathTranslator> translator;
+ bool isSVG = false;
+ FloatPoint origin = FloatPoint(textOrigin.x() + deltaX, textOrigin.y());
+ if (!fontData->isSVGFont())
+ translator = std::make_unique<MacGlyphToPathTranslator>(run, glyphBuffer, origin);
+ else {
+ TextRun::RenderingContext* renderingContext = run.renderingContext();
+ if (!renderingContext)
+ return DashArray();
+ translator = renderingContext->createGlyphToPathTranslator(*fontData, &run, glyphBuffer, 0, glyphBuffer.size(), origin);
+ isSVG = true;
+ }
+ DashArray result;
+ for (int index = 0; translator->containsMorePaths(); ++index, translator->advance()) {
+ GlyphIterationState info = GlyphIterationState(CGPointMake(0, 0), CGPointMake(0, 0), lineExtents.y(), lineExtents.y() + lineExtents.height(), lineExtents.x() + lineExtents.width(), lineExtents.x());
+ const SimpleFontData* localFontData = glyphBuffer.fontDataAt(index);
+ if (!localFontData || (!isSVG && localFontData->isSVGFont()) || (isSVG && localFontData != fontData)) {
+ // The advances will get all messed up if we do anything other than bail here.
+ result.clear();
+ break;
+ }
+ switch (translator->underlineType()) {
+ case GlyphToPathTranslator::GlyphUnderlineType::SkipDescenders: {
+ Path path = translator->path();
+ CGPathApply(path.platformPath(), &info, &findPathIntersections);
+ if (info.minX < info.maxX) {
+ result.append(info.minX - lineExtents.x());
+ result.append(info.maxX - lineExtents.x());
+ }
+ break;
+ }
+ case GlyphToPathTranslator::GlyphUnderlineType::SkipGlyph: {
+ std::pair<float, float> extents = translator->extents();
+ result.append(extents.first - lineExtents.x());
+ result.append(extents.second - lineExtents.x());
+ break;
+ }
+ case GlyphToPathTranslator::GlyphUnderlineType::DrawOverGlyph:
+ // Nothing to do
+ break;
+ }
+ }
+ return result;
+}
+#endif
+
+bool FontCascade::primaryFontDataIsSystemFont() const
+{
+#if PLATFORM(IOS) || __MAC_OS_X_VERSION_MIN_REQUIRED > 1090
+ const auto& fontData = primaryFontData();
+ return !fontData.isSVGFont() && CTFontDescriptorIsSystemUIFont(adoptCF(CTFontCopyFontDescriptor(fontData.platformData().ctFont())).get());
+#else
+ // System fonts are hidden by having a name that begins with a period, so simply search
+ // for that here rather than try to keep the list up to date.
+ return firstFamily().startsWith('.');
+#endif
+}
+
+}
</ins></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsmacFontCoreTextcppfromrev178496trunkSourceWebCoreplatformgraphicsmacSimpleFontDataCoreTextcpp"></a>
<div class="copfile"><h4>Copied: trunk/Source/WebCore/platform/graphics/mac/FontCoreText.cpp (from rev 178496, trunk/Source/WebCore/platform/graphics/mac/SimpleFontDataCoreText.cpp) (0 => 178518)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/mac/FontCoreText.cpp         (rev 0)
+++ trunk/Source/WebCore/platform/graphics/mac/FontCoreText.cpp        2015-01-15 19:29:05 UTC (rev 178518)
</span><span class="lines">@@ -0,0 +1,70 @@
</span><ins>+/*
+ * Copyright (C) 2005, 2006, 2012 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Alexey Proskuryakov
+ *
+ * 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. 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 INC. 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 "SimpleFontData.h"
+
+#if !PLATFORM(IOS)
+#include <ApplicationServices/ApplicationServices.h>
+#else
+#include <CoreText/CoreText.h>
+#endif
+
+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;
+ if (!addResult.isNewEntry)
+ return attributesDictionary.get();
+
+ attributesDictionary = adoptCF(CFDictionaryCreateMutable(kCFAllocatorDefault, 4, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
+ CFMutableDictionaryRef mutableAttributes = (CFMutableDictionaryRef)attributesDictionary.get();
+
+ CFDictionarySetValue(mutableAttributes, kCTFontAttributeName, platformData().ctFont());
+
+ if (!(typesettingFeatures & Kerning)) {
+ const float zero = 0;
+ static CFNumberRef zeroKerningValue = CFNumberCreate(kCFAllocatorDefault, kCFNumberFloatType, &zero);
+ CFDictionarySetValue(mutableAttributes, kCTKernAttributeName, zeroKerningValue);
+ }
+
+ bool allowLigatures = (orientation == Horizontal && platformData().allowsLigatures()) || (typesettingFeatures & Ligatures);
+ if (!allowLigatures) {
+ const int zero = 0;
+ static CFNumberRef essentialLigaturesValue = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &zero);
+ CFDictionarySetValue(mutableAttributes, kCTLigatureAttributeName, essentialLigaturesValue);
+ }
+
+ if (orientation == Vertical)
+ CFDictionarySetValue(mutableAttributes, kCTVerticalFormsAttributeName, kCFBooleanTrue);
+
+ return attributesDictionary.get();
+}
+
+} // namespace WebCore
</ins></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsmacFontMacmm"></a>
<div class="delfile"><h4>Deleted: trunk/Source/WebCore/platform/graphics/mac/FontMac.mm (178517 => 178518)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/mac/FontMac.mm        2015-01-15 19:20:03 UTC (rev 178517)
+++ trunk/Source/WebCore/platform/graphics/mac/FontMac.mm        2015-01-15 19:29:05 UTC (rev 178518)
</span><span class="lines">@@ -1,605 +0,0 @@
</span><del>-/*
- * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
- * (C) 1999 Antti Koivisto (koivisto@kde.org)
- * (C) 2000 Dirk Mueller (mueller@kde.org)
- * Copyright (C) 2003, 2006, 2007, 2008, 2009, 2010, 2011 Apple 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.
- */
-
-#import "config.h"
-#import "FontCascade.h"
-
-#import "CoreGraphicsSPI.h"
-#import "CoreTextSPI.h"
-#import "DashArray.h"
-#import "GlyphBuffer.h"
-#import "GraphicsContext.h"
-#import "Logging.h"
-#import "SimpleFontData.h"
-#import "WebCoreSystemInterface.h"
-#if USE(APPKIT)
-#import <AppKit/AppKit.h>
-#endif
-#import <wtf/MathExtras.h>
-
-#if ENABLE(LETTERPRESS)
-#import "CoreUISPI.h"
-#import "SoftLinking.h"
-
-SOFT_LINK_PRIVATE_FRAMEWORK(CoreUI)
-SOFT_LINK_CLASS(CoreUI, CUICatalog)
-SOFT_LINK_CLASS(CoreUI, CUIStyleEffectConfiguration)
-
-SOFT_LINK_FRAMEWORK(UIKit)
-SOFT_LINK(UIKit, _UIKitGetTextEffectsCatalog, CUICatalog *, (void), ())
-#endif
-
-#define SYNTHETIC_OBLIQUE_ANGLE 14
-
-#ifdef __LP64__
-#define URefCon void*
-#else
-#define URefCon UInt32
-#endif
-
-namespace WebCore {
-
-bool FontCascade::canReturnFallbackFontsForComplexText()
-{
- return true;
-}
-
-bool FontCascade::canExpandAroundIdeographsInComplexText()
-{
- return true;
-}
-
-static inline void fillVectorWithHorizontalGlyphPositions(Vector<CGPoint, 256>& positions, CGContextRef context, const CGSize* advances, size_t count)
-{
- CGAffineTransform matrix = CGAffineTransformInvert(CGContextGetTextMatrix(context));
- positions[0] = CGPointZero;
- for (size_t i = 1; i < count; ++i) {
- CGSize advance = CGSizeApplyAffineTransform(advances[i - 1], matrix);
- positions[i].x = positions[i - 1].x + advance.width;
- positions[i].y = positions[i - 1].y + advance.height;
- }
-}
-
-static inline bool shouldUseLetterpressEffect(const GraphicsContext& context)
-{
-#if ENABLE(LETTERPRESS)
- return context.textDrawingMode() & TextModeLetterpress;
-#else
- UNUSED_PARAM(context);
- return false;
-#endif
-}
-
-static void showLetterpressedGlyphsWithAdvances(const FloatPoint& point, const SimpleFontData* font, CGContextRef context, const CGGlyph* glyphs, const CGSize* advances, size_t count)
-{
-#if ENABLE(LETTERPRESS)
- if (!count)
- return;
-
- const FontPlatformData& platformData = font->platformData();
- if (platformData.orientation() == Vertical) {
- // FIXME: Implement support for vertical text. See <rdar://problem/13737298>.
- return;
- }
-
- CGContextSetTextPosition(context, point.x(), point.y());
- Vector<CGPoint, 256> positions(count);
- fillVectorWithHorizontalGlyphPositions(positions, context, advances, count);
-
- CTFontRef ctFont = platformData.ctFont();
- CGContextSetFontSize(context, CTFontGetSize(ctFont));
-
- static CUICatalog *catalog = _UIKitGetTextEffectsCatalog();
- if (!catalog)
- return;
-
- static CUIStyleEffectConfiguration *styleConfiguration;
- if (!styleConfiguration) {
- styleConfiguration = [allocCUIStyleEffectConfigurationInstance() init];
- styleConfiguration.useSimplifiedEffect = YES;
- }
-
- [catalog drawGlyphs:glyphs atPositions:positions.data() inContext:context withFont:ctFont count:count stylePresetName:@"_UIKitNewLetterpressStyle" styleConfiguration:styleConfiguration foregroundColor:CGContextGetFillColorAsColor(context)];
-#else
- UNUSED_PARAM(point);
- UNUSED_PARAM(font);
- UNUSED_PARAM(context);
- UNUSED_PARAM(glyphs);
- UNUSED_PARAM(advances);
- UNUSED_PARAM(count);
-#endif
-}
-
-static void showGlyphsWithAdvances(const FloatPoint& point, const SimpleFontData* font, CGContextRef context, const CGGlyph* glyphs, const CGSize* advances, size_t count)
-{
- if (!count)
- return;
-
- CGContextSetTextPosition(context, point.x(), point.y());
-
- const FontPlatformData& platformData = font->platformData();
- Vector<CGPoint, 256> positions(count);
- if (platformData.isColorBitmapFont())
- fillVectorWithHorizontalGlyphPositions(positions, context, advances, count);
- if (platformData.orientation() == Vertical) {
- CGAffineTransform savedMatrix;
- CGAffineTransform rotateLeftTransform = CGAffineTransformMake(0, -1, 1, 0, 0, 0);
- savedMatrix = CGContextGetTextMatrix(context);
- CGAffineTransform runMatrix = CGAffineTransformConcat(savedMatrix, rotateLeftTransform);
- CGContextSetTextMatrix(context, runMatrix);
-
- Vector<CGSize, 256> translations(count);
- CTFontGetVerticalTranslationsForGlyphs(platformData.ctFont(), glyphs, translations.data(), count);
-
- CGAffineTransform transform = CGAffineTransformInvert(CGContextGetTextMatrix(context));
-
- CGPoint position = FloatPoint(point.x(), point.y() + font->fontMetrics().floatAscent(IdeographicBaseline) - font->fontMetrics().floatAscent());
- for (size_t i = 0; i < count; ++i) {
- CGSize translation = CGSizeApplyAffineTransform(translations[i], rotateLeftTransform);
- positions[i] = CGPointApplyAffineTransform(CGPointMake(position.x - translation.width, position.y + translation.height), transform);
- position.x += advances[i].width;
- position.y += advances[i].height;
- }
- if (!platformData.isColorBitmapFont())
- CGContextShowGlyphsAtPositions(context, glyphs, positions.data(), count);
- else
- CTFontDrawGlyphs(platformData.ctFont(), glyphs, positions.data(), count, context);
- CGContextSetTextMatrix(context, savedMatrix);
- } else {
- if (!platformData.isColorBitmapFont())
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wdeprecated-declarations"
- CGContextShowGlyphsWithAdvances(context, glyphs, advances, count);
-#pragma clang diagnostic pop
- else
- CTFontDrawGlyphs(platformData.ctFont(), glyphs, positions.data(), count, context);
- }
-}
-
-#if PLATFORM(MAC)
-static void setCGFontRenderingMode(CGContextRef cgContext, NSFontRenderingMode renderingMode, BOOL shouldSubpixelQuantize)
-{
- if (renderingMode == NSFontIntegerAdvancementsRenderingMode) {
- CGContextSetShouldAntialiasFonts(cgContext, false);
- return;
- }
-
- CGContextSetShouldAntialiasFonts(cgContext, true);
-
- CGAffineTransform contextTransform = CGContextGetCTM(cgContext);
- BOOL isTranslationOrIntegralScale = WTF::isIntegral(contextTransform.a) && WTF::isIntegral(contextTransform.d) && contextTransform.b == 0.f && contextTransform.c == 0.f;
- BOOL isRotated = ((contextTransform.b || contextTransform.c) && (contextTransform.a || contextTransform.d));
- BOOL doSubpixelQuantization = isTranslationOrIntegralScale || (!isRotated && shouldSubpixelQuantize);
-
- CGContextSetShouldSubpixelPositionFonts(cgContext, renderingMode != NSFontAntialiasedIntegerAdvancementsRenderingMode || !isTranslationOrIntegralScale);
- CGContextSetShouldSubpixelQuantizeFonts(cgContext, doSubpixelQuantization);
-}
-#endif
-
-void FontCascade::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, const GlyphBuffer& glyphBuffer, int from, int numGlyphs, const FloatPoint& anchorPoint) const
-{
- const FontPlatformData& platformData = font->platformData();
- if (!platformData.size())
- return;
-
- CGContextRef cgContext = context->platformContext();
-
- bool shouldSmoothFonts;
- bool changeFontSmoothing;
-
- switch(fontDescription().fontSmoothing()) {
- case Antialiased: {
- context->setShouldAntialias(true);
- shouldSmoothFonts = false;
- changeFontSmoothing = true;
- break;
- }
- case SubpixelAntialiased: {
- context->setShouldAntialias(true);
- shouldSmoothFonts = true;
- changeFontSmoothing = true;
- break;
- }
- case NoSmoothing: {
- context->setShouldAntialias(false);
- shouldSmoothFonts = false;
- changeFontSmoothing = true;
- break;
- }
- case AutoSmoothing: {
- shouldSmoothFonts = true;
- changeFontSmoothing = false;
- break;
- }
- }
-
- if (!shouldUseSmoothing()) {
- shouldSmoothFonts = false;
- changeFontSmoothing = true;
- }
-
-#if !PLATFORM(IOS)
- bool originalShouldUseFontSmoothing = false;
- if (changeFontSmoothing) {
- originalShouldUseFontSmoothing = CGContextGetShouldSmoothFonts(cgContext);
- CGContextSetShouldSmoothFonts(cgContext, shouldSmoothFonts);
- }
-#endif
-
-#if !PLATFORM(IOS)
- NSFont* drawFont;
- if (!isPrinterFont()) {
- drawFont = [platformData.nsFont() screenFont];
- if (drawFont != platformData.nsFont()) {
- // We are getting this in too many places (3406411); use ERROR so it only prints on debug versions for now. (We should debug this also, eventually).
- LOG_ERROR("Attempting to set non-screen font (%@) when drawing to screen. Using screen font anyway, may result in incorrect metrics.",
- [[[platformData.nsFont() fontDescriptor] fontAttributes] objectForKey:NSFontNameAttribute]);
- }
- } else {
- drawFont = [platformData.nsFont() printerFont];
- if (drawFont != platformData.nsFont()) {
- NSLog(@"Attempting to set non-printer font (%@) when printing. Using printer font anyway, may result in incorrect metrics.",
- [[[platformData.nsFont() fontDescriptor] fontAttributes] objectForKey:NSFontNameAttribute]);
- }
- }
-#endif
-
- CGContextSetFont(cgContext, platformData.cgFont());
-
- bool useLetterpressEffect = shouldUseLetterpressEffect(*context);
- FloatPoint point = anchorPoint;
-#if PLATFORM(IOS)
- float fontSize = platformData.size();
- CGAffineTransform matrix = useLetterpressEffect || platformData.isColorBitmapFont() ? CGAffineTransformIdentity : CGAffineTransformMakeScale(fontSize, fontSize);
- if (platformData.m_isEmoji) {
- if (!context->emojiDrawingEnabled())
- return;
-
- // Mimic the positioining of non-bitmap glyphs, which are not subpixel-positioned.
- point.setY(ceilf(point.y()));
-
- // Emoji glyphs snap to the CSS pixel grid.
- point.setX(floorf(point.x()));
-
- // Emoji glyphs are offset one CSS pixel to the right.
- point.move(1, 0);
-
- // Emoji glyphs are offset vertically based on font size.
- float y = point.y();
- if (fontSize <= 15) {
- // Undo Core Text's y adjustment.
- static float yAdjustmentFactor = iosExecutableWasLinkedOnOrAfterVersion(wkIOSSystemVersion_6_0) ? .19 : .1;
- point.setY(floorf(y - yAdjustmentFactor * (fontSize + 2) + 2));
- } else {
- if (fontSize < 26)
- y -= .35f * fontSize - 10;
-
- // Undo Core Text's y adjustment.
- static float yAdjustment = iosExecutableWasLinkedOnOrAfterVersion(wkIOSSystemVersion_6_0) ? 3.8 : 2;
- point.setY(floorf(y - yAdjustment));
- }
- }
-#else
- CGAffineTransform matrix = CGAffineTransformIdentity;
- if (drawFont && !platformData.isColorBitmapFont())
- memcpy(&matrix, [drawFont matrix], sizeof(matrix));
-#endif
- matrix.b = -matrix.b;
- matrix.d = -matrix.d;
- if (platformData.m_syntheticOblique) {
- static float obliqueSkew = tanf(SYNTHETIC_OBLIQUE_ANGLE * piFloat / 180);
- if (platformData.orientation() == Vertical)
- matrix = CGAffineTransformConcat(matrix, CGAffineTransformMake(1, obliqueSkew, 0, 1, 0, 0));
- else
- matrix = CGAffineTransformConcat(matrix, CGAffineTransformMake(1, 0, -obliqueSkew, 1, 0, 0));
- }
- CGContextSetTextMatrix(cgContext, matrix);
-
-#if PLATFORM(IOS)
- CGContextSetFontSize(cgContext, 1);
- CGContextSetShouldSubpixelQuantizeFonts(cgContext, context->shouldSubpixelQuantizeFonts());
-#else
- setCGFontRenderingMode(cgContext, [drawFont renderingMode], context->shouldSubpixelQuantizeFonts());
- if (drawFont)
- CGContextSetFontSize(cgContext, 1);
- else
- CGContextSetFontSize(cgContext, platformData.m_size);
-#endif
-
-
- FloatSize shadowOffset;
- float shadowBlur;
- Color shadowColor;
- ColorSpace shadowColorSpace;
- ColorSpace fillColorSpace = context->fillColorSpace();
- context->getShadow(shadowOffset, shadowBlur, shadowColor, shadowColorSpace);
-
- AffineTransform contextCTM = context->getCTM();
- float syntheticBoldOffset = font->syntheticBoldOffset();
- if (syntheticBoldOffset && !contextCTM.isIdentityOrTranslationOrFlipped()) {
- FloatSize horizontalUnitSizeInDevicePixels = contextCTM.mapSize(FloatSize(1, 0));
- float horizontalUnitLengthInDevicePixels = sqrtf(horizontalUnitSizeInDevicePixels.width() * horizontalUnitSizeInDevicePixels.width() + horizontalUnitSizeInDevicePixels.height() * horizontalUnitSizeInDevicePixels.height());
- if (horizontalUnitLengthInDevicePixels)
- syntheticBoldOffset /= horizontalUnitLengthInDevicePixels;
- };
-
- bool hasSimpleShadow = context->textDrawingMode() == TextModeFill && shadowColor.isValid() && !shadowBlur && !platformData.isColorBitmapFont() && (!context->shadowsIgnoreTransforms() || contextCTM.isIdentityOrTranslationOrFlipped()) && !context->isInTransparencyLayer();
- if (hasSimpleShadow) {
- // Paint simple shadows ourselves instead of relying on CG shadows, to avoid losing subpixel antialiasing.
- context->clearShadow();
- Color fillColor = context->fillColor();
- Color shadowFillColor(shadowColor.red(), shadowColor.green(), shadowColor.blue(), shadowColor.alpha() * fillColor.alpha() / 255);
- context->setFillColor(shadowFillColor, shadowColorSpace);
- float shadowTextX = point.x() + shadowOffset.width();
- // If shadows are ignoring transforms, then we haven't applied the Y coordinate flip yet, so down is negative.
- float shadowTextY = point.y() + shadowOffset.height() * (context->shadowsIgnoreTransforms() ? -1 : 1);
- showGlyphsWithAdvances(FloatPoint(shadowTextX, shadowTextY), font, cgContext, glyphBuffer.glyphs(from), static_cast<const CGSize*>(glyphBuffer.advances(from)), numGlyphs);
-#if !PLATFORM(IOS)
- if (syntheticBoldOffset)
-#else
- if (syntheticBoldOffset && !platformData.m_isEmoji)
-#endif
- showGlyphsWithAdvances(FloatPoint(shadowTextX + syntheticBoldOffset, shadowTextY), font, cgContext, glyphBuffer.glyphs(from), static_cast<const CGSize*>(glyphBuffer.advances(from)), numGlyphs);
- context->setFillColor(fillColor, fillColorSpace);
- }
-
- if (useLetterpressEffect)
- showLetterpressedGlyphsWithAdvances(point, font, cgContext, glyphBuffer.glyphs(from), static_cast<const CGSize*>(glyphBuffer.advances(from)), numGlyphs);
- else
- showGlyphsWithAdvances(point, font, cgContext, glyphBuffer.glyphs(from), static_cast<const CGSize*>(glyphBuffer.advances(from)), numGlyphs);
-#if !PLATFORM(IOS)
- if (syntheticBoldOffset)
-#else
- if (syntheticBoldOffset && !platformData.m_isEmoji)
-#endif
- showGlyphsWithAdvances(FloatPoint(point.x() + syntheticBoldOffset, point.y()), font, cgContext, glyphBuffer.glyphs(from), static_cast<const CGSize*>(glyphBuffer.advances(from)), numGlyphs);
-
- if (hasSimpleShadow)
- context->setShadow(shadowOffset, shadowBlur, shadowColor, shadowColorSpace);
-
-#if !PLATFORM(IOS)
- if (changeFontSmoothing)
- CGContextSetShouldSmoothFonts(cgContext, originalShouldUseFontSmoothing);
-#endif
-}
-
-#if ENABLE(CSS3_TEXT_DECORATION_SKIP_INK)
-struct GlyphIterationState {
- GlyphIterationState(CGPoint startingPoint, CGPoint currentPoint, CGFloat y1, CGFloat y2, CGFloat minX, CGFloat maxX)
- : startingPoint(startingPoint)
- , currentPoint(currentPoint)
- , y1(y1)
- , y2(y2)
- , minX(minX)
- , maxX(maxX)
- {
- }
- CGPoint startingPoint;
- CGPoint currentPoint;
- CGFloat y1;
- CGFloat y2;
- CGFloat minX;
- CGFloat maxX;
-};
-
-static bool findIntersectionPoint(float y, CGPoint p1, CGPoint p2, CGFloat& x)
-{
- x = p1.x + (y - p1.y) * (p2.x - p1.x) / (p2.y - p1.y);
- return (p1.y < y && p2.y > y) || (p1.y > y && p2.y < y);
-}
-
-static void updateX(GlyphIterationState& state, CGFloat x)
-{
- state.minX = std::min(state.minX, x);
- state.maxX = std::max(state.maxX, x);
-}
-
-// This function is called by CGPathApply and is therefore invoked for each
-// contour in a glyph. This function models each contours as a straight line
-// and calculates the intersections between each pseudo-contour and
-// two horizontal lines (the upper and lower bounds of an underline) found in
-// GlyphIterationState::y1 and GlyphIterationState::y2. It keeps track of the
-// leftmost and rightmost intersection in GlyphIterationState::minX and
-// GlyphIterationState::maxX.
-static void findPathIntersections(void* stateAsVoidPointer, const CGPathElement* e)
-{
- auto& state = *static_cast<GlyphIterationState*>(stateAsVoidPointer);
- bool doIntersection = false;
- CGPoint point = CGPointZero;
- switch (e->type) {
- case kCGPathElementMoveToPoint:
- state.startingPoint = e->points[0];
- state.currentPoint = e->points[0];
- break;
- case kCGPathElementAddLineToPoint:
- doIntersection = true;
- point = e->points[0];
- break;
- case kCGPathElementAddQuadCurveToPoint:
- doIntersection = true;
- point = e->points[1];
- break;
- case kCGPathElementAddCurveToPoint:
- doIntersection = true;
- point = e->points[2];
- break;
- case kCGPathElementCloseSubpath:
- doIntersection = true;
- point = state.startingPoint;
- break;
- }
- if (!doIntersection)
- return;
- CGFloat x;
- if (findIntersectionPoint(state.y1, state.currentPoint, point, x))
- updateX(state, x);
- if (findIntersectionPoint(state.y2, state.currentPoint, point, x))
- updateX(state, x);
- if ((state.currentPoint.y >= state.y1 && state.currentPoint.y <= state.y2)
- || (state.currentPoint.y <= state.y1 && state.currentPoint.y >= state.y2))
- updateX(state, state.currentPoint.x);
- state.currentPoint = point;
-}
-
-class MacGlyphToPathTranslator final : public GlyphToPathTranslator {
-public:
- MacGlyphToPathTranslator(const TextRun& textRun, const GlyphBuffer& glyphBuffer, const FloatPoint& textOrigin)
- : m_index(0)
- , m_textRun(textRun)
- , m_glyphBuffer(glyphBuffer)
- , m_fontData(glyphBuffer.fontDataAt(m_index))
- , m_translation(CGAffineTransformScale(CGAffineTransformMakeTranslation(textOrigin.x(), textOrigin.y()), 1, -1))
- {
- moveToNextValidGlyph();
- }
-private:
- virtual bool containsMorePaths() override
- {
- return m_index != m_glyphBuffer.size();
- }
- virtual Path path() override;
- virtual std::pair<float, float> extents() override;
- virtual GlyphUnderlineType underlineType() override;
- virtual void advance() override;
- void moveToNextValidGlyph();
-
- int m_index;
- const TextRun& m_textRun;
- const GlyphBuffer& m_glyphBuffer;
- const SimpleFontData* m_fontData;
- CGAffineTransform m_translation;
-};
-
-Path MacGlyphToPathTranslator::path()
-{
- RetainPtr<CGPathRef> result = adoptCF(CTFontCreatePathForGlyph(m_fontData->platformData().ctFont(), m_glyphBuffer.glyphAt(m_index), &m_translation));
- return adoptCF(CGPathCreateMutableCopy(result.get()));
-}
-
-std::pair<float, float> MacGlyphToPathTranslator::extents()
-{
- CGPoint beginning = CGPointApplyAffineTransform(CGPointMake(0, 0), m_translation);
- CGSize end = CGSizeApplyAffineTransform(m_glyphBuffer.advanceAt(m_index), m_translation);
- return std::make_pair(static_cast<float>(beginning.x), static_cast<float>(beginning.x + end.width));
-}
-
-auto MacGlyphToPathTranslator::underlineType() -> GlyphUnderlineType
-{
- return computeUnderlineType(m_textRun, m_glyphBuffer, m_index);
-}
-
-void MacGlyphToPathTranslator::moveToNextValidGlyph()
-{
- if (!m_fontData->isSVGFont())
- return;
- advance();
-}
-
-void MacGlyphToPathTranslator::advance()
-{
- do {
- GlyphBufferAdvance advance = m_glyphBuffer.advanceAt(m_index);
- m_translation = CGAffineTransformTranslate(m_translation, advance.width(), advance.height());
- ++m_index;
- if (m_index >= m_glyphBuffer.size())
- break;
- m_fontData = m_glyphBuffer.fontDataAt(m_index);
- } while (m_fontData->isSVGFont() && m_index < m_glyphBuffer.size());
-}
-
-DashArray FontCascade::dashesForIntersectionsWithRect(const TextRun& run, const FloatPoint& textOrigin, const FloatRect& lineExtents) const
-{
- if (isLoadingCustomFonts())
- return DashArray();
-
- GlyphBuffer glyphBuffer;
- glyphBuffer.saveOffsetsInString();
- float deltaX;
- if (codePath(run) != FontCascade::Complex)
- deltaX = getGlyphsAndAdvancesForSimpleText(run, 0, run.length(), glyphBuffer);
- else
- deltaX = getGlyphsAndAdvancesForComplexText(run, 0, run.length(), glyphBuffer);
-
- if (!glyphBuffer.size())
- return DashArray();
-
- // FIXME: Handle SVG + non-SVG interleaved runs. https://bugs.webkit.org/show_bug.cgi?id=133778
- const SimpleFontData* fontData = glyphBuffer.fontDataAt(0);
- std::unique_ptr<GlyphToPathTranslator> translator;
- bool isSVG = false;
- FloatPoint origin = FloatPoint(textOrigin.x() + deltaX, textOrigin.y());
- if (!fontData->isSVGFont())
- translator = std::make_unique<MacGlyphToPathTranslator>(run, glyphBuffer, origin);
- else {
- TextRun::RenderingContext* renderingContext = run.renderingContext();
- if (!renderingContext)
- return DashArray();
- translator = renderingContext->createGlyphToPathTranslator(*fontData, &run, glyphBuffer, 0, glyphBuffer.size(), origin);
- isSVG = true;
- }
- DashArray result;
- for (int index = 0; translator->containsMorePaths(); ++index, translator->advance()) {
- GlyphIterationState info = GlyphIterationState(CGPointMake(0, 0), CGPointMake(0, 0), lineExtents.y(), lineExtents.y() + lineExtents.height(), lineExtents.x() + lineExtents.width(), lineExtents.x());
- const SimpleFontData* localFontData = glyphBuffer.fontDataAt(index);
- if (!localFontData || (!isSVG && localFontData->isSVGFont()) || (isSVG && localFontData != fontData)) {
- // The advances will get all messed up if we do anything other than bail here.
- result.clear();
- break;
- }
- switch (translator->underlineType()) {
- case GlyphToPathTranslator::GlyphUnderlineType::SkipDescenders: {
- Path path = translator->path();
- CGPathApply(path.platformPath(), &info, &findPathIntersections);
- if (info.minX < info.maxX) {
- result.append(info.minX - lineExtents.x());
- result.append(info.maxX - lineExtents.x());
- }
- break;
- }
- case GlyphToPathTranslator::GlyphUnderlineType::SkipGlyph: {
- std::pair<float, float> extents = translator->extents();
- result.append(extents.first - lineExtents.x());
- result.append(extents.second - lineExtents.x());
- break;
- }
- case GlyphToPathTranslator::GlyphUnderlineType::DrawOverGlyph:
- // Nothing to do
- break;
- }
- }
- return result;
-}
-#endif
-
-bool FontCascade::primaryFontDataIsSystemFont() const
-{
-#if PLATFORM(IOS) || __MAC_OS_X_VERSION_MIN_REQUIRED > 1090
- const auto& fontData = primaryFontData();
- return !fontData.isSVGFont() && CTFontDescriptorIsSystemUIFont(adoptCF(CTFontCopyFontDescriptor(fontData.platformData().ctFont())).get());
-#else
- // System fonts are hidden by having a name that begins with a period, so simply search
- // for that here rather than try to keep the list up to date.
- return firstFamily().startsWith('.');
-#endif
-}
-
-}
</del></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsmacFontMacmmfromrev178510trunkSourceWebCoreplatformgraphicsmacSimpleFontDataMacmm"></a>
<div class="copfile"><h4>Copied: trunk/Source/WebCore/platform/graphics/mac/FontMac.mm (from rev 178510, trunk/Source/WebCore/platform/graphics/mac/SimpleFontDataMac.mm) (0 => 178518)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/mac/FontMac.mm         (rev 0)
+++ trunk/Source/WebCore/platform/graphics/mac/FontMac.mm        2015-01-15 19:29:05 UTC (rev 178518)
</span><span class="lines">@@ -0,0 +1,474 @@
</span><ins>+/*
+ * Copyright (C) 2005, 2006, 2010, 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Alexey Proskuryakov
+ *
+ * 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. 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 INC. 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.
+ */
+
+#import "config.h"
+#import "SimpleFontData.h"
+
+#import "BlockExceptions.h"
+#import "Color.h"
+#import "CoreGraphicsSPI.h"
+#import "CoreTextSPI.h"
+#import "FloatRect.h"
+#import "FontCache.h"
+#import "FontCascade.h"
+#import "FontDescription.h"
+#import "SharedBuffer.h"
+#import "WebCoreSystemInterface.h"
+#if USE(APPKIT)
+#import <AppKit/AppKit.h>
+#import <ApplicationServices/ApplicationServices.h>
+#else
+#import <CoreText/CoreText.h>
+#endif
+#import <float.h>
+#import <unicode/uchar.h>
+#import <wtf/Assertions.h>
+#import <wtf/StdLibExtras.h>
+#import <wtf/RetainPtr.h>
+
+#if !PLATFORM(IOS)
+@interface NSFont (WebAppKitSecretAPI)
+- (BOOL)_isFakeFixedPitch;
+@end
+#endif
+
+namespace WebCore {
+
+#if USE(APPKIT)
+static bool fontHasVerticalGlyphs(CTFontRef ctFont)
+{
+ // The check doesn't look neat but this is what AppKit does for vertical writing...
+ RetainPtr<CFArrayRef> tableTags = adoptCF(CTFontCopyAvailableTables(ctFont, kCTFontTableOptionNoOptions));
+ CFIndex numTables = CFArrayGetCount(tableTags.get());
+ for (CFIndex index = 0; index < numTables; ++index) {
+ CTFontTableTag tag = (CTFontTableTag)(uintptr_t)CFArrayGetValueAtIndex(tableTags.get(), index);
+ if (tag == kCTFontTableVhea || tag == kCTFontTableVORG)
+ return true;
+ }
+ return false;
+}
+
+static bool initFontData(SimpleFontData* fontData)
+{
+ if (!fontData->platformData().cgFont())
+ return false;
+
+ return true;
+}
+
+static NSString *webFallbackFontFamily(void)
+{
+ static NSString *webFallbackFontFamily = [[[NSFont systemFontOfSize:16.0f] familyName] retain];
+ return webFallbackFontFamily;
+}
+
+const SimpleFontData* SimpleFontData::compositeFontReferenceFontData(NSFont *key) const
+{
+ if (!key || CFEqual(adoptCF(CTFontCopyPostScriptName(CTFontRef(key))).get(), CFSTR("LastResort")))
+ return nullptr;
+
+ if (!m_derivedFontData)
+ m_derivedFontData = std::make_unique<DerivedFontData>(isCustomFont());
+
+ auto addResult = m_derivedFontData->compositeFontReferences.add(key, nullptr);
+ if (addResult.isNewEntry) {
+ bool isUsingPrinterFont = platformData().isPrinterFont();
+ NSFont *substituteFont = isUsingPrinterFont ? [key printerFont] : [key screenFont];
+
+ CTFontSymbolicTraits traits = CTFontGetSymbolicTraits((CTFontRef)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());
+ addResult.iterator->value = SimpleFontData::create(substitutePlatform, isCustomFont());
+ }
+ return addResult.iterator->value.get();
+}
+
+void SimpleFontData::platformInit()
+{
+ m_syntheticBoldOffset = m_platformData.m_syntheticBold ? 1.0f : 0.f;
+
+ bool failedSetup = false;
+ if (!initFontData(this)) {
+ // Ack! Something very bad happened, like a corrupt font.
+ // Try looking for an alternate 'base' font for this renderer.
+
+ // Special case hack to use "Times New Roman" in place of "Times".
+ // "Times RO" is a common font whose family name is "Times".
+ // It overrides the normal "Times" family font.
+ // It also appears to have a corrupt regular variant.
+ NSString *fallbackFontFamily;
+ if ([[m_platformData.nsFont() familyName] isEqual:@"Times"])
+ 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
+ RetainPtr<NSFont> initialFont = m_platformData.nsFont();
+#endif
+ if (m_platformData.font())
+ m_platformData.setNSFont([[NSFontManager sharedFontManager] convertFont:m_platformData.nsFont() toFamily:fallbackFontFamily]);
+ else
+ m_platformData.setNSFont([NSFont fontWithName:fallbackFontFamily size:m_platformData.size()]);
+ if (!initFontData(this)) {
+ if ([fallbackFontFamily isEqual:@"Times New Roman"]) {
+ // OK, couldn't setup Times New Roman as an alternate to Times, fallback
+ // on the system font. If this fails we have no alternative left.
+ m_platformData.setNSFont([[NSFontManager sharedFontManager] convertFont:m_platformData.nsFont() toFamily:webFallbackFontFamily()]);
+ if (!initFontData(this)) {
+ // We tried, Times, Times New Roman, and the system font. No joy. We have to give up.
+ LOG_ERROR("unable to initialize with font %@", initialFont.get());
+ failedSetup = true;
+ }
+ } else {
+ // We tried the requested font and the system font. No joy. We have to give up.
+ LOG_ERROR("unable to initialize with font %@", initialFont.get());
+ failedSetup = true;
+ }
+ }
+
+ // Report the problem.
+ LOG_ERROR("Corrupt font detected, using %@ in place of %@.",
+ [m_platformData.nsFont() familyName], [initialFont.get() familyName]);
+ }
+
+ // If all else fails, try to set up using the system font.
+ // This is probably because Times and Times New Roman are both unavailable.
+ if (failedSetup) {
+ m_platformData.setNSFont([NSFont systemFontOfSize:[m_platformData.nsFont() pointSize]]);
+ LOG_ERROR("failed to set up font, using system font %s", m_platformData.font());
+ initFontData(this);
+ }
+
+ int iAscent;
+ int iDescent;
+ int iCapHeight;
+ 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.
+ iDescent = -abs(CGFontGetDescent(m_platformData.cgFont()));
+ iCapHeight = CGFontGetCapHeight(m_platformData.cgFont());
+ iLineGap = CGFontGetLeading(m_platformData.cgFont());
+ unitsPerEm = CGFontGetUnitsPerEm(m_platformData.cgFont());
+
+ float pointSize = m_platformData.m_size;
+ float ascent = scaleEmToUnits(iAscent, unitsPerEm) * pointSize;
+ float descent = -scaleEmToUnits(iDescent, unitsPerEm) * pointSize;
+ float capHeight = scaleEmToUnits(iCapHeight, unitsPerEm) * pointSize;
+
+ float lineGap = scaleEmToUnits(iLineGap, unitsPerEm) * pointSize;
+
+ // We need to adjust Times, Helvetica, and Courier to closely match the
+ // vertical metrics of their Microsoft counterparts that are the de facto
+ // web standard. The AppKit adjustment of 20% is too big and is
+ // incorrectly added to line spacing, so we use a 15% adjustment instead
+ // and add it to the ascent.
+ NSString *familyName = [m_platformData.nsFont() familyName];
+ if ([familyName isEqualToString:@"Times"] || [familyName isEqualToString:@"Helvetica"] || [familyName isEqualToString:@"Courier"])
+ ascent += floorf(((ascent + descent) * 0.15f) + 0.5f);
+
+ // Compute and store line spacing, before the line metrics hacks are applied.
+ m_fontMetrics.setLineSpacing(lroundf(ascent) + lroundf(descent) + lroundf(lineGap));
+
+ // Hack Hiragino line metrics to allow room for marked text underlines.
+ // <rdar://problem/5386183>
+ if (descent < 3 && lineGap >= 3 && [familyName hasPrefix:@"Hiragino"]) {
+ lineGap -= 3 - descent;
+ descent = 3;
+ }
+
+ if (platformData().orientation() == Vertical && !isTextOrientationFallback())
+ m_hasVerticalGlyphs = fontHasVerticalGlyphs(m_platformData.ctFont());
+
+ float xHeight;
+
+ if (platformData().orientation() == Horizontal) {
+ // Measure the actual character "x", since it's possible for it to extend below the baseline, and we need the
+ // reported x-height to only include the portion of the glyph that is above the baseline.
+ NSGlyph xGlyph = glyphForCharacter('x');
+ if (xGlyph)
+ xHeight = -CGRectGetMinY(platformBoundsForGlyph(xGlyph));
+ else
+ xHeight = scaleEmToUnits(CGFontGetXHeight(m_platformData.cgFont()), unitsPerEm) * pointSize;
+ } else
+ xHeight = verticalRightOrientationFontData()->fontMetrics().xHeight();
+
+ m_fontMetrics.setUnitsPerEm(unitsPerEm);
+ m_fontMetrics.setAscent(ascent);
+ m_fontMetrics.setDescent(descent);
+ m_fontMetrics.setCapHeight(capHeight);
+ m_fontMetrics.setLineGap(lineGap);
+ m_fontMetrics.setXHeight(xHeight);
+}
+
+static CFDataRef copyFontTableForTag(FontPlatformData& platformData, FourCharCode tableName)
+{
+ return CGFontCopyTableForTag(platformData.cgFont(), tableName);
+}
+
+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());
+ SInt16 os2AvgCharWidth = os2[2] * 256 + os2[3];
+ m_avgCharWidth = scaleEmToUnits(os2AvgCharWidth, m_fontMetrics.unitsPerEm()) * m_platformData.m_size;
+ }
+
+ RetainPtr<CFDataRef> headTable = adoptCF(copyFontTableForTag(m_platformData, 'head'));
+ if (headTable && CFDataGetLength(headTable.get()) >= 42) {
+ const UInt8* head = CFDataGetBytePtr(headTable.get());
+ ushort uxMin = head[36] * 256 + head[37];
+ ushort uxMax = head[40] * 256 + head[41];
+ SInt16 xMin = static_cast<SInt16>(uxMin);
+ SInt16 xMax = static_cast<SInt16>(uxMax);
+ float diff = static_cast<float>(xMax - xMin);
+ m_maxCharWidth = scaleEmToUnits(diff, m_fontMetrics.unitsPerEm()) * m_platformData.m_size;
+ }
+
+ // Fallback to a cross-platform estimate, which will populate these values if they are non-positive.
+ initCharWidths();
+}
+#endif // USE(APPKIT)
+
+void SimpleFontData::platformDestroy()
+{
+}
+
+#if !PLATFORM(IOS)
+PassRefPtr<SimpleFontData> SimpleFontData::platformCreateScaledFontData(const FontDescription& fontDescription, float scaleFactor) const
+{
+ if (isCustomFont()) {
+ FontPlatformData scaledFontData(m_platformData);
+ scaledFontData.m_size = scaledFontData.m_size * scaleFactor;
+ return SimpleFontData::create(scaledFontData, true, false);
+ }
+
+ BEGIN_BLOCK_OBJC_EXCEPTIONS;
+ float size = m_platformData.size() * scaleFactor;
+ FontPlatformData scaledFontData([[NSFontManager sharedFontManager] convertFont:m_platformData.nsFont() toSize:size], size, m_platformData.isPrinterFont(), 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.setNSFont(fontDescription.usePrinterFont() ? [scaledFontData.nsFont() printerFont] : [scaledFontData.nsFont() screenFont]);
+
+ if (scaledFontData.font()) {
+ NSFontManager *fontManager = [NSFontManager sharedFontManager];
+ NSFontTraitMask fontTraits = [fontManager traitsOfFont:m_platformData.nsFont()];
+
+ if (m_platformData.m_syntheticBold)
+ fontTraits |= NSBoldFontMask;
+ if (m_platformData.m_syntheticOblique)
+ fontTraits |= NSItalicFontMask;
+
+ NSFontTraitMask scaledFontTraits = [fontManager traitsOfFont:scaledFontData.nsFont()];
+ scaledFontData.m_syntheticBold = (fontTraits & NSBoldFontMask) && !(scaledFontTraits & NSBoldFontMask);
+ scaledFontData.m_syntheticOblique = (fontTraits & NSItalicFontMask) && !(scaledFontTraits & NSItalicFontMask);
+
+ return fontCache().fontForPlatformData(scaledFontData);
+ }
+ END_BLOCK_OBJC_EXCEPTIONS;
+
+ return 0;
+}
+
+void SimpleFontData::determinePitch()
+{
+ NSFont* f = m_platformData.nsFont();
+ // Special case Osaka-Mono.
+ // According to <rdar://problem/3999467>, we should treat Osaka-Mono as fixed pitch.
+ // Note that the AppKit does not report Osaka-Mono as fixed pitch.
+
+ // Special case MS-PGothic.
+ // According to <rdar://problem/4032938>, we should not treat MS-PGothic as fixed pitch.
+ // Note that AppKit does report MS-PGothic as fixed pitch.
+
+ // Special case MonotypeCorsiva
+ // According to <rdar://problem/5454704>, we should not treat MonotypeCorsiva as fixed pitch.
+ // Note that AppKit does report MonotypeCorsiva as fixed pitch.
+
+ NSString *name = [f fontName];
+ m_treatAsFixedPitch = ([f isFixedPitch] || [f _isFakeFixedPitch] ||
+ [name caseInsensitiveCompare:@"Osaka-Mono"] == NSOrderedSame) &&
+ [name caseInsensitiveCompare:@"MS-PGothic"] != NSOrderedSame &&
+ [name caseInsensitiveCompare:@"MonotypeCorsiva"] != NSOrderedSame;
+}
+#endif // !PLATFORM(IOS)
+
+FloatRect SimpleFontData::platformBoundsForGlyph(Glyph glyph) const
+{
+ FloatRect boundingBox;
+ boundingBox = CTFontGetBoundingRectsForGlyphs(m_platformData.ctFont(), platformData().orientation() == Vertical ? kCTFontVerticalOrientation : kCTFontHorizontalOrientation, &glyph, 0, 1);
+ boundingBox.setY(-boundingBox.maxY());
+ if (m_syntheticBoldOffset)
+ boundingBox.setWidth(boundingBox.width() + m_syntheticBoldOffset);
+
+ return boundingBox;
+}
+
+#if PLATFORM(MAC)
+inline CGFontRenderingStyle SimpleFontData::renderingStyle() const
+{
+ CGFontRenderingStyle style = kCGFontRenderingStyleAntialiasing | kCGFontRenderingStyleSubpixelPositioning | kCGFontRenderingStyleSubpixelQuantization;
+ NSFont *font = platformData().nsFont();
+ if (font) {
+ switch ([font renderingMode]) {
+ case NSFontIntegerAdvancementsRenderingMode:
+ style = 0;
+ break;
+ case NSFontAntialiasedIntegerAdvancementsRenderingMode:
+ style = kCGFontRenderingStyleAntialiasing;
+ break;
+ default:
+ break;
+ }
+ }
+ return style;
+}
+
+inline bool SimpleFontData::advanceForColorBitmapFont(Glyph glyph, CGSize& advance) const
+{
+ NSFont *font = platformData().nsFont();
+ if (!font || !platformData().isColorBitmapFont())
+ return false;
+ advance = NSSizeToCGSize([font advancementForGlyph:glyph]);
+ return true;
+}
+#endif
+
+static bool hasCustomTracking(CTFontRef font)
+{
+#if PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED < 1090
+ UNUSED_PARAM(font);
+ return false;
+#else
+ return CTFontDescriptorIsSystemUIFont(adoptCF(CTFontCopyFontDescriptor(font)).get());
+#endif
+}
+
+static inline bool isEmoji(const FontPlatformData& platformData)
+{
+#if PLATFORM(IOS)
+ return platformData.m_isEmoji;
+#else
+ UNUSED_PARAM(platformData);
+ return false;
+#endif
+}
+
+inline bool SimpleFontData::canUseFastGlyphAdvanceGetter(Glyph glyph, CGSize& advance, bool& populatedAdvance) const
+{
+ // Fast getter doesn't take custom tracking into account
+ if (hasCustomTracking(platformData().ctFont()))
+ return false;
+ // Fast getter doesn't work for emoji
+ if (isEmoji(platformData()))
+ return false;
+ // ... or for any bitmap fonts in general
+ if (advanceForColorBitmapFont(glyph, advance)) {
+ populatedAdvance = true;
+ return false;
+ }
+ return true;
+}
+
+float SimpleFontData::platformWidthForGlyph(Glyph glyph) const
+{
+ CGSize advance = CGSizeZero;
+ bool horizontal = platformData().orientation() == Horizontal;
+ bool populatedAdvance = false;
+ if ((horizontal || m_isBrokenIdeographFallback) && canUseFastGlyphAdvanceGetter(glyph, advance, populatedAdvance)) {
+ float pointSize = platformData().m_size;
+ CGAffineTransform m = CGAffineTransformMakeScale(pointSize, pointSize);
+ if (!CGFontGetGlyphAdvancesForStyle(platformData().cgFont(), &m, renderingStyle(), &glyph, 1, &advance)) {
+ RetainPtr<CFStringRef> fullName = adoptCF(CGFontCopyFullName(platformData().cgFont()));
+ LOG_ERROR("Unable to cache glyph widths for %@ %f", fullName.get(), pointSize);
+ advance.width = 0;
+ }
+ } else if (!populatedAdvance)
+ CTFontGetAdvancesForGlyphs(m_platformData.ctFont(), horizontal ? kCTFontHorizontalOrientation : kCTFontVerticalOrientation, &glyph, &advance, 1);
+
+ return advance.width + m_syntheticBoldOffset;
+}
+
+struct ProviderInfo {
+ const UChar* characters;
+ size_t length;
+ CFDictionaryRef attributes;
+};
+
+static const UniChar* provideStringAndAttributes(CFIndex stringIndex, CFIndex* count, CFDictionaryRef* attributes, void* context)
+{
+ ProviderInfo* info = static_cast<struct ProviderInfo*>(context);
+ if (stringIndex < 0 || static_cast<size_t>(stringIndex) >= info->length)
+ return 0;
+
+ *count = info->length - stringIndex;
+ *attributes = info->attributes;
+ return info->characters + stringIndex;
+}
+
+bool SimpleFontData::canRenderCombiningCharacterSequence(const UChar* characters, size_t length) const
+{
+ ASSERT(isMainThread());
+
+ if (!m_combiningCharacterSequenceSupport)
+ m_combiningCharacterSequenceSupport = std::make_unique<HashMap<String, bool>>();
+
+ WTF::HashMap<String, bool>::AddResult addResult = m_combiningCharacterSequenceSupport->add(String(characters, length), false);
+ if (!addResult.isNewEntry)
+ return addResult.iterator->value;
+
+ RetainPtr<CFTypeRef> fontEqualityObject = platformData().objectForEqualityCheck();
+
+ ProviderInfo info = { characters, length, getCFStringAttributes(0, platformData().orientation()) };
+ RetainPtr<CTLineRef> line = adoptCF(CTLineCreateWithUniCharProvider(&provideStringAndAttributes, 0, &info));
+
+ CFArrayRef runArray = CTLineGetGlyphRuns(line.get());
+ CFIndex runCount = CFArrayGetCount(runArray);
+
+ for (CFIndex r = 0; r < runCount; r++) {
+ CTRunRef ctRun = static_cast<CTRunRef>(CFArrayGetValueAtIndex(runArray, r));
+ ASSERT(CFGetTypeID(ctRun) == CTRunGetTypeID());
+ CFDictionaryRef runAttributes = CTRunGetAttributes(ctRun);
+ CTFontRef runFont = static_cast<CTFontRef>(CFDictionaryGetValue(runAttributes, kCTFontAttributeName));
+ if (!CFEqual(fontEqualityObject.get(), FontPlatformData::objectForEqualityCheck(runFont).get()))
+ return false;
+ }
+
+ addResult.iterator->value = true;
+ return true;
+}
+
+} // namespace WebCore
</ins></span></pre></div>
<a id="trunkSourceWebCoreplatformwinDragImageWincpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/win/DragImageWin.cpp (178517 => 178518)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/win/DragImageWin.cpp        2015-01-15 19:20:03 UTC (rev 178517)
+++ trunk/Source/WebCore/platform/win/DragImageWin.cpp        2015-01-15 19:29:05 UTC (rev 178518)
</span><span class="lines">@@ -27,7 +27,7 @@
</span><span class="cx"> #include "DragImage.h"
</span><span class="cx">
</span><span class="cx"> #include "FloatRoundedRect.h"
</span><del>-#include "Font.h"
</del><ins>+#include "FontCascade.h"
</ins><span class="cx"> #include "FontDescription.h"
</span><span class="cx"> #include "FontSelector.h"
</span><span class="cx"> #include "GraphicsContext.h"
</span><span class="lines">@@ -101,9 +101,9 @@
</span><span class="cx"> const float DragLinkLabelFontsize = 11;
</span><span class="cx"> const float DragLinkUrlFontSize = 10;
</span><span class="cx">
</span><del>-static Font dragLabelFont(int size, bool bold, FontRenderingMode renderingMode)
</del><ins>+static FontCascade dragLabelFont(int size, bool bold, FontRenderingMode renderingMode)
</ins><span class="cx"> {
</span><del>- Font result;
</del><ins>+ FontCascade result;
</ins><span class="cx"> NONCLIENTMETRICS metrics;
</span><span class="cx"> metrics.cbSize = sizeof(metrics);
</span><span class="cx"> SystemParametersInfo(SPI_GETNONCLIENTMETRICS, metrics.cbSize, &metrics, 0);
</span><span class="lines">@@ -114,7 +114,7 @@
</span><span class="cx"> description.setSpecifiedSize((float)size);
</span><span class="cx"> description.setComputedSize((float)size);
</span><span class="cx"> description.setRenderingMode(renderingMode);
</span><del>- result = Font(description, 0, 0);
</del><ins>+ result = FontCascade(description, 0, 0);
</ins><span class="cx"> result.update(0);
</span><span class="cx"> return result;
</span><span class="cx"> }
</span><span class="lines">@@ -123,8 +123,8 @@
</span><span class="cx"> {
</span><span class="cx"> // This is more or less an exact match for the Mac OS X code.
</span><span class="cx">
</span><del>- const Font* labelFont;
- const Font* urlFont;
</del><ins>+ const FontCascade* labelFont;
+ const FontCascade* urlFont;
</ins><span class="cx">
</span><span class="cx"> if (fontRenderingMode == AlternateRenderingMode) {
</span><span class="cx"> static const Font alternateRenderingModeLabelFont = dragLabelFont(DragLinkLabelFontsize, true, AlternateRenderingMode);
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformwinPopupMenuWincpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/win/PopupMenuWin.cpp (178517 => 178518)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/win/PopupMenuWin.cpp        2015-01-15 19:20:03 UTC (rev 178517)
+++ trunk/Source/WebCore/platform/win/PopupMenuWin.cpp        2015-01-15 19:29:05 UTC (rev 178518)
</span><span class="lines">@@ -335,11 +335,11 @@
</span><span class="cx"> if (text.isEmpty())
</span><span class="cx"> continue;
</span><span class="cx">
</span><del>- Font itemFont = client()->menuStyle().font();
</del><ins>+ FontCascade itemFont = client()->menuStyle().font();
</ins><span class="cx"> if (client()->itemIsLabel(i)) {
</span><span class="cx"> FontDescription d = itemFont.fontDescription();
</span><span class="cx"> d.setWeight(d.bolderWeight());
</span><del>- itemFont = Font(d, itemFont.letterSpacing(), itemFont.wordSpacing());
</del><ins>+ itemFont = FontCascade(d, itemFont.letterSpacing(), itemFont.wordSpacing());
</ins><span class="cx"> itemFont.update(m_popupClient->fontSelector());
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -641,11 +641,11 @@
</span><span class="cx"> TextRun textRun(itemText, 0, 0, TextRun::AllowTrailingExpansion, itemStyle.textDirection(), itemStyle.hasTextDirectionOverride());
</span><span class="cx"> context.setFillColor(optionTextColor, ColorSpaceDeviceRGB);
</span><span class="cx">
</span><del>- Font itemFont = client()->menuStyle().font();
</del><ins>+ FontCascade itemFont = client()->menuStyle().font();
</ins><span class="cx"> if (client()->itemIsLabel(index)) {
</span><span class="cx"> FontDescription d = itemFont.fontDescription();
</span><span class="cx"> d.setWeight(d.bolderWeight());
</span><del>- itemFont = Font(d, itemFont.letterSpacing(), itemFont.wordSpacing());
</del><ins>+ itemFont = FontCascade(d, itemFont.letterSpacing(), itemFont.wordSpacing());
</ins><span class="cx"> itemFont.update(m_popupClient->fontSelector());
</span><span class="cx"> }
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformwinWebCoreTextRenderercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/win/WebCoreTextRenderer.cpp (178517 => 178518)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/win/WebCoreTextRenderer.cpp        2015-01-15 19:20:03 UTC (rev 178517)
+++ trunk/Source/WebCore/platform/win/WebCoreTextRenderer.cpp        2015-01-15 19:29:05 UTC (rev 178518)
</span><span class="lines">@@ -25,7 +25,7 @@
</span><span class="cx"> #include "config.h"
</span><span class="cx"> #include "WebCoreTextRenderer.h"
</span><span class="cx">
</span><del>-#include "Font.h"
</del><ins>+#include "FontCascade.h"
</ins><span class="cx"> #include "FontDescription.h"
</span><span class="cx"> #include "GraphicsContext.h"
</span><span class="cx"> #include "StringTruncator.h"
</span><span class="lines">@@ -45,7 +45,7 @@
</span><span class="cx"> return true;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-static void doDrawTextAtPoint(GraphicsContext& context, const String& text, const IntPoint& point, const Font& font, const Color& color, int underlinedIndex)
</del><ins>+static void doDrawTextAtPoint(GraphicsContext& context, const String& text, const IntPoint& point, const FontCascade& font, const Color& color, int underlinedIndex)
</ins><span class="cx"> {
</span><span class="cx"> TextRun run(text);
</span><span class="cx">
</span><span class="lines">@@ -76,7 +76,7 @@
</span><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx">
</span><del>-void WebCoreDrawDoubledTextAtPoint(GraphicsContext& context, const String& text, const IntPoint& point, const Font& font, const Color& topColor, const Color& bottomColor, int underlinedIndex)
</del><ins>+void WebCoreDrawDoubledTextAtPoint(GraphicsContext& context, const String& text, const IntPoint& point, const FontCascade& font, const Color& topColor, const Color& bottomColor, int underlinedIndex)
</ins><span class="cx"> {
</span><span class="cx"> context.save();
</span><span class="cx">
</span><span class="lines">@@ -89,7 +89,7 @@
</span><span class="cx"> context.restore();
</span><span class="cx"> }
</span><span class="cx">
</span><del>-float WebCoreTextFloatWidth(const String& text, const Font& font)
</del><ins>+float WebCoreTextFloatWidth(const String& text, const FontCascade& font)
</ins><span class="cx"> {
</span><span class="cx"> return StringTruncator::width(text, font, StringTruncator::EnableRoundingHacks);
</span><span class="cx"> }
</span><span class="lines">@@ -106,12 +106,12 @@
</span><span class="cx">
</span><span class="cx"> void WebCoreSetAlwaysUsesComplexTextCodePath(bool complex)
</span><span class="cx"> {
</span><del>- Font::setCodePath(complex ? Font::Complex : Font::Auto);
</del><ins>+ Font::setCodePath(complex ? FontCascade::Complex : FontCascade::Auto);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> bool WebCoreAlwaysUsesComplexTextCodePath()
</span><span class="cx"> {
</span><del>- return Font::codePath() == Font::Complex;
</del><ins>+ return Font::codePath() == FontCascade::Complex;
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> } // namespace WebCore
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingRenderThemeSafaricpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/RenderThemeSafari.cpp (178517 => 178518)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/RenderThemeSafari.cpp        2015-01-15 19:20:03 UTC (rev 178517)
+++ trunk/Source/WebCore/rendering/RenderThemeSafari.cpp        2015-01-15 19:29:05 UTC (rev 178518)
</span><span class="lines">@@ -401,7 +401,7 @@
</span><span class="cx"> style.setLineHeight(RenderStyle::initialLineHeight());
</span><span class="cx">
</span><span class="cx"> if (style.setFontDescription(fontDescription))
</span><del>- style.font().update(styleResolver.fontSelector());
</del><ins>+ style.fontCascade().update(styleResolver.fontSelector());
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> NSControlSize RenderThemeSafari::controlSizeForSystemFont(RenderStyle& style) const
</span></span></pre>
</div>
</div>
</body>
</html>