~ubuntu-branches/ubuntu/precise/koffice/precise

« back to all changes in this revision

Viewing changes to filters/kword/msword-odf/paragraph.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Alessandro Ghersi
  • Date: 2010-10-27 17:52:57 UTC
  • mfrom: (0.12.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20101027175257-s04zqqk5bs8ckm9o
Tags: 1:2.2.83-0ubuntu1
* Merge with Debian git remaining changes:
 - Add build-deps on librcps-dev, opengtl-dev, libqtgtl-dev, freetds-dev,
   create-resources, libspnav-dev
 - Remove needless build-dep on libwv2-dev
 - koffice-libs recommends create-resources
 - krita recommends pstoedit
 - Keep our patches
* New upstream release 2.3 beta 3
  - Remove debian/patches fixed by upstream
  - Update install files

Show diffs side-by-side

added added

removed removed

Lines of Context:
25
25
 
26
26
#include <kdebug.h>
27
27
 
 
28
//define the static attribute
 
29
QString Paragraph::m_bgColor = "";
 
30
 
28
31
Paragraph::Paragraph(KoGenStyles* mainStyles, bool inStylesDotXml, bool isHeading, bool inHeaderFooter, int outlineLevel)
29
32
        : m_paragraphProperties(0),
30
33
        m_paragraphProperties2(0),
36
39
        m_inStylesDotXml(inStylesDotXml),
37
40
        m_isHeading(isHeading),
38
41
        m_outlineLevel(0),
 
42
        m_dropCapStatus(NoDropCap),
39
43
        m_inHeaderFooter(inHeaderFooter),
40
 
        m_containsPageNumberField(false)
 
44
        m_containsPageNumberField(false),
 
45
        m_combinedCharacters(false)
41
46
{
42
47
    kDebug(30513);
43
48
    m_mainStyles = mainStyles;
63
68
    m_odfParagraphStyle = 0;
64
69
}
65
70
 
66
 
void Paragraph::addRunOfText(QString text,  wvWare::SharedPtr<const wvWare::Word97::CHP> chp, QString fontName, const wvWare::StyleSheet& styles, bool addCompleteElement)
 
71
void Paragraph::addRunOfText(QString text,  wvWare::SharedPtr<const wvWare::Word97::CHP> chp,
 
72
                             QString fontName, const wvWare::StyleSheet& styles,
 
73
                             bool addCompleteElement)
67
74
{
68
75
    // Check for column break in this text string
69
76
    int colBreak = text.indexOf(QChar(0xE));
74
81
 
75
82
        // Add needed attribute to paragraph style.
76
83
        //
77
 
        // Note: This logic breaks down if this isn't the first string
78
 
        //       in the paragraph, or there are other strings with
79
 
        //       another colBreak later in the same paragraph.
 
84
        // NOTE: This logic breaks down if this isn't the first string in the
 
85
        //       paragraph, or there are other strings with another colBreak
 
86
        //       later in the same paragraph.
80
87
        m_odfParagraphStyle->addProperty("fo:break-before", "column", KoGenStyle::ParagraphType);
81
88
        // Remove character that signaled a column break
82
89
        text.remove(QChar(0xE));
83
90
    }
84
91
 
85
 
    // if it's inner paragraph, push back true
86
 
    // this is an m_textStyles.push_back(NULL) complement if we still need the style applied
 
92
    // if it's inner paragraph, push back true this is an
 
93
    // m_textStyles.push_back(NULL) complement if we still need the style
 
94
    // applied
87
95
    m_addCompleteElement.push_back(addCompleteElement);
88
96
 
89
97
    // Add text string to list.
90
 
    m_textStrings.push_back(QString(text));
 
98
    //m_textStrings.push_back(QString(text));
 
99
    m_textStrings.append(QString(text));
91
100
 
92
101
    // Now find out what style to associate with the string.
93
102
 
101
110
    const wvWare::Style* msTextStyle = styles.styleByIndex(chp->istd);
102
111
    Q_ASSERT(msTextStyle);
103
112
    QString msTextStyleName = Conversion::styleNameString(msTextStyle->name());
104
 
    kDebug(30513) << "text has characterstyle " << msTextStyleName;
 
113
    kDebug(30513) << "text based on characterstyle " << msTextStyleName;
105
114
 
106
 
    KoGenStyle *textStyle = m_mainStyles->styleForModification(msTextStyleName);
107
 
    if (!textStyle) {
108
 
        kWarning() << "Couldn't retrieve style for modification!";
109
 
    }
 
115
    KoGenStyle *textStyle;
110
116
 
111
117
    bool suppresFontSize = false;
112
118
    if (m_textStyles.size() == 0 && m_paragraphProperties->pap().dcs.lines > 1) {
113
119
        suppresFontSize = true;
114
120
    }
115
121
 
116
 
    // Modify the character style if we detect any diff between the
117
 
    // chp of the paragraph and the summed chp.
118
 
    const wvWare::Style* parentStyle = styles.styleByIndex(msTextStyle->m_std->istdBase);
119
 
    if (parentStyle) {
120
 
        applyCharacterProperties(chp, textStyle, m_paragraphStyle, suppresFontSize);
 
122
    // Apply any extra properties to our auto style
 
123
    // those extra properties is the diff beteween the referenceChp and the summed chp.
 
124
    // ReferenceCHP can be either the paragraph or a named style
 
125
    if (msTextStyle->sti() != 65) {
 
126
        // this is not default paragraph font
 
127
        textStyle = new KoGenStyle(KoGenStyle::TextAutoStyle, "text");
 
128
        if (m_inStylesDotXml) {
 
129
            textStyle->setAutoStyleInStylesDotXml(true);
 
130
        }
 
131
        textStyle->setParentName(msTextStyleName);
 
132
        //if we have a new font, process that
 
133
        const wvWare::Word97::CHP* refChp = &msTextStyle->chp();
 
134
        if (!refChp || refChp->ftcAscii != chp->ftcAscii) {
 
135
            if (!fontName.isEmpty()) {
 
136
                textStyle->addProperty(QString("style:font-name"), fontName, KoGenStyle::TextType);
 
137
            }
 
138
            applyCharacterProperties(chp, textStyle, msTextStyle, m_bgColor, suppresFontSize, m_combinedCharacters);
 
139
        }
 
140
    } else {
 
141
        // Default Paragraph Font, which is handled differently
 
142
        // Meaning we should really compare against the CHP of the paragraph
 
143
        textStyle = new KoGenStyle(KoGenStyle::TextAutoStyle, "text");
 
144
        if (m_inStylesDotXml) {
 
145
            textStyle->setAutoStyleInStylesDotXml(true);
 
146
        }
121
147
        //if we have a new font, process that
122
148
        const wvWare::Word97::CHP* refChp = &m_paragraphStyle->chp();
123
149
        if (!refChp || refChp->ftcAscii != chp->ftcAscii) {
125
151
                textStyle->addProperty(QString("style:font-name"), fontName, KoGenStyle::TextType);
126
152
            }
127
153
        }
128
 
    } else {
129
 
        textStyle = new KoGenStyle(KoGenStyle::TextAutoStyle, "text");
130
 
        if (m_inStylesDotXml) {
131
 
            textStyle->setAutoStyleInStylesDotXml(true);
132
 
        }
133
 
        if (!fontName.isEmpty()) {
134
 
            textStyle->addProperty(QString("style:font-name"), fontName, KoGenStyle::TextType);
135
 
        }
136
 
        applyCharacterProperties(chp, textStyle, m_paragraphStyle, suppresFontSize);
 
154
        applyCharacterProperties(chp, textStyle, m_paragraphStyle, m_bgColor, suppresFontSize, m_combinedCharacters);
137
155
    }
138
156
 
139
157
    //add text style to list
145
163
    kDebug(30513);
146
164
 
147
165
    // Set up the paragraph style.
148
 
    applyParagraphProperties(*m_paragraphProperties, m_odfParagraphStyle, m_paragraphStyle, m_inHeaderFooter && m_containsPageNumberField);
 
166
    applyParagraphProperties(*m_paragraphProperties, m_odfParagraphStyle, m_paragraphStyle,
 
167
                             m_inHeaderFooter && m_containsPageNumberField, this);
 
168
 
 
169
    // MS Word puts dropcap characters in its own paragraph with the
 
170
    // rest of the text in the subsequent paragraph. On the other
 
171
    // hand, ODF wants the whole paragraph to be one unit.
 
172
    //
 
173
    // So if this paragraph is only one string and we have a dropcap,
 
174
    // then we should combine this paragraph with the next, and write
 
175
    // them together.  That means we should just return here now so
 
176
    // that the next call to writeToFile() they will be in the same
 
177
    // paragraph.
 
178
    if (m_dropCapStatus == IsDropCapPara) {
 
179
        kDebug(30513) << "returning with drop cap paragraph";
 
180
        if (m_textStrings.size()) {
 
181
            if (m_textStyles[0] != 0) {
 
182
                m_dropCapStyleName= m_textStyles[0]->parentName();
 
183
            }
 
184
        }
 
185
        return;
 
186
    }
 
187
 
 
188
    // If there is a dropcap defined, then write it to the style.
 
189
    if (m_dropCapStatus == HasDropCapIntegrated) {
 
190
        kDebug(30513) << "Creating drop cap style";
 
191
 
 
192
        QBuffer buf;
 
193
        buf.open(QIODevice::WriteOnly);
 
194
        KoXmlWriter tmpWriter(&buf, 3);
 
195
        tmpWriter.startElement("style:drop-cap");
 
196
        tmpWriter.addAttribute("style:lines", m_dcs_lines);
 
197
        tmpWriter.addAttributePt("style:distance", m_dropCapDistance);
 
198
        // We have only support for fdct=1, i.e. regular dropcaps.
 
199
        // There is no support for fdct=2, i.e. dropcaps in the margin (ODF doesn't support this).
 
200
        tmpWriter.addAttribute("style:length", m_dcs_fdct > 0 ? 1 : 0);
 
201
        if (!m_dropCapStyleName.isEmpty()) {
 
202
            tmpWriter.addAttribute("style:style-name", m_dropCapStyleName.toUtf8());
 
203
        }
 
204
        tmpWriter.endElement(); //style:drop-cap
 
205
        buf.close();
 
206
 
 
207
        QString contents = QString::fromUtf8(buf.buffer(), buf.buffer().size());
 
208
        m_odfParagraphStyle->addChildElement("style:drop-cap", contents);
 
209
 
 
210
        m_dropCapStatus = NoDropCap;
 
211
    }
 
212
 
 
213
    QString textStyleName;
 
214
    //add paragraph style to the collection and its name to the content
 
215
    kDebug(30513) << "adding paragraphStyle";
 
216
    //add the attribute for our style in <text:p>
 
217
    textStyleName = "P";
 
218
    textStyleName = m_mainStyles->insert(*m_odfParagraphStyle, textStyleName);
 
219
 
 
220
    //check if the paragraph is inside of an absolutely positioned frame
 
221
    if ( !m_paragraphProperties->pap().fInTable &&
 
222
         (m_paragraphProperties->pap().dxaAbs != 0 || m_paragraphProperties->pap().dyaAbs) )
 
223
    {
 
224
        KoGenStyle userStyle(KoGenStyle::GraphicAutoStyle, "graphic");
 
225
        QString drawStyleName;
 
226
 
 
227
        writer->startElement("text:p", false);
 
228
        writer->addAttribute("text:style-name", textStyleName.toUtf8());
 
229
 
 
230
        int dxaAbs = 0;
 
231
        int dyaAbs = 0;
 
232
        const wvWare::Word97::PAP& pap = m_paragraphProperties->pap();
 
233
 
 
234
        //MS-DOC - sprmPDxaAbs - relative horizontal position to anchor
 
235
        // (-4) - center, (-8) - right, (-12) - inside, (-16) - outside 
 
236
        if (pap.dxaAbs == -4) {
 
237
            userStyle.addProperty("style:horizontal-pos","center");
 
238
        }
 
239
        else if (pap.dxaAbs == -8) {
 
240
            userStyle.addProperty("style:horizontal-pos","right");
 
241
        }
 
242
        else if (pap.dxaAbs == -12) {
 
243
            userStyle.addProperty("style:horizontal-pos","inside");
 
244
        }
 
245
        else if (pap.dxaAbs == -16) {
 
246
            userStyle.addProperty("style:horizontal-pos","outside");
 
247
        }
 
248
        else {
 
249
            dxaAbs = pap.dxaAbs;
 
250
            userStyle.addProperty("style:horizontal-pos","from-left");
 
251
        }
 
252
        //MS-DOC - sprmPDyaAbs - relative vertical position to anchor
 
253
        // (-4) - top, (-8) - middle, (-12) - bottom, (-16) - inside, 
 
254
        // (-20) - outside
 
255
        if (pap.dyaAbs == -4) {
 
256
            userStyle.addProperty("style:vertical-pos","top");
 
257
        }
 
258
        else if (pap.dyaAbs == -8) {
 
259
            userStyle.addProperty("style:vertical-pos","middle");
 
260
        }
 
261
        else if (pap.dyaAbs == -12) {
 
262
            userStyle.addProperty("style:vertical-pos","bottom");
 
263
        }
 
264
        else if (pap.dyaAbs == -16) {
 
265
            userStyle.addProperty("style:vertical-pos","inline");
 
266
        }
 
267
        else if (pap.dyaAbs == -20) {
 
268
            userStyle.addProperty("style:vertical-pos","inline");
 
269
        }
 
270
        else {
 
271
            dyaAbs = pap.dyaAbs;
 
272
            userStyle.addProperty("style:vertical-pos","from-top");
 
273
        }
 
274
        //MS-DOC - PositionCodeOperand - anchor vertical position
 
275
        // 0 - margin, 1 - page, 2 - paragraph
 
276
        if (pap.pcVert == 0) {
 
277
            userStyle.addProperty("style:vertical-rel","page-content");
 
278
        }
 
279
        else if (pap.pcVert == 1) {
 
280
            userStyle.addProperty("style:vertical-rel","page");
 
281
        }
 
282
        else if (pap.pcVert == 2) {
 
283
            userStyle.addProperty("style:vertical-rel","paragraph");
 
284
        }
 
285
        //MS-DOC - PositionCodeOperand - anchor horizontal position
 
286
        // 0 - current column, 1 - margin, 2 - page
 
287
        if (pap.pcHorz == 0) {
 
288
            userStyle.addProperty("style:horizontal-rel","paragraph");
 
289
        }
 
290
        else if (pap.pcHorz == 1) {
 
291
            userStyle.addProperty("style:horizontal-rel","page-content");
 
292
        }
 
293
        else if (pap.pcHorz == 2) {
 
294
            userStyle.addProperty("style:horizontal-rel","page");
 
295
        }
 
296
 
 
297
        drawStyleName = "fr";
 
298
        drawStyleName = m_mainStyles->insert(userStyle, drawStyleName);
 
299
        writer->startElement("draw:frame");
 
300
        writer->addAttribute("draw:style-name", drawStyleName.toUtf8());
 
301
        writer->addAttribute("text:anchor-type", "paragraph");
 
302
 
 
303
        if (pap.dxaWidth != 0) {
 
304
            writer->addAttributePt("svg:width", (double)pap.dxaWidth/20);
 
305
        }
 
306
        if (pap.dyaHeight != 0) {
 
307
            writer->addAttributePt("svg:height", (double)pap.dyaHeight/20);
 
308
        }
 
309
        writer->addAttributePt("svg:x", (double)dxaAbs/20);
 
310
        writer->addAttributePt("svg:y", (double)dyaAbs/20);
 
311
        writer->startElement("draw:text-box");
 
312
    }
149
313
 
150
314
    // Open paragraph or heading tag.
151
315
    if (m_isHeading) {
155
319
        writer->startElement("text:p", false);
156
320
    }
157
321
 
158
 
    //add paragraph style to the collection and its name to the content
159
 
    kDebug(30513) << "adding paragraphStyle";
160
 
    //add the attribute for our style in <text:p>
161
 
    QString styleName("P");
162
 
    styleName = m_mainStyles->insert(*m_odfParagraphStyle, styleName);
163
 
    writer->addAttribute("text:style-name", styleName.toUtf8());
164
 
 
165
 
    //just close the paragraph if there's no content
166
 
    if (m_textStrings.empty()) {
167
 
        writer->endElement(); //text:p
168
 
        return;
169
 
    }
170
 
 
171
 
    //loop through each text strings and styles (equal # of both)
172
 
    kDebug(30513) << "writing text spans now";
173
 
    QString oldStyleName;
174
 
    bool startedSpan = false;
175
 
    for (int i = 0; i < m_textStrings.size(); i++) {
176
 
        if (m_textStyles[i] == 0) {
177
 
            //if style is null, we have an inner paragraph and add the
178
 
            // complete paragraph element to writer
179
 
            //need to get const char* from the QString
180
 
            kDebug(30513) << "complete element: " <<
181
 
            m_textStrings[i].toLocal8Bit().constData();
182
 
            writer->addCompleteElement(m_textStrings[i].toLocal8Bit().constData());
183
 
        } else {
184
 
            //add text style to collection
185
 
            //put style into m_mainStyles & get its name
186
 
            //kDebug(30513) << m_textStyles[i]->type();
187
 
            styleName = 'T';
188
 
            styleName = m_mainStyles->insert(*m_textStyles[i], styleName);
189
 
 
190
 
            if (oldStyleName != styleName) {
 
322
    writer->addAttribute("text:style-name", textStyleName.toUtf8());
 
323
 
 
324
    //if there's any paragraph content
 
325
    if (!m_textStrings.isEmpty()) {
 
326
        //Loop through each text strings and styles (equal # of both) and write
 
327
        //them to the file.
 
328
        kDebug(30513) << "writing text spans now";
 
329
        QString oldStyleName;
 
330
        bool startedSpan = false;
 
331
        for (int i = 0; i < m_textStrings.size(); i++) {
 
332
            if (m_textStyles[i] == 0) {
191
333
                if (startedSpan) {
192
334
                    writer->endElement(); //text:span
193
335
                    startedSpan = false;
194
 
                }
195
 
                if (styleName != "DefaultParagraphFont") {
196
 
                    writer->startElement("text:span");
197
 
                    writer->addAttribute("text:style-name", styleName.toUtf8());
198
 
                    startedSpan = true;
199
 
                }
200
 
                oldStyleName = styleName;
201
 
            }
202
 
            //write text string to writer
203
 
            //now I just need to write the text:span to the header tag
204
 
            kDebug(30513) << "Writing \"" << m_textStrings[i] << "\"";
205
 
            if (m_addCompleteElement[i] == false) {
206
 
                writer->addTextSpan(m_textStrings[i]);
207
 
            } else {            // special case we need style applied and complete element added
 
336
                    oldStyleName = " ";
 
337
                }
 
338
                //if style is null, we have an inner paragraph and add the
 
339
                //complete paragraph element to writer need to get const char*
 
340
                //from the QString
 
341
                kDebug(30513) << "complete element: " << 
 
342
                                 m_textStrings[i].toLocal8Bit().constData();
208
343
                writer->addCompleteElement(m_textStrings[i].toLocal8Bit().constData());
 
344
            } else {
 
345
                //put style into m_mainStyles & get its name
 
346
                textStyleName = 'T';
 
347
                textStyleName = m_mainStyles->insert(*m_textStyles[i], textStyleName);
 
348
                //kDebug(30513) << m_textStyles[i]->type();
 
349
 
 
350
                if (oldStyleName != textStyleName) {
 
351
                    if (startedSpan) {
 
352
                        writer->endElement(); //text:span
 
353
                        startedSpan = false;
 
354
                    }
 
355
                    if (textStyleName != "DefaultParagraphFont") {
 
356
                        writer->startElement("text:span");
 
357
                        writer->addAttribute("text:style-name", textStyleName.toUtf8());
 
358
                        startedSpan = true;
 
359
                    }
 
360
                    oldStyleName = textStyleName;
 
361
                }
 
362
                //Write text string to writer.  Now I just need to write the
 
363
                //text:span to the header tag.
 
364
                kDebug(30513) << "Writing \"" << m_textStrings[i] << "\"";
 
365
                if (m_addCompleteElement[i] == false) {
 
366
                    writer->addTextSpan(m_textStrings[i]);
 
367
                }
 
368
                //special case we need style applied and complete element added
 
369
                else {
 
370
                    writer->addCompleteElement(m_textStrings[i].toLocal8Bit().constData());
 
371
                }
 
372
                //cleanup
 
373
                //delete m_textStyles[i];
 
374
                m_textStyles[i] = 0;
209
375
            }
210
 
 
211
 
            //cleanup
212
 
            //delete m_textStyles[i];
213
 
            m_textStyles[i] = 0;
 
376
        }
 
377
        // If we have an unfinished text:span, finish it now.
 
378
        if (startedSpan) {
 
379
            writer->endElement(); //text:span
 
380
            startedSpan = false;
214
381
        }
215
382
    }
216
 
    if (startedSpan) // we wrote a span of text so make sure we close the span tag
217
 
        writer->endElement(); //text:span
218
 
 
219
383
    //close the <text:p> or <text:h> tag we opened
220
384
    writer->endElement();
 
385
 
 
386
    //check if the paragraph is inside of an absolutely positioned frame
 
387
    if ( !m_paragraphProperties->pap().fInTable &&
 
388
         (m_paragraphProperties->pap().dxaAbs != 0 || m_paragraphProperties->pap().dyaAbs) )
 
389
    {
 
390
        writer->endElement(); //draw:text-box
 
391
        writer->endElement(); //draw:frame
 
392
        writer->endElement(); //close the <text:p>
 
393
    }
221
394
}
222
395
 
223
396
void Paragraph::setParagraphStyle(const wvWare::Style* paragraphStyle)
290
463
}
291
464
 
292
465
void Paragraph::applyParagraphProperties(const wvWare::ParagraphProperties& properties,
293
 
        KoGenStyle* style, const wvWare::Style* parentStyle, bool setDefaultAlign)
 
466
                                         KoGenStyle* style, const wvWare::Style* parentStyle,
 
467
                                         bool setDefaultAlign, Paragraph *paragraph)
294
468
{
295
469
    kDebug(30513);
296
470
 
330
504
            style->addProperty("style:writing-mode", "lr-tb", KoGenStyle::ParagraphType);
331
505
    }
332
506
 
333
 
    if (!refPap || refPap->shd.cvBack != pap.shd.cvBack) {
334
 
        if (pap.shd.cvBack != 0xff000000)
335
 
            style->addProperty(QString("fo:background-color"), '#' + QString::number(pap.shd.cvBack | 0xff000000, 16).right(6).toUpper());
336
 
        else
337
 
            style->addProperty("fo:background-color", "transparent", KoGenStyle::ParagraphType);
 
507
    // if there is no parent style OR the parent and child background color
 
508
    // don't match OR parent color was invalid, childs color is valid
 
509
    if (!refPap || refPap->shd.cvBack != pap.shd.cvBack ||
 
510
        (refPap->shd.shdAutoOrNill && !pap.shd.shdAutoOrNill) )
 
511
    {
 
512
        QString color;
 
513
        // is the color valid? (don't compare to black - 0xff000000 !!!)
 
514
        if (!pap.shd.shdAutoOrNill) {
 
515
            color = '#' + QString::number(pap.shd.cvBack | 0xff000000, 16).right(6).toUpper();
 
516
            //update the background-color information
 
517
            setBgColor(color);
 
518
        } else {
 
519
            color = "transparent";
 
520
        }
 
521
        style->addProperty("fo:background-color", color, KoGenStyle::ParagraphType);
338
522
    }
339
523
 
340
524
    //dxaLeft1 = first-line indent from left margin (signed, relative to dxaLeft)
444
628
        style->addProperty("fo:border-right", Conversion::setBorderAttributes(pap.brcRight), KoGenStyle::ParagraphType);
445
629
    }
446
630
 
 
631
    // Drop Cap Style (DCS)
447
632
    if (!refPap || refPap->dcs.fdct != pap.dcs.fdct || refPap->dcs.lines != pap.dcs.lines) {
 
633
        if (paragraph) {
 
634
            kDebug(30513) << "Processing drop cap";
 
635
            if (paragraph->m_textStrings.size() > 0)
 
636
                kDebug(30513) << "String = """ << paragraph->m_textStrings[0] << """";
 
637
            else
 
638
                kDebug(30513) << "No drop cap string";
 
639
 
 
640
            paragraph->m_dropCapStatus = IsDropCapPara;
 
641
            paragraph->m_dcs_fdct  = pap.dcs.fdct;
 
642
            paragraph->m_dcs_lines = pap.dcs.lines;
 
643
            paragraph->m_dropCapDistance = (qreal)pap.dxaFromText / (qreal)20.0;
 
644
        }
 
645
#if 0
448
646
        QBuffer buf;
449
647
        buf.open(QIODevice::WriteOnly);
450
648
        KoXmlWriter tmpWriter(&buf, 3);
451
 
        tmpWriter.startElement("style:drop-cap");
 
649
         tmpWriter.startElement("style:drop-cap");
452
650
        tmpWriter.addAttribute("style:lines", pap.dcs.lines);
453
651
        tmpWriter.addAttributePt("style:distance", (qreal)pap.dxaFromText / (qreal)20.0);
454
652
        tmpWriter.addAttribute("style:length", pap.dcs.fdct > 0 ? 1 : 0);
455
653
        tmpWriter.endElement();//style:drop-cap
456
654
        buf.close();
 
655
 
457
656
        QString contents = QString::fromUtf8(buf.buffer(), buf.buffer().size());
458
657
        style->addChildElement("style:drop-cap", contents);
 
658
#endif
459
659
    }
460
660
 
461
661
//TODO introduce diff for tabs too like in: if(!refPap || refPap->fKeep != pap
509
709
    }
510
710
} //end applyParagraphProperties
511
711
 
512
 
void Paragraph::applyCharacterProperties(const wvWare::Word97::CHP* chp, KoGenStyle* style, const wvWare::Style* parentStyle, bool suppressFontSize)
 
712
void Paragraph::applyCharacterProperties(const wvWare::Word97::CHP* chp, KoGenStyle* style, const wvWare::Style* parentStyle, QString bgColor, bool suppressFontSize, bool combineCharacters)
513
713
{
514
714
    //if we have a named style, set its CHP as the refChp
515
715
    const wvWare::Word97::CHP* refChp;
520
720
    }
521
721
 
522
722
    //ico = color of text, but this has been replaced by cv
523
 
    if (!refChp || refChp->cv != chp->cv) {
524
 
        style->addProperty(QString("fo:color"), '#' + QString::number(chp->cv | 0xff000000, 16).right(6).toUpper(), KoGenStyle::TextType);
 
723
    if (!refChp || (refChp->cv != chp->cv) || (chp->cv == wvWare::Word97::cvAuto)) {
 
724
        QString color;
 
725
        //use the color context to set the proper font color
 
726
        if (chp->cv == wvWare::Word97::cvAuto) {
 
727
            color = contrastFontColor(bgColor);
 
728
        } else {
 
729
            color = QString('#' + QString::number(chp->cv | 0xff000000, 16).right(6).toUpper());
 
730
        }
 
731
        style->addProperty(QString("fo:color"), color, KoGenStyle::TextType);
525
732
    }
526
733
 
527
734
    //hps = font size in half points
648
855
            style->addProperty("style:text-outline", "false", KoGenStyle::TextType);
649
856
    }
650
857
 
 
858
    // if the characters are combined, add proper style
 
859
    if (combineCharacters) {
 
860
        style->addProperty("style:text-combine","letters");
 
861
    }
651
862
 
652
863
    //dxaSpace = letterspacing in twips
653
864
    if (!refChp || refChp->dxaSpace != chp->dxaSpace) {
676
887
    }
677
888
}
678
889
 
 
890
void Paragraph::setCombinedCharacters(bool isCombined)
 
891
{
 
892
    m_combinedCharacters = isCombined;
 
893
}
 
894
 
 
895
Paragraph::DropCapStatus Paragraph::dropCapStatus() const
 
896
{
 
897
    return m_dropCapStatus;
 
898
}
 
899
 
 
900
void Paragraph::getDropCapData(QString *string, int *type, int *lines, qreal *distance, QString *style) const
 
901
{
 
902
    // As far as I can see there is only ever a single character as drop cap.
 
903
    *string = m_textStrings.isEmpty() ? QString() : m_textStrings[0];
 
904
    *type = m_dcs_fdct;
 
905
    *lines = m_dcs_lines;
 
906
    *distance = m_dropCapDistance;
 
907
    *style = m_dropCapStyleName;
 
908
}
 
909
 
 
910
 
 
911
void Paragraph::addDropCap(QString &string, int type, int lines, qreal distance, QString style)
 
912
{
 
913
    kDebug(30513) << "combining drop cap paragraph: " << string;
 
914
    if (m_dropCapStatus == IsDropCapPara) 
 
915
        kDebug(30513) << "This paragraph already has a dropcap set!";
 
916
 
 
917
    m_dropCapStatus = HasDropCapIntegrated;
 
918
 
 
919
    // Get the drop cap data.
 
920
    m_dcs_fdct        = type;
 
921
    m_dcs_lines       = lines;
 
922
    m_dropCapDistance = distance;
 
923
    m_dropCapStyleName = style;
 
924
 
 
925
    // Add the actual text.
 
926
    // Here we assume that there will only be one text snippet for the drop cap.
 
927
#if 1
 
928
 
 
929
#if 1
 
930
    kDebug(30513) << "size: " << m_textStrings.size();
 
931
    if (m_textStrings.isEmpty()) {
 
932
        m_textStrings.append(string);
 
933
        KoGenStyle* style = 0;
 
934
        m_textStyles.insert(m_textStyles.begin(), style);
 
935
    } else {
 
936
        m_textStrings[0].prepend(string);
 
937
    }
 
938
#else
 
939
    m_textStrings.prepend(string);
 
940
    KoGenStyle* style = 0;
 
941
    m_textStyles.insert(m_textStyles.begin(), style);
 
942
#endif
 
943
 
 
944
#else
 
945
    std::vector<QString>            tempStrings;
 
946
    std::vector<const KoGenStyle*>  tempStyles;
 
947
    tempStrings.push_back(dropCapParagraph->m_textStrings[0]);
 
948
    KoGenStyle* style = 0;
 
949
    tempStyles.push_back(style);
 
950
 
 
951
    if (dropCapParagraph->m_textStrings.size() > 0) {
 
952
        for (uint i = 0; i < m_textStrings.size(); ++i) {
 
953
            tempStrings.push_back(m_textStrings.[i]);
 
954
            tempStyles.push_back(m_textStyles.[i]);
 
955
        }            
 
956
    }
 
957
 
 
958
    m_textStrings = tempStrings;
 
959
    m_textStyles  = tempStyles;
 
960
#endif
 
961
}
 
962
 
 
963
 
 
964
int Paragraph::strings() const
 
965
{
 
966
    return m_textStrings.size();
 
967
}
 
968
 
 
969
QString Paragraph::string(int index) const
 
970
{
 
971
    return m_textStrings[index];
 
972
}
 
973
 
 
974
QString Paragraph::createTextStyle(wvWare::SharedPtr<const wvWare::Word97::CHP> chp, const wvWare::StyleSheet& styles)
 
975
{
 
976
    const wvWare::Style* msTextStyle = styles.styleByIndex(chp->istd);
 
977
    Q_ASSERT(msTextStyle);
 
978
    QString msTextStyleName = Conversion::styleNameString(msTextStyle->name());
 
979
    kDebug(30513) << "text based on characterstyle " << msTextStyleName;
 
980
 
 
981
    KoGenStyle *textStyle;
 
982
    textStyle = new KoGenStyle(KoGenStyle::TextAutoStyle, "text");
 
983
    if (m_inStylesDotXml) {
 
984
        textStyle->setAutoStyleInStylesDotXml(true);
 
985
    }
 
986
 
 
987
    bool suppresFontSize = false;
 
988
    if (m_paragraphProperties->pap().dcs.lines > 1) {
 
989
        suppresFontSize = true;
 
990
    }
 
991
    applyCharacterProperties(chp, textStyle, m_paragraphStyle, m_bgColor, suppresFontSize, m_combinedCharacters);
 
992
 
 
993
    QString textStyleName('T');
 
994
    textStyleName = m_mainStyles->insert(*textStyle, textStyleName);
 
995
 
 
996
    return textStyleName;
 
997
}
 
998
 
 
999
 
 
1000
QString Paragraph::contrastFontColor(QString name)
 
1001
{
 
1002
    QColor color(name);
 
1003
    int d = 0;
 
1004
 
 
1005
    // counting the perceptive luminance - human eye favors green color...
 
1006
    double a = 1 - (0.299 * color.red() + 0.587 * color.green() + 0.114 * color.blue()) / 255;
 
1007
 
 
1008
    if (a < 0.5) {
 
1009
        d = 0; // bright colors - black font
 
1010
    } else {
 
1011
        d = 255; // dark colors - white font
 
1012
    }
 
1013
    return  QColor(d, d, d).name();
 
1014
}