public static NonUniformRationalBSpline NonUniformRationalBSpline(MetafileReader reader, CommandHeader commandHeader) { // P1: (integer) spline order (=m) // P2: (integer) number of control points (=n) // P(3)-P(2+n): (points) array of control points // P(3+n)-P(2+2n+m): (real) list of knots, of length n+m. // P(3+2n+m): (real) parameter start value // P(4+2n+m): (real) parameter end value // P(5+2n+m)-P(4+3n+m): (real) list of weights, of length n. int splineOrder = reader.ReadInteger(); int numberOfControlPoints = reader.ReadInteger(); var controlPoints = new List <PointF>(); for (int i = 0; i < numberOfControlPoints; i++) { controlPoints.Add(reader.ReadPoint()); } var knots = new List <double>(); for (int i = 0; i < splineOrder + numberOfControlPoints; i++) { knots.Add(reader.ReadReal()); } double start = reader.ReadReal(); double end = reader.ReadReal(); var weights = new List <double>(); for (int i = 0; i < numberOfControlPoints; i++) { weights.Add(reader.ReadReal()); } return(new NonUniformRationalBSpline(splineOrder, controlPoints.ToArray(), knots.ToArray(), start, end, weights.ToArray())); }
public static BeginTileArray BeginTileArray(MetafileReader reader, CommandHeader commandHeader) { // P1: (point) position // P2: (enumerated) cell path direction: valid values are // 0 0° // 1 90° // 2 180° // 3 270° // P3: (enumerated) line progression direction: valid values are // 0 90° // 1 270° // P4: (integer) number of tiles in pth direction // P5: (integer) number of tiles in line direction // P6: (integer) number of cells/ tile in path direction // P7: (integer) number of cells/ tile in line direction // P8: (real) cell size in path direction // P9: (real) cell size in line direction // P10: (integer) image offset in path direction // P11: (integer) image offset in line direction // P12: (integer) image number of cells in path direction // P13: (integer) image number of cells in line direction return(new BeginTileArray( reader.ReadPoint(), reader.ReadEnum <CellPathDirection>(), reader.ReadEnum <LineProgressionDirection>(), reader.ReadInteger(), reader.ReadInteger(), reader.ReadInteger(), reader.ReadInteger(), reader.ReadReal(), reader.ReadReal(), reader.ReadInteger(), reader.ReadInteger(), reader.ReadInteger(), reader.ReadInteger())); }
public static FontProperties FontProperties(MetafileReader reader, CommandHeader commandHeader) { // FONT PROPERTIES: has a variable number of parameter 3-tuples (P1,P2,P3); each parameter 3-tuple contains // P1: (index) property indicator, valid values are // 1 font index // 2 standard version // 3 design source // 4 font family // 5 posture // 6 weight // 7 proportionate width // 8 included glyph collections // 9 included glyphs // 10 design size // 11 minimum size // 12 maximum size // 13 design group // 14 structure // >14 reserved for registered values // P2: (integer) priority, valid values are non-negative integers. // P3: (structured data record) property value record, each record contains a single member and is comprised of // [data type indicator, data element count, data element(s)]. var properties = new List <FontProperty>(); while (reader.HasMoreData((reader.Descriptor.IndexPrecision + reader.Descriptor.IntegerPrecision) / 8)) { int propertyIndicator = reader.ReadIndex(); int priority = reader.ReadInteger(); // The SDR for each of the standardized properties contains only one member (typed sequence) [ISO/IEC 8632-1 7.3.21] var record = ApplicationStructureDescriptorReader.ReadStructuredDataRecord(reader); properties.Add(new FontProperty(propertyIndicator, priority, record.Elements.First())); } return(new FontProperties(properties.ToArray())); }
public static VdcRealPrecision VdcRealPrecision(MetafileReader reader, CommandHeader commandHeader) { // P1: (enumerated) form of representation for real values: valid values are // 0 floating point format // 1 fixed point format // P2: (integer) field width for exponent or whole part (including 1 bit for sign) // P3: (integer) field width for fraction or fractional part return(new VdcRealPrecision(reader.ReadEnum <RealRepresentation>(), reader.ReadInteger(), reader.ReadInteger())); }
public static PatternTable PatternTable(MetafileReader reader, CommandHeader commandHeader) { // P1: (index) pattern table index // P2: (integer) nx, the dimension of colour array in the direction of the PATTERN SIZE width vector // P3: (integer) ny, the dimension of colour array in the direction of the PATTERN SIZE height vector // P4: (integer) local colour precision: valid values are as for the local colour precision parameter of CELL ARRAY. // P5: (colour array) pattern definition int index = reader.ReadIndex(); int nx = reader.ReadInteger(); int ny = reader.ReadInteger(); int localColorPrecision = reader.ReadInteger(); if (localColorPrecision == 0) { if (reader.Descriptor.ColorSelectionMode == ColorModeType.Direct) { localColorPrecision = reader.Descriptor.ColorPrecision; } else { localColorPrecision = reader.Descriptor.ColorIndexPrecision; } } // might be either 1/2/4 or 8/16/32 here; but we want byte-sizes in ReadColor if (localColorPrecision >= 8) { localColorPrecision /= 8; } var colors = new List <MetafileColor>(); int count = nx * ny; while (reader.HasMoreData() && count-- > 0) { colors.Add(reader.ReadColor(localColorPrecision)); } return(new PatternTable(index, nx, ny, colors.ToArray())); }
public static HatchStyleDefinition HatchStyleDefinition(MetafileReader reader, CommandHeader header) { // P1: (index) hatch index, valid values are negative. // P2: (enumerated) style indicator: valid values are // 0 parallel // 1 cross hatch // P3: (4(size specification)) hatch direction vectors specifier (x,y,x,y): see Part 1, subclause 7.1 for its form. // hatch direction vectors specifier is affected by INTERIOR STYLE SPECIFICATION MODE // P4: (size specification) duty cycle length: see Part 1, subclause 7.1 for its form. // duty cycle length is affected by INTERIOR STYLE SPECIFICATION MODE // P5: (integer) number of hatch lines (=n) // P6-P(5+n): (integers) list of n gap widths // P(6+n)-P(5+2n): (integers) list of n line types int hatchIndex = reader.ReadIndex(); HatchStyleIndicator styleIndicator = reader.ReadEnum <HatchStyleIndicator>(); double hatchDirectionStartX = reader.ReadSizeSpecification(reader.Descriptor.InteriorStyleSpecificationMode); double hatchDirectionStartY = reader.ReadSizeSpecification(reader.Descriptor.InteriorStyleSpecificationMode); double hatchDirectionEndX = reader.ReadSizeSpecification(reader.Descriptor.InteriorStyleSpecificationMode); double hatchDirectionEndY = reader.ReadSizeSpecification(reader.Descriptor.InteriorStyleSpecificationMode); double dutyCycleLength = reader.ReadSizeSpecification(reader.Descriptor.InteriorStyleSpecificationMode); int n = reader.ReadInteger(); var gapWidths = new List <int>(); for (int i = 0; i < n; i++) { gapWidths.Add(reader.ReadInteger()); } var lineTypes = new List <int>(); for (int i = 0; i < n; i++) { lineTypes.Add(reader.ReadInteger()); } return(new HatchStyleDefinition(hatchIndex, styleIndicator, new PointF((float)hatchDirectionStartX, (float)hatchDirectionStartY), new PointF((float)hatchDirectionEndX, (float)hatchDirectionEndY), dutyCycleLength, gapWidths.ToArray(), lineTypes.ToArray())); }
public static LineAndEdgeTypeDefinition LineAndEdgeTypeDefinition(MetafileReader reader, CommandHeader header) { // P1: (index) line type, valid values are negative. // P2: (size specification) dash cycle repeat length: see Part 1, subclause 7.1 for its form. // dash cycle repeat length is affected by LINE WIDTH SPECIFICATION MODE // P3-P(n+2): (integer) list of n dash elements int lineType = reader.ReadIndex(); double dashCycleRepeatLength = reader.ReadSizeSpecification(reader.Descriptor.LineWidthSpecificationMode); var dashElements = new List <int>(); while (reader.HasMoreData()) { dashElements.Add(reader.ReadInteger()); } return(new LineAndEdgeTypeDefinition(lineType, dashCycleRepeatLength, dashElements.ToArray())); }
public static MetafileElementsList MetafileElementsList(MetafileReader reader, CommandHeader commandHeader) { // P1: (integer) number of elements specified // P2: (index-pair array) List of metafile elements in this metafile. Each element is represented by two values: // the first is its element class code (as in Table 2) // the second is its element id code (as in Table 3 to Table 10). int numberOfElements = reader.ReadInteger(); // unused var elements = new List <string>(); while (reader.HasMoreData()) { int elementClass = reader.ReadIndex(); int elementId = reader.ReadIndex(); elements.Add(GetMetafileElementsListName(elementClass, elementId)); } return(new MetafileElementsList(elements)); }
public static StructuredDataRecord ReadStructuredDataRecord(MetafileReader reader) { // overall length seems to be encoded similar to the string length [ISO/IEC 8632-3 7, Table 1, Note 12] // (ie. one byte, followed by one word if its 255). int length = reader.ReadByte(); if (length == 255) { // FIXME: does an SDR also have a long form similar to a string? length = reader.ReadWord(); } var elements = new List <StructuredDataElement>(); long startPosition = reader.Position; // require at least the number of bytes for the enum and the count; which depends on integer/index precision: // > The integer of the "data count" and the index of the "data type index" are represented respectively at the current // > Integer Precision and the current Index Precision of the metafile. [ISO/IEC 8632-1 H.2.2] // some files seem to include padding or similar, which throws this off by having an extra byte available at the end while (reader.HasMoreData((reader.Descriptor.IndexPrecision + reader.Descriptor.IntegerPrecision) / 8)) { // enum is an index at the current index precision for SDR [ISO/IEC 8632-1 H.2.2] DataTypeIndex type = (DataTypeIndex)Enum.ToObject(typeof(DataTypeIndex), reader.ReadIndex()); // count is an interger at the current integer precision for SDR [ISO/IEC 8632-1 H.2.2] int count = reader.ReadInteger(); object[] values = new object[count]; for (int i = 0; i < count; i++) { values[i] = ReadValue(reader, type); } elements.Add(new StructuredDataElement(type, values)); // only read as much as specified by length if (reader.Position - startPosition >= length) { break; } } return(new StructuredDataRecord(elements)); }
public static EscapeCommand Escape(MetafileReader reader, CommandHeader commandHeader) { // P1: (integer) escape identifier // P2: (data record) escape data record; data records are bound as strings in this encoding. int identifier = reader.ReadInteger(); // attempt to parse the data record as structured record, in case it is a known one // otherwise it is probably application specific and cannot be assumed to be a structured record StructuredDataRecord dataRecord; if (EscapeCommand.KnownEscapeTypes.ContainsKey(identifier)) { dataRecord = ApplicationStructureDescriptorReader.ReadStructuredDataRecord(reader); } else { dataRecord = new StructuredDataRecord(new[] { new StructuredDataElement(DataTypeIndex.String, new object[] { reader.ReadString() }), }); } return(new EscapeCommand(identifier, dataRecord)); }
public static SegmentPickPriority SegmentPickPriority(MetafileReader reader, CommandHeader commandHeader) { // P1: (name) segment identifier // P2: (integer) segment pick priority: valid values are non-negative integers return(new SegmentPickPriority(reader.ReadName(), reader.ReadInteger())); }
public static ApplicationData ApplicationData(MetafileReader reader, CommandHeader commandHeader) { // P1: (integer) identifier // P2: (data record) application data record; data records are bound as strings in this encoding. return(new ApplicationData(reader.ReadInteger(), reader.ReadString())); }
public static VdcIntegerPrecision VdcIntegerPrecision(MetafileReader reader, CommandHeader commandHeader) { // P1: (integer) VDC integer precision; legal values are 16, 24 or 32; the value 8 is not permitted. return(new VdcIntegerPrecision(reader.ReadInteger())); }
public static CellArray CellArray(MetafileReader reader, CommandHeader commandHeader) { // P1: (point) corner point P // P2: (point) corner point Q // P3: (point) corner point R // P4: (integer) nx // P5: (integer) ny // P6: (integer) local colour precision: valid values are 0, 1, 2, 4, 8, 16, 24, and 32. If the value is zero (the // 'default colour precision indicator' value), the COLOUR (INDEX) PRECISION for the picture indicates the // precision with which the colour list is encoded. If the value is non-zero, the precision with which the colour // data is encoded is given by the value. // P7: (enumerated) cell representation mode: valid values are // 0 run length list mode // 1 packed list mode // P8: (colour list) array of cell colour values. // If the COLOUR SELECTION MODE is 'direct', the values will be direct colour values. If the COLOUR // SELECTION MODE is 'indexed', the values will be indexes into the COLOUR TABLE. // If the cell representation mode is 'packed list', the colour values are represented by rows of values, each // row starting on a word boundary. If the cell representation mode is 'run length', the colour list values are // represented by rows broken into runs of constant colour; each row starts on a word boundary. Each list // item consists of a cell count (integer) followed by a colour value. With the exception of the first run of a // row, the integer count of each run immediately follows the colour specifier of the preceding run with no // intervening padding. var p = reader.ReadPoint(); var q = reader.ReadPoint(); var r = reader.ReadPoint(); int nx = reader.ReadInteger(); int ny = reader.ReadInteger(); int localColorPrecision = reader.ReadInteger(); if (localColorPrecision == 0) { if (reader.Descriptor.ColorSelectionMode == ColorModeType.Direct) { localColorPrecision = reader.Descriptor.ColorPrecision; } else { localColorPrecision = reader.Descriptor.ColorIndexPrecision; } } // might be either 1/2/4 or 8/16/32 here; but we want byte-sizes in ReadColor if (localColorPrecision >= 8) { localColorPrecision /= 8; } var cellRepresentationMode = reader.ReadEnum <CellRepresentationMode>(); int totalCount = nx * ny; var colors = new List <MetafileColor>(); while (colors.Count < totalCount) { // chunks are split into rows; each row is word-aligned // word-align the next read if necessary if (reader.Position % 2 == 1 && reader.HasMoreData()) { reader.ReadByte(); } int rowCount = nx; while (rowCount > 0) { if (cellRepresentationMode == CellRepresentationMode.RunLengthList) { int cellCount = reader.ReadInteger(); rowCount -= cellCount; var cellColor = reader.ReadColor(localColorPrecision); colors.AddRange(Enumerable.Range(0, cellCount).Select(i => cellColor)); } else { rowCount--; colors.Add(reader.ReadColor(localColorPrecision)); } } } return(new CellArray(p, q, r, nx, ny, colors.ToArray())); }
public static SegmentPriorityExtent SegmentPriorityExtent(MetafileReader reader, CommandHeader commandHeader) { // P1: (integer) minimum segment priority value: valid values are non-negative integers // P2: (integer) maximum segment priority value: valid values are non-negative integers return(new SegmentPriorityExtent(reader.ReadInteger(), reader.ReadInteger())); }
public static MetafileVersion MetafileVersion(MetafileReader reader, CommandHeader commandHeader) { // P1: (integer) metafile version number: valid values are 1, 2, 3, 4 return(new MetafileVersion(reader.ReadInteger())); }
private static object ReadValue(MetafileReader reader, DataTypeIndex type) { switch (type) { case DataTypeIndex.StructuredDataRecord: return(ReadStructuredDataRecord(reader)); case DataTypeIndex.ColorIndex: return(reader.ReadIndexedColor()); case DataTypeIndex.ColorDirect: return(reader.ReadDirectColor()); case DataTypeIndex.Name: return(reader.ReadName()); case DataTypeIndex.Enumerated: return(reader.ReadEnum()); case DataTypeIndex.Integer: return(reader.ReadInteger()); case DataTypeIndex.Reserved: // TODO: what exactly does reserved mean in terms of advancing position? return(null); case DataTypeIndex.SignedInteger8bit: return(reader.ReadInteger(1, false)); case DataTypeIndex.SignedInteger16bit: return(reader.ReadInteger(2, false)); case DataTypeIndex.SignedInteger32bit: return(reader.ReadInteger(4, false)); case DataTypeIndex.Index: return(reader.ReadIndex()); case DataTypeIndex.Real: return(reader.ReadReal()); case DataTypeIndex.String: case DataTypeIndex.StringFixed: // TODO: difference between S and SF? charset/escape code handling? return(reader.ReadString()); case DataTypeIndex.ViewportCoordinate: return(reader.ReadViewportCoordinate()); case DataTypeIndex.VDC: return(reader.ReadVdc()); case DataTypeIndex.ColorComponent: return(reader.ReadColorValue()); case DataTypeIndex.UnsignedInteger8bit: return(reader.ReadInteger(1, true)); case DataTypeIndex.UnsignedInteger32Bit: return(reader.ReadInteger(4, true)); case DataTypeIndex.UnsignedInteger16bit: return(reader.ReadInteger(2, true)); case DataTypeIndex.BitStream: case DataTypeIndex.ColorList: default: // FIXME: how are those implemented? return(null); } }
public static IntegerPrecision IntegerPrecision(MetafileReader reader, CommandHeader commandHeader) { // P1: (integer) integer precision: valid values are 8, 16, 24 or 32 return(new IntegerPrecision(reader.ReadInteger())); }
public static InterpolatedInterior InterpolatedInterior(MetafileReader reader, CommandHeader commandHeader) { // P1: (index) style: valid values are // 1 parallel // 2 elliptical // 3 triangular // >3 reserved for registered values // P2: (2n(size specification)) reference geometry: see part 1, subclause 7.1 for its form. // P3: (integer) number of stages (=m) // P4: (real) array of m stage designators // P5: (colour) array of k colour specifiers: k=3 for triangular, m+1 otherwise. int style = reader.ReadIndex(); var referenceGeometry = new List <PointF>(); var stageDesignators = new List <double>(); var colorSpecifiers = new List <MetafileColor>(); // Legal values of the style parameter are positive integers. [ISO/IEC 8632-1 7.7.43] // Values greater than 3 are reserved for future standardization and registration. if (style >= 1 && style <= 3) { // parallel: the number of scalars shall be 2. The FILL REFERENCE POINT is one defining // point of a reference line. A second defining point of the reference line is defined by // the 2 scalars, which are respectively the x and y offset of the second point from the // FILL REFERENCE POINT. // elliptical: the number of scalars shall be 4. The FILL REFERENCE POINT is the centre of a // reference ellipse. The first pair of scalars are respectively the x and y offset from // the FILL REFERENCE POINT to the first CDP of ellipse and the second pair are // respectively the x and y offset from the FILL REFERENCE POINT to the second // CDP of ellipse. // triangular: the number of scalars shall be 4. The first pair of scalars are respectively the x and // y offset from the FILL REFERENCE POINT to the second corner of a reference // triangle and the second pair are respectively the x and y offset from the FILL // REFERENCE POINT to the third corner of the reference triangle. The number of // stages shall be 0 and the list of stage designators shall be empty. int geoCount; if (style == 1) { geoCount = 2; } else { geoCount = 4; } for (int i = 0; i < geoCount / 2; i++) { double rgX = reader.ReadSizeSpecification(reader.Descriptor.InteriorStyleSpecificationMode); double rgY = reader.ReadSizeSpecification(reader.Descriptor.InteriorStyleSpecificationMode); referenceGeometry.Add(new PointF((float)rgX, (float)rgY)); } int numberOfStages = reader.ReadInteger(); for (int i = 0; i < numberOfStages; i++) { stageDesignators.Add(reader.ReadReal()); } int numberOfColors = style == 3 ? 3 : numberOfStages + 1; for (int i = 0; i < numberOfColors; i++) { colorSpecifiers.Add(reader.ReadColor()); } } return(new InterpolatedInterior(style, referenceGeometry.ToArray(), stageDesignators.ToArray(), colorSpecifiers.ToArray())); }
public static ColorIndexPrecision ColorIndexPrecision(MetafileReader reader, CommandHeader commandHeader) { // P1: (integer) Colour index precision: valid values are 8, 16, 24 or 32 return(new ColorIndexPrecision(reader.ReadInteger())); }