page_handler.cpp
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:25k
源码类别:

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: page_handler.cpp,v $
  4.  * PRODUCTION Revision 1000.1  2004/06/01 21:03:36  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.17
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: page_handler.cpp,v 1000.1 2004/06/01 21:03:36 gouriano Exp $
  10.  * ===========================================================================
  11.  *
  12.  *                            PUBLIC DOMAIN NOTICE
  13.  *               National Center for Biotechnology Information
  14.  *
  15.  *  This software / database is a "United States Government Work" under the
  16.  *  terms of the United States Copyright Act.  It was written as part of
  17.  *  the author's official duties as a United States Government employee and
  18.  *  thus cannot be copyrighted.  This software / database is freely available
  19.  *  to the public for use. The National Library of Medicine and the U.S.
  20.  *  Government have not placed any restriction on its use or reproduction.
  21.  *
  22.  *  Although all reasonable efforts have been taken to ensure the accuracy
  23.  *  and reliability of the software and data, the NLM and the U.S.
  24.  *  Government do not and cannot warrant the performance or results that
  25.  *  may be obtained by using this software or data. The NLM and the U.S.
  26.  *  Government disclaim all warranties, express or implied, including
  27.  *  warranties of performance, merchantability or fitness for any particular
  28.  *  purpose.
  29.  *
  30.  *  Please cite the author in any work or product based on this material.
  31.  *
  32.  * ===========================================================================
  33.  *
  34.  * Authors:  Peter Meric
  35.  *
  36.  * File Description:
  37.  *   CPageHandler - manage pages in a PDF document
  38.  */
  39. #include <ncbi_pch.hpp>
  40. #include <gui/print/print_options.hpp>
  41. #include <gui/print/print_utils.hpp>
  42. #include <gui/utils/id_generator.hpp>
  43. #include "page_handler.hpp"
  44. #include "pdf_object.hpp"
  45. #include "pdf_object_writer.hpp"
  46. #include "pdf_obj.hpp"
  47. #include "panel_grid.hpp"
  48. BEGIN_NCBI_SCOPE
  49. CPageHandler::CPageHandler(const CPageBuffers& buffers,
  50.                            CPdfObjectWriter& obj_writer,
  51.                            CIdGenerator& objid_gen
  52.                           )
  53. : m_ObjWriter(&obj_writer),
  54.   m_ObjIdGenerator(&objid_gen),
  55.   m_PageTreeRootObj(new CPdfObject(m_ObjIdGenerator->NextId())),
  56.   m_PageBuffers(&buffers)
  57. {
  58. }
  59. CPageHandler::~CPageHandler()
  60. {
  61. }
  62. CPageHandler::TPdfObjectRef CPageHandler::GetObject(void) const
  63. {
  64.     return m_PageTreeRootObj;
  65. }
  66. void CPageHandler::SetOptions(const CPrintOptions& options)
  67. {
  68.     m_Options = &options;
  69.     const unsigned int pg_wide = m_Options->GetPagesWide();
  70.     const unsigned int pg_tall = m_Options->GetPagesTall();
  71.     m_PanelGrid.Reset(new CPanelGrid(*m_ObjIdGenerator, pg_wide, pg_tall));
  72. }
  73. void CPageHandler::x_Update(const CRef<CPdfDictionary>& pagedict)
  74. {
  75.     x_UpdatePageTreeRoot(pagedict);
  76. }
  77. void CPageHandler::x_UpdatePageTreeRoot(const CRef<CPdfDictionary>& pagedict)
  78. {
  79.     CPdfObject& root = *m_PageTreeRootObj;
  80.     root["Type"] = new CPdfName("Pages");
  81.     root["Count"] = new CPdfNumber(int(m_Pages.size()));
  82.     root["Rotate"] = new CPdfNumber(int(m_Options->GetPageOrientation()));
  83.     CRef<CPdfArray> kids(new CPdfArray());
  84.     ITERATE(vector<TPdfObjectRef>, it, m_Pages) {
  85.         kids->GetArray().push_back(CRef<CPdfObj>(new CPdfIndirectObj(*it)));
  86.     }
  87.     root["Kids"] = kids;
  88.     CRef<CPdfArray> mediabox(new CPdfArray());
  89.     CPdfArray::TArray& mbarr = mediabox->GetArray();
  90.     mbarr.push_back(CRef<CPdfObj>(new CPdfNumber(int(0))));
  91.     mbarr.push_back(CRef<CPdfObj>(new CPdfNumber(int(0))));
  92.     mbarr.push_back(CRef<CPdfObj>(new CPdfNumber(int(m_Options->GetMediaWidth()))));
  93.     mbarr.push_back(CRef<CPdfObj>(new CPdfNumber(int(m_Options->GetMediaHeight()))));
  94.     root["MediaBox"] = mediabox;
  95.     /*
  96.        root  << "     %/TrimBox [ "
  97.        << xs.first << ' ' << ys.first << ' '
  98.        << xs.second << ' ' << ys.second << " ]" << endl;
  99.        */
  100.     CRef<CPdfArray> procset(new CPdfArray());
  101.     CPdfArray::TArray& pset = procset->GetArray();
  102.     pset.push_back(CRef<CPdfObj>(new CPdfObj("/PDF")));
  103.     pset.push_back(CRef<CPdfObj>(new CPdfObj("/Text")));
  104.     //res["ProcSet"] = procset;
  105.     CPdfDictionary& dict = root.GetDictionary();
  106.     dict.Add(pagedict);
  107.     CRef<CPdfObj>& res = dict["Resources"];
  108.     if ( !res ) {
  109.         CRef<CPdfDictionary> resources(new CPdfDictionary());
  110.         (*resources)["ProcSet"] = procset;
  111.         res = resources;
  112.     } else {
  113.         CRef<CPdfDictionary> _res(dynamic_cast < CPdfDictionary*>(res.GetPointer()));
  114.         (*_res)["ProcSet"] = procset;
  115.     }
  116. }
  117. CPageHandler::TPdfObjectRef CPageHandler::x_CreateHeaderFooter(void)
  118. {
  119.     TPdfObjectRef hf_obj;
  120.     const string header(m_Options->GetHeader());
  121.     const string footer(m_Options->GetFooter());
  122.     const bool has_header = header.length() > 0;
  123.     const bool has_footer = footer.length() > 0;
  124.     if (has_header || has_footer) {
  125.         hf_obj.Reset(new CPdfObject(m_ObjIdGenerator->NextId()));
  126.         CPdfObject& obj = *hf_obj;
  127.         obj << "0 0 m n" << pdfbrk;
  128.         obj << "0 0 0 rg" << pdfbrk;
  129.         if (has_header) {
  130.             obj << "BT" << pdfbrk;
  131.             const TPdfUnit font_size = 8;
  132.             obj << "/F1 " << font_size << " Tf" << pdfbrk;
  133.             const TPdfUnit str_w = font_size * header.length();
  134.             obj << (m_Options->GetMediaWidth() - str_w) / 2 << ' '
  135.                 << m_Options->GetMediaHeight() - m_Options->GetHeaderOffset() - font_size << " Td" << pdfbrk;
  136.             obj << CPdfString(header) << "Tj" << pdfbrk;
  137.             obj << "ET" << pdfbrk;
  138.         }
  139.         if (has_footer) {
  140.             obj << "BT" << pdfbrk;
  141.             const TPdfUnit font_size = 8;
  142.             obj << "/F2 " << font_size << " Tf" << pdfbrk;
  143.             const TPdfUnit str_w = font_size * footer.length();
  144.             obj << (m_Options->GetMediaWidth() - str_w) / 2 << ' '
  145.                 << m_Options->GetFooterOffset() << " Td" << pdfbrk;
  146.             obj << CPdfString(footer) << "Tj" << pdfbrk;
  147.             obj << "ET" << pdfbrk;
  148.         }
  149.     }
  150.     return hf_obj;
  151. }
  152. CPageHandler::TPdfObjectRef CPageHandler::x_CreatePrintersMarks(const CRef<CPanel>& panel)
  153. {
  154.     TPdfObjectRef pmarks_obj(new CPdfObject(m_ObjIdGenerator->NextId()));
  155.     CPdfObject& pmarks = *pmarks_obj;
  156.     // create printer's marks, page alignment etc
  157.     pmarks << "0 0 m n" << pdfbrk;
  158.     pmarks << "0 0 0 rg" << pdfbrk;
  159.     pmarks << "BT" << pdfbrk;
  160.     pmarks << CPdfName("F1") << ' ' << CPdfNumber(8) << " Tf" << pdfbrk;
  161.     //
  162.     // output current panel number
  163.     //
  164.     const string pstr("Panel " + NStr::IntToString(panel->m_PanelNum)
  165.                       + " of " + NStr::IntToString(m_Options->GetNumPages())
  166.                      );
  167.     const string::size_type pstr_len(pstr.length() * 8);
  168.     pmarks << CPdfNumber(m_Options->GetMediaWidth() - pstr_len - 30) << ' '
  169.            << CPdfNumber(m_Options->GetMediaHeight() - 20) << " Td" << pdfbrk;
  170.     pmarks << CPdfString(pstr) << "Tj" << pdfbrk;
  171.     pmarks << "ET" << pdfbrk;
  172.     //
  173.     // corner crop marks
  174.     //
  175.     x_DrawCornerCropMarks(pmarks, 8);
  176.     //
  177.     // print neighbour pointers (links)
  178.     //
  179.     const CPanelGrid::SNeighbours n = m_PanelGrid->GetNeighbours(panel->m_Col, panel->m_Row);
  180.     TPdfObjectRef panelref = panel->m_Panel;
  181.     CPdfObject& panelobj = *panelref;
  182.     CRef<CPdfArray> annots(new CPdfArray());
  183.     const TPdfUnit link_margin = 30;
  184.     // draw top
  185.     if (n.top) {
  186.         const TPdfUnit x = m_Options->GetMediaWidth() / 2;
  187.         const TPdfUnit y = m_Options->GetMediaHeight() - link_margin;
  188.         annots->Add(x_DrawPanelLink(pmarks, n.top->m_PanelNum, x, y));
  189.     }
  190.     // draw bottom
  191.     if (n.bottom) {
  192.         const TPdfUnit x = m_Options->GetMediaWidth() / 2;
  193.         const TPdfUnit y = link_margin - 10;
  194.         annots->Add(x_DrawPanelLink(pmarks, n.bottom->m_PanelNum, x, y, eBottom));
  195.     }
  196.     // draw left
  197.     if (n.left) {
  198.         const TPdfUnit x = link_margin;
  199.         const TPdfUnit y = m_Options->GetMediaHeight() / 2;
  200.         annots->Add(x_DrawPanelLink(pmarks, n.left->m_PanelNum, x, y, eLeft));
  201.     }
  202.     // draw right
  203.     if (n.right) {
  204.         const TPdfUnit x = m_Options->GetMediaWidth() - link_margin;
  205.         const TPdfUnit y = m_Options->GetMediaHeight() / 2;
  206.         annots->Add(x_DrawPanelLink(pmarks, n.right->m_PanelNum, x, y, eRight));
  207.     }
  208.     if (annots->GetArray().size() > 0) {
  209.         panelobj["Annots"] = annots;
  210.     }
  211.     return pmarks_obj;
  212. }
  213. void CPageHandler::x_DrawCornerCropMarks(CPdfObject& obj, TPdfUnit margin) const
  214. {
  215.     const TPdfUnit cmark_len = 20;
  216.     const TPdfUnit cm_l = m_Options->GetMarginLeft();
  217.     const TPdfUnit cm_lm = cm_l - margin;
  218.     const TPdfUnit cm_t = m_Options->GetMediaHeight() - m_Options->GetMarginTop();
  219.     const TPdfUnit cm_tm = cm_t + margin;
  220.     const TPdfUnit cm_r = m_Options->GetMediaWidth() - m_Options->GetMarginRight();
  221.     const TPdfUnit cm_rm = cm_r + margin;
  222.     const TPdfUnit cm_b = m_Options->GetMarginBottom();
  223.     const TPdfUnit cm_bm = cm_b - margin;
  224.     // top left
  225.     obj << cm_lm - cmark_len << ' ' << cm_t << " m "
  226.         << cm_lm << ' ' << cm_t << " l s" << pdfbrk;
  227.     obj << cm_l << ' ' << cm_tm + cmark_len << " m "
  228.         << cm_l << ' ' << cm_tm << " l s" << pdfbrk;
  229.     // top right
  230.     obj << cm_rm + cmark_len << ' ' << cm_t << " m "
  231.         << cm_rm << ' ' << cm_t << " l s" << pdfbrk;
  232.     obj << cm_r << ' ' << cm_tm + cmark_len << " m "
  233.         << cm_r << ' ' << cm_tm << " l s" << pdfbrk;
  234.     // bottom left
  235.     obj << cm_lm - cmark_len << ' ' << cm_b << " m "
  236.         << cm_lm << ' ' << cm_b << " l s" << pdfbrk;
  237.     obj << cm_l << ' ' << cm_bm - cmark_len << " m "
  238.         << cm_l << ' ' << cm_bm << " l s" << pdfbrk;
  239.     // bottom right
  240.     obj << cm_rm + cmark_len << ' ' << cm_b << " m "
  241.         << cm_rm << ' ' << cm_b << " l s" << pdfbrk;
  242.     obj << cm_r << ' ' << cm_bm - cmark_len << " m "
  243.         << cm_r << ' ' << cm_bm << " l s" << pdfbrk;
  244. }
  245. CRef<CPdfArray> CPageHandler::x_DrawPanelLink(CPdfObject& obj,
  246.                                               unsigned int panel_num,
  247.                                               TPdfUnit x,
  248.                                               TPdfUnit y,
  249.                                               enum Side side
  250.                                              ) const
  251. {
  252.     const TPdfUnit link_width = 44;
  253.     const TPdfUnit link_width2 = link_width / 2;
  254.     const TPdfUnit fnt_h = 8;
  255.     TPdfUnit xlate_x;
  256.     TPdfUnit xlate_y;
  257.     int rot;
  258.     switch (side) {
  259.     case (eTop):
  260.     case (eBottom):
  261.         rot = (side == eTop) ? 0 : 180;
  262.         xlate_x = x - link_width2;
  263.         xlate_y = y;
  264.         break;
  265.     case (eLeft):
  266.         rot = 90;
  267.         xlate_x = x;
  268.         xlate_y = y - link_width2;
  269.         break;
  270.     case (eRight):
  271.         rot = 270;
  272.         xlate_x = x;
  273.         xlate_y = y + link_width2;
  274.         break;
  275.     }
  276.     obj << CPdfObj("q") << pdfbrk;
  277.     obj << CPdfTranslate(xlate_x, xlate_y) << pdfbrk;
  278.     if (side == eLeft || side == eRight) {
  279.         obj << CPdfRotate(rot) << pdfbrk;
  280.         rot = 0; // don't rotate again
  281.     }
  282.     obj << "BT" << pdfbrk;
  283.     //obj << CPdfName("F1") << ' ' << CPdfNumber(8) << " Tf" << pdfbrk;
  284.     const string txt("Panel " + NStr::IntToString(panel_num));
  285.     obj << "4 1 Td" << pdfbrk;
  286.     obj << CPdfString(txt) << "Tj" << pdfbrk;
  287.     obj << "ET" << pdfbrk;
  288.     if (rot != 0) {
  289.         obj << CPdfRotate(rot) << pdfbrk;
  290.     }
  291.     if (side == eBottom) {
  292.         // if upside down, then offset the triangles according to the text
  293.         obj << CPdfTranslate(-int(link_width), -int(fnt_h)) << pdfbrk;
  294.     }
  295.     obj << CPdfObj("0.416 0.549 0.792 rg") << pdfbrk;
  296.     const TPdfUnit _margin = 3;
  297.     const TPdfUnit tri_w = 16;
  298.     const TPdfUnit tri_h = 8;
  299.     x_DrawTriangle(obj, link_width / 2, fnt_h + _margin, tri_w, tri_h);
  300.     CRef<CPdfArray> annots(new CPdfArray());
  301.     CRef<CPdfDictionary> link_annot(new CPdfDictionary());
  302.     CPdfDictionary& link = *link_annot;
  303.     link["Type"] = new CPdfName("Annot");
  304.     link["Subtype"] = new CPdfName("Link");
  305.     string _x1, _x2, _y1, _y2;
  306.     switch (side) {
  307.     case (eTop):
  308.     case (eBottom):
  309.         _x1 = NStr::IntToString(int(x - link_width2 - _margin));
  310.         _y1 = NStr::IntToString(int(y - _margin));
  311.         _x2 = NStr::IntToString(int(x + link_width2 + _margin));
  312.         _y2 = NStr::IntToString(int(y + fnt_h + _margin));
  313.         break;
  314.     case (eLeft):
  315.     case (eRight):
  316.         {
  317.             const bool left = (side == eLeft);
  318.             _x1 = NStr::IntToString(int(x + (left ? 1 : -1) * _margin));
  319.             _y1 = NStr::IntToString(int(y + link_width2 + _margin));
  320.             _x2 = NStr::IntToString(int(x + (left ? -1 : 1) * (fnt_h + _margin)));
  321.             _y2 = NStr::IntToString(int(y - link_width2 - _margin));
  322.         }
  323.         break;
  324.     }
  325.     link["Rect"] = new CPdfObj("[" + _x1 + " " + _y1 + " " + _x2 + " " + _y2 + "]");
  326.     link["Border"] = new CPdfObj("[3 3 2]");
  327.     link["C"] = new CPdfObj("[0.416 0.549 0.792]");
  328.     link["H"] = new CPdfName("P");
  329.     CRef<CPdfArray> dest(new CPdfArray());
  330.     const CRef<CPanel> p = m_PanelGrid->GetPanel(panel_num);
  331.     dest->GetArray().push_back(CRef<CPdfObj>(new CPdfIndirectObj(p->m_Panel)));
  332.     dest->GetArray().push_back(CRef<CPdfObj>(new CPdfName("Fit")));
  333.     link["Dest"] = dest;
  334.     annots->GetArray().push_back(CRef<CPdfObj>(link_annot));
  335.     obj << CPdfObj("Q") << pdfbrk;
  336.     return annots;
  337. }
  338. void CPageHandler::x_DrawTriangle(CPdfObject& obj,
  339.                                   TPdfUnit x,
  340.                                   TPdfUnit y,
  341.                                   TPdfUnit width,
  342.                                   TPdfUnit height
  343.                                  ) const
  344. {
  345.     const TPdfUnit w = width / 2;
  346.     obj << CPdfNumber(x - w) << ' ' << CPdfNumber(y) << " m ";
  347.     obj << CPdfNumber(x) << ' ' << CPdfNumber(y + int(height)) << " l ";
  348.     obj << CPdfNumber(x + w) << ' ' << CPdfNumber(y) << " l h f" << pdfbrk;
  349. }
  350. CPageHandler::TPdfObjectRef CPageHandler::x_CreatePageClipObject(void)
  351. {
  352.     TPdfObjectRef clip_obj(new CPdfObject(m_ObjIdGenerator->NextId()));
  353.     CPdfObject& clip = *clip_obj;
  354.     // margin between actual margin and printing marks
  355.     const TPdfUnit pmm = 1;
  356.     // create printer's marks, page alignment etc
  357.     const TPdfUnit L = m_Options->GetMarginLeft() - pmm;
  358.     const TPdfUnit B = m_Options->GetMarginBottom() - pmm;
  359.     const TPdfUnit R = m_Options->GetMediaWidth() - m_Options->GetMarginLeft() + pmm;
  360.     const TPdfUnit T = m_Options->GetMediaHeight() - m_Options->GetMarginTop() + pmm;
  361.     clip << L << ' ' << B << " m ";
  362.     clip << R << ' ' << B << " l ";
  363.     clip << R << ' ' << T << " l ";
  364.     clip << L << ' ' << T << " l W n" << pdfbrk;
  365.     return clip_obj;
  366. }
  367. CPageHandler::TPdfObjectRef CPageHandler::x_CreateContentXForm(void)
  368. {
  369.     TPdfObjectRef xform_obj(new CPdfObject(m_ObjIdGenerator->NextId()));
  370.     CPdfObject& xform = *xform_obj;
  371.     //
  372.     // scale and translate the coordinate system based on the size of
  373.     // the page content
  374.     //
  375.     const CPageBuffers::TOffset docsize = m_PageBuffers->GetPageSize();
  376.     const pair<float, float> scale = x_GetPageScaling(docsize.first, docsize.second);
  377.     xform << scale.first << " 0 0 " << scale.second << " 0 0 cm" << pdfbrk;
  378.     const CBBox<3>& bbox = m_PageBuffers->GetBoundingBox();
  379.     const float x_off = bbox.GetNthRange(0).first;
  380.     const float y_off = bbox.GetNthRange(1).first;
  381.     xform << "1 0 0 1 " << -x_off << ' ' << -y_off << " cm" << pdfbrk;
  382.     return xform_obj;
  383. }
  384. CPageHandler::TPdfObjectRef CPageHandler::x_CreatePageXForm(const CRef<CPanel>& panel)
  385. {
  386.     // translate page according to offset
  387.     TPdfObjectRef xform_obj(new CPdfObject(m_ObjIdGenerator->NextId()));
  388.     CPdfObject& xform = *xform_obj;
  389.     const TOffset offset = x_GetPanelOffset(panel);
  390.     xform << "1 0 0 1 " << offset.first << ' ' << offset.second << " cm" << pdfbrk;
  391.     return xform_obj;
  392. }
  393. //
  394. // GetPanelOffset() - given dimensions in PDF (default user space)
  395. //                    coordinates, return page offsets in that coordinate
  396. //                    system given horizontal and vertical alignments.
  397. //
  398. // The horizontal/vertical factors specify the number of pages
  399. // by which to offset this panel
  400. //
  401. CPageHandler::TOffset CPageHandler::x_GetPanelOffset(const CRef<CPanel>& panel) const
  402. {
  403.     const TAlignment& halign = panel->m_HAlign;
  404.     const TAlignment& valign = panel->m_VAlign;
  405.     const unsigned int pg_wide = m_Options->GetPagesWide();
  406.     const unsigned int pg_tall = m_Options->GetPagesTall();
  407.     const TPdfUnit page_w = m_Options->GetPageTrimWidth();
  408.     const TPdfUnit page_h = m_Options->GetPageTrimHeight();
  409.     TSize docsize = x_GetScaledPageSize();
  410.     const TPdfUnit fullpg_wide = pg_wide < 3 ? 0 : pg_wide - 2;
  411.     const TPdfUnit fullpg_w = fullpg_wide * page_w;
  412.     if (halign == CPrintOptions::eCenter) {
  413.         docsize.first = page_w;
  414.     }
  415.     else {
  416.         docsize.first = (docsize.first - fullpg_w) / 2;
  417.     }
  418.     const TPdfUnit fullpg_tall = pg_tall < 3 ? 0 : pg_tall - 2;
  419.     const TPdfUnit fullpg_h = fullpg_tall * page_h;
  420.     if (valign == CPrintOptions::eMiddle) {
  421.         docsize.second = page_h;
  422.     }
  423.     else {
  424.         docsize.second = (docsize.second - fullpg_h) / 2;
  425.     }
  426.     //int h_offset = page_w * -panel->m_HPageOffset + m_Options->GetMarginLeft();
  427.     //int v_offset = page_h * -panel->m_VPageOffset + m_Options->GetMarginBottom();
  428.     TPdfUnit h_offset = -fullpg_w + m_Options->GetMarginLeft();
  429.     TPdfUnit v_offset = -fullpg_h + m_Options->GetMarginBottom();
  430.     switch (halign) {
  431.     case CPrintOptions::eLeft:
  432.         //h_offset += docsize.first - page_w;
  433.         break;
  434.     case CPrintOptions::eCenter:
  435.         h_offset += (page_w - docsize.first) / 2;
  436.         break;
  437.     case CPrintOptions::eRight:
  438.         h_offset += page_w - docsize.first;
  439.         break;
  440.     default:
  441.         break;
  442.     }
  443.     switch (valign) {
  444.     case CPrintOptions::eTop:
  445.         v_offset += page_h - docsize.second;
  446.         break;
  447.     case CPrintOptions::eMiddle:
  448.         v_offset += (page_h - docsize.second) / 2;
  449.         break;
  450.     case CPrintOptions::eBottom:
  451.         //v_offset += docsize.second - page_h;
  452.         break;
  453.     default:
  454.         break;
  455.     }
  456.     return make_pair(h_offset, v_offset);
  457. }
  458. //
  459. // x_GetPageScaling() - scale the dimensions in the user's coordinate system to
  460. //                      dimensions in PDF (default user space)
  461. //
  462. pair<float, float> CPageHandler::x_GetPageScaling(TPdfUnit w,
  463.                                                   TPdfUnit h,
  464.                                                   bool keepAspect
  465.                                                  ) const
  466. {
  467.     const TPdfUnit page_w = m_Options->GetPageTrimWidth();
  468.     const TPdfUnit page_h = m_Options->GetPageTrimHeight();
  469.     const TPdfUnit total_w = page_w * m_Options->GetPagesWide();
  470.     const TPdfUnit total_h = page_h * m_Options->GetPagesTall();
  471.     const float scale_w = float(total_w) / w;
  472.     const float scale_h = float(total_h) / h;
  473.     if (keepAspect) {
  474.         const float scale = scale_w < scale_h ? scale_w : scale_h;
  475.         return make_pair(scale, scale);
  476.     }
  477.     return make_pair(scale_w, scale_h);
  478. }
  479. void CPageHandler::SetContent(const TPdfObjectRef& content)
  480. {
  481.     m_Content = content;
  482. }
  483. void CPageHandler::WritePageTree(const CRef<CPdfDictionary>& pagedict)
  484. {
  485.     const_cast<CPageHandler*>(this)->x_Update(pagedict);
  486.     m_ObjWriter->WriteObject(m_PageTreeRootObj);
  487. }
  488. const CPageHandler::TSize CPageHandler::x_GetScaledPageSize(void) const
  489. {
  490.     const CPageBuffers::TOffset sz = m_PageBuffers->GetPageSize();
  491.     const pair<float, float> scale(x_GetPageScaling(sz.first, sz.second));
  492.     return TSize(scale.first * sz.first,
  493.                  scale.second * sz.second
  494.                 );
  495. }
  496. unsigned int CPageHandler::WritePages(void)
  497. {
  498.     //
  499.     // write the content object
  500.     //
  501.     m_ObjWriter->WriteObject(m_Content);
  502.     //
  503.     // write the header/footer object
  504.     //
  505.     TPdfObjectRef headfoot_obj = x_CreateHeaderFooter();
  506.     if (headfoot_obj.GetPointer()) {
  507.         m_StdContents.push_back(headfoot_obj);
  508.         m_ObjWriter->WriteObject(headfoot_obj);
  509.     }
  510.     //
  511.     // create the clip/crop object
  512.     //
  513.     m_Clip = x_CreatePageClipObject();
  514.     m_ObjWriter->WriteObject(m_Clip);
  515.     //
  516.     // create the content transform object
  517.     //
  518.     m_ContentPagesXForm = x_CreateContentXForm();
  519.     m_ObjWriter->WriteObject(m_ContentPagesXForm);
  520.     //
  521.     // generate and output the content pages
  522.     //
  523.     unsigned int panel_num = 1;
  524.     const unsigned int pg_wide = m_Options->GetPagesWide();
  525.     const unsigned int pg_tall = m_Options->GetPagesTall();
  526.     for (unsigned int row = 0; row < pg_tall; ++row) {
  527.         //const TAlignment valign = m_PanelGrid->GetVAlign(row);
  528.         for (unsigned int col = 0; col < pg_wide; ++col, ++panel_num) {
  529.             //const TAlignment halign = m_PanelGrid->GetHAlign(col);
  530.             const CRef<CPanel> panel = m_PanelGrid->GetPanel(col, row);
  531.             //
  532.             // create printer's marks
  533.             //
  534.             TPdfObjectRef printers_marks = x_CreatePrintersMarks(panel);
  535.             m_ObjWriter->WriteObject(printers_marks);
  536.             //
  537.             // offset the page (alignment)
  538.             //
  539.             TPdfObjectRef page_xform = x_CreatePageXForm(panel);
  540.             m_ObjWriter->WriteObject(page_xform);
  541.             //
  542.             // set the page contents
  543.             //
  544.             CRef<CPdfArray> contents(new CPdfArray());
  545.             CPdfArray::TArray& carr = contents->GetArray();
  546.             ITERATE(vector<TPdfObjectRef>, it, m_StdContents) {
  547.                 carr.push_back(CRef<CPdfObj>(new CPdfIndirectObj(*it)));
  548.             }
  549.             carr.push_back(CRef<CPdfObj>(new CPdfIndirectObj(printers_marks)));
  550.             carr.push_back(CRef<CPdfObj>(new CPdfIndirectObj(m_Clip)));
  551.             carr.push_back(CRef<CPdfObj>(new CPdfIndirectObj(page_xform)));
  552.             carr.push_back(CRef<CPdfObj>(new CPdfIndirectObj(m_ContentPagesXForm)));
  553.             carr.push_back(CRef<CPdfObj>(new CPdfIndirectObj(m_Content)));
  554.             x_CreatePage(panel->m_Panel, contents);
  555.         }
  556.     }
  557.     return m_PanelGrid->GetNumPanels();
  558. }
  559. void CPageHandler::x_CreatePage(TPdfObjectRef page, CRef<CPdfArray>& contents)
  560. {
  561.     // create page object
  562.     CPdfObject& pageobj = *page;
  563.     m_Pages.push_back(page);
  564.     pageobj["Type"] = new CPdfName("Page");
  565.     pageobj["Parent"] = new CPdfIndirectObj(m_PageTreeRootObj);
  566.     pageobj["Contents"] = contents;
  567.     //
  568.     // output the page
  569.     //
  570.     m_ObjWriter->WriteObject(page);
  571. }
  572. END_NCBI_SCOPE
  573. /*
  574.  * ===========================================================================
  575.  * $Log: page_handler.cpp,v $
  576.  * Revision 1000.1  2004/06/01 21:03:36  gouriano
  577.  * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.17
  578.  *
  579.  * Revision 1.17  2004/05/21 22:27:50  gorelenk
  580.  * Added PCH ncbi_pch.hpp
  581.  *
  582.  * Revision 1.16  2003/10/14 15:53:13  meric
  583.  * Add page header/footer object only if a header or footer is provided
  584.  *
  585.  * Revision 1.15  2003/08/15 17:02:15  meric
  586.  * Updates include paths for print-related files from gui/utils to gui/print
  587.  *
  588.  * Revision 1.14  2003/06/25 18:02:51  meric
  589.  * Source rearrangement: move "private" headers into the src/ tree
  590.  *
  591.  * Revision 1.13  2003/06/24 22:37:44  meric
  592.  * renamed struct Neighbours to struct SNeighbours, removed TNeighbours typedef
  593.  *
  594.  * Revision 1.12  2003/06/24 21:07:07  meric
  595.  * Only add Annots entry to Page object if there is at least one annotation
  596.  *
  597.  * Revision 1.11  2003/06/24 18:11:12  meric
  598.  * Further conversions from unsigned int -> CUnit::TPdfUnit
  599.  *
  600.  * Revision 1.10  2003/06/24 17:27:03  meric
  601.  * Use CUnit::TPdfUnit
  602.  *
  603.  * Revision 1.9  2003/06/24 15:53:25  meric
  604.  * Added x_GetPageScaling() and x_GetPanelOffset(), from CPrintOptions
  605.  * Added x_GetPanelOffset(), x_DrawPanelLink() and misc functions
  606.  * Improved printer's marks to include hyperlinked references to neighbouring
  607.  * panels and corner crop marks
  608.  *
  609.  * Revision 1.8  2003/06/18 17:25:38  meric
  610.  * Final phase of print reorg: remove dependence on gui/opengl and OpenGL
  611.  *
  612.  * Revision 1.7  2003/06/18 16:40:33  meric
  613.  * First phase of print reorg: remove dependence on gui/opengl and OpenGL
  614.  * except for class COpenGLPrintBuffer
  615.  *
  616.  * Revision 1.6  2003/06/17 18:58:08  meric
  617.  * Remove inline qualifier for x_GetScaledPageSize()
  618.  *
  619.  * Revision 1.5  2003/06/16 21:16:52  meric
  620.  * Added multi-page support
  621.  *
  622.  * Revision 1.4  2003/06/16 19:16:33  meric
  623.  * Fixed member initialization order in c'tor to match declaration order
  624.  *
  625.  * Revision 1.3  2003/06/16 15:59:11  dicuccio
  626.  * Work-in-progress: everything compiles, still much reorganization to be done.
  627.  * Moved generic functionality out of opengl/print/ and into gui/utils (print
  628.  * options, print dialogs, etc.).  Removed interactive state from CGlCanvas.
  629.  * Added hook in CView for opening standard print dialog, and for generic print
  630.  * handling.  Restored log for glcanvas.cpp
  631.  *
  632.  * Revision 1.2  2003/06/16 12:44:52  dicuccio
  633.  * Clean-up after initial commit
  634.  *
  635.  * Revision 1.1  2003 / 06 / 13 18:13:56  meric
  636.  * Initial version
  637.  *
  638.  *
  639.  * ===========================================================================
  640.  */