Skip to content

Feature: Support for clip-path#1562

Open
CaptainDario wants to merge 11 commits into
daohoangson:masterfrom
CaptainDario:feature-clip_path
Open

Feature: Support for clip-path#1562
CaptainDario wants to merge 11 commits into
daohoangson:masterfrom
CaptainDario:feature-clip_path

Conversation

@CaptainDario
Copy link
Copy Markdown
Contributor

@CaptainDario CaptainDario commented Mar 28, 2026

I want to make this package render the following HTML correctly.

HTML
<ol class="definition-list" data-count="1" style="--font-size-no-units: 16;--line-height: 1.5;--text-color: #d4d4d4;--text-color-light: #888888;--background-color: #1e1e1e;--border-color: #888888;--link-color: #68b5e9;--list-padding1: 1.4em;--list-padding2: 1.4em;list-style-type: none;padding-left: 0;margin: 0">
  <li class="definition-item" style="margin-bottom: 0.25em; list-style-type: none;">
    <span class="gloss-content" style="display: block;">
      <ul class="gloss-sc-ul" lang="ja" style="padding-left: 1.4em;margin: 0;list-style-type: '*'">
        <li class="gloss-sc-li">
          <span class="gloss-sc-span" style="font-size:0.7em;font-weight:bold;padding:0.15em 0.3em 0.3em 0.3em;word-break:keep-all;border-radius:0.3em;vertical-align:text-bottom;background-color:#565656;color:white;cursor:help;margin:0em 0.25em 0em 0em;" data-sc-code="n" title="noun (common) (futsuumeishi)">noun</span><span class="gloss-sc-span" style="font-size:0.7em;font-weight:bold;padding-top:0.15em;padding-right:0.3em;padding-bottom:0.3em;padding-left:0.3em;word-break:keep-all;border-radius:0.3em;vertical-align:text-bottom;background-color:brown;color:white;cursor:help;margin-right:0.25em;" data-sc-code="uk" title="word usually written using kana alone">kana</span>
          <ol class="gloss-sc-ol" style="padding-left: 1.4em;margin: 0">
            <li class="gloss-sc-li" style="list-style-type:&quot;① &quot;;" data-sc-sense-number="1">
              <ul class="gloss-sc-ul" style="color: #ffff00;padding-left: 1.4em;margin: 0" data-sc-content="glossary">
                <li class="gloss-sc-li">spring</li>
              </ul>
              <ul class="gloss-sc-ul" style="padding-left: 1.4em;margin: 0;margin-bottom: 0.5em">
                <li class="gloss-sc-li" style="list-style-type:circle;font-size:1.20em;" data-sc-content="example-sentence-a" lang="ja">その<span class="gloss-sc-span" style="color:#dd2121;text-shadow:0.5px 0.5px 1px gray;text-emphasis:circle crimson;text-decoration-line:underline;text-decoration-style:wavy;text-decoration-color:red;">ばね</span><ruby class="gloss-sc-ruby"><rt class="gloss-sc-rt">いっ</rt></ruby><ruby class="gloss-sc-ruby"><rt class="gloss-sc-rt"></rt></ruby><ruby class="gloss-sc-ruby"><rt class="gloss-sc-rt">くるま</rt></ruby><ruby class="gloss-sc-ruby"><rt class="gloss-sc-rt">ぜん</rt></ruby><ruby class="gloss-sc-ruby"><rt class="gloss-sc-rt">じゅう</rt></ruby><ruby class="gloss-sc-ruby"><rt class="gloss-sc-rt">りょう</rt></ruby><ruby class="gloss-sc-ruby"><rt class="gloss-sc-rt">ささ</rt></ruby>えている。</li>
                <li class="gloss-sc-li" style="list-style-type:none;font-size:0.70em;" data-sc-content="example-sentence-b" lang="en">That one spring carries the whole weight of the car.</li>
              </ul>
            </li>
          </ol>
        </li>
        <li class="gloss-sc-li">
          <span class="gloss-sc-span" style="font-size:0.7em;font-weight:bold;padding:0.15em 0.3em 0.3em 0.3em;word-break:keep-all;border-radius:0.3em;vertical-align:text-bottom;background-color:#565656;color:white;cursor:help;margin-right:0.25em;" data-sc-code="n" title="noun (common) (futsuumeishi)">noun</span><span class="gloss-sc-span" style="font-size:0.7em;font-weight:bold;padding:0.15em 0.3em 0.3em 0.3em;word-break:keep-all;border-radius:0.3em;vertical-align:text-bottom;background-color:brown;color:white;cursor:help;margin-right:0.25em;" data-sc-code="uk" title="word usually written using kana alone">kana</span><span class="gloss-sc-span" title="valid only for these forms and/or readings" style="cursor:help;"><span class="gloss-sc-span" style="color:red;"></span>ばね・バネ only<span class="gloss-sc-span" style="color:red;"></span></span>
          <ol class="gloss-sc-ol" style="padding-left: 1.4em;margin: 0">
            <li class="gloss-sc-li" style="list-style-type:&quot;② &quot;;" data-sc-sense-number="2">
              <ul class="gloss-sc-ul" style="color: #ffff00;padding-left: 1.4em;margin: 0" data-sc-content="glossary">
                <li class="gloss-sc-li">spring (in one's legs)</li>
                <li class="gloss-sc-li">bounce</li>
              </ul>
            </li>
            <li class="gloss-sc-li" style="list-style-type:&quot;③ &quot;;" data-sc-sense-number="3">
              <ul class="gloss-sc-ul" style="color: #ffff00;padding-left: 1.4em;margin: 0" data-sc-content="glossary">
                <li class="gloss-sc-li">springboard</li>
                <li class="gloss-sc-li">impetus</li>
              </ul>
            </li>
          </ol>
        </li>
        <li class="gloss-sc-li" data-sc-content="forms">
          <span class="gloss-sc-span" title="spelling and reading variants" style="font-size:0.7em;font-weight:bold;padding:0.15em 0.3em 0.3em 0.3em;word-break:keep-all;border-radius:0.3em;vertical-align:text-bottom;background-color:#565656;color:white;cursor:help;margin-right:0.25em;">forms</span>
          <div class="gloss-sc-table-container" style="display: block;overflow-x: auto;">
            <table class="gloss-sc-table" style="table-layout: auto;border-collapse: collapse;border-spacing: 0;color: var(--text-color);">
              <tbody>
                <tr class="gloss-sc-tr">
                  <th class="gloss-sc-th" style="border: 1px solid var(--border-color);padding: 0.25em;vertical-align: top;background-color: #2d2d2d;text-align: center;font-weight: normal"></th>
                  <th class="gloss-sc-th" style="border: 1px solid var(--border-color);padding: 0.25em;vertical-align: top;background-color: #2d2d2d;text-align: center;font-weight: normal;white-space: nowrap">発条</th>
                  <th class="gloss-sc-th" style="border: 1px solid var(--border-color);padding: 0.25em;vertical-align: top;background-color: #2d2d2d;text-align: center;font-weight: normal;white-space: nowrap">弾機</th>
                  <th class="gloss-sc-th" style="border: 1px solid var(--border-color);padding: 0.25em;vertical-align: top;background-color: #2d2d2d;text-align: center;font-weight: normal;white-space: nowrap">撥条</th>
                  <th class="gloss-sc-th" style="border: 1px solid var(--border-color);padding: 0.25em;vertical-align: top;background-color: #2d2d2d;text-align: center;font-weight: normal"><span class="gloss-sc-span" title="no associated kanji forms" style="color:red;cursor:help;"></span></th>
                </tr>
                <tr class="gloss-sc-tr">
                  <th class="gloss-sc-th" style="border: 1px solid var(--border-color);padding: 0.25em;vertical-align: top;background-color: #2d2d2d;font-weight: normal"><span class="gloss-sc-span" title="gikun (meaning as reading) or jukujikun (special kanji reading)" style="cursor:help;"><span class="gloss-sc-span" style="color:red;"></span>ばね<span class="gloss-sc-span" style="color:red;"></span></span></th>
                  <td class="gloss-sc-td" style="border: 1px solid var(--border-color);padding: 0.25em;vertical-align: top;text-align: center"><span class="gloss-sc-span" title="high priority form" style="padding:0.15em 0.2em;border-radius:1.00em;cursor:help;background-color:green;color:white;"></span></td>
                  <td class="gloss-sc-td" style="border: 1px solid var(--border-color);padding: 0.25em;vertical-align: top;text-align: center"><span class="gloss-sc-span" title="valid form/reading combination" style="padding:0.15em 0.2em;border-radius:1.00em;cursor:help;background-color:transparent;border-style:solid;border-width:0.75px;"></span></td>
                  <td class="gloss-sc-td" style="border: 1px solid var(--border-color);padding: 0.25em;vertical-align: top;text-align: center"><span class="gloss-sc-span" title="rarely used form" style="padding:0.15em 0.2em;border-radius:1.00em;cursor:help;background-color:purple;color:white;"></span></td>
                  <td class="gloss-sc-td" style="border: 1px solid var(--border-color);padding: 0.25em;vertical-align: top;text-align: center"></td>
                </tr>
                <tr class="gloss-sc-tr">
                  <th class="gloss-sc-th" style="border: 1px solid var(--border-color);padding: 0.25em;vertical-align: top;background-color: #2d2d2d;font-weight: normal">ぜんまい</th>
                  <td class="gloss-sc-td" style="border: 1px solid var(--border-color);padding: 0.25em;vertical-align: top;text-align: center"><span class="gloss-sc-span" title="valid form/reading combination" style="padding:0.15em 0.2em;border-radius:1.00em;cursor:help;background-color:transparent;border-style:solid;border-width:0.75px;"></span></td>
                  <td class="gloss-sc-td" style="border: 1px solid var(--border-color);padding: 0.25em;vertical-align: top;text-align: center"></td>
                  <td class="gloss-sc-td" style="border: 1px solid var(--border-color);padding: 0.25em;vertical-align: top;text-align: center"><span class="gloss-sc-span" title="rarely used form" style="padding:0.15em 0.2em;border-radius:1.00em;cursor:help;background:radial-gradient(purple 0.55em, black 1.00em);color:white;"></span></td>
                  <td class="gloss-sc-td" style="border: 1px solid var(--border-color);padding: 0.25em;vertical-align: top;text-align: center"></td>
                </tr>
                <tr class="gloss-sc-tr">
                  <th class="gloss-sc-th" style="border: 1px solid var(--border-color);padding: 0.25em;vertical-align: top;background-color: #2d2d2d;font-weight: normal">はつじょう</th>
                  <td class="gloss-sc-td" style="border: 1px solid var(--border-color);padding: 0.25em;vertical-align: top;text-align: center"><span class="gloss-sc-span" title="valid form/reading combination" style="padding:0.15em 0.2em;border-radius:1.00em;cursor:help;background-color:transparent;border-style:solid;border-width:0.75px;"></span></td>
                  <td class="gloss-sc-td" style="border: 1px solid var(--border-color);padding: 0.25em;vertical-align: top;text-align: center"></td>
                  <td class="gloss-sc-td" style="border: 1px solid var(--border-color);padding: 0.25em;vertical-align: top;text-align: center">
                    <div class="gloss-sc-div" title="rarely used form" style="clip-path:circle();cursor:help;background-color:purple;color:white;"></div>
                  </td>
                  <td class="gloss-sc-td" style="border: 1px solid var(--border-color);padding: 0.25em;vertical-align: top;text-align: center"></td>
                </tr>
                <tr class="gloss-sc-tr">
                  <th class="gloss-sc-th" style="border: 1px solid var(--border-color);padding: 0.25em;vertical-align: top;background-color: #2d2d2d;font-weight: normal">だんき</th>
                  <td class="gloss-sc-td" style="border: 1px solid var(--border-color);padding: 0.25em;vertical-align: top;text-align: center"></td>
                  <td class="gloss-sc-td" style="border: 1px solid var(--border-color);padding: 0.25em;vertical-align: top;text-align: center"><span class="gloss-sc-span" title="valid form/reading combination" style="padding:0.15em 0.2em;border-radius:1.00em;cursor:help;background-color:transparent;border-style:solid;border-width:0.75px;"></span></td>
                  <td class="gloss-sc-td" style="border: 1px solid var(--border-color);padding: 0.25em;vertical-align: top;text-align: center"></td>
                  <td class="gloss-sc-td" style="border: 1px solid var(--border-color);padding: 0.25em;vertical-align: top;text-align: center"></td>
                </tr>
                <tr class="gloss-sc-tr">
                  <th class="gloss-sc-th" style="border: 1px solid var(--border-color);padding: 0.25em;vertical-align: top;background-color: #2d2d2d;font-weight: normal">バネ</th>
                  <td class="gloss-sc-td" style="border: 1px solid var(--border-color);padding: 0.25em;vertical-align: top;text-align: center"></td>
                  <td class="gloss-sc-td" style="border: 1px solid var(--border-color);padding: 0.25em;vertical-align: top;text-align: center"></td>
                  <td class="gloss-sc-td" style="border: 1px solid var(--border-color);padding: 0.25em;vertical-align: top;text-align: center"></td>
                  <td class="gloss-sc-td" style="border: 1px solid var(--border-color);padding: 0.25em;vertical-align: top;text-align: center"><span class="gloss-sc-span" title="valid form/reading combination" style="padding:0.15em 0.2em;border-radius:1.00em;cursor:help;background-color:transparent;border-style:solid;border-width:0.75px;"></span></td>
                </tr>
              </tbody>
            </table>
          </div>
        </li>
      </ul>
    </span>
  </li>
</ol>

Comparison

Goal Current PR
goal current current

This PR's goal

Add CSS clip-path support

Implements the CSS clip-path inline style property for both flutter_widget_from_html_core and the fwfh_svg extension package.

What's supported

All standard CSS basic-shape functions:

CSS value Example HTML Flutter
polygon() clip-path: polygon(0% 0%, 100% 0%, 50% 100%)
View <div style="width: 100px; height: 100px; background: #E91E63; clip-path: polygon(0% 0%, 100% 0%, 50% 100%);"></div>
polygon
circle() clip-path: circle(50% at 50% 50%)
View <div style="width: 100px; height: 100px; background: #2196F3; clip-path: circle(50% at 50% 50%);"></div>
circle
ellipse() clip-path: ellipse(25% 40% at 50% 50%)
View <div style="width: 100px; height: 100px; background: #4CAF50; clip-path: ellipse(25% 40% at 50% 50%);"></div>
ellipse
inset() clip-path: inset(10% 20% round 8px)
View <div style="width: 100px; height: 100px; background: #FF9800; clip-path: inset(10% 20% round 8px);"></div>
inset
rect() clip-path: rect(10% 80% 90% 20%)
View <div style="width: 100px; height: 100px; background: #9C27B0; clip-path: rect(10% 80% 90% 20%);"></div>
rect
rect() round clip-path: rect(10% 80% 90% 20% round 10px)
View <div style="width: 100px; height: 100px; background: #9C27B0; clip-path: rect(10% 80% 90% 20% round 10px);"></div>
rect_round
xywh() clip-path: xywh(10% 20% 50% 40%)
View <div style="width: 100px; height: 100px; background: #00BCD4; clip-path: xywh(10% 20% 50% 40%);"></div>
xywh
xywh() round clip-path: xywh(10% 20% 50% 40% round 10px)
View <div style="width: 100px; height: 100px; background: #00BCD4; clip-path: xywh(10% 20% 50% 40% round 10px);"></div>
xywh_round
none none
View <div style="width: 100px; height: 100px; background: #795548; clip-path: none;"></div>
none
path() (svg not loaded) clip-path: path("M 50 5 L 61 35 L 95 35 L 68 57 L 79 91 L 50 70 L 21 91 L 32 57 L 5 35 L 39 35 Z")
View <div style="width: 100px; height: 100px; background: #000; clip-path: path('M 50 5 L 61 35 L 95 35 L 68 57 L 79 91 L 50 70 L 21 91 L 32 57 L 5 35 L 39 35 Z');"></div>
path
path() (svg loaded) clip-path: path("M 50 5 L 61 35 L 95 35 L 68 57 L 79 91 L 50 70 L 21 91 L 32 57 L 5 35 L 39 35 Z")
View <div style="width: 100px; height: 100px; background: #000; clip-path: path('M 50 5 L 61 35 L 95 35 L 68 57 L 79 91 L 50 70 L 21 91 L 32 57 L 5 35 L 39 35 Z');"></div>
image

Architecture

  • A new StyleClipPath build op in packages/core/lib/src/internal/ops/style_clip_path.dart follows the same pattern as StyleBackground: it registers via parseStyle, caches parsed state per element with setNonInherited<_StyleClipPathData>, and wraps the rendered widget in ClipPath inside onRenderBlock.
  • Percentage values are resolved against the element's actual pixel size at layout time inside CssClipPathClipper.getClip(Size).
  • A new priority slot BoxModel.clipPath sits between background and margin.
  • Two new WidgetFactory hooks: buildClipPath() (overridable default wraps with ClipPath) and buildClipPathFromSvgData() (default returns null; overridden by SvgFactory).

SVG path() integration

clip-path: path("M 0 0 L …") is handled via the path_parsing package (transitively included in fwfh_svg, now an explicit dependency). SvgFactory overrides buildClipPathFromSvgData() to parse the SVG path data at render time. Without SvgFactory loaded, path() is silently ignored and the element is left unclipped.

Not implemented

  • url(#id) references — would require SVG fragment lookup
  • geometry-box keywords (border-box, padding-box, etc.)
  • Combined box + shape values

Closes

#1505

@CaptainDario CaptainDario changed the title core implementation Support for clip-path Mar 28, 2026
@CaptainDario CaptainDario changed the title Support for clip-path Feature: Support for clip-path Apr 6, 2026
@CaptainDario CaptainDario marked this pull request as ready for review April 6, 2026 16:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant