Пример #1
0
		private void GenerateResources()
		{
			if (this.mat != null || this.texture != null || this.pixelData != null)
				this.ReleaseResources();

			int cols;
			int rows;
			cols = rows = (int)Math.Ceiling(Math.Sqrt(SupportedChars.Length));

			Pixmap.Layer pixelLayer = new Pixmap.Layer(MathF.RoundToInt(cols * this.internalFont.Size), MathF.RoundToInt(rows * (this.internalFont.Height + 1)));
			Pixmap.Layer glyphTemp;
			Pixmap.Layer glyphTempTypo;
			Bitmap bm;
			Bitmap measureBm = new Bitmap(1, 1);
			Rect[] atlas = new Rect[SupportedChars.Length];
			using (Graphics measureGraphics = Graphics.FromImage(measureBm))
			{
				Brush fntBrush = new SolidBrush(Color.Black);

				StringFormat formatDef = StringFormat.GenericDefault;
				formatDef.LineAlignment = StringAlignment.Near;
				formatDef.FormatFlags = 0;
				StringFormat formatTypo = StringFormat.GenericTypographic;
				formatTypo.LineAlignment = StringAlignment.Near;

				int x = 0;
				int y = 0;
				for (int i = 0; i < SupportedChars.Length; ++i)
				{
					string str = SupportedChars[i].ToString(CultureInfo.InvariantCulture);
					bool isSpace = str == " ";
					SizeF charSize = measureGraphics.MeasureString(str, this.internalFont, pixelLayer.Width, formatDef);

					// Render a single glyph
					bm = new Bitmap((int)Math.Ceiling(Math.Max(1, charSize.Width)), this.internalFont.Height + 1);
					using (Graphics glyphGraphics = Graphics.FromImage(bm))
					{
						glyphGraphics.Clear(Color.Transparent);
						glyphGraphics.TextRenderingHint = (System.Drawing.Text.TextRenderingHint)this.hint;
						glyphGraphics.DrawString(str, this.internalFont, fntBrush, new RectangleF(0, 0, bm.Width, bm.Height), formatDef);
					}
					glyphTemp = new Pixmap.Layer(bm);
					
					if (!isSpace)
					{
						Rectangle glyphTempBounds = glyphTemp.OpaqueBounds();
						glyphTemp.SubImage(glyphTempBounds.X, 0, glyphTempBounds.Width, glyphTemp.Height);
						if (BodyAscentRef.Contains(SupportedChars[i]))
							this.bodyAscent += glyphTempBounds.Height;
						
						// Render a single glyph in typographic mode
						bm = new Bitmap((int)Math.Ceiling(Math.Max(1, charSize.Width)), this.internalFont.Height + 1);
						using (Graphics glyphGraphics = Graphics.FromImage(bm))
						{
							glyphGraphics.Clear(Color.Transparent);
							glyphGraphics.TextRenderingHint = (System.Drawing.Text.TextRenderingHint)this.hint;
							glyphGraphics.DrawString(str, this.internalFont, fntBrush, new RectangleF(0, 0, bm.Width, bm.Height), formatTypo);
						}
						glyphTempTypo = new Pixmap.Layer(bm);
						glyphTempTypo.Crop(true, false);
					}
					else
						glyphTempTypo = glyphTemp;

					// Update xy values if it doesn't fit anymore
					if (x + glyphTemp.Width + 2 > pixelLayer.Width)
					{
						x = 0;
						y += (this.internalFont.Height + 1) + 2;
					}
					
					// Memorize atlas coordinates & glyph data
					this.maxGlyphWidth = Math.Max(this.maxGlyphWidth, glyphTemp.Width);
					this.glyphs[i].width = glyphTemp.Width;
					this.glyphs[i].height = glyphTemp.Height;
					this.glyphs[i].offsetX = glyphTemp.Width - glyphTempTypo.Width;
					if (isSpace)
					{
						this.glyphs[i].width /= 2;
						this.glyphs[i].offsetX /= 2;
					}
					atlas[i].X = x;
					atlas[i].Y = y;
					atlas[i].W = glyphTemp.Width;
					atlas[i].H = (this.internalFont.Height + 1);

					// Draw it onto the font surface
					glyphTemp.DrawOnto(pixelLayer, BlendMode.Solid, x, y);

					x += glyphTemp.Width + 2;
				}
			}

			// Adjust colors based on alpha value
			//for (int i = 0; i < pixelLayer.Data.Length; i++)
			System.Threading.Tasks.Parallel.For(0, pixelLayer.Data.Length, i =>
			{
				float factor = pixelLayer.Data[i].A / 255.0f;
				float invFactor = 1.0f - factor;
				pixelLayer.Data[i].R = (byte)Math.Min(255.0f, Math.Max(0.0f, this.bgColor.R * invFactor + this.color.R * factor));
				pixelLayer.Data[i].G = (byte)Math.Min(255.0f, Math.Max(0.0f, this.bgColor.G * invFactor + this.color.G * factor));
				pixelLayer.Data[i].B = (byte)Math.Min(255.0f, Math.Max(0.0f, this.bgColor.B * invFactor + this.color.B * factor));
				pixelLayer.Data[i].A = (byte)Math.Min(255.0f, Math.Max(0.0f, this.bgColor.A * invFactor + this.color.A * factor));
			});

			this.height = this.internalFont.Height;
			this.ascent = (int)Math.Round(this.internalFont.FontFamily.GetCellAscent(this.internalFont.Style) * this.internalFont.Size / this.internalFont.FontFamily.GetEmHeight(this.internalFont.Style));
			this.bodyAscent /= BodyAscentRef.Length;
			this.descent = (int)Math.Round(this.internalFont.FontFamily.GetCellDescent(this.internalFont.Style) * this.internalFont.GetHeight() / this.internalFont.FontFamily.GetLineSpacing(this.internalFont.Style));
			this.baseLine = (int)Math.Round(this.internalFont.FontFamily.GetCellAscent(this.internalFont.Style) * this.internalFont.GetHeight() / this.internalFont.FontFamily.GetLineSpacing(this.internalFont.Style));

			bool useNearest = this.hint == RenderHint.Monochrome || !this.filtering;

			this.pixelData = new Pixmap(pixelLayer);
			this.pixelData.Atlas = new List<Rect>(atlas);
			this.texture = new Texture(this.pixelData, 
				Texture.SizeMode.Enlarge, 
				useNearest ? OpenTK.Graphics.OpenGL.TextureMagFilter.Nearest : OpenTK.Graphics.OpenGL.TextureMagFilter.Linear,
				useNearest ? OpenTK.Graphics.OpenGL.TextureMinFilter.Nearest : OpenTK.Graphics.OpenGL.TextureMinFilter.LinearMipmapLinear);

			this.mat = new Material(this.hint == RenderHint.Monochrome ? DrawTechnique.Mask : DrawTechnique.Alpha, ColorRgba.White, this.texture);
		}
Пример #2
0
        private void GenerateResources()
        {
            if (this.mat != null || this.texture != null || this.pixelData != null)
                this.ReleaseResources();

            TextRenderingHint textRenderingHint;
            if (this.renderMode == RenderMode.MonochromeBitmap)
                textRenderingHint = TextRenderingHint.SingleBitPerPixelGridFit;
            else
                textRenderingHint = TextRenderingHint.AntiAliasGridFit;

            int cols;
            int rows;
            cols = rows = (int)Math.Ceiling(Math.Sqrt(SupportedChars.Length));

            Pixmap.Layer pixelLayer = new Pixmap.Layer(MathF.RoundToInt(cols * this.internalFont.Size * 1.2f), MathF.RoundToInt(rows * this.internalFont.Height * 1.2f));
            Pixmap.Layer glyphTemp;
            Pixmap.Layer glyphTempTypo;
            Bitmap bm;
            Bitmap measureBm = new Bitmap(1, 1);
            Rect[] atlas = new Rect[SupportedChars.Length];
            using (Graphics measureGraphics = Graphics.FromImage(measureBm))
            {
                Brush fntBrush = new SolidBrush(Color.Black);

                StringFormat formatDef = StringFormat.GenericDefault;
                formatDef.LineAlignment = StringAlignment.Near;
                formatDef.FormatFlags = 0;
                StringFormat formatTypo = StringFormat.GenericTypographic;
                formatTypo.LineAlignment = StringAlignment.Near;

                int x = 1;
                int y = 1;
                for (int i = 0; i < SupportedChars.Length; ++i)
                {
                    string str = SupportedChars[i].ToString(CultureInfo.InvariantCulture);
                    bool isSpace = str == " ";
                    SizeF charSize = measureGraphics.MeasureString(str, this.internalFont, pixelLayer.Width, formatDef);

                    // Rasterize a single glyph for rendering
                    bm = new Bitmap((int)Math.Ceiling(Math.Max(1, charSize.Width)), this.internalFont.Height + 1);
                    using (Graphics glyphGraphics = Graphics.FromImage(bm))
                    {
                        glyphGraphics.Clear(Color.Transparent);
                        glyphGraphics.TextRenderingHint = textRenderingHint;
                        glyphGraphics.DrawString(str, this.internalFont, fntBrush, new RectangleF(0, 0, bm.Width, bm.Height), formatDef);
                    }
                    glyphTemp = new Pixmap.Layer(bm);

                    // Rasterize a single glyph in typographic mode for metric analysis
                    if (!isSpace)
                    {
                        Rectangle glyphTempBounds = glyphTemp.OpaqueBounds();
                        glyphTemp.SubImage(glyphTempBounds.X, 0, glyphTempBounds.Width, glyphTemp.Height);
                        if (BodyAscentRef.Contains(SupportedChars[i]))
                            this.bodyAscent += glyphTempBounds.Height;

                        bm = new Bitmap((int)Math.Ceiling(Math.Max(1, charSize.Width)), this.internalFont.Height + 1);
                        using (Graphics glyphGraphics = Graphics.FromImage(bm))
                        {
                            glyphGraphics.Clear(Color.Transparent);
                            glyphGraphics.TextRenderingHint = textRenderingHint;
                            glyphGraphics.DrawString(str, this.internalFont, fntBrush, new RectangleF(0, 0, bm.Width, bm.Height), formatTypo);
                        }
                        glyphTempTypo = new Pixmap.Layer(bm);
                        glyphTempTypo.Crop(true, false);
                    }
                    else
                    {
                        glyphTempTypo = glyphTemp;
                    }

                    // Update xy values if it doesn't fit anymore
                    if (x + glyphTemp.Width + 2 > pixelLayer.Width)
                    {
                        x = 1;
                        y += this.internalFont.Height + MathF.Clamp((int)MathF.Ceiling(this.internalFont.Height * 0.1875f), 3, 10);
                    }

                    // Memorize atlas coordinates & glyph data
                    this.maxGlyphWidth = Math.Max(this.maxGlyphWidth, glyphTemp.Width);
                    this.glyphs[i].width = glyphTemp.Width;
                    this.glyphs[i].height = glyphTemp.Height;
                    this.glyphs[i].offsetX = glyphTemp.Width - glyphTempTypo.Width;
                    if (isSpace)
                    {
                        this.glyphs[i].width /= 2;
                        this.glyphs[i].offsetX /= 2;
                    }
                    atlas[i].X = x;
                    atlas[i].Y = y;
                    atlas[i].W = glyphTemp.Width;
                    atlas[i].H = (this.internalFont.Height + 1);

                    // Draw it onto the font surface
                    glyphTemp.DrawOnto(pixelLayer, BlendMode.Solid, x, y);

                    x += glyphTemp.Width + MathF.Clamp((int)MathF.Ceiling(this.internalFont.Height * 0.125f), 2, 10);
                }
            }

            // White out texture except alpha channel.
            for (int i = 0; i < pixelLayer.Data.Length; i++)
            {
                pixelLayer.Data[i].R = 255;
                pixelLayer.Data[i].G = 255;
                pixelLayer.Data[i].B = 255;
            }

            // Determine Font properties
            this.height = this.internalFont.Height;
            this.ascent = (int)Math.Round(this.internalFont.FontFamily.GetCellAscent(this.internalFont.Style) * this.internalFont.Size / this.internalFont.FontFamily.GetEmHeight(this.internalFont.Style));
            this.bodyAscent /= BodyAscentRef.Length;
            this.descent = (int)Math.Round(this.internalFont.FontFamily.GetCellDescent(this.internalFont.Style) * this.internalFont.GetHeight() / this.internalFont.FontFamily.GetLineSpacing(this.internalFont.Style));
            this.baseLine = (int)Math.Round(this.internalFont.FontFamily.GetCellAscent(this.internalFont.Style) * this.internalFont.GetHeight() / this.internalFont.FontFamily.GetLineSpacing(this.internalFont.Style));

            // Create internal Pixmap and Texture Resources
            this.pixelData = new Pixmap(pixelLayer);
            this.pixelData.Atlas = new List<Rect>(atlas);
            this.texture = new Texture(this.pixelData,
                Texture.SizeMode.Enlarge,
                this.IsPixelGridAligned ? TextureMagFilter.Nearest : TextureMagFilter.Linear,
                this.IsPixelGridAligned ? TextureMinFilter.Nearest : TextureMinFilter.LinearMipmapLinear);

            // Select DrawTechnique to use
            ContentRef<DrawTechnique> technique;
            if (this.renderMode == RenderMode.MonochromeBitmap)
                technique = DrawTechnique.Mask;
            else if (this.renderMode == RenderMode.GrayscaleBitmap)
                technique = DrawTechnique.Alpha;
            else if (this.renderMode == RenderMode.SmoothBitmap)
                technique = DrawTechnique.Alpha;
            else
                technique = DrawTechnique.SharpAlpha;

            // Create and configure internal BatchInfo
            BatchInfo matInfo = new BatchInfo(technique, ColorRgba.White, this.texture);
            if (technique == DrawTechnique.SharpAlpha)
            {
                matInfo.SetUniform("smoothness", this.size * 3.0f);
            }
            this.mat = new Material(matInfo);
        }
Пример #3
0
        private void LoadOrCreatePixelData(int cols, int rows, TextRenderingHint textRenderingHint)
        {
            Pixmap.Layer pixelLayer = new Pixmap.Layer(MathF.RoundToInt(cols*this.internalFont.Size*1.2f), MathF.RoundToInt(rows*this.internalFont.Height*1.2f));
            Pixmap.Layer glyphTemp;
            Pixmap.Layer glyphTempTypo;
            Bitmap bm;
            Bitmap measureBm = new Bitmap(1, 1);
            Rect[] atlas = new Rect[SupportedChars.Length];
            using (Graphics measureGraphics = Graphics.FromImage(measureBm))
            {
                Brush fntBrush = new SolidBrush(Color.Black);

                StringFormat formatDef = StringFormat.GenericDefault;
                formatDef.LineAlignment = StringAlignment.Near;
                formatDef.FormatFlags = 0;
                StringFormat formatTypo = StringFormat.GenericTypographic;
                formatTypo.LineAlignment = StringAlignment.Near;

                int x = 1;
                int y = 1;
                for (int i = 0; i < SupportedChars.Length; ++i)
                {
                    string str = SupportedChars[i].ToString(CultureInfo.InvariantCulture);
                    bool isSpace = str == " ";
                    SizeF charSize = measureGraphics.MeasureString(str, this.internalFont, pixelLayer.Width, formatDef);

                    // Rasterize a single glyph for rendering
                    bm = new Bitmap((int)Math.Ceiling(Math.Max(1, charSize.Width)), this.internalFont.Height + 1);
                    using (Graphics glyphGraphics = Graphics.FromImage(bm))
                    {
                        glyphGraphics.Clear(Color.Transparent);
                        glyphGraphics.TextRenderingHint = textRenderingHint;
                        glyphGraphics.DrawString(str, this.internalFont, fntBrush, new RectangleF(0, 0, bm.Width, bm.Height), formatDef);
                    }
                    glyphTemp = new Pixmap.Layer(bm);

                    // Rasterize a single glyph in typographic mode for metric analysis
                    if (!isSpace)
                    {
                        Rectangle glyphTempBounds = glyphTemp.OpaqueBounds();
                        glyphTemp.SubImage(glyphTempBounds.X, 0, glyphTempBounds.Width, glyphTemp.Height);
                        if (BodyAscentRef.Contains(SupportedChars[i]))
                            this.bodyAscent += glyphTempBounds.Height;

                        bm = new Bitmap((int) Math.Ceiling(Math.Max(1, charSize.Width)), this.internalFont.Height + 1);
                        using (Graphics glyphGraphics = Graphics.FromImage(bm))
                        {
                            glyphGraphics.Clear(Color.Transparent);
                            glyphGraphics.TextRenderingHint = textRenderingHint;
                            glyphGraphics.DrawString(str, this.internalFont, fntBrush, new RectangleF(0, 0, bm.Width, bm.Height), formatTypo);
                        }
                        glyphTempTypo = new Pixmap.Layer(bm);
                        glyphTempTypo.Crop(true, false);
                    }
                    else
                    {
                        glyphTempTypo = glyphTemp;
                    }

                    // Update xy values if it doesn't fit anymore
                    if (x + glyphTemp.Width + 2 > pixelLayer.Width)
                    {
                        x = 1;
                        y += this.internalFont.Height + MathF.Clamp((int) MathF.Ceiling(this.internalFont.Height*0.1875f), 3, 10);
                    }

                    // Memorize atlas coordinates & glyph data
                    this.maxGlyphWidth = Math.Max(this.maxGlyphWidth, glyphTemp.Width);
                    this.glyphs[i].width = glyphTemp.Width;
                    this.glyphs[i].height = glyphTemp.Height;
                    this.glyphs[i].offsetX = glyphTemp.Width - glyphTempTypo.Width;
                    if (isSpace)
                    {
                        this.glyphs[i].width /= 2;
                        this.glyphs[i].offsetX /= 2;
                    }
                    atlas[i].X = x;
                    atlas[i].Y = y;
                    atlas[i].W = glyphTemp.Width;
                    atlas[i].H = (this.internalFont.Height + 1);

                    // Draw it onto the font surface
                    glyphTemp.DrawOnto(pixelLayer, BlendMode.Solid, x, y);

                    x += glyphTemp.Width + MathF.Clamp((int) MathF.Ceiling(this.internalFont.Height*0.125f), 2, 10);

                    if(glyphTempTypo != glyphTemp)
                        glyphTempTypo.Dispose();

                    glyphTemp.Dispose();
                }
            }

            // White out texture except alpha channel.
            for (int i = 0; i < pixelLayer.Data.Length; i++)
            {
                pixelLayer.Data[i].R = 255;
                pixelLayer.Data[i].G = 255;
                pixelLayer.Data[i].B = 255;
            }

            this.pixelData = new Pixmap(pixelLayer) {Atlas = new List<Rect>(atlas)};
        }