using System; using System.Collections.Generic; using System.Text; using System.IO; using System.Collections; namespace FastReport.Export.BIFF8 { internal class BIFF8_MSODrawingRecord { Byte btWin32; Byte btMacOS; Byte[] uid; UInt16 tag; UInt32 size; UInt32 ref_count; UInt32 file_offset; Byte usage; Byte cbName; UInt16 picture_type; UInt16 blip_packed; // Byte[] UID0; Byte[] pic; Byte image_tag; ushort packed_options; internal void AddReference() { ref_count++; } internal void Read(StreamHelper stream, ushort packed_options) { btWin32 = (Byte)stream.ReadByte(); btMacOS = (Byte)stream.ReadByte(); uid = stream.ReadBytes(16); tag = stream.ReadUshort(); size = stream.ReadUint(); ref_count = stream.ReadUint(); file_offset = stream.ReadUint(); usage = (Byte)stream.ReadByte(); cbName = (Byte)stream.ReadByte(); stream.SkipBytes(2); this.packed_options = packed_options; } internal void Read_Picture(StreamHelper stream, UInt16 blip_packed, UInt16 type, int picture_size) { // picture_size = (int)blip_record_size - 17; Byte[] UID0; UID0 = stream.ReadBytes(16); //// Byte[] UID1 = ReadBytes(16); image_tag = (Byte)stream.ReadByte(); pic = stream.ReadBytes(picture_size); this.picture_type = type; this.blip_packed = blip_packed; //FileStream f = new FileStream(@"C:\Users\alman\Documents\pict.png", FileMode.Create); //f.Write(pic, 0, pic.Length); //f.Close(); } internal uint Write_Picture(StreamHelper stream) { uint payload_size = (uint)(uid.Length + 1 + pic.Length); stream.WriteUshort(this.blip_packed); // 0x6e00 stream.WriteUshort(this.picture_type); // PNG = 0xf01e stream.WriteUint(payload_size); stream.WriteBytes(uid); //// stream.WriteBytes(UID1); stream.WriteByte(image_tag); stream.WriteBytes(pic); //FileStream f = new FileStream(@"C:\Users\alman\Documents\pict.png", FileMode.Create); //f.Write(pic, 0, pic.Length); //f.Close(); return payload_size + 8; } internal void Write(StreamHelper stream) { stream.WriteUshort(packed_options); // 0x0052 stream.WriteUshort(0xf007); // BSE long bse_size_position = stream.Position; stream.WriteUint(0x0000); stream.WriteByte(btWin32); stream.WriteByte(btMacOS); stream.WriteBytes(uid); stream.WriteUshort(tag); stream.WriteUint(size); stream.WriteUint(ref_count); stream.WriteUint(file_offset); stream.WriteByte(usage); stream.WriteByte(cbName); stream.SkipBytes(2); uint blip_size = Write_Picture(stream); long current_position = stream.Position; blip_size += 36; stream.Position = bse_size_position; stream.WriteUint((UInt32)blip_size); stream.Position = current_position; } internal void LoadPicture(FastReport.Export.ExportIEMObject Obj, int index) { btWin32 = 6; // PNG btMacOS = 6; // PNG uid = new byte[16]; tag = 0xff; size = (uint)(8 + 16 + 1 + Obj.PictureStream.Length); ref_count = 1; file_offset = 0; usage = 0; cbName = 0; pic = new byte[Obj.PictureStream.Length]; Obj.PictureStream.Position = 0; Obj.PictureStream.Read(pic, 0, (int)Obj.PictureStream.Length); // Take midddle bytes as hash int idx = pic.Length / 2; for (int i = 0; i < 16; i++) uid[i] = pic[i + idx]; uid[0] = (byte)index; uid[15] = (byte)(index >> 4); picture_type = 0xf01e; blip_packed = 0x6e00; image_tag = 0xff; packed_options = 0x62; } } class BIFF8_MSODrawingGroup : ArrayList { UInt32 mso_spid; UInt32 cidcl; UInt32 cspSaved; UInt32 cdgSaved; ArrayList prop_list = new ArrayList(); UInt32 fillColor; UInt32 lineColor; UInt32 shadowColor; UInt32 threeDColor; private void Read_BstoreContainer(StreamHelper stream, UInt32 loop_record_size) { BIFF8_MSODrawingRecord local_record = new BIFF8_MSODrawingRecord(); while (loop_record_size > 0) { UInt16 blip_packed_data = stream.ReadUshort(); UInt16 blip_fbt = stream.ReadUshort(); UInt32 blip_record_size = stream.ReadUint(); // Get BLIP data switch (blip_fbt) { case 0xf007: // msofbtBSE local_record = new BIFF8_MSODrawingRecord(); local_record.Read(stream, blip_packed_data); this.Add(local_record); loop_record_size -= 36 /*blip_record_size*/; break; case 0xf01e: // PNG case 0xf01d: // JPEG local_record.Read_Picture(stream, blip_packed_data, blip_fbt, (int)blip_record_size - 17); loop_record_size -= blip_record_size; break; default: throw new Exception("BLIP not parsed yet"); } loop_record_size -= 8; //HEADER SIZE } } internal int Read(StreamHelper stream, int RecordSize) { long stored_position = stream.Position; UInt16 packed_data = stream.ReadUshort(); UInt16 fbt = stream.ReadUshort(); UInt32 total_record_size = stream.ReadUint(); RecordSize -= sizeof(UInt16) + sizeof(UInt16) + sizeof(UInt32); if (RecordSize > total_record_size) { throw new Exception("MSODRAWINGGROUP: Data layout error"); } if (RecordSize < total_record_size) { StreamHelper virtual_stream = new StreamHelper(); int tail = (int)total_record_size; do { byte[] record = stream.ReadBytes(RecordSize); virtual_stream.WriteBytes(record); //stream.Position += RecordSize; tail -= RecordSize; if (tail == 0) break; UInt16 RecordID = stream.ReadUshort(); if (RecordID != 0x0003c && RecordID != 0x000eb) // CONTINUE record { throw new Exception("MSODRAWINGGROUP: Data layout error"); } RecordSize = stream.ReadUshort(); } while (tail > 0); RecordSize = (int)(stream.Position - stored_position); stream = virtual_stream; stream.Position = 0; } else { RecordSize += sizeof(UInt16) + sizeof(UInt16) + sizeof(UInt32); } while (total_record_size > 0) { UInt16 dgg_packed_data = stream.ReadUshort(); UInt16 dgg_fbt = stream.ReadUshort(); UInt32 dgg_record_size = stream.ReadUint(); long shift = stream.Position - stored_position; switch (dgg_fbt) { case 0xf001: // msofbtBstoreContainer this.Read_BstoreContainer(stream, dgg_record_size); break; case 0xf006: // msofbtDgg mso_spid = stream.ReadUint(); cidcl = stream.ReadUint(); cspSaved = stream.ReadUint(); cdgSaved = stream.ReadUint(); for (int cid_idx = 1; cid_idx < cidcl; cid_idx++) { UInt32 dgid = stream.ReadUint(); UInt32 cspidCur = stream.ReadUint(); } break; case 0xf00b: // msofbtOPT UInt32 local_size = dgg_record_size; while (local_size > 0) { BIFF8_ShapeProp prop = new BIFF8_ShapeProp(); UInt32 prop_size = prop.ReadProperty(stream); prop_list.Add(prop); local_size -= prop_size; } foreach (BIFF8_ShapeProp prop in prop_list) { prop.ReadPayload(stream); } break; case 0xf11e: // msofbtSplitMenuColors fillColor = stream.ReadUint(); lineColor = stream.ReadUint(); shadowColor = stream.ReadUint(); threeDColor = stream.ReadUint(); break; default: stream.SkipBytes((int)dgg_record_size); break; } total_record_size -= 8 + dgg_record_size; } return RecordSize; } internal void Write(StreamHelper stream) { StreamHelper helper_stream = new StreamHelper(); this.mso_spid = 1026; this.cidcl = 2; this.cspSaved = 2; this.cdgSaved = (uint)this.Count; prop_list.Add(new BIFF8_ShapeProp(191, 0x00080008)); prop_list.Add(new BIFF8_ShapeProp(385, 0x08000041)); prop_list.Add(new BIFF8_ShapeProp(448, 0x08000040)); helper_stream.WriteUshort(0x000f); helper_stream.WriteUshort(0xf000); // msofbtDggContainer long dgg_container_size_position = helper_stream.Position; helper_stream.WriteUint(0); // fix me helper_stream.WriteUshort(0x0000); helper_stream.WriteUshort(0xf006); // msofbtDgg uint dgg_record_size = 16 + (cidcl - 1) * 8; helper_stream.WriteUint(dgg_record_size); // dgg_record_size helper_stream.WriteUint(mso_spid); helper_stream.WriteUint(cidcl); helper_stream.WriteUint(cspSaved); helper_stream.WriteUint(cdgSaved); for (int cid_idx = 1; cid_idx < cidcl; cid_idx++) { UInt32 dgid = 1; // fix me UInt32 cspidCur = 2; // fix me helper_stream.WriteUint(dgid); helper_stream.WriteUint(cspidCur); } helper_stream.WriteUshort((ushort)(0x000f | (this.Count << 4))); helper_stream.WriteUshort(0xf001); // msofbtBstoreContainer long bstore_size_position = helper_stream.Position; helper_stream.WriteUint(0x0000); foreach (BIFF8_MSODrawingRecord record in this) { record.Write(helper_stream); } long current_stream_position = helper_stream.Position; helper_stream.Position = bstore_size_position; bstore_size_position = current_stream_position - bstore_size_position - 4; helper_stream.WriteUint((uint)bstore_size_position); helper_stream.Position = current_stream_position; helper_stream.WriteUshort(0x0033); helper_stream.WriteUshort(0xf00b); // msofbtOPT long opt_size_position = helper_stream.Position; helper_stream.WriteUint(0x0000); foreach (BIFF8_ShapeProp prop in prop_list) prop.WriteProperty(helper_stream); foreach (BIFF8_ShapeProp prop in prop_list) prop.WritePayload(helper_stream); // Fix options size long curr_position = helper_stream.Position; helper_stream.Position = opt_size_position; opt_size_position = curr_position - opt_size_position - sizeof(UInt32); helper_stream.WriteUint((ushort)opt_size_position); helper_stream.Position = curr_position; // skip SplitMenuColors helper_stream.WriteUshort(0x0040); helper_stream.WriteUshort(0xf11e); // msofbtSplitMenuColors helper_stream.WriteUint(16); helper_stream.WriteUint(fillColor); helper_stream.WriteUint(lineColor); helper_stream.WriteUint(shadowColor); helper_stream.WriteUint(threeDColor); long last_byte_position = helper_stream.Position; helper_stream.Position = dgg_container_size_position; dgg_container_size_position = last_byte_position - dgg_container_size_position - 4; helper_stream.WriteUint((uint)dgg_container_size_position); helper_stream.Position = 0; // Split huge temporary stream into records int iteration_trick = 0; int tail_size = (int)helper_stream.Length; ushort chunk_size; while (tail_size > 0) { ushort item_type = (ushort)((iteration_trick < 2) ? 0x00eb : 0x003c); stream.WriteUshort(item_type); // MSODRAWINGGROUP : CONTINUE chunk_size = (ushort)((tail_size <= 8224) ? tail_size : 8224); stream.WriteUshort(chunk_size); byte[] pictures = helper_stream.ReadBytes(chunk_size); stream.WriteBytes(pictures); tail_size -= chunk_size; iteration_trick++; } helper_stream.Dispose(); helper_stream = null; } } }