page_handler.cpp

来自「ncbi源码」· C++ 代码 · 共 774 行 · 第 1/2 页

CPP
774
字号
/* * =========================================================================== * PRODUCTION $Log: page_handler.cpp,v $ * PRODUCTION Revision 1000.1  2004/06/01 21:03:36  gouriano * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.17 * PRODUCTION * =========================================================================== *//*  $Id: page_handler.cpp,v 1000.1 2004/06/01 21:03:36 gouriano Exp $ * =========================================================================== * *                            PUBLIC DOMAIN NOTICE *               National Center for Biotechnology Information * *  This software / database is a "United States Government Work" under the *  terms of the United States Copyright Act.  It was written as part of *  the author's official duties as a United States Government employee and *  thus cannot be copyrighted.  This software / database is freely available *  to the public for use. The National Library of Medicine and the U.S. *  Government have not placed any restriction on its use or reproduction. * *  Although all reasonable efforts have been taken to ensure the accuracy *  and reliability of the software and data, the NLM and the U.S. *  Government do not and cannot warrant the performance or results that *  may be obtained by using this software or data. The NLM and the U.S. *  Government disclaim all warranties, express or implied, including *  warranties of performance, merchantability or fitness for any particular *  purpose. * *  Please cite the author in any work or product based on this material. * * =========================================================================== * * Authors:  Peter Meric * * File Description: *   CPageHandler - manage pages in a PDF document */#include <ncbi_pch.hpp>#include <gui/print/print_options.hpp>#include <gui/print/print_utils.hpp>#include <gui/utils/id_generator.hpp>#include "page_handler.hpp"#include "pdf_object.hpp"#include "pdf_object_writer.hpp"#include "pdf_obj.hpp"#include "panel_grid.hpp"BEGIN_NCBI_SCOPECPageHandler::CPageHandler(const CPageBuffers& buffers,                           CPdfObjectWriter& obj_writer,                           CIdGenerator& objid_gen                          ): m_ObjWriter(&obj_writer),  m_ObjIdGenerator(&objid_gen),  m_PageTreeRootObj(new CPdfObject(m_ObjIdGenerator->NextId())),  m_PageBuffers(&buffers){}CPageHandler::~CPageHandler(){}CPageHandler::TPdfObjectRef CPageHandler::GetObject(void) const{    return m_PageTreeRootObj;}void CPageHandler::SetOptions(const CPrintOptions& options){    m_Options = &options;    const unsigned int pg_wide = m_Options->GetPagesWide();    const unsigned int pg_tall = m_Options->GetPagesTall();    m_PanelGrid.Reset(new CPanelGrid(*m_ObjIdGenerator, pg_wide, pg_tall));}void CPageHandler::x_Update(const CRef<CPdfDictionary>& pagedict){    x_UpdatePageTreeRoot(pagedict);}void CPageHandler::x_UpdatePageTreeRoot(const CRef<CPdfDictionary>& pagedict){    CPdfObject& root = *m_PageTreeRootObj;    root["Type"] = new CPdfName("Pages");    root["Count"] = new CPdfNumber(int(m_Pages.size()));    root["Rotate"] = new CPdfNumber(int(m_Options->GetPageOrientation()));    CRef<CPdfArray> kids(new CPdfArray());    ITERATE(vector<TPdfObjectRef>, it, m_Pages) {        kids->GetArray().push_back(CRef<CPdfObj>(new CPdfIndirectObj(*it)));    }    root["Kids"] = kids;    CRef<CPdfArray> mediabox(new CPdfArray());    CPdfArray::TArray& mbarr = mediabox->GetArray();    mbarr.push_back(CRef<CPdfObj>(new CPdfNumber(int(0))));    mbarr.push_back(CRef<CPdfObj>(new CPdfNumber(int(0))));    mbarr.push_back(CRef<CPdfObj>(new CPdfNumber(int(m_Options->GetMediaWidth()))));    mbarr.push_back(CRef<CPdfObj>(new CPdfNumber(int(m_Options->GetMediaHeight()))));    root["MediaBox"] = mediabox;    /*       root  << "     %/TrimBox [ "       << xs.first << ' ' << ys.first << ' '       << xs.second << ' ' << ys.second << " ]" << endl;       */    CRef<CPdfArray> procset(new CPdfArray());    CPdfArray::TArray& pset = procset->GetArray();    pset.push_back(CRef<CPdfObj>(new CPdfObj("/PDF")));    pset.push_back(CRef<CPdfObj>(new CPdfObj("/Text")));    //res["ProcSet"] = procset;    CPdfDictionary& dict = root.GetDictionary();    dict.Add(pagedict);    CRef<CPdfObj>& res = dict["Resources"];    if ( !res ) {        CRef<CPdfDictionary> resources(new CPdfDictionary());        (*resources)["ProcSet"] = procset;        res = resources;    } else {        CRef<CPdfDictionary> _res(dynamic_cast < CPdfDictionary*>(res.GetPointer()));        (*_res)["ProcSet"] = procset;    }}CPageHandler::TPdfObjectRef CPageHandler::x_CreateHeaderFooter(void){    TPdfObjectRef hf_obj;    const string header(m_Options->GetHeader());    const string footer(m_Options->GetFooter());    const bool has_header = header.length() > 0;    const bool has_footer = footer.length() > 0;    if (has_header || has_footer) {        hf_obj.Reset(new CPdfObject(m_ObjIdGenerator->NextId()));        CPdfObject& obj = *hf_obj;        obj << "0 0 m n" << pdfbrk;        obj << "0 0 0 rg" << pdfbrk;        if (has_header) {            obj << "BT" << pdfbrk;            const TPdfUnit font_size = 8;            obj << "/F1 " << font_size << " Tf" << pdfbrk;            const TPdfUnit str_w = font_size * header.length();            obj << (m_Options->GetMediaWidth() - str_w) / 2 << ' '                << m_Options->GetMediaHeight() - m_Options->GetHeaderOffset() - font_size << " Td" << pdfbrk;            obj << CPdfString(header) << "Tj" << pdfbrk;            obj << "ET" << pdfbrk;        }        if (has_footer) {            obj << "BT" << pdfbrk;            const TPdfUnit font_size = 8;            obj << "/F2 " << font_size << " Tf" << pdfbrk;            const TPdfUnit str_w = font_size * footer.length();            obj << (m_Options->GetMediaWidth() - str_w) / 2 << ' '                << m_Options->GetFooterOffset() << " Td" << pdfbrk;            obj << CPdfString(footer) << "Tj" << pdfbrk;            obj << "ET" << pdfbrk;        }    }    return hf_obj;}CPageHandler::TPdfObjectRef CPageHandler::x_CreatePrintersMarks(const CRef<CPanel>& panel){    TPdfObjectRef pmarks_obj(new CPdfObject(m_ObjIdGenerator->NextId()));    CPdfObject& pmarks = *pmarks_obj;    // create printer's marks, page alignment etc    pmarks << "0 0 m n" << pdfbrk;    pmarks << "0 0 0 rg" << pdfbrk;    pmarks << "BT" << pdfbrk;    pmarks << CPdfName("F1") << ' ' << CPdfNumber(8) << " Tf" << pdfbrk;    //    // output current panel number    //    const string pstr("Panel " + NStr::IntToString(panel->m_PanelNum)                      + " of " + NStr::IntToString(m_Options->GetNumPages())                     );    const string::size_type pstr_len(pstr.length() * 8);    pmarks << CPdfNumber(m_Options->GetMediaWidth() - pstr_len - 30) << ' '           << CPdfNumber(m_Options->GetMediaHeight() - 20) << " Td" << pdfbrk;    pmarks << CPdfString(pstr) << "Tj" << pdfbrk;    pmarks << "ET" << pdfbrk;    //    // corner crop marks    //    x_DrawCornerCropMarks(pmarks, 8);    //    // print neighbour pointers (links)    //    const CPanelGrid::SNeighbours n = m_PanelGrid->GetNeighbours(panel->m_Col, panel->m_Row);    TPdfObjectRef panelref = panel->m_Panel;    CPdfObject& panelobj = *panelref;    CRef<CPdfArray> annots(new CPdfArray());    const TPdfUnit link_margin = 30;    // draw top    if (n.top) {        const TPdfUnit x = m_Options->GetMediaWidth() / 2;        const TPdfUnit y = m_Options->GetMediaHeight() - link_margin;        annots->Add(x_DrawPanelLink(pmarks, n.top->m_PanelNum, x, y));    }    // draw bottom    if (n.bottom) {        const TPdfUnit x = m_Options->GetMediaWidth() / 2;        const TPdfUnit y = link_margin - 10;        annots->Add(x_DrawPanelLink(pmarks, n.bottom->m_PanelNum, x, y, eBottom));    }    // draw left    if (n.left) {        const TPdfUnit x = link_margin;        const TPdfUnit y = m_Options->GetMediaHeight() / 2;        annots->Add(x_DrawPanelLink(pmarks, n.left->m_PanelNum, x, y, eLeft));    }    // draw right    if (n.right) {        const TPdfUnit x = m_Options->GetMediaWidth() - link_margin;        const TPdfUnit y = m_Options->GetMediaHeight() / 2;        annots->Add(x_DrawPanelLink(pmarks, n.right->m_PanelNum, x, y, eRight));    }    if (annots->GetArray().size() > 0) {        panelobj["Annots"] = annots;    }    return pmarks_obj;}void CPageHandler::x_DrawCornerCropMarks(CPdfObject& obj, TPdfUnit margin) const{    const TPdfUnit cmark_len = 20;    const TPdfUnit cm_l = m_Options->GetMarginLeft();    const TPdfUnit cm_lm = cm_l - margin;    const TPdfUnit cm_t = m_Options->GetMediaHeight() - m_Options->GetMarginTop();    const TPdfUnit cm_tm = cm_t + margin;    const TPdfUnit cm_r = m_Options->GetMediaWidth() - m_Options->GetMarginRight();    const TPdfUnit cm_rm = cm_r + margin;    const TPdfUnit cm_b = m_Options->GetMarginBottom();    const TPdfUnit cm_bm = cm_b - margin;    // top left    obj << cm_lm - cmark_len << ' ' << cm_t << " m "        << cm_lm << ' ' << cm_t << " l s" << pdfbrk;    obj << cm_l << ' ' << cm_tm + cmark_len << " m "        << cm_l << ' ' << cm_tm << " l s" << pdfbrk;    // top right    obj << cm_rm + cmark_len << ' ' << cm_t << " m "        << cm_rm << ' ' << cm_t << " l s" << pdfbrk;    obj << cm_r << ' ' << cm_tm + cmark_len << " m "        << cm_r << ' ' << cm_tm << " l s" << pdfbrk;    // bottom left    obj << cm_lm - cmark_len << ' ' << cm_b << " m "        << cm_lm << ' ' << cm_b << " l s" << pdfbrk;    obj << cm_l << ' ' << cm_bm - cmark_len << " m "        << cm_l << ' ' << cm_bm << " l s" << pdfbrk;    // bottom right    obj << cm_rm + cmark_len << ' ' << cm_b << " m "        << cm_rm << ' ' << cm_b << " l s" << pdfbrk;    obj << cm_r << ' ' << cm_bm - cmark_len << " m "        << cm_r << ' ' << cm_bm << " l s" << pdfbrk;}CRef<CPdfArray> CPageHandler::x_DrawPanelLink(CPdfObject& obj,                                              unsigned int panel_num,                                              TPdfUnit x,                                              TPdfUnit y,                                              enum Side side                                             ) const{    const TPdfUnit link_width = 44;    const TPdfUnit link_width2 = link_width / 2;    const TPdfUnit fnt_h = 8;    TPdfUnit xlate_x;    TPdfUnit xlate_y;    int rot;    switch (side) {    case (eTop):    case (eBottom):        rot = (side == eTop) ? 0 : 180;        xlate_x = x - link_width2;        xlate_y = y;        break;    case (eLeft):        rot = 90;        xlate_x = x;        xlate_y = y - link_width2;        break;    case (eRight):        rot = 270;        xlate_x = x;        xlate_y = y + link_width2;        break;    }    obj << CPdfObj("q") << pdfbrk;    obj << CPdfTranslate(xlate_x, xlate_y) << pdfbrk;    if (side == eLeft || side == eRight) {        obj << CPdfRotate(rot) << pdfbrk;        rot = 0; // don't rotate again    }    obj << "BT" << pdfbrk;    //obj << CPdfName("F1") << ' ' << CPdfNumber(8) << " Tf" << pdfbrk;    const string txt("Panel " + NStr::IntToString(panel_num));    obj << "4 1 Td" << pdfbrk;    obj << CPdfString(txt) << "Tj" << pdfbrk;    obj << "ET" << pdfbrk;    if (rot != 0) {        obj << CPdfRotate(rot) << pdfbrk;    }    if (side == eBottom) {        // if upside down, then offset the triangles according to the text        obj << CPdfTranslate(-int(link_width), -int(fnt_h)) << pdfbrk;    }    obj << CPdfObj("0.416 0.549 0.792 rg") << pdfbrk;    const TPdfUnit _margin = 3;    const TPdfUnit tri_w = 16;    const TPdfUnit tri_h = 8;    x_DrawTriangle(obj, link_width / 2, fnt_h + _margin, tri_w, tri_h);    CRef<CPdfArray> annots(new CPdfArray());    CRef<CPdfDictionary> link_annot(new CPdfDictionary());    CPdfDictionary& link = *link_annot;    link["Type"] = new CPdfName("Annot");    link["Subtype"] = new CPdfName("Link");    string _x1, _x2, _y1, _y2;    switch (side) {    case (eTop):    case (eBottom):        _x1 = NStr::IntToString(int(x - link_width2 - _margin));        _y1 = NStr::IntToString(int(y - _margin));        _x2 = NStr::IntToString(int(x + link_width2 + _margin));        _y2 = NStr::IntToString(int(y + fnt_h + _margin));        break;    case (eLeft):    case (eRight):        {            const bool left = (side == eLeft);            _x1 = NStr::IntToString(int(x + (left ? 1 : -1) * _margin));            _y1 = NStr::IntToString(int(y + link_width2 + _margin));            _x2 = NStr::IntToString(int(x + (left ? -1 : 1) * (fnt_h + _margin)));            _y2 = NStr::IntToString(int(y - link_width2 - _margin));

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?