// TODO: consider making it public
        void LoadPdf(String filename)
        {
            try 
            {
                _pdfDoc = DW.Wrap(new PDFWrapper());

                //_pdfDoc.PDFLoadCompeted += new PDFLoadCompletedHandler(_pdfDoc_PDFLoadCompeted);
                //_pdfDoc.PDFLoadBegin += new PDFLoadBeginHandler(_pdfDoc_PDFLoadBegin);
                //_pdfDoc.UseMuPDF = true;

                LoadFile(filename, _pdfDoc);
            }
            catch (System.IO.IOException ex)
            {
                MessageBox.Show(ex.Message, "IOException");
            }
            catch (System.Security.SecurityException ex)
            {
                MessageBox.Show(ex.Message, "SecurityException");
            }
            catch (System.IO.InvalidDataException ex)
            {
                MessageBox.Show(ex.Message, "InvalidDataException");
            }

            // New doc requires new performance info
            PerfInfo = new PdfRenderPerformanceInfo();
        }
示例#2
0
        public void Initialize(BookLibrary library)
        {
            ArgCheck.NotNull(library, "library");
            _library = library;

            _renderManager = DW.Wrap(new ScreenRenderManager(_library, pbContent.Size));
            _renderManager.o.PaperColorChanged += new EventHandler(o_PaperColorChanged);
        }
示例#3
0
 // Token: 0x060000D8 RID: 216 RVA: 0x0000E278 File Offset: 0x0000C478
 public void \u0002(DW \u0002)
 {
     if (\u0002 == this.\u0006)
     {
         return;
     }
     if (\u0002 != null)
     {
         throw new ArgumentException(global::\u0006\u2001.\u0002(-1829139669));
     }
     this.\u0003 <DW>(ref this.\u0006);
 }
        public PrefetchManager(DW<PageImageCache> cache, 
            IPageCacheContextManager contextManager)
        {
            ArgCheck.NotNull(cache, "cache");
            ArgCheck.NotNull(contextManager, "contextManager");

            Cache = cache;
            ContextManager = contextManager;

            ContextManager.CacheContextChanged += OnCacheContextChanged;

            Policy = RenderFactory.Default.GetPrefetchPolicy();
        }
示例#5
0
 public override int GetHashCode()
 {
     unchecked
     {
         int result = base.GetHashCode();
         result = (result * 397) ^ (W != null ? W.GetHashCode() : 0);
         result = (result * 397) ^ (PW != null ? PW.GetHashCode() : 0);
         result = (result * 397) ^ (DW != null ? DW.GetHashCode() : 0);
         result = (result * 397) ^ ReturnBody.GetHashCode();
         result = (result * 397) ^ Context.GetHashCode();
         result = (result * 397) ^ IncludeContext.GetHashCode();
         return(result);
     }
 }
示例#6
0
        /// <summary>
        /// 获取MB
        /// </summary>
        /// <param name="length">字节</param>
        /// <returns></returns>
        public static decimal GetFileLength(long length, DW dw)
        {
            double res  = length * 1.0;
            int    size = (int)dw;
            long   _dw  = 1;

            for (int i = 0; i < size; i++)
            {
                _dw = _dw * 1024;
            }
            decimal fileLlength = (decimal)res / _dw;

            return(RoundHelper.Round(fileLlength, 2));
        }
示例#7
0
        /// <summary>
        /// 获取KB
        /// </summary>
        /// <param name="length">字节</param>
        /// <returns></returns>
        public static decimal GetFileLength(decimal length, DW dw)
        {
            int  size = (int)dw;
            long _dw  = 1;

            for (int i = 0; i < size; i++)
            {
                _dw = _dw * 1024;
            }

            decimal fileLlength = length / _dw;

            return(RoundHelper.Round(fileLlength, 2));
        }
示例#8
0
        public TestCaseStatus Show(TestCaseStatus initStatus, LayoutTestCase tcase, DW<Bitmap> bitmap)
        {
            lbFilename.Text = Path.GetFileName(tcase.Filename);
            lbPageNum.Text = tcase.PageNum.ToString();
            Comment = tcase.Comment;

            pbPage.Image = bitmap.o;
            Status = initStatus;

            ShowDialog();

            tcase.Comment = Comment;

            return Status;
        }
示例#9
0
        public static void Days()
        {
            int num;

            bool flag = true;

            while (flag)
            {
                Console.WriteLine("Введите день недели:");
                string  input = Console.ReadLine();
                DayWeek DW;

                if (Int32.TryParse(input, out num))
                {
                    num  = int.Parse(input);
                    flag = false;
                }
                else
                {
                    Console.WriteLine("Некорректный ввод!");
                }

                DW = (DayWeek)num;

                if (num == 1)
                {
                    Console.WriteLine(DW.ToString() + " - Начало рабочей недели");
                }
                else if (((num == 2) || (num == 3) || (num == 4)))
                {
                    Console.WriteLine(DW.ToString() + " - Середина рабочей недели");
                }
                else if ((num == 5))
                {
                    Console.WriteLine(DW.ToString() + " - Конец рабочей недели");
                }
                else if ((num == 6) || (num == 7))
                {
                    Console.WriteLine(DW.ToString() + " - Выходной день");
                }
                else
                {
                    Console.WriteLine("Пожалуйста, введите значение от 1 до 7");
                    flag = true;
                    continue;
                }
            }
        }
示例#10
0
        protected override void calcDeepWounds()
        {
            // Main Hand
            float mhActivates =
                /*Yellow  */ CriticalYellowsOverDurMH +
                /*White   */ WhiteAtks.MhActivates * (1f - timeLostPerc) * WhiteAtks.MHAtkTable.Crit;

            // Off Hand
            float ohActivates = (CombatFactors.useOH ?
                                 // No OnAttacks for OH
                                 /*Yellow*/ CriticalYellowsOverDurOH +
                                 /*White */ WhiteAtks.OhActivates * (1f - timeLostPerc) * WhiteAtks.OHAtkTable.Crit
                : 0f);

            // Push to the Ability
            DW.SetAllAbilityActivates(mhActivates, ohActivates);
        }
示例#11
0
        public BookContent(Book book, DW<PageImageCache> imageCache = null)
        {
            ArgCheck.NotNull(book, "book");
            _book = book;

            // null is ok
            ImageCache = imageCache;

            // Load layouts 
            Layouts = new Dictionary<int, PageLayout>();
            if (Settings.Default.Cache_SaveLayouts)
            {
                Layouts = XmlHelper.DeserializeOrDefault(LayoutsFile, Layouts);
            }

            _layoutStrategy = RenderFactory.Default.GetLayoutStrategy();

            // Slightly hacky but best way to do it
            // -- set the book position info if it's null
            if (Book.CurrentPosition == null)
            {
                Book.CurrentPosition = PositionInBook.FromPhysicalPage(1, BookProvider.o.PageCount);
            }
        }
示例#12
0
        static void Main(string[] args)
        {
            List <string> ProKeys = new List <string>()
            {
                "hd7", "s6d", "s7u"
            };
            List <string> ExpKeys = new List <string>()
            {
                "8jd", "s8j", "pso"
            };

            Console.WriteLine("Введите ключ");
            string         o;
            DocumentWorker DW;

            o = Console.ReadLine();
            if (ProKeys.Contains(o))
            {
                DW = new ProDocumentWorker();
                Console.WriteLine("Вы ввели ключ Pro");
            }
            else if (ExpKeys.Contains(o))
            {
                DW = new ExpertDocumentWorker();
                Console.WriteLine("Вы ввели ключ Exp");
            }
            else
            {
                DW = new DocumentWorker();
                Console.WriteLine("Ключ не правильный");
            }
            DW.OpenDocument();
            DW.EditDocument();
            DW.SaveDocument();
            Console.ReadKey();
        }
示例#13
0
        public DW<Bitmap> Debug_DrawLayout(DW<Bitmap> originalBitmap = null)
        {
            DW<Bitmap> bmp = DW.Wrap(new Bitmap(PageSize.Width, PageSize.Height, PixelFormat.Format24bppRgb));
            if (IsEmpty) { return bmp; }

            using (Graphics g = Graphics.FromImage(bmp.o))
            {
                if (originalBitmap != null)
                {
                    g.DrawImageUnscaled(originalBitmap.o, 0, 0);
                }

                Debug_DrawLayout(g, PageSize);

                // Content bounds (most important)
                g.FillRectangle(_backShadeBrush, 0, 0, Bounds.Left, PageSize.Height);
                g.FillRectangle(_backShadeBrush, Bounds.Right, 0, PageSize.Width - Bounds.Right, PageSize.Height);
                g.FillRectangle(_backShadeBrush, Bounds.Left, 0, Bounds.Width, Bounds.Top);
                g.FillRectangle(_backShadeBrush, Bounds.Left, Bounds.Bottom, Bounds.Width, PageSize.Height - Bounds.Bottom);

                Debug_DrawLayout(g, PageSize);
            }
            return bmp;
        }
示例#14
0
        // Ultimately need a different opener for providing R<T> vs Rm<T>
        private NewResourceChain <DW <Node> > SimpleRootCase <T>(OfResourceBank.DResourceSourceDefinition <T> resourceSourceDefinition, bool isForMinor)
        {
            object lockThisChain = new string[] { "" };
            // var calculatedObjectSlots = new LifetimeBase<ObjectSlot>();
            var objectSlot = new ObjectSlot();



            Func <OfResourceBank.IdentityAndDraw <T> > currentGetIdentityAndGetDraw_thisMutatesAndIsClosedOver = null;

            OfResourceBank.IdentityAndDraw <T> currentIdentityAndGetDraw_thisMutatesAndIsClosedOver = null;



            Dictionary <Guid, ObjectSlot> perSurvivor = new Dictionary <Guid, ObjectSlot>();

            var resourceChainID = AllocateResourceChainIDTakingMasterLock();


            Func <ObjectSlot, Action> addAndGetKillAssumesLock =
                value =>
            {
                // current implementation capturing *this*
                var insertID = Guid.NewGuid();
                // lock (theLock)
                {
                    perSurvivor.Add(insertID, value);
                    return
                        (() =>                         // this is the returned 'kill' funciton - it takes its own lock.
                    {
                        bool removeWholeChain = false; // okay to fill this in lock because once true, it's all over anyway
                        lock (lockThisChain)
                        {
                            perSurvivor.Remove(insertID);
                            if (!perSurvivor.Any())
                            {
                                removeWholeChain = true;
                            }
                        }
                        if (removeWholeChain)
                        {
                            lock (MasterLock)
                            {
                                ChainIDToPerChain.Remove(resourceChainID);
                            }
                        }
                    });
                }
            };


            Action wipeAssumingHaveChainLock =
                () =>
            {
                foreach (var e in perSurvivor.Values)
                {
                    e.PossibleObjectAndChildRefsStillOwedValue = None <ObjectPresent>();
                }
            };

            currentGetIdentityAndGetDraw_thisMutatesAndIsClosedOver =
                resourceSourceDefinition(
                    replacement =>
            {
                lock (lockThisChain)
                {
                    currentGetIdentityAndGetDraw_thisMutatesAndIsClosedOver = replacement;
                    currentIdentityAndGetDraw_thisMutatesAndIsClosedOver    = currentGetIdentityAndGetDraw_thisMutatesAndIsClosedOver();
                    wipeAssumingHaveChainLock();
                }
            });

            // give it an initial value
            currentIdentityAndGetDraw_thisMutatesAndIsClosedOver = currentGetIdentityAndGetDraw_thisMutatesAndIsClosedOver();


            var rootNode = new DW <Node>(
                new Node(
                    new NodeCommon(
                        lockThisChain,
                        addAndGetKillAssumesLock,
                        () => // in chain lock
            {
                var newIdentityAndDraw = currentGetIdentityAndGetDraw_thisMutatesAndIsClosedOver();
                if (currentIdentityAndGetDraw_thisMutatesAndIsClosedOver.Identity.Equals(newIdentityAndDraw.Identity))
                {
                    // no identity change - don't wipe
                }
                else
                {
                    currentIdentityAndGetDraw_thisMutatesAndIsClosedOver = newIdentityAndDraw;
                    // wipe them all
                    wipeAssumingHaveChainLock();
                }
            }),
                    objectSlot,
                    () => currentIdentityAndGetDraw_thisMutatesAndIsClosedOver.Draw(),
                    isForMinor,
                    None <DAlterTotalMajorCountToParent>()),
                addAndGetKillAssumesLock(objectSlot));

            lock (MasterLock) // never take locks in reverse
            {
                ChainIDToPerChain.Add(
                    resourceChainID,
                    new PerResourceChain(
                        () =>
                {
                    lock (lockThisChain)
                    {
                        foreach (var e in perSurvivor.Values)
                        {
                            e.PossibleObjectAndChildRefsStillOwedValue = None <ObjectPresent>();
                        }
                    }
                }));
            }
            return
                (new NewResourceChain <DW <Node> >(
                     rootNode,
                     () =>
            {
                lock (lockThisChain)
                {
                    wipeAssumingHaveChainLock();
                }
            }));
        }
示例#15
0
 public ContentsMinor(DW <Node> node)
 {
     mNode = node;
 }
示例#16
0
 public Contents(DW <Node> node)
 {
     mNode = node;
 }
示例#17
0
        // important - building sub need to keep its value-generating ability alive
        private static DW <Node> BuildSubNode(DW <Node> parent, Func <object, object> f, bool isForMinor) // don't need thread to do this, only lock when GetKill is called as matter of course
        {
            var subsObjectSlot = new ObjectSlot();
            var nodeCommon     = parent.Value.NodeCommon;

            var myGuidRelativeToParent = Guid.NewGuid();
            var underlyingKill         =
                Func(
                    () =>
            {
                lock (nodeCommon.LockThisChain)
                {
                    // A prior revision had this lock-assuming call outside the lock, a probable/obvious cause of symptom A.H. found in a 3/2017 bulk test.
                    var returnedUnderlyingKill = nodeCommon.GetKillForNewSlotAssumesLock(subsObjectSlot);


                    // add childrefs to parent
                    if (isForMinor)
                    {
                        parent.Value.MinorChildReferencesBackToThis = parent.Value.MinorChildReferencesBackToThis.Add(myGuidRelativeToParent);
                    }
                    else
                    {
                        parent.Value.MajorChildReferencesBackToThis = parent.Value.MajorChildReferencesBackToThis.Add(myGuidRelativeToParent);
                    }

                    var originalObjectSlot = parent.Value.ObjectSlot;
                    if (originalObjectSlot.PossibleObjectAndChildRefsStillOwedValue.HasValue)
                    {
                        var ot = originalObjectSlot.PossibleObjectAndChildRefsStillOwedValue.Value;
                        originalObjectSlot.PossibleObjectAndChildRefsStillOwedValue = Some(new ObjectPresent(ot.Obj, isForMinor ? ot.MajorsStillOwedValue : ot.MajorsStillOwedValue.Add(myGuidRelativeToParent), isForMinor ? ot.MinorsStillOwedValue.Add(myGuidRelativeToParent) : ot.MinorsStillOwedValue));
                    }
                    if (!isForMinor)
                    {
                        AlterTotalMajorsHereandDown(myGuidRelativeToParent, parent.Value, x => x + 1);
                    }

                    return(returnedUnderlyingKill);
                }
            })();

            Action decrefParentAssumingLock =
                () =>
            {
                var parentObjectSlot = parent.Value.ObjectSlot;
                if (parentObjectSlot.PossibleObjectAndChildRefsStillOwedValue.HasValue)
                {
                    var ot = parentObjectSlot.PossibleObjectAndChildRefsStillOwedValue.Value;
                    parentObjectSlot.PossibleObjectAndChildRefsStillOwedValue = Some(new ObjectPresent(ot.Obj, isForMinor ? ot.MajorsStillOwedValue : ot.MajorsStillOwedValue.Remove(myGuidRelativeToParent), isForMinor ? ot.MinorsStillOwedValue.Remove(myGuidRelativeToParent) : ot.MinorsStillOwedValue));

                    // Here is where we'd compare the 'stillOwedValue' to 0, and, if the Node is for a minor/not needed for its own sake, obliterate its own cached value.
                    // Remember, originalObjectSlot refers to the parent - have we refcounted it down to zero?

                    // Here's the real trick - if none in the ChildRefToMajorCountItRepresents are represented in either of the pathway arrays, this means
                    // noone under you, who is or has a major, is owed anything.

                    var op = parentObjectSlot.PossibleObjectAndChildRefsStillOwedValue.Value;
                    if (parent.Value.IsForMinor
                        &&
                        (!op.MajorsStillOwedValue.Any(parent.Value.ChildRefToMajorCountItRepresents.ContainsKey))
                        &&
                        (!op.MinorsStillOwedValue.Any(parent.Value.ChildRefToMajorCountItRepresents.ContainsKey)))
                    {
                        parentObjectSlot.PossibleObjectAndChildRefsStillOwedValue = None <ObjectPresent>();
                    }
                }
            };

            return
                (new DW <Node>(
                     new Node(
                         nodeCommon,
                         subsObjectSlot,
                         () =>
            {
                var backsValue = parent.Value.GetValueHereAssumingAlreadyLocked();
                // This *should* have forced it to exist.
                decrefParentAssumingLock(); // we took our view of it.
                return f(backsValue);
            }                               // the capture of original and its DW here is *crucial*
                         , isForMinor,
                         Some(new DAlterTotalMajorCountToParent(ff => AlterTotalMajorsHereandDown(myGuidRelativeToParent, parent.Value, ff)))),
                     () =>
            {
                lock (nodeCommon.LockThisChain)
                {
                    // Remove childrefs from parent - we're done
                    if (isForMinor)
                    {
                        parent.Value.MinorChildReferencesBackToThis = parent.Value.MinorChildReferencesBackToThis.Remove(myGuidRelativeToParent);
                    }
                    else
                    {
                        parent.Value.MajorChildReferencesBackToThis = parent.Value.MajorChildReferencesBackToThis.Remove(myGuidRelativeToParent);
                    }

                    // Going away - if not a minor, deduct from parent and any under's count of how many majors are interested
                    if (!isForMinor)
                    {
                        AlterTotalMajorsHereandDown(myGuidRelativeToParent, parent.Value, x => x - 1);
                    }
                    // Important to change majors count first in that decrefParent will have the parent assess if anyone cares about its value

                    decrefParentAssumingLock();


                    underlyingKill();
                }
            }));
        }
        PageLayout DetectLayout(DW<PDFWrapper> doc, PDFPage page)
        {
            Size pageSize = new Size(doc.o.PageWidth, doc.o.PageHeight);
            PageLayout layout = new PageLayout(pageSize);

            // Get text
            // TODO: check how text is split in multicolumn case -- is this the method with correct options (flow, not physical)
            layout.Text = page.Text;

            var words = new List<LayoutElement>();
            var nonEmptyWords = page.WordList
                .Where(x => !x.Bounds.IsEmpty && !x.Word.IsEmpty())
                .Select(x => LayoutElement.NewWord(pageSize, x.Bounds, x.Word));

            words.AddRange(nonEmptyWords);

            // Detect rows and columns
            var rows = words.Split(StartsNewRow).Select(ws => LayoutElement.NewRow(ws, LayoutElementType.Row));
            var cols = rows.Split(StartsNewColumn).Select(rs => LayoutElement.NewRow(rs, LayoutElementType.Column));

            // TODO: detect header/footer
            layout.Children.AddRange(cols);

            // Strange bug -- if doing the following, first word is missing and last word is blank.
            // However, with LINQ query above it's fine

            //List<PDFTextWord> ws = new List<PDFTextWord>();
            //ws.AddRange(page.WordList);

            if (layout.Children.Count > 0)
            {
                layout.SetBoundsFromNodes(true);

                /*
                // expand by width a bit (to prevent cutting off words which
                // may not be recognized properly.
                int expandWidth = (0.05 * layout.Bounds.Width).Round();

                RectangleF expBounds = layout.UnitBounds;
                expBounds.X -= expandWidth / 2;
                expBounds.Width += expandWidth;

                if (expBounds.X <= 1 && expBounds.Width <= 1)
                {
                    layout.UnitBounds = expBounds;
                }
                 */
            }

            // error checking
            if (layout.Bounds.X < 0 || layout.Bounds.Y < 0 ||
                layout.Bounds.Width <= 0 || layout.Bounds.Height <= 0)
            {
                logger.Error("Wrong bounds: " + layout.Bounds + " images: " + page.ImagesCount);

                float height = page.ImagesCount > 0 ? 1 : 0.1f;

                layout.UnitBounds = new RectangleF(0,0, 1, height);
            }

            // TODO: detect rows

            // TODO: detect header/footer (if any)

            return layout;
        }
示例#19
0
 private void bPrevPage_Click(object sender, EventArgs e)
 {
     CurrentScreenImage = _renderManager.o.RenderPrevious();            
 }
示例#20
0
 public override DW<IBookContent> NewBookContent(Book book, DW<PageImageCache> cache)
 {
     throw new NotImplementedException();
 }
示例#21
0
 public abstract DW<IBookContent> NewBookContent(Book book, DW<PageImageCache> cache = null);
示例#22
0
 private void bNextPage_Click(object sender, EventArgs e)
 {
     CurrentScreenImage = _renderManager.o.RenderNext();
 }
示例#23
0
 public AssembleScreenAlgorithm(DW<IBookContent> bookContent)
 {
     BookContent = bookContent;
 }
示例#24
0
 public AssemblePreviousScreenAlgorithm(DW<IBookContent> p) 
     : base(p) { }
示例#25
0
 public AssembleNextScreenAlgorithm(DW<IBookContent> p)
     : base(p) 
 {
     _assembleCurrent = new AssembleCurrentScreenAlgorithm(p);
 }
示例#26
0
 public AssembleCurrentScreenAlgorithm(DW<IBookContent> p) 
     : base(p) { }
 public override DW<IBookContent> NewBookContent(Book book, DW<PageImageCache> cache)
 {
     return BookContent;
 }
示例#28
0
 public override DW<IBookContent> NewBookContent(Book book, DW<PageImageCache> cache)
 {
     return DW.Wrap<IBookContent>(new BookContent(book, cache));
 }
 void DisposePdfDoc()
 {
     if (_pdfDoc != null)
     {
         _pdfDoc.DisposeItem();
         _pdfDoc = null;
     }
 }
示例#30
0
 public void Dispose()
 {
     if (_bookProvider != null)
     {
         _bookProvider.DisposeItem();
     }
     if (Layouts != null)
     {
         Layouts.Clear();
         Layouts = null;
     }
     if (ImageCache != null)
     {
         // Do not dispose, we don't own it
         ImageCache = null;
     }
 }
        static bool LoadFile(string filename, DW<PDFWrapper> pdfDoc)
        {
            try
            {
                // Not supported by MuPDF: 
                // pdfDoc.LoadPDF(fileStream);

                bool loaded = pdfDoc.o.LoadPDF(filename);
                return loaded;
            }
            catch (System.Security.SecurityException)
            {
                throw new NotImplementedException("UI for password-protected PDF not implemented");
                /*
                PDFViewer.frmPassword frm = new PDFViewer.frmPassword();
                if (frm.ShowDialog() == DialogResult.OK)
                {
                    if (!frm.UserPassword.Equals(String.Empty))
                    {
                        pdfDoc.UserPassword = frm.UserPassword;
                    }
                    if (!frm.OwnerPassword.Equals(String.Empty))
                    {
                        pdfDoc.OwnerPassword = frm.OwnerPassword;
                    }
                    return LoadFile(filename, pdfDoc);
                }
                else
                {
                    // TODO: better error message
                    MessageBox.Show(Resources.UIStrings.ErrorFileEncrypted, filename);
                    return false;
                }
                 */

           }
        }
示例#32
0
        private void timerDelayedRender_Tick(object sender, EventArgs e)
        {
            timerResize.Stop();
            if (Book == null) { return; }

            _renderManager.o.ScreenSize = pbContent.Size;
            CurrentScreenImage = _renderManager.o.Render();
        }
        public void Create(LayoutTestCase tcase)
        {
            if (_haltTests) { Assert.Ignore("Halt tests"); }

            if (_bookContent == null || _bookContent.o.Book.Filename != tcase.Filename)
            {
                if (_bookContent != null) 
                {
                    _bookContent.DisposeItem();
                    _bookContent = null;
                }

                Book book = new Book(tcase.Filename);
                _bookContent = DW.Wrap<IBookContent>(new BookContent(book, null));
            }

            IPageLayoutStrategy alg = new PdfWordsLayoutStrategy();
            PageLayout layout = alg.DetectLayoutFromBook(_bookContent.o, tcase.PageNum);
            layout.SetPageSizeToScreen(600);

            // Get staus based on the layout
            TestCaseStatus status = tcase.GetStatus(layout);
            
            // Skip pages that pass the test
            if (status == TestCaseStatus.Pass_Good ||
                status == TestCaseStatus.Pass_Acceptable) 
            { 
                return; 
            }

            DW<Bitmap> page = DW.Wrap(_bookContent.o.BookProvider.o.RenderPageImage(tcase.PageNum, layout.PageSize));
            DW<Bitmap> newPage = layout.Debug_DrawLayout(page);

            TestCaseStatus newStatus = _form.Show(status, tcase, newPage);

            page.DisposeItem();
            newPage.DisposeItem();

            if (newStatus == TestCaseStatus.HaltTest)
            {
                _haltTests = true;
                Assert.Ignore("Halt tests");                
            }

            // Update test case object
            tcase.Comment = _form.Comment;

            if (newStatus == TestCaseStatus.Pass_Acceptable ||
                newStatus == TestCaseStatus.Pass_Good)
            {
                tcase.ExpectedLayout = layout;
                tcase.ExpectedLayoutAccurate = (newStatus == TestCaseStatus.Pass_Good);
            }

            if (newStatus == TestCaseStatus.Ignore_Clear)
            {
                tcase.ExpectedLayout = null;
            }

            switch (newStatus)
            {
                case TestCaseStatus.Fail:
                    Assert.Fail("Failed: " + tcase.Comment);
                    break;
                case TestCaseStatus.Ignore:
                case TestCaseStatus.Ignore_Clear:
                    Assert.Ignore("Ignore: " + tcase.Comment);
                    break;
                case TestCaseStatus.Unknown:
                    Assert.Inconclusive();
                    break;
            }
        }