/* * Copyright (c) 1994 Paul Vojta. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * NOTE: * xdvi is based on prior work as noted in the modification history, below. */ /* * DVI previewer for X. * * Eric Cooper, CMU, September 1985. * * Code derived from dvi-imagen.c. * * Modification history: * 1/1986 Modified for X.10 --Bob Scheifler, MIT LCS. * 7/1988 Modified for X.11 --Mark Eichin, MIT * 12/1988 Added 'R' option, toolkit, magnifying glass * --Paul Vojta, UC Berkeley. * 2/1989 Added tpic support --Jeffrey Lee, U of Toronto * 4/1989 Modified for System V --Donald Richardson, Clarkson Univ. * 3/1990 Added VMS support --Scott Allendorf, U of Iowa * 7/1990 Added reflection mode --Michael Pak, Hebrew U of Jerusalem * 1/1992 Added greyscale code --Till Brychcy, Techn. Univ. Muenchen * and Lee Hetherington, MIT * 4/1994 Added DPS support, bounding box * --Ricardo Telichevesky * and Luis Miguel Silveira, MIT RLE. */ #include "dvi_init.h" #include "dviwin.h" #include #include #include #include #include extern "C" { #include "dvi.h" } #include "fontpool.h" #include "glyph.h" #include "oconfig.h" void dvifile::process_preamble(void) { command_pointer = dvi_Data; Q_UINT8 magic_number = readUINT8(); if (magic_number != PRE) { errorMsg = i18n("The DVI file does not start with the preamble."); return; } magic_number = readUINT8(); if (magic_number != 2) { errorMsg = i18n("The DVI file contains the wrong version of DVI output for this program. " "Hint: If you use the typesetting system Omega, you have to use a special " "program, such as oxdvi."); return; } numerator = readUINT32(); denominator = readUINT32(); magnification = readUINT32(); dimconv = (((double) numerator * magnification) / ((double) denominator * 1000.0)); // @@@@ This does not fit the description of dimconv in the header file!!! dimconv = dimconv * (((long) pixels_per_inch)<<16) / 254000; // Read the generatorString (such as "TeX output ..." from the // DVI-File). The variable "magic_number" holds the length of the // string. char job_id[300]; magic_number = readUINT8(); strncpy(job_id, (char *)command_pointer, magic_number); job_id[magic_number] = '\0'; generatorString = job_id; } /** find_postamble locates the beginning of the postamble and leaves the file ready to start reading at that location. */ void dvifile::find_postamble(void) { // Move backwards through the TRAILER bytes command_pointer = dvi_Data + size_of_file - 1; while((*command_pointer == TRAILER) && (command_pointer > dvi_Data)) command_pointer--; if (command_pointer == dvi_Data) { errorMsg = i18n("The DVI file is badly corrupted. KDVI was not able to find the postamble."); return; } // And this is finally the pointer to the beginning of the postamble command_pointer -= 4; beginning_of_postamble = readUINT32(); command_pointer = dvi_Data + beginning_of_postamble; } void dvifile::read_postamble(void) { Q_UINT8 magic_byte = readUINT8(); if (magic_byte != POST) { errorMsg = i18n("The postamble does not begin with the POST command."); return; } last_page_offset = readUINT32(); // Skip the numerator, denominator and magnification, the largest // box height and width and the maximal depth of the stack. These // are not used at the moment. command_pointer += 4 + 4 + 4 + 4 + 4 + 2; // The number of pages is more interesting for us. total_pages = readUINT16(); // As a next step, read the font definitions. Q_UINT8 cmnd = readUINT8(); while (cmnd >= FNTDEF1 && cmnd <= FNTDEF4) { Q_UINT32 TeXnumber = readUINT(cmnd-FNTDEF1+1); Q_UINT32 checksum = readUINT32(); Q_UINT32 scale = readUINT32(); Q_UINT32 design = readUINT32(); Q_UINT16 len = readUINT8() + readUINT8(); char *fontname = new char[len + 1]; strncpy(fontname, (char *)command_pointer, len ); fontname[len] = '\0'; command_pointer += len; #ifdef DEBUG_FONTS kdDebug() << "Postamble: define font \"" << fontname << "\" scale=" << scale << " design=" << design << endl; #endif // Calculate the fsize as: fsize = 0.001 * scale / design * magnification * MFResolutions[MetafontMode] struct font *fontp = font_pool->appendx(fontname, checksum, scale, design, 0.001*scale/design*magnification*MFResolutions[font_pool->getMetafontMode()], dimconv); // Insert font in dictionary and make sure the dictionary is big // enough. if (tn_table.size()-2 <= tn_table.count()) // Not quite optimal. The size of the dictionary should be a // prime. I don't care. tn_table.resize(tn_table.size()*2); tn_table.insert(TeXnumber, fontp); // Read the next command cmnd = readUINT8(); } if (cmnd != POSTPOST) { errorMsg = i18n("The postamble contained a command other than FNTDEF."); return; } // Now we remove all those fonts from the memory which are no longer // in use. font_pool->release_fonts(); } void dvifile::prepare_pages() { #ifdef DEBUG_DVIFILE kdDebug() << "prepare_pages" << endl; #endif page_offset = new Q_UINT32[total_pages+1]; if (page_offset == 0) { kdError(4300) << "No memory for page list!" << endl; return; } page_offset[total_pages] = beginning_of_postamble; Q_UINT16 i = total_pages-1; page_offset[i] = last_page_offset; // Follow back pointers through pages in the DVI file, storing the // offsets in the page_offset table. // @@@@ ADD CHECK FOR CONSISTENCY !!! NEVER LET THE COMMAND PTR POINT OUTSIDE THE ALLOCATED MEM !!!! while (i > 0) { command_pointer = dvi_Data + page_offset[i--]; if (readUINT8() != BOP) { errorMsg = i18n("The page %1 does not start with the BOP command.").arg(i+1); return; } command_pointer += 10 * 4; page_offset[i] = readUINT32(); if ((dvi_Data+page_offset[i] < dvi_Data)||(dvi_Data+page_offset[i] > dvi_Data+size_of_file)) page_offset[i] = 0; } } dvifile::dvifile(QString fname, fontPool *pool, bool sourceSpecialMark) { #ifdef DEBUG_DVIFILE kdDebug() << "init_dvi_file: " << fname << endl; #endif errorMsg = QString::null; dvi_Data = 0; page_offset = 0; font_pool = pool; sourceSpecialMarker = sourceSpecialMark; QFile file(fname); filename = file.name(); file.open( IO_ReadOnly ); size_of_file = file.size(); dvi_Data = new Q_UINT8[size_of_file]; // Sets the end pointer for the bigEndianByteReader so that the // whole memory buffer is readable end_pointer = dvi_Data+size_of_file; if (dvi_Data == 0) { kdError() << i18n("Not enough memory to load the DVI-file."); return; } file.readBlock((char *)dvi_Data, size_of_file); file.close(); if (file.status() != IO_Ok) { kdError() << i18n("Could not load the DVI-file."); return; } tn_table.clear(); process_preamble(); find_postamble(); read_postamble(); prepare_pages(); return; } dvifile::~dvifile() { #ifdef DEBUG_DVIFILE kdDebug() << "destroy dvi-file" << endl; #endif if (dvi_Data != 0) delete [] dvi_Data; if (font_pool != 0) font_pool->mark_fonts_as_unused(); if (page_offset != NULL) delete [] page_offset; }