| <!DOCTYPE html> |
| <!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]--> |
| <!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8"> <![endif]--> |
| <!--[if IE 8]> <html class="no-js lt-ie9"> <![endif]--> |
| <!--[if gt IE 8]><!--> <html class="no-js"> <!--<![endif]--><head> |
| <meta charset='utf-8'/><meta http-equiv='X-UA-Compatible' content='IE=edge'/><meta name='viewport' content='width=device-width, initial-scale=1'/><meta name='keywords' content='groovy, emoji'/><meta name='description' content='Season's greetings with some emoji fun.'/><title>The Apache Groovy programming language - Blogs - Season’s Greetings with Emojis</title><link href='../img/favicon.ico' type='image/x-ico' rel='icon'/><link rel='stylesheet' type='text/css' href='../css/bootstrap.css'/><link rel='stylesheet' type='text/css' href='../css/font-awesome.min.css'/><link rel='stylesheet' type='text/css' href='../css/style.css'/><link rel='stylesheet' type='text/css' href='https://cdnjs.cloudflare.com/ajax/libs/prettify/r298/prettify.min.css'/> |
| </head><body> |
| <div id='fork-me'> |
| <a href='https://github.com/apache/groovy'> |
| <img style='position: fixed; top: 20px; right: -58px; border: 0; z-index: 100; transform: rotate(45deg);' src='/img/horizontal-github-ribbon.png'/> |
| </a> |
| </div><div id='st-container' class='st-container st-effect-9'> |
| <nav class='st-menu st-effect-9' id='menu-12'> |
| <h2 class='icon icon-lab'>Socialize</h2><ul> |
| <li> |
| <a href='https://groovy-lang.org/mailing-lists.html' class='icon'><span class='fa fa-envelope'></span> Discuss on the mailing-list</a> |
| </li><li> |
| <a href='https://twitter.com/ApacheGroovy' class='icon'><span class='fa fa-twitter'></span> Groovy on Twitter</a> |
| </li><li> |
| <a href='https://groovy-lang.org/events.html' class='icon'><span class='fa fa-calendar'></span> Events and conferences</a> |
| </li><li> |
| <a href='https://github.com/apache/groovy' class='icon'><span class='fa fa-github'></span> Source code on GitHub</a> |
| </li><li> |
| <a href='https://groovy-lang.org/reporting-issues.html' class='icon'><span class='fa fa-bug'></span> Report issues in Jira</a> |
| </li><li> |
| <a href='http://stackoverflow.com/questions/tagged/groovy' class='icon'><span class='fa fa-stack-overflow'></span> Stack Overflow questions</a> |
| </li><li> |
| <a href='http://groovycommunity.com/' class='icon'><span class='fa fa-slack'></span> Slack Community</a> |
| </li> |
| </ul> |
| </nav><div class='st-pusher'> |
| <div class='st-content'> |
| <div class='st-content-inner'> |
| <!--[if lt IE 7]> |
| <p class="browsehappy">You are using an <strong>outdated</strong> browser. Please <a href="http://browsehappy.com/">upgrade your browser</a> to improve your experience.</p> |
| <![endif]--><div><div class='navbar navbar-default navbar-static-top' role='navigation'> |
| <div class='container'> |
| <div class='navbar-header'> |
| <button type='button' class='navbar-toggle' data-toggle='collapse' data-target='.navbar-collapse'> |
| <span class='sr-only'></span><span class='icon-bar'></span><span class='icon-bar'></span><span class='icon-bar'></span> |
| </button><a class='navbar-brand' href='../index.html'> |
| <i class='fa fa-star'></i> Apache Groovy |
| </a> |
| </div><div class='navbar-collapse collapse'> |
| <ul class='nav navbar-nav navbar-right'> |
| <li class=''><a href='https://groovy-lang.org/learn.html'>Learn</a></li><li class=''><a href='https://groovy-lang.org/documentation.html'>Documentation</a></li><li class=''><a href='/download.html'>Download</a></li><li class=''><a href='https://groovy-lang.org/support.html'>Support</a></li><li class=''><a href='/'>Contribute</a></li><li class=''><a href='https://groovy-lang.org/ecosystem.html'>Ecosystem</a></li><li class=''><a href='/blog'>Blog posts</a></li><li class=''><a href='https://groovy.apache.org/events.html'></a></li><li> |
| <a data-effect='st-effect-9' class='st-trigger' href='#'>Socialize</a> |
| </li><li class=''> |
| <a href='../search.html'> |
| <i class='fa fa-search'></i> |
| </a> |
| </li> |
| </ul> |
| </div> |
| </div> |
| </div><div id='content' class='page-1'><div class='row'><div class='row-fluid'><div class='col-lg-3'><ul class='nav-sidebar'><li><a href='./'>Blog index</a></li><li class='active'><a href='#doc'>Season’s Greetings with Emojis</a></li><li><a href='#_jdk_21_new_features' class='anchor-link'>JDK 21 New Features</a></li><li><a href='#_playing_with_emojis_with_groovy' class='anchor-link'>Playing with Emojis with Groovy</a></li><li><a href='#_more_information' class='anchor-link'>More Information</a></li></ul><br/><ul class='nav-sidebar'><li style='padding: 0.35em 0.625em; background-color: #eee'><span>Related posts</span></li><li><a href='./deep-learning-and-eclipse-collections'>Deep Learning and Eclipse Collections</a></li><li><a href='./zipping-collections-with-groovy'>Zipping Collections with Groovy</a></li><li><a href='./adventures-with-groovyfx'>Adventures with GroovyFX</a></li><li><a href='./helloworldemoji'>Hello World with Emojis</a></li><li><a href='./fruity-eclipse-collections'>Fruity Eclipse Collections</a></li><li><a href='./set-operations-with-groovy'>Set Operators with Groovy</a></li></ul></div><div class='col-lg-8 col-lg-pull-0'><a name='doc'></a><h1>Season’s Greetings with Emojis</h1><p><span>Author: <i>Paul King</i></span><br/><span>Published: 2023-12-23 12:24PM</span></p><hr/><div id="preamble"> |
| <div class="sectionbody"> |
| <div class="paragraph"> |
| <p>In a <a href="https://groovy.apache.org/blog/helloworldemoji">previous blog post</a> |
| we looked at a fun way to write a <em>hello world</em> script using Groovy and Emojis.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Let’s look at some of the additional emoji API calls |
| available in JDK 21. We’re using Groovy 5.0.0-alpha-4, |
| but most of the examples work as is with recent Groovy 4 versions. |
| Groovy 5, adds one shortcut for making it easier to get to code points |
| as an array.</p> |
| </div> |
| </div> |
| </div> |
| <div class="sect1"> |
| <h2 id="_jdk_21_new_features">JDK 21 New Features</h2> |
| <div class="sectionbody"> |
| <div class="paragraph"> |
| <p>As part of <a href="https://bugs.openjdk.org/browse/JDK-8303018">JDK-8303018</a>, JDK 21 adds the following API calls to <code>java.lang.Character</code>:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="prettyprint highlight"><code data-lang="java">public static boolean isEmoji(int codePoint) |
| public static boolean isEmojiPresentation(int codePoint) |
| public static boolean isEmojiModifier(int codePoint) |
| public static boolean isEmojiModifierBase(int codePoint) |
| public static boolean isEmojiComponent(int codePoint) |
| public static boolean isExtendedPictographic(int codePoint)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Also added was equivalent functionality when performing regex matches |
| using the following special binary properties:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><code>\p{IsEmoji}</code></p> |
| </li> |
| <li> |
| <p><code>\p{IsEmoji_Presentation}</code></p> |
| </li> |
| <li> |
| <p><code>\p{IsEmoji_Modifier}</code></p> |
| </li> |
| <li> |
| <p><code>\p{IsEmoji_Modifier_Base}</code></p> |
| </li> |
| <li> |
| <p><code>\p{IsEmoji_Component}</code></p> |
| </li> |
| <li> |
| <p><code>\p{IsExtended_Pictographic}</code></p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>Let’s have a look at using these features from Groovy.</p> |
| </div> |
| </div> |
| </div> |
| <div class="sect1"> |
| <h2 id="_playing_with_emojis_with_groovy">Playing with Emojis with Groovy</h2> |
| <div class="sectionbody"> |
| <div class="paragraph"> |
| <p>First, we’ll have a look at a String containing 3 emojis: |
| a Christmas tree, Mrs Claus, and Santa Claus. |
| We’ll check that the 3 Unicode code points for that String |
| all correspond to emojis using one of the new API calls:</p> |
| </div> |
| <div class="paragraph"> |
| <p><span class="image"><img src="img/emoji1.png" alt="using isEmoji"></span></p> |
| </div> |
| <div class="paragraph"> |
| <p>We can check using the newly added regex binary properties as well. |
| The Groovy regex operator (<code>==~</code>) ensures that the String exactly matches 3 emojis:</p> |
| </div> |
| <div class="paragraph"> |
| <p><span class="image"><img src="img/emoji2.png" alt="using isEmoji"></span></p> |
| </div> |
| <div class="paragraph"> |
| <p>Unicode supports various forms of modification by sequencing Unicode characters. |
| One of the simplest examples is when some "base" emoji character is followed |
| by a skin-tone emoji modifier. The two consecutive characters are re-interpreted, |
| resulting in a single emoji with skin tone.</p> |
| </div> |
| <div class="paragraph"> |
| <p>We’ll see that the Christmas tree cannot be used as an emoji modifier |
| base, but the two Claus emojis can. Also, we can see that all 5 skin |
| tone emoji characters can be used as emoji modifiers:</p> |
| </div> |
| <div class="paragraph"> |
| <p><span class="image"><img src="img/emoji3.png" alt="using isEmoji"></span></p> |
| </div> |
| <div class="paragraph"> |
| <p>Let’s try some combinations. We’ll combine the Santa emoji with |
| some of the skin tones. Depending on your IDE/editor, you’ll probably |
| see a single emoji, but it is made up of multiple Unicode code points.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If we look at the code points from the "single" emoji, |
| it will be the same as the "bare" Santa emoji plus the code points |
| from the skin tone emoji:</p> |
| </div> |
| <div class="paragraph"> |
| <p><span class="image"><img src="img/emoji4.png" alt="using isEmoji"></span></p> |
| </div> |
| <div class="paragraph"> |
| <p>We are also checking the emoji roles using a regex. |
| We can see the base followed by the modifier.</p> |
| </div> |
| <div class="paragraph"> |
| <p>We can put all this together to check all five toned Santas as follows:</p> |
| </div> |
| <div class="paragraph"> |
| <p><span class="image"><img src="img/emoji5.png" alt="using isEmoji"></span></p> |
| </div> |
| <div class="paragraph"> |
| <p>Another sequencing trick offered by Unicode is to combine related |
| emojis to form new ones with an intervening <em>zero width joiner</em> (ZWJ). |
| For example, you might combine the woman emoji, "👩", possibly with |
| an additional skin tone emoji, then a ZWJ character (Unicode 200D in hex), |
| followed by the rocket emoji "🚀", which combined gives |
| a female astronaut emoji "👩🏽🚀".</p> |
| </div> |
| <div class="paragraph"> |
| <p>Unicode has a special Mx Claus emoji which can be used to represent |
| a gender-neutral alternative to Mrs Claus or Santa Claus, or to indicate |
| a person with strong Christmas spirit. It combines the adult emoji, "🧑", |
| the ZWJ character, and the Christmas tree emoji.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Again if we look at the code points, the code points for the "combined" emoji |
| is just the code points of the individual components one after the other, |
| as we see on the first line. The second line shows how to enter the combined |
| emoji using Unicode. The first and last parts are represented as surrogate |
| pairs which are combined into the correct code points automatically.</p> |
| </div> |
| <div class="paragraph"> |
| <p><span class="image"><img src="img/emoji6.png" alt="using isEmoji"></span></p> |
| </div> |
| <div class="paragraph"> |
| <p>The last two lines show checking the combined emoji with regex. |
| We can check the exact Unicode characters using regex’s <code>\x{…​}</code> notation, |
| noting that we don’t use surrogate pairs. We can also check the |
| emoji names using the <code>\N{…​}</code> notation.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Combinations aren’t limited to size two. One of the possible "family" emoji combinations |
| combines 3 emojis, with interleaved ZWJ characters.</p> |
| </div> |
| <div class="paragraph"> |
| <p><span class="image"><img src="img/emoji7.png" alt="using isEmoji"></span></p> |
| </div> |
| <div class="paragraph"> |
| <p>We can do similar regex checks as previously, checking the |
| exact Unicode values or the names.</p> |
| </div> |
| <div class="paragraph"> |
| <p>As a final example, let’s look at the "🙋🏻♀️" emoji. |
| Looking at the first line of code below might lead us to think we have combined |
| three characters, but checking the size shows there are 5 parts to the |
| combined emoji. The first and last emojis are already combinations. |
| The "🙋🏻" emoji combines a base emoji with a skin tone. |
| The "♀️" emoji combines the female sign character "♀" with a special |
| <em>variation selector</em> character, which indicates that the previous character |
| should be treated as an emoji rather than a character.</p> |
| </div> |
| <div class="paragraph"> |
| <p><span class="image"><img src="img/emoji8.png" alt="using isEmoji"></span></p> |
| </div> |
| <div class="paragraph"> |
| <p>We can put the new emoji API calls through their paces by checking |
| various properties for each part of the combined emoji.</p> |
| </div> |
| <div class="paragraph"> |
| <p>We can do similar checks using regex. |
| We can check for an exact match of the Unicode characters exactly, |
| by their emoji names, or by role each part plays as shown below:</p> |
| </div> |
| <div class="paragraph"> |
| <p><span class="image"><img src="img/emoji9.png" alt="using isEmoji"></span></p> |
| </div> |
| <div class="paragraph"> |
| <p>We hope you have enjoyed this little exploration of the |
| new JDK 21 emoji features.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Oh yes, and Season’s greetings everyone 🎄🎅☃️🎁🌟🎉!</p> |
| </div> |
| </div> |
| </div> |
| <div class="sect1"> |
| <h2 id="_more_information">More Information</h2> |
| <div class="sectionbody"> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><a href="https://github.com/paulk-asert/groovy-seasonsgreetings">Source code</a></p> |
| </li> |
| <li> |
| <p><a href="https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/lang/Character.html">JDK 21 JavaDoc for java.lang.Character</a></p> |
| </li> |
| <li> |
| <p><a href="https://www.youtube.com/watch?v=O1oq1sbUnmU">Java 21 Improved Emoji Support 💪 Video</a></p> |
| </li> |
| <li> |
| <p><a href="https://inside.java/2023/11/20/sip089/">Improved Emoji Support in Java 21 - Sip of Java</a></p> |
| </li> |
| </ul> |
| </div> |
| </div> |
| </div></div></div></div></div><footer id='footer'> |
| <div class='row'> |
| <div class='colset-3-footer'> |
| <div class='col-1'> |
| <h1>Groovy</h1><ul> |
| <li><a href='https://groovy-lang.org/learn.html'>Learn</a></li><li><a href='https://groovy-lang.org/documentation.html'>Documentation</a></li><li><a href='/download.html'>Download</a></li><li><a href='https://groovy-lang.org/support.html'>Support</a></li><li><a href='/'>Contribute</a></li><li><a href='https://groovy-lang.org/ecosystem.html'>Ecosystem</a></li><li><a href='/blog'>Blog posts</a></li><li><a href='https://groovy.apache.org/events.html'></a></li> |
| </ul> |
| </div><div class='col-2'> |
| <h1>About</h1><ul> |
| <li><a href='https://github.com/apache/groovy'>Source code</a></li><li><a href='https://groovy-lang.org/security.html'>Security</a></li><li><a href='https://groovy-lang.org/learn.html#books'>Books</a></li><li><a href='https://groovy-lang.org/thanks.html'>Thanks</a></li><li><a href='http://www.apache.org/foundation/sponsorship.html'>Sponsorship</a></li><li><a href='https://groovy-lang.org/faq.html'>FAQ</a></li><li><a href='https://groovy-lang.org/search.html'>Search</a></li> |
| </ul> |
| </div><div class='col-3'> |
| <h1>Socialize</h1><ul> |
| <li><a href='https://groovy-lang.org/mailing-lists.html'>Discuss on the mailing-list</a></li><li><a href='https://twitter.com/ApacheGroovy'>Groovy on Twitter</a></li><li><a href='https://groovy-lang.org/events.html'>Events and conferences</a></li><li><a href='https://github.com/apache/groovy'>Source code on GitHub</a></li><li><a href='https://groovy-lang.org/reporting-issues.html'>Report issues in Jira</a></li><li><a href='http://stackoverflow.com/questions/tagged/groovy'>Stack Overflow questions</a></li><li><a href='http://groovycommunity.com/'>Slack Community</a></li> |
| </ul> |
| </div><div class='col-right'> |
| <p> |
| The Groovy programming language is supported by the <a href='http://www.apache.org'>Apache Software Foundation</a> and the Groovy community. |
| </p><div text-align='right'> |
| <img src='../img/asf_logo.png' title='The Apache Software Foundation' alt='The Apache Software Foundation' style='width:60%'/> |
| </div><p>Apache® and the Apache feather logo are either registered trademarks or trademarks of The Apache Software Foundation.</p> |
| </div> |
| </div><div class='clearfix'>© 2003-2024 the Apache Groovy project — Groovy is Open Source: <a href='http://www.apache.org/licenses/LICENSE-2.0.html' alt='Apache 2 License'>license</a>, <a href='https://privacy.apache.org/policies/privacy-policy-public.html'>privacy policy</a>.</div> |
| </div> |
| </footer></div> |
| </div> |
| </div> |
| </div> |
| </div><script src='../js/vendor/jquery-1.10.2.min.js' defer></script><script src='../js/vendor/classie.js' defer></script><script src='../js/vendor/bootstrap.js' defer></script><script src='../js/vendor/sidebarEffects.js' defer></script><script src='../js/vendor/modernizr-2.6.2.min.js' defer></script><script src='../js/plugins.js' defer></script><script src='https://cdnjs.cloudflare.com/ajax/libs/prettify/r298/prettify.min.js'></script><script>document.addEventListener('DOMContentLoaded',prettyPrint)</script><script> |
| (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ |
| (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), |
| m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) |
| })(window,document,'script','//www.google-analytics.com/analytics.js','ga'); |
| |
| ga('create', 'UA-257558-10', 'auto'); |
| ga('send', 'pageview'); |
| </script> |
| </body></html> |