mirror of
https://github.com/penpot/penpot.git
synced 2025-12-12 06:24:17 +01:00
Merge pull request #7189 from penpot/azazeln28-feat-text-playground-fonts
🎉 Add multiple fonts to text editor WASM playground
This commit is contained in:
958
frontend/text-editor/src/fonts.css
Normal file
958
frontend/text-editor/src/fonts.css
Normal file
@@ -0,0 +1,958 @@
|
||||
/* cyrillic-ext */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: italic;
|
||||
font-weight: 100;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFTjWacfw6zH4dthXcyms1lPpC8I_b0juU057p-xEJZj11l4.woff2) format('woff2');
|
||||
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
||||
}
|
||||
|
||||
/* cyrillic */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: italic;
|
||||
font-weight: 100;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFTjWacfw6zH4dthXcyms1lPpC8I_b0juU057p-xEJ9j11l4.woff2) format('woff2');
|
||||
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
|
||||
}
|
||||
|
||||
/* vietnamese */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: italic;
|
||||
font-weight: 100;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFTjWacfw6zH4dthXcyms1lPpC8I_b0juU057p-xEJRj11l4.woff2) format('woff2');
|
||||
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
|
||||
}
|
||||
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: italic;
|
||||
font-weight: 100;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFTjWacfw6zH4dthXcyms1lPpC8I_b0juU057p-xEJVj11l4.woff2) format('woff2');
|
||||
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: italic;
|
||||
font-weight: 100;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFTjWacfw6zH4dthXcyms1lPpC8I_b0juU057p-xEJtj1w.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
|
||||
/* cyrillic-ext */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: italic;
|
||||
font-weight: 200;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFTkWacfw6zH4dthXcyms1lPpC8I_b0juU057p8dAYxJ8mRBkw.woff2) format('woff2');
|
||||
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
||||
}
|
||||
|
||||
/* cyrillic */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: italic;
|
||||
font-weight: 200;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFTkWacfw6zH4dthXcyms1lPpC8I_b0juU057p8dAYxA8mRBkw.woff2) format('woff2');
|
||||
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
|
||||
}
|
||||
|
||||
/* vietnamese */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: italic;
|
||||
font-weight: 200;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFTkWacfw6zH4dthXcyms1lPpC8I_b0juU057p8dAYxL8mRBkw.woff2) format('woff2');
|
||||
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
|
||||
}
|
||||
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: italic;
|
||||
font-weight: 200;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFTkWacfw6zH4dthXcyms1lPpC8I_b0juU057p8dAYxK8mRBkw.woff2) format('woff2');
|
||||
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: italic;
|
||||
font-weight: 200;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFTkWacfw6zH4dthXcyms1lPpC8I_b0juU057p8dAYxE8mQ.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
|
||||
/* cyrillic-ext */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: italic;
|
||||
font-weight: 300;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFTkWacfw6zH4dthXcyms1lPpC8I_b0juU057p95AoxJ8mRBkw.woff2) format('woff2');
|
||||
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
||||
}
|
||||
|
||||
/* cyrillic */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: italic;
|
||||
font-weight: 300;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFTkWacfw6zH4dthXcyms1lPpC8I_b0juU057p95AoxA8mRBkw.woff2) format('woff2');
|
||||
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
|
||||
}
|
||||
|
||||
/* vietnamese */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: italic;
|
||||
font-weight: 300;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFTkWacfw6zH4dthXcyms1lPpC8I_b0juU057p95AoxL8mRBkw.woff2) format('woff2');
|
||||
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
|
||||
}
|
||||
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: italic;
|
||||
font-weight: 300;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFTkWacfw6zH4dthXcyms1lPpC8I_b0juU057p95AoxK8mRBkw.woff2) format('woff2');
|
||||
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: italic;
|
||||
font-weight: 300;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFTkWacfw6zH4dthXcyms1lPpC8I_b0juU057p95AoxE8mQ.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
|
||||
/* cyrillic-ext */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: italic;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFThWacfw6zH4dthXcyms1lPpC8I_b0juU057pffIJl70w.woff2) format('woff2');
|
||||
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
||||
}
|
||||
|
||||
/* cyrillic */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: italic;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFThWacfw6zH4dthXcyms1lPpC8I_b0juU057pfWIJl70w.woff2) format('woff2');
|
||||
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
|
||||
}
|
||||
|
||||
/* vietnamese */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: italic;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFThWacfw6zH4dthXcyms1lPpC8I_b0juU057pfdIJl70w.woff2) format('woff2');
|
||||
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
|
||||
}
|
||||
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: italic;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFThWacfw6zH4dthXcyms1lPpC8I_b0juU057pfcIJl70w.woff2) format('woff2');
|
||||
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: italic;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFThWacfw6zH4dthXcyms1lPpC8I_b0juU057pfSIJk.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
|
||||
/* cyrillic-ext */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: italic;
|
||||
font-weight: 500;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFTkWacfw6zH4dthXcyms1lPpC8I_b0juU057p8hA4xJ8mRBkw.woff2) format('woff2');
|
||||
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
||||
}
|
||||
|
||||
/* cyrillic */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: italic;
|
||||
font-weight: 500;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFTkWacfw6zH4dthXcyms1lPpC8I_b0juU057p8hA4xA8mRBkw.woff2) format('woff2');
|
||||
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
|
||||
}
|
||||
|
||||
/* vietnamese */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: italic;
|
||||
font-weight: 500;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFTkWacfw6zH4dthXcyms1lPpC8I_b0juU057p8hA4xL8mRBkw.woff2) format('woff2');
|
||||
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
|
||||
}
|
||||
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: italic;
|
||||
font-weight: 500;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFTkWacfw6zH4dthXcyms1lPpC8I_b0juU057p8hA4xK8mRBkw.woff2) format('woff2');
|
||||
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: italic;
|
||||
font-weight: 500;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFTkWacfw6zH4dthXcyms1lPpC8I_b0juU057p8hA4xE8mQ.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
|
||||
/* cyrillic-ext */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: italic;
|
||||
font-weight: 600;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFTkWacfw6zH4dthXcyms1lPpC8I_b0juU057p8NBIxJ8mRBkw.woff2) format('woff2');
|
||||
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
||||
}
|
||||
|
||||
/* cyrillic */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: italic;
|
||||
font-weight: 600;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFTkWacfw6zH4dthXcyms1lPpC8I_b0juU057p8NBIxA8mRBkw.woff2) format('woff2');
|
||||
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
|
||||
}
|
||||
|
||||
/* vietnamese */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: italic;
|
||||
font-weight: 600;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFTkWacfw6zH4dthXcyms1lPpC8I_b0juU057p8NBIxL8mRBkw.woff2) format('woff2');
|
||||
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
|
||||
}
|
||||
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: italic;
|
||||
font-weight: 600;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFTkWacfw6zH4dthXcyms1lPpC8I_b0juU057p8NBIxK8mRBkw.woff2) format('woff2');
|
||||
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: italic;
|
||||
font-weight: 600;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFTkWacfw6zH4dthXcyms1lPpC8I_b0juU057p8NBIxE8mQ.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
|
||||
/* cyrillic-ext */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: italic;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFTkWacfw6zH4dthXcyms1lPpC8I_b0juU057p9pBYxJ8mRBkw.woff2) format('woff2');
|
||||
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
||||
}
|
||||
|
||||
/* cyrillic */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: italic;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFTkWacfw6zH4dthXcyms1lPpC8I_b0juU057p9pBYxA8mRBkw.woff2) format('woff2');
|
||||
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
|
||||
}
|
||||
|
||||
/* vietnamese */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: italic;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFTkWacfw6zH4dthXcyms1lPpC8I_b0juU057p9pBYxL8mRBkw.woff2) format('woff2');
|
||||
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
|
||||
}
|
||||
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: italic;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFTkWacfw6zH4dthXcyms1lPpC8I_b0juU057p9pBYxK8mRBkw.woff2) format('woff2');
|
||||
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: italic;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFTkWacfw6zH4dthXcyms1lPpC8I_b0juU057p9pBYxE8mQ.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
|
||||
/* cyrillic-ext */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: italic;
|
||||
font-weight: 800;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFTkWacfw6zH4dthXcyms1lPpC8I_b0juU057p91BoxJ8mRBkw.woff2) format('woff2');
|
||||
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
||||
}
|
||||
|
||||
/* cyrillic */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: italic;
|
||||
font-weight: 800;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFTkWacfw6zH4dthXcyms1lPpC8I_b0juU057p91BoxA8mRBkw.woff2) format('woff2');
|
||||
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
|
||||
}
|
||||
|
||||
/* vietnamese */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: italic;
|
||||
font-weight: 800;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFTkWacfw6zH4dthXcyms1lPpC8I_b0juU057p91BoxL8mRBkw.woff2) format('woff2');
|
||||
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
|
||||
}
|
||||
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: italic;
|
||||
font-weight: 800;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFTkWacfw6zH4dthXcyms1lPpC8I_b0juU057p91BoxK8mRBkw.woff2) format('woff2');
|
||||
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: italic;
|
||||
font-weight: 800;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFTkWacfw6zH4dthXcyms1lPpC8I_b0juU057p91BoxE8mQ.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
|
||||
/* cyrillic-ext */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: italic;
|
||||
font-weight: 900;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFTkWacfw6zH4dthXcyms1lPpC8I_b0juU057p9RB4xJ8mRBkw.woff2) format('woff2');
|
||||
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
||||
}
|
||||
|
||||
/* cyrillic */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: italic;
|
||||
font-weight: 900;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFTkWacfw6zH4dthXcyms1lPpC8I_b0juU057p9RB4xA8mRBkw.woff2) format('woff2');
|
||||
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
|
||||
}
|
||||
|
||||
/* vietnamese */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: italic;
|
||||
font-weight: 900;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFTkWacfw6zH4dthXcyms1lPpC8I_b0juU057p9RB4xL8mRBkw.woff2) format('woff2');
|
||||
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
|
||||
}
|
||||
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: italic;
|
||||
font-weight: 900;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFTkWacfw6zH4dthXcyms1lPpC8I_b0juU057p9RB4xK8mRBkw.woff2) format('woff2');
|
||||
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: italic;
|
||||
font-weight: 900;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFTkWacfw6zH4dthXcyms1lPpC8I_b0juU057p9RB4xE8mQ.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
|
||||
/* cyrillic-ext */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: normal;
|
||||
font-weight: 100;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFThWacfw6zH4dthXcyms1lPpC8I_b0juU0xiJffIJl70w.woff2) format('woff2');
|
||||
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
||||
}
|
||||
|
||||
/* cyrillic */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: normal;
|
||||
font-weight: 100;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFThWacfw6zH4dthXcyms1lPpC8I_b0juU0xiJfWIJl70w.woff2) format('woff2');
|
||||
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
|
||||
}
|
||||
|
||||
/* vietnamese */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: normal;
|
||||
font-weight: 100;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFThWacfw6zH4dthXcyms1lPpC8I_b0juU0xiJfdIJl70w.woff2) format('woff2');
|
||||
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
|
||||
}
|
||||
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: normal;
|
||||
font-weight: 100;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFThWacfw6zH4dthXcyms1lPpC8I_b0juU0xiJfcIJl70w.woff2) format('woff2');
|
||||
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: normal;
|
||||
font-weight: 100;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFThWacfw6zH4dthXcyms1lPpC8I_b0juU0xiJfSIJk.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
|
||||
/* cyrillic-ext */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: normal;
|
||||
font-weight: 200;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFTiWacfw6zH4dthXcyms1lPpC8I_b0juU0xJIbFCrxG6mA.woff2) format('woff2');
|
||||
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
||||
}
|
||||
|
||||
/* cyrillic */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: normal;
|
||||
font-weight: 200;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFTiWacfw6zH4dthXcyms1lPpC8I_b0juU0xJIbFA7xG6mA.woff2) format('woff2');
|
||||
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
|
||||
}
|
||||
|
||||
/* vietnamese */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: normal;
|
||||
font-weight: 200;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFTiWacfw6zH4dthXcyms1lPpC8I_b0juU0xJIbFCLxG6mA.woff2) format('woff2');
|
||||
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
|
||||
}
|
||||
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: normal;
|
||||
font-weight: 200;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFTiWacfw6zH4dthXcyms1lPpC8I_b0juU0xJIbFCbxG6mA.woff2) format('woff2');
|
||||
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: normal;
|
||||
font-weight: 200;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFTiWacfw6zH4dthXcyms1lPpC8I_b0juU0xJIbFB7xG.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
|
||||
/* cyrillic-ext */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: normal;
|
||||
font-weight: 300;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFTiWacfw6zH4dthXcyms1lPpC8I_b0juU0xQIXFCrxG6mA.woff2) format('woff2');
|
||||
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
||||
}
|
||||
|
||||
/* cyrillic */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: normal;
|
||||
font-weight: 300;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFTiWacfw6zH4dthXcyms1lPpC8I_b0juU0xQIXFA7xG6mA.woff2) format('woff2');
|
||||
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
|
||||
}
|
||||
|
||||
/* vietnamese */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: normal;
|
||||
font-weight: 300;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFTiWacfw6zH4dthXcyms1lPpC8I_b0juU0xQIXFCLxG6mA.woff2) format('woff2');
|
||||
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
|
||||
}
|
||||
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: normal;
|
||||
font-weight: 300;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFTiWacfw6zH4dthXcyms1lPpC8I_b0juU0xQIXFCbxG6mA.woff2) format('woff2');
|
||||
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: normal;
|
||||
font-weight: 300;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFTiWacfw6zH4dthXcyms1lPpC8I_b0juU0xQIXFB7xG.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
|
||||
/* cyrillic-ext */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFTvWacfw6zH4dthXcyms1lPpC8I_b0juU055qfQOJ0.woff2) format('woff2');
|
||||
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
||||
}
|
||||
|
||||
/* cyrillic */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFTvWacfw6zH4dthXcyms1lPpC8I_b0juU0576fQOJ0.woff2) format('woff2');
|
||||
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
|
||||
}
|
||||
|
||||
/* vietnamese */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFTvWacfw6zH4dthXcyms1lPpC8I_b0juU055KfQOJ0.woff2) format('woff2');
|
||||
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
|
||||
}
|
||||
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFTvWacfw6zH4dthXcyms1lPpC8I_b0juU055afQOJ0.woff2) format('woff2');
|
||||
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFTvWacfw6zH4dthXcyms1lPpC8I_b0juU0566fQ.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
|
||||
/* cyrillic-ext */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFTiWacfw6zH4dthXcyms1lPpC8I_b0juU0xGITFCrxG6mA.woff2) format('woff2');
|
||||
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
||||
}
|
||||
|
||||
/* cyrillic */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFTiWacfw6zH4dthXcyms1lPpC8I_b0juU0xGITFA7xG6mA.woff2) format('woff2');
|
||||
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
|
||||
}
|
||||
|
||||
/* vietnamese */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFTiWacfw6zH4dthXcyms1lPpC8I_b0juU0xGITFCLxG6mA.woff2) format('woff2');
|
||||
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
|
||||
}
|
||||
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFTiWacfw6zH4dthXcyms1lPpC8I_b0juU0xGITFCbxG6mA.woff2) format('woff2');
|
||||
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFTiWacfw6zH4dthXcyms1lPpC8I_b0juU0xGITFB7xG.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
|
||||
/* cyrillic-ext */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFTiWacfw6zH4dthXcyms1lPpC8I_b0juU0xNIPFCrxG6mA.woff2) format('woff2');
|
||||
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
||||
}
|
||||
|
||||
/* cyrillic */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFTiWacfw6zH4dthXcyms1lPpC8I_b0juU0xNIPFA7xG6mA.woff2) format('woff2');
|
||||
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
|
||||
}
|
||||
|
||||
/* vietnamese */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFTiWacfw6zH4dthXcyms1lPpC8I_b0juU0xNIPFCLxG6mA.woff2) format('woff2');
|
||||
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
|
||||
}
|
||||
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFTiWacfw6zH4dthXcyms1lPpC8I_b0juU0xNIPFCbxG6mA.woff2) format('woff2');
|
||||
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFTiWacfw6zH4dthXcyms1lPpC8I_b0juU0xNIPFB7xG.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
|
||||
/* cyrillic-ext */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFTiWacfw6zH4dthXcyms1lPpC8I_b0juU0xUILFCrxG6mA.woff2) format('woff2');
|
||||
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
||||
}
|
||||
|
||||
/* cyrillic */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFTiWacfw6zH4dthXcyms1lPpC8I_b0juU0xUILFA7xG6mA.woff2) format('woff2');
|
||||
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
|
||||
}
|
||||
|
||||
/* vietnamese */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFTiWacfw6zH4dthXcyms1lPpC8I_b0juU0xUILFCLxG6mA.woff2) format('woff2');
|
||||
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
|
||||
}
|
||||
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFTiWacfw6zH4dthXcyms1lPpC8I_b0juU0xUILFCbxG6mA.woff2) format('woff2');
|
||||
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFTiWacfw6zH4dthXcyms1lPpC8I_b0juU0xUILFB7xG.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
|
||||
/* cyrillic-ext */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: normal;
|
||||
font-weight: 800;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFTiWacfw6zH4dthXcyms1lPpC8I_b0juU0xTIHFCrxG6mA.woff2) format('woff2');
|
||||
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
||||
}
|
||||
|
||||
/* cyrillic */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: normal;
|
||||
font-weight: 800;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFTiWacfw6zH4dthXcyms1lPpC8I_b0juU0xTIHFA7xG6mA.woff2) format('woff2');
|
||||
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
|
||||
}
|
||||
|
||||
/* vietnamese */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: normal;
|
||||
font-weight: 800;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFTiWacfw6zH4dthXcyms1lPpC8I_b0juU0xTIHFCLxG6mA.woff2) format('woff2');
|
||||
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
|
||||
}
|
||||
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: normal;
|
||||
font-weight: 800;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFTiWacfw6zH4dthXcyms1lPpC8I_b0juU0xTIHFCbxG6mA.woff2) format('woff2');
|
||||
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: normal;
|
||||
font-weight: 800;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFTiWacfw6zH4dthXcyms1lPpC8I_b0juU0xTIHFB7xG.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
|
||||
/* cyrillic-ext */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: normal;
|
||||
font-weight: 900;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFTiWacfw6zH4dthXcyms1lPpC8I_b0juU0xaIDFCrxG6mA.woff2) format('woff2');
|
||||
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
||||
}
|
||||
|
||||
/* cyrillic */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: normal;
|
||||
font-weight: 900;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFTiWacfw6zH4dthXcyms1lPpC8I_b0juU0xaIDFA7xG6mA.woff2) format('woff2');
|
||||
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
|
||||
}
|
||||
|
||||
/* vietnamese */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: normal;
|
||||
font-weight: 900;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFTiWacfw6zH4dthXcyms1lPpC8I_b0juU0xaIDFCLxG6mA.woff2) format('woff2');
|
||||
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
|
||||
}
|
||||
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: normal;
|
||||
font-weight: 900;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFTiWacfw6zH4dthXcyms1lPpC8I_b0juU0xaIDFCbxG6mA.woff2) format('woff2');
|
||||
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'MontserratAlternates';
|
||||
font-style: normal;
|
||||
font-weight: 900;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/montserratalternates/v17/mFTiWacfw6zH4dthXcyms1lPpC8I_b0juU0xaIDFB7xG.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
|
||||
/* cyrillic-ext */
|
||||
@font-face {
|
||||
font-family: 'Oswald';
|
||||
font-style: normal;
|
||||
font-weight: 200 700;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/oswald/v56/TK3iWkUHHAIjg752FD8Ghe4.woff2) format('woff2');
|
||||
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
||||
}
|
||||
|
||||
/* cyrillic */
|
||||
@font-face {
|
||||
font-family: 'Oswald';
|
||||
font-style: normal;
|
||||
font-weight: 200 700;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/oswald/v56/TK3iWkUHHAIjg752HT8Ghe4.woff2) format('woff2');
|
||||
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
|
||||
}
|
||||
|
||||
/* vietnamese */
|
||||
@font-face {
|
||||
font-family: 'Oswald';
|
||||
font-style: normal;
|
||||
font-weight: 200 700;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/oswald/v56/TK3iWkUHHAIjg752Fj8Ghe4.woff2) format('woff2');
|
||||
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
|
||||
}
|
||||
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'Oswald';
|
||||
font-style: normal;
|
||||
font-weight: 200 700;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/oswald/v56/TK3iWkUHHAIjg752Fz8Ghe4.woff2) format('woff2');
|
||||
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'Oswald';
|
||||
font-style: normal;
|
||||
font-weight: 200 700;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/oswald/v56/TK3iWkUHHAIjg752GT8G.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
|
||||
/* fallback */
|
||||
@font-face {
|
||||
font-family: 'Playwrite MX Guides';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url(https://fonts.gstatic.com/s/playwritemxguides/v1/k3kMo9ESPe9dzQ1UGbvoZhnhbtfklWqN0qk.woff2) format('woff2');
|
||||
}
|
||||
@@ -2,19 +2,12 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Open+Sans:ital,wght@0,300..800;1,300..800&family=Playwrite+ES:wght@100..400&family=Playwrite+NZ:wght@100..400&family=Playwrite+US+Trad:wght@100..400&family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap" rel="stylesheet">
|
||||
<link rel="icon" type="image/svg+xml" href="/javascript.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Penpot - Text Editor Playground</title>
|
||||
<style>
|
||||
#output {
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="playground">
|
||||
<form>
|
||||
<fieldset>
|
||||
<legend>Styles</legend>
|
||||
@@ -220,7 +213,340 @@
|
||||
Text output
|
||||
|
||||
-->
|
||||
<div id="output"></div>
|
||||
<script type="module" src="/main.js"></script>
|
||||
<canvas id="canvas"></canvas>
|
||||
</div>
|
||||
<script type="module">
|
||||
import "./style.css";
|
||||
import "./fonts.css";
|
||||
import "./editor/TextEditor.css";
|
||||
import { TextEditor } from "./editor/TextEditor";
|
||||
import { SelectionControllerDebug } from "./editor/debug/SelectionControllerDebug";
|
||||
import initWasmModule from './wasm/render_wasm.js';
|
||||
import {
|
||||
init, assignCanvas, render, setupInteraction, useShape, setShapeChildren, addTextShape, updateTextShape, hexToU32ARGB,getRandomInt, getRandomColor, getRandomFloat, addShapeSolidFill, addShapeSolidStrokeFill, storeFonts
|
||||
} from './wasm/lib.js';
|
||||
|
||||
async function loadFontList() {
|
||||
const response = await fetch('fonts/fonts.txt')
|
||||
const text = await response.text()
|
||||
const fonts = text.split('\n').filter(l => !!l)
|
||||
return fonts
|
||||
}
|
||||
|
||||
function getFontStyleWeight(fontStyleName) {
|
||||
if (fontStyleName.startsWith('Thin')) {
|
||||
return 100
|
||||
} else if (fontStyleName.startsWith('ExtraLight')) {
|
||||
return 200
|
||||
} else if (fontStyleName.startsWith('Light')) {
|
||||
return 300
|
||||
} else if (fontStyleName.startsWith('Regular')) {
|
||||
return 400
|
||||
} else if (fontStyleName.startsWith('Medium')) {
|
||||
return 500
|
||||
} else if (fontStyleName.startsWith('SemiBold')) {
|
||||
return 600
|
||||
} else if (fontStyleName.startsWith('Bold')) {
|
||||
return 700
|
||||
} else if (fontStyleName.startsWith('ExtraBold')) {
|
||||
return 800
|
||||
} else if (fontStyleName.startsWith('Black')) {
|
||||
return 900
|
||||
} else {
|
||||
return 400
|
||||
}
|
||||
}
|
||||
|
||||
async function loadFonts() {
|
||||
const fontData = new Map()
|
||||
const fonts = await loadFontList()
|
||||
for (const font of fonts) {
|
||||
const response = await fetch(`fonts/${font}`)
|
||||
const arrayBuffer = await response.arrayBuffer()
|
||||
const [fontName, fontStyleNameAndExtension] = font.split('-')
|
||||
const [fontStyleName, extension] = fontStyleNameAndExtension.split('.')
|
||||
if (!fontData.has(fontName)) {
|
||||
fontData.set(fontName, [])
|
||||
}
|
||||
const id = crypto.randomUUID()
|
||||
const weight = getFontStyleWeight(fontStyleName)
|
||||
const isItalic = (fontStyleName.endsWith('Italic'))
|
||||
const currentFontData = fontData.get(fontName)
|
||||
currentFontData.push({
|
||||
id,
|
||||
url: `fonts/${font}`,
|
||||
name: fontName,
|
||||
weight: weight,
|
||||
style: isItalic ? 'italic' : 'normal',
|
||||
arrayBuffer,
|
||||
})
|
||||
}
|
||||
return fontData
|
||||
}
|
||||
|
||||
const searchParams = new URLSearchParams(location.search);
|
||||
const debug = searchParams.has("debug")
|
||||
? searchParams.get("debug").split(",")
|
||||
: [];
|
||||
|
||||
const textEditorSelectionImposterElement = document.getElementById(
|
||||
"text-editor-selection-imposter",
|
||||
);
|
||||
|
||||
const textEditorElement = document.querySelector(".text-editor-content");
|
||||
const textEditor = new TextEditor(textEditorElement, {
|
||||
styleDefaults: {
|
||||
"font-family": "MontserratAlternates",
|
||||
"font-size": "14",
|
||||
"font-weight": "500",
|
||||
"font-style": "normal",
|
||||
"line-height": "1.2",
|
||||
"letter-spacing": "0",
|
||||
direction: "ltr",
|
||||
"text-align": "left",
|
||||
"text-transform": "none",
|
||||
"text-decoration": "none",
|
||||
"--typography-ref-id": '["~#\'",null]',
|
||||
"--typography-ref-file": '["~#\'",null]',
|
||||
"--font-id": '["~#\'","MontserratAlternates"]',
|
||||
"--fills": '[["^ ","~:fill-color","#000000","~:fill-opacity",1]]',
|
||||
},
|
||||
selectionImposterElement: textEditorSelectionImposterElement,
|
||||
debug: new SelectionControllerDebug({
|
||||
direction: document.getElementById("direction"),
|
||||
multiElement: document.getElementById("multi"),
|
||||
multiInlineElement: document.getElementById("multi-inline"),
|
||||
multiParagraphElement: document.getElementById("multi-paragraph"),
|
||||
isParagraphStart: document.getElementById("is-paragraph-start"),
|
||||
isParagraphEnd: document.getElementById("is-paragraph-end"),
|
||||
isInlineStart: document.getElementById("is-inline-start"),
|
||||
isInlineEnd: document.getElementById("is-inline-end"),
|
||||
isTextAnchor: document.getElementById("is-text-anchor"),
|
||||
isTextFocus: document.getElementById("is-text-focus"),
|
||||
focusNode: document.getElementById("focus-node"),
|
||||
focusOffset: document.getElementById("focus-offset"),
|
||||
focusInline: document.getElementById("focus-inline"),
|
||||
focusParagraph: document.getElementById("focus-paragraph"),
|
||||
anchorNode: document.getElementById("anchor-node"),
|
||||
anchorOffset: document.getElementById("anchor-offset"),
|
||||
anchorInline: document.getElementById("anchor-inline"),
|
||||
anchorParagraph: document.getElementById("anchor-paragraph"),
|
||||
startContainer: document.getElementById("start-container"),
|
||||
startOffset: document.getElementById("start-offset"),
|
||||
endContainer: document.getElementById("end-container"),
|
||||
endOffset: document.getElementById("end-offset"),
|
||||
}),
|
||||
});
|
||||
|
||||
const fontFamilyElement = document.getElementById("font-family");
|
||||
const fontSizeElement = document.getElementById("font-size");
|
||||
const fontWeightElement = document.getElementById("font-weight");
|
||||
const fontStyleElement = document.getElementById("font-style");
|
||||
|
||||
const directionLTRElement = document.getElementById("direction-ltr");
|
||||
const directionRTLElement = document.getElementById("direction-rtl");
|
||||
|
||||
const lineHeightElement = document.getElementById("line-height");
|
||||
const letterSpacingElement = document.getElementById("letter-spacing");
|
||||
|
||||
const textAlignLeftElement = document.getElementById("text-align-left");
|
||||
const textAlignCenterElement = document.getElementById("text-align-center");
|
||||
const textAlignRightElement = document.getElementById("text-align-right");
|
||||
const textAlignJustifyElement = document.getElementById("text-align-justify");
|
||||
|
||||
const fonts = await loadFonts()
|
||||
console.log(fonts)
|
||||
const fontFamiliesFragment = document.createDocumentFragment()
|
||||
for (const [font, fontData] of fonts) {
|
||||
const fontFamilyOptionElement = document.createElement('option')
|
||||
fontFamilyOptionElement.value = font
|
||||
fontFamilyOptionElement.textContent = font
|
||||
fontFamiliesFragment.appendChild(fontFamilyOptionElement)
|
||||
}
|
||||
fontFamilyElement.replaceChildren(fontFamiliesFragment)
|
||||
|
||||
function onDirectionChange(e) {
|
||||
if (debug.includes("events")) {
|
||||
console.log(e);
|
||||
}
|
||||
if (e.target.checked) {
|
||||
textEditor.applyStylesToSelection({
|
||||
direction: e.target.value,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
directionLTRElement.addEventListener("change", onDirectionChange);
|
||||
directionRTLElement.addEventListener("change", onDirectionChange);
|
||||
|
||||
function onTextAlignChange(e) {
|
||||
if (debug.includes("events")) {
|
||||
console.log(e);
|
||||
}
|
||||
if (e.target.checked) {
|
||||
textEditor.applyStylesToSelection({
|
||||
"text-align": e.target.value,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
textAlignLeftElement.addEventListener("change", onTextAlignChange);
|
||||
textAlignCenterElement.addEventListener("change", onTextAlignChange);
|
||||
textAlignRightElement.addEventListener("change", onTextAlignChange);
|
||||
textAlignJustifyElement.addEventListener("change", onTextAlignChange);
|
||||
|
||||
fontFamilyElement.addEventListener("change", (e) => {
|
||||
if (debug.includes("events")) {
|
||||
console.log(e);
|
||||
}
|
||||
const fontStyles = fonts.get(e.target.value)
|
||||
console.log('fontStyles', fontStyles)
|
||||
textEditor.applyStylesToSelection({
|
||||
"font-family": e.target.value,
|
||||
});
|
||||
});
|
||||
|
||||
fontWeightElement.addEventListener("change", (e) => {
|
||||
if (debug.includes("events")) {
|
||||
console.log(e);
|
||||
}
|
||||
textEditor.applyStylesToSelection({
|
||||
"font-weight": e.target.value,
|
||||
});
|
||||
});
|
||||
|
||||
fontSizeElement.addEventListener("change", (e) => {
|
||||
if (debug.includes("events")) {
|
||||
console.log(e);
|
||||
}
|
||||
textEditor.applyStylesToSelection({
|
||||
"font-size": e.target.value,
|
||||
});
|
||||
});
|
||||
|
||||
lineHeightElement.addEventListener("change", (e) => {
|
||||
if (debug.includes("events")) {
|
||||
console.log(e);
|
||||
}
|
||||
textEditor.applyStylesToSelection({
|
||||
"line-height": e.target.value,
|
||||
});
|
||||
});
|
||||
|
||||
letterSpacingElement.addEventListener("change", (e) => {
|
||||
if (debug.includes("events")) {
|
||||
console.log(e);
|
||||
}
|
||||
textEditor.applyStylesToSelection({
|
||||
"letter-spacing": e.target.value,
|
||||
});
|
||||
});
|
||||
|
||||
fontStyleElement.addEventListener("change", (e) => {
|
||||
if (debug.includes("events")) {
|
||||
console.log(e);
|
||||
}
|
||||
textEditor.applyStylesToSelection({
|
||||
"font-style": e.target.value,
|
||||
});
|
||||
});
|
||||
|
||||
function formatHTML(html, options) {
|
||||
const spaces = options?.spaces ?? 4;
|
||||
let indent = 0;
|
||||
return html.replace(/<\/?(.*?)>/g, (fullMatch) => {
|
||||
let str = fullMatch + "\n";
|
||||
if (fullMatch.startsWith("</")) {
|
||||
--indent;
|
||||
str = " ".repeat(indent * spaces) + str;
|
||||
} else {
|
||||
str = " ".repeat(indent * spaces) + str;
|
||||
++indent;
|
||||
if (fullMatch === "<br>") --indent;
|
||||
}
|
||||
return str;
|
||||
});
|
||||
}
|
||||
|
||||
const fontSize = 14;
|
||||
const children = [];
|
||||
const uuid = crypto.randomUUID();
|
||||
children.push(uuid);
|
||||
const outputElement = document.getElementById("output");
|
||||
textEditorElement.addEventListener("input", (e) => {
|
||||
if (debug.includes("events")) {
|
||||
console.log(e);
|
||||
}
|
||||
outputElement.textContent = formatHTML(textEditor.element.innerHTML);
|
||||
});
|
||||
|
||||
textEditor.addEventListener("needslayout", (e) => {
|
||||
useShape(uuid);
|
||||
updateTextShape(textEditor.root, fonts);
|
||||
render();
|
||||
})
|
||||
|
||||
textEditor.addEventListener("stylechange", (e) => {
|
||||
if (debug.includes("events")) {
|
||||
console.log(e);
|
||||
}
|
||||
const fontSize = parseInt(e.detail.getPropertyValue("font-size"), 10);
|
||||
const fontWeight = e.detail.getPropertyValue("font-weight");
|
||||
const fontStyle = e.detail.getPropertyValue("font-style");
|
||||
const fontFamily = e.detail.getPropertyValue("font-family");
|
||||
|
||||
fontFamilyElement.value = fontFamily;
|
||||
fontSizeElement.value = fontSize;
|
||||
fontStyleElement.value = fontStyle;
|
||||
fontWeightElement.value = fontWeight;
|
||||
|
||||
const textAlign = e.detail.getPropertyValue("text-align");
|
||||
textAlignLeftElement.checked = textAlign === "left";
|
||||
textAlignCenterElement.checked = textAlign === "center";
|
||||
textAlignRightElement.checked = textAlign === "right";
|
||||
textAlignJustifyElement.checked = textAlign === "justify";
|
||||
|
||||
const direction = e.detail.getPropertyValue("direction");
|
||||
directionLTRElement.checked = direction === "ltr";
|
||||
directionRTLElement.checked = direction === "rtl";
|
||||
});
|
||||
|
||||
const canvas = document.getElementById("canvas");
|
||||
canvas.width = window.innerWidth;
|
||||
canvas.height = window.innerHeight;
|
||||
|
||||
const MIN_LINES = 1;
|
||||
const MAX_LINES = 5;
|
||||
const MIN_WORDS = 1;
|
||||
const MAX_WORDS = 10;
|
||||
|
||||
initWasmModule().then(Module => {
|
||||
init(Module);
|
||||
assignCanvas(canvas);
|
||||
Module._set_canvas_background(hexToU32ARGB("#FABADA", 1));
|
||||
Module._set_view(1, 0, 0);
|
||||
Module._init_shapes_pool(1);
|
||||
setupInteraction(canvas);
|
||||
|
||||
storeFonts(fonts)
|
||||
|
||||
useShape(uuid);
|
||||
Module._set_parent(0, 0, 0, 0);
|
||||
Module._set_shape_type(5);
|
||||
|
||||
const x1 = 0;
|
||||
const y1 = 0;
|
||||
const width = canvas.width;
|
||||
const height = canvas.height;
|
||||
Module._set_shape_selrect(x1, y1, x1 + width, y1 + height);
|
||||
|
||||
addTextShape("", fonts);
|
||||
|
||||
useShape("00000000-0000-0000-0000-000000000000");
|
||||
setShapeChildren(children);
|
||||
render()
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,216 +0,0 @@
|
||||
/**
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* Copyright (c) KALEIDOS INC
|
||||
*/
|
||||
|
||||
import "./style.css";
|
||||
import "./editor/TextEditor.css";
|
||||
import { TextEditor } from "./editor/TextEditor";
|
||||
import { SelectionControllerDebug } from "./editor/debug/SelectionControllerDebug";
|
||||
|
||||
const searchParams = new URLSearchParams(location.search);
|
||||
const debug = searchParams.has("debug")
|
||||
? searchParams.get("debug").split(",")
|
||||
: [];
|
||||
|
||||
const textEditorSelectionImposterElement = document.getElementById(
|
||||
"text-editor-selection-imposter",
|
||||
);
|
||||
|
||||
const textEditorElement = document.querySelector(".text-editor-content");
|
||||
const textEditor = new TextEditor(textEditorElement, {
|
||||
styleDefaults: {
|
||||
"font-family": "sourcesanspro",
|
||||
"font-size": "14",
|
||||
"font-weight": "500",
|
||||
"font-style": "normal",
|
||||
"line-height": "1.2",
|
||||
"letter-spacing": "0",
|
||||
direction: "ltr",
|
||||
"text-align": "left",
|
||||
"text-transform": "none",
|
||||
"text-decoration": "none",
|
||||
"--typography-ref-id": '["~#\'",null]',
|
||||
"--typography-ref-file": '["~#\'",null]',
|
||||
"--font-id": '["~#\'","sourcesanspro"]',
|
||||
"--fills": '[["^ ","~:fill-color","#000000","~:fill-opacity",1]]',
|
||||
},
|
||||
selectionImposterElement: textEditorSelectionImposterElement,
|
||||
debug: new SelectionControllerDebug({
|
||||
direction: document.getElementById("direction"),
|
||||
multiElement: document.getElementById("multi"),
|
||||
multiInlineElement: document.getElementById("multi-inline"),
|
||||
multiParagraphElement: document.getElementById("multi-paragraph"),
|
||||
isParagraphStart: document.getElementById("is-paragraph-start"),
|
||||
isParagraphEnd: document.getElementById("is-paragraph-end"),
|
||||
isInlineStart: document.getElementById("is-inline-start"),
|
||||
isInlineEnd: document.getElementById("is-inline-end"),
|
||||
isTextAnchor: document.getElementById("is-text-anchor"),
|
||||
isTextFocus: document.getElementById("is-text-focus"),
|
||||
focusNode: document.getElementById("focus-node"),
|
||||
focusOffset: document.getElementById("focus-offset"),
|
||||
focusInline: document.getElementById("focus-inline"),
|
||||
focusParagraph: document.getElementById("focus-paragraph"),
|
||||
anchorNode: document.getElementById("anchor-node"),
|
||||
anchorOffset: document.getElementById("anchor-offset"),
|
||||
anchorInline: document.getElementById("anchor-inline"),
|
||||
anchorParagraph: document.getElementById("anchor-paragraph"),
|
||||
startContainer: document.getElementById("start-container"),
|
||||
startOffset: document.getElementById("start-offset"),
|
||||
endContainer: document.getElementById("end-container"),
|
||||
endOffset: document.getElementById("end-offset"),
|
||||
}),
|
||||
});
|
||||
|
||||
const fontFamilyElement = document.getElementById("font-family");
|
||||
const fontSizeElement = document.getElementById("font-size");
|
||||
const fontWeightElement = document.getElementById("font-weight");
|
||||
const fontStyleElement = document.getElementById("font-style");
|
||||
|
||||
const directionLTRElement = document.getElementById("direction-ltr");
|
||||
const directionRTLElement = document.getElementById("direction-rtl");
|
||||
|
||||
const lineHeightElement = document.getElementById("line-height");
|
||||
const letterSpacingElement = document.getElementById("letter-spacing");
|
||||
|
||||
const textAlignLeftElement = document.getElementById("text-align-left");
|
||||
const textAlignCenterElement = document.getElementById("text-align-center");
|
||||
const textAlignRightElement = document.getElementById("text-align-right");
|
||||
const textAlignJustifyElement = document.getElementById("text-align-justify");
|
||||
|
||||
function onDirectionChange(e) {
|
||||
if (debug.includes("events")) {
|
||||
console.log(e);
|
||||
}
|
||||
if (e.target.checked) {
|
||||
textEditor.applyStylesToSelection({
|
||||
direction: e.target.value,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
directionLTRElement.addEventListener("change", onDirectionChange);
|
||||
directionRTLElement.addEventListener("change", onDirectionChange);
|
||||
|
||||
function onTextAlignChange(e) {
|
||||
if (debug.includes("events")) {
|
||||
console.log(e);
|
||||
}
|
||||
if (e.target.checked) {
|
||||
textEditor.applyStylesToSelection({
|
||||
"text-align": e.target.value,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
textAlignLeftElement.addEventListener("change", onTextAlignChange);
|
||||
textAlignCenterElement.addEventListener("change", onTextAlignChange);
|
||||
textAlignRightElement.addEventListener("change", onTextAlignChange);
|
||||
textAlignJustifyElement.addEventListener("change", onTextAlignChange);
|
||||
|
||||
fontFamilyElement.addEventListener("change", (e) => {
|
||||
if (debug.includes("events")) {
|
||||
console.log(e);
|
||||
}
|
||||
textEditor.applyStylesToSelection({
|
||||
"font-family": e.target.value,
|
||||
});
|
||||
});
|
||||
|
||||
fontWeightElement.addEventListener("change", (e) => {
|
||||
if (debug.includes("events")) {
|
||||
console.log(e);
|
||||
}
|
||||
textEditor.applyStylesToSelection({
|
||||
"font-weight": e.target.value,
|
||||
});
|
||||
});
|
||||
|
||||
fontSizeElement.addEventListener("change", (e) => {
|
||||
if (debug.includes("events")) {
|
||||
console.log(e);
|
||||
}
|
||||
textEditor.applyStylesToSelection({
|
||||
"font-size": e.target.value,
|
||||
});
|
||||
});
|
||||
|
||||
lineHeightElement.addEventListener("change", (e) => {
|
||||
if (debug.includes("events")) {
|
||||
console.log(e);
|
||||
}
|
||||
textEditor.applyStylesToSelection({
|
||||
"line-height": e.target.value,
|
||||
});
|
||||
});
|
||||
|
||||
letterSpacingElement.addEventListener("change", (e) => {
|
||||
if (debug.includes("events")) {
|
||||
console.log(e);
|
||||
}
|
||||
textEditor.applyStylesToSelection({
|
||||
"letter-spacing": e.target.value,
|
||||
});
|
||||
});
|
||||
|
||||
fontStyleElement.addEventListener("change", (e) => {
|
||||
if (debug.includes("events")) {
|
||||
console.log(e);
|
||||
}
|
||||
textEditor.applyStylesToSelection({
|
||||
"font-style": e.target.value,
|
||||
});
|
||||
});
|
||||
|
||||
function formatHTML(html, options) {
|
||||
const spaces = options?.spaces ?? 4;
|
||||
let indent = 0;
|
||||
return html.replace(/<\/?(.*?)>/g, (fullMatch) => {
|
||||
let str = fullMatch + "\n";
|
||||
if (fullMatch.startsWith("</")) {
|
||||
--indent;
|
||||
str = " ".repeat(indent * spaces) + str;
|
||||
} else {
|
||||
str = " ".repeat(indent * spaces) + str;
|
||||
++indent;
|
||||
if (fullMatch === "<br>") --indent;
|
||||
}
|
||||
return str;
|
||||
});
|
||||
}
|
||||
|
||||
const outputElement = document.getElementById("output");
|
||||
textEditorElement.addEventListener("input", (e) => {
|
||||
if (debug.includes("events")) {
|
||||
console.log(e);
|
||||
}
|
||||
outputElement.textContent = formatHTML(textEditor.element.innerHTML);
|
||||
});
|
||||
|
||||
textEditor.addEventListener("stylechange", (e) => {
|
||||
if (debug.includes("events")) {
|
||||
console.log(e);
|
||||
}
|
||||
const fontSize = parseInt(e.detail.getPropertyValue("font-size"), 10);
|
||||
const fontWeight = e.detail.getPropertyValue("font-weight");
|
||||
const fontStyle = e.detail.getPropertyValue("font-style");
|
||||
const fontFamily = e.detail.getPropertyValue("font-family");
|
||||
|
||||
fontFamilyElement.value = fontFamily;
|
||||
fontSizeElement.value = fontSize;
|
||||
fontStyleElement.value = fontStyle;
|
||||
fontWeightElement.value = fontWeight;
|
||||
|
||||
const textAlign = e.detail.getPropertyValue("text-align");
|
||||
textAlignLeftElement.checked = textAlign === "left";
|
||||
textAlignCenterElement.checked = textAlign === "center";
|
||||
textAlignRightElement.checked = textAlign === "right";
|
||||
textAlignJustifyElement.checked = textAlign === "justify";
|
||||
|
||||
const direction = e.detail.getPropertyValue("direction");
|
||||
directionLTRElement.checked = direction === "ltr";
|
||||
directionRTLElement.checked = direction === "rtl";
|
||||
});
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
frontend/text-editor/src/public/fonts/Oswald-Bold.ttf
Normal file
BIN
frontend/text-editor/src/public/fonts/Oswald-Bold.ttf
Normal file
Binary file not shown.
BIN
frontend/text-editor/src/public/fonts/Oswald-ExtraLight.ttf
Normal file
BIN
frontend/text-editor/src/public/fonts/Oswald-ExtraLight.ttf
Normal file
Binary file not shown.
BIN
frontend/text-editor/src/public/fonts/Oswald-Light.ttf
Normal file
BIN
frontend/text-editor/src/public/fonts/Oswald-Light.ttf
Normal file
Binary file not shown.
BIN
frontend/text-editor/src/public/fonts/Oswald-Medium.ttf
Normal file
BIN
frontend/text-editor/src/public/fonts/Oswald-Medium.ttf
Normal file
Binary file not shown.
BIN
frontend/text-editor/src/public/fonts/Oswald-Regular.ttf
Normal file
BIN
frontend/text-editor/src/public/fonts/Oswald-Regular.ttf
Normal file
Binary file not shown.
BIN
frontend/text-editor/src/public/fonts/Oswald-SemiBold.ttf
Normal file
BIN
frontend/text-editor/src/public/fonts/Oswald-SemiBold.ttf
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
26
frontend/text-editor/src/public/fonts/fonts.txt
Normal file
26
frontend/text-editor/src/public/fonts/fonts.txt
Normal file
@@ -0,0 +1,26 @@
|
||||
MontserratAlternates-BlackItalic.ttf
|
||||
MontserratAlternates-Black.ttf
|
||||
MontserratAlternates-BoldItalic.ttf
|
||||
MontserratAlternates-Bold.ttf
|
||||
MontserratAlternates-ExtraBoldItalic.ttf
|
||||
MontserratAlternates-ExtraBold.ttf
|
||||
MontserratAlternates-ExtraLightItalic.ttf
|
||||
MontserratAlternates-ExtraLight.ttf
|
||||
MontserratAlternates-Italic.ttf
|
||||
MontserratAlternates-LightItalic.ttf
|
||||
MontserratAlternates-Light.ttf
|
||||
MontserratAlternates-MediumItalic.ttf
|
||||
MontserratAlternates-Medium.ttf
|
||||
MontserratAlternates-Regular.ttf
|
||||
MontserratAlternates-SemiBoldItalic.ttf
|
||||
MontserratAlternates-SemiBold.ttf
|
||||
MontserratAlternates-ThinItalic.ttf
|
||||
MontserratAlternates-Thin.ttf
|
||||
Oswald-Bold.ttf
|
||||
Oswald-ExtraLight.ttf
|
||||
Oswald-Light.ttf
|
||||
Oswald-Medium.ttf
|
||||
Oswald-Regular.ttf
|
||||
Oswald-SemiBold.ttf
|
||||
Oswald-VariableFont_wght.ttf
|
||||
PlaywriteMXGuides-Regular.ttf
|
||||
|
Before Width: | Height: | Size: 995 B After Width: | Height: | Size: 995 B |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
@@ -1,482 +0,0 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Open+Sans:ital,wght@0,300..800;1,300..800&family=Playwrite+ES:wght@100..400&family=Playwrite+NZ:wght@100..400&family=Playwrite+US+Trad:wght@100..400&family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap" rel="stylesheet">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Penpot - Text Editor Playground</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="playground">
|
||||
<form>
|
||||
<fieldset>
|
||||
<legend>Styles</legend>
|
||||
<!-- Font -->
|
||||
<div class="form-group">
|
||||
<label for="font-family">Font family</label>
|
||||
<select id="font-family">
|
||||
<option value="Open+Sans">Open Sans</option>
|
||||
<option value="sourcesanspro">Source Sans Pro</option>
|
||||
<option value="whatever">Whatever</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="font-size">Font size</label>
|
||||
<input id="font-size" type="number" value="14" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="font-weight">Font weight</label>
|
||||
<select id="font-weight">
|
||||
<option value="100">100</option>
|
||||
<option value="200">200</option>
|
||||
<option value="300">300</option>
|
||||
<option value="400">400 (normal)</option>
|
||||
<option value="500">500</option>
|
||||
<option value="600">600</option>
|
||||
<option value="700">700 (bold)</option>
|
||||
<option value="800">800</option>
|
||||
<option value="900">900</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="font-style">Font style</label>
|
||||
<select id="font-style">
|
||||
<option value="normal">normal</option>
|
||||
<option value="italic">italic</option>
|
||||
<option value="oblique">oblique</option>
|
||||
</select>
|
||||
</div>
|
||||
<!-- Text attributes -->
|
||||
<div class="form-group">
|
||||
<label for="line-height">Line height</label>
|
||||
<input id="line-height" type="number" value="1.0" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="letter-spacing">Letter spacing</label>
|
||||
<input id="letter-spacing" type="number" value="0.0" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="direction-ltr">LTR</label>
|
||||
<input id="direction-ltr" type="radio" name="direction" value="ltr" checked />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="direction-rtl">RTL</label>
|
||||
<input id="direction-rtl" type="radio" name="direction" value="rtl" />
|
||||
</div>
|
||||
<!-- Text Align -->
|
||||
<div class="form-group">
|
||||
<label for="text-align-left">Align left</label>
|
||||
<input id="text-align-left" type="radio" name="text-align" value="left" checked />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="text-align-center">Align center</label>
|
||||
<input id="text-align-center" type="radio" name="text-align" value="center" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="text-align-right">Align right</label>
|
||||
<input id="text-align-right" type="radio" name="text-align" value="right" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="text-align-justify">Align justify</label>
|
||||
<input id="text-align-justify" type="radio" name="text-align" value="justify" />
|
||||
</div>
|
||||
<!-- Text Transform -->
|
||||
<div class="form-group">
|
||||
<label for="text-transform-none">None</label>
|
||||
<input id="text-transform-none" type="radio" name="text-transform" value="none" checked />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="text-transform-uppercase">Uppercase</label>
|
||||
<input id="text-transform-uppercase" type="radio" name="text-transform" value="uppercase" checked />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="text-transform-capitalize">Capitalize</label>
|
||||
<input id="text-transform-capitalize" type="radio" name="text-transform" value="capitalize" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="text-transform-lowercase">Lowercase</label>
|
||||
<input id="text-transform-lowercase" type="radio" name="text-transform" value="lowercase" />
|
||||
</div>
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<legend>Debug</legend>
|
||||
<div class="form-group">
|
||||
<label for="direction">Direction</label>
|
||||
<input id="direction" readonly type="text" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="focus-node">Focus Node</label>
|
||||
<input id="focus-node" readonly type="text" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="focus-offset">Focus offset</label>
|
||||
<input id="focus-offset" readonly type="number">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="focus-inline">Focus Inline</label>
|
||||
<input id="focus-inline" readonly type="text" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="focus-paragraph">Focus Paragraph</label>
|
||||
<input id="focus-paragraph" readonly type="text" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="anchor-node">Anchor Node</label>
|
||||
<input id="anchor-node" readonly type="text" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="anchor-offset">Anchor offset</label>
|
||||
<input id="anchor-offset" readonly type="number">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="anchor-inline">Anchor Inline</label>
|
||||
<input id="anchor-inline" readonly type="text" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="anchor-paragraph">Anchor Paragraph</label>
|
||||
<input id="anchor-paragraph" readonly type="text" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="start-container">Start container</label>
|
||||
<input id="start-container" readonly type="text" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="start-offset">Start offset</label>
|
||||
<input id="start-offset" readonly type="text" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="end-container">End container</label>
|
||||
<input id="end-container" readonly type="text" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="end-offset">End offset</label>
|
||||
<input id="end-offset" readonly type="text" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="multi">Multi?</label>
|
||||
<input id="multi" readonly type="checkbox" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="multi-inline">Multi inline?</label>
|
||||
<input id="multi-inline" readonly type="checkbox" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="multi-paragraph">Multi paragraph?</label>
|
||||
<input id="multi-paragraph" readonly type="checkbox" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="is-text-focus">Is text focus?</label>
|
||||
<input id="is-text-focus" readonly type="checkbox" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="is-text-anchor">Is text anchor?</label>
|
||||
<input id="is-text-anchor" readonly type="checkbox" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="is-paragraph-start">Is paragraph start?</label>
|
||||
<input id="is-paragraph-start" readonly type="checkbox" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="is-paragraph-end">Is paragraph end?</label>
|
||||
<input id="is-paragraph-end" readonly type="checkbox" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="is-inline-start">Is inline start?</label>
|
||||
<input id="is-inline-start" readonly type="checkbox" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="is-inline-end">Is inline end?</label>
|
||||
<input id="is-inline-end" readonly type="checkbox">
|
||||
</div>
|
||||
</fieldset>
|
||||
</form>
|
||||
<!--
|
||||
|
||||
Editor
|
||||
|
||||
-->
|
||||
<div class="text-editor-container align-top">
|
||||
<div
|
||||
id="text-editor-selection-imposter"
|
||||
class="text-editor-selection-imposter"></div>
|
||||
<div
|
||||
class="text-editor-content"
|
||||
contenteditable="true"
|
||||
role="textbox"
|
||||
aria-multiline="true"
|
||||
aria-autocomplete="none"
|
||||
spellcheck="false"
|
||||
autocapitalize="false"></div>
|
||||
</div>
|
||||
<!--
|
||||
|
||||
Text output
|
||||
|
||||
-->
|
||||
<canvas id="canvas"></canvas>
|
||||
</div>
|
||||
<script type="module">
|
||||
import "./style.css";
|
||||
import "./editor/TextEditor.css";
|
||||
import { TextEditor } from "./editor/TextEditor";
|
||||
import { SelectionControllerDebug } from "./editor/debug/SelectionControllerDebug";
|
||||
import initWasmModule from './wasm/render_wasm.js';
|
||||
import {
|
||||
init, assignCanvas, render, setupInteraction, useShape, setShapeChildren, addTextShape, updateTextShape, hexToU32ARGB,getRandomInt, getRandomColor, getRandomFloat, addShapeSolidFill, addShapeSolidStrokeFill
|
||||
} from './wasm/lib.js';
|
||||
|
||||
const searchParams = new URLSearchParams(location.search);
|
||||
const debug = searchParams.has("debug")
|
||||
? searchParams.get("debug").split(",")
|
||||
: [];
|
||||
|
||||
const textEditorSelectionImposterElement = document.getElementById(
|
||||
"text-editor-selection-imposter",
|
||||
);
|
||||
|
||||
const textEditorElement = document.querySelector(".text-editor-content");
|
||||
const textEditor = new TextEditor(textEditorElement, {
|
||||
styleDefaults: {
|
||||
"font-family": "sourcesanspro",
|
||||
"font-size": "14",
|
||||
"font-weight": "500",
|
||||
"font-style": "normal",
|
||||
"line-height": "1.2",
|
||||
"letter-spacing": "0",
|
||||
direction: "ltr",
|
||||
"text-align": "left",
|
||||
"text-transform": "none",
|
||||
"text-decoration": "none",
|
||||
"--typography-ref-id": '["~#\'",null]',
|
||||
"--typography-ref-file": '["~#\'",null]',
|
||||
"--font-id": '["~#\'","sourcesanspro"]',
|
||||
"--fills": '[["^ ","~:fill-color","#000000","~:fill-opacity",1]]',
|
||||
},
|
||||
selectionImposterElement: textEditorSelectionImposterElement,
|
||||
debug: new SelectionControllerDebug({
|
||||
direction: document.getElementById("direction"),
|
||||
multiElement: document.getElementById("multi"),
|
||||
multiInlineElement: document.getElementById("multi-inline"),
|
||||
multiParagraphElement: document.getElementById("multi-paragraph"),
|
||||
isParagraphStart: document.getElementById("is-paragraph-start"),
|
||||
isParagraphEnd: document.getElementById("is-paragraph-end"),
|
||||
isInlineStart: document.getElementById("is-inline-start"),
|
||||
isInlineEnd: document.getElementById("is-inline-end"),
|
||||
isTextAnchor: document.getElementById("is-text-anchor"),
|
||||
isTextFocus: document.getElementById("is-text-focus"),
|
||||
focusNode: document.getElementById("focus-node"),
|
||||
focusOffset: document.getElementById("focus-offset"),
|
||||
focusInline: document.getElementById("focus-inline"),
|
||||
focusParagraph: document.getElementById("focus-paragraph"),
|
||||
anchorNode: document.getElementById("anchor-node"),
|
||||
anchorOffset: document.getElementById("anchor-offset"),
|
||||
anchorInline: document.getElementById("anchor-inline"),
|
||||
anchorParagraph: document.getElementById("anchor-paragraph"),
|
||||
startContainer: document.getElementById("start-container"),
|
||||
startOffset: document.getElementById("start-offset"),
|
||||
endContainer: document.getElementById("end-container"),
|
||||
endOffset: document.getElementById("end-offset"),
|
||||
}),
|
||||
});
|
||||
|
||||
const fontFamilyElement = document.getElementById("font-family");
|
||||
const fontSizeElement = document.getElementById("font-size");
|
||||
const fontWeightElement = document.getElementById("font-weight");
|
||||
const fontStyleElement = document.getElementById("font-style");
|
||||
|
||||
const directionLTRElement = document.getElementById("direction-ltr");
|
||||
const directionRTLElement = document.getElementById("direction-rtl");
|
||||
|
||||
const lineHeightElement = document.getElementById("line-height");
|
||||
const letterSpacingElement = document.getElementById("letter-spacing");
|
||||
|
||||
const textAlignLeftElement = document.getElementById("text-align-left");
|
||||
const textAlignCenterElement = document.getElementById("text-align-center");
|
||||
const textAlignRightElement = document.getElementById("text-align-right");
|
||||
const textAlignJustifyElement = document.getElementById("text-align-justify");
|
||||
|
||||
function onDirectionChange(e) {
|
||||
if (debug.includes("events")) {
|
||||
console.log(e);
|
||||
}
|
||||
if (e.target.checked) {
|
||||
textEditor.applyStylesToSelection({
|
||||
direction: e.target.value,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
directionLTRElement.addEventListener("change", onDirectionChange);
|
||||
directionRTLElement.addEventListener("change", onDirectionChange);
|
||||
|
||||
function onTextAlignChange(e) {
|
||||
if (debug.includes("events")) {
|
||||
console.log(e);
|
||||
}
|
||||
if (e.target.checked) {
|
||||
textEditor.applyStylesToSelection({
|
||||
"text-align": e.target.value,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
textAlignLeftElement.addEventListener("change", onTextAlignChange);
|
||||
textAlignCenterElement.addEventListener("change", onTextAlignChange);
|
||||
textAlignRightElement.addEventListener("change", onTextAlignChange);
|
||||
textAlignJustifyElement.addEventListener("change", onTextAlignChange);
|
||||
|
||||
fontFamilyElement.addEventListener("change", (e) => {
|
||||
if (debug.includes("events")) {
|
||||
console.log(e);
|
||||
}
|
||||
textEditor.applyStylesToSelection({
|
||||
"font-family": e.target.value,
|
||||
});
|
||||
});
|
||||
|
||||
fontWeightElement.addEventListener("change", (e) => {
|
||||
if (debug.includes("events")) {
|
||||
console.log(e);
|
||||
}
|
||||
textEditor.applyStylesToSelection({
|
||||
"font-weight": e.target.value,
|
||||
});
|
||||
});
|
||||
|
||||
fontSizeElement.addEventListener("change", (e) => {
|
||||
if (debug.includes("events")) {
|
||||
console.log(e);
|
||||
}
|
||||
textEditor.applyStylesToSelection({
|
||||
"font-size": e.target.value,
|
||||
});
|
||||
});
|
||||
|
||||
lineHeightElement.addEventListener("change", (e) => {
|
||||
if (debug.includes("events")) {
|
||||
console.log(e);
|
||||
}
|
||||
textEditor.applyStylesToSelection({
|
||||
"line-height": e.target.value,
|
||||
});
|
||||
});
|
||||
|
||||
letterSpacingElement.addEventListener("change", (e) => {
|
||||
if (debug.includes("events")) {
|
||||
console.log(e);
|
||||
}
|
||||
textEditor.applyStylesToSelection({
|
||||
"letter-spacing": e.target.value,
|
||||
});
|
||||
});
|
||||
|
||||
fontStyleElement.addEventListener("change", (e) => {
|
||||
if (debug.includes("events")) {
|
||||
console.log(e);
|
||||
}
|
||||
textEditor.applyStylesToSelection({
|
||||
"font-style": e.target.value,
|
||||
});
|
||||
});
|
||||
|
||||
function formatHTML(html, options) {
|
||||
const spaces = options?.spaces ?? 4;
|
||||
let indent = 0;
|
||||
return html.replace(/<\/?(.*?)>/g, (fullMatch) => {
|
||||
let str = fullMatch + "\n";
|
||||
if (fullMatch.startsWith("</")) {
|
||||
--indent;
|
||||
str = " ".repeat(indent * spaces) + str;
|
||||
} else {
|
||||
str = " ".repeat(indent * spaces) + str;
|
||||
++indent;
|
||||
if (fullMatch === "<br>") --indent;
|
||||
}
|
||||
return str;
|
||||
});
|
||||
}
|
||||
|
||||
const fontSize = 14;
|
||||
const children = [];
|
||||
const uuid = crypto.randomUUID();
|
||||
children.push(uuid);
|
||||
const outputElement = document.getElementById("output");
|
||||
textEditorElement.addEventListener("input", (e) => {
|
||||
if (debug.includes("events")) {
|
||||
console.log(e);
|
||||
}
|
||||
outputElement.textContent = formatHTML(textEditor.element.innerHTML);
|
||||
});
|
||||
|
||||
textEditor.addEventListener("needslayout", (e) => {
|
||||
useShape(uuid);
|
||||
updateTextShape(fontSize, textEditor.root);
|
||||
render();
|
||||
})
|
||||
|
||||
textEditor.addEventListener("stylechange", (e) => {
|
||||
if (debug.includes("events")) {
|
||||
console.log(e);
|
||||
}
|
||||
const fontSize = parseInt(e.detail.getPropertyValue("font-size"), 10);
|
||||
const fontWeight = e.detail.getPropertyValue("font-weight");
|
||||
const fontStyle = e.detail.getPropertyValue("font-style");
|
||||
const fontFamily = e.detail.getPropertyValue("font-family");
|
||||
|
||||
fontFamilyElement.value = fontFamily;
|
||||
fontSizeElement.value = fontSize;
|
||||
fontStyleElement.value = fontStyle;
|
||||
fontWeightElement.value = fontWeight;
|
||||
|
||||
const textAlign = e.detail.getPropertyValue("text-align");
|
||||
textAlignLeftElement.checked = textAlign === "left";
|
||||
textAlignCenterElement.checked = textAlign === "center";
|
||||
textAlignRightElement.checked = textAlign === "right";
|
||||
textAlignJustifyElement.checked = textAlign === "justify";
|
||||
|
||||
const direction = e.detail.getPropertyValue("direction");
|
||||
directionLTRElement.checked = direction === "ltr";
|
||||
directionRTLElement.checked = direction === "rtl";
|
||||
});
|
||||
|
||||
const canvas = document.getElementById("canvas");
|
||||
canvas.width = window.innerWidth;
|
||||
canvas.height = window.innerHeight;
|
||||
|
||||
const MIN_LINES = 1;
|
||||
const MAX_LINES = 5;
|
||||
const MIN_WORDS = 1;
|
||||
const MAX_WORDS = 10;
|
||||
|
||||
initWasmModule().then(Module => {
|
||||
init(Module);
|
||||
assignCanvas(canvas);
|
||||
Module._set_canvas_background(hexToU32ARGB("#FABADA", 1));
|
||||
Module._set_view(1, 0, 0);
|
||||
Module._init_shapes_pool(1);
|
||||
setupInteraction(canvas);
|
||||
|
||||
|
||||
useShape(uuid);
|
||||
Module._set_parent(0, 0, 0, 0);
|
||||
Module._set_shape_type(5);
|
||||
|
||||
const x1 = 0;
|
||||
const y1 = 0;
|
||||
const width = canvas.width;
|
||||
const height = canvas.height;
|
||||
Module._set_shape_selrect(x1, y1, x1 + width, y1 + height);
|
||||
|
||||
addTextShape(fontSize, "");
|
||||
|
||||
useShape("00000000-0000-0000-0000-000000000000");
|
||||
setShapeChildren(children);
|
||||
render()
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -182,7 +182,6 @@ export function set_parent(id) {
|
||||
}
|
||||
|
||||
export function render() {
|
||||
console.log('render')
|
||||
Module._set_view(1, 0, 0);
|
||||
Module._render_from_cache();
|
||||
debouncedRender();
|
||||
@@ -284,9 +283,11 @@ function getFontStyle(fontStyle) {
|
||||
switch (fontStyle) {
|
||||
default:
|
||||
case 'normal':
|
||||
case 'regular':
|
||||
return 0;
|
||||
case 'oblique':
|
||||
case 'italic':
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -316,6 +317,7 @@ function setParagraphData(dview, { numLeaves, textAlign, textDirection, textDeco
|
||||
}
|
||||
|
||||
function setLeafData(dview, leafOffset, {
|
||||
fontId,
|
||||
fontStyle,
|
||||
fontSize,
|
||||
fontWeight,
|
||||
@@ -331,10 +333,10 @@ function setLeafData(dview, leafOffset, {
|
||||
dview.setFloat32(leafOffset + 4, fontSize, true); // font-size
|
||||
dview.setFloat32(leafOffset + 8, letterSpacing, true); // letter-spacing
|
||||
dview.setInt32(leafOffset + 12, fontWeight, true); // font-weight: normal
|
||||
dview.setUint32(leafOffset + 16, 0, true); // font-id (UUID part 1)
|
||||
dview.setUint32(leafOffset + 20, 0, true); // font-id (UUID part 2)
|
||||
dview.setUint32(leafOffset + 24, 0, true); // font-id (UUID part 3)
|
||||
dview.setUint32(leafOffset + 28, 0, true); // font-id (UUID part 4)
|
||||
dview.setUint32(leafOffset + 16, fontId[0], true); // font-id (UUID part 1)
|
||||
dview.setUint32(leafOffset + 20, fontId[1], true); // font-id (UUID part 2)
|
||||
dview.setUint32(leafOffset + 24, fontId[2], true); // font-id (UUID part 3)
|
||||
dview.setUint32(leafOffset + 28, fontId[3], true); // font-id (UUID part 4)
|
||||
dview.setUint32(leafOffset + 32, 0, true); // font-family hash
|
||||
dview.setUint32(leafOffset + 36, 0, true); // font-variant-id (UUID part 1)
|
||||
dview.setUint32(leafOffset + 40, 0, true); // font-variant-id (UUID part 2)
|
||||
@@ -344,7 +346,15 @@ function setLeafData(dview, leafOffset, {
|
||||
dview.setUint32(leafOffset + 56, totalFills, true); // total fills count
|
||||
}
|
||||
|
||||
export function updateTextShape(fontSize, root) {
|
||||
function getFontFrom(fontFamily, fontWeight, fontStyle, fonts) {
|
||||
const fontList = fonts.get(fontFamily)
|
||||
if (!fontList) {
|
||||
return null
|
||||
}
|
||||
return fontList.find(fontData => fontData.weight === fontWeight && fontStyle === fontData.style)
|
||||
}
|
||||
|
||||
export function updateTextShape(root, fonts) {
|
||||
// Calculate fills
|
||||
const fills = [
|
||||
{
|
||||
@@ -358,7 +368,6 @@ export function updateTextShape(fontSize, root) {
|
||||
const totalFillsSize = totalFills * FILL_SIZE;
|
||||
|
||||
const paragraphs = root.children;
|
||||
console.log("paragraphs", paragraphs.length);
|
||||
|
||||
Module._clear_shape_text();
|
||||
for (const paragraph of paragraphs) {
|
||||
@@ -366,19 +375,16 @@ export function updateTextShape(fontSize, root) {
|
||||
|
||||
const leaves = paragraph.children;
|
||||
const numLeaves = leaves.length;
|
||||
console.log("leaves", numLeaves);
|
||||
|
||||
for (const leaf of leaves) {
|
||||
const text = leaf.textContent;
|
||||
const textBuffer = new TextEncoder().encode(text);
|
||||
const textSize = textBuffer.byteLength;
|
||||
console.log("text", text, textSize);
|
||||
totalSize += LEAF_ATTR_SIZE + totalFillsSize;
|
||||
}
|
||||
|
||||
totalSize += paragraph.textContent.length;
|
||||
|
||||
console.log("Total Size", totalSize);
|
||||
// Allocate buffer
|
||||
const bufferPtr = allocBytes(totalSize);
|
||||
const heap = new Uint8Array(Module.HEAPU8.buffer, bufferPtr, totalSize);
|
||||
@@ -387,39 +393,21 @@ export function updateTextShape(fontSize, root) {
|
||||
const textAlign = getTextAlign(
|
||||
paragraph.style.getPropertyValue("text-align"),
|
||||
);
|
||||
console.log("text-align", textAlign);
|
||||
const textDirection = getTextDirection(
|
||||
paragraph.style.getPropertyValue("text-direction"),
|
||||
);
|
||||
console.log("text-direction", textDirection);
|
||||
const textDecoration = getTextDecoration(
|
||||
paragraph.style.getPropertyValue("text-decoration"),
|
||||
);
|
||||
console.log("text-decoration", textDecoration);
|
||||
const textTransform = getTextTransform(
|
||||
paragraph.style.getPropertyValue("text-transform"),
|
||||
);
|
||||
console.log("text-transform", textTransform);
|
||||
const lineHeight = parseFloat(
|
||||
paragraph.style.getPropertyValue("line-height"),
|
||||
);
|
||||
console.log("line-height", lineHeight);
|
||||
const letterSpacing = parseFloat(
|
||||
paragraph.style.getPropertyValue("letter-spacing"),
|
||||
);
|
||||
console.log("letter-spacing", letterSpacing);
|
||||
|
||||
/*
|
||||
num_leaves: u32,
|
||||
text_align: u8,
|
||||
text_direction: u8,
|
||||
text_decoration: u8,
|
||||
text_transform: u8,
|
||||
line_height: f32,
|
||||
letter_spacing: f32,
|
||||
typography_ref_file: [u32; 4],
|
||||
typography_ref_id: [u32; 4],
|
||||
*/
|
||||
|
||||
setParagraphData(dview, {
|
||||
numLeaves,
|
||||
@@ -432,31 +420,25 @@ export function updateTextShape(fontSize, root) {
|
||||
})
|
||||
let leafOffset = PARAGRAPH_ATTR_SIZE;
|
||||
for (const leaf of leaves) {
|
||||
console.log(
|
||||
"leafOffset",
|
||||
leafOffset,
|
||||
PARAGRAPH_ATTR_SIZE,
|
||||
LEAF_ATTR_SIZE,
|
||||
FILL_SIZE,
|
||||
totalFills,
|
||||
totalFillsSize,
|
||||
);
|
||||
const fontStyle = getFontStyle(leaf.style.getPropertyValue("font-style"));
|
||||
const fontStyle = leaf.style.getPropertyValue("font-style");
|
||||
const fontStyleSerialized = getFontStyle(fontStyle);
|
||||
const fontSize = parseFloat(leaf.style.getPropertyValue("font-size"));
|
||||
const letterSpacing = parseFloat(leaf.style.getPropertyValue("letter-spacing"))
|
||||
console.log("font-size", fontSize, "letter-spacing", letterSpacing);
|
||||
const fontWeight = parseInt(
|
||||
leaf.style.getPropertyValue("font-weight"),
|
||||
10,
|
||||
);
|
||||
console.log("font-weight", fontWeight);
|
||||
|
||||
const text = leaf.textContent;
|
||||
const textBuffer = new TextEncoder().encode(text);
|
||||
const textSize = textBuffer.byteLength;
|
||||
|
||||
const fontFamily = leaf.style.getPropertyValue('font-family');
|
||||
const fontData = getFontFrom(fontFamily, fontWeight, fontStyle, fonts)
|
||||
const defaultFontId = new Uint32Array([0, 0, 0, 0])
|
||||
const fontId = fontData ? getU32(fontData.id) : defaultFontId
|
||||
setLeafData(dview, leafOffset, {
|
||||
fontStyle,
|
||||
fontId,
|
||||
fontStyle: fontStyleSerialized,
|
||||
textDecoration: 0,
|
||||
textTransform: 0,
|
||||
textDirection: 0,
|
||||
@@ -464,8 +446,8 @@ export function updateTextShape(fontSize, root) {
|
||||
fontWeight,
|
||||
letterSpacing,
|
||||
textSize,
|
||||
totalFills
|
||||
})
|
||||
totalFills,
|
||||
});
|
||||
|
||||
// Serialize fills
|
||||
let fillOffset = leafOffset + LEAF_ATTR_SIZE;
|
||||
@@ -485,14 +467,13 @@ export function updateTextShape(fontSize, root) {
|
||||
|
||||
// Add text content
|
||||
const textOffset = leafOffset;
|
||||
console.log('textOffset', textOffset);
|
||||
heap.set(textBuffer, textOffset);
|
||||
|
||||
Module._set_shape_text_content();
|
||||
}
|
||||
}
|
||||
|
||||
export function addTextShape(fontSize, text) {
|
||||
export function addTextShape(text, fonts) {
|
||||
const numLeaves = 1; // Single text leaf for simplicity
|
||||
const textBuffer = new TextEncoder().encode(text);
|
||||
const textSize = textBuffer.byteLength;
|
||||
@@ -529,13 +510,25 @@ export function addTextShape(fontSize, text) {
|
||||
|
||||
// Serialize leaf attributes
|
||||
const leafOffset = PARAGRAPH_ATTR_SIZE;
|
||||
const fontStyle = getFontStyle('normal');
|
||||
const fontStyleSerialized = getFontStyle(fontStyle);
|
||||
const fontSize = 14;
|
||||
const letterSpacing = 0;
|
||||
const fontWeight = 400;
|
||||
const fontFamily = 'MontserratAlternates';
|
||||
const fontData = getFontFrom(fontFamily, fontWeight, fontStyle, fonts);
|
||||
const defaultFontId = new Uint32Array([0, 0, 0, 0]);
|
||||
const fontId = fontData ? getU32(fontData.id) : defaultFontId;
|
||||
|
||||
setLeafData(dview, leafOffset, {
|
||||
fontId,
|
||||
fontSize,
|
||||
fontWeight: 400,
|
||||
fontStyle: fontStyleSerialized,
|
||||
fontWeight,
|
||||
textDecoration: 0,
|
||||
textDirection: 0,
|
||||
textTransform: 0,
|
||||
letterSpacing: 0,
|
||||
letterSpacing,
|
||||
textSize,
|
||||
totalFills,
|
||||
});
|
||||
@@ -558,3 +551,44 @@ export function addTextShape(fontSize, text) {
|
||||
// Call the WebAssembly function
|
||||
Module._set_shape_text_content();
|
||||
}
|
||||
|
||||
export function storeFonts(fonts) {
|
||||
for (const [fontName, fontStyles] of fonts) {
|
||||
for (const font of fontStyles) {
|
||||
const shapeId = getU32('00000000-0000-0000-0000-000000000000');
|
||||
const fontId = getU32(font.id);
|
||||
const weight = font.weight;
|
||||
const style = getFontStyle(font.style);
|
||||
const size = font.arrayBuffer.byteLength;
|
||||
const ptr = Module._alloc_bytes(size);
|
||||
const heap = Module.HEAPU8;
|
||||
const mem = new Uint8Array(heap.buffer, ptr, size);
|
||||
mem.set(new Uint8Array(font.arrayBuffer));
|
||||
const emoji = false
|
||||
const fallback = false
|
||||
Module._store_font(
|
||||
shapeId[0],
|
||||
shapeId[1],
|
||||
shapeId[2],
|
||||
shapeId[3],
|
||||
fontId[0],
|
||||
fontId[1],
|
||||
fontId[2],
|
||||
fontId[3],
|
||||
weight,
|
||||
style,
|
||||
emoji,
|
||||
fallback,
|
||||
);
|
||||
Module._is_font_uploaded(
|
||||
fontId[0],
|
||||
fontId[1],
|
||||
fontId[2],
|
||||
fontId[3],
|
||||
weight,
|
||||
style,
|
||||
emoji,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user