8
8
'../Core/defineProperties' ,
9
9
'../Core/DeveloperError' ,
10
10
'../Core/DistanceDisplayCondition' ,
11
+ '../Core/freezeObject' ,
11
12
'../Core/NearFarScalar' ,
12
13
'./Billboard' ,
13
14
'./HeightReference' ,
@@ -24,6 +25,7 @@ define([
24
25
defineProperties ,
25
26
DeveloperError ,
26
27
DistanceDisplayCondition ,
28
+ freezeObject ,
27
29
NearFarScalar ,
28
30
Billboard ,
29
31
HeightReference ,
@@ -32,6 +34,13 @@ define([
32
34
VerticalOrigin ) {
33
35
'use strict' ;
34
36
37
+ var textTypes = freezeObject ( {
38
+ LTR : 0 ,
39
+ RTL : 1 ,
40
+ WEAK : 2 ,
41
+ BRACKETS : 3
42
+ } ) ;
43
+
35
44
function rebindAllGlyphs ( label ) {
36
45
if ( ! label . _rebindAllGlyphs && ! label . _repositionAllGlyphs ) {
37
46
// only push label if it's not already been marked dirty
@@ -110,7 +119,8 @@ define([
110
119
distanceDisplayCondition = DistanceDisplayCondition . clone ( distanceDisplayCondition ) ;
111
120
}
112
121
113
- this . _text = defaultValue ( options . text , '' ) ;
122
+ this . _renderedText = undefined ;
123
+ this . _text = undefined ;
114
124
this . _show = defaultValue ( options . show , true ) ;
115
125
this . _font = defaultValue ( options . font , '30px sans-serif' ) ;
116
126
this . _fillColor = Color . clone ( defaultValue ( options . fillColor , Color . WHITE ) ) ;
@@ -147,6 +157,8 @@ define([
147
157
148
158
this . _clusterShow = true ;
149
159
160
+ this . text = defaultValue ( options . text , '' ) ;
161
+
150
162
this . _updateClamping ( ) ;
151
163
}
152
164
@@ -281,6 +293,7 @@ define([
281
293
282
294
if ( this . _text !== value ) {
283
295
this . _text = value ;
296
+ this . _renderedText = Label . enableRightToLeftDetection ? reverseRtl ( value ) : value ;
284
297
rebindAllGlyphs ( this ) ;
285
298
}
286
299
}
@@ -1167,7 +1180,7 @@ define([
1167
1180
this . _verticalOrigin === other . _verticalOrigin &&
1168
1181
this . _horizontalOrigin === other . _horizontalOrigin &&
1169
1182
this . _heightReference === other . _heightReference &&
1170
- this . _text === other . _text &&
1183
+ this . _renderedText === other . _renderedText &&
1171
1184
this . _font === other . _font &&
1172
1185
Cartesian3 . equals ( this . _position , other . _position ) &&
1173
1186
Color . equals ( this . _fillColor , other . _fillColor ) &&
@@ -1196,5 +1209,202 @@ define([
1196
1209
return false ;
1197
1210
} ;
1198
1211
1212
+ /**
1213
+ * Determines whether or not run the algorithm, that match the text of the label to right-to-left languages
1214
+ * @memberof Label
1215
+ * @type {Boolean }
1216
+ * @default false
1217
+ *
1218
+ * @example
1219
+ * // Example 1.
1220
+ * // Set a label's rightToLeft before init
1221
+ * Cesium.Label.enableRightToLeftDetection = true;
1222
+ * var myLabelEntity = viewer.entities.add({
1223
+ * label: {
1224
+ * id: 'my label',
1225
+ * text: 'זה טקסט בעברית \n ועכשיו יורדים שורה',
1226
+ * }
1227
+ * });
1228
+ *
1229
+ * @example
1230
+ * // Example 2.
1231
+ * var myLabelEntity = viewer.entities.add({
1232
+ * label: {
1233
+ * id: 'my label',
1234
+ * text: 'English text'
1235
+ * }
1236
+ * });
1237
+ * // Set a label's rightToLeft after init
1238
+ * Cesium.Label.enableRightToLeftDetection = true;
1239
+ * myLabelEntity.text = 'טקסט חדש';
1240
+ */
1241
+ Label . enableRightToLeftDetection = false ;
1242
+
1243
+ function convertTextToTypes ( text , rtlChars ) {
1244
+ var ltrChars = / [ a - z A - Z 0 - 9 ] / ;
1245
+ var bracketsChars = / [ ( ) [ \] { } < > ] / ;
1246
+ var parsedText = [ ] ;
1247
+ var word = '' ;
1248
+ var lastType = textTypes . LTR ;
1249
+ var currentType = '' ;
1250
+ var textLength = text . length ;
1251
+ for ( var textIndex = 0 ; textIndex < textLength ; ++ textIndex ) {
1252
+ var character = text . charAt ( textIndex ) ;
1253
+ if ( rtlChars . test ( character ) ) {
1254
+ currentType = textTypes . RTL ;
1255
+ }
1256
+ else if ( ltrChars . test ( character ) ) {
1257
+ currentType = textTypes . LTR ;
1258
+ }
1259
+ else if ( bracketsChars . test ( character ) ) {
1260
+ currentType = textTypes . BRACKETS ;
1261
+ }
1262
+ else {
1263
+ currentType = textTypes . WEAK ;
1264
+ }
1265
+
1266
+ if ( textIndex === 0 ) {
1267
+ lastType = currentType ;
1268
+ }
1269
+
1270
+ if ( lastType === currentType && currentType !== textTypes . BRACKETS ) {
1271
+ word += character ;
1272
+ }
1273
+ else {
1274
+ if ( word !== '' ) {
1275
+ parsedText . push ( { Type : lastType , Word : word } ) ;
1276
+ }
1277
+ lastType = currentType ;
1278
+ word = character ;
1279
+ }
1280
+ }
1281
+ parsedText . push ( { Type : currentType , Word : word } ) ;
1282
+ return parsedText ;
1283
+ }
1284
+
1285
+ function reverseWord ( word ) {
1286
+ return word . split ( '' ) . reverse ( ) . join ( '' ) ;
1287
+ }
1288
+
1289
+ function spliceWord ( result , pointer , word ) {
1290
+ return result . slice ( 0 , pointer ) + word + result . slice ( pointer ) ;
1291
+ }
1292
+
1293
+ function reverseBrackets ( bracket ) {
1294
+ switch ( bracket ) {
1295
+ case '(' :
1296
+ return ')' ;
1297
+ case ')' :
1298
+ return '(' ;
1299
+ case '[' :
1300
+ return ']' ;
1301
+ case ']' :
1302
+ return '[' ;
1303
+ case '{' :
1304
+ return '}' ;
1305
+ case '}' :
1306
+ return '{' ;
1307
+ case '<' :
1308
+ return '>' ;
1309
+ case '>' :
1310
+ return '<' ;
1311
+ }
1312
+ }
1313
+
1314
+ /**
1315
+ *
1316
+ * @param {String } value the text to parse and reorder
1317
+ * @returns {String } the text as rightToLeft direction
1318
+ * @private
1319
+ */
1320
+ function reverseRtl ( value ) {
1321
+ var rtlChars = / [ \u05D0 - \u05EA ] / ;
1322
+ var texts = value . split ( '\n' ) ;
1323
+ var result = '' ;
1324
+ for ( var i = 0 ; i < texts . length ; i ++ ) {
1325
+ var text = texts [ i ] ;
1326
+ var rtlDir = rtlChars . test ( text . charAt ( 0 ) ) ;
1327
+ var parsedText = convertTextToTypes ( text , rtlChars ) ;
1328
+
1329
+ var splicePointer = 0 ;
1330
+ var line = '' ;
1331
+ for ( var wordIndex = 0 ; wordIndex < parsedText . length ; ++ wordIndex ) {
1332
+ var subText = parsedText [ wordIndex ] ;
1333
+ var reverse = subText . Type === textTypes . BRACKETS ? reverseBrackets ( subText . Word ) : subText . Word ;
1334
+ if ( rtlDir ) {
1335
+ if ( subText . Type === textTypes . RTL ) {
1336
+ line = reverseWord ( subText . Word ) + line ;
1337
+ splicePointer = 0 ;
1338
+ }
1339
+ else if ( subText . Type === textTypes . LTR ) {
1340
+ line = spliceWord ( line , splicePointer , subText . Word ) ;
1341
+ splicePointer += subText . Word . length ;
1342
+ }
1343
+ else if ( subText . Type === textTypes . WEAK || subText . Type === textTypes . BRACKETS ) {
1344
+ if ( subText . Type === textTypes . WEAK && parsedText [ wordIndex - 1 ] . Type === textTypes . BRACKETS ) {
1345
+ line = reverseWord ( subText . Word ) + line ;
1346
+ }
1347
+ else if ( parsedText [ wordIndex - 1 ] . Type === textTypes . RTL ) {
1348
+ line = reverse + line ;
1349
+ splicePointer = 0 ;
1350
+ }
1351
+ else if ( parsedText . length > wordIndex + 1 ) {
1352
+ if ( parsedText [ wordIndex + 1 ] . Type === textTypes . RTL ) {
1353
+ line = reverse + line ;
1354
+ splicePointer = 0 ;
1355
+ }
1356
+ else {
1357
+ line = spliceWord ( line , splicePointer , subText . Word ) ;
1358
+ splicePointer += subText . Word . length ;
1359
+ }
1360
+ }
1361
+ else {
1362
+ line = spliceWord ( line , 0 , reverse ) ;
1363
+ }
1364
+ }
1365
+ }
1366
+ else if ( subText . Type === textTypes . RTL ) {
1367
+ line = spliceWord ( line , splicePointer , reverseWord ( subText . Word ) ) ;
1368
+ }
1369
+ else if ( subText . Type === textTypes . LTR ) {
1370
+ line += subText . Word ;
1371
+ splicePointer = line . length ;
1372
+ }
1373
+ else if ( subText . Type === textTypes . WEAK || subText . Type === textTypes . BRACKETS ) {
1374
+ if ( wordIndex > 0 ) {
1375
+ if ( parsedText [ wordIndex - 1 ] . Type === textTypes . RTL ) {
1376
+ if ( parsedText . length > wordIndex + 1 ) {
1377
+ if ( parsedText [ wordIndex + 1 ] . Type === textTypes . RTL ) {
1378
+ line = spliceWord ( line , splicePointer , reverse ) ;
1379
+ }
1380
+ else {
1381
+ line += subText . Word ;
1382
+ splicePointer = line . length ;
1383
+ }
1384
+ }
1385
+ else {
1386
+ line += subText . Word ;
1387
+ }
1388
+ }
1389
+ else {
1390
+ line += subText . Word ;
1391
+ splicePointer = line . length ;
1392
+ }
1393
+ }
1394
+ else {
1395
+ line += subText . Word ;
1396
+ splicePointer = line . length ;
1397
+ }
1398
+ }
1399
+ }
1400
+
1401
+ result += line ;
1402
+ if ( i < texts . length - 1 ) {
1403
+ result += '\n' ;
1404
+ }
1405
+ }
1406
+ return result ;
1407
+ }
1408
+
1199
1409
return Label ;
1200
1410
} ) ;
0 commit comments