Пример #1
0
        private void ValidateVertexCache()
        {
            if (this.vertTextCache != null &&
                this.vertIconsCache != null &&
                this.vertCountCache != null &&
                this.metricsCache != null &&
                !this.updateVertexCache)
            {
                // No need to update.
                return;
            }
            this.updateVertexCache = false;

            int fontNum = this.fonts != null ? this.fonts.Length : 0;

            // Setting up buffers
            {
                int countCacheLen = 1 + fontNum;
                if (this.vertCountCache == null || this.vertCountCache.Length != countCacheLen)
                    this.vertCountCache = new int[countCacheLen];

                int iconVertCount = this.iconCount * 4;
                if (this.vertIconsCache == null || this.vertIconsCache.Length < iconVertCount)
                    this.vertIconsCache = new VertexC1P3T2[iconVertCount];
                this.vertCountCache[0] = iconVertCount;

                if (this.vertTextCache == null || this.vertTextCache.Length != fontNum)
                    this.vertTextCache = new VertexC1P3T2[fontNum][];
                for (int i = 0; i < this.vertTextCache.Length; i++)
                {
                    int textVertCount = this.fontGlyphCount.Length > i ? this.fontGlyphCount[i] * 4 : 0;
                    this.vertCountCache[i + 1] = textVertCount;
                    if (this.vertTextCache[i] == null || this.vertTextCache[i].Length < textVertCount)
                        this.vertTextCache[i] = new VertexC1P3T2[textVertCount];
                }
            }

            // Rendering
            {
                RenderState state = new RenderState(this);
                Element elem;
                int[] vertTextLen = new int[fontNum];
                int vertIconLen = 0;
                while ((elem = state.NextElement()) != null)
                {
                    if (elem is TextElement && state.Font != null)
                    {
                        TextElement textElem = elem as TextElement;
                        VertexC1P3T2[] textElemVert = null;
                        int count = state.Font.EmitTextVertices(
                            state.CurrentElemText,
                            ref textElemVert,
                            state.CurrentElemOffset.X,
                            state.CurrentElemOffset.Y + state.LineBaseLine - state.Font.BaseLine,
                            state.Color);
                        Array.Copy(textElemVert, 0, this.vertTextCache[state.FontIndex], state.CurrentElemTextVertexIndex, count);
                        vertTextLen[state.FontIndex] = state.CurrentElemTextVertexIndex + count;
                    }
                    else if (elem is IconElement)
                    {
                        IconElement iconElem = elem as IconElement;
                        Icon icon = iconElem.IconIndex >= 0 && iconElem.IconIndex < this.icons.Length ? this.icons[iconElem.IconIndex] : new Icon();
                        Vector2 iconOffset = icon.offset;
                        Vector2 iconSize = icon.size;
                        Rect iconUvRect = icon.uvRect;

                        this.vertIconsCache[state.CurrentElemIconVertexIndex + 0].Pos.X = state.CurrentElemOffset.X + iconOffset.X;
                        this.vertIconsCache[state.CurrentElemIconVertexIndex + 0].Pos.Y = state.CurrentElemOffset.Y + state.LineBaseLine - iconSize.Y + iconOffset.Y;
                        this.vertIconsCache[state.CurrentElemIconVertexIndex + 0].Pos.Z = 0;
                        this.vertIconsCache[state.CurrentElemIconVertexIndex + 0].Color = state.Color;
                        this.vertIconsCache[state.CurrentElemIconVertexIndex + 0].TexCoord = iconUvRect.TopLeft;

                        this.vertIconsCache[state.CurrentElemIconVertexIndex + 1].Pos.X = state.CurrentElemOffset.X + iconSize.X + iconOffset.X;
                        this.vertIconsCache[state.CurrentElemIconVertexIndex + 1].Pos.Y = state.CurrentElemOffset.Y + state.LineBaseLine - iconSize.Y + iconOffset.Y;
                        this.vertIconsCache[state.CurrentElemIconVertexIndex + 1].Pos.Z = 0;
                        this.vertIconsCache[state.CurrentElemIconVertexIndex + 1].Color = state.Color;
                        this.vertIconsCache[state.CurrentElemIconVertexIndex + 1].TexCoord = iconUvRect.TopRight;

                        this.vertIconsCache[state.CurrentElemIconVertexIndex + 2].Pos.X = state.CurrentElemOffset.X + iconSize.X + iconOffset.X;
                        this.vertIconsCache[state.CurrentElemIconVertexIndex + 2].Pos.Y = state.CurrentElemOffset.Y + state.LineBaseLine + iconOffset.Y;
                        this.vertIconsCache[state.CurrentElemIconVertexIndex + 2].Pos.Z = 0;
                        this.vertIconsCache[state.CurrentElemIconVertexIndex + 2].Color = state.Color;
                        this.vertIconsCache[state.CurrentElemIconVertexIndex + 2].TexCoord = iconUvRect.BottomRight;

                        this.vertIconsCache[state.CurrentElemIconVertexIndex + 3].Pos.X = state.CurrentElemOffset.X + iconOffset.X;
                        this.vertIconsCache[state.CurrentElemIconVertexIndex + 3].Pos.Y = state.CurrentElemOffset.Y + state.LineBaseLine + iconOffset.Y;
                        this.vertIconsCache[state.CurrentElemIconVertexIndex + 3].Pos.Z = 0;
                        this.vertIconsCache[state.CurrentElemIconVertexIndex + 3].Color = state.Color;
                        this.vertIconsCache[state.CurrentElemIconVertexIndex + 3].TexCoord = iconUvRect.BottomLeft;

                        vertIconLen = state.CurrentElemIconVertexIndex + 4;
                    }
                }

                this.vertCountCache[0] = vertIconLen;
                for (int i = 0; i < fontNum; i++)
                    this.vertCountCache[i + 1] = vertTextLen[i];
            }

            // Updating the metrics cache
            {
                Vector2 size = Vector2.Zero;
                List<Rect> lineBounds = new List<Rect>(16);
                List<Rect> elementBounds = new List<Rect>(this.elements.Length);

                RenderState state = new RenderState(this);
                Element elem;
                Vector2 elemSize;
                Vector2 elemOffset;
                int lastElemIndex = -1;
                int lastLineIndex = 0;
                bool elemIndexChanged = true;
                bool lineChanged = true;
                bool hasBounds;
                while ((elem = state.NextElement()) != null)
                {
                    if (elem is TextElement && state.Font != null)
                    {
                        TextElement textElem = elem as TextElement;
                        elemSize = state.Font.MeasureText(state.CurrentElemText);
                        elemOffset = new Vector2(state.CurrentElemOffset.X, state.CurrentElemOffset.Y + state.LineBaseLine - state.Font.BaseLine);
                    }
                    else if (elem is IconElement && this.icons != null)
                    {
                        IconElement iconElem = elem as IconElement;
                        bool iconValid = iconElem.IconIndex > 0 && iconElem.IconIndex < this.icons.Length;
                        elemSize = iconValid ? this.icons[iconElem.IconIndex].size : Vector2.Zero;
                        elemOffset = new Vector2(state.CurrentElemOffset.X, state.CurrentElemOffset.Y + state.LineBaseLine - elemSize.Y);
                    }
                    else
                    {
                        elemSize = Vector2.Zero;
                        elemOffset = Vector2.Zero;
                    }
                    hasBounds = elemSize != Vector2.Zero;

                    if (elemIndexChanged) elementBounds.Add(Rect.Empty);
                    if (hasBounds && elementBounds[elementBounds.Count - 1] == Rect.Empty)
                        elementBounds[elementBounds.Count - 1] = new Rect(elemOffset.X, elemOffset.Y, elemSize.X, elemSize.Y);
                    else if (hasBounds)
                        elementBounds[elementBounds.Count - 1] = elementBounds[elementBounds.Count - 1].ExpandedToContain(elemOffset.X, elemOffset.Y, elemSize.X, elemSize.Y);

                    if (lineChanged) lineBounds.Add(Rect.Empty);
                    if (hasBounds && lineBounds[lineBounds.Count - 1] == Rect.Empty)
                        lineBounds[lineBounds.Count - 1] = new Rect(elemOffset.X, elemOffset.Y, elemSize.X, elemSize.Y);
                    else if (hasBounds)
                        lineBounds[lineBounds.Count - 1] = lineBounds[lineBounds.Count - 1].ExpandedToContain(elemOffset.X, elemOffset.Y, elemSize.X, elemSize.Y);

                    size.X = Math.Max(size.X, elemOffset.X + elemSize.X);
                    size.Y = Math.Max(size.Y, elemOffset.Y + elemSize.Y);

                    elemIndexChanged = lastElemIndex != state.CurrentElemIndex;
                    lineChanged = lastLineIndex != state.CurrentLineIndex;
                    lastElemIndex = state.CurrentElemIndex;
                    lastLineIndex = state.CurrentLineIndex;
                }

                this.metricsCache = new Metrics(size, lineBounds, elementBounds);
            }
        }
Пример #2
0
        /// <summary>
        /// Renders a text to the specified target Image.
        /// </summary>
        /// <param name="text"></param>
        /// <param name="target"></param>
        public void RenderToBitmap(string text, PixelData target, float x = 0.0f, float y = 0.0f, PixelData icons = null)
        {
            // Rendering
            int fontNum = this.fonts != null ? this.fonts.Length : 0;
            RenderState state = new RenderState(this);
            Element elem;
            while ((elem = state.NextElement()) != null)
            {
                if (elem is TextElement && state.Font != null)
                {
                    TextElement textElem = elem as TextElement;
                    state.Font.RenderToBitmap(
                        state.CurrentElemText,
                        target,
                        x + state.CurrentElemOffset.X,
                        y + state.CurrentElemOffset.Y + state.LineBaseLine - state.Font.BaseLine,
                        state.Color);
                }
                else if (elem is IconElement)
                {
                    IconElement iconElem = elem as IconElement;
                    Icon icon = iconElem.IconIndex >= 0 && iconElem.IconIndex < this.icons.Length ? this.icons[iconElem.IconIndex] : new Icon();
                    Vector2 iconSize = icon.size;
                    Vector2 iconOffset = icon.offset;
                    Rect iconUvRect = icon.uvRect;
                    Vector2 dataCoord = iconUvRect.Pos * new Vector2(icons.Width, icons.Height);
                    Vector2 dataSize = iconUvRect.Size * new Vector2(icons.Width, icons.Height);

                    PixelData iconLayer = icons.CloneSubImage(
                        MathF.RoundToInt(dataCoord.X),
                        MathF.RoundToInt(dataCoord.Y),
                        MathF.RoundToInt(dataSize.X),
                        MathF.RoundToInt(dataSize.Y));
                    iconLayer.Rescale(
                        MathF.RoundToInt(iconSize.X),
                        MathF.RoundToInt(iconSize.Y));
                    iconLayer.DrawOnto(target,
                        BlendMode.Alpha,
                        MathF.RoundToInt(x + state.CurrentElemOffset.X + iconOffset.X),
                        MathF.RoundToInt(y + state.CurrentElemOffset.Y + state.LineBaseLine - iconSize.Y + iconOffset.Y),
                        iconLayer.Width,
                        iconLayer.Height,
                        0,
                        0,
                        state.Color);

                }
            }
        }
Пример #3
0
		/// <summary>
		/// Measures the formatted text block.
		/// </summary>
		/// <returns>A <see cref="Metrics"/> object that describes this FormattedText.</returns>
		public Metrics Measure()
		{
			Vector2 size = Vector2.Zero;
			List<Rect> lineBounds = new List<Rect>();
			List<Rect> elementBounds = new List<Rect>();

			RenderState state = new RenderState(this);
			Element elem;
			Vector2 elemSize;
			Vector2 elemOffset;
			int lastElemIndex = -1;
			int lastLineIndex = 0;
			bool elemIndexChanged = true;
			bool lineChanged = true;
			bool hasBounds;
			while ((elem = state.NextElement()) != null)
			{
				if (elem is TextElement && state.Font != null)
				{
					TextElement textElem = elem as TextElement;
					elemSize = state.Font.MeasureText(state.CurrentElemText);
					elemOffset = new Vector2(state.CurrentElemOffset.X, state.CurrentElemOffset.Y/* + state.LineBaseLine - state.Font.Ascent*/);
					//if (elemSize.Y != 0.0f) elemSize.Y -= state.LineBaseLine - state.Font.Ascent;
				}
				else if (elem is IconElement && this.icons != null)
				{
					IconElement iconElem = elem as IconElement;
					bool iconValid = iconElem.IconIndex > 0 && iconElem.IconIndex < this.icons.Length;
					elemSize = iconValid ? this.icons[iconElem.IconIndex].size : Vector2.Zero;
					elemOffset = new Vector2(state.CurrentElemOffset.X, state.CurrentElemOffset.Y/* + state.LineBaseLine - elemSize.Y*/);
					//if (elemSize.Y != 0.0f) elemSize.Y -= state.LineBaseLine - elemSize.Y;
				}
				else
				{
					elemSize = Vector2.Zero;
					elemOffset = Vector2.Zero;
				}
				hasBounds = elemSize != Vector2.Zero;

				if (elemIndexChanged) elementBounds.Add(Rect.Empty);
				if (hasBounds && elementBounds[elementBounds.Count - 1] == Rect.Empty)
					elementBounds[elementBounds.Count - 1] = new Rect(elemOffset.X, elemOffset.Y, elemSize.X, elemSize.Y);
				else if (hasBounds)
					elementBounds[elementBounds.Count - 1] = elementBounds[elementBounds.Count - 1].ExpandToContain(elemOffset.X, elemOffset.Y, elemSize.X, elemSize.Y);
				
				if (lineChanged) lineBounds.Add(Rect.Empty);
				if (hasBounds && lineBounds[lineBounds.Count - 1] == Rect.Empty)
					lineBounds[lineBounds.Count - 1] = new Rect(elemOffset.X, elemOffset.Y, elemSize.X, elemSize.Y);
				else if (hasBounds)
					lineBounds[lineBounds.Count - 1] = lineBounds[lineBounds.Count - 1].ExpandToContain(elemOffset.X, elemOffset.Y, elemSize.X, elemSize.Y);

				size.X = Math.Max(size.X, elemOffset.X + elemSize.X);
				size.Y = Math.Max(size.Y, elemOffset.Y + elemSize.Y);

				elemIndexChanged = lastElemIndex != state.CurrentElemIndex;
				lineChanged = lastLineIndex != state.CurrentLineIndex;
				lastElemIndex = state.CurrentElemIndex;
				lastLineIndex = state.CurrentLineIndex;
			}

			return new Metrics(size, lineBounds, elementBounds);
		}
Пример #4
0
        /// <summary>
        /// Renders a text to the specified target Image.
        /// </summary>
        /// <param name="text"></param>
        /// <param name="target"></param>
        public void RenderToBitmap(string text, System.Drawing.Image target, float x = 0.0f, float y = 0.0f, System.Drawing.Image icons = null)
        {
            using (System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(target))
            {
                g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
                g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;

                // Rendering
                int fontNum = this.fonts != null ? this.fonts.Length : 0;
                RenderState state = new RenderState(this);
                Element elem;
                while ((elem = state.NextElement()) != null)
                {
                    if (elem is TextElement && state.Font != null)
                    {
                        TextElement textElem = elem as TextElement;
                        state.Font.RenderToBitmap(
                            state.CurrentElemText,
                            target,
                            x + state.CurrentElemOffset.X,
                            y + state.CurrentElemOffset.Y + state.LineBaseLine - state.Font.BaseLine,
                            state.Color);
                    }
                    else if (elem is IconElement)
                    {
                        IconElement iconElem = elem as IconElement;
                        Icon icon = iconElem.IconIndex >= 0 && iconElem.IconIndex < this.icons.Length ? this.icons[iconElem.IconIndex] : new Icon();
                        Vector2 iconSize = icon.size;
                        Vector2 iconOffset = icon.offset;
                        Rect iconUvRect = icon.uvRect;
                        Vector2 dataCoord = iconUvRect.Pos * new Vector2(icons.Width, icons.Height);
                        Vector2 dataSize = iconUvRect.Size * new Vector2(icons.Width, icons.Height);

                        var attrib = new System.Drawing.Imaging.ImageAttributes();
                        attrib.SetColorMatrix(new System.Drawing.Imaging.ColorMatrix(new[] {
                            new[] {state.Color.R / 255.0f, 0, 0, 0},
                            new[] {0, state.Color.G / 255.0f, 0, 0},
                            new[] {0, 0, state.Color.B / 255.0f, 0},
                            new[] {0, 0, 0, state.Color.A / 255.0f} }));
                        g.DrawImage(icons,
                            new System.Drawing.Rectangle(
                                MathF.RoundToInt(x + state.CurrentElemOffset.X + iconOffset.X),
                                MathF.RoundToInt(y + state.CurrentElemOffset.Y + state.LineBaseLine - iconSize.Y + iconOffset.Y),
                                MathF.RoundToInt(iconSize.X),
                                MathF.RoundToInt(iconSize.Y)),
                            dataCoord.X, dataCoord.Y, dataSize.X, dataSize.Y,
                            System.Drawing.GraphicsUnit.Pixel,
                            attrib);
                    }
                }
            }
        }
Пример #5
0
		private void ValidateVertexCache()
		{
			if (this.vertTextCache != null && this.vertIconsCache != null && !this.updateVertexCache) return;
			this.updateVertexCache = false;

			int fontNum = this.fonts != null ? this.fonts.Length : 0;

			// Setting up vertex buffers
			if (this.vertIconsCache == null || this.vertIconsCache.Length != this.iconCount * 4)
				this.vertIconsCache = new VertexC1P3T2[this.iconCount * 4];
			if (this.vertTextCache == null || this.vertTextCache.Length != fontNum) 
				this.vertTextCache = new VertexC1P3T2[fontNum][];
			for (int i = 0; i < this.vertTextCache.Length; i++)
				if (this.vertTextCache[i] == null || this.vertTextCache[i].Length != (this.fontGlyphCount.Length > i ? this.fontGlyphCount[i] * 4 : 0)) 
					this.vertTextCache[i] = new VertexC1P3T2[this.fontGlyphCount.Length > i ? this.fontGlyphCount[i] * 4 : 0];

			// Rendering
			RenderState state = new RenderState(this);
			Element elem;
			int[] vertTextLen = new int[fontNum];
			int vertIconLen = 0;
			while ((elem = state.NextElement()) != null)
			{
				if (elem is TextElement && state.Font != null)
				{
					TextElement textElem = elem as TextElement;
					VertexC1P3T2[] textElemVert = null;
					state.Font.EmitTextVertices(
						state.CurrentElemText, 
						ref textElemVert, 
						state.CurrentElemOffset.X, 
						state.CurrentElemOffset.Y + state.LineBaseLine - state.Font.BaseLine, 
						state.Color);
					Array.Copy(textElemVert, 0, this.vertTextCache[state.FontIndex], state.CurrentElemTextVertexIndex, textElemVert.Length);
					vertTextLen[state.FontIndex] = state.CurrentElemTextVertexIndex + textElemVert.Length;
				}
				else if (elem is IconElement)
				{
					IconElement iconElem = elem as IconElement;
					Icon icon = iconElem.IconIndex >= 0 && iconElem.IconIndex < this.icons.Length ? this.icons[iconElem.IconIndex] : new Icon();
					Vector2 iconSize = icon.size;
					Rect iconUvRect = icon.uvRect;

					this.vertIconsCache[state.CurrentElemIconVertexIndex + 0].Pos.X = state.CurrentElemOffset.X;
					this.vertIconsCache[state.CurrentElemIconVertexIndex + 0].Pos.Y = state.CurrentElemOffset.Y + state.LineBaseLine - iconSize.Y;
					this.vertIconsCache[state.CurrentElemIconVertexIndex + 0].Pos.Z = 0;
					this.vertIconsCache[state.CurrentElemIconVertexIndex + 0].Color = state.Color;
					this.vertIconsCache[state.CurrentElemIconVertexIndex + 0].TexCoord = iconUvRect.TopLeft;

					this.vertIconsCache[state.CurrentElemIconVertexIndex + 1].Pos.X = state.CurrentElemOffset.X + iconSize.X;
					this.vertIconsCache[state.CurrentElemIconVertexIndex + 1].Pos.Y = state.CurrentElemOffset.Y + state.LineBaseLine - iconSize.Y;
					this.vertIconsCache[state.CurrentElemIconVertexIndex + 1].Pos.Z = 0;
					this.vertIconsCache[state.CurrentElemIconVertexIndex + 1].Color = state.Color;
					this.vertIconsCache[state.CurrentElemIconVertexIndex + 1].TexCoord = iconUvRect.TopRight;

					this.vertIconsCache[state.CurrentElemIconVertexIndex + 2].Pos.X = state.CurrentElemOffset.X + iconSize.X;
					this.vertIconsCache[state.CurrentElemIconVertexIndex + 2].Pos.Y = state.CurrentElemOffset.Y + state.LineBaseLine;
					this.vertIconsCache[state.CurrentElemIconVertexIndex + 2].Pos.Z = 0;
					this.vertIconsCache[state.CurrentElemIconVertexIndex + 2].Color = state.Color;
					this.vertIconsCache[state.CurrentElemIconVertexIndex + 2].TexCoord = iconUvRect.BottomRight;

					this.vertIconsCache[state.CurrentElemIconVertexIndex + 3].Pos.X = state.CurrentElemOffset.X;
					this.vertIconsCache[state.CurrentElemIconVertexIndex + 3].Pos.Y = state.CurrentElemOffset.Y + state.LineBaseLine;
					this.vertIconsCache[state.CurrentElemIconVertexIndex + 3].Pos.Z = 0;
					this.vertIconsCache[state.CurrentElemIconVertexIndex + 3].Color = state.Color;
					this.vertIconsCache[state.CurrentElemIconVertexIndex + 3].TexCoord = iconUvRect.BottomLeft;

					vertIconLen = state.CurrentElemIconVertexIndex + 4;
				}
			}

			for (int i = 0; i < fontNum; i++)
			{
				if (this.vertTextCache[i].Length > vertTextLen[i])
					Array.Resize(ref this.vertTextCache[i], vertTextLen[i]);
			}
			if (this.vertIconsCache.Length > vertIconLen)
				Array.Resize(ref this.vertIconsCache, vertIconLen);
		}