Project

General

Profile

Support #3173

WPieCharts unprintable to PDF with 1 or 0 items.

Added by Anonymous about 8 years ago. Updated over 7 years ago.

Status:
Closed
Priority:
Normal
Assignee:
Michael Vilsker
Target version:
Start date:
05/20/2014
Due date:
% Done:

0%

Estimated time:

Description

Not sure if this is a bug, but when I make a WPieChart with 1 or 0 items, it becomes unprintable in PDFs, the page simply reads "Failed to load PDF document". The WPieChart prints fine if it has 2 or more items. How can I print a PDF with 1 or less items?

The code I used is the sample code from the widget gallery PDF output Rendering HTML to PDF example, with some minor modifications.

The sample code is below, with the WPieChart initialization and printing below that.

namespace
{
  void HPDF_STDCALL error_handler(HPDF_STATUS error_no, HPDF_STATUS detail_no, void *user_data)
  {
    user_data;
    fprintf(stderr, "libharu error: error_no=%04X, detail_no=%d\n", (u32) error_no, (s32) detail_no);
  }
}

class ReportResource : public Wt::WResource
{
public:
  ReportResource(const std::vector<Wt::Chart::WPieChart*> pie_charts, Wt::WTable* table, Wt::WObject* parent = 0) : Wt::WResource(parent),
    _table(NULL)
  {
    suggestFileName("report.pdf");
    _table = table;
    s32 charts = pie_charts.size();
    for(s32 chart = 0; chart < charts; ++chart)
    {
      _pie_charts.push_back(pie_charts[chart]);
    }
  }
  ReportResource(Wt::Chart::WPieChart* pie_charts, Wt::WTable* table, Wt::WObject* parent = 0) : Wt::WResource(parent),
    _table(NULL)
  {
    suggestFileName("report.pdf");
    _table = table;
    _pie_charts.push_back(pie_charts);
  }

  virtual void handleRequest(const Wt::Http::Request& request, Wt::Http::Response& response)
  {
    request;
    response.setMimeType("application/pdf");

    HPDF_Doc pdf = HPDF_New(error_handler, 0);

    // Note: UTF-8 encoding (for TrueType fonts) is only available since libharu 2.3.0 !
    HPDF_UseUTFEncodings(pdf);

    renderReport(pdf);

    HPDF_SaveToStream(pdf);
    unsigned int size = HPDF_GetStreamSize(pdf);
    HPDF_BYTE *buf = new HPDF_BYTE[size];
    HPDF_ReadFromStream (pdf, buf, &size);
    HPDF_Free(pdf);
    response.out().write((char*)buf, size);
    delete[] buf;
  }

private:

  Wt::WTable* _table;
  std::vector<Wt::Chart::WPieChart*> _pie_charts;

  void renderReport(HPDF_Doc pdf)
  {
    //Get the html for the table
    std::stringstream ss;
    _table->htmlText(ss);
    renderPdf(ss.str(), pdf);
  }

  void renderPdf(const Wt::WString& html, HPDF_Doc pdf)
  {
    //Make the page
    HPDF_Page page = HPDF_AddPage(pdf);
    HPDF_Page_SetSize(page, HPDF_PAGE_SIZE_A4, HPDF_PAGE_PORTRAIT);

    //Get the renderer to render the table data
    Wt::Render::WPdfRenderer renderer(pdf, page);
    renderer.setMargin(1.50);
    renderer.setDpi(180);
    renderer.useStyleSheet("Ventus/examples/simple/css/normalize.css");
    renderer.useStyleSheet("Ventus/examples/simple/css/simple.css");
    renderer.useStyleSheet("Ventus/build/ventus.css");
    renderer.useStyleSheet("Ventus/examples/simple/css/browseralert.css");
    renderer.render(html);

    //Make a pdf image to render the chart
    Wt::WPdfImage pdfImage(100, 100, this);
    Wt::WPainter* p = renderer.getPainter(renderer.startPage(0));
    u32 charts = _pie_charts.size();
    u32 position = 500;
    for(u32 chart = 0; chart < charts; ++chart)
    {
      _pie_charts[chart]->paint(*p, Wt::WRectF(200, position, 900, 900));
      position += 900;
    }
    std::ofstream f("report.pdf", std::ios::out | std::ios::app | std::ios::binary);
    pdfImage.write(f);
  }
};

WPieChart initialization and printing. I'm also aiming to print a table on the same page, but you can ignore that code.

  Wt::WContainerWidget* container = new Wt::WContainerWidget();

  Wt::WPushButton* make_pdf = new Wt::WPushButton("Create pdf sample");

  //Create table 
  Wt::WTable* report_table = new Wt::WTable(container);
  report_table->addStyleClass("table table-bordered table-striped no-wrap");
  report_table->setHeaderCount(1);
  report_table->setMargin(Wt::WLength::Auto, Wt::Left | Wt::Right);
  report_table->setMargin(30, Wt::Top | Wt::Bottom);
  report_table->setMaximumSize(400, Wt::WLength::Auto);

  report_table->elementAt(0, 0)->addWidget(new Wt::WText("Category"));
  report_table->elementAt(0, 1)->addWidget(new Wt::WText("Total Cost"));

  //Setup the chart's model
  Wt::WStandardItemModel* _graph_model = new Wt::WStandardItemModel(container);

  // Configure the header.
  _graph_model->insertColumns(_graph_model->columnCount(), 2);
  _graph_model->setHeaderData(0, Wt::WString("Item"));
  _graph_model->setHeaderData(1, Wt::WString("Amount"));

  //Create a pie chart
  Wt::Chart::WPieChart *pie_chart = new Wt::Chart::WPieChart(container);
  pie_chart->setModel(_graph_model);  // Set the model.
  pie_chart->setLabelsColumn(0);      // Set the column that holds the labels.
  pie_chart->setDataColumn(1);        // Set the column that holds the data.
  // Configure location and type of labels.
  pie_chart->setDisplayLabels(Wt::Chart::Outside | Wt::Chart::TextLabel | Wt::Chart::TextPercentage); //Set where to display the text
  // Enable a 3D and shadow effect.
  pie_chart->setPerspectiveEnabled(true, 0.2); // Enable a 3D effect.
  pie_chart->setShadowEnabled(true);
  //pie_chart->setExplode(0, 0.3);  // Explode the first item.
  pie_chart->setPalette(new GraphPalette(Wt::Chart::WStandardPalette::GrayScale));  //Set the palette
  pie_chart->resize(800, 400);    // WPaintedWidget must be given an explicit size.
  pie_chart->setMargin(10, Wt::Top | Wt::Bottom); // Add margin vertically.
  pie_chart->setMargin(Wt::WLength::Auto, Wt::Left | Wt::Right); // Center horizontally.

  // Set data in the model.
  _graph_model->insertRows(_graph_model->rowCount(), 1);
  _graph_model->setData(   _graph_model->rowCount() - 1, 0, Wt::WString("Blueberry"));
  _graph_model->setData(   _graph_model->rowCount() - 1, 1, 120);
  _graph_model->insertRows(_graph_model->rowCount(), 1);
  _graph_model->setData(   _graph_model->rowCount() - 1, 0, Wt::WString("Cherry"));
  _graph_model->setData(   _graph_model->rowCount() - 1, 1, 10);

  ReportResource* pdf = new ReportResource(pie_chart, report_table, container);
  make_pdf->setLink(pdf);

When the button is pressed, it should create the PDF. Removing the code that adds 2 sample items to the WPieChart right below the "// Set data in the model." comment will cause the error to happen. Is it something I am doing wrong with initializing the WPieChart, or some other setting?

#1

Updated by Koen Deforche about 8 years ago

  • Status changed from New to InProgress
  • Assignee set to Michael Vilsker
  • Target version changed from 3.3.2 to 3.3.4

Michael, I suspect this is an error in libharu, which we can easily work around if we avoid creating an arc of exactly 360 degrees?

#2

Updated by Michael Vilsker about 8 years ago

Hey Denis,

I could not reproduce the error message (maybe we use different versions of haru).

There was a problem in drawing circle.

You will be able to find the fix on git soon, I believe that will also fix the other error.

#3

Updated by Michael Vilsker about 8 years ago

  • Status changed from InProgress to Resolved
#4

Updated by Koen Deforche over 7 years ago

  • Status changed from Resolved to Closed

Also available in: Atom PDF