|
117 | 117 | /** |
118 | 118 | * Checks if two sets of Emoji characters render the same visually. |
119 | 119 | * |
| 120 | + * This is used to determine if the browser is rendering an emoji with multiple data points |
| 121 | + * correctly. set1 is the emoji in the correct form, using a zero-width joiner. set2 is the emoji |
| 122 | + * in the incorrect form, using a zero-width space. If the two sets render the same, then the browser |
| 123 | + * does not support the emoji correctly. |
| 124 | + * |
120 | 125 | * This function may be serialized to run in a Worker. Therefore, it cannot refer to variables from the containing |
121 | 126 | * scope. Everything must be passed by parameters. |
122 | 127 | * |
|
160 | 165 | } ); |
161 | 166 | } |
162 | 167 |
|
| 168 | + /** |
| 169 | + * Checks if the center point of a single emoji is empty. |
| 170 | + * |
| 171 | + * This is used to determine if the browser is rendering an emoji with a single data point |
| 172 | + * correctly. The center point of an incorrectly rendered emoji will be empty. A correctly |
| 173 | + * rendered emoji will have a non-zero value at the center point. |
| 174 | + * |
| 175 | + * This function may be serialized to run in a Worker. Therefore, it cannot refer to variables from the containing |
| 176 | + * scope. Everything must be passed by parameters. |
| 177 | + * |
| 178 | + * @since 6.8.2 |
| 179 | + * |
| 180 | + * @private |
| 181 | + * |
| 182 | + * @param {CanvasRenderingContext2D} context 2D Context. |
| 183 | + * @param {string} emoji Emoji to test. |
| 184 | + * |
| 185 | + * @return {boolean} True if the center point is empty. |
| 186 | + */ |
| 187 | + function emojiRendersEmptyCenterPoint( context, emoji ) { |
| 188 | + // Cleanup from previous test. |
| 189 | + context.clearRect( 0, 0, context.canvas.width, context.canvas.height ); |
| 190 | + context.fillText( emoji, 0, 0 ); |
| 191 | + |
| 192 | + // Test if the center point (16, 16) is empty (0,0,0,0). |
| 193 | + var centerPoint = context.getImageData(16, 16, 1, 1); |
| 194 | + for ( var i = 0; i < centerPoint.data.length; i++ ) { |
| 195 | + if ( centerPoint.data[ i ] !== 0 ) { |
| 196 | + // Stop checking the moment it's known not to be empty. |
| 197 | + return false; |
| 198 | + } |
| 199 | + } |
| 200 | + |
| 201 | + return true; |
| 202 | + } |
| 203 | + |
163 | 204 | /** |
164 | 205 | * Determines if the browser properly renders Emoji that Twemoji can supplement. |
165 | 206 | * |
|
173 | 214 | * @param {CanvasRenderingContext2D} context 2D Context. |
174 | 215 | * @param {string} type Whether to test for support of "flag" or "emoji". |
175 | 216 | * @param {Function} emojiSetsRenderIdentically Reference to emojiSetsRenderIdentically function, needed due to minification. |
| 217 | + * @param {Function} emojiRendersEmptyCenterPoint Reference to emojiRendersEmptyCenterPoint function, needed due to minification. |
176 | 218 | * |
177 | 219 | * @return {boolean} True if the browser can render emoji, false if it cannot. |
178 | 220 | */ |
179 | | - function browserSupportsEmoji( context, type, emojiSetsRenderIdentically ) { |
| 221 | + function browserSupportsEmoji( context, type, emojiSetsRenderIdentically, emojiRendersEmptyCenterPoint ) { |
180 | 222 | var isIdentical; |
181 | 223 |
|
182 | 224 | switch ( type ) { |
|
198 | 240 | } |
199 | 241 |
|
200 | 242 | /* |
201 | | - * Test for UN flag compatibility. This is the least supported of the letter locale flags, |
| 243 | + * Test for Sark flag compatibility. This is the least supported of the letter locale flags, |
202 | 244 | * so gives us an easy test for full support. |
203 | 245 | * |
204 | 246 | * To test for support, we try to render it, and compare the rendering to how it would look if |
205 | | - * the browser doesn't render it correctly ([U] + [N]). |
| 247 | + * the browser doesn't render it correctly ([C] + [Q]). |
206 | 248 | */ |
207 | 249 | isIdentical = emojiSetsRenderIdentically( |
208 | 250 | context, |
209 | | - '\uD83C\uDDFA\uD83C\uDDF3', // as the sequence of two code points |
210 | | - '\uD83C\uDDFA\u200B\uD83C\uDDF3' // as the two code points separated by a zero-width space |
| 251 | + '\uD83C\uDDE8\uD83C\uDDF6', // as the sequence of two code points |
| 252 | + '\uD83C\uDDE8\u200B\uD83C\uDDF6' // as the two code points separated by a zero-width space |
211 | 253 | ); |
212 | 254 |
|
213 | 255 | if ( isIdentical ) { |
|
232 | 274 | return ! isIdentical; |
233 | 275 | case 'emoji': |
234 | 276 | /* |
235 | | - * Rise Like a Phoenix. |
| 277 | + * Does Emoji 16.0 cause the browser to go splat? |
236 | 278 | * |
237 | | - * To test for Emoji 15.1 support, try to render a new emoji: Phoenix. |
| 279 | + * To test for Emoji 16.0 support, try to render a new emoji: Splatter. |
238 | 280 | * |
239 | | - * A phoenix, a mythical immortal bird with flame-like feathers found in the folklore of many global |
240 | | - * cultures. Often used to symbolize renewal or rebirth. |
| 281 | + * The splatter emoji is a single code point emoji. Testing for browser support |
| 282 | + * required testing the center point of the emoji to see if it is empty. |
241 | 283 | * |
242 | | - * The Phoenix emoji is a ZWJ sequence combining 🐦 Bird, Zero Width Joiner and 🔥 Fire. |
243 | | - * These display as a single emoji on supported platforms. |
| 284 | + * 0xD83E 0xDEDF (\uD83E\uDEDF) == Splatter. |
244 | 285 | * |
245 | | - * 0xD83D 0xDC26 (\uD83D\uDC26) == 🐦 Bird |
246 | | - * 0x200D == Zero-Width Joiner (ZWJ) that links the code points for the new emoji or |
247 | | - * 0x200B == Zero-Width Space (ZWS) that is rendered for clients not supporting the new emoji. |
248 | | - * 0xD83D 0xDD25 (\uD83D\uDD25) == 🔥 Fire |
249 | | - * |
250 | | - * When updating this test for future Emoji releases, ensure that individual emoji that make up the |
251 | | - * sequence come from older emoji standards. |
| 286 | + * When updating this test, please ensure that the emoji is either a single code point |
| 287 | + * or switch to using the emojiSetsRenderIdentically function and testing with a zero-width |
| 288 | + * joiner vs a zero-width space. |
252 | 289 | */ |
253 | | - isIdentical = emojiSetsRenderIdentically( |
254 | | - context, |
255 | | - '\uD83D\uDC26\u200D\uD83D\uDD25', // as the zero-width joiner sequence |
256 | | - '\uD83D\uDC26\u200B\uD83D\uDD25' // separated by a zero-width space |
257 | | - ); |
258 | | - |
259 | | - return ! isIdentical; |
| 290 | + var notSupported = emojiRendersEmptyCenterPoint( context, '\uD83E\uDEDF' ); |
| 291 | + return ! notSupported; |
260 | 292 | } |
261 | 293 |
|
262 | 294 | return false; |
|
275 | 307 | * @param {string[]} tests Tests. |
276 | 308 | * @param {Function} browserSupportsEmoji Reference to browserSupportsEmoji function, needed due to minification. |
277 | 309 | * @param {Function} emojiSetsRenderIdentically Reference to emojiSetsRenderIdentically function, needed due to minification. |
| 310 | + * @param {Function} emojiRendersEmptyCenterPoint Reference to emojiRendersEmptyCenterPoint function, needed due to minification. |
278 | 311 | * |
279 | 312 | * @return {SupportTests} Support tests. |
280 | 313 | */ |
281 | | - function testEmojiSupports( tests, browserSupportsEmoji, emojiSetsRenderIdentically ) { |
| 314 | + function testEmojiSupports( tests, browserSupportsEmoji, emojiSetsRenderIdentically, emojiRendersEmptyCenterPoint ) { |
282 | 315 | var canvas; |
283 | 316 | if ( |
284 | 317 | typeof WorkerGlobalScope !== 'undefined' && |
|
301 | 334 |
|
302 | 335 | var supports = {}; |
303 | 336 | tests.forEach( function ( test ) { |
304 | | - supports[ test ] = browserSupportsEmoji( context, test, emojiSetsRenderIdentically ); |
| 337 | + supports[ test ] = browserSupportsEmoji( context, test, emojiSetsRenderIdentically, emojiRendersEmptyCenterPoint ); |
305 | 338 | } ); |
306 | 339 | return supports; |
307 | 340 | } |
|
354 | 387 | [ |
355 | 388 | JSON.stringify( tests ), |
356 | 389 | browserSupportsEmoji.toString(), |
357 | | - emojiSetsRenderIdentically.toString() |
| 390 | + emojiSetsRenderIdentically.toString(), |
| 391 | + emojiRendersEmptyCenterPoint.toString() |
358 | 392 | ].join( ',' ) + |
359 | 393 | '));'; |
360 | 394 | var blob = new Blob( [ workerScript ], { |
|
371 | 405 | } catch ( e ) {} |
372 | 406 | } |
373 | 407 |
|
374 | | - supportTests = testEmojiSupports( tests, browserSupportsEmoji, emojiSetsRenderIdentically ); |
| 408 | + supportTests = testEmojiSupports( tests, browserSupportsEmoji, emojiSetsRenderIdentically, emojiRendersEmptyCenterPoint ); |
375 | 409 | setSessionSupportTests( supportTests ); |
376 | 410 | resolve( supportTests ); |
377 | 411 | } ) |
|
0 commit comments