text export support for bullets and hyperlinks

SVGFilter:
- new:
implExportTextShapeIndex, implEmbedBulletGlyphs, implEmbedBulletGlyph,
implExportTextEmbeddedBitmaps
- modified:
implExportShape, implCreateObjectsFromShapes, implCreateObjectsFromShape

SVGActionWriter:
- new:
GetChecksum
- modified:
ImplWriteActions, WriteMetaFile
 
SVGTextWriter:
-new:
implExportHyperlinkIds, implWriteBulletChars, writeBitmapPlaceholder, 
implWriteEmbeddedBitmaps, setTextShape, implRegisterInterface, 
implGetValidIDFromInterface
-modified:
nextParagraph, nextTextPortion, startTextShape, endTextShape, startTextParagraph, 
endTextParagraph, writeTextPortion, implWriteTextPortion
This commit is contained in:
Marco Cecchetti
2012-10-10 12:03:28 +02:00
committed by Thorsten Behrens
parent 5626e72394
commit b76628acb1
4 changed files with 1022 additions and 35 deletions
+222 -12
View File
@@ -89,6 +89,7 @@ static const char aOOOAttrDateTimeField[] = NSPREFIX "date-time-field";
static const char aOOOAttrFooterField[] = NSPREFIX "footer-field";
static const char aOOOAttrHeaderField[] = NSPREFIX "header-field";
static const char aOOOAttrHasTransition[] = NSPREFIX "has-transition";
static const char aOOOAttrIdList[] = NSPREFIX "id-list";
// ooo xml attributes for pages and shapes
static const char aOOOAttrName[] = NSPREFIX "name";
@@ -800,12 +801,16 @@ sal_Bool SVGFilter::implExportDocument()
mpSVGFontExport = new SVGFontExport( *mpSVGExport, aObjects );
mpSVGWriter = new SVGActionWriter( *mpSVGExport, *mpSVGFontExport );
if( mpSVGExport->IsEmbedFonts() )
{
mpSVGFontExport->EmbedFonts();
}
if( !mpSVGExport->IsUsePositionedCharacters() )
{
implExportTextShapeIndex();
implEmbedBulletGlyphs();
implExportTextEmbeddedBitmaps();
}
implExportMasterPages( mMasterPageTargets, 0, mMasterPageTargets.getLength() - 1 );
implExportDrawPages( mSelectedPages, 0, nLastPage );
@@ -1138,6 +1143,154 @@ sal_Bool SVGFilter::implExportAnimations()
return bRet;
}
// -----------------------------------------------------------------------------
void SVGFilter::implExportTextShapeIndex()
{
mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "class", B2UCONST( "TextShapeIndex" ) );
SvXMLElementExport aDefsContainerElem( *mpSVGExport, XML_NAMESPACE_NONE, "defs", sal_True, sal_True );
sal_Int32 nCount = mSelectedPages.getLength();
for( sal_Int32 i = 0; i < nCount; ++i )
{
const Reference< XDrawPage > & xDrawPage = mSelectedPages[i];
if( mTextShapeIdListMap.find( xDrawPage ) != mTextShapeIdListMap.end() )
{
OUString sTextShapeIdList = mTextShapeIdListMap[xDrawPage].trim();
Reference< XInterface > xRef( xDrawPage, UNO_QUERY );
const OUString& rPageId = implGetValidIDFromInterface( xRef );
if( !rPageId.isEmpty() && !sTextShapeIdList.isEmpty() )
{
mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, aOOOAttrSlide, rPageId );
mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, aOOOAttrIdList, sTextShapeIdList );
SvXMLElementExport aGElem( *mpSVGExport, XML_NAMESPACE_NONE, "g", sal_True, sal_True );
}
}
}
}
// -----------------------------------------------------------------------------
void SVGFilter::implEmbedBulletGlyphs()
{
mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "class", B2UCONST( "EmbeddedBulletChars" ) );
SvXMLElementExport aDefsContainerElem( *mpSVGExport, XML_NAMESPACE_NONE, "defs", sal_True, sal_True );
OUString sPathData = B2UCONST( "M 580,1141 L 1163,571 580,0 -4,571 580,1141 Z" );
implEmbedBulletGlyph( 57356, sPathData );
sPathData = B2UCONST( "M 8,1128 L 1137,1128 1137,0 8,0 8,1128 Z" );
implEmbedBulletGlyph( 57354, sPathData );
sPathData = B2UCONST( "M 174,0 L 602,739 174,1481 1456,739 174,0 Z M 1358,739 L 309,1346 659,739 1358,739 Z" );
implEmbedBulletGlyph( 10146, sPathData );
sPathData = B2UCONST( "M 2015,739 L 1276,0 717,0 1260,543 174,543 174,936 1260,936 717,1481 1274,1481 2015,739 Z" );
implEmbedBulletGlyph( 10132, sPathData );
sPathData = B2UCONST( "M 0,-2 C -7,14 -16,27 -25,37 L 356,567 C 262,823 215,952 215,954 215,979 228,992 255,992 264,992 276,990 289,987 310,991 331,999 354,1012 L 381,999 492,748 772,1049 836,1024 860,1049 C 881,1039 901,1025 922,1006 886,937 835,863 770,784 769,783 710,716 594,584 L 774,223 C 774,196 753,168 711,139 L 727,119 C 717,90 699,76 672,76 641,76 570,178 457,381 L 164,-76 C 142,-110 111,-127 72,-127 30,-127 9,-110 8,-76 1,-67 -2,-52 -2,-32 -2,-23 -1,-13 0,-2 Z" );
implEmbedBulletGlyph( 10007, sPathData );
sPathData = B2UCONST( "M 285,-33 C 182,-33 111,30 74,156 52,228 41,333 41,471 41,549 55,616 82,672 116,743 169,778 240,778 293,778 328,747 346,684 L 369,508 C 377,444 397,411 428,410 L 1163,1116 C 1174,1127 1196,1133 1229,1133 1271,1133 1292,1118 1292,1087 L 1292,965 C 1292,929 1282,901 1262,881 L 442,47 C 390,-6 338,-33 285,-33 Z" );
implEmbedBulletGlyph( 10004, sPathData );
sPathData = B2UCONST( "M 813,0 C 632,0 489,54 383,161 276,268 223,411 223,592 223,773 276,916 383,1023 489,1130 632,1184 813,1184 992,1184 1136,1130 1245,1023 1353,916 1407,772 1407,592 1407,412 1353,268 1245,161 1136,54 992,0 813,0 Z" );
implEmbedBulletGlyph( 9679, sPathData );
sPathData = B2UCONST( "M 346,457 C 273,457 209,483 155,535 101,586 74,649 74,723 74,796 101,859 155,911 209,963 273,989 346,989 419,989 480,963 531,910 582,859 608,796 608,723 608,648 583,586 532,535 482,483 420,457 346,457 Z" );
implEmbedBulletGlyph( 8226, sPathData );
sPathData = B2UCONST( "M -4,459 L 1135,459 1135,606 -4,606 -4,459 Z" );
implEmbedBulletGlyph( 8211, sPathData );
}
// -----------------------------------------------------------------------------
void SVGFilter::implEmbedBulletGlyph( sal_Unicode cBullet, const ::rtl::OUString & sPathData )
{
OUString sId = B2UCONST( "bullet-char-template(" );
sId += OUString::valueOf( (sal_Int32)cBullet );
sId += B2UCONST( ")" );
mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "id", sId );
double fFactor = 1.0 / 2048;
OUString sFactor = OUString::valueOf( fFactor );
OUString sTransform = B2UCONST( "scale(" );
sTransform += sFactor; sTransform += B2UCONST( ",-" ); sTransform += sFactor;
sTransform += B2UCONST( ")" );
mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "transform", sTransform );
SvXMLElementExport aGElem( *mpSVGExport, XML_NAMESPACE_NONE, "g", sal_True, sal_True );
mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "d", sPathData );
SvXMLElementExport aPathElem( *mpSVGExport, XML_NAMESPACE_NONE, "path", sal_True, sal_True );
}
// -----------------------------------------------------------------------------
/** SVGFilter::implExportTextEmbeddedBitmaps
* We export bitmaps embedded into text shapes, such as those used by list
* items with image style, only once in a specic <defs> element.
*/
sal_Bool SVGFilter::implExportTextEmbeddedBitmaps()
{
mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "class", B2UCONST( "TextEmbeddedBitmaps" ) );
SvXMLElementExport aDefsContainerElem( *mpSVGExport, XML_NAMESPACE_NONE, "defs", sal_True, sal_True );
OUString sId;
MetaBitmapActionSet::const_iterator it = mEmbeddedBitmapActionSet.begin();
MetaBitmapActionSet::const_iterator end = mEmbeddedBitmapActionSet.end();
for( ; it != end; ++it)
{
const GDIMetaFile& aMtf = it->GetRepresentation();
if( aMtf.GetActionSize() == 1 )
{
MetaBmpExScaleAction* pAction = (MetaBmpExScaleAction*) aMtf.GetAction( 0 );
if( pAction )
{
sal_uLong nId = pAction->GetBitmapEx().GetChecksum();
sId = B2UCONST( "bitmap(" );
sId += OUString::valueOf( (sal_Int64)nId );
sId += B2UCONST( ")" );
mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "id", sId );
const Reference< XShape >& rxShape = (const Reference< XShape >&)( it->GetObject() );
Reference< XPropertySet > xShapePropSet( rxShape, UNO_QUERY );
::com::sun::star::awt::Rectangle aBoundRect;
if( xShapePropSet.is() && ( xShapePropSet->getPropertyValue( B2UCONST( "BoundRect" ) ) >>= aBoundRect ) )
{
// Origin of the coordinate device must be (0,0).
const Point aTopLeft;
const Size aSize( aBoundRect.Width, aBoundRect.Height );
const Point aPt = pAction->GetPoint();
// The image must be exported with x, y attribute set to 0,
// on the contrary when referenced by a <use> element,
// specifying the wanted position, they will result
// misplaced.
pAction->Move( -aPt.X(), -aPt.Y() );
mpSVGWriter->WriteMetaFile( aTopLeft, aSize, aMtf, SVGWRITER_WRITE_ALL, NULL );
// We reset to the original values so that when the <use>
// element is created the x, y attributes are correct.
pAction->Move( aPt.X(), aPt.Y() );
}
else
{
OSL_FAIL( "implExportTextEmbeddedBitmaps: no shape bounding box." );
return sal_False;
}
}
else
{
OSL_FAIL( "implExportTextEmbeddedBitmaps: metafile should have MetaBmpExScaleAction only." );
return sal_False;
}
}
else
{
OSL_FAIL( "implExportTextEmbeddedBitmaps: metafile should have a single action." );
return sal_False;
}
}
return sal_True;
}
// -----------------------------------------------------------------------------
@@ -1572,11 +1725,21 @@ sal_Bool SVGFilter::implExportShape( const Reference< XShape >& rxShape )
//mpSVGExport->AddAttributeIdLegacy( XML_NAMESPACE_DRAW, rShapeId );
}
const GDIMetaFile* pEmbeddedBitmapsMtf = NULL;
if( mEmbeddedBitmapActionMap.find( rxShape ) != mEmbeddedBitmapActionMap.end() )
{
Reference< XText > xText( rxShape, UNO_QUERY );
mpSVGWriter->bIsTextShape = xText.is();
pEmbeddedBitmapsMtf = &( mEmbeddedBitmapActionMap[ rxShape ].GetRepresentation() );
}
{
// Reference< XText > xText( rxShape, UNO_QUERY );
// mpSVGWriter->bIsTextShape = xText.is();
SvXMLElementExport aExp2( *mpSVGExport, XML_NAMESPACE_NONE, "g", sal_True, sal_True );
mpSVGWriter->WriteMetaFile( aTopLeft, aSize, rMtf, SVGWRITER_WRITE_ALL, pElementId );
mpSVGWriter->WriteMetaFile( aTopLeft, aSize, rMtf,
SVGWRITER_WRITE_ALL,
pElementId,
&rxShape,
pEmbeddedBitmapsMtf );
}
}
@@ -1606,7 +1769,7 @@ sal_Bool SVGFilter::implCreateObjects()
Reference< XShapes > xShapes( xMasterPage, UNO_QUERY );
if( xShapes.is() )
implCreateObjectsFromShapes( xShapes );
implCreateObjectsFromShapes( xMasterPage, xShapes );
}
}
@@ -1641,7 +1804,7 @@ sal_Bool SVGFilter::implCreateObjects()
Reference< XShapes > xShapes( xDrawPage, UNO_QUERY );
if( xShapes.is() )
implCreateObjectsFromShapes( xShapes );
implCreateObjectsFromShapes( xDrawPage, xShapes );
}
}
return sal_True;
@@ -1649,7 +1812,7 @@ sal_Bool SVGFilter::implCreateObjects()
// -----------------------------------------------------------------------------
sal_Bool SVGFilter::implCreateObjectsFromShapes( const Reference< XShapes >& rxShapes )
sal_Bool SVGFilter::implCreateObjectsFromShapes( const Reference< XDrawPage > & rxPage, const Reference< XShapes >& rxShapes )
{
Reference< XShape > xShape;
sal_Bool bRet = sal_False;
@@ -1657,7 +1820,7 @@ sal_Bool SVGFilter::implCreateObjectsFromShapes( const Reference< XShapes >& rxS
for( sal_Int32 i = 0, nCount = rxShapes->getCount(); i < nCount; ++i )
{
if( ( rxShapes->getByIndex( i ) >>= xShape ) && xShape.is() )
bRet = implCreateObjectsFromShape( xShape ) || bRet;
bRet = implCreateObjectsFromShape( rxPage, xShape ) || bRet;
xShape = NULL;
}
@@ -1667,15 +1830,16 @@ sal_Bool SVGFilter::implCreateObjectsFromShapes( const Reference< XShapes >& rxS
// -----------------------------------------------------------------------------
sal_Bool SVGFilter::implCreateObjectsFromShape( const Reference< XShape >& rxShape )
sal_Bool SVGFilter::implCreateObjectsFromShape( const Reference< XDrawPage > & rxPage, const Reference< XShape >& rxShape )
{
sal_Bool bRet = sal_False;
if( rxShape->getShapeType().lastIndexOf( B2UCONST( "drawing.GroupShape" ) ) != -1 )
{
Reference< XShapes > xShapes( rxShape, UNO_QUERY );
if( xShapes.is() )
bRet = implCreateObjectsFromShapes( xShapes );
bRet = implCreateObjectsFromShapes( rxPage, xShapes );
}
else
{
@@ -1700,8 +1864,54 @@ sal_Bool SVGFilter::implCreateObjectsFromShape( const Reference< XShape >& rxSha
(*mpObjects)[ rxShape ] = ObjectRepresentation( rxShape, aMtf );
}
else
(*mpObjects)[ rxShape ] = ObjectRepresentation( rxShape, aGraphic.GetGDIMetaFile() );
{
Reference< XText > xText( rxShape, UNO_QUERY );
sal_Bool bIsTextShape = xText.is();
if( !mpSVGExport->IsUsePositionedCharacters() && bIsTextShape )
{
// We create a map of text shape ids.
implRegisterInterface( rxShape );
Reference< XInterface > xRef( rxShape, UNO_QUERY );
const OUString& rShapeId = implGetValidIDFromInterface( xRef );
if( !rShapeId.isEmpty() )
{
mTextShapeIdListMap[rxPage] += rShapeId;
mTextShapeIdListMap[rxPage] += B2UCONST( " " );
}
// We create a set of bitmaps embedded into text shape.
GDIMetaFile aMtf;
const Point aNullPt;
const Size aSize( pObj->GetCurrentBoundRect().GetSize() );
MetaAction* pAction;
const GDIMetaFile& rMtf = aGraphic.GetGDIMetaFile();
sal_uLong nCount = rMtf.GetActionSize();
for( sal_uLong nCurAction = 0; nCurAction < nCount; ++nCurAction )
{
pAction = rMtf.GetAction( nCurAction );
const sal_uInt16 nType = pAction->GetType();
if( nType == META_BMPEXSCALE_ACTION )
{
GDIMetaFile aEmbeddedBitmapMtf;
pAction->Duplicate();
aEmbeddedBitmapMtf.AddAction( pAction );
aEmbeddedBitmapMtf.SetPrefSize( aSize );
aEmbeddedBitmapMtf.SetPrefMapMode( MAP_100TH_MM );
mEmbeddedBitmapActionSet.insert( ObjectRepresentation( rxShape, aEmbeddedBitmapMtf ) );
pAction->Duplicate();
aMtf.AddAction( pAction );
}
}
aMtf.SetPrefSize( aSize );
aMtf.SetPrefMapMode( MAP_100TH_MM );
mEmbeddedBitmapActionMap[ rxShape ] = ObjectRepresentation( rxShape, aMtf );
}
(*mpObjects)[ rxShape ] = ObjectRepresentation( rxShape, aGraphic.GetGDIMetaFile() );
}
bRet = sal_True;
}
}
+77 -2
View File
@@ -226,6 +226,70 @@ struct HashUChar
size_t operator()( const sal_Unicode uchar ) const { return static_cast< size_t >( uchar ); }
};
// ---------------------------
// - HashBmpExScale -
// ---------------------------
struct HashBmpExScale
{
size_t operator()( const ObjectRepresentation& rObjRep ) const
{
const GDIMetaFile& aMtf = rObjRep.GetRepresentation();
if( aMtf.GetActionSize() == 1 )
{
const MetaBmpExScaleAction* pAction = (const MetaBmpExScaleAction*) aMtf.GetAction( 0 );
if( pAction )
{
return static_cast< size_t >( pAction->GetBitmapEx().GetChecksum() );
}
else
{
OSL_FAIL( "HashBmpExScale: metafile should have MetaBmpExScaleAction only." );
return 0;
}
}
else
{
OSL_FAIL( "HashBmpExScale: metafile should have a single action." );
return 0;
}
}
};
// ---------------------------
// - EqualityBmpExScale -
// ---------------------------
struct EqualityBmpExScale
{
bool operator()( const ObjectRepresentation& rObjRep1,
const ObjectRepresentation& rObjRep2 ) const
{
const GDIMetaFile& aMtf1 = rObjRep1.GetRepresentation();
const GDIMetaFile& aMtf2 = rObjRep2.GetRepresentation();
if( aMtf1.GetActionSize() == 1 && aMtf2.GetActionSize() == 1 )
{
const MetaBmpExScaleAction* pA1 = (const MetaBmpExScaleAction*) aMtf1.GetAction( 0 );
const MetaBmpExScaleAction* pA2 = (const MetaBmpExScaleAction*) aMtf2.GetAction( 0 );
if( pA1 && pA2 )
{
return ( pA1->GetBitmapEx().GetChecksum() == pA2->GetBitmapEx().GetChecksum() );
}
else
{
OSL_FAIL( "EqualityBmpExScale: metafile should have MetaBmpExScaleAction only." );
return false;
}
}
else
{
OSL_FAIL( "EqualityBmpExScale: metafile should have a single action." );
return false;
}
}
};
// -------------
// - SVGFilter -
@@ -250,6 +314,10 @@ public:
typedef ::boost::unordered_map< ::rtl::OUString, UCharSet, HashOUString > UCharSetMap;
typedef ::boost::unordered_map< Reference< XInterface >, UCharSetMap, HashReferenceXInterface > UCharSetMapMap;
typedef ::boost::unordered_map< Reference< XInterface >, ::rtl::OUString, HashReferenceXInterface > UOStringMap;
typedef ::boost::unordered_set< ObjectRepresentation, HashBmpExScale, EqualityBmpExScale > MetaBitmapActionSet;
private:
Reference< XMultiServiceFactory > mxMSF;
@@ -267,6 +335,9 @@ private:
::rtl::OUString msClipPathId;
UCharSetMapMap mTextFieldCharSets;
Reference< XInterface > mCreateOjectsCurrentMasterPage;
UOStringMap mTextShapeIdListMap;
MetaBitmapActionSet mEmbeddedBitmapActionSet;
ObjectMap mEmbeddedBitmapActionMap;
ObjectMap* mpObjects;
Reference< XComponent > mxSrcDoc;
@@ -285,6 +356,10 @@ private:
sal_Bool implGetPagePropSet( const Reference< XDrawPage > & rxPage );
sal_Bool implGenerateMetaData();
void implExportTextShapeIndex();
void implEmbedBulletGlyphs();
void implEmbedBulletGlyph( sal_Unicode cBullet, const ::rtl::OUString & sPathData );
sal_Bool implExportTextEmbeddedBitmaps();
sal_Bool implGenerateScript();
sal_Bool implExportDocument();
@@ -303,8 +378,8 @@ private:
sal_Bool implExportShape( const Reference< XShape >& rxShape );
sal_Bool implCreateObjects();
sal_Bool implCreateObjectsFromShapes( const Reference< XShapes >& rxShapes );
sal_Bool implCreateObjectsFromShape( const Reference< XShape >& rxShape );
sal_Bool implCreateObjectsFromShapes( const Reference< XDrawPage > & rxPage, const Reference< XShapes >& rxShapes );
sal_Bool implCreateObjectsFromShape( const Reference< XDrawPage > & rxPage, const Reference< XShape >& rxShape );
sal_Bool implCreateObjectsFromBackground( const Reference< XDrawPage >& rxMasterPage );
::rtl::OUString implGetClassFromShape( const Reference< XShape >& rxShape );
+623 -14
View File
@@ -31,9 +31,10 @@
#include "svgfontexport.hxx"
#include "svgwriter.hxx"
#include <rtl/crc.h>
#include <vcl/unohelp.hxx>
#include <tools/helpers.hxx>
#include <xmloff/unointerfacetouniqueidentifiermapper.hxx>
#include <sax/tools/converter.hxx>
#include <boost/shared_array.hpp>
@@ -97,8 +98,19 @@ static const char aXMLAttrPatternUnits[] = "patternUnits";
static const char aXMLAttrOffset[] = "offset";
static const char aXMLAttrStopColor[] = "stop-color";
#define NSPREFIX "ooo:"
static const char aOOOAttrNumberingType[] = NSPREFIX "numbering-type";
static sal_Char const XML_UNO_NAME_NRULE_NUMBERINGTYPE[] = "NumberingType";
static sal_Char const XML_UNO_NAME_NRULE_BULLET_CHAR[] = "BulletChar";
// -----------------------------------------------------------------------------
// ----------------------
// - SVGAttributeWriter -
// ----------------------
@@ -443,12 +455,25 @@ SVGTextWriter::SVGTextWriter( SVGExport& rExport, SVGFontExport& rFontExport )
mrFontExport( rFontExport ),
mpContext( NULL ),
mpVDev( NULL ),
mrTextShape(),
mrParagraphEnumeration(),
mrTextPortionEnumeration(),
mrCurrentTextPortion(),
mpTextEmbeddedBitmapMtf( NULL ),
mpTargetMapMode( NULL ),
mpTextShapeElem( NULL ),
mpTextParagraphElem( NULL ),
mpTextPositionElem( NULL ),
mnLeftTextPortionLength( 0 ),
maTextPos(0,0),
mnTextWidth(0),
mbPositioningNeeded( sal_False ),
mbIsNumbering( sal_False ),
maBulletListItemMap(),
mbIsListLevelStyleImage( sal_False ),
mbLineBreak( sal_False ),
mbIsURLField( sal_False ),
msUrl(),
mbIsPlacehlolderShape( sal_False ),
mbIWS( sal_False ),
maCurrentFont(),
@@ -465,6 +490,21 @@ SVGTextWriter::~SVGTextWriter()
// -----------------------------------------------------------------------------
void SVGTextWriter::implRegisterInterface( const Reference< XInterface >& rxIf )
{
if( rxIf.is() )
(mrExport.getInterfaceToIdentifierMapper()).registerReference( rxIf );
}
// -----------------------------------------------------------------------------
const ::rtl::OUString & SVGTextWriter::implGetValidIDFromInterface( const Reference< XInterface >& rxIf )
{
return (mrExport.getInterfaceToIdentifierMapper()).getIdentifier( rxIf );
}
// -----------------------------------------------------------------------------
void SVGTextWriter::implMap( const Size& rSz, Size& rDstSz ) const
{
if( mpVDev && mpTargetMapMode )
@@ -818,8 +858,236 @@ void SVGTextWriter::implSetFontFamily()
// -----------------------------------------------------------------------------
sal_Bool SVGTextWriter::nextParagraph()
{
mrTextPortionEnumeration.clear();
if( mrParagraphEnumeration.is() && mrParagraphEnumeration->hasMoreElements() )
{
Reference < XTextContent > xTextContent( mrParagraphEnumeration->nextElement(), UNO_QUERY_THROW );
if( xTextContent.is() )
{
Reference< XServiceInfo > xServiceInfo( xTextContent, UNO_QUERY_THROW );
if( xServiceInfo.is() )
{
OUString sInfo;
if( xServiceInfo->supportsService( B2UCONST( "com.sun.star.text.Paragraph" ) ) )
{
Reference< XPropertySet > xPropSet( xTextContent, UNO_QUERY_THROW );
Reference< XPropertySetInfo > xPropSetInfo = xPropSet->getPropertySetInfo();
mbIsNumbering = sal_False;
mbIsListLevelStyleImage = sal_False;
if( xPropSetInfo->hasPropertyByName( B2UCONST( "NumberingLevel" ) ) )
{
sal_Int16 nListLevel = 0;
if( xPropSet->getPropertyValue( B2UCONST( "NumberingLevel" ) ) >>= nListLevel )
{
mbIsNumbering = sal_True;
sInfo = B2UCONST( "NumberingLevel: " );
sInfo += OUString::valueOf( (sal_Int32)nListLevel );
mrExport.AddAttribute( XML_NAMESPACE_NONE, "style", sInfo );
Reference< XIndexReplace > xNumRules;
if( xPropSetInfo->hasPropertyByName( B2UCONST( "NumberingRules" ) ) )
{
xPropSet->getPropertyValue( B2UCONST( "NumberingRules" ) ) >>= xNumRules;
}
if( xNumRules.is() && ( nListLevel < xNumRules->getCount() ) )
{
Sequence<PropertyValue> aProps;
if( xNumRules->getByIndex( nListLevel ) >>= aProps )
{
sal_Int16 eType = NumberingType::CHAR_SPECIAL;
sal_Unicode cBullet = 0xf095;
const sal_Int32 nCount = aProps.getLength();
const PropertyValue* pPropArray = aProps.getConstArray();
for( sal_Int32 i = 0; i < nCount; ++i )
{
const PropertyValue& rProp = pPropArray[i];
if( rProp.Name.equalsAsciiL( XML_UNO_NAME_NRULE_NUMBERINGTYPE, sizeof(XML_UNO_NAME_NRULE_NUMBERINGTYPE)-1 ) )
{
rProp.Value >>= eType;
}
else if( rProp.Name.equalsAsciiL( XML_UNO_NAME_NRULE_BULLET_CHAR, sizeof(XML_UNO_NAME_NRULE_BULLET_CHAR)-1 ) )
{
OUString sValue;
rProp.Value >>= sValue;
if( !sValue.isEmpty() )
{
cBullet = (sal_Unicode)sValue[0];
}
}
}
meNumberingType = eType;
mbIsListLevelStyleImage = ( NumberingType::BITMAP == meNumberingType );
if( NumberingType::CHAR_SPECIAL == meNumberingType )
{
if( cBullet )
{
if( cBullet < ' ' )
{
cBullet = 0xF000 + 149;
}
mcBulletChar = cBullet;
// text:bullet-char="..."
sInfo = OUString::valueOf( (sal_Int32) cBullet );
mrExport.AddAttribute( XML_NAMESPACE_NONE, "bullet-char", sInfo );
}
}
}
}
}
}
Reference< XEnumerationAccess > xEnumerationAccess( xTextContent, UNO_QUERY_THROW );
Reference< XEnumeration > xEnumeration( xEnumerationAccess->createEnumeration(), UNO_QUERY_THROW );
if( xEnumeration.is() && xEnumeration->hasMoreElements() )
{
mrTextPortionEnumeration.set( xEnumeration );
}
sInfo = B2UCONST( "Paragraph" );
}
else if( xServiceInfo->supportsService( B2UCONST( "com.sun.star.text.Table" ) ) )
{
sInfo = B2UCONST( "Table" );
}
else
{
OSL_FAIL( "SVGTextWriter::nextParagraph: Unknown text content." );
return sal_False;
}
mrExport.AddAttribute( XML_NAMESPACE_NONE, "class", sInfo );
SvXMLElementExport aParaElem( mrExport, XML_NAMESPACE_NONE, "desc", mbIWS, mbIWS );
}
Reference< XInterface > xRef( xTextContent, UNO_QUERY );
const OUString& rParagraphId = implGetValidIDFromInterface( xRef );
if( !rParagraphId.isEmpty() )
{
mrExport.AddAttribute( XML_NAMESPACE_NONE, "id", rParagraphId );
}
return sal_True;
}
}
return sal_False;
}
// -----------------------------------------------------------------------------
sal_Bool SVGTextWriter::nextTextPortion()
{
mrCurrentTextPortion.clear();
mbIsURLField = sal_False;
if( mrTextPortionEnumeration.is() && mrTextPortionEnumeration->hasMoreElements() )
{
OUString sInfo;
Reference< XPropertySet > xPortionPropSet( mrTextPortionEnumeration->nextElement(), UNO_QUERY );
Reference< XPropertySetInfo > xPortionPropInfo( xPortionPropSet->getPropertySetInfo() );
Reference < XTextRange > xPortionTextRange( xPortionPropSet, UNO_QUERY);
if( xPortionPropSet.is() && xPortionPropInfo.is()
&& xPortionPropInfo->hasPropertyByName( B2UCONST( "TextPortionType" ) ) )
{
::rtl::OUString sPortionType;
if( xPortionPropSet->getPropertyValue( B2UCONST( "TextPortionType" ) ) >>= sPortionType )
{
sInfo = B2UCONST( "type: " );
sInfo += sPortionType;
sInfo += B2UCONST( "; " );
}
if( xPortionTextRange.is() )
{
sInfo += B2UCONST( "content: " );
sInfo += xPortionTextRange->getString();
sInfo += B2UCONST( "; " );
mrCurrentTextPortion.set( xPortionTextRange );
Reference < XPropertySet > xRangePropSet( xPortionTextRange, UNO_QUERY );
if( xRangePropSet.is() && xRangePropSet->getPropertySetInfo()->hasPropertyByName( B2UCONST( "TextField" ) ) )
{
Reference < XTextField > xTextField( xRangePropSet->getPropertyValue( B2UCONST( "TextField" ) ), UNO_QUERY );
if( xTextField.is() )
{
const ::rtl::OUString sServicePrefix( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.text.textfield.") );
Reference< XServiceInfo > xService( xTextField, UNO_QUERY );
const Sequence< OUString > aServices = xService->getSupportedServiceNames();
const OUString* pNames = aServices.getConstArray();
sal_Int32 nCount = aServices.getLength();
OUString sFieldName; // service name postfix of current field
// search for TextField service name
while( nCount-- )
{
if ( pNames->matchIgnoreAsciiCase( sServicePrefix ) )
{
// TextField found => postfix is field type!
sFieldName = pNames->copy( sServicePrefix.getLength() );
break;
}
++pNames;
}
sInfo += B2UCONST( "text field type: " );
sInfo += sFieldName;
sInfo += B2UCONST( "; " );
mbIsURLField = sFieldName.equalsAscii( "URL" );
if( mbIsURLField )
{
Reference<XPropertySet> xTextFieldPropSet(xTextField, UNO_QUERY);
if( xTextFieldPropSet.is() )
{
OUString sURL;
if( ( xTextFieldPropSet->getPropertyValue( sFieldName ) ) >>= sURL )
{
sInfo += B2UCONST( "url: " );
sInfo += mrExport.GetRelativeReference( sURL );
msUrl = mrExport.GetRelativeReference( sURL );
if( !msUrl.isEmpty() )
{
implRegisterInterface( xPortionTextRange );
Reference< XInterface > xRef( xPortionTextRange, UNO_QUERY );
const OUString& rTextPortionId = implGetValidIDFromInterface( xRef );
if( !rTextPortionId.isEmpty() )
{
msHyperlinkIdList += rTextPortionId;
msHyperlinkIdList += B2UCONST( " " );
}
}
}
}
}
}
}
}
mrExport.AddAttribute( XML_NAMESPACE_NONE, "class", B2UCONST( "TextPortion" ) );
SvXMLElementExport aPortionElem( mrExport, XML_NAMESPACE_NONE, "desc", mbIWS, mbIWS );
mrExport.GetDocHandler()->characters( sInfo );
return sal_True;
}
}
return sal_False;
}
// -----------------------------------------------------------------------------
void SVGTextWriter::startTextShape()
{
if( mrTextShape.is() )
{
Reference< XEnumerationAccess > xEnumerationAccess( mrTextShape, UNO_QUERY_THROW );
Reference< XEnumeration > xEnumeration( xEnumerationAccess->createEnumeration(), UNO_QUERY_THROW );
if( xEnumeration.is() && xEnumeration->hasMoreElements() )
{
mrParagraphEnumeration.set( xEnumeration );
}
}
if( mpTextShapeElem )
{
OSL_FAIL( "SVGTextWriter::startTextShape: text shape already defined." );
@@ -827,6 +1095,7 @@ void SVGTextWriter::startTextShape()
else
{
maParentFont = Font();
mrExport.AddAttribute( XML_NAMESPACE_NONE, "class", B2UCONST( "TextShape" ) );
mpTextShapeElem = new SvXMLElementExport( mrExport, XML_NAMESPACE_NONE, aXMLElemText, sal_True, mbIWS );
startTextParagraph();
}
@@ -837,11 +1106,20 @@ void SVGTextWriter::startTextShape()
void SVGTextWriter::endTextShape()
{
endTextParagraph();
if( mrTextShape.is() )
mrTextShape.clear();
if( mrParagraphEnumeration.is() )
mrParagraphEnumeration.clear();
if( mpTextShapeElem )
{
delete mpTextShapeElem;
mpTextShapeElem = NULL;
}
// these need to be invoked after the <text> element has been closed
implExportHyperlinkIds();
implWriteBulletChars();
implWriteEmbeddedBitmaps();
}
// -----------------------------------------------------------------------------
@@ -849,11 +1127,36 @@ void SVGTextWriter::endTextShape()
void SVGTextWriter::startTextParagraph()
{
endTextParagraph();
nextParagraph();
if( mbIsNumbering )
{
OUString sNumberingType;
switch( meNumberingType )
{
case( NumberingType::CHAR_SPECIAL ):
sNumberingType = B2UCONST( "bullet-style" );
break;
case( NumberingType::BITMAP ):
sNumberingType = B2UCONST( "image-style" );
break;
default:
sNumberingType = B2UCONST( "number-style" );
break;
}
mrExport.AddAttribute( XML_NAMESPACE_NONE, aOOOAttrNumberingType, sNumberingType );
mrExport.AddAttribute( XML_NAMESPACE_NONE, "class", B2UCONST( "ListItem" ) );
}
else
{
mrExport.AddAttribute( XML_NAMESPACE_NONE, "class", B2UCONST( "TextParagraph" ) );
}
maParentFont = Font();
addFontAttributes( /* isTexTContainer: */ true );
mpTextParagraphElem = new SvXMLElementExport( mrExport, XML_NAMESPACE_NONE, aXMLElemTspan, mbIWS, mbIWS );
if( !mbIsListLevelStyleImage )
{
startTextPosition();
}
}
// -----------------------------------------------------------------------------
@@ -861,11 +1164,16 @@ void SVGTextWriter::startTextParagraph()
void SVGTextWriter::endTextParagraph()
{
endTextPosition();
mbIsNumbering = sal_False;
mbIsListLevelStyleImage = sal_False;
mbPositioningNeeded = sal_False;
if( mpTextParagraphElem )
{
delete mpTextParagraphElem;
mpTextParagraphElem = NULL;
}
}
// -----------------------------------------------------------------------------
@@ -895,10 +1203,215 @@ void SVGTextWriter::endTextPosition()
// -----------------------------------------------------------------------------
void SVGTextWriter::implExportHyperlinkIds()
{
if( !msHyperlinkIdList.isEmpty() )
{
mrExport.AddAttribute( XML_NAMESPACE_NONE, "class", B2UCONST( "HyperlinkIdList" ) );
SvXMLElementExport aDescElem( mrExport, XML_NAMESPACE_NONE, "desc", sal_True, sal_True );
mrExport.GetDocHandler()->characters( msHyperlinkIdList.trim() );
msHyperlinkIdList = OUString();
}
}
// -----------------------------------------------------------------------------
void SVGTextWriter::implWriteBulletChars()
{
if( maBulletListItemMap.empty() )
return;
mrExport.AddAttribute( XML_NAMESPACE_NONE, "class", B2UCONST( "BulletChars" ) );
SvXMLElementExport aGroupElem( mrExport, XML_NAMESPACE_NONE, aXMLElemG, sal_True, sal_True );
BulletListItemInfoMap::const_iterator it = maBulletListItemMap.begin();
BulletListItemInfoMap::const_iterator end = maBulletListItemMap.end();
OUString sId, sPosition, sScaling, sRefId;
for( ; it != end; ++it )
{
// <g id="?" > (used by animations)
{
// As id we use the id of the text portion placeholder wrapped
// by bullet-char(*)
sId = B2UCONST( "bullet-char(" );
sId += it->first;
sId += B2UCONST( ")" );
mrExport.AddAttribute( XML_NAMESPACE_NONE, "id", sId );
SvXMLElementExport aBulletCharElem( mrExport, XML_NAMESPACE_NONE, aXMLElemG, sal_True, sal_True );
// <g transform="translate(x,y)" >
{
const BulletListItemInfo& rInfo = it->second;
// Add positioning attribute through a translation
sPosition = B2UCONST( "translate(" );
sPosition += OUString::valueOf( rInfo.aPos.X() );
sPosition += B2UCONST( "," );
sPosition += OUString::valueOf( rInfo.aPos.Y() );
sPosition += B2UCONST( ")" );
mrExport.AddAttribute( XML_NAMESPACE_NONE, "transform", sPosition );
mpContext->AddPaintAttr( COL_TRANSPARENT, rInfo.aColor );
SvXMLElementExport aPositioningElem( mrExport, XML_NAMESPACE_NONE, aXMLElemG, sal_True, sal_True );
// <use transform="scale(font-size)" xlink:ref="/" >
{
// Add size attribute through a scaling
sScaling = B2UCONST( "scale(" );
sScaling += OUString::valueOf( rInfo.nFontSize );
sScaling += B2UCONST( "," );
sScaling += OUString::valueOf( rInfo.nFontSize );
sScaling += B2UCONST( ")" );
mrExport.AddAttribute( XML_NAMESPACE_NONE, "transform", sScaling );
// Add ref attribute
sRefId = B2UCONST( "#bullet-char-template(" );
sRefId += OUString::valueOf( (sal_Int32)( rInfo.cBulletChar ) );
sRefId += B2UCONST( ")" );
mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrXLinkHRef, sRefId );
SvXMLElementExport aRefElem( mrExport, XML_NAMESPACE_NONE, "use", sal_True, sal_True );
}
} // close aPositioningElem
} // close aBulletCharElem
}
// clear the map
maBulletListItemMap.clear();
}
// -----------------------------------------------------------------------------
void SVGTextWriter::writeBitmapPlaceholder( const MetaBmpExScaleAction* pAction )
{
// text position element
const Point& rPos = pAction->GetPoint();
implMap( rPos, maTextPos );
startTextPosition();
mbPositioningNeeded = sal_True;
if( mbIsNumbering )
{
mbIsNumbering = sal_False;
mbIsListLevelStyleImage = sal_False;
}
// bitmap placeholder element
sal_uLong nId = SVGActionWriter::GetChecksum( pAction );
OUString sId = B2UCONST( "bitmap-placeholder(" );
sId += OUString::valueOf( (sal_Int64)nId );
sId += B2UCONST( ")" );
mrExport.AddAttribute( XML_NAMESPACE_NONE, "id", sId );
mrExport.AddAttribute( XML_NAMESPACE_NONE, "class", B2UCONST( "BitmapPlaceholder" ) );
SvXMLElementExport aSVGTspanElem( mrExport, XML_NAMESPACE_NONE, aXMLElemTspan, mbIWS, mbIWS );
}
// -----------------------------------------------------------------------------
void SVGTextWriter::implWriteEmbeddedBitmaps()
{
if( mpTextEmbeddedBitmapMtf && mpTextEmbeddedBitmapMtf->GetActionSize() )
{
mrExport.AddAttribute( XML_NAMESPACE_NONE, "class", B2UCONST( "EmbeddedBitmaps" ) );
SvXMLElementExport aEmbBitmapGroupElem( mrExport, XML_NAMESPACE_NONE, aXMLElemG, sal_True, sal_True );
const GDIMetaFile& rMtf = *mpTextEmbeddedBitmapMtf;
OUString sId, sRefId;
sal_uLong nId;
sal_uLong nCount = rMtf.GetActionSize();
for( sal_uLong nCurAction = 0; nCurAction < nCount; nCurAction++ )
{
MetaBmpExScaleAction* pAction = (MetaBmpExScaleAction*) rMtf.GetAction( nCurAction );
// <g id="?" > (used by animations)
{
// embedded bitmap id
nId = SVGActionWriter::GetChecksum( pAction );
sId = B2UCONST( "embedded-bitmap(" );
sId += OUString::valueOf( (sal_Int64)nId );
sId += B2UCONST( ")" );
mrExport.AddAttribute( XML_NAMESPACE_NONE, "id", sId );
SvXMLElementExport aEmbBitmapElem( mrExport, XML_NAMESPACE_NONE, aXMLElemG, sal_True, sal_True );
// <use x="?" y="?" xlink:ref="?" >
{
// referenced bitmap template
nId = pAction->GetBitmapEx().GetChecksum();
sRefId = B2UCONST( "#bitmap(" );
sRefId += OUString::valueOf( (sal_Int64)nId );
sRefId += B2UCONST( ")" );
const Point& rPt = pAction->GetPoint();
const Size& rSz = pAction->GetSize();
Point aPt;
Size aSz;
implMap( rPt, aPt );
implMap( rSz, aSz );
mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrX, OUString::valueOf( aPt.X() ) );
mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrY, OUString::valueOf( aPt.Y() ) );
mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrXLinkHRef, sRefId );
SvXMLElementExport aRefElem( mrExport, XML_NAMESPACE_NONE, "use", sal_True, sal_True );
}
} // close aEmbBitmapElem
}
}
}
// -----------------------------------------------------------------------------
void SVGTextWriter::writeTextPortion( const Point& rPos,
const String& rText,
sal_Bool bApplyMapping )
{
if( rText.Len() == 0 )
return;
mbLineBreak = sal_False;
if( !mbIsNumbering || mbIsListLevelStyleImage )
{
bool bNotSync = true;
OUString sContent;
sal_Int32 nStartPos;
do
{
while( bNotSync )
{
if( mnLeftTextPortionLength <= 0 )
{
if( !nextTextPortion() )
break;
else
{
sContent = mrCurrentTextPortion->getString();
mnLeftTextPortionLength = sContent.getLength();
}
}
else
{
sContent = mrCurrentTextPortion->getString();
}
nStartPos = sContent.getLength() - mnLeftTextPortionLength;
if( nStartPos < 0 ) nStartPos = 0;
mnLeftTextPortionLength -= rText.Len();
if( sContent.isEmpty() )
continue;
if( sContent.equalsAscii( "\n" ) )
mbLineBreak = sal_True;
if( sContent.match( rText, nStartPos ) )
bNotSync = false;
}
} while( bNotSync && nextParagraph() );
}
if( !mpVDev )
OSL_FAIL( "SVGTextWriter::writeTextPortion: invalid virtual device." );
@@ -1014,24 +1527,72 @@ void SVGTextWriter::implWriteTextPortion( const Point& rPos,
else
aPos = rPos;
if( maTextPos.Y() != aPos.Y() )
{
// In case the text position moved backward we could have a line break
// so we end the current line and start a new one.
if( ( maTextPos.X() + mnTextWidth ) > aPos.X() )
if( mbPositioningNeeded )
{
mbPositioningNeeded = sal_False;
maTextPos.setX( aPos.X() );
maTextPos.setY( aPos.Y() );
startTextPosition();
}
else // superscript, subscript, bullets
else if( maTextPos.Y() != aPos.Y() )
{
// In case the text position moved backward we could have a line break
// so we end the current line and start a new one.
if( mbLineBreak || ( ( maTextPos.X() + mnTextWidth ) > aPos.X() ) )
{
mbLineBreak = sal_False;
maTextPos.setX( aPos.X() );
maTextPos.setY( aPos.Y() );
startTextPosition();
}
else // superscript, subscript, list item numbering
{
//mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrY, ::rtl::OUString::valueOf( aPos.Y() ) );
maTextPos.setY( aPos.Y() );
startTextPosition( sal_False /* do not export x attribute */ );
}
}
// we are dealing with a bullet, so set up this for the next text portion
if( mbIsNumbering )
{
mbIsNumbering = sal_False;
mbPositioningNeeded = sal_True;
if( meNumberingType == NumberingType::CHAR_SPECIAL )
{
// Create an id for the current text portion
implRegisterInterface( mrCurrentTextPortion );
// Add the needed info to the BulletListItemMap
Reference< XInterface > xRef( mrCurrentTextPortion, UNO_QUERY );
const OUString& rId = implGetValidIDFromInterface( xRef );
if( !rId.isEmpty() )
{
BulletListItemInfo& aBulletListItemInfo = maBulletListItemMap[ rId ];
aBulletListItemInfo.nFontSize = rFont.GetHeight();
aBulletListItemInfo.aColor = aTextColor;
aBulletListItemInfo.aPos = maTextPos;
aBulletListItemInfo.cBulletChar = mcBulletChar;
// Make this text portion a bullet placeholder
mrExport.AddAttribute( XML_NAMESPACE_NONE, "id", rId );
mrExport.AddAttribute( XML_NAMESPACE_NONE, "class", B2UCONST( "BulletPlaceholder" ) );
SvXMLElementExport aSVGTspanElem( mrExport, XML_NAMESPACE_NONE, aXMLElemTspan, mbIWS, mbIWS );
return;
}
}
}
Reference< XInterface > xRef( mrCurrentTextPortion, UNO_QUERY );
const OUString& rTextPortionId = implGetValidIDFromInterface( xRef );
if( !rTextPortionId.isEmpty() )
{
mrExport.AddAttribute( XML_NAMESPACE_NONE, "id", rTextPortionId );
}
if( mbIsURLField && !msUrl.isEmpty() )
{
mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrXLinkHRef, msUrl );
}
addFontAttributes( /* isTexTContainer: */ false );
@@ -1236,6 +1797,35 @@ PolyPolygon& SVGActionWriter::ImplMap( const PolyPolygon& rPolyPoly, PolyPolygon
// -----------------------------------------------------------------------------
sal_uLong SVGActionWriter::GetChecksum( const MetaBmpExScaleAction* pAct )
{
sal_uLong nCrc = 0;
SVBT16 aBT16;
SVBT32 aBT32;
ShortToSVBT16( pAct->GetType(), aBT16 );
nCrc = rtl_crc32( nCrc, aBT16, 2 );
UInt32ToSVBT32( pAct->GetBitmapEx().GetChecksum(), aBT32 );
nCrc = rtl_crc32( nCrc, aBT32, 4 );
UInt32ToSVBT32( pAct->GetPoint().X(), aBT32 );
nCrc = rtl_crc32( nCrc, aBT32, 4 );
UInt32ToSVBT32( pAct->GetPoint().Y(), aBT32 );
nCrc = rtl_crc32( nCrc, aBT32, 4 );
UInt32ToSVBT32( pAct->GetSize().Width(), aBT32 );
nCrc = rtl_crc32( nCrc, aBT32, 4 );
UInt32ToSVBT32( pAct->GetSize().Height(), aBT32 );
nCrc = rtl_crc32( nCrc, aBT32, 4 );
return nCrc;
}
// -----------------------------------------------------------------------------
void SVGActionWriter::ImplWriteLine( const Point& rPt1, const Point& rPt2,
const Color* pLineColor, sal_Bool bApplyMapping )
{
@@ -2043,14 +2633,23 @@ void SVGActionWriter::ImplWriteBmp( const BitmapEx& rBmpEx,
void SVGActionWriter::ImplWriteActions( const GDIMetaFile& rMtf,
sal_uInt32 nWriteFlags,
const ::rtl::OUString* pElementId )
const ::rtl::OUString* pElementId,
const Reference< XShape >* pxShape,
const GDIMetaFile* pTextEmbeddedBitmapMtf )
{
if( mnInnerMtfCount )
nWriteFlags |= SVGWRITER_NO_SHAPE_COMMENTS;
if( !mrExport.IsUsePositionedCharacters() && pxShape
&& Reference< XText >( *pxShape, UNO_QUERY ).is() )
{
Reference< XText > xText( *pxShape, UNO_QUERY );
maTextWriter.setTextShape( xText, pTextEmbeddedBitmapMtf );
}
mbIsPlacehlolderShape = false;
maTextWriter.setPlaceholderShapeFlag( false );
if( pElementId != NULL && ( *pElementId == sPlaceholderTag ) )
if( ( pElementId != NULL ) && ( *pElementId == sPlaceholderTag ) )
{
mbIsPlacehlolderShape = true;
maTextWriter.setPlaceholderShapeFlag( true );
@@ -2063,7 +2662,7 @@ void SVGActionWriter::ImplWriteActions( const GDIMetaFile& rMtf,
const MetaAction* pAction = rMtf.GetAction( nCurAction );
const sal_uInt16 nType = pAction->GetType();
if( bIsTextShape )
if( maTextWriter.getTextShape().is() )
{
try
{
@@ -2677,11 +3276,19 @@ void SVGActionWriter::ImplWriteActions( const GDIMetaFile& rMtf,
{
const MetaBmpExScaleAction* pA = (const MetaBmpExScaleAction*) pAction;
// Bitmaps embedded into text shapes are collected and exported elsewhere.
if( maTextWriter.getTextShape().is() )
{
maTextWriter.writeBitmapPlaceholder( pA );
}
else
{
ImplWriteBmp( pA->GetBitmapEx(),
pA->GetPoint(), pA->GetSize(),
Point(), pA->GetBitmapEx().GetSizePixel() );
}
}
}
break;
case( META_BMPEXSCALEPART_ACTION ):
@@ -2874,7 +3481,9 @@ void SVGActionWriter::WriteMetaFile( const Point& rPos100thmm,
const Size& rSize100thmm,
const GDIMetaFile& rMtf,
sal_uInt32 nWriteFlags,
const ::rtl::OUString* pElementId )
const ::rtl::OUString* pElementId,
const Reference< XShape >* pXShape,
const GDIMetaFile* pTextEmbeddedBitmapMtf )
{
MapMode aMapMode( rMtf.GetPrefMapMode() );
Size aPrefSize( rMtf.GetPrefSize() );
@@ -2895,7 +3504,7 @@ void SVGActionWriter::WriteMetaFile( const Point& rPos100thmm,
mapCurShape.reset();
ImplWriteActions( rMtf, nWriteFlags, pElementId );
ImplWriteActions( rMtf, nWriteFlags, pElementId, pXShape, pTextEmbeddedBitmapMtf );
// draw open shape that doesn't have a border
if( mapCurShape.get() )
+98 -5
View File
@@ -45,6 +45,12 @@
#include <xmloff/nmspmap.hxx>
#include <com/sun/star/uno/Reference.h>
#include <com/sun/star/container/XEnumerationAccess.hpp>
#include <com/sun/star/container/XEnumeration.hpp>
#include <com/sun/star/container/XIndexReplace.hpp>
#include <com/sun/star/lang/XServiceInfo.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/beans/XPropertySetInfo.hpp>
#include <com/sun/star/uno/RuntimeException.hpp>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/lang/XComponent.hpp>
@@ -55,6 +61,21 @@
#include <com/sun/star/xml/sax/XExtendedDocumentHandler.hpp>
#include <com/sun/star/i18n/CharacterIteratorMode.hpp>
#include <com/sun/star/i18n/XBreakIterator.hpp>
#include <com/sun/star/drawing/XShape.hpp>
#include <com/sun/star/text/XText.hpp>
#include <com/sun/star/text/XTextContent.hpp>
#include <com/sun/star/text/XTextRange.hpp>
#include <com/sun/star/text/XTextField.hpp>
#include <com/sun/star/style/NumberingType.hpp>
// -----------------------------------------------------------------------------
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::container;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::text;
using namespace ::com::sun::star::drawing;
using namespace ::com::sun::star::style;
// -----------------------------------------------------------------------------
@@ -141,29 +162,68 @@ struct SVGShapeDescriptor
}
};
// -------------------
// - SVGActionWriter -
// -------------------
class SVGAttributeWriter;
class GDIMetaFile;
// ---------------------------
// - BulletListItemInfo -
// ---------------------------
struct BulletListItemInfo
{
long nFontSize;
Color aColor;
Point aPos;
sal_Unicode cBulletChar;
};
// ---------------------------
// - OUStringHasher -
// ---------------------------
struct OUStringHasher
{
size_t operator()( const ::rtl::OUString& oustr ) const { return static_cast< size_t >( oustr.hashCode() ); }
};
// -------------------
// - SVGTextWriter -
// -------------------
class SVGTextWriter
{
public:
typedef ::boost::unordered_map< ::rtl::OUString, BulletListItemInfo, OUStringHasher > BulletListItemInfoMap;
private:
SVGExport& mrExport;
SVGFontExport& mrFontExport;
SVGAttributeWriter* mpContext;
VirtualDevice* mpVDev;
Reference<XText> mrTextShape;
Reference<XEnumeration> mrParagraphEnumeration;
Reference<XEnumeration> mrTextPortionEnumeration;
Reference<XTextRange> mrCurrentTextPortion;
const GDIMetaFile* mpTextEmbeddedBitmapMtf;
MapMode* mpTargetMapMode;
SvXMLElementExport* mpTextShapeElem;
SvXMLElementExport* mpTextParagraphElem;
SvXMLElementExport* mpTextPositionElem;
sal_Int32 mnLeftTextPortionLength;
Point maTextPos;
long int mnTextWidth;
sal_Bool mbPositioningNeeded;
sal_Bool mbIsNumbering;
sal_Int16 meNumberingType;
sal_Unicode mcBulletChar;
BulletListItemInfoMap maBulletListItemMap;
sal_Bool mbIsListLevelStyleImage;
sal_Bool mbLineBreak;
sal_Bool mbIsURLField;
::rtl::OUString msUrl;
::rtl::OUString msHyperlinkIdList;
sal_Bool mbIsPlacehlolderShape;
sal_Bool mbIWS;
Font maCurrentFont;
@@ -177,12 +237,19 @@ class SVGTextWriter
void setTextProperties( const GDIMetaFile& rMtf, sal_uLong nCurAction );
void addFontAttributes( sal_Bool bIsTextContainer );
sal_Bool nextParagraph();
sal_Bool nextTextPortion();
void startTextShape();
void endTextShape();
void startTextParagraph();
void endTextParagraph();
void startTextPosition( sal_Bool bExportX = sal_True, sal_Bool bExportY = sal_True);
void endTextPosition();
void implExportHyperlinkIds();
void implWriteBulletChars();
void writeBitmapPlaceholder( const MetaBmpExScaleAction* pAction );
void implWriteEmbeddedBitmaps();
void writeTextPortion( const Point& rPos, const String& rText,
sal_Bool bApplyMapping = sal_True );
void implWriteTextPortion( const Point& rPos, const String& rText,
@@ -201,6 +268,19 @@ class SVGTextWriter
mpContext = pContext;
}
void setTextShape( const Reference<XText>& rxText,
const GDIMetaFile* pTextEmbeddedBitmapMtf )
{
mrTextShape.set( rxText );
mpTextEmbeddedBitmapMtf = pTextEmbeddedBitmapMtf;
}
const Reference<XText>& getTextShape() const
{
return mrTextShape;
}
void setPlaceholderShapeFlag( sal_Bool bState )
{
mbIsPlacehlolderShape = bState;
@@ -213,9 +293,15 @@ class SVGTextWriter
void implSetFontFamily();
template< typename SubType >
sal_Bool implGetTextPosition( const MetaAction* pAction, Point& raPos, sal_Bool& bEmpty );
void implRegisterInterface( const Reference< XInterface >& rxIf );
const ::rtl::OUString & implGetValidIDFromInterface( const Reference< XInterface >& rxIf );
};
// -------------------
// - SVGActionWriter -
// -------------------
class SVGActionWriter
{
@@ -289,13 +375,18 @@ private:
void ImplCheckFontAttributes();
void ImplCheckPaintAttributes();
void ImplWriteActions( const GDIMetaFile& rMtf, sal_uInt32 nWriteFlags, const ::rtl::OUString* pElementId );
void ImplWriteActions( const GDIMetaFile& rMtf,
sal_uInt32 nWriteFlags,
const ::rtl::OUString* pElementId,
const Reference< XShape >* pXShape = NULL,
const GDIMetaFile* pTextEmbeddedBitmapMtf = NULL );
Font ImplSetCorrectFontHeight() const;
public:
static ::rtl::OUString GetPathString( const PolyPolygon& rPolyPoly, sal_Bool bLine );
static sal_uLong GetChecksum( const MetaBmpExScaleAction* pAct );
public:
@@ -306,7 +397,9 @@ public:
const Size& rSize100thmm,
const GDIMetaFile& rMtf,
sal_uInt32 nWriteFlags,
const ::rtl::OUString* pElementId = NULL );
const ::rtl::OUString* pElementId = NULL,
const Reference< XShape >* pXShape = NULL,
const GDIMetaFile* pTextEmbeddedBitmapMtf = NULL );
sal_Bool bIsTextShape;
};