private static bool LoadTextTextures(Text text) { var success = true; for (var i = 0; i < text.Content.Length; i++) { if (SpriteRendererPanel.TextTextures.ContainsKey(text.GetCharKey(i))) { continue; } var glyphSlot = FontGlyphs.GetOrSetGlyphMetrics(text, i); var gdipBitmap = default(Bitmap); using (var glyph = glyphSlot.GetGlyph()) { var bitmapGlyph = glyph.ToBitmapGlyph(); var bitmap = bitmapGlyph.Bitmap; if (bitmap.Rows != 0) { var metricRect = new Rectangle( (bitmap.Width - glyphSlot.Metrics.Width.Round()) / 2, (bitmap.Rows - glyphSlot.Metrics.Height.Round()) / 2, glyphSlot.Metrics.Width.Round(), glyphSlot.Metrics.Height.Round()); gdipBitmap = bitmap.ToGdipBitmap(Color.White).Crop(metricRect); // TODO: Fix real reason for malformed X if (text.Content[i] == 'X' && Math.Abs(text.Font.SizeInPoints - 15) < double.Epsilon * 8) { var fixedXBitmap = new Bitmap(gdipBitmap, metricRect.Size); for (int c = 0; c < metricRect.Width; c++) { fixedXBitmap.SetPixel(c, metricRect.Height - 1, fixedXBitmap.GetPixel(c, metricRect.Height - 2)); } gdipBitmap = fixedXBitmap; } } else { gdipBitmap = new Bitmap(1, 1); } var newTexture = new Texture(gdipBitmap, (SpriteRendererPanel.UsedTextureUnits - 1).ToTextureUnit()); if (newTexture.Loaded) { SpriteRendererPanel.TextTextures[text.GetCharKey(i)] = newTexture; } success &= newTexture.Loaded; } } return(success); }
public static GlyphSlot GetOrSetGlyphMetrics(Text text, int i) { if (!FontGlyphs.TextFaces.TryGetValue(text.Font, out var face)) { var windowFontFamily = new System.Windows.Media.FontFamily(text.Font.FontFamily.Name); var typeface = new Typeface(windowFontFamily, FontStyles.Normal, FontWeights.Normal, FontStretches.Normal); typeface.TryGetGlyphTypeface(out var glyphTypeface); face = new Face(FontGlyphs.TextLibrary, glyphTypeface.FontUri.AbsolutePath); face.SetCharSize(0, text.Font.SizeInPoints * 64, 1, 1); FontGlyphs.TextFaces[text.Font] = face; FontGlyphs.TextFaceHeights[text.Font] = face.Size.Metrics.Height; } if (face.GetCharIndex(text.Content[i]) == 0) { if (!FontGlyphs.FallbackTextFaces.TryGetValue(text.Font, out face)) { face = new Face(FontGlyphs.TextLibrary, FontGlyphs.FallbackFontBytes, 1); face.SetCharSize(0, text.Font.SizeInPoints * 64, 1, 1); FontGlyphs.FallbackTextFaces[text.Font] = face; } } face.LoadChar(text.Content[i], LoadFlags.Default, LoadTarget.Mono); var glyphSlot = face.Glyph; glyphSlot.RenderGlyph(RenderMode.Mono); FontGlyphs.TextMetrics[text.GetCharKey(i)] = glyphSlot.Metrics; return(glyphSlot); }
private static int GetOrSetTextureUnit(Text text, int index) { if (string.IsNullOrWhiteSpace(text?.Content)) { return(-1); } if (SpriteRendererPanel.TextureUnits.ContainsKey(Tuple.Create(TextureType.Text, text.GetCharKey(index)))) { return(SpriteRendererPanel.TextureUnits[Tuple.Create(TextureType.Text, text.GetCharKey(index))].ToInt()); } else { // If at 16, will have already drawn batch if (SpriteRendererPanel.TextureUnits.Count >= SpriteRendererPanel.UsedTextureUnits - 1) { SpriteRendererPanel.TextureUnits.Clear(); } if (SpriteRendererPanel.TextTextures.ContainsKey(text.GetCharKey(index)) || SpriteRendererPanel.LoadTextTextures(text)) { var unitNumber = SpriteRendererPanel.TextureUnits.Count; var usedUnit = unitNumber.ToTextureUnit(); var usedTexture = SpriteRendererPanel.TextTextures[text.GetCharKey(index)]; usedTexture.Use(usedUnit); SpriteRendererPanel.Shader.SetInt($"textureArrays[{unitNumber}]", unitNumber); SpriteRendererPanel.Shader.SetInt($"sheetW[{unitNumber}]", usedTexture.Width); SpriteRendererPanel.Shader.SetInt($"sheetH[{unitNumber}]", usedTexture.Height); SpriteRendererPanel.TextureUnits[Tuple.Create(TextureType.Text, text.GetCharKey(index))] = usedUnit; return(unitNumber); } else { return(-1); } } }