/// <summary> /// SendFreehandLine sends a free hand line annotation to the handler. /// </summary> /// <param name="handler">The handler.</param> /// <param name="properties">The properties.</param> /// <returns>true if the operation succeeded otherwise returns false.</returns> private static bool SendFreehandLine(IWangAnnotationHandler handler, WangAnnotationProperties properties) { /* * Freehand Line * Definition: A series of lines such that the starting point of line n+1 is the same as the ending point of line n. * Attributes: rgbColor1, bHighlighting, uLineSize * Named Blocks and Associated Structures: * - OiAnoDat AN_POINTS * - OiFilNam Not used * - OiDIB Not used * - OiGroup STR * - OiIndex STR * - OiAnText Not used */ if (properties.HasPoints) { SendFreehandLine(handler, properties.OiGroup, properties.OiIndex, properties.MarkAttributes.Bounds, properties.Points, properties.MarkAttributes.Color1, properties.MarkAttributes.Highlighting, properties.MarkAttributes.LineSize); return(true); } return(false); }
/// <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> /// SendFilledPolygon sends a "Filled polygon" annotation to the handler. /// </summary> /// <param name="handler">The handler.</param> /// <param name="properties">The properties.</param> /// <returns>true if the operation succeeded otherwise returns false.</returns> private static bool SendFilledPolygon(IWangAnnotationHandler handler, WangAnnotationProperties properties) { /* * Filled Polygon * Please note this type was not mentionned within the documentation. The implementation * of this type is kind of reverse engineering. It's a mix between rectangles and free hand lines. * * Definition: A polygon with a filled center. * Attributes: rgbColor1, bHighlighting * Named Blocks and Associated Structures * - OiAnoDat AN_POINTS * - OiFilNam Not used * - OiDIB Not used * - OiGroup STR * - OiIndex STR * - OiAnText Not used */ if (properties.HasPoints) { SendFilledPolygon(handler, properties.OiGroup, properties.OiIndex, properties.MarkAttributes.Bounds, properties.Points, properties.MarkAttributes.Color1, properties.MarkAttributes.Highlighting); return(true); } return(false); }
/// <summary> /// SendTextFromFile sends a text from file annotation to the handler. /// </summary> /// <param name="handler">The handler.</param> /// <param name="properties">The properties.</param> /// <returns>true if the operation succeeded otherwise returns false.</returns> private static bool SendTextFromFile(IWangAnnotationHandler handler, WangAnnotationProperties properties) { /* * Text From File * Definition: Text supplied from a file. The file format is Text Only, which is only ASCII with carriage returns, line feeds, and tabs. * Attributes: rgbColor1, lfFont * Named Blocks and Associated Structures: * - OiAnoDat Not used * - OiFilNam Not used * - OiDIB Not used * - OiGroup STR * - OiIndex STR * - OiAnText OIAN_TEXTPRIVDATA */ if (properties.HasDisplayText) { // TODO - David Ometto - 2016-11-24 - We miss the time_t read for the moment SendTextFromFile(handler, properties.OiGroup, properties.OiIndex, properties.MarkAttributes.Bounds, properties.DisplayText.Orientation, properties.DisplayText.CreationScale, properties.DisplayText.Text, properties.MarkAttributes.Color1, properties.MarkAttributes.LogFont); return(true); } return(false); }
/// <summary> /// SendOcrRegion sends an ocr region annotation to the handler. /// </summary> /// <param name="handler">The handler.</param> /// <param name="properties">The properties.</param> /// <returns>true if the operation succeeded otherwise returns false.</returns> private static bool SendOcrRegion(IWangAnnotationHandler handler, WangAnnotationProperties properties) { /* * OCR region * Definition: A rectangular region in which to perform OCR. * Attributes: rgbColor1, lfFont * Named Blocks and Associated Structures: * - OiAnoDat Not used * - OiFilNam Not used * - OiDIB Not used * - OiGroup STR * - OiIndex STR * - OiAnText OIAN_TEXTPRIVDATA (This will contain a sequential number string). */ if (properties.HasDisplayText) { // TODO - David Ometto - 2016-11-24 - We miss the time_t read for the moment SendTextFromFile(handler, properties.OiGroup, properties.OiIndex, properties.MarkAttributes.Bounds, properties.DisplayText.Orientation, properties.DisplayText.CreationScale, properties.DisplayText.Text, properties.MarkAttributes.Color1, properties.MarkAttributes.LogFont); return(true); } return(false); }
/// <summary> /// SendTextStamp sends a text stamp annotation to the handler. /// </summary> /// <param name="handler">The handler.</param> /// <param name="properties">The properties.</param> /// <returns>true if the operation succeeded otherwise returns false.</returns> private static bool SendTextStamp(IWangAnnotationHandler handler, WangAnnotationProperties properties) { /* * Text Stamp * Definition: Text that contains a pre-defined string which may include, for example, the date and/or time when the mark was applied. * Attributes: rgbColor1, lfFont * Named Blocks and Associated Structures: * - OiAnoDat Not used * - OiFilNam Not used * - OiDIB Not used * - OiGroup STR * - OiIndex STR * - OiAnText OIAN_TEXTPRIVDATA * */ if (properties.HasDisplayText) { // TODO - David Ometto - 2016-11-24 - We miss the time_t read for the moment SendTextStamp(handler, properties.OiGroup, properties.OiIndex, properties.MarkAttributes.Bounds, properties.DisplayText.Orientation, properties.DisplayText.CreationScale, properties.DisplayText.Text, properties.MarkAttributes.Color1, properties.MarkAttributes.LogFont); return(true); } return(false); }
/// <summary> /// SendAttachANote sends an "attach a note" annotation to the handler. /// </summary> /// <param name="handler">The handler.</param> /// <param name="properties">The properties.</param> /// <returns>true if the operation succeeded otherwise returns false.</returns> private static bool SendAttachANote(IWangAnnotationHandler handler, WangAnnotationProperties properties) { /* * Attach-a-Note * Definition: A colored rectangle that contains text. * Attributes: rgbColor1, rgbColor2, lfFont * Named Blocks and Associated Structures: * - OiAnoDat Not used * - OiFilNam Not used * - OiDIB Not used * - OiGroup STR * - OiIndex STR * - OiAnText OIAN_TEXTPRIVDATA */ if (properties.HasDisplayText) { SendAttachANote(handler, properties.OiGroup, properties.OiIndex, properties.MarkAttributes.Bounds, properties.DisplayText.Orientation, properties.DisplayText.CreationScale, properties.DisplayText.Text, properties.MarkAttributes.Color1, properties.MarkAttributes.Color2, properties.MarkAttributes.LogFont); return(true); } return(false); }
/// <summary> /// OnDone has to be called when the whole data have been read. /// </summary> /// <remarks> /// The previous mark is sent to the handler if necessary. /// </remarks> /// <param name="handler">The Wang annotation handler.</param> /// <param name="propertiesCurrent">The current properties.</param> private static bool OnDone(IWangAnnotationHandler handler, WangAnnotationProperties propertiesCurrent) { if (propertiesCurrent.HasMarkAttributes) { return(WangAnnotationTranslator.Send(handler, propertiesCurrent)); } return(true); }
/// <summary> /// Send sends the annotation with the current properties to the handler. /// </summary> /// <param name="handler">The handler.</param> /// <param name="properties">The properties.</param> /// <returns>true if the operation succeeded otherwise returns false.</returns> public static bool Send(IWangAnnotationHandler handler, WangAnnotationProperties properties) { // TODO - David Ometto - 2016-11-23 - Study the best way to deal with the Visible property for each and every mark type. // Preconditions #if DEBUG Debug.Assert(properties.HasMarkAttributes); #endif //DEBUG switch (properties.MarkAttributes.Type) { case WangMarkType.StraightLine: return(SendStraightLine(handler, properties)); case WangMarkType.TypedText: return(SendTypedText(handler, properties)); case WangMarkType.AttachANote: return(SendAttachANote(handler, properties)); case WangMarkType.FilledRectangle: return(SendFilledRectangle(handler, properties)); case WangMarkType.HollowRectangle: return(SendHollowRectangle(handler, properties)); case WangMarkType.FilledPolygon: return(SendFilledPolygon(handler, properties)); case WangMarkType.HollowPolygon: return(SendHollowPolygon(handler, properties)); case WangMarkType.FreehandLine: return(SendFreehandLine(handler, properties)); case WangMarkType.ImageEmbedded: return(SendImageEmbeded(handler, properties)); case WangMarkType.TextStamp: return(SendTextStamp(handler, properties)); case WangMarkType.TextFromFile: return(SendTextFromFile(handler, properties)); case WangMarkType.OcrRegion: return(SendOcrRegion(handler, properties)); case WangMarkType.ImageReference: case WangMarkType.Form: case WangMarkType.Invalid: default: // TODO - David Ometto - 2016-11-22 - We have to develop the support for this annotation type return(false); break; } }
/// <summary> /// Read reads the Wang annotations within the provided tag data and calls the handler accordingly. /// </summary> /// <param name="handler">The Wang annotation handler.</param> /// <param name="tagData">The tag data.</param> /// <returns>true if the operation succeeded otherwise returns false.</returns> public static bool Read(IWangAnnotationHandler handler, byte[] tagData) { WangStream wangStream = new WangStream(tagData); if (!WangAnnotationsReader.ReadHeader(wangStream)) { return(false); } WangAnnotationProperties propertiesDefault = new WangAnnotationProperties(); WangAnnotationProperties propertiesCurrent = new WangAnnotationProperties(); while (!wangStream.IsEnd()) { WangDataType dataType; Int32 dataSize; bool blockRead = false; if (ReadDataType(out dataType, out dataSize, wangStream) && wangStream.AvailableBytes() >= dataSize) { switch (dataType) { case WangDataType.DefaultNamedBlock: // Data in this block will be part of each newly-created mark. blockRead = OnUpdateDefaultProperties(propertiesDefault, wangStream, dataSize); break; case WangDataType.Attributes: // The attribute structure of the next annotation mark. // This type also implies the end of the previous mark’s data, erefore the beginning of an annotation mark. blockRead = OnNewMark(handler, propertiesCurrent, wangStream, dataSize, propertiesDefault); break; case WangDataType.NamedBlock: // A named block that is part of the preceding annotation mark. blockRead = OnUpdateProperties(propertiesCurrent, wangStream, dataSize); break; } } if (!blockRead) { return(false); } } return(OnDone(handler, propertiesCurrent)); }
/// <summary> /// SendFilledRectangle sends a "Filled rectangle" annotation to the handler. /// </summary> /// <param name="handler">The handler.</param> /// <param name="properties">The properties.</param> /// <returns>true if the operation succeeded otherwise returns false.</returns> private static bool SendFilledRectangle(IWangAnnotationHandler handler, WangAnnotationProperties properties) { /* * Filled Rectangle * Definition: A rectangle with a filled center. * Attributes: rgbColor1, bHighlighting * Named Blocks and Associated Structures * - OiAnoDat Not used * - OiFilNam Not used * - OiDIB Not used * - OiGroup STR * - OiIndex STR * - OiAnText Not used */ SendFilledRectangle(handler, properties.OiGroup, properties.OiIndex, properties.MarkAttributes.Bounds, properties.MarkAttributes.Color1, properties.MarkAttributes.Highlighting); return(true); }
/// <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> /// SendImageEmbeded sends an "Image Embedded" annotation to the handler. /// </summary> /// <param name="handler">The handler.</param> /// <param name="properties">The properties.</param> /// <returns>true if the operation succeeded otherwise returns false.</returns> private static bool SendImageEmbeded(IWangAnnotationHandler handler, WangAnnotationProperties properties) { /* * Image Embedded * Definition: An embedded image. * Attributes: bTransparent * Named Blocks and Associated Stuctures * - OiAnoDat AN_NEW_ROTATE_STRUCT * - OiFilNam AN_NAME_STRUCT * - OiDIB AN_IMAGE_STRUCT * - OiGroup STR * - OiIndex STR * - OiAnText Not used */ if (properties.HasDib && properties.HasFilename && properties.HasDib) { SendImageEmbeded(handler, properties.OiGroup, properties.OiIndex, properties.MarkAttributes.Bounds, properties.MarkAttributes.Transparent, properties.Rotation, properties.Filename, properties.DibInfo); return(true); } return(false); }
/// <summary> /// SendStraightLine sends a straight line annotation to the handler. /// </summary> /// <param name="handler">The handler.</param> /// <param name="properties">The properties.</param> /// <returns>true if the operation succeeded otherwise returns false.</returns> private static bool SendStraightLine(IWangAnnotationHandler handler, WangAnnotationProperties properties) { /* * Straight Line * Definition: A line with a defined starting and ending point. * Attributes: rgbColor1, bHighlighting, uLineSize * Named Blocks and Associated Structures: * - OiAnoDat AN_POINTS * - OiFilNam Not used * - OiDIB Not used * - OiGroup STR * - OiIndex STR * - OiAnText Not used */ if (properties.HasPoints && WangAnnotationTranslation.PointsLength(properties.Points) == 2) { SendStraightLine(handler, properties.OiGroup, properties.OiIndex, properties.MarkAttributes.Bounds, properties.Points, properties.MarkAttributes.Color1, properties.MarkAttributes.Highlighting, properties.MarkAttributes.LineSize); return(true); } return(false); }
/// <summary> /// SendTypedText sends a typed text annotation to the handler. /// </summary> /// <param name="handler">The handler.</param> /// <param name="properties">The properties.</param> /// <returns>true if the operation succeeded otherwise returns false.</returns> private static bool SendTypedText(IWangAnnotationHandler handler, WangAnnotationProperties properties) { /* * Typed Text * Definition: A series of characters entered from the keyboard. * Attributes: rgbColor1, lfFont * Named Blocks and Associated Structures: * - OiAnoDat Not used * - OiFilNam Not used * - OiDIB Not used * - OiGroup STR * - OiIndex STR * - OiAnText OIAN_TEXTPRIVDATA */ if (properties.HasDisplayText) { if (properties.HasHyperlink) { SendLink(handler, properties.OiGroup, properties.OiIndex, properties.MarkAttributes.Bounds, properties.DisplayText.Orientation, properties.DisplayText.CreationScale, properties.DisplayText.Text, properties.Hyperlink.InternalLink, properties.Hyperlink.Link, properties.Hyperlink.WorkingDirectory, properties.Hyperlink.Location, properties.MarkAttributes.Color1, properties.MarkAttributes.LogFont); } else { SendTypedText(handler, properties.OiGroup, properties.OiIndex, properties.MarkAttributes.Bounds, properties.DisplayText.Orientation, properties.DisplayText.CreationScale, properties.DisplayText.Text, properties.MarkAttributes.Color1, properties.MarkAttributes.LogFont); } return(true); } return(false); }
/// <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); } }
/// <summary> /// OnUpdateProperties updates the properties with the upcoming block. /// </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> private static bool OnUpdateProperties(WangAnnotationProperties properties, IWangStream stream, int dataSize) { return(ReadBlock(properties, stream, dataSize)); }