diff --git a/src/wp-includes/fonts/twemoji/LICENSE-GRAPHICS b/src/wp-includes/fonts/twemoji/LICENSE-GRAPHICS new file mode 100644 index 0000000000000..dc8853a70cfa9 --- /dev/null +++ b/src/wp-includes/fonts/twemoji/LICENSE-GRAPHICS @@ -0,0 +1,393 @@ +Attribution 4.0 International + +======================================================================= + +Creative Commons Corporation ("Creative Commons") is not a law firm and +does not provide legal services or legal advice. Distribution of +Creative Commons public licenses does not create a lawyer-client or +other relationship. Creative Commons makes its licenses and related +information available on an "as-is" basis. Creative Commons gives no +warranties regarding its licenses, any material licensed under their +terms and conditions, or any related information. Creative Commons +disclaims all liability for damages resulting from their use to the +fullest extent possible. + +Using Creative Commons Public Licenses + +Creative Commons public licenses provide a standard set of terms and +conditions that creators and other rights holders may use to share +original works of authorship and other material subject to copyright +and certain other rights specified in the public license below. The +following considerations are for informational purposes only, are not +exhaustive, and do not form part of our licenses. + + Considerations for licensors: Our public licenses are + intended for use by those authorized to give the public + permission to use material in ways otherwise restricted by + copyright and certain other rights. Our licenses are + irrevocable. Licensors should read and understand the terms + and conditions of the license they choose before applying it. + Licensors should also secure all rights necessary before + applying our licenses so that the public can reuse the + material as expected. Licensors should clearly mark any + material not subject to the license. This includes other CC- + licensed material, or material used under an exception or + limitation to copyright. More considerations for licensors: + wiki.creativecommons.org/Considerations_for_licensors + + Considerations for the public: By using one of our public + licenses, a licensor grants the public permission to use the + licensed material under specified terms and conditions. If + the licensor's permission is not necessary for any reason--for + example, because of any applicable exception or limitation to + copyright--then that use is not regulated by the license. Our + licenses grant only permissions under copyright and certain + other rights that a licensor has authority to grant. Use of + the licensed material may still be restricted for other + reasons, including because others have copyright or other + rights in the material. A licensor may make special requests, + such as asking that all changes be marked or described. + Although not required by our licenses, you are encouraged to + respect those requests where reasonable. More_considerations + for the public: + wiki.creativecommons.org/Considerations_for_licensees + +======================================================================= + +Creative Commons Attribution 4.0 International Public License + +By exercising the Licensed Rights (defined below), You accept and agree +to be bound by the terms and conditions of this Creative Commons +Attribution 4.0 International Public License ("Public License"). To the +extent this Public License may be interpreted as a contract, You are +granted the Licensed Rights in consideration of Your acceptance of +these terms and conditions, and the Licensor grants You such rights in +consideration of benefits the Licensor receives from making the +Licensed Material available under these terms and conditions. + + +Section 1 -- Definitions. + + a. Adapted Material means material subject to Copyright and Similar + Rights that is derived from or based upon the Licensed Material + and in which the Licensed Material is translated, altered, + arranged, transformed, or otherwise modified in a manner requiring + permission under the Copyright and Similar Rights held by the + Licensor. For purposes of this Public License, where the Licensed + Material is a musical work, performance, or sound recording, + Adapted Material is always produced where the Licensed Material is + synched in timed relation with a moving image. + + b. Adapter's License means the license You apply to Your Copyright + and Similar Rights in Your contributions to Adapted Material in + accordance with the terms and conditions of this Public License. + + c. Copyright and Similar Rights means copyright and/or similar rights + closely related to copyright including, without limitation, + performance, broadcast, sound recording, and Sui Generis Database + Rights, without regard to how the rights are labeled or + categorized. For purposes of this Public License, the rights + specified in Section 2(b)(1)-(2) are not Copyright and Similar + Rights. + + d. Effective Technological Measures means those measures that, in the + absence of proper authority, may not be circumvented under laws + fulfilling obligations under Article 11 of the WIPO Copyright + Treaty adopted on December 20, 1996, and/or similar international + agreements. + + e. Exceptions and Limitations means fair use, fair dealing, and/or + any other exception or limitation to Copyright and Similar Rights + that applies to Your use of the Licensed Material. + + f. Licensed Material means the artistic or literary work, database, + or other material to which the Licensor applied this Public + License. + + g. Licensed Rights means the rights granted to You subject to the + terms and conditions of this Public License, which are limited to + all Copyright and Similar Rights that apply to Your use of the + Licensed Material and that the Licensor has authority to license. + + h. Licensor means the individual(s) or entity(ies) granting rights + under this Public License. + + i. Share means to provide material to the public by any means or + process that requires permission under the Licensed Rights, such + as reproduction, public display, public performance, distribution, + dissemination, communication, or importation, and to make material + available to the public including in ways that members of the + public may access the material from a place and at a time + individually chosen by them. + + j. Sui Generis Database Rights means rights other than copyright + resulting from Directive 96/9/EC of the European Parliament and of + the Council of 11 March 1996 on the legal protection of databases, + as amended and/or succeeded, as well as other essentially + equivalent rights anywhere in the world. + + k. You means the individual or entity exercising the Licensed Rights + under this Public License. Your has a corresponding meaning. + + +Section 2 -- Scope. + + a. License grant. + + 1. Subject to the terms and conditions of this Public License, + the Licensor hereby grants You a worldwide, royalty-free, + non-sublicensable, non-exclusive, irrevocable license to + exercise the Licensed Rights in the Licensed Material to: + + a. reproduce and Share the Licensed Material, in whole or + in part; and + + b. produce, reproduce, and Share Adapted Material. + + 2. Exceptions and Limitations. For the avoidance of doubt, where + Exceptions and Limitations apply to Your use, this Public + License does not apply, and You do not need to comply with + its terms and conditions. + + 3. Term. The term of this Public License is specified in Section + 6(a). + + 4. Media and formats; technical modifications allowed. The + Licensor authorizes You to exercise the Licensed Rights in + all media and formats whether now known or hereafter created, + and to make technical modifications necessary to do so. The + Licensor waives and/or agrees not to assert any right or + authority to forbid You from making technical modifications + necessary to exercise the Licensed Rights, including + technical modifications necessary to circumvent Effective + Technological Measures. For purposes of this Public License, + simply making modifications authorized by this Section 2(a) + (4) never produces Adapted Material. + + 5. Downstream recipients. + + a. Offer from the Licensor -- Licensed Material. Every + recipient of the Licensed Material automatically + receives an offer from the Licensor to exercise the + Licensed Rights under the terms and conditions of this + Public License. + + b. No downstream restrictions. You may not offer or impose + any additional or different terms or conditions on, or + apply any Effective Technological Measures to, the + Licensed Material if doing so restricts exercise of the + Licensed Rights by any recipient of the Licensed + Material. + + 6. No endorsement. Nothing in this Public License constitutes or + may be construed as permission to assert or imply that You + are, or that Your use of the Licensed Material is, connected + with, or sponsored, endorsed, or granted official status by, + the Licensor or others designated to receive attribution as + provided in Section 3(a)(1)(A)(i). + + b. Other rights. + + 1. Moral rights, such as the right of integrity, are not + licensed under this Public License, nor are publicity, + privacy, and/or other similar personality rights; however, to + the extent possible, the Licensor waives and/or agrees not to + assert any such rights held by the Licensor to the limited + extent necessary to allow You to exercise the Licensed + Rights, but not otherwise. + + 2. Patent and trademark rights are not licensed under this + Public License. + + 3. To the extent possible, the Licensor waives any right to + collect royalties from You for the exercise of the Licensed + Rights, whether directly or through a collecting society + under any voluntary or waivable statutory or compulsory + licensing scheme. In all other cases the Licensor expressly + reserves any right to collect such royalties. + + +Section 3 -- License Conditions. + +Your exercise of the Licensed Rights is expressly made subject to the +following conditions. + + a. Attribution. + + 1. If You Share the Licensed Material (including in modified + form), You must: + + a. retain the following if it is supplied by the Licensor + with the Licensed Material: + + i. identification of the creator(s) of the Licensed + Material and any others designated to receive + attribution, in any reasonable manner requested by + the Licensor (including by pseudonym if + designated); + + ii. a copyright notice; + + iii. a notice that refers to this Public License; + + iv. a notice that refers to the disclaimer of + warranties; + + v. a URI or hyperlink to the Licensed Material to the + extent reasonably practicable; + + b. indicate if You modified the Licensed Material and + retain an indication of any previous modifications; and + + c. indicate the Licensed Material is licensed under this + Public License, and include the text of, or the URI or + hyperlink to, this Public License. + + 2. You may satisfy the conditions in Section 3(a)(1) in any + reasonable manner based on the medium, means, and context in + which You Share the Licensed Material. For example, it may be + reasonable to satisfy the conditions by providing a URI or + hyperlink to a resource that includes the required + information. + + 3. If requested by the Licensor, You must remove any of the + information required by Section 3(a)(1)(A) to the extent + reasonably practicable. + + 4. If You Share Adapted Material You produce, the Adapter's + License You apply must not prevent recipients of the Adapted + Material from complying with this Public License. + + +Section 4 -- Sui Generis Database Rights. + +Where the Licensed Rights include Sui Generis Database Rights that +apply to Your use of the Licensed Material: + + a. for the avoidance of doubt, Section 2(a)(1) grants You the right + to extract, reuse, reproduce, and Share all or a substantial + portion of the contents of the database; + + b. if You include all or a substantial portion of the database + contents in a database in which You have Sui Generis Database + Rights, then the database in which You have Sui Generis Database + Rights (but not its individual contents) is Adapted Material; and + + c. You must comply with the conditions in Section 3(a) if You Share + all or a substantial portion of the contents of the database. + +For the avoidance of doubt, this Section 4 supplements and does not +replace Your obligations under this Public License where the Licensed +Rights include other Copyright and Similar Rights. + + +Section 5 -- Disclaimer of Warranties and Limitation of Liability. + + a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE + EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS + AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF + ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS, + IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION, + WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR + PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS, + ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT + KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT + ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU. + + b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE + TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION, + NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT, + INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES, + COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR + USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN + ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR + DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR + IN PART, THIS LIMITATION MAY NOT APPLY TO YOU. + + c. The disclaimer of warranties and limitation of liability provided + above shall be interpreted in a manner that, to the extent + possible, most closely approximates an absolute disclaimer and + waiver of all liability. + + +Section 6 -- Term and Termination. + + a. This Public License applies for the term of the Copyright and + Similar Rights licensed here. However, if You fail to comply with + this Public License, then Your rights under this Public License + terminate automatically. + + b. Where Your right to use the Licensed Material has terminated under + Section 6(a), it reinstates: + + 1. automatically as of the date the violation is cured, provided + it is cured within 30 days of Your discovery of the + violation; or + + 2. upon express reinstatement by the Licensor. + + For the avoidance of doubt, this Section 6(b) does not affect any + right the Licensor may have to seek remedies for Your violations + of this Public License. + + c. For the avoidance of doubt, the Licensor may also offer the + Licensed Material under separate terms or conditions or stop + distributing the Licensed Material at any time; however, doing so + will not terminate this Public License. + + d. Sections 1, 5, 6, 7, and 8 survive termination of this Public + License. + + +Section 7 -- Other Terms and Conditions. + + a. The Licensor shall not be bound by any additional or different + terms or conditions communicated by You unless expressly agreed. + + b. Any arrangements, understandings, or agreements regarding the + Licensed Material not stated herein are separate from and + independent of the terms and conditions of this Public License. + + +Section 8 -- Interpretation. + + a. For the avoidance of doubt, this Public License does not, and + shall not be interpreted to, reduce, limit, restrict, or impose + conditions on any use of the Licensed Material that could lawfully + be made without permission under this Public License. + + b. To the extent possible, if any provision of this Public License is + deemed unenforceable, it shall be automatically reformed to the + minimum extent necessary to make it enforceable. If the provision + cannot be reformed, it shall be severed from this Public License + without affecting the enforceability of the remaining terms and + conditions. + + c. No term or condition of this Public License will be waived and no + failure to comply consented to unless expressly agreed to by the + Licensor. + + d. Nothing in this Public License constitutes or may be interpreted + as a limitation upon, or waiver of, any privileges and immunities + that apply to the Licensor or You, including from the legal + processes of any jurisdiction or authority. + + +======================================================================= + +Creative Commons is not a party to its public licenses. +Notwithstanding, Creative Commons may elect to apply one of its public +licenses to material it publishes and in those instances will be +considered the "Licensor." Except for the limited purpose of indicating +that material is shared under a Creative Commons public license or as +otherwise permitted by the Creative Commons policies published at +creativecommons.org/policies, Creative Commons does not authorize the +use of the trademark "Creative Commons" or any other trademark or logo +of Creative Commons without its prior written consent including, +without limitation, in connection with any unauthorized modifications +to any of its public licenses or any other arrangements, +understandings, or agreements concerning use of licensed material. For +the avoidance of doubt, this paragraph does not form part of the public +licenses. + +Creative Commons may be contacted at creativecommons.org. diff --git a/src/wp-includes/fonts/twemoji/aliases.txt b/src/wp-includes/fonts/twemoji/aliases.txt new file mode 100644 index 0000000000000..e2bbe0240dcb1 --- /dev/null +++ b/src/wp-includes/fonts/twemoji/aliases.txt @@ -0,0 +1,1052 @@ +1f3c3-1f3fb-200d-2640-200d-27a1-fe0f.svg +1f3c3-1f3fb-200d-2640-200d-27a1.svg +1f3c3-1f3fb-200d-2640-fe0f-200d-27a1.svg +1f3c3-1f3fb-200d-2640.svg +1f3c3-1f3fb-200d-2642-200d-27a1-fe0f.svg +1f3c3-1f3fb-200d-2642-200d-27a1.svg +1f3c3-1f3fb-200d-2642-fe0f-200d-27a1.svg +1f3c3-1f3fb-200d-2642.svg +1f3c3-1f3fb-200d-27a1.svg +1f3c3-1f3fc-200d-2640-200d-27a1-fe0f.svg +1f3c3-1f3fc-200d-2640-200d-27a1.svg +1f3c3-1f3fc-200d-2640-fe0f-200d-27a1.svg +1f3c3-1f3fc-200d-2640.svg +1f3c3-1f3fc-200d-2642-200d-27a1-fe0f.svg +1f3c3-1f3fc-200d-2642-200d-27a1.svg +1f3c3-1f3fc-200d-2642-fe0f-200d-27a1.svg +1f3c3-1f3fc-200d-2642.svg +1f3c3-1f3fc-200d-27a1.svg +1f3c3-1f3fd-200d-2640-200d-27a1-fe0f.svg +1f3c3-1f3fd-200d-2640-200d-27a1.svg +1f3c3-1f3fd-200d-2640-fe0f-200d-27a1.svg +1f3c3-1f3fd-200d-2640.svg +1f3c3-1f3fd-200d-2642-200d-27a1-fe0f.svg +1f3c3-1f3fd-200d-2642-200d-27a1.svg +1f3c3-1f3fd-200d-2642-fe0f-200d-27a1.svg +1f3c3-1f3fd-200d-2642.svg +1f3c3-1f3fd-200d-27a1.svg +1f3c3-1f3fe-200d-2640-200d-27a1-fe0f.svg +1f3c3-1f3fe-200d-2640-200d-27a1.svg +1f3c3-1f3fe-200d-2640-fe0f-200d-27a1.svg +1f3c3-1f3fe-200d-2640.svg +1f3c3-1f3fe-200d-2642-200d-27a1-fe0f.svg +1f3c3-1f3fe-200d-2642-200d-27a1.svg +1f3c3-1f3fe-200d-2642-fe0f-200d-27a1.svg +1f3c3-1f3fe-200d-2642.svg +1f3c3-1f3fe-200d-27a1.svg +1f3c3-1f3ff-200d-2640-200d-27a1-fe0f.svg +1f3c3-1f3ff-200d-2640-200d-27a1.svg +1f3c3-1f3ff-200d-2640-fe0f-200d-27a1.svg +1f3c3-1f3ff-200d-2640.svg +1f3c3-1f3ff-200d-2642-200d-27a1-fe0f.svg +1f3c3-1f3ff-200d-2642-200d-27a1.svg +1f3c3-1f3ff-200d-2642-fe0f-200d-27a1.svg +1f3c3-1f3ff-200d-2642.svg +1f3c3-1f3ff-200d-27a1.svg +1f3c3-200d-2640-200d-27a1-fe0f.svg +1f3c3-200d-2640-200d-27a1.svg +1f3c3-200d-2640-fe0f-200d-27a1.svg +1f3c3-200d-2640.svg +1f3c3-200d-2642-200d-27a1-fe0f.svg +1f3c3-200d-2642-200d-27a1.svg +1f3c3-200d-2642-fe0f-200d-27a1.svg +1f3c3-200d-2642.svg +1f3c3-200d-27a1.svg +1f3c4-1f3fb-200d-2640.svg +1f3c4-1f3fb-200d-2642.svg +1f3c4-1f3fc-200d-2640.svg +1f3c4-1f3fc-200d-2642.svg +1f3c4-1f3fd-200d-2640.svg +1f3c4-1f3fd-200d-2642.svg +1f3c4-1f3fe-200d-2640.svg +1f3c4-1f3fe-200d-2642.svg +1f3c4-1f3ff-200d-2640.svg +1f3c4-1f3ff-200d-2642.svg +1f3c4-200d-2640.svg +1f3c4-200d-2642.svg +1f3ca-1f3fb-200d-2640.svg +1f3ca-1f3fb-200d-2642.svg +1f3ca-1f3fc-200d-2640.svg +1f3ca-1f3fc-200d-2642.svg +1f3ca-1f3fd-200d-2640.svg +1f3ca-1f3fd-200d-2642.svg +1f3ca-1f3fe-200d-2640.svg +1f3ca-1f3fe-200d-2642.svg +1f3ca-1f3ff-200d-2640.svg +1f3ca-1f3ff-200d-2642.svg +1f3ca-200d-2640.svg +1f3ca-200d-2642.svg +1f3cb-1f3fb-200d-2640.svg +1f3cb-1f3fb-200d-2642.svg +1f3cb-1f3fc-200d-2640.svg +1f3cb-1f3fc-200d-2642.svg +1f3cb-1f3fd-200d-2640.svg +1f3cb-1f3fd-200d-2642.svg +1f3cb-1f3fe-200d-2640.svg +1f3cb-1f3fe-200d-2642.svg +1f3cb-1f3ff-200d-2640.svg +1f3cb-1f3ff-200d-2642.svg +1f3cb-200d-2640-fe0f.svg +1f3cb-200d-2640.svg +1f3cb-200d-2642-fe0f.svg +1f3cb-200d-2642.svg +1f3cb-fe0f-200d-2640.svg +1f3cb-fe0f-200d-2642.svg +1f3cc-1f3fb-200d-2640.svg +1f3cc-1f3fb-200d-2642.svg +1f3cc-1f3fc-200d-2640.svg +1f3cc-1f3fc-200d-2642.svg +1f3cc-1f3fd-200d-2640.svg +1f3cc-1f3fd-200d-2642.svg +1f3cc-1f3fe-200d-2640.svg +1f3cc-1f3fe-200d-2642.svg +1f3cc-1f3ff-200d-2640.svg +1f3cc-1f3ff-200d-2642.svg +1f3cc-200d-2640-fe0f.svg +1f3cc-200d-2640.svg +1f3cc-200d-2642-fe0f.svg +1f3cc-200d-2642.svg +1f3cc-fe0f-200d-2640.svg +1f3cc-fe0f-200d-2642.svg +1f3f3-200d-1f308.svg +1f3f3-200d-26a7-fe0f.svg +1f3f3-200d-26a7.svg +1f3f3-fe0f-200d-26a7.svg +1f3f4-200d-2620.svg +1f43b-200d-2744.svg +1f441-200d-1f5e8-fe0f.svg +1f441-fe0f-200d-1f5e8.svg +1f468-1f3fb-200d-1f9af-200d-27a1.svg +1f468-1f3fb-200d-1f9bc-200d-27a1.svg +1f468-1f3fb-200d-1f9bd-200d-27a1.svg +1f468-1f3fb-200d-2695.svg +1f468-1f3fb-200d-2696.svg +1f468-1f3fb-200d-2708.svg +1f468-1f3fb-200d-2764-200d-1f468-1f3fb.svg +1f468-1f3fb-200d-2764-200d-1f468-1f3fc.svg +1f468-1f3fb-200d-2764-200d-1f468-1f3fd.svg +1f468-1f3fb-200d-2764-200d-1f468-1f3fe.svg +1f468-1f3fb-200d-2764-200d-1f468-1f3ff.svg +1f468-1f3fb-200d-2764-200d-1f48b-200d-1f468-1f3fb.svg +1f468-1f3fb-200d-2764-200d-1f48b-200d-1f468-1f3fc.svg +1f468-1f3fb-200d-2764-200d-1f48b-200d-1f468-1f3fd.svg +1f468-1f3fb-200d-2764-200d-1f48b-200d-1f468-1f3fe.svg +1f468-1f3fb-200d-2764-200d-1f48b-200d-1f468-1f3ff.svg +1f468-1f3fc-200d-1f9af-200d-27a1.svg +1f468-1f3fc-200d-1f9bc-200d-27a1.svg +1f468-1f3fc-200d-1f9bd-200d-27a1.svg +1f468-1f3fc-200d-2695.svg +1f468-1f3fc-200d-2696.svg +1f468-1f3fc-200d-2708.svg +1f468-1f3fc-200d-2764-200d-1f468-1f3fb.svg +1f468-1f3fc-200d-2764-200d-1f468-1f3fc.svg +1f468-1f3fc-200d-2764-200d-1f468-1f3fd.svg +1f468-1f3fc-200d-2764-200d-1f468-1f3fe.svg +1f468-1f3fc-200d-2764-200d-1f468-1f3ff.svg +1f468-1f3fc-200d-2764-200d-1f48b-200d-1f468-1f3fb.svg +1f468-1f3fc-200d-2764-200d-1f48b-200d-1f468-1f3fc.svg +1f468-1f3fc-200d-2764-200d-1f48b-200d-1f468-1f3fd.svg +1f468-1f3fc-200d-2764-200d-1f48b-200d-1f468-1f3fe.svg +1f468-1f3fc-200d-2764-200d-1f48b-200d-1f468-1f3ff.svg +1f468-1f3fd-200d-1f9af-200d-27a1.svg +1f468-1f3fd-200d-1f9bc-200d-27a1.svg +1f468-1f3fd-200d-1f9bd-200d-27a1.svg +1f468-1f3fd-200d-2695.svg +1f468-1f3fd-200d-2696.svg +1f468-1f3fd-200d-2708.svg +1f468-1f3fd-200d-2764-200d-1f468-1f3fb.svg +1f468-1f3fd-200d-2764-200d-1f468-1f3fc.svg +1f468-1f3fd-200d-2764-200d-1f468-1f3fd.svg +1f468-1f3fd-200d-2764-200d-1f468-1f3fe.svg +1f468-1f3fd-200d-2764-200d-1f468-1f3ff.svg +1f468-1f3fd-200d-2764-200d-1f48b-200d-1f468-1f3fb.svg +1f468-1f3fd-200d-2764-200d-1f48b-200d-1f468-1f3fc.svg +1f468-1f3fd-200d-2764-200d-1f48b-200d-1f468-1f3fd.svg +1f468-1f3fd-200d-2764-200d-1f48b-200d-1f468-1f3fe.svg +1f468-1f3fd-200d-2764-200d-1f48b-200d-1f468-1f3ff.svg +1f468-1f3fe-200d-1f9af-200d-27a1.svg +1f468-1f3fe-200d-1f9bc-200d-27a1.svg +1f468-1f3fe-200d-1f9bd-200d-27a1.svg +1f468-1f3fe-200d-2695.svg +1f468-1f3fe-200d-2696.svg +1f468-1f3fe-200d-2708.svg +1f468-1f3fe-200d-2764-200d-1f468-1f3fb.svg +1f468-1f3fe-200d-2764-200d-1f468-1f3fc.svg +1f468-1f3fe-200d-2764-200d-1f468-1f3fd.svg +1f468-1f3fe-200d-2764-200d-1f468-1f3fe.svg +1f468-1f3fe-200d-2764-200d-1f468-1f3ff.svg +1f468-1f3fe-200d-2764-200d-1f48b-200d-1f468-1f3fb.svg +1f468-1f3fe-200d-2764-200d-1f48b-200d-1f468-1f3fc.svg +1f468-1f3fe-200d-2764-200d-1f48b-200d-1f468-1f3fd.svg +1f468-1f3fe-200d-2764-200d-1f48b-200d-1f468-1f3fe.svg +1f468-1f3fe-200d-2764-200d-1f48b-200d-1f468-1f3ff.svg +1f468-1f3ff-200d-1f9af-200d-27a1.svg +1f468-1f3ff-200d-1f9bc-200d-27a1.svg +1f468-1f3ff-200d-1f9bd-200d-27a1.svg +1f468-1f3ff-200d-2695.svg +1f468-1f3ff-200d-2696.svg +1f468-1f3ff-200d-2708.svg +1f468-1f3ff-200d-2764-200d-1f468-1f3fb.svg +1f468-1f3ff-200d-2764-200d-1f468-1f3fc.svg +1f468-1f3ff-200d-2764-200d-1f468-1f3fd.svg +1f468-1f3ff-200d-2764-200d-1f468-1f3fe.svg +1f468-1f3ff-200d-2764-200d-1f468-1f3ff.svg +1f468-1f3ff-200d-2764-200d-1f48b-200d-1f468-1f3fb.svg +1f468-1f3ff-200d-2764-200d-1f48b-200d-1f468-1f3fc.svg +1f468-1f3ff-200d-2764-200d-1f48b-200d-1f468-1f3fd.svg +1f468-1f3ff-200d-2764-200d-1f48b-200d-1f468-1f3fe.svg +1f468-1f3ff-200d-2764-200d-1f48b-200d-1f468-1f3ff.svg +1f468-200d-1f9af-200d-27a1.svg +1f468-200d-1f9bc-200d-27a1.svg +1f468-200d-1f9bd-200d-27a1.svg +1f468-200d-2695.svg +1f468-200d-2696.svg +1f468-200d-2708.svg +1f468-200d-2764-200d-1f468.svg +1f468-200d-2764-200d-1f48b-200d-1f468.svg +1f469-1f3fb-200d-1f9af-200d-27a1.svg +1f469-1f3fb-200d-1f9bc-200d-27a1.svg +1f469-1f3fb-200d-1f9bd-200d-27a1.svg +1f469-1f3fb-200d-2695.svg +1f469-1f3fb-200d-2696.svg +1f469-1f3fb-200d-2708.svg +1f469-1f3fb-200d-2764-200d-1f468-1f3fb.svg +1f469-1f3fb-200d-2764-200d-1f468-1f3fc.svg +1f469-1f3fb-200d-2764-200d-1f468-1f3fd.svg +1f469-1f3fb-200d-2764-200d-1f468-1f3fe.svg +1f469-1f3fb-200d-2764-200d-1f468-1f3ff.svg +1f469-1f3fb-200d-2764-200d-1f469-1f3fb.svg +1f469-1f3fb-200d-2764-200d-1f469-1f3fc.svg +1f469-1f3fb-200d-2764-200d-1f469-1f3fd.svg +1f469-1f3fb-200d-2764-200d-1f469-1f3fe.svg +1f469-1f3fb-200d-2764-200d-1f469-1f3ff.svg +1f469-1f3fb-200d-2764-200d-1f48b-200d-1f468-1f3fb.svg +1f469-1f3fb-200d-2764-200d-1f48b-200d-1f468-1f3fc.svg +1f469-1f3fb-200d-2764-200d-1f48b-200d-1f468-1f3fd.svg +1f469-1f3fb-200d-2764-200d-1f48b-200d-1f468-1f3fe.svg +1f469-1f3fb-200d-2764-200d-1f48b-200d-1f468-1f3ff.svg +1f469-1f3fb-200d-2764-200d-1f48b-200d-1f469-1f3fb.svg +1f469-1f3fb-200d-2764-200d-1f48b-200d-1f469-1f3fc.svg +1f469-1f3fb-200d-2764-200d-1f48b-200d-1f469-1f3fd.svg +1f469-1f3fb-200d-2764-200d-1f48b-200d-1f469-1f3fe.svg +1f469-1f3fb-200d-2764-200d-1f48b-200d-1f469-1f3ff.svg +1f469-1f3fc-200d-1f9af-200d-27a1.svg +1f469-1f3fc-200d-1f9bc-200d-27a1.svg +1f469-1f3fc-200d-1f9bd-200d-27a1.svg +1f469-1f3fc-200d-2695.svg +1f469-1f3fc-200d-2696.svg +1f469-1f3fc-200d-2708.svg +1f469-1f3fc-200d-2764-200d-1f468-1f3fb.svg +1f469-1f3fc-200d-2764-200d-1f468-1f3fc.svg +1f469-1f3fc-200d-2764-200d-1f468-1f3fd.svg +1f469-1f3fc-200d-2764-200d-1f468-1f3fe.svg +1f469-1f3fc-200d-2764-200d-1f468-1f3ff.svg +1f469-1f3fc-200d-2764-200d-1f469-1f3fb.svg +1f469-1f3fc-200d-2764-200d-1f469-1f3fc.svg +1f469-1f3fc-200d-2764-200d-1f469-1f3fd.svg +1f469-1f3fc-200d-2764-200d-1f469-1f3fe.svg +1f469-1f3fc-200d-2764-200d-1f469-1f3ff.svg +1f469-1f3fc-200d-2764-200d-1f48b-200d-1f468-1f3fb.svg +1f469-1f3fc-200d-2764-200d-1f48b-200d-1f468-1f3fc.svg +1f469-1f3fc-200d-2764-200d-1f48b-200d-1f468-1f3fd.svg +1f469-1f3fc-200d-2764-200d-1f48b-200d-1f468-1f3fe.svg +1f469-1f3fc-200d-2764-200d-1f48b-200d-1f468-1f3ff.svg +1f469-1f3fc-200d-2764-200d-1f48b-200d-1f469-1f3fb.svg +1f469-1f3fc-200d-2764-200d-1f48b-200d-1f469-1f3fc.svg +1f469-1f3fc-200d-2764-200d-1f48b-200d-1f469-1f3fd.svg +1f469-1f3fc-200d-2764-200d-1f48b-200d-1f469-1f3fe.svg +1f469-1f3fc-200d-2764-200d-1f48b-200d-1f469-1f3ff.svg +1f469-1f3fd-200d-1f9af-200d-27a1.svg +1f469-1f3fd-200d-1f9bc-200d-27a1.svg +1f469-1f3fd-200d-1f9bd-200d-27a1.svg +1f469-1f3fd-200d-2695.svg +1f469-1f3fd-200d-2696.svg +1f469-1f3fd-200d-2708.svg +1f469-1f3fd-200d-2764-200d-1f468-1f3fb.svg +1f469-1f3fd-200d-2764-200d-1f468-1f3fc.svg +1f469-1f3fd-200d-2764-200d-1f468-1f3fd.svg +1f469-1f3fd-200d-2764-200d-1f468-1f3fe.svg +1f469-1f3fd-200d-2764-200d-1f468-1f3ff.svg +1f469-1f3fd-200d-2764-200d-1f469-1f3fb.svg +1f469-1f3fd-200d-2764-200d-1f469-1f3fc.svg +1f469-1f3fd-200d-2764-200d-1f469-1f3fd.svg +1f469-1f3fd-200d-2764-200d-1f469-1f3fe.svg +1f469-1f3fd-200d-2764-200d-1f469-1f3ff.svg +1f469-1f3fd-200d-2764-200d-1f48b-200d-1f468-1f3fb.svg +1f469-1f3fd-200d-2764-200d-1f48b-200d-1f468-1f3fc.svg +1f469-1f3fd-200d-2764-200d-1f48b-200d-1f468-1f3fd.svg +1f469-1f3fd-200d-2764-200d-1f48b-200d-1f468-1f3fe.svg +1f469-1f3fd-200d-2764-200d-1f48b-200d-1f468-1f3ff.svg +1f469-1f3fd-200d-2764-200d-1f48b-200d-1f469-1f3fb.svg +1f469-1f3fd-200d-2764-200d-1f48b-200d-1f469-1f3fc.svg +1f469-1f3fd-200d-2764-200d-1f48b-200d-1f469-1f3fd.svg +1f469-1f3fd-200d-2764-200d-1f48b-200d-1f469-1f3fe.svg +1f469-1f3fd-200d-2764-200d-1f48b-200d-1f469-1f3ff.svg +1f469-1f3fe-200d-1f9af-200d-27a1.svg +1f469-1f3fe-200d-1f9bc-200d-27a1.svg +1f469-1f3fe-200d-1f9bd-200d-27a1.svg +1f469-1f3fe-200d-2695.svg +1f469-1f3fe-200d-2696.svg +1f469-1f3fe-200d-2708.svg +1f469-1f3fe-200d-2764-200d-1f468-1f3fb.svg +1f469-1f3fe-200d-2764-200d-1f468-1f3fc.svg +1f469-1f3fe-200d-2764-200d-1f468-1f3fd.svg +1f469-1f3fe-200d-2764-200d-1f468-1f3fe.svg +1f469-1f3fe-200d-2764-200d-1f468-1f3ff.svg +1f469-1f3fe-200d-2764-200d-1f469-1f3fb.svg +1f469-1f3fe-200d-2764-200d-1f469-1f3fc.svg +1f469-1f3fe-200d-2764-200d-1f469-1f3fd.svg +1f469-1f3fe-200d-2764-200d-1f469-1f3fe.svg +1f469-1f3fe-200d-2764-200d-1f469-1f3ff.svg +1f469-1f3fe-200d-2764-200d-1f48b-200d-1f468-1f3fb.svg +1f469-1f3fe-200d-2764-200d-1f48b-200d-1f468-1f3fc.svg +1f469-1f3fe-200d-2764-200d-1f48b-200d-1f468-1f3fd.svg +1f469-1f3fe-200d-2764-200d-1f48b-200d-1f468-1f3fe.svg +1f469-1f3fe-200d-2764-200d-1f48b-200d-1f468-1f3ff.svg +1f469-1f3fe-200d-2764-200d-1f48b-200d-1f469-1f3fb.svg +1f469-1f3fe-200d-2764-200d-1f48b-200d-1f469-1f3fc.svg +1f469-1f3fe-200d-2764-200d-1f48b-200d-1f469-1f3fd.svg +1f469-1f3fe-200d-2764-200d-1f48b-200d-1f469-1f3fe.svg +1f469-1f3fe-200d-2764-200d-1f48b-200d-1f469-1f3ff.svg +1f469-1f3ff-200d-1f9af-200d-27a1.svg +1f469-1f3ff-200d-1f9bc-200d-27a1.svg +1f469-1f3ff-200d-1f9bd-200d-27a1.svg +1f469-1f3ff-200d-2695.svg +1f469-1f3ff-200d-2696.svg +1f469-1f3ff-200d-2708.svg +1f469-1f3ff-200d-2764-200d-1f468-1f3fb.svg +1f469-1f3ff-200d-2764-200d-1f468-1f3fc.svg +1f469-1f3ff-200d-2764-200d-1f468-1f3fd.svg +1f469-1f3ff-200d-2764-200d-1f468-1f3fe.svg +1f469-1f3ff-200d-2764-200d-1f468-1f3ff.svg +1f469-1f3ff-200d-2764-200d-1f469-1f3fb.svg +1f469-1f3ff-200d-2764-200d-1f469-1f3fc.svg +1f469-1f3ff-200d-2764-200d-1f469-1f3fd.svg +1f469-1f3ff-200d-2764-200d-1f469-1f3fe.svg +1f469-1f3ff-200d-2764-200d-1f469-1f3ff.svg +1f469-1f3ff-200d-2764-200d-1f48b-200d-1f468-1f3fb.svg +1f469-1f3ff-200d-2764-200d-1f48b-200d-1f468-1f3fc.svg +1f469-1f3ff-200d-2764-200d-1f48b-200d-1f468-1f3fd.svg +1f469-1f3ff-200d-2764-200d-1f48b-200d-1f468-1f3fe.svg +1f469-1f3ff-200d-2764-200d-1f48b-200d-1f468-1f3ff.svg +1f469-1f3ff-200d-2764-200d-1f48b-200d-1f469-1f3fb.svg +1f469-1f3ff-200d-2764-200d-1f48b-200d-1f469-1f3fc.svg +1f469-1f3ff-200d-2764-200d-1f48b-200d-1f469-1f3fd.svg +1f469-1f3ff-200d-2764-200d-1f48b-200d-1f469-1f3fe.svg +1f469-1f3ff-200d-2764-200d-1f48b-200d-1f469-1f3ff.svg +1f469-200d-1f9af-200d-27a1.svg +1f469-200d-1f9bc-200d-27a1.svg +1f469-200d-1f9bd-200d-27a1.svg +1f469-200d-2695.svg +1f469-200d-2696.svg +1f469-200d-2708.svg +1f469-200d-2764-200d-1f468.svg +1f469-200d-2764-200d-1f469.svg +1f469-200d-2764-200d-1f48b-200d-1f468.svg +1f469-200d-2764-200d-1f48b-200d-1f469.svg +1f46e-1f3fb-200d-2640.svg +1f46e-1f3fb-200d-2642.svg +1f46e-1f3fc-200d-2640.svg +1f46e-1f3fc-200d-2642.svg +1f46e-1f3fd-200d-2640.svg +1f46e-1f3fd-200d-2642.svg +1f46e-1f3fe-200d-2640.svg +1f46e-1f3fe-200d-2642.svg +1f46e-1f3ff-200d-2640.svg +1f46e-1f3ff-200d-2642.svg +1f46e-200d-2640.svg +1f46e-200d-2642.svg +1f46f-1f3fb-200d-2640.svg +1f46f-1f3fb-200d-2642.svg +1f46f-1f3fc-200d-2640.svg +1f46f-1f3fc-200d-2642.svg +1f46f-1f3fd-200d-2640.svg +1f46f-1f3fd-200d-2642.svg +1f46f-1f3fe-200d-2640.svg +1f46f-1f3fe-200d-2642.svg +1f46f-1f3ff-200d-2640.svg +1f46f-1f3ff-200d-2642.svg +1f46f-200d-2640.svg +1f46f-200d-2642.svg +1f470-1f3fb-200d-2640.svg +1f470-1f3fb-200d-2642.svg +1f470-1f3fc-200d-2640.svg +1f470-1f3fc-200d-2642.svg +1f470-1f3fd-200d-2640.svg +1f470-1f3fd-200d-2642.svg +1f470-1f3fe-200d-2640.svg +1f470-1f3fe-200d-2642.svg +1f470-1f3ff-200d-2640.svg +1f470-1f3ff-200d-2642.svg +1f470-200d-2640.svg +1f470-200d-2642.svg +1f471-1f3fb-200d-2640.svg +1f471-1f3fb-200d-2642.svg +1f471-1f3fc-200d-2640.svg +1f471-1f3fc-200d-2642.svg +1f471-1f3fd-200d-2640.svg +1f471-1f3fd-200d-2642.svg +1f471-1f3fe-200d-2640.svg +1f471-1f3fe-200d-2642.svg +1f471-1f3ff-200d-2640.svg +1f471-1f3ff-200d-2642.svg +1f471-200d-2640.svg +1f471-200d-2642.svg +1f473-1f3fb-200d-2640.svg +1f473-1f3fb-200d-2642.svg +1f473-1f3fc-200d-2640.svg +1f473-1f3fc-200d-2642.svg +1f473-1f3fd-200d-2640.svg +1f473-1f3fd-200d-2642.svg +1f473-1f3fe-200d-2640.svg +1f473-1f3fe-200d-2642.svg +1f473-1f3ff-200d-2640.svg +1f473-1f3ff-200d-2642.svg +1f473-200d-2640.svg +1f473-200d-2642.svg +1f477-1f3fb-200d-2640.svg +1f477-1f3fb-200d-2642.svg +1f477-1f3fc-200d-2640.svg +1f477-1f3fc-200d-2642.svg +1f477-1f3fd-200d-2640.svg +1f477-1f3fd-200d-2642.svg +1f477-1f3fe-200d-2640.svg +1f477-1f3fe-200d-2642.svg +1f477-1f3ff-200d-2640.svg +1f477-1f3ff-200d-2642.svg +1f477-200d-2640.svg +1f477-200d-2642.svg +1f481-1f3fb-200d-2640.svg +1f481-1f3fb-200d-2642.svg +1f481-1f3fc-200d-2640.svg +1f481-1f3fc-200d-2642.svg +1f481-1f3fd-200d-2640.svg +1f481-1f3fd-200d-2642.svg +1f481-1f3fe-200d-2640.svg +1f481-1f3fe-200d-2642.svg +1f481-1f3ff-200d-2640.svg +1f481-1f3ff-200d-2642.svg +1f481-200d-2640.svg +1f481-200d-2642.svg +1f482-1f3fb-200d-2640.svg +1f482-1f3fb-200d-2642.svg +1f482-1f3fc-200d-2640.svg +1f482-1f3fc-200d-2642.svg +1f482-1f3fd-200d-2640.svg +1f482-1f3fd-200d-2642.svg +1f482-1f3fe-200d-2640.svg +1f482-1f3fe-200d-2642.svg +1f482-1f3ff-200d-2640.svg +1f482-1f3ff-200d-2642.svg +1f482-200d-2640.svg +1f482-200d-2642.svg +1f486-1f3fb-200d-2640.svg +1f486-1f3fb-200d-2642.svg +1f486-1f3fc-200d-2640.svg +1f486-1f3fc-200d-2642.svg +1f486-1f3fd-200d-2640.svg +1f486-1f3fd-200d-2642.svg +1f486-1f3fe-200d-2640.svg +1f486-1f3fe-200d-2642.svg +1f486-1f3ff-200d-2640.svg +1f486-1f3ff-200d-2642.svg +1f486-200d-2640.svg +1f486-200d-2642.svg +1f487-1f3fb-200d-2640.svg +1f487-1f3fb-200d-2642.svg +1f487-1f3fc-200d-2640.svg +1f487-1f3fc-200d-2642.svg +1f487-1f3fd-200d-2640.svg +1f487-1f3fd-200d-2642.svg +1f487-1f3fe-200d-2640.svg +1f487-1f3fe-200d-2642.svg +1f487-1f3ff-200d-2640.svg +1f487-1f3ff-200d-2642.svg +1f487-200d-2640.svg +1f487-200d-2642.svg +1f575-1f3fb-200d-2640.svg +1f575-1f3fb-200d-2642.svg +1f575-1f3fc-200d-2640.svg +1f575-1f3fc-200d-2642.svg +1f575-1f3fd-200d-2640.svg +1f575-1f3fd-200d-2642.svg +1f575-1f3fe-200d-2640.svg +1f575-1f3fe-200d-2642.svg +1f575-1f3ff-200d-2640.svg +1f575-1f3ff-200d-2642.svg +1f575-200d-2640-fe0f.svg +1f575-200d-2640.svg +1f575-200d-2642-fe0f.svg +1f575-200d-2642.svg +1f575-fe0f-200d-2640.svg +1f575-fe0f-200d-2642.svg +1f636-200d-1f32b.svg +1f642-200d-2194.svg +1f642-200d-2195.svg +1f645-1f3fb-200d-2640.svg +1f645-1f3fb-200d-2642.svg +1f645-1f3fc-200d-2640.svg +1f645-1f3fc-200d-2642.svg +1f645-1f3fd-200d-2640.svg +1f645-1f3fd-200d-2642.svg +1f645-1f3fe-200d-2640.svg +1f645-1f3fe-200d-2642.svg +1f645-1f3ff-200d-2640.svg +1f645-1f3ff-200d-2642.svg +1f645-200d-2640.svg +1f645-200d-2642.svg +1f646-1f3fb-200d-2640.svg +1f646-1f3fb-200d-2642.svg +1f646-1f3fc-200d-2640.svg +1f646-1f3fc-200d-2642.svg +1f646-1f3fd-200d-2640.svg +1f646-1f3fd-200d-2642.svg +1f646-1f3fe-200d-2640.svg +1f646-1f3fe-200d-2642.svg +1f646-1f3ff-200d-2640.svg +1f646-1f3ff-200d-2642.svg +1f646-200d-2640.svg +1f646-200d-2642.svg +1f647-1f3fb-200d-2640.svg +1f647-1f3fb-200d-2642.svg +1f647-1f3fc-200d-2640.svg +1f647-1f3fc-200d-2642.svg +1f647-1f3fd-200d-2640.svg +1f647-1f3fd-200d-2642.svg +1f647-1f3fe-200d-2640.svg +1f647-1f3fe-200d-2642.svg +1f647-1f3ff-200d-2640.svg +1f647-1f3ff-200d-2642.svg +1f647-200d-2640.svg +1f647-200d-2642.svg +1f64b-1f3fb-200d-2640.svg +1f64b-1f3fb-200d-2642.svg +1f64b-1f3fc-200d-2640.svg +1f64b-1f3fc-200d-2642.svg +1f64b-1f3fd-200d-2640.svg +1f64b-1f3fd-200d-2642.svg +1f64b-1f3fe-200d-2640.svg +1f64b-1f3fe-200d-2642.svg +1f64b-1f3ff-200d-2640.svg +1f64b-1f3ff-200d-2642.svg +1f64b-200d-2640.svg +1f64b-200d-2642.svg +1f64d-1f3fb-200d-2640.svg +1f64d-1f3fb-200d-2642.svg +1f64d-1f3fc-200d-2640.svg +1f64d-1f3fc-200d-2642.svg +1f64d-1f3fd-200d-2640.svg +1f64d-1f3fd-200d-2642.svg +1f64d-1f3fe-200d-2640.svg +1f64d-1f3fe-200d-2642.svg +1f64d-1f3ff-200d-2640.svg +1f64d-1f3ff-200d-2642.svg +1f64d-200d-2640.svg +1f64d-200d-2642.svg +1f64e-1f3fb-200d-2640.svg +1f64e-1f3fb-200d-2642.svg +1f64e-1f3fc-200d-2640.svg +1f64e-1f3fc-200d-2642.svg +1f64e-1f3fd-200d-2640.svg +1f64e-1f3fd-200d-2642.svg +1f64e-1f3fe-200d-2640.svg +1f64e-1f3fe-200d-2642.svg +1f64e-1f3ff-200d-2640.svg +1f64e-1f3ff-200d-2642.svg +1f64e-200d-2640.svg +1f64e-200d-2642.svg +1f6a3-1f3fb-200d-2640.svg +1f6a3-1f3fb-200d-2642.svg +1f6a3-1f3fc-200d-2640.svg +1f6a3-1f3fc-200d-2642.svg +1f6a3-1f3fd-200d-2640.svg +1f6a3-1f3fd-200d-2642.svg +1f6a3-1f3fe-200d-2640.svg +1f6a3-1f3fe-200d-2642.svg +1f6a3-1f3ff-200d-2640.svg +1f6a3-1f3ff-200d-2642.svg +1f6a3-200d-2640.svg +1f6a3-200d-2642.svg +1f6b4-1f3fb-200d-2640.svg +1f6b4-1f3fb-200d-2642.svg +1f6b4-1f3fc-200d-2640.svg +1f6b4-1f3fc-200d-2642.svg +1f6b4-1f3fd-200d-2640.svg +1f6b4-1f3fd-200d-2642.svg +1f6b4-1f3fe-200d-2640.svg +1f6b4-1f3fe-200d-2642.svg +1f6b4-1f3ff-200d-2640.svg +1f6b4-1f3ff-200d-2642.svg +1f6b4-200d-2640.svg +1f6b4-200d-2642.svg +1f6b5-1f3fb-200d-2640.svg +1f6b5-1f3fb-200d-2642.svg +1f6b5-1f3fc-200d-2640.svg +1f6b5-1f3fc-200d-2642.svg +1f6b5-1f3fd-200d-2640.svg +1f6b5-1f3fd-200d-2642.svg +1f6b5-1f3fe-200d-2640.svg +1f6b5-1f3fe-200d-2642.svg +1f6b5-1f3ff-200d-2640.svg +1f6b5-1f3ff-200d-2642.svg +1f6b5-200d-2640.svg +1f6b5-200d-2642.svg +1f6b6-1f3fb-200d-2640-200d-27a1-fe0f.svg +1f6b6-1f3fb-200d-2640-200d-27a1.svg +1f6b6-1f3fb-200d-2640-fe0f-200d-27a1.svg +1f6b6-1f3fb-200d-2640.svg +1f6b6-1f3fb-200d-2642-200d-27a1-fe0f.svg +1f6b6-1f3fb-200d-2642-200d-27a1.svg +1f6b6-1f3fb-200d-2642-fe0f-200d-27a1.svg +1f6b6-1f3fb-200d-2642.svg +1f6b6-1f3fb-200d-27a1.svg +1f6b6-1f3fc-200d-2640-200d-27a1-fe0f.svg +1f6b6-1f3fc-200d-2640-200d-27a1.svg +1f6b6-1f3fc-200d-2640-fe0f-200d-27a1.svg +1f6b6-1f3fc-200d-2640.svg +1f6b6-1f3fc-200d-2642-200d-27a1-fe0f.svg +1f6b6-1f3fc-200d-2642-200d-27a1.svg +1f6b6-1f3fc-200d-2642-fe0f-200d-27a1.svg +1f6b6-1f3fc-200d-2642.svg +1f6b6-1f3fc-200d-27a1.svg +1f6b6-1f3fd-200d-2640-200d-27a1-fe0f.svg +1f6b6-1f3fd-200d-2640-200d-27a1.svg +1f6b6-1f3fd-200d-2640-fe0f-200d-27a1.svg +1f6b6-1f3fd-200d-2640.svg +1f6b6-1f3fd-200d-2642-200d-27a1-fe0f.svg +1f6b6-1f3fd-200d-2642-200d-27a1.svg +1f6b6-1f3fd-200d-2642-fe0f-200d-27a1.svg +1f6b6-1f3fd-200d-2642.svg +1f6b6-1f3fd-200d-27a1.svg +1f6b6-1f3fe-200d-2640-200d-27a1-fe0f.svg +1f6b6-1f3fe-200d-2640-200d-27a1.svg +1f6b6-1f3fe-200d-2640-fe0f-200d-27a1.svg +1f6b6-1f3fe-200d-2640.svg +1f6b6-1f3fe-200d-2642-200d-27a1-fe0f.svg +1f6b6-1f3fe-200d-2642-200d-27a1.svg +1f6b6-1f3fe-200d-2642-fe0f-200d-27a1.svg +1f6b6-1f3fe-200d-2642.svg +1f6b6-1f3fe-200d-27a1.svg +1f6b6-1f3ff-200d-2640-200d-27a1-fe0f.svg +1f6b6-1f3ff-200d-2640-200d-27a1.svg +1f6b6-1f3ff-200d-2640-fe0f-200d-27a1.svg +1f6b6-1f3ff-200d-2640.svg +1f6b6-1f3ff-200d-2642-200d-27a1-fe0f.svg +1f6b6-1f3ff-200d-2642-200d-27a1.svg +1f6b6-1f3ff-200d-2642-fe0f-200d-27a1.svg +1f6b6-1f3ff-200d-2642.svg +1f6b6-1f3ff-200d-27a1.svg +1f6b6-200d-2640-200d-27a1-fe0f.svg +1f6b6-200d-2640-200d-27a1.svg +1f6b6-200d-2640-fe0f-200d-27a1.svg +1f6b6-200d-2640.svg +1f6b6-200d-2642-200d-27a1-fe0f.svg +1f6b6-200d-2642-200d-27a1.svg +1f6b6-200d-2642-fe0f-200d-27a1.svg +1f6b6-200d-2642.svg +1f6b6-200d-27a1.svg +1f926-1f3fb-200d-2640.svg +1f926-1f3fb-200d-2642.svg +1f926-1f3fc-200d-2640.svg +1f926-1f3fc-200d-2642.svg +1f926-1f3fd-200d-2640.svg +1f926-1f3fd-200d-2642.svg +1f926-1f3fe-200d-2640.svg +1f926-1f3fe-200d-2642.svg +1f926-1f3ff-200d-2640.svg +1f926-1f3ff-200d-2642.svg +1f926-200d-2640.svg +1f926-200d-2642.svg +1f935-1f3fb-200d-2640.svg +1f935-1f3fb-200d-2642.svg +1f935-1f3fc-200d-2640.svg +1f935-1f3fc-200d-2642.svg +1f935-1f3fd-200d-2640.svg +1f935-1f3fd-200d-2642.svg +1f935-1f3fe-200d-2640.svg +1f935-1f3fe-200d-2642.svg +1f935-1f3ff-200d-2640.svg +1f935-1f3ff-200d-2642.svg +1f935-200d-2640.svg +1f935-200d-2642.svg +1f937-1f3fb-200d-2640.svg +1f937-1f3fb-200d-2642.svg +1f937-1f3fc-200d-2640.svg +1f937-1f3fc-200d-2642.svg +1f937-1f3fd-200d-2640.svg +1f937-1f3fd-200d-2642.svg +1f937-1f3fe-200d-2640.svg +1f937-1f3fe-200d-2642.svg +1f937-1f3ff-200d-2640.svg +1f937-1f3ff-200d-2642.svg +1f937-200d-2640.svg +1f937-200d-2642.svg +1f938-1f3fb-200d-2640.svg +1f938-1f3fb-200d-2642.svg +1f938-1f3fc-200d-2640.svg +1f938-1f3fc-200d-2642.svg +1f938-1f3fd-200d-2640.svg +1f938-1f3fd-200d-2642.svg +1f938-1f3fe-200d-2640.svg +1f938-1f3fe-200d-2642.svg +1f938-1f3ff-200d-2640.svg +1f938-1f3ff-200d-2642.svg +1f938-200d-2640.svg +1f938-200d-2642.svg +1f939-1f3fb-200d-2640.svg +1f939-1f3fb-200d-2642.svg +1f939-1f3fc-200d-2640.svg +1f939-1f3fc-200d-2642.svg +1f939-1f3fd-200d-2640.svg +1f939-1f3fd-200d-2642.svg +1f939-1f3fe-200d-2640.svg +1f939-1f3fe-200d-2642.svg +1f939-1f3ff-200d-2640.svg +1f939-1f3ff-200d-2642.svg +1f939-200d-2640.svg +1f939-200d-2642.svg +1f93c-1f3fb-200d-2640.svg +1f93c-1f3fb-200d-2642.svg +1f93c-1f3fc-200d-2640.svg +1f93c-1f3fc-200d-2642.svg +1f93c-1f3fd-200d-2640.svg +1f93c-1f3fd-200d-2642.svg +1f93c-1f3fe-200d-2640.svg +1f93c-1f3fe-200d-2642.svg +1f93c-1f3ff-200d-2640.svg +1f93c-1f3ff-200d-2642.svg +1f93c-200d-2640.svg +1f93c-200d-2642.svg +1f93d-1f3fb-200d-2640.svg +1f93d-1f3fb-200d-2642.svg +1f93d-1f3fc-200d-2640.svg +1f93d-1f3fc-200d-2642.svg +1f93d-1f3fd-200d-2640.svg +1f93d-1f3fd-200d-2642.svg +1f93d-1f3fe-200d-2640.svg +1f93d-1f3fe-200d-2642.svg +1f93d-1f3ff-200d-2640.svg +1f93d-1f3ff-200d-2642.svg +1f93d-200d-2640.svg +1f93d-200d-2642.svg +1f93e-1f3fb-200d-2640.svg +1f93e-1f3fb-200d-2642.svg +1f93e-1f3fc-200d-2640.svg +1f93e-1f3fc-200d-2642.svg +1f93e-1f3fd-200d-2640.svg +1f93e-1f3fd-200d-2642.svg +1f93e-1f3fe-200d-2640.svg +1f93e-1f3fe-200d-2642.svg +1f93e-1f3ff-200d-2640.svg +1f93e-1f3ff-200d-2642.svg +1f93e-200d-2640.svg +1f93e-200d-2642.svg +1f9b8-1f3fb-200d-2640.svg +1f9b8-1f3fb-200d-2642.svg +1f9b8-1f3fc-200d-2640.svg +1f9b8-1f3fc-200d-2642.svg +1f9b8-1f3fd-200d-2640.svg +1f9b8-1f3fd-200d-2642.svg +1f9b8-1f3fe-200d-2640.svg +1f9b8-1f3fe-200d-2642.svg +1f9b8-1f3ff-200d-2640.svg +1f9b8-1f3ff-200d-2642.svg +1f9b8-200d-2640.svg +1f9b8-200d-2642.svg +1f9b9-1f3fb-200d-2640.svg +1f9b9-1f3fb-200d-2642.svg +1f9b9-1f3fc-200d-2640.svg +1f9b9-1f3fc-200d-2642.svg +1f9b9-1f3fd-200d-2640.svg +1f9b9-1f3fd-200d-2642.svg +1f9b9-1f3fe-200d-2640.svg +1f9b9-1f3fe-200d-2642.svg +1f9b9-1f3ff-200d-2640.svg +1f9b9-1f3ff-200d-2642.svg +1f9b9-200d-2640.svg +1f9b9-200d-2642.svg +1f9cd-1f3fb-200d-2640.svg +1f9cd-1f3fb-200d-2642.svg +1f9cd-1f3fc-200d-2640.svg +1f9cd-1f3fc-200d-2642.svg +1f9cd-1f3fd-200d-2640.svg +1f9cd-1f3fd-200d-2642.svg +1f9cd-1f3fe-200d-2640.svg +1f9cd-1f3fe-200d-2642.svg +1f9cd-1f3ff-200d-2640.svg +1f9cd-1f3ff-200d-2642.svg +1f9cd-200d-2640.svg +1f9cd-200d-2642.svg +1f9ce-1f3fb-200d-2640-200d-27a1-fe0f.svg +1f9ce-1f3fb-200d-2640-200d-27a1.svg +1f9ce-1f3fb-200d-2640-fe0f-200d-27a1.svg +1f9ce-1f3fb-200d-2640.svg +1f9ce-1f3fb-200d-2642-200d-27a1-fe0f.svg +1f9ce-1f3fb-200d-2642-200d-27a1.svg +1f9ce-1f3fb-200d-2642-fe0f-200d-27a1.svg +1f9ce-1f3fb-200d-2642.svg +1f9ce-1f3fb-200d-27a1.svg +1f9ce-1f3fc-200d-2640-200d-27a1-fe0f.svg +1f9ce-1f3fc-200d-2640-200d-27a1.svg +1f9ce-1f3fc-200d-2640-fe0f-200d-27a1.svg +1f9ce-1f3fc-200d-2640.svg +1f9ce-1f3fc-200d-2642-200d-27a1-fe0f.svg +1f9ce-1f3fc-200d-2642-200d-27a1.svg +1f9ce-1f3fc-200d-2642-fe0f-200d-27a1.svg +1f9ce-1f3fc-200d-2642.svg +1f9ce-1f3fc-200d-27a1.svg +1f9ce-1f3fd-200d-2640-200d-27a1-fe0f.svg +1f9ce-1f3fd-200d-2640-200d-27a1.svg +1f9ce-1f3fd-200d-2640-fe0f-200d-27a1.svg +1f9ce-1f3fd-200d-2640.svg +1f9ce-1f3fd-200d-2642-200d-27a1-fe0f.svg +1f9ce-1f3fd-200d-2642-200d-27a1.svg +1f9ce-1f3fd-200d-2642-fe0f-200d-27a1.svg +1f9ce-1f3fd-200d-2642.svg +1f9ce-1f3fd-200d-27a1.svg +1f9ce-1f3fe-200d-2640-200d-27a1-fe0f.svg +1f9ce-1f3fe-200d-2640-200d-27a1.svg +1f9ce-1f3fe-200d-2640-fe0f-200d-27a1.svg +1f9ce-1f3fe-200d-2640.svg +1f9ce-1f3fe-200d-2642-200d-27a1-fe0f.svg +1f9ce-1f3fe-200d-2642-200d-27a1.svg +1f9ce-1f3fe-200d-2642-fe0f-200d-27a1.svg +1f9ce-1f3fe-200d-2642.svg +1f9ce-1f3fe-200d-27a1.svg +1f9ce-1f3ff-200d-2640-200d-27a1-fe0f.svg +1f9ce-1f3ff-200d-2640-200d-27a1.svg +1f9ce-1f3ff-200d-2640-fe0f-200d-27a1.svg +1f9ce-1f3ff-200d-2640.svg +1f9ce-1f3ff-200d-2642-200d-27a1-fe0f.svg +1f9ce-1f3ff-200d-2642-200d-27a1.svg +1f9ce-1f3ff-200d-2642-fe0f-200d-27a1.svg +1f9ce-1f3ff-200d-2642.svg +1f9ce-1f3ff-200d-27a1.svg +1f9ce-200d-2640-200d-27a1-fe0f.svg +1f9ce-200d-2640-200d-27a1.svg +1f9ce-200d-2640-fe0f-200d-27a1.svg +1f9ce-200d-2640.svg +1f9ce-200d-2642-200d-27a1-fe0f.svg +1f9ce-200d-2642-200d-27a1.svg +1f9ce-200d-2642-fe0f-200d-27a1.svg +1f9ce-200d-2642.svg +1f9ce-200d-27a1.svg +1f9cf-1f3fb-200d-2640.svg +1f9cf-1f3fb-200d-2642.svg +1f9cf-1f3fc-200d-2640.svg +1f9cf-1f3fc-200d-2642.svg +1f9cf-1f3fd-200d-2640.svg +1f9cf-1f3fd-200d-2642.svg +1f9cf-1f3fe-200d-2640.svg +1f9cf-1f3fe-200d-2642.svg +1f9cf-1f3ff-200d-2640.svg +1f9cf-1f3ff-200d-2642.svg +1f9cf-200d-2640.svg +1f9cf-200d-2642.svg +1f9d1-1f3fb-200d-1f9af-200d-27a1.svg +1f9d1-1f3fb-200d-1f9bc-200d-27a1.svg +1f9d1-1f3fb-200d-1f9bd-200d-27a1.svg +1f9d1-1f3fb-200d-2695.svg +1f9d1-1f3fb-200d-2696.svg +1f9d1-1f3fb-200d-2708.svg +1f9d1-1f3fb-200d-2764-200d-1f48b-200d-1f9d1-1f3fc.svg +1f9d1-1f3fb-200d-2764-200d-1f48b-200d-1f9d1-1f3fd.svg +1f9d1-1f3fb-200d-2764-200d-1f48b-200d-1f9d1-1f3fe.svg +1f9d1-1f3fb-200d-2764-200d-1f48b-200d-1f9d1-1f3ff.svg +1f9d1-1f3fb-200d-2764-200d-1f9d1-1f3fc.svg +1f9d1-1f3fb-200d-2764-200d-1f9d1-1f3fd.svg +1f9d1-1f3fb-200d-2764-200d-1f9d1-1f3fe.svg +1f9d1-1f3fb-200d-2764-200d-1f9d1-1f3ff.svg +1f9d1-1f3fc-200d-1f9af-200d-27a1.svg +1f9d1-1f3fc-200d-1f9bc-200d-27a1.svg +1f9d1-1f3fc-200d-1f9bd-200d-27a1.svg +1f9d1-1f3fc-200d-2695.svg +1f9d1-1f3fc-200d-2696.svg +1f9d1-1f3fc-200d-2708.svg +1f9d1-1f3fc-200d-2764-200d-1f48b-200d-1f9d1-1f3fb.svg +1f9d1-1f3fc-200d-2764-200d-1f48b-200d-1f9d1-1f3fd.svg +1f9d1-1f3fc-200d-2764-200d-1f48b-200d-1f9d1-1f3fe.svg +1f9d1-1f3fc-200d-2764-200d-1f48b-200d-1f9d1-1f3ff.svg +1f9d1-1f3fc-200d-2764-200d-1f9d1-1f3fb.svg +1f9d1-1f3fc-200d-2764-200d-1f9d1-1f3fd.svg +1f9d1-1f3fc-200d-2764-200d-1f9d1-1f3fe.svg +1f9d1-1f3fc-200d-2764-200d-1f9d1-1f3ff.svg +1f9d1-1f3fd-200d-1f9af-200d-27a1.svg +1f9d1-1f3fd-200d-1f9bc-200d-27a1.svg +1f9d1-1f3fd-200d-1f9bd-200d-27a1.svg +1f9d1-1f3fd-200d-2695.svg +1f9d1-1f3fd-200d-2696.svg +1f9d1-1f3fd-200d-2708.svg +1f9d1-1f3fd-200d-2764-200d-1f48b-200d-1f9d1-1f3fb.svg +1f9d1-1f3fd-200d-2764-200d-1f48b-200d-1f9d1-1f3fc.svg +1f9d1-1f3fd-200d-2764-200d-1f48b-200d-1f9d1-1f3fe.svg +1f9d1-1f3fd-200d-2764-200d-1f48b-200d-1f9d1-1f3ff.svg +1f9d1-1f3fd-200d-2764-200d-1f9d1-1f3fb.svg +1f9d1-1f3fd-200d-2764-200d-1f9d1-1f3fc.svg +1f9d1-1f3fd-200d-2764-200d-1f9d1-1f3fe.svg +1f9d1-1f3fd-200d-2764-200d-1f9d1-1f3ff.svg +1f9d1-1f3fe-200d-1f9af-200d-27a1.svg +1f9d1-1f3fe-200d-1f9bc-200d-27a1.svg +1f9d1-1f3fe-200d-1f9bd-200d-27a1.svg +1f9d1-1f3fe-200d-2695.svg +1f9d1-1f3fe-200d-2696.svg +1f9d1-1f3fe-200d-2708.svg +1f9d1-1f3fe-200d-2764-200d-1f48b-200d-1f9d1-1f3fb.svg +1f9d1-1f3fe-200d-2764-200d-1f48b-200d-1f9d1-1f3fc.svg +1f9d1-1f3fe-200d-2764-200d-1f48b-200d-1f9d1-1f3fd.svg +1f9d1-1f3fe-200d-2764-200d-1f48b-200d-1f9d1-1f3ff.svg +1f9d1-1f3fe-200d-2764-200d-1f9d1-1f3fb.svg +1f9d1-1f3fe-200d-2764-200d-1f9d1-1f3fc.svg +1f9d1-1f3fe-200d-2764-200d-1f9d1-1f3fd.svg +1f9d1-1f3fe-200d-2764-200d-1f9d1-1f3ff.svg +1f9d1-1f3ff-200d-1f9af-200d-27a1.svg +1f9d1-1f3ff-200d-1f9bc-200d-27a1.svg +1f9d1-1f3ff-200d-1f9bd-200d-27a1.svg +1f9d1-1f3ff-200d-2695.svg +1f9d1-1f3ff-200d-2696.svg +1f9d1-1f3ff-200d-2708.svg +1f9d1-1f3ff-200d-2764-200d-1f48b-200d-1f9d1-1f3fb.svg +1f9d1-1f3ff-200d-2764-200d-1f48b-200d-1f9d1-1f3fc.svg +1f9d1-1f3ff-200d-2764-200d-1f48b-200d-1f9d1-1f3fd.svg +1f9d1-1f3ff-200d-2764-200d-1f48b-200d-1f9d1-1f3fe.svg +1f9d1-1f3ff-200d-2764-200d-1f9d1-1f3fb.svg +1f9d1-1f3ff-200d-2764-200d-1f9d1-1f3fc.svg +1f9d1-1f3ff-200d-2764-200d-1f9d1-1f3fd.svg +1f9d1-1f3ff-200d-2764-200d-1f9d1-1f3fe.svg +1f9d1-200d-1f9af-200d-27a1.svg +1f9d1-200d-1f9bc-200d-27a1.svg +1f9d1-200d-1f9bd-200d-27a1.svg +1f9d1-200d-2695.svg +1f9d1-200d-2696.svg +1f9d1-200d-2708.svg +1f9d4-1f3fb-200d-2640.svg +1f9d4-1f3fb-200d-2642.svg +1f9d4-1f3fc-200d-2640.svg +1f9d4-1f3fc-200d-2642.svg +1f9d4-1f3fd-200d-2640.svg +1f9d4-1f3fd-200d-2642.svg +1f9d4-1f3fe-200d-2640.svg +1f9d4-1f3fe-200d-2642.svg +1f9d4-1f3ff-200d-2640.svg +1f9d4-1f3ff-200d-2642.svg +1f9d4-200d-2640.svg +1f9d4-200d-2642.svg +1f9d6-1f3fb-200d-2640.svg +1f9d6-1f3fb-200d-2642.svg +1f9d6-1f3fc-200d-2640.svg +1f9d6-1f3fc-200d-2642.svg +1f9d6-1f3fd-200d-2640.svg +1f9d6-1f3fd-200d-2642.svg +1f9d6-1f3fe-200d-2640.svg +1f9d6-1f3fe-200d-2642.svg +1f9d6-1f3ff-200d-2640.svg +1f9d6-1f3ff-200d-2642.svg +1f9d6-200d-2640.svg +1f9d6-200d-2642.svg +1f9d7-1f3fb-200d-2640.svg +1f9d7-1f3fb-200d-2642.svg +1f9d7-1f3fc-200d-2640.svg +1f9d7-1f3fc-200d-2642.svg +1f9d7-1f3fd-200d-2640.svg +1f9d7-1f3fd-200d-2642.svg +1f9d7-1f3fe-200d-2640.svg +1f9d7-1f3fe-200d-2642.svg +1f9d7-1f3ff-200d-2640.svg +1f9d7-1f3ff-200d-2642.svg +1f9d7-200d-2640.svg +1f9d7-200d-2642.svg +1f9d8-1f3fb-200d-2640.svg +1f9d8-1f3fb-200d-2642.svg +1f9d8-1f3fc-200d-2640.svg +1f9d8-1f3fc-200d-2642.svg +1f9d8-1f3fd-200d-2640.svg +1f9d8-1f3fd-200d-2642.svg +1f9d8-1f3fe-200d-2640.svg +1f9d8-1f3fe-200d-2642.svg +1f9d8-1f3ff-200d-2640.svg +1f9d8-1f3ff-200d-2642.svg +1f9d8-200d-2640.svg +1f9d8-200d-2642.svg +1f9d9-1f3fb-200d-2640.svg +1f9d9-1f3fb-200d-2642.svg +1f9d9-1f3fc-200d-2640.svg +1f9d9-1f3fc-200d-2642.svg +1f9d9-1f3fd-200d-2640.svg +1f9d9-1f3fd-200d-2642.svg +1f9d9-1f3fe-200d-2640.svg +1f9d9-1f3fe-200d-2642.svg +1f9d9-1f3ff-200d-2640.svg +1f9d9-1f3ff-200d-2642.svg +1f9d9-200d-2640.svg +1f9d9-200d-2642.svg +1f9da-1f3fb-200d-2640.svg +1f9da-1f3fb-200d-2642.svg +1f9da-1f3fc-200d-2640.svg +1f9da-1f3fc-200d-2642.svg +1f9da-1f3fd-200d-2640.svg +1f9da-1f3fd-200d-2642.svg +1f9da-1f3fe-200d-2640.svg +1f9da-1f3fe-200d-2642.svg +1f9da-1f3ff-200d-2640.svg +1f9da-1f3ff-200d-2642.svg +1f9da-200d-2640.svg +1f9da-200d-2642.svg +1f9db-1f3fb-200d-2640.svg +1f9db-1f3fb-200d-2642.svg +1f9db-1f3fc-200d-2640.svg +1f9db-1f3fc-200d-2642.svg +1f9db-1f3fd-200d-2640.svg +1f9db-1f3fd-200d-2642.svg +1f9db-1f3fe-200d-2640.svg +1f9db-1f3fe-200d-2642.svg +1f9db-1f3ff-200d-2640.svg +1f9db-1f3ff-200d-2642.svg +1f9db-200d-2640.svg +1f9db-200d-2642.svg +1f9dc-1f3fb-200d-2640.svg +1f9dc-1f3fb-200d-2642.svg +1f9dc-1f3fc-200d-2640.svg +1f9dc-1f3fc-200d-2642.svg +1f9dc-1f3fd-200d-2640.svg +1f9dc-1f3fd-200d-2642.svg +1f9dc-1f3fe-200d-2640.svg +1f9dc-1f3fe-200d-2642.svg +1f9dc-1f3ff-200d-2640.svg +1f9dc-1f3ff-200d-2642.svg +1f9dc-200d-2640.svg +1f9dc-200d-2642.svg +1f9dd-1f3fb-200d-2640.svg +1f9dd-1f3fb-200d-2642.svg +1f9dd-1f3fc-200d-2640.svg +1f9dd-1f3fc-200d-2642.svg +1f9dd-1f3fd-200d-2640.svg +1f9dd-1f3fd-200d-2642.svg +1f9dd-1f3fe-200d-2640.svg +1f9dd-1f3fe-200d-2642.svg +1f9dd-1f3ff-200d-2640.svg +1f9dd-1f3ff-200d-2642.svg +1f9dd-200d-2640.svg +1f9dd-200d-2642.svg +1f9de-200d-2640.svg +1f9de-200d-2642.svg +1f9df-200d-2640.svg +1f9df-200d-2642.svg +26d3-200d-1f4a5.svg +26f9-1f3fb-200d-2640.svg +26f9-1f3fb-200d-2642.svg +26f9-1f3fc-200d-2640.svg +26f9-1f3fc-200d-2642.svg +26f9-1f3fd-200d-2640.svg +26f9-1f3fd-200d-2642.svg +26f9-1f3fe-200d-2640.svg +26f9-1f3fe-200d-2642.svg +26f9-1f3ff-200d-2640.svg +26f9-1f3ff-200d-2642.svg +26f9-200d-2640-fe0f.svg +26f9-200d-2640.svg +26f9-200d-2642-fe0f.svg +26f9-200d-2642.svg +26f9-fe0f-200d-2640.svg +26f9-fe0f-200d-2642.svg +2764-200d-1f525.svg +2764-200d-1fa79.svg diff --git a/src/wp-includes/fonts/twemoji/manifest.json b/src/wp-includes/fonts/twemoji/manifest.json new file mode 100644 index 0000000000000..cc85664deccd6 --- /dev/null +++ b/src/wp-includes/fonts/twemoji/manifest.json @@ -0,0 +1,438 @@ +{ + "font": "twemoji-colrv1.woff2", + "family": "Twemoji", + "color_format": "glyf_colr_1", + "twemoji": { + "version": "v17.0.3", + "repository": "https://github.com/jdecked/twemoji", + "commit": "b6b55fef1e8636b540a6d016a4729ca8cdf2e60b", + "commit_date": "2026-06-01T22:16:04Z", + "archive_url": "https://codeload.github.com/jdecked/twemoji/tar.gz/b6b55fef1e8636b540a6d016a4729ca8cdf2e60b", + "archive_sha256": "705d79de1460e5e775f362f0d0f01fbe3ef8d65bf4648c490e4649704584f747", + "svg_count": 4009, + "svg_tree_sha256": "acf4b1719e91b046d9fd543d7c177705e54188e38e5600f3b591631152e4761d", + "graphics_license": "CC-BY-4.0" + }, + "source_normalization": [ + { + "file": "1f349.svg", + "rule": "pad viewBox to a centered square", + "input_sha256": "33c1d59d27324b861d394eaac4cdb6eb5f4d8b12b9e442f4bbf3653a5946bea8", + "output_sha256": "400477de6a8fce3ee1f08f55fbf75deeb53a36db6c49ae9364580a168a85eb8f", + "unchanged": false + } + ], + "aliases": { + "stage": "normalization added by this build; not part of the Twemoji input", + "rule": "Each fully-qualified sequence with FE0F gets an alias without any FE0F (in Chromium, GSUB mappings that include FE0F did not apply and those sequences rendered split), and each minimally-qualified or unqualified sequence in emoji-test.txt without its own SVG gets one; an alias is a copy of the fully-qualified SVG.", + "count": 1052, + "sha256": "687db880f7318d32406f5063792eef156722eb46f32ffaa0999539b7816c61e0" + }, + "rgi": { + "url": "https://www.unicode.org/Public/17.0.0/emoji/emoji-test.txt", + "sha256": "1d8a944f88d7952f7ef7c5167fef3c67995bcae24543949710231b03a201acda" + }, + "tools": { + "nanoemoji": "0.16.0", + "picosvg": "0.23.0", + "fonttools": "4.65.0", + "uharfbuzz": "0.56.1", + "brotli": "1.2.0", + "skia-pathops": "0.9.2" + }, + "source_date_epoch": 1780352164, + "output": { + "woff2_bytes": 657364, + "woff2_sha256": "0e8645e0fcbb7c98b18eeaa099122633a9129823336f6a76a944a31be07a4700", + "ttf_bytes": 1494564, + "ttf_sha256": "d1240b1b22192396bb5461ce598ab41a35ca72ddceb2264e19a3eb49213bbab6" + }, + "font_tables": { + "tables": [ + "COLR", + "CPAL", + "GSUB", + "GlyphOrder", + "OS/2", + "cmap", + "glyf", + "head", + "hhea", + "hmtx", + "loca", + "maxp", + "name", + "post" + ], + "colr_version": 1, + "glyphs": 13351, + "cmap_codepoints": 1453, + "units_per_em": 1024 + }, + "coverage": { + "by_status": { + "component": { + "total": 9, + "visible": 9, + "strict": 9 + }, + "fully-qualified": { + "total": 3944, + "visible": 3944, + "strict": 3724 + }, + "minimally-qualified": { + "total": 1029, + "visible": 1029, + "strict": 1029 + }, + "unqualified": { + "total": 243, + "visible": 243, + "strict": 243 + } + }, + "by_kind": { + "component/single": { + "total": 9, + "visible": 9, + "strict": 9 + }, + "fully-qualified/flag": { + "total": 259, + "visible": 259, + "strict": 259 + }, + "fully-qualified/keycap": { + "total": 12, + "visible": 12, + "strict": 0 + }, + "fully-qualified/modifier": { + "total": 665, + "visible": 665, + "strict": 665 + }, + "fully-qualified/single": { + "total": 1391, + "visible": 1391, + "strict": 1184 + }, + "fully-qualified/tag": { + "total": 3, + "visible": 3, + "strict": 3 + }, + "fully-qualified/zwj": { + "total": 1614, + "visible": 1614, + "strict": 1613 + }, + "minimally-qualified/zwj": { + "total": 1029, + "visible": 1029, + "strict": 1029 + }, + "unqualified/keycap": { + "total": 12, + "visible": 12, + "strict": 12 + }, + "unqualified/single": { + "total": 207, + "visible": 207, + "strict": 207 + }, + "unqualified/zwj": { + "total": 24, + "visible": 24, + "strict": 24 + } + }, + "not_visible": [] + }, + "subsets": { + "flags": { + "font": "twemoji-colrv1-flags.woff2", + "derived_from": "twemoji-colrv1.woff2", + "rule": "fontTools subset of the full WOFF2 to the requested code points, keeping every layout feature and the name table; a ligature stays when all of its components do.", + "profile": "Country flags (regional indicator pairs), subdivision flags (black flag, tag characters, cancel tag), and the rainbow, transgender and pirate flags, in every spelling in emoji-test.txt. This is the range the asset supports; which flags Core replaces is decided by its detection and renderer.", + "requested_codepoints": [ + "1F1E6", + "1F1E7", + "1F1E8", + "1F1E9", + "1F1EA", + "1F1EB", + "1F1EC", + "1F1ED", + "1F1EE", + "1F1EF", + "1F1F0", + "1F1F1", + "1F1F2", + "1F1F3", + "1F1F4", + "1F1F5", + "1F1F6", + "1F1F7", + "1F1F8", + "1F1F9", + "1F1FA", + "1F1FB", + "1F1FC", + "1F1FD", + "1F1FE", + "1F1FF", + "1F3F3", + "1F3F4", + "E0020", + "E0021", + "E0022", + "E0023", + "E0024", + "E0025", + "E0026", + "E0027", + "E0028", + "E0029", + "E002A", + "E002B", + "E002C", + "E002D", + "E002E", + "E002F", + "E0030", + "E0031", + "E0032", + "E0033", + "E0034", + "E0035", + "E0036", + "E0037", + "E0038", + "E0039", + "E003A", + "E003B", + "E003C", + "E003D", + "E003E", + "E003F", + "E0040", + "E0041", + "E0042", + "E0043", + "E0044", + "E0045", + "E0046", + "E0047", + "E0048", + "E0049", + "E004A", + "E004B", + "E004C", + "E004D", + "E004E", + "E004F", + "E0050", + "E0051", + "E0052", + "E0053", + "E0054", + "E0055", + "E0056", + "E0057", + "E0058", + "E0059", + "E005A", + "E005B", + "E005C", + "E005D", + "E005E", + "E005F", + "E0060", + "E0061", + "E0062", + "E0063", + "E0064", + "E0065", + "E0066", + "E0067", + "E0068", + "E0069", + "E006A", + "E006B", + "E006C", + "E006D", + "E006E", + "E006F", + "E0070", + "E0071", + "E0072", + "E0073", + "E0074", + "E0075", + "E0076", + "E0077", + "E0078", + "E0079", + "E007A", + "E007B", + "E007C", + "E007D", + "E007E", + "E007F", + "200D", + "FE0F", + "1F308", + "26A7", + "2620" + ], + "cmap_codepoints": [ + "200D", + "2620", + "26A7", + "FE0F", + "1F1E6", + "1F1E7", + "1F1E8", + "1F1E9", + "1F1EA", + "1F1EB", + "1F1EC", + "1F1ED", + "1F1EE", + "1F1EF", + "1F1F0", + "1F1F1", + "1F1F2", + "1F1F3", + "1F1F4", + "1F1F5", + "1F1F6", + "1F1F7", + "1F1F8", + "1F1F9", + "1F1FA", + "1F1FB", + "1F1FC", + "1F1FD", + "1F1FE", + "1F1FF", + "1F308", + "1F3F3", + "1F3F4", + "E0062", + "E0063", + "E0065", + "E0067", + "E006C", + "E006E", + "E0073", + "E0074", + "E0077", + "E007F" + ], + "woff2_bytes": 108888, + "woff2_sha256": "108cd5e892d9ca9cab788b573115d9662b4aa6fa24b48520cf4b792951fee649", + "font_tables": { + "tables": [ + "COLR", + "CPAL", + "GSUB", + "GlyphOrder", + "OS/2", + "cmap", + "glyf", + "head", + "hhea", + "hmtx", + "loca", + "maxp", + "name", + "post" + ], + "colr_version": 1, + "glyphs": 1620, + "cmap_codepoints": 43, + "units_per_em": 1024 + }, + "coverage": { + "by_status": { + "fully-qualified": { + "total": 265, + "visible": 265, + "strict": 265 + }, + "minimally-qualified": { + "total": 2, + "visible": 2, + "strict": 2 + }, + "unqualified": { + "total": 3, + "visible": 3, + "strict": 3 + } + }, + "by_kind": { + "fully-qualified/flag": { + "total": 259, + "visible": 259, + "strict": 259 + }, + "fully-qualified/tag": { + "total": 3, + "visible": 3, + "strict": 3 + }, + "fully-qualified/zwj": { + "total": 3, + "visible": 3, + "strict": 3 + }, + "minimally-qualified/zwj": { + "total": 2, + "visible": 2, + "strict": 2 + }, + "unqualified/zwj": { + "total": 3, + "visible": 3, + "strict": 3 + } + }, + "not_visible": [] + } + } + }, + "browser_vqa": [ + { + "font": "twemoji-colrv1.woff2", + "woff2_sha256": "0e8645e0fcbb7c98b18eeaa099122633a9129823336f6a76a944a31be07a4700", + "browser": "Edge 153.0.4234.32", + "platform": "Windows", + "date": "2026-09-19", + "check": "vqa/index.html: every sequence in emoji-test.txt drawn in the font and in the system emoji font; passes when one glyph wide, not plain black ink, and different from the system font's drawing", + "results": { + "fully-qualified": "3944/3944", + "minimally-qualified": "1029/1029", + "unqualified": "243/243", + "component": "9/9" + } + }, + { + "font": "twemoji-colrv1-flags.woff2", + "woff2_sha256": "108cd5e892d9ca9cab788b573115d9662b4aa6fa24b48520cf4b792951fee649", + "browser": "Edge 153.0.4234.32", + "platform": "Windows", + "date": "2026-09-20", + "check": "vqa/index.html?only=flags: the flag profile only, same criteria", + "results": { + "fully-qualified": "265/265", + "minimally-qualified": "2/2", + "unqualified": "3/3" + } + } + ] +} diff --git a/src/wp-includes/fonts/twemoji/source.txt b/src/wp-includes/fonts/twemoji/source.txt new file mode 100644 index 0000000000000..21586d7ea282a --- /dev/null +++ b/src/wp-includes/fonts/twemoji/source.txt @@ -0,0 +1,8 @@ +Font: Twemoji (twemoji-colrv1.woff2) +Source: https://github.com/jdecked/twemoji v17.0.3, commit b6b55fef1e8636b540a6d016a4729ca8cdf2e60b, assets/svg (4009 files) +Upstream source normalization (not part of Twemoji): 1f349.svg: pad viewBox to a centered square (33c1d59d27324b861d394eaac4cdb6eb5f4d8b12b9e442f4bbf3653a5946bea8 -> 400477de6a8fce3ee1f08f55fbf75deeb53a36db6c49ae9364580a168a85eb8f) +Aliases (not part of Twemoji): 1052, each a copy of a fully-qualified SVG under a spelling without FE0F: all FE0F removed (in Chromium, GSUB mappings that include FE0F did not apply), and the minimally-qualified and unqualified spellings in Unicode emoji-test.txt 17.0 (list SHA-256 687db880f7318d32406f5063792eef156722eb46f32ffaa0999539b7816c61e0) +Build: nanoemoji 0.16.0, color format glyf_colr_1, then WOFF2 (fontTools 4.65.0) +Subset flags: twemoji-colrv1-flags.woff2, cut from twemoji-colrv1.woff2 with the fontTools subsetter (43 code points) +License: graphics CC-BY 4.0 (LICENSE-GRAPHICS); attribution: Twitter, Inc and other contributors, and jdecked and other contributors +Purpose: emoji font fallback, built once by maintainers and served as a static file diff --git a/src/wp-includes/fonts/twemoji/twemoji-colrv1-flags.woff2 b/src/wp-includes/fonts/twemoji/twemoji-colrv1-flags.woff2 new file mode 100644 index 0000000000000..248a87af4101e Binary files /dev/null and b/src/wp-includes/fonts/twemoji/twemoji-colrv1-flags.woff2 differ diff --git a/src/wp-includes/fonts/twemoji/twemoji-colrv1.woff2 b/src/wp-includes/fonts/twemoji/twemoji-colrv1.woff2 new file mode 100644 index 0000000000000..464ebd2091fcb Binary files /dev/null and b/src/wp-includes/fonts/twemoji/twemoji-colrv1.woff2 differ diff --git a/tools/emoji/Dockerfile b/tools/emoji/Dockerfile new file mode 100644 index 0000000000000..6fdd3f8947958 --- /dev/null +++ b/tools/emoji/Dockerfile @@ -0,0 +1,11 @@ +# Build environment for the Twemoji COLRv1 font. +# +# The same image gives the same tools on Windows, macOS and Linux. It is for +# maintainers updating Twemoji, not for sites: sites serve the built WOFF2. +FROM python:3.12-slim@sha256:2f17fc044b579bab302c2e8054d3a686e2cb9a83de48e70534b94cd8ebbe06a9 + +COPY requirements.lock /tmp/requirements.lock +RUN pip install --no-cache-dir --no-deps -r /tmp/requirements.lock + +WORKDIR /work +ENTRYPOINT ["python", "/work/build-twemoji-colrv1.py"] diff --git a/tools/emoji/README.md b/tools/emoji/README.md new file mode 100644 index 0000000000000..5fb8ccd621b54 --- /dev/null +++ b/tools/emoji/README.md @@ -0,0 +1,59 @@ +# Twemoji COLRv1 font + +`build-twemoji-colrv1.py` builds `src/wp-includes/fonts/twemoji/twemoji-colrv1.woff2`, Twemoji as one COLRv1 color font, and `twemoji-colrv1-flags.woff2`, a subset of it with only the flags. See [#66144](https://core.trac.wordpress.org/ticket/66144). + +This is a maintainer tool, run when Twemoji is updated. Sites never run it: they serve the WOFF2 files as static files. The script and its pins record where the fonts came from, and let anyone build it again and get the same bytes. + +Nothing loads the fonts yet. Using them, for the emoji a browser cannot draw, is follow-up work in #66144. + +## Build + +The Docker image pins the base image by digest and installs every Python package from `requirements.lock`, so the tools are the same on every platform. + +```sh +docker build -t twemoji-colrv1-build tools/emoji +docker run --rm -v "$PWD/tools/emoji:/work" -v "$PWD/src/wp-includes/fonts/twemoji:/out" -v ":/cache" \ + twemoji-colrv1-build v17.0.3 --cache /cache --out /out +``` + +With `--verify`, the script builds again in a temporary directory and fails unless the result is byte-identical to the files in `--out`: + +```sh +docker run --rm -v "$PWD/tools/emoji:/work" -v "$PWD/src/wp-includes/fonts/twemoji:/out" -v ":/cache" \ + twemoji-colrv1-build v17.0.3 --cache /cache --out /out --verify +``` + +`` is any directory for the downloaded Twemoji archive and Unicode's `emoji-test.txt`. A full build takes about 20 minutes. + +## What the build does + +1. Downloads the Twemoji release archive by commit and checks its SHA-256, and the SHA-256 of its SVG set, against `sources.json`. A changed archive or SVG set stops the build. `--record` pins the hashes of a new version whose entries are still `null`. +2. Normalizes the input, as recorded below. +3. Builds the SVGs into a glyf + COLRv1 font with nanoemoji (`glyf_colr_1`, `clipbox_quantization = 32`), with `SOURCE_DATE_EPOCH` set to the Twemoji commit date. +4. Writes the Twemoji attribution into the font's name table and compresses the font to WOFF2. +5. Cuts the flags subset out of that WOFF2. +6. Shapes every sequence in Unicode's `emoji-test.txt` with HarfBuzz and records the counts, for the full font and, limited to the flag profile, for the subset. +7. Writes `manifest.json` (input, tools, output SHA-256, coverage), `source.txt`, `LICENSE-GRAPHICS` and `aliases.txt` next to the font. + +## Flags subset + +`twemoji-colrv1-flags.woff2` is cut from the full font with the fontTools subsetter, never built separately, so it has the same artwork, aliases and license. It keeps the code points in `FLAGS_CODEPOINTS` (regional indicators, the white and black flags, tag characters, and ZWJ, VS16, rainbow, transgender symbol and skull and crossbones), and a ligature stays when all of its components do. For v17.0.3 it is 108,888 bytes, about a sixth of the full font. Subsets are declared in `SUBSETS` in the build script, each with its file, the code points it asks for and the sequences its coverage is measured on; another profile, such as every emoji except the flags, would be one more entry. + +It covers the flag profile: country flags, subdivision flags such as England, Scotland and Wales, and the rainbow, transgender and pirate flags, in every spelling in `emoji-test.txt`. That is the range the asset supports; which flags are replaced is decided by emoji detection and, later, the renderer. It is for browsers that draw other emoji but not flags, such as Chromium on Windows. + +## Normalization + +Neither step is part of Twemoji. `manifest.json` and `source.txt` record the rules and hashes. + +- **Aliases for spellings without FE0F.** Each fully-qualified sequence also gets its spelling with every FE0F removed, and each minimally-qualified or unqualified spelling in `emoji-test.txt` gets one too: a copy of the fully-qualified SVG under that name (1,052 for v17.0.3, listed in `aliases.txt`). In a build without them, Edge rendered 960 fully-qualified sequences split, every one whose SVG name includes FE0F; with them, all 3,944 render as one glyph. +- **Square viewBox.** Files in `SQUARE_VIEWBOX` get their viewBox padded to a centered square. `1f349.svg` in v17.0.3 has `viewBox="0 0 36 25.22"`, which gave it an advance of 1713 against 1275 for every other glyph. It is reported upstream in [jdecked/twemoji#133](https://github.com/jdecked/twemoji/issues/133), with a fix open in [#102](https://github.com/jdecked/twemoji/pull/102); the entry can be removed once that lands. Any other SVG with a non-square viewBox stops the build. + +## Checking a font + +Whether a font renders correctly is checked in a browser, not with HarfBuzz alone: HarfBuzz shaped all 3,944 fully-qualified sequences to one glyph in the build without aliases. The check used for v17.0.3 drew each sequence in the font and in the system emoji font, and required one glyph width, the font's colors, and a result that differs from the system font's. In Edge 153 on Windows, all 3,944 fully-qualified, 1,029 minimally-qualified, 243 unqualified and 9 component sequences passed with the full font, and every sequence in the flag profile passed with the flags subset (265 fully-qualified, 2 minimally-qualified, 3 unqualified). + +Browser results are recorded in `sources.json` after a build, for each output's SHA-256, and the build copies them into `manifest.json` only for outputs with the same SHA-256. + +## License + +Twemoji's code is MIT; its graphics are CC-BY 4.0. The font carries the attribution in its name table (copyright, license description and license URL), and `LICENSE-GRAPHICS` and `source.txt` sit next to it. diff --git a/tools/emoji/build-twemoji-colrv1.py b/tools/emoji/build-twemoji-colrv1.py new file mode 100644 index 0000000000000..5d03aaff0079c --- /dev/null +++ b/tools/emoji/build-twemoji-colrv1.py @@ -0,0 +1,578 @@ +#!/usr/bin/env python3 +"""Build the Twemoji COLRv1 font from a pinned Twemoji release. + +This is a maintainer tool. WordPress sites never run it: they serve the WOFF2 +it writes. It exists so that the font can be traced to its source and built +again when Twemoji is updated. + + build-twemoji-colrv1.py v17.0.3 --cache /cache --out src/wp-includes/fonts/twemoji + build-twemoji-colrv1.py v17.0.3 --cache /cache --out src/wp-includes/fonts/twemoji --verify + +See README.md for running it in the pinned Docker image. + +Steps: + +1. Download the release archive for the pinned commit, and check its SHA-256 + and the SHA-256 of its SVG files against sources.json. With --record, a + version whose hashes are still null gets them written instead. +2. Normalize the listed upstream sources (SQUARE_VIEWBOX). Add a copy of an + SVG for each sequence emoji-test.txt lists without one of + its FE0F (minimally-qualified or unqualified), under that sequence's name, + so the font draws both spellings. Then build the SVGs into a glyf + COLRv1 + font with nanoemoji. +3. Write the Twemoji attribution into the font's name table. +4. Compress the font to WOFF2. +5. Shape every sequence in Unicode's emoji-test.txt with HarfBuzz and count + which ones the font draws as a single visible glyph. +6. Write manifest.json, source.txt and LICENSE-GRAPHICS next to the font. + +--verify builds again in a temporary directory and fails unless the new font +and manifest are byte-identical to the ones in --out. +""" + +import argparse +import hashlib +import io +import json +import os +import re +import shutil +import subprocess +import sys +import tarfile +import tempfile +import urllib.request +from collections import Counter +from datetime import datetime +from importlib import metadata +from pathlib import Path + +HERE = Path(__file__).resolve().parent +SOURCES = HERE / "sources.json" +FAMILY = "Twemoji" +FONT_FILE = "twemoji-colrv1.woff2" +FLAGS_FILE = "twemoji-colrv1-flags.woff2" + +# The flags subset is cut from the full font, never built separately, so it +# shares its artwork, aliases and license. These are the code points it asks +# for: regional indicators, the white and black flags, tag characters, and +# the ZWJ, VS16, rainbow, transgender symbol and skull and crossbones that the +# rainbow, transgender and pirate flags are made of. A ligature is kept when +# all of its components are. +FLAGS_CODEPOINTS = ( + tuple(range(0x1F1E6, 0x1F200)) + + (0x1F3F3, 0x1F3F4) + + tuple(range(0xE0020, 0xE0080)) + + (0x200D, 0xFE0F, 0x1F308, 0x26A7, 0x2620) +) +ZWJ_FLAGS = ((0x1F3F3, 0x200D, 0x1F308), (0x1F3F3, 0x200D, 0x26A7), (0x1F3F4, 0x200D, 0x2620)) + + +def is_flag_profile(codepoints): + """The flag profile: country, subdivision, rainbow, transgender and pirate flags, in any spelling.""" + if len(codepoints) == 2 and all(0x1F1E6 <= c <= 0x1F1FF for c in codepoints): + return True + if ( + len(codepoints) > 2 + and codepoints[0] == 0x1F3F4 + and codepoints[-1] == 0xE007F + and all(0xE0020 <= c <= 0xE007E for c in codepoints[1:-1]) + ): + return True + return tuple(c for c in codepoints if c != 0xFE0F) in ZWJ_FLAGS + + +# Subsets cut from the full font. Each names its file, the code points it +# asks the subsetter for (a function of the full font's cmap), and the +# sequences it is meant to draw, which its coverage is measured on. Another +# profile, such as everything but the flags, is another entry here. +SUBSETS = { + "flags": { + "file": FLAGS_FILE, + "codepoints": lambda full_cmap: FLAGS_CODEPOINTS, + "profile": is_flag_profile, + "description": "Country flags (regional indicator pairs), subdivision flags (black flag, tag characters, cancel tag), and the rainbow, transgender and pirate flags, in every spelling in emoji-test.txt. This is the range the asset supports; which flags Core replaces is decided by its detection and renderer.", + }, +} +TOOLS = ("nanoemoji", "picosvg", "fonttools", "uharfbuzz", "brotli", "skia-pathops") +LICENSE_URL = "https://creativecommons.org/licenses/by/4.0/" + + +def sha256_bytes(data): + return hashlib.sha256(data).hexdigest() + + +def sha256_file(path): + return sha256_bytes(Path(path).read_bytes()) + + +def fail(message): + print(f"error: {message}", file=sys.stderr) + sys.exit(1) + + +def load_sources(): + return json.loads(SOURCES.read_text(encoding="utf-8")) + + +def save_sources(sources): + SOURCES.write_text(json.dumps(sources, indent="\t", ensure_ascii=False) + "\n", encoding="utf-8", newline="\n") + + +def fetch(url, path): + if not path.exists(): + print(f"Downloading {url}") + with urllib.request.urlopen(url) as response: + path.write_bytes(response.read()) + return path.read_bytes() + + +def check_pin(entry, key, actual, record, label): + """Compares a hash with sources.json, or records it with --record.""" + pinned = entry.get(key) + if pinned is None: + if not record: + fail(f"{label} is not pinned yet ({actual}); run with --record to pin it") + entry[key] = actual + return True + if pinned != actual: + fail(f"{label} does not match sources.json: expected {pinned}, got {actual}") + return False + + +def extract_svgs(archive, svg_dir): + """Extracts assets/svg/*.svg and returns {file name: bytes}.""" + svgs = {} + with tarfile.open(fileobj=io.BytesIO(archive), mode="r:gz") as tar: + for member in tar.getmembers(): + parts = member.name.split("/") + if member.isfile() and len(parts) == 4 and parts[1:3] == ["assets", "svg"] and parts[3].endswith(".svg"): + svgs[parts[3]] = tar.extractfile(member).read() + elif member.isfile() and len(parts) == 2 and parts[1] == "LICENSE-GRAPHICS": + svgs["LICENSE-GRAPHICS"] = tar.extractfile(member).read() + license_text = svgs.pop("LICENSE-GRAPHICS", None) + if license_text is None: + fail("the archive has no LICENSE-GRAPHICS") + if svg_dir.exists(): + shutil.rmtree(svg_dir) + svg_dir.mkdir(parents=True) + for name, data in svgs.items(): + (svg_dir / name).write_bytes(data) + return svgs, license_text + + +def svg_tree_sha256(svgs): + """One hash for the SVG set: each file's name and SHA-256, sorted by name.""" + lines = "".join(f"{name}\0{sha256_bytes(data)}\n" for name, data in sorted(svgs.items())) + return sha256_bytes(lines.encode("utf-8")) + + +# Upstream source normalization: files changed before the build, and how. +# A non-square viewBox did not match the advance width of the rest of the +# nanoemoji output: in the first v17.0.3 build, 1f349.svg (viewBox +# "0 0 36 25.22") got an advance of 1713 against 1275 for every other glyph. +# These files are padded to a centered square. Any other file with a +# non-square viewBox stops the build. +SQUARE_VIEWBOX = ("1f349.svg",) + + +def square_viewbox(data): + """Pads the SVG's viewBox to a square with the artwork centered.""" + text = data.decode("utf-8") + match = re.search(r'viewBox="([^"]+)"', text) + x, y, w, h = (float(v) for v in match.group(1).split()) + side = max(w, h) + box = [x - (side - w) / 2, y - (side - h) / 2, side, side] + value = " ".join(f"{v:.4f}".rstrip("0").rstrip(".") for v in box) + return (text[: match.start(1)] + value + text[match.end(1) :]).encode("utf-8") + + +def viewbox_is_square(data): + match = re.search(rb'viewBox="([^"]+)"', data) + if not match: + return False + w, h = (float(v) for v in match.group(1).split()[2:]) + return w == h + + +def normalize_sources(svg_dir): + """Applies SQUARE_VIEWBOX and returns what changed, with hashes.""" + changed = [] + for path in sorted(svg_dir.glob("*.svg")): + data = path.read_bytes() + if path.name in SQUARE_VIEWBOX: + new = square_viewbox(data) + changed.append({ + "file": path.name, + "rule": "pad viewBox to a centered square", + "input_sha256": sha256_bytes(data), + "output_sha256": sha256_bytes(new), + "unchanged": new == data, + }) + path.write_bytes(new) + elif not viewbox_is_square(data): + fail(f"{path.name} has a non-square viewBox; add it to SQUARE_VIEWBOX or fix the input") + return changed + + +def svg_name(codepoints): + return "-".join(f"{c:x}" for c in codepoints) + ".svg" + + +def add_unqualified_aliases(svg_dir, emoji_test): + """Copies SVGs for sequences written without some or all of their FE0F. + + Twemoji names many SVGs by their fully-qualified sequence, FE0F included. + In Chromium, the GSUB mapping for those sequences did not apply and they + rendered split (Edge VQA of the first build: 960 fully-qualified sequences, + every one whose SVG name includes FE0F), so every fully-qualified sequence + gets an alias with all FE0F removed. The minimally-qualified and unqualified spellings in + emoji-test.txt get one too. Each alias is a copy of the fully-qualified + SVG, so nanoemoji maps it to the same artwork. Returns the file names. + """ + existing = {p.name for p in svg_dir.glob("*.svg")} + by_stripped = {} + for codepoints, status in parse_emoji_test(emoji_test): + if status != "fully-qualified": + continue + stripped = tuple(c for c in codepoints if c != 0xFE0F) + for candidate in (svg_name(codepoints), svg_name(stripped)): + if candidate in existing: + by_stripped[stripped] = candidate + break + aliases = [] + + def add(name, source): + if name in existing or source is None: + return + (svg_dir / name).write_bytes((svg_dir / source).read_bytes()) + existing.add(name) + aliases.append(name) + + for stripped, source in sorted(by_stripped.items()): + add(svg_name(stripped), source) + for codepoints, status in parse_emoji_test(emoji_test): + if status in ("minimally-qualified", "unqualified"): + add(svg_name(codepoints), by_stripped.get(tuple(c for c in codepoints if c != 0xFE0F))) + return sorted(aliases) + + +def build_ttf(svg_dir, build_dir, env): + config = build_dir / "twemoji.toml" + srcs = ", ".join(json.dumps(p.as_posix()) for p in sorted(svg_dir.glob("*.svg"))) + config.write_text( + f'family = "{FAMILY}"\n' + 'output_file = "twemoji-colrv1.ttf"\n' + 'color_format = "glyf_colr_1"\n' + "clipbox_quantization = 32\n" + # A static font: nanoemoji wants the tables, and leaving them empty + # means no variation axes. + "\n[axis]\n" + f"\n[master.regular]\nstyle_name = \"Regular\"\nsrcs = [{srcs}]\n" + "\n[master.regular.position]\n", + encoding="utf-8", + ) + subprocess.run(["nanoemoji", f"--build_dir={build_dir}", str(config)], check=True, env=env) + return build_dir / "twemoji-colrv1.ttf" + + +def set_names(ttf_path, version): + from fontTools.ttLib import TTFont + + font = TTFont(ttf_path) + names = { + 0: "Twemoji graphics: Copyright Twitter, Inc and other contributors, and jdecked and other contributors.", + 5: f"Version {version.lstrip('v')}; Twemoji {version}", + 13: f"Twemoji graphics are licensed under CC-BY 4.0: {LICENSE_URL}", + 14: LICENSE_URL, + } + for name_id, value in names.items(): + font["name"].setName(value, name_id, 3, 1, 0x409) + font.save(ttf_path) + + +def to_woff2(ttf_path, woff2_path): + from fontTools.ttLib import woff2 + + woff2.compress(str(ttf_path), str(woff2_path)) + + +def parse_emoji_test(text): + """Yields (codepoints, status) for each sequence in emoji-test.txt.""" + for line in text.splitlines(): + line = line.split("#", 1)[0].strip() + if not line or ";" not in line: + continue + codes, status = (part.strip() for part in line.split(";", 1)) + yield tuple(int(c, 16) for c in codes.split()), status + + +def kind(codepoints): + cps = set(codepoints) + if 0x200D in cps: + return "zwj" + if 0xE007F in cps: + return "tag" + if len(codepoints) == 2 and all(0x1F1E6 <= c <= 0x1F1FF for c in codepoints): + return "flag" + if 0x20E3 in cps: + return "keycap" + if any(0x1F3FB <= c <= 0x1F3FF for c in codepoints) and len(codepoints) > 1: + return "modifier" + return "single" + + +def cut_subset(full_woff2, codepoints, woff2_path, ttf_path): + """Cuts a subset out of the full WOFF2; returns its cmap code points.""" + from fontTools import subset + from fontTools.ttLib import TTFont + + options = subset.Options() + options.layout_features = ["*"] + options.name_IDs = ["*"] + options.name_languages = ["*"] + options.name_legacy = True + options.notdef_outline = True + options.glyph_names = False + font = TTFont(full_woff2) + subsetter = subset.Subsetter(options) + subsetter.populate(unicodes=codepoints) + subsetter.subset(font) + font.flavor = "woff2" + font.save(woff2_path) + font.flavor = None + font.save(ttf_path) + return sorted(TTFont(ttf_path).getBestCmap()) + + +def measure(font_path, emoji_test, only=None): + """Counts the sequences the font draws as one glyph, by status and kind. + + `visible` hides default-ignorable characters such as FE0F, as browsers do: + a sequence counts when one visible glyph is left. `strict` counts only + sequences shaped to exactly one glyph with nothing hidden. `only` limits + the count to the sequences it accepts. + """ + import uharfbuzz as hb + + blob = hb.Blob.from_file_path(str(font_path)) + font = hb.Font(hb.Face(blob)) + + def shape(codepoints, hide): + buf = hb.Buffer() + buf.add_codepoints(list(codepoints)) + buf.guess_segment_properties() + if hide: + buf.flags = hb.BufferFlags.REMOVE_DEFAULT_IGNORABLES + hb.shape(font, buf) + glyphs = [info.codepoint for info in buf.glyph_infos] + return len(glyphs) == 1 and glyphs[0] != 0 + + totals, visible, strict, missing = Counter(), Counter(), Counter(), [] + for codepoints, status in parse_emoji_test(emoji_test): + if only is not None and not only(codepoints): + continue + key = f"{status}/{kind(codepoints)}" + totals[key] += 1 + strict[key] += int(shape(codepoints, False)) + if shape(codepoints, True): + visible[key] += 1 + else: + missing.append(f"{status}: " + " ".join(f"{c:04X}" for c in codepoints)) + + def rollup(keys): + return { + "total": sum(totals[k] for k in keys), + "visible": sum(visible[k] for k in keys), + "strict": sum(strict[k] for k in keys), + } + + statuses = sorted({k.split("/")[0] for k in totals}) + return { + "by_status": {s: rollup([k for k in totals if k.startswith(s + "/")]) for s in statuses}, + "by_kind": {k: rollup([k]) for k in sorted(totals)}, + "not_visible": missing, + } + + +def font_cmap(ttf_path): + from fontTools.ttLib import TTFont + + return TTFont(ttf_path).getBestCmap() + + +def font_tables(ttf_path): + from fontTools.ttLib import TTFont + + font = TTFont(ttf_path) + colr = font["COLR"] if "COLR" in font else None + return { + "tables": sorted(font.keys()), + "colr_version": colr.version if colr is not None else None, + "glyphs": len(font.getGlyphOrder()), + "cmap_codepoints": len(font.getBestCmap()), + "units_per_em": font["head"].unitsPerEm, + } + + +def build(version, cache, out, record): + sources = load_sources() + entry = sources["versions"].get(version) + if entry is None: + fail(f"{version} is not in sources.json") + changed = False + + archive_url = f"https://codeload.github.com/jdecked/twemoji/tar.gz/{entry['commit']}" + archive = fetch(archive_url, cache / f"twemoji-{entry['commit']}.tar.gz") + changed |= check_pin(entry, "archive_sha256", sha256_bytes(archive), record, "archive SHA-256") + + work = Path(tempfile.mkdtemp(prefix="twemoji-colrv1-")) + try: + svgs, license_text = extract_svgs(archive, work / "svg") + changed |= check_pin(entry, "svg_tree_sha256", svg_tree_sha256(svgs), record, "SVG tree SHA-256") + changed |= check_pin(entry, "svg_count", len(svgs), record, "SVG count") + + rgi_path = cache / "emoji-test-17.0.txt" + rgi = fetch(sources["rgi"]["url"], rgi_path) + if sha256_bytes(rgi) != sources["rgi"]["sha256"]: + fail("emoji-test.txt does not match sources.json") + normalized = normalize_sources(work / "svg") + aliases = add_unqualified_aliases(work / "svg", rgi.decode("utf-8")) + + # nanoemoji and fontTools stamp the font with this time instead of now. + epoch = int(datetime.fromisoformat(entry["commit_date"].replace("Z", "+00:00")).timestamp()) + env = dict(os.environ, SOURCE_DATE_EPOCH=str(epoch)) + os.environ["SOURCE_DATE_EPOCH"] = str(epoch) + + build_dir = work / "build" + build_dir.mkdir() + ttf = build_ttf(work / "svg", build_dir, env) + set_names(ttf, version) + out.mkdir(parents=True, exist_ok=True) + woff2 = out / FONT_FILE + to_woff2(ttf, woff2) + full_cmap = sorted(font_cmap(ttf)) + subsets = {} + for name, spec in SUBSETS.items(): + requested = tuple(spec["codepoints"](full_cmap)) + subset_woff2 = out / spec["file"] + subset_ttf = work / (Path(spec["file"]).stem + ".ttf") + cmap = cut_subset(woff2, requested, subset_woff2, subset_ttf) + subsets[name] = { + "font": spec["file"], + "derived_from": FONT_FILE, + "rule": "fontTools subset of the full WOFF2 to the requested code points, keeping every layout feature and the name table; a ligature stays when all of its components do.", + "profile": spec["description"], + "requested_codepoints": [f"{c:04X}" for c in requested], + "cmap_codepoints": [f"{c:04X}" for c in cmap], + "woff2_bytes": subset_woff2.stat().st_size, + "woff2_sha256": sha256_file(subset_woff2), + "font_tables": font_tables(subset_ttf), + "coverage": measure(subset_ttf, rgi.decode("utf-8"), only=spec["profile"]), + } + outputs = {sha256_file(woff2)} | {s["woff2_sha256"] for s in subsets.values()} + + manifest = { + "font": FONT_FILE, + "family": FAMILY, + "color_format": "glyf_colr_1", + "twemoji": { + "version": version, + "repository": sources["repository"], + "commit": entry["commit"], + "commit_date": entry["commit_date"], + "archive_url": archive_url, + "archive_sha256": entry["archive_sha256"], + "svg_count": entry["svg_count"], + "svg_tree_sha256": entry["svg_tree_sha256"], + "graphics_license": "CC-BY-4.0", + }, + "source_normalization": normalized, + "aliases": { + "stage": "normalization added by this build; not part of the Twemoji input", + "rule": "Each fully-qualified sequence with FE0F gets an alias without any FE0F (in Chromium, GSUB mappings that include FE0F did not apply and those sequences rendered split), and each minimally-qualified or unqualified sequence in emoji-test.txt without its own SVG gets one; an alias is a copy of the fully-qualified SVG.", + "count": len(aliases), + "sha256": sha256_bytes("".join(a + chr(10) for a in aliases).encode("utf-8")), + }, + "rgi": sources["rgi"], + "tools": {name: metadata.version(name) for name in TOOLS}, + "source_date_epoch": epoch, + "output": { + "woff2_bytes": woff2.stat().st_size, + "woff2_sha256": sha256_file(woff2), + "ttf_bytes": ttf.stat().st_size, + "ttf_sha256": sha256_file(ttf), + }, + "font_tables": font_tables(ttf), + "coverage": measure(ttf, rgi.decode("utf-8")), + "subsets": subsets, + # Browser results are recorded in sources.json after a build, and + # are carried over only for outputs with the same SHA-256. + "browser_vqa": [r for r in entry.get("browser_vqa", []) if r.get("woff2_sha256") in outputs], + } + (out / "manifest.json").write_text(json.dumps(manifest, indent="\t", ensure_ascii=False) + "\n", encoding="utf-8", newline="\n") + (out / "LICENSE-GRAPHICS").write_bytes(license_text) + # The alias list itself, so its SHA-256 in the manifest can be checked. + (out / "aliases.txt").write_text("".join(a + chr(10) for a in aliases), encoding="utf-8", newline="\n") + (out / "source.txt").write_text( + f"Font: {FAMILY} ({FONT_FILE})\n" + f"Source: {sources['repository']} {version}, commit {entry['commit']}, assets/svg ({entry['svg_count']} files)\n" + "Upstream source normalization (not part of Twemoji): " + + "; ".join(f"{n['file']}: {n['rule']} ({n['input_sha256']} -> {n['output_sha256']})" for n in normalized) + + "\n" + f"Aliases (not part of Twemoji): {len(aliases)}, each a copy of a fully-qualified SVG under a spelling without FE0F: all FE0F removed (in Chromium, GSUB mappings that include FE0F did not apply), and the minimally-qualified and unqualified spellings in Unicode emoji-test.txt 17.0 (list SHA-256 {manifest['aliases']['sha256']})\n" + f"Build: nanoemoji {metadata.version('nanoemoji')}, color format glyf_colr_1, then WOFF2 (fontTools {metadata.version('fonttools')})\n" + + "".join( + f"Subset {name}: {s['font']}, cut from {FONT_FILE} with the fontTools subsetter ({len(s['cmap_codepoints'])} code points)\n" + for name, s in subsets.items() + ) + + "License: graphics CC-BY 4.0 (LICENSE-GRAPHICS); attribution: Twitter, Inc and other contributors, and jdecked and other contributors\n" + "Purpose: emoji font fallback, built once by maintainers and served as a static file\n", + encoding="utf-8", + newline="\n", + ) + finally: + shutil.rmtree(work, ignore_errors=True) + + if changed: + save_sources(sources) + print(f"Pinned {version} in sources.json") + return manifest + + +def main(): + parser = argparse.ArgumentParser(description=__doc__.split("\n\n")[0]) + parser.add_argument("version", help="Twemoji release tag in sources.json, such as v17.0.3") + parser.add_argument("--cache", type=Path, required=True, help="Directory for the downloaded archive and emoji-test.txt") + parser.add_argument("--out", type=Path, required=True, help="Directory for the font and its manifest") + parser.add_argument("--record", action="store_true", help="Pin hashes that are still null in sources.json") + parser.add_argument("--verify", action="store_true", help="Build again and compare with --out") + args = parser.parse_args() + args.cache.mkdir(parents=True, exist_ok=True) + + if not args.verify: + manifest = build(args.version, args.cache, args.out, args.record) + for status, counts in manifest["coverage"]["by_status"].items(): + print(f"{status}: visible {counts['visible']}/{counts['total']}, strict {counts['strict']}/{counts['total']}") + print(f"{FONT_FILE}: {manifest['output']['woff2_bytes']} bytes, {manifest['aliases']['count']} aliases") + for name, s in manifest["subsets"].items(): + for status, counts in s["coverage"]["by_status"].items(): + print(f"{name} {status}: visible {counts['visible']}/{counts['total']}") + print(f"{s['font']}: {s['woff2_bytes']} bytes, {len(s['cmap_codepoints'])} code points") + print(f"{len(manifest['browser_vqa'])} browser results carried over") + return + + with tempfile.TemporaryDirectory() as tmp: + fresh = Path(tmp) + build(args.version, args.cache, fresh, record=False) + problems = [ + name for name in (FONT_FILE, *(s["file"] for s in SUBSETS.values()), "manifest.json", "source.txt", "LICENSE-GRAPHICS", "aliases.txt") + if not (args.out / name).exists() or (args.out / name).read_bytes() != (fresh / name).read_bytes() + ] + if problems: + fail("rebuild differs from --out: " + ", ".join(problems)) + print(f"Verified: a fresh build of {args.version} is byte-identical to {args.out}") + + +if __name__ == "__main__": + main() diff --git a/tools/emoji/requirements.in b/tools/emoji/requirements.in new file mode 100644 index 0000000000000..aabeab16ac91b --- /dev/null +++ b/tools/emoji/requirements.in @@ -0,0 +1,8 @@ +# Top-level build tools. requirements.lock pins these and everything they +# pull in; the image installs from the lock file. +nanoemoji==0.16.0 +picosvg==0.23.0 +fonttools==4.65.0 +brotli==1.2.0 +uharfbuzz==0.56.1 +ninja==1.13.2 diff --git a/tools/emoji/requirements.lock b/tools/emoji/requirements.lock new file mode 100644 index 0000000000000..f300778eece43 --- /dev/null +++ b/tools/emoji/requirements.lock @@ -0,0 +1,24 @@ +# Every package the build installs, resolved from requirements.in with +# pip freeze in the Dockerfile's base image. Update both files together. +absl-py==2.5.0 +attrs==26.1.0 +booleanOperations==0.10.0 +brotli==1.2.0 +cffsubr==0.4.0 +fontMath==0.10.0 +fonttools==4.65.0 +lxml==6.1.3 +nanoemoji==0.16.0 +ninja==1.13.2 +picosvg==0.23.0 +pillow==12.3.0 +pngquant-cli==3.0.3 +pyclipper==1.4.0 +regex==2026.9.10 +resvg-cli==0.44.0 +skia-pathops==0.9.2 +toml==0.10.2 +ufo2ft==3.9.0 +ufoLib2==0.18.1 +uharfbuzz==0.56.1 +zopfli==0.4.3 diff --git a/tools/emoji/sources.json b/tools/emoji/sources.json new file mode 100644 index 0000000000000..b808e2733385a --- /dev/null +++ b/tools/emoji/sources.json @@ -0,0 +1,52 @@ +{ + "repository": "https://github.com/jdecked/twemoji", + "versions": { + "v17.0.3": { + "commit": "b6b55fef1e8636b540a6d016a4729ca8cdf2e60b", + "commit_date": "2026-06-01T22:16:04Z", + "archive_sha256": "705d79de1460e5e775f362f0d0f01fbe3ef8d65bf4648c490e4649704584f747", + "svg_tree_sha256": "acf4b1719e91b046d9fd543d7c177705e54188e38e5600f3b591631152e4761d", + "svg_count": 4009, + "browser_vqa": [ + { + "font": "twemoji-colrv1.woff2", + "woff2_sha256": "0e8645e0fcbb7c98b18eeaa099122633a9129823336f6a76a944a31be07a4700", + "browser": "Edge 153.0.4234.32", + "platform": "Windows", + "date": "2026-09-19", + "check": "vqa/index.html: every sequence in emoji-test.txt drawn in the font and in the system emoji font; passes when one glyph wide, not plain black ink, and different from the system font's drawing", + "results": { + "fully-qualified": "3944/3944", + "minimally-qualified": "1029/1029", + "unqualified": "243/243", + "component": "9/9" + } + }, + { + "font": "twemoji-colrv1-flags.woff2", + "woff2_sha256": "108cd5e892d9ca9cab788b573115d9662b4aa6fa24b48520cf4b792951fee649", + "browser": "Edge 153.0.4234.32", + "platform": "Windows", + "date": "2026-09-20", + "check": "vqa/index.html?only=flags: the flag profile only, same criteria", + "results": { + "fully-qualified": "265/265", + "minimally-qualified": "2/2", + "unqualified": "3/3" + } + } + ] + }, + "v17.0.2": { + "commit": "388f518b756404152f128a3539f5e7f9a6f1ebd6", + "commit_date": "2025-11-04T20:44:09Z", + "archive_sha256": "097e9b665da40c8bda2730bf1fe6b1efa71316adc3b6bffceabe7d24eaa49d03", + "svg_tree_sha256": "acf4b1719e91b046d9fd543d7c177705e54188e38e5600f3b591631152e4761d", + "svg_count": 4009 + } + }, + "rgi": { + "url": "https://www.unicode.org/Public/17.0.0/emoji/emoji-test.txt", + "sha256": "1d8a944f88d7952f7ef7c5167fef3c67995bcae24543949710231b03a201acda" + } +}