├── .gitignore ├── Writers ├── DelimiterElementWriter.cs ├── EscapeWriter.cs ├── ApplicationStructureDescriptorWriter.cs └── ExternalWriter.cs ├── CgmInfoGui ├── Assets │ └── avalonia-logo.ico ├── ViewModels │ ├── ViewModelBase.cs │ ├── Nodes │ │ ├── SimpleNode.cs │ │ ├── UnsupportedContainer.cs │ │ ├── FontListNode.cs │ │ ├── Sources │ │ │ ├── ITileSource.cs │ │ │ ├── TileSource.cs │ │ │ └── BitonalTileSource.cs │ │ ├── PictureNode.cs │ │ ├── MetafileNode.cs │ │ ├── SegmentNode.cs │ │ ├── InvalidCommandNode.cs │ │ ├── UnsupportedNode.cs │ │ ├── NodeBase.cs │ │ ├── APSAttributeNode.cs │ │ ├── MetafileDescriptionNode.cs │ │ └── HotspotNode.cs │ ├── CompanionFileViewModel.cs │ ├── HotspotsViewModel.cs │ ├── ApplicationStructureViewModel.cs │ └── DockFactory.cs ├── Views │ ├── MainWindow.axaml.cs │ ├── HotspotsView.axaml.cs │ ├── CompanionFileView.axaml.cs │ ├── MetafileStructureView.axaml.cs │ ├── ApplicationStructureView.axaml.cs │ ├── ApplicationStructureView.axaml │ ├── HotspotsView.axaml │ └── CompanionFileView.axaml ├── Globals.axaml ├── Controls │ ├── PropertyGrid │ │ ├── ReadOnlyPropertyGrid.axaml.cs │ │ └── ReadOnlyPropertyGrid.axaml │ ├── PropertiesPanel.axaml.cs │ ├── RawPanel.axaml.cs │ └── OffsetColumn.cs ├── Program.cs ├── ViewLocator.cs ├── Converters │ ├── HexConverter.cs │ ├── FileSizeConverter.cs │ └── StringJoinConverter.cs ├── app.manifest ├── Traversal │ ├── XCFDocumentBuilderVisitor.cs │ ├── APSStructureBuilderVisitor.cs │ └── MetafileContext.cs ├── App.axaml ├── App.axaml.cs └── Services │ └── IFileService.cs ├── BinaryEncoding ├── DelimiterElementReader.cs ├── ApplicationStructureDescriptorReader.cs ├── CommandHeader.cs ├── ExternalReader.cs └── EscapeReader.cs ├── Commands ├── Enums │ ├── RealRepresentation.cs │ ├── CellRepresentationMode.cs │ ├── ColorSpace.cs │ ├── RegionIndicator.cs │ ├── OnOffIndicator.cs │ ├── ArcClosureType.cs │ ├── FinalFlag.cs │ ├── ColorModeType.cs │ ├── ColorModel.cs │ ├── Highlighting.cs │ ├── ActionRequired.cs │ ├── ScalingModeType.cs │ ├── VdcTypeSpecification.cs │ ├── InheritanceFlag.cs │ ├── AspectSourceFlagsValue.cs │ ├── ClipInheritanceType.cs │ ├── HatchStyleIndicator.cs │ ├── InheritanceFilterSetting.cs │ ├── SegmentTransformationApplication.cs │ ├── LineProgressionDirection.cs │ ├── RealPrecisionSpecification.cs │ ├── TextPathMode.cs │ ├── ClippingMode.cs │ ├── TextPrecisionType.cs │ ├── TextPathType.cs │ ├── CellPathDirection.cs │ ├── EdgeOutFlags.cs │ ├── WidthSpecificationModeType.cs │ ├── DeviceViewportSpecificationModeType.cs │ ├── CharacterCodingAnnouncerType.cs │ ├── HorizontalTextAlignment.cs │ ├── CharacterSetType.cs │ ├── VerticalTextAlignment.cs │ ├── InteriorStyleType.cs │ ├── DataTypeIndex.cs │ └── AspectSourceFlagsType.cs ├── StructuredDataElement.cs ├── Delimiter │ ├── EndFigure.cs │ ├── EndMetafile.cs │ ├── EndPicture.cs │ ├── EndSegment.cs │ ├── BeginFigure.cs │ ├── EndTileArray.cs │ ├── BeginPictureBody.cs │ ├── EndCompoundLine.cs │ ├── BeginCompoundLine.cs │ ├── EndProtectionRegion.cs │ ├── EndCompoundTextPath.cs │ ├── EndApplicationStructure.cs │ ├── BeginCompoundTextPath.cs │ ├── BeginApplicationStructureBody.cs │ ├── BeginMetafile.cs │ ├── BeginPicture.cs │ ├── BeginSegment.cs │ ├── BeginProtectionRegion.cs │ └── BeginApplicationStructure.cs ├── Control │ ├── NewRegion.cs │ ├── MiterLimit.cs │ ├── VdcIntegerPrecision.cs │ ├── AuxiliaryColor.cs │ ├── SavePrimitiveContext.cs │ ├── ClipIndicator.cs │ ├── EdgeClippingMode.cs │ ├── LineClippingMode.cs │ ├── RestorePrimitiveContext.cs │ ├── Transparency.cs │ ├── MarkerClippingMode.cs │ ├── GeneralizedTextPathMode.cs │ ├── ClipRectangle.cs │ ├── ProtectionRegionIndicator.cs │ └── VdcRealPrecision.cs ├── GraphicalPrimitives │ ├── ConnectingEdge.cs │ ├── Polygon.cs │ ├── Polyline.cs │ ├── Polymarker.cs │ ├── DisjointPolyline.cs │ ├── AppendText.cs │ ├── Circle.cs │ ├── Rectangle.cs │ ├── PolygonSet.cs │ ├── TextCommand.cs │ ├── CircularArc3Point.cs │ ├── ParabolicArc.cs │ ├── CircularArcCenter.cs │ ├── Ellipse.cs │ ├── CircularArcCenterReversed.cs │ ├── CircularArc3PointClose.cs │ ├── NonUniformBSpline.cs │ ├── RestrictedText.cs │ ├── CircularArcCenterClose.cs │ ├── CellArray.cs │ ├── EllipticalArc.cs │ ├── HyperbolicArc.cs │ ├── NonUniformRationalBSpline.cs │ ├── MetafileCompressionTypes.cs │ ├── Tile.cs │ ├── EllipticalArcClose.cs │ ├── BitonalTile.cs │ └── Polybezier.cs ├── Segment │ ├── InheritanceFilterItem.cs │ ├── InheritanceFilter.cs │ ├── ClipInheritance.cs │ ├── SegmentPickPriority.cs │ ├── SegmentDisplayPriority.cs │ ├── SegmentTransformation.cs │ ├── SegmentHighlighting.cs │ └── CopySegment.cs ├── Attributes │ ├── EdgeWidth.cs │ ├── LineWidth.cs │ ├── MarkerSize.cs │ ├── PatternIndex.cs │ ├── TextFontIndex.cs │ ├── EdgeBundleIndex.cs │ ├── FillBundleIndex.cs │ ├── LineBundleIndex.cs │ ├── TextBundleIndex.cs │ ├── CharacterHeight.cs │ ├── CharacterSetIndex.cs │ ├── MarkerBundleIndex.cs │ ├── PickIdentifier.cs │ ├── TextPath.cs │ ├── EdgeColor.cs │ ├── FillColor.cs │ ├── LineColor.cs │ ├── TextColor.cs │ ├── MarkerColor.cs │ ├── CharacterExpansionFactor.cs │ ├── EdgeTypeInitialOffset.cs │ ├── LineTypeInitialOffset.cs │ ├── AlternateCharacterSetIndex.cs │ ├── InteriorStyle.cs │ ├── EdgeVisibility.cs │ ├── TextPrecision.cs │ ├── FillReferencePoint.cs │ ├── CharacterSpacing.cs │ ├── ColorTable.cs │ ├── PatternSize.cs │ ├── CharacterOrientation.cs │ ├── AspectSourceFlags.cs │ ├── PatternTable.cs │ ├── TextAlignment.cs │ ├── EdgeJoin.cs │ ├── LineJoin.cs │ ├── EdgeTypeContinuation.cs │ ├── LineTypeContinuation.cs │ ├── RestrictedTextType.cs │ ├── EdgeType.cs │ └── InterpolatedInterior.cs ├── MetafileDescriptor │ ├── MetafileVersion.cs │ ├── NamePrecision.cs │ ├── ColorPrecision.cs │ ├── IndexPrecision.cs │ ├── MaximumColorIndex.cs │ ├── IntegerPrecision.cs │ ├── ColorIndexPrecision.cs │ ├── FontList.cs │ ├── MetafileDescription.cs │ ├── VdcType.cs │ ├── ColorModelCommand.cs │ ├── MetafileDefaultsReplacement.cs │ ├── MaximumVdcExtent.cs │ ├── SegmentPriorityExtent.cs │ ├── CharacterCodingAnnouncer.cs │ └── CharacterSetList.cs ├── PictureDescriptor │ ├── BackgroundColor.cs │ ├── ColorSelectionMode.cs │ ├── VdcExtent.cs │ ├── DeviceViewport.cs │ ├── EdgeWidthSpecificationMode.cs │ ├── LineWidthSpecificationMode.cs │ ├── MarkerSizeSpecificationMode.cs │ ├── InteriorStyleSpecificationMode.cs │ ├── ScalingMode.cs │ ├── LineAndEdgeTypeDefinition.cs │ ├── DeviceViewportSpecificationMode.cs │ ├── GeometricPatternDefinition.cs │ └── HatchStyleDefinition.cs ├── External │ ├── ApplicationData.cs │ └── Message.cs ├── StructuredDataRecord.cs ├── ApplicationStructureDescriptor │ └── ApplicationStructureAttribute.cs ├── Command.cs └── TextTokenAttribute.cs ├── Utilities ├── ARGB.cs ├── MetafilePoint.cs ├── MetafileColorRGB.cs ├── MetafileColor.cs ├── MetafileMatrix.cs ├── MetafileColorIndexed.cs ├── MetafileColorCIE.cs ├── TrackingBuffer.cs └── MetafileColorCMYK.cs ├── Common.props ├── StreamExtensions.cs ├── TextEncoding ├── ApplicationStructureDescriptorReader.cs ├── ExternalReader.cs └── EscapeReader.cs ├── MetafileProperties.cs ├── EncodingExtensions.cs ├── .github ├── workflows │ └── dotnet.yml └── dependabot.yml ├── CgmInfoCmd └── CgmInfoCmd.csproj ├── Traversal └── MetafilePropertyVisitor.cs └── CgmInfo.csproj /.gitignore: -------------------------------------------------------------------------------- 1 | *.user 2 | *.suo 3 | *.bak 4 | /packages 5 | bin/ 6 | obj/ 7 | /.vs/ 8 | /.cr/ 9 | -------------------------------------------------------------------------------- /Writers/DelimiterElementWriter.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BhaaLseN/CgmInfo/HEAD/Writers/DelimiterElementWriter.cs -------------------------------------------------------------------------------- /CgmInfoGui/Assets/avalonia-logo.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BhaaLseN/CgmInfo/HEAD/CgmInfoGui/Assets/avalonia-logo.ico -------------------------------------------------------------------------------- /BinaryEncoding/DelimiterElementReader.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BhaaLseN/CgmInfo/HEAD/BinaryEncoding/DelimiterElementReader.cs -------------------------------------------------------------------------------- /CgmInfoGui/ViewModels/ViewModelBase.cs: -------------------------------------------------------------------------------- 1 | using CommunityToolkit.Mvvm.ComponentModel; 2 | 3 | namespace CgmInfoGui.ViewModels; 4 | 5 | public class ViewModelBase : ObservableObject 6 | { 7 | } 8 | -------------------------------------------------------------------------------- /Commands/Enums/RealRepresentation.cs: -------------------------------------------------------------------------------- 1 | namespace CgmInfo.Commands.Enums 2 | { 3 | public enum RealRepresentation 4 | { 5 | FloatingPoint = 0, 6 | FixedPoint = 1, 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Commands/Enums/CellRepresentationMode.cs: -------------------------------------------------------------------------------- 1 | namespace CgmInfo.Commands.Enums 2 | { 3 | public enum CellRepresentationMode 4 | { 5 | RunLengthList = 0, 6 | PackedList = 1, 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Commands/Enums/ColorSpace.cs: -------------------------------------------------------------------------------- 1 | namespace CgmInfo.Commands.Enums 2 | { 3 | public enum ColorSpace 4 | { 5 | Unknown = 0, 6 | RGB, 7 | CMYK, 8 | CIE, 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Commands/Enums/RegionIndicator.cs: -------------------------------------------------------------------------------- 1 | namespace CgmInfo.Commands.Enums 2 | { 3 | public enum RegionIndicator 4 | { 5 | Off = 1, 6 | Clip = 2, 7 | Shield = 3, 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Commands/Enums/OnOffIndicator.cs: -------------------------------------------------------------------------------- 1 | namespace CgmInfo.Commands.Enums 2 | { 3 | public enum OnOffIndicator 4 | { 5 | [TextToken("OFF")] 6 | Off = 0, 7 | [TextToken("ON")] 8 | On = 1, 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Commands/Enums/ArcClosureType.cs: -------------------------------------------------------------------------------- 1 | namespace CgmInfo.Commands.Enums 2 | { 3 | public enum ArcClosureType 4 | { 5 | [TextToken("PIE")] 6 | Pie = 0, 7 | [TextToken("CHORD")] 8 | Chord = 1, 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Commands/Enums/FinalFlag.cs: -------------------------------------------------------------------------------- 1 | namespace CgmInfo.Commands.Enums 2 | { 3 | public enum FinalFlag 4 | { 5 | [TextToken("NOTFINAL")] 6 | NotFinal = 0, 7 | [TextToken("FINAL")] 8 | Final = 1, 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /CgmInfoGui/Views/MainWindow.axaml.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Controls; 2 | 3 | namespace CgmInfoGui.Views; 4 | 5 | public partial class MainWindow : Window 6 | { 7 | public MainWindow() 8 | { 9 | InitializeComponent(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Commands/Enums/ColorModeType.cs: -------------------------------------------------------------------------------- 1 | namespace CgmInfo.Commands.Enums 2 | { 3 | public enum ColorModeType 4 | { 5 | [TextToken("INDEXED")] 6 | Indexed = 0, 7 | [TextToken("DIRECT")] 8 | Direct = 1, 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Commands/Enums/ColorModel.cs: -------------------------------------------------------------------------------- 1 | namespace CgmInfo.Commands.Enums 2 | { 3 | public enum ColorModel 4 | { 5 | RGB = 1, 6 | CIELAB = 2, 7 | CIELUV = 3, 8 | CMYK = 4, 9 | RGBrelated = 5, 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Commands/Enums/Highlighting.cs: -------------------------------------------------------------------------------- 1 | namespace CgmInfo.Commands.Enums 2 | { 3 | public enum Highlighting 4 | { 5 | [TextToken("NORMAL")] 6 | Normal = 0, 7 | [TextToken("HIGHL")] 8 | Highlighted = 1, 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /CgmInfoGui/ViewModels/Nodes/SimpleNode.cs: -------------------------------------------------------------------------------- 1 | namespace CgmInfoGui.ViewModels.Nodes; 2 | 3 | public class SimpleNode(string? name) : NodeBase 4 | { 5 | public string Name { get; } = name ?? string.Empty; 6 | public override string DisplayName => Name; 7 | } 8 | -------------------------------------------------------------------------------- /Commands/Enums/ActionRequired.cs: -------------------------------------------------------------------------------- 1 | namespace CgmInfo.Commands.Enums 2 | { 3 | public enum ActionRequired 4 | { 5 | [TextToken("NOACTION")] 6 | NoAction = 0, 7 | [TextToken("ACTION")] 8 | Action = 1, 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /CgmInfoGui/Views/HotspotsView.axaml.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Controls; 2 | 3 | namespace CgmInfoGui.Views; 4 | 5 | public partial class HotspotsView : UserControl 6 | { 7 | public HotspotsView() 8 | { 9 | InitializeComponent(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Commands/Enums/ScalingModeType.cs: -------------------------------------------------------------------------------- 1 | namespace CgmInfo.Commands.Enums 2 | { 3 | public enum ScalingModeType 4 | { 5 | [TextToken("ABSTRACT")] 6 | Abstract = 0, 7 | [TextToken("METRIC")] 8 | Metric = 1, 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Commands/Enums/VdcTypeSpecification.cs: -------------------------------------------------------------------------------- 1 | namespace CgmInfo.Commands.Enums 2 | { 3 | public enum VdcTypeSpecification 4 | { 5 | [TextToken("INTEGER")] 6 | Integer = 0, 7 | [TextToken("REAL")] 8 | Real = 1, 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Commands/Enums/InheritanceFlag.cs: -------------------------------------------------------------------------------- 1 | namespace CgmInfo.Commands.Enums 2 | { 3 | public enum InheritanceFlag 4 | { 5 | [TextToken("STLIST")] 6 | StateList = 0, 7 | [TextToken("APS")] 8 | ApplicationStructure = 1, 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /CgmInfoGui/Views/CompanionFileView.axaml.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Controls; 2 | 3 | namespace CgmInfoGui.Views; 4 | 5 | public partial class CompanionFileView : UserControl 6 | { 7 | public CompanionFileView() 8 | { 9 | InitializeComponent(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Commands/Enums/AspectSourceFlagsValue.cs: -------------------------------------------------------------------------------- 1 | namespace CgmInfo.Commands.Enums 2 | { 3 | public enum AspectSourceFlagsValue 4 | { 5 | [TextToken("INDIV")] 6 | Individual = 0, 7 | [TextToken("BUNDLED")] 8 | Bundled = 1, 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Commands/Enums/ClipInheritanceType.cs: -------------------------------------------------------------------------------- 1 | namespace CgmInfo.Commands.Enums 2 | { 3 | public enum ClipInheritanceType 4 | { 5 | [TextToken("STLIST")] 6 | StateList = 0, 7 | [TextToken("INTERSECTION")] 8 | Intersection = 1, 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Commands/Enums/HatchStyleIndicator.cs: -------------------------------------------------------------------------------- 1 | namespace CgmInfo.Commands.Enums 2 | { 3 | public enum HatchStyleIndicator 4 | { 5 | [TextToken("PARALLEL")] 6 | Parallel = 0, 7 | [TextToken("CROSSHATCH")] 8 | CrossHatch = 1, 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Commands/Enums/InheritanceFilterSetting.cs: -------------------------------------------------------------------------------- 1 | namespace CgmInfo.Commands.Enums 2 | { 3 | public enum InheritanceFilterSetting 4 | { 5 | [TextToken("STLIST")] 6 | StateList = 0, 7 | [TextToken("SEG")] 8 | Segment = 1, 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Commands/Enums/SegmentTransformationApplication.cs: -------------------------------------------------------------------------------- 1 | namespace CgmInfo.Commands.Enums 2 | { 3 | public enum SegmentTransformationApplication 4 | { 5 | [TextToken("NO")] 6 | No = 0, 7 | [TextToken("YES")] 8 | Yes = 1, 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /CgmInfoGui/Views/MetafileStructureView.axaml.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Controls; 2 | 3 | namespace CgmInfoGui.Views; 4 | 5 | public partial class MetafileStructureView : UserControl 6 | { 7 | public MetafileStructureView() 8 | { 9 | InitializeComponent(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /CgmInfoGui/Globals.axaml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | -------------------------------------------------------------------------------- /Commands/Enums/LineProgressionDirection.cs: -------------------------------------------------------------------------------- 1 | namespace CgmInfo.Commands.Enums 2 | { 3 | public enum LineProgressionDirection 4 | { 5 | [TextToken("90")] 6 | Clockwise_90deg = 0, 7 | [TextToken("270")] 8 | CounterClockwise_270deg = 1, 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /CgmInfoGui/Views/ApplicationStructureView.axaml.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Controls; 2 | 3 | namespace CgmInfoGui.Views; 4 | 5 | public partial class ApplicationStructureView : UserControl 6 | { 7 | public ApplicationStructureView() 8 | { 9 | InitializeComponent(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /CgmInfoGui/ViewModels/Nodes/UnsupportedContainer.cs: -------------------------------------------------------------------------------- 1 | namespace CgmInfoGui.ViewModels.Nodes; 2 | 3 | public class UnsupportedContainer : NodeBase 4 | { 5 | public override string DisplayName 6 | { 7 | get { return string.Format("Unsupported Nodes [{0} entries]", Nodes.Count); } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Commands/Enums/RealPrecisionSpecification.cs: -------------------------------------------------------------------------------- 1 | namespace CgmInfo.Commands.Enums 2 | { 3 | public enum RealPrecisionSpecification 4 | { 5 | Unsupported = 0, 6 | FloatingPoint32Bit, 7 | FloatingPoint64Bit, 8 | FixedPoint32Bit, 9 | FixedPoint64Bit, 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Commands/Enums/TextPathMode.cs: -------------------------------------------------------------------------------- 1 | namespace CgmInfo.Commands.Enums 2 | { 3 | public enum TextPathMode 4 | { 5 | [TextToken("OFF")] 6 | Off = 0, 7 | [TextToken("NONAXIS")] 8 | NonTangential = 1, 9 | [TextToken("AXIS")] 10 | AxisTangential = 2, 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Commands/Enums/ClippingMode.cs: -------------------------------------------------------------------------------- 1 | namespace CgmInfo.Commands.Enums 2 | { 3 | public enum ClippingMode 4 | { 5 | [TextToken("LOCUS")] 6 | Locus = 0, 7 | [TextToken("SHAPE")] 8 | Shape = 1, 9 | [TextToken("LOCUSTHENSHAPE")] 10 | LocusThenShape = 2, 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Commands/Enums/TextPrecisionType.cs: -------------------------------------------------------------------------------- 1 | namespace CgmInfo.Commands.Enums 2 | { 3 | public enum TextPrecisionType 4 | { 5 | [TextToken("STRING")] 6 | String = 0, 7 | [TextToken("CHAR")] 8 | Character = 1, 9 | [TextToken("STROKE")] 10 | Stroke = 2, 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Commands/Enums/TextPathType.cs: -------------------------------------------------------------------------------- 1 | namespace CgmInfo.Commands.Enums 2 | { 3 | public enum TextPathType 4 | { 5 | [TextToken("RIGHT")] 6 | Right = 0, 7 | [TextToken("LEFT")] 8 | Left = 1, 9 | [TextToken("UP")] 10 | Up = 2, 11 | [TextToken("DOWN")] 12 | Down = 3, 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Utilities/ARGB.cs: -------------------------------------------------------------------------------- 1 | namespace CgmInfo.Utilities 2 | { 3 | public struct ARGB 4 | { 5 | public int Alpha { get; set; } 6 | public int Red { get; set; } 7 | public int Green { get; set; } 8 | public int Blue { get; set; } 9 | 10 | public override string ToString() => $"A={Alpha} R={Red} G={Green} B={Blue}"; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Commands/Enums/CellPathDirection.cs: -------------------------------------------------------------------------------- 1 | namespace CgmInfo.Commands.Enums 2 | { 3 | public enum CellPathDirection 4 | { 5 | [TextToken("0")] 6 | Right_0deg = 0, 7 | [TextToken("90")] 8 | Down_90deg = 1, 9 | [TextToken("180")] 10 | Left_180deg = 2, 11 | [TextToken("270")] 12 | Up_270deg = 3, 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Commands/Enums/EdgeOutFlags.cs: -------------------------------------------------------------------------------- 1 | namespace CgmInfo.Commands.Enums 2 | { 3 | public enum EdgeOutFlags 4 | { 5 | [TextToken("INVIS")] 6 | Invisible = 0, 7 | [TextToken("VIS")] 8 | Visible = 1, 9 | [TextToken("CLOSEINVIS")] 10 | InvisibleClose = 2, 11 | [TextToken("CLOSEVIS")] 12 | VisibleClose = 3, 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Commands/Enums/WidthSpecificationModeType.cs: -------------------------------------------------------------------------------- 1 | namespace CgmInfo.Commands.Enums 2 | { 3 | public enum WidthSpecificationModeType 4 | { 5 | [TextToken("ABS")] 6 | Absolute = 0, 7 | [TextToken("SCALED")] 8 | Scaled = 1, 9 | [TextToken("FRACTIONAL")] 10 | Fractional = 2, 11 | [TextToken("MM")] 12 | Millimeters = 3, 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Utilities/MetafilePoint.cs: -------------------------------------------------------------------------------- 1 | namespace CgmInfo.Utilities 2 | { 3 | public struct MetafilePoint 4 | { 5 | public MetafilePoint(double x, double y) 6 | { 7 | X = x; 8 | Y = y; 9 | } 10 | public double X { get; set; } 11 | public double Y { get; set; } 12 | 13 | public override string ToString() => $"X={X} Y={Y}"; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Commands/Enums/DeviceViewportSpecificationModeType.cs: -------------------------------------------------------------------------------- 1 | namespace CgmInfo.Commands.Enums 2 | { 3 | public enum DeviceViewportSpecificationModeType 4 | { 5 | [TextToken("FRACTION")] 6 | FractionOfDrawingSurface = 0, 7 | [TextToken("MM")] 8 | MillimetersWithScaleFactor = 1, 9 | [TextToken("PHYDEVCOORD")] 10 | PhysicalDeviceCoordinates = 2, 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Common.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | BhaaL 5 | BhaaL 6 | https://github.com/BhaaLseN/CgmInfo 7 | Git 8 | 3.0.0.0 9 | latest 10 | true 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /Commands/Enums/CharacterCodingAnnouncerType.cs: -------------------------------------------------------------------------------- 1 | namespace CgmInfo.Commands.Enums 2 | { 3 | public enum CharacterCodingAnnouncerType 4 | { 5 | [TextToken("BASIC7BIT")] 6 | Basic7Bit = 0, 7 | [TextToken("BASIC8BIT")] 8 | Basic8Bit = 1, 9 | [TextToken("EXTD7BIT")] 10 | Extended7Bit = 2, 11 | [TextToken("EXTD8BIT")] 12 | Extended8Bit = 3, 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Commands/Enums/HorizontalTextAlignment.cs: -------------------------------------------------------------------------------- 1 | namespace CgmInfo.Commands.Enums 2 | { 3 | public enum HorizontalTextAlignment 4 | { 5 | [TextToken("NORMHORIZ")] 6 | Normal = 0, 7 | [TextToken("LEFT")] 8 | Left = 1, 9 | [TextToken("CTR")] 10 | Center = 2, 11 | [TextToken("RIGHT")] 12 | Right = 3, 13 | [TextToken("CONTHORIZ")] 14 | Continuous = 4, 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Commands/StructuredDataElement.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Commands.Enums; 2 | 3 | namespace CgmInfo.Commands 4 | { 5 | public class StructuredDataElement 6 | { 7 | public StructuredDataElement(DataTypeIndex type, object[] values) 8 | { 9 | Type = type; 10 | Values = values; 11 | } 12 | 13 | public DataTypeIndex Type { get; } 14 | public object[] Values { get; } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /StreamExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | 4 | namespace CgmInfo 5 | { 6 | internal static class StreamExtensions 7 | { 8 | public static ushort ReadWord(this Stream stream) 9 | { 10 | if (stream == null) 11 | throw new ArgumentNullException(nameof(stream)); 12 | 13 | return (ushort)((stream.ReadByte() << 8) | stream.ReadByte()); 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Commands/Delimiter/EndFigure.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | 3 | namespace CgmInfo.Commands.Delimiter 4 | { 5 | [TextToken("ENDFIGURE")] 6 | public class EndFigure : Command 7 | { 8 | public EndFigure() 9 | : base(0, 9) 10 | { 11 | } 12 | 13 | public override void Accept(ICommandVisitor visitor, T parameter) 14 | { 15 | visitor.AcceptDelimiterEndFigure(this, parameter); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Commands/Delimiter/EndMetafile.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | 3 | namespace CgmInfo.Commands.Delimiter 4 | { 5 | [TextToken("ENDMF")] 6 | public class EndMetafile : Command 7 | { 8 | public EndMetafile() 9 | : base(0, 2) 10 | { 11 | } 12 | 13 | public override void Accept(ICommandVisitor visitor, T parameter) 14 | { 15 | visitor.AcceptDelimiterEndMetafile(this, parameter); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Commands/Delimiter/EndPicture.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | 3 | namespace CgmInfo.Commands.Delimiter 4 | { 5 | [TextToken("ENDPIC")] 6 | public class EndPicture : Command 7 | { 8 | public EndPicture() 9 | : base(0, 5) 10 | { 11 | } 12 | 13 | public override void Accept(ICommandVisitor visitor, T parameter) 14 | { 15 | visitor.AcceptDelimiterEndPicture(this, parameter); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Commands/Delimiter/EndSegment.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | 3 | namespace CgmInfo.Commands.Delimiter 4 | { 5 | [TextToken("ENDSEG")] 6 | public class EndSegment : Command 7 | { 8 | public EndSegment() 9 | : base(0, 7) 10 | { 11 | } 12 | 13 | public override void Accept(ICommandVisitor visitor, T parameter) 14 | { 15 | visitor.AcceptDelimiterEndSegment(this, parameter); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Commands/Control/NewRegion.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | 3 | namespace CgmInfo.Commands.MetafileDescriptor 4 | { 5 | [TextToken("NEWREGION")] 6 | public class NewRegion : Command 7 | { 8 | public NewRegion() 9 | : base(3, 10) 10 | { 11 | } 12 | 13 | public override void Accept(ICommandVisitor visitor, T parameter) 14 | { 15 | visitor.AcceptControlNewRegion(this, parameter); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Commands/Delimiter/BeginFigure.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | 3 | namespace CgmInfo.Commands.Delimiter 4 | { 5 | [TextToken("BEGFIGURE")] 6 | public class BeginFigure : Command 7 | { 8 | public BeginFigure() 9 | : base(0, 8) 10 | { 11 | } 12 | 13 | public override void Accept(ICommandVisitor visitor, T parameter) 14 | { 15 | visitor.AcceptDelimiterBeginFigure(this, parameter); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Commands/Delimiter/EndTileArray.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | 3 | namespace CgmInfo.Commands.Delimiter 4 | { 5 | [TextToken("ENDTILEARRAY")] 6 | public class EndTileArray : Command 7 | { 8 | public EndTileArray() 9 | : base(0, 20) 10 | { 11 | } 12 | 13 | public override void Accept(ICommandVisitor visitor, T parameter) 14 | { 15 | visitor.AcceptDelimiterEndTileArray(this, parameter); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Commands/Delimiter/BeginPictureBody.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | 3 | namespace CgmInfo.Commands.Delimiter 4 | { 5 | [TextToken("BEGPICBODY")] 6 | public class BeginPictureBody : Command 7 | { 8 | public BeginPictureBody() 9 | : base(0, 4) 10 | { 11 | } 12 | 13 | public override void Accept(ICommandVisitor visitor, T parameter) 14 | { 15 | visitor.AcceptDelimiterBeginPictureBody(this, parameter); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Commands/Delimiter/EndCompoundLine.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | 3 | namespace CgmInfo.Commands.Delimiter 4 | { 5 | [TextToken("ENDCOMPOLINE")] 6 | public class EndCompoundLine : Command 7 | { 8 | public EndCompoundLine() 9 | : base(0, 16) 10 | { 11 | } 12 | 13 | public override void Accept(ICommandVisitor visitor, T parameter) 14 | { 15 | visitor.AcceptDelimiterEndCompoundLine(this, parameter); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Commands/Enums/CharacterSetType.cs: -------------------------------------------------------------------------------- 1 | namespace CgmInfo.Commands.Enums 2 | { 3 | public enum CharacterSetType 4 | { 5 | [TextToken("STD94")] 6 | GSet94Characters = 0, 7 | [TextToken("STD96")] 8 | GSet96Characters = 1, 9 | [TextToken("STD94MULTIBYTE")] 10 | GSet94CharactersMultibyte = 2, 11 | [TextToken("STD96MULTIBYTE")] 12 | GSet96CharactersMultibyte = 3, 13 | [TextToken("COMPLETECODE")] 14 | CompleteCode = 4, 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /CgmInfoGui/ViewModels/Nodes/FontListNode.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using CgmInfo.Commands.MetafileDescriptor; 3 | 4 | namespace CgmInfoGui.ViewModels.Nodes; 5 | 6 | public class FontListNode : NodeBase 7 | { 8 | public FontListNode(FontList fontList) 9 | { 10 | Nodes.AddRange(fontList.Fonts.Select(font => new SimpleNode(font))); 11 | } 12 | 13 | public override string DisplayName 14 | { 15 | get { return string.Format("FONT LIST: [{0} entries]", Nodes.Count); } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Commands/Delimiter/BeginCompoundLine.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | 3 | namespace CgmInfo.Commands.Delimiter 4 | { 5 | [TextToken("BEGCOMPOLINE")] 6 | public class BeginCompoundLine : Command 7 | { 8 | public BeginCompoundLine() 9 | : base(0, 15) 10 | { 11 | } 12 | 13 | public override void Accept(ICommandVisitor visitor, T parameter) 14 | { 15 | visitor.AcceptDelimiterBeginCompoundLine(this, parameter); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Commands/Delimiter/EndProtectionRegion.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | 3 | namespace CgmInfo.Commands.Delimiter 4 | { 5 | [TextToken("ENDPROTREGION")] 6 | public class EndProtectionRegion : Command 7 | { 8 | public EndProtectionRegion() 9 | : base(0, 14) 10 | { 11 | } 12 | 13 | public override void Accept(ICommandVisitor visitor, T parameter) 14 | { 15 | visitor.AcceptDelimiterEndProtectionRegion(this, parameter); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /CgmInfoGui/ViewModels/Nodes/Sources/ITileSource.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Commands; 2 | 3 | namespace CgmInfoGui.ViewModels.Nodes.Sources; 4 | 5 | public interface ITileSource 6 | { 7 | bool IsBlackAndWhite { get; } 8 | int CompressionType { get; } 9 | byte[] CompressedCells { get; } 10 | StructuredDataRecord Parameters { get; } 11 | 12 | // Width/Height in Pixels 13 | int Width { get; } 14 | int Height { get; } 15 | int DpiX { get; } 16 | int DpiY { get; } 17 | int ColorPrecision { get; } 18 | } 19 | -------------------------------------------------------------------------------- /Commands/Delimiter/EndCompoundTextPath.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | 3 | namespace CgmInfo.Commands.Delimiter 4 | { 5 | [TextToken("ENDCOMPOTEXTPATH")] 6 | public class EndCompoundTextPath : Command 7 | { 8 | public EndCompoundTextPath() 9 | : base(0, 18) 10 | { 11 | } 12 | 13 | public override void Accept(ICommandVisitor visitor, T parameter) 14 | { 15 | visitor.AcceptDelimiterEndCompoundTextPath(this, parameter); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Commands/GraphicalPrimitives/ConnectingEdge.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | 3 | namespace CgmInfo.Commands.GraphicalPrimitives 4 | { 5 | [TextToken("CONNEDGE")] 6 | public class ConnectingEdge : Command 7 | { 8 | public ConnectingEdge() 9 | : base(4, 21) 10 | { 11 | } 12 | 13 | public override void Accept(ICommandVisitor visitor, T parameter) 14 | { 15 | visitor.AcceptGraphicalPrimitiveConnectingEdge(this, parameter); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Commands/Delimiter/EndApplicationStructure.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | 3 | namespace CgmInfo.Commands.Delimiter 4 | { 5 | [TextToken("ENDAPS")] 6 | public class EndApplicationStructure : Command 7 | { 8 | public EndApplicationStructure() 9 | : base(0, 23) 10 | { 11 | } 12 | 13 | public override void Accept(ICommandVisitor visitor, T parameter) 14 | { 15 | visitor.AcceptDelimiterEndApplicationStructure(this, parameter); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Commands/Delimiter/BeginCompoundTextPath.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | 3 | namespace CgmInfo.Commands.Delimiter 4 | { 5 | [TextToken("BEGCOMPOTEXTPATH")] 6 | public class BeginCompoundTextPath : Command 7 | { 8 | public BeginCompoundTextPath() 9 | : base(0, 17) 10 | { 11 | } 12 | 13 | public override void Accept(ICommandVisitor visitor, T parameter) 14 | { 15 | visitor.AcceptDelimiterBeginCompoundTextPath(this, parameter); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Commands/Segment/InheritanceFilterItem.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Commands.Enums; 2 | 3 | namespace CgmInfo.Commands.Segment 4 | { 5 | public class InheritanceFilterItem 6 | { 7 | public InheritanceFilterItem(InheritanceFilterDesignator designator, InheritanceFilterSetting setting) 8 | { 9 | Designator = designator; 10 | Setting = setting; 11 | } 12 | 13 | public InheritanceFilterDesignator Designator { get; } 14 | public InheritanceFilterSetting Setting { get; } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /CgmInfoGui/ViewModels/Nodes/PictureNode.cs: -------------------------------------------------------------------------------- 1 | namespace CgmInfoGui.ViewModels.Nodes; 2 | 3 | public class PictureNode : NodeBase 4 | { 5 | public PictureNode(string name) 6 | { 7 | Name = name; 8 | Descriptor = new SimpleNode("PICTURE DESCRIPTOR"); 9 | Nodes.Add(Descriptor); 10 | } 11 | public string Name { get; } 12 | public SimpleNode Descriptor { get; } 13 | 14 | public override string DisplayName 15 | { 16 | get { return string.Format("BEGIN PICTURE: '{0}'", Name); } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Commands/Enums/VerticalTextAlignment.cs: -------------------------------------------------------------------------------- 1 | namespace CgmInfo.Commands.Enums 2 | { 3 | public enum VerticalTextAlignment 4 | { 5 | [TextToken("NORMVERT")] 6 | Normal = 0, 7 | [TextToken("TOP")] 8 | Top = 1, 9 | [TextToken("CAP")] 10 | Cap = 2, 11 | [TextToken("HALF")] 12 | Half = 3, 13 | [TextToken("BASE")] 14 | Base = 4, 15 | [TextToken("BOTTOM")] 16 | Bottom = 5, 17 | [TextToken("CONTVERT")] 18 | Continuous = 6, 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /CgmInfoGui/ViewModels/Nodes/MetafileNode.cs: -------------------------------------------------------------------------------- 1 | namespace CgmInfoGui.ViewModels.Nodes; 2 | 3 | public class MetafileNode : NodeBase 4 | { 5 | public MetafileNode(string name) 6 | { 7 | Name = name; 8 | Descriptor = new SimpleNode("METAFILE DESCRIPTOR"); 9 | Nodes.Add(Descriptor); 10 | } 11 | public string Name { get; } 12 | public SimpleNode Descriptor { get; } 13 | 14 | public override string DisplayName 15 | { 16 | get { return string.Format("BEGIN METAFILE: '{0}'", Name); } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /TextEncoding/ApplicationStructureDescriptorReader.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Commands.ApplicationStructureDescriptor; 2 | 3 | namespace CgmInfo.TextEncoding 4 | { 5 | internal static class ApplicationStructureDescriptorReader 6 | { 7 | public static ApplicationStructureAttribute ApplicationStructureAttribute(MetafileReader reader) 8 | { 9 | string attributeType = reader.ReadString(); 10 | return new ApplicationStructureAttribute(attributeType, reader.ReadStructuredDataRecord()); 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Commands/Enums/InteriorStyleType.cs: -------------------------------------------------------------------------------- 1 | namespace CgmInfo.Commands.Enums 2 | { 3 | public enum InteriorStyleType 4 | { 5 | [TextToken("HOLLOW")] 6 | Hollow = 0, 7 | [TextToken("SOLID")] 8 | Solid = 1, 9 | [TextToken("PAT")] 10 | Pattern = 2, 11 | [TextToken("HATCH")] 12 | Hatch = 3, 13 | [TextToken("EMPTY")] 14 | Empty = 4, 15 | [TextToken("GEOPAT")] 16 | GeometricPattern = 5, 17 | [TextToken("INTERP")] 18 | Interpolated = 6, 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /CgmInfoGui/ViewModels/Nodes/SegmentNode.cs: -------------------------------------------------------------------------------- 1 | namespace CgmInfoGui.ViewModels.Nodes; 2 | 3 | public class SegmentNode : NodeBase 4 | { 5 | public SegmentNode(int identifier) 6 | { 7 | Identifier = identifier; 8 | Descriptor = new SimpleNode("SEGMENT DESCRIPTOR"); 9 | Nodes.Add(Descriptor); 10 | } 11 | public int Identifier { get; } 12 | public SimpleNode Descriptor { get; } 13 | 14 | public override string DisplayName 15 | { 16 | get { return string.Format("BEGIN SEGMENT: {0}", Identifier); } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Commands/Delimiter/BeginApplicationStructureBody.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | 3 | namespace CgmInfo.Commands.Delimiter 4 | { 5 | [TextToken("BEGAPSBODY")] 6 | public class BeginApplicationStructureBody : Command 7 | { 8 | public BeginApplicationStructureBody() 9 | : base(0, 22) 10 | { 11 | } 12 | 13 | public override void Accept(ICommandVisitor visitor, T parameter) 14 | { 15 | visitor.AcceptDelimiterBeginApplicationStructureBody(this, parameter); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Commands/Attributes/EdgeWidth.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | 3 | namespace CgmInfo.Commands.Attributes 4 | { 5 | [TextToken("EDGEWIDTH")] 6 | public class EdgeWidth : Command 7 | { 8 | public EdgeWidth(double width) 9 | : base(5, 28) 10 | { 11 | Width = width; 12 | } 13 | 14 | public double Width { get; } 15 | 16 | public override void Accept(ICommandVisitor visitor, T parameter) 17 | { 18 | visitor.AcceptAttributeEdgeWidth(this, parameter); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Commands/Attributes/LineWidth.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | 3 | namespace CgmInfo.Commands.Attributes 4 | { 5 | [TextToken("LINEWIDTH")] 6 | public class LineWidth : Command 7 | { 8 | public LineWidth(double width) 9 | : base(5, 3) 10 | { 11 | Width = width; 12 | } 13 | 14 | public double Width { get; } 15 | 16 | public override void Accept(ICommandVisitor visitor, T parameter) 17 | { 18 | visitor.AcceptAttributeLineWidth(this, parameter); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Commands/Attributes/MarkerSize.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | 3 | namespace CgmInfo.Commands.Attributes 4 | { 5 | [TextToken("MARKERSIZE")] 6 | public class MarkerSize : Command 7 | { 8 | public MarkerSize(double size) 9 | : base(5, 7) 10 | { 11 | Size = size; 12 | } 13 | 14 | public double Size { get; } 15 | 16 | public override void Accept(ICommandVisitor visitor, T parameter) 17 | { 18 | visitor.AcceptAttributeMarkerSize(this, parameter); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Commands/Attributes/PatternIndex.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | 3 | namespace CgmInfo.Commands.Attributes 4 | { 5 | [TextToken("PATINDEX")] 6 | public class PatternIndex : Command 7 | { 8 | public PatternIndex(int index) 9 | : base(5, 25) 10 | { 11 | Index = index; 12 | } 13 | 14 | public int Index { get; } 15 | 16 | public override void Accept(ICommandVisitor visitor, T parameter) 17 | { 18 | visitor.AcceptAttributePatternIndex(this, parameter); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Commands/Delimiter/BeginMetafile.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | 3 | namespace CgmInfo.Commands.Delimiter 4 | { 5 | [TextToken("BEGMF")] 6 | public class BeginMetafile : Command 7 | { 8 | public BeginMetafile(string name) 9 | : base(0, 1) 10 | { 11 | Name = name; 12 | } 13 | 14 | public string Name { get; } 15 | 16 | public override void Accept(ICommandVisitor visitor, T parameter) 17 | { 18 | visitor.AcceptDelimiterBeginMetafile(this, parameter); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Commands/Delimiter/BeginPicture.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | 3 | namespace CgmInfo.Commands.Delimiter 4 | { 5 | [TextToken("BEGPIC")] 6 | public class BeginPicture : Command 7 | { 8 | public BeginPicture(string name) 9 | : base(0, 3) 10 | { 11 | Name = name; 12 | } 13 | 14 | public string Name { get; } 15 | 16 | public override void Accept(ICommandVisitor visitor, T parameter) 17 | { 18 | visitor.AcceptDelimiterBeginPicture(this, parameter); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /CgmInfoGui/Controls/PropertyGrid/ReadOnlyPropertyGrid.axaml.cs: -------------------------------------------------------------------------------- 1 | using Avalonia; 2 | using Avalonia.Controls.Primitives; 3 | 4 | namespace CgmInfoGui.Controls.PropertyGrid; 5 | 6 | public class ReadOnlyPropertyGrid : TemplatedControl 7 | { 8 | public static readonly StyledProperty SelectedObjectProperty = 9 | AvaloniaProperty.Register(nameof(SelectedObject)); 10 | public object SelectedObject 11 | { 12 | get => GetValue(SelectedObjectProperty); 13 | set => SetValue(SelectedObjectProperty, value); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Commands/Control/MiterLimit.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | 3 | namespace CgmInfo.Commands.MetafileDescriptor 4 | { 5 | [TextToken("MITRELIMIT")] 6 | public class MiterLimit : Command 7 | { 8 | public MiterLimit(double limit) 9 | : base(3, 19) 10 | { 11 | Limit = limit; 12 | } 13 | 14 | public double Limit { get; } 15 | 16 | public override void Accept(ICommandVisitor visitor, T parameter) 17 | { 18 | visitor.AcceptControlMiterLimit(this, parameter); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Commands/Attributes/TextFontIndex.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | 3 | namespace CgmInfo.Commands.Attributes 4 | { 5 | [TextToken("TEXTFONTINDEX")] 6 | public class TextFontIndex : Command 7 | { 8 | public TextFontIndex(int index) 9 | : base(5, 10) 10 | { 11 | Index = index; 12 | } 13 | 14 | public int Index { get; } 15 | 16 | public override void Accept(ICommandVisitor visitor, T parameter) 17 | { 18 | visitor.AcceptAttributeTextFontIndex(this, parameter); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Commands/Attributes/EdgeBundleIndex.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | 3 | namespace CgmInfo.Commands.Attributes 4 | { 5 | [TextToken("EDGEINDEX")] 6 | public class EdgeBundleIndex : Command 7 | { 8 | public EdgeBundleIndex(int index) 9 | : base(5, 26) 10 | { 11 | Index = index; 12 | } 13 | 14 | public int Index { get; } 15 | 16 | public override void Accept(ICommandVisitor visitor, T parameter) 17 | { 18 | visitor.AcceptAttributeEdgeBundleIndex(this, parameter); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Commands/Attributes/FillBundleIndex.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | 3 | namespace CgmInfo.Commands.Attributes 4 | { 5 | [TextToken("FILLINDEX")] 6 | public class FillBundleIndex : Command 7 | { 8 | public FillBundleIndex(int index) 9 | : base(5, 21) 10 | { 11 | Index = index; 12 | } 13 | 14 | public int Index { get; } 15 | 16 | public override void Accept(ICommandVisitor visitor, T parameter) 17 | { 18 | visitor.AcceptAttributeFillBundleIndex(this, parameter); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Commands/Attributes/LineBundleIndex.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | 3 | namespace CgmInfo.Commands.Attributes 4 | { 5 | [TextToken("LINEINDEX")] 6 | public class LineBundleIndex : Command 7 | { 8 | public LineBundleIndex(int index) 9 | : base(5, 1) 10 | { 11 | Index = index; 12 | } 13 | 14 | public int Index { get; } 15 | 16 | public override void Accept(ICommandVisitor visitor, T parameter) 17 | { 18 | visitor.AcceptAttributeLineBundleIndex(this, parameter); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Commands/Attributes/TextBundleIndex.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | 3 | namespace CgmInfo.Commands.Attributes 4 | { 5 | [TextToken("TEXTINDEX")] 6 | public class TextBundleIndex : Command 7 | { 8 | public TextBundleIndex(int index) 9 | : base(5, 9) 10 | { 11 | Index = index; 12 | } 13 | 14 | public int Index { get; } 15 | 16 | public override void Accept(ICommandVisitor visitor, T parameter) 17 | { 18 | visitor.AcceptAttributeTextBundleIndex(this, parameter); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Commands/Delimiter/BeginSegment.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | 3 | namespace CgmInfo.Commands.Delimiter 4 | { 5 | [TextToken("BEGSEG")] 6 | public class BeginSegment : Command 7 | { 8 | public BeginSegment(int identifier) 9 | : base(0, 6) 10 | { 11 | Identifier = identifier; 12 | } 13 | 14 | public int Identifier { get; } 15 | 16 | public override void Accept(ICommandVisitor visitor, T parameter) 17 | { 18 | visitor.AcceptDelimiterBeginSegment(this, parameter); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /CgmInfoGui/Controls/PropertiesPanel.axaml.cs: -------------------------------------------------------------------------------- 1 | using Avalonia; 2 | using Avalonia.Controls; 3 | 4 | namespace CgmInfoGui.Controls; 5 | 6 | public partial class PropertiesPanel : UserControl 7 | { 8 | public PropertiesPanel() 9 | { 10 | InitializeComponent(); 11 | } 12 | 13 | public static readonly StyledProperty SourceProperty = 14 | AvaloniaProperty.Register(nameof(Source)); 15 | 16 | public object? Source 17 | { 18 | get => GetValue(SourceProperty); 19 | set => SetValue(SourceProperty, value); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Commands/Attributes/CharacterHeight.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | 3 | namespace CgmInfo.Commands.Attributes 4 | { 5 | [TextToken("CHARHEIGHT")] 6 | public class CharacterHeight : Command 7 | { 8 | public CharacterHeight(double height) 9 | : base(5, 15) 10 | { 11 | Height = height; 12 | } 13 | 14 | public double Height { get; } 15 | 16 | public override void Accept(ICommandVisitor visitor, T parameter) 17 | { 18 | visitor.AcceptAttributeCharacterHeight(this, parameter); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Commands/Attributes/CharacterSetIndex.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | 3 | namespace CgmInfo.Commands.Attributes 4 | { 5 | [TextToken("CHARSETINDEX")] 6 | public class CharacterSetIndex : Command 7 | { 8 | public CharacterSetIndex(int index) 9 | : base(5, 19) 10 | { 11 | Index = index; 12 | } 13 | 14 | public int Index { get; } 15 | 16 | public override void Accept(ICommandVisitor visitor, T parameter) 17 | { 18 | visitor.AcceptAttributeCharacterSetIndex(this, parameter); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Commands/Attributes/MarkerBundleIndex.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | 3 | namespace CgmInfo.Commands.Attributes 4 | { 5 | [TextToken("MARKERINDEX")] 6 | public class MarkerBundleIndex : Command 7 | { 8 | public MarkerBundleIndex(int index) 9 | : base(5, 5) 10 | { 11 | Index = index; 12 | } 13 | 14 | public int Index { get; } 15 | 16 | public override void Accept(ICommandVisitor visitor, T parameter) 17 | { 18 | visitor.AcceptAttributeMarkerBundleIndex(this, parameter); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Commands/Attributes/PickIdentifier.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | 3 | namespace CgmInfo.Commands.Attributes 4 | { 5 | [TextToken("PICKID")] 6 | public class PickIdentifier : Command 7 | { 8 | public PickIdentifier(int identifier) 9 | : base(5, 36) 10 | { 11 | Identifier = identifier; 12 | } 13 | 14 | public int Identifier { get; } 15 | 16 | public override void Accept(ICommandVisitor visitor, T parameter) 17 | { 18 | visitor.AcceptAttributePickIdentifier(this, parameter); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Commands/Attributes/TextPath.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Commands.Enums; 2 | using CgmInfo.Traversal; 3 | 4 | namespace CgmInfo.Commands.Attributes 5 | { 6 | [TextToken("TEXTPATH")] 7 | public class TextPath : Command 8 | { 9 | public TextPath(TextPathType path) 10 | : base(5, 17) 11 | { 12 | Path = path; 13 | } 14 | 15 | public TextPathType Path { get; } 16 | 17 | public override void Accept(ICommandVisitor visitor, T parameter) 18 | { 19 | visitor.AcceptAttributeTextPath(this, parameter); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Commands/Attributes/EdgeColor.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | using CgmInfo.Utilities; 3 | 4 | namespace CgmInfo.Commands.Attributes 5 | { 6 | [TextToken("EDGECOLR")] 7 | public class EdgeColor : Command 8 | { 9 | public EdgeColor(MetafileColor color) 10 | : base(5, 29) 11 | { 12 | Color = color; 13 | } 14 | 15 | public MetafileColor Color { get; } 16 | 17 | public override void Accept(ICommandVisitor visitor, T parameter) 18 | { 19 | visitor.AcceptAttributeEdgeColor(this, parameter); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Commands/Attributes/FillColor.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | using CgmInfo.Utilities; 3 | 4 | namespace CgmInfo.Commands.Attributes 5 | { 6 | [TextToken("FILLCOLR")] 7 | public class FillColor : Command 8 | { 9 | public FillColor(MetafileColor color) 10 | : base(5, 23) 11 | { 12 | Color = color; 13 | } 14 | 15 | public MetafileColor Color { get; } 16 | 17 | public override void Accept(ICommandVisitor visitor, T parameter) 18 | { 19 | visitor.AcceptAttributeFillColor(this, parameter); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Commands/Attributes/LineColor.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | using CgmInfo.Utilities; 3 | 4 | namespace CgmInfo.Commands.Attributes 5 | { 6 | [TextToken("LINECOLR")] 7 | public class LineColor : Command 8 | { 9 | public LineColor(MetafileColor color) 10 | : base(5, 4) 11 | { 12 | Color = color; 13 | } 14 | 15 | public MetafileColor Color { get; } 16 | 17 | public override void Accept(ICommandVisitor visitor, T parameter) 18 | { 19 | visitor.AcceptAttributeLineColor(this, parameter); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Commands/Attributes/TextColor.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | using CgmInfo.Utilities; 3 | 4 | namespace CgmInfo.Commands.Attributes 5 | { 6 | [TextToken("TEXTCOLR")] 7 | public class TextColor : Command 8 | { 9 | public TextColor(MetafileColor color) 10 | : base(5, 14) 11 | { 12 | Color = color; 13 | } 14 | 15 | public MetafileColor Color { get; } 16 | 17 | public override void Accept(ICommandVisitor visitor, T parameter) 18 | { 19 | visitor.AcceptAttributeTextColor(this, parameter); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Commands/MetafileDescriptor/MetafileVersion.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | 3 | namespace CgmInfo.Commands.MetafileDescriptor 4 | { 5 | [TextToken("MFVERSION")] 6 | public class MetafileVersion : Command 7 | { 8 | public MetafileVersion(int version) 9 | : base(1, 1) 10 | { 11 | Version = version; 12 | } 13 | 14 | public int Version { get; } 15 | 16 | public override void Accept(ICommandVisitor visitor, T parameter) 17 | { 18 | visitor.AcceptMetafileDescriptorMetafileVersion(this, parameter); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Commands/MetafileDescriptor/NamePrecision.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | 3 | namespace CgmInfo.Commands.MetafileDescriptor 4 | { 5 | [TextToken("NAMEPREC")] 6 | public class NamePrecision : Command 7 | { 8 | public NamePrecision(int precision) 9 | : base(1, 16) 10 | { 11 | Precision = precision; 12 | } 13 | 14 | public int Precision { get; } 15 | 16 | public override void Accept(ICommandVisitor visitor, T parameter) 17 | { 18 | visitor.AcceptMetafileDescriptorNamePrecision(this, parameter); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /CgmInfoGui/Controls/RawPanel.axaml.cs: -------------------------------------------------------------------------------- 1 | using Avalonia; 2 | using Avalonia.Controls; 3 | using CgmInfoGui.ViewModels.Nodes; 4 | 5 | namespace CgmInfoGui.Controls; 6 | 7 | public partial class RawPanel : UserControl 8 | { 9 | public RawPanel() 10 | { 11 | InitializeComponent(); 12 | } 13 | 14 | public static readonly StyledProperty SourceProperty = 15 | AvaloniaProperty.Register(nameof(Source)); 16 | 17 | public NodeBase? Source 18 | { 19 | get => GetValue(SourceProperty); 20 | set => SetValue(SourceProperty, value); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Commands/Attributes/MarkerColor.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | using CgmInfo.Utilities; 3 | 4 | namespace CgmInfo.Commands.Attributes 5 | { 6 | [TextToken("MARKERCOLR")] 7 | public class MarkerColor : Command 8 | { 9 | public MarkerColor(MetafileColor color) 10 | : base(5, 8) 11 | { 12 | Color = color; 13 | } 14 | 15 | public MetafileColor Color { get; } 16 | 17 | public override void Accept(ICommandVisitor visitor, T parameter) 18 | { 19 | visitor.AcceptAttributeMarkerColor(this, parameter); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Commands/MetafileDescriptor/ColorPrecision.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | 3 | namespace CgmInfo.Commands.MetafileDescriptor 4 | { 5 | [TextToken("COLRPREC")] 6 | public class ColorPrecision : Command 7 | { 8 | public ColorPrecision(int precision) 9 | : base(1, 7) 10 | { 11 | Precision = precision; 12 | } 13 | 14 | public int Precision { get; } 15 | 16 | public override void Accept(ICommandVisitor visitor, T parameter) 17 | { 18 | visitor.AcceptMetafileDescriptorColorPrecision(this, parameter); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Commands/MetafileDescriptor/IndexPrecision.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | 3 | namespace CgmInfo.Commands.MetafileDescriptor 4 | { 5 | [TextToken("INDEXPREC")] 6 | public class IndexPrecision : Command 7 | { 8 | public IndexPrecision(int precision) 9 | : base(1, 6) 10 | { 11 | Precision = precision; 12 | } 13 | 14 | public int Precision { get; } 15 | 16 | public override void Accept(ICommandVisitor visitor, T parameter) 17 | { 18 | visitor.AcceptMetafileDescriptorIndexPrecision(this, parameter); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Commands/MetafileDescriptor/MaximumColorIndex.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | 3 | namespace CgmInfo.Commands.MetafileDescriptor 4 | { 5 | [TextToken("MAXCOLRINDEX")] 6 | public class MaximumColorIndex : Command 7 | { 8 | public MaximumColorIndex(int index) 9 | : base(1, 9) 10 | { 11 | Index = index; 12 | } 13 | 14 | public int Index { get; } 15 | 16 | public override void Accept(ICommandVisitor visitor, T parameter) 17 | { 18 | visitor.AcceptMetafileDescriptorMaximumColorIndex(this, parameter); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Commands/Control/VdcIntegerPrecision.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | 3 | namespace CgmInfo.Commands.MetafileDescriptor 4 | { 5 | [TextToken("VDCINTEGERPREC")] 6 | public class VdcIntegerPrecision : Command 7 | { 8 | public VdcIntegerPrecision(int precision) 9 | : base(3, 1) 10 | { 11 | Precision = precision; 12 | } 13 | 14 | public int Precision { get; } 15 | 16 | public override void Accept(ICommandVisitor visitor, T parameter) 17 | { 18 | visitor.AcceptControlVdcIntegerPrecision(this, parameter); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Commands/Segment/InheritanceFilter.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | 3 | namespace CgmInfo.Commands.Segment 4 | { 5 | [TextToken("INHFILTER")] 6 | public class InheritanceFilter : Command 7 | { 8 | public InheritanceFilter(InheritanceFilterItem[] items) 9 | : base(8, 2) 10 | { 11 | Items = items; 12 | } 13 | 14 | public InheritanceFilterItem[] Items { get; } 15 | 16 | public override void Accept(ICommandVisitor visitor, T parameter) 17 | { 18 | visitor.AcceptSegmentInheritanceFilter(this, parameter); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Commands/Attributes/CharacterExpansionFactor.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | 3 | namespace CgmInfo.Commands.Attributes 4 | { 5 | [TextToken("CHAREXPAN")] 6 | public class CharacterExpansionFactor : Command 7 | { 8 | public CharacterExpansionFactor(double factor) 9 | : base(5, 12) 10 | { 11 | Factor = factor; 12 | } 13 | 14 | public double Factor { get; } 15 | 16 | public override void Accept(ICommandVisitor visitor, T parameter) 17 | { 18 | visitor.AcceptAttributeCharacterExpansionFactor(this, parameter); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Commands/Attributes/EdgeTypeInitialOffset.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | 3 | namespace CgmInfo.Commands.Attributes 4 | { 5 | [TextToken("EDGETYPEINITOFFSET")] 6 | public class EdgeTypeInitialOffset : Command 7 | { 8 | public EdgeTypeInitialOffset(double offset) 9 | : base(5, 47) 10 | { 11 | Offset = offset; 12 | } 13 | 14 | public double Offset { get; } 15 | 16 | public override void Accept(ICommandVisitor visitor, T parameter) 17 | { 18 | visitor.AcceptAttributeEdgeTypeInitialOffset(this, parameter); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Commands/Attributes/LineTypeInitialOffset.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | 3 | namespace CgmInfo.Commands.Attributes 4 | { 5 | [TextToken("LINETYPEINITOFFSET")] 6 | public class LineTypeInitialOffset : Command 7 | { 8 | public LineTypeInitialOffset(double offset) 9 | : base(5, 40) 10 | { 11 | Offset = offset; 12 | } 13 | 14 | public double Offset { get; } 15 | 16 | public override void Accept(ICommandVisitor visitor, T parameter) 17 | { 18 | visitor.AcceptAttributeLineTypeInitialOffset(this, parameter); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Commands/Control/AuxiliaryColor.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | using CgmInfo.Utilities; 3 | 4 | namespace CgmInfo.Commands.MetafileDescriptor 5 | { 6 | [TextToken("AUXCOLR")] 7 | public class AuxiliaryColor : Command 8 | { 9 | public AuxiliaryColor(MetafileColor color) 10 | : base(3, 3) 11 | { 12 | Color = color; 13 | } 14 | 15 | public MetafileColor Color { get; } 16 | 17 | public override void Accept(ICommandVisitor visitor, T parameter) 18 | { 19 | visitor.AcceptControlAuxiliaryColor(this, parameter); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Commands/MetafileDescriptor/IntegerPrecision.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | 3 | namespace CgmInfo.Commands.MetafileDescriptor 4 | { 5 | [TextToken("INTEGERPREC")] 6 | public class IntegerPrecision : Command 7 | { 8 | public IntegerPrecision(int precision) 9 | : base(1, 4) 10 | { 11 | Precision = precision; 12 | } 13 | 14 | public int Precision { get; } 15 | 16 | public override void Accept(ICommandVisitor visitor, T parameter) 17 | { 18 | visitor.AcceptMetafileDescriptorIntegerPrecision(this, parameter); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Commands/Attributes/AlternateCharacterSetIndex.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | 3 | namespace CgmInfo.Commands.Attributes 4 | { 5 | [TextToken("ALTCHARSETINDEX")] 6 | public class AlternateCharacterSetIndex : Command 7 | { 8 | public AlternateCharacterSetIndex(int index) 9 | : base(5, 20) 10 | { 11 | Index = index; 12 | } 13 | 14 | public int Index { get; } 15 | 16 | public override void Accept(ICommandVisitor visitor, T parameter) 17 | { 18 | visitor.AcceptAttributeAlternateCharacterSetIndex(this, parameter); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Commands/Control/SavePrimitiveContext.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | 3 | namespace CgmInfo.Commands.MetafileDescriptor 4 | { 5 | [TextToken("SAVEPRIMCONT")] 6 | public class SavePrimitiveContext : Command 7 | { 8 | public SavePrimitiveContext(int contextName) 9 | : base(3, 11) 10 | { 11 | ContextName = contextName; 12 | } 13 | 14 | public int ContextName { get; } 15 | 16 | public override void Accept(ICommandVisitor visitor, T parameter) 17 | { 18 | visitor.AcceptControlSavePrimitiveContext(this, parameter); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Commands/Delimiter/BeginProtectionRegion.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | 3 | namespace CgmInfo.Commands.Delimiter 4 | { 5 | [TextToken("BEGPROTREGION")] 6 | public class BeginProtectionRegion : Command 7 | { 8 | public BeginProtectionRegion(int regionIndex) 9 | : base(0, 13) 10 | { 11 | RegionIndex = regionIndex; 12 | } 13 | 14 | public int RegionIndex { get; } 15 | 16 | public override void Accept(ICommandVisitor visitor, T parameter) 17 | { 18 | visitor.AcceptDelimiterBeginProtectionRegion(this, parameter); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Commands/GraphicalPrimitives/Polygon.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | using CgmInfo.Utilities; 3 | 4 | namespace CgmInfo.Commands.GraphicalPrimitives 5 | { 6 | [TextToken("POLYGON")] 7 | public class Polygon : Command 8 | { 9 | public Polygon(MetafilePoint[] points) 10 | : base(4, 7) 11 | { 12 | Points = points; 13 | } 14 | 15 | public MetafilePoint[] Points { get; } 16 | 17 | public override void Accept(ICommandVisitor visitor, T parameter) 18 | { 19 | visitor.AcceptGraphicalPrimitivePolygon(this, parameter); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Commands/GraphicalPrimitives/Polyline.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | using CgmInfo.Utilities; 3 | 4 | namespace CgmInfo.Commands.GraphicalPrimitives 5 | { 6 | [TextToken("LINE")] 7 | public class Polyline : Command 8 | { 9 | public Polyline(MetafilePoint[] points) 10 | : base(4, 1) 11 | { 12 | Points = points; 13 | } 14 | 15 | public MetafilePoint[] Points { get; } 16 | 17 | public override void Accept(ICommandVisitor visitor, T parameter) 18 | { 19 | visitor.AcceptGraphicalPrimitivePolyline(this, parameter); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Commands/Attributes/InteriorStyle.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Commands.Enums; 2 | using CgmInfo.Traversal; 3 | 4 | namespace CgmInfo.Commands.Attributes 5 | { 6 | [TextToken("INTSTYLE")] 7 | public class InteriorStyle : Command 8 | { 9 | public InteriorStyle(InteriorStyleType style) 10 | : base(5, 22) 11 | { 12 | Style = style; 13 | } 14 | 15 | public InteriorStyleType Style { get; } 16 | 17 | public override void Accept(ICommandVisitor visitor, T parameter) 18 | { 19 | visitor.AcceptAttributeInteriorStyle(this, parameter); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Commands/Control/ClipIndicator.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Commands.Enums; 2 | using CgmInfo.Traversal; 3 | 4 | namespace CgmInfo.Commands.MetafileDescriptor 5 | { 6 | [TextToken("CLIP")] 7 | public class ClipIndicator : Command 8 | { 9 | public ClipIndicator(OnOffIndicator indicator) 10 | : base(3, 6) 11 | { 12 | Indicator = indicator; 13 | } 14 | 15 | public OnOffIndicator Indicator { get; } 16 | 17 | public override void Accept(ICommandVisitor visitor, T parameter) 18 | { 19 | visitor.AcceptControlClipIndicator(this, parameter); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Commands/Control/EdgeClippingMode.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Commands.Enums; 2 | using CgmInfo.Traversal; 3 | 4 | namespace CgmInfo.Commands.MetafileDescriptor 5 | { 6 | [TextToken("EDGECLIPMODE")] 7 | public class EdgeClippingMode : Command 8 | { 9 | public EdgeClippingMode(ClippingMode mode) 10 | : base(3, 9) 11 | { 12 | Mode = mode; 13 | } 14 | 15 | public ClippingMode Mode { get; } 16 | 17 | public override void Accept(ICommandVisitor visitor, T parameter) 18 | { 19 | visitor.AcceptControlEdgeClippingMode(this, parameter); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Commands/Control/LineClippingMode.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Commands.Enums; 2 | using CgmInfo.Traversal; 3 | 4 | namespace CgmInfo.Commands.MetafileDescriptor 5 | { 6 | [TextToken("LINECLIPMODE")] 7 | public class LineClippingMode : Command 8 | { 9 | public LineClippingMode(ClippingMode mode) 10 | : base(3, 7) 11 | { 12 | Mode = mode; 13 | } 14 | 15 | public ClippingMode Mode { get; } 16 | 17 | public override void Accept(ICommandVisitor visitor, T parameter) 18 | { 19 | visitor.AcceptControlLineClippingMode(this, parameter); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Commands/Control/RestorePrimitiveContext.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | 3 | namespace CgmInfo.Commands.MetafileDescriptor 4 | { 5 | [TextToken("RESPRIMCONT")] 6 | public class RestorePrimitiveContext : Command 7 | { 8 | public RestorePrimitiveContext(int contextName) 9 | : base(3, 12) 10 | { 11 | ContextName = contextName; 12 | } 13 | 14 | public int ContextName { get; } 15 | 16 | public override void Accept(ICommandVisitor visitor, T parameter) 17 | { 18 | visitor.AcceptControlRestorePrimitiveContext(this, parameter); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Commands/GraphicalPrimitives/Polymarker.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | using CgmInfo.Utilities; 3 | 4 | namespace CgmInfo.Commands.GraphicalPrimitives 5 | { 6 | [TextToken("MARKER")] 7 | public class Polymarker : Command 8 | { 9 | public Polymarker(MetafilePoint[] points) 10 | : base(4, 3) 11 | { 12 | Points = points; 13 | } 14 | 15 | public MetafilePoint[] Points { get; } 16 | 17 | public override void Accept(ICommandVisitor visitor, T parameter) 18 | { 19 | visitor.AcceptGraphicalPrimitivePolymarker(this, parameter); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Commands/MetafileDescriptor/ColorIndexPrecision.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | 3 | namespace CgmInfo.Commands.MetafileDescriptor 4 | { 5 | [TextToken("COLRINDEXPREC")] 6 | public class ColorIndexPrecision : Command 7 | { 8 | public ColorIndexPrecision(int precision) 9 | : base(1, 8) 10 | { 11 | Precision = precision; 12 | } 13 | 14 | public int Precision { get; } 15 | 16 | public override void Accept(ICommandVisitor visitor, T parameter) 17 | { 18 | visitor.AcceptMetafileDescriptorColorIndexPrecision(this, parameter); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Commands/Control/Transparency.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Commands.Enums; 2 | using CgmInfo.Traversal; 3 | 4 | namespace CgmInfo.Commands.MetafileDescriptor 5 | { 6 | [TextToken("TRANSPARENCY")] 7 | public class Transparency : Command 8 | { 9 | public Transparency(OnOffIndicator indicator) 10 | : base(3, 4) 11 | { 12 | Indicator = indicator; 13 | } 14 | 15 | public OnOffIndicator Indicator { get; } 16 | 17 | public override void Accept(ICommandVisitor visitor, T parameter) 18 | { 19 | visitor.AcceptControlTransparency(this, parameter); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Commands/MetafileDescriptor/FontList.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using CgmInfo.Traversal; 3 | 4 | namespace CgmInfo.Commands.MetafileDescriptor 5 | { 6 | [TextToken("FONTLIST")] 7 | public class FontList : Command 8 | { 9 | public FontList(IEnumerable fonts) 10 | : base(1, 13) 11 | { 12 | Fonts = fonts; 13 | } 14 | 15 | public IEnumerable Fonts { get; } 16 | 17 | public override void Accept(ICommandVisitor visitor, T parameter) 18 | { 19 | visitor.AcceptMetafileDescriptorFontList(this, parameter); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Commands/MetafileDescriptor/MetafileDescription.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | 3 | namespace CgmInfo.Commands.MetafileDescriptor 4 | { 5 | [TextToken("MFDESC")] 6 | public class MetafileDescription : Command 7 | { 8 | public MetafileDescription(string description) 9 | : base(1, 2) 10 | { 11 | Description = description; 12 | } 13 | 14 | public string Description { get; } 15 | 16 | public override void Accept(ICommandVisitor visitor, T parameter) 17 | { 18 | visitor.AcceptMetafileDescriptorMetafileDescription(this, parameter); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /CgmInfoGui/Views/ApplicationStructureView.axaml: -------------------------------------------------------------------------------- 1 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Commands/Attributes/EdgeVisibility.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Commands.Enums; 2 | using CgmInfo.Traversal; 3 | 4 | namespace CgmInfo.Commands.Attributes 5 | { 6 | [TextToken("EDGEVIS")] 7 | public class EdgeVisibility : Command 8 | { 9 | public EdgeVisibility(OnOffIndicator visibility) 10 | : base(5, 30) 11 | { 12 | Visibility = visibility; 13 | } 14 | 15 | public OnOffIndicator Visibility { get; } 16 | 17 | public override void Accept(ICommandVisitor visitor, T parameter) 18 | { 19 | visitor.AcceptAttributeEdgeVisibility(this, parameter); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Commands/Attributes/TextPrecision.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Commands.Enums; 2 | using CgmInfo.Traversal; 3 | 4 | namespace CgmInfo.Commands.Attributes 5 | { 6 | [TextToken("TEXTPREC")] 7 | public class TextPrecision : Command 8 | { 9 | public TextPrecision(TextPrecisionType precision) 10 | : base(5, 11) 11 | { 12 | Precision = precision; 13 | } 14 | 15 | public TextPrecisionType Precision { get; } 16 | 17 | public override void Accept(ICommandVisitor visitor, T parameter) 18 | { 19 | visitor.AcceptAttributeTextPrecision(this, parameter); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Commands/Control/MarkerClippingMode.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Commands.Enums; 2 | using CgmInfo.Traversal; 3 | 4 | namespace CgmInfo.Commands.MetafileDescriptor 5 | { 6 | [TextToken("MARKERCLIPMODE")] 7 | public class MarkerClippingMode : Command 8 | { 9 | public MarkerClippingMode(ClippingMode mode) 10 | : base(3, 8) 11 | { 12 | Mode = mode; 13 | } 14 | 15 | public ClippingMode Mode { get; } 16 | 17 | public override void Accept(ICommandVisitor visitor, T parameter) 18 | { 19 | visitor.AcceptControlMarkerClippingMode(this, parameter); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Commands/PictureDescriptor/BackgroundColor.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | using CgmInfo.Utilities; 3 | 4 | namespace CgmInfo.Commands.PictureDescriptor 5 | { 6 | [TextToken("BACKCOLR")] 7 | public class BackgroundColor : Command 8 | { 9 | public BackgroundColor(MetafileColor color) 10 | : base(2, 7) 11 | { 12 | Color = color; 13 | } 14 | 15 | public MetafileColor Color { get; } 16 | 17 | public override void Accept(ICommandVisitor visitor, T parameter) 18 | { 19 | visitor.AcceptPictureDescriptorBackgroundColor(this, parameter); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Writers/EscapeWriter.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Commands; 2 | using CgmInfo.Commands.Escape; 3 | 4 | namespace CgmInfo.Writers 5 | { 6 | // [ISO/IEC 8632-3 8.8] 7 | internal static class EscapeWriter 8 | { 9 | public static void Escape(MetafileWriter writer, Command command) 10 | { 11 | var escape = (EscapeCommand)command; 12 | // P1: (integer) escape identifier 13 | writer.WriteInteger(escape.Identifier); 14 | // P2: (data record) escape data record; data records are bound as strings in this encoding. 15 | writer.WriteStructuredDataRecord(escape.DataRecord); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Commands/Control/GeneralizedTextPathMode.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Commands.Enums; 2 | using CgmInfo.Traversal; 3 | 4 | namespace CgmInfo.Commands.MetafileDescriptor 5 | { 6 | [TextToken("GENTEXTPATHMODE")] 7 | public class GeneralizedTextPathMode : Command 8 | { 9 | public GeneralizedTextPathMode(TextPathMode mode) 10 | : base(3, 18) 11 | { 12 | Mode = mode; 13 | } 14 | 15 | public TextPathMode Mode { get; } 16 | 17 | public override void Accept(ICommandVisitor visitor, T parameter) 18 | { 19 | visitor.AcceptControlGeneralizedTextPathMode(this, parameter); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Commands/GraphicalPrimitives/DisjointPolyline.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | using CgmInfo.Utilities; 3 | 4 | namespace CgmInfo.Commands.GraphicalPrimitives 5 | { 6 | [TextToken("DISJTLINE")] 7 | public class DisjointPolyline : Command 8 | { 9 | public DisjointPolyline(MetafilePoint[] points) 10 | : base(4, 2) 11 | { 12 | Points = points; 13 | } 14 | 15 | public MetafilePoint[] Points { get; } 16 | 17 | public override void Accept(ICommandVisitor visitor, T parameter) 18 | { 19 | visitor.AcceptGraphicalPrimitiveDisjointPolyline(this, parameter); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Commands/MetafileDescriptor/VdcType.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Commands.Enums; 2 | using CgmInfo.Traversal; 3 | 4 | namespace CgmInfo.Commands.MetafileDescriptor 5 | { 6 | [TextToken("VDCTYPE")] 7 | public class VdcType : Command 8 | { 9 | public VdcType(VdcTypeSpecification specification) 10 | : base(1, 3) 11 | { 12 | Specification = specification; 13 | } 14 | 15 | public VdcTypeSpecification Specification { get; } 16 | 17 | public override void Accept(ICommandVisitor visitor, T parameter) 18 | { 19 | visitor.AcceptMetafileDescriptorVdcType(this, parameter); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /MetafileProperties.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace CgmInfo 4 | { 5 | public class MetafileProperties 6 | { 7 | public MetafileProperties(bool isBinaryEncoding, long fileSize) 8 | { 9 | IsBinaryEncoding = isBinaryEncoding; 10 | FileSize = fileSize; 11 | } 12 | 13 | public bool IsBinaryEncoding { get; } 14 | public long FileSize { get; } 15 | public string Name { get; internal set; } = null!; 16 | public int Version { get; internal set; } 17 | public string? Profile { get; internal set; } 18 | public List EncodingChanges { get; } = []; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Commands/Segment/ClipInheritance.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Commands.Enums; 2 | using CgmInfo.Traversal; 3 | 4 | namespace CgmInfo.Commands.Segment 5 | { 6 | [TextToken("CLIPINH")] 7 | public class ClipInheritance : Command 8 | { 9 | public ClipInheritance(ClipInheritanceType inheritanceType) 10 | : base(8, 3) 11 | { 12 | InheritanceType = inheritanceType; 13 | } 14 | 15 | public ClipInheritanceType InheritanceType { get; } 16 | 17 | public override void Accept(ICommandVisitor visitor, T parameter) 18 | { 19 | visitor.AcceptSegmentClipInheritance(this, parameter); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /BinaryEncoding/ApplicationStructureDescriptorReader.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Commands.ApplicationStructureDescriptor; 2 | 3 | namespace CgmInfo.BinaryEncoding 4 | { 5 | // [ISO/IEC 8632-3 8.11] 6 | internal static class ApplicationStructureDescriptorReader 7 | { 8 | public static ApplicationStructureAttribute ApplicationStructureAttribute(MetafileReader reader, CommandHeader commandHeader) 9 | { 10 | // P1: (string fixed) application structure attribute type 11 | // P2: (structured data record) data record 12 | return new ApplicationStructureAttribute(reader.ReadString(), reader.ReadStructuredDataRecord()); 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Commands/Attributes/FillReferencePoint.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | using CgmInfo.Utilities; 3 | 4 | namespace CgmInfo.Commands.Attributes 5 | { 6 | [TextToken("FILLREFPT")] 7 | public class FillReferencePoint : Command 8 | { 9 | public FillReferencePoint(MetafilePoint referencePoint) 10 | : base(5, 31) 11 | { 12 | ReferencePoint = referencePoint; 13 | } 14 | 15 | public MetafilePoint ReferencePoint { get; } 16 | 17 | public override void Accept(ICommandVisitor visitor, T parameter) 18 | { 19 | visitor.AcceptAttributeFillReferencePoint(this, parameter); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Commands/Attributes/CharacterSpacing.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | 3 | namespace CgmInfo.Commands.Attributes 4 | { 5 | [TextToken("CHARSPACE")] 6 | public class CharacterSpacing : Command 7 | { 8 | public CharacterSpacing(double additionalIntercharacterSpace) 9 | : base(5, 13) 10 | { 11 | AdditionalIntercharacterSpace = additionalIntercharacterSpace; 12 | } 13 | 14 | public double AdditionalIntercharacterSpace { get; } 15 | 16 | public override void Accept(ICommandVisitor visitor, T parameter) 17 | { 18 | visitor.AcceptAttributeCharacterSpacing(this, parameter); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Commands/PictureDescriptor/ColorSelectionMode.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Commands.Enums; 2 | using CgmInfo.Traversal; 3 | 4 | namespace CgmInfo.Commands.PictureDescriptor 5 | { 6 | [TextToken("COLRMODE")] 7 | public class ColorSelectionMode : Command 8 | { 9 | public ColorSelectionMode(ColorModeType colorMode) 10 | : base(2, 2) 11 | { 12 | ColorMode = colorMode; 13 | } 14 | 15 | public ColorModeType ColorMode { get; } 16 | 17 | public override void Accept(ICommandVisitor visitor, T parameter) 18 | { 19 | visitor.AcceptPictureDescriptorColorSelectionMode(this, parameter); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /CgmInfoGui/ViewModels/Nodes/InvalidCommandNode.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Commands; 2 | 3 | namespace CgmInfoGui.ViewModels.Nodes; 4 | 5 | public class InvalidCommandNode : NodeBase 6 | { 7 | private readonly InvalidCommand _invalidCommand; 8 | 9 | public InvalidCommandNode(InvalidCommand invalidCommand) 10 | { 11 | _invalidCommand = invalidCommand; 12 | 13 | string commandIdentifier = invalidCommand.IsTextEncoding ? invalidCommand.ElementName : $"{invalidCommand.ElementClass}/{invalidCommand.ElementId}"; 14 | DisplayName = $"Error reading {commandIdentifier}: {invalidCommand.Exception.Message}"; 15 | } 16 | 17 | public override string DisplayName { get; } 18 | } 19 | -------------------------------------------------------------------------------- /Commands/MetafileDescriptor/ColorModelCommand.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Commands.Enums; 2 | using CgmInfo.Traversal; 3 | 4 | namespace CgmInfo.Commands.MetafileDescriptor 5 | { 6 | [TextToken("COLRMODEL")] 7 | public class ColorModelCommand : Command 8 | { 9 | public ColorModelCommand(int colorModelValue) 10 | : base(1, 19) 11 | { 12 | ColorModel = (ColorModel)colorModelValue; 13 | } 14 | 15 | public ColorModel ColorModel { get; } 16 | 17 | public override void Accept(ICommandVisitor visitor, T parameter) 18 | { 19 | visitor.AcceptMetafileDescriptorColorModel(this, parameter); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /EncodingExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | 3 | namespace CgmInfo 4 | { 5 | internal static class EncodingExtensions 6 | { 7 | public static bool Supports(this Encoding encoding, string? s) 8 | { 9 | // assume a null encoding is never supported 10 | if (encoding == null) 11 | return false; 12 | // assume every encoding supports an empty string 13 | if (string.IsNullOrEmpty(s)) 14 | return true; 15 | 16 | byte[] originalBytes = encoding.GetBytes(s); 17 | string roundtrip = encoding.GetString(originalBytes); 18 | return s == roundtrip; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Commands/External/ApplicationData.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | 3 | namespace CgmInfo.Commands.External 4 | { 5 | [TextToken("APPLDATA")] 6 | public class ApplicationData : Command 7 | { 8 | public ApplicationData(int identifier, string dataRecord) 9 | : base(7, 2) 10 | { 11 | Identifier = identifier; 12 | DataRecord = dataRecord; 13 | } 14 | 15 | public int Identifier { get; } 16 | public string DataRecord { get; } 17 | 18 | public override void Accept(ICommandVisitor visitor, T parameter) 19 | { 20 | visitor.AcceptExternalApplicationData(this, parameter); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Commands/GraphicalPrimitives/AppendText.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Commands.Enums; 2 | using CgmInfo.Traversal; 3 | 4 | namespace CgmInfo.Commands.GraphicalPrimitives 5 | { 6 | [TextToken("APNDTEXT")] 7 | public class AppendText : Command 8 | { 9 | public AppendText(FinalFlag final, string text) 10 | : base(4, 6) 11 | { 12 | Final = final; 13 | Text = text; 14 | } 15 | public FinalFlag Final { get; } 16 | public string Text { get; } 17 | 18 | public override void Accept(ICommandVisitor visitor, T parameter) 19 | { 20 | visitor.AcceptGraphicalPrimitiveAppendText(this, parameter); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Commands/GraphicalPrimitives/Circle.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | using CgmInfo.Utilities; 3 | 4 | namespace CgmInfo.Commands.GraphicalPrimitives 5 | { 6 | [TextToken("CIRCLE")] 7 | public class Circle : Command 8 | { 9 | public Circle(MetafilePoint center, double radius) 10 | : base(4, 12) 11 | { 12 | Center = center; 13 | Radius = radius; 14 | } 15 | 16 | public MetafilePoint Center { get; } 17 | public double Radius { get; } 18 | 19 | public override void Accept(ICommandVisitor visitor, T parameter) 20 | { 21 | visitor.AcceptGraphicalPrimitiveCircle(this, parameter); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Commands/Attributes/ColorTable.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | using CgmInfo.Utilities; 3 | 4 | namespace CgmInfo.Commands.Attributes 5 | { 6 | [TextToken("COLRTABLE")] 7 | public class ColorTable : Command 8 | { 9 | public ColorTable(int startIndex, MetafileColor[] colors) 10 | : base(5, 34) 11 | { 12 | StartIndex = startIndex; 13 | Colors = colors; 14 | } 15 | 16 | public int StartIndex { get; } 17 | public MetafileColor[] Colors { get; } 18 | 19 | public override void Accept(ICommandVisitor visitor, T parameter) 20 | { 21 | visitor.AcceptAttributeColorTable(this, parameter); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Commands/Attributes/PatternSize.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | using CgmInfo.Utilities; 3 | 4 | namespace CgmInfo.Commands.Attributes 5 | { 6 | [TextToken("PATSIZE")] 7 | public class PatternSize : Command 8 | { 9 | public PatternSize(MetafilePoint width, MetafilePoint height) 10 | : base(5, 33) 11 | { 12 | Width = width; 13 | Height = height; 14 | } 15 | 16 | public MetafilePoint Width { get; } 17 | public MetafilePoint Height { get; } 18 | 19 | public override void Accept(ICommandVisitor visitor, T parameter) 20 | { 21 | visitor.AcceptAttributePatternSize(this, parameter); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /BinaryEncoding/CommandHeader.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Utilities; 2 | 3 | namespace CgmInfo.BinaryEncoding 4 | { 5 | #if DEBUG 6 | [System.Diagnostics.DebuggerDisplay("Class={ElementClass}, Id={ElementId}")] 7 | #endif 8 | public class CommandHeader 9 | { 10 | public CommandHeader(int elementClass, int elementId, int parameterListLength) 11 | { 12 | ElementClass = elementClass; 13 | ElementId = elementId; 14 | ParameterListLength = parameterListLength; 15 | } 16 | public int ElementClass { get; } 17 | public int ElementId { get; } 18 | public int ParameterListLength { get; } 19 | 20 | internal TrackingBuffer? Buffer { get; init; } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Commands/Segment/SegmentPickPriority.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | 3 | namespace CgmInfo.Commands.Segment 4 | { 5 | [TextToken("SEGPICKPRI")] 6 | public class SegmentPickPriority : Command 7 | { 8 | public SegmentPickPriority(int segmentIdentifier, int priority) 9 | : base(8, 7) 10 | { 11 | SegmentIdentifier = segmentIdentifier; 12 | Priority = priority; 13 | } 14 | 15 | public int SegmentIdentifier { get; } 16 | public int Priority { get; } 17 | 18 | public override void Accept(ICommandVisitor visitor, T parameter) 19 | { 20 | visitor.AcceptSegmentSegmentPickPriority(this, parameter); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Commands/Attributes/CharacterOrientation.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | using CgmInfo.Utilities; 3 | 4 | namespace CgmInfo.Commands.Attributes 5 | { 6 | [TextToken("CHARORI")] 7 | public class CharacterOrientation : Command 8 | { 9 | public CharacterOrientation(MetafilePoint up, MetafilePoint @base) 10 | : base(5, 16) 11 | { 12 | Base = @base; 13 | Up = up; 14 | } 15 | 16 | public MetafilePoint Up { get; } 17 | public MetafilePoint Base { get; } 18 | 19 | public override void Accept(ICommandVisitor visitor, T parameter) 20 | { 21 | visitor.AcceptAttributeCharacterOrientation(this, parameter); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Commands/Segment/SegmentDisplayPriority.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | 3 | namespace CgmInfo.Commands.Segment 4 | { 5 | [TextToken("SEGDISPPRI")] 6 | public class SegmentDisplayPriority : Command 7 | { 8 | public SegmentDisplayPriority(int segmentIdentifier, int priority) 9 | : base(8, 6) 10 | { 11 | SegmentIdentifier = segmentIdentifier; 12 | Priority = priority; 13 | } 14 | 15 | public int SegmentIdentifier { get; } 16 | public int Priority { get; } 17 | 18 | public override void Accept(ICommandVisitor visitor, T parameter) 19 | { 20 | visitor.AcceptSegmentSegmentDisplayPriority(this, parameter); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Utilities/MetafileColorRGB.cs: -------------------------------------------------------------------------------- 1 | namespace CgmInfo.Utilities 2 | { 3 | public class MetafileColorRGB : MetafileColor 4 | { 5 | public int Red { get; } 6 | public int Green { get; } 7 | public int Blue { get; } 8 | 9 | public MetafileColorRGB(int red, int green, int blue) 10 | { 11 | Red = red; 12 | Green = green; 13 | Blue = blue; 14 | } 15 | public override ARGB ToARGB() 16 | { 17 | return new ARGB { Alpha = 255, Red = Red, Green = Green, Blue = Blue }; 18 | } 19 | protected override string GetStringValue() 20 | { 21 | return string.Format("R={0} G={1} B={2}", Red, Green, Blue); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /.github/workflows/dotnet.yml: -------------------------------------------------------------------------------- 1 | name: .NET 2 | 3 | on: 4 | push: 5 | branches: ["master"] 6 | pull_request: 7 | branches: ["master"] 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | 13 | steps: 14 | - uses: actions/checkout@v4 15 | - name: Setup .NET 16 | uses: actions/setup-dotnet@v4 17 | with: 18 | dotnet-version: 9.0.x 19 | - uses: actions/cache@v4 20 | with: 21 | path: ~/.nuget/packages 22 | key: ${{ runner.os }}-nuget-${{ hashFiles('**/*.csproj') }} 23 | restore-keys: | 24 | ${{ runner.os }}-nuget 25 | - name: Restore dependencies 26 | run: dotnet restore 27 | - name: Build 28 | run: dotnet build --no-restore 29 | -------------------------------------------------------------------------------- /Commands/External/Message.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Commands.Enums; 2 | using CgmInfo.Traversal; 3 | 4 | namespace CgmInfo.Commands.External 5 | { 6 | [TextToken("MESSAGE")] 7 | public class Message : Command 8 | { 9 | public Message(ActionRequired actionRequired, string messageString) 10 | : base(7, 1) 11 | { 12 | ActionRequired = actionRequired; 13 | MessageString = messageString; 14 | } 15 | 16 | public ActionRequired ActionRequired { get; } 17 | public string MessageString { get; } 18 | 19 | public override void Accept(ICommandVisitor visitor, T parameter) 20 | { 21 | visitor.AcceptExternalMessage(this, parameter); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Commands/StructuredDataRecord.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace CgmInfo.Commands 4 | { 5 | // structured data records are self-defining structures [ISO/IEC 8632-3 7, Table 1, Note 17] 6 | // each record contains a single member and is comprised of [ISO/IEC 8632-3 8.3, 21 FONT PROPERTIES, P3] 7 | // data type indicator 8 | // data element count 9 | // data element(s) 10 | // see also [ISO/IEC 8632-1 Annex C, C.2.2] 11 | public class StructuredDataRecord 12 | { 13 | public StructuredDataRecord(IEnumerable elements) 14 | { 15 | Elements = elements; 16 | } 17 | 18 | public IEnumerable Elements { get; } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /CgmInfoGui/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Avalonia; 3 | 4 | namespace CgmInfoGui; 5 | 6 | internal sealed class Program 7 | { 8 | // Initialization code. Don't use any Avalonia, third-party APIs or any 9 | // SynchronizationContext-reliant code before AppMain is called: things aren't initialized 10 | // yet and stuff might break. 11 | [STAThread] 12 | public static void Main(string[] args) => BuildAvaloniaApp() 13 | .StartWithClassicDesktopLifetime(args); 14 | 15 | // Avalonia configuration, don't remove; also used by visual designer. 16 | public static AppBuilder BuildAvaloniaApp() 17 | => AppBuilder.Configure() 18 | .UsePlatformDetect() 19 | .WithInterFont() 20 | .LogToTrace(); 21 | } 22 | -------------------------------------------------------------------------------- /Commands/Attributes/AspectSourceFlags.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using CgmInfo.Commands.Enums; 3 | using CgmInfo.Traversal; 4 | 5 | namespace CgmInfo.Commands.Attributes 6 | { 7 | [TextToken("ASF")] 8 | public class AspectSourceFlags : Command 9 | { 10 | public AspectSourceFlags(IDictionary values) 11 | : base(5, 35) 12 | { 13 | Values = values; 14 | } 15 | 16 | public IDictionary Values { get; } 17 | 18 | public override void Accept(ICommandVisitor visitor, T parameter) 19 | { 20 | visitor.AcceptAttributeAspectSourceFlags(this, parameter); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Commands/MetafileDescriptor/MetafileDefaultsReplacement.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using CgmInfo.Traversal; 3 | 4 | namespace CgmInfo.Commands.MetafileDescriptor 5 | { 6 | [TextToken("BEGMFDEFAULTS", EndToken = "ENDMFDEFAULTS")] 7 | public class MetafileDefaultsReplacement : Command 8 | { 9 | public MetafileDefaultsReplacement(IEnumerable commands) 10 | : base(1, 12) 11 | { 12 | Commands = commands; 13 | } 14 | 15 | public IEnumerable Commands { get; } 16 | 17 | public override void Accept(ICommandVisitor visitor, T parameter) 18 | { 19 | visitor.AcceptMetafileDescriptorMetafileDefaultsReplacement(this, parameter); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Commands/Control/ClipRectangle.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | using CgmInfo.Utilities; 3 | 4 | namespace CgmInfo.Commands.MetafileDescriptor 5 | { 6 | [TextToken("CLIPRECT")] 7 | public class ClipRectangle : Command 8 | { 9 | public ClipRectangle(MetafilePoint firstCorner, MetafilePoint secondCorner) 10 | : base(3, 5) 11 | { 12 | FirstCorner = firstCorner; 13 | SecondCorner = secondCorner; 14 | } 15 | 16 | public MetafilePoint FirstCorner { get; } 17 | public MetafilePoint SecondCorner { get; } 18 | 19 | public override void Accept(ICommandVisitor visitor, T parameter) 20 | { 21 | visitor.AcceptControlClipRectangle(this, parameter); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Commands/Control/ProtectionRegionIndicator.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Commands.Enums; 2 | using CgmInfo.Traversal; 3 | 4 | namespace CgmInfo.Commands.MetafileDescriptor 5 | { 6 | [TextToken("PROTREGION")] 7 | public class ProtectionRegionIndicator : Command 8 | { 9 | public ProtectionRegionIndicator(int index, RegionIndicator indicator) 10 | : base(3, 17) 11 | { 12 | Indicator = indicator; 13 | Index = index; 14 | } 15 | 16 | public int Index { get; } 17 | public RegionIndicator Indicator { get; } 18 | 19 | public override void Accept(ICommandVisitor visitor, T parameter) 20 | { 21 | visitor.AcceptControlProtectionRegionIndicator(this, parameter); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Commands/GraphicalPrimitives/Rectangle.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | using CgmInfo.Utilities; 3 | 4 | namespace CgmInfo.Commands.GraphicalPrimitives 5 | { 6 | [TextToken("RECT")] 7 | public class Rectangle : Command 8 | { 9 | public Rectangle(MetafilePoint firstCorner, MetafilePoint secondCorner) 10 | : base(4, 11) 11 | { 12 | FirstCorner = firstCorner; 13 | SecondCorner = secondCorner; 14 | } 15 | 16 | public MetafilePoint FirstCorner { get; } 17 | public MetafilePoint SecondCorner { get; } 18 | 19 | public override void Accept(ICommandVisitor visitor, T parameter) 20 | { 21 | visitor.AcceptGraphicalPrimitiveRectangle(this, parameter); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Commands/PictureDescriptor/VdcExtent.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | using CgmInfo.Utilities; 3 | 4 | namespace CgmInfo.Commands.PictureDescriptor 5 | { 6 | [TextToken("VDCEXT")] 7 | public class VdcExtent : Command 8 | { 9 | public VdcExtent(MetafilePoint firstCorner, MetafilePoint secondCorner) 10 | : base(2, 6) 11 | { 12 | FirstCorner = firstCorner; 13 | SecondCorner = secondCorner; 14 | } 15 | 16 | public MetafilePoint FirstCorner { get; } 17 | public MetafilePoint SecondCorner { get; } 18 | 19 | public override void Accept(ICommandVisitor visitor, T parameter) 20 | { 21 | visitor.AcceptPictureDescriptorVdcExtent(this, parameter); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Commands/Segment/SegmentTransformation.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | using CgmInfo.Utilities; 3 | 4 | namespace CgmInfo.Commands.Segment 5 | { 6 | [TextToken("SEGTRAN")] 7 | public class SegmentTransformation : Command 8 | { 9 | public SegmentTransformation(int segmentIdentifier, MetafileMatrix matrix) 10 | : base(8, 4) 11 | { 12 | SegmentIdentifier = segmentIdentifier; 13 | Matrix = matrix; 14 | } 15 | 16 | public int SegmentIdentifier { get; } 17 | public MetafileMatrix Matrix { get; } 18 | 19 | public override void Accept(ICommandVisitor visitor, T parameter) 20 | { 21 | visitor.AcceptSegmentSegmentTransformation(this, parameter); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Commands/GraphicalPrimitives/PolygonSet.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Commands.Enums; 2 | using CgmInfo.Traversal; 3 | using CgmInfo.Utilities; 4 | 5 | namespace CgmInfo.Commands.GraphicalPrimitives 6 | { 7 | [TextToken("POLYGONSET")] 8 | public class PolygonSet : Command 9 | { 10 | public PolygonSet(MetafilePoint[] points, EdgeOutFlags[] flags) 11 | : base(4, 8) 12 | { 13 | Points = points; 14 | Flags = flags; 15 | } 16 | 17 | public MetafilePoint[] Points { get; } 18 | public EdgeOutFlags[] Flags { get; } 19 | 20 | public override void Accept(ICommandVisitor visitor, T parameter) 21 | { 22 | visitor.AcceptGraphicalPrimitivePolygonSet(this, parameter); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Commands/PictureDescriptor/DeviceViewport.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | using CgmInfo.Utilities; 3 | 4 | namespace CgmInfo.Commands.PictureDescriptor 5 | { 6 | [TextToken("DEVVP")] 7 | public class DeviceViewport : Command 8 | { 9 | public DeviceViewport(MetafilePoint firstCorner, MetafilePoint secondCorner) 10 | : base(2, 8) 11 | { 12 | FirstCorner = firstCorner; 13 | SecondCorner = secondCorner; 14 | } 15 | 16 | public MetafilePoint FirstCorner { get; } 17 | public MetafilePoint SecondCorner { get; } 18 | 19 | public override void Accept(ICommandVisitor visitor, T parameter) 20 | { 21 | visitor.AcceptPictureDescriptorDeviceViewport(this, parameter); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Commands/Segment/SegmentHighlighting.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Commands.Enums; 2 | using CgmInfo.Traversal; 3 | 4 | namespace CgmInfo.Commands.Segment 5 | { 6 | [TextToken("SEGHIGHL")] 7 | public class SegmentHighlighting : Command 8 | { 9 | public SegmentHighlighting(int segmentIdentifier, Highlighting highlighting) 10 | : base(8, 5) 11 | { 12 | SegmentIdentifier = segmentIdentifier; 13 | Highlighting = highlighting; 14 | } 15 | 16 | public int SegmentIdentifier { get; } 17 | public Highlighting Highlighting { get; } 18 | 19 | public override void Accept(ICommandVisitor visitor, T parameter) 20 | { 21 | visitor.AcceptSegmentSegmentHighlighting(this, parameter); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Commands/PictureDescriptor/EdgeWidthSpecificationMode.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Commands.Enums; 2 | using CgmInfo.Traversal; 3 | 4 | namespace CgmInfo.Commands.PictureDescriptor 5 | { 6 | [TextToken("EDGEWIDTHMODE")] 7 | public class EdgeWidthSpecificationMode : Command 8 | { 9 | public EdgeWidthSpecificationMode(WidthSpecificationModeType widthSpecificationMode) 10 | : base(2, 5) 11 | { 12 | WidthSpecificationMode = widthSpecificationMode; 13 | } 14 | 15 | public WidthSpecificationModeType WidthSpecificationMode { get; } 16 | 17 | public override void Accept(ICommandVisitor visitor, T parameter) 18 | { 19 | visitor.AcceptPictureDescriptorEdgeWidthSpecificationMode(this, parameter); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Commands/PictureDescriptor/LineWidthSpecificationMode.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Commands.Enums; 2 | using CgmInfo.Traversal; 3 | 4 | namespace CgmInfo.Commands.PictureDescriptor 5 | { 6 | [TextToken("LINEWIDTHMODE")] 7 | public class LineWidthSpecificationMode : Command 8 | { 9 | public LineWidthSpecificationMode(WidthSpecificationModeType widthSpecificationMode) 10 | : base(2, 3) 11 | { 12 | WidthSpecificationMode = widthSpecificationMode; 13 | } 14 | 15 | public WidthSpecificationModeType WidthSpecificationMode { get; } 16 | 17 | public override void Accept(ICommandVisitor visitor, T parameter) 18 | { 19 | visitor.AcceptPictureDescriptorLineWidthSpecificationMode(this, parameter); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Utilities/MetafileColor.cs: -------------------------------------------------------------------------------- 1 | namespace CgmInfo.Utilities 2 | { 3 | public abstract class MetafileColor 4 | { 5 | public abstract ARGB ToARGB(); 6 | protected abstract string GetStringValue(); 7 | 8 | public override string ToString() 9 | { 10 | return GetStringValue(); 11 | } 12 | 13 | public override int GetHashCode() => GetStringValue().GetHashCode(); 14 | public override bool Equals(object obj) 15 | { 16 | if (!(obj is MetafileColor metafileColor)) 17 | return false; 18 | if (metafileColor is MetafileColorIndexed indexedColor) 19 | return indexedColor.Equals(this); 20 | return metafileColor.GetStringValue() == GetStringValue(); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Commands/PictureDescriptor/MarkerSizeSpecificationMode.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Commands.Enums; 2 | using CgmInfo.Traversal; 3 | 4 | namespace CgmInfo.Commands.PictureDescriptor 5 | { 6 | [TextToken("MARKERSIZEMODE")] 7 | public class MarkerSizeSpecificationMode : Command 8 | { 9 | public MarkerSizeSpecificationMode(WidthSpecificationModeType widthSpecificationMode) 10 | : base(2, 4) 11 | { 12 | WidthSpecificationMode = widthSpecificationMode; 13 | } 14 | 15 | public WidthSpecificationModeType WidthSpecificationMode { get; } 16 | 17 | public override void Accept(ICommandVisitor visitor, T parameter) 18 | { 19 | visitor.AcceptPictureDescriptorMarkerSizeSpecificationMode(this, parameter); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Utilities/MetafileMatrix.cs: -------------------------------------------------------------------------------- 1 | namespace CgmInfo.Utilities 2 | { 3 | public sealed class MetafileMatrix 4 | { 5 | public MetafileMatrix(double a11, double a12, double a21, double a22, double a13, double a23) 6 | { 7 | A11 = a11; 8 | A12 = a12; 9 | 10 | A21 = a21; 11 | A22 = a22; 12 | 13 | A13 = a13; 14 | A23 = a23; 15 | 16 | Elements = new[] { A11, A12, A21, A22, A13, A23 }; 17 | } 18 | 19 | public double A11 { get; } 20 | public double A12 { get; } 21 | 22 | public double A21 { get; } 23 | public double A22 { get; } 24 | 25 | public double A13 { get; } 26 | public double A23 { get; } 27 | 28 | public double[] Elements { get; } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Commands/MetafileDescriptor/MaximumVdcExtent.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | using CgmInfo.Utilities; 3 | 4 | namespace CgmInfo.Commands.MetafileDescriptor 5 | { 6 | [TextToken("MAXVDCEXT")] 7 | public class MaximumVdcExtent : Command 8 | { 9 | public MaximumVdcExtent(MetafilePoint firstCorner, MetafilePoint secondCorner) 10 | : base(1, 17) 11 | { 12 | FirstCorner = firstCorner; 13 | SecondCorner = secondCorner; 14 | } 15 | 16 | public MetafilePoint FirstCorner { get; } 17 | public MetafilePoint SecondCorner { get; } 18 | 19 | public override void Accept(ICommandVisitor visitor, T parameter) 20 | { 21 | visitor.AcceptMetafileDescriptorMaximumVdcExtent(this, parameter); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Commands/MetafileDescriptor/SegmentPriorityExtent.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | 3 | namespace CgmInfo.Commands.MetafileDescriptor 4 | { 5 | [TextToken("SEGPRIEXT")] 6 | public class SegmentPriorityExtent : Command 7 | { 8 | public SegmentPriorityExtent(int minPriorityValue, int maxPriorityValue) 9 | : base(1, 18) 10 | { 11 | MinimumPriorityValue = minPriorityValue; 12 | MaximumPriorityValue = maxPriorityValue; 13 | } 14 | 15 | public int MinimumPriorityValue { get; } 16 | public int MaximumPriorityValue { get; } 17 | 18 | public override void Accept(ICommandVisitor visitor, T parameter) 19 | { 20 | visitor.AcceptMetafileDescriptorSegmentPriorityExtent(this, parameter); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Commands/PictureDescriptor/InteriorStyleSpecificationMode.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Commands.Enums; 2 | using CgmInfo.Traversal; 3 | 4 | namespace CgmInfo.Commands.PictureDescriptor 5 | { 6 | [TextToken("INTSTYLEMODE")] 7 | public class InteriorStyleSpecificationMode : Command 8 | { 9 | public InteriorStyleSpecificationMode(WidthSpecificationModeType widthSpecificationMode) 10 | : base(2, 16) 11 | { 12 | WidthSpecificationMode = widthSpecificationMode; 13 | } 14 | 15 | public WidthSpecificationModeType WidthSpecificationMode { get; } 16 | 17 | public override void Accept(ICommandVisitor visitor, T parameter) 18 | { 19 | visitor.AcceptPictureDescriptorInteriorStyleSpecificationMode(this, parameter); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Writers/ApplicationStructureDescriptorWriter.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Commands; 2 | using CgmInfo.Commands.ApplicationStructureDescriptor; 3 | 4 | namespace CgmInfo.Writers 5 | { 6 | // [ISO/IEC 8632-3 8.11] 7 | internal static class ApplicationStructureDescriptorWriter 8 | { 9 | public static void ApplicationStructureAttribute(MetafileWriter writer, Command command) 10 | { 11 | var applicationStructureAttribute = (ApplicationStructureAttribute)command; 12 | // P1: (string fixed) application structure attribute type 13 | writer.WriteString(applicationStructureAttribute.AttributeType); 14 | // P2: (structured data record) data record 15 | writer.WriteStructuredDataRecord(applicationStructureAttribute.DataRecord); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Commands/MetafileDescriptor/CharacterCodingAnnouncer.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Commands.Enums; 2 | using CgmInfo.Traversal; 3 | 4 | namespace CgmInfo.Commands.MetafileDescriptor 5 | { 6 | [TextToken("CHARCODING")] 7 | public class CharacterCodingAnnouncer : Command 8 | { 9 | public CharacterCodingAnnouncer(CharacterCodingAnnouncerType characterCodingAnnouncerType) 10 | : base(1, 15) 11 | { 12 | CharacterCodingAnnouncerType = characterCodingAnnouncerType; 13 | } 14 | 15 | public CharacterCodingAnnouncerType CharacterCodingAnnouncerType { get; } 16 | 17 | public override void Accept(ICommandVisitor visitor, T parameter) 18 | { 19 | visitor.AcceptMetafileDescriptorCharacterCodingAnnouncer(this, parameter); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Commands/PictureDescriptor/ScalingMode.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Commands.Enums; 2 | using CgmInfo.Traversal; 3 | 4 | namespace CgmInfo.Commands.PictureDescriptor 5 | { 6 | [TextToken("SCALEMODE")] 7 | public class ScalingMode : Command 8 | { 9 | public ScalingMode(ScalingModeType scalingMode, double metricScalingFactor) 10 | : base(2, 1) 11 | { 12 | ScalingModeType = scalingMode; 13 | MetricScalingFactor = metricScalingFactor; 14 | } 15 | 16 | public ScalingModeType ScalingModeType { get; } 17 | public double MetricScalingFactor { get; } 18 | 19 | public override void Accept(ICommandVisitor visitor, T parameter) 20 | { 21 | visitor.AcceptPictureDescriptorScalingMode(this, parameter); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /CgmInfoGui/ViewModels/Nodes/UnsupportedNode.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Commands; 2 | 3 | namespace CgmInfoGui.ViewModels.Nodes; 4 | 5 | public class UnsupportedNode : NodeBase 6 | { 7 | private readonly UnsupportedCommand _unsupportedCommand; 8 | public UnsupportedNode(UnsupportedCommand unsupportedCommand) 9 | { 10 | _unsupportedCommand = unsupportedCommand; 11 | } 12 | public override string DisplayName 13 | { 14 | get 15 | { 16 | if (_unsupportedCommand.IsTextEncoding) 17 | return string.Format("{0} (Parameters: '{1}')", _unsupportedCommand.ElementName, _unsupportedCommand.RawParameters); 18 | else 19 | return string.Format("Element Class={0}, Id={1}", _unsupportedCommand.ElementClass, _unsupportedCommand.ElementId); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Commands/GraphicalPrimitives/TextCommand.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Commands.Enums; 2 | using CgmInfo.Traversal; 3 | using CgmInfo.Utilities; 4 | 5 | namespace CgmInfo.Commands.GraphicalPrimitives 6 | { 7 | [TextToken("TEXT")] 8 | public class TextCommand : Command 9 | { 10 | public TextCommand(MetafilePoint position, FinalFlag final, string text) 11 | : base(4, 4) 12 | { 13 | Position = position; 14 | Final = final; 15 | Text = text; 16 | } 17 | public MetafilePoint Position { get; } 18 | public FinalFlag Final { get; } 19 | public string Text { get; } 20 | 21 | public override void Accept(ICommandVisitor visitor, T parameter) 22 | { 23 | visitor.AcceptGraphicalPrimitiveText(this, parameter); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /CgmInfoGui/ViewLocator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Avalonia.Controls; 3 | using Avalonia.Controls.Templates; 4 | using CgmInfoGui.ViewModels; 5 | using Dock.Model.Core; 6 | 7 | namespace CgmInfoGui; 8 | 9 | public class ViewLocator : IDataTemplate 10 | { 11 | public Control? Build(object? param) 12 | { 13 | if (param is null) 14 | return null; 15 | 16 | var name = param.GetType().FullName!.Replace("ViewModel", "View", StringComparison.Ordinal); 17 | var type = Type.GetType(name); 18 | 19 | if (type != null) 20 | { 21 | return (Control)Activator.CreateInstance(type)!; 22 | } 23 | 24 | return new TextBlock { Text = "Not Found: " + name }; 25 | } 26 | 27 | public bool Match(object? data) 28 | { 29 | return data is ViewModelBase or IDockable; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Commands/ApplicationStructureDescriptor/ApplicationStructureAttribute.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | 3 | namespace CgmInfo.Commands.ApplicationStructureDescriptor 4 | { 5 | [TextToken("APSATTR")] 6 | public class ApplicationStructureAttribute : Command 7 | { 8 | public ApplicationStructureAttribute(string attributeType, StructuredDataRecord dataRecord) 9 | : base(9, 1) 10 | { 11 | AttributeType = attributeType; 12 | DataRecord = dataRecord; 13 | 14 | } 15 | 16 | public string AttributeType { get; } 17 | public StructuredDataRecord DataRecord { get; } 18 | 19 | public override void Accept(ICommandVisitor visitor, T parameter) 20 | { 21 | visitor.AcceptApplicationStructureDescriptorAttribute(this, parameter); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Commands/Attributes/PatternTable.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | using CgmInfo.Utilities; 3 | 4 | namespace CgmInfo.Commands.Attributes 5 | { 6 | [TextToken("PATTABLE")] 7 | public class PatternTable : Command 8 | { 9 | public PatternTable(int index, int width, int height, MetafileColor[] colors) 10 | : base(5, 32) 11 | { 12 | Index = index; 13 | Width = width; 14 | Height = height; 15 | Colors = colors; 16 | } 17 | 18 | public int Index { get; } 19 | public int Width { get; } 20 | public int Height { get; } 21 | public MetafileColor[] Colors { get; } 22 | 23 | public override void Accept(ICommandVisitor visitor, T parameter) 24 | { 25 | visitor.AcceptAttributePatternTable(this, parameter); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /CgmInfoGui/ViewModels/Nodes/NodeBase.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using CgmInfo.Commands; 4 | using CommunityToolkit.Mvvm.ComponentModel; 5 | 6 | namespace CgmInfoGui.ViewModels.Nodes; 7 | 8 | public abstract class NodeBase : ObservableObject, IEnumerable 9 | { 10 | public abstract string DisplayName { get; } 11 | public List Nodes { get; } = []; 12 | public Command? Command { get; set; } 13 | 14 | private bool _isExpanded; 15 | public bool IsExpanded 16 | { 17 | get { return _isExpanded; } 18 | set { SetProperty(ref _isExpanded, value); } 19 | } 20 | 21 | public virtual void Add(NodeBase node) => Nodes.Add(node); 22 | 23 | public IEnumerator GetEnumerator() => Nodes.GetEnumerator(); 24 | IEnumerator IEnumerable.GetEnumerator() => Nodes.GetEnumerator(); 25 | } 26 | -------------------------------------------------------------------------------- /Commands/Command.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using CgmInfo.Traversal; 3 | using CgmInfo.Utilities; 4 | 5 | namespace CgmInfo.Commands 6 | { 7 | #if DEBUG 8 | [System.Diagnostics.DebuggerDisplay("{ElementClass}/{ElementId}")] 9 | #endif 10 | public abstract class Command 11 | { 12 | protected Command(int elementClass, int elementId) 13 | { 14 | ElementClass = elementClass; 15 | ElementId = elementId; 16 | } 17 | 18 | public int ElementId { get; } 19 | public int ElementClass { get; } 20 | 21 | /// The internal buffer data representing this command (as read from the input). 22 | [Browsable(false)] 23 | public TrackingBuffer? Buffer { get; internal set; } 24 | 25 | public abstract void Accept(ICommandVisitor visitor, T parameter); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Commands/GraphicalPrimitives/CircularArc3Point.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | using CgmInfo.Utilities; 3 | 4 | namespace CgmInfo.Commands.GraphicalPrimitives 5 | { 6 | [TextToken("ARC3PT")] 7 | public class CircularArc3Point : Command 8 | { 9 | public CircularArc3Point(MetafilePoint start, MetafilePoint intermediate, MetafilePoint end) 10 | : base(4, 13) 11 | { 12 | Start = start; 13 | Intermediate = intermediate; 14 | End = end; 15 | } 16 | 17 | public MetafilePoint Intermediate { get; } 18 | public MetafilePoint Start { get; } 19 | public MetafilePoint End { get; } 20 | 21 | public override void Accept(ICommandVisitor visitor, T parameter) 22 | { 23 | visitor.AcceptGraphicalPrimitiveCircularArc3Point(this, parameter); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /CgmInfoGui/Converters/HexConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Text; 4 | using Avalonia.Data.Converters; 5 | using AvaloniaHex.Document; 6 | using CgmInfo.Commands; 7 | 8 | namespace CgmInfoGui.Converters; 9 | 10 | public sealed class HexConverter : IValueConverter 11 | { 12 | public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) 13 | { 14 | if (value is not UnsupportedCommand cmd) 15 | return null; 16 | 17 | if (cmd.IsTextEncoding) 18 | return new MemoryBinaryDocument(Encoding.UTF8.GetBytes(cmd.RawParameters), isReadOnly: true); 19 | 20 | return new MemoryBinaryDocument(cmd.RawBuffer, isReadOnly: true); 21 | } 22 | public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) => throw new NotImplementedException(); 23 | } 24 | -------------------------------------------------------------------------------- /Commands/Delimiter/BeginApplicationStructure.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Commands.Enums; 2 | using CgmInfo.Traversal; 3 | 4 | namespace CgmInfo.Commands.Delimiter 5 | { 6 | [TextToken("BEGAPS")] 7 | public class BeginApplicationStructure : Command 8 | { 9 | public BeginApplicationStructure(string identifier, string type, InheritanceFlag inheritanceFlag) 10 | : base(0, 21) 11 | { 12 | Identifier = identifier; 13 | Type = type; 14 | Inheritance = inheritanceFlag; 15 | } 16 | 17 | public string Identifier { get; } 18 | public string Type { get; } 19 | public InheritanceFlag Inheritance { get; } 20 | 21 | public override void Accept(ICommandVisitor visitor, T parameter) 22 | { 23 | visitor.AcceptDelimiterBeginApplicationStructure(this, parameter); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Commands/Enums/DataTypeIndex.cs: -------------------------------------------------------------------------------- 1 | namespace CgmInfo.Commands.Enums 2 | { 3 | public enum DataTypeIndex 4 | { 5 | // Values [ISO/IEC 8632-1 Annex C, C.2.2] 6 | // Descriptions [ISO/IEC 8632-1 7.1, Table 10] 7 | StructuredDataRecord = 1, 8 | ColorIndex = 2, 9 | ColorDirect = 3, 10 | Name = 4, 11 | Enumerated = 5, 12 | Integer = 6, 13 | Reserved = 7, 14 | SignedInteger8bit = 8, 15 | SignedInteger16bit = 9, 16 | SignedInteger32bit = 10, 17 | Index = 11, 18 | Real = 12, 19 | String = 13, 20 | StringFixed = 14, 21 | ViewportCoordinate = 15, 22 | VDC = 16, 23 | ColorComponent = 17, 24 | UnsignedInteger8bit = 18, 25 | UnsignedInteger32bit = 19, 26 | BitStream = 20, 27 | ColorList = 21, 28 | UnsignedInteger16bit = 22, 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Commands/GraphicalPrimitives/ParabolicArc.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | using CgmInfo.Utilities; 3 | 4 | namespace CgmInfo.Commands.GraphicalPrimitives 5 | { 6 | [TextToken("PARABARC")] 7 | public class ParabolicArc : Command 8 | { 9 | public ParabolicArc(MetafilePoint tangentIntersectionPoint, MetafilePoint start, MetafilePoint end) 10 | : base(4, 23) 11 | { 12 | TangentIntersectionPoint = tangentIntersectionPoint; 13 | Start = start; 14 | End = end; 15 | } 16 | 17 | public MetafilePoint TangentIntersectionPoint { get; } 18 | public MetafilePoint Start { get; } 19 | public MetafilePoint End { get; } 20 | 21 | public override void Accept(ICommandVisitor visitor, T parameter) 22 | { 23 | visitor.AcceptGraphicalPrimitiveParabolicArc(this, parameter); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Commands/PictureDescriptor/LineAndEdgeTypeDefinition.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | 3 | namespace CgmInfo.Commands.PictureDescriptor 4 | { 5 | [TextToken("LINEEDGETYPEDEF")] 6 | public class LineAndEdgeTypeDefinition : Command 7 | { 8 | public LineAndEdgeTypeDefinition(int lineType, double dashCycleRepeatLength, int[] dashElements) 9 | : base(2, 17) 10 | { 11 | LineType = lineType; 12 | DashCycleRepeatLength = dashCycleRepeatLength; 13 | DashElements = dashElements; 14 | } 15 | 16 | public int LineType { get; } 17 | public double DashCycleRepeatLength { get; } 18 | public int[] DashElements { get; } 19 | 20 | public override void Accept(ICommandVisitor visitor, T parameter) 21 | { 22 | visitor.AcceptPictureDescriptorLineAndEdgeTypeDefinition(this, parameter); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /TextEncoding/ExternalReader.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Commands.Enums; 2 | using CgmInfo.Commands.External; 3 | 4 | namespace CgmInfo.TextEncoding 5 | { 6 | internal static class ExternalReader 7 | { 8 | public static Message Message(MetafileReader reader) 9 | { 10 | return new Message(ParseActionRequired(reader.ReadEnum()), reader.ReadString()); 11 | } 12 | public static ApplicationData ApplicationData(MetafileReader reader) 13 | { 14 | return new ApplicationData(reader.ReadInteger(), reader.ReadString()); 15 | } 16 | 17 | private static ActionRequired ParseActionRequired(string token) 18 | { 19 | // assume "no action" unless action is required 20 | if (token.ToUpperInvariant() == "ACTION") 21 | return ActionRequired.Action; 22 | return ActionRequired.NoAction; 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /CgmInfoGui/Views/HotspotsView.axaml: -------------------------------------------------------------------------------- 1 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /CgmInfoCmd/CgmInfoCmd.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | net9.0 4 | CgmInfoCmd 5 | CgmInfoCmd 6 | CGM Metafile Info command line tool for testing 7 | 8 | Exe 9 | CgmInfoCmd.Program 10 | 11 | 12 | 13 | 14 | 15 | bin\Debug\ 16 | 17 | 18 | bin\Release\ 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /Commands/PictureDescriptor/DeviceViewportSpecificationMode.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Commands.Enums; 2 | using CgmInfo.Traversal; 3 | 4 | namespace CgmInfo.Commands.PictureDescriptor 5 | { 6 | [TextToken("DEVVPMODE")] 7 | public class DeviceViewportSpecificationMode : Command 8 | { 9 | public DeviceViewportSpecificationMode(DeviceViewportSpecificationModeType deviceViewportSpecificationMode, double scaleFactor) 10 | : base(2, 9) 11 | { 12 | SpecificationMode = deviceViewportSpecificationMode; 13 | ScaleFactor = scaleFactor; 14 | } 15 | 16 | public DeviceViewportSpecificationModeType SpecificationMode { get; } 17 | public double ScaleFactor { get; } 18 | 19 | public override void Accept(ICommandVisitor visitor, T parameter) 20 | { 21 | visitor.AcceptPictureDescriptorDeviceViewportSpecificationMode(this, parameter); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Commands/GraphicalPrimitives/CircularArcCenter.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | using CgmInfo.Utilities; 3 | 4 | namespace CgmInfo.Commands.GraphicalPrimitives 5 | { 6 | [TextToken("ARCCTR")] 7 | public class CircularArcCenter : Command 8 | { 9 | public CircularArcCenter(MetafilePoint center, MetafilePoint start, MetafilePoint end, double radius) 10 | : base(4, 15) 11 | { 12 | Center = center; 13 | Start = start; 14 | End = end; 15 | Radius = radius; 16 | } 17 | 18 | public MetafilePoint Center { get; } 19 | public MetafilePoint Start { get; } 20 | public MetafilePoint End { get; } 21 | public double Radius { get; } 22 | 23 | public override void Accept(ICommandVisitor visitor, T parameter) 24 | { 25 | visitor.AcceptGraphicalPrimitiveCircularArcCenter(this, parameter); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Commands/GraphicalPrimitives/Ellipse.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | using CgmInfo.Utilities; 3 | 4 | namespace CgmInfo.Commands.GraphicalPrimitives 5 | { 6 | [TextToken("ELLIPSE")] 7 | public class Ellipse : Command 8 | { 9 | public Ellipse(MetafilePoint center, MetafilePoint firstConjugateDiameter, MetafilePoint secondConjugateDiameter) 10 | : base(4, 17) 11 | { 12 | Center = center; 13 | FirstConjugateDiameter = firstConjugateDiameter; 14 | SecondConjugateDiameter = secondConjugateDiameter; 15 | } 16 | 17 | public MetafilePoint Center { get; } 18 | public MetafilePoint FirstConjugateDiameter { get; } 19 | public MetafilePoint SecondConjugateDiameter { get; } 20 | 21 | public override void Accept(ICommandVisitor visitor, T parameter) 22 | { 23 | visitor.AcceptGraphicalPrimitiveEllipse(this, parameter); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /CgmInfoGui/app.manifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | 10 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /Commands/GraphicalPrimitives/CircularArcCenterReversed.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | using CgmInfo.Utilities; 3 | 4 | namespace CgmInfo.Commands.GraphicalPrimitives 5 | { 6 | [TextToken("ARCCTRREV")] 7 | public class CircularArcCenterReversed : Command 8 | { 9 | public CircularArcCenterReversed(MetafilePoint center, MetafilePoint start, MetafilePoint end, double radius) 10 | : base(4, 20) 11 | { 12 | Center = center; 13 | Start = start; 14 | End = end; 15 | Radius = radius; 16 | } 17 | 18 | public MetafilePoint Center { get; } 19 | public MetafilePoint Start { get; } 20 | public MetafilePoint End { get; } 21 | public double Radius { get; } 22 | 23 | public override void Accept(ICommandVisitor visitor, T parameter) 24 | { 25 | visitor.AcceptGraphicalPrimitiveCircularArcCenterReversed(this, parameter); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Commands/Segment/CopySegment.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Commands.Enums; 2 | using CgmInfo.Traversal; 3 | using CgmInfo.Utilities; 4 | 5 | namespace CgmInfo.Commands.Segment 6 | { 7 | [TextToken("COPYSEG")] 8 | public class CopySegment : Command 9 | { 10 | public CopySegment(int segmentIdentifier, MetafileMatrix matrix, SegmentTransformationApplication transformationApplication) 11 | : base(8, 1) 12 | { 13 | SegmentIdentifier = segmentIdentifier; 14 | Matrix = matrix; 15 | TransformationApplication = transformationApplication; 16 | } 17 | 18 | public int SegmentIdentifier { get; } 19 | public MetafileMatrix Matrix { get; } 20 | public SegmentTransformationApplication TransformationApplication { get; } 21 | 22 | public override void Accept(ICommandVisitor visitor, T parameter) 23 | { 24 | visitor.AcceptSegmentCopySegment(this, parameter); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file 5 | 6 | version: 2 7 | updates: 8 | - package-ecosystem: "nuget" # See documentation for possible values 9 | directory: "/" # Location of package manifests 10 | schedule: 11 | interval: "weekly" 12 | groups: 13 | Avalonia: 14 | patterns: 15 | - "*Avalonia*" 16 | - "Dock.Model.Mvvm" 17 | SixLabors: 18 | patterns: 19 | - "SixLabors*" 20 | ignore: 21 | - dependency-name: "Avalonia.Controls.TreeDataGrid" 22 | # Versions starting at 11.2.0 are commercial for a lack of open source contributors/maintainers. 23 | versions: [ ">=11.2.0" ] 24 | 25 | -------------------------------------------------------------------------------- /CgmInfoGui/Converters/FileSizeConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using Avalonia.Data.Converters; 4 | 5 | namespace CgmInfoGui.Converters; 6 | 7 | public sealed class FileSizeConverter : IValueConverter 8 | { 9 | private static readonly string[] Suffixes = ["B", "KB", "MB", "GB", "TB"]; 10 | public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) 11 | { 12 | if (value is not long lValue) 13 | return value; 14 | 15 | double fileSize = lValue; 16 | int suffixIndex = 0; 17 | while (fileSize > 1024 && suffixIndex < Suffixes.Length) 18 | { 19 | fileSize /= 1024; 20 | suffixIndex++; 21 | } 22 | return string.Format("{0:0.##} {1}", fileSize, Suffixes[suffixIndex]); 23 | } 24 | 25 | public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) 26 | { 27 | throw new NotImplementedException(); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /CgmInfoGui/Traversal/XCFDocumentBuilderVisitor.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Commands.ApplicationStructureDescriptor; 2 | using CgmInfo.Commands.Delimiter; 3 | using CgmInfo.Traversal; 4 | 5 | namespace CgmInfoGui.Traversal; 6 | 7 | public class XCFDocumentBuilderVisitor : CommandVisitor 8 | { 9 | public override void AcceptApplicationStructureDescriptorAttribute(ApplicationStructureAttribute applicationStructureAttribute, XCFDocumentContext parameter) 10 | { 11 | parameter.AddAPSAttribute(applicationStructureAttribute); 12 | } 13 | 14 | public override void AcceptDelimiterBeginApplicationStructure(BeginApplicationStructure beginApplicationStructure, XCFDocumentContext parameter) 15 | { 16 | parameter.AddAPSElement(beginApplicationStructure); 17 | } 18 | 19 | public override void AcceptDelimiterBeginApplicationStructureBody(BeginApplicationStructureBody beginApplicationStructureBody, XCFDocumentContext parameter) 20 | { 21 | parameter.RemoveEmptyAPSElement(); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /BinaryEncoding/ExternalReader.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Commands.Enums; 2 | using CgmInfo.Commands.External; 3 | 4 | namespace CgmInfo.BinaryEncoding 5 | { 6 | // [ISO/IEC 8632-3 8.9] 7 | internal static class ExternalReader 8 | { 9 | public static Message Message(MetafileReader reader, CommandHeader commandHeader) 10 | { 11 | // P1: (enumerated) action-required flag: valid values are 12 | // 0 noaction 13 | // 1 action 14 | // P2: (string fixed) message string 15 | return new Message(reader.ReadEnum(), reader.ReadString()); 16 | } 17 | 18 | public static ApplicationData ApplicationData(MetafileReader reader, CommandHeader commandHeader) 19 | { 20 | // P1: (integer) identifier 21 | // P2: (data record) application data record; data records are bound as strings in this encoding. 22 | return new ApplicationData(reader.ReadInteger(), reader.ReadString()); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Commands/GraphicalPrimitives/CircularArc3PointClose.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Commands.Enums; 2 | using CgmInfo.Traversal; 3 | using CgmInfo.Utilities; 4 | 5 | namespace CgmInfo.Commands.GraphicalPrimitives 6 | { 7 | [TextToken("ARC3PTCLOSE")] 8 | public class CircularArc3PointClose : Command 9 | { 10 | public CircularArc3PointClose(MetafilePoint start, MetafilePoint intermediate, MetafilePoint end, ArcClosureType closure) 11 | : base(4, 14) 12 | { 13 | Start = start; 14 | Intermediate = intermediate; 15 | End = end; 16 | Closure = closure; 17 | } 18 | 19 | public MetafilePoint Intermediate { get; } 20 | public MetafilePoint Start { get; } 21 | public MetafilePoint End { get; } 22 | public ArcClosureType Closure { get; } 23 | 24 | public override void Accept(ICommandVisitor visitor, T parameter) 25 | { 26 | visitor.AcceptGraphicalPrimitiveCircularArc3PointClose(this, parameter); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Commands/GraphicalPrimitives/NonUniformBSpline.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | using CgmInfo.Utilities; 3 | 4 | namespace CgmInfo.Commands.GraphicalPrimitives 5 | { 6 | [TextToken("NUB")] 7 | public class NonUniformBSpline : Command 8 | { 9 | public NonUniformBSpline(int splineOrder, MetafilePoint[] controlPoints, double[] knots, double start, double end) 10 | : base(4, 24) 11 | { 12 | SplineOrder = splineOrder; 13 | ControlPoints = controlPoints; 14 | Knots = knots; 15 | Start = start; 16 | End = end; 17 | } 18 | 19 | public int SplineOrder { get; } 20 | public MetafilePoint[] ControlPoints { get; } 21 | public double[] Knots { get; } 22 | public double Start { get; } 23 | public double End { get; } 24 | 25 | public override void Accept(ICommandVisitor visitor, T parameter) 26 | { 27 | visitor.AcceptGraphicalPrimitiveNonUniformBSpline(this, parameter); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Commands/GraphicalPrimitives/RestrictedText.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Commands.Enums; 2 | using CgmInfo.Traversal; 3 | using CgmInfo.Utilities; 4 | 5 | namespace CgmInfo.Commands.GraphicalPrimitives 6 | { 7 | [TextToken("RESTRTEXT")] 8 | public class RestrictedText : Command 9 | { 10 | public RestrictedText(double deltaWidth, double deltaHeight, MetafilePoint position, FinalFlag final, string text) 11 | : base(4, 5) 12 | { 13 | DeltaWidth = deltaWidth; 14 | DeltaHeight = deltaHeight; 15 | Position = position; 16 | Final = final; 17 | Text = text; 18 | } 19 | public double DeltaWidth { get; } 20 | public double DeltaHeight { get; } 21 | public MetafilePoint Position { get; } 22 | public FinalFlag Final { get; } 23 | public string Text { get; } 24 | 25 | public override void Accept(ICommandVisitor visitor, T parameter) 26 | { 27 | visitor.AcceptGraphicalPrimitiveRestrictedText(this, parameter); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /TextEncoding/EscapeReader.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Commands; 2 | using CgmInfo.Commands.Enums; 3 | using CgmInfo.Commands.Escape; 4 | 5 | namespace CgmInfo.TextEncoding 6 | { 7 | internal static class EscapeReader 8 | { 9 | public static EscapeCommand Escape(MetafileReader reader) 10 | { 11 | int identifier = reader.ReadInteger(); 12 | 13 | // attempt to parse the data record as structured record, in case it is a known one 14 | // otherwise it is probably application specific and cannot be assumed to be a structured record 15 | StructuredDataRecord dataRecord; 16 | if (EscapeCommand.KnownEscapeTypes.ContainsKey(identifier)) 17 | dataRecord = reader.ReadStructuredDataRecord(); 18 | else 19 | dataRecord = new StructuredDataRecord(new[] 20 | { 21 | new StructuredDataElement(DataTypeIndex.String, new object[] { reader.ReadString() }), 22 | }); 23 | return new EscapeCommand(identifier, dataRecord); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Commands/GraphicalPrimitives/CircularArcCenterClose.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Commands.Enums; 2 | using CgmInfo.Traversal; 3 | using CgmInfo.Utilities; 4 | 5 | namespace CgmInfo.Commands.GraphicalPrimitives 6 | { 7 | [TextToken("ARCCTRCLOSE")] 8 | public class CircularArcCenterClose : Command 9 | { 10 | public CircularArcCenterClose(MetafilePoint center, MetafilePoint start, MetafilePoint end, double radius, ArcClosureType closure) 11 | : base(4, 16) 12 | { 13 | Center = center; 14 | Start = start; 15 | End = end; 16 | Radius = radius; 17 | Closure = closure; 18 | } 19 | 20 | public MetafilePoint Center { get; } 21 | public MetafilePoint Start { get; } 22 | public MetafilePoint End { get; } 23 | public double Radius { get; } 24 | public ArcClosureType Closure { get; } 25 | 26 | public override void Accept(ICommandVisitor visitor, T parameter) 27 | { 28 | visitor.AcceptGraphicalPrimitiveCircularArcCenterClose(this, parameter); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Commands/PictureDescriptor/GeometricPatternDefinition.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | using CgmInfo.Utilities; 3 | 4 | namespace CgmInfo.Commands.PictureDescriptor 5 | { 6 | [TextToken("GEOPATDEF")] 7 | public class GeometricPatternDefinition : Command 8 | { 9 | public GeometricPatternDefinition(int geometricPatternIndex, int segmentIdentifier, MetafilePoint firstCorner, MetafilePoint secondCorner) 10 | : base(2, 19) 11 | { 12 | GeometricPatternIndex = geometricPatternIndex; 13 | FirstCorner = firstCorner; 14 | SecondCorner = secondCorner; 15 | SegmentIdentifier = segmentIdentifier; 16 | } 17 | 18 | public int GeometricPatternIndex { get; } 19 | public int SegmentIdentifier { get; } 20 | public MetafilePoint FirstCorner { get; } 21 | public MetafilePoint SecondCorner { get; } 22 | 23 | public override void Accept(ICommandVisitor visitor, T parameter) 24 | { 25 | visitor.AcceptPictureDescriptorGeometricPatternDefinition(this, parameter); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /CgmInfoGui/ViewModels/CompanionFileViewModel.cs: -------------------------------------------------------------------------------- 1 | using System.Xml.Linq; 2 | using CgmInfo.Commands; 3 | using CgmInfo.Traversal; 4 | using CgmInfoGui.Traversal; 5 | using Dock.Model.Mvvm.Controls; 6 | 7 | namespace CgmInfoGui.ViewModels; 8 | 9 | public class CompanionFileViewModel : Document, ICommandReceiver 10 | { 11 | private XDocument? _xcfDocument; 12 | public XDocument? XCFDocument 13 | { 14 | get { return _xcfDocument; } 15 | set { SetProperty(ref _xcfDocument, value); } 16 | } 17 | 18 | public CompanionFileViewModel() 19 | { 20 | Title = "XCF"; 21 | CanClose = false; 22 | } 23 | 24 | ICommandAcceptor ICommandReceiver.BeginReceiving() => new Acceptor(this); 25 | private sealed class Acceptor(CompanionFileViewModel parent) : ICommandAcceptor 26 | { 27 | private readonly XCFDocumentBuilderVisitor _visitor = new (); 28 | private readonly XCFDocumentContext _parameters = new(); 29 | public void Accept(Command command) => command.Accept(_visitor, _parameters); 30 | public void Dispose() => parent.XCFDocument = _parameters.XCF; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /CgmInfoGui/Views/CompanionFileView.axaml: -------------------------------------------------------------------------------- 1 | 11 | 12 | 13 | 14 | 19 | 20 | -------------------------------------------------------------------------------- /Commands/Attributes/TextAlignment.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Commands.Enums; 2 | using CgmInfo.Traversal; 3 | 4 | namespace CgmInfo.Commands.Attributes 5 | { 6 | [TextToken("TEXTALIGN")] 7 | public class TextAlignment : Command 8 | { 9 | public TextAlignment(HorizontalTextAlignment horizontal, VerticalTextAlignment vertical, double horizontalContinuousAlignment, double verticalContinuousAlignment) 10 | : base(5, 18) 11 | { 12 | Horizontal = horizontal; 13 | Vertical = vertical; 14 | HorizontalContinuousAlignment = horizontalContinuousAlignment; 15 | VerticalContinuousAlignment = verticalContinuousAlignment; 16 | } 17 | 18 | public HorizontalTextAlignment Horizontal { get; } 19 | public VerticalTextAlignment Vertical { get; } 20 | public double HorizontalContinuousAlignment { get; } 21 | public double VerticalContinuousAlignment { get; } 22 | 23 | public override void Accept(ICommandVisitor visitor, T parameter) 24 | { 25 | visitor.AcceptAttributeTextAlignment(this, parameter); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Writers/ExternalWriter.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Commands; 2 | using CgmInfo.Commands.External; 3 | 4 | namespace CgmInfo.Writers 5 | { 6 | // [ISO/IEC 8632-3 8.9] 7 | internal static class ExternalWriter 8 | { 9 | public static void Message(MetafileWriter writer, Command command) 10 | { 11 | var message = (Message)command; 12 | // P1: (enumerated) action-required flag: valid values are 13 | // 0 noaction 14 | // 1 action 15 | writer.WriteEnum(message.ActionRequired); 16 | // P2: (string fixed) message string 17 | writer.WriteString(message.MessageString); 18 | } 19 | 20 | public static void ApplicationData(MetafileWriter writer, Command command) 21 | { 22 | var applicationData = (ApplicationData)command; 23 | // P1: (integer) identifier 24 | writer.WriteInteger(applicationData.Identifier); 25 | // P2: (data record) application data record; data records are bound as strings in this encoding. 26 | writer.WriteString(applicationData.DataRecord); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Commands/GraphicalPrimitives/CellArray.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | using CgmInfo.Utilities; 3 | 4 | namespace CgmInfo.Commands.GraphicalPrimitives 5 | { 6 | [TextToken("CELLARRAY")] 7 | public class CellArray : Command 8 | { 9 | public CellArray(MetafilePoint cornerPointP, MetafilePoint cornerPointQ, MetafilePoint cornerPointR, int nx, int ny, MetafileColor[] colors) 10 | : base(4, 9) 11 | { 12 | CornerPointP = cornerPointP; 13 | CornerPointQ = cornerPointQ; 14 | CornerPointR = cornerPointR; 15 | NX = nx; 16 | NY = ny; 17 | Colors = colors; 18 | } 19 | 20 | public MetafilePoint CornerPointP { get; } 21 | public MetafilePoint CornerPointQ { get; } 22 | public MetafilePoint CornerPointR { get; } 23 | public int NX { get; } 24 | public int NY { get; } 25 | public MetafileColor[] Colors { get; } 26 | 27 | public override void Accept(ICommandVisitor visitor, T parameter) 28 | { 29 | visitor.AcceptGraphicalPrimitiveCellArray(this, parameter); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Commands/GraphicalPrimitives/EllipticalArc.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | using CgmInfo.Utilities; 3 | 4 | namespace CgmInfo.Commands.GraphicalPrimitives 5 | { 6 | [TextToken("ELLIPARC")] 7 | public class EllipticalArc : Command 8 | { 9 | public EllipticalArc(MetafilePoint center, MetafilePoint firstConjugateDiameter, MetafilePoint secondConjugateDiameter, MetafilePoint start, MetafilePoint end) 10 | : base(4, 18) 11 | { 12 | Center = center; 13 | FirstConjugateDiameter = firstConjugateDiameter; 14 | SecondConjugateDiameter = secondConjugateDiameter; 15 | Start = start; 16 | End = end; 17 | } 18 | 19 | public MetafilePoint Center { get; } 20 | public MetafilePoint FirstConjugateDiameter { get; } 21 | public MetafilePoint SecondConjugateDiameter { get; } 22 | public MetafilePoint Start { get; } 23 | public MetafilePoint End { get; } 24 | 25 | public override void Accept(ICommandVisitor visitor, T parameter) 26 | { 27 | visitor.AcceptGraphicalPrimitiveEllipticalArc(this, parameter); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Commands/GraphicalPrimitives/HyperbolicArc.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | using CgmInfo.Utilities; 3 | 4 | namespace CgmInfo.Commands.GraphicalPrimitives 5 | { 6 | [TextToken("HYPERBARC")] 7 | public class HyperbolicArc : Command 8 | { 9 | public HyperbolicArc(MetafilePoint center, MetafilePoint traverseRadiusEndPoint, MetafilePoint conjugateRadiusEndPoint, MetafilePoint start, MetafilePoint end) 10 | : base(4, 22) 11 | { 12 | Center = center; 13 | TraverseRadiusEndPoint = traverseRadiusEndPoint; 14 | ConjugateRadiusEndPoint = conjugateRadiusEndPoint; 15 | Start = start; 16 | End = end; 17 | } 18 | 19 | public MetafilePoint Center { get; } 20 | public MetafilePoint TraverseRadiusEndPoint { get; } 21 | public MetafilePoint ConjugateRadiusEndPoint { get; } 22 | public MetafilePoint Start { get; } 23 | public MetafilePoint End { get; } 24 | 25 | public override void Accept(ICommandVisitor visitor, T parameter) 26 | { 27 | visitor.AcceptGraphicalPrimitiveHyperbolicArc(this, parameter); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Commands/GraphicalPrimitives/NonUniformRationalBSpline.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | using CgmInfo.Utilities; 3 | 4 | namespace CgmInfo.Commands.GraphicalPrimitives 5 | { 6 | [TextToken("NURB")] 7 | public class NonUniformRationalBSpline : Command 8 | { 9 | public NonUniformRationalBSpline(int splineOrder, MetafilePoint[] controlPoints, double[] knots, double start, double end, double[] weights) 10 | : base(4, 25) 11 | { 12 | SplineOrder = splineOrder; 13 | ControlPoints = controlPoints; 14 | Knots = knots; 15 | Start = start; 16 | End = end; 17 | Weights = weights; 18 | } 19 | 20 | public int SplineOrder { get; } 21 | public MetafilePoint[] ControlPoints { get; } 22 | public double[] Knots { get; } 23 | public double Start { get; } 24 | public double End { get; } 25 | public double[] Weights { get; } 26 | 27 | public override void Accept(ICommandVisitor visitor, T parameter) 28 | { 29 | visitor.AcceptGraphicalPrimitiveNonUniformRationalBSpline(this, parameter); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /CgmInfoGui/ViewModels/HotspotsViewModel.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using CgmInfo.Commands; 4 | using CgmInfoGui.Traversal; 5 | using CgmInfoGui.ViewModels.Nodes; 6 | using Dock.Model.Mvvm.Controls; 7 | 8 | namespace CgmInfoGui.ViewModels; 9 | 10 | public class HotspotsViewModel : Document, ICommandReceiver 11 | { 12 | private List? _hotspots; 13 | public List? Hotspots 14 | { 15 | get { return _hotspots; } 16 | set { SetProperty(ref _hotspots, value); } 17 | } 18 | 19 | public HotspotsViewModel() 20 | { 21 | Title = "Hotspots"; 22 | CanClose = false; 23 | } 24 | 25 | ICommandAcceptor ICommandReceiver.BeginReceiving() => new Acceptor(this); 26 | private sealed class Acceptor(HotspotsViewModel parent) : ICommandAcceptor 27 | { 28 | private readonly HotspotBuilderVisitor _visitor = new(); 29 | private readonly HotspotContext _parameters = new(); 30 | public void Accept(Command command) => command.Accept(_visitor, _parameters); 31 | public void Dispose() => parent.Hotspots = [.. _parameters.RootLevel.OfType()]; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /CgmInfoGui/ViewModels/Nodes/APSAttributeNode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using CgmInfo.Commands.ApplicationStructureDescriptor; 4 | 5 | namespace CgmInfoGui.ViewModels.Nodes; 6 | 7 | public class APSAttributeNode : NodeBase 8 | { 9 | public APSAttributeNode(ApplicationStructureAttribute apsAttribute) 10 | { 11 | Name = apsAttribute.AttributeType; 12 | Nodes.AddRange(apsAttribute.DataRecord.Elements.SelectMany(e => e.Values).Select(e => new SimpleNode(Convert.ToString(e)))); 13 | 14 | // pick out a few interresting attribute types that might be useful later on 15 | object[] allValues = apsAttribute.DataRecord.Elements.SelectMany(el => el.Values).ToArray(); 16 | switch (Name.ToUpperInvariant()) 17 | { 18 | case "NAME": 19 | case "LAYERNAME": 20 | if (allValues is [var singleValue]) 21 | Value = Convert.ToString(singleValue); 22 | break; 23 | } 24 | } 25 | public string Name { get; } 26 | // only set when it matches a particularly interesting type 27 | public string? Value { get; } 28 | 29 | public override string DisplayName => Name; 30 | } 31 | -------------------------------------------------------------------------------- /Commands/MetafileDescriptor/CharacterSetList.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using CgmInfo.Commands.Enums; 3 | using CgmInfo.Traversal; 4 | 5 | namespace CgmInfo.Commands.MetafileDescriptor 6 | { 7 | [TextToken("CHARSETLIST")] 8 | public class CharacterSetList : Command 9 | { 10 | public CharacterSetList(IEnumerable entries) 11 | : base(1, 14) 12 | { 13 | Entries = entries; 14 | } 15 | 16 | public IEnumerable Entries { get; } 17 | 18 | public override void Accept(ICommandVisitor visitor, T parameter) 19 | { 20 | visitor.AcceptMetafileDescriptorCharacterSetList(this, parameter); 21 | } 22 | } 23 | public class CharacterSetListEntry 24 | { 25 | public CharacterSetListEntry(CharacterSetType characterSetType, string designationSequenceTail) 26 | { 27 | CharacterSetType = characterSetType; 28 | DesignationSequenceTail = designationSequenceTail; 29 | } 30 | 31 | public CharacterSetType CharacterSetType { get; } 32 | public string DesignationSequenceTail { get; } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /CgmInfoGui/ViewModels/ApplicationStructureViewModel.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using CgmInfo.Commands; 3 | using CgmInfoGui.Traversal; 4 | using CgmInfoGui.ViewModels.Nodes; 5 | using Dock.Model.Mvvm.Controls; 6 | 7 | namespace CgmInfoGui.ViewModels; 8 | 9 | public class ApplicationStructureViewModel : Document, ICommandReceiver 10 | { 11 | private List? _apsNodes; 12 | public List? APSNodes 13 | { 14 | get { return _apsNodes; } 15 | set { SetProperty(ref _apsNodes, value); } 16 | } 17 | 18 | public ApplicationStructureViewModel() 19 | { 20 | Title = "APS Structure"; 21 | CanClose = false; 22 | } 23 | 24 | ICommandAcceptor ICommandReceiver.BeginReceiving() => new Acceptor(this); 25 | private sealed class Acceptor(ApplicationStructureViewModel parent) : ICommandAcceptor 26 | { 27 | private readonly APSStructureBuilderVisitor _visitor = new(); 28 | private readonly APSStructureContext _parameters = new(); 29 | public void Accept(Command command) => command.Accept(_visitor, _parameters); 30 | public void Dispose() => parent.APSNodes = [.. _parameters.RootLevel]; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /CgmInfoGui/Converters/StringJoinConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using Avalonia; 5 | using Avalonia.Data.Converters; 6 | 7 | namespace CgmInfoGui.Converters; 8 | 9 | public sealed class StringJoinConverter : IValueConverter 10 | { 11 | public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) 12 | { 13 | if (parameter is not string glue) 14 | { 15 | if (parameter is char glueChar) 16 | glue = glueChar.ToString(); 17 | else 18 | glue = Environment.NewLine; 19 | } 20 | 21 | if (value is IEnumerable values) 22 | { 23 | string str = string.Join(glue, values); 24 | // don't return an empty string; bindings might want to overrule this. 25 | if (string.IsNullOrWhiteSpace(str)) 26 | return AvaloniaProperty.UnsetValue; 27 | 28 | return str; 29 | } 30 | 31 | return value; 32 | } 33 | public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) => throw new NotImplementedException(); 34 | } 35 | -------------------------------------------------------------------------------- /Utilities/MetafileColorIndexed.cs: -------------------------------------------------------------------------------- 1 | namespace CgmInfo.Utilities 2 | { 3 | public class MetafileColorIndexed : MetafileColor 4 | { 5 | private readonly MetafileColor _actualColor; 6 | 7 | public int Index { get; } 8 | 9 | public MetafileColorIndexed(int colorIndex, MetafileColor actualColor) 10 | { 11 | _actualColor = actualColor; 12 | Index = colorIndex; 13 | } 14 | public override ARGB ToARGB() 15 | { 16 | if (_actualColor == null) 17 | return default(ARGB); 18 | return _actualColor.ToARGB(); 19 | } 20 | protected override string GetStringValue() 21 | { 22 | if (_actualColor != null) 23 | return string.Format("Color Index {0} ({1})", Index, _actualColor); 24 | else 25 | return string.Format("Color Index {0} (not known by COLOUR TABLE)", Index); 26 | } 27 | 28 | public override int GetHashCode() => _actualColor != null ? _actualColor.GetHashCode() : base.GetHashCode(); 29 | public override bool Equals(object obj) => _actualColor != null ? _actualColor.Equals(obj) : base.Equals(obj); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Commands/GraphicalPrimitives/MetafileCompressionTypes.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Collections.ObjectModel; 3 | 4 | namespace CgmInfo.Commands.GraphicalPrimitives 5 | { 6 | public static class MetafileCompressionTypes 7 | { 8 | public static IReadOnlyDictionary KnownCompressionTypes { get; } = new ReadOnlyDictionary(new Dictionary 9 | { 10 | // compression types originally part of ISO/IEC 8632:1999 11 | { 0, "Null Background" }, 12 | { 1, "Null Foreground" }, 13 | { 2, "T6" }, 14 | { 3, "T4 1-dimensional" }, 15 | { 4, "T4 2-dimensional" }, 16 | { 5, "Bitmap (uncompressed)" }, 17 | { 6, "Run Length" }, 18 | // line types later registered with the ISO/IEC 9973 Items Register 19 | { 7, "Baseline JPEG" }, 20 | { 8, "LZW" }, 21 | { 9, "PNG Compression Method 0" }, 22 | }); 23 | public static string GetName(int index) 24 | { 25 | if (KnownCompressionTypes.TryGetValue(index, out string name)) 26 | return name; 27 | 28 | return "Reserved"; 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /CgmInfoGui/Controls/PropertyGrid/ReadOnlyPropertyGrid.axaml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /Commands/GraphicalPrimitives/Tile.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | 3 | namespace CgmInfo.Commands.GraphicalPrimitives 4 | { 5 | [TextToken("TILE")] 6 | public class Tile : Command 7 | { 8 | public Tile(int compressionType, int rowPaddingIndicator, int cellColorPrecision, StructuredDataRecord parameters, byte[] compressedCells) 9 | : base(4, 29) 10 | { 11 | CompressionType = compressionType; 12 | CompressionTypeName = MetafileCompressionTypes.GetName(compressionType); 13 | RowPaddingIndicator = rowPaddingIndicator; 14 | CellColorPrecision = cellColorPrecision; 15 | Parameters = parameters; 16 | CompressedCells = compressedCells; 17 | } 18 | 19 | public int CompressionType { get; } 20 | public string CompressionTypeName { get; } 21 | public int RowPaddingIndicator { get; } 22 | public int CellColorPrecision { get; } 23 | public StructuredDataRecord Parameters { get; } 24 | public byte[] CompressedCells { get; } 25 | 26 | public override void Accept(ICommandVisitor visitor, T parameter) 27 | { 28 | visitor.AcceptGraphicalPrimitiveTile(this, parameter); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Utilities/MetafileColorCIE.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using CgmInfo.Commands.Enums; 3 | 4 | namespace CgmInfo.Utilities 5 | { 6 | public class MetafileColorCIE : MetafileColor 7 | { 8 | public ColorModel ColorModel { get; } 9 | public double Component1 { get; } 10 | public double Component2 { get; } 11 | public double Component3 { get; } 12 | 13 | public MetafileColorCIE(ColorModel colorModel, double component1, double component2, double component3) 14 | { 15 | ColorModel = colorModel; 16 | Component1 = component1; 17 | Component2 = component2; 18 | Component3 = component3; 19 | } 20 | public override ARGB ToARGB() 21 | { 22 | // CIELAB/CIELUV/RGB-related are not exactly .NET Color values, and need to be converted first. 23 | // TODO: actually convert them to RGB (using CIEXYZ for example, [ISO/IEC 8632-1 Annex G]) 24 | throw new NotSupportedException("CIE* Color Model conversions are not supported right now, sorry."); 25 | } 26 | protected override string GetStringValue() 27 | { 28 | return string.Format("{0} {1}/{2}/{3}", ColorModel, Component1, Component2, Component3); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /CgmInfoGui/ViewModels/Nodes/MetafileDescriptionNode.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using CgmInfo.Utilities; 3 | 4 | namespace CgmInfoGui.ViewModels.Nodes; 5 | 6 | public class MetafileDescriptionNode : NodeBase 7 | { 8 | public MetafileDescriptionNode(string description) 9 | { 10 | Description = description; 11 | 12 | var entries = MetafileDescriptionParser.ParseDescription(description); 13 | if (entries.Any()) 14 | { 15 | var original = new SimpleNode(string.Format("Original String: [{0} characters]", description.Length)); 16 | original.Nodes.Add(new SimpleNode(description)); 17 | Nodes.Add(original); 18 | Nodes.AddRange(entries.Select(k => new SimpleNode(string.Format("{0}: {1}", k.Key, k.Value)))); 19 | } 20 | } 21 | public string Description { get; } 22 | 23 | public override string DisplayName 24 | { 25 | get 26 | { 27 | if (Nodes.Any()) 28 | // show the number of individual parameters; excluding the "original string" one 29 | return string.Format("METAFILE DESCRIPTION: [{0} entries]", Nodes.Count - 1); 30 | else 31 | return string.Format("METAFILE DESCRIPTION: {0}", Description); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /CgmInfoGui/ViewModels/Nodes/Sources/TileSource.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using CgmInfo.Commands; 3 | using CgmInfo.Commands.Delimiter; 4 | using CgmInfo.Commands.GraphicalPrimitives; 5 | 6 | namespace CgmInfoGui.ViewModels.Nodes.Sources; 7 | 8 | internal sealed class TileSource : ITileSource 9 | { 10 | private readonly Tile _tile; 11 | private readonly BeginTileArray _tileArray; 12 | 13 | public TileSource(Tile tile, BeginTileArray tileArray) 14 | { 15 | _tile = tile ?? throw new ArgumentNullException(nameof(tile)); 16 | _tileArray = tileArray ?? throw new ArgumentNullException(nameof(tileArray)); 17 | DpiX = (int)Math.Round(tileArray.PathDirectionCellSize * 25.4); 18 | DpiY = (int)Math.Round(tileArray.LineDirectionCellSize * 25.4); 19 | } 20 | 21 | public bool IsBlackAndWhite => false; 22 | 23 | public int CompressionType => _tile.CompressionType; 24 | public byte[] CompressedCells => _tile.CompressedCells; 25 | public StructuredDataRecord Parameters => _tile.Parameters; 26 | 27 | public int Width => _tileArray.PathDirectionImageCellCount; 28 | public int Height => _tileArray.LineDirectionImageCellCount; 29 | public int DpiX { get; } 30 | public int DpiY { get; } 31 | public int ColorPrecision => _tile.CellColorPrecision; 32 | } 33 | -------------------------------------------------------------------------------- /BinaryEncoding/EscapeReader.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Commands; 2 | using CgmInfo.Commands.Enums; 3 | using CgmInfo.Commands.Escape; 4 | 5 | namespace CgmInfo.BinaryEncoding 6 | { 7 | // [ISO/IEC 8632-3 8.8] 8 | internal static class EscapeReader 9 | { 10 | public static EscapeCommand Escape(MetafileReader reader, CommandHeader commandHeader) 11 | { 12 | // P1: (integer) escape identifier 13 | // P2: (data record) escape data record; data records are bound as strings in this encoding. 14 | int identifier = reader.ReadInteger(); 15 | 16 | // attempt to parse the data record as structured record, in case it is a known one 17 | // otherwise it is probably application specific and cannot be assumed to be a structured record 18 | StructuredDataRecord dataRecord; 19 | if (EscapeCommand.KnownEscapeTypes.ContainsKey(identifier)) 20 | dataRecord = reader.ReadStructuredDataRecord(); 21 | else 22 | dataRecord = new StructuredDataRecord(new[] 23 | { 24 | new StructuredDataElement(DataTypeIndex.String, new object[] { reader.ReadString() }), 25 | }); 26 | return new EscapeCommand(identifier, dataRecord); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /CgmInfoGui/Traversal/APSStructureBuilderVisitor.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Commands.ApplicationStructureDescriptor; 2 | using CgmInfo.Commands.Delimiter; 3 | using CgmInfo.Traversal; 4 | 5 | namespace CgmInfoGui.Traversal; 6 | 7 | public class APSStructureBuilderVisitor : CommandVisitor 8 | { 9 | public override void AcceptApplicationStructureDescriptorAttribute(ApplicationStructureAttribute applicationStructureAttribute, APSStructureContext parameter) 10 | { 11 | parameter.AddAttributeNode(applicationStructureAttribute); 12 | } 13 | 14 | public override void AcceptDelimiterBeginApplicationStructure(BeginApplicationStructure beginApplicationStructure, APSStructureContext parameter) 15 | { 16 | parameter.BeginLevel("{0} '{1}'", beginApplicationStructure.Type, beginApplicationStructure.Identifier); 17 | } 18 | 19 | public override void AcceptDelimiterBeginApplicationStructureBody(BeginApplicationStructureBody beginApplicationStructureBody, APSStructureContext parameter) 20 | { 21 | // left blank for now, but we never know if/when we'd need it. 22 | } 23 | 24 | public override void AcceptDelimiterEndApplicationStructure(EndApplicationStructure endApplicationStructure, APSStructureContext parameter) 25 | { 26 | parameter.EndLevel(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Commands/Enums/AspectSourceFlagsType.cs: -------------------------------------------------------------------------------- 1 | namespace CgmInfo.Commands.Enums 2 | { 3 | public enum AspectSourceFlagsType 4 | { 5 | [TextToken("LINETYPE")] 6 | LineType = 0, 7 | [TextToken("LINEWIDTH")] 8 | LineWidth = 1, 9 | [TextToken("LINECOLR")] 10 | LineColor = 2, 11 | [TextToken("MARKERTYPE")] 12 | MarkerType = 3, 13 | [TextToken("MARKERSIZE")] 14 | MarkerSize = 4, 15 | [TextToken("MARKERCOLR")] 16 | MarkerColor = 5, 17 | [TextToken("TEXTFONTINDEX")] 18 | TextFontIndex = 6, 19 | [TextToken("TEXTPREC")] 20 | TextPrecision = 7, 21 | [TextToken("CHAREXPAN")] 22 | CharacterExpansionFactor = 8, 23 | [TextToken("CHARSPACE")] 24 | CharacterSpacing = 9, 25 | [TextToken("TEXTCOLR")] 26 | TextColor = 10, 27 | [TextToken("INTSTYLE")] 28 | InteriorStyle = 11, 29 | [TextToken("FILLCOLR")] 30 | FillColor = 12, 31 | [TextToken("HATCHINDEX")] 32 | HatchIndex = 13, 33 | [TextToken("PATINDEX")] 34 | PatternIndex = 14, 35 | [TextToken("EDGETYPE")] 36 | EdgeType = 15, 37 | [TextToken("EDGEWIDTH")] 38 | EdgeWidth = 16, 39 | [TextToken("EDGECOLR")] 40 | EdgeColor = 17, 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Commands/GraphicalPrimitives/EllipticalArcClose.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Commands.Enums; 2 | using CgmInfo.Traversal; 3 | using CgmInfo.Utilities; 4 | 5 | namespace CgmInfo.Commands.GraphicalPrimitives 6 | { 7 | [TextToken("ELLIPARCCLOSE")] 8 | public class EllipticalArcClose : Command 9 | { 10 | public EllipticalArcClose(MetafilePoint center, MetafilePoint firstConjugateDiameter, MetafilePoint secondConjugateDiameter, MetafilePoint start, MetafilePoint end, ArcClosureType closure) 11 | : base(4, 19) 12 | { 13 | Center = center; 14 | FirstConjugateDiameter = firstConjugateDiameter; 15 | SecondConjugateDiameter = secondConjugateDiameter; 16 | Start = start; 17 | End = end; 18 | Closure = closure; 19 | } 20 | 21 | public MetafilePoint Center { get; } 22 | public MetafilePoint FirstConjugateDiameter { get; } 23 | public MetafilePoint SecondConjugateDiameter { get; } 24 | public MetafilePoint Start { get; } 25 | public MetafilePoint End { get; } 26 | public ArcClosureType Closure { get; } 27 | 28 | public override void Accept(ICommandVisitor visitor, T parameter) 29 | { 30 | visitor.AcceptGraphicalPrimitiveEllipticalArcClose(this, parameter); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Commands/Attributes/EdgeJoin.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Collections.ObjectModel; 3 | using CgmInfo.Traversal; 4 | 5 | namespace CgmInfo.Commands.Attributes 6 | { 7 | [TextToken("EDGEJOIN")] 8 | public class EdgeJoin : Command 9 | { 10 | public EdgeJoin(int index) 11 | : base(5, 45) 12 | { 13 | Index = index; 14 | Name = GetName(index); 15 | } 16 | 17 | public int Index { get; } 18 | public string Name { get; } 19 | 20 | public override void Accept(ICommandVisitor visitor, T parameter) 21 | { 22 | visitor.AcceptAttributeEdgeJoin(this, parameter); 23 | } 24 | 25 | public static IReadOnlyDictionary KnownEdgeJoinIndicators { get; } = new ReadOnlyDictionary(new Dictionary 26 | { 27 | // edge join indicators originally part of ISO/IEC 8632:1999 28 | { 1, "Unspecified" }, 29 | { 2, "Mitre" }, 30 | { 3, "Round" }, 31 | { 4, "Bevel" }, 32 | }); 33 | public static string GetName(int index) 34 | { 35 | if (KnownEdgeJoinIndicators.TryGetValue(index, out string name)) 36 | return name; 37 | 38 | return "Reserved"; 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Commands/Attributes/LineJoin.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Collections.ObjectModel; 3 | using CgmInfo.Traversal; 4 | 5 | namespace CgmInfo.Commands.Attributes 6 | { 7 | [TextToken("LINEJOIN")] 8 | public class LineJoin : Command 9 | { 10 | public LineJoin(int index) 11 | : base(5, 38) 12 | { 13 | Index = index; 14 | Name = GetName(index); 15 | } 16 | 17 | public int Index { get; } 18 | public string Name { get; } 19 | 20 | public override void Accept(ICommandVisitor visitor, T parameter) 21 | { 22 | visitor.AcceptAttributeLineJoin(this, parameter); 23 | } 24 | 25 | public static IReadOnlyDictionary KnownLineJoinIndicators { get; } = new ReadOnlyDictionary(new Dictionary 26 | { 27 | // line join indicators originally part of ISO/IEC 8632:1999 28 | { 1, "Unspecified" }, 29 | { 2, "Mitre" }, 30 | { 3, "Round" }, 31 | { 4, "Bevel" }, 32 | }); 33 | public static string GetName(int index) 34 | { 35 | if (KnownLineJoinIndicators.TryGetValue(index, out string name)) 36 | return name; 37 | 38 | return "Reserved"; 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Utilities/TrackingBuffer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace CgmInfo.Utilities; 7 | 8 | public sealed class TrackingBuffer(long position) 9 | { 10 | private readonly List _buffer = []; 11 | 12 | public long Start { get; } = position; 13 | public bool Unaligned { get; private set; } 14 | public List EncodingChanges { get; } = []; 15 | 16 | public byte[] Buffer => [.. _buffer]; 17 | 18 | internal void SetAlign(byte align) 19 | { 20 | Unaligned = true; 21 | _buffer.Add(align); 22 | } 23 | internal void SetHeader(ushort commandHeader) => _buffer.AddRange(BE(BitConverter.GetBytes(commandHeader))); 24 | internal void AddLongCommand(ushort longFormCommandHeader) => _buffer.AddRange(BE(BitConverter.GetBytes(longFormCommandHeader))); 25 | internal void AddBuffer(byte[] buffer) => _buffer.AddRange(buffer); 26 | internal void SwitchEncoding(Encoding oldEncoding, Encoding newEncoding) 27 | { 28 | EncodingChanges.Add($"{oldEncoding.EncodingName} -> {newEncoding.EncodingName}"); 29 | } 30 | 31 | private static IEnumerable BE(IEnumerable buffer) 32 | { 33 | if (BitConverter.IsLittleEndian) 34 | buffer = buffer.Reverse(); 35 | return buffer; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /CgmInfoGui/ViewModels/Nodes/Sources/BitonalTileSource.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using CgmInfo.Commands; 3 | using CgmInfo.Commands.Delimiter; 4 | using CgmInfo.Commands.GraphicalPrimitives; 5 | 6 | namespace CgmInfoGui.ViewModels.Nodes.Sources; 7 | 8 | internal sealed class BitonalTileSource : ITileSource 9 | { 10 | private readonly BitonalTile _bitonalTile; 11 | private readonly BeginTileArray _tileArray; 12 | 13 | public BitonalTileSource(BitonalTile bitonalTile, BeginTileArray tileArray) 14 | { 15 | _bitonalTile = bitonalTile ?? throw new ArgumentNullException(nameof(bitonalTile)); 16 | _tileArray = tileArray ?? throw new ArgumentNullException(nameof(tileArray)); 17 | DpiX = (int)Math.Round(tileArray.PathDirectionCellSize * 25.4); 18 | DpiY = (int)Math.Round(tileArray.LineDirectionCellSize * 25.4); 19 | } 20 | 21 | public bool IsBlackAndWhite => true; 22 | 23 | public int CompressionType => _bitonalTile.CompressionType; 24 | public byte[] CompressedCells => _bitonalTile.CompressedCells; 25 | public StructuredDataRecord Parameters => _bitonalTile.Parameters; 26 | 27 | public int Width => _tileArray.PathDirectionImageCellCount; 28 | public int Height => _tileArray.LineDirectionImageCellCount; 29 | public int DpiX { get; } 30 | public int DpiY { get; } 31 | public int ColorPrecision => 1; // we're black/white; one bit of precision is enough. 32 | } 33 | -------------------------------------------------------------------------------- /Commands/Attributes/EdgeTypeContinuation.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Collections.ObjectModel; 3 | using CgmInfo.Traversal; 4 | 5 | namespace CgmInfo.Commands.Attributes 6 | { 7 | [TextToken("EDGETYPECONT")] 8 | public class EdgeTypeContinuation : Command 9 | { 10 | public EdgeTypeContinuation(int index) 11 | : base(5, 46) 12 | { 13 | Index = index; 14 | Name = GetName(index); 15 | } 16 | 17 | public int Index { get; } 18 | public string Name { get; } 19 | 20 | public override void Accept(ICommandVisitor visitor, T parameter) 21 | { 22 | visitor.AcceptAttributeEdgeTypeContinuation(this, parameter); 23 | } 24 | 25 | public static IReadOnlyDictionary KnownEdgeTypeContinuations { get; } = new ReadOnlyDictionary(new Dictionary 26 | { 27 | // edge type continuations originally part of ISO/IEC 8632:1999 28 | { 1, "Unspecified" }, 29 | { 2, "Continue" }, 30 | { 3, "Restart" }, 31 | { 4, "Adaptive Continue" }, 32 | }); 33 | public static string GetName(int index) 34 | { 35 | if (KnownEdgeTypeContinuations.TryGetValue(index, out string name)) 36 | return name; 37 | 38 | return "Reserved"; 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Commands/Attributes/LineTypeContinuation.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Collections.ObjectModel; 3 | using CgmInfo.Traversal; 4 | 5 | namespace CgmInfo.Commands.Attributes 6 | { 7 | [TextToken("LINETYPECONT")] 8 | public class LineTypeContinuation : Command 9 | { 10 | public LineTypeContinuation(int index) 11 | : base(5, 39) 12 | { 13 | Index = index; 14 | Name = GetName(index); 15 | } 16 | 17 | public int Index { get; } 18 | public string Name { get; } 19 | 20 | public override void Accept(ICommandVisitor visitor, T parameter) 21 | { 22 | visitor.AcceptAttributeLineTypeContinuation(this, parameter); 23 | } 24 | 25 | public static IReadOnlyDictionary KnownLineTypeContinuations { get; } = new ReadOnlyDictionary(new Dictionary 26 | { 27 | // line type continuations originally part of ISO/IEC 8632:1999 28 | { 1, "Unspecified" }, 29 | { 2, "Continue" }, 30 | { 3, "Restart" }, 31 | { 4, "Adaptive Continue" }, 32 | }); 33 | public static string GetName(int index) 34 | { 35 | if (KnownLineTypeContinuations.TryGetValue(index, out string name)) 36 | return name; 37 | 38 | return "Reserved"; 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Utilities/MetafileColorCMYK.cs: -------------------------------------------------------------------------------- 1 | namespace CgmInfo.Utilities 2 | { 3 | public class MetafileColorCMYK : MetafileColor 4 | { 5 | public int Cyan { get; } 6 | public int Magenta { get; } 7 | public int Yellow { get; } 8 | public int Black { get; } 9 | 10 | public MetafileColorCMYK(int cyan, int magenta, int yellow, int black) 11 | { 12 | Cyan = cyan; 13 | Magenta = magenta; 14 | Yellow = yellow; 15 | Black = black; 16 | } 17 | public override ARGB ToARGB() 18 | { 19 | double c = Cyan / 255.0; 20 | double m = Magenta / 255.0; 21 | double y = Yellow / 255.0; 22 | double k = Black / 255.0; 23 | 24 | double r = c * (1.0 - k) + k; 25 | double g = m * (1.0 - k) + k; 26 | double b = y * (1.0 - k) + k; 27 | 28 | r = (1.0 - r) * 255.0 + 0.5; 29 | g = (1.0 - g) * 255.0 + 0.5; 30 | b = (1.0 - b) * 255.0 + 0.5; 31 | 32 | int red = (int)r; 33 | int green = (int)g; 34 | int blue = (int)b; 35 | 36 | return new ARGB { Alpha = 255, Red = red, Green = green, Blue = blue }; 37 | } 38 | protected override string GetStringValue() 39 | { 40 | return string.Format("C={0} M={1} Y={2} K={3}", Cyan, Magenta, Yellow, Black); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /CgmInfoGui/Controls/OffsetColumn.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Avalonia.Media.TextFormatting; 3 | using AvaloniaHex.Rendering; 4 | using CgmInfoGui.ViewModels.Nodes; 5 | 6 | namespace CgmInfoGui.Controls; 7 | 8 | internal class OffsetColumn : AvaloniaHex.Rendering.OffsetColumn 9 | { 10 | public override TextLine? CreateTextLine(VisualBytesLine line) 11 | { 12 | if (HexView is null) 13 | throw new InvalidOperationException(); 14 | 15 | ulong offset = line.Range.Start.ByteIndex; 16 | if (HexView.DataContext is NodeBase { Command.Buffer.Start: long start }) 17 | offset += (ulong)start; 18 | string text = IsUppercase 19 | ? $"{offset:X8}:" 20 | : $"{offset:x8}:"; 21 | 22 | var properties = GetTextRunProperties(); 23 | return TextFormatter.Current.FormatLine( 24 | new SimpleTextSource(text, properties), 25 | 0, 26 | double.MaxValue, 27 | new GenericTextParagraphProperties(properties) 28 | )!; 29 | } 30 | 31 | private readonly struct SimpleTextSource(string text, TextRunProperties defaultProperties) : ITextSource 32 | { 33 | public TextRun GetTextRun(int textSourceIndex) 34 | { 35 | if (textSourceIndex >= text.Length) 36 | return new TextEndOfParagraph(); 37 | 38 | return new TextCharacters(text, defaultProperties); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Commands/TextTokenAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | 4 | namespace CgmInfo.Commands 5 | { 6 | [AttributeUsage(AttributeTargets.Class | AttributeTargets.Field, AllowMultiple = false, Inherited = false)] 7 | public sealed class TextTokenAttribute : Attribute 8 | { 9 | public string Token { get; } 10 | public string? EndToken { get; set; } 11 | 12 | public TextTokenAttribute(string token) 13 | { 14 | Token = token; 15 | } 16 | 17 | public static string? GetToken(Command command) 18 | { 19 | var textTokenAttribute = command?.GetType().GetTypeInfo().GetCustomAttribute(); 20 | return textTokenAttribute?.Token; 21 | } 22 | public static string? GetEndToken(Command command) 23 | { 24 | var textTokenAttribute = command?.GetType().GetTypeInfo().GetCustomAttribute(); 25 | return textTokenAttribute?.EndToken; 26 | } 27 | // enums shouldn't really have an EndToken, so it doesn't make much sense to provide a GetEndToken method here. 28 | public static string? GetToken(TEnum enumValue) where TEnum : Enum 29 | { 30 | var textTokenAttribute = typeof(TEnum).GetRuntimeField(enumValue.ToString())?.GetCustomAttribute(); 31 | return textTokenAttribute?.Token; 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /CgmInfoGui/App.axaml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /Commands/Attributes/RestrictedTextType.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Collections.ObjectModel; 3 | using CgmInfo.Traversal; 4 | 5 | namespace CgmInfo.Commands.Attributes 6 | { 7 | [TextToken("RESTRTEXTTYPE")] 8 | public class RestrictedTextType : Command 9 | { 10 | public RestrictedTextType(int index) 11 | : base(5, 42) 12 | { 13 | Index = index; 14 | Name = GetName(index); 15 | } 16 | 17 | public int Index { get; } 18 | public string Name { get; } 19 | 20 | public override void Accept(ICommandVisitor visitor, T parameter) 21 | { 22 | visitor.AcceptAttributeRestrictedTextType(this, parameter); 23 | } 24 | 25 | public static IReadOnlyDictionary KnownRestrictionTypes { get; } = new ReadOnlyDictionary(new Dictionary 26 | { 27 | // restriction types originally part of ISO/IEC 8632:1999 28 | { 1, "Basic" }, 29 | { 2, "Boxed-Cap" }, 30 | { 3, "Boxed-All" }, 31 | { 4, "Isotropic-Cap" }, 32 | { 5, "Isotropic-All" }, 33 | { 6, "Justified" }, 34 | }); 35 | public static string GetName(int index) 36 | { 37 | if (KnownRestrictionTypes.TryGetValue(index, out string name)) 38 | return name; 39 | 40 | return "Reserved"; 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Commands/PictureDescriptor/HatchStyleDefinition.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Commands.Enums; 2 | using CgmInfo.Traversal; 3 | using CgmInfo.Utilities; 4 | 5 | namespace CgmInfo.Commands.PictureDescriptor 6 | { 7 | [TextToken("HATCHSTYLEDEF")] 8 | public class HatchStyleDefinition : Command 9 | { 10 | public HatchStyleDefinition(int hatchIndex, HatchStyleIndicator styleIndicator, MetafilePoint hatchDirectionStart, MetafilePoint hatchDirectionEnd, double dutyCycleLength, int[] gapWidths, int[] lineTypes) 11 | : base(2, 18) 12 | { 13 | HatchIndex = hatchIndex; 14 | StyleIndicator = styleIndicator; 15 | HatchDirectionStart = hatchDirectionStart; 16 | HatchDirectionEnd = hatchDirectionEnd; 17 | DutyCycleLength = dutyCycleLength; 18 | GapWidths = gapWidths; 19 | LineTypes = lineTypes; 20 | } 21 | 22 | public int HatchIndex { get; } 23 | public double DutyCycleLength { get; } 24 | public int[] GapWidths { get; } 25 | public int[] LineTypes { get; } 26 | public MetafilePoint HatchDirectionStart { get; } 27 | public MetafilePoint HatchDirectionEnd { get; } 28 | public HatchStyleIndicator StyleIndicator { get; } 29 | 30 | public override void Accept(ICommandVisitor visitor, T parameter) 31 | { 32 | visitor.AcceptPictureDescriptorHatchStyleDefinition(this, parameter); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /CgmInfoGui/ViewModels/DockFactory.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using Dock.Model.Controls; 3 | using Dock.Model.Core; 4 | using Dock.Model.Mvvm; 5 | using Dock.Model.Mvvm.Controls; 6 | 7 | namespace CgmInfoGui.ViewModels; 8 | 9 | public class DockFactory : Factory 10 | { 11 | private readonly MainWindowViewModel _mainWindowViewModel; 12 | public DockFactory(MainWindowViewModel mainWindowViewModel) 13 | { 14 | _mainWindowViewModel = mainWindowViewModel; 15 | } 16 | public override IRootDock CreateLayout() 17 | { 18 | var root = CreateRootDock(); 19 | 20 | var mainDocuments = new DocumentDock 21 | { 22 | VisibleDockables = _mainWindowViewModel.Documents, 23 | CanCreateDocument = false, 24 | }; 25 | mainDocuments.ActiveDockable = mainDocuments.DefaultDockable = mainDocuments.VisibleDockables.FirstOrDefault(); 26 | 27 | var mainLayout = new ProportionalDock 28 | { 29 | Orientation = Orientation.Horizontal, 30 | VisibleDockables = CreateList(mainDocuments), 31 | ActiveDockable = mainDocuments, 32 | DefaultDockable = mainDocuments, 33 | IsCollapsable = false, 34 | }; 35 | 36 | root.VisibleDockables = CreateList(mainLayout); 37 | root.DefaultDockable = mainLayout; 38 | root.ActiveDockable = mainLayout; 39 | root.IsCollapsable = false; 40 | return root; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Commands/GraphicalPrimitives/BitonalTile.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Traversal; 2 | using CgmInfo.Utilities; 3 | 4 | namespace CgmInfo.Commands.GraphicalPrimitives 5 | { 6 | [TextToken("BITONALTILE")] 7 | public class BitonalTile : Command 8 | { 9 | public BitonalTile(int compressionType, int rowPaddingIndicator, MetafileColor cellBackgroundColor, MetafileColor cellForegroundColor, StructuredDataRecord parameters, byte[] compressedCells) 10 | : base(4, 28) 11 | { 12 | CompressionType = compressionType; 13 | CompressionTypeName = MetafileCompressionTypes.GetName(compressionType); 14 | RowPaddingIndicator = rowPaddingIndicator; 15 | CellBackgroundColor = cellBackgroundColor; 16 | CellForegroundColor = cellForegroundColor; 17 | Parameters = parameters; 18 | CompressedCells = compressedCells; 19 | } 20 | 21 | public int CompressionType { get; } 22 | public string CompressionTypeName { get; } 23 | public int RowPaddingIndicator { get; } 24 | public MetafileColor CellBackgroundColor { get; } 25 | public MetafileColor CellForegroundColor { get; } 26 | public StructuredDataRecord Parameters { get; } 27 | public byte[] CompressedCells { get; } 28 | 29 | public override void Accept(ICommandVisitor visitor, T parameter) 30 | { 31 | visitor.AcceptGraphicalPrimitiveBitonalTile(this, parameter); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Traversal/MetafilePropertyVisitor.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using CgmInfo.Commands.Delimiter; 3 | using CgmInfo.Commands.MetafileDescriptor; 4 | using CgmInfo.Utilities; 5 | 6 | namespace CgmInfo.Traversal 7 | { 8 | internal class MetafilePropertyVisitor : CommandVisitor 9 | { 10 | public override void AcceptDelimiterBeginMetafile(BeginMetafile beginMetafile, MetafileProperties parameter) 11 | { 12 | parameter.Name = beginMetafile.Name; 13 | } 14 | public override void AcceptMetafileDescriptorMetafileVersion(MetafileVersion metafileVersion, MetafileProperties parameter) 15 | { 16 | parameter.Version = metafileVersion.Version; 17 | } 18 | public override void AcceptMetafileDescriptorMetafileDescription(MetafileDescription metafileDescription, MetafileProperties parameter) 19 | { 20 | var keys = MetafileDescriptionParser.ParseDescription(metafileDescription.Description); 21 | if (keys.Any()) 22 | { 23 | if (!keys.TryGetValue("ProfileId", out string profileId)) 24 | profileId = "ISO/IEC 8632"; 25 | if (!keys.TryGetValue("ProfileEd", out string profileEd)) 26 | profileEd = "(guess)"; 27 | 28 | parameter.Profile = string.Format("{0} {1}", profileId, profileEd); 29 | } 30 | else 31 | { 32 | parameter.Profile = "ISO/IEC 8632 (guess)"; 33 | } 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Commands/Attributes/EdgeType.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Collections.ObjectModel; 3 | using CgmInfo.Traversal; 4 | 5 | namespace CgmInfo.Commands.Attributes 6 | { 7 | [TextToken("EDGETYPE")] 8 | public class EdgeType : Command 9 | { 10 | public EdgeType(int index) 11 | : base(5, 27) 12 | { 13 | Index = index; 14 | Name = GetName(index); 15 | } 16 | 17 | public int Index { get; } 18 | public string Name { get; } 19 | 20 | public override void Accept(ICommandVisitor visitor, T parameter) 21 | { 22 | visitor.AcceptAttributeEdgeType(this, parameter); 23 | } 24 | 25 | public static IReadOnlyDictionary KnownEdgeTypes { get; } = new ReadOnlyDictionary(new Dictionary 26 | { 27 | // there is no value 0, guessing it should mean "None" if it ever happens 28 | { 0, "None" }, 29 | // edge types originally part of ISO/IEC 8632:1999 30 | { 1, "Solid" }, 31 | { 2, "Dash" }, 32 | { 3, "Dot" }, 33 | { 4, "Dash-Dot" }, 34 | { 5, "Dash-Dot-Dot" }, 35 | }); 36 | public static string GetName(int index) 37 | { 38 | if (index < 0) 39 | return "Private"; 40 | 41 | if (KnownEdgeTypes.TryGetValue(index, out string name)) 42 | return name; 43 | 44 | return "Reserved"; 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /CgmInfoGui/ViewModels/Nodes/HotspotNode.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | namespace CgmInfoGui.ViewModels.Nodes; 4 | 5 | public class HotspotNode : NodeBase 6 | { 7 | public HotspotNode(string identifier) 8 | { 9 | ID = identifier; 10 | // TODO: maybe calculate the actual boundaries if the region type stays at 0? 11 | RegionValues = []; 12 | } 13 | 14 | public string ID { get; } 15 | public string? Name { get; set; } 16 | public string? Screentip { get; set; } 17 | [ReadOnly(true)] 18 | public HotspotRegionType RegionType { get; set; } 19 | public double[] RegionValues { get; set; } 20 | public HotspotLinkTarget? LinkTarget { get; set; } 21 | 22 | public override string DisplayName 23 | { 24 | get { return string.Format("{0} '{1}'", ID, string.IsNullOrEmpty(Name) ? "(no name)" : Name); } 25 | } 26 | } 27 | 28 | public enum HotspotRegionType 29 | { 30 | Object = 0, 31 | Rectangle = 1, 32 | Ellipse = 2, 33 | Polygon = 3, 34 | Polybezier = 4, 35 | } 36 | 37 | public sealed class HotspotLinkTarget(string? destination, string? title, string? target) 38 | { 39 | public string Destination { get; } = destination ?? string.Empty; 40 | public string? Title { get; } = title; 41 | public string? Target { get; } = target; 42 | 43 | public override string ToString() 44 | { 45 | if (!string.IsNullOrEmpty(Title)) 46 | return string.Format("{0} ({1})", Title, Destination); 47 | else 48 | return Destination; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /Commands/GraphicalPrimitives/Polybezier.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Collections.ObjectModel; 3 | using CgmInfo.Traversal; 4 | using CgmInfo.Utilities; 5 | 6 | namespace CgmInfo.Commands.GraphicalPrimitives 7 | { 8 | [TextToken("POLYBEZIER")] 9 | public class Polybezier : Command 10 | { 11 | public Polybezier(int continuityIndicator, MetafilePoint[] pointSequences) 12 | : base(4, 26) 13 | { 14 | ContinuityIndicator = continuityIndicator; 15 | Name = GetName(continuityIndicator); 16 | PointSequences = pointSequences; 17 | } 18 | 19 | public int ContinuityIndicator { get; } 20 | public string Name { get; } 21 | public MetafilePoint[] PointSequences { get; } 22 | 23 | public override void Accept(ICommandVisitor visitor, T parameter) 24 | { 25 | visitor.AcceptGraphicalPrimitivePolybezier(this, parameter); 26 | } 27 | 28 | public static IReadOnlyDictionary KnownContinuityIndicators { get; } = new ReadOnlyDictionary(new Dictionary 29 | { 30 | // continuity indicators originally part of ISO/IEC 8632:1999 31 | { 1, "Discontinuous" }, 32 | { 2, "Continuous" }, 33 | }); 34 | public static string GetName(int index) 35 | { 36 | if (KnownContinuityIndicators.TryGetValue(index, out string name)) 37 | return name; 38 | 39 | return "Reserved"; 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /CgmInfo.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0 5 | CgmInfo 6 | CgmInfo 7 | CGM Metafile Info Library 8 | enable 9 | latest 10 | 11 | 12 | 13 | bin\Debug\ 14 | 15 | 16 | 17 | bin\Release\ 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | all 44 | runtime; build; native; contentfiles; analyzers; buildtransitive 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /CgmInfoGui/App.axaml.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using Avalonia; 3 | using Avalonia.Controls.ApplicationLifetimes; 4 | using Avalonia.Data.Core; 5 | using Avalonia.Data.Core.Plugins; 6 | using Avalonia.Markup.Xaml; 7 | using CgmInfoGui.Services; 8 | using CgmInfoGui.ViewModels; 9 | using CgmInfoGui.Views; 10 | 11 | namespace CgmInfoGui; 12 | 13 | public partial class App : Application 14 | { 15 | public override void Initialize() 16 | { 17 | AvaloniaXamlLoader.Load(this); 18 | } 19 | 20 | public override void OnFrameworkInitializationCompleted() 21 | { 22 | if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) 23 | { 24 | // Avoid duplicate validations from both Avalonia and the CommunityToolkit. 25 | // More info: https://docs.avaloniaui.net/docs/guides/development-guides/data-validation#manage-validationplugins 26 | DisableAvaloniaDataAnnotationValidation(); 27 | var mainWindow = new MainWindow(); 28 | mainWindow.DataContext = new MainWindowViewModel(new FileService(mainWindow)); 29 | desktop.MainWindow = mainWindow; 30 | } 31 | 32 | base.OnFrameworkInitializationCompleted(); 33 | } 34 | 35 | private void DisableAvaloniaDataAnnotationValidation() 36 | { 37 | // Get an array of plugins to remove 38 | var dataValidationPluginsToRemove = 39 | BindingPlugins.DataValidators.OfType().ToArray(); 40 | 41 | // remove each entry found 42 | foreach (var plugin in dataValidationPluginsToRemove) 43 | { 44 | BindingPlugins.DataValidators.Remove(plugin); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /CgmInfoGui/Traversal/MetafileContext.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using CgmInfo.Commands; 4 | using CgmInfoGui.ViewModels.Nodes; 5 | 6 | namespace CgmInfoGui.Traversal; 7 | 8 | public class MetafileContext : NodeContext 9 | { 10 | public NodeBase AddMetafileDescriptorNode(string format, params object[] args) 11 | { 12 | var newNode = new SimpleNode(string.Format(format, args)); 13 | AddDescriptorNode(newNode); 14 | return newNode; 15 | } 16 | public void AddDescriptorNode(NodeBase node) 17 | { 18 | var metafile = RootLevel.OfType().FirstOrDefault(); 19 | if (metafile == null) 20 | throw new InvalidOperationException("Got a Metafile Descriptor element without a Metafile"); 21 | metafile.Descriptor.Nodes.Add(node); 22 | LastAddedNode = node; 23 | } 24 | 25 | public void AddUnsupportedNode(UnsupportedCommand unsupportedCommand) 26 | { 27 | var counterNode = RootLevel.OfType().FirstOrDefault(); 28 | if (counterNode == null) 29 | { 30 | counterNode = new UnsupportedCounter(); 31 | RootLevel.Add(counterNode); 32 | } 33 | counterNode.Count(unsupportedCommand); 34 | 35 | var level = CurrentLevelNodes; 36 | var container = level.OfType().FirstOrDefault(); 37 | if (container == null) 38 | { 39 | container = new UnsupportedContainer(); 40 | level.Insert(0, container); 41 | } 42 | var unsupportedNode = new UnsupportedNode(unsupportedCommand); 43 | LastAddedNode = unsupportedNode; 44 | container.Add(unsupportedNode); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Commands/Attributes/InterpolatedInterior.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Collections.ObjectModel; 3 | using CgmInfo.Traversal; 4 | using CgmInfo.Utilities; 5 | 6 | namespace CgmInfo.Commands.Attributes 7 | { 8 | [TextToken("INTERPINT")] 9 | public class InterpolatedInterior : Command 10 | { 11 | public InterpolatedInterior(int index, MetafilePoint[] referenceGeometry, double[] stageDesignators, MetafileColor[] colorSpecifiers) 12 | : base(5, 43) 13 | { 14 | Index = index; 15 | Name = GetName(index); 16 | ReferenceGeometry = referenceGeometry; 17 | StageDesignators = stageDesignators; 18 | ColorSpecifiers = colorSpecifiers; 19 | } 20 | 21 | public int Index { get; } 22 | public string Name { get; } 23 | public MetafilePoint[] ReferenceGeometry { get; } 24 | public double[] StageDesignators { get; } 25 | public MetafileColor[] ColorSpecifiers { get; } 26 | 27 | public override void Accept(ICommandVisitor visitor, T parameter) 28 | { 29 | visitor.AcceptAttributeInterpolatedInterior(this, parameter); 30 | } 31 | 32 | public static IReadOnlyDictionary KnownInteriorStyles { get; } = new ReadOnlyDictionary(new Dictionary 33 | { 34 | // interior styles originally part of ISO/IEC 8632:1999 35 | { 1, "Parallel" }, 36 | { 2, "Elliptical" }, 37 | { 3, "Triangular" }, 38 | }); 39 | public static string GetName(int index) 40 | { 41 | if (KnownInteriorStyles.TryGetValue(index, out string name)) 42 | return name; 43 | 44 | return "Reserved"; 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /Commands/Control/VdcRealPrecision.cs: -------------------------------------------------------------------------------- 1 | using CgmInfo.Commands.Enums; 2 | using CgmInfo.Traversal; 3 | 4 | namespace CgmInfo.Commands.MetafileDescriptor 5 | { 6 | [TextToken("VDCREALPREC")] 7 | public class VdcRealPrecision : Command 8 | { 9 | public VdcRealPrecision(RealRepresentation representationForm, int exponentWidth, int fractionWidth) 10 | : base(3, 2) 11 | { 12 | RepresentationForm = representationForm; 13 | ExponentWidth = exponentWidth; 14 | FractionWidth = fractionWidth; 15 | 16 | if (RepresentationForm == RealRepresentation.FloatingPoint) 17 | { 18 | if (ExponentWidth == 9 && FractionWidth == 23) 19 | Specification = RealPrecisionSpecification.FloatingPoint32Bit; 20 | else if (ExponentWidth == 12 && FractionWidth == 52) 21 | Specification = RealPrecisionSpecification.FloatingPoint64Bit; 22 | } 23 | else if (RepresentationForm == RealRepresentation.FixedPoint) 24 | { 25 | if (ExponentWidth == 16 && FractionWidth == 16) 26 | Specification = RealPrecisionSpecification.FixedPoint32Bit; 27 | else if (ExponentWidth == 32 && FractionWidth == 32) 28 | Specification = RealPrecisionSpecification.FixedPoint64Bit; 29 | } 30 | } 31 | 32 | public RealRepresentation RepresentationForm { get; } 33 | public int ExponentWidth { get; } 34 | public int FractionWidth { get; } 35 | public RealPrecisionSpecification Specification { get; } 36 | 37 | public override void Accept(ICommandVisitor visitor, T parameter) 38 | { 39 | visitor.AcceptControlVdcRealPrecision(this, parameter); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /CgmInfoGui/Services/IFileService.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using System.Threading.Tasks; 3 | using Avalonia.Platform.Storage; 4 | using CgmInfoGui.Views; 5 | 6 | namespace CgmInfoGui.Services; 7 | 8 | public interface IFileService 9 | { 10 | Task OpenFileAsync(string title, params (string Name, string Filter)[] filters); 11 | Task SaveFileAsync(string title, params (string Name, string Filter)[] filters); 12 | } 13 | internal sealed class FileService : IFileService 14 | { 15 | private readonly MainWindow _target; 16 | 17 | public FileService(MainWindow target) 18 | { 19 | _target = target; 20 | } 21 | 22 | public async Task OpenFileAsync(string title, params (string Name, string Filter)[] filters) 23 | { 24 | var files = await _target.StorageProvider.OpenFilePickerAsync(new() 25 | { 26 | AllowMultiple = false, 27 | FileTypeFilter = [.. filters.Select(f => new FilePickerFileType(f.Name) { Patterns = f.Filter.Split('|') })], 28 | Title = title, 29 | }); 30 | var pick = files?.FirstOrDefault(); 31 | if (pick is null) 32 | return null; 33 | 34 | return pick.TryGetLocalPath(); 35 | } 36 | public async Task SaveFileAsync(string title, params (string Name, string Filter)[] filters) 37 | { 38 | var pick = await _target.StorageProvider.SaveFilePickerAsync(new() 39 | { 40 | DefaultExtension = filters.FirstOrDefault().Filter, 41 | FileTypeChoices = [.. filters.Select(f => new FilePickerFileType(f.Name) { Patterns = f.Filter.Split('|') })], 42 | ShowOverwritePrompt = true, 43 | Title = title, 44 | }); 45 | if (pick is null) 46 | return null; 47 | 48 | return pick.TryGetLocalPath(); 49 | } 50 | } 51 | --------------------------------------------------------------------------------