Last active
June 18, 2022 17:56
-
-
Save krypt-lynx/5b34d7e29bc56ffe98179d02090e4f53 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Text; | |
using System.Threading.Tasks; | |
using VRage.Game.ModAPI.Ingame; | |
namespace Script | |
{ | |
#region ingame script start | |
public enum WordWrapOptions | |
{ | |
None = 0, | |
Overflow = 1, | |
SplitWords = 2, | |
NewLineExtra = 4, | |
Default = None | |
} | |
public interface IFontDataProvider | |
{ | |
int Width(char ch); | |
int Width(string str, char lead = '\0'); | |
int Height(); | |
int LetterSpacing(char left, char right); | |
} | |
public class StringUtils | |
{ | |
public StringUtils(IFontDataProvider dataProvider) | |
{ | |
this.dataProvider = dataProvider; | |
} | |
IFontDataProvider dataProvider = null; | |
public List<string> Wrap(string str, int width, WordWrapOptions options = WordWrapOptions.Default) | |
{ | |
int end; | |
return Wrap(str, x => width, 0, out end, options); | |
} | |
public List<string> Wrap(string str, Func<int, int> width, WordWrapOptions options = WordWrapOptions.Default) | |
{ | |
int end; | |
return Wrap(str, width, 0, out end, options); | |
} | |
public List<string> Wrap(string str, Func<int, int> width, int start, out int end, WordWrapOptions options = WordWrapOptions.Default) | |
{ | |
List<string> lines = new List<string>(); | |
bool allowClipping = (options | WordWrapOptions.Overflow) == options; | |
bool splitWords = (options | WordWrapOptions.SplitWords) == options; | |
bool newLineExtra = (options | WordWrapOptions.NewLineExtra) == options; | |
StringBuilder line = new StringBuilder(); | |
StringBuilder candidate = new StringBuilder(); | |
int lWidth = width(lines.Count); | |
if (lWidth == -1) | |
{ | |
end = start; | |
return lines; | |
} | |
int cWidth = 0; | |
char left = '\0'; | |
char[] chars = str.ToCharArray(); | |
int i = start; | |
int imax = chars.Length; | |
for (; i < imax; i++) | |
{ | |
char ch = chars[i]; | |
int delta = dataProvider.LetterSpacing(left, ch) + dataProvider.Width(ch); | |
if (ch == '\n') | |
{ | |
// New line: | |
// Finishing text line | |
// If 'newLineExtra': Adding extra line if text line was not empty | |
line.Append(candidate); | |
lines.Add(line.ToString()); | |
if (newLineExtra && line.Length > 0) | |
{ | |
lines.Add(""); | |
} | |
candidate.Clear(); | |
cWidth = 0; | |
line.Clear(); | |
lWidth = width(lines.Count); | |
if (lWidth == -1) | |
{ | |
goto loop_break; | |
} | |
} | |
else if (ch == '\r') | |
{ | |
// ignoting 'caret return' characters | |
} | |
else if (splitWords || !char.IsWhiteSpace(ch)) | |
{ | |
// building 'candidate' until there is space for it | |
// starting new line in case if 'candidate' becoming too long | |
// inserting is as in case if already at new line | |
if (cWidth + delta > lWidth) | |
{ | |
if (lWidth < width(lines.Count)) | |
{ | |
lines.Add(line.ToString()); | |
line.Clear(); | |
lWidth = width(lines.Count); | |
if (lWidth == -1) | |
{ | |
goto loop_break; | |
} | |
} | |
if ( | |
(cWidth + delta > width(lines.Count)) && | |
!(allowClipping && candidate.Length == 0) | |
) | |
{ | |
if (candidate.Length == 0) | |
{ | |
goto loop_break; | |
} | |
line.Append(candidate); | |
lines.Add(line.ToString()); | |
line.Clear(); | |
lWidth = width(lines.Count); | |
if (lWidth == -1) | |
{ | |
goto loop_break; | |
} | |
candidate.Clear(); | |
candidate.Append(ch); | |
cWidth = delta; | |
} | |
else | |
{ | |
cWidth += delta; | |
candidate.Append(ch); | |
} | |
} | |
else | |
{ | |
cWidth += delta; | |
candidate.Append(ch); | |
} | |
} | |
else | |
{ | |
// insering candidate at current line | |
// adding whitespace if can, staring new line if can't | |
line.Append(candidate); | |
lWidth -= cWidth; | |
candidate.Clear(); | |
cWidth = 0; | |
if (lWidth <= delta) | |
{ | |
lines.Add(line.ToString()); | |
line.Clear(); | |
lWidth = width(lines.Count); | |
if (lWidth == -1) | |
{ | |
goto loop_break; | |
} | |
} | |
else | |
{ | |
lWidth -= delta; | |
line.Append(ch); | |
} | |
} | |
} | |
// appending tail | |
if (candidate.Length > 0) | |
{ | |
line.Append(candidate); | |
} | |
if (line.Length > 0 || lines.Count == 0) | |
{ | |
lines.Add(line.ToString()); | |
} | |
loop_break: | |
end = i; | |
return lines; | |
} | |
} | |
class DebugFontDataProvider : IFontDataProvider | |
{ | |
static string cRef = | |
"\n\n\n\n\n\n'|¦ˉ‘’‚\nј\n !I`ijl ¡¨¯´¸ÌÍÎÏìíîïĨĩĪīĮįİıĵĺļľłˆˇ˘˙˚˛˜˝ІЇії‹›∙\n" + | |
"(),.1:;[]ft{}·ţťŧț\n\"-rªºŀŕŗř\n*²³¹\n\\°“”„\nґ\n/ijтэє\nL_vx«»ĹĻĽĿŁГгзлхчҐ–" + | |
"•\n7?Jcz¢¿çćĉċčĴźżžЃЈЧавийнопсъьѓѕќ\n3FKTabdeghknopqsuy£µÝàáâãäåèéêëðñòóôõö" + | |
"øùúûüýþÿāăąďđēĕėęěĝğġģĥħĶķńņňʼnōŏőśŝşšŢŤŦũūŭůűųŶŷŸșȚЎЗКЛбдекруцяёђћўџ\n+<=>E" + | |
"^~¬±¶ÈÉÊË×÷ĒĔĖĘĚЄЏЕНЭ−\n#0245689CXZ¤¥ÇßĆĈĊČŹŻŽƒЁЌАБВДИЙПРСТУХЬ€\n$&GHPUVY§Ù" + | |
"ÚÛÜÞĀĜĞĠĢĤĦŨŪŬŮŰŲОФЦЪЯжы†‡\nABDNOQRSÀÁÂÃÄÅÐÑÒÓÔÕÖØĂĄĎĐŃŅŇŌŎŐŔŖŘŚŜŞŠȘЅЊЖф□\n" + | |
"љ\nю\n%IJЫ\n@©®мшњ\nMМШ\nmw¼ŵЮщ\n¾æœЉ\n½Щ\n™\nWÆŒŴ—…‰\n\n\n\n\n\n\n\n" + | |
"\n\n"; | |
static string kRef = | |
"\nЖв?ж?\nъв>\nьв>\nҐ,?-?.?‚?„?…?–?—?š>œ>à>á>â>ã>ä>å>æ>ç>è>é>ê>ë>ð>ñ?ò>ó>ô>õ" + | |
">ö>ø>ù?ú?û?ü?ž?ā>ă>ą>ć>ĉ>č>ď>đ>ě>ē>ĕ>ę>ĝ>ğ>ń?ň?ō>ŏ>ŕ?ř?ś>ŝ>ş>ș>ũ?ū?ŭ?ů?ų?ŵ?" + | |
"ź?Ц>Ш>Ы?Ю?б>в?ж?н>"; | |
static Dictionary<char, int> cW; | |
static Dictionary<char, Dictionary<char, int>> kP; | |
public DebugFontDataProvider() | |
{ | |
cW = new Dictionary<char, int>(); | |
int w = 0; | |
foreach (char c in cRef) | |
{ | |
if (c == '\n') | |
w++; | |
else | |
cW[c] = w; | |
} | |
kP = new Dictionary<char, Dictionary<char, int>>(); | |
Dictionary<char, int> cur = null; | |
for (var e = ((IList<char>)kRef.ToCharArray()).GetEnumerator(); e.MoveNext();) | |
{ | |
char c1 = e.Current; | |
e.MoveNext(); | |
char c2 = e.Current; | |
if (c1 == '\n') | |
kP[c2] = cur = new Dictionary<char, int>(); | |
else | |
cur[c1] = c2 - 64; | |
} | |
} | |
public int Width(char ch) | |
{ | |
int w; | |
cW.TryGetValue(ch, out w); | |
return w; | |
} | |
public int Width(string str, char lead = '\0') | |
{ | |
char lc = lead; | |
int wd = 0, w; | |
foreach (var c in str) | |
{ | |
cW.TryGetValue(c, out w); | |
wd += w + 1; | |
if (kP.ContainsKey(lc)) | |
{ | |
kP[lc].TryGetValue(c, out w); | |
wd += w; | |
} | |
lc = c; | |
} | |
return wd; | |
} | |
public int LetterSpacing(char left, char right) | |
{ | |
if (kP.ContainsKey(left)) | |
{ | |
int w; | |
kP[left].TryGetValue(right, out w); | |
return w + 1; | |
} | |
return 1; | |
} | |
int SpacingOrZero(char left, char right) | |
{ | |
if (left == '\0' || right == '\0') | |
{ | |
return 0; | |
} | |
else | |
{ | |
return LetterSpacing(left, right); | |
} | |
} | |
public int Height() | |
{ | |
return 37; | |
} | |
} | |
class MonospacedFontDataProvider : IFontDataProvider | |
{ | |
const int charWidth = 24; | |
const int lineHeight = 37; | |
const int letterSpacing = 1; | |
public int LetterSpacing(char left, char right) | |
{ | |
return letterSpacing; | |
} | |
public int Width(char ch) | |
{ | |
return charWidth; | |
} | |
public int Width(string str, char lead = '\0') | |
{ | |
return (charWidth + letterSpacing) * str.Length; | |
} | |
public int Height() | |
{ | |
return lineHeight; | |
} | |
} | |
#endregion // ingame script end | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment