Survivalcraft API 1.8.2.3 v1.8.2.3
Survivalcraft 2.4
载入中...
搜索中...
未找到
BitmapFont.cs
浏览该文件的文档.
1using System.Reflection;
3using SixLabors.ImageSharp.PixelFormats;
4
5namespace Engine.Media {
6 public class BitmapFont : IDisposable {
7 public class Counter {
8 short[] m_counts = new short[32];
9
10 public int MaxUsedIndex { get; private set; } = -1;
11
12 public void Increment(int i) {
13 while (i >= m_counts.Length) {
14 short[] counts = m_counts;
15 m_counts = new short[m_counts.Length * 2];
16 Array.Copy(counts, m_counts, MaxUsedIndex + 1);
17 }
18 m_counts[i]++;
20 }
21
22 public int Get(int i) => m_counts[i];
23
24 public void Clear() {
25 Array.Clear(m_counts, 0, MaxUsedIndex + 1);
26 MaxUsedIndex = -1;
27 }
28 }
29
30 public class Glyph(char code, Vector2 texCoord1, Vector2 texCoord2, Vector2 offset, float width) {
31 public readonly char Code = code;
32
33 public readonly bool IsBlank = texCoord1 == texCoord2;
34
35 public readonly Vector2 TexCoord1 = texCoord1;
36
37 public readonly Vector2 TexCoord2 = texCoord2;
38
39 public readonly Vector2 Offset = offset;
40
41 public readonly float Width = width;
42 }
43
44 public class KerningSettings {
45 public int Limit = 5;
46
47 public int Tolerance = 1;
48
49 public int BulkingRadius = 1;
50
51 public float BulkingGradient = 1f;
52 }
53
54 public static BitmapFont m_debugFont;
55
57
58 public Image m_image;
59
60 public Dictionary<int, short> m_kerningPairs;
61
62 public Texture2D Texture { get; set; }
63
64 public float GlyphHeight { get; set; }
65
66 public float LineHeight { get; set; }
67
68 public Vector2 Spacing { get; set; }
69
70 public float Scale { get; set; }
71
72 public Glyph FallbackGlyph { get; set; }
73
74 public static Glyph EmptyGlyph = new((char)0, Vector2.Zero, Vector2.Zero, Vector2.Zero, 0f);
75
76 public char MaxGlyphCode { get; set; }
77
78 public static BitmapFont DebugFont {
79 get {
80 if (m_debugFont == null) {
81#if ANDROID
82#pragma warning disable CA1416
83 using Stream stream = EngineActivity.m_activity.Assets?.Open("Debugfont.png");
84 using Stream stream2 = EngineActivity.m_activity.Assets?.Open("Debugfont.lst");
85#pragma warning restore CA1416
86#else
87 using Stream stream = typeof(BitmapFont).GetTypeInfo().Assembly.GetManifestResourceStream("Engine.Resources.Debugfont.png");
88 using Stream stream2 = typeof(BitmapFont).GetTypeInfo().Assembly.GetManifestResourceStream("Engine.Resources.Debugfont.lst");
89#endif
90 if (stream == null) {
91 throw new FileNotFoundException("Debugfont.png");
92 }
93 if (stream2 == null) {
94 throw new FileNotFoundException("Debugfont.lst");
95 }
96 m_debugFont = Initialize(stream, stream2);
97 }
98 return m_debugFont;
99 }
100 }
101
108 public static BitmapFont Initialize(Stream TextureStream, Stream GlyphsStream, Vector2? customGlyphOffset = null) =>
109 Initialize(Texture2D.Load(TextureStream), GlyphsStream, customGlyphOffset);
110
111 public static BitmapFont Initialize(Texture2D texture, Stream GlyphsStream, Vector2? customGlyphOffset = null) {
112 try {
113 char[] splitters = [(char)0x20, (char)0x09]; // 空格和制表符
114 BitmapFont bitmapFont = new();
115 StreamReader streamReader = new(GlyphsStream);
116 string firstLine = streamReader.ReadLine();
117 if (firstLine == null) {
118 throw new FormatException("The first line of the .lst file of the bitmap font can not be founded");
119 }
120 int num = int.Parse(firstLine);
121 Glyph[] array = new Glyph[num];
122 for (int i = 0; i < num; i++) {
123 string line = streamReader.ReadLine();
124 if (line == null) {
125 throw new FormatException($"The {i + 2} line of the .lst file of the bitmap font can not be founded");
126 }
127 string[] arr = line.Split(splitters, StringSplitOptions.None);
128 if (arr.Length == 9) {
129 string[] tmp = new string[8];
130 tmp[0] = " ";
131 for (int j = 2; j < arr.Length; j++) {
132 tmp[j - 1] = arr[j];
133 }
134 arr = tmp;
135 }
136 char code = char.Parse(arr[0]);
137 Vector2 texCoord = new(float.Parse(arr[1]), float.Parse(arr[2]));
138 Vector2 texCoord2 = new(float.Parse(arr[3]), float.Parse(arr[4]));
139 Vector2 offset = new(float.Parse(arr[5]), float.Parse(arr[6]));
140 if (customGlyphOffset.HasValue) {
141 offset += customGlyphOffset.Value;
142 }
143 float width = float.Parse(arr[7]);
144 array[i] = new Glyph(code, texCoord, texCoord2, offset, width);
145 }
146 string glyphHeightLine = streamReader.ReadLine();
147 if (glyphHeightLine == null) {
148 throw new FormatException("The height line of the .lst file of the bitmap font can not be founded");
149 }
150 float glyphHeight = float.Parse(glyphHeightLine);
151 string spacingLine = streamReader.ReadLine();
152 if (spacingLine == null) {
153 throw new FormatException("The spacing line of the .lst file of the bitmap font can not be founded");
154 }
155 string[] arr2 = spacingLine.Split(splitters, StringSplitOptions.None);
156 Vector2 spacing = new(float.Parse(arr2[0]), float.Parse(arr2[1]));
157 string scaleLine = streamReader.ReadLine();
158 if (scaleLine == null) {
159 throw new FormatException("The scale line of the .lst file of the bitmap font can not be founded");
160 }
161 float scale = float.Parse(scaleLine);
162 string fallbackLine = streamReader.ReadLine();
163 if (fallbackLine == null) {
164 throw new FormatException("The fallback line of the .lst file of the bitmap font can not be founded");
165 }
166 char fallbackCode = char.Parse(fallbackLine);
167 string kerningCountLine = streamReader.ReadLine();
168 if (kerningCountLine != null) {
169 int kerningCount = int.Parse(kerningCountLine);
170 for (int j = 0; j < kerningCount; j++) {
171 string line = streamReader.ReadLine();
172 if (line == null) {
173 throw new FormatException($"The {j + 7} line of the .lst file of the bitmap font can not be founded");
174 }
175 string[] arr = line.Split(splitters, StringSplitOptions.None);
176 if (arr.Length == 3) {
177 char code2 = char.Parse(arr[0]);
178 char followingCode = char.Parse(arr[1]);
179 float num3 = float.Parse(arr[2]);
180 bitmapFont.SetKerning(code2, followingCode, num3);
181 }
182 }
183 }
184 bitmapFont.Initialize(
185 texture,
186 null,
187 array,
188 fallbackCode,
189 glyphHeight,
190 spacing,
191 scale
192 );
193 return bitmapFont;
194 }
195 catch (Exception e) {
196 Log.Error(e.Message);
197 return null;
198 }
199 }
200
201 public BitmapFont(Texture2D texture, IEnumerable<Glyph> glyphs, char fallbackCode, float glyphHeight, Vector2 spacing, float scale) {
203 texture,
204 null,
205 glyphs,
206 fallbackCode,
207 glyphHeight,
208 spacing,
209 scale
210 );
211 }
212
213 public void Dispose() {
214 if (Texture != null) {
215 Texture.Dispose();
216 Texture = null;
217 }
218 }
219
220 public Glyph GetGlyph(char code) => code == 0 ? EmptyGlyph :
221 code >= m_glyphsByCode.Length ? FallbackGlyph : m_glyphsByCode[code];
222
223 public float GetKerning(char code, char followingCode) {
224 short value = 0;
225 if (m_kerningPairs != null) {
226 m_kerningPairs.TryGetValue((int)(((uint)code << 16) | followingCode), out value);
227 }
228 return value;
229 }
230
231 public Vector2 MeasureText(string text, Vector2 scale, Vector2 spacing) => MeasureText(text, 0, text.Length, scale, spacing);
232
233 public Vector2 MeasureText(string text, int start, int count, Vector2 scale, Vector2 spacing) {
234 scale *= Scale;
235 spacing += Spacing;
236 float num = GlyphHeight + spacing.Y;
237 Vector2 vector = new(0f, num);
238 Vector2 vector2 = vector;
239 int i = start;
240 for (int num2 = start + count; i < num2; i++) {
241 char c = text[i];
242 if (c == '\n') {
243 vector.X = 0f;
244 vector.Y += num;
245 if (vector.Y > vector2.Y) {
246 vector2.Y = vector.Y;
247 }
248 }
249 else if (c != '\r'
250 && c != '\u200b') {
251 if (c == '\u00a0') {
252 c = ' ';
253 }
254 Glyph glyph = GetGlyph(c);
255 float num3 = i < text.Length - 1 ? GetKerning(c, text[i + 1]) : 0f;
256 vector.X += glyph.Width - num3 + spacing.X;
257 if (vector.X > vector2.X) {
258 vector2.X = vector.X;
259 }
260 }
261 }
262 return vector2 * scale;
263 }
264
265 public int FitText(float width, string text, float scale, float spacing) => FitText(width, text, 0, text.Length, scale, spacing);
266
267 public int FitText(float width, string text, int start, int length, float scale, float spacing) {
268 scale *= Scale;
269 spacing += Spacing.X;
270 float num = 0f;
271 for (int i = start; i < start + length; i++) {
272 char c = text[i];
273 if (c == '\n') {
274 num = 0f;
275 }
276 else if (c != '\r'
277 && c != '\u200b') {
278 if (c == '\u00a0') {
279 c = ' ';
280 }
281 Glyph glyph = GetGlyph(c);
282 float num2 = i < text.Length - 1 ? GetKerning(c, text[i + 1]) : 0f;
283 num += (glyph.Width - num2 + spacing) * scale;
284 if (num > width) {
285 return i - start;
286 }
287 }
288 }
289 return length;
290 }
291
292 public float CalculateCharacterPosition(string text, int characterIndex, Vector2 scale, Vector2 spacing) {
293 characterIndex = Math.Clamp(characterIndex, 0, text.Length);
294 return MeasureText(text, 0, characterIndex, scale, spacing).X;
295 }
296
297 public static BitmapFont Load(Image image,
298 char firstCode,
299 char fallbackCode,
300 Vector2 spacing,
301 float scale,
302 Vector2 offset,
303 KerningSettings kerningSettings = null,
304 int mipLevelsCount = 1,
305 bool premultiplyAlpha = true) => InternalLoad(
306 image,
307 firstCode,
308 fallbackCode,
309 spacing,
310 scale,
311 offset,
312 kerningSettings,
313 mipLevelsCount,
314 premultiplyAlpha,
315 true
316 );
317
318 public static BitmapFont Load(Stream stream,
319 char firstCode,
320 char fallbackCode,
321 Vector2 spacing,
322 float scale,
323 Vector2 offset,
324 KerningSettings kerningSettings = null,
325 int mipLevelsCount = 1,
326 bool premultiplyAlpha = true) => Load(
327 Image.Load(stream),
328 firstCode,
329 fallbackCode,
330 spacing,
331 scale,
332 offset,
333 kerningSettings,
334 mipLevelsCount,
335 premultiplyAlpha
336 );
337
338 public static BitmapFont Load(string fileName,
339 char firstCode,
340 char fallbackCode,
341 Vector2 spacing,
342 float scale,
343 Vector2 offset,
344 KerningSettings kerningSettings = null,
345 int mipLevelsCount = 1,
346 bool premultiplyAlpha = true) {
347 using (Stream stream = Storage.OpenFile(fileName, OpenFileMode.Read)) {
348 return Load(
349 stream,
350 firstCode,
351 fallbackCode,
352 spacing,
353 scale,
354 offset,
355 kerningSettings,
356 mipLevelsCount,
357 premultiplyAlpha
358 );
359 }
360 }
361
362 static BitmapFont() {
363 Display.DeviceReset += delegate {
364 if (m_debugFont != null) {
365 using Stream stream = typeof(BitmapFont).GetTypeInfo().Assembly.GetManifestResourceStream("Engine.Resources.Debugfont.png");
366 using Stream stream2 = typeof(BitmapFont).GetTypeInfo().Assembly.GetManifestResourceStream("Engine.Resources.Debugfont.lst");
367 m_debugFont = Initialize(stream, stream2);
368 }
369 };
370 }
371
372 internal BitmapFont() { }
373
374 internal static BitmapFont InternalLoad(Image image,
375 char firstCode,
376 char fallbackCode,
377 Vector2 spacing,
378 float scale,
379 Vector2 offset,
380 KerningSettings kerningSettings,
381 int mipLevelsCount,
382 bool premultiplyAlpha,
383 bool createTexture) {
384 List<Rectangle> list = new(FindGlyphs(image));
385 List<Rectangle> list2 = new(list.Select(r => CropGlyph(image, r)));
386 if (list.Count == 0) {
387 throw new InvalidOperationException("No glyphs found in BitmapFont image.");
388 }
389 int num = int.MaxValue;
390 int num2 = int.MaxValue;
391 int num3 = int.MaxValue;
392 int num4 = int.MaxValue;
393 for (int i = 0; i < list2.Count; i++) {
394 if (list2[i].Width > 0
395 && list2[i].Height > 0) {
396 num = Math.Min(num, list2[i].Left - list[i].Left);
397 num2 = Math.Min(num2, list2[i].Top - list[i].Top);
398 num3 = Math.Min(num3, list[i].Right - list2[i].Right);
399 num4 = Math.Min(num4, list[i].Bottom - list2[i].Bottom);
400 }
401 }
402 int num5 = firstCode;
403 float num6 = 0f;
404 List<Glyph> list3 = [];
405 for (int j = 0; j < list2.Count; j++) {
406 Vector2 texCoord;
407 Vector2 texCoord2;
408 Vector2 offset2;
409 if (list2[j].Width > 0
410 && list2[j].Height > 0) {
411 texCoord = new Vector2((list2[j].Left - 0.5f) / image.Width, (list2[j].Top - 0.5f) / image.Height);
412 texCoord2 = new Vector2((list2[j].Right + 0.5f) / image.Width, (list2[j].Bottom + 0.5f) / image.Height);
413 offset2 = new Vector2(list2[j].Left - list[j].Left - num - 0.5f, list2[j].Top - list[j].Top - num2 - 0.5f);
414 }
415 else {
416 texCoord = Vector2.Zero;
417 texCoord2 = Vector2.Zero;
418 offset2 = Vector2.Zero;
419 }
420 offset2 += offset;
421 float width = list[j].Width - num - num3;
422 num6 = Math.Max(num6, list[j].Height - num2 - num4);
423 list3.Add(new Glyph((char)num5, texCoord, texCoord2, offset2, width));
424 num5++;
425 }
426 Image image2 = new(image.Width, image.Height);
427 image.m_trueImage.ProcessPixelRows(
428 image2.m_trueImage,
429 (sourceAccessor, targetAccessor) => {
430 for (int i = 0; i < sourceAccessor.Height; i++) {
431 Span<Rgba32> sourceRow = sourceAccessor.GetRowSpan(i);
432 Span<Rgba32> targetRow = targetAccessor.GetRowSpan(i);
433 for (int x = 0; x < sourceRow.Length; x++) {
434 Rgba32 sourcePixel = sourceRow[x];
435 targetRow[x] = sourcePixel.IsMagenta() ? SixLabors.ImageSharp.Color.Transparent :
436 premultiplyAlpha ? sourcePixel.PremultiplyAlpha() : sourcePixel;
437 }
438 }
439 }
440 );
441 Texture2D texture = createTexture ? Texture2D.Load(image2, mipLevelsCount) : null;
442 Image image3 = createTexture ? null : image2;
443 BitmapFont bitmapFont = new();
444 bitmapFont.Initialize(
445 texture,
446 image3,
447 list3,
448 fallbackCode,
449 num6,
450 spacing,
451 scale
452 );
453 if (kerningSettings != null) {
454 int[][] array = new int[list.Count][];
455 int[][] array2 = new int[list.Count][];
456 for (int l = 0; l < list.Count; l++) {
457 CalculateKerningDepths(image, list2[l], out array[l], out array2[l]);
458 array[l] = ApplyKerningBulking(array[l], kerningSettings.BulkingRadius, kerningSettings.BulkingGradient);
459 array2[l] = ApplyKerningBulking(array2[l], kerningSettings.BulkingRadius, kerningSettings.BulkingGradient);
460 }
461 Counter counter = new();
462 for (int m = 0; m < list.Count; m++) {
463 for (int n = 0; n < list.Count; n++) {
464 int num7 = list2[m].Top - list[m].Top;
465 int x = list2[m].Bottom - list[m].Top;
466 int num8 = list2[n].Top - list[n].Top;
467 int x2 = list2[n].Bottom - list[n].Top;
468 int num9 = MathUtils.Max(num7, num8);
469 int num10 = MathUtils.Min(x, x2);
470 counter.Clear();
471 for (int num11 = num9; num11 < num10; num11++) {
472 int num12 = num11 - num7;
473 int num13 = num11 - num8;
474 int num14 = array2[m][num12];
475 int num15 = array[n][num13];
476 counter.Increment(num15 + num14);
477 }
478 int num16 = Math.Min(kerningSettings.Limit - 1, counter.MaxUsedIndex);
479 int tolerance = kerningSettings.Tolerance;
480 int num17 = 0;
481 int num18;
482 for (num18 = 0; num18 <= num16; num18++) {
483 num17 += counter.Get(num18);
484 if (num17 > tolerance) {
485 break;
486 }
487 }
488 if (num18 != 0) {
489 bitmapFont.SetKerning((char)(m + firstCode), (char)(n + firstCode), num18);
490 }
491 }
492 }
493 }
494 return bitmapFont;
495 }
496
497 internal void Initialize(Texture2D texture,
498 Image image,
499 IEnumerable<Glyph> glyphs,
500 char fallbackCode,
501 float glyphHeight,
502 Vector2 spacing,
503 float scale) {
504 Dispose();
505 Texture = texture;
506 m_image = image;
507 GlyphHeight = glyphHeight;
508 LineHeight = glyphHeight + spacing.Y;
509 Spacing = spacing;
510 Scale = scale;
511 IEnumerable<Glyph> enumerable = glyphs as Glyph[] ?? glyphs.ToArray();
512 foreach (Glyph glyph in enumerable) {
513 if (glyph.Code == fallbackCode) {
514 FallbackGlyph = glyph;
515 }
516 if (glyph.Code > MaxGlyphCode) {
517 MaxGlyphCode = glyph.Code;
518 }
519 }
520 FallbackGlyph ??= enumerable.First(g => g.Code == 0);
522 for (int i = 0; i < m_glyphsByCode.Length; i++) {
524 }
525 foreach (Glyph glyph in enumerable) {
526 m_glyphsByCode[glyph.Code] = glyph;
527 }
528 }
529
530 public static IEnumerable<Rectangle> FindGlyphs(Image image) {
531 int y = 1;
532 while (y < image.Height) {
533 int num;
534 for (int x = 1; x < image.Width; x = num) {
535 if (!image.GetPixelFast(x, y).IsMagenta()
536 && image.GetPixelFast(x - 1, y).IsMagenta()
537 && image.GetPixelFast(x, y - 1).IsMagenta()) {
538 int i = 1;
539 int j = 1;
540 for (; x + i < image.Width && !image.GetPixelFast(x + i, y).IsMagenta(); i++) { }
541 for (; y + j < image.Height && !image.GetPixelFast(x, y + j).IsMagenta(); j++) { }
542 yield return new Rectangle(x, y, i, j);
543 }
544 num = x + 1;
545 }
546 num = y + 1;
547 y = num;
548 }
549 }
550
551 public static int[] ApplyKerningBulking(int[] depths, int radius, float gradient) {
552 int[] array = new int[depths.Length];
553 for (int i = 0; i < depths.Length; i++) {
554 array[i] = depths[i];
555 int num = MathUtils.Max(i - radius, 0);
556 int num2 = MathUtils.Min(i + radius, depths.Length - 1);
557 for (int j = num; j <= num2; j++) {
558 int num3 = Math.Abs(j - i);
559 int x = depths[j] + (int)Math.Round(gradient * num3);
560 array[i] = MathUtils.Min(array[i], x);
561 }
562 }
563 return array;
564 }
565
566 public static void CalculateKerningDepths(Image image, Rectangle rectangle, out int[] leftDepths, out int[] rightDepths) {
567 leftDepths = new int[rectangle.Height];
568 rightDepths = new int[rectangle.Height];
569 for (int i = rectangle.Top; i < rectangle.Bottom; i++) {
570 int num = i - rectangle.Top;
571 leftDepths[num] = rectangle.Width;
572 rightDepths[num] = rectangle.Width;
573 for (int j = rectangle.Left; j < rectangle.Right; j++) {
574 if (image.GetPixel(j, i).A != 0) {
575 leftDepths[num] = MathUtils.Min(leftDepths[num], j - rectangle.Left);
576 rightDepths[num] = MathUtils.Min(rightDepths[num], rectangle.Right - j - 1);
577 }
578 }
579 }
580 }
581
582 public BitmapFont Clone(float scale, Vector2 spacing) => new() {
589 Spacing = spacing,
590 Scale = scale,
593 };
594
595 public static Rectangle CropGlyph(Image image, Rectangle rectangle) {
596 int num = int.MaxValue;
597 int num2 = int.MaxValue;
598 int num3 = int.MinValue;
599 int num4 = int.MinValue;
600 for (int i = rectangle.Left; i < rectangle.Left + rectangle.Width; i++) {
601 for (int j = rectangle.Top; j < rectangle.Top + rectangle.Height; j++) {
602 if (image.GetPixelFast(i, j).A != 0) {
603 num = Math.Min(num, i);
604 num2 = Math.Min(num2, j);
605 num3 = Math.Max(num3, i);
606 num4 = Math.Max(num4, j);
607 }
608 }
609 }
610 return num == int.MaxValue
611 ? new Rectangle(rectangle.Left, rectangle.Top, 0, 0)
612 : new Rectangle(num, num2, num3 - num + 1, num4 - num2 + 1);
613 }
614
615 public void SetKerning(char code, char followingCode, float kerning) {
616 m_kerningPairs ??= new Dictionary<int, short>();
617 m_kerningPairs[(int)(((uint)code << 16) | followingCode)] = (short)kerning;
618 }
619 }
620}
static Texture2D Load(LegacyImage image, int mipLevelsCount=1)
static void Error(object message)
定义 Log.cs:80
static int Min(int x1, int x2)
static int Max(int x1, int x2)
static BitmapFont InternalLoad(Image image, char firstCode, char fallbackCode, Vector2 spacing, float scale, Vector2 offset, KerningSettings kerningSettings, int mipLevelsCount, bool premultiplyAlpha, bool createTexture)
float GetKerning(char code, char followingCode)
static void CalculateKerningDepths(Image image, Rectangle rectangle, out int[] leftDepths, out int[] rightDepths)
static BitmapFont Initialize(Texture2D texture, Stream GlyphsStream, Vector2? customGlyphOffset=null)
static BitmapFont m_debugFont
static IEnumerable< Rectangle > FindGlyphs(Image image)
Dictionary< int, short > m_kerningPairs
static Rectangle CropGlyph(Image image, Rectangle rectangle)
BitmapFont Clone(float scale, Vector2 spacing)
int FitText(float width, string text, int start, int length, float scale, float spacing)
Vector2 MeasureText(string text, int start, int count, Vector2 scale, Vector2 spacing)
BitmapFont(Texture2D texture, IEnumerable< Glyph > glyphs, char fallbackCode, float glyphHeight, Vector2 spacing, float scale)
void SetKerning(char code, char followingCode, float kerning)
static BitmapFont Load(Stream stream, char firstCode, char fallbackCode, Vector2 spacing, float scale, Vector2 offset, KerningSettings kerningSettings=null, int mipLevelsCount=1, bool premultiplyAlpha=true)
Vector2 MeasureText(string text, Vector2 scale, Vector2 spacing)
static BitmapFont DebugFont
static BitmapFont Initialize(Stream TextureStream, Stream GlyphsStream, Vector2? customGlyphOffset=null)
纹理图
int FitText(float width, string text, float scale, float spacing)
static int[] ApplyKerningBulking(int[] depths, int radius, float gradient)
void Initialize(Texture2D texture, Image image, IEnumerable< Glyph > glyphs, char fallbackCode, float glyphHeight, Vector2 spacing, float scale)
static BitmapFont Load(Image image, char firstCode, char fallbackCode, Vector2 spacing, float scale, Vector2 offset, KerningSettings kerningSettings=null, int mipLevelsCount=1, bool premultiplyAlpha=true)
float CalculateCharacterPosition(string text, int characterIndex, Vector2 scale, Vector2 spacing)
static BitmapFont Load(string fileName, char firstCode, char fallbackCode, Vector2 spacing, float scale, Vector2 offset, KerningSettings kerningSettings=null, int mipLevelsCount=1, bool premultiplyAlpha=true)
Color GetPixel(int x, int y)
static Image Load(Stream stream, ImageFileFormat format)
readonly Image< Rgba32 > m_trueImage
Rgba32 GetPixelFast(int x, int y)
static Stream OpenFile(string path, OpenFileMode openFileMode)
static readonly Vector2 Zero
static Vector2 Max(Vector2 v, float f)