summaryrefslogtreecommitdiff
path: root/filter
diff options
context:
space:
mode:
authorMarco Cecchetti <mrcekets@gmail.com>2012-08-18 19:25:17 +0200
committerThorsten Behrens <tbehrens@suse.com>2012-10-10 12:03:29 +0200
commitdf9a436a85fa281cd53d46fdb832965d36aa9135 (patch)
tree69e222544256125606f0ddca850ac98c04a57f2d /filter
parentdd188c470acbd6151b4ed6b71b194ed0bb3c2685 (diff)
Handled META_BMPSCALE_ACTION, supported hyperlinks, text selection support.
The implCreateObjectFromShape method of the SVGFilter class has been modified in order to handling bitmap meta actions of type META_BMPSCALE_ACTION for each bitmap embedded into a text shape. The implCreateObjectFromShape method of the SVGFilter class has been modified in order to avoid to generate an id for empty text shapes. The MetaSlide class has two new methods for collecting text shapes from the text shape exported index and hyperlinks. A new HyperlinkElement class has been designed for handling text portion with an attached URL. The routine handling mouse click has been modified in order to interacting with the EventMultiplexer instance belonging to the current slide even when no animations are exported. All that let us supporting both web links and local links to slide belonging to the current document. The routine handling mouse click has been modified in order to avoid to start the next effect or switch to the next slide when there is a text fragment selected. Now when the user selects text or performs a right click in order to copy the selected text no further action is executed by the presentation engine. When the left mouse button is clicked the previous selection is discarded but still no further action is performed by the presentation engine. The implCreateObjectFromShape method of the SVGFilter class has been modified in order to avoid of adding to the group of embedded bitmaps those bitmap belonging to XShape object convertible to XText but that does not contain any text shape meta comment action. Now a meta bitmap action is handled by the SVGTextWriter class only if the action is between a meta comment action of type XTEXT_PAINTSHAPE_BEGIN and a meta comment action of type XTEXT_PAINTSHAPE_END. The writeBitmapPlaceholder and implWriteEmbeddedBitmaps methods of the SVGTextWriter class have been modified in order to change the way the id of the <use> elements that reference a bitmap is created. That has been needed because when two <use> element referencing the same bitmap and embedded into two different text shapes but placed at the same position (e.g. for instance when they belong to different slide) they got the same id. Now the id is built by prepending the meta bitmap action checksum with the text shape id followed by a dot.
Diffstat (limited to 'filter')
-rw-r--r--filter/source/svg/presentation_engine.js459
-rw-r--r--filter/source/svg/svgexport.cxx212
-rw-r--r--filter/source/svg/svgfilter.hxx59
-rw-r--r--filter/source/svg/svgwriter.cxx134
-rw-r--r--filter/source/svg/svgwriter.hxx13
5 files changed, 720 insertions, 157 deletions
diff --git a/filter/source/svg/presentation_engine.js b/filter/source/svg/presentation_engine.js
index 27075cdff291..5fc68f6b214a 100644
--- a/filter/source/svg/presentation_engine.js
+++ b/filter/source/svg/presentation_engine.js
@@ -316,6 +316,72 @@ function mouseHandlerDispatch( aEvt, anAction )
document.onmouseup = function( aEvt ) { return mouseHandlerDispatch( aEvt, MOUSE_UP ); };
//document.onmousemove = function( aEvt ) { return mouseHandlerDispatch( aEvt, MOUSE_MOVE ); };
+
+/** mouseClickHelper
+ *
+ * @return {Object}
+ * a mouse click handler
+ */
+function mouseClickHelper( aEvt )
+{
+ // In case text is selected we stay on the current slide.
+ // Anyway if we are dealing with Firefox there is an issue:
+ // Firefox supports a naive way of selecting svg text, if you click
+ // on text the current selection is set to the whole text fragment
+ // wrapped by the related <tspan> element.
+ // That means until you click on text you never move to the next slide.
+ // In order to avoid this case we do not test the status of current
+ // selection, when the presentation is running on a mozilla browser.
+ if( !Detect.isMozilla )
+ {
+ var aWindowObject = document.defaultView;
+ if( aWindowObject )
+ {
+ var aTextSelection = aWindowObject.getSelection();
+ var sSelectedText = aTextSelection.toString();
+ if( sSelectedText )
+ {
+ log( 'text selection: ' + sSelectedText );
+ if( sLastSelectedText !== sSelectedText )
+ {
+ bTextHasBeenSelected = true;
+ sLastSelectedText = sSelectedText;
+ }
+ else
+ {
+ bTextHasBeenSelected = false;
+ }
+ return null;
+ }
+ else if( bTextHasBeenSelected )
+ {
+ bTextHasBeenSelected = false;
+ sLastSelectedText = '';
+ return null;
+ }
+ }
+ else
+ {
+ log( 'error: HyperlinkElement.handleClick: invalid window object.' );
+ }
+ }
+
+ var aSlideAnimationsHandler = theMetaDoc.aMetaSlideSet[nCurSlide].aSlideAnimationsHandler;
+ if( aSlideAnimationsHandler )
+ {
+ var aCurrentEventMultiplexer = aSlideAnimationsHandler.aEventMultiplexer;
+ if( aCurrentEventMultiplexer )
+ {
+ if( aCurrentEventMultiplexer.hasRegisteredMouseClickHandlers() )
+ {
+ return aCurrentEventMultiplexer.notifyMouseClick( aEvt );
+ }
+ }
+ }
+ return slideOnMouseUp( aEvt );
+}
+
+
/** Function to supply the default mouse handler dictionary.
*
* @returns default mouse handler dictionary
@@ -329,10 +395,11 @@ function getDefaultMouseHandlerDictionary()
// slide mode
mouseHandlerDict[SLIDE_MODE][MOUSE_UP]
+ = mouseClickHelper;
//= function( aEvt ) { return slideOnMouseDown( aEvt ); };
- = function( aEvt ) { return ( aSlideShow.aEventMultiplexer ) ?
- aSlideShow.aEventMultiplexer.notifyMouseClick( aEvt )
- : slideOnMouseUp( aEvt ); };
+// = function( aEvt ) { return ( aSlideShow.aEventMultiplexer ) ?
+// aSlideShow.aEventMultiplexer.notifyMouseClick( aEvt )
+// : slideOnMouseUp( aEvt ); };
mouseHandlerDict[SLIDE_MODE][MOUSE_WHEEL]
= function( aEvt ) { return slideOnMouseWheel( aEvt ); };
@@ -615,6 +682,152 @@ PathTools.arcAsBezier = function( last, rx, ry, xRotg, large, sweep, x, y )
};
+function has( name )
+{
+ return has.cache[name];
+}
+
+has.cache = {};
+
+has.add = function( name, test )
+{
+ has.cache[name] = test;
+};
+
+function configureDetectionTools()
+{
+ if( !navigator )
+ {
+ log( 'error: configureDetectionTools: configuration failed' );
+ return null;
+ }
+
+ var n = navigator,
+ dua = n.userAgent,
+ dav = n.appVersion,
+ tv = parseFloat(dav);
+
+ has.add('air', dua.indexOf('AdobeAIR') >= 0),
+ has.add('khtml', dav.indexOf('Konqueror') >= 0 ? tv : undefined);
+ has.add('webkit', parseFloat(dua.split('WebKit/')[1]) || undefined);
+ has.add('chrome', parseFloat(dua.split('Chrome/')[1]) || undefined);
+ has.add('safari', dav.indexOf('Safari')>=0 && !has('chrome') ? parseFloat(dav.split('Version/')[1]) : undefined);
+ has.add('mac', dav.indexOf('Macintosh') >= 0);
+ has.add('quirks', document.compatMode == 'BackCompat');
+ has.add('ios', /iPhone|iPod|iPad/.test(dua));
+ has.add('android', parseFloat(dua.split('Android ')[1]) || undefined);
+
+ if(!has('webkit')){
+ // Opera
+ if(dua.indexOf('Opera') >= 0){
+ // see http://dev.opera.com/articles/view/opera-ua-string-changes and http://www.useragentstring.com/pages/Opera/
+ // 9.8 has both styles; <9.8, 9.9 only old style
+ has.add('opera', tv >= 9.8 ? parseFloat(dua.split('Version/')[1]) || tv : tv);
+ }
+
+ // Mozilla and firefox
+ if(dua.indexOf('Gecko') >= 0 && !has('khtml') && !has('webkit')){
+ has.add('mozilla', tv);
+ }
+ if(has('mozilla')){
+ //We really need to get away from this. Consider a sane isGecko approach for the future.
+ has.add('ff', parseFloat(dua.split('Firefox/')[1] || dua.split('Minefield/')[1]) || undefined);
+ }
+
+ // IE
+ if(document.all && !has('opera')){
+ var isIE = parseFloat(dav.split('MSIE ')[1]) || undefined;
+
+ //In cases where the page has an HTTP header or META tag with
+ //X-UA-Compatible, then it is in emulation mode.
+ //Make sure isIE reflects the desired version.
+ //document.documentMode of 5 means quirks mode.
+ //Only switch the value if documentMode's major version
+ //is different from isIE's major version.
+ var mode = document.documentMode;
+ if(mode && mode != 5 && Math.floor(isIE) != mode){
+ isIE = mode;
+ }
+
+ has.add('ie', isIE);
+ }
+
+ // Wii
+ has.add('wii', typeof opera != 'undefined' && opera.wiiremote);
+ }
+
+ var detect =
+ {
+ // isFF: Number|undefined
+ // Version as a Number if client is FireFox. undefined otherwise. Corresponds to
+ // major detected FireFox version (1.5, 2, 3, etc.)
+ isFF: has('ff'),
+
+ // isIE: Number|undefined
+ // Version as a Number if client is MSIE(PC). undefined otherwise. Corresponds to
+ // major detected IE version (6, 7, 8, etc.)
+ isIE: has('ie'),
+
+ // isKhtml: Number|undefined
+ // Version as a Number if client is a KHTML browser. undefined otherwise. Corresponds to major
+ // detected version.
+ isKhtml: has('khtml'),
+
+ // isWebKit: Number|undefined
+ // Version as a Number if client is a WebKit-derived browser (Konqueror,
+ // Safari, Chrome, etc.). undefined otherwise.
+ isWebKit: has('webkit'),
+
+ // isMozilla: Number|undefined
+ // Version as a Number if client is a Mozilla-based browser (Firefox,
+ // SeaMonkey). undefined otherwise. Corresponds to major detected version.
+ isMozilla: has('mozilla'),
+ // isMoz: Number|undefined
+ // Version as a Number if client is a Mozilla-based browser (Firefox,
+ // SeaMonkey). undefined otherwise. Corresponds to major detected version.
+ isMoz: has('mozilla'),
+
+ // isOpera: Number|undefined
+ // Version as a Number if client is Opera. undefined otherwise. Corresponds to
+ // major detected version.
+ isOpera: has('opera'),
+
+ // isSafari: Number|undefined
+ // Version as a Number if client is Safari or iPhone. undefined otherwise.
+ isSafari: has('safari'),
+
+ // isChrome: Number|undefined
+ // Version as a Number if client is Chrome browser. undefined otherwise.
+ isChrome: has('chrome'),
+
+ // isMac: Boolean
+ // True if the client runs on Mac
+ isMac: has('mac'),
+
+ // isIos: Boolean
+ // True if client is iPhone, iPod, or iPad
+ isIos: has('ios'),
+
+ // isAndroid: Number|undefined
+ // Version as a Number if client is android browser. undefined otherwise.
+ isAndroid: has('android'),
+
+ // isWii: Boolean
+ // True if client is Wii
+ isWii: has('wii'),
+
+ // isQuirks: Boolean
+ // Page is in quirks mode.
+ isQuirks: has('quirks'),
+
+ // isAir: Boolean
+ // True if client is Adobe Air
+ isAir: has('air')
+ };
+ return detect;
+}
+
+
/*****
* @dojoend
@@ -937,6 +1150,24 @@ function PriorityQueue( aCompareFunc )
this.aCompareFunc = aCompareFunc;
}
+PriorityQueue.prototype.clone = function()
+{
+ var aCopy = new PriorityQueue( this.aCompareFunc );
+ var src = this.aSequence;
+ var dest = [];
+ var i, l;
+ for( i = 0, l = src.length; i < l; ++i )
+ {
+ if( i in src )
+ {
+ dest.push( src[i] );
+ }
+ }
+ aCopy.aSequence = dest;
+
+ return aCopy;
+};
+
PriorityQueue.prototype.top = function()
{
return this.aSequence[0];
@@ -1171,11 +1402,15 @@ var INDEX_COLUMNS_DEFAULT = 3;
var INDEX_OFFSET = 0;
// Initialization.
+var Detect = configureDetectionTools();
var theMetaDoc;
var theSlideIndexPage;
var currentMode = SLIDE_MODE;
var processingEffect = false;
var nCurSlide = undefined;
+var bTextHasBeenSelected = false;
+var sLastSelectedText = '';
+
// Initialize char and key code dictionaries.
var charCodeDictionary = getDefaultCharCodeDictionary();
@@ -1240,6 +1475,7 @@ function instantiate( TemplateClass, BaseType )
return TemplateClass.instanceSet[ nSize ].instance;
}
+
// ------------------------------------------------------------------------------------------ //
/**********************************
** Helper functions and classes **
@@ -1284,11 +1520,19 @@ function warning( bCondition, sMessage )
function getNSAttribute( sNSPrefix, aElem, sAttrName )
{
if( !aElem ) return null;
- if( aElem.hasAttributeNS( NSS[sNSPrefix], sAttrName ) )
+ if( 'getAttributeNS' in aElem )
{
return aElem.getAttributeNS( NSS[sNSPrefix], sAttrName );
}
- return null;
+ else
+ {
+ return aElem.getAttribute( sNSPrefix + ':' + sAttrName );
+ }
+// if( aElem.hasAttributeNS( NSS[sNSPrefix], sAttrName ) )
+// {
+// return aElem.getAttributeNS( NSS[sNSPrefix], sAttrName );
+// }
+// return null;
}
function getOOOAttribute( aElem, sAttrName )
@@ -1691,6 +1935,12 @@ function MetaSlide( sMetaSlideId, aMetaDoc )
if( false && this.aSlideAnimationsHandler.aRootNode )
log( this.aSlideAnimationsHandler.aRootNode.info( true ) );
+ // We collect text shapes included in this slide .
+ this.aTextShapeSet = this.collectTextShapes();
+
+ // We initialize hyperlinks
+ this.aHyperlinkSet = this.initHyperlinks();
+
}
MetaSlide.prototype =
@@ -1821,6 +2071,78 @@ initFixedTextFieldContentProvider : function( aOOOAttribute )
return this.theMetaDoc.aTextFieldContentProviderSet[ nIndex ];
},
+collectTextShapes : function()
+{
+ var aTextShapeSet = new Array();
+ var aTextShapeIndexElem = getElementByClassName( document, 'TextShapeIndex' );
+ if( aTextShapeIndexElem )
+ {
+ var aIndexEntryList = getElementChildren( aTextShapeIndexElem );
+ var i;
+ for( i = 0; i < aIndexEntryList.length; ++i )
+ {
+ var sSlideId = getOOOAttribute( aIndexEntryList[i], 'slide' );
+ if( sSlideId === this.slideId )
+ {
+ var sTextShapeIds = getOOOAttribute( aIndexEntryList[i], 'id-list' );
+ if( sTextShapeIds )
+ {
+ //log( 'slide id: ' + this.slideId + ' text shape id list: ' + sTextShapeIds );
+ var aTextShapeIdSet = sTextShapeIds.split( ' ' );
+ var j;
+ for( j = 0; j < aTextShapeIdSet.length; ++j )
+ {
+ var aTextShapeElem = document.getElementById( aTextShapeIdSet[j] );
+ if( aTextShapeElem )
+ {
+ aTextShapeSet.push( aTextShapeElem );
+ }
+ else
+ {
+ log( 'warning: MetaSlide.collectTextShapes: text shape with id <' + aTextShapeIdSet[j] + '> is not valid.' );
+ }
+ }
+ }
+ break;
+ }
+ }
+ }
+ return aTextShapeSet;
+},
+
+initHyperlinks : function()
+{
+ var aHyperlinkSet = new Object();
+ var i;
+ for( i = 0; i < this.aTextShapeSet.length; ++i )
+ {
+ if( this.aTextShapeSet[i] )
+ {
+ var aHyperlinkIdList = getElementByClassName( this.aTextShapeSet[i], 'HyperlinkIdList' );
+ if( aHyperlinkIdList )
+ {
+ var sHyperlinkIds = aHyperlinkIdList.textContent;
+ if( sHyperlinkIds )
+ {
+ var aHyperlinkIdSet = sHyperlinkIds.trim().split( ' ' );
+ var j;
+ for( j = 0; j < aHyperlinkIdSet.length; ++j )
+ {
+ var sId = aHyperlinkIdSet[j];
+ //log( 'initHyperlinks: j=' + j + ' id: <' + sId + '>' );
+ var aHyperlinkElem = document.getElementById( sId );
+ if( aHyperlinkElem )
+ {
+ aHyperlinkSet[ sId ] = new HyperlinkElement( sId, aHyperlinkElem, this.aSlideAnimationsHandler.aEventMultiplexer );
+ }
+ }
+ }
+ }
+ }
+ }
+ return aHyperlinkSet;
+},
+
getSlideAnimationsRoot : function()
{
return this.theMetaDoc.aSlideAnimationsMap[ this.slideId ];
@@ -9294,6 +9616,7 @@ function AnimatedTextElement( aElement )
}
}
+ // In case there are embedded bitmaps we need to clone them
var aBitmapElemSet = new Array();
var aBitmapCloneSet = new Array();
var aBitmapPlaceholderSet = getElementsByClassName( aElement, 'BitmapPlaceholder' );
@@ -9346,6 +9669,7 @@ function AnimatedTextElement( aElement )
aBulletCharClone.setAttribute( 'visibility', 'inherit' );
if( aBulletCharElem )
aBulletCharElem.setAttribute( 'visibility', 'hidden' );
+
for( i = 0; i < aBitmapCloneSet.length; ++i )
{
if( aBitmapElemSet[i] )
@@ -10166,6 +10490,102 @@ SourceEventElement.prototype.setDefaultCursor = function()
this.aElement.setAttribute( 'style', 'cursor: default' );
};
+// ------------------------------------------------------------------------------------------ //
+
+function HyperlinkElement( sId, aElement, aEventMultiplexer )
+{
+ if( !aElement )
+ {
+ log( 'error: HyperlinkElement: passed element is not valid' );
+ return;
+ }
+ if( !aEventMultiplexer )
+ {
+ log( 'error: HyperlinkElement: passed event multiplexer is not valid' );
+ return;
+ }
+
+ this.sId = sId;
+ this.aElement = aElement;
+ this.aEventMultiplexer = aEventMultiplexer;
+ this.nTargetSlideIndex = undefined;
+
+ this.sURL = getNSAttribute( 'xlink', this.aElement, 'href' );
+ if( this.sURL )
+ {
+ if( this.sURL[0] === '#' )
+ {
+ if( this.sURL.substr(1, 5) === 'Slide' )
+ {
+ var sSlideIndex = this.sURL.split( ' ' )[1];
+ this.nTargetSlideIndex = parseInt( sSlideIndex ) - 1;
+ }
+ }
+
+ this.aEventMultiplexer.registerMouseClickHandler( this, 1100 );
+
+ this.bIsPointerOver = false;
+ this.aElement.addEventListener( 'mouseover', bind2( HyperlinkElement.prototype.onMouseEnter, this), false );
+ this.aElement.addEventListener( 'mouseout', bind2( HyperlinkElement.prototype.onMouseLeave, this), false );
+ }
+ else
+ {
+ log( 'warning: HyperlinkElement(' + this.sId + '): url is empty' );
+ }
+}
+
+HyperlinkElement.prototype.onMouseEnter = function()
+{
+ this.bIsPointerOver = true;
+ this.setPointerCursor();
+};
+
+HyperlinkElement.prototype.onMouseLeave = function()
+{
+ this.bIsPointerOver = false;
+ this.setDefaultCursor();
+};
+
+HyperlinkElement.prototype.handleClick = function( aMouseEvent )
+{
+ if( !this.bIsPointerOver ) return false;
+
+ //log( 'hyperlink: ' + this.sURL );
+
+ if( this.nTargetSlideIndex !== undefined )
+ {
+ aSlideShow.displaySlide( this.nTargetSlideIndex, true );
+ }
+ else
+ {
+ var aWindowObject = document.defaultView;
+ if( aWindowObject )
+ {
+ aWindowObject.open( this.sURL, this.sId );
+ }
+ else
+ {
+ log( 'error: HyperlinkElement.handleClick: invalid window object.' );
+ }
+ }
+
+
+ return true;
+};
+
+HyperlinkElement.prototype.setPointerCursor = function()
+{
+ if( this.bClickHandled )
+ return;
+
+ this.aElement.setAttribute( 'style', 'cursor: pointer' );
+};
+
+HyperlinkElement.prototype.setDefaultCursor = function()
+{
+ this.aElement.setAttribute( 'style', 'cursor: default' );
+};
+
// ------------------------------------------------------------------------------------------ //
function InteractiveAnimationSequence( nId )
@@ -10257,9 +10677,11 @@ PriorityEntry.compare = function( aLhsEntry, aRhsEntry )
return ( aLhsEntry.nPriority < aRhsEntry.nPriority );
};
+
// ------------------------------------------------------------------------------------------ //
function EventMultiplexer( aTimerEventQueue )
{
+ this.nId = EventMultiplexer.getUniqueId();
this.aTimerEventQueue = aTimerEventQueue;
this.aEventMap = new Object();
this.aSkipEffectEndHandlerSet = new Array();
@@ -10273,6 +10695,25 @@ function EventMultiplexer( aTimerEventQueue )
this.aRewindedEffectHandlerSet = new Object();
}
+EventMultiplexer.CURR_UNIQUE_ID = 0;
+
+EventMultiplexer.getUniqueId = function()
+{
+ ++EventMultiplexer.CURR_UNIQUE_ID;
+ return EventMultiplexer.CURR_UNIQUE_ID;
+};
+
+EventMultiplexer.prototype.getId = function()
+{
+ return this.nId;
+}
+
+EventMultiplexer.prototype.hasRegisteredMouseClickHandlers = function()
+{
+ var nSize = this.aMouseClickHandlerSet.size();
+ return ( nSize > 0 );
+}
+
EventMultiplexer.prototype.registerMouseClickHandler = function( aHandler, nPriority )
{
var aHandlerEntry = new PriorityEntry( aHandler, nPriority );
@@ -10281,11 +10722,11 @@ EventMultiplexer.prototype.registerMouseClickHandler = function( aHandler, nPrio
EventMultiplexer.prototype.notifyMouseClick = function( aMouseEvent )
{
- var aMouseClickHandlerSet = this.aMouseClickHandlerSet;
- var nSize = aMouseClickHandlerSet.size();
- for( var i = 0; i < nSize; ++i )
+ var aMouseClickHandlerSet = this.aMouseClickHandlerSet.clone();
+ while( !aMouseClickHandlerSet.isEmpty() )
{
- var aHandlerEntry = aMouseClickHandlerSet.aSequence[i];
+ var aHandlerEntry = aMouseClickHandlerSet.top();
+ aMouseClickHandlerSet.pop();
if( aHandlerEntry.aValue.handleClick( aMouseEvent ) )
break;
}
diff --git a/filter/source/svg/svgexport.cxx b/filter/source/svg/svgexport.cxx
index 038b2dbada10..38cad60161a2 100644
--- a/filter/source/svg/svgexport.cxx
+++ b/filter/source/svg/svgexport.cxx
@@ -455,6 +455,102 @@ sal_Bool ObjectRepresentation::operator==( const ObjectRepresentation& rPresenta
( *mpMtf == *rPresentation.mpMtf ) );
}
+// -----------------------------------------------------------------------------
+
+sal_uLong GetBitmapChecksum( const MetaAction* pAction )
+{
+ sal_uLong nChecksum = 0;
+ const sal_uInt16 nType = pAction->GetType();
+
+ switch( nType )
+ {
+ case( META_BMPSCALE_ACTION ):
+ {
+ const MetaBmpScaleAction* pA = (const MetaBmpScaleAction*) pAction;
+ if( pA )
+ nChecksum = pA->GetBitmap().GetChecksum();
+ else
+ OSL_FAIL( "GetBitmapChecksum: MetaBmpScaleAction pointer is null." );
+ }
+ break;
+ case( META_BMPEXSCALE_ACTION ):
+ {
+ const MetaBmpExScaleAction* pA = (const MetaBmpExScaleAction*) pAction;
+ if( pA )
+ nChecksum = pA->GetBitmapEx().GetChecksum();
+ else
+ OSL_FAIL( "GetBitmapChecksum: MetaBmpExScaleAction pointer is null." );
+ }
+ break;
+ }
+ return nChecksum;
+}
+// -----------------------------------------------------------------------------
+
+void MetaBitmapActionGetPoint( const MetaAction* pAction, Point& rPt )
+{
+ const sal_uInt16 nType = pAction->GetType();
+ switch( nType )
+ {
+ case( META_BMPSCALE_ACTION ):
+ {
+ const MetaBmpScaleAction* pA = (const MetaBmpScaleAction*) pAction;
+ if( pA )
+ rPt = pA->GetPoint();
+ else
+ OSL_FAIL( "MetaBitmapActionGetPoint: MetaBmpScaleAction pointer is null." );
+ }
+ break;
+ case( META_BMPEXSCALE_ACTION ):
+ {
+ const MetaBmpExScaleAction* pA = (const MetaBmpExScaleAction*) pAction;
+ if( pA )
+ rPt = pA->GetPoint();
+ else
+ OSL_FAIL( "MetaBitmapActionGetPoint: MetaBmpExScaleAction pointer is null." );
+ }
+ break;
+ }
+
+}
+
+// -----------------------------------------------------------------------------
+
+size_t HashBitmap::operator()( const ObjectRepresentation& rObjRep ) const
+{
+ const GDIMetaFile& aMtf = rObjRep.GetRepresentation();
+ if( aMtf.GetActionSize() == 1 )
+ {
+ return static_cast< size_t >( GetBitmapChecksum( aMtf.GetAction( 0 ) ) );
+ }
+ else
+ {
+ OSL_FAIL( "HashBitmap: metafile should have a single action." );
+ return 0;
+ }
+}
+
+// -----------------------------------------------------------------------------
+
+bool EqualityBitmap::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 )
+ {
+ sal_uLong nChecksum1 = GetBitmapChecksum( aMtf1.GetAction( 0 ) );
+ sal_uLong nChecksum2 = GetBitmapChecksum( aMtf2.GetAction( 0 ) );
+ return ( nChecksum1 == nChecksum2 );
+ }
+ else
+ {
+ OSL_FAIL( "EqualityBitmap: metafile should have a single action." );
+ return false;
+ }
+}
+
+
// -------------
// - SVGFilter -
// -------------
@@ -1245,10 +1341,10 @@ sal_Bool SVGFilter::implExportTextEmbeddedBitmaps()
if( aMtf.GetActionSize() == 1 )
{
- MetaBmpExScaleAction* pAction = (MetaBmpExScaleAction*) aMtf.GetAction( 0 );
+ MetaAction* pAction = aMtf.GetAction( 0 );
if( pAction )
{
- sal_uLong nId = pAction->GetBitmapEx().GetChecksum();
+ sal_uLong nId = GetBitmapChecksum( pAction );
sId = B2UCONST( "bitmap(" );
sId += OUString::valueOf( (sal_Int64)nId );
sId += B2UCONST( ")" );
@@ -1263,7 +1359,8 @@ sal_Bool SVGFilter::implExportTextEmbeddedBitmaps()
const Point aTopLeft;
const Size aSize( aBoundRect.Width, aBoundRect.Height );
- const Point aPt = pAction->GetPoint();
+ Point aPt;
+ MetaBitmapActionGetPoint( pAction, aPt );
// 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
@@ -1726,7 +1823,7 @@ sal_Bool SVGFilter::implExportShape( const Reference< XShape >& rxShape )
if( !rShapeId.isEmpty() )
{
mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "id", rShapeId );
- //mpSVGExport->AddAttributeIdLegacy( XML_NAMESPACE_DRAW, rShapeId );
+
}
const GDIMetaFile* pEmbeddedBitmapsMtf = NULL;
@@ -1736,8 +1833,6 @@ sal_Bool SVGFilter::implExportShape( const Reference< XShape >& rxShape )
}
{
-// 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,
@@ -1869,54 +1964,83 @@ sal_Bool SVGFilter::implCreateObjectsFromShape( const Reference< XDrawPage > & r
}
else
{
- Reference< XText > xText( rxShape, UNO_QUERY );
- sal_Bool bIsTextShape = xText.is();
-
- if( !mpSVGExport->IsUsePositionedCharacters() && bIsTextShape )
+ if( aGraphic.GetGDIMetaFile().GetActionSize() )
{
+ Reference< XText > xText( rxShape, UNO_QUERY );
+ sal_Bool bIsTextShape = xText.is();
- // We create a map of text shape ids.
- implRegisterInterface( rxShape );
- Reference< XInterface > xRef( rxShape, UNO_QUERY );
- const OUString& rShapeId = implGetValidIDFromInterface( xRef );
- if( !rShapeId.isEmpty() )
+ if( !mpSVGExport->IsUsePositionedCharacters() && bIsTextShape )
{
- 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();
+ Reference< XPropertySet > xShapePropSet( rxShape, UNO_QUERY );
- if( nType == META_BMPEXSCALE_ACTION )
+ if( xShapePropSet.is() )
{
- 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 );
+ sal_Bool bHideObj = sal_False;
+
+ if( mbPresentation )
+ {
+ xShapePropSet->getPropertyValue( B2UCONST( "IsEmptyPresentationObject" ) ) >>= bHideObj;
+ }
+
+ if( !bHideObj )
+ {
+ // 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;
+ sal_Bool bIsTextShapeStarted = sal_False;
+ 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_COMMENT_ACTION )
+ {
+ const MetaCommentAction* pA = (const MetaCommentAction*) pAction;
+ if( ( pA->GetComment().equalsIgnoreAsciiCaseL(RTL_CONSTASCII_STRINGPARAM("XTEXT_PAINTSHAPE_BEGIN")) ) )
+ {
+ bIsTextShapeStarted = sal_True;
+ }
+ else if( ( pA->GetComment().equalsIgnoreAsciiCaseL( RTL_CONSTASCII_STRINGPARAM( "XTEXT_PAINTSHAPE_END" ) ) ) )
+ {
+ bIsTextShapeStarted = sal_False;
+ }
+ }
+ if( bIsTextShapeStarted && ( nType == META_BMPSCALE_ACTION || 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 );
+ }
}
}
- aMtf.SetPrefSize( aSize );
- aMtf.SetPrefMapMode( MAP_100TH_MM );
- mEmbeddedBitmapActionMap[ rxShape ] = ObjectRepresentation( rxShape, aMtf );
}
-
(*mpObjects)[ rxShape ] = ObjectRepresentation( rxShape, aGraphic.GetGDIMetaFile() );
+ bRet = sal_True;
}
- bRet = sal_True;
}
}
}
diff --git a/filter/source/svg/svgfilter.hxx b/filter/source/svg/svgfilter.hxx
index 9a0ba8f09ac8..3ef33a655ac3 100644
--- a/filter/source/svg/svgfilter.hxx
+++ b/filter/source/svg/svgfilter.hxx
@@ -227,67 +227,22 @@ struct HashUChar
};
// ---------------------------
-// - HashBmpExScale -
+// - HashBitmap -
// ---------------------------
-struct HashBmpExScale
+struct HashBitmap
{
- 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;
- }
- }
+ size_t operator()( const ObjectRepresentation& rObjRep ) const;
};
// ---------------------------
-// - EqualityBmpExScale -
+// - EqualityBitmap -
// ---------------------------
-struct EqualityBmpExScale
+struct EqualityBitmap
{
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;
- }
-
- }
+ const ObjectRepresentation& rObjRep2 ) const;
};
@@ -316,7 +271,7 @@ public:
typedef ::boost::unordered_map< Reference< XInterface >, ::rtl::OUString, HashReferenceXInterface > UOStringMap;
- typedef ::boost::unordered_set< ObjectRepresentation, HashBmpExScale, EqualityBmpExScale > MetaBitmapActionSet;
+ typedef ::boost::unordered_set< ObjectRepresentation, HashBitmap, EqualityBitmap > MetaBitmapActionSet;
private:
diff --git a/filter/source/svg/svgwriter.cxx b/filter/source/svg/svgwriter.cxx
index ca3f5393c7cb..2575bfe3aa03 100644
--- a/filter/source/svg/svgwriter.cxx
+++ b/filter/source/svg/svgwriter.cxx
@@ -455,7 +455,9 @@ SVGTextWriter::SVGTextWriter( SVGExport& rExport, SVGFontExport& rFontExport )
mrFontExport( rFontExport ),
mpContext( NULL ),
mpVDev( NULL ),
+ mbIsTextShapeStarted( sal_False ),
mrTextShape(),
+ msShapeId(),
mrParagraphEnumeration(),
mrCurrentTextParagraph(),
mrTextPortionEnumeration(),
@@ -576,10 +578,10 @@ sal_Bool SVGTextWriter::implGetTextPosition<MetaTextRectAction>( const MetaActio
// -----------------------------------------------------------------------------
-template<>
-sal_Bool SVGTextWriter::implGetTextPosition<MetaBmpExScaleAction>( const MetaAction* pAction, Point& raPos, sal_Bool& rbEmpty )
+template< typename SubType >
+sal_Bool SVGTextWriter::implGetTextPositionFromBitmap( const MetaAction* pAction, Point& raPos, sal_Bool& rbEmpty )
{
- const MetaBmpExScaleAction* pA = (const MetaBmpExScaleAction*) pAction;
+ const SubType* pA = (const SubType*) pAction;
raPos = pA->GetPoint();
rbEmpty = sal_False;
return sal_True;
@@ -640,9 +642,15 @@ sal_Int32 SVGTextWriter::setTextPosition( const GDIMetaFile& rMtf, sal_uLong& nC
}
break;
+ case( META_BMPSCALE_ACTION ):
+ {
+ bConfigured = implGetTextPositionFromBitmap<MetaBmpScaleAction>( pAction, aPos, bEmpty );
+ }
+ break;
+
case( META_BMPEXSCALE_ACTION ):
{
- bConfigured = implGetTextPosition<MetaBmpExScaleAction>( pAction, aPos, bEmpty );
+ bConfigured = implGetTextPositionFromBitmap<MetaBmpExScaleAction>( pAction, aPos, bEmpty );
}
break;
@@ -911,6 +919,9 @@ sal_Bool SVGTextWriter::createParagraphEnumeration()
{
if( mrTextShape.is() )
{
+ Reference< XInterface > xRef( mrTextShape, UNO_QUERY );
+ msShapeId = implGetValidIDFromInterface( xRef );
+
Reference< XEnumerationAccess > xEnumerationAccess( mrTextShape, UNO_QUERY_THROW );
Reference< XEnumeration > xEnumeration( xEnumerationAccess->createEnumeration(), UNO_QUERY_THROW );
if( xEnumeration.is() )
@@ -1219,6 +1230,7 @@ void SVGTextWriter::startTextShape()
}
{
+ mbIsTextShapeStarted = sal_True;
maParentFont = Font();
mrExport.AddAttribute( XML_NAMESPACE_NONE, "class", B2UCONST( "TextShape" ) );
mpTextShapeElem = new SvXMLElementExport( mrExport, XML_NAMESPACE_NONE, aXMLElemText, sal_True, mbIWS );
@@ -1242,6 +1254,7 @@ void SVGTextWriter::endTextShape()
delete mpTextShapeElem;
mpTextShapeElem = NULL;
}
+ mbIsTextShapeStarted = sal_False;
// these need to be invoked after the <text> element has been closed
implExportHyperlinkIds();
implWriteBulletChars();
@@ -1336,7 +1349,7 @@ 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 );
+ SvXMLElementExport aDescElem( mrExport, XML_NAMESPACE_NONE, "desc", sal_True, sal_False );
mrExport.GetDocHandler()->characters( msHyperlinkIdList.trim() );
msHyperlinkIdList = OUString();
}
@@ -1413,7 +1426,8 @@ void SVGTextWriter::implWriteBulletChars()
// -----------------------------------------------------------------------------
-void SVGTextWriter::writeBitmapPlaceholder( const MetaBmpExScaleAction* pAction )
+template< typename MetaBitmapActionType >
+void SVGTextWriter::writeBitmapPlaceholder( const MetaBitmapActionType* pAction )
{
// text position element
const Point& rPos = pAction->GetPoint();
@@ -1429,6 +1443,8 @@ void SVGTextWriter::writeBitmapPlaceholder( const MetaBmpExScaleAction* pAction
// bitmap placeholder element
sal_uLong nId = SVGActionWriter::GetChecksum( pAction );
OUString sId = B2UCONST( "bitmap-placeholder(" );
+ sId += msShapeId;
+ sId += B2UCONST( "." );
sId += OUString::valueOf( (sal_Int64)nId );
sId += B2UCONST( ")" );
@@ -1452,17 +1468,43 @@ void SVGTextWriter::implWriteEmbeddedBitmaps()
const GDIMetaFile& rMtf = *mpTextEmbeddedBitmapMtf;
OUString sId, sRefId;
- sal_uLong nId;
+ sal_uLong nId, nChecksum;
+ Point aPt;
+ Size aSz;
sal_uLong nCount = rMtf.GetActionSize();
for( sal_uLong nCurAction = 0; nCurAction < nCount; nCurAction++ )
{
- MetaBmpExScaleAction* pAction = (MetaBmpExScaleAction*) rMtf.GetAction( nCurAction );
+
+ const MetaAction* pAction = rMtf.GetAction( nCurAction );
+ const sal_uInt16 nType = pAction->GetType();
+
+ switch( nType )
+ {
+ case( META_BMPSCALE_ACTION ):
+ {
+ const MetaBmpScaleAction* pA = (const MetaBmpScaleAction*) pAction;
+ nChecksum = pA->GetBitmap().GetChecksum();
+ aPt = pA->GetPoint();
+ aSz = pA->GetSize();
+ }
+ break;
+ case( META_BMPEXSCALE_ACTION ):
+ {
+ const MetaBmpExScaleAction* pA = (const MetaBmpExScaleAction*) pAction;
+ nChecksum = pA->GetBitmapEx().GetChecksum();
+ aPt = pA->GetPoint();
+ aSz = pA->GetSize();
+ }
+ break;
+ }
// <g id="?" > (used by animations)
{
// embedded bitmap id
nId = SVGActionWriter::GetChecksum( pAction );
sId = B2UCONST( "embedded-bitmap(" );
+ sId += msShapeId;
+ sId += B2UCONST( "." );
sId += OUString::valueOf( (sal_Int64)nId );
sId += B2UCONST( ")" );
mrExport.AddAttribute( XML_NAMESPACE_NONE, "id", sId );
@@ -1473,20 +1515,17 @@ void SVGTextWriter::implWriteEmbeddedBitmaps()
// <use x="?" y="?" xlink:ref="?" >
{
// referenced bitmap template
- nId = pAction->GetBitmapEx().GetChecksum();
sRefId = B2UCONST( "#bitmap(" );
- sRefId += OUString::valueOf( (sal_Int64)nId );
+ sRefId += OUString::valueOf( (sal_Int64)nChecksum );
sRefId += B2UCONST( ")" );
- const Point& rPt = pAction->GetPoint();
- const Size& rSz = pAction->GetSize();
- Point aPt;
- Size aSz;
- implMap( rPt, aPt );
- implMap( rSz, aSz );
+ Point aPoint;
+ Size aSize;
+ implMap( aPt, aPoint );
+ implMap( aSz, aSize );
- 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, aXMLAttrX, OUString::valueOf( aPoint.X() ) );
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrY, OUString::valueOf( aPoint.Y() ) );
mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrXLinkHRef, sRefId );
SvXMLElementExport aRefElem( mrExport, XML_NAMESPACE_NONE, "use", sal_True, sal_True );
@@ -1906,31 +1945,13 @@ PolyPolygon& SVGActionWriter::ImplMap( const PolyPolygon& rPolyPoly, PolyPolygon
// -----------------------------------------------------------------------------
-sal_uLong SVGActionWriter::GetChecksum( const MetaBmpExScaleAction* pAct )
+sal_uLong SVGActionWriter::GetChecksum( const MetaAction* pAction )
{
- 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;
+ GDIMetaFile aMtf;
+ MetaAction* pA = (MetaAction*)pAction;
+ pA->Duplicate();
+ aMtf.AddAction( pA );
+ return aMtf.GetChecksum();
}
// -----------------------------------------------------------------------------
@@ -2749,11 +2770,12 @@ void SVGActionWriter::ImplWriteActions( const GDIMetaFile& rMtf,
if( mnInnerMtfCount )
nWriteFlags |= SVGWRITER_NO_SHAPE_COMMENTS;
+
+ bool bIsTextShape = false;
if( !mrExport.IsUsePositionedCharacters() && pxShape
&& Reference< XText >( *pxShape, UNO_QUERY ).is() )
{
- Reference< XText > xText( *pxShape, UNO_QUERY );
- maTextWriter.setTextShape( xText, pTextEmbeddedBitmapMtf );
+ bIsTextShape = true;
}
mbIsPlacehlolderShape = false;
@@ -2769,7 +2791,7 @@ void SVGActionWriter::ImplWriteActions( const GDIMetaFile& rMtf,
const MetaAction* pAction = rMtf.GetAction( nCurAction );
const sal_uInt16 nType = pAction->GetType();
- if( maTextWriter.getTextShape().is() )
+ if( bIsTextShape )
{
try
{
@@ -3225,6 +3247,12 @@ void SVGActionWriter::ImplWriteActions( const GDIMetaFile& rMtf,
{
if( ( pA->GetComment().equalsIgnoreAsciiCaseL( RTL_CONSTASCII_STRINGPARAM( "XTEXT_PAINTSHAPE_BEGIN" ) ) ) )
{
+ if( pxShape )
+ {
+ Reference< XText > xText( *pxShape, UNO_QUERY );
+ if( xText.is() )
+ maTextWriter.setTextShape( xText, pTextEmbeddedBitmapMtf );
+ }
maTextWriter.createParagraphEnumeration();
{
// nTextFound == -1 => no text found
@@ -3343,9 +3371,17 @@ void SVGActionWriter::ImplWriteActions( const GDIMetaFile& rMtf,
{
const MetaBmpScaleAction* pA = (const MetaBmpScaleAction*) pAction;
- ImplWriteBmp( pA->GetBitmap(),
- pA->GetPoint(), pA->GetSize(),
- Point(), pA->GetBitmap().GetSizePixel() );
+ // Bitmaps embedded into text shapes are collected and exported elsewhere.
+ if( maTextWriter.isTextShapeStarted() )
+ {
+ maTextWriter.writeBitmapPlaceholder( pA );
+ }
+ else
+ {
+ ImplWriteBmp( pA->GetBitmap(),
+ pA->GetPoint(), pA->GetSize(),
+ Point(), pA->GetBitmap().GetSizePixel() );
+ }
}
}
break;
@@ -3383,7 +3419,7 @@ 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() )
+ if( maTextWriter.isTextShapeStarted() )
{
maTextWriter.writeBitmapPlaceholder( pA );
}
diff --git a/filter/source/svg/svgwriter.hxx b/filter/source/svg/svgwriter.hxx
index 125c5efe157c..7f79f6ffaade 100644
--- a/filter/source/svg/svgwriter.hxx
+++ b/filter/source/svg/svgwriter.hxx
@@ -204,7 +204,9 @@ class SVGTextWriter
SVGFontExport& mrFontExport;
SVGAttributeWriter* mpContext;
VirtualDevice* mpVDev;
+ sal_Bool mbIsTextShapeStarted;
Reference<XText> mrTextShape;
+ ::rtl::OUString msShapeId;
Reference<XEnumeration> mrParagraphEnumeration;
Reference<XTextContent> mrCurrentTextParagraph;
Reference<XEnumeration> mrTextPortionEnumeration;
@@ -244,6 +246,7 @@ class SVGTextWriter
sal_Bool nextParagraph();
sal_Bool nextTextPortion();
+ sal_Bool isTextShapeStarted() { return mbIsTextShapeStarted; }
void startTextShape();
void endTextShape();
void startTextParagraph();
@@ -252,7 +255,8 @@ class SVGTextWriter
void endTextPosition();
void implExportHyperlinkIds();
void implWriteBulletChars();
- void writeBitmapPlaceholder( const MetaBmpExScaleAction* pAction );
+ template< typename MetaBitmapActionType >
+ void writeBitmapPlaceholder( const MetaBitmapActionType* pAction );
void implWriteEmbeddedBitmaps();
void writeTextPortion( const Point& rPos, const String& rText,
sal_Bool bApplyMapping = sal_True );
@@ -295,8 +299,12 @@ class SVGTextWriter
void implMap( const Point& rPt, Point& rDstPt ) const;
void implSetCurrentFont();
void implSetFontFamily();
+
template< typename SubType >
sal_Bool implGetTextPosition( const MetaAction* pAction, Point& raPos, sal_Bool& bEmpty );
+ template< typename SubType >
+ sal_Bool implGetTextPositionFromBitmap( const MetaAction* pAction, Point& raPos, sal_Bool& rbEmpty );
+
void implRegisterInterface( const Reference< XInterface >& rxIf );
const ::rtl::OUString & implGetValidIDFromInterface( const Reference< XInterface >& rxIf );
@@ -390,7 +398,7 @@ private:
public:
static ::rtl::OUString GetPathString( const PolyPolygon& rPolyPoly, sal_Bool bLine );
- static sal_uLong GetChecksum( const MetaBmpExScaleAction* pAct );
+ static sal_uLong GetChecksum( const MetaAction* pAction );
public:
@@ -404,7 +412,6 @@ public:
const ::rtl::OUString* pElementId = NULL,
const Reference< XShape >* pXShape = NULL,
const GDIMetaFile* pTextEmbeddedBitmapMtf = NULL );
- sal_Bool bIsTextShape;
};
#endif