コード例 #1
0
ファイル: WordDrawing.c プロジェクト: flyonok/DocFormats
static ImageInfo *getImageInfoObject(DFNode *concrete)
{
    DFNode *shape = DFChildWithTag(concrete,VML_SHAPE);
    DFNode *imageData = DFChildWithTag(shape,VML_IMAGEDATA);
    const char *cssText = DFGetAttribute(shape,NULL_STYLE);
    const char *rId = DFGetAttribute(imageData,OREL_ID);
    if ((shape == NULL) || (imageData == NULL) || (cssText == NULL) || (rId == NULL))
        return NULL;

    CSSProperties *imgProperties = CSSPropertiesNewWithString(cssText);
    CSSLength width = CSSLengthFromString(CSSGet(imgProperties,"width"));
    CSSLength height = CSSLengthFromString(CSSGet(imgProperties,"height"));
    CSSPropertiesRelease(imgProperties);

    if (!CSSLengthIsValid(width) || !CSSLengthIsAbsolute(width))
        return NULL;

    if (!CSSLengthIsValid(height) || !CSSLengthIsAbsolute(height))
        return NULL;

    double widthPts = convertBetweenUnits(width.value,width.units,UnitsPt);
    double heightPts = convertBetweenUnits(height.value,height.units,UnitsPt);

    ImageInfo *info = ImageInfoNew(rId,widthPts,heightPts);

    DFNode *oleObject = DFChildWithTag(concrete,MSOFFICE_OLEOBJECT);
    info->progId = DFGetAttribute(oleObject,NULL_PROGID);

    return info;
}
コード例 #2
0
ファイル: WordDrawing.c プロジェクト: flyonok/DocFormats
static PointsSize pointsSizeFromHTMLImg(WordConverter *converter, DFNode *img, PixelSize fileSize)
{
    double aspectRatio;
    if (fileSize.heightPx > 0.0)
        aspectRatio = fileSize.widthPx/(double)fileSize.heightPx;
    else
        aspectRatio = 1.0;

    CSSSize htmlSize = HTML_getImageDimensions(img);

    double widthPts = WordSectionContentWidthPts(converter->mainSection);
    if (CSSLengthIsValid(htmlSize.width)) {
        if (CSSLengthIsPercentage(htmlSize.width))
            widthPts = (htmlSize.width.value/100.0)*WordSectionContentWidthPts(converter->mainSection);
        else if (CSSLengthIsAbsolute(htmlSize.width))
            widthPts = convertBetweenUnits(htmlSize.width.value,htmlSize.width.units,UnitsPt);
    }

    double heightPts = widthPts/aspectRatio;

    if ((widthPts <= 0) || (heightPts <= 0)) {
        widthPts = WordSectionContentWidthPts(converter->mainSection);
        heightPts = widthPts/aspectRatio;
    }

    PointsSize result;
    result.widthPts = widthPts;
    result.heightPts = heightPts;
    return result;
}
コード例 #3
0
static ListDimensions cssPropertiesIndent(CSSProperties *properties)
{
    ListDimensions result;
    result.marginLeftPct = 0;
    result.textIndentPct = 0;
    result.totalPct = 0;

    if (CSSGet(properties,"margin-left") != NULL) {
        CSSLength length = CSSLengthFromString(CSSGet(properties,"margin-left"));
        if (CSSLengthIsValid(length) && (length.units == UnitsPct))
            result.marginLeftPct = length.value;
    }

    if (CSSGet(properties,"text-indent") != NULL) {
        CSSLength length = CSSLengthFromString(CSSGet(properties,"text-indent"));
        if (CSSLengthIsValid(length) && (length.units == UnitsPct))
            result.textIndentPct = length.value;
    }

    result.totalPct = result.marginLeftPct + result.textIndentPct;

    return result;
}
コード例 #4
0
static CellPadding getPadding(CSSSheet *styleSheet, WordStyle *wordStyle, CSSProperties *cellProperties)
{
    const char *paddingLeftStr = NULL;
    const char *paddingRightStr = NULL;

    CSSStyle *style;
    if ((wordStyle != NULL) && (wordStyle->selector != NULL)) {
        style = CSSSheetLookupSelector(styleSheet,wordStyle->selector,0,0);
    }
    else {
        style = CSSSheetDefaultStyleForFamily(styleSheet,StyleFamilyTable);
    }

    if (style != NULL) {
        paddingLeftStr = CSSGet(CSSStyleCell(style),"padding-left");
        paddingRightStr = CSSGet(CSSStyleCell(style),"padding-right");
    }

    if (CSSGet(cellProperties,"padding-left") != NULL)
        paddingLeftStr = CSSGet(cellProperties,"padding-left");
    if (CSSGet(cellProperties,"padding-right") != NULL)
        paddingRightStr = CSSGet(cellProperties,"padding-right");;

    CellPadding padding;
    padding.leftPts = 0;
    padding.rightPts = 0;

    CSSLength paddingLeftLength = CSSLengthFromString(paddingLeftStr);
    if (CSSLengthIsValid(paddingLeftLength) && (paddingLeftLength.units == UnitsPt))
        padding.leftPts = paddingLeftLength.value;;

    CSSLength paddingRightLength = CSSLengthFromString(paddingRightStr);
    if (CSSLengthIsValid(paddingRightLength) && (paddingRightLength.units == UnitsPt))
        padding.rightPts = paddingRightLength.value;;

    return padding;
}
コード例 #5
0
// FIXME: make private to this file
double listDesiredIndent(WordConverter *conv, const char *numId, const char *ilvl)
{
    CSSProperties *properties = CSSPropertiesNew();
    listProperties(conv,numId,ilvl,properties);
    double result = 0.0;

    if (CSSGet(properties,"margin-left") != NULL) {
        CSSLength length = CSSLengthFromString(CSSGet(properties,"margin-left"));
        if (CSSLengthIsValid(length) && (length.units == UnitsPct))
            result += length.value;
    }

    CSSPropertiesRelease(properties);
    return result;
}
コード例 #6
0
int CSSLengthIsAbsolute(CSSLength length)
{
    if (!CSSLengthIsValid(length))
        return 0;
    switch (length.units) {
        case UnitsIn:
        case UnitsCm:
        case UnitsMm:
        case UnitsPt:
        case UnitsPc:
        case UnitsPx:
            return 1;
        default:
            return 0;
    }
}
コード例 #7
0
int CSSLengthIsPercentage(CSSLength length)
{
    return (CSSLengthIsValid(length) && (length.units == UnitsPct));
}
コード例 #8
0
static void adjustMarginLeft(DFNode *element, double adjustPct, int noTextIndent)
{
    if ((element->tag != HTML_TABLE) && !HTML_isParagraphTag(element->tag))
        return;;

    const char *cssText = DFGetAttribute(element,HTML_STYLE);
    CSSProperties *properties = CSSPropertiesNewWithString(cssText);

    double oldMarginLeft = 0;
    if (CSSGet(properties,"margin-left") != NULL) {
        CSSLength length = CSSLengthFromString(CSSGet(properties,"margin-left"));
        if (CSSLengthIsValid(length) && (length.units == UnitsPct))
            oldMarginLeft = length.value;

        if (CSSGet(properties,"width") != NULL) {
            CSSLength length = CSSLengthFromString(CSSGet(properties,"width"));
            if (CSSLengthIsValid(length) && (length.units == UnitsPct)) {
                double oldWidth = length.value;
                double newWidth = oldWidth + oldMarginLeft;
                char buf[100];
                CSSPut(properties,"width",DFFormatDoublePct(buf,100,newWidth));
            }
        }
    }

    double oldTextIndent = 0;
    if (CSSGet(properties,"text-indent") != NULL) {
        CSSLength length = CSSLengthFromString(CSSGet(properties,"text-indent"));
        if (CSSLengthIsValid(length) && (length.units == UnitsPct))
            oldTextIndent = length.value;
    }

    double newMarginLeft = oldMarginLeft + adjustPct;
    double newTextIndent = oldTextIndent;

    if (newMarginLeft < 0)
        newMarginLeft = 0;
    if (fabs(newMarginLeft) >= 0.01) {
        char buf[100];
        CSSPut(properties,"margin-left",DFFormatDoublePct(buf,100,newMarginLeft));
    }
    else {
        CSSPut(properties,"margin-left",NULL);
    }

    if (noTextIndent) {
        CSSPut(properties,"text-indent",NULL);
    }
    else if (newTextIndent < -newMarginLeft) {
        // Don't allow negative text-indent
        newTextIndent = -newMarginLeft;
        if (fabs(newTextIndent) >= 0.01) {
            char buf[100];
            CSSPut(properties,"text-indent",DFFormatDoublePct(buf,100,newTextIndent));
        }
        else {
            CSSPut(properties,"text-indent",NULL);
        }
    }

    char *propertiesText = CSSPropertiesCopyDescription(properties);
    if (strlen(propertiesText) == 0)
        DFRemoveAttribute(element,HTML_STYLE);
    else
        DFSetAttribute(element,HTML_STYLE,propertiesText);
    free(propertiesText);

    CSSPropertiesRelease(properties);
}
コード例 #9
0
void WordPutPPr(DFNode *pPr, CSSProperties *properties, const char *styleId, WordSection *section, int outlineLvl)
{
    assert(pPr->tag == WORD_PPR);

    // The child elements of pPr have to be in a specific order. So we build up a structure based
    // on the existing elements (updated as appropriate from newProperties), and then rebuild
    // from that

    CSSProperties *oldp = CSSPropertiesNew();
    CSSProperties *newp = properties;
    const char *oldStyleId = NULL;
    const char *newStyleId = styleId;
    WordGetPPr(pPr,oldp,&oldStyleId,section);

    {
        DFNode *children[PREDEFINED_TAG_COUNT];
        childrenToArray(pPr,children);

        int existingOutlineLvl = -1;
        if (children[WORD_OUTLINELVL] != NULL) {
            const char *value = DFGetAttribute(children[WORD_OUTLINELVL],WORD_VAL);
            if (value != NULL)
                existingOutlineLvl = atoi(value);
        }

        // Style name
        if (!DFStringEquals(oldStyleId,newStyleId)) {
            if (newStyleId != NULL) {
                children[WORD_PSTYLE] = DFCreateElement(pPr->doc,WORD_PSTYLE);
                DFSetAttribute(children[WORD_PSTYLE],WORD_VAL,newStyleId);
            }
            else {
                children[WORD_PSTYLE] = NULL;
            }
        }

        // Paragraph border (pBdr)

        if (children[WORD_PBDR] == NULL)
            children[WORD_PBDR] = DFCreateElement(pPr->doc,WORD_PBDR);

        WordPutPBdr(children[WORD_PBDR],oldp,newp);

        if (children[WORD_PBDR]->first == NULL)
            children[WORD_PBDR] = NULL;

        // Numbering and outline level
        // Don't change these properties for styles with outline level >= 6, as these can't be
        // represented with the standard HTML heading elements, which only go from h1 - h6
        // (outline levels 0 - 5)
        if (existingOutlineLvl < 6) {
            if (children[WORD_NUMPR] == NULL)
                children[WORD_NUMPR] = DFCreateElement(pPr->doc,WORD_NUMPR);

            WordPutNumPr(children[WORD_NUMPR],newp);

            if (children[WORD_NUMPR]->first == NULL)
                children[WORD_NUMPR] = NULL;

            if ((outlineLvl >= 0) && (outlineLvl <= 5)) {
                if (children[WORD_OUTLINELVL] == NULL)
                    children[WORD_OUTLINELVL] = DFCreateElement(pPr->doc,WORD_OUTLINELVL);
                DFFormatAttribute(children[WORD_OUTLINELVL],WORD_VAL,"%d",outlineLvl);
            }
            else {
                children[WORD_OUTLINELVL] = NULL;
            }
        }

        // background-color

        char *oldBackgroundColor = CSSHexColor(CSSGet(oldp,"background-color"),0);
        char *newBackgroundColor = CSSHexColor(CSSGet(newp,"background-color"),0);
        if (!DFStringEquals(oldBackgroundColor,newBackgroundColor))
            WordPutShd(pPr->doc,&children[WORD_SHD],newBackgroundColor);
        free(oldBackgroundColor);
        free(newBackgroundColor);

        // text-align

        if (!DFStringEquals(CSSGet(oldp,"text-align"),CSSGet(newp,"text-align"))) {
            const char *newTextAlign = CSSGet(newp,"text-align");
            if (newTextAlign != NULL) {
                const char *val = NULL;
                if (!strcmp(newTextAlign,"left"))
                    val = "left";
                else if (!strcmp(newTextAlign,"right"))
                    val = "right";
                else if (!strcmp(newTextAlign,"center"))
                    val = "center";
                else if (!strcmp(newTextAlign,"justify"))
                    val = "both";
                if (val != NULL) {
                    children[WORD_JC] = DFCreateElement(pPr->doc,WORD_JC);
                    DFSetAttribute(children[WORD_JC],WORD_VAL,val);
                }
            }
            else {
                children[WORD_JC] = NULL;
            }
        }

        if ((section != NULL) && (WordSectionContentWidth(section) >= 0)) {
            const char *oldMarginLeft = CSSGet(oldp,"margin-left");
            const char *oldMarginRight = CSSGet(oldp,"margin-right");
            const char *oldTextIndent = CSSGet(oldp,"text-indent");
            const char *newMarginLeft = CSSGet(newp,"margin-left");
            const char *newMarginRight = CSSGet(newp,"margin-right");
            const char *newTextIndent = CSSGet(newp,"text-indent");

            // Special case of the List_Paragraph style, which is used by Word to ensure lists are indented. We
            // don't set this property for HTML, because it automatically indents lists. However we need to ensure
            // that it remains unchanged when updating the word document
            const char *newWordMarginLeft = CSSGet(newp,"-word-margin-left");
            if (newMarginLeft == NULL)
                newMarginLeft = newWordMarginLeft;

            if ((newMarginLeft == NULL) && (newMarginRight == NULL) && (newTextIndent == NULL)) {
                children[WORD_IND] = NULL;
            }
            else {
                if (children[WORD_IND] == NULL)
                    children[WORD_IND] = DFCreateElement(pPr->doc,WORD_IND);

                if (!DFStringEquals(oldMarginLeft,newMarginLeft)) {
                    if (newMarginLeft != NULL)
                        updateTwipsFromLength(children[WORD_IND],WORD_LEFT,newMarginLeft,WordSectionContentWidth(section));
                    else
                        DFRemoveAttribute(children[WORD_IND],WORD_LEFT);
                    DFRemoveAttribute(children[WORD_IND],WORD_START);
                }

                if (!DFStringEquals(oldMarginRight,newMarginRight)) {
                    if (newMarginRight != NULL)
                        updateTwipsFromLength(children[WORD_IND],WORD_RIGHT,newMarginRight,WordSectionContentWidth(section));
                    else
                        DFRemoveAttribute(children[WORD_IND],WORD_RIGHT);
                    DFRemoveAttribute(children[WORD_IND],WORD_END);
                }

                if (!DFStringEquals(oldTextIndent,newTextIndent)) {
                    if (newTextIndent != NULL) {
                        CSSLength length = CSSLengthFromString(newTextIndent);

                        if (CSSLengthIsValid(length)) {
                            double pts = CSSLengthToPts(length,WordSectionContentWidthPts(section));
                            int twips = (int)round(pts*20);

                            if (twips >= 0) {
                                DFFormatAttribute(children[WORD_IND],WORD_FIRSTLINE,"%d",twips);
                                DFRemoveAttribute(children[WORD_IND],WORD_HANGING);
                            }
                            else {
                                DFFormatAttribute(children[WORD_IND],WORD_HANGING,"%d",-twips);
                                DFRemoveAttribute(children[WORD_IND],WORD_FIRSTLINE);
                            }
                        }
                    }
                    else {
                        DFRemoveAttribute(children[WORD_IND],WORD_FIRSTLINE);
                        DFRemoveAttribute(children[WORD_IND],WORD_HANGING);
                    }
                }

            }
        }

        if (!DFStringEquals(CSSGet(oldp,"margin-top"),CSSGet(newp,"margin-top")) ||
            !DFStringEquals(CSSGet(oldp,"margin-bottom"),CSSGet(newp,"margin-bottom")) ||
            !DFStringEquals(CSSGet(oldp,"line-height"),CSSGet(newp,"line-height"))) {

            if ((CSSGet(newp,"margin-top") == NULL) &&
                (CSSGet(newp,"margin-bottom") == NULL) &&
                (CSSGet(newp,"line-height") == NULL)) {
                children[WORD_SPACING] = NULL;
            }
            else {
                children[WORD_SPACING] = DFCreateElement(pPr->doc,WORD_SPACING);

                if (DFStringEquals(CSSGet(newp,"margin-top"),"-word-auto")) {
                    DFSetAttribute(children[WORD_SPACING],WORD_BEFORE,"100");
                    DFSetAttribute(children[WORD_SPACING],WORD_BEFOREAUTOSPACING,"1");
                }
                else {
                    char *before = twipsFromCSS(CSSGet(newp,"margin-top"),WordSectionContentWidth(section));
                    DFSetAttribute(children[WORD_SPACING],WORD_BEFORE,before);
                    DFSetAttribute(children[WORD_SPACING],WORD_BEFOREAUTOSPACING,NULL);
                    free(before);
                }

                if (DFStringEquals(CSSGet(newp,"margin-bottom"),"-word-auto")) {
                    DFSetAttribute(children[WORD_SPACING],WORD_AFTER,"100");
                    DFSetAttribute(children[WORD_SPACING],WORD_AFTERAUTOSPACING,"1");
                }
                else {
                    char *after = twipsFromCSS(CSSGet(newp,"margin-bottom"),WordSectionContentWidth(section));
                    DFSetAttribute(children[WORD_SPACING],WORD_AFTER,after);
                    DFSetAttribute(children[WORD_SPACING],WORD_AFTERAUTOSPACING,NULL);
                    free(after);
                }

                CSSLength lineHeight = CSSLengthFromString(CSSGet(newp,"line-height"));
                if (CSSLengthIsValid(lineHeight) && (lineHeight.units == UnitsPct)) {
                    int value = (int)round(lineHeight.value*2.4);
                    DFFormatAttribute(children[WORD_SPACING],WORD_LINE,"%d",value);
                }
                
                if (children[WORD_SPACING]->attrsCount == 0)
                    children[WORD_SPACING] = NULL;
            }
        }
        
        replaceChildrenFromArray(pPr,children,WordPPR_Children);
    }
    CSSPropertiesRelease(oldp);
}
コード例 #10
0
static void WordTblPut(WordPutData *put, DFNode *abstract, DFNode *concrete)
{
    if ((abstract->tag != HTML_TABLE) || (concrete->tag != WORD_TBL))
        return;;

    DFTable *abstractStructure = HTML_tableStructure(abstract);
    const char *inlineCSSText = DFGetAttribute(abstract,HTML_STYLE);
    CSSProperties *tableProperties = CSSPropertiesNewWithString(inlineCSSText);
    CSSProperties *cellProperties = CSSPropertiesNew();
    const char *className = DFGetAttribute(abstract,HTML_CLASS);
    char *selector = CSSMakeSelector("table",className);
    WordStyle *style = WordSheetStyleForSelector(put->conv->styles,selector);
    CellPadding padding = getPadding(put->conv->styleSheet,style,cellProperties);

    DFNode *tblPr = DFChildWithTag(concrete,WORD_TBLPR);
    if (tblPr == NULL)
        tblPr = DFCreateElement(concrete->doc,WORD_TBLPR);;

    DFNode *tblGrid = DFChildWithTag(concrete,WORD_TBLGRID);
    if (tblGrid == NULL)
        tblGrid = DFCreateElement(concrete->doc,WORD_TBLGRID);

    while (concrete->first != NULL)
        DFRemoveNode(concrete->first);

    const char *oldJc = DFGetChildAttribute(tblPr,WORD_JC,WORD_VAL);
    WordPutTblPr(tblPr,tableProperties,NULL,put->conv->mainSection,style != NULL ? style->styleId : NULL);
    const char *newJc = DFGetChildAttribute(tblPr,WORD_JC,WORD_VAL);

    double tableWidthPct = 100;
    if (CSSGet(tableProperties,"width") != NULL) {
        CSSLength length = CSSLengthFromString(CSSGet(tableProperties,"width"));
        if (CSSLengthIsValid(length) && (length.units == UnitsPct))
            tableWidthPct = length.value;
    }

    double contentWidthPts = WordSectionContentWidthPts(put->conv->mainSection);
    double totalWidthPts = (contentWidthPts+padding.leftPts+padding.rightPts)*(tableWidthPct/100.0);

    while (tblGrid->first != NULL)
        DFRemoveNode(tblGrid->first);
    for (unsigned int i = 0; i < abstractStructure->cols; i++) {
        DFNode *gridCol = DFCreateChildElement(tblGrid,WORD_GRIDCOL);

        double colWidthPct = DFTablePctWidthForCol(abstractStructure,i);
        double colWidthPts = totalWidthPts*colWidthPct/100.0;
        int colWidthTwips = (int)round(colWidthPts*20);

        DFFormatAttribute(gridCol,WORD_W,"%d",colWidthTwips);
    }

    DFAppendChild(concrete,tblPr);
    DFAppendChild(concrete,tblGrid);
    for (unsigned int row = 0; row < abstractStructure->rows; row++) {
        DFNode *htmlTr = DFTableGetRowElement(abstractStructure,row);
        DFNode *wordTr = concreteRowForAbstractRow(put,htmlTr);
        updateTrJc(wordTr,oldJc,newJc);
        DFAppendChild(concrete,wordTr);
        unsigned int col = 0;
        while (col < abstractStructure->cols) {

            DFCell *cell = DFTableGetCell(abstractStructure,row,col);
            assert(cell != NULL);

            DFNode *tc = WordConverterGetConcrete(put,cell->element);
            if ((tc == NULL) || (row != cell->row))
                tc = DFCreateElement(concrete->doc,WORD_TC);
            DFAppendChild(wordTr,tc);

            if (cell->row == row)
                WordTcPut(put,cell->element,tc);;

            const char *vMerge = NULL;
            if (cell->rowSpan > 1) {
                if (row == cell->row)
                    vMerge = "restart";
                else
                    vMerge = "continue";
            }

            DFNode *tcPr = DFChildWithTag(tc,WORD_TCPR);
            if (tcPr == NULL)
                tcPr = DFCreateElement(concrete->doc,WORD_TCPR);
            // Make sure tcPr comes first
            DFInsertBefore(tc,tcPr,tc->first);

            WordPutTcPr2(tcPr,cell->colSpan,vMerge);

            const char *inlineCSSText = DFGetAttribute(cell->element,HTML_STYLE);
            CSSProperties *innerCellProperties = CSSPropertiesNewWithString(inlineCSSText);

            if ((row == cell->row) && (totalWidthPts > 0)) {
                double spannedWidthPct = 0;
                for (unsigned int c = col; c < col + cell->colSpan; c++)
                    spannedWidthPct += DFTablePctWidthForCol(abstractStructure,c);
                char buf[100];
                CSSPut(innerCellProperties,"width",DFFormatDoublePct(buf,100,spannedWidthPct));
            }

            WordPutTcPr1(tcPr,innerCellProperties);

            int haveBlockLevelElement = 0;
            for (DFNode *tcChild = tc->first; tcChild != NULL; tcChild = tcChild->next) {
                if (WordBlockLevelLens.isVisible(put,tcChild))
                    haveBlockLevelElement = 1;
            }

            // Every cell must contain at least one block-level element
            if (!haveBlockLevelElement) {
                DFNode *p = DFCreateElement(concrete->doc,WORD_P);
                DFAppendChild(tc,p);
            }

            col += cell->colSpan;
            CSSPropertiesRelease(innerCellProperties);
        }
    }

    free(selector);
    DFTableRelease(abstractStructure);
    CSSPropertiesRelease(tableProperties);
    CSSPropertiesRelease(cellProperties);
}