PacketStreamReader::FrameInfo PacketStreamReader::Stream::peekFrameHeader(const PacketStreamReader& p)
{
    if (_frame)
        return _frame;

    _frame.frame_streampos = tellg();

    if (peekTag() == TAG_SRC_JSON)
    {
        readTag(TAG_SRC_JSON);
        _frame.src = readUINT();
        json::parse(_frame.meta, *this);
    }

    _frame.packet_streampos = tellg();

    readTag(TAG_SRC_PACKET);
    _frame.time = readTimestamp();

    if (_frame)
    {
        if (readUINT() != _frame.src)
            throw std::runtime_error("Frame preceded by metadata for a mismatched source. Stream may be corrupt.");
    }
    else
        _frame.src = readUINT();

    _frame.size = p.Sources()[_frame.src].data_size_bytes;
    if (!_frame.size)
        _frame.size = readUINT();
    _frame.sequence_num = p.GetPacketIndex(_frame.src);

    _tag = TAG_SRC_PACKET;

    return _frame;
}
예제 #2
0
파일: dviFile.cpp 프로젝트: JPriya/Okular
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();
}
예제 #3
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 */
}