<!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>[174279] 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/174279">174279</a></dd>
<dt>Author</dt> <dd>mmaxfield@apple.com</dd>
<dt>Date</dt> <dd>2014-10-03 13:10:56 -0700 (Fri, 03 Oct 2014)</dd>
</dl>
<h3>Log Message</h3>
<pre>[SVG -> OTF Converter] Support non-BMP codepoints
https://bugs.webkit.org/show_bug.cgi?id=137097
Patch by Myles C. Maxfield <mmaxfield@apple.com> on 2014-09-28
Reviewed by Darin Adler.
This patch has two pieces:
1) Moves write16(), overwrite32() and overwrite16() inside SVGToOTFFontConverter. This
is so that we don't have to keep passing around references to m_result everywhere. Instead,
put the output vector inside the class as an instance member variable. In addition, rename
write32() and write16() to append32() and append16(), and provide a copy of append32 inside
SVGToOTFFontConverter.
2) Change the "Codepoint" typedef to be a String, and rename it to Codepoints. This is so that
we can implement ligatures later on. Update all the places that use this variable to work with
a String of multiple codepoints.
This patch updates the CMAP table to use format 12 instead of format 4. It currently only maps
single codepoints to glyph IDs and skips all multi-codepoint glyphs. We will implement
ligatures in another patch.
Test: svg/custom/glyph-selection-non-bmp.svg
* svg/SVGToOTFFontConversion.cpp:
(WebCore::append32): Append a result to a given vector. This is for the path transcoder.
(WebCore::SVGToOTFFontConverter::releaseResult): WTF::move()'s the result.
(WebCore::SVGToOTFFontConverter::GlyphData::GlyphData): Update to take Codepoints instead of Codepoint.
(WebCore::SVGToOTFFontConverter::append32): Piece 1 above.
(WebCore::SVGToOTFFontConverter::append16): Ditto.
(WebCore::SVGToOTFFontConverter::append4ByteCode): Convenience function.
(WebCore::SVGToOTFFontConverter::overwrite32): Piece 1 above.
(WebCore::SVGToOTFFontConverter::overwrite16): Ditto.
(WebCore::SVGToOTFFontConverter::appendCMAPTable): Update to format 12.
(WebCore::SVGToOTFFontConverter::appendHEADTable): Passing in a result vector is no longer necessary.
(WebCore::SVGToOTFFontConverter::appendHHEATable): Ditto.
(WebCore::SVGToOTFFontConverter::appendHMTXTable): Ditto.
(WebCore::SVGToOTFFontConverter::appendMAXPTable): Ditto.
(WebCore::SVGToOTFFontConverter::appendNAMETable): Ditto.
(WebCore::SVGToOTFFontConverter::appendOS2Table): Ditto.
(WebCore::SVGToOTFFontConverter::appendPOSTTable): Ditto.
(WebCore::isValidStringForCFF): Ditto.
(WebCore::SVGToOTFFontConverter::appendCFFValidString): Ditto.
(WebCore::SVGToOTFFontConverter::appendCFFTable): Ditto.
(WebCore::SVGToOTFFontConverter::appendVORGTable): Ditto.
(WebCore::SVGToOTFFontConverter::appendVHEATable): Ditto.
(WebCore::SVGToOTFFontConverter::appendVMTXTable): Ditto.
(WebCore::SVGToOTFFontConverter::addCodepointRanges): Update for Codepoints.
(WebCore::SVGToOTFFontConverter::addCodepoints): Ditto.
(WebCore::SVGToOTFFontConverter::addGlyphNames): Ditto.
(WebCore::SVGToOTFFontConverter::appendKERNSubtable): Ditto.
(WebCore::SVGToOTFFontConverter::appendKERNTable): Ditto.
(WebCore::writeCFFEncodedNumber): Passing in a result vector is no longer necessary.
(WebCore::SVGToOTFFontConverter::appendGlyphData): Update for Codepoints.
(WebCore::SVGToOTFFontConverter::processGlyphElement): Update for Codepoints.
(WebCore::SVGToOTFFontConverter::compareCodepointsLexicographically): Comparing Codepoints
(WebCore::SVGToOTFFontConverter::SVGToOTFFontConverter): Update for Codepoints.
(WebCore::SVGToOTFFontConverter::calculateChecksum): Passing in a result vector is no longer necessary.
(WebCore::SVGToOTFFontConverter::appendTable): Ditto.
(WebCore::SVGToOTFFontConverter::convertSVGToOTFFont): Ditto.
(WebCore::convertSVGToOTFFont): Move out of the result vector.
(WebCore::write32): Deleted.
(WebCore::write16): Deleted.
(WebCore::overwrite32): Deleted.
(WebCore::appendCFFValidString): Deleted.
(WebCore::transcodeGlyphPaths): Deleted.
(WebCore::calculateChecksum): Deleted.</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoresvgSVGToOTFFontConversioncpp">trunk/Source/WebCore/svg/SVGToOTFFontConversion.cpp</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (174278 => 174279)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2014-10-03 20:08:32 UTC (rev 174278)
+++ trunk/Source/WebCore/ChangeLog        2014-10-03 20:10:56 UTC (rev 174279)
</span><span class="lines">@@ -1,3 +1,72 @@
</span><ins>+2014-09-28 Myles C. Maxfield <mmaxfield@apple.com>
+
+ [SVG -> OTF Converter] Support non-BMP codepoints
+ https://bugs.webkit.org/show_bug.cgi?id=137097
+
+ Reviewed by Darin Adler.
+
+ This patch has two pieces:
+
+ 1) Moves write16(), overwrite32() and overwrite16() inside SVGToOTFFontConverter. This
+ is so that we don't have to keep passing around references to m_result everywhere. Instead,
+ put the output vector inside the class as an instance member variable. In addition, rename
+ write32() and write16() to append32() and append16(), and provide a copy of append32 inside
+ SVGToOTFFontConverter.
+
+ 2) Change the "Codepoint" typedef to be a String, and rename it to Codepoints. This is so that
+ we can implement ligatures later on. Update all the places that use this variable to work with
+ a String of multiple codepoints.
+
+ This patch updates the CMAP table to use format 12 instead of format 4. It currently only maps
+ single codepoints to glyph IDs and skips all multi-codepoint glyphs. We will implement
+ ligatures in another patch.
+
+ Test: svg/custom/glyph-selection-non-bmp.svg
+
+ * svg/SVGToOTFFontConversion.cpp:
+ (WebCore::append32): Append a result to a given vector. This is for the path transcoder.
+ (WebCore::SVGToOTFFontConverter::releaseResult): WTF::move()'s the result.
+ (WebCore::SVGToOTFFontConverter::GlyphData::GlyphData): Update to take Codepoints instead of Codepoint.
+ (WebCore::SVGToOTFFontConverter::append32): Piece 1 above.
+ (WebCore::SVGToOTFFontConverter::append16): Ditto.
+ (WebCore::SVGToOTFFontConverter::append4ByteCode): Convenience function.
+ (WebCore::SVGToOTFFontConverter::overwrite32): Piece 1 above.
+ (WebCore::SVGToOTFFontConverter::overwrite16): Ditto.
+ (WebCore::SVGToOTFFontConverter::appendCMAPTable): Update to format 12.
+ (WebCore::SVGToOTFFontConverter::appendHEADTable): Passing in a result vector is no longer necessary.
+ (WebCore::SVGToOTFFontConverter::appendHHEATable): Ditto.
+ (WebCore::SVGToOTFFontConverter::appendHMTXTable): Ditto.
+ (WebCore::SVGToOTFFontConverter::appendMAXPTable): Ditto.
+ (WebCore::SVGToOTFFontConverter::appendNAMETable): Ditto.
+ (WebCore::SVGToOTFFontConverter::appendOS2Table): Ditto.
+ (WebCore::SVGToOTFFontConverter::appendPOSTTable): Ditto.
+ (WebCore::isValidStringForCFF): Ditto.
+ (WebCore::SVGToOTFFontConverter::appendCFFValidString): Ditto.
+ (WebCore::SVGToOTFFontConverter::appendCFFTable): Ditto.
+ (WebCore::SVGToOTFFontConverter::appendVORGTable): Ditto.
+ (WebCore::SVGToOTFFontConverter::appendVHEATable): Ditto.
+ (WebCore::SVGToOTFFontConverter::appendVMTXTable): Ditto.
+ (WebCore::SVGToOTFFontConverter::addCodepointRanges): Update for Codepoints.
+ (WebCore::SVGToOTFFontConverter::addCodepoints): Ditto.
+ (WebCore::SVGToOTFFontConverter::addGlyphNames): Ditto.
+ (WebCore::SVGToOTFFontConverter::appendKERNSubtable): Ditto.
+ (WebCore::SVGToOTFFontConverter::appendKERNTable): Ditto.
+ (WebCore::writeCFFEncodedNumber): Passing in a result vector is no longer necessary.
+ (WebCore::SVGToOTFFontConverter::appendGlyphData): Update for Codepoints.
+ (WebCore::SVGToOTFFontConverter::processGlyphElement): Update for Codepoints.
+ (WebCore::SVGToOTFFontConverter::compareCodepointsLexicographically): Comparing Codepoints
+ (WebCore::SVGToOTFFontConverter::SVGToOTFFontConverter): Update for Codepoints.
+ (WebCore::SVGToOTFFontConverter::calculateChecksum): Passing in a result vector is no longer necessary.
+ (WebCore::SVGToOTFFontConverter::appendTable): Ditto.
+ (WebCore::SVGToOTFFontConverter::convertSVGToOTFFont): Ditto.
+ (WebCore::convertSVGToOTFFont): Move out of the result vector.
+ (WebCore::write32): Deleted.
+ (WebCore::write16): Deleted.
+ (WebCore::overwrite32): Deleted.
+ (WebCore::appendCFFValidString): Deleted.
+ (WebCore::transcodeGlyphPaths): Deleted.
+ (WebCore::calculateChecksum): Deleted.
+
</ins><span class="cx"> 2014-10-03 Commit Queue <commit-queue@webkit.org>
</span><span class="cx">
</span><span class="cx"> Unreviewed, rolling out r174270.
</span></span></pre></div>
<a id="trunkSourceWebCoresvgSVGToOTFFontConversioncpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/svg/SVGToOTFFontConversion.cpp (174278 => 174279)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/svg/SVGToOTFFontConversion.cpp        2014-10-03 20:08:32 UTC (rev 174278)
+++ trunk/Source/WebCore/svg/SVGToOTFFontConversion.cpp        2014-10-03 20:10:56 UTC (rev 174279)
</span><span class="lines">@@ -40,60 +40,41 @@
</span><span class="cx">
</span><span class="cx"> namespace WebCore {
</span><span class="cx">
</span><del>-static inline void write32(Vector<char>& vector, uint32_t value)
</del><ins>+static inline void append32(Vector<char>& result, uint32_t value)
</ins><span class="cx"> {
</span><del>- vector.append(value >> 24);
- vector.append(value >> 16);
- vector.append(value >> 8);
- vector.append(value);
</del><ins>+ result.append(value >> 24);
+ result.append(value >> 16);
+ result.append(value >> 8);
+ result.append(value);
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-static inline void write16(Vector<char>& vector, uint16_t value)
-{
- vector.append(value >> 8);
- vector.append(value);
-}
-
-static inline void overwrite32(Vector<char>& vector, unsigned location, uint32_t value)
-{
- ASSERT(vector.size() >= location + 4);
- vector[location] = value >> 24;
- vector[location + 1] = value >> 16;
- vector[location + 2] = value >> 8;
- vector[location + 3] = value;
-}
-
-static inline void overwrite16(Vector<char>& vector, unsigned location, uint16_t value)
-{
- ASSERT(vector.size() >= location + 2);
- vector[location] = value >> 8;
- vector[location + 1] = value;
-}
-
</del><span class="cx"> class SVGToOTFFontConverter {
</span><span class="cx"> public:
</span><span class="cx"> SVGToOTFFontConverter(const SVGFontElement&);
</span><del>- Vector<char> convertSVGToOTFFont();
</del><ins>+ void convertSVGToOTFFont();
</ins><span class="cx">
</span><ins>+ Vector<char> releaseResult()
+ {
+ return WTF::move(m_result);
+ }
+
</ins><span class="cx"> private:
</span><del>- typedef UChar Codepoint; // FIXME: Only support BMP for now
-
</del><span class="cx"> struct GlyphData {
</span><del>- GlyphData(Vector<char>&& charString, const SVGGlyphElement* glyphElement, float horizontalAdvance, float verticalAdvance, FloatRect boundingBox, Codepoint codepoint)
</del><ins>+ GlyphData(Vector<char>&& charString, const SVGGlyphElement* glyphElement, float horizontalAdvance, float verticalAdvance, FloatRect boundingBox, const String& codepoints)
</ins><span class="cx"> : boundingBox(boundingBox)
</span><span class="cx"> , charString(charString)
</span><ins>+ , codepoints(codepoints)
</ins><span class="cx"> , glyphElement(glyphElement)
</span><span class="cx"> , horizontalAdvance(horizontalAdvance)
</span><span class="cx"> , verticalAdvance(verticalAdvance)
</span><del>- , codepoint(codepoint)
</del><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> FloatRect boundingBox;
</span><span class="cx"> Vector<char> charString;
</span><ins>+ String codepoints;
</ins><span class="cx"> const SVGGlyphElement* glyphElement;
</span><span class="cx"> float horizontalAdvance;
</span><span class="cx"> float verticalAdvance;
</span><del>- Codepoint codepoint;
</del><span class="cx"> };
</span><span class="cx">
</span><span class="cx"> struct KerningData {
</span><span class="lines">@@ -108,39 +89,81 @@
</span><span class="cx"> int16_t adjustment;
</span><span class="cx"> };
</span><span class="cx">
</span><ins>+ void append32(uint32_t value)
+ {
+ WebCore::append32(m_result, value);
+ }
+
+ void append32BitCode(const char code[4])
+ {
+ m_result.append(code[0]);
+ m_result.append(code[1]);
+ m_result.append(code[2]);
+ m_result.append(code[3]);
+ }
+
+ void append16(uint16_t value)
+ {
+ m_result.append(value >> 8);
+ m_result.append(value);
+ }
+
+ void overwrite32(unsigned location, uint32_t value)
+ {
+ ASSERT(m_result.size() >= location + 4);
+ m_result[location] = value >> 24;
+ m_result[location + 1] = value >> 16;
+ m_result[location + 2] = value >> 8;
+ m_result[location + 3] = value;
+ }
+
+ void overwrite16(unsigned location, uint16_t value)
+ {
+ ASSERT(m_result.size() >= location + 2);
+ m_result[location] = value >> 8;
+ m_result[location + 1] = value;
+ }
+
</ins><span class="cx"> static const size_t headerSize = 12;
</span><span class="cx"> static const size_t directoryEntrySize = 16;
</span><span class="cx">
</span><del>- void processGlyphElement(const SVGElement& glyphOrMissingGlyphElement, const SVGGlyphElement*, float defaultHorizontalAdvance, float defaultVerticalAdvance, Codepoint, bool& initialGlyph);
</del><ins>+ uint32_t calculateChecksum(size_t startingOffset, size_t endingOffset) const;
</ins><span class="cx">
</span><del>- typedef void (SVGToOTFFontConverter::*FontAppendingFunction)(Vector<char> &) const;
- void appendTable(const char identifier[4], Vector<char>&, FontAppendingFunction);
- void appendCMAPTable(Vector<char>&) const;
- void appendHEADTable(Vector<char>&) const;
- void appendHHEATable(Vector<char>&) const;
- void appendHMTXTable(Vector<char>&) const;
- void appendVHEATable(Vector<char>&) const;
- void appendVMTXTable(Vector<char>&) const;
- void appendKERNTable(Vector<char>&) const;
- void appendMAXPTable(Vector<char>&) const;
- void appendNAMETable(Vector<char>&) const;
- void appendOS2Table(Vector<char>&) const;
- void appendPOSTTable(Vector<char>&) const;
- void appendCFFTable(Vector<char>&) const;
- void appendVORGTable(Vector<char>&) const;
</del><ins>+ void processGlyphElement(const SVGElement& glyphOrMissingGlyphElement, const SVGGlyphElement*, float defaultHorizontalAdvance, float defaultVerticalAdvance, const String& codepoints, bool& initialGlyph);
</ins><span class="cx">
</span><ins>+ typedef void (SVGToOTFFontConverter::*FontAppendingFunction)();
+ void appendTable(const char identifier[4], FontAppendingFunction);
+ void appendCMAPTable();
+ void appendHEADTable();
+ void appendHHEATable();
+ void appendHMTXTable();
+ void appendVHEATable();
+ void appendVMTXTable();
+ void appendKERNTable();
+ void appendMAXPTable();
+ void appendNAMETable();
+ void appendOS2Table();
+ void appendPOSTTable();
+ void appendCFFTable();
+ void appendVORGTable();
+
+ static bool compareCodepointsLexicographically(const GlyphData&, const GlyphData&);
+
+ void appendValidCFFString(const String&);
+
</ins><span class="cx"> Vector<char> transcodeGlyphPaths(float width, const SVGElement& glyphOrMissingGlyphElement, FloatRect& boundingBox) const;
</span><span class="cx">
</span><del>- void addCodepointRanges(const UnicodeRanges&, HashSet<uint16_t>& glyphSet) const;
- void addCodepoints(const HashSet<String>& codepoints, HashSet<uint16_t>& glyphSet) const;
- void addGlyphNames(const HashSet<String>& glyphNames, HashSet<uint16_t>& glyphSet) const;
</del><ins>+ void addCodepointRanges(const UnicodeRanges&, HashSet<Glyph>& glyphSet) const;
+ void addCodepoints(const HashSet<String>& codepoints, HashSet<Glyph>& glyphSet) const;
+ void addGlyphNames(const HashSet<String>& glyphNames, HashSet<Glyph>& glyphSet) const;
</ins><span class="cx"> void addKerningPair(Vector<KerningData>&, const SVGKerningPair&) const;
</span><del>- template<typename T> size_t appendKERNSubtable(Vector<char>& result, bool (T::*buildKerningPair)(SVGKerningPair&) const, uint16_t coverage) const;
- size_t finishAppendingKERNSubtable(Vector<char>& result, Vector<KerningData>, uint16_t coverage) const;
</del><ins>+ template<typename T> size_t appendKERNSubtable(bool (T::*buildKerningPair)(SVGKerningPair&) const, uint16_t coverage);
+ size_t finishAppendingKERNSubtable(Vector<KerningData>, uint16_t coverage);
</ins><span class="cx">
</span><span class="cx"> Vector<GlyphData> m_glyphs;
</span><span class="cx"> HashMap<String, Glyph> m_glyphNameToIndexMap; // SVG 1.1: "It is recommended that glyph names be unique within a font."
</span><del>- HashMap<UChar32, Glyph> m_codepointToIndexMap; // FIXME: There might be many glyphs that map to a single codepoint.
</del><ins>+ HashMap<String, Vector<Glyph, 1>> m_codepointsToIndicesMap;
+ Vector<char> m_result;
</ins><span class="cx"> FloatRect m_boundingBox;
</span><span class="cx"> const SVGFontElement& m_fontElement;
</span><span class="cx"> const SVGFontFaceElement* m_fontFaceElement;
</span><span class="lines">@@ -172,68 +195,73 @@
</span><span class="cx"> return result;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-void SVGToOTFFontConverter::appendCMAPTable(Vector<char>& result) const
</del><ins>+void SVGToOTFFontConverter::appendCMAPTable()
</ins><span class="cx"> {
</span><del>- auto startingOffset = result.size();
- write16(result, 0);
- write16(result, 1); // Number subtables
</del><ins>+ auto startingOffset = m_result.size();
+ append16(0);
+ append16(1); // Number subtables
</ins><span class="cx">
</span><del>- write16(result, 0); // Unicode
- write16(result, 3); // Unicode version 2.2+
- write32(result, result.size() - startingOffset + sizeof(uint32_t)); // Byte offset of subtable
</del><ins>+ append16(0); // Unicode
+ append16(3); // Unicode version 2.2+
+ append32(m_result.size() - startingOffset + sizeof(uint32_t)); // Byte offset of subtable
</ins><span class="cx">
</span><span class="cx"> // Braindead scheme: One segment for each character
</span><span class="cx"> ASSERT(m_glyphs.size() < 0xFFFF);
</span><del>- uint16_t segCount = m_glyphs.size() + 1;
- write16(result, 4); // Format: Only support the Basic Multilingual Plane for now
- write16(result, 22 + m_glyphs.size() * 2); // length
- write16(result, 0); // Language independent
- write16(result, 2 * segCount); // segCountX2: "2 x segCount"
- uint16_t originalSearchRange = roundDownToPowerOfTwo(segCount);
- uint16_t searchRange = 2 * originalSearchRange; // searchRange: "2 x (2**floor(log2(segCount)))"
- write16(result, searchRange);
- write16(result, integralLog2(originalSearchRange)); // entrySelector: "log2(searchRange/2)"
- write16(result, (2 * segCount) - searchRange); // rangeShift: "2 x segCount - searchRange"
</del><ins>+ auto subtableLocation = m_result.size();
+ append32(12 << 16); // Format 12
+ append32(0); // Placeholder for byte length
+ append32(0); // Language independent
+ append32(0); // Placeholder for nGroups
</ins><span class="cx">
</span><del>- for (auto& glyph : m_glyphs)
- write16(result, glyph.codepoint); // EndCode
- write16(result, 0xFFFF); // "To ensure that the search will terminate, the final endCode value must be 0xFFFF."
- write16(result, 0); // Reserved
- for (auto& glyph : m_glyphs)
- write16(result, glyph.codepoint); // startCode
- write16(result, 0xFFFF);
- for (Glyph i = 0; i < m_glyphs.size(); ++i) {
- // Note that this value can be "negative," but that is okay because wrapping is defined and expected here
- write16(result, i - m_glyphs[i].codepoint); // idDelta
</del><ins>+ uint16_t nGroups = 0;
+ UChar32 previousCodepoint = std::numeric_limits<UChar32>::max();
+ for (size_t i = 0; i < m_glyphs.size(); ++i) {
+ auto& glyph = m_glyphs[i];
+ unsigned codepointSize = 0;
+ UChar32 codepoint;
+ if (glyph.codepoints.isNull())
+ codepoint = 0;
+ else if (glyph.codepoints.is8Bit())
+ codepoint = glyph.codepoints[codepointSize++];
+ else
+ U16_NEXT(glyph.codepoints.characters16(), codepointSize, glyph.codepoints.length(), codepoint);
+
+ // Don't map ligatures here.
+ if (glyph.codepoints.length() > codepointSize || codepoint == previousCodepoint)
+ continue;
+
+ append32(codepoint); // startCharCode
+ append32(codepoint); // endCharCode
+ append32(i); // startGlyphCode
+ ++nGroups;
+ previousCodepoint = codepoint;
</ins><span class="cx"> }
</span><del>- write16(result, 1);
- for (unsigned i = 0; i < m_glyphs.size(); ++i)
- write16(result, 0); // idRangeOffset
- write16(result, 0);
</del><ins>+ overwrite32(subtableLocation + 4, m_result.size() - subtableLocation);
+ overwrite32(subtableLocation + 12, nGroups);
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-void SVGToOTFFontConverter::appendHEADTable(Vector<char>& result) const
</del><ins>+void SVGToOTFFontConverter::appendHEADTable()
</ins><span class="cx"> {
</span><del>- write32(result, 0x00010000); // Version
- write32(result, 0x00010000); // Revision
- write32(result, 0); // Checksum placeholder; to be overwritten by the caller.
- write32(result, 0x5F0F3CF5); // Magic number.
- write16(result, (1 << 9) | 1);
</del><ins>+ append32(0x00010000); // Version
+ append32(0x00010000); // Revision
+ append32(0); // Checksum placeholder; to be overwritten by the caller.
+ append32(0x5F0F3CF5); // Magic number.
+ append16((1 << 9) | 1);
</ins><span class="cx">
</span><del>- write16(result, m_unitsPerEm);
- write32(result, 0); // First half of creation date
- write32(result, 0); // Last half of creation date
- write32(result, 0); // First half of modification date
- write32(result, 0); // Last half of modification date
- write16(result, m_boundingBox.x()); // Minimum X
- write16(result, m_boundingBox.y()); // Minimum Y
- write16(result, m_boundingBox.maxX()); // Maximum X
- write16(result, m_boundingBox.maxY()); // Maximum Y
- write16(result, (m_italic ? 1 << 1 : 0) | (m_weight >= 7 ? 1 : 0));
- write16(result, 3); // Smallest readable size in pixels
- write16(result, 0); // Might contain LTR or RTL glyphs
- write16(result, 0); // Short offsets in the 'loca' table. However, OTF fonts don't have a 'loca' table so this is irrelevant
- write16(result, 0); // Glyph data format
</del><ins>+ append16(m_unitsPerEm);
+ append32(0); // First half of creation date
+ append32(0); // Last half of creation date
+ append32(0); // First half of modification date
+ append32(0); // Last half of modification date
+ append16(m_boundingBox.x()); // Minimum X
+ append16(m_boundingBox.y()); // Minimum Y
+ append16(m_boundingBox.maxX()); // Maximum X
+ append16(m_boundingBox.maxY()); // Maximum Y
+ append16((m_italic ? 1 << 1 : 0) | (m_weight >= 7 ? 1 : 0));
+ append16(3); // Smallest readable size in pixels
+ append16(0); // Might contain LTR or RTL glyphs
+ append16(0); // Short offsets in the 'loca' table. However, OTF fonts don't have a 'loca' table so this is irrelevant
+ append16(0); // Glyph data format
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> // Assumption: T2 can hold every value that a T1 can hold.
</span><span class="lines">@@ -244,13 +272,13 @@
</span><span class="cx"> return static_cast<T1>(x);
</span><span class="cx"> }
</span><span class="cx">
</span><del>-void SVGToOTFFontConverter::appendHHEATable(Vector<char>& result) const
</del><ins>+void SVGToOTFFontConverter::appendHHEATable()
</ins><span class="cx"> {
</span><span class="cx"> int16_t ascent;
</span><span class="cx"> int16_t descent;
</span><span class="cx"> if (!m_fontFaceElement) {
</span><del>- ascent = std::numeric_limits<int16_t>::max();
- descent = std::numeric_limits<int16_t>::max();
</del><ins>+ ascent = m_unitsPerEm;
+ descent = 1;
</ins><span class="cx"> } else {
</span><span class="cx"> ascent = m_fontFaceElement->ascent();
</span><span class="cx"> descent = m_fontFaceElement->descent();
</span><span class="lines">@@ -264,70 +292,70 @@
</span><span class="cx"> descent = 1;
</span><span class="cx"> }
</span><span class="cx">
</span><del>- write32(result, 0x00010000); // Version
- write16(result, ascent);
- write16(result, descent);
</del><ins>+ append32(0x00010000); // Version
+ append16(ascent);
+ append16(descent);
</ins><span class="cx"> // WebKit SVG font rendering has hard coded the line gap to be 1/10th of the font size since 2008 (see r29719).
</span><del>- write16(result, m_unitsPerEm / 10); // Line gap
- write16(result, clampTo<uint16_t>(m_advanceWidthMax));
- write16(result, clampTo<int16_t>(m_boundingBox.x())); // Minimum left side bearing
- write16(result, clampTo<int16_t>(m_minRightSideBearing)); // Minimum right side bearing
- write16(result, clampTo<int16_t>(m_boundingBox.maxX())); // X maximum extent
</del><ins>+ append16(m_unitsPerEm / 10); // Line gap
+ append16(clampTo<uint16_t>(m_advanceWidthMax));
+ append16(clampTo<int16_t>(m_boundingBox.x())); // Minimum left side bearing
+ append16(clampTo<int16_t>(m_minRightSideBearing)); // Minimum right side bearing
+ append16(clampTo<int16_t>(m_boundingBox.maxX())); // X maximum extent
</ins><span class="cx"> // Since WebKit draws the caret and ignores the following values, it doesn't matter what we set them to.
</span><del>- write16(result, 1); // Vertical caret
- write16(result, 0); // Vertical caret
- write16(result, 0); // "Set value to 0 for non-slanted fonts"
- write32(result, 0); // Reserved
- write32(result, 0); // Reserved
- write16(result, 0); // Current format
- write16(result, m_glyphs.size()); // Number of advance widths in HMTX table
</del><ins>+ append16(1); // Vertical caret
+ append16(0); // Vertical caret
+ append16(0); // "Set value to 0 for non-slanted fonts"
+ append32(0); // Reserved
+ append32(0); // Reserved
+ append16(0); // Current format
+ append16(m_glyphs.size()); // Number of advance widths in HMTX table
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-void SVGToOTFFontConverter::appendHMTXTable(Vector<char>& result) const
</del><ins>+void SVGToOTFFontConverter::appendHMTXTable()
</ins><span class="cx"> {
</span><span class="cx"> for (auto& glyph : m_glyphs) {
</span><del>- write16(result, clampTo<uint16_t>(glyph.horizontalAdvance));
- write16(result, clampTo<int16_t>(glyph.boundingBox.x()));
</del><ins>+ append16(clampTo<uint16_t>(glyph.horizontalAdvance));
+ append16(clampTo<int16_t>(glyph.boundingBox.x()));
</ins><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx">
</span><del>-void SVGToOTFFontConverter::appendMAXPTable(Vector<char>& result) const
</del><ins>+void SVGToOTFFontConverter::appendMAXPTable()
</ins><span class="cx"> {
</span><del>- write32(result, 0x00010000); // Version
- write16(result, m_glyphs.size());
- write16(result, 0xFFFF); // Maximum number of points in non-compound glyph
- write16(result, 0xFFFF); // Maximum number of contours in non-compound glyph
- write16(result, 0xFFFF); // Maximum number of points in compound glyph
- write16(result, 0xFFFF); // Maximum number of contours in compound glyph
- write16(result, 2); // Maximum number of zones
- write16(result, 0); // Maximum number of points used in zone 0
- write16(result, 0); // Maximum number of storage area locations
- write16(result, 0); // Maximum number of function definitions
- write16(result, 0); // Maximum number of instruction definitions
- write16(result, 0); // Maximum stack depth
- write16(result, 0); // Maximum size of instructions
- write16(result, m_glyphs.size()); // Maximum number of glyphs referenced at top level
- write16(result, 0); // No compound glyphs
</del><ins>+ append32(0x00010000); // Version
+ append16(m_glyphs.size());
+ append16(0xFFFF); // Maximum number of points in non-compound glyph
+ append16(0xFFFF); // Maximum number of contours in non-compound glyph
+ append16(0xFFFF); // Maximum number of points in compound glyph
+ append16(0xFFFF); // Maximum number of contours in compound glyph
+ append16(2); // Maximum number of zones
+ append16(0); // Maximum number of points used in zone 0
+ append16(0); // Maximum number of storage area locations
+ append16(0); // Maximum number of function definitions
+ append16(0); // Maximum number of instruction definitions
+ append16(0); // Maximum stack depth
+ append16(0); // Maximum size of instructions
+ append16(m_glyphs.size()); // Maximum number of glyphs referenced at top level
+ append16(0); // No compound glyphs
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-void SVGToOTFFontConverter::appendNAMETable(Vector<char>& result) const
</del><ins>+void SVGToOTFFontConverter::appendNAMETable()
</ins><span class="cx"> {
</span><del>- write16(result, 0); // Format selector
- write16(result, 1); // Number of name records in table
- write16(result, 18); // Offset in bytes to the beginning of name character strings
</del><ins>+ append16(0); // Format selector
+ append16(1); // Number of name records in table
+ append16(18); // Offset in bytes to the beginning of name character strings
</ins><span class="cx">
</span><del>- write16(result, 0); // Unicode
- write16(result, 3); // Unicode version 2.0 or later
- write16(result, 0); // Language
- write16(result, 1); // Name identifier. 1 = Font family
- write16(result, m_fontFamily.length());
- write16(result, 0); // Offset into name data
</del><ins>+ append16(0); // Unicode
+ append16(3); // Unicode version 2.0 or later
+ append16(0); // Language
+ append16(1); // Name identifier. 1 = Font family
+ append16(m_fontFamily.length());
+ append16(0); // Offset into name data
</ins><span class="cx">
</span><del>- for (unsigned i = 0; i < m_fontFamily.length(); ++i)
- write16(result, m_fontFamily[i]);
</del><ins>+ for (auto codeUnit : StringView(m_fontFamily).codeUnits())
+ append16(codeUnit);
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-void SVGToOTFFontConverter::appendOS2Table(Vector<char>& result) const
</del><ins>+void SVGToOTFFontConverter::appendOS2Table()
</ins><span class="cx"> {
</span><span class="cx"> int16_t averageAdvance = m_unitsPerEm;
</span><span class="cx"> bool ok;
</span><span class="lines">@@ -337,23 +365,23 @@
</span><span class="cx"> if (ok)
</span><span class="cx"> averageAdvance = clampTo<int16_t>(value);
</span><span class="cx">
</span><del>- write16(result, 0); // Version
- write16(result, averageAdvance);
- write16(result, m_weight); // Weight class
- write16(result, 5); // Width class
- write16(result, 0); // Protected font
</del><ins>+ append16(0); // Version
+ append16(averageAdvance);
+ append16(m_weight); // Weight class
+ append16(5); // Width class
+ append16(0); // Protected font
</ins><span class="cx"> // WebKit handles these superscripts and subscripts
</span><del>- write16(result, 0); // Subscript X Size
- write16(result, 0); // Subscript Y Size
- write16(result, 0); // Subscript X Offset
- write16(result, 0); // Subscript Y Offset
- write16(result, 0); // Superscript X Size
- write16(result, 0); // Superscript Y Size
- write16(result, 0); // Superscript X Offset
- write16(result, 0); // Superscript Y Offset
- write16(result, 0); // Strikeout width
- write16(result, 0); // Strikeout Position
- write16(result, 0); // No classification
</del><ins>+ append16(0); // Subscript X Size
+ append16(0); // Subscript Y Size
+ append16(0); // Subscript X Offset
+ append16(0); // Subscript Y Offset
+ append16(0); // Superscript X Size
+ append16(0); // Superscript Y Size
+ append16(0); // Superscript X Offset
+ append16(0); // Superscript Y Offset
+ append16(0); // Strikeout width
+ append16(0); // Strikeout Position
+ append16(0); // No classification
</ins><span class="cx">
</span><span class="cx"> unsigned numPanoseBytes = 0;
</span><span class="cx"> const unsigned panoseSize = 10;
</span><span class="lines">@@ -372,54 +400,54 @@
</span><span class="cx"> }
</span><span class="cx"> if (numPanoseBytes != panoseSize)
</span><span class="cx"> memset(panoseBytes, 0, panoseSize);
</span><del>- result.append(panoseBytes, panoseSize);
</del><ins>+ m_result.append(panoseBytes, panoseSize);
</ins><span class="cx">
</span><span class="cx"> for (int i = 0; i < 4; ++i)
</span><del>- write32(result, 0); // "Bit assignments are pending. Set to 0"
- write32(result, 0x544B4257); // Font Vendor. "WBKT"
- write16(result, (m_weight >= 7 ? 1 << 5 : 0) | (m_italic ? 1 : 0)); // Font Patterns.
- write16(result, m_glyphs.first().codepoint); // First unicode index
- write16(result, m_glyphs.last().codepoint); // Last unicode index
</del><ins>+ append32(0); // "Bit assignments are pending. Set to 0"
+ append32(0x544B4257); // Font Vendor. "WBKT"
+ append16((m_weight >= 7 ? 1 << 5 : 0) | (m_italic ? 1 : 0)); // Font Patterns.
+ append16(0); // First unicode index
+ append16(0xFFFF); // Last unicode index
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-void SVGToOTFFontConverter::appendPOSTTable(Vector<char>& result) const
</del><ins>+void SVGToOTFFontConverter::appendPOSTTable()
</ins><span class="cx"> {
</span><del>- write32(result, 0x00030000); // Format. Printing is undefined
- write32(result, 0); // Italic angle in degrees
- write16(result, 0); // Underline position
- write16(result, 0); // Underline thickness
- write32(result, 0); // Monospaced
- write32(result, 0); // "Minimum memory usage when a TrueType font is downloaded as a Type 42 font"
- write32(result, 0); // "Maximum memory usage when a TrueType font is downloaded as a Type 42 font"
- write32(result, 0); // "Minimum memory usage when a TrueType font is downloaded as a Type 1 font"
- write32(result, 0); // "Maximum memory usage when a TrueType font is downloaded as a Type 1 font"
</del><ins>+ append32(0x00030000); // Format. Printing is undefined
+ append32(0); // Italic angle in degrees
+ append16(0); // Underline position
+ append16(0); // Underline thickness
+ append32(0); // Monospaced
+ append32(0); // "Minimum memory usage when a TrueType font is downloaded as a Type 42 font"
+ append32(0); // "Maximum memory usage when a TrueType font is downloaded as a Type 42 font"
+ append32(0); // "Minimum memory usage when a TrueType font is downloaded as a Type 1 font"
+ append32(0); // "Maximum memory usage when a TrueType font is downloaded as a Type 1 font"
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> static bool isValidStringForCFF(const String& string)
</span><span class="cx"> {
</span><del>- for (unsigned i = 0; i < string.length(); ++i) {
- if (string[i] < 33 || string[i] > 126)
</del><ins>+ for (auto c : StringView(string).codeUnits()) {
+ if (c < 33 || c > 126)
</ins><span class="cx"> return false;
</span><span class="cx"> }
</span><span class="cx"> return true;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-static void appendValidCFFString(Vector<char>& output, const String& string)
</del><ins>+void SVGToOTFFontConverter::appendValidCFFString(const String& string)
</ins><span class="cx"> {
</span><span class="cx"> ASSERT(isValidStringForCFF(string));
</span><del>- for (unsigned i = 0; i < string.length(); ++i)
- output.append(string[i]);
</del><ins>+ for (auto c : StringView(string).codeUnits())
+ m_result.append(c);
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-void SVGToOTFFontConverter::appendCFFTable(Vector<char>& result) const
</del><ins>+void SVGToOTFFontConverter::appendCFFTable()
</ins><span class="cx"> {
</span><del>- auto startingOffset = result.size();
</del><ins>+ auto startingOffset = m_result.size();
</ins><span class="cx">
</span><span class="cx"> // Header
</span><del>- result.append(1); // Major version
- result.append(0); // Minor version
- result.append(4); // Header size
- result.append(4); // Offsets within CFF table are 4 bytes long
</del><ins>+ m_result.append(1); // Major version
+ m_result.append(0); // Minor version
+ m_result.append(4); // Header size
+ m_result.append(4); // Offsets within CFF table are 4 bytes long
</ins><span class="cx">
</span><span class="cx"> // Name INDEX
</span><span class="cx"> String fontName;
</span><span class="lines">@@ -429,11 +457,11 @@
</span><span class="cx"> if (isValidStringForCFF(potentialFontName))
</span><span class="cx"> fontName = potentialFontName;
</span><span class="cx"> }
</span><del>- write16(result, 1); // INDEX contains 1 element
- result.append(4); // Offsets in this INDEX are 4 bytes long
- write32(result, 1); // 1-index offset of name data
- write32(result, fontName.length() + 1); // 1-index offset just past end of name data
- appendValidCFFString(result, fontName);
</del><ins>+ append16(1); // INDEX contains 1 element
+ m_result.append(4); // Offsets in this INDEX are 4 bytes long
+ append32(1); // 1-index offset of name data
+ append32(fontName.length() + 1); // 1-index offset just past end of name data
+ appendValidCFFString(fontName);
</ins><span class="cx">
</span><span class="cx"> String weight;
</span><span class="cx"> if (m_fontFaceElement) {
</span><span class="lines">@@ -455,131 +483,131 @@
</span><span class="cx"> const unsigned sizeOfTopIndex = 45 + (hasWeight ? 6 : 0);
</span><span class="cx">
</span><span class="cx"> // Top DICT INDEX.
</span><del>- write16(result, 1); // INDEX contains 1 element
- result.append(4); // Offsets in this INDEX are 4 bytes long
- write32(result, 1); // 1-index offset of DICT data
- write32(result, 1 + sizeOfTopIndex); // 1-index offset just past end of DICT data
</del><ins>+ append16(1); // INDEX contains 1 element
+ m_result.append(4); // Offsets in this INDEX are 4 bytes long
+ append32(1); // 1-index offset of DICT data
+ append32(1 + sizeOfTopIndex); // 1-index offset just past end of DICT data
</ins><span class="cx">
</span><span class="cx"> // DICT information
</span><span class="cx"> #if !ASSERT_DISABLED
</span><del>- unsigned topDictStart = result.size();
</del><ins>+ unsigned topDictStart = m_result.size();
</ins><span class="cx"> #endif
</span><del>- result.append(operand32Bit);
- write32(result, userDefinedStringStartIndex);
- result.append(fullNameKey);
- result.append(operand32Bit);
- write32(result, userDefinedStringStartIndex);
- result.append(familyNameKey);
</del><ins>+ m_result.append(operand32Bit);
+ append32(userDefinedStringStartIndex);
+ m_result.append(fullNameKey);
+ m_result.append(operand32Bit);
+ append32(userDefinedStringStartIndex);
+ m_result.append(familyNameKey);
</ins><span class="cx"> if (hasWeight) {
</span><del>- result.append(operand32Bit);
- write32(result, userDefinedStringStartIndex + 1);
- result.append(weightKey);
</del><ins>+ m_result.append(operand32Bit);
+ append32(userDefinedStringStartIndex + 1);
+ m_result.append(weightKey);
</ins><span class="cx"> }
</span><del>- result.append(operand32Bit);
- write32(result, clampTo<int32_t>(m_boundingBox.x()));
- result.append(operand32Bit);
- write32(result, clampTo<int32_t>(m_boundingBox.maxX()));
- result.append(operand32Bit);
- write32(result, clampTo<int32_t>(m_boundingBox.y()));
- result.append(operand32Bit);
- write32(result, clampTo<int32_t>(m_boundingBox.maxY()));
- result.append(fontBBoxKey);
- result.append(operand32Bit);
- unsigned charsetOffsetLocation = result.size();
- write32(result, 0); // Offset of Charset info. Will be overwritten later.
- result.append(charsetIndexKey);
- result.append(operand32Bit);
- unsigned charstringsOffsetLocation = result.size();
- write32(result, 0); // Offset of CharStrings INDEX. Will be overwritten later.
- result.append(charstringsIndexKey);
- ASSERT(result.size() == topDictStart + sizeOfTopIndex);
</del><ins>+ m_result.append(operand32Bit);
+ append32(clampTo<int32_t>(m_boundingBox.x()));
+ m_result.append(operand32Bit);
+ append32(clampTo<int32_t>(m_boundingBox.maxX()));
+ m_result.append(operand32Bit);
+ append32(clampTo<int32_t>(m_boundingBox.y()));
+ m_result.append(operand32Bit);
+ append32(clampTo<int32_t>(m_boundingBox.maxY()));
+ m_result.append(fontBBoxKey);
+ m_result.append(operand32Bit);
+ unsigned charsetOffsetLocation = m_result.size();
+ append32(0); // Offset of Charset info. Will be overwritten later.
+ m_result.append(charsetIndexKey);
+ m_result.append(operand32Bit);
+ unsigned charstringsOffsetLocation = m_result.size();
+ append32(0); // Offset of CharStrings INDEX. Will be overwritten later.
+ m_result.append(charstringsIndexKey);
+ ASSERT(m_result.size() == topDictStart + sizeOfTopIndex);
</ins><span class="cx">
</span><span class="cx"> // String INDEX
</span><del>- write16(result, 1 + (hasWeight ? 1 : 0)); // Number of elements in INDEX
- result.append(4); // Offsets in this INDEX are 4 bytes long
</del><ins>+ append16(1 + (hasWeight ? 1 : 0)); // Number of elements in INDEX
+ m_result.append(4); // Offsets in this INDEX are 4 bytes long
</ins><span class="cx"> uint32_t offset = 1;
</span><del>- write32(result, offset);
</del><ins>+ append32(offset);
</ins><span class="cx"> offset += fontName.length();
</span><del>- write32(result, offset);
</del><ins>+ append32(offset);
</ins><span class="cx"> if (hasWeight) {
</span><span class="cx"> offset += weight.length();
</span><del>- write32(result, offset);
</del><ins>+ append32(offset);
</ins><span class="cx"> }
</span><del>- appendValidCFFString(result, fontName);
- appendValidCFFString(result, weight);
</del><ins>+ appendValidCFFString(fontName);
+ appendValidCFFString(weight);
</ins><span class="cx">
</span><del>- write16(result, 0); // Empty subroutine INDEX
</del><ins>+ append16(0); // Empty subroutine INDEX
</ins><span class="cx">
</span><span class="cx"> // Charset info
</span><del>- overwrite32(result, charsetOffsetLocation, result.size() - startingOffset);
- result.append(0);
</del><ins>+ overwrite32(charsetOffsetLocation, m_result.size() - startingOffset);
+ m_result.append(0);
</ins><span class="cx"> for (Glyph i = 1; i < m_glyphs.size(); ++i)
</span><del>- write16(result, i);
</del><ins>+ append16(i);
</ins><span class="cx">
</span><span class="cx"> // CharStrings INDEX
</span><del>- overwrite32(result, charstringsOffsetLocation, result.size() - startingOffset);
- write16(result, m_glyphs.size());
- result.append(4); // Offsets in this INDEX are 4 bytes long
</del><ins>+ overwrite32(charstringsOffsetLocation, m_result.size() - startingOffset);
+ append16(m_glyphs.size());
+ m_result.append(4); // Offsets in this INDEX are 4 bytes long
</ins><span class="cx"> offset = 1;
</span><del>- write32(result, offset);
</del><ins>+ append32(offset);
</ins><span class="cx"> for (auto& glyph : m_glyphs) {
</span><span class="cx"> offset += glyph.charString.size();
</span><del>- write32(result, offset);
</del><ins>+ append32(offset);
</ins><span class="cx"> }
</span><span class="cx"> for (auto& glyph : m_glyphs)
</span><del>- result.appendVector(glyph.charString);
</del><ins>+ m_result.appendVector(glyph.charString);
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-void SVGToOTFFontConverter::appendVORGTable(Vector<char>& result) const
</del><ins>+void SVGToOTFFontConverter::appendVORGTable()
</ins><span class="cx"> {
</span><del>- write16(result, 1); // Major version
- write16(result, 0); // Minor version
</del><ins>+ append16(1); // Major version
+ append16(0); // Minor version
</ins><span class="cx">
</span><span class="cx"> bool ok;
</span><span class="cx"> int16_t defaultVerticalOriginY = clampTo<int16_t>(m_fontElement.fastGetAttribute(SVGNames::vert_origin_yAttr).toInt(&ok));
</span><span class="cx"> if (!ok && m_missingGlyphElement)
</span><span class="cx"> defaultVerticalOriginY = clampTo<int16_t>(m_missingGlyphElement->fastGetAttribute(SVGNames::vert_origin_yAttr).toInt());
</span><del>- write16(result, defaultVerticalOriginY);
</del><ins>+ append16(defaultVerticalOriginY);
</ins><span class="cx">
</span><del>- auto tableSizeOffset = result.size();
- write16(result, 0); // Place to write table size.
</del><ins>+ auto tableSizeOffset = m_result.size();
+ append16(0); // Place to write table size.
</ins><span class="cx"> for (Glyph i = 0; i < m_glyphs.size(); ++i) {
</span><span class="cx"> if (auto* glyph = m_glyphs[i].glyphElement) {
</span><span class="cx"> if (int16_t verticalOriginY = clampTo<int16_t>(glyph->fastGetAttribute(SVGNames::vert_origin_yAttr).toInt())) {
</span><del>- write16(result, i);
- write16(result, verticalOriginY);
</del><ins>+ append16(i);
+ append16(verticalOriginY);
</ins><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx"> }
</span><del>- ASSERT(!((result.size() - tableSizeOffset - 2) % 4));
- overwrite16(result, tableSizeOffset, (result.size() - tableSizeOffset - 2) / 4);
</del><ins>+ ASSERT(!((m_result.size() - tableSizeOffset - 2) % 4));
+ overwrite16(tableSizeOffset, (m_result.size() - tableSizeOffset - 2) / 4);
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-void SVGToOTFFontConverter::appendVHEATable(Vector<char>& result) const
</del><ins>+void SVGToOTFFontConverter::appendVHEATable()
</ins><span class="cx"> {
</span><del>- write32(result, 0x00011000); // Version
- write16(result, m_unitsPerEm / 2); // Vertical typographic ascender (vertical baseline to the right)
- write16(result, clampTo<int16_t>(-static_cast<int>(m_unitsPerEm / 2))); // Vertical typographic descender
- write16(result, m_unitsPerEm / 10); // Vertical typographic line gap
- write16(result, clampTo<int16_t>(m_advanceHeightMax));
- write16(result, clampTo<int16_t>(m_unitsPerEm - m_boundingBox.maxY())); // Minimum top side bearing
- write16(result, clampTo<int16_t>(m_boundingBox.y())); // Minimum bottom side bearing
- write16(result, clampTo<int16_t>(m_unitsPerEm - m_boundingBox.y())); // Y maximum extent
</del><ins>+ append32(0x00011000); // Version
+ append16(m_unitsPerEm / 2); // Vertical typographic ascender (vertical baseline to the right)
+ append16(clampTo<int16_t>(-static_cast<int>(m_unitsPerEm / 2))); // Vertical typographic descender
+ append16(m_unitsPerEm / 10); // Vertical typographic line gap
+ append16(clampTo<int16_t>(m_advanceHeightMax));
+ append16(clampTo<int16_t>(m_unitsPerEm - m_boundingBox.maxY())); // Minimum top side bearing
+ append16(clampTo<int16_t>(m_boundingBox.y())); // Minimum bottom side bearing
+ append16(clampTo<int16_t>(m_unitsPerEm - m_boundingBox.y())); // Y maximum extent
</ins><span class="cx"> // Since WebKit draws the caret and ignores the following values, it doesn't matter what we set them to.
</span><del>- write16(result, 1); // Vertical caret
- write16(result, 0); // Vertical caret
- write16(result, 0); // "Set value to 0 for non-slanted fonts"
- write32(result, 0); // Reserved
- write32(result, 0); // Reserved
- write16(result, 0); // "Set to 0"
- write16(result, m_glyphs.size()); // Number of advance heights in VMTX table
</del><ins>+ append16(1); // Vertical caret
+ append16(0); // Vertical caret
+ append16(0); // "Set value to 0 for non-slanted fonts"
+ append32(0); // Reserved
+ append32(0); // Reserved
+ append16(0); // "Set to 0"
+ append16(m_glyphs.size()); // Number of advance heights in VMTX table
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-void SVGToOTFFontConverter::appendVMTXTable(Vector<char>& result) const
</del><ins>+void SVGToOTFFontConverter::appendVMTXTable()
</ins><span class="cx"> {
</span><span class="cx"> for (auto& glyph : m_glyphs) {
</span><del>- write16(result, clampTo<uint16_t>(glyph.verticalAdvance));
- write16(result, clampTo<int16_t>(m_unitsPerEm - glyph.boundingBox.maxY())); // top side bearing
</del><ins>+ append16(clampTo<uint16_t>(glyph.verticalAdvance));
+ append16(clampTo<int16_t>(m_unitsPerEm - glyph.boundingBox.maxY())); // top side bearing
</ins><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -587,10 +615,14 @@
</span><span class="cx"> {
</span><span class="cx"> for (auto& unicodeRange : unicodeRanges) {
</span><span class="cx"> for (auto codepoint = unicodeRange.first; codepoint <= unicodeRange.second; ++codepoint) {
</span><del>- if (!m_codepointToIndexMap.isValidKey(codepoint))
- continue;
- if (Glyph glyph = m_codepointToIndexMap.get(codepoint))
- glyphSet.add(glyph);
</del><ins>+ UChar buffer[2];
+ uint8_t length = 0;
+ UBool error = false;
+ U16_APPEND(buffer, length, 2, codepoint, error);
+ if (!error) {
+ for (auto index : m_codepointsToIndicesMap.get(String(buffer, length)))
+ glyphSet.add(index);
+ }
</ins><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx"> }
</span><span class="lines">@@ -598,24 +630,12 @@
</span><span class="cx"> void SVGToOTFFontConverter::addCodepoints(const HashSet<String>& codepoints, HashSet<Glyph>& glyphSet) const
</span><span class="cx"> {
</span><span class="cx"> for (auto& codepointString : codepoints) {
</span><del>- auto codepointStringLength = codepointString.length();
- unsigned i = 0;
- while (i < codepointStringLength) {
- // FIXME: Canonicalization might be necessary
- UChar32 codepoint;
- if (codepointString.is8Bit())
- codepoint = codepointString.characters8()[i++];
- else
- U16_NEXT(codepointString.characters16(), i, codepointStringLength, codepoint);
- if (!m_codepointToIndexMap.isValidKey(codepoint))
- continue;
- if (Glyph glyph = m_codepointToIndexMap.get(codepoint))
- glyphSet.add(glyph);
- }
</del><ins>+ for (auto index : m_codepointsToIndicesMap.get(codepointString))
+ glyphSet.add(index);
</ins><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx">
</span><del>-void SVGToOTFFontConverter::addGlyphNames(const HashSet<String>& glyphNames, HashSet<uint16_t>& glyphSet) const
</del><ins>+void SVGToOTFFontConverter::addGlyphNames(const HashSet<String>& glyphNames, HashSet<Glyph>& glyphSet) const
</ins><span class="cx"> {
</span><span class="cx"> for (auto& glyphName : glyphNames) {
</span><span class="cx"> if (Glyph glyph = m_glyphNameToIndexMap.get(glyphName))
</span><span class="lines">@@ -642,7 +662,7 @@
</span><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx">
</span><del>-template<typename T> inline size_t SVGToOTFFontConverter::appendKERNSubtable(Vector<char>& result, bool (T::*buildKerningPair)(SVGKerningPair&) const, uint16_t coverage) const
</del><ins>+template<typename T> inline size_t SVGToOTFFontConverter::appendKERNSubtable(bool (T::*buildKerningPair)(SVGKerningPair&) const, uint16_t coverage)
</ins><span class="cx"> {
</span><span class="cx"> Vector<KerningData> kerningData;
</span><span class="cx"> for (auto& element : childrenOfType<T>(m_fontElement)) {
</span><span class="lines">@@ -650,10 +670,10 @@
</span><span class="cx"> if ((element.*buildKerningPair)(kerningPair))
</span><span class="cx"> addKerningPair(kerningData, kerningPair);
</span><span class="cx"> }
</span><del>- return finishAppendingKERNSubtable(result, WTF::move(kerningData), coverage);
</del><ins>+ return finishAppendingKERNSubtable(WTF::move(kerningData), coverage);
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-size_t SVGToOTFFontConverter::finishAppendingKERNSubtable(Vector<char>& result, Vector<KerningData> kerningData, uint16_t coverage) const
</del><ins>+size_t SVGToOTFFontConverter::finishAppendingKERNSubtable(Vector<KerningData> kerningData, uint16_t coverage)
</ins><span class="cx"> {
</span><span class="cx"> std::sort(kerningData.begin(), kerningData.end(), [](const KerningData& a, const KerningData& b) {
</span><span class="cx"> return a.glyph1 < b.glyph1 || (a.glyph1 == b.glyph1 && a.glyph2 < b.glyph2);
</span><span class="lines">@@ -665,50 +685,50 @@
</span><span class="cx"> sizeOfKerningDataTable = 14;
</span><span class="cx"> }
</span><span class="cx">
</span><del>- write16(result, 0); // Version of subtable
- write16(result, sizeOfKerningDataTable); // Length of this subtable
- write16(result, coverage); // Table coverage bitfield
</del><ins>+ append16(0); // Version of subtable
+ append16(sizeOfKerningDataTable); // Length of this subtable
+ append16(coverage); // Table coverage bitfield
</ins><span class="cx">
</span><span class="cx"> uint16_t roundedNumKerningPairs = roundDownToPowerOfTwo(kerningData.size());
</span><span class="cx">
</span><del>- write16(result, kerningData.size());
- write16(result, roundedNumKerningPairs * 6); // searchRange: "The largest power of two less than or equal to the value of nPairs, multiplied by the size in bytes of an entry in the table."
- write16(result, integralLog2(roundedNumKerningPairs)); // entrySelector: "log2 of the largest power of two less than or equal to the value of nPairs."
- write16(result, (kerningData.size() - roundedNumKerningPairs) * 6); // rangeShift: "The value of nPairs minus the largest power of two less than or equal to nPairs,
</del><ins>+ append16(kerningData.size());
+ append16(roundedNumKerningPairs * 6); // searchRange: "The largest power of two less than or equal to the value of nPairs, multiplied by the size in bytes of an entry in the table."
+ append16(integralLog2(roundedNumKerningPairs)); // entrySelector: "log2 of the largest power of two less than or equal to the value of nPairs."
+ append16((kerningData.size() - roundedNumKerningPairs) * 6); // rangeShift: "The value of nPairs minus the largest power of two less than or equal to nPairs,
</ins><span class="cx"> // and then multiplied by the size in bytes of an entry in the table."
</span><span class="cx">
</span><span class="cx"> for (auto& kerningData : kerningData) {
</span><del>- write16(result, kerningData.glyph1);
- write16(result, kerningData.glyph2);
- write16(result, kerningData.adjustment);
</del><ins>+ append16(kerningData.glyph1);
+ append16(kerningData.glyph2);
+ append16(kerningData.adjustment);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> return sizeOfKerningDataTable;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-void SVGToOTFFontConverter::appendKERNTable(Vector<char>& result) const
</del><ins>+void SVGToOTFFontConverter::appendKERNTable()
</ins><span class="cx"> {
</span><del>- write16(result, 0); // Version
- write16(result, 2); // Number of subtables
</del><ins>+ append16(0); // Version
+ append16(2); // Number of subtables
</ins><span class="cx">
</span><span class="cx"> #if !ASSERT_DISABLED
</span><del>- auto subtablesOffset = result.size();
</del><ins>+ auto subtablesOffset = m_result.size();
</ins><span class="cx"> #endif
</span><span class="cx">
</span><del>- size_t sizeOfHorizontalSubtable = appendKERNSubtable<SVGHKernElement>(result, &SVGHKernElement::buildHorizontalKerningPair, 1);
- ASSERT_UNUSED(sizeOfHorizontalSubtable, subtablesOffset + sizeOfHorizontalSubtable == result.size());
- size_t sizeOfVerticalSubtable = appendKERNSubtable<SVGVKernElement>(result, &SVGVKernElement::buildVerticalKerningPair, 0);
- ASSERT_UNUSED(sizeOfVerticalSubtable, subtablesOffset + sizeOfHorizontalSubtable + sizeOfVerticalSubtable == result.size());
</del><ins>+ size_t sizeOfHorizontalSubtable = appendKERNSubtable<SVGHKernElement>(&SVGHKernElement::buildHorizontalKerningPair, 1);
+ ASSERT_UNUSED(sizeOfHorizontalSubtable, subtablesOffset + sizeOfHorizontalSubtable == m_result.size());
+ size_t sizeOfVerticalSubtable = appendKERNSubtable<SVGVKernElement>(&SVGVKernElement::buildVerticalKerningPair, 0);
+ ASSERT_UNUSED(sizeOfVerticalSubtable, subtablesOffset + sizeOfHorizontalSubtable + sizeOfVerticalSubtable == m_result.size());
</ins><span class="cx">
</span><span class="cx"> // Work around a bug in Apple's font parser by adding some padding bytes. <rdar://problem/18401901>
</span><span class="cx"> for (int i = 0; i < 6; ++i)
</span><del>- result.append(0);
</del><ins>+ m_result.append(0);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> static void writeCFFEncodedNumber(Vector<char>& vector, float number)
</span><span class="cx"> {
</span><span class="cx"> vector.append(0xFF);
</span><del>- write32(vector, number * 0x10000);
</del><ins>+ append32(vector, number * 0x10000);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> static const char rLineTo = 0x05;
</span><span class="lines">@@ -847,7 +867,7 @@
</span><span class="cx"> return result;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-void SVGToOTFFontConverter::processGlyphElement(const SVGElement& glyphOrMissingGlyphElement, const SVGGlyphElement* glyphElement, float defaultHorizontalAdvance, float defaultVerticalAdvance, Codepoint codepoint, bool& initialGlyph)
</del><ins>+void SVGToOTFFontConverter::processGlyphElement(const SVGElement& glyphOrMissingGlyphElement, const SVGGlyphElement* glyphElement, float defaultHorizontalAdvance, float defaultVerticalAdvance, const String& codepoints, bool& initialGlyph)
</ins><span class="cx"> {
</span><span class="cx"> bool ok;
</span><span class="cx"> float horizontalAdvance = glyphOrMissingGlyphElement.fastGetAttribute(SVGNames::horiz_adv_xAttr).toFloat(&ok);
</span><span class="lines">@@ -868,9 +888,39 @@
</span><span class="cx"> m_minRightSideBearing = std::min(m_minRightSideBearing, horizontalAdvance - glyphBoundingBox.maxX());
</span><span class="cx"> initialGlyph = false;
</span><span class="cx">
</span><del>- m_glyphs.append(GlyphData(WTF::move(path), glyphElement, horizontalAdvance, verticalAdvance, m_boundingBox, codepoint));
</del><ins>+ m_glyphs.append(GlyphData(WTF::move(path), glyphElement, horizontalAdvance, verticalAdvance, m_boundingBox, codepoints));
</ins><span class="cx"> }
</span><span class="cx">
</span><ins>+bool SVGToOTFFontConverter::compareCodepointsLexicographically(const GlyphData& data1, const GlyphData& data2)
+{
+ unsigned i1 = 0;
+ unsigned i2 = 0;
+ unsigned length1 = data1.codepoints.length();
+ unsigned length2 = data2.codepoints.length();
+ while (i1 < length1 && i2 < length2) {
+ UChar32 codepoint1, codepoint2;
+ if (data1.codepoints.is8Bit())
+ codepoint1 = data1.codepoints[i1++];
+ else
+ U16_NEXT(data1.codepoints.characters16(), i1, length1, codepoint1);
+
+ if (data2.codepoints.is8Bit())
+ codepoint2 = data2.codepoints[i2++];
+ else
+ U16_NEXT(data2.codepoints.characters16(), i2, length2, codepoint2);
+
+ if (codepoint1 < codepoint2)
+ return true;
+ if (codepoint1 > codepoint2)
+ return false;
+ }
+
+ if (length1 == length2 && data1.glyphElement
+ && equalIgnoringCase(data1.glyphElement->fastGetAttribute(SVGNames::arabic_formAttr), "isolated"))
+ return true;
+ return length1 < length2;
+}
+
</ins><span class="cx"> SVGToOTFFontConverter::SVGToOTFFontConverter(const SVGFontElement& fontElement)
</span><span class="cx"> : m_fontElement(fontElement)
</span><span class="cx"> , m_fontFaceElement(childrenOfType<SVGFontFaceElement>(m_fontElement).first())
</span><span class="lines">@@ -891,7 +941,7 @@
</span><span class="cx"> m_unitsPerEm = m_fontFaceElement->unitsPerEm();
</span><span class="cx">
</span><span class="cx"> if (m_missingGlyphElement)
</span><del>- processGlyphElement(*m_missingGlyphElement, nullptr, defaultHorizontalAdvance, defaultVerticalAdvance, 0, initialGlyph);
</del><ins>+ processGlyphElement(*m_missingGlyphElement, nullptr, defaultHorizontalAdvance, defaultVerticalAdvance, String(), initialGlyph);
</ins><span class="cx"> else {
</span><span class="cx"> Vector<char> notdefCharString;
</span><span class="cx"> writeCFFEncodedNumber(notdefCharString, m_unitsPerEm);
</span><span class="lines">@@ -899,14 +949,13 @@
</span><span class="cx"> writeCFFEncodedNumber(notdefCharString, 0);
</span><span class="cx"> notdefCharString.append(rMoveTo);
</span><span class="cx"> notdefCharString.append(endChar);
</span><del>- m_glyphs.append(GlyphData(WTF::move(notdefCharString), nullptr, m_unitsPerEm, m_unitsPerEm, FloatRect(), 0));
</del><ins>+ m_glyphs.append(GlyphData(WTF::move(notdefCharString), nullptr, m_unitsPerEm, m_unitsPerEm, FloatRect(), String()));
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> for (auto& glyphElement : childrenOfType<SVGGlyphElement>(m_fontElement)) {
</span><span class="cx"> auto& unicodeAttribute = glyphElement.fastGetAttribute(SVGNames::unicodeAttr);
</span><del>- // Only support Basic Multilingual Plane w/o ligatures for now
- if (unicodeAttribute.length() == 1)
- processGlyphElement(glyphElement, &glyphElement, defaultHorizontalAdvance, defaultVerticalAdvance, unicodeAttribute[0], initialGlyph);
</del><ins>+ if (!unicodeAttribute.isEmpty()) // If we can never actually trigger this glyph, ignore it completely
+ processGlyphElement(glyphElement, &glyphElement, defaultHorizontalAdvance, defaultVerticalAdvance, unicodeAttribute, initialGlyph);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> if (m_glyphs.size() > std::numeric_limits<Glyph>::max()) {
</span><span class="lines">@@ -914,9 +963,7 @@
</span><span class="cx"> return;
</span><span class="cx"> }
</span><span class="cx">
</span><del>- std::sort(m_glyphs.begin(), m_glyphs.end(), [](const GlyphData& data1, const GlyphData& data2) {
- return data1.codepoint < data2.codepoint;
- });
</del><ins>+ std::sort(m_glyphs.begin(), m_glyphs.end(), &compareCodepointsLexicographically);
</ins><span class="cx">
</span><span class="cx"> for (Glyph i = 0; i < m_glyphs.size(); ++i) {
</span><span class="cx"> GlyphData& glyph = m_glyphs[i];
</span><span class="lines">@@ -925,8 +972,8 @@
</span><span class="cx"> if (!glyphName.isNull())
</span><span class="cx"> m_glyphNameToIndexMap.add(glyphName, i);
</span><span class="cx"> }
</span><del>- if (m_codepointToIndexMap.isValidKey(glyph.codepoint))
- m_codepointToIndexMap.add(glyph.codepoint, i);
</del><ins>+ if (m_codepointsToIndicesMap.isValidKey(glyph.codepoints))
+ m_codepointsToIndicesMap.add(glyph.codepoints, Vector<Glyph>()).iterator->value.append(i);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> // FIXME: Handle commas.
</span><span class="lines">@@ -963,92 +1010,92 @@
</span><span class="cx"> return !(x & 3);
</span><span class="cx"> }
</span><span class="cx">
</span><del>-static uint32_t calculateChecksum(const Vector<char>& table, size_t startingOffset, size_t endingOffset)
</del><ins>+uint32_t SVGToOTFFontConverter::calculateChecksum(size_t startingOffset, size_t endingOffset) const
</ins><span class="cx"> {
</span><span class="cx"> ASSERT(isFourByteAligned(endingOffset - startingOffset));
</span><span class="cx"> uint32_t sum = 0;
</span><span class="cx"> for (size_t offset = startingOffset; offset < endingOffset; offset += 4) {
</span><del>- sum += (static_cast<unsigned char>(table[offset + 3]) << 24)
- | (static_cast<unsigned char>(table[offset + 2]) << 16)
- | (static_cast<unsigned char>(table[offset + 1]) << 8)
- | static_cast<unsigned char>(table[offset]);
</del><ins>+ sum += (static_cast<unsigned char>(m_result[offset + 3]) << 24)
+ | (static_cast<unsigned char>(m_result[offset + 2]) << 16)
+ | (static_cast<unsigned char>(m_result[offset + 1]) << 8)
+ | static_cast<unsigned char>(m_result[offset]);
</ins><span class="cx"> }
</span><span class="cx"> return sum;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-void SVGToOTFFontConverter::appendTable(const char identifier[4], Vector<char>& output, FontAppendingFunction appendingFunction)
</del><ins>+void SVGToOTFFontConverter::appendTable(const char identifier[4], FontAppendingFunction appendingFunction)
</ins><span class="cx"> {
</span><del>- size_t offset = output.size();
</del><ins>+ size_t offset = m_result.size();
</ins><span class="cx"> ASSERT(isFourByteAligned(offset));
</span><del>- (this->*appendingFunction)(output);
- size_t unpaddedSize = output.size() - offset;
- while (!isFourByteAligned(output.size()))
- output.append(0);
- ASSERT(isFourByteAligned(output.size()));
</del><ins>+ (this->*appendingFunction)();
+ size_t unpaddedSize = m_result.size() - offset;
+ while (!isFourByteAligned(m_result.size()))
+ m_result.append(0);
+ ASSERT(isFourByteAligned(m_result.size()));
</ins><span class="cx"> size_t directoryEntryOffset = headerSize + m_tablesAppendedCount * directoryEntrySize;
</span><del>- output[directoryEntryOffset] = identifier[0];
- output[directoryEntryOffset + 1] = identifier[1];
- output[directoryEntryOffset + 2] = identifier[2];
- output[directoryEntryOffset + 3] = identifier[3];
- overwrite32(output, directoryEntryOffset + 4, calculateChecksum(output, offset, output.size()));
- overwrite32(output, directoryEntryOffset + 8, offset);
- overwrite32(output, directoryEntryOffset + 12, unpaddedSize);
</del><ins>+ m_result[directoryEntryOffset] = identifier[0];
+ m_result[directoryEntryOffset + 1] = identifier[1];
+ m_result[directoryEntryOffset + 2] = identifier[2];
+ m_result[directoryEntryOffset + 3] = identifier[3];
+ overwrite32(directoryEntryOffset + 4, calculateChecksum(offset, m_result.size()));
+ overwrite32(directoryEntryOffset + 8, offset);
+ overwrite32(directoryEntryOffset + 12, unpaddedSize);
</ins><span class="cx"> ++m_tablesAppendedCount;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-Vector<char> SVGToOTFFontConverter::convertSVGToOTFFont()
</del><ins>+void SVGToOTFFontConverter::convertSVGToOTFFont()
</ins><span class="cx"> {
</span><span class="cx"> Vector<char> result;
</span><span class="cx">
</span><span class="cx"> if (m_glyphs.isEmpty())
</span><del>- return result;
</del><ins>+ return;
</ins><span class="cx">
</span><span class="cx"> uint16_t numTables = 13;
</span><span class="cx"> uint16_t roundedNumTables = roundDownToPowerOfTwo(numTables);
</span><span class="cx"> uint16_t searchRange = roundedNumTables * 16; // searchRange: "(Maximum power of 2 <= numTables) x 16."
</span><span class="cx">
</span><del>- result.append('O');
- result.append('T');
- result.append('T');
- result.append('O');
- write16(result, numTables);
- write16(result, searchRange);
- write16(result, integralLog2(roundedNumTables)); // entrySelector: "Log2(maximum power of 2 <= numTables)."
- write16(result, numTables * 16 - searchRange); // rangeShift: "NumTables x 16-searchRange."
</del><ins>+ m_result.append('O');
+ m_result.append('T');
+ m_result.append('T');
+ m_result.append('O');
+ append16(numTables);
+ append16(searchRange);
+ append16(integralLog2(roundedNumTables)); // entrySelector: "Log2(maximum power of 2 <= numTables)."
+ append16(numTables * 16 - searchRange); // rangeShift: "NumTables x 16-searchRange."
</ins><span class="cx">
</span><span class="cx"> ASSERT(result.size() == headerSize);
</span><span class="cx">
</span><span class="cx"> // Leave space for the directory entries.
</span><span class="cx"> for (size_t i = 0; i < directoryEntrySize * numTables; ++i)
</span><del>- result.append(0);
</del><ins>+ m_result.append(0);
</ins><span class="cx">
</span><del>- appendTable("CFF ", result, &SVGToOTFFontConverter::appendCFFTable);
- appendTable("OS/2", result, &SVGToOTFFontConverter::appendOS2Table);
- appendTable("VORG", result, &SVGToOTFFontConverter::appendVORGTable);
- appendTable("cmap", result, &SVGToOTFFontConverter::appendCMAPTable);
- auto headTableOffset = result.size();
- appendTable("head", result, &SVGToOTFFontConverter::appendHEADTable);
- appendTable("hhea", result, &SVGToOTFFontConverter::appendHHEATable);
- appendTable("hmtx", result, &SVGToOTFFontConverter::appendHMTXTable);
- appendTable("kern", result, &SVGToOTFFontConverter::appendKERNTable);
- appendTable("maxp", result, &SVGToOTFFontConverter::appendMAXPTable);
- appendTable("name", result, &SVGToOTFFontConverter::appendNAMETable);
- appendTable("post", result, &SVGToOTFFontConverter::appendPOSTTable);
- appendTable("vhea", result, &SVGToOTFFontConverter::appendVHEATable);
- appendTable("vmtx", result, &SVGToOTFFontConverter::appendVMTXTable);
</del><ins>+ appendTable("CFF ", &SVGToOTFFontConverter::appendCFFTable);
+ appendTable("OS/2", &SVGToOTFFontConverter::appendOS2Table);
+ appendTable("VORG", &SVGToOTFFontConverter::appendVORGTable);
+ appendTable("cmap", &SVGToOTFFontConverter::appendCMAPTable);
+ auto headTableOffset = m_result.size();
+ appendTable("head", &SVGToOTFFontConverter::appendHEADTable);
+ appendTable("hhea", &SVGToOTFFontConverter::appendHHEATable);
+ appendTable("hmtx", &SVGToOTFFontConverter::appendHMTXTable);
+ appendTable("kern", &SVGToOTFFontConverter::appendKERNTable);
+ appendTable("maxp", &SVGToOTFFontConverter::appendMAXPTable);
+ appendTable("name", &SVGToOTFFontConverter::appendNAMETable);
+ appendTable("post", &SVGToOTFFontConverter::appendPOSTTable);
+ appendTable("vhea", &SVGToOTFFontConverter::appendVHEATable);
+ appendTable("vmtx", &SVGToOTFFontConverter::appendVMTXTable);
</ins><span class="cx">
</span><span class="cx"> ASSERT(numTables == m_tablesAppendedCount);
</span><span class="cx">
</span><span class="cx"> // checksumAdjustment: "To compute: set it to 0, calculate the checksum for the 'head' table and put it in the table directory,
</span><span class="cx"> // sum the entire font as uint32, then store B1B0AFBA - sum. The checksum for the 'head' table will now be wrong. That is OK."
</span><del>- overwrite32(result, headTableOffset + 8, 0xB1B0AFBAU - calculateChecksum(result, 0, result.size()));
-
- return result;
</del><ins>+ overwrite32(headTableOffset + 8, 0xB1B0AFBAU - calculateChecksum(0, result.size()));
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> Vector<char> convertSVGToOTFFont(const SVGFontElement& element)
</span><span class="cx"> {
</span><del>- return SVGToOTFFontConverter(element).convertSVGToOTFFont();
</del><ins>+ SVGToOTFFontConverter converter(element);
+ converter.convertSVGToOTFFont();
+ return converter.releaseResult();
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> }
</span></span></pre>
</div>
</div>
</body>
</html>