void WordsGraphicsHandler::definePositionAttributes(KoGenStyle& style, const DrawStyle& ds) { if (m_processingGroup) return; const KoGenStyle::PropertyType gt = KoGenStyle::GraphicType; if (m_objectType == Inline) { style.addProperty("style:vertical-rel", "baseline", gt); style.addProperty("style:vertical-pos", "top", gt); } else { style.addProperty("style:horizontal-pos", getHorizontalPos(ds.posH()), gt); style.addProperty("style:horizontal-rel", getHorizontalRel(ds.posRelH()), gt); style.addProperty("style:vertical-pos", getVerticalPos(ds.posV()), gt); style.addProperty("style:vertical-rel", getVerticalRel(ds.posRelV()), gt); } }
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 }
void WordsGraphicsHandler::defineWrappingAttributes(KoGenStyle& style, const DrawStyle& ds) { if (m_processingGroup) return; if (m_objectType == Inline) return; const KoGenStyle::PropertyType gt = KoGenStyle::GraphicType; wvWare::Word97::FSPA* spa = m_pSpa; // style:number-wrapped-paragraphs // style:run-through // style:wrap // style:wrap-contour // style:wrap-contour-mode // style:wrap-dynamic-threshold if (spa != 0) { bool check_wrk = false; switch (spa->wr) { case 0: //wrap around the object case 2: //square wrapping check_wrk = true; break; case 1: //top and bottom wrapping style.addProperty("style:wrap", "none", gt); break; case 3: //in front or behind the text style.addProperty("style:wrap", "run-through", gt); //check if shape is behind the text if ((spa->fBelowText == 1) || (ds.fBehindDocument())) { style.addProperty("style:run-through", "background", gt); } else { style.addProperty("style:run-through", "foreground", gt); } break; case 4: //tight wrapping check_wrk = true; style.addProperty("style:wrap-contour", "true", gt); style.addProperty("style:wrap-contour-mode", "outside", gt); break; case 5: //through wrapping check_wrk = true; style.addProperty("style:wrap-contour", "true", gt); style.addProperty("style:wrap-contour-mode", "full", gt); break; } //check details of the text wrapping around this shape if (check_wrk) { switch (spa->wrk) { case 0: style.addProperty("style:wrap", "parallel", gt); break; case 1: style.addProperty("style:wrap", "left", gt); break; case 2: style.addProperty("style:wrap", "right", gt); break; case 3: style.addProperty("style:wrap", "biggest", gt); break; } } // ODF-1.2: specifies the number of paragraphs that can wrap around a // frame if wrap mode is in {left, right, parallel, dynamic} and anchor // type is in {char, paragraph} if ((spa->wr != 1) && (spa->wr != 3)) { style.addProperty("style:number-wrapped-paragraphs", "no-limit"); } } else { style.addProperty("style:wrap", "run-through", gt); if (ds.fBehindDocument()) { style.addProperty("style:run-through", "background", gt); } else { style.addProperty("style:run-through", "foreground", gt); } } }
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 }