/// <summary> /// ReadHyperlink reads a structure designed to hold an hyperlink for a Wang annotation. /// </summary> /// <remarks> /// This methods aplies when the specifications are mentionning the availability of an HYPERLINK_NB structure. /// </remarks> /// <param name="stream">The stream to read the data in.</param> /// <param name="dataSize">The data size.</param> /// <returns>the hyperlink.</returns> public static WangHyperlink ReadHyperlink(IWangStream stream, int dataSize) { /* * HYPERLINK_NB * Type Name Description * int nVersion The version number of this data. * int nLinkSize The size of the link string in bytes. * char szLinkString The variable length multi-byte name string. * int nLocationSize The size of the location string. * char szLocationString The variable length multi-byte location string. * int nWorkDirSize The size of the working directory string. * char szWorkDirString The variable length multi-byte working directory string. * int nFlags One or more of the following flags OR’ed together: * 1 = Can remove hyperlink from mark. * 2 = Hyperlink refers to this document. */ if (stream.AvailableBytes() < 4) { return(null); } int version = stream.ReadInt32(); string[] stringInformation = new string[3]; for (int index = 0; index < stringInformation.Length; index++) { if (stream.AvailableBytes() < 4) { return(null); } int size = stream.ReadInt32(); if (stream.AvailableBytes() < size) { return(null); } stringInformation[index] = ReadCharString(stream, size); } if (stream.AvailableBytes() < 4) { return(null); } int flag = stream.ReadInt32(); return(new WangHyperlink(stringInformation[0], stringInformation[1], stringInformation[2], ((int)flag & 1) != 0, ((int)flag & 2) != 0)); }
/// <summary> /// ReadPoints reads a structure designed to hold points. /// </summary> /// <remarks> /// This methods aplies when the specifications are mentionning the availability of a AN_POINTS 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, null if an error occured.</returns> public static int[] ReadPoints(IWangStream stream, int dataSize) { /* * This implementation is based on the following C++ typedef: * typedef struct tagAnPoints{ * int nMaxPoints; // The maximum number of points; must * // be equal to the value of nPoints. * int nPoints; // The current number of points. * POINT ptPoint[1]; // Points marking the beginning and * // ending of the line segment(s); in * // FULLSIZE (not scaled) coordinates * // relative to the upper left corner * // of lrBounds in * // OIAN_MARK_ATTRIBUTES. * } AN_POINTS; */ // We need at least two integers. if (dataSize < 8) { return(null); } int max = stream.ReadInt32(); int count = stream.ReadInt32(); // Although the available spec explains the opposite, max and count may be different if (max < count) { return(null); } // The size of the data is exactly the size of two integers // plus the size for the maximum number of points. if ((8 + max * 2 * 4) != dataSize) { return(null); } int coordinatesCount = 2 * count; int[] readData = new int[coordinatesCount]; stream.ReadInts32(readData, coordinatesCount); // Although the available spec explains the opposite, max and count may be different // and we have to skip the unused data. // 2 coordinates, 4 bytes per coordinate stream.SkipBytes((max - count) * 2 * 4); return(readData); }
/// <summary> /// ReadDataType reads the datatype. /// </summary> /// <param name="dataType">To retrieve the data type.</param> /// <param name="dataSize">To retrieve the data size.</param> /// <param name="stream">The stream to read the data in.</param> /// <returns>true if the operation succeeded otherwise returns false.</returns> public static bool ReadDataType(out WangDataType dataType, out int dataSize, IWangStream stream) { if (stream.AvailableBytes() >= 8) { int intDataType = stream.ReadInt32(); dataSize = stream.ReadInt32(); dataType = intDataType < ConversionWangDataTypes.Length ? ConversionWangDataTypes[intDataType] : WangDataType.Invalid; return(true); } dataSize = 0; dataType = WangDataType.Invalid; return(false); }
/// <summary> /// ReadLogFont reads a structure designed to hold font 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> /// <returns>The data read.</returns> public static WangLogFont ReadLogfont(IWangStream stream) { if (stream.AvailableBytes() >= 56) { /* * This implementation is based on the following C++ typedef: * typedef struct tagLOGFONT { * LONG lfHeight; * LONG lfWidth; * LONG lfEscapement; * LONG lfOrientation; * LONG lfWeight; * BYTE lfItalic; * BYTE lfUnderline; * BYTE lfStrikeOut; * BYTE lfCharSet; * BYTE lfOutPrecision; * BYTE lfClipPrecision; * BYTE lfQuality; * BYTE lfPitchAndFamily; * TCHAR lfFaceName[LF_FACESIZE]; * } LOGFONT, *PLOGFONT; */ WangLogFont readData = new WangLogFont(); readData.Height = stream.ReadInt32(); readData.Width = stream.ReadInt32(); readData.Escapement = stream.ReadInt32(); readData.Orientation = stream.ReadInt32(); readData.Weight = stream.ReadInt32(); readData.Italic = stream.ReadByte() != 0; readData.Underline = stream.ReadByte() != 0; readData.StrikeOut = stream.ReadByte() != 0; readData.CharSet = stream.ReadByte(); readData.OutPrecision = stream.ReadByte(); readData.ClipPrecision = stream.ReadByte(); readData.Quality = stream.ReadByte(); readData.PitchAndFamily = stream.ReadByte(); readData.FaceName = ReadCharString(stream, 28); return(readData); } return(null); }
/// <summary> /// ReadRotation reads a scaling and resolution information for image marks. /// </summary> /// <remarks> /// This methods aplies when the specifications are mentionning the availability of a AN_NEW_ROTATE_STRUCT 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, null if an error occured.</returns> public static WangRotation ReadRotation(IWangStream stream, int dataSize) { // The expected data size is fixed. if (dataSize == 56) { /* * This implementation is based on the following C++ typedef: * typedef struct tagAnNewRotateStruct{ * int rotation; // 1=Original * // 2=Rotate right (90 degrees clockwise) * // 3=Flip (180 degrees clockwise) * // 4=Rotate left (270 degrees clockwise) * // 5=Vertical mirror (reflected around a * // vertical line) * // 6=Vertical mirror + Rotate right * // 7=Vertical mirror + Flip * // 8=Vertical mirror + Rotate left * int scale; // Set to 1000. * int nHRes; // Set to value of nOrigHRes. * int nVRes; // Set to value of nOrigVRes. * int nOrigHRes; // Resolution of image mark in DPI. * int nOrigVRes; // Resolution of image mark in DPI. * BOOL bReserved1; // Set to 0. * BOOL bReserved2; // Set to 0. * int nReserved[6]; * }AN_NEW_ROTATE_STRUCT; */ int rotation = stream.ReadInt32(); int scale = stream.ReadInt32(); #if DEBUG Debug.Assert(scale == 1000); #endif //DEBUG int nHRes = stream.ReadInt32(); int nVRes = stream.ReadInt32(); int horizontalResolution = stream.ReadInt32(); int verticalResolution = stream.ReadInt32(); #if DEBUG // This equality is part of the specifications but does not occur every time. // Debug.Assert(nHRes == readData.OrigHRes); // This equality is part of the specifications but does not occur every time. // Debug.Assert(nVRes == readData.OrigVRes); #endif //DEBUG stream.SkipBytes(4); stream.SkipBytes(4); stream.SkipBytes(6 * 4); return(new WangRotation(rotation, horizontalResolution, verticalResolution)); } return(null); }
/// <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> /// ReadHeader reads the header for the tag holding the Wang annotations. /// </summary> /// <param name="stream">The stream to read the data in.</param> /// <returns>true if the operation succeeded otherwise returns false.</returns> public static bool ReadHeader(IWangStream stream) { if (stream.AvailableBytes() >= 8) { /* * The annotation data itself consists of a 4-byte header, which is not currently used (reserved for future use). * The header should be skipped on read and written as zeros. Note, however, that it is included in the TIFF tag's Data Count field. * The header is followed by four bytes in Intel order that specify size of INTs and UINTs and byte ordering: * 4 bytes: * 0 = Intel 16-bit (least-significant byte to most-significant byte and two-byte INTs and UINTs) * 1 = Intel 32-bit (least-significant byte to most-significant byte and four-byte INTs and UINTs) */ stream.SkipBytes(4); if (stream.ReadInt32() == 0) { // 0 = Intel 16-bit (least-significant byte to most-significant byte and two-byte INTs and UINTs) // TODO - David Ometto - 2016-11-21 - Add support for 16-bit annotations. // TODO - David Ometto - 2016-11-21 - Find a good way to send the error. } return(true); } return(false); }
/// <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); }