/// <summary>
        /// ReadAnoDatBlock reads an "OiAnoDat" block.
        /// </summary>
        /// <param name="properties">The properties to be updated with the data.</param>
        /// <param name="stream">The stream to read the data in.</param>
        /// <param name="dataSize">The size of the data</param>
        private static bool ReadAnoDatBlock(WangAnnotationProperties properties, IWangStream stream, int dataSize)
        {
#if DEBUG
            Debug.Assert(stream.AvailableBytes() >= dataSize);
#endif // DEBUG
            if (properties.HasMarkAttributes)
            {
                switch (properties.MarkAttributes.Type)
                {
                case WangMarkType.StraightLine:
                case WangMarkType.FreehandLine:
                case WangMarkType.HollowPolygon:
                case WangMarkType.FilledPolygon:
                    int [] points = WangAnnotationStructureReader.ReadPoints(stream, dataSize);
                    properties.SetPoints(points);
                    return(true);

                case WangMarkType.ImageEmbedded:
                    WangRotation rotation = WangAnnotationStructureReader.ReadRotation(stream, dataSize);
                    properties.SetRotation(rotation);
                    return(true);

                default:
                    // TODO - David Ometto - 2016-11-22 - Add support for all types
                    break;
                }
            }
            return(false);
        }
        /// <summary>
        /// OnNewMark has to be called when a new mark starts.
        /// </summary>
        /// <remarks>
        /// The previous mark is sent to the handler and the properties are initialized with default properties and the mark attributes.
        /// </remarks>
        /// <param name="handler">The Wang annotation handler.</param>
        /// <param name="propertiesCurrent">The current properties.</param>
        /// <param name="stream">The stream to read the data in.</param>
        /// <param name="dataSize">The size of the block.</param>
        /// <param name="propertiesDefault">The default properties.</param>
        /// <returns>true if the operation succeeded otherwise returns false.</returns>
        private static bool OnNewMark(IWangAnnotationHandler handler, WangAnnotationProperties propertiesCurrent,
                                      IWangStream stream, int dataSize, WangAnnotationProperties propertiesDefault)
        {
            if (propertiesCurrent.HasMarkAttributes && !WangAnnotationTranslator.Send(handler, propertiesCurrent))
            {
                return(false);
            }

            propertiesCurrent.CopyFrom(propertiesDefault);

            WangMarkAttributes markAttributes = WangAnnotationStructureReader.ReadMarkAttributes(stream, dataSize);

            if (markAttributes == null)
            {
                return(false);
            }
            propertiesCurrent.SetMarkAttributes(markAttributes);
            return(true);
        }
        /// <summary>
        /// ReadDisplayText reads a structure designed to hold display text.
        /// </summary>
        /// <remarks>
        /// This methods aplies when the specifications are mentionning the availability of a OIAN_TEXTPRIVDATA structure.
        /// </remarks>
        /// <param name="stream">The stream to read the data in.</param>
        /// <param name="dataSize">The size of the data to read.</param>
        /// <returns>The data read.</returns>
        public static WangDisplayText ReadDisplayText(IWangStream stream, int dataSize)
        {
            // At least 4 values with 4 bytes are required
            if (dataSize >= 16)
            {
                /*
                 * Type         Name                Description
                 * int          nCurrentOrientation Angle of text baseline to image in tenths of a degree; valid values are 0, 900, 1800, 2700.
                 *
                 * UINT         uReserved1          Always 1000 when writing ignore when reading.
                 *
                 * UINT         uCreationScale      Always 72000 divided by the vertical resolution of the  base image when writing.
                 *                                  Used to modify the Attributes.lfFont.lfHeight variable for display.
                 *
                 * UINT         uAnoTextLength      64K byte limit (32K for multi-byte data) for Attach-a-Note, typed text, text from file;
                 *                                  255 byte limit for text stamp.
                 *
                 * char         szAnoText[*]        Text string for text mark types.
                 */


                int orientation = stream.ReadInt32();
#if DEBUG
                Debug.Assert(orientation == 0 || orientation == 900 || orientation == 1800 || orientation == 2700);
#endif // DEBUG
                UInt32 uReserved1 = stream.ReadUint32();
#if DEBUG
                // 1000 is the value described within the specs but we have some cases with something else.
                // Debug.Assert(uReserved1 == 1000 );
#endif // DEBUG
                uint creationScale = stream.ReadUint32();
                int  textSize      = (int)stream.ReadUint32();
                // It is necessary to have enough data for the characters.
                if (textSize <= (dataSize - 16))
                {
                    string text = WangAnnotationStructureReader.ReadCharString(stream, textSize);
                    stream.SkipBytes(dataSize - 16 - textSize);
                    return(new WangDisplayText(orientation, creationScale, text));
                }
            }
            return(null);
        }
        /// <summary>
        /// ReadNamedBlockHeader reads a named block header.
        /// </summary>
        /// <param name="stream">The stream to read the data in.</param>
        /// <param name="count">The number of bytes to character to read in the buffer.</param>
        /// <returns>The data read, null if an error occurred.</returns>
        public static WangNamedBlockHeader ReadNamedBlockHeader(IWangStream stream, int count)
        {
            // The expected data size is fixed.
            if (count == 12)
            {
                /*
                 * 8 bytes  =  name of named block
                 * 4 bytes  =  size (n) of named block
                 * 4 bytes  =  reserved. Only present and necessary with  Intel 16-bit format. Skip on read and write as zeros.
                 */
                WangNamedBlockHeader header =
                    new WangNamedBlockHeader(WangAnnotationStructureReader.ReadCharString(stream, 8), stream.ReadInt32());

                // TODO - David Ometto - 2016-11-21 - Add support for non Intel, big endian and 16 bit fun to handle here
                // Only present and necessary with  Intel 16-bit format. Skip on read and write as zeros.

                return(header);
            }
            return(null);
        }
        /// <summary>
        /// ReadMarkAttributes reads a structure designed to hold mark attributes.
        /// </summary>
        /// <remarks>
        /// This methods aplies when the specifications are mentionning the availability of a OIAN_MARK_ATTRIBUTES structure.
        /// </remarks>
        /// <param name="stream">The stream to read the data in.</param>
        /// <param name="dataSize">The size of the data to read.</param>
        /// <returns>The data read.</returns>
        public static WangMarkAttributes ReadMarkAttributes(IWangStream stream, int dataSize)
        {
            // The expected data size is fixed.
            if (dataSize == 164)
            {
                /*
                 * Type         Name                Description
                 * UINT         uType               The type of the mark.
                 * LRECT        lrBounds            Rectangle in FULLSIZE units; equivalent to type RECT.
                 *                                  Can be a rectangle or two points.
                 * RGBQUAD      rgbColor1           The main color; for example, the color of all lines, all rectangles, and standalone text.
                 * RGBQUAD      rgbColor2           The secondary color; for example, the color of the text of an Attach-a-Note.
                 * BOOL         bHighlighting       TRUE - The mark is drawn highlighted. Highlighting
                 *                                  performs the same function as a highlighting marker on a
                 *                                  piece of paper. Valid only for lines, rectangles, and
                 *                                  freehand.
                 * BOOL         bTransparent        TRUE - The mark is drawn transparent. A transparent
                 *                                  mark does not draw white pixels. That is, transparent
                 *                                  replaces white pixels with whatever is behind those pixels.
                 *                                  Available only for images.
                 * UINT         uLineSize           The width of the line in pixels.
                 * UINT         uReserved1          Reserved; must be set to 0.
                 * UINT         uReserved2          Reserved; must be set to 0.
                 * LOGFONT      lfFont              The font information for the text, consisting of standard
                 *                                  font attributes of font size, name, style, effects, and
                 *                                  background color.
                 * DWORD        bReserved3          Reserved; must be set to 0.
                 * time_t       Time                The time that the mark was first saved, in seconds, from
                 *                                  00:00:00 1-1-1970 GMT. Every annotation mark has
                 *                                  time as one of its attributes. If you do not set the time before
                 *                                  the file is saved, the time is set to the date and time that the
                 *                                  save was initiated. This time is in the form returned by the
                 *                                  "time" C call, which is the number of seconds since
                 *                                  midnight 00:00:00 on 1-1-1970 GMT. If necessary, refer
                 *                                  to your C documentation for a more detailed description.
                 * BOOL         bVisible            TRUE - The mark is currently set to be visible.
                 *                                  Annotation marks can be visible or hidden.
                 * DWORD        dwReserved4         Reserved; must be set to 0x0FF83F.
                 * long         lReserved[10]       Must be set to 0.
                 */

                uint         uintMarkType = stream.ReadUint32();
                WangMarkType type         = uintMarkType < ConversionWangMarkTypes.Length
                    ? ConversionWangMarkTypes[uintMarkType]
                    : WangMarkType.Invalid;
                WangMarkAttributes readData = new WangMarkAttributes(type);

                if (!WangAnnotationStructureReader.ReadRectangle(readData.Bounds, stream))
                {
                    return(null);
                }
                if (!WangAnnotationStructureReader.ReadRgbQuad(readData.Color1, stream))
                {
                    return(null);
                }
                if (!WangAnnotationStructureReader.ReadRgbQuad(readData.Color2, stream))
                {
                    return(null);
                }

                readData.Highlighting = WangAnnotationStructureReader.ReadBool(stream);
                readData.Transparent  = WangAnnotationStructureReader.ReadBool(stream);
                readData.LineSize     = stream.ReadUint32();
                uint uReserved1 = stream.ReadUint32();
#if DEBUG
                // Reserved; must be set to 0.
                Debug.Assert(uReserved1 == 0);
#endif // DEBUG
                uint uReserved2 = stream.ReadUint32();
#if DEBUG
                // Reserved; must be set to 0.
                Debug.Assert(uReserved2 == 0);
#endif // DEBUG
                readData.LogFont = ReadLogfont(stream);

                uint bReserved3 = stream.ReadUint32();
#if DEBUG
                // Reserved; must be set to 0.
                // For some reason several file have a non 0 value there.
                // Debug.Assert(bReserved3 == 0);
#endif // DEBUG
                // Skip time
                // TODO - David Ometto - 2016-11-21 - Add support for reading time_t structure.
                stream.SkipBytes(8);

                readData.Visible = WangAnnotationStructureReader.ReadBool(stream);

                // Reserved; must be set to 0x0FF83F... but for some reason several file have a non 0 value there.
                uint dwReserved4 = stream.ReadUint32();

                // Skip 10 reserved long must be set to 0 (which is not true all of the time).
                stream.SkipBytes(40);

                return(readData);
            }
            else
            {
                return(null);
            }
        }
        /// <summary>
        /// ReadBlock reads the block and updates the properties accordingly.
        /// </summary>
        /// <param name="properties">The properties to update.</param>
        /// <param name="stream">The stream to read the data in.</param>
        /// <param name="dataSize">The size of the block.</param>
        /// <returns>true if the operation succeeded otherwise returns false.</returns>
        public static bool ReadBlock(WangAnnotationProperties properties, IWangStream stream, int dataSize)
        {
#if DEBUG
            Debug.Assert(stream.AvailableBytes() >= dataSize);
#endif // DEBUG
            WangNamedBlockHeader header = WangAnnotationStructureReader.ReadNamedBlockHeader(stream, dataSize);
            if (header == null || header.Size > stream.AvailableBytes())
            {
                return(false);
            }

            /*
             * Named Block          Associated Structure            Usage
             * OiAnoDat             For lines: AN_POINTS            List coordinates for lines and freehand marks.
             *                      For images:AN_NEW_ROTATE_STRUCT Hold scaling and resolution information for image marks.
             * OiFilNam             AN_NAME_STRUCT                  Hold file name for image marks.
             * OiDIB                AN_IMAGE_STRUCT                 Store DIB data.
             * OiGroup (required)   STR                             Create sets of marks (required).
             * OiIndex (required)   STR                             Assign unique number, originating at 0, for each mark.
             *                                                      To facilitate easy application control, the next available number is generated by incrementing by 1 the number just assigned and storing it in the default OiIndex mark.
             * OiAnText             OIAN_TEXTPRIVDATA               Display text annotation marks.
             * OiHypLnk             HYPERLINK_NB                    Turn mark into a hyperlink.
             */
            if (header.Name == "OiAnoDat")
            {
                // TODO - David Ometto - 2016-11-24 - Unit test this method
                return(ReadAnoDatBlock(properties, stream, header.Size));
            }
            else if (header.Name == "OiFilNam")
            {
                properties.SetFilename(WangAnnotationStructureReader.ReadCharString(stream, header.Size));
                return(true);
            }
            else if (header.Name == "OiDIB")
            {
                properties.SetDibInfo(WangAnnotationStructureReader.ReadDib(stream, header.Size));
                return(true);
            }
            else if (header.Name == "OiGroup")
            {
                properties.OiGroup = WangAnnotationStructureReader.ReadCharString(stream, header.Size);
                return(true);
            }
            else if (header.Name == "OiIndex")
            {
                properties.OiIndex = WangAnnotationStructureReader.ReadCharString(stream, header.Size);
                return(true);
            }
            else if (header.Name == "OiAnText")
            {
                WangDisplayText displayText = WangAnnotationStructureReader.ReadDisplayText(stream, header.Size);
                if (displayText == null)
                {
                    return(false);
                }
                properties.SetDisplayText(displayText);
                return(true);
            }
            else if (header.Name == "OiHypLnk")
            {
                WangHyperlink hyperlink = WangAnnotationStructureReader.ReadHyperlink(stream, header.Size);
                if (hyperlink == null)
                {
                    return(false);
                }
                properties.SetHyperlink(hyperlink);
                return(true);
            }
            else
            {
                // We just skip unknown data
                stream.SkipBytes(header.Size);
                return(true);
            }
        }