public override void Save(Stream stream, CharacterDocument document) { var bw = new BinaryWriter(stream); var page = document.Pages[0]; var canvas = page.Canvas; int lasty = canvas.FindEndY(CanvasElement.Default); var xbh = new XBinHeader { Width = (ushort)canvas.Size.Width, Height = (ushort)(lasty + 1), Compress = EnableCompression, NonBlink = document.ICEColours }; if (page.Palette.Count == 16 && page.Palette != Palette.GetDosPalette()) { xbh.Palette = true; } xbh.Font = true; if (xbh.Font) { xbh.FontSize = (byte)page.Font.Size.Height; xbh.Font512 |= page.Font.NumChars > 256; } xbh.Write(bw); if (xbh.Palette) { page.Palette.Save(bw, 2); } if (xbh.Font) { page.Font.Save(bw); } if (xbh.Compress) { for (int y = 0; y <= lasty; y++) { WriteCompressedRow(canvas, y, bw); } } else { for (int y = 0; y <= lasty; y++) { for (int x = 0; x < canvas.Width; x++) { var ce = canvas[x, y]; bw.Write((byte)ce.Character); bw.Write((byte)ce.Attribute); } } } bw.Flush(); }
public override void Load(Stream fs, CharacterDocument document, CharacterHandler handler) { var page = document.Pages[0]; var br = new BinaryReader(fs); try { var header = new XBinHeader(br); if (header.XBinID != XBinHeader.XBIN_ID) { throw new FileLoadException("not a valid XBIN file"); } var loadSize = new Size(0, 0); var canvas = page.Canvas; document.ICEColours = header.NonBlink; ResizeCanvasWidth(fs, document, canvas, header); loadSize.Width = (document.EditMode && header.Width > canvas.Size.Width) ? canvas.Size.Width : header.Width; loadSize.Height = (document.EditMode && header.Height > canvas.Size.Height) ? canvas.Size.Height : header.Height; if (header.Palette) { page.Palette.Load(br, 16, 2); } if (header.Font) { var f = new BitFont(header.Font512 ? 512 : 256, 8, header.FontSize, BitFont.StandardCodePage); f.Load(br); #if DEBUG /* Used to save an XBIN font for use in PabloDraw * * Stream s = new FileStream("c:\\font.fnt", FileMode.Create); * BinaryWriter bw = new BinaryWriter(s); * f.Save(bw); * bw.Close(); * s.Close(); * /* */ #endif page.Font = f; } ResizeCanvasHeight(document, canvas, loadSize.Height); var ce = new CanvasElement(32, 7); var args = new WaitEventArgs(); if (header.Compress) { for (int y = 0; y < loadSize.Height; y++) { int x = 0; while (x < header.Width) { document.OnWait(args); if (args.Exit) { break; } int countbyte = br.ReadByte(); if (countbyte == -1) { break; } int runlength = (countbyte & 0x3F) + 1; switch ((CompressionType)(countbyte & 0xc0)) { case CompressionType.NoCompression: while (runlength > 0) { ce.Character = br.ReadByte(); ce.Attribute = br.ReadByte(); if (x < canvas.Size.Width) { canvas[x, y] = ce; } x++; runlength--; } break; case CompressionType.Character: ce.Character = br.ReadByte(); while (runlength > 0) { ce.Attribute = br.ReadByte(); if (x < canvas.Size.Width) { canvas[x, y] = ce; } x++; runlength--; } break; case CompressionType.Attribute: ce.Attribute = br.ReadByte(); while (runlength > 0) { ce.Character = br.ReadByte(); if (x < canvas.Size.Width) { canvas[x, y] = ce; } x++; runlength--; } break; case CompressionType.Both: ce.Character = br.ReadByte(); ce.Attribute = br.ReadByte(); while (runlength > 0) { if (x < canvas.Size.Width) { canvas[x, y] = ce; } x++; runlength--; } break; } } } } else { for (int y = 0; y < loadSize.Height; y++) { for (int x = 0; x < header.Width; x++) { document.OnWait(args); if (args.Exit) { break; } ce.Character = br.ReadByte(); ce.Attribute = br.ReadByte(); if (x < canvas.Size.Width) { canvas[x, y] = ce; } } } } } catch (EndOfStreamException) { // reached end of file, so we're okay } }