示例#1
0
void PDFDocument::PDFOutlineItem::BuildRecursive(
    fz_outline* src,
    std::vector<std::unique_ptr<Document::OutlineItem>>* output) {
  assert(output != nullptr);
  for (fz_outline* i = src; i != nullptr; i = i->next) {
    PDFOutlineItem* item = new PDFOutlineItem(i);
    if (i->down != nullptr) {
      BuildRecursive(i->down, &(item->_children));
    }
    output->push_back(std::unique_ptr<Document::OutlineItem>(item));
  }
}
示例#2
0
PDFDocument::PDFOutlineItem* PDFDocument::PDFOutlineItem::Build(
    fz_context* ctx, fz_outline* src) {
  PDFOutlineItem* root = nullptr;
  std::vector<std::unique_ptr<OutlineItem>> items;
  BuildRecursive(src, &items);
  fz_drop_outline(ctx, src);
  if (items.empty()) {
    return nullptr;
  } else if (items.size() == 1) {
    root =  dynamic_cast<PDFOutlineItem*>(items[0].release());
  } else {
    root = new PDFOutlineItem(nullptr);
    root->_title = DEFAULT_ROOT_OUTLINE_ITEM_TITLE;
    root->_children.swap(items);
  }
  return root;
}
示例#3
0
PDFDocument::PDFOutlineItem *PDFDocument::PDFOutlineItem::Build(
    fz_context *ctx, fz_outline *src) {
  PDFOutlineItem *root = nullptr;
  std::vector<std::unique_ptr<OutlineItem>> items;
  BuildRecursive(src, &items);
  fz_free_outline(ctx, src);
  if (items.empty()) {
    return nullptr;
  } else if (items.size() == 1) {
    root =  dynamic_cast<PDFOutlineItem *>(items[0].release());
  } else {
    root = new PDFOutlineItem(nullptr);
    root->_title = "TABLE OF CONTENTS";
    root->_children.swap(items);
  }
  return root;
}
示例#4
0
void QuadTree::Build(Scene * scene)
{
    SafeDelete(head);
    
    List<MeshInstanceNode*> meshNodes;
    scene->GetChildNodes(meshNodes);
    
    AABBox3 sceneBoundingBox = scene->GetWTMaximumBoundingBox();
    //Logger::Debug("min(%f, %f, %f)-max(%f, %f, %f)", sceneBoundingBox.min.x, sceneBoundingBox.min.y, sceneBoundingBox.min.z, sceneBoundingBox.max.x, sceneBoundingBox.max.y, sceneBoundingBox.max.z);
    head = cache.New();
    head->SetBoundingBox(sceneBoundingBox);
    
    nodeCount = 1;
    Logger::Debug("Objects in quad-tree: %d", meshNodes.size());
    uint64 buildTime = SystemTimer::Instance()->AbsoluteMS();
    BuildRecursive(head, meshNodes);
    buildTime = SystemTimer::Instance()->AbsoluteMS() - buildTime;
    Logger::Debug("Nodes in quad-tree: %d. Build time: %lld", nodeCount, buildTime);
}
示例#5
0
void QuadTree::BuildRecursive(QuadTreeNode * node, List<MeshInstanceNode*> & meshNodes)
{
    cache.Reset();
    
    //meshNodes
    AABBox3 bbox = node->GetBoundingBox();
    
    AABBox3 childBoxes[4]; 
    Vector3 halfSize = (bbox.max - bbox.min) / 2.0f;
    childBoxes[0] = AABBox3(Vector3(bbox.min.x, bbox.min.y, bbox.min.z), Vector3(bbox.min.x + halfSize.x, bbox.min.y + halfSize.y, bbox.max.z));
    childBoxes[1] = AABBox3(Vector3(bbox.min.x + halfSize.x, bbox.min.y, bbox.min.z), Vector3(bbox.max.x, bbox.min.y + halfSize.y, bbox.max.z));
    childBoxes[2] = AABBox3(Vector3(bbox.min.x, bbox.min.y + halfSize.y, bbox.min.z), Vector3(bbox.min.x + halfSize.x, bbox.max.y, bbox.max.z));
    childBoxes[3] = AABBox3(Vector3(bbox.min.x + halfSize.x, bbox.min.y + halfSize.y, bbox.min.z), Vector3(bbox.max.x, bbox.max.y, bbox.max.z));
    
    AABBox3 realChildBox[4];
    
    int32 childCount[4] = {0, 0, 0, 0};
    List<MeshInstanceNode*> childLists[4];
    
    for (List<MeshInstanceNode*>::iterator it = meshNodes.begin(); it != meshNodes.end();)
    {
        MeshInstanceNode * mesh = *it;
        bool nodeIn = false;
        for (int k = 0; k < 4; ++k)
        {
            const AABBox3 & bbox = mesh->GetWTMaximumBoundingBox();
            if (childBoxes[k].IsInside(bbox))
            {
                childCount[k]++;
                childLists[k].push_back(mesh);
                realChildBox[k].AddAABBox(bbox);
                nodeIn = true;
                break;
            }
        }
        if (nodeIn)
        {
            it = meshNodes.erase(it);
        }else
        {
            it++;
        }
        
    }
    
    //for (each new node where number of nodes inside is not 0 build recursively) 
    for (int k = 0; k < 4; ++k)
    {
        if (childCount[k] > 0)
        {
            nodeCount++;
            node->children[k] = cache.New();
            node->children[k]->SetBoundingBox(realChildBox[k]);
            BuildRecursive(node->children[k], childLists[k]);
        }
    }    
    
    // all objects that are not in childs remains in this node
    for (List<MeshInstanceNode*>::iterator it = meshNodes.begin(); it != meshNodes.end(); ++it)
    {
        node->objectsInside.push_back(SafeRetain(*it));
    }
}
示例#6
0
std::string PDFDocument::GetPageText(int page, int line_sep) {
  // 1. Init MuPDF structures.
  pdf_page* page_struct = GetPage(page);

#if MUPDF_VERSION < 10012
  fz_stext_sheet* text_sheet = fz_new_stext_sheet(_fz_context);
#endif

  // 2. Render page.
#if MUPDF_VERSION >= 10012
  fz_stext_options stext_options = {0};
  // See #elif MUPDF_VERSION >= 10009 block below.
  fz_stext_page* text_page = fz_new_stext_page_from_page(
      _fz_context, &(page_struct->super), &stext_options);
#elif MUPDF_VERSION >= 10010
  fz_stext_options stext_options = {0};
  // See #elif MUPDF_VERSION >= 10009 block below.
  fz_stext_page* text_page = fz_new_stext_page_from_page(
      _fz_context, &(page_struct->super), text_sheet, &stext_options);
#elif MUPDF_VERSION >= 10009
  // The function below is a wrapper around fz_run_page that uses a fresh
  // device. We can't use pdf_run_page to gather the text for us.
  // These notes are also left in here in case MuPDF's API changes again.
  fz_stext_page* text_page = fz_new_stext_page_from_page(
      _fz_context, &(page_struct->super), text_sheet);
#else
  fz_stext_page* text_page = fz_new_text_page(_fz_context);
  fz_device* dev = fz_new_stext_device(_fz_context, text_sheet, text_page);
  // I've no idea what fz_{begin,end}_page do, but without them pdf_run_page
  // segfaults :-/
  fz_begin_page(_fz_context, dev, &fz_infinite_rect, &fz_identity);
  pdf_run_page(
      _fz_context, _pdf_document, page_struct, dev, &fz_identity, nullptr);
  fz_end_page(_fz_context, dev);
#endif

  // 3. Build text.
  std::string r;
#if MUPDF_VERSION >= 10012
  for (fz_stext_block* text_block = text_page->first_block;
       text_block != nullptr; text_block = text_block->next) {
    if (text_block->type != FZ_STEXT_BLOCK_TEXT) {
      continue;
    }
    for (fz_stext_line* text_line = text_block->u.t.first_line;
         text_line != nullptr; text_line = text_line->next) {
      for (fz_stext_char* text_char = text_line->first_char;
           text_char != nullptr; text_char = text_char->next) {
        {
          const int c = text_char->c;
#else
  for (fz_page_block* page_block = text_page->blocks;
       page_block < text_page->blocks + text_page->len; ++page_block) {
    assert(page_block != nullptr);
    if (page_block->type != FZ_PAGE_BLOCK_TEXT) {
      continue;
    }
    fz_stext_block* const text_block = page_block->u.text;
    assert(text_block != nullptr);
    for (fz_stext_line* text_line = text_block->lines;
         text_line < text_block->lines + text_block->len; ++text_line) {
      assert(text_line != nullptr);
      for (fz_stext_span* text_span = text_line->first_span;
           text_span != nullptr; text_span = text_span->next) {
        for (int i = 0; i < text_span->len; ++i) {
          const int c = text_span->text[i].c;
#endif
          // A single UTF-8 character cannot take more than 4 bytes, but let's
          // go for 8.
          char buffer[8];
          const int num_bytes = fz_runetochar(buffer, c);
          assert(num_bytes <= static_cast<int>(sizeof(buffer)));
          buffer[num_bytes] = '\0';
          r += buffer;
        }
      }
      if (!isspace(r.back())) {
        r += line_sep;
      }
    }
  }

  // 4. Clean up.
  fz_drop_stext_page(_fz_context, text_page);
#if MUPDF_VERSION < 10012
  fz_drop_stext_sheet(_fz_context, text_sheet);
#endif

  return r;
}

PDFDocument::PDFOutlineItem::~PDFOutlineItem() {}

PDFDocument::PDFOutlineItem::PDFOutlineItem(fz_outline* src) {
  if (src == nullptr) {
    _dest_page = -1;
  } else {
    _title = src->title;
#if MUPDF_VERSION >= 10010
    _dest_page = src->page;
#else
    _dest_page = src->dest.ld.gotor.page;
#endif
  }
}

int PDFDocument::PDFOutlineItem::GetDestPage() const { return _dest_page; }

PDFDocument::PDFOutlineItem* PDFDocument::PDFOutlineItem::Build(
    fz_context* ctx, fz_outline* src) {
  PDFOutlineItem* root = nullptr;
  std::vector<std::unique_ptr<OutlineItem>> items;
  BuildRecursive(src, &items);
  fz_drop_outline(ctx, src);
  if (items.empty()) {
    return nullptr;
  } else if (items.size() == 1) {
    root = dynamic_cast<PDFOutlineItem*>(items[0].release());
  } else {
    root = new PDFOutlineItem(nullptr);
    root->_title = DEFAULT_ROOT_OUTLINE_ITEM_TITLE;
    root->_children.swap(items);
  }
  return root;
}

void PDFDocument::PDFOutlineItem::BuildRecursive(
    fz_outline* src,
    std::vector<std::unique_ptr<Document::OutlineItem>>* output) {
  assert(output != nullptr);
  for (fz_outline* i = src; i != nullptr; i = i->next) {
    PDFOutlineItem* item = new PDFOutlineItem(i);
    if (i->down != nullptr) {
      BuildRecursive(i->down, &(item->_children));
    }
    output->push_back(std::unique_ptr<Document::OutlineItem>(item));
  }
}

PDFDocument::PDFPageCache::PDFPageCache(int cache_size, PDFDocument* parent)
    : Cache<int, pdf_page*>(cache_size), _parent(parent) {}

PDFDocument::PDFPageCache::~PDFPageCache() { Clear(); }

pdf_page* PDFDocument::PDFPageCache::Load(const int& page) {
  std::unique_lock<std::mutex> lock(_mutex);
  return pdf_load_page(_parent->_fz_context, _parent->_pdf_document, page);
}

void PDFDocument::PDFPageCache::Discard(
    const int& page, pdf_page* const& page_struct) {
  std::unique_lock<std::mutex> lock(_mutex);
  pdf_drop_page(_parent->_fz_context, _parent->_pdf_document, page_struct);
}