Esempio n. 1
0
        /// <summary>
        /// Draw this text block within specified bounds
        /// </summary>
        /// <param name="g">Graphic context</param>
        /// <param name="bounds">Bounds</param>
        public void Draw(GdiGraphics g, Rectangle bounds)
        {
            if (parts == null || proposedWidth != bounds.Width)
            {
                proposedWidth = bounds.Width;
                RecreateCache(g);
            }

            int i = 0;

            for (; i < parts.Length; i++)
            {
                Part currentPart = parts[i];

                // TODO: Rework this...
                if (currentPart.Flags == PartFlags.Alignment)
                {
                    if (currentPart.Alignment.LineWidth > 0)
                    {
                        bounds.X += (bounds.Width - currentPart.Alignment.LineWidth);
                    }
                    continue;
                }

                if (currentPart.Text.Location.Y + currentPart.Text.Height > bounds.Height)
                {
                    break;
                }

                Point p = currentPart.Text.Location;
                p.X += bounds.X;
                p.Y += bounds.Y;

                if (currentPart.Text.Font == null)
                {
                    if (imageResourceCallback != null)
                    {
                        Image image = imageResourceCallback(currentPart.Text.Value);
                        if (image != null)
                        {
                            g.ManagedGraphics.DrawImage(image, p);
                        }
                    }
                }
                else
                {
                    g.DrawString(currentPart.Text.Value, currentPart.Text.Font, currentPart.Text.Color, p);
                }
            }
        }
Esempio n. 2
0
        /// <summary>
        /// Measure height of the text block
        /// </summary>
        /// <param name="g">Graphic context</param>
        /// <returns>Height</returns>
        public int MeasureHeight(GdiGraphics g)
        {
            if (parts == null)
            {
                RecreateCache(g);
            }
            if (parts.Length == 0)
            {
                return(0);
            }

            Part lastPart = parts[parts.Length - 1];

            return(lastPart.Text.Location.Y + lastPart.Text.Height);
        }
Esempio n. 3
0
        /// <summary>
        /// Measure block content and recreate cache
        /// </summary>
        /// <param name="g">Graphic context</param>
        private void RecreateCache(GdiGraphics g)
        {
            if (text == null)
            {
                return;
            }

            List <Part> processedParts = new List <Part>();

            string unprocessedText = text;

            Color currentColor = defaultColor;
            Font  currentFont  = font;

            Point currentLocation = Point.Empty;

            int firstPartOfLine = 0;

            int lineAlignIndex = -1;

            while (unprocessedText.Length > 0)
            {
                Part part;

                int formatIndex = unprocessedText.IndexOf("\f[", StringComparison.Ordinal);
                while (formatIndex == 0)
                {
                    int formatIndexEnd = unprocessedText.IndexOf(']', formatIndex + 2);
                    if (formatIndexEnd == -1)
                    {
                        throw new InvalidDataException("Missing closing format bracket");
                    }

                    string formatString = unprocessedText.Substring(formatIndex + 2, formatIndexEnd - (formatIndex + 2));
                    switch (formatString)
                    {
                    case "Rc":      // Reset Color
                        currentColor = defaultColor;
                        break;

                    case "Rs":      // Reset Style
                        currentFont = font;
                        break;

                    case "B":       // Bold
                        currentFont = new Font(font, currentFont.Style ^ FontStyle.Bold);
                        break;

                    case "I":       // Italic
                        currentFont = new Font(font, currentFont.Style ^ FontStyle.Italic);
                        break;

                    case "U":       // Underline
                        currentFont = new Font(font, currentFont.Style ^ FontStyle.Underline);
                        break;

                    case "S":       // Strikeout
                        currentFont = new Font(font, currentFont.Style ^ FontStyle.Strikeout);
                        break;

                    case "-":       // Right Align
                        // TODO: Rework this...
                        if (lineAlignIndex == -1)
                        {
                            lineAlignIndex = processedParts.Count;

                            part       = default(Part);
                            part.Flags = PartFlags.Alignment;
                            processedParts.Add(part);
                        }
                        break;

                    default:        // Image Resource
                        if (formatString.StartsWith("image:", StringComparison.Ordinal))
                        {
                            string resourceName = formatString.Substring(6);

                            if (imageResourceCallback == null)
                            {
                                throw new NotSupportedException("ImageResourceCallback is not specified");
                            }

                            Image image = imageResourceCallback(resourceName);
                            if (image == null)
                            {
                                throw new InvalidDataException("Resource \"" + resourceName + "\" not found");
                            }

                            if (currentLocation.X + image.Width > proposedWidth)
                            {
                                PerformVerticalAlignment(processedParts, firstPartOfLine);
                                goto End;
                            }

                            part               = default(Part);
                            part.Text.Value    = resourceName;
                            part.Text.Location = currentLocation;
                            part.Text.Height   = image.Height;
                            processedParts.Add(part);

                            currentLocation.X += image.Width;
                        }
                        else         // Custom Color
                        {
                            NumberStyles styles;
                            if (formatString.StartsWith("0x", StringComparison.Ordinal))
                            {
                                formatString = formatString.Substring(2);
                                styles       = NumberStyles.HexNumber;
                            }
                            else
                            {
                                styles = NumberStyles.Integer;
                            }

                            uint color;
                            if (!uint.TryParse(formatString, styles, NumberFormatInfo.CurrentInfo, out color))
                            {
                                throw new InvalidDataException("Unknown format descriptor \"" + formatString + "\"");
                            }

                            currentColor = Color.FromArgb((int)color);
                        }
                        break;
                    }

                    unprocessedText = unprocessedText.Substring(formatIndexEnd + 1);

                    formatIndex = unprocessedText.IndexOf("\f[", StringComparison.Ordinal);
                }

                if (unprocessedText.Length == 0)
                {
                    if (lineAlignIndex != -1)
                    {
                        part = processedParts[lineAlignIndex];
                        part.Alignment.LineWidth       = currentLocation.X;
                        processedParts[lineAlignIndex] = part;
                    }

                    PerformVerticalAlignment(processedParts, firstPartOfLine);
                    break;
                }

                int    charFit, charFitWidth;
                string measuredString = (formatIndex > 0 ? unprocessedText.Substring(0, formatIndex) : unprocessedText);
                Size   size           = g.MeasureString(measuredString, currentFont, proposedWidth - currentLocation.X, out charFit, out charFitWidth);

                if (formatIndex != -1 && formatIndex <= charFit)
                {
                    int endOfLine = unprocessedText.IndexOf('\n', 0, formatIndex);
                    if (endOfLine != -1)
                    {
                        // '\n' is nearest
                        part               = default(Part);
                        part.Text.Value    = unprocessedText.Substring(0, endOfLine);
                        part.Text.Location = currentLocation;
                        part.Text.Color    = currentColor;
                        part.Text.Font     = currentFont;
                        part.Text.Height   = size.Height;
                        processedParts.Add(part);

                        if (lineAlignIndex != -1)
                        {
                            part = processedParts[lineAlignIndex];
                            part.Alignment.LineWidth       = currentLocation.X + charFitWidth;
                            processedParts[lineAlignIndex] = part;
                        }

                        PerformVerticalAlignment(processedParts, firstPartOfLine);
                        break;
                    }
                    else
                    {
                        // '\f' is nearest
                        part               = default(Part);
                        part.Text.Value    = unprocessedText.Substring(0, formatIndex);
                        part.Text.Location = currentLocation;
                        part.Text.Color    = currentColor;
                        part.Text.Font     = currentFont;
                        part.Text.Height   = size.Height;
                        processedParts.Add(part);

                        currentLocation.X += charFitWidth;

                        unprocessedText = unprocessedText.Substring(formatIndex);
                    }
                }
                else if (charFit < unprocessedText.Length)
                {
                    if (charFit > 2)
                    {
                        part               = default(Part);
                        part.Text.Value    = unprocessedText.Substring(0, charFit - 2) + "...";
                        part.Text.Location = currentLocation;
                        part.Text.Color    = currentColor;
                        part.Text.Font     = currentFont;
                        part.Text.Height   = size.Height;
                        processedParts.Add(part);
                    }

                    PerformVerticalAlignment(processedParts, firstPartOfLine);

                    break;
                }
                else
                {
                    int endOfLine = unprocessedText.IndexOf('\n');
                    if (endOfLine == -1)
                    {
                        // Value is short enough
                        part               = default(Part);
                        part.Text.Value    = unprocessedText;
                        part.Text.Location = currentLocation;
                        part.Text.Color    = currentColor;
                        part.Text.Font     = currentFont;
                        part.Text.Height   = size.Height;
                        processedParts.Add(part);

                        if (lineAlignIndex != -1)
                        {
                            part = processedParts[lineAlignIndex];
                            part.Alignment.LineWidth       = (currentLocation.X + charFitWidth);
                            processedParts[lineAlignIndex] = part;
                            lineAlignIndex = -1;
                        }

                        PerformVerticalAlignment(processedParts, firstPartOfLine);

                        unprocessedText = string.Empty;
                    }
                    else
                    {
                        // '\n' found
                        part               = default(Part);
                        part.Text.Value    = unprocessedText.Substring(0, endOfLine);
                        part.Text.Location = currentLocation;
                        part.Text.Color    = currentColor;
                        part.Text.Font     = currentFont;
                        part.Text.Height   = size.Height;
                        processedParts.Add(part);

                        if (lineAlignIndex != -1)
                        {
                            part = processedParts[lineAlignIndex];
                            part.Alignment.LineWidth       = (currentLocation.X + charFitWidth);
                            processedParts[lineAlignIndex] = part;
                        }

                        PerformVerticalAlignment(processedParts, firstPartOfLine);
                        break;
                    }
                }
            }

End:
            if (processedParts.Count > 0)
            {
                int last = processedParts.Count - 1;
                if (processedParts[last].Flags == PartFlags.Alignment)
                {
                    processedParts.RemoveAt(last);
                }
            }

            parts = processedParts.ToArray();
        }