/// <inheritdoc/>
        public Boolean Equals(ShapedStringBuilder other)
        {
            if (other == null || other.Length != Length)
            {
                return(false);
            }

            if (IsEmpty && other.Length == 0)
            {
                return(true);
            }

            if (Source is IStringSource <ShapedChar> src)
            {
                for (int ixstr = Start, ixother = 0; ixother < Length; ixstr++, ixother++)
                {
                    if (src[ixstr] != other[ixother])
                    {
                        return(false);
                    }
                }
                return(true);
            }

            return(false);
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="ShapedStringSegment"/> structure.
        /// </summary>
        /// <param name="source">The source <see cref="ShapedStringBuilder"/> object from which the segment's shaped characters are retrieved.</param>
        public ShapedStringSegment(ShapedStringBuilder source)
        {
            Contract.Require(source, nameof(source));

            this.Source = source;
            this.Start  = 0;
            this.Length = source.Length;

            this.hashCode = CalculateHashCode(source, 0, source.Length);
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="ShapedStringSegment"/> structure.
        /// </summary>
        /// <param name="source">The source <see cref="ShapedStringBuilder"/> object from which the segment's characters are retrieved.</param>
        /// <param name="start">The index of the segment's first shaped character within its parent shaped string.</param>
        /// <param name="length">The number of shaped characters in the string segment.</param>
        public ShapedStringSegment(ShapedStringBuilder source, Int32 start, Int32 length)
        {
            Contract.Require(source, nameof(source));
            Contract.EnsureRange(start >= 0 && start <= source.Length, nameof(start));
            Contract.EnsureRange(length >= 0 && start + length <= source.Length, nameof(length));

            this.Source = source;
            this.Start  = start;
            this.Length = length;

            this.hashCode = CalculateHashCode(source, start, length);
        }
 /// <summary>
 /// Appends the contents of a subset of this shaping buffer to the specified <see cref="ShapedStringBuilder"/> instance.
 /// </summary>
 /// <param name="builder">The <see cref="ShapedStringBuilder"/> instance to which to append this shaper's contents.</param>
 /// <param name="fontFace">The font face with which to shape the string.</param>
 /// <param name="start">The offset of the character in the original string which corresponds to the beginning of the shaped substring.</param>
 /// <param name="length">The number of characters in the raw substring from which to create the shaped substring.</param>
 /// <param name="sourceIndexOffset">The offset which is applied to the source indices assigned to shaped characters in the resulting string.</param>
 public abstract void AppendTo(ShapedStringBuilder builder, UltravioletFontFace fontFace, Int32 start, Int32 length, Int32 sourceIndexOffset = 0);