private List <ShxGlyphCommand> ParseCommands(byte[] data, ShxFontEncoding encoding = ShxFontEncoding.Unicode) { var reader = new ByteReader(data); var commands = ShxGlyph.ParseCommands(reader, encoding, isBigFont: false); return(commands); }
private ShxGlyphCommand ParseCommand(byte[] data, ShxFontEncoding encoding = ShxFontEncoding.Unicode) { var commands = ParseCommands(data, encoding); return(commands.Single()); }
internal static List <ShxGlyphCommand> ParseCommands(ByteReader reader, ShxFontEncoding fontEncoding, bool isBigFont) { var commands = new List <ShxGlyphCommand>(); while (reader.TryReadByte(out var command) && command != 0) { var distance = (command & 0xF0) >> 4; var direction = command & 0x0F; var isBareCommand = distance == 0; if (isBareCommand) { // special command handling for no movement switch (command) { case 1: // pen down commands.Add(new ShxGlyphCommandPenDown()); break; case 2: // pen up commands.Add(new ShxGlyphCommandPenUp()); break; case 3: // divide scaling vector by specified value if (reader.TryReadByte(out var divr)) { commands.Add(new ShxGlyphCommandUpdateScaleVector(1.0 / divr)); } break; case 4: // multiply scaling vector by specified value if (reader.TryReadByte(out var mulr)) { commands.Add(new ShxGlyphCommandUpdateScaleVector(mulr));; } break; case 5: // push location commands.Add(new ShxGlyphCommandPushPoint()); break; case 6: // pop location commands.Add(new ShxGlyphCommandPopPoint()); break; case 7: { if (isBigFont) { // https://help.autodesk.com/view/ACD/2020/ENU/?guid=GUID-00ED0CC6-A4BE-4591-93FA-598CC40AA43D if (reader.TryReadByte(out var replayCode)) { if (replayCode == 0 && reader.TryReadSByte(out var xoffset) && reader.TryReadSByte(out var yoffset) && reader.TryReadByte(out var width) && reader.TryReadByte(out var height)) { commands.Add(new ShxGlyphCommandReplayCharacter(replayCode, xoffset, yoffset, width, height)); } } else { // sometimes it's not zero? reader.TryReadByte(out var lowerByte); var fullCode = (ushort)((replayCode << 8) | lowerByte); commands.Add(new ShxGlyphCommandReplayCharacter(fullCode)); } } else { // replay the given character code if (fontEncoding == ShxFontEncoding.Unicode) { if (reader.TryReadUInt16BigEndian(out var replayCode)) { commands.Add(new ShxGlyphCommandReplayCharacter(replayCode)); } } else { if (reader.TryReadByte(out var replayCode)) { commands.Add(new ShxGlyphCommandReplayCharacter(replayCode)); } } } } break; case 8: { // move x, y if (reader.TryReadSByte(out var xOffset) && reader.TryReadSByte(out var yOffset)) { commands.Add(new ShxGlyphCommandMoveCursor(xOffset, yOffset)); } } break; case 9: { // move x, y until 0, 0 while (reader.TryReadSByte(out var xOffset) && reader.TryReadSByte(out var yOffset)) { if (xOffset == 0.0 && yOffset == 0.0) { // done break; } commands.Add(new ShxGlyphCommandMoveCursor(xOffset, yOffset)); } } break; case 0xA: { // octant arc if (reader.TryReadByte(out var radius) && reader.TryReadByte(out var sc)) { var isCounterClockwise = (sc & 0b10000000) == 0; var startingOctant = (sc & 0b01110000) >> 4; var octantCount = sc & 0b00000111; commands.Add(new ShxGlyphCommandOctantArc(radius, startingOctant, octantCount, isCounterClockwise)); } } break; case 0xB: { // fractional arc if (reader.TryReadByte(out var startOffset) && reader.TryReadByte(out var endOffset) && reader.TryReadByte(out var highRadius) && reader.TryReadByte(out var radius) && reader.TryReadByte(out var sc)) { var isCounterClockwise = (sc & 0b10000000) == 0; var startingOctant = (sc & 0b01110000) >> 4; var octantCount = sc & 0b00000111; commands.Add(new ShxGlyphCommandFractionalArc(startOffset, endOffset, highRadius, radius, startingOctant, octantCount, isCounterClockwise)); } } break; case 0xC: { // arc if (reader.TryReadSByte(out var xDisplacement) && reader.TryReadSByte(out var yDisplacement) && reader.TryReadSByte(out var bulge)) { commands.Add(new ShxGlyphCommandArc(xDisplacement, yDisplacement, bulge)); } } break; case 0xD: { // continuous arcs while (reader.TryReadSByte(out var xDisplacement) && reader.TryReadSByte(out var yDisplacement)) { if (xDisplacement == 0 && yDisplacement == 0) { break; } if (reader.TryReadSByte(out var bulge)) { commands.Add(new ShxGlyphCommandArc(xDisplacement, yDisplacement, bulge)); } } } break; case 0xE: // skip next command if in horizontal mode commands.Add(new ShxGlyphCommandSkipNextIfHorizontal()); break; case 0xF: // TODO: unknown/unsupported break; case 0: // shouldn't happen break; default: break; } } else { var vector = DirectionVectors[direction]; var delta = vector * distance; commands.Add(new ShxGlyphCommandMoveCursor(delta.X, delta.Y)); } } return(commands); }