private void glCanvas1_KeyPress(object sender, KeyPressEventArgs e) { if (e.KeyChar == 'b') { BlendingSourceFactor source; BlendingDestinationFactor dest; this.blendFactorHelper.GetNext(out source, out dest); this.glText.BlendSwitch.SourceFactor = source; this.glText.BlendSwitch.DestFactor = dest; this.UpdateLabel(); } else if (e.KeyChar == 'o') { if (this.openTextureDlg.ShowDialog() == System.Windows.Forms.DialogResult.OK) { string ttfFilename = this.openTextureDlg.FileName; this.glText.Dispose(); FontResource fontResouce = FontResource.Load(ttfFilename, ' ', (char)126); var glText = new GLText(AnchorStyles.Left | AnchorStyles.Top, new Padding(3, 3, 3, 3), new Size(850, 50), -100, 100, fontResouce); glText.Initialize(); glText.SwitchList.Add(new ClearColorSwitch());// show black back color to indicate glText's area. glText.SetText("The quick brown fox jumps over the lazy dog!"); this.glText = glText; uiRoot.Controls.Add(glText); this.formPropertyGrid.DisplayObject(glText); } } }
/// <summary> /// 用于渲染字符串。 /// Rendering gridder of hexadrons. /// </summary> public PointSpriteStringElement( //IScientificCamera camera, string text, Vertex position, int fontSize = 32, GLColor textColor = null) IScientificCamera camera, string content, Vertex position, GLColor textColor = null, int fontSize = 32, int maxRowWidth = 256) { if (fontSize >= 256) { throw new ArgumentException(); } this.camera = camera; this.content = content; this.position = position; this.fontSize = fontSize; if (textColor == null) { this.textColor = new vec3(1, 1, 1); } else { this.textColor = new vec3(textColor.R, textColor.G, textColor.B); } if (0 < maxRowWidth && maxRowWidth < 257) { this.maxRowWidth = maxRowWidth; } else { throw new ArgumentOutOfRangeException("max row width must between 0 and 257(not include 0 or 257)"); } this.fontResource = FontResource.Instance; }
public void Compile(FontResource fontResource, string outputPath, CompilerParameters parameters) { if ((parameters != null) && parameters.Exists("use-proxy-variable")) { useProxyVariable = true; } if ((parameters != null) && parameters.Exists("output-extension")) { outputExtension = parameters["output-extension"]; } if ((parameters != null) && parameters.Exists("include-files")) { includeFiles = parameters["include-files"]; } string fileName = String.Format("{0}.{1}", fontResource.Id, outputExtension); string path = Path.Combine(outputPath, fileName); TextWriter writer = new StreamWriter( new FileStream( path, FileMode.Create, FileAccess.Write, FileShare.None)); try { GenerateOutput(fontResource.Font, writer); } finally { writer.Close(); } }
/// <summary> /// TODO: 这里生成的中间贴图太大,有优化的空间 /// </summary> /// <param name="content"></param> private void InitTexture(string content, int fontSize, int maxRowWidth, FontResource fontResource) { Bitmap contentBitmap = fontResource.GenerateBitmapForString(content, fontSize, maxRowWidth); // get texture's size int targetTextureWidth; { this.textureWidth = contentBitmap.Width; targetTextureWidth = contentBitmap.Width; } // scale contentBitmap to right size System.Drawing.Bitmap targetImage = contentBitmap; if (contentBitmap.Width != targetTextureWidth || contentBitmap.Height != targetTextureWidth) { // Resize the image. targetImage = (System.Drawing.Bitmap)contentBitmap.GetThumbnailImage( targetTextureWidth, targetTextureWidth, null, IntPtr.Zero); } // generate texture { // Lock the image bits (so that we can pass them to OGL). BitmapData bitmapData = targetImage.LockBits( new Rectangle(0, 0, targetImage.Width, targetImage.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); //GL.ActiveTexture(GL.GL_TEXTURE0); GL.GenTextures(1, texture); GL.BindTexture(GL.GL_TEXTURE_2D, texture[0]); GL.TexImage2D(GL.GL_TEXTURE_2D, 0, (int)GL.GL_RGBA, targetImage.Width, targetImage.Height, 0, GL.GL_BGRA, GL.GL_UNSIGNED_BYTE, bitmapData.Scan0); // Unlock the image. targetImage.UnlockBits(bitmapData); /* We require 1 byte alignment when uploading texture data */ //GL.PixelStorei(GL.GL_UNPACK_ALIGNMENT, 1); /* Clamping to edges is important to prevent artifacts when scaling */ GL.TexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, (int)GL.GL_CLAMP_TO_EDGE); GL.TexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, (int)GL.GL_CLAMP_TO_EDGE); /* Linear filtering usually looks best for text */ GL.TexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, (int)GL.GL_LINEAR); GL.TexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, (int)GL.GL_LINEAR); } // release images { //targetImage.Save("PointSpriteFontElement-TargetImage.png"); if (targetImage != contentBitmap) { targetImage.Dispose(); } contentBitmap.Dispose(); } }
public bool SaveFont(string resourceFile, string fontName, string imageFileRoot) { if (Path.IsPathRooted(resourceFile) == false) { resourceFile = Path.Combine(Directory.GetCurrentDirectory(), resourceFile); } string localImagePartialPath; string dir = Path.GetDirectoryName(resourceFile); if (Path.IsPathRooted(imageFileRoot) == false) { localImagePartialPath = imageFileRoot; imageFileRoot = Path.Combine(Path.GetDirectoryName(resourceFile), imageFileRoot); } else { localImagePartialPath = GetRelativePath(dir, imageFileRoot); } localImagePartialPath = localImagePartialPath.Replace(Path.DirectorySeparatorChar.ToString(), "/"); FontResource fontResource = new FontResource(); foreach (var fs in Font.FontSurfaces) { var res = new FontSurfaceResource(); var localImagePath = localImagePartialPath + "-" + fs.Key.ToString() + ".png"; var impl = (BitmapFontImpl)fs.Value.Impl; res.Name = fontName; res.Image = localImagePath; res.Metrics = impl.FontMetrics.Clone(); res.Size = fs.Key.Size; res.Style = fs.Key.Style; var imagePath = Path.Combine(dir, localImagePath); var surface = (Surface)impl.Surface; surface.SaveTo(imagePath); fontResource.Add(res); } var fonts = new FontResourceCollection { { fontName, fontResource } }; var resLoader = new ResourceDataSerializer(); var result = resLoader.Serialize(fonts); File.WriteAllText(resourceFile, result); return(true); }
public VectorFont(FontResource res, int size) { Size = size; if (GameController.OnGodot) { _font = new Godot.DynamicFont { FontData = res.FontData, Size = size, }; } else { Handle = IoCManager.Resolve <IFontManagerInternal>().MakeInstance(res.FontFaceHandle, size); } }
/// /// Build a dictionary of font names and their associated information used to encode the data /// as unicode strings. /// private void ParseFonts(PdfPage page) { var fontResource = page.Resources.Elements.GetDictionary("/Font")?.Elements; if (fontResource == null) { return; } //All that above isn't going to do, but it's close... foreach (var fontName in fontResource.Keys) { var resource = fontResource[fontName] as PdfReference; var font = new FontResource(fontName, resource); FontLookup[fontName] = font; } }
internal static FontResource GetFontResource(string fontName, int fontSize) { EnsureFontIsRegistered(); FontResource result = null; foreach (var font in _fonts) { if (result == null) { result = font; continue; } if (fontName != null && result.fontName != fontName && font.fontName == fontName) { result = font; continue; } if (result.fontSize < fontSize && font.fontSize > result.fontSize) { result = font; continue; } if (result.fontSize > fontSize && font.fontSize >= fontSize && font.fontSize < result.fontSize) { result = font; } } if (result == null) { result = _fonts[0]; } if (fontName != null && result.fontName != fontName) { Debug.LogError("Font not found: " + fontName); } return(result); }
///// <summary> ///// 获取或设置此字符串的字体资源。 ///// </summary> //public FontResource Resource //{ // get { return this.resouce; } // set // { // if (value != this.resouce) // { // this.resouce = value; // InitTexture(this.content, this.FontSize, this.resouce); // } // } //} //public void UpdateProperties(string content, GLColor color, int fontSize, FontResource fontResource) //{ //} /// <summary> /// 用shader+VAO+组装的texture显示字符串 /// </summary> /// <param name="content">要显示的字符串</param> /// <param name="position">字符串的中心位置</param> /// <param name="color">文字颜色,默认为黑色</param> /// <param name="fontSize">字体大小,默认为32</param> /// <param name="fontResource">字体资源。默认的字体资源只支持ASCII码。</param> public PointSpriteStringElement( string content, vec3 position, GLColor color = null, int fontSize = 32, int maxRowWidth = 256, FontResource fontResource = null) { if (fontSize > 256) { throw new ArgumentException(); } this.content = content; this.position = position; if (color == null) { textColor = new vec3(0, 0, 0); } else { textColor = new vec3(color.R, color.G, color.B); } this.fontSize = fontSize; if (0 < maxRowWidth && maxRowWidth < 257) { this.maxRowWidth = maxRowWidth; } else { throw new ArgumentOutOfRangeException("max row width must between 0 and 257(not include 0 or 257)"); } if (fontResource == null) { this.resource = FontResource.Default; } else { this.resource = fontResource; } }
public VectorFont(FontResource res, int size) { Size = size; Handle = IoCManager.Resolve <IFontManagerInternal>().MakeInstance(res.FontFaceHandle, size); }
/// <summary> /// TODO: 这里生成的中间贴图太大,有优化的空间 /// </summary> /// <param name="content"></param> private void InitTexture(OpenGL gl, string content, int fontSize, int maxRowWidth, FontResource resource) { // step 1: get totalLength int totalLength = 0; { int glyphsLength = 0; for (int i = 0; i < content.Length; i++) { char c = content[i]; CharacterInfo cInfo; if (fontResource.CharInfoDict.TryGetValue(c, out cInfo)) { int glyphWidth = cInfo.width; glyphsLength += glyphWidth; } //else //{ throw new Exception(string.Format("Not support for display the char [{0}]", c)); } } //glyphsLength = (glyphsLength * this.fontSize / FontResource.Instance.FontHeight); int interval = fontResource.FontHeight / 10; if (interval < 1) { interval = 1; } //interval = fontResource.CharInfoDict[' '].width / 10; if (interval < 1) { interval = 1; } totalLength = glyphsLength + interval * (content.Length - 1); } // step 2: setup contentBitmap Bitmap contentBitmap = null; { int interval = fontResource.FontHeight / 10; if (interval < 1) { interval = 1; } //int totalLength = glyphsLength + interval * (content.Length - 1); int currentTextureWidth = 0; int currentWidthPos = 0; int currentHeightPos = 0; if (totalLength * fontSize > maxRowWidth * fontResource.FontHeight)// 超过1行能显示的内容 { currentTextureWidth = maxRowWidth * fontResource.FontHeight / fontSize; int lineCount = (totalLength - 1) / currentTextureWidth + 1; // 确保整篇文字的高度在贴图中间。 currentHeightPos = (currentTextureWidth - fontResource.FontHeight * lineCount) / 2; //- FontResource.Instance.FontHeight / 2; } else//只在一行内即可显示所有字符 { if (totalLength >= fontResource.FontHeight) { currentTextureWidth = totalLength; // 确保整篇文字的高度在贴图中间。 currentHeightPos = (currentTextureWidth - fontResource.FontHeight) / 2; //- FontResource.Instance.FontHeight / 2; } else { currentTextureWidth = fontResource.FontHeight; currentWidthPos = (currentTextureWidth - totalLength) / 2; //glyphsLength = fontResource.FontHeight; } } //this.textureWidth = textureWidth * this.fontSize / FontResource.Instance.FontHeight; //currentWidthPosition = currentWidthPosition * this.fontSize / FontResource.Instance.FontHeight; //currentHeightPosition = currentHeightPosition * this.fontSize / FontResource.Instance.FontHeight; contentBitmap = new Bitmap(currentTextureWidth, currentTextureWidth); Graphics gContentBitmap = Graphics.FromImage(contentBitmap); Bitmap bigBitmap = fontResource.FontBitmap; for (int i = 0; i < content.Length; i++) { char c = content[i]; CharacterInfo cInfo; if (fontResource.CharInfoDict.TryGetValue(c, out cInfo)) { if (currentWidthPos + cInfo.width > contentBitmap.Width) { currentWidthPos = 0; currentHeightPos += fontResource.FontHeight; } gContentBitmap.DrawImage(bigBitmap, new Rectangle(currentWidthPos, currentHeightPos, cInfo.width, fontResource.FontHeight), new Rectangle(cInfo.xoffset, cInfo.yoffset, cInfo.width, fontResource.FontHeight), GraphicsUnit.Pixel); currentWidthPos += cInfo.width + interval; } } gContentBitmap.Dispose(); //contentBitmap.Save("PointSpriteStringElement-contentBitmap.png"); System.Drawing.Bitmap bmp = null; if (totalLength * fontSize > maxRowWidth * fontResource.FontHeight)// 超过1行能显示的内容 { bmp = (System.Drawing.Bitmap)contentBitmap.GetThumbnailImage( maxRowWidth, maxRowWidth, null, IntPtr.Zero); } else//只在一行内即可显示所有字符 { if (totalLength >= fontResource.FontHeight) { bmp = (System.Drawing.Bitmap)contentBitmap.GetThumbnailImage( totalLength * fontSize / resource.FontHeight, totalLength * fontSize / resource.FontHeight, null, IntPtr.Zero); } else { bmp = (System.Drawing.Bitmap)contentBitmap.GetThumbnailImage( fontSize, fontSize, null, IntPtr.Zero); } } contentBitmap.Dispose(); contentBitmap = bmp; //contentBitmap.Save("PointSpriteStringElement-contentBitmap-scaled.png"); } // step 4: get texture's size int targetTextureWidth; { //// Get the maximum texture size supported by OpenGL. //int[] textureMaxSize = { 0 }; //GL.GetInteger(GetTarget.MaxTextureSize, textureMaxSize); //// Find the target width and height sizes, which is just the highest //// posible power of two that'll fit into the image. //targetTextureWidth = textureMaxSize[0]; ////System.Drawing.Bitmap bitmap = contentBitmap; //int scaledWidth = 8 * contentBitmap.Width * fontSize / fontResource.FontHeight; //for (int size = 1; size <= textureMaxSize[0]; size *= 2) //{ // if (scaledWidth < size) // { // targetTextureWidth = size / 2; // break; // } // if (scaledWidth == size) // targetTextureWidth = size; //} //this.textureWidth = targetTextureWidth; this.textureWidth = contentBitmap.Width; targetTextureWidth = contentBitmap.Width; } // step 5: scale contentBitmap to right size System.Drawing.Bitmap targetImage = contentBitmap; if (contentBitmap.Width != targetTextureWidth || contentBitmap.Height != targetTextureWidth) { // Resize the image. targetImage = (System.Drawing.Bitmap)contentBitmap.GetThumbnailImage( targetTextureWidth, targetTextureWidth, null, IntPtr.Zero); } // step 6: generate texture { // Lock the image bits (so that we can pass them to OGL). BitmapData bitmapData = targetImage.LockBits( new Rectangle(0, 0, targetImage.Width, targetImage.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); //gl.ActiveTexture(gl.GL_TEXTURE0); gl.GenTextures(1, texture); gl.BindTexture(OpenGL.GL_TEXTURE_2D, texture[0]); gl.TexImage2D(OpenGL.GL_TEXTURE_2D, 0, (int)OpenGL.GL_RGBA, targetImage.Width, targetImage.Height, 0, OpenGL.GL_BGRA, OpenGL.GL_UNSIGNED_BYTE, bitmapData.Scan0); // Unlock the image. targetImage.UnlockBits(bitmapData); /* We require 1 byte alignment when uploading texture data */ //gl.PixelStorei(OpenGL.GL_UNPACK_ALIGNMENT, 1); /* Clamping to edges is important to prevent artifacts when scaling */ gl.TexParameter(OpenGL.GL_TEXTURE_2D, OpenGL.GL_TEXTURE_WRAP_S, (int)OpenGL.GL_CLAMP_TO_EDGE); gl.TexParameter(OpenGL.GL_TEXTURE_2D, OpenGL.GL_TEXTURE_WRAP_T, (int)OpenGL.GL_CLAMP_TO_EDGE); /* Linear filtering usually looks best for text */ gl.TexParameter(OpenGL.GL_TEXTURE_2D, OpenGL.GL_TEXTURE_MIN_FILTER, (int)OpenGL.GL_LINEAR); gl.TexParameter(OpenGL.GL_TEXTURE_2D, OpenGL.GL_TEXTURE_MAG_FILTER, (int)OpenGL.GL_LINEAR); } // step 7: release images { //targetImage.Save("PointSpriteStringElement-TargetImage.png"); if (targetImage != contentBitmap) { targetImage.Dispose(); } contentBitmap.Dispose(); } }
internal static void RegisterFont(FontResource resource) { _fonts.Add(resource); }
public SimpleUIPointSpriteStringElement(IUILayoutParam param, string content, vec3 position, GLColor color = null, int fontSize = 32, int maxRowWidth = 256, FontResource fontResource = null) { IUILayout layout = this; layout.Param = param; this.element = new PointSpriteStringElement(content, position, color, fontSize, maxRowWidth, fontResource); }
/// <summary> /// 简单地生成一行文字。 /// </summary> /// <param name="content"></param> /// <returns></returns> public static StringModel GetModel(this string content) { StringModel model = new StringModel(); var glyphPositions = new StringModel.GlyphPosition[content.Length]; FontResource fontResource = CSharpGL.GlyphTextures.FontResource.Default; var glyphTexCoords = new StringModel.GlyphTexCoord[content.Length]; //fontResource.GenerateBitmapForString(content, 10, 10000); int currentWidth = 0; int currentHeight = 0; /* * 0 3 4 6 8 11 12 15 * ------- ------- ------- ------- * | | | | | | | | * | | | | | | | | * | | | | | | | | * ------- ------- ------- ------- * 1 2 5 6 9 10 13 14 */ for (int i = 0; i < content.Length; i++) { char ch = content[i]; CharacterInfo info = fontResource.CharInfoDict[ch]; glyphPositions[i] = new StringModel.GlyphPosition( new GLM.vec2(currentWidth, currentHeight + fontResource.FontHeight), new GLM.vec2(currentWidth, currentHeight), new GLM.vec2(currentWidth + info.width, currentHeight), new GLM.vec2(currentWidth + info.width, currentHeight + fontResource.FontHeight)); const int shrimp = 2; glyphTexCoords[i] = new StringModel.GlyphTexCoord( new GLM.vec2((float)(info.xoffset + shrimp) / (float)fontResource.FontBitmap.Width, (float)(currentHeight) / (float)fontResource.FontBitmap.Height), new GLM.vec2((float)(info.xoffset + shrimp) / (float)fontResource.FontBitmap.Width, (float)(currentHeight + fontResource.FontHeight) / (float)fontResource.FontBitmap.Height), new GLM.vec2((float)(info.xoffset - shrimp + info.width) / (float)fontResource.FontBitmap.Width, (float)(currentHeight + fontResource.FontHeight) / (float)fontResource.FontBitmap.Height), new GLM.vec2((float)(info.xoffset - shrimp + info.width) / (float)fontResource.FontBitmap.Width, (float)(currentHeight) / (float)fontResource.FontBitmap.Height) ); currentWidth += info.width + 10; } // move to center for (int i = 0; i < content.Length; i++) { StringModel.GlyphPosition position = glyphPositions[i]; position.leftUp.x -= currentWidth / 2; position.leftDown.x -= currentWidth / 2; position.rightUp.x -= currentWidth / 2; position.rightDown.x -= currentWidth / 2; position.leftUp.y -= (currentHeight + fontResource.FontHeight) / 2; position.leftDown.y -= (currentHeight + fontResource.FontHeight) / 2; position.rightUp.y -= (currentHeight + fontResource.FontHeight) / 2; position.rightDown.y -= (currentHeight + fontResource.FontHeight) / 2; position.leftUp.x /= (currentHeight + fontResource.FontHeight); position.leftDown.x /= (currentHeight + fontResource.FontHeight); position.rightUp.x /= (currentHeight + fontResource.FontHeight); position.rightDown.x /= (currentHeight + fontResource.FontHeight); position.leftUp.y /= (currentHeight + fontResource.FontHeight); position.leftDown.y /= (currentHeight + fontResource.FontHeight); position.rightUp.y /= (currentHeight + fontResource.FontHeight); position.rightDown.y /= (currentHeight + fontResource.FontHeight); glyphPositions[i] = position; } var glyphColors = new StringModel.GlyphColor[content.Length]; for (int i = 0; i < glyphColors.Length; i++) { glyphColors[i] = new StringModel.GlyphColor( new GLM.vec4(0, 0, 0, 1), new GLM.vec4(0, 0, 0, 1), new GLM.vec4(0, 0, 0, 1), new GLM.vec4(0, 0, 0, 1) ); } model.positions = glyphPositions; model.texCoords = glyphTexCoords; model.colors = glyphColors; model.glyphTexture = FontTextureManager.Instance.GetTexture2D(fontResource.FontBitmap); return(model); }
public static void Dump(FontResource rc) { Console.WriteLine(rc.ToString()); }
public override void Visit(FontResource resource) { FontResourceCompiler compiler = new FontResourceCompiler(); compiler.Compile(resource, outputFolder, parameters); }