Xiaoxiangquan has uploaded a new change for review.
https://gerrit.wikimedia.org/r/153375
Change subject: Detect tofu with the specified font family, and display popup
when click the tofu
......................................................................
Detect tofu with the specified font family, and display popup when click the
tofu
Change-Id: I6f7461a34133e7350a7585bd2a955a7be1b06adc
---
M Resources.php
A resources/css/ext.uls.webfonts.tofu.css
M resources/js/ext.uls.webfonts.js
A resources/js/ext.uls.webfonts.tofu.js
4 files changed, 239 insertions(+), 1 deletion(-)
git pull
ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/UniversalLanguageSelector
refs/changes/75/153375/1
diff --git a/Resources.php b/Resources.php
index d0a2b79..3220fae 100644
--- a/Resources.php
+++ b/Resources.php
@@ -158,11 +158,20 @@
),
) + $resourcePaths;
+$wgResourceModules['ext.uls.webfonts.tofu'] = array(
+ 'scripts' => 'resources/js/ext.uls.webfonts.tofu.js',
+ 'styles' => 'resources/css/ext.uls.webfonts.tofu.css',
+ 'dependencies' => array(
+ 'ext.uls.init',
+ ),
+) + $resourcePaths;
+
$wgResourceModules['ext.uls.webfonts'] = array(
'scripts' => 'resources/js/ext.uls.webfonts.js',
'dependencies' => array(
'ext.uls.init',
'ext.uls.preferences',
+ 'ext.uls.webfonts.tofu',
),
) + $resourcePaths;
diff --git a/resources/css/ext.uls.webfonts.tofu.css
b/resources/css/ext.uls.webfonts.tofu.css
new file mode 100644
index 0000000..99f3b9d
--- /dev/null
+++ b/resources/css/ext.uls.webfonts.tofu.css
@@ -0,0 +1,37 @@
+.tofu_popup {
+ width: 300px;
+ display: block;
+ padding: 1px;
+ position: absolute;
+ border: 1px solid #4c77aa;
+ background: #f2f7fd;
+ z-index: 11;
+ zoom: 1;
+ text-align: left;
+}
+
+.tofu_popup h3 {
+ background: #4c77aa;
+ color: #fff;
+ font-size: 20px;
+ padding: 5px;
+ margin: 0px;
+}
+
+.tofu_popup_content {
+ font-size: 15px;
+ line-height: 20px;
+ float: left;
+ width: 100%;
+ height: 100%;
+}
+
+.tofu_popup_bg {
+ position: absolute;
+ display: block;
+ left: 0;
+ top: 0;
+ background: #000;
+ opacity: 0.3;
+ z-index: 10
+}
diff --git a/resources/js/ext.uls.webfonts.js b/resources/js/ext.uls.webfonts.js
index 9bc30ca..8497dc8 100644
--- a/resources/js/ext.uls.webfonts.js
+++ b/resources/js/ext.uls.webfonts.js
@@ -101,7 +101,7 @@
width[index] = $fixture.width() || width[index-1];
height[index] = $fixture.height();
- if( index > 0 &&
+ if ( index > 0 &&
( width[index] !== width[index - 1] ||
height[index] !== height[index - 1] )
) {
@@ -220,6 +220,11 @@
// will be applied automatically to such future
elements.
$( 'body' ).data( 'webfonts' ).load( 'Autonym' );
}, 0 );
+
+ // run later, to wait for all webfonts downloaded and all chars
rendered
+ setTimeout( function() {
+ mw.webfonts.markTofus();
+ }, 3000 );
};
$( document ).ready( function () {
diff --git a/resources/js/ext.uls.webfonts.tofu.js
b/resources/js/ext.uls.webfonts.tofu.js
new file mode 100644
index 0000000..f36c235
--- /dev/null
+++ b/resources/js/ext.uls.webfonts.tofu.js
@@ -0,0 +1,187 @@
+/**
+ * ULS-Webfonts tofu detection and glyph collector binder
+ *
+ * Copyright (C) 2012 Alolita Sharma, Amir Aharoni, Arun Ganesh, Brandon
Harris,
+ * Niklas Laxström, Pau Giner, Santhosh Thottingal, Siebrand Mazeland and other
+ * contributors. See CREDITS for a list.
+ *
+ * UniversalLanguageSelector is dual licensed GPLv2 or later and MIT. You don't
+ * have to do anything special to choose one license or the other and you don't
+ * have to notify anyone which license you are using. You are free to use
+ * UniversalLanguageSelector in commercial projects as long as the copyright
+ * header is left intact. See files GPL-LICENSE and MIT-LICENSE for details.
+ *
+ * @file
+ * @ingroup Extensions
+ * @licence GNU General Public Licence 2.0 or later
+ * @licence MIT License
+ */
+( function ( $, mw ) {
+ 'use strict';
+
+ var tofuSalt = '\u0D00',
+ // cache for tofu images: { fontFamily => tofuImage }
+ tofuImages = {},
+ // cache for tofu detection: { fontFamily => { char =>
isTofuOrNot } }
+ tofuMaps = {};
+
+ mw.webfonts = mw.webfonts || {};
+ /**
+ * Convert a single grapheme to image pixel array
+ *
+ * Draw the character on canvas, and return the image in format: rgba
...
+ * Note that some unicode code units do not form a single, complete
grapheme
+ * (e.g. a surrogate such as \uD800 or a combining character such as
\u0302).
+ * In other cases, the number of graphemes depends on the font (e.g.
Malayalam)
+ *
+ * @param {string} grapheme A string that forms a single grapheme (e.g.
a single Han character)
+ * @return {array}
+ */
+ function charToImage( ch, fontFamily ) {
+ var $canvas, canvasContext;
+
+ // width/height=1+12+1, put the 12px char at center, and leave
1px as
+ // padding. 12px * 12px is large enough to render a Han
character. Some
+ // complex scripts may have wider graphemes formed of many
codepoints,
+ // but then they probably don't also have fixed-width rendering.
+ $canvas = $( '<canvas>' )
+ .prop( {
+ width: 14,
+ height: 14
+ } );
+
+ canvasContext = $canvas[0].getContext( '2d' );
+ canvasContext.font = '12px ' + fontFamily;
+ canvasContext.fillText( ch, 1, 11 );
+
+ return canvasContext
+ .getImageData( 0, 0, $canvas[0].width,
$canvas[0].height )
+ .data;
+ }
+
+ /**
+ * Detect tofu by comparing image pixels
+ *
+ * Create tofu's and every character's images, compare them to see if
any
+ * character is rendered as a tofu.
+ *
+ * TODO: in some non-Han unicode ranges, multiple code
+ * points form a single grapheme (e.g. combining accents, Indian
scripts).
+ * In some cases, the number of graphemes even depends on the font
(e.g. Malayalam).
+ *
+ * @param {string} text Text to detect
+ * @param {string} fontFamily The fontFamily setting
+ * @return {array} Tofus detected in text with the fontFamily setting
+ */
+ function detectTofuByImage( text, fontFamily ) {
+ var charImage, diff, i, j, ch, tofuMap, tofuImage, tofus = [];
+
+ // init and get the tofu map
+ if ( !tofuMaps.hasOwnProperty( fontFamily ) ) {
+ tofuMaps[ fontFamily ] = {};
+ }
+ tofuMap = tofuMaps[ fontFamily ];
+
+ for ( i in text ) {
+ ch = text[i];
+ // skip spaces
+ if ( /\s/.test( ch ) ) {
+ continue;
+ }
+ // cache hitted
+ if ( tofuMap.hasOwnProperty( ch ) ) {
+ if ( tofuMap[ ch ] ) {
+ tofus.push( ch );
+ }
+ continue;
+ }
+
+ // init and get the tofu image
+ if ( !tofuImages.hasOwnProperty( fontFamily ) ) {
+ tofuImages[ fontFamily ] = charToImage(
tofuSalt, fontFamily ); // a known tofu
+ }
+ tofuImage = tofuImages[ fontFamily ];
+
+ // detect by comparing image
+ charImage = charToImage( ch, fontFamily );
+ tofuMap[ ch ] = true;
+ for ( j = 0; j < tofuImage.length; j++ ) {
+ if ( charImage[j] !== tofuImage[j] ) {
+ // different from the tofu image, it's
not a tofu
+ tofuMap[ ch ] = false;
+ break;
+ }
+ }
+
+ // No difference has been found, tofu detected
+ if ( tofuMap[ ch ] ) {
+ tofus.push( ch );
+ }
+ }
+ return tofus;
+ }
+
+ mw.webfonts.showTofuPopup = function( charCode, fontFamily ) {
+ var hexCharCode = '0x' + charCode.toString(16).toUpperCase(),
+ tofuPopupHtml =
+ '<h3>Missing Glyph</h3>'
+ + '<table class="popup_content">'
+ + '<tr><td>Glyph\'s Unicode </td><td>: ' + hexCharCode
+ '</td></tr>'
+ + '<tr><td>Font Family </td><td>: ' + fontFamily +
'</td></tr>'
+ + '</table>';
+
+ // popup background
+ $( '<div>' )
+ .prop( {
+ 'id': 'tofuPopupBg',
+ 'class': 'tofu_popup_bg'
+ } )
+ .css( {
+ 'width': $( window ).width() + "px",
+ 'height': Math.max( $( window ).height(), $(
document ).height() ) + "px"
+ } )
+ .click( function() {
+ $( '.tofu_popup' ).remove();
+ $( this ).remove();
+ } )
+ .appendTo( $( 'body' ) );
+
+ // popup window
+ $( '<div>' )
+ .prop( { 'class': 'tofu_popup' } )
+ .html( tofuPopupHtml )
+ .css( {
+ 'left': ( $( window ).width() - 302 ) / 2 +
"px",
+ 'top': ( $( window ).height() - 302 ) / 2 + "px"
+ } )
+ .appendTo( $( 'body' ) );
+ };
+
+ /**
+ * Search tofus in the DOM tree, and mark it with a link to a popup
window
+ */
+ mw.webfonts.markTofus = function() {
+ var fontFamily, text, tofus, i, $tofuPopup, callback;
+
+ $('#content * :not(:empty)').each( function() {
+ // only process leaves in the tree
+ if ( $(this).children().length > 0 ) {
+ return;
+ }
+ fontFamily = $(this).css('fontFamily');
+ text = $(this).html();
+ tofus = detectTofuByImage( text, fontFamily );
+ for ( i in tofus ) {
+ callback = 'mw.webfonts.showTofuPopup(' +
tofus[i].charCodeAt(0) + ', "' + fontFamily + '")';
+ $tofuPopup = $( '<a>' )
+ .prop( { 'href': 'javascript:' +
callback } )
+ .css( { 'text-decoration': 'underline'
} )
+ .text( tofus[i] );
+ text = text.replace( tofus[i],
$tofuPopup[0].outerHTML );
+ }
+ if ( tofus.length > 0 ) {
+ $(this).html( text );
+ }
+ } );
+ };
+}( jQuery, mediaWiki ) );
--
To view, visit https://gerrit.wikimedia.org/r/153375
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I6f7461a34133e7350a7585bd2a955a7be1b06adc
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/UniversalLanguageSelector
Gerrit-Branch: master
Gerrit-Owner: Xiaoxiangquan <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits