Exemplo n.º 1
0
void Document::processStyles()
{
    kDebug(30513) ;

    const wvWare::StyleSheet& styles = m_parser->styleSheet();
    unsigned int count = styles.size();
    kDebug(30513) << "styles count=" << count;

    //loop through each style
    for (unsigned int i = 0; i < count ; ++i) {
        //grab style
        const wvWare::Style* style = styles.styleByIndex(i);
        Q_ASSERT(style);
        QString displayName = Conversion::string(style->name());
        QString name = Conversion::styleName2QString(style->name());

        // if the invariant style identifier says it's a style used for line numbers
        if (style->sti() == 40) {
            m_lineNumbersStyleName = name;  // store the name of that style
        }

        // Process paragraph styles.
        if (style && style->type() == sgcPara) {
            //create this style & add formatting info to it
            kDebug(30513) << "creating ODT paragraphstyle" << name;
            KoGenStyle userStyle(KoGenStyle::ParagraphStyle, "paragraph");
            userStyle.addAttribute("style:display-name", displayName);

            const wvWare::Style* followingStyle = styles.styleByIndex(style->followingStyle());
            if (followingStyle && followingStyle != style) {
                QString followingName = Conversion::styleName2QString(followingStyle->name());
                userStyle.addAttribute("style:next-style-name", followingName);
            }

            const wvWare::Style* parentStyle = styles.styleByIndex(style->m_std->istdBase);
            if (parentStyle) {
                userStyle.setParentName(Conversion::styleName2QString(parentStyle->name()));
            }

            //set font name in style
            QString fontName = m_textHandler->getFont(style->chp().ftcAscii);
            if (!fontName.isEmpty()) {
                m_mainStyles->insertFontFace(KoFontFace(fontName));
                userStyle.addProperty(QString("style:font-name"), fontName, KoGenStyle::TextType);
            }

            // Process the paragraph and character properties.
            Paragraph::applyParagraphProperties(style->paragraphProperties(), &userStyle, parentStyle, false, 0, 0, QString());
            Paragraph::applyCharacterProperties(&style->chp(), &userStyle, parentStyle, false, false, currentBgColor());

            // Add style to main collection, using the name that it
            // had in the .doc.
            QString actualName = m_mainStyles->insert(userStyle, name, KoGenStyles::DontAddNumberToName);
            kDebug(30513) << "added style " << actualName;

            //save names of TOC related styles
            if (actualName.contains("TOC")) {
                m_tocStyleNames.append(actualName);
            }
        } else if (style && style->type() == sgcChp) {
            //create this style & add formatting info to it
            kDebug(30513) << "creating ODT textstyle" << name;
            KoGenStyle userStyle(KoGenStyle::TextStyle, "text");
            userStyle.addAttribute("style:display-name", displayName);

            const wvWare::Style* parentStyle = styles.styleByIndex(style->m_std->istdBase);
            if (parentStyle) {
                userStyle.setParentName(Conversion::styleName2QString(parentStyle->name()));
            }

            //set font name in style
            QString fontName = m_textHandler->getFont(style->chp().ftcAscii);
            if (!fontName.isEmpty()) {
                m_mainStyles->insertFontFace(KoFontFace(fontName));
                userStyle.addProperty(QString("style:font-name"), fontName, KoGenStyle::TextType);
            }

            // Process the character and paragraph properties.
            Paragraph::applyCharacterProperties(&style->chp(), &userStyle, parentStyle, false, false, currentBgColor());

            //add style to main collection, using the name that it had in the .doc
            QString actualName = m_mainStyles->insert(userStyle, name, KoGenStyles::DontAddNumberToName);
            kDebug(30513) << "added style " << actualName;
        }
    }
    //also create a default style which is needed to store the default tab spacing
    KoGenStyle defaultStyle(KoGenStyle::ParagraphStyle, "paragraph");
    defaultStyle.setDefaultStyle(true);
    defaultStyle.addPropertyPt("style:tab-stop-distance", (qreal)m_parser->dop().dxaTab / 20.0);
    m_mainStyles->insert(defaultStyle, "nevershown");
}
Exemplo n.º 2
0
void Document::setPageLayoutStyle(KoGenStyle* pageLayoutStyle,
                                  wvWare::SharedPtr<const wvWare::Word97::SEP> sep,
                                  bool firstPage)
{
    // TODO: Check page-layout attributes specific for the first page.

    //get width & height in points
    double width = (double)sep->xaPage / 20.0;
    double height = (double)sep->yaPage / 20.0;
    pageLayoutStyle->addPropertyPt("fo:page-width", width);
    pageLayoutStyle->addPropertyPt("fo:page-height", height);
    pageLayoutStyle->addProperty("style:footnote-max-height", "0in");
    pageLayoutStyle->addProperty("style:writing-mode", "lr-tb");
    bool landscape = (sep->dmOrientPage == 2);
    pageLayoutStyle->addProperty("style:print-orientation", landscape ? "landscape" : "portrait");
    pageLayoutStyle->addProperty("style:num-format", "1");

    DrawStyle ds = m_graphicsHandler->getBgDrawStyle();
    if (ds.fFilled()) {
        switch (ds.fillType()) {
        case msofillSolid:
        {
            // PptToOdp::toQColor helper function can be used instead of this conversion
            MSO::OfficeArtCOLORREF clr = ds.fillColor();
            QColor color(clr.red, clr.green, clr.blue);
            QString tmp = color.name();
            pageLayoutStyle->addProperty("fo:background-color", tmp);

            //update the background-color information if required
            if (tmp != currentBgColor()) {
                updateBgColor(tmp);
            }
            break;
        }
        //TODO:
//         case msofillShade:
//         case msofillShadeCenter:
//         case msofillShadeShape:
//         case msofillShadeScale:
//         case msofillShadeTitle:
//
        //TODO:
//         case msofillPattern:
//         case msofillTexture:
//
        case msofillPicture:
        {
            // picture can be stored in OfficeArtBStoreContainer or in
            // fillBlip_complex if complex = true only picture in
            // OfficeArtBStoreContainer is handled now
            QString filePath = m_graphicsHandler->getPicturePath(ds.fillBlip());

            if (!filePath.isEmpty()) {
                QBuffer buffer;
                KoXmlWriter bkgImageWriter(&buffer);

                bkgImageWriter.startElement("style:background-image");
                bkgImageWriter.addAttribute("xlink:href", filePath);
                bkgImageWriter.addAttribute("xlink:type", "simple");
                bkgImageWriter.addAttribute("xlink:actuate", "onLoad");
                bkgImageWriter.endElement(); //style:background-image

                QString contents = QString::fromUtf8(((QBuffer*)bkgImageWriter.device())->buffer(),
                                         ((QBuffer*)bkgImageWriter.device())->buffer().size());

                pageLayoutStyle->addChildElement("0", contents);
            }
        break;
        }
        //TODO:
//         case msofillBackground:
        default:
            break;
        }
    }

    // NOTE: margin-top and margin-bottom are updated in slotSectionFound based
    // on the information if the header/footer was empty/non-empty.
    //
    // Maybe we should set the minimum height of header/footer to qAbs(dyaTop -
    // dyaHdrTop)/qAbs(dyaBottom - dyaHdrBottom)
    //
    // The height of both header and footer is unknown, so it's not possible to
    // set margin-bottom for the header and margin-top for the footer properly.
    // Both dyaTop and dyaBottom do not tell us where the header/footer ends.
    //
    // MSWord specific:
    // For each x in {header, footer, body}, x has an independent ruler.
    //
    // Also both header and footer are treated like a separate document, so if
    // you insert a border into the body, then header/footer margins do not
    // change.  We are not able to store this into ODF properly.

    QString header("<style:header-style>");
    header.append("<style:header-footer-properties");

    // The spec says the top-margin MUST be grown to avoid overlapping the
    // space that is occupied by headers.  Not ODF compatible.
    if (sep->dyaTop >= 0) {
        header.append(" style:dynamic-spacing=\"true\"");
        header.append(" fo:margin-bottom=\"0pt\"");
    } else {
        //TODO: tests required, I would prefer margin-bottom set to ZERO
        header.append(" style:dynamic-spacing=\"false\"");
        header.append(" fo:margin-bottom=\"");
#if 0
        qreal headerMarginTop = qAbs(sep->dyaTop) - sep->dyaHdrTop;
        if (headerMarginTop > 0) {
            header.append(QString::number(headerMarginTop / 20.0, 'f'));
        } else
#endif
            header.append("0");
        header.append("pt\"");

    }
    header.append(" fo:min-height=\"14pt\"/>");
    header.append("</style:header-style>");

    QString footer("<style:footer-style>");
    footer.append("<style:header-footer-properties");

    // The spec says the bottom-margin MUST be grown to avoid overlapping the
    // space that is occupied by footers or footnotes.  Not ODF compatible.
    if (sep->dyaBottom > 0) {
        footer.append(" style:dynamic-spacing=\"true\"");
        footer.append(" fo:margin-top=\"0pt\"");
    } else {
        //TODO: tests required, I would prefer margin-top set to ZERO
        footer.append(" style:dynamic-spacing=\"false\"");
        footer.append(" fo:margin-top=\"");
        qreal headerMarginBottom = qAbs(sep->dyaBottom) - sep->dyaHdrBottom;
        if (headerMarginBottom >= 400) {
            footer.append(QString::number(headerMarginBottom / 20.0, 'f'));
        } else {
            footer.append("14");
        }
        footer.append("pt\"");
    }
    footer.append(" fo:min-height=\"10pt\"/>");
    footer.append("</style:footer-style>");

    pageLayoutStyle->addProperty("1header-style", header, KoGenStyle::StyleChildElement);
    pageLayoutStyle->addProperty("2footer-style", footer, KoGenStyle::StyleChildElement);

    //Page borders, check to which page-layout the border information has to be
    //applied: 0 - all pages, 1 - first page only, 2 - all but first.

    //NOTE: 3 - whole document, not mentioned in the "Word Binary File Format
    //(.doc) Structure Specification", but mentiond in word97_generated.h
    if ( (sep->pgbApplyTo == 0) ||
        ((sep->pgbApplyTo == 1) && firstPage) ||
        ((sep->pgbApplyTo == 2) && !firstPage))
    {
        // FIXME: check if we can use fo:border instead of fo:border-left, etc.
        if (sep->brcLeft.brcType != 0) {
            pageLayoutStyle->addProperty("fo:border-left",
                                         Conversion::setBorderAttributes(sep->brcLeft));
            pageLayoutStyle->addProperty("calligra:specialborder-left",
                                         Conversion::borderCalligraAttributes(sep->brcLeft));
        }
        if (sep->brcTop.brcType != 0) {
            pageLayoutStyle->addProperty("fo:border-top",
                                         Conversion::setBorderAttributes(sep->brcTop));
            pageLayoutStyle->addProperty("calligra:specialborder-top",
                                         Conversion::borderCalligraAttributes(sep->brcTop));
        }
        if (sep->brcRight.brcType != 0) {
            pageLayoutStyle->addProperty("fo:border-right",
                                         Conversion::setBorderAttributes(sep->brcRight));
            pageLayoutStyle->addProperty("calligra:specialborder-right",
                                         Conversion::borderCalligraAttributes(sep->brcRight));
        }
        if (sep->brcBottom.brcType != 0) {
            pageLayoutStyle->addProperty("fo:border-bottom",
                                         Conversion::setBorderAttributes(sep->brcBottom));
            pageLayoutStyle->addProperty("calligra:specialborder-bottom",
                                         Conversion::borderCalligraAttributes(sep->brcBottom));
        }
    }
    // TODO: use sep->fEndNote to set the 'use endnotes or footnotes' flag
}
Exemplo n.º 3
0
void Document::setPageLayoutStyle(KoGenStyle* pageLayoutStyle,
                                  wvWare::SharedPtr<const wvWare::Word97::SEP> sep,
                                  bool firstPage)
{
    // TODO: Check page-layout attributes specific for the first page.

    //get width & height in points
    double width = (double)sep->xaPage / 20.0;
    double height = (double)sep->yaPage / 20.0;
    pageLayoutStyle->addPropertyPt("fo:page-width", width);
    pageLayoutStyle->addPropertyPt("fo:page-height", height);
    pageLayoutStyle->addProperty("style:footnote-max-height", "0in");
    pageLayoutStyle->addProperty("style:writing-mode", "lr-tb");
    bool landscape = (sep->dmOrientPage == 2);
    pageLayoutStyle->addProperty("style:print-orientation", landscape ? "landscape" : "portrait");
    pageLayoutStyle->addProperty("style:num-format", "1");

    // Set default left/right margins for the case when there is no
    // border.  This will be changed below if there are borders defined.
    pageLayoutStyle->addPropertyPt("fo:margin-left", (double)sep->dxaLeft / 20.0);
    pageLayoutStyle->addPropertyPt("fo:margin-right", (double)sep->dxaRight / 20.0);

    DrawStyle ds = m_graphicsHandler->getDrawingStyle();
    // TODO: use ds.fillType to enable fill efects for document background

    // When more complete background-color implementation will be added to filter,
    // PptToOdp::toQColor helper function can be used instead of this conversion
    MSO::OfficeArtCOLORREF clr = ds.fillColor();
    QColor color(clr.red, clr.green, clr.blue);
    QString tmp = color.name();
    pageLayoutStyle->addProperty("fo:background-color", tmp);

    //update the background-color information if required
    if (tmp != currentBgColor()) {
        updateBgColor(tmp);
    }

    //set the minimum height of header/footer to the full margin minus margin above header
    //problem with footer is that it is not possible to say how big the footer is.
    QString header("<style:header-style>");
    header.append("<style:header-footer-properties fo:margin-bottom=\"");
    header.append(QString::number((sep->dyaTop - sep->dyaHdrTop) / 20.0));
    header.append("pt\" fo:min-height=\"14pt\"/>");
    header.append("</style:header-style>");

    QString footer("<style:footer-style>");
    footer.append("<style:header-footer-properties fo:margin-top=\"");
    if (sep->dyaBottom > (int)sep->dyaHdrBottom) {
        if ((sep->dyaBottom - sep->dyaHdrBottom) >= 400) {
            footer.append(QString::number((sep->dyaBottom - sep->dyaHdrBottom) / 20.0));
        } else {
            footer.append("14");
        }
    }
    else {
        footer.append("14");
    }
    footer.append("pt\" fo:min-height=\"10pt\"/>");
    footer.append("</style:footer-style>");

    pageLayoutStyle->addProperty("1header-style", header, KoGenStyle::StyleChildElement);
    pageLayoutStyle->addProperty("2footer-style", footer, KoGenStyle::StyleChildElement);

    //Page borders, check to which page-layout the border information has to be
    //applied: 0 - all pages, 1 - first page only, 2 - all but first.

    //NOTE: 3 - whole document, not mentioned in the "Word Binary File Format
    //(.doc) Structure Specification", but mentiond in word97_generated.h
    if ( (sep->pgbApplyTo == 0) ||
        ((sep->pgbApplyTo == 1) && firstPage) ||
        ((sep->pgbApplyTo == 2) && !firstPage))
    {
        // FIXME: check if we can use fo:border instead of fo:border-left, etc.
        if (sep->brcLeft.brcType != 0) {
            pageLayoutStyle->addProperty("fo:border-left",
                                         Conversion::setBorderAttributes(sep->brcLeft));
            pageLayoutStyle->addProperty("koffice:specialborder-left",
                                         Conversion::borderKOfficeAttributes(sep->brcLeft));
        }
        if (sep->brcTop.brcType != 0) {
            pageLayoutStyle->addProperty("fo:border-top",
                                         Conversion::setBorderAttributes(sep->brcTop));
            pageLayoutStyle->addProperty("koffice:specialborder-top",
                                         Conversion::borderKOfficeAttributes(sep->brcTop));
        }
        if (sep->brcRight.brcType != 0) {
            pageLayoutStyle->addProperty("fo:border-right",
                                         Conversion::setBorderAttributes(sep->brcRight));
            pageLayoutStyle->addProperty("koffice:specialborder-right",
                                         Conversion::borderKOfficeAttributes(sep->brcRight));
        }
        if (sep->brcBottom.brcType != 0) {
            pageLayoutStyle->addProperty("fo:border-bottom",
                                         Conversion::setBorderAttributes(sep->brcBottom));
            pageLayoutStyle->addProperty("koffice:specialborder-bottom",
                                         Conversion::borderKOfficeAttributes(sep->brcBottom));
        }
    }
    // the pgbOffsetFrom variable determins how to calculate the margins and paddings.
    if (sep->pgbOffsetFrom == 0) {
        // page border offset is from the text
        pageLayoutStyle->addPropertyPt("fo:padding-left",   sep->brcLeft.dptSpace);
        pageLayoutStyle->addPropertyPt("fo:padding-top",    sep->brcTop.dptSpace);
        pageLayoutStyle->addPropertyPt("fo:padding-right",  sep->brcRight.dptSpace);
        pageLayoutStyle->addPropertyPt("fo:padding-bottom", sep->brcBottom.dptSpace);
        // FIXME: How should fo:margin be created in this case?
    } else {
        // page border offset is from the edge of the page

        // Add margin. This value is fetched directly from the BRC's.
        pageLayoutStyle->addPropertyPt("fo:margin-left",   sep->brcLeft.dptSpace);
        pageLayoutStyle->addPropertyPt("fo:margin-top",    sep->brcTop.dptSpace);
        pageLayoutStyle->addPropertyPt("fo:margin-right",  sep->brcRight.dptSpace);
        pageLayoutStyle->addPropertyPt("fo:margin-bottom", sep->brcBottom.dptSpace);

        // The *20 and /20 below is the conversion between twips (1/20th of a point) and points.
        pageLayoutStyle->addPropertyPt("fo:padding-left",
                                         (sep->dxaLeft - (sep->brcLeft.dptSpace * 20)) / 20);
        pageLayoutStyle->addPropertyPt("fo:padding-top",
                                         (sep->dyaTop - (sep->brcTop.dptSpace * 20)) / 20);
        pageLayoutStyle->addPropertyPt("fo:padding-right",
                                         (sep->dxaRight - (sep->brcRight.dptSpace * 20)) / 20);
        pageLayoutStyle->addPropertyPt("fo:padding-bottom",
                                         (sep->dyaBottom - (sep->brcBottom.dptSpace * 20)) / 20);
    }
    // TODO: use sep->fEndNote to set the 'use endnotes or footnotes' flag
}