<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<!DOCTYPE bugzilla SYSTEM "https://bugs.webkit.org/page.cgi?id=bugzilla.dtd">

<bugzilla version="5.0.4.1"
          urlbase="https://bugs.webkit.org/"
          
          maintainer="admin@webkit.org"
>

    <bug>
          <bug_id>136688</bug_id>
          
          <creation_ts>2014-09-09 16:50:42 -0700</creation_ts>
          <short_desc>Initial implementation of SVG to OTF font converter</short_desc>
          <delta_ts>2014-09-16 11:09:36 -0700</delta_ts>
          <reporter_accessible>1</reporter_accessible>
          <cclist_accessible>1</cclist_accessible>
          <classification_id>1</classification_id>
          <classification>Unclassified</classification>
          <product>WebKit</product>
          <component>SVG</component>
          <version>528+ (Nightly build)</version>
          <rep_platform>Unspecified</rep_platform>
          <op_sys>Unspecified</op_sys>
          <bug_status>RESOLVED</bug_status>
          <resolution>FIXED</resolution>
          
          
          <bug_file_loc></bug_file_loc>
          <status_whiteboard></status_whiteboard>
          <keywords></keywords>
          <priority>P2</priority>
          <bug_severity>Normal</bug_severity>
          <target_milestone>---</target_milestone>
          
          
          <everconfirmed>1</everconfirmed>
          <reporter name="Myles C. Maxfield">mmaxfield</reporter>
          <assigned_to name="Myles C. Maxfield">mmaxfield</assigned_to>
          <cc>commit-queue</cc>
    
    <cc>dino</cc>
    
    <cc>d-r</cc>
    
    <cc>fmalita</cc>
    
    <cc>gyuyoung.kim</cc>
    
    <cc>jonlee</cc>
    
    <cc>krit</cc>
    
    <cc>pdr</cc>
    
    <cc>schenney</cc>
    
    <cc>sergio</cc>
    
    <cc>simon.fraser</cc>
    
    <cc>thorton</cc>
    
    <cc>yuki.sekiguchi</cc>
    
    <cc>zimmermann</cc>
          

      

      

      

          <comment_sort_order>oldest_to_newest</comment_sort_order>  
          <long_desc isprivate="0" >
    <commentid>1034208</commentid>
    <comment_count>0</comment_count>
    <who name="Myles C. Maxfield">mmaxfield</who>
    <bug_when>2014-09-09 16:50:42 -0700</bug_when>
    <thetext>Initial implementation of SVG to OTF font converter</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1034213</commentid>
    <comment_count>1</comment_count>
      <attachid>237873</attachid>
    <who name="Myles C. Maxfield">mmaxfield</who>
    <bug_when>2014-09-09 17:05:45 -0700</bug_when>
    <thetext>Created attachment 237873
Patch</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1034231</commentid>
    <comment_count>2</comment_count>
    <who name="Philip Rogers">pdr</who>
    <bug_when>2014-09-09 21:54:31 -0700</bug_when>
    <thetext>Wow, this is amazing work!

I worry that SVG fonts may not be worth this complexity though. SVG fonts are not supported in IE or Firefox and they were recently removed from Chromium (https://groups.google.com/a/chromium.org/d/msg/blink-dev/pYbbUcYvlYY/LQvFvM8KZZEJ). SVG fonts were also moved out of SVG2 (http://lists.w3.org/Archives/Public/www-svg/2013Jan/0030.html) and into a module.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1034232</commentid>
    <comment_count>3</comment_count>
    <who name="Tim Horton">thorton</who>
    <bug_when>2014-09-09 22:30:35 -0700</bug_when>
    <thetext>Walled garden content might sway the equation slightly in a different direction for us, resulting in this neat experiment.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1034305</commentid>
    <comment_count>4</comment_count>
    <who name="Myles C. Maxfield">mmaxfield</who>
    <bug_when>2014-09-10 08:24:34 -0700</bug_when>
    <thetext>After running the benchmark on ToT for 21 hours, this is now at least a 500x speedup</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1034327</commentid>
    <comment_count>5</comment_count>
      <attachid>237873</attachid>
    <who name="Darin Adler">darin</who>
    <bug_when>2014-09-10 09:07:10 -0700</bug_when>
    <thetext>Comment on attachment 237873
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=237873&amp;action=review

Seems OK. I spotted quite a few mistakes.

This mixes types: Using uint16 as well as uint16_t.

This replicates parsing with subtly different rules from the rules used in the actual SVG font parsing code. All the hardcoded strings here and such might not be the best way to do the parsing.

&gt; Source/WebCore/svg/SVGToOTFFontConversion.cpp:40
&gt; +static inline void writeUInt32(Vector&lt;char&gt;&amp; vector, uint32_t value)

I would just call this write32; could overload for different types (unsigned vs. signed).

&gt; Source/WebCore/svg/SVGToOTFFontConversion.cpp:43
&gt; +    uint32_t bigEndianValue = htonl(value);
&gt; +    vector.append(reinterpret_cast_ptr&lt;char*&gt;(&amp;bigEndianValue), sizeof(bigEndianValue));

I think it would be better to just write:

    vector.append(value &gt;&gt; 24);
    vector.append(value &gt;&gt; 16);
    vector.append(value &gt;&gt; 8);
    vector.append(value);

&gt; Source/WebCore/svg/SVGToOTFFontConversion.cpp:46
&gt; +static inline void writeUInt16(Vector&lt;char&gt;&amp; vector, uint16_t value)

I would just call this write16; could overload for different types (unsigned vs. signed).

&gt; Source/WebCore/svg/SVGToOTFFontConversion.cpp:49
&gt; +    uint16_t bigEndianValue = htons(value);
&gt; +    vector.append(reinterpret_cast_ptr&lt;char*&gt;(&amp;bigEndianValue), sizeof(bigEndianValue));

I think it would be better to just write:

    vector.append(value &gt;&gt; 8);
    vector.append(value);

&gt; Source/WebCore/svg/SVGToOTFFontConversion.cpp:60
&gt; +    // Use unsigned chars to avoid wraparound problems
&gt; +    unsigned char* ptr = reinterpret_cast_ptr&lt;unsigned char*&gt;(vector.data() + location);
&gt; +    *(ptr++) = static_cast&lt;unsigned char&gt;(value &gt;&gt; 24);
&gt; +    *(ptr++) = static_cast&lt;unsigned char&gt;(value &gt;&gt; 16);
&gt; +    *(ptr++) = static_cast&lt;unsigned char&gt;(value &gt;&gt; 8);
&gt; +    *(ptr++) = static_cast&lt;unsigned char&gt;(value &gt;&gt; 0);

The use of unsigned char here isn’t necessary. The function would work equally well if we didn’t do the reinterpret_cast. Also no need to do auto-increments instead of indexing.

&gt; Source/WebCore/svg/SVGToOTFFontConversion.cpp:100
&gt; +    Vector&lt;char&gt; createCMAPTable();
&gt; +    Vector&lt;char&gt; createHEADTable();
&gt; +    Vector&lt;char&gt; createHHEATable();
&gt; +    Vector&lt;char&gt; createHMTXTable();
&gt; +    Vector&lt;char&gt; createMAXPTable();
&gt; +    Vector&lt;char&gt; createNAMETable();
&gt; +    Vector&lt;char&gt; createOS2Table();
&gt; +    Vector&lt;char&gt; createPOSTTable();
&gt; +    Vector&lt;char&gt; createCFFTable();
&gt; +    Vector&lt;char&gt; createVORGTable();

Seems to me that creating each table in a separate vector requires excessive memory allocation. An efficient design would be to have functions that append to an existing vector, like the write helper functions above, or use some kind of streaming abstraction. We’d first leave room for the offsets, then lay down the tables and write out the offsets after the fact. Rather than building all the tables in separate buffers just so we can get their sizes. Should be pretty easy to write it that way instead.

&gt; Source/WebCore/svg/SVGToOTFFontConversion.cpp:181
&gt; +    uint16 unitsPerEm = m_fontFaceElement ? m_fontFaceElement-&gt;unitsPerEm() : 0;

Elsewhere you use types like uint16_t, but here you use uint16, a less portable alternative.

&gt; Source/WebCore/svg/SVGToOTFFontConversion.cpp:213
&gt; +    uint16 ascent = std::numeric_limits&lt;int16_t&gt;::max();
&gt; +    uint16 descent = std::numeric_limits&lt;int16_t&gt;::max();

Strange to use an unsigned integer, but default to signed 16-bit maximum.

&gt; Source/WebCore/svg/SVGToOTFFontConversion.cpp:285
&gt; +    for (unsigned i = 0; i &lt; m_fontFamily.length(); ++i)
&gt; +        writeUInt16(result, m_fontFamily[i]);

Should use a modern for loop.

&gt; Source/WebCore/svg/SVGToOTFFontConversion.cpp:295
&gt; +    const auto&amp; attribute = m_fontElement.getAttribute(&quot;horiz-adv-x&quot;);

auto&amp; would be fine; const adds nothing here.

fastGetAttribute. Also good

&gt; Source/WebCore/svg/SVGToOTFFontConversion.cpp:299
&gt; +    int value = attribute.toInt(&amp;ok);
&gt; +    if (ok)
&gt; +        averageAdvance = value;

This will overflow if the int is too big for a 16-bit integer.

&gt; Source/WebCore/svg/SVGToOTFFontConversion.cpp:372
&gt; +    if (string.isEmpty())
&gt; +        return true;

No need to optimize this case. Just remove this code.

&gt; Source/WebCore/svg/SVGToOTFFontConversion.cpp:374
&gt; +    if (!string.is8Bit())
&gt; +        return false;

This doesn’t make sense. We should not be checking this. It’s possible for a 16-bit string to have all value characters but just happen to be stored in 16-bit format. Just remove this incorrect code.

&gt; Source/WebCore/svg/SVGToOTFFontConversion.cpp:392
&gt; +    String fontName = String();

&quot;= String()&quot; is an no-op. We should remove it.

&gt; Source/WebCore/svg/SVGToOTFFontConversion.cpp:399
&gt; +    ASSERT(fontName.is8Bit());

This is wrong. It’s not right to do this.

&gt; Source/WebCore/svg/SVGToOTFFontConversion.cpp:404
&gt; +    result.append(fontName.characters8(), fontName.length());

We should write a function that knowns how to append all the characters one at a time. It’s not right to use characters8. Even if the string has all Latin-1 characters it’s not guaranteed to be stored 8-bit.

&gt; Source/WebCore/svg/SVGToOTFFontConversion.cpp:408
&gt; +        const auto&amp; potentialWeight = m_fontFaceElement-&gt;fastGetAttribute(SVGNames::font_weightAttr);

The const adds nothing here.

&gt; Source/WebCore/svg/SVGToOTFFontConversion.cpp:471
&gt; +        ASSERT(weight.is8Bit());

Same problem with incorrect assertion here.

&gt; Source/WebCore/svg/SVGToOTFFontConversion.cpp:476
&gt; +    result.append(fontName.characters8(), fontName.length());
&gt; +    result.append(weight.characters8(), weight.length());

Same problem with incorrect use of characters8 here.

&gt; Source/WebCore/svg/SVGToOTFFontConversion.cpp:492
&gt; +    for (const auto&amp; glyph : m_glyphs) {

I would omit the const here.

&gt; Source/WebCore/svg/SVGToOTFFontConversion.cpp:496
&gt; +    for (const auto&amp; glyph : m_glyphs)

I would omit the const here.

&gt; Source/WebCore/svg/SVGToOTFFontConversion.cpp:520
&gt; +            const auto&amp; attribute = m_glyphs[i].glyphElement-&gt;fastGetAttribute(SVGNames::vert_origin_yAttr);

const here does nothing

&gt; Source/WebCore/svg/SVGToOTFFontConversion.cpp:522
&gt; +                if (int16_t verticalOriginY = atoi(reinterpret_cast_ptr&lt;const char*&gt;(attribute.characters8())))

Incorrect to use atoi here. Incorrect to check is8Bit and use characters8 here. Need to use something more like the toInt code path above.

&gt; Source/WebCore/svg/SVGToOTFFontConversion.cpp:531
&gt; +        writeUInt16(result, p.first);
&gt; +        writeUInt16(result, p.second);

I suggest just appending these as we go, and then going back to patch in the size, rather than building up a Vector&lt;pair&gt; just so we can count the sizes.

&gt; Source/WebCore/svg/SVGToOTFFontConversion.cpp:538
&gt; +    int raw = number * pow(2, 16);

Math here will be done as double rather than flow, since pow returns a double. Is that what we want?

&gt; Source/WebCore/svg/SVGToOTFFontConversion.cpp:554
&gt; +        // FIXME: We probably want the initial moveto to use horiz-origin-x and horiz-origin-y... unless we&apos;re vertical...

Not sure what the &quot;...&quot; mean here.

&gt; Source/WebCore/svg/SVGToOTFFontConversion.cpp:696
&gt; +    for (const auto&amp; glyph : childrenOfType&lt;SVGGlyphElement&gt;(m_fontElement)) {

The const here adds nothing.

&gt; Source/WebCore/svg/SVGToOTFFontConversion.cpp:697
&gt; +        const auto&amp; unicodeAttribute = glyph.getAttribute(&quot;unicode&quot;);

Should use fastGetAttribute. The const here adds nothing.

&gt; Source/WebCore/svg/SVGToOTFFontConversion.cpp:701
&gt; +            const auto&amp; advanceAttribute = glyph.fastGetAttribute(SVGNames::horiz_adv_xAttr);

The const here adds nothing.

&gt; Source/WebCore/svg/SVGToOTFFontConversion.cpp:723
&gt; +    std::sort(m_glyphs.begin(), m_glyphs.end(), &amp;compareGlyphData);

I suggest a lambda here rather than a static member function.

&gt; Source/WebCore/svg/SVGToOTFFontConversion.cpp:727
&gt; +        const auto&amp; fontWeightAttribute = m_fontFaceElement-&gt;fastGetAttribute(SVGNames::font_weightAttr);

The const here isn’t helpful.

&gt; Source/WebCore/svg/SVGToOTFFontConversion.cpp:729
&gt; +        String(fontWeightAttribute).split(&quot; &quot;, split);

Instead of:

    String(fontWeightAttribute)

Should use:

    fontWeightAttribute.string()

&gt; Source/WebCore/svg/SVGToOTFFontConversion.cpp:730
&gt; +        for (const auto&amp; s : split) {

Please don&apos;t use a single character here.

&gt; Source/WebCore/svg/SVGToOTFFontConversion.cpp:759
&gt; +    const uint32_t* ptr = reinterpret_cast_ptr&lt;const uint32_t*&gt;(table.data());
&gt; +    const uint32_t* const endPtr = reinterpret_cast_ptr&lt;const uint32_t*&gt;(table.data() + table.size());
&gt; +    for (; ptr &lt; endPtr; ++ptr)
&gt; +        sum += *ptr;

This is endian-specific checksumming, and it’s not going to work right on both little-endian and big-endian systems. Since we go to the trouble of doing big-endian appending, it’s clear that the checksumming is well defined as either little or big-endian.

It’s easy to write code that does that correctly, buildin each 32-bit number out of four characters we extract with unsigned shifting, rather than doing the reinterpret_cast style. If big-endian it would be:

    for (size_t i = 0; i &lt; table.size(); i += 4) {
        sum += (static_cast&lt;unsigned char&gt;(table[i]) &lt;&lt; 24)
            | (static_cast&lt;unsigned char&gt;(table[i + 1]) &lt;&lt; 16)
            | (static_cast&lt;unsigned char&gt;(table[i + 2]) &lt;&lt; 8)
            | static_cast&lt;unsigned char&gt;(table[i + 3]);
    }

If little-endian then:

    for (size_t i = 0; i &lt; table.size(); i += 4) {
        sum += (static_cast&lt;unsigned char&gt;(table[i + 3]) &lt;&lt; 24)
            | (static_cast&lt;unsigned char&gt;(table[i + 2]) &lt;&lt; 16)
            | (static_cast&lt;unsigned char&gt;(table[i + 1]) &lt;&lt; 8)
            | static_cast&lt;unsigned char&gt;(table[i]);
    }

&gt; Source/WebCore/svg/SVGToOTFFontConversion.cpp:766
&gt; +    uint32_t size = table.size();

I don’t think size is a good name for this; should give a different name.

&gt; Source/WebCore/svg/SVGToOTFFontConversion.cpp:768
&gt; +        table.append(static_cast&lt;char&gt;(0));

Why is this static_cast needed? It should compile fine without this.

&gt; Source/WebCore/svg/SVGToOTFFontConversion.h:29
&gt; +#include &lt;WTF/Vector.h&gt;

Needs to be &lt;wtf/Vector.h&gt; for case sensitive file systems.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1034505</commentid>
    <comment_count>6</comment_count>
      <attachid>237873</attachid>
    <who name="Myles C. Maxfield">mmaxfield</who>
    <bug_when>2014-09-10 19:29:45 -0700</bug_when>
    <thetext>Comment on attachment 237873
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=237873&amp;action=review

&gt;&gt; Source/WebCore/svg/SVGToOTFFontConversion.cpp:40
&gt;&gt; +static inline void writeUInt32(Vector&lt;char&gt;&amp; vector, uint32_t value)
&gt; 
&gt; I would just call this write32; could overload for different types (unsigned vs. signed).

Done.

&gt;&gt; Source/WebCore/svg/SVGToOTFFontConversion.cpp:43
&gt;&gt; +    vector.append(reinterpret_cast_ptr&lt;char*&gt;(&amp;bigEndianValue), sizeof(bigEndianValue));
&gt; 
&gt; I think it would be better to just write:
&gt; 
&gt;     vector.append(value &gt;&gt; 24);
&gt;     vector.append(value &gt;&gt; 16);
&gt;     vector.append(value &gt;&gt; 8);
&gt;     vector.append(value);

Done.

&gt;&gt; Source/WebCore/svg/SVGToOTFFontConversion.cpp:46
&gt;&gt; +static inline void writeUInt16(Vector&lt;char&gt;&amp; vector, uint16_t value)
&gt; 
&gt; I would just call this write16; could overload for different types (unsigned vs. signed).

Done.

&gt;&gt; Source/WebCore/svg/SVGToOTFFontConversion.cpp:49
&gt;&gt; +    vector.append(reinterpret_cast_ptr&lt;char*&gt;(&amp;bigEndianValue), sizeof(bigEndianValue));
&gt; 
&gt; I think it would be better to just write:
&gt; 
&gt;     vector.append(value &gt;&gt; 8);
&gt;     vector.append(value);

Done.

&gt;&gt; Source/WebCore/svg/SVGToOTFFontConversion.cpp:60
&gt;&gt; +    *(ptr++) = static_cast&lt;unsigned char&gt;(value &gt;&gt; 0);
&gt; 
&gt; The use of unsigned char here isn’t necessary. The function would work equally well if we didn’t do the reinterpret_cast. Also no need to do auto-increments instead of indexing.

Done.

&gt;&gt; Source/WebCore/svg/SVGToOTFFontConversion.cpp:100
&gt;&gt; +    Vector&lt;char&gt; createVORGTable();
&gt; 
&gt; Seems to me that creating each table in a separate vector requires excessive memory allocation. An efficient design would be to have functions that append to an existing vector, like the write helper functions above, or use some kind of streaming abstraction. We’d first leave room for the offsets, then lay down the tables and write out the offsets after the fact. Rather than building all the tables in separate buffers just so we can get their sizes. Should be pretty easy to write it that way instead.

I did it to simplify the code that writes the directory table entries, however, I think you&apos;re right. I&apos;ll do this tomorrow.

&gt;&gt; Source/WebCore/svg/SVGToOTFFontConversion.cpp:181
&gt;&gt; +    uint16 unitsPerEm = m_fontFaceElement ? m_fontFaceElement-&gt;unitsPerEm() : 0;
&gt; 
&gt; Elsewhere you use types like uint16_t, but here you use uint16, a less portable alternative.

Done.

&gt;&gt; Source/WebCore/svg/SVGToOTFFontConversion.cpp:213
&gt;&gt; +    uint16 descent = std::numeric_limits&lt;int16_t&gt;::max();
&gt; 
&gt; Strange to use an unsigned integer, but default to signed 16-bit maximum.

Typo; done.

&gt;&gt; Source/WebCore/svg/SVGToOTFFontConversion.cpp:285
&gt;&gt; +        writeUInt16(result, m_fontFamily[i]);
&gt; 
&gt; Should use a modern for loop.

String doesn&apos;t support the modern for loop syntax (for accessing characters). Perhaps this support could be added in a later patch.

&gt;&gt; Source/WebCore/svg/SVGToOTFFontConversion.cpp:295
&gt;&gt; +    const auto&amp; attribute = m_fontElement.getAttribute(&quot;horiz-adv-x&quot;);
&gt; 
&gt; auto&amp; would be fine; const adds nothing here.
&gt; 
&gt; fastGetAttribute. Also good

Done.

Done.

&gt;&gt; Source/WebCore/svg/SVGToOTFFontConversion.cpp:299
&gt;&gt; +        averageAdvance = value;
&gt; 
&gt; This will overflow if the int is too big for a 16-bit integer.

Done.

&gt;&gt; Source/WebCore/svg/SVGToOTFFontConversion.cpp:372
&gt;&gt; +        return true;
&gt; 
&gt; No need to optimize this case. Just remove this code.

Done.

&gt;&gt; Source/WebCore/svg/SVGToOTFFontConversion.cpp:374
&gt;&gt; +        return false;
&gt; 
&gt; This doesn’t make sense. We should not be checking this. It’s possible for a 16-bit string to have all value characters but just happen to be stored in 16-bit format. Just remove this incorrect code.

Yeah, you&apos;re right. Done.

&gt;&gt; Source/WebCore/svg/SVGToOTFFontConversion.cpp:392
&gt;&gt; +    String fontName = String();
&gt; 
&gt; &quot;= String()&quot; is an no-op. We should remove it.

Done.

&gt;&gt; Source/WebCore/svg/SVGToOTFFontConversion.cpp:399
&gt;&gt; +    ASSERT(fontName.is8Bit());
&gt; 
&gt; This is wrong. It’s not right to do this.

Done.

&gt;&gt; Source/WebCore/svg/SVGToOTFFontConversion.cpp:404
&gt;&gt; +    result.append(fontName.characters8(), fontName.length());
&gt; 
&gt; We should write a function that knowns how to append all the characters one at a time. It’s not right to use characters8. Even if the string has all Latin-1 characters it’s not guaranteed to be stored 8-bit.

Done.

&gt;&gt; Source/WebCore/svg/SVGToOTFFontConversion.cpp:408
&gt;&gt; +        const auto&amp; potentialWeight = m_fontFaceElement-&gt;fastGetAttribute(SVGNames::font_weightAttr);
&gt; 
&gt; The const adds nothing here.

Done.

&gt;&gt; Source/WebCore/svg/SVGToOTFFontConversion.cpp:471
&gt;&gt; +        ASSERT(weight.is8Bit());
&gt; 
&gt; Same problem with incorrect assertion here.

Done.

&gt;&gt; Source/WebCore/svg/SVGToOTFFontConversion.cpp:476
&gt;&gt; +    result.append(weight.characters8(), weight.length());
&gt; 
&gt; Same problem with incorrect use of characters8 here.

Done.

&gt;&gt; Source/WebCore/svg/SVGToOTFFontConversion.cpp:492
&gt;&gt; +    for (const auto&amp; glyph : m_glyphs) {
&gt; 
&gt; I would omit the const here.

Done.

&gt;&gt; Source/WebCore/svg/SVGToOTFFontConversion.cpp:496
&gt;&gt; +    for (const auto&amp; glyph : m_glyphs)
&gt; 
&gt; I would omit the const here.

Done.

&gt;&gt; Source/WebCore/svg/SVGToOTFFontConversion.cpp:520
&gt;&gt; +            const auto&amp; attribute = m_glyphs[i].glyphElement-&gt;fastGetAttribute(SVGNames::vert_origin_yAttr);
&gt; 
&gt; const here does nothing

Done.

&gt;&gt; Source/WebCore/svg/SVGToOTFFontConversion.cpp:522
&gt;&gt; +                if (int16_t verticalOriginY = atoi(reinterpret_cast_ptr&lt;const char*&gt;(attribute.characters8())))
&gt; 
&gt; Incorrect to use atoi here. Incorrect to check is8Bit and use characters8 here. Need to use something more like the toInt code path above.

Done.

&gt;&gt; Source/WebCore/svg/SVGToOTFFontConversion.cpp:538
&gt;&gt; +    int raw = number * pow(2, 16);
&gt; 
&gt; Math here will be done as double rather than flow, since pow returns a double. Is that what we want?

Nope. Done.

&gt;&gt; Source/WebCore/svg/SVGToOTFFontConversion.cpp:554
&gt;&gt; +        // FIXME: We probably want the initial moveto to use horiz-origin-x and horiz-origin-y... unless we&apos;re vertical...
&gt; 
&gt; Not sure what the &quot;...&quot; mean here.

Removed.

&gt;&gt; Source/WebCore/svg/SVGToOTFFontConversion.cpp:696
&gt;&gt; +    for (const auto&amp; glyph : childrenOfType&lt;SVGGlyphElement&gt;(m_fontElement)) {
&gt; 
&gt; The const here adds nothing.

Done.

&gt;&gt; Source/WebCore/svg/SVGToOTFFontConversion.cpp:697
&gt;&gt; +        const auto&amp; unicodeAttribute = glyph.getAttribute(&quot;unicode&quot;);
&gt; 
&gt; Should use fastGetAttribute. The const here adds nothing.

Done.

&gt;&gt; Source/WebCore/svg/SVGToOTFFontConversion.cpp:701
&gt;&gt; +            const auto&amp; advanceAttribute = glyph.fastGetAttribute(SVGNames::horiz_adv_xAttr);
&gt; 
&gt; The const here adds nothing.

Done.

&gt;&gt; Source/WebCore/svg/SVGToOTFFontConversion.cpp:723
&gt;&gt; +    std::sort(m_glyphs.begin(), m_glyphs.end(), &amp;compareGlyphData);
&gt; 
&gt; I suggest a lambda here rather than a static member function.

Done.

&gt;&gt; Source/WebCore/svg/SVGToOTFFontConversion.cpp:727
&gt;&gt; +        const auto&amp; fontWeightAttribute = m_fontFaceElement-&gt;fastGetAttribute(SVGNames::font_weightAttr);
&gt; 
&gt; The const here isn’t helpful.

Done.

&gt;&gt; Source/WebCore/svg/SVGToOTFFontConversion.cpp:729
&gt;&gt; +        String(fontWeightAttribute).split(&quot; &quot;, split);
&gt; 
&gt; Instead of:
&gt; 
&gt;     String(fontWeightAttribute)
&gt; 
&gt; Should use:
&gt; 
&gt;     fontWeightAttribute.string()

Done.

&gt;&gt; Source/WebCore/svg/SVGToOTFFontConversion.cpp:730
&gt;&gt; +        for (const auto&amp; s : split) {
&gt; 
&gt; Please don&apos;t use a single character here.

Done.

&gt;&gt; Source/WebCore/svg/SVGToOTFFontConversion.cpp:759
&gt;&gt; +        sum += *ptr;
&gt; 
&gt; This is endian-specific checksumming, and it’s not going to work right on both little-endian and big-endian systems. Since we go to the trouble of doing big-endian appending, it’s clear that the checksumming is well defined as either little or big-endian.
&gt; 
&gt; It’s easy to write code that does that correctly, buildin each 32-bit number out of four characters we extract with unsigned shifting, rather than doing the reinterpret_cast style. If big-endian it would be:
&gt; 
&gt;     for (size_t i = 0; i &lt; table.size(); i += 4) {
&gt;         sum += (static_cast&lt;unsigned char&gt;(table[i]) &lt;&lt; 24)
&gt;             | (static_cast&lt;unsigned char&gt;(table[i + 1]) &lt;&lt; 16)
&gt;             | (static_cast&lt;unsigned char&gt;(table[i + 2]) &lt;&lt; 8)
&gt;             | static_cast&lt;unsigned char&gt;(table[i + 3]);
&gt;     }
&gt; 
&gt; If little-endian then:
&gt; 
&gt;     for (size_t i = 0; i &lt; table.size(); i += 4) {
&gt;         sum += (static_cast&lt;unsigned char&gt;(table[i + 3]) &lt;&lt; 24)
&gt;             | (static_cast&lt;unsigned char&gt;(table[i + 2]) &lt;&lt; 16)
&gt;             | (static_cast&lt;unsigned char&gt;(table[i + 1]) &lt;&lt; 8)
&gt;             | static_cast&lt;unsigned char&gt;(table[i]);
&gt;     }

Done.

&gt;&gt; Source/WebCore/svg/SVGToOTFFontConversion.cpp:766
&gt;&gt; +    uint32_t size = table.size();
&gt; 
&gt; I don’t think size is a good name for this; should give a different name.

Done.

&gt;&gt; Source/WebCore/svg/SVGToOTFFontConversion.cpp:768
&gt;&gt; +        table.append(static_cast&lt;char&gt;(0));
&gt; 
&gt; Why is this static_cast needed? It should compile fine without this.

Done.

&gt;&gt; Source/WebCore/svg/SVGToOTFFontConversion.h:29
&gt;&gt; +#include &lt;WTF/Vector.h&gt;
&gt; 
&gt; Needs to be &lt;wtf/Vector.h&gt; for case sensitive file systems.

Done.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1035506</commentid>
    <comment_count>7</comment_count>
    <who name="Myles C. Maxfield">mmaxfield</who>
    <bug_when>2014-09-16 11:09:36 -0700</bug_when>
    <thetext>http://trac.webkit.org/changeset/173521</thetext>
  </long_desc>
      
          <attachment
              isobsolete="0"
              ispatch="1"
              isprivate="0"
          >
            <attachid>237873</attachid>
            <date>2014-09-09 17:05:45 -0700</date>
            <delta_ts>2014-09-10 19:29:44 -0700</delta_ts>
            <desc>Patch</desc>
            <filename>bug-136688-20140909170541.patch</filename>
            <type>text/plain</type>
            <size>45413</size>
            <attacher name="Myles C. Maxfield">mmaxfield</attacher>
            
              <data encoding="base64">U3VidmVyc2lvbiBSZXZpc2lvbjogMTczNDE4CmRpZmYgLS1naXQgYS9Tb3VyY2UvV2ViQ29yZS9D
aGFuZ2VMb2cgYi9Tb3VyY2UvV2ViQ29yZS9DaGFuZ2VMb2cKaW5kZXggMWFiZTBhMTlmODhmNjlm
M2IxMGZjZjdmYjU0NWZiZmYwZDk1OTUxOC4uNTUwM2M3MTExNjc1MjcyNDRjZjRmMzgxOTg0NTE1
ZDU3NzQyZDQ2OCAxMDA2NDQKLS0tIGEvU291cmNlL1dlYkNvcmUvQ2hhbmdlTG9nCisrKyBiL1Nv
dXJjZS9XZWJDb3JlL0NoYW5nZUxvZwpAQCAtMSwzICsxLDY3IEBACisyMDE0LTA5LTA5ICBNeWxl
cyBDLiBNYXhmaWVsZCAgPG1tYXhmaWVsZEBhcHBsZS5jb20+CisKKyAgICAgICAgSW5pdGlhbCBp
bXBsZW1lbnRhdGlvbiBvZiBTVkcgdG8gT1RGIGZvbnQgY29udmVydGVyCisgICAgICAgIGh0dHBz
Oi8vYnVncy53ZWJraXQub3JnL3Nob3dfYnVnLmNnaT9pZD0xMzY2ODgKKworICAgICAgICBSZXZp
ZXdlZCBieSBOT0JPRFkgKE9PUFMhKS4KKworICAgICAgICBUaGlzIHBhdGNoIGNyZWF0ZXMgYSBu
ZXcgZmlsZSBhbmQgbmV3IGZ1bmN0aW9uIHdoaWNoIHR1cm5zIGFuIFNWRyBmb250IGludG8gYW4g
T3BlblR5cGUgZm9udC4KKyAgICAgICAgVGhpcyBmdW5jdGlvbiBpcyBub3QgdmVyeSBmdWxsIGZl
YXR1cmVkLCBhbmQgYXMgc3VjaCBpcyBuZXZlciBjYWxsZWQuIEhvd2V2ZXIsIGl0IHdvcmtzIHdp
dGgKKyAgICAgICAgZm9udHMgdGhhdCBvbmx5IHN1cHBvcnQgc2ltcGxlIGhvcml6b250YWwgYmFz
aWMgbXVsdGlsaW5ndWFsIHBsYW5lIGNvZGVwb2ludHMuIEl0IGhhcyBvbmx5CisgICAgICAgIGJl
ZW4gdGVzdGVkIG9uIE9TIFgsIGFuZCBkb2VzIG5vdCBoYXZlIGFueSBhdXRvbWF0ZWQgdGVzdHMu
IFRoaXMgcGF0Y2ggaXMgb25seSBqdW1waW5nIG9mZgorICAgICAgICBwb2ludCwgbGF5aW5nIHRo
ZSBiYXNpYyBncm91bmR3b3JrIGZvciBhIG1vcmUgcm9idXN0IGZvbnQgY29udmVydGVyLgorCisg
ICAgICAgIFRoZSBnb2FsIG9mIHRoaXMgcGF0Y2ggaXMgdG8gZXZlbnR1YWxseSBhbGxvdyB1cyB0
byBkZWxldGUgdGhlIGNvZGVwYXRoIHdpdGggd2hpY2ggd2UgZHJhdworICAgICAgICB0ZXh0IHVz
aW5nIFNWRyBmb250cy4gVXNpbmcgYSBuYXRpdmUgY29kZXBhdGggaW5zdGVhZCB3aWxsIGFsbG93
IGZvciBiZXR0ZXIgcGVyZm9ybWFuY2UsCisgICAgICAgIHNlY3VyaXR5LCBhbmQgY29kZSBjbGFy
aXR5LiBJbiBteSBpbml0aWFsIGJlbmNobWFya3MsIHVzaW5nIHRoaXMgY29udmVydGVyIGluc3Rl
YWQgb2YgdGhlCisgICAgICAgIFNWRyBjb2RlcGF0aCBpcyBhdCBsZWFzdCBhIDEwMHggc3BlZWQg
aW1wcm92ZW1lbnQgKGFmdGVyIHJ1bm5pbmcgZm9yIDQgaG91cnMgSSBzdGVwcGVkCisgICAgICAg
IGF3YXkgZnJvbSBteSBtYWNoaW5lKS4KKworICAgICAgICBObyBuZXcgdGVzdHMgYmVjYXVzZSB0
aGUgZnVuY3Rpb24gaXMgbm90IHJlYWR5IHRvIGJlIGNhbGxlZCAoeWV0ISkKKworICAgICAgICAq
IFdlYkNvcmUueGNvZGVwcm9qL3Byb2plY3QucGJ4cHJvajogQWRkIG5ldyBmaWxlLgorICAgICAg
ICAqIHN2Zy9TVkdQYXRoQnVpbGRlci5oOiBTaW5nbGUgZnVuY3Rpb24uIFRha2VzIGEgU1ZHRm9u
dEVsZW1lbnQgYW5kIHJldHVybnMgYSBieXRlCisgICAgICAgIHJlcHJlc2VudGF0aW9uIG9mIHRo
ZSBPVEYgZm9udCAoaW4gYSBWZWN0b3I8Y2hhcj4pLgorICAgICAgICAqIHN2Zy9TVkdUb09URkZv
bnRDb252ZXJzaW9uLmNwcDogQWRkZWQuCisgICAgICAgIChXZWJDb3JlOjp3cml0ZVVJbnQzMik6
IFdyaXRlIGEgYmlnLWVuZGlhbiBJbnQzMi4KKyAgICAgICAgKFdlYkNvcmU6OndyaXRlVUludDE2
KTogV3JpdGUgYSBiaWctZW5kaWFuIEludDE2LgorICAgICAgICAoV2ViQ29yZTo6b3ZlcndyaXRl
VUludDMyKTogT3ZlcndyaXRlIGFuIGV4aXN0aW5nIEludDMyIGluIGEgdmVjdG9yIChpbnN0ZWFk
IG9mIGFwcGVuZGluZykKKyAgICAgICAgKFdlYkNvcmU6OndyaXRlSW50MTYpOiBTaWduZWQgdmVy
c2lvbiBvZiB3cml0ZVVJbnQxNi4KKyAgICAgICAgKFdlYkNvcmU6OlNWR1RvT1RGRm9udENvbnZl
cnRlcjo6R2x5cGhEYXRhOjpHbHlwaERhdGEpOiBJbnRlcm5hbCBjbGFzcyB0byBob2xkIHN0YXRl
IGR1cmluZworICAgICAgICBmdW5jdGlvbiBjYWxscy4KKyAgICAgICAgKFdlYkNvcmU6OnJvdW5k
RG93blRvUG93ZXJPZlR3byk6CisgICAgICAgIChXZWJDb3JlOjpTVkdUb09URkZvbnRDb252ZXJ0
ZXI6OmNyZWF0ZUNNQVBUYWJsZSk6IFNlZSBmdW5jdGlvbiBuYW1lLgorICAgICAgICAoV2ViQ29y
ZTo6U1ZHVG9PVEZGb250Q29udmVydGVyOjpjcmVhdGVIRUFEVGFibGUpOiBEaXR0by4KKyAgICAg
ICAgKFdlYkNvcmU6OmNsYW1wRmxvYXRUbyk6IFVzZWQgdG8gY2xhbXAgZmxvYXRzIHRvIGZpdCBp
bnRvIHBhcnRpY3VsYXIgZGF0YSB0eXBlcy4KKyAgICAgICAgKFdlYkNvcmU6OlNWR1RvT1RGRm9u
dENvbnZlcnRlcjo6Y3JlYXRlSEhFQVRhYmxlKTogU2VlIGZ1bmN0aW9uIG5hbWUuCisgICAgICAg
IChXZWJDb3JlOjpTVkdUb09URkZvbnRDb252ZXJ0ZXI6OmNyZWF0ZUhNVFhUYWJsZSk6IERpdHRv
LgorICAgICAgICAoV2ViQ29yZTo6U1ZHVG9PVEZGb250Q29udmVydGVyOjpjcmVhdGVNQVhQVGFi
bGUpOiBEaXR0by4KKyAgICAgICAgKFdlYkNvcmU6OlNWR1RvT1RGRm9udENvbnZlcnRlcjo6Y3Jl
YXRlTkFNRVRhYmxlKTogRGl0dG8uCisgICAgICAgIChXZWJDb3JlOjpTVkdUb09URkZvbnRDb252
ZXJ0ZXI6OmNyZWF0ZU9TMlRhYmxlKTogRGl0dG8uCisgICAgICAgIChXZWJDb3JlOjpTVkdUb09U
RkZvbnRDb252ZXJ0ZXI6OmNyZWF0ZVBPU1RUYWJsZSk6IERpdHRvLgorICAgICAgICAoV2ViQ29y
ZTo6aXNWYWxpZFN0cmluZ0ZvckNGRik6IFRoZSBDRkYgZm9udCBmb3JtYXQgb25seSBhbGxvd3Mg
c3RyaW5ncyB3aXRoIHBhcnRpY3VsYXIKKyAgICAgICAgY2hhcmFjdGVycyBpbiB0aGVtLgorICAg
ICAgICAoV2ViQ29yZTo6U1ZHVG9PVEZGb250Q29udmVydGVyOjpjcmVhdGVDRkZUYWJsZSk6IFNl
ZSBmdW5jdGlvbiBuYW1lLgorICAgICAgICAoV2ViQ29yZTo6U1ZHVG9PVEZGb250Q29udmVydGVy
OjpjcmVhdGVWT1JHVGFibGUpOiBTZWUgZnVuY3Rpb24gbmFtZS4KKyAgICAgICAgKFdlYkNvcmU6
OndyaXRlQ0ZGRW5jb2RlZE51bWJlcik6IENGRiBoYXMgdGhpcyB3YWNreSBlbmNvZGluZyBzY2hl
bWUgZm9yIGVuY29kaW5nIGFuZAorICAgICAgICBkZWNvZGluZyBudW1iZXJzLgorICAgICAgICAo
V2ViQ29yZTo6Q0ZGQnVpbGRlcjo6Q0ZGQnVpbGRlcik6IFN1YmNsYXNzIG9mIFNWR1BhdGhCdWls
ZGVyLCB3aGljaCBpcyB1c2VkIGZvciBidWlsZGluZworICAgICAgICBDRkYgQ2hhclN0cmluZ3Mg
KHdoaWNoIGFyZSBnbHlwaCBwYXRoIHJlcHJlc2VudGF0aW9ucykuCisgICAgICAgIChXZWJDb3Jl
OjpDRkZCdWlsZGVyOjp1cGRhdGVGb3JDb25zdGl0dWVudFBvaW50KTogSW52b2tlZCBmb3IgZXZl
cnkgcG9pbnQgaW4gYSBwYXRoLCBkb2VzCisgICAgICAgIHRoaW5ncyBsaWtlIHVwZGF0ZXMgZ2x5
cGggYm91bmRpbmcgYm94IGluZm9ybWF0aW9uLgorICAgICAgICAoV2ViQ29yZTo6Q0ZGQnVpbGRl
cjo6Ym91bmRpbmdCb3gpOiBHZXR0ZXIuCisgICAgICAgIChXZWJDb3JlOjp0cmFuc2NvZGVHbHlw
aFBhdGhzKTogU1ZHIHBhdGggZGF0YSBzdHJpbmcgLT4gQ0ZGIENoYXJTdHJpbmcKKyAgICAgICAg
KFdlYkNvcmU6OlNWR1RvT1RGRm9udENvbnZlcnRlcjo6Y29tcGFyZUdseXBoRGF0YSk6IFVzZWQg
Zm9yIHNvcnRpbmcgZ2x5cGhzICh0aGUgQ01BUAorICAgICAgICB0YWJsZSBtdXN0IGJlIHNvcnRl
ZCkuCisgICAgICAgIChXZWJDb3JlOjpTVkdUb09URkZvbnRDb252ZXJ0ZXI6OlNWR1RvT1RGRm9u
dENvbnZlcnRlcik6IEdlbmVyYXRlIGludGVybmFsIHN0YXRlIGFoZWFkIG9mCisgICAgICAgIHRp
bWUgYmVmb3JlIGdlbmVyYXRpbmcgYW55IHRhYmxlcy4KKyAgICAgICAgKFdlYkNvcmU6OmNhbGN1
bGF0ZUNoZWNrc3VtKTogT1RGIGZpbGVzIGhhdmUgY2hlY2tzdW1zLgorICAgICAgICAoV2ViQ29y
ZTo6YXBwZW5kVGFibGVEaXJlY3RvcnlFbnRyeSk6IEludm9rZWQgZm9yIGVhY2ggZW50cnkgaW4g
dGhlIHRhYmxlIG9mIGNvbnRlbnRzIG9mCisgICAgICAgIHRoZSBPVEYgZm9udC4KKyAgICAgICAg
KFdlYkNvcmU6OlNWR1RvT1RGRm9udENvbnZlcnRlcjo6Y29udmVydFNWR1RvT1RGRm9udCk6IFdy
aXRlIG91dCB0aGUgdGFibGVzLgorICAgICAgICAoV2ViQ29yZTo6Y29udmVydFNWR1RvT1RGRm9u
dCk6IEVudHJ5IHBvaW50LgorICAgICAgICAqIHN2Zy9TVkdUb09URkZvbnRDb252ZXJzaW9uLmg6
IEFkZGVkLgorCiAyMDE0LTA5LTA4ICBNeWxlcyBDLiBNYXhmaWVsZCAgPG1tYXhmaWVsZEBhcHBs
ZS5jb20+CiAKICAgICAgICAgUkVHUkVTU0lPTiAocjE3MjE1Myk6IFRleHQgZHJhd24gd2l0aCB3
cm9uZyBjb2xvciB3aGVuIHNlY29uZCB0ZXh0IHNoYWRvdyBoYXMgemVybyBvZmZzZXQgYW5kIGJs
dXIgKGJyZWFrcyBidXR0b25zIGF0IGF3cy5hbWF6b24uY29tKQpkaWZmIC0tZ2l0IGEvU291cmNl
L1dlYkNvcmUvV2ViQ29yZS54Y29kZXByb2ovcHJvamVjdC5wYnhwcm9qIGIvU291cmNlL1dlYkNv
cmUvV2ViQ29yZS54Y29kZXByb2ovcHJvamVjdC5wYnhwcm9qCmluZGV4IGZhMzUzNjU2MmUxMmEy
MDYyYWVmNGU0NGZiNzc2ODdmMTQyYjM0OGIuLjNmOTZjOWVmMzAwZjhmZGRjZWJiMWUwOTJjNjRj
YzIwZjFlZmUzZDMgMTAwNjQ0Ci0tLSBhL1NvdXJjZS9XZWJDb3JlL1dlYkNvcmUueGNvZGVwcm9q
L3Byb2plY3QucGJ4cHJvagorKysgYi9Tb3VyY2UvV2ViQ29yZS9XZWJDb3JlLnhjb2RlcHJvai9w
cm9qZWN0LnBieHByb2oKQEAgLTk1Miw2ICs5NTIsOCBAQAogCQkxQ0I0MjE0QzBBRjJCMkNBMDA4
NUFEOTEgLyogRE9NSFRNTEVsZW1lbnRJbnRlcm5hbC5oIGluIENvcHkgR2VuZXJhdGVkIEhlYWRl
cnMgKi8gPSB7aXNhID0gUEJYQnVpbGRGaWxlOyBmaWxlUmVmID0gODVFNzExNTgwQUM1RDUzNDAw
NTMyNzBGIC8qIERPTUhUTUxFbGVtZW50SW50ZXJuYWwuaCAqLzsgfTsKIAkJMUNCNDIxNEQwQUYy
QjJDQTAwODVBRDkxIC8qIERPTVJhbmdlSW50ZXJuYWwuaCBpbiBDb3B5IEdlbmVyYXRlZCBIZWFk
ZXJzICovID0ge2lzYSA9IFBCWEJ1aWxkRmlsZTsgZmlsZVJlZiA9IDg1MzhGMDVBMEFENzIyRjEw
MDZBODFEMSAvKiBET01SYW5nZUludGVybmFsLmggKi87IH07CiAJCTFDQ0E3MzIyMTBBREQ0NEEw
MEZENDQwRCAvKiBET01IVE1MSW5wdXRFbGVtZW50UHJpdmF0ZS5oIGluIENvcHkgR2VuZXJhdGVk
IEhlYWRlcnMgKi8gPSB7aXNhID0gUEJYQnVpbGRGaWxlOyBmaWxlUmVmID0gMUNDQTczMjExMEFE
RDQzRTAwRkQ0NDBEIC8qIERPTUhUTUxJbnB1dEVsZW1lbnRQcml2YXRlLmggKi87IH07CisJCTFD
Q0RGNUJEMTk5MDMzMjQwMEJDRUJBRCAvKiBTVkdUb09URkZvbnRDb252ZXJzaW9uLmNwcCBpbiBT
b3VyY2VzICovID0ge2lzYSA9IFBCWEJ1aWxkRmlsZTsgZmlsZVJlZiA9IDFDQ0RGNUJCMTk5MDMz
MjQwMEJDRUJBRCAvKiBTVkdUb09URkZvbnRDb252ZXJzaW9uLmNwcCAqLzsgfTsKKwkJMUNDREY1
QkUxOTkwMzMyNDAwQkNFQkFEIC8qIFNWR1RvT1RGRm9udENvbnZlcnNpb24uaCBpbiBIZWFkZXJz
ICovID0ge2lzYSA9IFBCWEJ1aWxkRmlsZTsgZmlsZVJlZiA9IDFDQ0RGNUJDMTk5MDMzMjQwMEJD
RUJBRCAvKiBTVkdUb09URkZvbnRDb252ZXJzaW9uLmggKi87IH07CiAJCTFDRTgzQUMzMEFEQUZG
RDcwMDkzNTRGNiAvKiBEZWxldGVCdXR0b25Db250cm9sbGVyLmNwcCBpbiBTb3VyY2VzICovID0g
e2lzYSA9IFBCWEJ1aWxkRmlsZTsgZmlsZVJlZiA9IDFDNEM4RUZGMEFEODVEODcwMDk0NzVDRSAv
KiBEZWxldGVCdXR0b25Db250cm9sbGVyLmNwcCAqLzsgfTsKIAkJMUNFODNBQzQwQURBRkZEODAw
OTM1NEY2IC8qIERlbGV0ZUJ1dHRvbi5jcHAgaW4gU291cmNlcyAqLyA9IHtpc2EgPSBQQlhCdWls
ZEZpbGU7IGZpbGVSZWYgPSAxQzRDOEY2MzBBRDg2NTVEMDA5NDc1Q0UgLyogRGVsZXRlQnV0dG9u
LmNwcCAqLzsgfTsKIAkJMUNGNkJERkEwRTlCQjI2QTAwMjVFMUNEIC8qIE9iakNFdmVudExpc3Rl
bmVyLmggaW4gSGVhZGVycyAqLyA9IHtpc2EgPSBQQlhCdWlsZEZpbGU7IGZpbGVSZWYgPSAxQ0Y2
QkRGODBFOUJCMjZBMDAyNUUxQ0QgLyogT2JqQ0V2ZW50TGlzdGVuZXIuaCAqLzsgfTsKQEAgLTc4
OTcsNiArNzg5OSw4IEBACiAJCTFDQUYzNDdGMEE2QzQwNTIwMEFCRTA2RSAvKiBXZWJTY3JpcHRP
YmplY3QubW0gKi8gPSB7aXNhID0gUEJYRmlsZVJlZmVyZW5jZTsgZmlsZUVuY29kaW5nID0gNDsg
bGFzdEtub3duRmlsZVR5cGUgPSBzb3VyY2Vjb2RlLmNwcC5vYmpjcHA7IHBhdGggPSBXZWJTY3Jp
cHRPYmplY3QubW07IHNvdXJjZVRyZWUgPSAiPGdyb3VwPiI7IH07CiAJCTFDQUYzNDgwMEE2QzQw
NTIwMEFCRTA2RSAvKiBXZWJTY3JpcHRPYmplY3RQcml2YXRlLmggKi8gPSB7aXNhID0gUEJYRmls
ZVJlZmVyZW5jZTsgZmlsZUVuY29kaW5nID0gNDsgbGFzdEtub3duRmlsZVR5cGUgPSBzb3VyY2Vj
b2RlLmMuaDsgcGF0aCA9IFdlYlNjcmlwdE9iamVjdFByaXZhdGUuaDsgc291cmNlVHJlZSA9ICI8
Z3JvdXA+IjsgfTsKIAkJMUNDQTczMjExMEFERDQzRTAwRkQ0NDBEIC8qIERPTUhUTUxJbnB1dEVs
ZW1lbnRQcml2YXRlLmggKi8gPSB7aXNhID0gUEJYRmlsZVJlZmVyZW5jZTsgZmlsZUVuY29kaW5n
ID0gNDsgbGFzdEtub3duRmlsZVR5cGUgPSBzb3VyY2Vjb2RlLmMuaDsgcGF0aCA9IERPTUhUTUxJ
bnB1dEVsZW1lbnRQcml2YXRlLmg7IHNvdXJjZVRyZWUgPSAiPGdyb3VwPiI7IH07CisJCTFDQ0RG
NUJCMTk5MDMzMjQwMEJDRUJBRCAvKiBTVkdUb09URkZvbnRDb252ZXJzaW9uLmNwcCAqLyA9IHtp
c2EgPSBQQlhGaWxlUmVmZXJlbmNlOyBmaWxlRW5jb2RpbmcgPSA0OyBsYXN0S25vd25GaWxlVHlw
ZSA9IHNvdXJjZWNvZGUuY3BwLmNwcDsgcGF0aCA9IFNWR1RvT1RGRm9udENvbnZlcnNpb24uY3Bw
OyBzb3VyY2VUcmVlID0gIjxncm91cD4iOyB9OworCQkxQ0NERjVCQzE5OTAzMzI0MDBCQ0VCQUQg
LyogU1ZHVG9PVEZGb250Q29udmVyc2lvbi5oICovID0ge2lzYSA9IFBCWEZpbGVSZWZlcmVuY2U7
IGZpbGVFbmNvZGluZyA9IDQ7IGxhc3RLbm93bkZpbGVUeXBlID0gc291cmNlY29kZS5jLmg7IHBh
dGggPSBTVkdUb09URkZvbnRDb252ZXJzaW9uLmg7IHNvdXJjZVRyZWUgPSAiPGdyb3VwPiI7IH07
CiAJCTFDRDBCNjIwMEFBQkRCNTAwMEQwQTNGRiAvKiBQdWJsaWNET01JbnRlcmZhY2VzLmggKi8g
PSB7aXNhID0gUEJYRmlsZVJlZmVyZW5jZTsgZmlsZUVuY29kaW5nID0gNDsgbGFzdEtub3duRmls
ZVR5cGUgPSBzb3VyY2Vjb2RlLmMuaDsgcGF0aCA9IFB1YmxpY0RPTUludGVyZmFjZXMuaDsgc291
cmNlVHJlZSA9ICI8Z3JvdXA+IjsgfTsKIAkJMUNERDQ1RTQwQkE5Qzg0NjAwRjkwMTQ3IC8qIERl
YnVnUmVsZWFzZS54Y2NvbmZpZyAqLyA9IHtpc2EgPSBQQlhGaWxlUmVmZXJlbmNlOyBmaWxlRW5j
b2RpbmcgPSA0OyBsYXN0S25vd25GaWxlVHlwZSA9IHRleHQueGNjb25maWc7IHBhdGggPSBEZWJ1
Z1JlbGVhc2UueGNjb25maWc7IHNvdXJjZVRyZWUgPSAiPGdyb3VwPiI7IH07CiAJCTFDREQ0NUU1
MEJBOUM4NDYwMEY5MDE0NyAvKiBXZWJDb3JlLnhjY29uZmlnICovID0ge2lzYSA9IFBCWEZpbGVS
ZWZlcmVuY2U7IGZpbGVFbmNvZGluZyA9IDQ7IGxhc3RLbm93bkZpbGVUeXBlID0gdGV4dC54Y2Nv
bmZpZzsgcGF0aCA9IFdlYkNvcmUueGNjb25maWc7IHNvdXJjZVRyZWUgPSAiPGdyb3VwPiI7IH07
CkBAIC0yMDE3Miw2ICsyMDE3Niw4IEBACiAJCQkJQjJFNEVDOTUwRDAwQzIyQjAwNDMyNjQzIC8q
IFNWR1pvb21FdmVudC5oICovLAogCQkJCUIyRTRFQzk2MEQwMEMyMkIwMDQzMjY0MyAvKiBTVkda
b29tRXZlbnQuaWRsICovLAogCQkJCUIyOEM2QTI2MEQwMEM0NDgwMDMzNEFBNCAvKiB4bGlua2F0
dHJzLmluICovLAorCQkJCTFDQ0RGNUJCMTk5MDMzMjQwMEJDRUJBRCAvKiBTVkdUb09URkZvbnRD
b252ZXJzaW9uLmNwcCAqLywKKwkJCQkxQ0NERjVCQzE5OTAzMzI0MDBCQ0VCQUQgLyogU1ZHVG9P
VEZGb250Q29udmVyc2lvbi5oICovLAogCQkJKTsKIAkJCXBhdGggPSBzdmc7CiAJCQlzb3VyY2VU
cmVlID0gIjxncm91cD4iOwpAQCAtMjQ5NzUsNiArMjQ5ODEsNyBAQAogCQkJCUIyRkEzRDk3MEFC
NzVBNkYwMDBFNUFDNCAvKiBKU1NWR0ZpbHRlckVsZW1lbnQuaCBpbiBIZWFkZXJzICovLAogCQkJ
CUIyN0IyODI2MENFRjBDMDcwMEQzOUQ1NCAvKiBKU1NWR0ZvbnRFbGVtZW50LmggaW4gSGVhZGVy
cyAqLywKIAkJCQlBODNCNzkwNTBDQ0FGRjE1MDAwQjA4MjUgLyogSlNTVkdGb250RmFjZUVsZW1l
bnQuaCBpbiBIZWFkZXJzICovLAorCQkJCTFDQ0RGNUJFMTk5MDMzMjQwMEJDRUJBRCAvKiBTVkdU
b09URkZvbnRDb252ZXJzaW9uLmggaW4gSGVhZGVycyAqLywKIAkJCQlBODNCNzkwMDBDQ0FGRjE1
MDAwQjA4MjUgLyogSlNTVkdGb250RmFjZUZvcm1hdEVsZW1lbnQuaCBpbiBIZWFkZXJzICovLAog
CQkJCUE4M0I3OTAyMENDQUZGMTUwMDBCMDgyNSAvKiBKU1NWR0ZvbnRGYWNlTmFtZUVsZW1lbnQu
aCBpbiBIZWFkZXJzICovLAogCQkJCUE4M0I3OEZFMENDQUZGMTUwMDBCMDgyNSAvKiBKU1NWR0Zv
bnRGYWNlU3JjRWxlbWVudC5oIGluIEhlYWRlcnMgKi8sCkBAIC0yNjk4MCw2ICsyNjk4Nyw3IEBA
CiAJCQkJRkQ1Njg2QzkxM0FDMTgwMjAwQjY5QzY4IC8qIEFzeW5jQXVkaW9EZWNvZGVyLmNwcCBp
biBTb3VyY2VzICovLAogCQkJCUUxQ0RFOTIwMTUwMThFRDAwMDg2MkNDNSAvKiBBc3luY0ZpbGVT
dHJlYW0uY3BwIGluIFNvdXJjZXMgKi8sCiAJCQkJMEZGRDRENjAxODY1MUZBMzAwNTEyRjZFIC8q
IEFzeW5jU2Nyb2xsaW5nQ29vcmRpbmF0b3IuY3BwIGluIFNvdXJjZXMgKi8sCisJCQkJMUNDREY1
QkQxOTkwMzMyNDAwQkNFQkFEIC8qIFNWR1RvT1RGRm9udENvbnZlcnNpb24uY3BwIGluIFNvdXJj
ZXMgKi8sCiAJCQkJQThDNEE4MEUwOUQ1NjMyNzAwMDNBQzhEIC8qIEF0dHIuY3BwIGluIFNvdXJj
ZXMgKi8sCiAJCQkJRkQ2MjlFQTQxNTRCNDcxNjAwMDZEMDI2IC8qIEF1ZGlvQmFzaWNJbnNwZWN0
b3JOb2RlLmNwcCBpbiBTb3VyY2VzICovLAogCQkJCUZEMzE1RkY2MTJCMDI2NzYwMEMxQTM1OSAv
KiBBdWRpb0Jhc2ljUHJvY2Vzc29yTm9kZS5jcHAgaW4gU291cmNlcyAqLywKZGlmZiAtLWdpdCBh
L1NvdXJjZS9XZWJDb3JlL3N2Zy9TVkdQYXRoQnVpbGRlci5oIGIvU291cmNlL1dlYkNvcmUvc3Zn
L1NWR1BhdGhCdWlsZGVyLmgKaW5kZXggMjYyNzUzNjU4ZTIxNDI0NWJmZmRmMjBhM2NhM2YzOWE5
NDEwN2FhMS4uZWExNWIzZWJmNDViNDUyZmExZjZkZDIwODA5NzQwYmRhY2YwYjc0NCAxMDA2NDQK
LS0tIGEvU291cmNlL1dlYkNvcmUvc3ZnL1NWR1BhdGhCdWlsZGVyLmgKKysrIGIvU291cmNlL1dl
YkNvcmUvc3ZnL1NWR1BhdGhCdWlsZGVyLmgKQEAgLTM3LDYgKzM3LDkgQEAgcHVibGljOgogCiAg
ICAgdm9pZCBzZXRDdXJyZW50UGF0aChQYXRoKiBwYXRoKSB7IG1fcGF0aCA9IHBhdGg7IH0KIAor
cHJvdGVjdGVkOgorICAgIEZsb2F0UG9pbnQgbV9jdXJyZW50OworCiBwcml2YXRlOgogICAgIHZp
cnR1YWwgdm9pZCBpbmNyZW1lbnRQYXRoU2VnbWVudENvdW50KCkgb3ZlcnJpZGUgeyB9CiAgICAg
dmlydHVhbCBib29sIGNvbnRpbnVlQ29uc3VtaW5nKCkgb3ZlcnJpZGUgeyByZXR1cm4gdHJ1ZTsg
fQpAQCAtNTcsNyArNjAsNiBAQCBwcml2YXRlOgogICAgIHZpcnR1YWwgdm9pZCBhcmNUbyhmbG9h
dCwgZmxvYXQsIGZsb2F0LCBib29sLCBib29sLCBjb25zdCBGbG9hdFBvaW50JiwgUGF0aENvb3Jk
aW5hdGVNb2RlKSBvdmVycmlkZSB7IEFTU0VSVF9OT1RfUkVBQ0hFRCgpOyB9CiAKICAgICBQYXRo
KiBtX3BhdGg7Ci0gICAgRmxvYXRQb2ludCBtX2N1cnJlbnQ7CiB9OwogCiB9IC8vIG5hbWVzcGFj
ZSBXZWJDb3JlCmRpZmYgLS1naXQgYS9Tb3VyY2UvV2ViQ29yZS9zdmcvU1ZHVG9PVEZGb250Q29u
dmVyc2lvbi5jcHAgYi9Tb3VyY2UvV2ViQ29yZS9zdmcvU1ZHVG9PVEZGb250Q29udmVyc2lvbi5j
cHAKbmV3IGZpbGUgbW9kZSAxMDA2NDQKaW5kZXggMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw
MDAwMDAwMDAwMDAwMC4uNDI5N2Q2NzhiYWNhYWFhOGM3MGQzMjJiYzYxZWM3Yjk1NGRkMmZmNQot
LS0gL2Rldi9udWxsCisrKyBiL1NvdXJjZS9XZWJDb3JlL3N2Zy9TVkdUb09URkZvbnRDb252ZXJz
aW9uLmNwcApAQCAtMCwwICsxLDg1MiBAQAorLyoKKyAqIENvcHlyaWdodCAoQykgMjAxMCBBcHBs
ZSBJbmMuIEFsbCByaWdodHMgcmVzZXJ2ZWQuCisgKgorICogUmVkaXN0cmlidXRpb24gYW5kIHVz
ZSBpbiBzb3VyY2UgYW5kIGJpbmFyeSBmb3Jtcywgd2l0aCBvciB3aXRob3V0CisgKiBtb2RpZmlj
YXRpb24sIGFyZSBwZXJtaXR0ZWQgcHJvdmlkZWQgdGhhdCB0aGUgZm9sbG93aW5nIGNvbmRpdGlv
bnMKKyAqIGFyZSBtZXQ6CisgKiAxLiBSZWRpc3RyaWJ1dGlvbnMgb2Ygc291cmNlIGNvZGUgbXVz
dCByZXRhaW4gdGhlIGFib3ZlIGNvcHlyaWdodAorICogICAgbm90aWNlLCB0aGlzIGxpc3Qgb2Yg
Y29uZGl0aW9ucyBhbmQgdGhlIGZvbGxvd2luZyBkaXNjbGFpbWVyLgorICogMi4gUmVkaXN0cmli
dXRpb25zIGluIGJpbmFyeSBmb3JtIG11c3QgcmVwcm9kdWNlIHRoZSBhYm92ZSBjb3B5cmlnaHQK
KyAqICAgIG5vdGljZSwgdGhpcyBsaXN0IG9mIGNvbmRpdGlvbnMgYW5kIHRoZSBmb2xsb3dpbmcg
ZGlzY2xhaW1lciBpbiB0aGUKKyAqICAgIGRvY3VtZW50YXRpb24gYW5kL29yIG90aGVyIG1hdGVy
aWFscyBwcm92aWRlZCB3aXRoIHRoZSBkaXN0cmlidXRpb24uCisgKgorICogVEhJUyBTT0ZUV0FS
RSBJUyBQUk9WSURFRCBCWSBBUFBMRSBJTkMuIEFORCBJVFMgQ09OVFJJQlVUT1JTIGBgQVMgSVMn
JworICogQU5EIEFOWSBFWFBSRVNTIE9SIElNUExJRUQgV0FSUkFOVElFUywgSU5DTFVESU5HLCBC
VVQgTk9UIExJTUlURUQgVE8sCisgKiBUSEUgSU1QTElFRCBXQVJSQU5USUVTIE9GIE1FUkNIQU5U
QUJJTElUWSBBTkQgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSCisgKiBQVVJQT1NFIEFSRSBESVND
TEFJTUVELiBJTiBOTyBFVkVOVCBTSEFMTCBBUFBMRSBJTkMuIE9SIElUUyBDT05UUklCVVRPUlMK
KyAqIEJFIExJQUJMRSBGT1IgQU5ZIERJUkVDVCwgSU5ESVJFQ1QsIElOQ0lERU5UQUwsIFNQRUNJ
QUwsIEVYRU1QTEFSWSwgT1IKKyAqIENPTlNFUVVFTlRJQUwgREFNQUdFUyAoSU5DTFVESU5HLCBC
VVQgTk9UIExJTUlURUQgVE8sIFBST0NVUkVNRU5UIE9GCisgKiBTVUJTVElUVVRFIEdPT0RTIE9S
IFNFUlZJQ0VTOyBMT1NTIE9GIFVTRSwgREFUQSwgT1IgUFJPRklUUzsgT1IgQlVTSU5FU1MKKyAq
IElOVEVSUlVQVElPTikgSE9XRVZFUiBDQVVTRUQgQU5EIE9OIEFOWSBUSEVPUlkgT0YgTElBQklM
SVRZLCBXSEVUSEVSIElOCisgKiBDT05UUkFDVCwgU1RSSUNUIExJQUJJTElUWSwgT1IgVE9SVCAo
SU5DTFVESU5HIE5FR0xJR0VOQ0UgT1IgT1RIRVJXSVNFKQorICogQVJJU0lORyBJTiBBTlkgV0FZ
IE9VVCBPRiBUSEUgVVNFIE9GIFRISVMgU09GVFdBUkUsIEVWRU4gSUYgQURWSVNFRCBPRgorICog
VEhFIFBPU1NJQklMSVRZIE9GIFNVQ0ggREFNQUdFLgorICovCisKKyNpbmNsdWRlICJjb25maWcu
aCIKKyNpbmNsdWRlICJTVkdUb09URkZvbnRDb252ZXJzaW9uLmgiCisKKyNpbmNsdWRlICJDU1NT
dHlsZURlY2xhcmF0aW9uLmgiCisjaW5jbHVkZSAiRWxlbWVudENoaWxkSXRlcmF0b3IuaCIKKyNp
bmNsdWRlICJTVkdGb250RWxlbWVudC5oIgorI2luY2x1ZGUgIlNWR0ZvbnRGYWNlRWxlbWVudC5o
IgorI2luY2x1ZGUgIlNWR0dseXBoRWxlbWVudC5oIgorI2luY2x1ZGUgIlNWR1BhdGhCdWlsZGVy
LmgiCisjaW5jbHVkZSAiU1ZHUGF0aFBhcnNlci5oIgorI2luY2x1ZGUgIlNWR1BhdGhTdHJpbmdT
b3VyY2UuaCIKKworbmFtZXNwYWNlIFdlYkNvcmUgeworCitzdGF0aWMgaW5saW5lIHZvaWQgd3Jp
dGVVSW50MzIoVmVjdG9yPGNoYXI+JiB2ZWN0b3IsIHVpbnQzMl90IHZhbHVlKQoreworICAgIHVp
bnQzMl90IGJpZ0VuZGlhblZhbHVlID0gaHRvbmwodmFsdWUpOworICAgIHZlY3Rvci5hcHBlbmQo
cmVpbnRlcnByZXRfY2FzdF9wdHI8Y2hhcio+KCZiaWdFbmRpYW5WYWx1ZSksIHNpemVvZihiaWdF
bmRpYW5WYWx1ZSkpOworfQorCitzdGF0aWMgaW5saW5lIHZvaWQgd3JpdGVVSW50MTYoVmVjdG9y
PGNoYXI+JiB2ZWN0b3IsIHVpbnQxNl90IHZhbHVlKQoreworICAgIHVpbnQxNl90IGJpZ0VuZGlh
blZhbHVlID0gaHRvbnModmFsdWUpOworICAgIHZlY3Rvci5hcHBlbmQocmVpbnRlcnByZXRfY2Fz
dF9wdHI8Y2hhcio+KCZiaWdFbmRpYW5WYWx1ZSksIHNpemVvZihiaWdFbmRpYW5WYWx1ZSkpOwor
fQorCitzdGF0aWMgaW5saW5lIHZvaWQgb3ZlcndyaXRlVUludDMyKFZlY3RvcjxjaGFyPiYgdmVj
dG9yLCB1bnNpZ25lZCBsb2NhdGlvbiwgdWludDMyX3QgdmFsdWUpCit7CisgICAgQVNTRVJUKHZl
Y3Rvci5zaXplKCkgPj0gbG9jYXRpb24gKyA0KTsKKyAgICAvLyBVc2UgdW5zaWduZWQgY2hhcnMg
dG8gYXZvaWQgd3JhcGFyb3VuZCBwcm9ibGVtcworICAgIHVuc2lnbmVkIGNoYXIqIHB0ciA9IHJl
aW50ZXJwcmV0X2Nhc3RfcHRyPHVuc2lnbmVkIGNoYXIqPih2ZWN0b3IuZGF0YSgpICsgbG9jYXRp
b24pOworICAgICoocHRyKyspID0gc3RhdGljX2Nhc3Q8dW5zaWduZWQgY2hhcj4odmFsdWUgPj4g
MjQpOworICAgICoocHRyKyspID0gc3RhdGljX2Nhc3Q8dW5zaWduZWQgY2hhcj4odmFsdWUgPj4g
MTYpOworICAgICoocHRyKyspID0gc3RhdGljX2Nhc3Q8dW5zaWduZWQgY2hhcj4odmFsdWUgPj4g
OCk7CisgICAgKihwdHIrKykgPSBzdGF0aWNfY2FzdDx1bnNpZ25lZCBjaGFyPih2YWx1ZSA+PiAw
KTsKK30KKworc3RhdGljIGlubGluZSB2b2lkIHdyaXRlSW50MTYoVmVjdG9yPGNoYXI+JiB2ZWN0
b3IsIGludDE2X3QgdmFsdWUpCit7CisgICAgd3JpdGVVSW50MTYodmVjdG9yLCB2YWx1ZSk7Cit9
CisKK2NsYXNzIFNWR1RvT1RGRm9udENvbnZlcnRlciB7CitwdWJsaWM6CisgICAgU1ZHVG9PVEZG
b250Q29udmVydGVyKGNvbnN0IFNWR0ZvbnRFbGVtZW50Jik7CisgICAgVmVjdG9yPGNoYXI+IGNv
bnZlcnRTVkdUb09URkZvbnQoKTsKKworcHJpdmF0ZToKKyAgICB0eXBlZGVmIHVpbnQxNl90IFNJ
RDsgLy8gU3RyaW5nIElECisgICAgc3RydWN0IEdseXBoRGF0YSB7CisgICAgICAgIEdseXBoRGF0
YShWZWN0b3I8Y2hhcj4gY2hhclN0cmluZywgY29uc3QgU1ZHR2x5cGhFbGVtZW50KiBnbHlwaEVs
ZW1lbnQsIGZsb2F0IGFkdmFuY2UsIEZsb2F0UmVjdCBib3VuZGluZ0JveCwgdWludDE2X3QgY29k
ZXBvaW50KQorICAgICAgICAgICAgOiBib3VuZGluZ0JveChib3VuZGluZ0JveCkKKyAgICAgICAg
ICAgICwgY2hhclN0cmluZyhjaGFyU3RyaW5nKQorICAgICAgICAgICAgLCBnbHlwaEVsZW1lbnQo
Z2x5cGhFbGVtZW50KQorICAgICAgICAgICAgLCBhZHZhbmNlKGFkdmFuY2UpCisgICAgICAgICAg
ICAsIGNvZGVwb2ludChjb2RlcG9pbnQpCisgICAgICAgIHsKKyAgICAgICAgfQorICAgICAgICBG
bG9hdFJlY3QgYm91bmRpbmdCb3g7CisgICAgICAgIFZlY3RvcjxjaGFyPiBjaGFyU3RyaW5nOwor
ICAgICAgICBjb25zdCBTVkdHbHlwaEVsZW1lbnQqIGdseXBoRWxlbWVudDsKKyAgICAgICAgZmxv
YXQgYWR2YW5jZTsKKyAgICAgICAgdWludDE2X3QgY29kZXBvaW50OworICAgIH07CisKKyAgICBW
ZWN0b3I8Y2hhcj4gY3JlYXRlQ01BUFRhYmxlKCk7CisgICAgVmVjdG9yPGNoYXI+IGNyZWF0ZUhF
QURUYWJsZSgpOworICAgIFZlY3RvcjxjaGFyPiBjcmVhdGVISEVBVGFibGUoKTsKKyAgICBWZWN0
b3I8Y2hhcj4gY3JlYXRlSE1UWFRhYmxlKCk7CisgICAgVmVjdG9yPGNoYXI+IGNyZWF0ZU1BWFBU
YWJsZSgpOworICAgIFZlY3RvcjxjaGFyPiBjcmVhdGVOQU1FVGFibGUoKTsKKyAgICBWZWN0b3I8
Y2hhcj4gY3JlYXRlT1MyVGFibGUoKTsKKyAgICBWZWN0b3I8Y2hhcj4gY3JlYXRlUE9TVFRhYmxl
KCk7CisgICAgVmVjdG9yPGNoYXI+IGNyZWF0ZUNGRlRhYmxlKCk7CisgICAgVmVjdG9yPGNoYXI+
IGNyZWF0ZVZPUkdUYWJsZSgpOworCisgICAgc3RhdGljIGJvb2wgY29tcGFyZUdseXBoRGF0YShj
b25zdCBHbHlwaERhdGEmLCBjb25zdCBHbHlwaERhdGEmKTsKKworICAgIFZlY3RvcjxHbHlwaERh
dGE+IG1fZ2x5cGhzOworICAgIEZsb2F0UmVjdCBtX2JvdW5kaW5nQm94OworICAgIGNvbnN0IFNW
R0ZvbnRFbGVtZW50JiBtX2ZvbnRFbGVtZW50OworICAgIGNvbnN0IFNWR0ZvbnRGYWNlRWxlbWVu
dCogbV9mb250RmFjZUVsZW1lbnQ7CisgICAgU3RyaW5nIG1fZm9udEZhbWlseTsKKyAgICBmbG9h
dCBtX2FkdmFuY2VXaWR0aE1heDsKKyAgICBmbG9hdCBtX21pblJpZ2h0U2lkZUJlYXJpbmc7Cisg
ICAgY2hhciBtX3dlaWdodDsKKyAgICBib29sIG1faXRhbGljOworfTsKKworc3RhdGljIHVpbnQx
Nl90IHJvdW5kRG93blRvUG93ZXJPZlR3byh1aW50MTZfdCB4KQoreworICAgIHggfD0geCA+PiAx
OworICAgIHggfD0geCA+PiAyOworICAgIHggfD0geCA+PiA0OworICAgIHggfD0geCA+PiA4Owor
ICAgIHJldHVybiAoeCA+PiAxKSArIDE7Cit9CisKK1ZlY3RvcjxjaGFyPiBTVkdUb09URkZvbnRD
b252ZXJ0ZXI6OmNyZWF0ZUNNQVBUYWJsZSgpCit7CisgICAgVmVjdG9yPGNoYXI+IHJlc3VsdDsK
KyAgICB3cml0ZVVJbnQxNihyZXN1bHQsIDApOworICAgIHdyaXRlVUludDE2KHJlc3VsdCwgMSk7
IC8vIE51bWJlciBzdWJ0YWJsZXMKKworICAgIHdyaXRlVUludDE2KHJlc3VsdCwgMCk7IC8vIFVu
aWNvZGUKKyAgICB3cml0ZVVJbnQxNihyZXN1bHQsIDMpOyAvLyBVbmljb2RlIHZlcnNpb24gMi4y
KworICAgIHdyaXRlVUludDMyKHJlc3VsdCwgcmVzdWx0LnNpemUoKSArIHNpemVvZih1aW50MzJf
dCkpOyAvLyBCeXRlIG9mZnNldCBvZiBzdWJ0YWJsZQorCisgICAgLy8gQnJhaW5kZWFkIHNjaGVt
ZTogT25lIHNlZ21lbnQgZm9yIGVhY2ggY2hhcmFjdGVyCisgICAgQVNTRVJUKG1fZ2x5cGhzLnNp
emUoKSA8IDB4RkZGRik7CisgICAgdWludDE2X3Qgc2VnQ291bnQgPSBtX2dseXBocy5zaXplKCkg
KyAxOworICAgIHdyaXRlVUludDE2KHJlc3VsdCwgNCk7IC8vIEZvcm1hdDogT25seSBzdXBwb3J0
IHRoZSBCYXNpYyBNdWx0aWxpbmd1YWwgUGxhbmUgZm9yIG5vdworICAgIHdyaXRlVUludDE2KHJl
c3VsdCwgMjIgKyBtX2dseXBocy5zaXplKCkgKiAyKTsgLy8gbGVuZ3RoCisgICAgd3JpdGVVSW50
MTYocmVzdWx0LCAwKTsgLy8gTGFuZ3VhZ2UgaW5kZXBlbmRlbnQKKyAgICB3cml0ZVVJbnQxNihy
ZXN1bHQsIDIgKiBzZWdDb3VudCk7CisgICAgdWludDE2X3Qgb3JpZ2luYWxTZWFyY2hSYW5nZSA9
IHJvdW5kRG93blRvUG93ZXJPZlR3byhzZWdDb3VudCk7CisgICAgdWludDE2X3Qgc2VhcmNoUmFu
Z2UgPSAyICogb3JpZ2luYWxTZWFyY2hSYW5nZTsKKyAgICB3cml0ZVVJbnQxNihyZXN1bHQsIHNl
YXJjaFJhbmdlKTsKKyAgICB1aW50MTZfdCBlbnRyeVNlbGVjdG9yID0gMDsKKyAgICB3aGlsZSAo
b3JpZ2luYWxTZWFyY2hSYW5nZSA+Pj0gMSkKKyAgICAgICAgKytlbnRyeVNlbGVjdG9yOworICAg
IHdyaXRlVUludDE2KHJlc3VsdCwgZW50cnlTZWxlY3Rvcik7CisgICAgd3JpdGVVSW50MTYocmVz
dWx0LCAoMiAqIHNlZ0NvdW50KSAtIHNlYXJjaFJhbmdlKTsKKworICAgIGZvciAoY29uc3QgYXV0
byYgZ2x5cGggOiBtX2dseXBocykKKyAgICAgICAgd3JpdGVVSW50MTYocmVzdWx0LCBnbHlwaC5j
b2RlcG9pbnQpOyAvLyBFbmRDb2RlCisgICAgd3JpdGVVSW50MTYocmVzdWx0LCAweEZGRkYpOyAv
LyAiVG8gZW5zdXJlIHRoYXQgdGhlIHNlYXJjaCB3aWxsIHRlcm1pbmF0ZSwgdGhlIGZpbmFsIGVu
ZENvZGUgdmFsdWUgbXVzdCBiZSAweEZGRkYuIgorICAgIHdyaXRlVUludDE2KHJlc3VsdCwgMCk7
IC8vIFJlc2VydmVkCisgICAgZm9yIChjb25zdCBhdXRvJiBnbHlwaCA6IG1fZ2x5cGhzKQorICAg
ICAgICB3cml0ZVVJbnQxNihyZXN1bHQsIGdseXBoLmNvZGVwb2ludCk7IC8vIHN0YXJ0Q29kZQor
ICAgIHdyaXRlVUludDE2KHJlc3VsdCwgMHhGRkZGKTsKKyAgICBmb3IgKHVuc2lnbmVkIGkgPSAw
OyBpIDwgbV9nbHlwaHMuc2l6ZSgpOyArK2kpIHsKKyAgICAgICAgLy8gTm90ZSB0aGF0IHRoaXMg
dmFsdWUgY2FuIGJlICJuZWdhdGl2ZSwiIGJ1dCB0aGF0IGlzIG9rYXkgYmVjYXVzZSB3cmFwcGlu
ZyBpcyBkZWZpbmVkIGFuZCBleHBlY3RlZCBoZXJlCisgICAgICAgIHdyaXRlVUludDE2KHJlc3Vs
dCwgc3RhdGljX2Nhc3Q8dWludDE2X3Q+KGkpIC0gbV9nbHlwaHNbaV0uY29kZXBvaW50KTsgLy8g
aWREZWx0YQorICAgIH0KKyAgICB3cml0ZVVJbnQxNihyZXN1bHQsIDEpOworICAgIGZvciAodW5z
aWduZWQgaSA9IDA7IGkgPCBtX2dseXBocy5zaXplKCk7ICsraSkKKyAgICAgICAgd3JpdGVVSW50
MTYocmVzdWx0LCAwKTsgLy8gaWRSYW5nZU9mZnNldAorICAgIHdyaXRlVUludDE2KHJlc3VsdCwg
MCk7CisgICAgcmV0dXJuIHJlc3VsdDsKK30KKworVmVjdG9yPGNoYXI+IFNWR1RvT1RGRm9udENv
bnZlcnRlcjo6Y3JlYXRlSEVBRFRhYmxlKCkKK3sKKyAgICBWZWN0b3I8Y2hhcj4gcmVzdWx0Owor
ICAgIHdyaXRlVUludDMyKHJlc3VsdCwgMHgwMDAxMDAwMCk7IC8vIFZlcnNpb24KKyAgICB3cml0
ZVVJbnQzMihyZXN1bHQsIDB4MDAwMTAwMDApOyAvLyBSZXZpc2lvbgorICAgIHdyaXRlVUludDMy
KHJlc3VsdCwgMCk7IC8vIENoZWNrc3VtIGFkanVzdG1lbnQKKyAgICAvLyBNYWdpYyBudW1iZXIu
ICJTZXQgdG8gMHg1RjBGM0NGNSIKKyAgICByZXN1bHQuYXBwZW5kKDB4NUYpOworICAgIHJlc3Vs
dC5hcHBlbmQoMHgwRik7CisgICAgcmVzdWx0LmFwcGVuZCgweDNDKTsKKyAgICByZXN1bHQuYXBw
ZW5kKC0weDBCKTsgLy8gV3JhcGFyb3VuZAorICAgIHdyaXRlVUludDE2KHJlc3VsdCwgKDEgPDwg
OSkgfCAxKTsKKworICAgIHVpbnQxNiB1bml0c1BlckVtID0gbV9mb250RmFjZUVsZW1lbnQgPyBt
X2ZvbnRGYWNlRWxlbWVudC0+dW5pdHNQZXJFbSgpIDogMDsKKworICAgIHdyaXRlVUludDE2KHJl
c3VsdCwgdW5pdHNQZXJFbSk7CisgICAgd3JpdGVVSW50MzIocmVzdWx0LCAwKTsgLy8gRmlyc3Qg
aGFsZiBvZiBjcmVhdGlvbiBkYXRlCisgICAgd3JpdGVVSW50MzIocmVzdWx0LCAwKTsgLy8gTGFz
dCBoYWxmIG9mIGNyZWF0aW9uIGRhdGUKKyAgICB3cml0ZVVJbnQzMihyZXN1bHQsIDApOyAvLyBG
aXJzdCBoYWxmIG9mIG1vZGlmaWNhdGlvbiBkYXRlCisgICAgd3JpdGVVSW50MzIocmVzdWx0LCAw
KTsgLy8gTGFzdCBoYWxmIG9mIG1vZGlmaWNhdGlvbiBkYXRlCisgICAgd3JpdGVJbnQxNihyZXN1
bHQsIHN0ZDo6bnVtZXJpY19saW1pdHM8aW50MTZfdD46Om1pbigpKTsgLy8gTWluaW11bSBYCisg
ICAgd3JpdGVJbnQxNihyZXN1bHQsIHN0ZDo6bnVtZXJpY19saW1pdHM8aW50MTZfdD46Om1pbigp
KTsgLy8gTWluaW11bSBZCisgICAgd3JpdGVJbnQxNihyZXN1bHQsIHN0ZDo6bnVtZXJpY19saW1p
dHM8aW50MTZfdD46Om1heCgpKTsgLy8gTWF4aW11bSBYCisgICAgd3JpdGVJbnQxNihyZXN1bHQs
IHN0ZDo6bnVtZXJpY19saW1pdHM8aW50MTZfdD46Om1heCgpKTsgLy8gTWF4aW11bSBZCisgICAg
d3JpdGVVSW50MTYocmVzdWx0LCAobV9pdGFsaWMgPyAxIDw8IDEgOiAwKSB8IChtX3dlaWdodCA+
PSA3ID8gMSA6IDApKTsKKyAgICB3cml0ZVVJbnQxNihyZXN1bHQsIDMpOyAvLyBTbWFsbGVzdCBy
ZWFkYWJsZSBzaXplIGluIHBpeGVscworICAgIHdyaXRlVUludDE2KHJlc3VsdCwgMCk7IC8vIE1p
Z2h0IGNvbnRhaW4gTFRSIG9yIFJUTCBnbHlwaHMKKyAgICB3cml0ZVVJbnQxNihyZXN1bHQsIDAp
OyAvLyBTaG9ydCBvZmZzZXRzIGluIHRoZSAnbG9jYScgdGFibGUuIEhvd2V2ZXIsIE9URiBmb250
cyBkb24ndCBoYXZlIGEgJ2xvY2EnIHRhYmxlIHNvIHRoaXMgaXMgaXJyZWxldmFudAorICAgIHdy
aXRlVUludDE2KHJlc3VsdCwgMCk7IC8vIEdseXBoIGRhdGEgZm9ybWF0CisgICAgcmV0dXJuIHJl
c3VsdDsKK30KKwordGVtcGxhdGUgPHR5cGVuYW1lIFQ+CitzdGF0aWMgaW5saW5lIFQgY2xhbXBG
bG9hdFRvKGZsb2F0IHgpCit7CisgICAgeCA9IHN0ZDo6bWluKHgsIHN0YXRpY19jYXN0PGZsb2F0
PihzdGQ6Om51bWVyaWNfbGltaXRzPFQ+OjptYXgoKSkpOworICAgIHggPSBzdGQ6Om1heCh4LCBz
dGF0aWNfY2FzdDxmbG9hdD4oc3RkOjpudW1lcmljX2xpbWl0czxUPjo6bWluKCkpKTsKKyAgICBy
ZXR1cm4gc3RhdGljX2Nhc3Q8aW50MTZfdD4oeCk7Cit9CisKK1ZlY3RvcjxjaGFyPiBTVkdUb09U
RkZvbnRDb252ZXJ0ZXI6OmNyZWF0ZUhIRUFUYWJsZSgpCit7CisgICAgVmVjdG9yPGNoYXI+IHJl
c3VsdDsKKyAgICB1aW50MTYgdW5pdHNQZXJFbSA9IDA7CisgICAgdWludDE2IGFzY2VudCA9IHN0
ZDo6bnVtZXJpY19saW1pdHM8aW50MTZfdD46Om1heCgpOworICAgIHVpbnQxNiBkZXNjZW50ID0g
c3RkOjpudW1lcmljX2xpbWl0czxpbnQxNl90Pjo6bWF4KCk7CisgICAgaWYgKG1fZm9udEZhY2VF
bGVtZW50KSB7CisgICAgICAgIHVuaXRzUGVyRW0gPSBtX2ZvbnRGYWNlRWxlbWVudC0+dW5pdHNQ
ZXJFbSgpOworICAgICAgICBhc2NlbnQgPSBtX2ZvbnRGYWNlRWxlbWVudC0+YXNjZW50KCk7Cisg
ICAgICAgIGRlc2NlbnQgPSBtX2ZvbnRGYWNlRWxlbWVudC0+ZGVzY2VudCgpOworICAgIH0KKwor
ICAgIHdyaXRlVUludDMyKHJlc3VsdCwgMHgwMDAxMDAwMCk7IC8vIFZlcnNpb24KKyAgICB3cml0
ZVVJbnQxNihyZXN1bHQsIGFzY2VudCk7CisgICAgd3JpdGVVSW50MTYocmVzdWx0LCBkZXNjZW50
KTsKKyAgICB3cml0ZVVJbnQxNihyZXN1bHQsIDApOyAvLyBMaW5lIGdhcAorICAgIHdyaXRlVUlu
dDE2KHJlc3VsdCwgY2xhbXBGbG9hdFRvPHVpbnQxNl90PihtX2FkdmFuY2VXaWR0aE1heCkpOwor
ICAgIHdyaXRlVUludDE2KHJlc3VsdCwgY2xhbXBGbG9hdFRvPGludDE2X3Q+KG1fYm91bmRpbmdC
b3gueCgpKSk7IC8vIE1pbmltdW0gbGVmdCBzaWRlIGJlYXJpbmcKKyAgICB3cml0ZVVJbnQxNihy
ZXN1bHQsIGNsYW1wRmxvYXRUbzxpbnQxNl90PihtX21pblJpZ2h0U2lkZUJlYXJpbmcpKTsgLy8g
TWluaW11bSByaWdodCBzaWRlIGJlYXJpbmcKKyAgICB3cml0ZVVJbnQxNihyZXN1bHQsIGNsYW1w
RmxvYXRUbzxpbnQxNl90PihtX2JvdW5kaW5nQm94Lm1heFgoKSkpOyAvLyBYIG1heGltdW0gZXh0
ZW50CisgICAgLy8gV2ViS2l0IGRyYXdzIHRoZSBjYXJldAorICAgIHdyaXRlVUludDE2KHJlc3Vs
dCwgMSk7IC8vIFZlcnRpY2FsIGNhcmV0CisgICAgd3JpdGVVSW50MTYocmVzdWx0LCAwKTsgLy8g
VmVydGljYWwgY2FyZXQKKyAgICB3cml0ZVVJbnQxNihyZXN1bHQsIDApOyAvLyAiU2V0IHZhbHVl
IHRvIDAgZm9yIG5vbi1zbGFudGVkIGZvbnRzIgorICAgIHdyaXRlVUludDMyKHJlc3VsdCwgMCk7
IC8vIFJlc2VydmVkCisgICAgd3JpdGVVSW50MzIocmVzdWx0LCAwKTsgLy8gUmVzZXJ2ZWQKKyAg
ICB3cml0ZVVJbnQxNihyZXN1bHQsIDApOyAvLyBDdXJyZW50IGZvcm1hdAorICAgIHdyaXRlVUlu
dDE2KHJlc3VsdCwgbV9nbHlwaHMuc2l6ZSgpKTsgLy8gTnVtYmVyIG9mIGFkdmFuY2Ugd2lkdGhz
IGluIEhNVFggdGFibGUKKyAgICByZXR1cm4gcmVzdWx0OworfQorCitWZWN0b3I8Y2hhcj4gU1ZH
VG9PVEZGb250Q29udmVydGVyOjpjcmVhdGVITVRYVGFibGUoKQoreworICAgIFZlY3RvcjxjaGFy
PiByZXN1bHQ7CisgICAgZm9yIChjb25zdCBhdXRvJiBnbHlwaCA6IG1fZ2x5cGhzKSB7CisgICAg
ICAgIHdyaXRlVUludDE2KHJlc3VsdCwgY2xhbXBGbG9hdFRvPHVpbnQxNl90PihnbHlwaC5hZHZh
bmNlKSk7CisgICAgICAgIHdyaXRlSW50MTYocmVzdWx0LCBjbGFtcEZsb2F0VG88aW50MTZfdD4o
Z2x5cGguYm91bmRpbmdCb3gueCgpKSk7CisgICAgfQorICAgIHJldHVybiByZXN1bHQ7Cit9CisK
K1ZlY3RvcjxjaGFyPiBTVkdUb09URkZvbnRDb252ZXJ0ZXI6OmNyZWF0ZU1BWFBUYWJsZSgpCit7
CisgICAgVmVjdG9yPGNoYXI+IHJlc3VsdDsKKyAgICB3cml0ZVVJbnQzMihyZXN1bHQsIDB4MDAw
MTAwMDApOyAvLyBWZXJzaW9uCisgICAgd3JpdGVVSW50MTYocmVzdWx0LCBtX2dseXBocy5zaXpl
KCkpOworICAgIHdyaXRlVUludDE2KHJlc3VsdCwgMHhGRkZGKTsgLy8gTWF4aW11bSBudW1iZXIg
b2YgcG9pbnRzIGluIG5vbi1jb21wb3VuZCBnbHlwaAorICAgIHdyaXRlVUludDE2KHJlc3VsdCwg
MHhGRkZGKTsgLy8gTWF4aW11bSBudW1iZXIgb2YgY29udG91cnMgaW4gbm9uLWNvbXBvdW5kIGds
eXBoCisgICAgd3JpdGVVSW50MTYocmVzdWx0LCAweEZGRkYpOyAvLyBNYXhpbXVtIG51bWJlciBv
ZiBwb2ludHMgaW4gY29tcG91bmQgZ2x5cGgKKyAgICB3cml0ZVVJbnQxNihyZXN1bHQsIDB4RkZG
Rik7IC8vIE1heGltdW0gbnVtYmVyIG9mIGNvbnRvdXJzIGluIGNvbXBvdW5kIGdseXBoCisgICAg
d3JpdGVVSW50MTYocmVzdWx0LCAyKTsgLy8gTWF4aW11bSBudW1iZXIgb2Ygem9uZXMKKyAgICB3
cml0ZVVJbnQxNihyZXN1bHQsIDApOyAvLyBNYXhpbXVtIG51bWJlciBvZiBwb2ludHMgdXNlZCBp
biB6b25lIDAKKyAgICB3cml0ZVVJbnQxNihyZXN1bHQsIDApOyAvLyBNYXhpbXVtIG51bWJlciBv
ZiBzdG9yYWdlIGFyZWEgbG9jYXRpb25zCisgICAgd3JpdGVVSW50MTYocmVzdWx0LCAwKTsgLy8g
TWF4aW11bSBudW1iZXIgb2YgZnVuY3Rpb24gZGVmaW5pdGlvbnMKKyAgICB3cml0ZVVJbnQxNihy
ZXN1bHQsIDApOyAvLyBNYXhpbXVtIG51bWJlciBvZiBpbnN0cnVjdGlvbiBkZWZpbml0aW9ucwor
ICAgIHdyaXRlVUludDE2KHJlc3VsdCwgMCk7IC8vIE1heGltdW0gc3RhY2sgZGVwdGgKKyAgICB3
cml0ZVVJbnQxNihyZXN1bHQsIDApOyAvLyBNYXhpbXVtIHNpemUgb2YgaW5zdHJ1Y3Rpb25zCisg
ICAgd3JpdGVVSW50MTYocmVzdWx0LCBtX2dseXBocy5zaXplKCkpOyAvLyBNYXhpbXVtIG51bWJl
ciBvZiBnbHlwaHMgcmVmZXJlbmNlZCBhdCB0b3AgbGV2ZWwKKyAgICB3cml0ZVVJbnQxNihyZXN1
bHQsIDApOyAvLyBObyBjb21wb3VuZCBnbHlwaHMKKyAgICByZXR1cm4gcmVzdWx0OworfQorCitW
ZWN0b3I8Y2hhcj4gU1ZHVG9PVEZGb250Q29udmVydGVyOjpjcmVhdGVOQU1FVGFibGUoKQorewor
ICAgIFZlY3RvcjxjaGFyPiByZXN1bHQ7CisgICAgd3JpdGVVSW50MTYocmVzdWx0LCAwKTsgLy8g
Rm9ybWF0IHNlbGVjdG9yCisgICAgd3JpdGVVSW50MTYocmVzdWx0LCAxKTsgLy8gTnVtYmVyIG9m
IG5hbWUgcmVjb3JkcyBpbiB0YWJsZQorICAgIHdyaXRlVUludDE2KHJlc3VsdCwgMTgpOyAvLyBP
ZmZzZXQgaW4gYnl0ZXMgdG8gdGhlIGJlZ2lubmluZyBvZiBuYW1lIGNoYXJhY3RlciBzdHJpbmdz
CisKKyAgICB3cml0ZVVJbnQxNihyZXN1bHQsIDApOyAvLyBVbmljb2RlCisgICAgd3JpdGVVSW50
MTYocmVzdWx0LCAzKTsgLy8gVW5pY29kZSB2ZXJzaW9uIDIuMCBvciBsYXRlcgorICAgIHdyaXRl
VUludDE2KHJlc3VsdCwgMCk7IC8vIExhbmd1YWdlCisgICAgd3JpdGVVSW50MTYocmVzdWx0LCAx
KTsgLy8gTmFtZSBpZGVudGlmaWVyLiAxID0gRm9udCBmYW1pbHkKKyAgICB3cml0ZVVJbnQxNihy
ZXN1bHQsIG1fZm9udEZhbWlseS5sZW5ndGgoKSk7CisgICAgd3JpdGVVSW50MTYocmVzdWx0LCAw
KTsgLy8gT2Zmc2V0IGludG8gbmFtZSBkYXRhCisKKyAgICBmb3IgKHVuc2lnbmVkIGkgPSAwOyBp
IDwgbV9mb250RmFtaWx5Lmxlbmd0aCgpOyArK2kpCisgICAgICAgIHdyaXRlVUludDE2KHJlc3Vs
dCwgbV9mb250RmFtaWx5W2ldKTsKKyAgICByZXR1cm4gcmVzdWx0OworfQorCitWZWN0b3I8Y2hh
cj4gU1ZHVG9PVEZGb250Q29udmVydGVyOjpjcmVhdGVPUzJUYWJsZSgpCit7CisgICAgVmVjdG9y
PGNoYXI+IHJlc3VsdDsKKyAgICAvLyBGSVhNRTogV2UgY2FuIGxvb2sgYXQgdGhlIG1pc3Npbmcg
Z2x5cGggaW5mbyBmb3IgdGhpcworICAgIHVpbnQxNiB1bml0c1BlckVtID0gbV9mb250RmFjZUVs
ZW1lbnQgPyBtX2ZvbnRGYWNlRWxlbWVudC0+dW5pdHNQZXJFbSgpIDogMDsKKyAgICBpbnQxNl90
IGF2ZXJhZ2VBZHZhbmNlID0gdW5pdHNQZXJFbSAvIDI7CisgICAgY29uc3QgYXV0byYgYXR0cmli
dXRlID0gbV9mb250RWxlbWVudC5nZXRBdHRyaWJ1dGUoImhvcml6LWFkdi14Iik7CisgICAgYm9v
bCBvayA9IHRydWU7CisgICAgaW50IHZhbHVlID0gYXR0cmlidXRlLnRvSW50KCZvayk7CisgICAg
aWYgKG9rKQorICAgICAgICBhdmVyYWdlQWR2YW5jZSA9IHZhbHVlOworCisgICAgd3JpdGVVSW50
MTYocmVzdWx0LCAwKTsgLy8gVmVyc2lvbgorICAgIHdyaXRlVUludDE2KHJlc3VsdCwgYXZlcmFn
ZUFkdmFuY2UpOworICAgIHdyaXRlVUludDE2KHJlc3VsdCwgbV93ZWlnaHQpOyAvLyBXZWlnaHQg
Y2xhc3MKKyAgICB3cml0ZVVJbnQxNihyZXN1bHQsIDUpOyAvLyBXaWR0aCBjbGFzcworICAgIHdy
aXRlVUludDE2KHJlc3VsdCwgMCk7IC8vIFByb3RlY3RlZCBmb250CisgICAgLy8gV2ViS2l0IGhh
bmRsZXMgdGhlc2Ugc3VwZXJzY3JpcHRzIGFuZCBzdWJzY3JpcHRzCisgICAgd3JpdGVVSW50MTYo
cmVzdWx0LCAwKTsgLy8gU3Vic2NyaXB0IFggU2l6ZQorICAgIHdyaXRlVUludDE2KHJlc3VsdCwg
MCk7IC8vIFN1YnNjcmlwdCBZIFNpemUKKyAgICB3cml0ZVVJbnQxNihyZXN1bHQsIDApOyAvLyBT
dWJzY3JpcHQgWCBPZmZzZXQKKyAgICB3cml0ZVVJbnQxNihyZXN1bHQsIDApOyAvLyBTdWJzY3Jp
cHQgWSBPZmZzZXQKKyAgICB3cml0ZVVJbnQxNihyZXN1bHQsIDApOyAvLyBTdXBlcnNjcmlwdCBY
IFNpemUKKyAgICB3cml0ZVVJbnQxNihyZXN1bHQsIDApOyAvLyBTdXBlcnNjcmlwdCBZIFNpemUK
KyAgICB3cml0ZVVJbnQxNihyZXN1bHQsIDApOyAvLyBTdXBlcnNjcmlwdCBYIE9mZnNldAorICAg
IHdyaXRlVUludDE2KHJlc3VsdCwgMCk7IC8vIFN1cGVyc2NyaXB0IFkgT2Zmc2V0CisgICAgd3Jp
dGVVSW50MTYocmVzdWx0LCAwKTsgLy8gU3RyaWtlb3V0IHdpZHRoCisgICAgd3JpdGVVSW50MTYo
cmVzdWx0LCAwKTsgLy8gU3RyaWtlb3V0IFBvc2l0aW9uCisgICAgd3JpdGVVSW50MTYocmVzdWx0
LCAwKTsgLy8gTm8gY2xhc3NpZmljYXRpb24KKworICAgIFZlY3Rvcjx1bnNpZ25lZCBjaGFyPiBz
cGVjaWZpZWRQYW5vc2U7CisgICAgaWYgKG1fZm9udEZhY2VFbGVtZW50KSB7CisgICAgICAgIGNv
bnN0IGF1dG8mIGF0dHJpYnV0ZSA9IG1fZm9udEZhY2VFbGVtZW50LT5mYXN0R2V0QXR0cmlidXRl
KFNWR05hbWVzOjpwYW5vc2VfMUF0dHIpOworICAgICAgICBWZWN0b3I8U3RyaW5nPiBzcGxpdDsK
KyAgICAgICAgU3RyaW5nKGF0dHJpYnV0ZSkuc3BsaXQoIiAiLCBzcGxpdCk7CisgICAgICAgIGlm
IChzcGxpdC5zaXplKCkgPT0gMTApIHsKKyAgICAgICAgICAgIGZvciAoY29uc3QgYXV0byYgcyA6
IHNwbGl0KSB7CisgICAgICAgICAgICAgICAgYm9vbCBvayA9IHRydWU7CisgICAgICAgICAgICAg
ICAgaW50IHZhbHVlID0gcy50b0ludCgmb2spOworICAgICAgICAgICAgICAgIGlmICghb2sgfHwg
dmFsdWUgPCAwIHx8IHZhbHVlID4gMHhGRikgeworICAgICAgICAgICAgICAgICAgICBzcGVjaWZp
ZWRQYW5vc2UuY2xlYXIoKTsKKyAgICAgICAgICAgICAgICAgICAgYnJlYWs7CisgICAgICAgICAg
ICAgICAgfQorICAgICAgICAgICAgICAgIHNwZWNpZmllZFBhbm9zZS5hcHBlbmQoc3RhdGljX2Nh
c3Q8dW5zaWduZWQgY2hhcj4odmFsdWUpKTsKKyAgICAgICAgICAgIH0KKyAgICAgICAgfQorICAg
IH0KKworICAgIGlmIChzcGVjaWZpZWRQYW5vc2Uuc2l6ZSgpID09IDEwKSB7CisgICAgICAgIGZv
ciAoY2hhciBjIDogc3BlY2lmaWVkUGFub3NlKQorICAgICAgICAgICAgcmVzdWx0LmFwcGVuZChj
KTsKKyAgICB9IGVsc2UgeworICAgICAgICBmb3IgKGludCBpID0gMDsgaSA8IDEwOyArK2kpCisg
ICAgICAgICAgICByZXN1bHQuYXBwZW5kKDApOyAvLyBQQU5PU0U6IEFueQorICAgIH0KKworICAg
IGZvciAoaW50IGkgPSAwOyBpIDwgNDsgKytpKQorICAgICAgICB3cml0ZVVJbnQzMihyZXN1bHQs
IDApOyAvLyAiQml0IGFzc2lnbm1lbnRzIGFyZSBwZW5kaW5nLiBTZXQgdG8gMCIKKyAgICB3cml0
ZVVJbnQzMihyZXN1bHQsIDB4NTQ0QjQyNTcpOyAvLyBGb250IFZlbmRvci4gIldCS1QiCisgICAg
d3JpdGVVSW50MTYocmVzdWx0LCAobV93ZWlnaHQgPj0gNyA/IDEgPDwgNSA6IDApIHwgKG1faXRh
bGljID8gMSA6IDApKTsgLy8gRm9udCBQYXR0ZXJucy4KKyAgICB3cml0ZVVJbnQxNihyZXN1bHQs
IG1fZ2x5cGhzWzBdLmNvZGVwb2ludCk7IC8vIEZpcnN0IHVuaWNvZGUgaW5kZXgKKyAgICB3cml0
ZVVJbnQxNihyZXN1bHQsIG1fZ2x5cGhzW21fZ2x5cGhzLnNpemUoKSAtIDFdLmNvZGVwb2ludCk7
IC8vIExhc3QgdW5pY29kZSBpbmRleAorICAgIHJldHVybiByZXN1bHQ7Cit9CisKK1ZlY3Rvcjxj
aGFyPiBTVkdUb09URkZvbnRDb252ZXJ0ZXI6OmNyZWF0ZVBPU1RUYWJsZSgpCit7CisgICAgVmVj
dG9yPGNoYXI+IHJlc3VsdDsKKyAgICB3cml0ZVVJbnQzMihyZXN1bHQsIDB4MDAwMzAwMDApOyAv
LyBGb3JtYXQuIFByaW50aW5nIGlzIHVuZGVmaW5lZAorICAgIHdyaXRlVUludDMyKHJlc3VsdCwg
MCk7IC8vIEl0YWxpYyBhbmdsZSBpbiBkZWdyZWVzCisgICAgd3JpdGVVSW50MTYocmVzdWx0LCAw
KTsgLy8gVW5kZXJsaW5lIHBvc2l0aW9uCisgICAgd3JpdGVVSW50MTYocmVzdWx0LCAwKTsgLy8g
VW5kZXJsaW5lIHRoaWNrbmVzcworICAgIHdyaXRlVUludDMyKHJlc3VsdCwgMCk7IC8vIE1vbm9z
cGFjZWQKKyAgICB3cml0ZVVJbnQzMihyZXN1bHQsIDApOyAvLyAiTWluaW11bSBtZW1vcnkgdXNh
Z2Ugd2hlbiBhIFRydWVUeXBlIGZvbnQgaXMgZG93bmxvYWRlZCBhcyBhIFR5cGUgNDIgZm9udCIK
KyAgICB3cml0ZVVJbnQzMihyZXN1bHQsIDApOyAvLyAiTWF4aW11bSBtZW1vcnkgdXNhZ2Ugd2hl
biBhIFRydWVUeXBlIGZvbnQgaXMgZG93bmxvYWRlZCBhcyBhIFR5cGUgNDIgZm9udCIKKyAgICB3
cml0ZVVJbnQzMihyZXN1bHQsIDApOyAvLyAiTWluaW11bSBtZW1vcnkgdXNhZ2Ugd2hlbiBhIFRy
dWVUeXBlIGZvbnQgaXMgZG93bmxvYWRlZCBhcyBhIFR5cGUgMSBmb250IgorICAgIHdyaXRlVUlu
dDMyKHJlc3VsdCwgMCk7IC8vICJNYXhpbXVtIG1lbW9yeSB1c2FnZSB3aGVuIGEgVHJ1ZVR5cGUg
Zm9udCBpcyBkb3dubG9hZGVkIGFzIGEgVHlwZSAxIGZvbnQiCisgICAgcmV0dXJuIHJlc3VsdDsK
K30KKworc3RhdGljIGJvb2wgaXNWYWxpZFN0cmluZ0ZvckNGRihjb25zdCBTdHJpbmcmIHN0cmlu
ZykKK3sKKyAgICBpZiAoc3RyaW5nLmlzRW1wdHkoKSkKKyAgICAgICAgcmV0dXJuIHRydWU7Cisg
ICAgaWYgKCFzdHJpbmcuaXM4Qml0KCkpCisgICAgICAgIHJldHVybiBmYWxzZTsKKyAgICBmb3Ig
KHVuc2lnbmVkIGkgPSAwOyBpIDwgc3RyaW5nLmxlbmd0aCgpOyArK2kpIHsKKyAgICAgICAgaWYg
KHN0cmluZ1tpXSA8IDMzIHx8IHN0cmluZ1tpXSA+IDEyNikKKyAgICAgICAgICAgIHJldHVybiBm
YWxzZTsKKyAgICB9CisgICAgcmV0dXJuIHRydWU7Cit9CisKK1ZlY3RvcjxjaGFyPiBTVkdUb09U
RkZvbnRDb252ZXJ0ZXI6OmNyZWF0ZUNGRlRhYmxlKCkKK3sKKyAgICBWZWN0b3I8Y2hhcj4gcmVz
dWx0OworICAgIC8vIEhlYWRlcgorICAgIHJlc3VsdC5hcHBlbmQoMSk7IC8vIE1ham9yIHZlcnNp
b24KKyAgICByZXN1bHQuYXBwZW5kKDApOyAvLyBNaW5vciB2ZXJzaW9uCisgICAgcmVzdWx0LmFw
cGVuZCg0KTsgLy8gSGVhZGVyIHNpemUKKyAgICByZXN1bHQuYXBwZW5kKDQpOyAvLyBPZmZzZXRz
IHdpdGhpbiBDRkYgdGFibGUgYXJlIDQgYnl0ZXMgbG9uZworCisgICAgLy8gTmFtZSBJTkRFWAor
ICAgIFN0cmluZyBmb250TmFtZSA9IFN0cmluZygpOworICAgIGlmIChtX2ZvbnRGYWNlRWxlbWVu
dCkgeworICAgICAgICAvLyBGSVhNRTogZm9udEZhbWlseSgpIGhlcmUgbWlnaHQgbm90IGJlIHF1
aXRlIHdoYXQgSSB3YW50CisgICAgICAgIFN0cmluZyBwb3RlbnRpYWxGb250TmFtZSA9IG1fZm9u
dEZhbWlseTsKKyAgICAgICAgaWYgKGlzVmFsaWRTdHJpbmdGb3JDRkYocG90ZW50aWFsRm9udE5h
bWUpKQorICAgICAgICAgICAgZm9udE5hbWUgPSBwb3RlbnRpYWxGb250TmFtZTsKKyAgICB9Cisg
ICAgQVNTRVJUKGZvbnROYW1lLmlzOEJpdCgpKTsKKyAgICB3cml0ZVVJbnQxNihyZXN1bHQsIDEp
OyAvLyBJTkRFWCBjb250YWlucyAxIGVsZW1lbnQKKyAgICByZXN1bHQuYXBwZW5kKDQpOyAvLyBP
ZmZzZXRzIGluIHRoaXMgSU5ERVggYXJlIDQgYnl0ZXMgbG9uZworICAgIHdyaXRlVUludDMyKHJl
c3VsdCwgMSk7IC8vIDEtaW5kZXggb2Zmc2V0IG9mIG5hbWUgZGF0YQorICAgIHdyaXRlVUludDMy
KHJlc3VsdCwgZm9udE5hbWUubGVuZ3RoKCkgKyAxKTsgLy8gMS1pbmRleCBvZmZzZXQganVzdCBw
YXN0IGVuZCBvZiBuYW1lIGRhdGEKKyAgICByZXN1bHQuYXBwZW5kKGZvbnROYW1lLmNoYXJhY3Rl
cnM4KCksIGZvbnROYW1lLmxlbmd0aCgpKTsKKworICAgIFN0cmluZyB3ZWlnaHQ7CisgICAgaWYg
KG1fZm9udEZhY2VFbGVtZW50KSB7CisgICAgICAgIGNvbnN0IGF1dG8mIHBvdGVudGlhbFdlaWdo
dCA9IG1fZm9udEZhY2VFbGVtZW50LT5mYXN0R2V0QXR0cmlidXRlKFNWR05hbWVzOjpmb250X3dl
aWdodEF0dHIpOworICAgICAgICBpZiAoaXNWYWxpZFN0cmluZ0ZvckNGRihwb3RlbnRpYWxXZWln
aHQpKQorICAgICAgICAgICAgd2VpZ2h0ID0gcG90ZW50aWFsV2VpZ2h0OworICAgIH0KKworICAg
IGNvbnN0IGNoYXIgb3BlcmFuZDMyQml0ID0gMjk7CisgICAgY29uc3QgY2hhciBmdWxsTmFtZUtl
eSA9IDI7CisgICAgY29uc3QgY2hhciBmYW1pbHlOYW1lS2V5ID0gMzsKKyAgICBjb25zdCBjaGFy
IHdlaWdodEtleSA9IDQ7CisgICAgY29uc3QgY2hhciBmb250QkJveEtleSA9IDU7CisgICAgY29u
c3QgY2hhciBjaGFyc2V0SW5kZXhLZXkgPSAxNTsKKyAgICBjb25zdCBjaGFyIGNoYXJzdHJpbmdz
SW5kZXhLZXkgPSAxNzsKKyAgICBjb25zdCB1aW50MzJfdCB1c2VyRGVmaW5lZFN0cmluZ1N0YXJ0
SW5kZXggPSAzOTE7CisgICAgY29uc3QgdW5zaWduZWQgc2l6ZU9mVG9wSW5kZXggPSA0NSArICh3
ZWlnaHQuaXNFbXB0eSgpID8gMCA6IDYpOworCisgICAgLy8gVG9wIERJQ1QgSU5ERVguCisgICAg
d3JpdGVVSW50MTYocmVzdWx0LCAxKTsgLy8gSU5ERVggY29udGFpbnMgMSBlbGVtZW50CisgICAg
cmVzdWx0LmFwcGVuZCg0KTsgLy8gT2Zmc2V0cyBpbiB0aGlzIElOREVYIGFyZSA0IGJ5dGVzIGxv
bmcKKyAgICB3cml0ZVVJbnQzMihyZXN1bHQsIDEpOyAvLyAxLWluZGV4IG9mZnNldCBvZiBESUNU
IGRhdGEKKyAgICB3cml0ZVVJbnQzMihyZXN1bHQsIDEgKyBzaXplT2ZUb3BJbmRleCk7IC8vIDEt
aW5kZXggb2Zmc2V0IGp1c3QgcGFzdCBlbmQgb2YgRElDVCBkYXRhCisKKyAgICAvLyBESUNUIGlu
Zm9ybWF0aW9uCisjaWYgIUFTU0VSVF9ESVNBQkxFRAorICAgIHVuc2lnbmVkIHRvcERpY3RTdGFy
dCA9IHJlc3VsdC5zaXplKCk7CisjZW5kaWYKKyAgICByZXN1bHQuYXBwZW5kKG9wZXJhbmQzMkJp
dCk7CisgICAgd3JpdGVVSW50MzIocmVzdWx0LCB1c2VyRGVmaW5lZFN0cmluZ1N0YXJ0SW5kZXgp
OworICAgIHJlc3VsdC5hcHBlbmQoZnVsbE5hbWVLZXkpOworICAgIHJlc3VsdC5hcHBlbmQob3Bl
cmFuZDMyQml0KTsKKyAgICB3cml0ZVVJbnQzMihyZXN1bHQsIHVzZXJEZWZpbmVkU3RyaW5nU3Rh
cnRJbmRleCk7CisgICAgcmVzdWx0LmFwcGVuZChmYW1pbHlOYW1lS2V5KTsKKyAgICBpZiAoIXdl
aWdodC5pc0VtcHR5KCkpIHsKKyAgICAgICAgcmVzdWx0LmFwcGVuZChvcGVyYW5kMzJCaXQpOwor
ICAgICAgICB3cml0ZVVJbnQzMihyZXN1bHQsIHVzZXJEZWZpbmVkU3RyaW5nU3RhcnRJbmRleCAr
IDEpOworICAgICAgICByZXN1bHQuYXBwZW5kKHdlaWdodEtleSk7CisgICAgfQorICAgIHJlc3Vs
dC5hcHBlbmQob3BlcmFuZDMyQml0KTsKKyAgICB3cml0ZVVJbnQzMihyZXN1bHQsIGNsYW1wRmxv
YXRUbzxpbnQzMl90PihtX2JvdW5kaW5nQm94LngoKSkpOworICAgIHJlc3VsdC5hcHBlbmQob3Bl
cmFuZDMyQml0KTsKKyAgICB3cml0ZVVJbnQzMihyZXN1bHQsIGNsYW1wRmxvYXRUbzxpbnQzMl90
PihtX2JvdW5kaW5nQm94Lm1heFgoKSkpOworICAgIHJlc3VsdC5hcHBlbmQob3BlcmFuZDMyQml0
KTsKKyAgICB3cml0ZVVJbnQzMihyZXN1bHQsIGNsYW1wRmxvYXRUbzxpbnQzMl90PihtX2JvdW5k
aW5nQm94LnkoKSkpOworICAgIHJlc3VsdC5hcHBlbmQob3BlcmFuZDMyQml0KTsKKyAgICB3cml0
ZVVJbnQzMihyZXN1bHQsIGNsYW1wRmxvYXRUbzxpbnQzMl90PihtX2JvdW5kaW5nQm94Lm1heFko
KSkpOworICAgIHJlc3VsdC5hcHBlbmQoZm9udEJCb3hLZXkpOworICAgIHJlc3VsdC5hcHBlbmQo
b3BlcmFuZDMyQml0KTsKKyAgICB1bnNpZ25lZCBjaGFyc2V0T2Zmc2V0TG9jYXRpb24gPSByZXN1
bHQuc2l6ZSgpOworICAgIHdyaXRlVUludDMyKHJlc3VsdCwgMCk7IC8vIE9mZnNldCBvZiBDaGFy
c2V0IGluZm8uIFdpbGwgYmUgb3ZlcndyaXR0ZW4gbGF0ZXIuCisgICAgcmVzdWx0LmFwcGVuZChj
aGFyc2V0SW5kZXhLZXkpOworICAgIHJlc3VsdC5hcHBlbmQob3BlcmFuZDMyQml0KTsKKyAgICB1
bnNpZ25lZCBjaGFyc3RyaW5nc09mZnNldExvY2F0aW9uID0gcmVzdWx0LnNpemUoKTsKKyAgICB3
cml0ZVVJbnQzMihyZXN1bHQsIDApOyAvLyBPZmZzZXQgb2YgQ2hhclN0cmluZ3MgSU5ERVguIFdp
bGwgYmUgb3ZlcndyaXR0ZW4gbGF0ZXIuCisgICAgcmVzdWx0LmFwcGVuZChjaGFyc3RyaW5nc0lu
ZGV4S2V5KTsKKyAgICBBU1NFUlQocmVzdWx0LnNpemUoKSA9PSB0b3BEaWN0U3RhcnQgKyBzaXpl
T2ZUb3BJbmRleCk7CisKKyAgICAvLyBTdHJpbmcgSU5ERVgKKyAgICB3cml0ZVVJbnQxNihyZXN1
bHQsIDEgKyAod2VpZ2h0LmlzRW1wdHkoKSA/IDAgOiAxKSk7IC8vIE51bWJlciBvZiBlbGVtZW50
cyBpbiBJTkRFWAorICAgIHJlc3VsdC5hcHBlbmQoNCk7IC8vIE9mZnNldHMgaW4gdGhpcyBJTkRF
WCBhcmUgNCBieXRlcyBsb25nCisgICAgdWludDMyX3Qgb2Zmc2V0ID0gMTsKKyAgICB3cml0ZVVJ
bnQzMihyZXN1bHQsIG9mZnNldCk7CisgICAgb2Zmc2V0ICs9IGZvbnROYW1lLmxlbmd0aCgpOwor
ICAgIHdyaXRlVUludDMyKHJlc3VsdCwgb2Zmc2V0KTsKKyAgICBpZiAoIXdlaWdodC5pc0VtcHR5
KCkpIHsKKyAgICAgICAgQVNTRVJUKHdlaWdodC5pczhCaXQoKSk7CisgICAgICAgIG9mZnNldCAr
PSB3ZWlnaHQubGVuZ3RoKCk7CisgICAgICAgIHdyaXRlVUludDMyKHJlc3VsdCwgb2Zmc2V0KTsK
KyAgICB9CisgICAgcmVzdWx0LmFwcGVuZChmb250TmFtZS5jaGFyYWN0ZXJzOCgpLCBmb250TmFt
ZS5sZW5ndGgoKSk7CisgICAgcmVzdWx0LmFwcGVuZCh3ZWlnaHQuY2hhcmFjdGVyczgoKSwgd2Vp
Z2h0Lmxlbmd0aCgpKTsKKworICAgIHdyaXRlVUludDE2KHJlc3VsdCwgMCk7IC8vIEVtcHR5IHN1
YnJvdXRpbmUgSU5ERVgKKworICAgIC8vIENoYXJzZXQgaW5mbworICAgIG92ZXJ3cml0ZVVJbnQz
MihyZXN1bHQsIGNoYXJzZXRPZmZzZXRMb2NhdGlvbiwgcmVzdWx0LnNpemUoKSk7CisgICAgcmVz
dWx0LmFwcGVuZCgwKTsKKyAgICBmb3IgKHVuc2lnbmVkIGkgPSAxOyBpIDwgbV9nbHlwaHMuc2l6
ZSgpOyArK2kpCisgICAgICAgIHdyaXRlVUludDE2KHJlc3VsdCwgaSk7CisKKyAgICAvLyBDaGFy
U3RyaW5ncyBJTkRFWAorICAgIG92ZXJ3cml0ZVVJbnQzMihyZXN1bHQsIGNoYXJzdHJpbmdzT2Zm
c2V0TG9jYXRpb24sIHJlc3VsdC5zaXplKCkpOworICAgIHdyaXRlVUludDE2KHJlc3VsdCwgbV9n
bHlwaHMuc2l6ZSgpKTsKKyAgICByZXN1bHQuYXBwZW5kKDQpOyAvLyBPZmZzZXRzIGluIHRoaXMg
SU5ERVggYXJlIDQgYnl0ZXMgbG9uZworICAgIG9mZnNldCA9IDE7CisgICAgd3JpdGVVSW50MzIo
cmVzdWx0LCBvZmZzZXQpOworICAgIGZvciAoY29uc3QgYXV0byYgZ2x5cGggOiBtX2dseXBocykg
eworICAgICAgICBvZmZzZXQgKz0gZ2x5cGguY2hhclN0cmluZy5zaXplKCk7CisgICAgICAgIHdy
aXRlVUludDMyKHJlc3VsdCwgb2Zmc2V0KTsKKyAgICB9CisgICAgZm9yIChjb25zdCBhdXRvJiBn
bHlwaCA6IG1fZ2x5cGhzKQorICAgICAgICByZXN1bHQuYXBwZW5kVmVjdG9yKGdseXBoLmNoYXJT
dHJpbmcpOworCisgICAgcmV0dXJuIHJlc3VsdDsKK30KKworVmVjdG9yPGNoYXI+IFNWR1RvT1RG
Rm9udENvbnZlcnRlcjo6Y3JlYXRlVk9SR1RhYmxlKCkKK3sKKyAgICBWZWN0b3I8Y2hhcj4gcmVz
dWx0OworICAgIHdyaXRlVUludDE2KHJlc3VsdCwgMSk7IC8vIE1ham9yIHZlcnNpb24KKyAgICB3
cml0ZVVJbnQxNihyZXN1bHQsIDApOyAvLyBNaW5vciB2ZXJzaW9uCisKKyAgICAvLyBGSVhNRTog
V2UgY2FuIHVzZSB0aGUgbWlzc2luZyBnbHlwaCBpbmZvIGZvciB0aGlzCisgICAgaW50MTZfdCBk
ZWZhdWx0VmVydGljYWxPcmlnaW5ZID0gMDsKKyAgICBjb25zdCBhdXRvJiBhdHRyaWJ1dGUgPSBt
X2ZvbnRFbGVtZW50LmZhc3RHZXRBdHRyaWJ1dGUoU1ZHTmFtZXM6OnZlcnRfb3JpZ2luX3lBdHRy
KTsKKyAgICBpZiAoYXR0cmlidXRlICE9IG51bGxBdG9tICYmIGF0dHJpYnV0ZS5pczhCaXQoKSkg
eworICAgICAgICBpZiAoaW50IHZlcnRpY2FsT3JpZ2luWSA9IGF0b2kocmVpbnRlcnByZXRfY2Fz
dF9wdHI8Y29uc3QgY2hhcio+KGF0dHJpYnV0ZS5jaGFyYWN0ZXJzOCgpKSkpCisgICAgICAgICAg
ICBkZWZhdWx0VmVydGljYWxPcmlnaW5ZID0gdmVydGljYWxPcmlnaW5ZOworICAgIH0KKyAgICB3
cml0ZVVJbnQxNihyZXN1bHQsIGRlZmF1bHRWZXJ0aWNhbE9yaWdpblkpOworCisgICAgVmVjdG9y
PHN0ZDo6cGFpcjx1aW50MTZfdCwgaW50MTZfdD4+IG9yaWdpbnM7CisgICAgZm9yICh1aW50MTZf
dCBpID0gMDsgaSA8IG1fZ2x5cGhzLnNpemUoKTsgKytpKSB7CisgICAgICAgIGlmIChtX2dseXBo
c1tpXS5nbHlwaEVsZW1lbnQpIHsKKyAgICAgICAgICAgIGNvbnN0IGF1dG8mIGF0dHJpYnV0ZSA9
IG1fZ2x5cGhzW2ldLmdseXBoRWxlbWVudC0+ZmFzdEdldEF0dHJpYnV0ZShTVkdOYW1lczo6dmVy
dF9vcmlnaW5feUF0dHIpOworICAgICAgICAgICAgaWYgKGF0dHJpYnV0ZSAhPSBudWxsQXRvbSAm
JiBhdHRyaWJ1dGUuaXM4Qml0KCkpIHsKKyAgICAgICAgICAgICAgICBpZiAoaW50MTZfdCB2ZXJ0
aWNhbE9yaWdpblkgPSBhdG9pKHJlaW50ZXJwcmV0X2Nhc3RfcHRyPGNvbnN0IGNoYXIqPihhdHRy
aWJ1dGUuY2hhcmFjdGVyczgoKSkpKQorICAgICAgICAgICAgICAgICAgICBvcmlnaW5zLmFwcGVu
ZChzdGQ6Om1ha2VfcGFpcihpLCB2ZXJ0aWNhbE9yaWdpblkpKTsKKyAgICAgICAgICAgIH0KKyAg
ICAgICAgfQorICAgIH0KKyAgICB3cml0ZVVJbnQxNihyZXN1bHQsIG9yaWdpbnMuc2l6ZSgpKTsK
KworICAgIGZvciAoY29uc3QgYXV0byYgcCA6IG9yaWdpbnMpIHsKKyAgICAgICAgd3JpdGVVSW50
MTYocmVzdWx0LCBwLmZpcnN0KTsKKyAgICAgICAgd3JpdGVVSW50MTYocmVzdWx0LCBwLnNlY29u
ZCk7CisgICAgfQorICAgIHJldHVybiByZXN1bHQ7Cit9CisKK3N0YXRpYyB2b2lkIHdyaXRlQ0ZG
RW5jb2RlZE51bWJlcihWZWN0b3I8Y2hhcj4mIHZlY3RvciwgZmxvYXQgbnVtYmVyKQoreworICAg
IGludCByYXcgPSBudW1iZXIgKiBwb3coMiwgMTYpOworICAgIHZlY3Rvci5hcHBlbmQoLTEpOyAv
LyAweEZGCisgICAgd3JpdGVVSW50MzIodmVjdG9yLCByYXcpOworfQorCitzdGF0aWMgY29uc3Qg
Y2hhciByTGluZVRvID0gMHgwNTsKK3N0YXRpYyBjb25zdCBjaGFyIHJyQ3VydmVUbyA9IDB4MDg7
CitzdGF0aWMgY29uc3QgY2hhciBlbmRDaGFyID0gMHgwZTsKK3N0YXRpYyBjb25zdCBjaGFyIHJN
b3ZlVG8gPSAweDE1OworCitjbGFzcyBDRkZCdWlsZGVyIDogcHVibGljIFNWR1BhdGhCdWlsZGVy
IHsKK3B1YmxpYzoKKyAgICBDRkZCdWlsZGVyKFZlY3RvcjxjaGFyPiYgY2ZmRGF0YSwgZmxvYXQg
d2lkdGgpCisgICAgICAgIDogbV9jZmZEYXRhKGNmZkRhdGEpCisgICAgICAgICwgbV9maXJzdFBv
aW50KHRydWUpCisgICAgeworICAgICAgICAvLyBGSVhNRTogV2UgcHJvYmFibHkgd2FudCB0aGUg
aW5pdGlhbCBtb3ZldG8gdG8gdXNlIGhvcml6LW9yaWdpbi14IGFuZCBob3Jpei1vcmlnaW4teS4u
LiB1bmxlc3Mgd2UncmUgdmVydGljYWwuLi4KKyAgICAgICAgd3JpdGVDRkZFbmNvZGVkTnVtYmVy
KG1fY2ZmRGF0YSwgd2lkdGgpOworICAgICAgICB3cml0ZUNGRkVuY29kZWROdW1iZXIobV9jZmZE
YXRhLCAwKTsKKyAgICAgICAgd3JpdGVDRkZFbmNvZGVkTnVtYmVyKG1fY2ZmRGF0YSwgMCk7Cisg
ICAgICAgIG1fY2ZmRGF0YS5hcHBlbmQock1vdmVUbyk7CisgICAgfQorCisgICAgdm9pZCB1cGRh
dGVGb3JDb25zdGl0dWVudFBvaW50KEZsb2F0UG9pbnQgeCkKKyAgICB7CisgICAgICAgIGlmICht
X2ZpcnN0UG9pbnQpCisgICAgICAgICAgICBtX2JvdW5kaW5nQm94ID0gRmxvYXRSZWN0KHgsIEZs
b2F0U2l6ZSgpKTsKKyAgICAgICAgZWxzZQorICAgICAgICAgICAgbV9ib3VuZGluZ0JveC5leHRl
bmQoeCk7CisgICAgICAgIG1fZmlyc3RQb2ludCA9IGZhbHNlOworICAgIH0KKworICAgIHZvaWQg
bW92ZVRvKGNvbnN0IEZsb2F0UG9pbnQmIHRhcmdldFBvaW50LCBib29sIGNsb3NlZCwgUGF0aENv
b3JkaW5hdGVNb2RlIG1vZGUpIG92ZXJyaWRlCisgICAgeworICAgICAgICBGbG9hdFBvaW50IGRl
c3RpbmF0aW9uID0gbW9kZSA9PSBBYnNvbHV0ZUNvb3JkaW5hdGVzID8gdGFyZ2V0UG9pbnQgOiBt
X2N1cnJlbnQgKyB0YXJnZXRQb2ludDsKKyAgICAgICAgdXBkYXRlRm9yQ29uc3RpdHVlbnRQb2lu
dChkZXN0aW5hdGlvbik7CisgICAgICAgIEZsb2F0U2l6ZSBkZWx0YSA9IGRlc3RpbmF0aW9uIC0g
bV9jdXJyZW50OworCisgICAgICAgIGlmIChjbG9zZWQgJiYgbV9jZmZEYXRhLnNpemUoKSkKKyAg
ICAgICAgICAgIGNsb3NlUGF0aCgpOworCisgICAgICAgIHdyaXRlQ0ZGRW5jb2RlZE51bWJlciht
X2NmZkRhdGEsIGRlbHRhLndpZHRoKCkpOworICAgICAgICB3cml0ZUNGRkVuY29kZWROdW1iZXIo
bV9jZmZEYXRhLCBkZWx0YS5oZWlnaHQoKSk7CisgICAgICAgIG1fY2ZmRGF0YS5hcHBlbmQock1v
dmVUbyk7CisKKyAgICAgICAgbV9jdXJyZW50ID0gZGVzdGluYXRpb247CisgICAgICAgIG1fc3Rh
cnRpbmdQb2ludCA9IG1fY3VycmVudDsKKyAgICB9CisKKyAgICB2b2lkIGxpbmVUbyhjb25zdCBG
bG9hdFBvaW50JiB0YXJnZXRQb2ludCwgUGF0aENvb3JkaW5hdGVNb2RlIG1vZGUpIG92ZXJyaWRl
CisgICAgeworICAgICAgICBGbG9hdFBvaW50IGRlc3RpbmF0aW9uID0gbW9kZSA9PSBBYnNvbHV0
ZUNvb3JkaW5hdGVzID8gdGFyZ2V0UG9pbnQgOiBtX2N1cnJlbnQgKyB0YXJnZXRQb2ludDsKKyAg
ICAgICAgdXBkYXRlRm9yQ29uc3RpdHVlbnRQb2ludChkZXN0aW5hdGlvbik7CisgICAgICAgIEZs
b2F0U2l6ZSBkZWx0YSA9IGRlc3RpbmF0aW9uIC0gbV9jdXJyZW50OworCisgICAgICAgIHdyaXRl
Q0ZGRW5jb2RlZE51bWJlcihtX2NmZkRhdGEsIGRlbHRhLndpZHRoKCkpOworICAgICAgICB3cml0
ZUNGRkVuY29kZWROdW1iZXIobV9jZmZEYXRhLCBkZWx0YS5oZWlnaHQoKSk7CisgICAgICAgIG1f
Y2ZmRGF0YS5hcHBlbmQockxpbmVUbyk7CisKKyAgICAgICAgbV9jdXJyZW50ID0gZGVzdGluYXRp
b247CisgICAgfQorCisgICAgdm9pZCBjdXJ2ZVRvQ3ViaWMoY29uc3QgRmxvYXRQb2ludCYgcG9p
bnQxLCBjb25zdCBGbG9hdFBvaW50JiBwb2ludDIsIGNvbnN0IEZsb2F0UG9pbnQmIHRhcmdldFBv
aW50LCBQYXRoQ29vcmRpbmF0ZU1vZGUgbW9kZSkgb3ZlcnJpZGUKKyAgICB7CisgICAgICAgIC8v
IEZJWE1FOiBUaGlzIGNhbiBiZSBtYWRlIHdheSBmYXN0ZXIKKyAgICAgICAgRmxvYXRQb2ludCBk
ZXN0aW5hdGlvbjEgPSBwb2ludDE7CisgICAgICAgIEZsb2F0UG9pbnQgZGVzdGluYXRpb24yID0g
cG9pbnQyOworICAgICAgICBGbG9hdFBvaW50IGRlc3RpbmF0aW9uMyA9IHRhcmdldFBvaW50Owor
ICAgICAgICBpZiAobW9kZSA9PSBSZWxhdGl2ZUNvb3JkaW5hdGVzKSB7CisgICAgICAgICAgICBk
ZXN0aW5hdGlvbjEgKz0gbV9jdXJyZW50OworICAgICAgICAgICAgZGVzdGluYXRpb24yICs9IG1f
Y3VycmVudDsKKyAgICAgICAgICAgIGRlc3RpbmF0aW9uMyArPSBtX2N1cnJlbnQ7CisgICAgICAg
IH0KKyAgICAgICAgdXBkYXRlRm9yQ29uc3RpdHVlbnRQb2ludChkZXN0aW5hdGlvbjEpOworICAg
ICAgICB1cGRhdGVGb3JDb25zdGl0dWVudFBvaW50KGRlc3RpbmF0aW9uMik7CisgICAgICAgIHVw
ZGF0ZUZvckNvbnN0aXR1ZW50UG9pbnQoZGVzdGluYXRpb24zKTsKKyAgICAgICAgRmxvYXRTaXpl
IGRlbHRhMyA9IGRlc3RpbmF0aW9uMyAtIGRlc3RpbmF0aW9uMjsKKyAgICAgICAgRmxvYXRTaXpl
IGRlbHRhMiA9IGRlc3RpbmF0aW9uMiAtIGRlc3RpbmF0aW9uMTsKKyAgICAgICAgRmxvYXRTaXpl
IGRlbHRhMSA9IGRlc3RpbmF0aW9uMSAtIG1fY3VycmVudDsKKworICAgICAgICB3cml0ZUNGRkVu
Y29kZWROdW1iZXIobV9jZmZEYXRhLCBkZWx0YTEud2lkdGgoKSk7CisgICAgICAgIHdyaXRlQ0ZG
RW5jb2RlZE51bWJlcihtX2NmZkRhdGEsIGRlbHRhMS5oZWlnaHQoKSk7CisgICAgICAgIHdyaXRl
Q0ZGRW5jb2RlZE51bWJlcihtX2NmZkRhdGEsIGRlbHRhMi53aWR0aCgpKTsKKyAgICAgICAgd3Jp
dGVDRkZFbmNvZGVkTnVtYmVyKG1fY2ZmRGF0YSwgZGVsdGEyLmhlaWdodCgpKTsKKyAgICAgICAg
d3JpdGVDRkZFbmNvZGVkTnVtYmVyKG1fY2ZmRGF0YSwgZGVsdGEzLndpZHRoKCkpOworICAgICAg
ICB3cml0ZUNGRkVuY29kZWROdW1iZXIobV9jZmZEYXRhLCBkZWx0YTMuaGVpZ2h0KCkpOworICAg
ICAgICBtX2NmZkRhdGEuYXBwZW5kKHJyQ3VydmVUbyk7CisKKyAgICAgICAgbV9jdXJyZW50ID0g
ZGVzdGluYXRpb24zOworICAgIH0KKworICAgIHZvaWQgY2xvc2VQYXRoKCkgb3ZlcnJpZGUKKyAg
ICB7CisgICAgICAgIGlmIChtX2N1cnJlbnQgIT0gbV9zdGFydGluZ1BvaW50KQorICAgICAgICAg
ICAgbGluZVRvKG1fc3RhcnRpbmdQb2ludCwgQWJzb2x1dGVDb29yZGluYXRlcyk7CisgICAgfQor
CisgICAgRmxvYXRSZWN0IGJvdW5kaW5nQm94KCkKKyAgICB7CisgICAgICAgIHJldHVybiBtX2Jv
dW5kaW5nQm94OworICAgIH0KKworcHJpdmF0ZToKKyAgICBWZWN0b3I8Y2hhcj4mIG1fY2ZmRGF0
YTsKKyAgICBGbG9hdFBvaW50IG1fc3RhcnRpbmdQb2ludDsKKyAgICBGbG9hdFJlY3QgbV9ib3Vu
ZGluZ0JveDsKKyAgICBib29sIG1fZmlyc3RQb2ludDsKK307CisKK3N0YXRpYyBWZWN0b3I8Y2hh
cj4gdHJhbnNjb2RlR2x5cGhQYXRocyhmbG9hdCB3aWR0aCwgY29uc3QgU1ZHR2x5cGhFbGVtZW50
JiBnbHlwaEVsZW1lbnQsIEZsb2F0UmVjdCYgYm91bmRpbmdCb3gpCit7CisgICAgVmVjdG9yPGNo
YXI+IHJlc3VsdDsKKyAgICBjb25zdCBhdXRvJiBkQXR0cmlidXRlID0gZ2x5cGhFbGVtZW50LmZh
c3RHZXRBdHRyaWJ1dGUoU1ZHTmFtZXM6OmRBdHRyKTsKKyAgICBpZiAoZEF0dHJpYnV0ZS5pc0Vt
cHR5KCkpIHsKKyAgICAgICAgd3JpdGVDRkZFbmNvZGVkTnVtYmVyKHJlc3VsdCwgd2lkdGgpOwor
ICAgICAgICB3cml0ZUNGRkVuY29kZWROdW1iZXIocmVzdWx0LCAwKTsKKyAgICAgICAgd3JpdGVD
RkZFbmNvZGVkTnVtYmVyKHJlc3VsdCwgMCk7CisgICAgICAgIHJlc3VsdC5hcHBlbmQock1vdmVU
byk7CisgICAgICAgIHJlc3VsdC5hcHBlbmQoZW5kQ2hhcik7CisgICAgICAgIHJldHVybiByZXN1
bHQ7CisgICAgfQorCisgICAgQ0ZGQnVpbGRlciBidWlsZGVyKHJlc3VsdCwgd2lkdGgpOworICAg
IFNWR1BhdGhTdHJpbmdTb3VyY2Ugc291cmNlKGRBdHRyaWJ1dGUpOworICAgIFNWR1BhdGhQYXJz
ZXIgcGFyc2VyOworICAgIHBhcnNlci5zZXRDdXJyZW50U291cmNlKCZzb3VyY2UpOworICAgIHBh
cnNlci5zZXRDdXJyZW50Q29uc3VtZXIoJmJ1aWxkZXIpOworCisgICAgYm9vbCBvayA9IHBhcnNl
ci5wYXJzZVBhdGhEYXRhRnJvbVNvdXJjZShOb3JtYWxpemVkUGFyc2luZyk7CisgICAgcGFyc2Vy
LmNsZWFudXAoKTsKKworICAgIGlmICghb2spCisgICAgICAgIHJlc3VsdC5jbGVhcigpOworCisg
ICAgYm91bmRpbmdCb3ggPSBidWlsZGVyLmJvdW5kaW5nQm94KCk7CisKKyAgICByZXN1bHQuYXBw
ZW5kKGVuZENoYXIpOworICAgIHJldHVybiByZXN1bHQ7Cit9CisKK2Jvb2wgU1ZHVG9PVEZGb250
Q29udmVydGVyOjpjb21wYXJlR2x5cGhEYXRhKGNvbnN0IEdseXBoRGF0YSYgZGF0YTEsIGNvbnN0
IEdseXBoRGF0YSYgZGF0YTIpCit7CisgICAgcmV0dXJuIGRhdGExLmNvZGVwb2ludCA8IGRhdGEy
LmNvZGVwb2ludDsKK30KKworU1ZHVG9PVEZGb250Q29udmVydGVyOjpTVkdUb09URkZvbnRDb252
ZXJ0ZXIoY29uc3QgU1ZHRm9udEVsZW1lbnQmIGZvbnRFbGVtZW50KQorICAgIDogbV9mb250RWxl
bWVudChmb250RWxlbWVudCkKKyAgICAsIG1fZm9udEZhY2VFbGVtZW50KGNoaWxkcmVuT2ZUeXBl
PFNWR0ZvbnRGYWNlRWxlbWVudD4obV9mb250RWxlbWVudCkuZmlyc3QoKSkKKyAgICAsIG1fYWR2
YW5jZVdpZHRoTWF4KDApCisgICAgLCBtX21pblJpZ2h0U2lkZUJlYXJpbmcoc3RkOjpudW1lcmlj
X2xpbWl0czxmbG9hdD46Om1heCgpKQorICAgICwgbV93ZWlnaHQoNSkKKyAgICAsIG1faXRhbGlj
KGZhbHNlKQoreworICAgIC8vIEZJWE1FOiBVc2UgdGhlIG1pc3NpbmdHbHlwaCBpbmZvCisgICAg
VmVjdG9yPGNoYXIsIDE+IG5vdGRlZkNoYXJTdHJpbmc7CisgICAgbm90ZGVmQ2hhclN0cmluZy5h
cHBlbmQoZW5kQ2hhcik7CisgICAgbV9nbHlwaHMuYXBwZW5kKEdseXBoRGF0YShub3RkZWZDaGFy
U3RyaW5nLCBudWxscHRyLCBtX2ZvbnRGYWNlRWxlbWVudCA/IG1fZm9udEZhY2VFbGVtZW50LT51
bml0c1BlckVtKCkgOiAwLCBGbG9hdFJlY3QoKSwgMCkpOworICAgIGJvb2wgaW5pdGlhbEdseXBo
ID0gdHJ1ZTsKKyAgICBmb3IgKGNvbnN0IGF1dG8mIGdseXBoIDogY2hpbGRyZW5PZlR5cGU8U1ZH
R2x5cGhFbGVtZW50PihtX2ZvbnRFbGVtZW50KSkgeworICAgICAgICBjb25zdCBhdXRvJiB1bmlj
b2RlQXR0cmlidXRlID0gZ2x5cGguZ2V0QXR0cmlidXRlKCJ1bmljb2RlIik7CisgICAgICAgIC8v
IE9ubHkgc3VwcG9ydCBCYXNpYyBNdWx0aWxpbmd1YWwgUGxhbmUgdy9vIGxpZ2F0dXJlcyBmb3Ig
bm93CisgICAgICAgIGlmICh1bmljb2RlQXR0cmlidXRlLmxlbmd0aCgpID09IDEpIHsKKyAgICAg
ICAgICAgIGZsb2F0IGVmZmVjdGl2ZUFkdmFuY2UgPSAwOworICAgICAgICAgICAgY29uc3QgYXV0
byYgYWR2YW5jZUF0dHJpYnV0ZSA9IGdseXBoLmZhc3RHZXRBdHRyaWJ1dGUoU1ZHTmFtZXM6Omhv
cml6X2Fkdl94QXR0cik7CisgICAgICAgICAgICBpZiAoIWFkdmFuY2VBdHRyaWJ1dGUuaXNFbXB0
eSgpKSB7CisgICAgICAgICAgICAgICAgYm9vbCBvayA9IHRydWU7CisgICAgICAgICAgICAgICAg
ZmxvYXQgYWR2YW5jZSA9IGFkdmFuY2VBdHRyaWJ1dGUudG9GbG9hdCgmb2spOworICAgICAgICAg
ICAgICAgIGlmIChvaykgeworICAgICAgICAgICAgICAgICAgICBlZmZlY3RpdmVBZHZhbmNlID0g
YWR2YW5jZTsKKyAgICAgICAgICAgICAgICAgICAgbV9hZHZhbmNlV2lkdGhNYXggPSBzdGQ6Om1h
eChtX2FkdmFuY2VXaWR0aE1heCwgYWR2YW5jZSk7CisgICAgICAgICAgICAgICAgfQorICAgICAg
ICAgICAgfQorCisgICAgICAgICAgICBGbG9hdFJlY3QgZ2x5cGhCb3VuZGluZ0JveDsKKyAgICAg
ICAgICAgIGNvbnN0IGF1dG8mIHBhdGggPSB0cmFuc2NvZGVHbHlwaFBhdGhzKGVmZmVjdGl2ZUFk
dmFuY2UsIGdseXBoLCBnbHlwaEJvdW5kaW5nQm94KTsKKyAgICAgICAgICAgIGlmIChpbml0aWFs
R2x5cGgpCisgICAgICAgICAgICAgICAgbV9ib3VuZGluZ0JveCA9IGdseXBoQm91bmRpbmdCb3g7
CisgICAgICAgICAgICBlbHNlCisgICAgICAgICAgICAgICAgbV9ib3VuZGluZ0JveC51bml0ZShn
bHlwaEJvdW5kaW5nQm94KTsKKyAgICAgICAgICAgIG1fbWluUmlnaHRTaWRlQmVhcmluZyA9IHN0
ZDo6bWluKG1fbWluUmlnaHRTaWRlQmVhcmluZywgZWZmZWN0aXZlQWR2YW5jZSAtIGdseXBoQm91
bmRpbmdCb3gubWF4WCgpKTsKKyAgICAgICAgICAgIGluaXRpYWxHbHlwaCA9IGZhbHNlOworCisg
ICAgICAgICAgICBtX2dseXBocy5hcHBlbmQoR2x5cGhEYXRhKHBhdGgsICZnbHlwaCwgZWZmZWN0
aXZlQWR2YW5jZSwgZ2x5cGhCb3VuZGluZ0JveCwgdW5pY29kZUF0dHJpYnV0ZVswXSkpOworICAg
ICAgICB9CisgICAgfQorICAgIHN0ZDo6c29ydChtX2dseXBocy5iZWdpbigpLCBtX2dseXBocy5l
bmQoKSwgJmNvbXBhcmVHbHlwaERhdGEpOworCisgICAgLy8gRklYTUU6IEhhbmRsZSBjb21tYXMK
KyAgICBpZiAobV9mb250RmFjZUVsZW1lbnQpIHsKKyAgICAgICAgY29uc3QgYXV0byYgZm9udFdl
aWdodEF0dHJpYnV0ZSA9IG1fZm9udEZhY2VFbGVtZW50LT5mYXN0R2V0QXR0cmlidXRlKFNWR05h
bWVzOjpmb250X3dlaWdodEF0dHIpOworICAgICAgICBWZWN0b3I8U3RyaW5nPiBzcGxpdDsKKyAg
ICAgICAgU3RyaW5nKGZvbnRXZWlnaHRBdHRyaWJ1dGUpLnNwbGl0KCIgIiwgc3BsaXQpOworICAg
ICAgICBmb3IgKGNvbnN0IGF1dG8mIHMgOiBzcGxpdCkgeworICAgICAgICAgICAgaWYgKHMgPT0g
ImJvbGQiKQorICAgICAgICAgICAgICAgIG1fd2VpZ2h0ID0gNzsKKyAgICAgICAgICAgIGJvb2wg
b2sgPSB0cnVlOworICAgICAgICAgICAgaW50IHZhbHVlID0gcy50b0ludCgmb2spOworICAgICAg
ICAgICAgaWYgKG9rICYmIHZhbHVlID49IDAgJiYgdmFsdWUgPCAxMDAwKQorICAgICAgICAgICAg
ICAgIG1fd2VpZ2h0ID0gdmFsdWUgLyAxMDA7CisgICAgICAgIH0KKyAgICAgICAgY29uc3QgYXV0
byYgZm9udFN0eWxlQXR0cmlidXRlID0gbV9mb250RmFjZUVsZW1lbnQtPmZhc3RHZXRBdHRyaWJ1
dGUoU1ZHTmFtZXM6OmZvbnRfd2VpZ2h0QXR0cik7CisgICAgICAgIHNwbGl0LmNsZWFyKCk7Cisg
ICAgICAgIFN0cmluZyhmb250U3R5bGVBdHRyaWJ1dGUpLnNwbGl0KCIgIiwgc3BsaXQpOworICAg
ICAgICBmb3IgKGNvbnN0IGF1dG8mIHMgOiBzcGxpdCkgeworICAgICAgICAgICAgaWYgKHMgPT0g
Iml0YWxpYyIgfHwgcyA9PSAib2JsaXF1ZSIpCisgICAgICAgICAgICAgICAgbV9pdGFsaWMgPSB0
cnVlOworICAgICAgICB9CisgICAgfQorCisgICAgLy8gTWlnaHQgbm90IGJlIHF1aXRlIHdoYXQg
SSB3YW50CisgICAgaWYgKG1fZm9udEZhY2VFbGVtZW50KQorICAgICAgICBtX2ZvbnRGYW1pbHkg
PSBtX2ZvbnRGYWNlRWxlbWVudC0+Zm9udEZhbWlseSgpOworfQorCitzdGF0aWMgdWludDMyX3Qg
Y2FsY3VsYXRlQ2hlY2tzdW0oY29uc3QgVmVjdG9yPGNoYXI+JiB0YWJsZSkKK3sKKyAgICBBU1NF
UlQoIShyZWludGVycHJldF9jYXN0PHNpemVfdD4odGFibGUuZGF0YSgpKSAmIHNpemVvZih1aW50
MzJfdCktMSkpOworICAgIHVpbnQzMl90IHN1bSA9IDA7CisgICAgY29uc3QgdWludDMyX3QqIHB0
ciA9IHJlaW50ZXJwcmV0X2Nhc3RfcHRyPGNvbnN0IHVpbnQzMl90Kj4odGFibGUuZGF0YSgpKTsK
KyAgICBjb25zdCB1aW50MzJfdCogY29uc3QgZW5kUHRyID0gcmVpbnRlcnByZXRfY2FzdF9wdHI8
Y29uc3QgdWludDMyX3QqPih0YWJsZS5kYXRhKCkgKyB0YWJsZS5zaXplKCkpOworICAgIGZvciAo
OyBwdHIgPCBlbmRQdHI7ICsrcHRyKQorICAgICAgICBzdW0gKz0gKnB0cjsKKyAgICBBU1NFUlQo
cHRyID09IGVuZFB0cik7CisgICAgcmV0dXJuIHN1bTsKK30KKworc3RhdGljIHZvaWQgYXBwZW5k
VGFibGVEaXJlY3RvcnlFbnRyeShjb25zdCBjaGFyIGlkZW50aWZpZXJbNF0sIFZlY3RvcjxjaGFy
PiYgc25mdCwgVmVjdG9yPGNoYXI+JiB0YWJsZSwgdWludDMyX3QmIG9mZnNldCkKK3sKKyAgICB1
aW50MzJfdCBzaXplID0gdGFibGUuc2l6ZSgpOworICAgIHdoaWxlICh0YWJsZS5zaXplKCkgJSBz
aXplb2YodWludDMyX3QpKQorICAgICAgICB0YWJsZS5hcHBlbmQoc3RhdGljX2Nhc3Q8Y2hhcj4o
MCkpOworCisgICAgc25mdC5hcHBlbmQoaWRlbnRpZmllclswXSk7CisgICAgc25mdC5hcHBlbmQo
aWRlbnRpZmllclsxXSk7CisgICAgc25mdC5hcHBlbmQoaWRlbnRpZmllclsyXSk7CisgICAgc25m
dC5hcHBlbmQoaWRlbnRpZmllclszXSk7CisgICAgd3JpdGVVSW50MzIoc25mdCwgY2FsY3VsYXRl
Q2hlY2tzdW0odGFibGUpKTsKKyAgICB3cml0ZVVJbnQzMihzbmZ0LCBvZmZzZXQpOworICAgIHdy
aXRlVUludDMyKHNuZnQsIHNpemUpOworICAgIG9mZnNldCArPSB0YWJsZS5zaXplKCk7Cit9CisK
K1ZlY3RvcjxjaGFyPiBTVkdUb09URkZvbnRDb252ZXJ0ZXI6OmNvbnZlcnRTVkdUb09URkZvbnQo
KQoreworICAgIFZlY3RvcjxjaGFyPiByZXN1bHQ7CisgICAgaWYgKG1fZ2x5cGhzLnNpemUoKSA+
IDB4RkZGRiB8fCAhbV9nbHlwaHMuc2l6ZSgpKQorICAgICAgICByZXR1cm4gcmVzdWx0OworCisg
ICAgdWludDE2X3QgbnVtVGFibGVzID0gMTA7CisgICAgdWludDE2X3Qgcm91bmRlZE51bVRhYmxl
cyA9IHJvdW5kRG93blRvUG93ZXJPZlR3byhudW1UYWJsZXMpOworICAgIHVpbnQxNl90IHNlYXJj
aFJhbmdlID0gcm91bmRlZE51bVRhYmxlcyAqIDE2OworICAgIHVpbnQxNl90IGVudHJ5U2VsZWN0
b3IgPSAwOworICAgIHdoaWxlIChyb3VuZGVkTnVtVGFibGVzID4+PSAxKQorICAgICAgICArK2Vu
dHJ5U2VsZWN0b3I7CisKKyAgICByZXN1bHQuYXBwZW5kKCdPJyk7CisgICAgcmVzdWx0LmFwcGVu
ZCgnVCcpOworICAgIHJlc3VsdC5hcHBlbmQoJ1QnKTsKKyAgICByZXN1bHQuYXBwZW5kKCdPJyk7
CisgICAgd3JpdGVVSW50MTYocmVzdWx0LCBudW1UYWJsZXMpOworICAgIHdyaXRlVUludDE2KHJl
c3VsdCwgc2VhcmNoUmFuZ2UpOworICAgIHdyaXRlVUludDE2KHJlc3VsdCwgZW50cnlTZWxlY3Rv
cik7CisgICAgd3JpdGVVSW50MTYocmVzdWx0LCBudW1UYWJsZXMgKiAxNiAtIHNlYXJjaFJhbmdl
KTsKKworICAgIC8vIEZJWE1FOiBJbXBsZW1lbnQgbW9yZSB0YWJsZXMsIGxpa2UgdmhlYSBhbmQg
dm10eCAoYW5kIGtlcm4hKQorICAgIGF1dG8gQ01BUFRhYmxlID0gY3JlYXRlQ01BUFRhYmxlKCk7
CisgICAgYXV0byBIRUFEVGFibGUgPSBjcmVhdGVIRUFEVGFibGUoKTsKKyAgICBhdXRvIEhIRUFU
YWJsZSA9IGNyZWF0ZUhIRUFUYWJsZSgpOworICAgIGF1dG8gSE1UWFRhYmxlID0gY3JlYXRlSE1U
WFRhYmxlKCk7CisgICAgYXV0byBNQVhQVGFibGUgPSBjcmVhdGVNQVhQVGFibGUoKTsKKyAgICBh
dXRvIE5BTUVUYWJsZSA9IGNyZWF0ZU5BTUVUYWJsZSgpOworICAgIGF1dG8gT1MyVGFibGUgPSBj
cmVhdGVPUzJUYWJsZSgpOworICAgIGF1dG8gUE9TVFRhYmxlID0gY3JlYXRlUE9TVFRhYmxlKCk7
CisgICAgYXV0byBDRkZUYWJsZSA9IGNyZWF0ZUNGRlRhYmxlKCk7CisgICAgYXV0byBWT1JHVGFi
bGUgPSBjcmVhdGVWT1JHVGFibGUoKTsKKworICAgIHVpbnQzMl90IG9mZnNldCA9IDE2ICogbnVt
VGFibGVzICsgMTI7CisgICAgYXBwZW5kVGFibGVEaXJlY3RvcnlFbnRyeSgiQ0ZGICIsIHJlc3Vs
dCwgQ0ZGVGFibGUsIG9mZnNldCk7CisgICAgYXBwZW5kVGFibGVEaXJlY3RvcnlFbnRyeSgiT1Mv
MiIsIHJlc3VsdCwgT1MyVGFibGUsIG9mZnNldCk7CisgICAgYXBwZW5kVGFibGVEaXJlY3RvcnlF
bnRyeSgiVk9SRyIsIHJlc3VsdCwgVk9SR1RhYmxlLCBvZmZzZXQpOworICAgIGFwcGVuZFRhYmxl
RGlyZWN0b3J5RW50cnkoImNtYXAiLCByZXN1bHQsIENNQVBUYWJsZSwgb2Zmc2V0KTsKKyAgICBh
cHBlbmRUYWJsZURpcmVjdG9yeUVudHJ5KCJoZWFkIiwgcmVzdWx0LCBIRUFEVGFibGUsIG9mZnNl
dCk7CisgICAgYXBwZW5kVGFibGVEaXJlY3RvcnlFbnRyeSgiaGhlYSIsIHJlc3VsdCwgSEhFQVRh
YmxlLCBvZmZzZXQpOworICAgIGFwcGVuZFRhYmxlRGlyZWN0b3J5RW50cnkoImhtdHgiLCByZXN1
bHQsIEhNVFhUYWJsZSwgb2Zmc2V0KTsKKyAgICBhcHBlbmRUYWJsZURpcmVjdG9yeUVudHJ5KCJt
YXhwIiwgcmVzdWx0LCBNQVhQVGFibGUsIG9mZnNldCk7CisgICAgYXBwZW5kVGFibGVEaXJlY3Rv
cnlFbnRyeSgibmFtZSIsIHJlc3VsdCwgTkFNRVRhYmxlLCBvZmZzZXQpOworICAgIGFwcGVuZFRh
YmxlRGlyZWN0b3J5RW50cnkoInBvc3QiLCByZXN1bHQsIFBPU1RUYWJsZSwgb2Zmc2V0KTsKKwor
ICAgIHJlc3VsdC5hcHBlbmRWZWN0b3IoQ0ZGVGFibGUpOworICAgIHJlc3VsdC5hcHBlbmRWZWN0
b3IoT1MyVGFibGUpOworICAgIHJlc3VsdC5hcHBlbmRWZWN0b3IoVk9SR1RhYmxlKTsKKyAgICBy
ZXN1bHQuYXBwZW5kVmVjdG9yKENNQVBUYWJsZSk7CisgICAgYXV0byBoZWFkVGFibGVPZmZzZXQg
PSByZXN1bHQuc2l6ZSgpOworICAgIHJlc3VsdC5hcHBlbmRWZWN0b3IoSEVBRFRhYmxlKTsKKyAg
ICByZXN1bHQuYXBwZW5kVmVjdG9yKEhIRUFUYWJsZSk7CisgICAgcmVzdWx0LmFwcGVuZFZlY3Rv
cihITVRYVGFibGUpOworICAgIHJlc3VsdC5hcHBlbmRWZWN0b3IoTUFYUFRhYmxlKTsKKyAgICBy
ZXN1bHQuYXBwZW5kVmVjdG9yKE5BTUVUYWJsZSk7CisgICAgcmVzdWx0LmFwcGVuZFZlY3RvcihQ
T1NUVGFibGUpOworCisgICAgLy8gY2hlY2tTdW1BZGp1c3RtZW50OiAiVG8gY29tcHV0ZTogc2V0
IGl0IHRvIDAsIGNhbGN1bGF0ZSB0aGUgY2hlY2tzdW0gZm9yIHRoZSAnaGVhZCcgdGFibGUgYW5k
IHB1dCBpdCBpbiB0aGUgdGFibGUgZGlyZWN0b3J5LAorICAgIC8vIHN1bSB0aGUgZW50aXJlIGZv
bnQgYXMgdWludDMyLCB0aGVuIHN0b3JlIEIxQjBBRkJBIC0gc3VtLiBUaGUgY2hlY2tzdW0gZm9y
IHRoZSAnaGVhZCcgdGFibGUgd2lsbCBub3cgYmUgd3JvbmcuIFRoYXQgaXMgT0suIgorICAgIHVp
bnQzMl90IGNoZWNrc3VtQWRqdXN0bWVudCA9IDB4QjFCMEFGQkFVIC0gY2FsY3VsYXRlQ2hlY2tz
dW0ocmVzdWx0KTsKKyAgICBvdmVyd3JpdGVVSW50MzIocmVzdWx0LCBoZWFkVGFibGVPZmZzZXQg
KyA4LCBjaGVja3N1bUFkanVzdG1lbnQpOworICAgIEFTU0VSVCgqcmVpbnRlcnByZXRfY2FzdF9w
dHI8Y29uc3QgdWludDMyX3QqPihyZXN1bHQuZGF0YSgpICsgaGVhZFRhYmxlT2Zmc2V0ICsgOCkg
PT0gaHRvbmwoY2hlY2tzdW1BZGp1c3RtZW50KSk7CisKKyAgICByZXR1cm4gcmVzdWx0OworfQor
CitWZWN0b3I8Y2hhcj4gY29udmVydFNWR1RvT1RGRm9udChjb25zdCBTVkdGb250RWxlbWVudCYg
ZWxlbWVudCkKK3sKKyAgICByZXR1cm4gU1ZHVG9PVEZGb250Q29udmVydGVyKGVsZW1lbnQpLmNv
bnZlcnRTVkdUb09URkZvbnQoKTsKK30KKworfQpkaWZmIC0tZ2l0IGEvU291cmNlL1dlYkNvcmUv
c3ZnL1NWR1RvT1RGRm9udENvbnZlcnNpb24uaCBiL1NvdXJjZS9XZWJDb3JlL3N2Zy9TVkdUb09U
RkZvbnRDb252ZXJzaW9uLmgKbmV3IGZpbGUgbW9kZSAxMDA2NDQKaW5kZXggMDAwMDAwMDAwMDAw
MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMC4uZGViMWUwYzJlMmI2NGYwMmZmY2MzYzdlYmZh
Yjg5NWI4MDkzNTgwYwotLS0gL2Rldi9udWxsCisrKyBiL1NvdXJjZS9XZWJDb3JlL3N2Zy9TVkdU
b09URkZvbnRDb252ZXJzaW9uLmgKQEAgLTAsMCArMSwzOSBAQAorLyoKKyAqIENvcHlyaWdodCAo
QykgMjAxMCBBcHBsZSBJbmMuIEFsbCByaWdodHMgcmVzZXJ2ZWQuCisgKgorICogUmVkaXN0cmli
dXRpb24gYW5kIHVzZSBpbiBzb3VyY2UgYW5kIGJpbmFyeSBmb3Jtcywgd2l0aCBvciB3aXRob3V0
CisgKiBtb2RpZmljYXRpb24sIGFyZSBwZXJtaXR0ZWQgcHJvdmlkZWQgdGhhdCB0aGUgZm9sbG93
aW5nIGNvbmRpdGlvbnMKKyAqIGFyZSBtZXQ6CisgKiAxLiBSZWRpc3RyaWJ1dGlvbnMgb2Ygc291
cmNlIGNvZGUgbXVzdCByZXRhaW4gdGhlIGFib3ZlIGNvcHlyaWdodAorICogICAgbm90aWNlLCB0
aGlzIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIGZvbGxvd2luZyBkaXNjbGFpbWVyLgorICog
Mi4gUmVkaXN0cmlidXRpb25zIGluIGJpbmFyeSBmb3JtIG11c3QgcmVwcm9kdWNlIHRoZSBhYm92
ZSBjb3B5cmlnaHQKKyAqICAgIG5vdGljZSwgdGhpcyBsaXN0IG9mIGNvbmRpdGlvbnMgYW5kIHRo
ZSBmb2xsb3dpbmcgZGlzY2xhaW1lciBpbiB0aGUKKyAqICAgIGRvY3VtZW50YXRpb24gYW5kL29y
IG90aGVyIG1hdGVyaWFscyBwcm92aWRlZCB3aXRoIHRoZSBkaXN0cmlidXRpb24uCisgKgorICog
VEhJUyBTT0ZUV0FSRSBJUyBQUk9WSURFRCBCWSBBUFBMRSBJTkMuIEFORCBJVFMgQ09OVFJJQlVU
T1JTIGBgQVMgSVMnJworICogQU5EIEFOWSBFWFBSRVNTIE9SIElNUExJRUQgV0FSUkFOVElFUywg
SU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sCisgKiBUSEUgSU1QTElFRCBXQVJSQU5USUVT
IE9GIE1FUkNIQU5UQUJJTElUWSBBTkQgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSCisgKiBQVVJQ
T1NFIEFSRSBESVNDTEFJTUVELiBJTiBOTyBFVkVOVCBTSEFMTCBBUFBMRSBJTkMuIE9SIElUUyBD
T05UUklCVVRPUlMKKyAqIEJFIExJQUJMRSBGT1IgQU5ZIERJUkVDVCwgSU5ESVJFQ1QsIElOQ0lE
RU5UQUwsIFNQRUNJQUwsIEVYRU1QTEFSWSwgT1IKKyAqIENPTlNFUVVFTlRJQUwgREFNQUdFUyAo
SU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFBST0NVUkVNRU5UIE9GCisgKiBTVUJTVElU
VVRFIEdPT0RTIE9SIFNFUlZJQ0VTOyBMT1NTIE9GIFVTRSwgREFUQSwgT1IgUFJPRklUUzsgT1Ig
QlVTSU5FU1MKKyAqIElOVEVSUlVQVElPTikgSE9XRVZFUiBDQVVTRUQgQU5EIE9OIEFOWSBUSEVP
UlkgT0YgTElBQklMSVRZLCBXSEVUSEVSIElOCisgKiBDT05UUkFDVCwgU1RSSUNUIExJQUJJTElU
WSwgT1IgVE9SVCAoSU5DTFVESU5HIE5FR0xJR0VOQ0UgT1IgT1RIRVJXSVNFKQorICogQVJJU0lO
RyBJTiBBTlkgV0FZIE9VVCBPRiBUSEUgVVNFIE9GIFRISVMgU09GVFdBUkUsIEVWRU4gSUYgQURW
SVNFRCBPRgorICogVEhFIFBPU1NJQklMSVRZIE9GIFNVQ0ggREFNQUdFLgorICovCisKKyNpZm5k
ZWYgU1ZHVG9PVEZGb250Q29udmVyc2lvbl9oCisjZGVmaW5lIFNWR1RvT1RGRm9udENvbnZlcnNp
b25faAorCisjaW5jbHVkZSA8V1RGL1ZlY3Rvci5oPgorCituYW1lc3BhY2UgV2ViQ29yZSB7CisK
K2NsYXNzIFNWR0ZvbnRFbGVtZW50OworCitWZWN0b3I8Y2hhcj4gY29udmVydFNWR1RvT1RGRm9u
dChjb25zdCBTVkdGb250RWxlbWVudCYpOworCit9CisKKyNlbmRpZgo=
</data>
<flag name="review"
          id="262622"
          type_id="1"
          status="+"
          setter="darin"
    />
          </attachment>
      

    </bug>

</bugzilla>