XyText-UTF8

Scripting tools to allow display of text on a prim: XyText 1.5 , XyzzyText, XyyyyzText, XyText-UTF8, XyzzyText-UTF8, ZZText, VariText
== Introduction ==
After some years of using XyzzyText I eventually got convinced that Xyzzy is really slow compared to xytext solutions. Probably a bit less lag, but when used in lessons people clearly noticed the filling up of lines terribly slow. So I backported my utf8 experience to XyText.
Also I noticed that whenever I needed to adapt xyXXXX to a new character set or encoding or if wanting to change the parameters for slicing, gridding, offsetting and finding the UTF8 counterpart in the internal lists was really difficult.
This is why here I'm proposing new parametrized CELL using 5 chars able to be driven by external main script.
If you want to have a quick start on using this you should get inworld the device so that you can have all the scripts already in place in a prebuilt 10 rows * 40 characters board.
https://marketplace.secondlife.com/p/xyutf82010/4275140
== Variations using new SetLinkParametersFast (new server 1.38) ==
After April 2010, it is now much more easy to produce a board using a very limited amount of scripts and having good performances.
If you want to have a notecard and some pre-built samples with instructions on how to produce a xyText-UTF8 board easily, please refer here https://marketplace.secondlife.com/p/xyutf82010/4275140
Here the notecard:
XyUTF8 new usage
You can use this in various modalities:
0. Be sure to have an empty shell with proper cells set up and numbered so that first line is 1000-100x
and title line is made by cells starting from 20000-􀀀
1. Very simple one.
Just put this script in your board 􀀁
You can add your program at the end of the simple one
default
{
 state_entry()
 {
 XY_init(0,0);
 XY_write(0,"hello line #0");
 }
 
} 
2. If you like linked messages you can use the slightly more complex script 􀀂,
and add your own script this way:
default
{
 state_entry()
 {
 // 0=row where to write 0 first one, 19 is the title
 // ^ this is what to write
 // this needed to be sure only xytext will answer
 llMessageLinked(LINK_SET,0,"first line","xytext");
 }
}
NB: Use 
as a new script
3. If you have many lines and you want to improve performance you might need to add multiple 􀀃 scripts, being sure to rename them with trailing -start.end such as
xyutf8 2010-0.3 (script dealing with writing on the 0 1 2 3 rows)
xyutf8 2010-4.7 (script dealing with writing on the 4 5 6 7 rows)
xyutf8 2010-8.19 (script dealing with writing on the 8 9 19 title rows)
to have load distributed over various slaves so to improve net performance.
Click here for a dissertation on what UTF8 is, why is needed to display special characters and how to produce new UTF8 chars with a python script for OpenSource product Gimp: XyText-UTF8 Gimp Texture Creation
== The super parametrizable cell ==
This cell has the following interesting characteristics:
* It names itself after the object name number ("1000" for instance) this can be a bit unconvenient, but is a compromise among the linking order of standard xytext and the xyzzytext-m-n. You can find a way to rename all the linked object automagically ;)
=== Setting parameters and texture ===
* It can receive in one shot the configuration of the texture and all parameters:
<lsl>
 llMessageLinked(LINK_SET, 204005, 
 llList2CSV( [ 
 10, // knum number of characters per row
 <-0.44,0.1,0>, // offset multiplier for cols
 <0.422,-0.05,0>, // offset multiplier for rows
 
 // change the first two in each row to change multiplier for zooming chars
 <0.15, 0.05, 0>,
 <0.06, 0.05, 0>, 
 <-0.86, 0.05, 0>,
 <0.06, 0.05, 0>, 
 <0.15, 0.05, 0>, 
 
 // change the first two x and y in each row to "move characters along x,y axis
 <0.035, 0, 0>,
 <-0.012,0,0>,
 <-0.298, 0, 0>,
 <-0.012,0,0>,
 <-0.055, 0, 0>
 ]), "db6664f6-057f-becf-bb1e-924255c2c7fd");
 
</lsl>
=== Setting the UTF8 decode table ===
* It can be instructed on the listing of decode table to understand with a simple message like this:
<lsl>
decode = [ "%C3%A8", "%C2%A1", ..... ];
llMessageLinked(LINK_SET, 204006, llList2CSV(decode),NULL_KEY);
</lsl>
for instance a complete settings for portuguese can be:
Note that this list MUST match that used producing the texture in python-fu as described before!!
<lsl>
 // special UTF-8 chars for European languages
 // these 80 chars correspond to the following chars in CP850 codepage: (some are not viewable in editor)
 
 // Ç ü é â ä à å ç ê ë
 decode= [ "%C3%87", "%C3%BC", "%C3%A9", "%C3%A2", "%C3%A4", "%C3%A0", "%C3%A5", "%C3%A7", "%C3%AA", "%C3%AB",
 // è ï î ì Ä Å É æ Æ BLACK RIGHT-POINTING TRIANGLE
 "%C3%A8", "%C3%AF", "%C3%AE", "%C3%AC", "%C3%84", "%C3%85", "%C3%89", "%C3%A6", "%C3%AE", "%E2%96%B6",
 // ö ò û ù ÿ Ö Ü ¢ £ ¥
 "%C3%B6", "%C3%B2", "%C3%BB", "%C3%B9", "%C3%BF", "%C3%96", "%C3%9C", "%C2%A2", "%C2%A3", "%C2%A5",
 // A^ copyright á í ó ú ñ Ñ ª º"
 "%C3%82", "%C2%A9", "%C3%A1", "%C3%AD", "%C3%B3", "%C3%BA", "%C3%B1", "%C3%91", "%C2%AA", "%C2%BA",
 // ¿ O^ ¬ ½ ¼ ¡ « » alfa ß"
 "%C2%BF", "%C3%94", "%C2%AC", "%C2%BD", "%C2%BC", "%C2%A1", "%C2%AB", "%C2%BB", "%CE%B1", "%C3%9F",
 // gamma pi bigsigma smsigma mu 
 "%CE%93", "%CF%80", "%CE%A3", "%CF%83", "%C2%B5" ];
 
 // tau BIGfi theta omega delta 
 decode=(decode=[])+decode+ [ "%CF%84", "%CE%A6", "%CE%98", "%CE%A9", "%CE%B4",
 // Uu uu EPS INTERS 3bars +- <= >= INTEGRUP INTEGRDOWN
 "%C5%AC", "%C5%AD", "%CE%B5", "%E2%88%A9", "%E2%89%A1", "%C2%B1", "%E2%89%A5", "%E2%89%A4", "%E2%8C%A0", "%E2%8C%A1",
 // A/ A\ a~ A~ E^ I/ O/ o~ O~ o^
 "%C3%81", "%C3%80", "%C3%A3", "%C3%83", "%C3%8A", "%C3%8D", "%C3%93", "%C3%B5", "%C3%95", "%C3%B4" ];
</lsl>
=== The cell code ===
<lsl>
////////////////////////////////////////////
// XyText v1.2 Script (5 Face, Single Texture)
// Simplified Esperanto version
//
// Written by Xylor Baysklef
//
// Modified by Kermitt Quirk 19/01/2006
// To add support for 5 face prim instead of 3
//
// Modified by Salahzar Stenvaag to show International UTF8 chars
// May 2009
// With easily personalization for each language
//
////////////////////////////////////////////
/////////////// CONSTANTS ///////////////////
// XyText Message Map.
integer SET_PARAMS = 204005;
// set params is a CSV value including the following:
// # is 1..5 knum, kcol<v>, krow<v>, kmul#<v*5>, koff#<v*5>, and in id=gFontTexture
integer SET_DECODE = 204006;
integer SET_COLOR = 204007;
// This is an extended character escape sequence.
string ESCAPE_SEQUENCE = "\\e";
// This is used to get an index for the extended character.
string EXTENDED_INDEX = "12345";
// Face numbers.
integer FACE_1 = 3;
integer FACE_2 = 7;
integer FACE_3 = 4;
integer FACE_4 = 6;
integer FACE_5 = 1;
// number of characters for each "line" in texture
integer knum=10;
// adjusting offset + multipliers for columns and rows
vector kcol=<-0.445,0.1,0>; // offset + multiplier for cols
vector krow=<0.422,-0.05,0>; // offset + multiplier for rows
// texture resizing for each face
vector kmul1=<0.15, 0.05, 0>; // multiplicator for 1st char
vector kmul2=<0.06, 0.05, 0>; // multiplicator for 2nd char
vector kmul3=<-0.86, 0.05, 0>; // central char
vector kmul4=<0.06, 0.05, 0>;
vector kmul5=<0.15, 0.05, 0>;
// offset for each face
vector koff1=<0.045, 0, 0>; 
vector koff2=<0,0,0>;
vector koff3=<-0.284, 0, 0>;
vector koff4=<0,0,0>;
vector koff5=<-0.046, 0, 0>;
list decode; integer ME;
// Used to hide the text after a fade-out.
key TRANSPARENT = "701917a8-d614-471f-13dd-5f4644e36e3c";
///////////// END CONSTANTS ////////////////
///////////// GLOBAL VARIABLES ///////////////
// This is the key of the font we are displaying.
key gFontTexture = "ce614b28-e80e-5731-3aca-c23dca1b3b70";
// All displayable characters. Default to ASCII order.
string gCharIndex;
// This is the channel to listen on while acting
// as a cell in a larger display.
integer gCellChannel = -1;
// This is the starting character position in the cell channel message
// to render.
integer gCellCharPosition = 0;
// This is whether or not to use the fade in/out special effect.
integer gCellUseFading = FALSE;
// This is how long to display the text before fading out (if using
// fading special effect).
// Note: < 0 means don't fade out.
float gCellHoldDelay = 1.0;
/////////// END GLOBAL VARIABLES ////////////
ResetCharIndex() { ’
 gCharIndex = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`";
 gCharIndex += "abcdefghijklmnopqrstuvwxyz{|}~\n\n\n\n\n";
 decode=[];
 
}
vector GetGridOffset(integer index) {
 // Calculate the offset needed to display this character.
 integer Row = index / knum - 1;
 integer Col = index % knum;
 // Return the offset in the texture.
 return < kcol.x + kcol.y * Col, krow.x + krow.y * Row, 0.0>;
} 
ShowChars(vector grid_offset1, vector grid_offset2, vector grid_offset3, vector grid_offset4, vector grid_offset5) {
 // Set the primitive textures directly.
 
 llSetPrimitiveParams( [
 PRIM_TEXTURE, FACE_1, (string)gFontTexture, kmul1, grid_offset1 + koff1, 0.0,
 PRIM_TEXTURE, FACE_2, (string)gFontTexture, kmul2, grid_offset2 + koff2, 0.0,
 PRIM_TEXTURE, FACE_3, (string)gFontTexture, kmul3, grid_offset3 + koff3, 0.0,
 PRIM_TEXTURE, FACE_4, (string)gFontTexture, kmul4, grid_offset4 + koff4, 0.0,
 PRIM_TEXTURE, FACE_5, (string)gFontTexture, kmul5, grid_offset5 + koff5, 0.0
 ]);
}
// SALAHZAR intelligent procedure to extract UTF-8 codes and convert to index in our "cp850"-like table
integer GetIndex(string char)
{
 integer ret=llSubStringIndex(gCharIndex, char);
 //llSay(0,"pos: "+(string)ret);
 if(ret>=0) return ret;
 
 // special char do nice trick :)
 string escaped=llEscapeURL(char);
 //llSay(0,"char: "+escaped);
 integer found=llListFindList(decode, [escaped]);
 
 // Return blank if not found
 if(found<0) return 0;
 
 // return correct index
 return 100+found;
 
}
// END SALAHZAR
 
 
RenderString(string str) { 
 // Get the grid positions for each pair of characters. 
 vector GridOffset1 = GetGridOffset( GetIndex(llGetSubString(str, 0, 0)) ); // SALAHZAR intermediate function
 vector GridOffset2 = GetGridOffset( GetIndex(llGetSubString(str, 1, 1)) ); // SALAHZAR
 vector GridOffset3 = GetGridOffset( GetIndex(llGetSubString(str, 2, 2)) ); // SALAHZAR
 vector GridOffset4 = GetGridOffset( GetIndex(llGetSubString(str, 3, 3)) ); // SALAHZAR
 vector GridOffset5 = GetGridOffset( GetIndex(llGetSubString(str, 4, 4)) ); // SALAHZAR
 
 // Use these grid positions to display the correct textures/offsets. 
 ShowChars(GridOffset1, GridOffset2, GridOffset3, GridOffset4, GridOffset5); 
} 
integer ConvertIndex(integer index) {
 // This converts from an ASCII based index to our indexing scheme.
 if (index >= 32) // ' ' or higher
 index -= 32;
 else { // index < 32
 // Quick bounds check.
 if (index > 15)
 index = 15;
 index += 94; // extended characters
 }
 return index;
}
default {
 state_entry() {
 // Initialize the character index.
 ResetCharIndex(); ME=(integer)llGetObjectName();
 RenderString(llGetObjectName());
 
 }
 link_message(integer sender, integer channel, string data, key id) {
 if (channel == ME) {
 RenderString(data);
 return;
 }
 // set_params will return in key the texture id, and in data
 // knum, kcol<v>, krow<v>, kmul#<v*5>, koff#<v*5>, and in id=gFontTexture
 if (channel == SET_PARAMS) {
 llSetText("*",<1,1,1>,1); // show we are working
 list l=llCSV2List(data);
 // Use the new texture instead of the current one.
 gFontTexture = id;
 // Change the currently shown texture.
 llSetTexture(gFontTexture, FACE_1);
 llSetTexture(gFontTexture, FACE_2);
 llSetTexture(gFontTexture, FACE_3);
 llSetTexture(gFontTexture, FACE_4);
 llSetTexture(gFontTexture, FACE_5);
 integer i=0;
 knum=(integer)llList2String(l,i++);
 kcol=(vector)llList2String(l,i++);
 krow=(vector)llList2String(l,i++);
 // kmul#
 kmul1=(vector)llList2String(l,i++);
 kmul2=(vector)llList2String(l,i++);
 kmul3=(vector)llList2String(l,i++);
 kmul4=(vector)llList2String(l,i++);
 kmul5=(vector)llList2String(l,i++);
 // koff#
 koff1=(vector)llList2String(l,i++);
 koff2=(vector)llList2String(l,i++);
 koff3=(vector)llList2String(l,i++);
 koff4=(vector)llList2String(l,i++);
 koff5=(vector)llList2String(l,i++);
 
 
 llSetText("",<1,1,1>,1); // remove working mark
 //RenderString("mmmmm");
 
 return;
 }
 // change the decode array to be able to easily change font
 if(channel == SET_DECODE) {
 
 // we are lucky since decode does NOT contain normal characters like ","
 decode=llCSV2List(data);
 return;
 }
 if (channel == SET_COLOR) {
 vector newColor = (vector)data;
 llSetColor(newColor, ALL_SIDES);
 }
 }
}
</lsl>
== A very simple application ==
* You can find the supercell for free here: http://alisl.org/salahzar/sendinventory.php?av=00000000-0000-0000-0000-0000000000000&obj=Super.cell.rename.me.1000
* Have an array of super cells like that listed before and name them with consecutive numbers: 1000, 1001, 1002, 1003
* Link the cells with a root back-panel holding the following sample script:
<lsl>
// 
// This is a sample for driving the XyText SuperCell
//
setCells()
{
 // set positions and texture
 
 llMessageLinked(LINK_SET, 204005, 
 llList2CSV( [ 
 10, // knum number of characters per row
 <-0.44,0.1,0>, // offset multiplier for cols
 <0.422,-0.05,0>, // offset multiplier for rows
 // change the first two in each row to change multiplier for zooming chars
 <0.15, 0.05, 0>,
 <0.06, 0.05, 0>, 
 <-0.86, 0.05, 0>,
 <0.06, 0.05, 0>, 
 <0.15, 0.05, 0>, 
 // change the first two x and y in each row to "move characters along x,y axis
 <0.035, 0, 0>,
 <-0.012,0,0>,
 <-0.298, 0, 0>,
 <-0.012,0,0>,
 <-0.055, 0, 0>
 ]), "db6664f6-057f-becf-bb1e-924255c2c7fd");
 
 
 // special UTF-8 chars for European languages
 // these 80 chars correspond to the following chars in CP850 codepage: (some are not viewable in editor)
 
 // Ç ü é â ä à å ç ê ë
 list decode= [ "%C3%87", "%C3%BC", "%C3%A9", "%C3%A2", "%C3%A4", "%C3%A0", "%C3%A5", "%C3%A7", "%C3%AA", "%C3%AB",
 // è ï î ì Ä Å É æ Æ BLACK RIGHT-POINTING TRIANGLE
 "%C3%A8", "%C3%AF", "%C3%AE", "%C3%AC", "%C3%84", "%C3%85", "%C3%89", "%C3%A6", "%C3%AE", "%E2%96%B6",
 // ö ò û ù ÿ Ö Ü ¢ £ ¥
 "%C3%B6", "%C3%B2", "%C3%BB", "%C3%B9", "%C3%BF", "%C3%96", "%C3%9C", "%C2%A2", "%C2%A3", "%C2%A5",
 // A^ copyright á í ó ú ñ Ñ ª º"
 "%C3%82", "%C2%A9", "%C3%A1", "%C3%AD", "%C3%B3", "%C3%BA", "%C3%B1", "%C3%91", "%C2%AA", "%C2%BA",
 // ¿ O^ ¬ ½ ¼ ¡ « » alfa ß"
 "%C2%BF", "%C3%94", "%C2%AC", "%C2%BD", "%C2%BC", "%C2%A1", "%C2%AB", "%C2%BB", "%CE%B1", "%C3%9F",
 // gamma pi bigsigma smsigma mu 
 "%CE%93", "%CF%80", "%CE%A3", "%CF%83", "%C2%B5" ];
 
 // tau BIGfi theta omega delta 
 decode=(decode=[])+decode+ [ "%CF%84", "%CE%A6", "%CE%98", "%CE%A9", "%CE%B4",
 // Uu uu EPS INTERS 3bars +- <= >= INTEGRUP INTEGRDOWN
 "%C5%AC", "%C5%AD", "%CE%B5", "%E2%88%A9", "%E2%89%A1", "%C2%B1", "%E2%89%A5", "%E2%89%A4", "%E2%8C%A0", "%E2%8C%A1",
 // A/ A\ a~ A~ E^ I/ O/ o~ O~ o^
 "%C3%81", "%C3%80", "%C3%A3", "%C3%83", "%C3%8A", "%C3%8D", "%C3%93", "%C3%B5", "%C3%95", "%C3%B4" ];
 
 llMessageLinked(LINK_SET, 204006, llList2CSV(decode),NULL_KEY);
 
}
default
{
 state_entry()
 {
 // set properly the supercells
 setCells();
 
 // clear cells 1000 1002
 llMessageLinked(LINK_SET,1000," "," ");
 llMessageLinked(LINK_SET,1001," "," ");
 llMessageLinked(LINK_SET,1002," "," ");
 llMessageLinked(LINK_SET,1003," "," ");
 
 
 
 }
 touch_start(integer total_number)
 {
 string avatarName=llDetectedName(0);
 llMessageLinked(LINK_SET,1000,llGetSubString(avatarName,0,4),"");
 llMessageLinked(LINK_SET,1001,llGetSubString(avatarName,5,9),"");
 llMessageLinked(LINK_SET,1002,llGetSubString(avatarName,10,14),"");
 llMessageLinked(LINK_SET,1002,llGetSubString(avatarName,15,19),"");
 
 }
}
</lsl>
== An example real application in world ==
get or have a look to this opensourced, full permissions and free object
You can get this object here https://marketplace.secondlife.com/p/xyutf82010/4275140