Пример #1
0
void dvifile::prepare_pages()
{
#ifdef DEBUG_DVIFILE
  kDebug(kvs::dvi) << "prepare_pages";
#endif
  if (total_pages == 0)
    return;

  page_offset.resize(total_pages+1);
  if (page_offset.size() < (total_pages+1)) {
    kError(kvs::dvi) << "No memory for page list!" << endl;
    return;
  }
  for(int i=0; i<=total_pages; i++)
    page_offset[i] = 0;

  page_offset[int(total_pages)] = beginning_of_postamble;
  int j = total_pages-1;
  page_offset[j] = last_page_offset;

  // Follow back pointers through pages in the DVI file, storing the
  // offsets in the page_offset table.
   while (j > 0) {
    command_pointer  = dvi_Data() + page_offset[j--];
    if (readUINT8() != BOP) {
      errorMsg = i18n("The page %1 does not start with the BOP command.", j+1);
      return;
    }
    command_pointer += 10 * 4;
    page_offset[j] = readUINT32();
    if ((dvi_Data()+page_offset[j] < dvi_Data())||(dvi_Data()+page_offset[j] > dvi_Data()+size_of_file))
      break;
  }
}
Пример #2
0
void dvifile::process_preamble()
{
  command_pointer = dvi_Data();

  quint8 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, denominator and the magnification value that describe
      how many centimeters there are in one TeX unit, as explained in
      section A.3 of the DVI driver standard, Level 0, published by
      the TUG DVI driver standards committee. */
  quint32 numerator     = readUINT32();
  quint32 denominator   = readUINT32();
  _magnification = readUINT32();

  cmPerDVIunit =  (double(numerator) / double(denominator)) * (double(_magnification) / 1000.0) * (1.0 / 1e5);


  // 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;
}
Пример #3
0
void dvifile::read_postamble()
{
  quint8 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.
  quint8 cmnd = readUINT8();
  while (cmnd >= FNTDEF1 && cmnd <= FNTDEF4) {
    quint32 TeXnumber = readUINT(cmnd-FNTDEF1+1);
    quint32 checksum  = readUINT32(); // Checksum of the font, as found by TeX in the TFM file

    // Read scale and design factor, and the name of the font. All
    // these are explained in section A.4 of the DVI driver standard,
    // Level 0, published by the TUG DVI driver standards committee
    quint32 scale     = readUINT32();
    quint32 design    = readUINT32();
    quint16 len       = readUINT8() + readUINT8(); // Length of the font name, including the directory name
    QByteArray fontname((char*)command_pointer, len);
    command_pointer += len;

#ifdef DEBUG_FONTS
    kDebug(kvs::dvi) << "Postamble: define font \"" << fontname << "\" scale=" << scale << " design=" << design;
#endif

    // According to section A.4 of the DVI driver standard, this font
    // shall be enlarged by the following factor before it is used.
    double enlargement_factor = (double(scale) * double(_magnification))/(double(design) * 1000.0);

    if (font_pool != 0) {
      TeXFontDefinition *fontp = font_pool->appendx(fontname, checksum, scale, enlargement_factor);

      // Insert font in dictionary and make sure the dictionary is big
      // enough.
      if (tn_table.capacity()-2 <= tn_table.count())
        // Not quite optimal. The size of the dictionary should be a
        // prime for optimal performance. I don't care.
        tn_table.reserve(tn_table.capacity()*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.
  if (font_pool != 0)
    font_pool->release_fonts();
}
Пример #4
0
void dviRenderer::draw_part(double current_dimconv, bool is_vfmacro)
{
#ifdef DEBUG_RENDER
    kDebug(kvs::dvi) << "draw_part";
#endif

    qint32 RRtmp=0, WWtmp=0, XXtmp=0, YYtmp=0, ZZtmp=0;
    quint8 ch;

    currinf.fontp        = NULL;
    currinf.set_char_p   = &dviRenderer::set_no_char;

    int last_space_index = 0;
    bool space_encountered = false;
    bool after_space = false;
    for (;;) {
        space_encountered = false;
        ch = readUINT8();
        if (ch <= (unsigned char) (SETCHAR0 + 127)) {
            (this->*currinf.set_char_p)(ch, ch);
        } else if (FNTNUM0 <= ch && ch <= (unsigned char) (FNTNUM0 + 63)) {
            currinf.fontp = currinf.fonttable->value(ch - FNTNUM0);
            if (currinf.fontp == NULL) {
                errorMsg = i18n("The DVI code referred to font #%1, which was not previously defined.", ch - FNTNUM0);
                return;
            }
            currinf.set_char_p = currinf.fontp->set_char_p;
        } else {
            qint32 a, b;

            switch (ch) {
            case SET1:
            case PUT1:
                (this->*currinf.set_char_p)(ch, readUINT8());
                break;

            case SETRULE:
                if (is_vfmacro == false) {
                    word_boundary_encountered = true;
                    line_boundary_encountered = true;
                }
                /* Be careful, dvicopy outputs rules with height =
                   0x80000000. We don't want any SIGFPE here. */
                a = readUINT32();
                b = readUINT32();
                b = ((long) (b *  current_dimconv));
                if (a > 0 && b > 0) {
                    int h = ((int) ROUNDUP(((long) (a *  current_dimconv)), shrinkfactor * 65536));
                    int w =  ((int) ROUNDUP(b, shrinkfactor * 65536));

                    if (colorStack.isEmpty())
                        foreGroundPainter->fillRect( ((int) ((currinf.data.dvi_h) / (shrinkfactor * 65536))),
                                                     currinf.data.pxl_v - h + 1, w?w:1, h?h:1, globalColor );
                    else
                        foreGroundPainter->fillRect( ((int) ((currinf.data.dvi_h) / (shrinkfactor * 65536))),
                                                     currinf.data.pxl_v - h + 1, w?w:1, h?h:1, colorStack.top() );
                }
                currinf.data.dvi_h += b;
                break;

            case PUTRULE:
                if (is_vfmacro == false) {
                    word_boundary_encountered = true;
                    line_boundary_encountered = true;
                }
                a = readUINT32();
                b = readUINT32();
                a = ((long) (a *  current_dimconv));
                b = ((long) (b *  current_dimconv));
                if (a > 0 && b > 0) {
                    int h = ((int) ROUNDUP(a, shrinkfactor * 65536));
                    int w = ((int) ROUNDUP(b, shrinkfactor * 65536));
                    if (colorStack.isEmpty())
                        foreGroundPainter->fillRect( ((int) ((currinf.data.dvi_h) / (shrinkfactor * 65536))),
                                                     currinf.data.pxl_v - h + 1, w?w:1, h?h:1, globalColor );
                    else
                        foreGroundPainter->fillRect( ((int) ((currinf.data.dvi_h) / (shrinkfactor * 65536))),
                                                     currinf.data.pxl_v - h + 1, w?w:1, h?h:1, colorStack.top() );
                }
                break;

            case NOP:
                break;

            case BOP:
                if (is_vfmacro == false) {
                    word_boundary_encountered = true;
                    line_boundary_encountered = true;
                }
                command_pointer += 11 * 4;
                currinf.data.dvi_h = 1200 << 16; // Reminder: DVI-coordinates start at (1",1") from top of page
                currinf.data.dvi_v = 1200;
                currinf.data.pxl_v = int(currinf.data.dvi_v/shrinkfactor);
                currinf.data.w = currinf.data.x = currinf.data.y = currinf.data.z = 0;
                break;

            case EOP:
                // Check if we are just at the end of a virtual font macro.
                if (is_vfmacro == false) {
                    // This is really the end of a page, and not just the end
                    // of a macro. Mark the end of the current word.
                    word_boundary_encountered = true;
                    line_boundary_encountered = true;
                    // Sanity check for the dvi-file: The DVI-standard asserts
                    // that at the end of a page, the stack should always be
                    // empty.
                    if (!stack.isEmpty()) {
                        kDebug(kvs::dvi) << "DRAW: The stack was not empty when the EOP command was encountered.";
                        errorMsg = i18n("The stack was not empty when the EOP command was encountered.");
                        return;
                    }
                }
                return;

            case PUSH:
                stack.push(currinf.data);
                break;

            case POP:
                if (stack.isEmpty()) {
                    errorMsg = i18n("The stack was empty when a POP command was encountered.");
                    return;
                } else
                    currinf.data = stack.pop();
                word_boundary_encountered = true;
                line_boundary_encountered = true;
                break;

            case RIGHT1:
            case RIGHT2:
            case RIGHT3:
            case RIGHT4:
                RRtmp = readINT(ch - RIGHT1 + 1);

                // A horizontal motion in the range 4 * font space [f] < h <
                // font space [f] will be treated as a kern that is not
                // indicated in the printouts that DVItype produces between
                // brackets. We allow a larger space in the negative
                // direction than in the positive one, because TEX makes
                // comparatively large backspaces when it positions
                // accents. (comments stolen from the source of dvitype)
                if ((is_vfmacro == false) &&
                        (currinf.fontp != 0) &&
                        ((RRtmp >= currinf.fontp->scaled_size_in_DVI_units/6) || (RRtmp <= -4*(currinf.fontp->scaled_size_in_DVI_units/6))) &&
                        (currentlyDrawnPage->textBoxList.size() > 0)) {
                    //currentlyDrawnPage->textBoxList[currentlyDrawnPage->textBoxList.size()-1].text += ' ';
                    space_encountered = true;
                }
                currinf.data.dvi_h += ((long) (RRtmp *  current_dimconv));
                break;

            case W1:
            case W2:
            case W3:
            case W4:
                WWtmp = readINT(ch - W0);
                currinf.data.w = ((long) (WWtmp *  current_dimconv));
            case W0:
                if ((is_vfmacro == false) &&
                        (currinf.fontp != 0) &&
                        ((WWtmp >= currinf.fontp->scaled_size_in_DVI_units/6) || (WWtmp <= -4*(currinf.fontp->scaled_size_in_DVI_units/6))) &&
                        (currentlyDrawnPage->textBoxList.size() > 0) ) {
                    //currentlyDrawnPage->textBoxList[currentlyDrawnPage->textBoxList.size()-1].text += ' ';
                    space_encountered = true;
                }
                currinf.data.dvi_h += currinf.data.w;
                break;

            case X1:
            case X2:
            case X3:
            case X4:
                XXtmp = readINT(ch - X0);
                currinf.data.x = ((long) (XXtmp *  current_dimconv));
            case X0:
                if ((is_vfmacro == false)  &&
                        (currinf.fontp != 0) &&
                        ((XXtmp >= currinf.fontp->scaled_size_in_DVI_units/6) || (XXtmp <= -4*(currinf.fontp->scaled_size_in_DVI_units/6))) &&
                        (currentlyDrawnPage->textBoxList.size() > 0)) {
                    //currentlyDrawnPage->textBoxList[currentlyDrawnPage->textBoxList.size()-1].text += ' ';
                    space_encountered = true;
                }
                currinf.data.dvi_h += currinf.data.x;
                break;

            case DOWN1:
            case DOWN2:
            case DOWN3:
            case DOWN4:
            {
                qint32 DDtmp = readINT(ch - DOWN1 + 1);
                if ((is_vfmacro == false) &&
                        (currinf.fontp != 0) &&
                        (abs(DDtmp) >= 5*(currinf.fontp->scaled_size_in_DVI_units/6)) &&
                        (currentlyDrawnPage->textBoxList.size() > 0)) {
                    word_boundary_encountered = true;
                    line_boundary_encountered = true;
                    space_encountered = true;
                    if (abs(DDtmp) >= 10*(currinf.fontp->scaled_size_in_DVI_units/6))
                        currentlyDrawnPage->textBoxList[currentlyDrawnPage->textBoxList.size()-1].text += '\n';
                }
                currinf.data.dvi_v += ((long) (DDtmp *  current_dimconv))/65536;
                currinf.data.pxl_v  = int(currinf.data.dvi_v/shrinkfactor);
            }
            break;

            case Y1:
            case Y2:
            case Y3:
            case Y4:
                YYtmp = readINT(ch - Y0);
                currinf.data.y    = ((long) (YYtmp *  current_dimconv));
            case Y0:
                if ((is_vfmacro == false) &&
                        (currinf.fontp != 0) &&
                        (abs(YYtmp) >= 5*(currinf.fontp->scaled_size_in_DVI_units/6)) &&
                        (currentlyDrawnPage->textBoxList.size() > 0)) {
                    word_boundary_encountered = true;
                    line_boundary_encountered = true;
                    space_encountered = true;
                    if (abs(YYtmp) >= 10*(currinf.fontp->scaled_size_in_DVI_units/6))
                        currentlyDrawnPage->textBoxList[currentlyDrawnPage->textBoxList.size()-1].text += '\n';
                }
                currinf.data.dvi_v += currinf.data.y/65536;
                currinf.data.pxl_v = int(currinf.data.dvi_v/shrinkfactor);
                break;

            case Z1:
            case Z2:
            case Z3:
            case Z4:
                ZZtmp = readINT(ch - Z0);
                currinf.data.z    = ((long) (ZZtmp *  current_dimconv));
            case Z0:
                if ((is_vfmacro == false) &&
                        (currinf.fontp != 0) &&
                        (abs(ZZtmp) >= 5*(currinf.fontp->scaled_size_in_DVI_units/6)) &&
                        (currentlyDrawnPage->textBoxList.size() > 0)) {
                    word_boundary_encountered = true;
                    line_boundary_encountered = true;
                    space_encountered = true;
                    if (abs(ZZtmp) >= 10*(currinf.fontp->scaled_size_in_DVI_units/6))
                        currentlyDrawnPage->textBoxList[currentlyDrawnPage->textBoxList.size()-1].text += '\n';
                }
                currinf.data.dvi_v += currinf.data.z/65536;
                currinf.data.pxl_v  = int(currinf.data.dvi_v/shrinkfactor);
                break;

            case FNT1:
            case FNT2:
            case FNT3:
                currinf.fontp = currinf.fonttable->value(readUINT(ch - FNT1 + 1));
                if (currinf.fontp == NULL) {
                    errorMsg = i18n("The DVI code referred to a font which was not previously defined.");
                    return;
                }
                currinf.set_char_p = currinf.fontp->set_char_p;
                break;

            case FNT4:
                currinf.fontp = currinf.fonttable->value(readINT(ch - FNT1 + 1));
                if (currinf.fontp == NULL) {
                    errorMsg = i18n("The DVI code referred to a font which was not previously defined.");
                    return;
                }
                currinf.set_char_p = currinf.fontp->set_char_p;
                break;

            case XXX1:
            case XXX2:
            case XXX3:
            case XXX4:
                if (is_vfmacro == false) {
                    word_boundary_encountered = true;
                    line_boundary_encountered = true;
                    space_encountered = true;
                }
                a = readUINT(ch - XXX1 + 1);
                if (a > 0) {
                    char        *cmd        = new char[a+1];
                    strncpy(cmd, (char *)command_pointer, a);
                    command_pointer += a;
                    cmd[a] = '\0';
                    applicationDoSpecial(cmd);
                    delete [] cmd;
                }
                break;

            case FNTDEF1:
            case FNTDEF2:
            case FNTDEF3:
            case FNTDEF4:
                command_pointer += 12 + ch - FNTDEF1 + 1;
                {
                    quint8 tempa = readUINT8();
                    quint8 tempb = readUINT8();
                    command_pointer += tempa + tempb;
                }
                break;

            case PRE:
            case POST:
            case POSTPOST:
                errorMsg = i18n("An illegal command was encountered.");
                return;
                break;

            default:
                errorMsg = i18n("The unknown op-code %1 was encountered.", ch);
                return;
            } /* end switch*/
        } /* end else (ch not a SETCHAR or FNTNUM) */

#ifdef DEBUG_RENDER
        if (currentlyDrawnPage->textBoxList.size() > 0)
            kDebug(kvs::dvi) << "Element:"
                             << currentlyDrawnPage->textBoxList.last().box
                             << currentlyDrawnPage->textBoxList.last().text
                             << " ? s:" << space_encountered
                             << " / nl:" << line_boundary_encountered
                             << " / w:" << word_boundary_encountered
                             << ", " << last_space_index << "/"
                             << currentlyDrawnPage->textBoxList.size();
#endif

        /* heuristic to properly detect newlines; a space is needed */
        if (after_space &&
                line_boundary_encountered && word_boundary_encountered) {
            if (currentlyDrawnPage->textBoxList.last().text.endsWith('\n'))
                currentlyDrawnPage->textBoxList.last().text.chop(1);
            currentlyDrawnPage->textBoxList.last().text += " \n";
            after_space = false;
        }

        /* a "space" has been found and there is some (new) character
           in the array */
        if (space_encountered &&
                (currentlyDrawnPage->textBoxList.size() > last_space_index)) {
            for (int lidx = last_space_index+1; lidx<currentlyDrawnPage->textBoxList.size(); ++lidx) {
                // merge two adjacent boxes which are part of the same word
                currentlyDrawnPage->textBoxList[lidx-1].box.setRight(currentlyDrawnPage->textBoxList[lidx].box.x());
            }
#ifdef DEBUG_RENDER
            QString lastword(currentlyDrawnPage->textBoxList[last_space_index].text);
            for (int lidx = last_space_index+1; lidx<currentlyDrawnPage->textBoxList.size(); ++lidx)
                lastword += currentlyDrawnPage->textBoxList[lidx].text;
            kDebug(kvs::dvi) << "space encountered: '" << lastword << "'";
#endif
            last_space_index = currentlyDrawnPage->textBoxList.size();
            after_space = true;
        }
    } /* end for */
}