Mike Flynn Mike Flynn - 1 month ago 8
ASP.NET (C#) Question

Center Website On One Page with ABCPDF

I have code that does a good job of centering html inside one page on abcpdf. This was provided to me from websupergoo company that created abcpdf. However, my application pool keeps shutting down, and I believe its a performance issue. I even have caching enabled. Is there anyway to optimize this code. Basically what is happening is the code makes calls to a html page, and figures out the boundary dimensions to set the browser width so it can fit within the pdf dimensions. Doing this makes calls over and over to a html page, but I was told if its cached it wouldn't make an actual request but read the cache. There just has to be a easier way to do this since it does take a while to render. This issue seems to happen when multiple requests to a url that uses abcpdf at once.

using (var doc = new Doc())
{
doc.HtmlOptions.Timeout = 60000;
doc.HtmlOptions.PageCacheEnabled = true;
doc.HtmlOptions.PageCacheExpiry = 600000;

doc.HtmlOptions.Engine = Engine;
doc.Rect.Inset(PageInsetHorizontal, PageInsetVertical);
doc.Color.String = "255, 255, 255";

const double heightTolerance = 18; // in points, the max allowed space at the bottom
const int widthIncrement = 96; // in pixels, just an appropriate initial browser width increment
var tallWidth = 0; // the lower browser width
var wideWidth = 0; // the upper browser width
Debug.WriteLine("Adding Url: " + Url);
var id = doc.AddImageUrl(Url);
var scrollWidth = doc.GetInfoInt(id, "ScrollWidth");
var contentWidth = doc.GetInfoInt(id, "ContentWidth");
var toContentWidth = contentWidth - scrollWidth;

while (true)
{
var width = doc.GetInfoInt(id, "ContentWidth");
var height = doc.GetInfoInt(id, "ContentHeight");

Debug.WriteLine("Initial Content Width: " + width);
Debug.WriteLine("Initial Content Height: " + height);

var tooTall = false;
var docScrollWidth = doc.GetInfoInt(id, "ScrollWidth");

Debug.WriteLine("Scroll Width: " + docScrollWidth);

if (docScrollWidth < scrollWidth)
{
scrollWidth = docScrollWidth;
contentWidth = scrollWidth + toContentWidth;

Debug.WriteLine("New Scroll Width: " + scrollWidth);
Debug.WriteLine("New Content Width: " + contentWidth);
}

Debug.WriteLine("Width: " + width);

if (width + 1 < contentWidth)
{
Debug.WriteLine("Too Tall: " + Url);
tooTall = true;
}
// assuming doc.Rect originally specifies the maximum bounding area
if (tooTall || doc.Rect.Width * height > doc.Rect.Height * width)
{
Debug.WriteLine("TOO TALL");
Debug.WriteLine("Delete Html: " + id);

// too tall
doc.Delete(id);

Debug.WriteLine("Browser Width: " + doc.HtmlOptions.BrowserWidth);

if (doc.HtmlOptions.BrowserWidth == 0)
{
doc.HtmlOptions.BrowserWidth = Convert.ToInt32(height*doc.Rect.Width/doc.Rect.Height);
Debug.WriteLine("New BrowserWidth: " + doc.HtmlOptions.BrowserWidth);
}
else
{
tallWidth = doc.HtmlOptions.BrowserWidth;

Debug.WriteLine("Tall Width: " + tallWidth);
Debug.WriteLine("Wide Width: " + wideWidth);

if (wideWidth == 0)
{
doc.HtmlOptions.BrowserWidth = tallWidth + widthIncrement;
Debug.WriteLine("New Browser Width: " + doc.HtmlOptions.BrowserWidth);
}
else if (tallWidth + 1 < wideWidth)
{
doc.HtmlOptions.BrowserWidth = (tallWidth + wideWidth)/2;
Debug.WriteLine("New Browser Width: " + doc.HtmlOptions.BrowserWidth);
}
else
{
doc.HtmlOptions.BrowserWidth = wideWidth;
Debug.WriteLine("New Browser Width: " + doc.HtmlOptions.BrowserWidth);
Debug.WriteLine("Adding Url: " + Url);
Debug.WriteLine("Found Fit");
doc.AddImageUrl(Url);
break;
}
}
}
else if (doc.Rect.Width * height < (doc.Rect.Height - heightTolerance) * width)
{
Debug.WriteLine("TOO WIDE");
Debug.WriteLine("Browser Width: " + doc.HtmlOptions.BrowserWidth);

// too wide
if (doc.HtmlOptions.BrowserWidth == 0)
{
doc.HtmlOptions.BrowserWidth = Convert.ToInt32(height * doc.Rect.Width / doc.Rect.Height);
Debug.WriteLine("New Browser Width: " + doc.HtmlOptions.BrowserWidth);
}
else
{
wideWidth = doc.HtmlOptions.BrowserWidth;

Debug.WriteLine("Tall Width: " + tallWidth);
Debug.WriteLine("Wide Width: " + wideWidth);

if (tallWidth == 0)
{
doc.HtmlOptions.BrowserWidth = wideWidth >= 2 * widthIncrement ? wideWidth - widthIncrement : wideWidth / 2;
Debug.WriteLine("New Browser Width: " + doc.HtmlOptions.BrowserWidth);
}
else if (tallWidth + 1 < wideWidth)
{
doc.HtmlOptions.BrowserWidth = (tallWidth + wideWidth)/2;
Debug.WriteLine("New Browser Width: " + doc.HtmlOptions.BrowserWidth);
}
else
{
Debug.WriteLine("Found Fit");

break;
}
}

Debug.WriteLine("Delete Html: " + id);

doc.Delete(id);
}
else
break;

Debug.WriteLine("Adding Url: " + Url);

id = doc.AddImageUrl(Url);
}

using (var ms = new MemoryStream())
{
doc.Save(ms);
if (ms.CanSeek)
{
ms.Seek(0, SeekOrigin.Begin);
}
return ms.GetBuffer();
}
}

Answer

I found some other code and I tweaked it and this seems to work great.

using (var doc = new Doc())
{
  if(!EnableCache)
    doc.HtmlOptions.PageCacheClear();

    if (MakeLandscape)
    {
      var w = doc.MediaBox.Width;
      var h = doc.MediaBox.Height;
      var l = doc.MediaBox.Left;
      var b = doc.MediaBox.Bottom;

      doc.Transform.Rotate(90, l, b);
      doc.Transform.Translate(w, 0);

      doc.Rect.Width = h;
      doc.Rect.Height = w;
    }

    doc.HtmlOptions.Timeout = 60000;
    doc.HtmlOptions.PageCacheEnabled = EnableCache;
    doc.HtmlOptions.PageCacheExpiry = 600000;

    doc.HtmlOptions.Engine = Engine;
    doc.Rect.Inset(PageInsetHorizontal, PageInsetVertical);
    doc.Color.String = "255, 255, 255";

    doc.HtmlOptions.Paged = false;
    doc.HtmlOptions.BrowserWidth = (MakeLandscape ? PageWidth + PageInsetHorizontal : PageHeight + PageInsetVertical) * Convert.ToInt32(doc.Rect.Width / doc.Rect.Height);

    var id = doc.AddImageUrl(Url);

    if (MakeLandscape)
    {
      var scrollWidth = doc.GetInfoInt(id, "ScrollWidth");
      var contentWidth = doc.GetInfoInt(id, "ContentWidth");

      if (scrollWidth > contentWidth)
      {
        var scrollHeight = doc.GetInfoInt(id, "ScrollHeight");
        doc.Delete(id);
        doc.HtmlOptions.BrowserWidth = Convert.ToInt32(scrollHeight * doc.Rect.Width / doc.Rect.Height);

        id = doc.AddImageUrl(Url);
      }
    }
    else
    {
      var scrollHeight = doc.GetInfoInt(id, "ScrollHeight");
      var contentHeight = doc.GetInfoInt(id, "ContentHeight");

      if (scrollHeight > contentHeight + (PageInsetVertical *2))
      {
        var scrollWidth = doc.GetInfoInt(id, "ScrollWidth");
        doc.Delete(id);
        doc.HtmlOptions.BrowserWidth = Convert.ToInt32(((double)scrollHeight / contentHeight) * scrollWidth);
        id = doc.AddImageUrl(Url);
      }
    }

    if (MakeLandscape)
    {
      doc.SetInfo(doc.GetInfoInt(doc.Root, "Pages"), "/Rotate", "90");
    }

    using (var ms = new MemoryStream())
    {
      doc.Save(ms);
      if (ms.CanSeek)
      {
        ms.Seek(0, SeekOrigin.Begin);
      }
      return ms.GetBuffer();
    }
  }
Comments