Commit e82e0acd authored by Matus Uzak's avatar Matus Uzak
Browse files

doc: Added support for Bullet Pictures.

BUG:239469
parent 44bf28f8
......@@ -238,7 +238,7 @@ void WordsGraphicsHandler::emitTextBoxFound(unsigned int index, bool stylesxml)
emit textBoxFound(index, stylesxml);
}
void WordsGraphicsHandler::handleInlineObject(const wvWare::PictureData& data)
QString WordsGraphicsHandler::handleInlineObject(const wvWare::PictureData& data, const bool isBulletPicture)
{
//TODO: The globalCP might be required to obtain the SPA structure for
//inline MS-ODRAW shapes with missing OfficeArtClientAnchor.
......@@ -249,6 +249,7 @@ void WordsGraphicsHandler::handleInlineObject(const wvWare::PictureData& data)
//msosptPictureFrame shapes is stored in the PICF struture.
kDebug(30513) ;
QString ret;
quint32 size = (data.picf->lcb - data.picf->cbHeader);
#ifdef DEBUG_GHANDLER
......@@ -260,22 +261,24 @@ void WordsGraphicsHandler::handleInlineObject(const wvWare::PictureData& data)
//the picture is store in some external file
if (data.picf->mfp.mm == MM_SHAPEFILE) {
DrawingWriter out(*m_currentWriter, *m_mainStyles, m_document->writingHeader());
m_objectType = Inline;
m_picf = data.picf;
insertEmptyInlineFrame(out);
return;
if (!isBulletPicture) {
DrawingWriter out(*m_currentWriter, *m_mainStyles, m_document->writingHeader());
m_objectType = Inline;
m_picf = data.picf;
insertEmptyInlineFrame(out);
}
return ret;
}
// going to parse and process the Data stream content
LEInputStream* in = m_document->dataStream();
if (!in) {
kDebug(30513) << "Data stream not provided, no access to inline shapes!";
return;
return ret;
}
if (data.fcPic > in->getSize()) {
kDebug(30513) << "OfficeArtInlineSpContainer offset out of range, skipping!";
return;
return ret;
}
#ifdef DEBUG_GHANDLER
......@@ -294,11 +297,11 @@ void WordsGraphicsHandler::handleInlineObject(const wvWare::PictureData& data)
} catch (const IOException& e) {
kDebug(30513) << e.msg;
in->rewind(_zero);
return;
return ret;
} catch (...) {
kWarning(30513) << "Warning: Caught an unknown exception!";
in->rewind(_zero);
return;
return ret;
}
in->rewind(_zero);
......@@ -332,6 +335,10 @@ void WordsGraphicsHandler::handleInlineObject(const wvWare::PictureData& data)
}
m_store->leaveDirectory();
if (isBulletPicture) {
return ref.name;
}
bool inStylesXml = m_document->writingHeader();
DrawingWriter out(*m_currentWriter, *m_mainStyles, inStylesXml);
......@@ -342,6 +349,8 @@ void WordsGraphicsHandler::handleInlineObject(const wvWare::PictureData& data)
const OfficeArtSpContainer* o = &(co.shape);
processDrawingObject(*o, out);
return ret;
}
void WordsGraphicsHandler::handleFloatingObject(unsigned int globalCP)
......
......@@ -144,7 +144,7 @@ public:
* This method gets called when an inline object is found by wv2 parser.
* @param data PictureData as defined in functordata.h
*/
virtual void handleInlineObject(const wvWare::PictureData& data);
virtual QString handleInlineObject(const wvWare::PictureData& data, const bool isBulletPicture = false);
/**
* Get the DrawStyle to access document backgroud properties and defaults.
......
......@@ -48,8 +48,6 @@
#include "document.h"
#include "msdoc.h"
enum ListType {BulletType, NumberType, PictureType, DefaultType};
wvWare::U8 WordsReplacementHandler::hardLineBreak()
{
return '\n';
......@@ -1830,12 +1828,6 @@ bool WordsTextHandler::writeListInfo(KoXmlWriter* writer, const wvWare::Word97::
return false;
}
ListType type = NumberType;
//TODO: Where is the rest of the logic?
if (listInfo->numberFormat() == msonfcBullet) {
type = BulletType;
}
//put the currently used writer in the stack
m_usedListWriters.push(writer);
......@@ -1846,7 +1838,7 @@ bool WordsTextHandler::writeListInfo(KoXmlWriter* writer, const wvWare::Word97::
m_currentListLevel = listLevel;
// update automatic numbering info
if (type == NumberType) {
if (listInfo->type() == wvWare::ListInfo::NumberType) {
if (m_continueListNum.contains(listId)) {
if (listLevel <= m_continueListNum[listId].first) {
m_continueListNum[listId].second = true;
......@@ -1884,7 +1876,7 @@ bool WordsTextHandler::writeListInfo(KoXmlWriter* writer, const wvWare::Word97::
writer->startElement("text:list");
writer->addAttribute("text:style-name", m_listStyleName);
if (type == NumberType) {
if (listInfo->type() == wvWare::ListInfo::NumberType) {
QString key = QString("%1").arg(listId);
key.append(QString(".lvl%1").arg(listLevel));
......@@ -1913,7 +1905,7 @@ bool WordsTextHandler::writeListInfo(KoXmlWriter* writer, const wvWare::Word97::
}
// restart numbering if applicable
if (type == NumberType) {
if (listInfo->type() == wvWare::ListInfo::NumberType) {
if (!m_continueListNum.contains(listId) ||
(m_continueListNum.contains(listId) && !m_continueListNum[listId].second)) {
writer->addAttribute("text:start-value", listInfo->startAt());
......@@ -1928,7 +1920,9 @@ bool WordsTextHandler::writeListInfo(KoXmlWriter* writer, const wvWare::Word97::
* A helper function to add the <style:list-level-properties> child element to
* the <text:list-level-style-*> element.
*/
void setListLevelProperties(KoXmlWriter& out, const wvWare::Word97::PAP& pap, const wvWare::ListInfo& listInfo)
void setListLevelProperties(KoXmlWriter& out,
const wvWare::Word97::PAP& pap, const wvWare::ListInfo& listInfo,
const QString& fontSizePt)
{
//
// TEXT POSITION:
......@@ -1970,6 +1964,17 @@ void setListLevelProperties(KoXmlWriter& out, const wvWare::Word97::PAP& pap, co
default:
break;
}
//TODO: make use of PICF, only use fontSize if chp->fNoAutoSize == 0
if (listInfo.type() == wvWare::ListInfo::PictureType) {
if (!fontSizePt.isEmpty()) {
out.addAttribute("fo:width", fontSizePt);
out.addAttribute("fo:height", fontSizePt);
} else {
kDebug(30513) << "Can NOT set automatic size of the bullet picture, fontSize empty!";
}
}
//text:list-level-position-and-space-mode
out.addAttribute("text:list-level-position-and-space-mode", "label-alignment");
//style:list-level-label-alignment
......@@ -2015,15 +2020,10 @@ void WordsTextHandler::updateListStyle() throw(InvalidFormatException)
}
const wvWare::Word97::PAP& pap = m_currentPPs->pap();
const wvWare::SharedPtr<wvWare::Word97::CHP> chp = listInfo->text().chp;
wvWare::UString text = listInfo->text().text;
int nfc = listInfo->numberFormat();
ListType type = NumberType;
//TODO: Where is the rest of the logic?
if (nfc == msonfcBullet) {
type = BulletType;
}
QBuffer buf;
buf.open(QIODevice::WriteOnly);
KoXmlWriter out(&buf);
......@@ -2031,7 +2031,7 @@ void WordsTextHandler::updateListStyle() throw(InvalidFormatException)
//---------------------------------------------
// list-level-style-*
//---------------------------------------------
if (type == BulletType) {
if (listInfo->type() == wvWare::ListInfo::BulletType) {
out.startElement("text:list-level-style-bullet");
if (text.length() == 1) {
// With bullets, text can only be one character, which tells us
......@@ -2058,6 +2058,13 @@ void WordsTextHandler::updateListStyle() throw(InvalidFormatException)
kWarning(30513) << "Bullet with more than one character, not supported";
}
}
else if (listInfo->type() == wvWare::ListInfo::PictureType) {
out.startElement("text:list-level-style-image");
out.addAttribute("xlink:href", listInfo->bulletPictureName().prepend(QString("Pictures/")));
out.addAttribute("xlink:type", "simple");
out.addAttribute("xlink:show", "embed");
out.addAttribute("xlink:actuate", "onLoad");
}
else {
out.startElement("text:list-level-style-number");
......@@ -2170,7 +2177,6 @@ void WordsTextHandler::updateListStyle() throw(InvalidFormatException)
//---------------------------------------------
// text-properties
//---------------------------------------------
const wvWare::SharedPtr<wvWare::Word97::CHP> chp = listInfo->text().chp;
KoGenStyle textStyle(KoGenStyle::TextStyle, "text");
if (chp) {
......@@ -2188,7 +2194,7 @@ void WordsTextHandler::updateListStyle() throw(InvalidFormatException)
//MSWord: A label does NOT inherit Underline from text-properties of the
//paragraph style. A bullet does not inherit {Italics, Bold}.
if (type != NumberType) {
if (listInfo->type() != wvWare::ListInfo::NumberType) {
if ((textStyle.property("fo:font-style")).isEmpty()) {
textStyle.addProperty("fo:font-style", "normal");
}
......@@ -2205,7 +2211,7 @@ void WordsTextHandler::updateListStyle() throw(InvalidFormatException)
//---------------------------------------------
// list-level-properties
//---------------------------------------------
setListLevelProperties(out, pap, *listInfo);
setListLevelProperties(out, pap, *listInfo, textStyle.property("fo:font-size"));
out.endElement(); //text:list-level-style-*
//---------------------------------------------
......@@ -2252,7 +2258,8 @@ void WordsTextHandler::saveState()
{
kDebug(30513);
m_oldStates.push(State(m_currentTable, m_paragraph, m_listStyleName,
m_currentListLevel, m_currentListID, m_previousLists,
m_currentListLevel, m_currentListID,
m_previousLists,
m_drawingWriter, m_insideDrawing));
m_currentTable = 0;
m_paragraph = 0;
......
code | sprm | operand
=============================================================================================
0x 0836 | sprmCFItalic |
0x 0839 | sprmCFShadow |
0x 083c | sprmCFVanish | Specifies whether the text is formatted as hidden.
0x 0855 | sprmCFSpec | Specifies whether the current text has a special meaning.
0x 286f | sprmCIdctHint | Hint on which of the language, font, size, bold, and italic properties to use.
0x 2a3e | sprmCKul | The underlining style of the text.
0x 2a42 | sprmCIco | Specifies the color of the text. The default text color is cvAuto.
0x 2a53 | sprmCFDStrike |
0x 485f | sprmCLidBi | The language of the text when the text is displayed R-t-L or is complex script
0x 486d | sprmCRgLid0_80 | The language of the text, except for East Asian languages.
0x 4873 | sprmCRgLid0 | The language of the text, except for East Asian languages.
0x 4874 | sprmCRgLid1 | The language of the text if it is an East Asian language.
0x 4888 | sprmCPbiGrf | Specifies whether a picture is used as a bullet character when rendering the bullet.
0x 4a43 | sprmCHps | An unsigned 2-byte integer that specifies the size of the text.
0x 4a4f | sprmCRgFtc0 | Index into the font table.
0x 4a51 | sprmCRgFtc2 | Index into the font table.
0x 4a5e | sprmCFtcBi | Index into the font table (SttbfFfn).
0x 4a61 | sprmCHpsBi | An unsigned 2-byte integer that specifies the size of the text (Right-to-Left).
0x 6815 | sprmCRsidProp | Revision save ID.
0x 6816 | sprmCRsidText | Revision save ID.
0x 6870 | sprmCCv | A COLORREF value that specifies the color of the text.
0x 6877 | sprmCCvUl | A COLORREF value that specifies the color of the text underline.
0x 6887 | sprmCPbiIBullet | A CP value in Bullet Pictures document that specifies which picture is used as a bullet.
0x 6a03 | sprmCPicLocation | Specifies either picture position in Data Stream/binary data/name of OLE object storage.
0x 6a09 | sprmCSymbol | Designates the character as a symbol and specifies it's font and character code.
=============================================================================================
0x 2403 | sprmPJc80 | Physical justification of the paragraph.
0x 2461 | sprmPJc | Logical justification of the paragraph.
0x 260a | sprmPIlvl | List level of the paragraph.
0x 460b | sprmPIlfo | List identificator.
0x 6424 | sprmPBrcTop80 | Top border of the paragraph.
0x 6425 | sprmPBrcLeft80 | Left border of the paragraph.
0x 6426 | sprmPBrcBottom80 |
0c 6427 | sprmPBrcRight80 |
0x 6467 | sprmPRsid | Revision save ID.
0x 840e | sprmPDxaRight80 | Physical right indent of the paragraph [twips]
0x 840f | sprmPDxaLeft80 | Physical left indent of the P (Paragraph) [twips].
0x 8411 | sprmPDxaLeft180 | Logical left indent of the 1st line of the P, relative to the rest of the P [twips].
0x 845d | sprmPDxaRight | Logical right indent of the paragraph [twips]
0x 845e | sprmPDxaLeft | Logical left indent of the P (Paragraph) [twips].
0x 8460 | sprmPDxaLeft1 | Logical left indent of the 1st line of the P, relative to the rest of the P [twips].
0x a413 | sprmPDyaBefore | Spacing before this paragraph [twips].
0x c60d | sprmPChgTabsPapx | Custom tab stops to be added or ignored.
0x c615 | sprmPChgTabs | Custom tab stops that are added or ignored.
0x c64e | sprmPBrcTop | Top border of the paragraph.
0x c64f | sprmPBrcLeft |
0x c650 | sprmPBrcBottom |
0x c651 | sprmPBrcRight |
=============================================================================================
......@@ -135,18 +135,16 @@ Bookmarks::~Bookmarks()
delete m_start;
}
BookmarkData Bookmarks::bookmark( U32 globalCP, bool& ok )
BookmarkData Bookmarks::bookmark( const U32 globalCP, bool& ok )
{
#ifdef WV2_DEBUG_BOOKMARK
wvlog << " globalCP=" << globalCP << endl;
#endif
ok = false;
if ( (m_startIt && m_startIt->current()) &&
(m_startIt->currentStart() == globalCP) &&
(m_nameIt != m_name.end()) )
{
ok = false;
if (m_valid.isEmpty()) {
wvlog << "BUG: m_valid empty?";
} else if (m_valid.first()) {
......@@ -178,9 +176,45 @@ BookmarkData Bookmarks::bookmark( U32 globalCP, bool& ok )
#endif
return BookmarkData( start, end, name );
}
return BookmarkData( 0, 0, wvWare::UString("") );
}
BookmarkData Bookmarks::bookmark(const UString& name, bool& ok ) const
{
std::vector<UString>::const_iterator nameIt = m_name.begin();
PLCFIterator<Word97::BKF> startIt(*m_start);
PLCFIterator<Word97::BKL>* endIt = 0;
if (m_nFib < Word8nFib) {
endIt = new PLCFIterator<Word97::BKL>(*m_end);
}
while (startIt.current()) {
if (*nameIt == name) {
U32 start = startIt.currentStart();
U32 end = start;
if (m_nFib < Word8nFib) {
end = endIt->currentStart();
delete endIt;
} else {
U16 ibkl = startIt.current()->ibkl;
end = m_endCP[ibkl];
}
ok = true;
return BookmarkData( start, end, name );
}
++startIt;
++nameIt;
if (m_nFib < Word8nFib) {
++( *endIt );
}
}
if (m_nFib < Word8nFib) {
delete endIt;
}
ok = false;
return BookmarkData( 0, 0, wvWare::UString("") );
return BookmarkData( 0, 0, UString("") );
}
U32 Bookmarks::nextBookmarkStart()
......@@ -250,7 +284,6 @@ void Bookmarks::check( U32 globalCP )
#ifdef WV2_DEBUG_BOOKMARK
wvlog << "Bookmark skipped! CP:" << globalCP;
m_num--;
#endif
}
}
......
......@@ -56,7 +56,15 @@ namespace wvWare
* found. If @param ok is false no valid bookmark has been found
* and the returned BookmarkData structure is invalid.
*/
BookmarkData bookmark( U32 globalCP, bool& ok );
BookmarkData bookmark( const U32 globalCP, bool& ok );
/**
* Get the BookmarkData for the Bookmark of @param name. The
* @param ok flag is true if a bookmark has been found. If @param
* ok is false no valid bookmark has been found and the returned
* BookmarkData structure is invalid.
*/
BookmarkData bookmark( const UString& name, bool& ok ) const;
/**
* Returns the global CP of the next bookmark start,
......
......@@ -21,7 +21,6 @@
#include "paragraphproperties.h"
#include "functor.h"
#include "wvlog.h"
#include <QList>
using namespace wvWare;
......@@ -143,8 +142,9 @@ void GraphicsHandler::handleFloatingObject(unsigned int /*globalCP*/)
}
void GraphicsHandler::handleInlineObject(const PictureData& /*data*/)
QString GraphicsHandler::handleInlineObject(const PictureData& /*data*/, const bool /*isBulletPicture*/)
{
return QString();
}
TextHandler::~TextHandler()
......
......@@ -77,7 +77,7 @@ namespace wvWare {
public:
virtual ~SubDocumentHandler();
/**
/**
* Set the progress of WordDocument Stream processing. All other
* streams (Table, Data) are refered from this one.
*/
......@@ -216,17 +216,17 @@ namespace wvWare {
virtual ~GraphicsHandler();
/**
* This method gets called when a floating object is found.
* @param globalCP (character position)
*/
/**
* This method gets called when a floating object is found.
* @param globalCP (character position)
*/
virtual void handleFloatingObject(unsigned int globalCP);
/**
* This method gets called when an inline object is found. @param data
* the picture properties and offset into data stream.
*/
virtual void handleInlineObject(const PictureData& data);
/**
* This method gets called when an inline object is found. @param data
* the picture properties and offset into data stream.
*/
virtual QString handleInlineObject(const PictureData& data, const bool isBulletPicture = false);
};
......
......@@ -16,6 +16,7 @@
Boston, MA 02111-1307, USA.
*/
#include "../../msdoc.h"
#include "lists.h"
#include "olestream.h"
#include "word97_generated.h"
......@@ -609,7 +610,7 @@ ListInfo::ListInfo( Word97::PAP& pap, const Word97::CHP& chp, ListInfoProvider&
m_linkedIstd( istdNil ), m_restartingCounter( false ), m_numberFormat( 0 ),
m_alignment( 0 ), m_isLegal( false ), m_notRestarted( false ), m_prev( false ),
m_prevSpace( false ), m_isWord6( false ), m_followingChar( 0 ), m_lsid( 0 ),
m_space( 0 ), m_indent( 0 )
m_space( 0 ), m_indent( 0 ), m_picAutoSize( false ), m_type( NumberType )
{
if ( !listInfoProvider.setPAP( &pap ) ) {
return;
......@@ -639,6 +640,14 @@ ListInfo::ListInfo( Word97::PAP& pap, const Word97::CHP& chp, ListInfoProvider&
m_followingChar = level->followingChar();
m_space = level->space();
m_indent = level->indent();
if (m_numberFormat == msonfcBullet) {
m_type = BulletType;
}
if (m_text.chp->fPicBullet) {
m_type = PictureType;
m_picAutoSize = !m_text.chp->fNoAutoSize;
}
} else {
wvlog << "Bug: The ListLevel is 0!!" << endl;
}
......
......@@ -25,6 +25,7 @@
#include "ustring.h"
#include "sharedptr.h"
#include "wv2_export.h"
#include <QString>
namespace wvWare
{
......@@ -67,6 +68,8 @@ namespace wvWare
class ListInfo
{
public:
enum ListType {BulletType, NumberType, PictureType, DefaultType};
ListInfo( Word97::PAP& pap, const Word97::CHP& chp, ListInfoProvider& listInfoProvider );
/**
......@@ -164,6 +167,27 @@ namespace wvWare
*/
void dump() const;
/**
* Set the name of the bullet picture.
*/
void setBulletPictureName(const QString& name ) { m_picName = name; };
/**
* @return bullet picture name.
*/
QString bulletPictureName() const { return m_picName; };
/**
* @return whether the size of the picture changes automatically to
* match the size of the text that follows the bullet
*/
bool isBulletPictureAutoSize() const { return m_picAutoSize; };
/**
* @return list type.
*/
ListType type() const { return m_type; };
private:
ListInfo& operator=( const ListInfo& rhs );
......@@ -182,6 +206,9 @@ namespace wvWare
S32 m_lsid;
U16 m_space;
U16 m_indent;
QString m_picName;
bool m_picAutoSize;
ListType m_type;
};
......
......@@ -57,6 +57,11 @@ const ListInfo* ParagraphProperties::listInfo() const
return m_listInfo;
}
void ParagraphProperties::setBulletPictureName(const QString& name)
{
m_listInfo->setBulletPictureName(name);
}
void ParagraphProperties::createListInfo( ListInfoProvider& listInfoProvider, const Word97::CHP& chp)
{
if ( m_listInfo || !listInfoProvider.isValid( m_pap.ilfo, m_pap.nLvlAnm ) ) {
......
......@@ -50,6 +50,11 @@ namespace wvWare
*/
const ListInfo* listInfo() const;
/**
* Set the name of the bullet picture into ListInfo.
*/
void setBulletPictureName(const QString& name);
/**
* @internal
*/
......
......@@ -318,6 +318,7 @@ void Parser9x::parseTextBox(uint index, bool stylesxml)
PLCFIterator<Word97::FTXBXS> it( plcftxbxTxt->at( index ) );
//TODO: Do we need to save the state here?
saveState( it.currentRun() - 1, TextBox );
U32 offset = m_fib.ccpText + it.currentStart();
offset += m_fib.ccpFtn + m_fib.ccpHdd + m_fib.ccpAtn + m_fib.ccpEdn;
......@@ -495,7 +496,7 @@ void Parser9x::parseHelper( Position startPos )
U32 limit = it.currentRun(); // Number of characters in this piece
// Check whether the text starts somewhere within the piece, reset at
// the end of the loop body
// the end of the loop body.
if ( startPos.offset != 0 ) {
fc += unicode ? startPos.offset * 2 : startPos.offset;
limit -= startPos.offset;
......@@ -746,6 +747,45 @@ void Parser9x::processParagraph( U32 fc )
props->pap().dump();
#endif
// Parse the bullet picture data.
const Word97::CHP* bulletChp = 0;
if (props->listInfo()) {
bulletChp = (props->listInfo()->text()).chp;
}
if (bulletChp && bulletChp->fPicBullet) {
bool ok;
BookmarkData data( m_bookmarks->bookmark(UString("_PictureBullets"), ok) );
if (ok) {
Position pos(data.startCP + bulletChp->picBulletCP, m_plcfpcd);
PLCFIterator<Word97::PCD> it( m_plcfpcd->at( pos.piece ));
U32 fc = it.current()->fc;
bool unicode;
realFC( fc, unicode );
fc += unicode ? pos.offset * 2: pos.offset;
Word97::CHP* bulletPicChp = new Word97::CHP();
m_properties->fullSavedChp( fc, bulletPicChp, 0 );
if (bulletPicChp->fSpec) {
m_wordDocument->push();
m_wordDocument->seek( fc, WV2_SEEK_SET );
U8 c = m_wordDocument->readU8();
m_wordDocument->pop();
if (c == TextHandler::Picture) {
SharedPtr<const Word97::CHP> sharedBPChp( bulletPicChp );
QString name = emitPictureData( 0, sharedBPChp, true);
props->setBulletPictureName(name);