/// <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); } }