|
Packit |
df99a1 |
//C- -*- C++ -*-
|
|
Packit |
df99a1 |
//C- -------------------------------------------------------------------
|
|
Packit |
df99a1 |
//C- DjVuLibre-3.5
|
|
Packit |
df99a1 |
//C- Copyright (c) 2002 Leon Bottou and Yann Le Cun.
|
|
Packit |
df99a1 |
//C- Copyright (c) 2001 AT&T
|
|
Packit |
df99a1 |
//C-
|
|
Packit |
df99a1 |
//C- This software is subject to, and may be distributed under, the
|
|
Packit |
df99a1 |
//C- GNU General Public License, either Version 2 of the license,
|
|
Packit |
df99a1 |
//C- or (at your option) any later version. The license should have
|
|
Packit |
df99a1 |
//C- accompanied the software or you may obtain a copy of the license
|
|
Packit |
df99a1 |
//C- from the Free Software Foundation at http://www.fsf.org .
|
|
Packit |
df99a1 |
//C-
|
|
Packit |
df99a1 |
//C- This program is distributed in the hope that it will be useful,
|
|
Packit |
df99a1 |
//C- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
df99a1 |
//C- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit |
df99a1 |
//C- GNU General Public License for more details.
|
|
Packit |
df99a1 |
//C-
|
|
Packit |
df99a1 |
//C- DjVuLibre-3.5 is derived from the DjVu(r) Reference Library from
|
|
Packit |
df99a1 |
//C- Lizardtech Software. Lizardtech Software has authorized us to
|
|
Packit |
df99a1 |
//C- replace the original DjVu(r) Reference Library notice by the following
|
|
Packit |
df99a1 |
//C- text (see doc/lizard2002.djvu and doc/lizardtech2007.djvu):
|
|
Packit |
df99a1 |
//C-
|
|
Packit |
df99a1 |
//C- ------------------------------------------------------------------
|
|
Packit |
df99a1 |
//C- | DjVu (r) Reference Library (v. 3.5)
|
|
Packit |
df99a1 |
//C- | Copyright (c) 1999-2001 LizardTech, Inc. All Rights Reserved.
|
|
Packit |
df99a1 |
//C- | The DjVu Reference Library is protected by U.S. Pat. No.
|
|
Packit |
df99a1 |
//C- | 6,058,214 and patents pending.
|
|
Packit |
df99a1 |
//C- |
|
|
Packit |
df99a1 |
//C- | This software is subject to, and may be distributed under, the
|
|
Packit |
df99a1 |
//C- | GNU General Public License, either Version 2 of the license,
|
|
Packit |
df99a1 |
//C- | or (at your option) any later version. The license should have
|
|
Packit |
df99a1 |
//C- | accompanied the software or you may obtain a copy of the license
|
|
Packit |
df99a1 |
//C- | from the Free Software Foundation at http://www.fsf.org .
|
|
Packit |
df99a1 |
//C- |
|
|
Packit |
df99a1 |
//C- | The computer code originally released by LizardTech under this
|
|
Packit |
df99a1 |
//C- | license and unmodified by other parties is deemed "the LIZARDTECH
|
|
Packit |
df99a1 |
//C- | ORIGINAL CODE." Subject to any third party intellectual property
|
|
Packit |
df99a1 |
//C- | claims, LizardTech grants recipient a worldwide, royalty-free,
|
|
Packit |
df99a1 |
//C- | non-exclusive license to make, use, sell, or otherwise dispose of
|
|
Packit |
df99a1 |
//C- | the LIZARDTECH ORIGINAL CODE or of programs derived from the
|
|
Packit |
df99a1 |
//C- | LIZARDTECH ORIGINAL CODE in compliance with the terms of the GNU
|
|
Packit |
df99a1 |
//C- | General Public License. This grant only confers the right to
|
|
Packit |
df99a1 |
//C- | infringe patent claims underlying the LIZARDTECH ORIGINAL CODE to
|
|
Packit |
df99a1 |
//C- | the extent such infringement is reasonably necessary to enable
|
|
Packit |
df99a1 |
//C- | recipient to make, have made, practice, sell, or otherwise dispose
|
|
Packit |
df99a1 |
//C- | of the LIZARDTECH ORIGINAL CODE (or portions thereof) and not to
|
|
Packit |
df99a1 |
//C- | any greater extent that may be necessary to utilize further
|
|
Packit |
df99a1 |
//C- | modifications or combinations.
|
|
Packit |
df99a1 |
//C- |
|
|
Packit |
df99a1 |
//C- | The LIZARDTECH ORIGINAL CODE is provided "AS IS" WITHOUT WARRANTY
|
|
Packit |
df99a1 |
//C- | OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
|
Packit |
df99a1 |
//C- | TO ANY WARRANTY OF NON-INFRINGEMENT, OR ANY IMPLIED WARRANTY OF
|
|
Packit |
df99a1 |
//C- | MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
|
|
Packit |
df99a1 |
//C- +------------------------------------------------------------------
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
#ifndef _DJVMDIR_H
|
|
Packit |
df99a1 |
#define _DJVMDIR_H
|
|
Packit |
df99a1 |
#ifdef HAVE_CONFIG_H
|
|
Packit |
df99a1 |
#include "config.h"
|
|
Packit |
df99a1 |
#endif
|
|
Packit |
df99a1 |
#if NEED_GNUG_PRAGMAS
|
|
Packit |
df99a1 |
# pragma interface
|
|
Packit |
df99a1 |
#endif
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/** @name DjVmDir.h
|
|
Packit |
df99a1 |
Files #"DjVmDir.h"# and #"DjVmDir.cpp"# implement class \Ref{DjVmDir} for
|
|
Packit |
df99a1 |
representing the directory of a DjVu multipage document.
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
{\bf Bundled vs. Indirect format} --- There are currently two multipage
|
|
Packit |
df99a1 |
DjVu formats supported: {\em bundled} and {\em indirect}. In the first
|
|
Packit |
df99a1 |
format all component files composing a given document are packaged (or
|
|
Packit |
df99a1 |
bundled) into one file, in the second one every page and component is
|
|
Packit |
df99a1 |
stored in a separate file and there is one more file, which contains the
|
|
Packit |
df99a1 |
list of all others.
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
{\bf Multipage DjVu format} --- Multipage DjVu documents follow the EA
|
|
Packit |
df99a1 |
IFF85 format (cf. \Ref{IFFByteStream.h}.) A document is composed of a
|
|
Packit |
df99a1 |
#"FORM:DJVM"# whose first chunk is a #"DIRM"# chunk containing the {\em
|
|
Packit |
df99a1 |
document directory}. This directory lists all component files composing
|
|
Packit |
df99a1 |
the given document, helps to access every component file and identify the
|
|
Packit |
df99a1 |
pages of the document.
|
|
Packit |
df99a1 |
\begin{itemize}
|
|
Packit |
df99a1 |
\item In a {\em bundled} multipage file, the component files
|
|
Packit |
df99a1 |
are stored immediately after the #"DIRM"# chunk,
|
|
Packit |
df99a1 |
within the #"FORM:DJVU"# composite chunk.
|
|
Packit |
df99a1 |
\item In an {\em indirect} multipage file, the component files are
|
|
Packit |
df99a1 |
stored in different files whose URLs are composed using information
|
|
Packit |
df99a1 |
stored in the #"DIRM"# chunk.
|
|
Packit |
df99a1 |
\end{itemize}
|
|
Packit |
df99a1 |
Most of the component files represent pages of a document. Some files
|
|
Packit |
df99a1 |
however represent data shared by several pages. The pages refer to these
|
|
Packit |
df99a1 |
supporting files by means of an inclusion chunk (#"INCL"# chunks)
|
|
Packit |
df99a1 |
identifying the supporting file.
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
{\bf Document Directory} --- Every directory record describes a component
|
|
Packit |
df99a1 |
file. Each component file is identified by a small string named the
|
|
Packit |
df99a1 |
identifier (ID). Each component file also contains a file name and a
|
|
Packit |
df99a1 |
title. The format of the #"DIRM"# chunk is described in section
|
|
Packit |
df99a1 |
\Ref{Format of the DIRM chunk.}.
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
Theoretically, IDs are used to uniquely identify each component file in
|
|
Packit |
df99a1 |
#"INCL"# chunks, names are used to compose the the URLs of the component
|
|
Packit |
df99a1 |
files in an indirect multipage DjVu file, and titles are cosmetic names
|
|
Packit |
df99a1 |
possibly displayed when viewing a page of a document. There are however
|
|
Packit |
df99a1 |
many problems with this scheme, and we {\em strongly suggest}, with the
|
|
Packit |
df99a1 |
current implementation to always make the file ID, the file name and the
|
|
Packit |
df99a1 |
file title identical.
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
@memo Implements DjVu multipage document directory
|
|
Packit |
df99a1 |
@author Andrei Erofeev <eaf@geocities.com>
|
|
Packit |
df99a1 |
*/
|
|
Packit |
df99a1 |
//@{
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
#include "GString.h"
|
|
Packit |
df99a1 |
#include "GThreads.h"
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
#ifdef HAVE_NAMESPACES
|
|
Packit |
df99a1 |
namespace DJVU {
|
|
Packit |
df99a1 |
# ifdef NOT_DEFINED // Just to fool emacs c++ mode
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
#endif
|
|
Packit |
df99a1 |
#endif
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
class ByteStream;
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/** Implements DjVu multipage document directory. There are currently two
|
|
Packit |
df99a1 |
multipage DjVu formats supported: {\em bundled} and {\em indirect}. In
|
|
Packit |
df99a1 |
the first format all component files composing a given document are
|
|
Packit |
df99a1 |
packaged (or bundled) into one file, in the second one every page and
|
|
Packit |
df99a1 |
component is stored in a separate file and there is one more file, which
|
|
Packit |
df99a1 |
contains the list of all others.
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
The multipage document directory lists all component files composing the
|
|
Packit |
df99a1 |
given document, helps to access every file, identify pages and maintain
|
|
Packit |
df99a1 |
user-specified shortcuts. Every directory record describes a file
|
|
Packit |
df99a1 |
composing the document. Each file is identified by a small string named
|
|
Packit |
df99a1 |
the identifier (ID). Each file may also contain a file name and a title.
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
The #DjVmDir# class represents a multipage document directory. Its main
|
|
Packit |
df99a1 |
purpose is to encode and decode the document directory when writing or
|
|
Packit |
df99a1 |
reading the #DIRM# chunk. Normally you don't have to create this class
|
|
Packit |
df99a1 |
yourself. It's done automatically when \Ref{DjVmDoc} class initializes
|
|
Packit |
df99a1 |
itself. It may be useful though to be able to access records in the
|
|
Packit |
df99a1 |
directory because some classes (like \Ref{DjVuDocument} and \Ref{DjVmDoc})
|
|
Packit |
df99a1 |
return a pointer to #DjVmDir# in some cases. */
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
class DJVUAPI DjVmDir : public GPEnabled
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
protected:
|
|
Packit |
df99a1 |
/** Class \Ref{DjVmDir::File} represents the directory records
|
|
Packit |
df99a1 |
managed by class \Ref{DjVmDir}. */
|
|
Packit |
df99a1 |
DjVmDir(void) { } ;
|
|
Packit |
df99a1 |
public:
|
|
Packit |
df99a1 |
class File;
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
static const int version;
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/** Class \Ref{DjVmDir::File} represents the directory records
|
|
Packit |
df99a1 |
managed by class \Ref{DjVmDir}. */
|
|
Packit |
df99a1 |
static GP<DjVmDir> create(void) {return new DjVmDir; } ;
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/** Decodes the directory from the specified stream. */
|
|
Packit |
df99a1 |
void decode(const GP<ByteStream> &stream);
|
|
Packit |
df99a1 |
/** Encodes the directory into the specified stream. */
|
|
Packit |
df99a1 |
void encode(const GP<ByteStream> &stream, const bool do_rename=false) const;
|
|
Packit |
df99a1 |
/** Encodes the directory into the specified stream,
|
|
Packit |
df99a1 |
explicitely as bundled or indirect. */
|
|
Packit |
df99a1 |
void encode(const GP<ByteStream> &stream,
|
|
Packit |
df99a1 |
const bool bundled, const bool do_rename) const;
|
|
Packit |
df99a1 |
/** Tests if directory defines an {\em indirect} document. */
|
|
Packit |
df99a1 |
inline bool is_indirect(void) const;
|
|
Packit |
df99a1 |
/** Tests if the directory defines a {\em bundled} document. */
|
|
Packit |
df99a1 |
inline bool is_bundled(void) const;
|
|
Packit |
df99a1 |
/** Translates page numbers to file records. */
|
|
Packit |
df99a1 |
GP<File> page_to_file(int page_num) const;
|
|
Packit |
df99a1 |
/** Translates file names to file records. */
|
|
Packit |
df99a1 |
GP<File> name_to_file(const GUTF8String & name) const;
|
|
Packit |
df99a1 |
/** Translates file IDs to file records. */
|
|
Packit |
df99a1 |
GP<File> id_to_file(const GUTF8String &id) const;
|
|
Packit |
df99a1 |
/** Translates file shortcuts to file records. */
|
|
Packit |
df99a1 |
GP<File> title_to_file(const GUTF8String &title) const;
|
|
Packit |
df99a1 |
/** Access file record by position. */
|
|
Packit |
df99a1 |
GP<File> pos_to_file(int fileno, int *ppageno=0) const;
|
|
Packit |
df99a1 |
/** Returns position of the file in the directory. */
|
|
Packit |
df99a1 |
int get_file_pos(const File * f) const;
|
|
Packit |
df99a1 |
/** Returns position of the given page in the directory. */
|
|
Packit |
df99a1 |
int get_page_pos(int page_num) const;
|
|
Packit |
df99a1 |
/** Check for duplicate names, and resolve them. */
|
|
Packit |
df99a1 |
GPList<File> resolve_duplicates(const bool save_as_bundled);
|
|
Packit |
df99a1 |
/** Returns a copy of the list of file records. */
|
|
Packit |
df99a1 |
GPList<File> get_files_list(void) const;
|
|
Packit |
df99a1 |
/** Returns the number of file records. */
|
|
Packit |
df99a1 |
int get_files_num(void) const;
|
|
Packit |
df99a1 |
/** Returns the number of file records representing pages. */
|
|
Packit |
df99a1 |
int get_pages_num(void) const;
|
|
Packit |
df99a1 |
/** Returns back pointer to the file with #SHARED_ANNO# flag.
|
|
Packit |
df99a1 |
Note that there may be only one file with shared annotations
|
|
Packit |
df99a1 |
in any multipage DjVu document. */
|
|
Packit |
df99a1 |
GP<File> get_shared_anno_file(void) const;
|
|
Packit |
df99a1 |
/** Changes the title of the file with ID #id#. */
|
|
Packit |
df99a1 |
void set_file_title(const GUTF8String &id, const GUTF8String &title);
|
|
Packit |
df99a1 |
/** Changes the name of the file with ID #id#. */
|
|
Packit |
df99a1 |
void set_file_name(const GUTF8String &id, const GUTF8String &name);
|
|
Packit |
df99a1 |
/** Inserts the specified file record at the specified position.
|
|
Packit |
df99a1 |
Specifying #pos# equal to #-1# means to append. The actual position
|
|
Packit |
df99a1 |
inserted is returned. */
|
|
Packit |
df99a1 |
int insert_file(const GP<File> & file, int pos=-1);
|
|
Packit |
df99a1 |
/** Removes a file record with ID #id#. */
|
|
Packit |
df99a1 |
void delete_file(const GUTF8String &id;;
|
|
Packit |
df99a1 |
private:
|
|
Packit |
df99a1 |
GCriticalSection class_lock;
|
|
Packit |
df99a1 |
GPList<File> files_list;
|
|
Packit |
df99a1 |
GPArray<File> page2file;
|
|
Packit |
df99a1 |
GPMap<GUTF8String, File> name2file;
|
|
Packit |
df99a1 |
GPMap<GUTF8String, File> id2file;
|
|
Packit |
df99a1 |
GPMap<GUTF8String, File> title2file;
|
|
Packit |
df99a1 |
private: //dummy stuff
|
|
Packit |
df99a1 |
static void decode(ByteStream *);
|
|
Packit |
df99a1 |
static void encode(ByteStream *);
|
|
Packit |
df99a1 |
};
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
class DJVUAPI DjVmDir::File : public GPEnabled
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
public:
|
|
Packit |
df99a1 |
// Out of the record: INCLUDE below must be zero and PAGE must be one.
|
|
Packit |
df99a1 |
// This is to avoid problems with the File constructor, which now takes
|
|
Packit |
df99a1 |
// 'int file_type' as the last argument instead of 'bool is_page'
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/** File type. Possible file types are:
|
|
Packit |
df99a1 |
\begin{description}
|
|
Packit |
df99a1 |
\item[PAGE] This is a top level page file. It may include other
|
|
Packit |
df99a1 |
#INCLUDE#d files, which may in turn be shared between
|
|
Packit |
df99a1 |
different pages.
|
|
Packit |
df99a1 |
\item[INCLUDE] This file is included into some other file inside
|
|
Packit |
df99a1 |
this document.
|
|
Packit |
df99a1 |
\item[THUMBNAILS] This file contains thumbnails for the document
|
|
Packit |
df99a1 |
pages.
|
|
Packit |
df99a1 |
\item[SHARED_ANNO] This file contains annotations shared by
|
|
Packit |
df99a1 |
all the pages. It's supposed to be included into every page
|
|
Packit |
df99a1 |
for the annotations to take effect. There may be only one
|
|
Packit |
df99a1 |
file with shared annotations in a document.
|
|
Packit |
df99a1 |
\end{description} */
|
|
Packit |
df99a1 |
enum FILE_TYPE { INCLUDE=0, PAGE=1, THUMBNAILS=2, SHARED_ANNO=3 };
|
|
Packit |
df99a1 |
protected:
|
|
Packit |
df99a1 |
/** Default constructor. */
|
|
Packit |
df99a1 |
File(void);
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
public:
|
|
Packit |
df99a1 |
static GP<File> create(void) { return new File(); }
|
|
Packit |
df99a1 |
static GP<File> create(const GUTF8String &load_name,
|
|
Packit |
df99a1 |
const GUTF8String &save_name, const GUTF8String &title,
|
|
Packit |
df99a1 |
const FILE_TYPE file_type);
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/** Check for filenames that are not valid for the native encoding,
|
|
Packit |
df99a1 |
and change them. */
|
|
Packit |
df99a1 |
const GUTF8String &check_save_name(const bool as_bundled);
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/** File name. The optional file name must be unique and is the name
|
|
Packit |
df99a1 |
that will be used when the document is saved to an indirect file.
|
|
Packit |
df99a1 |
If not assigned, the value of #id# will be used for this purpose.
|
|
Packit |
df99a1 |
By keeping the name in {\em bundled} document we guarantee, that it
|
|
Packit |
df99a1 |
can be expanded later into {\em indirect} document and files will
|
|
Packit |
df99a1 |
still have the same names, if the name is legal on a given filesystem.
|
|
Packit |
df99a1 |
*/
|
|
Packit |
df99a1 |
const GUTF8String &get_save_name(void) const;
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/** File identifier. The encoder assigns a unique identifier to each file
|
|
Packit |
df99a1 |
in a multipage document. This is the name used when loading files.
|
|
Packit |
df99a1 |
Indirection chunks in other files (#"INCL"# chunks) may refer to another
|
|
Packit |
df99a1 |
file using its identifier. */
|
|
Packit |
df99a1 |
const GUTF8String &get_load_name(void) const;
|
|
Packit |
df99a1 |
void set_load_name(const GUTF8String &id;;
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/** File title. The file title is assigned by the user and may be used as
|
|
Packit |
df99a1 |
a shortcut for viewing a particular page. Names like #"chapter1"# or
|
|
Packit |
df99a1 |
#"appendix"# are appropriate. */
|
|
Packit |
df99a1 |
const GUTF8String &get_title() const;
|
|
Packit |
df99a1 |
void set_title(const GUTF8String &id;;
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/** Reports an ascii string indicating file type. */
|
|
Packit |
df99a1 |
GUTF8String get_str_type(void) const;
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/** Offset of the file data in a bundled DJVM file. This number is
|
|
Packit |
df99a1 |
relevant in the {\em bundled} case only when everything is packed into
|
|
Packit |
df99a1 |
one single file. */
|
|
Packit |
df99a1 |
int offset;
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/** Size of the file data in a bundled DJVM file. This number is
|
|
Packit |
df99a1 |
relevant in the {\em bundled} case only when everything is
|
|
Packit |
df99a1 |
packed into one single file. */
|
|
Packit |
df99a1 |
int size;
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/** Have we checked the saved file name, to see if it is valid on the
|
|
Packit |
df99a1 |
local disk? */
|
|
Packit |
df99a1 |
bool valid_name;
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/** Tests if this file represents a page of the document. */
|
|
Packit |
df99a1 |
bool is_page(void) const
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
return (flags & TYPE_MASK)==PAGE;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/** Returns #TRUE# if this file is included into some other files of
|
|
Packit |
df99a1 |
this document. */
|
|
Packit |
df99a1 |
bool is_include(void) const
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
return (flags & TYPE_MASK)==INCLUDE;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/** Returns #TRUE# if this file contains thumbnails for the document pages. */
|
|
Packit |
df99a1 |
bool is_thumbnails(void) const
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
return (flags & TYPE_MASK)==THUMBNAILS;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/** Returns the page number of this file. This function returns
|
|
Packit |
df99a1 |
#-1# if this file does not represent a page of the document. */
|
|
Packit |
df99a1 |
bool is_shared_anno(void) const
|
|
Packit |
df99a1 |
{ return (flags & TYPE_MASK)==SHARED_ANNO; }
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
int get_page_num(void) const
|
|
Packit |
df99a1 |
{ return page_num; }
|
|
Packit |
df99a1 |
protected:
|
|
Packit |
df99a1 |
GUTF8String name;
|
|
Packit |
df99a1 |
GUTF8String oldname;
|
|
Packit |
df99a1 |
GUTF8String id;
|
|
Packit |
df99a1 |
GUTF8String title;
|
|
Packit |
df99a1 |
void set_save_name(const GUTF8String &name);
|
|
Packit |
df99a1 |
private:
|
|
Packit |
df99a1 |
friend class DjVmDir;
|
|
Packit |
df99a1 |
enum FLAGS_0 { IS_PAGE_0=1, HAS_NAME_0=2, HAS_TITLE_0=4 };
|
|
Packit |
df99a1 |
enum FLAGS_1 { HAS_NAME=0x80, HAS_TITLE=0x40, TYPE_MASK=0x3f };
|
|
Packit |
df99a1 |
unsigned char flags;
|
|
Packit |
df99a1 |
int page_num;
|
|
Packit |
df99a1 |
};
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
inline const GUTF8String &
|
|
Packit |
df99a1 |
DjVmDir::File::get_load_name(void) const
|
|
Packit |
df99a1 |
{ return id; }
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
inline const GUTF8String &
|
|
Packit |
df99a1 |
DjVmDir::File::get_title() const
|
|
Packit |
df99a1 |
{ return *(title.length()?&title:&id;; }
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
inline void
|
|
Packit |
df99a1 |
DjVmDir::File::set_title(const GUTF8String &xtitle) { title=xtitle; }
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/** @name Format of the DIRM chunk.
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
{\bf Variants} --- There are two versions of the #"DIRM"# chunk format.
|
|
Packit |
df99a1 |
The version number is identified by the seven low bits of the first byte
|
|
Packit |
df99a1 |
of the chunk. Version {\bf 0} is obsolete and should never be used. This
|
|
Packit |
df99a1 |
section describes version {\bf 1}. There are two major multipage DjVu
|
|
Packit |
df99a1 |
formats supported: {\em bundled} and {\em indirect}. The #"DIRM"# chunk
|
|
Packit |
df99a1 |
indicates which format is used in the most significant bit of the first
|
|
Packit |
df99a1 |
byte of the chunk. The document is bundled when this bit is set.
|
|
Packit |
df99a1 |
Otherwise the document is indirect.
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
{\bf Unencoded data} --- The #"DIRM"# chunk is composed some unencoded
|
|
Packit |
df99a1 |
data followed by \Ref{bzz} encoded data. The unencoded data starts with
|
|
Packit |
df99a1 |
the version byte and a 16 bit integer representing the number of component
|
|
Packit |
df99a1 |
files. All integers are encoded with the most significant byte first.
|
|
Packit |
df99a1 |
\begin{verbatim}
|
|
Packit |
df99a1 |
BYTE: Flags/Version: 0x<bundled>0000011
|
|
Packit |
df99a1 |
INT16: Number of component files.
|
|
Packit |
df99a1 |
\end{verbatim}
|
|
Packit |
df99a1 |
When the document is a bundled document (i.e. the flag #bundled# is set),
|
|
Packit |
df99a1 |
this header is followed by the offsets of each of the component files within
|
|
Packit |
df99a1 |
the #"FORM:DJVM"#. These offsets allow for random component file access.
|
|
Packit |
df99a1 |
\begin{verbatim}
|
|
Packit |
df99a1 |
INT32: Offset of first component file.
|
|
Packit |
df99a1 |
INT32: Offset of second component file.
|
|
Packit |
df99a1 |
...
|
|
Packit |
df99a1 |
INT32: Offset of last component file.
|
|
Packit |
df99a1 |
\end{verbatim}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
{\bf BZZ encoded data} --- The rest of the chunk is entirely compressed
|
|
Packit |
df99a1 |
with the BZZ general purpose compressor. We describe now the data fed
|
|
Packit |
df99a1 |
into (or retrieved from) the BZZ codec (cf. \Ref{BSByteStream}.) First
|
|
Packit |
df99a1 |
come the sizes and the flags associated with each component file.
|
|
Packit |
df99a1 |
\begin{verbatim}
|
|
Packit |
df99a1 |
INT24: Size of the first component file.
|
|
Packit |
df99a1 |
INT24: Size of the second component file.
|
|
Packit |
df99a1 |
...
|
|
Packit |
df99a1 |
INT24: Size of the last component file.
|
|
Packit |
df99a1 |
BYTE: Flag byte for the first component file.
|
|
Packit |
df99a1 |
BYTE: Flag byte for the second component file.
|
|
Packit |
df99a1 |
...
|
|
Packit |
df99a1 |
BYTE: Flag byte for the last component file.
|
|
Packit |
df99a1 |
\end{verbatim}
|
|
Packit |
df99a1 |
The flag bytes have the following format:
|
|
Packit |
df99a1 |
\begin{verbatim}
|
|
Packit |
df99a1 |
0b<hasname><hastitle>000000 for a file included by other files.
|
|
Packit |
df99a1 |
0b<hasname><hastitle>000001 for a file representing a page.
|
|
Packit |
df99a1 |
0b<hasname><hastitle>000010 for a file containing thumbnails.
|
|
Packit |
df99a1 |
\end{verbatim}
|
|
Packit |
df99a1 |
Flag #hasname# is set when the name of the file is different from the file
|
|
Packit |
df99a1 |
ID. Flag #hastitle# is set when the title of the file is different from
|
|
Packit |
df99a1 |
the file ID. These flags are used to avoid encoding the same string three
|
|
Packit |
df99a1 |
times. Then come a sequence of zero terminated strings. There are one to
|
|
Packit |
df99a1 |
three such strings per component file. The first string contains the ID
|
|
Packit |
df99a1 |
of the component file. The second string contains the name of the
|
|
Packit |
df99a1 |
component file. It is only present when the flag #hasname# is set. The third
|
|
Packit |
df99a1 |
one contains the title of the component file. It is only present when the
|
|
Packit |
df99a1 |
flag #hastitle# is set. The \Ref{bzz} encoding system makes sure that
|
|
Packit |
df99a1 |
all these strings will be encoded efficiently despite their possible
|
|
Packit |
df99a1 |
redundancies.
|
|
Packit |
df99a1 |
\begin{verbatim}
|
|
Packit |
df99a1 |
ZSTR: ID of the first component file.
|
|
Packit |
df99a1 |
ZSTR: Name of the first component file (only if #hasname# is set.)
|
|
Packit |
df99a1 |
ZSTR: Title of the first component file (only if #hastitle# is set.)
|
|
Packit |
df99a1 |
...
|
|
Packit |
df99a1 |
ZSTR: ID of the last component file.
|
|
Packit |
df99a1 |
ZSTR: Name of the last component file (only if #hasname# is set.)
|
|
Packit |
df99a1 |
ZSTR: Title of the last component file (only if #hastitle# is set.)
|
|
Packit |
df99a1 |
\end{verbatim}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
@memo Description of the format of the DIRM chunk. */
|
|
Packit |
df99a1 |
//@}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
// -------------- IMPLEMENTATION
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
inline bool
|
|
Packit |
df99a1 |
DjVmDir::is_bundled(void) const
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
return ! is_indirect();
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
inline bool
|
|
Packit |
df99a1 |
DjVmDir::is_indirect(void) const
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
GCriticalSectionLock lock((GCriticalSection *) &class_lock);
|
|
Packit |
df99a1 |
return ( files_list.size() && files_list[files_list] != 0 &&
|
|
Packit |
df99a1 |
files_list[files_list]->offset==0 );
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
// ----- THE END
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
#ifdef HAVE_NAMESPACES
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
# ifndef NOT_USING_DJVU_NAMESPACE
|
|
Packit |
df99a1 |
using namespace DJVU;
|
|
Packit |
df99a1 |
# endif
|
|
Packit |
df99a1 |
#endif
|
|
Packit |
df99a1 |
#endif
|