private void FixupHeaderForWriting(BBeB book) { if (book.MetaData == null) { // TODO - This is just because we don't have any metadata yet Debug.WriteLineIf(s_bDebugMode, "Book has no metadata - Mocking some up for testing"); MemoryStream metaStream = new MemoryStream(); XmlSerializer xmlSerializer = new XmlSerializer(typeof(BookMetaData)); BookMetaData md = new BookMetaData(); xmlSerializer.Serialize(metaStream, md); metaStream.Seek(0, SeekOrigin.Begin); book.MetaData = md; //.Load(metaStream); } if (book.Header.wVersion >= 800) { if (book.ThumbnailData == null) { throw new InvalidBookException("Don't have a thumbnail image"); } book.Header.dwThumbSize = (uint)book.ThumbnailData.Length; } book.Header.NumberOfObjects = (ulong)book.Objects.Count; }
private void ConnectPageTree(BBeB book) { Debug.WriteLineIf(s_bDebugMode, "Connecting page tree"); PageTreeObject pageTree = (PageTreeObject)book.FindFirstObject(typeof(PageTreeObject)); if (pageTree == null) { throw new InvalidBookException("Couldn't find the required PageTree object"); } UInt32ArrayTag pageListTag = (UInt32ArrayTag)pageTree.FindFirstTag(TagId.PageList); if (pageListTag == null) { throw new InvalidBookException("Couldn't find the required PageList tag"); } foreach (uint id in pageListTag.Value) { PageObject page = (PageObject)book.FindObject((ushort)id); if (page == null) { throw new InvalidBookException("Can't find page id " + id); } pageTree.Pages.Add(page); } }
/// <summary> /// Resolve the object ID's that are used to specify references to /// the actual references. /// </summary> private void ConnectObjects(BBeB book) { Debug.WriteLineIf(s_bDebugMode, "Connecting objects"); ConnectPageTree(book); ConnectPages(book); ConnectBlocks(book); ConnectTexts(book); }
private void ConnectTexts(BBeB book) { foreach (BBeBObject obj in book.Objects) { if (obj.GetType() == typeof(TextObject)) { ConnectText((TextObject)obj, book); } } }
private void ConnectBlocks(BBeB book) { foreach (BBeBObject obj in book.Objects) { if (obj.GetType() == typeof(BlockObject)) { ConnectBlock((BlockObject)obj, book); } } }
private void ConnectPages(BBeB book) { foreach (BBeBObject obj in book.Objects) { if (obj.GetType() == typeof(PageObject)) { ConnectPage((PageObject)obj, book); } } }
private void ConnectPage(PageObject page, BBeB book) { Debug.WriteLineIf(s_bDebugMode, "Connecting page: " + page.ID); UInt32ArrayTag childIDs = (UInt32ArrayTag)page.FindFirstTag(TagId.PageObjectIds); if (childIDs != null) { foreach (uint id in childIDs.Value) { BBeBObject child = book.FindObject((ushort)id); if (child == null) { throw new InvalidBookException("Can't find object id " + id); } Debug.Assert(child.ID == id); Debug.WriteLineIf(s_bDebugMode, " Child: " + child.GetType().ToString() + " - id:" + child.ID); page.Children.Add(child); } } UInt32Tag objInfoTag = (UInt32Tag)page.FindFirstTag(TagId.ObjectInfoLink); if (objInfoTag != null) { page.InfoObj = book.FindObject((ushort)objInfoTag.Value); if (page.InfoObj == null) { throw new InvalidBookException("Can't find info object id " + objInfoTag.Value); } } StreamTagGroup stream = (StreamTagGroup)page.FindFirstTag(TagId.StreamGroup); if (stream != null) { BBeBObject tempObj = new BBeBObject(0x0); page.StreamTags = BBeBTagFactory.ParseAllTags(tempObj, stream.Data); } UInt32Tag linkTag = (UInt32Tag)page.FindFirstTag(TagId.Link); if (linkTag != null) { BBeBObject linkedObj = book.FindObject((ushort)linkTag.Value); if (linkedObj == null) { throw new InvalidBookException("Can't find object id " + linkTag.Value); } page.LinkObj = linkedObj; } }
public BBeB ParseHTML(HtmlDocument doc, BindingParams bindingParams, TocEntry tocEntries) { m_Book = new BBeB(); byte[] thumb = File.ReadAllBytes(bindingParams.IconFile); setHeaderValues(thumb.Length); m_Book.MetaData = bindingParams.MetaData; m_Book.ThumbnailData = thumb; // Create our default Attribute objects createDefaultAttributeObjects(BBeB.ReaderPageWidth, BBeB.ReaderPageHeight); // cover page works, but it's ugly createCoverPage(); m_CurrentPage = createPage(); PageObject firstBookPage = m_CurrentPage; m_StartReadingBlock = null; m_StartReadingPage = null; addBookPage(m_CurrentPage); IHTMLDocument2 dom = (IHTMLDocument2)doc.DomDocument; IHTMLDOMNode domNode = (IHTMLDOMNode)dom.body; IHTMLDOMChildrenCollection children = (IHTMLDOMChildrenCollection)domNode.childNodes; TextBlockBuilder tbBuilder = new TextBlockBuilder(GetNextObjId(), m_CharMapper); foreach (IHTMLDOMNode child in children) { tbBuilder = ParseDomNode(child, tbBuilder); } PrintHTMLElementChildren(children); // If we have any text left then add it FlushTextToBlock(m_CurrentPage, tbBuilder, m_MainBodyTextAttr); finalizePage(m_CurrentPage); // Create the table of contents createTocPage(firstBookPage, tocEntries); m_TocObject.AddEntry(m_StartReadingPage.ID, m_StartReadingBlock.ID, "Start Reading"); // Also serialize the table of contents object m_TocObject.Serialize(); finalizeBook(); return(m_Book); }
private void SerializeHeader(BBeB book, BBeBinaryWriter writer) { BBeBHeader header = book.Header; TocObject tocObject = (TocObject)book.FindObject((ushort)header.dwTocObjectId); if (tocObject == null) { throw new InvalidBookException("Can't find the TOC object"); } writer.Write(header.signature); writer.Write(header.wVersion); writer.Write(header.wPseudoEncByte); writer.Write(header.dwRootObjectId); writer.Write(header.NumberOfObjects); m_dwIndexOffsetVal = writer.Position; writer.Write(header.ObjectIndexOffset); writer.Write(header.dwUnknown1); writer.Write(header.byBindingDir); writer.Write(header.byPadding1); writer.Write(header.wDPI); writer.Write(header.wPadding2); writer.Write(header.wScreenWidth); writer.Write(header.wScreenHeight); writer.Write(header.byColorDepth); writer.Write(header.byPadding3); writer.Write(header.byUnkonwn2); writer.Write(header.dwTocObjectId); writer.WriteStreamOffsetReference(tocObject); // This may seem a little wasteful as we actually serialize the MetaData object twice // Once here and onces when we actualy write it to the stream, however we need to set // the compressed size in the header and we can only do it by compressing it first. // Really we should store the compressed byte stream and just save that out // but its not very big so the overhead is quite small { MemoryStream mem = new MemoryStream(); BinaryWriter sw = new BinaryWriter(mem); header.wDocInfoCompSize = (ushort)(SerializeMetaData(book.MetaData, sw) + 4); } writer.Write(header.wDocInfoCompSize); Debug.Assert(writer.Position == 0x4E); if (header.wVersion >= 800) { writer.Write(header.wThumbnailFlags); writer.Write(header.dwThumbSize); Debug.Assert(writer.Position == 0x54); } }
private void ConnectBlock(BlockObject block, BBeB book) { UInt32Tag linkTag = (UInt32Tag)block.FindFirstTag(TagId.Link); if (linkTag == null) { throw new InvalidBookException("Can't find link for block " + block.ID); } block.LinkObj = book.FindObject((ushort)linkTag.Value); if (block.LinkObj == null) { throw new InvalidBookException("Can't find object id " + linkTag.Value); } }
private void ConnectText(TextObject text, BBeB book) { UInt32Tag linkTag = (UInt32Tag)text.FindFirstTag(TagId.Link); if (linkTag == null) { throw new InvalidBookException("Can't find link for block " + text.ID); } BBeBObject LinkObj = book.FindObject((ushort)linkTag.Value); if (LinkObj == null) { throw new InvalidBookException("Can't find object id " + linkTag.Value); } }
public BBeB Deserialize(Stream bbebStream) { BinaryReader reader = new BinaryReader(bbebStream, Encoding.Unicode); BBeB book = new BBeB(); BBeBHeader header = DeserializeHeader(reader); header.Validate(); book.Header = header; book.MetaData = DeserializeMetaData(reader, header.wDocInfoCompSize); if (header.wVersion >= 800) { book.ThumbnailData = reader.ReadBytes((int)header.dwThumbSize); } // See http://www.sven.de/librie/Librie/LrfFormat for more information on this table. const ulong k_dwObjTableElementSize = 4 * sizeof(uint); ulong nTotalSize = 0; BBeBObjectFactory objFactory = new BBeBObjectFactory(); Debug.WriteLineIf(s_bDebugMode, "File contains " + header.NumberOfObjects + " objects"); for (ulong idxObj = 0; idxObj < header.NumberOfObjects; idxObj++) { reader.BaseStream.Seek((long)(header.ObjectIndexOffset + idxObj * k_dwObjTableElementSize), SeekOrigin.Begin); uint id = reader.ReadUInt32(); uint offset = reader.ReadUInt32(); uint size = reader.ReadUInt32(); nTotalSize += size; reader.BaseStream.Seek(offset, SeekOrigin.Begin); book.Objects.Add(objFactory.CreateObject(reader, id, size)); } Debug.WriteLineIf(s_bDebugMode, "Total size: " + nTotalSize); ConnectObjects(book); return(book); }
public bool SaveDocument(BindingParams bindingParameters, TocEntry tocEntries, BBeBLib.Serializer.CharacterMapper charMapper, HtmlDocument document) { bool ret = false; string filename = bindingParameters.MetaData.BookInfo.Author + " - " + bindingParameters.MetaData.BookInfo.Title; SaveFileDialog dialog = new SaveFileDialog(); dialog.FileName = filename; dialog.Filter = "BBeB/LRF Files (*.lrf)|*.lrf"; if (dialog.ShowDialog() == DialogResult.OK) { Host.Status("Converting...."); Application.DoEvents(); HTMLToBbebTransform transformer = new HTMLToBbebTransform(charMapper); BBeB book = transformer.ParseHTML(document, bindingParameters, tocEntries); Host.Status("Saving...."); Application.DoEvents(); // Save book now File.Delete(dialog.FileName); BBeBLib.Serializer.BBeBSerializer serializer = new BBeBLib.Serializer.BBeBSerializer(); FileStream newLrfStream = File.OpenWrite(dialog.FileName); try { serializer.Serialize(newLrfStream, book); } catch (Exception ex) { // TODO Need to get these strings from a resource for localization purposes string msg = string.Format("Couldn't save file {0}\n{1}", dialog.FileName, ex.ToString()); MessageBox.Show(msg, "Error saving file!", MessageBoxButtons.OK, MessageBoxIcon.Error); } finally { newLrfStream.Close(); } Host.Status("Finished."); } return(ret); }
/// <summary> /// Serialize the object to the supplied stream. /// </summary> /// <param name="stream">Write the serialized bytes of the book to this stream.</param> /// <param name="book">The book to serialize</param> public void Serialize(Stream stream, BBeB book) { m_dwIndexOffsetVal = 0; FixupHeaderForWriting(book); BBeBinaryWriter writer = new BBeBinaryWriter(stream); book.Header.Validate(); SerializeHeader(book, writer); SerializeMetaData(book.MetaData, writer); if (book.Header.wVersion >= 800) { writer.Write(book.ThumbnailData); } // Now go back and update the position of the object index now that we // know where its offset in the stream. long dwObjIdxStartOffset = writer.Position; writer.Position = m_dwIndexOffsetVal; writer.Write((ulong)dwObjIdxStartOffset); writer.Position = dwObjIdxStartOffset; // Write the object offset index table foreach (BBeBObject obj in book.Objects) { writer.Write((uint)obj.ID); writer.WriteStreamOffsetReference(obj); // Will be fixed up later writer.WriteStreamSizeReference(obj); // Will be fixed up later writer.Write((uint)0x0); // Unused and reserved } // Now write out all the objects foreach (BBeBObject obj in book.Objects) { SerializeObject(obj, writer); } writer.Flush(); writer.ResolveReferences(); }
public BBeBWriter(BBeB book) { this.book = book; writePages(); }
public HTMLWriter(BBeB book) : base(book) { }