blob: 1d75dd14989ffcdd9f8a979e0c0b491247762c7b [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
#include "oox/core/xmlfilterbase.hxx"
#include "oox/export/drawingml.hxx"
#include "oox/export/utils.hxx"
#include <cstdio>
#include <com/sun/star/awt/CharSet.hpp>
#include <com/sun/star/awt/FontDescriptor.hpp>
#include <com/sun/star/awt/FontSlant.hpp>
#include <com/sun/star/awt/FontWeight.hpp>
#include <com/sun/star/awt/FontUnderline.hpp>
#include <com/sun/star/awt/Gradient.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/beans/XPropertyState.hpp>
#include <com/sun/star/container/XEnumerationAccess.hpp>
#include <com/sun/star/drawing/BitmapMode.hpp>
#include <com/sun/star/drawing/EnhancedCustomShapeAdjustmentValue.hpp>
#include <com/sun/star/drawing/LineDash.hpp>
#include <com/sun/star/drawing/LineJoint.hpp>
#include <com/sun/star/drawing/LineStyle.hpp>
#include <com/sun/star/drawing/TextHorizontalAdjust.hpp>
#include <com/sun/star/drawing/TextVerticalAdjust.hpp>
#include <com/sun/star/i18n/ScriptType.hpp>
#include <com/sun/star/io/XOutputStream.hpp>
#include <com/sun/star/style/ParagraphAdjust.hpp>
#include <com/sun/star/text/XText.hpp>
#include <com/sun/star/text/XTextContent.hpp>
#include <com/sun/star/text/XTextField.hpp>
#include <com/sun/star/text/XTextRange.hpp>
#include <tools/stream.hxx>
#include <tools/string.hxx>
#include <vcl/cvtgrf.hxx>
#include <unotools/fontcvt.hxx>
#include <vcl/graph.hxx>
#include <svtools/grfmgr.hxx>
#include <rtl/strbuf.hxx>
#include <sfx2/app.hxx>
#include <svl/languageoptions.hxx>
#include <svx/escherex.hxx>
#include <svx/svxenum.hxx>
using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::drawing;
using namespace ::com::sun::star::i18n;
using ::com::sun::star::beans::PropertyState;
using ::com::sun::star::beans::PropertyValue;
using ::com::sun::star::beans::XPropertySet;
using ::com::sun::star::beans::XPropertyState;
using ::com::sun::star::container::XEnumeration;
using ::com::sun::star::container::XEnumerationAccess;
using ::com::sun::star::container::XIndexAccess;
using ::com::sun::star::io::XOutputStream;
using ::com::sun::star::text::XText;
using ::com::sun::star::text::XTextContent;
using ::com::sun::star::text::XTextField;
using ::com::sun::star::text::XTextRange;
using ::rtl::OString;
using ::rtl::OStringBuffer;
using ::rtl::OUString;
using ::rtl::OUStringBuffer;
using ::sax_fastparser::FSHelperPtr;
DBG(extern void dump_pset(Reference< XPropertySet > rXPropSet));
namespace oox {
namespace drawingml {
#define GETA(propName) \
GetProperty( rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( #propName ) ) )
#define GETAD(propName) \
( GetPropertyAndState( rXPropSet, rXPropState, String( RTL_CONSTASCII_USTRINGPARAM( #propName ) ), eState ) && eState == beans::PropertyState_DIRECT_VALUE )
#define GET(variable, propName) \
if ( GETA(propName) ) \
mAny >>= variable;
// not thread safe
int DrawingML::mnImageCounter = 1;
void DrawingML::ResetCounters()
{
mnImageCounter = 1;
}
bool DrawingML::GetProperty( Reference< XPropertySet > rXPropSet, String aName )
{
bool bRetValue = false;
try {
mAny = rXPropSet->getPropertyValue( aName );
if ( mAny.hasValue() )
bRetValue = true;
} catch( Exception& ) { /* printf ("exception when trying to get value of property: %s\n", ST(aName)); */ }
return bRetValue;
}
bool DrawingML::GetPropertyAndState( Reference< XPropertySet > rXPropSet, Reference< XPropertyState > rXPropState, String aName, PropertyState& eState )
{
bool bRetValue = false;
try {
mAny = rXPropSet->getPropertyValue( aName );
if ( mAny.hasValue() ) {
bRetValue = true;
eState = rXPropState->getPropertyState( aName );
}
} catch( Exception& ) { /* printf ("exception when trying to get value of property: %s\n", ST(aName)); */ }
return bRetValue;
}
void DrawingML::WriteColor( sal_uInt32 nColor )
{
OString sColor = OString::valueOf( ( sal_Int64 ) nColor, 16 );
if( sColor.getLength() < 6 ) {
OStringBuffer sBuf( "0" );
int remains = 5 - sColor.getLength();
while( remains > 0 ) {
sBuf.append( "0" );
remains--;
}
sBuf.append( sColor );
sColor = sBuf.getStr();
}
mpFS->singleElementNS( XML_a, XML_srgbClr, XML_val, sColor.getStr(), FSEND );
}
void DrawingML::WriteSolidFill( sal_uInt32 nColor )
{
mpFS->startElementNS( XML_a, XML_solidFill, FSEND );
WriteColor( nColor );
mpFS->endElementNS( XML_a, XML_solidFill );
}
void DrawingML::WriteSolidFill( Reference< XPropertySet > rXPropSet )
{
if ( GetProperty( rXPropSet, S( "FillColor" ) ) )
WriteSolidFill( *((sal_uInt32*) mAny.getValue()) & 0xffffff );
}
void DrawingML::WriteGradientStop( sal_uInt16 nStop, sal_uInt32 nColor )
{
mpFS->startElementNS( XML_a, XML_gs,
XML_pos, I32S( nStop * 1000 ),
FSEND );
WriteColor( nColor );
mpFS->endElementNS( XML_a, XML_gs );
}
sal_uInt32 DrawingML::ColorWithIntensity( sal_uInt32 nColor, sal_uInt32 nIntensity )
{
return ( ( ( nColor & 0xff ) * nIntensity ) / 100 )
| ( ( ( ( ( nColor & 0xff00 ) >> 8 ) * nIntensity ) / 100 ) << 8 )
| ( ( ( ( ( nColor & 0xff0000 ) >> 8 ) * nIntensity ) / 100 ) << 8 );
}
void DrawingML::WriteGradientFill( Reference< XPropertySet > rXPropSet )
{
awt::Gradient aGradient;
if( GETA( FillGradient ) ) {
aGradient = *static_cast< const awt::Gradient* >( mAny.getValue() );
mpFS->startElementNS( XML_a, XML_gradFill, FSEND );
switch( aGradient.Style ) {
default:
case GradientStyle_LINEAR:
mpFS->startElementNS( XML_a, XML_gsLst, FSEND );
WriteGradientStop( 0, ColorWithIntensity( aGradient.StartColor, aGradient.StartIntensity ) );
WriteGradientStop( 100, ColorWithIntensity( aGradient.EndColor, aGradient.EndIntensity ) );
mpFS->endElementNS( XML_a, XML_gsLst );
mpFS->singleElementNS( XML_a, XML_lin,
XML_ang, I32S( ( ( ( 3600 - aGradient.Angle + 900 ) * 6000 ) % 21600000 ) ),
FSEND );
break;
case GradientStyle_AXIAL:
mpFS->startElementNS( XML_a, XML_gsLst, FSEND );
WriteGradientStop( 0, ColorWithIntensity( aGradient.EndColor, aGradient.EndIntensity ) );
WriteGradientStop( 50, ColorWithIntensity( aGradient.StartColor, aGradient.StartIntensity ) );
WriteGradientStop( 100, ColorWithIntensity( aGradient.EndColor, aGradient.EndIntensity ) );
mpFS->endElementNS( XML_a, XML_gsLst );
mpFS->singleElementNS( XML_a, XML_lin,
XML_ang, I32S( ( ( ( 3600 - aGradient.Angle + 900 ) * 6000 ) % 21600000 ) ),
FSEND );
break;
/* I don't see how to apply transformation to gradients, so
* elliptical will end as radial and square as
* rectangular. also position offsets are not applied */
case GradientStyle_RADIAL:
case GradientStyle_ELLIPTICAL:
case GradientStyle_RECT:
case GradientStyle_SQUARE:
mpFS->startElementNS( XML_a, XML_gsLst, FSEND );
WriteGradientStop( 0, ColorWithIntensity( aGradient.EndColor, aGradient.EndIntensity ) );
WriteGradientStop( 100, ColorWithIntensity( aGradient.StartColor, aGradient.StartIntensity ) );
mpFS->endElementNS( XML_a, XML_gsLst );
mpFS->singleElementNS( XML_a, XML_path,
XML_path, ( aGradient.Style == awt::GradientStyle_RADIAL || aGradient.Style == awt::GradientStyle_ELLIPTICAL ) ? "circle" : "rect",
FSEND );
break;
}
mpFS->endElementNS( XML_a, XML_gradFill );
}
}
void DrawingML::WriteLineArrow( Reference< XPropertySet > rXPropSet, sal_Bool bLineStart )
{
ESCHER_LineEnd eLineEnd;
sal_Int32 nArrowLength;
sal_Int32 nArrowWidth;
if ( EscherPropertyContainer::GetLineArrow( bLineStart, rXPropSet, eLineEnd, nArrowLength, nArrowWidth ) ) {
const char* len;
const char* type;
const char* width;
switch( nArrowLength ) {
case ESCHER_LineShortArrow:
len = "sm";
break;
default:
case ESCHER_LineMediumLenArrow:
len = "med";
break;
case ESCHER_LineLongArrow:
len = "lg";
break;
}
switch( eLineEnd ) {
default:
case ESCHER_LineNoEnd:
type = "none";
break;
case ESCHER_LineArrowEnd:
type = "triangle";
break;
case ESCHER_LineArrowStealthEnd:
type = "stealth";
break;
case ESCHER_LineArrowDiamondEnd:
type = "diamond";
break;
case ESCHER_LineArrowOvalEnd:
type = "oval";
break;
case ESCHER_LineArrowOpenEnd:
type = "arrow";
break;
}
switch( nArrowWidth ) {
case ESCHER_LineNarrowArrow:
width = "sm";
break;
default:
case ESCHER_LineMediumWidthArrow:
width = "med";
break;
case ESCHER_LineWideArrow:
width = "lg";
break;
}
mpFS->singleElementNS( XML_a, bLineStart ? XML_headEnd : XML_tailEnd,
XML_len, len,
XML_type, type,
XML_w, width,
FSEND );
}
}
void DrawingML::WriteOutline( Reference< XPropertySet > rXPropSet )
{
drawing::LineStyle aLineStyle( drawing::LineStyle_NONE );
GET( aLineStyle, LineStyle );
if( aLineStyle == drawing::LineStyle_NONE )
return;
sal_uInt32 nLineWidth = 0;
sal_uInt32 nColor = 0;
sal_Bool bColorSet = FALSE;
const char* cap = NULL;
drawing::LineDash aLineDash;
sal_Bool bDashSet = FALSE;
GET( nLineWidth, LineWidth );
switch( aLineStyle ) {
case drawing::LineStyle_DASH:
if( GETA( LineDash ) ) {
aLineDash = *(drawing::LineDash*) mAny.getValue();
bDashSet = TRUE;
if( aLineDash.Style == DashStyle_ROUND || aLineDash.Style == DashStyle_ROUNDRELATIVE )
cap = "rnd";
DBG(printf("dash dots: %d dashes: %d dotlen: %d dashlen: %d distance: %d\n",
int( aLineDash.Dots ), int( aLineDash.Dashes ), int( aLineDash.DotLen ), int( aLineDash.DashLen ), int( aLineDash.Distance )));
}
/* fallthru intended */
case drawing::LineStyle_SOLID:
default:
if ( GETA( LineColor ) ) {
nColor = *((sal_uInt32*) mAny.getValue()) & 0xffffff;
bColorSet = TRUE;
}
break;
}
mpFS->startElementNS( XML_a, XML_ln,
XML_cap, cap,
XML_w, nLineWidth > 1 ? I64S( MM100toEMU( nLineWidth ) ) : NULL,
FSEND );
if( bColorSet )
WriteSolidFill( nColor );
if( bDashSet ) {
mpFS->startElementNS( XML_a, XML_custDash, FSEND );
int i;
for( i = 0; i < aLineDash.Dots; i ++ )
mpFS->singleElementNS( XML_a, XML_ds,
XML_d, aLineDash.DotLen ? I64S( aLineDash.DotLen*1000 ) : "100000",
XML_sp, I64S( aLineDash.Distance*1000 ),
FSEND );
for( i = 0; i < aLineDash.Dashes; i ++ )
mpFS->singleElementNS( XML_a, XML_ds,
XML_d, aLineDash.DashLen ? I64S( aLineDash.DashLen*1000 ) : "100000",
XML_sp, I64S( aLineDash.Distance*1000 ),
FSEND );
mpFS->endElementNS( XML_a, XML_custDash );
}
if( nLineWidth > 1 && GETA( LineJoint ) ) {
LineJoint eLineJoint;
mAny >>= eLineJoint;
switch( eLineJoint ) {
case LineJoint_NONE:
case LineJoint_MIDDLE:
case LineJoint_BEVEL:
mpFS->singleElementNS( XML_a, XML_bevel, FSEND );
break;
default:
case LineJoint_MITER:
mpFS->singleElementNS( XML_a, XML_miter, FSEND );
break;
case LineJoint_ROUND:
mpFS->singleElementNS( XML_a, XML_round, FSEND );
break;
}
}
WriteLineArrow( rXPropSet, sal_True );
WriteLineArrow( rXPropSet, sal_False );
mpFS->endElementNS( XML_a, XML_ln );
}
OUString DrawingML::WriteImage( const OUString& rURL )
{
ByteString aURLBS( UniString( rURL ), RTL_TEXTENCODING_UTF8 );
const char aURLBegin[] = "vnd.sun.star.GraphicObject:";
int index = aURLBS.Search( aURLBegin );
if ( index != STRING_NOTFOUND ) {
DBG(printf ("begin: %ld %s\n", long( sizeof( aURLBegin ) ), USS( rURL ) + sizeof( aURLBegin ) - 1 ));
aURLBS.Erase( 0, sizeof( aURLBegin ) - 1 );
Graphic aGraphic = GraphicObject( aURLBS ).GetTransformedGraphic ();
return WriteImage( aGraphic );
} else {
// add link to relations
}
return OUString();
}
OUString DrawingML::WriteImage( const Graphic& rGraphic )
{
GfxLink aLink = rGraphic.GetLink ();
OUString sMediaType;
const char* sExtension = NULL;
OUString sRelId;
SvMemoryStream aStream;
const void* aData = aLink.GetData();
sal_Size nDataSize = aLink.GetDataSize();
switch ( aLink.GetType() ) {
case GFX_LINK_TYPE_NATIVE_GIF:
sMediaType = US( "image/gif" );
sExtension = ".gif";
break;
// #15508# added BMP type for better exports
// export not yet active, so adding for reference (not checked)
case GFX_LINK_TYPE_NATIVE_BMP:
sMediaType = US( "image/bmp" );
sExtension = ".bmp";
break;
case GFX_LINK_TYPE_NATIVE_JPG:
sMediaType = US( "image/jpeg" );
sExtension = ".jpeg";
break;
case GFX_LINK_TYPE_NATIVE_PNG:
sMediaType = US( "image/png" );
sExtension = ".png";
break;
case GFX_LINK_TYPE_NATIVE_TIF:
sMediaType = US( "image/tiff" );
sExtension = ".tiff";
break;
case GFX_LINK_TYPE_NATIVE_WMF:
sMediaType = US( "image/x-wmf" );
sExtension = ".wmf";
break;
case GFX_LINK_TYPE_NATIVE_MET:
sMediaType = US( "image/x-met" );
sExtension = ".met";
break;
case GFX_LINK_TYPE_NATIVE_PCT:
sMediaType = US( "image/x-pict" );
sExtension = ".pct";
break;
default: {
GraphicType aType = rGraphic.GetType();
if ( aType == GRAPHIC_BITMAP ) {
GraphicConverter::Export( aStream, rGraphic, CVT_PNG );
sMediaType = US( "image/png" );
sExtension = ".png";
} else if ( aType == GRAPHIC_GDIMETAFILE ) {
GraphicConverter::Export( aStream, rGraphic, CVT_EMF );
sMediaType = US( "image/x-emf" );
sExtension = ".emf";
} else {
OSL_TRACE( "unhandled graphic type" );
break;
}
aData = aStream.GetData();
nDataSize = aStream.GetSize();
break;
}
}
const char *pComponent = NULL;
switch ( meDocumentType )
{
case DOCUMENT_DOCX: pComponent = "word"; break;
case DOCUMENT_PPTX: pComponent = "ppt"; break;
case DOCUMENT_XLSX: pComponent = "xl"; break;
}
Reference< XOutputStream > xOutStream = mpFB->openOutputStream( OUStringBuffer()
.appendAscii( pComponent )
.appendAscii( "/media/image" )
.append( (sal_Int32) mnImageCounter )
.appendAscii( sExtension )
.makeStringAndClear(),
sMediaType );
xOutStream->writeBytes( Sequence< sal_Int8 >( (const sal_Int8*) aData, nDataSize ) );
xOutStream->closeOutput();
const char *pImagePrefix = NULL;
switch ( meDocumentType )
{
case DOCUMENT_DOCX:
pImagePrefix = "media/image";
break;
case DOCUMENT_PPTX:
case DOCUMENT_XLSX:
pImagePrefix = "../media/image";
break;
}
sRelId = mpFB->addRelation( mpFS->getOutputStream(),
US( "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" ),
OUStringBuffer()
.appendAscii( pImagePrefix )
.append( (sal_Int32) mnImageCounter ++ )
.appendAscii( sExtension )
.makeStringAndClear() );
return sRelId;
}
OUString DrawingML::WriteBlip( OUString& rURL )
{
OUString sRelId = WriteImage( rURL );
mpFS->singleElementNS( XML_a, XML_blip,
FSNS( XML_r, XML_embed), OUStringToOString( sRelId, RTL_TEXTENCODING_UTF8 ).getStr(),
FSEND );
return sRelId;
}
void DrawingML::WriteBlipMode( Reference< XPropertySet > rXPropSet )
{
BitmapMode eBitmapMode( BitmapMode_NO_REPEAT );
if (GetProperty( rXPropSet, S( "FillBitmapMode" ) ) )
mAny >>= eBitmapMode;
DBG(printf("fill bitmap mode: %d\n", eBitmapMode));
switch (eBitmapMode) {
case BitmapMode_REPEAT:
mpFS->singleElementNS( XML_a, XML_tile, FSEND );
break;
default:
;
}
}
void DrawingML::WriteBlipFill( Reference< XPropertySet > rXPropSet, String sURLPropName )
{
WriteBlipFill( rXPropSet, sURLPropName, XML_a );
}
void DrawingML::WriteBlipFill( Reference< XPropertySet > rXPropSet, String sURLPropName, sal_Int32 nXmlNamespace )
{
if ( GetProperty( rXPropSet, sURLPropName ) ) {
OUString aURL;
mAny >>= aURL;
DBG(printf ("URL: %s\n", OUStringToOString( aURL, RTL_TEXTENCODING_UTF8 ).getStr() ));
if( !aURL.getLength() )
return;
mpFS->startElementNS( nXmlNamespace , XML_blipFill, FSEND );
WriteBlip( aURL );
if( sURLPropName == S( "FillBitmapURL" ) )
WriteBlipMode( rXPropSet );
else if( GetProperty( rXPropSet, S( "FillBitmapStretch" ) ) ) {
bool bStretch = false;
mAny >>= bStretch;
if( bStretch )
WriteStretch();
}
mpFS->endElementNS( nXmlNamespace, XML_blipFill );
}
}
void DrawingML::WriteStretch()
{
mpFS->startElementNS( XML_a, XML_stretch, FSEND );
mpFS->singleElementNS( XML_a, XML_fillRect, FSEND );
mpFS->endElementNS( XML_a, XML_stretch );
}
void DrawingML::WriteTransformation( const Rectangle& rRect,
sal_Bool bFlipH, sal_Bool bFlipV, sal_Int32 nRotation )
{
mpFS->startElementNS( XML_a, XML_xfrm,
XML_flipH, bFlipH ? "1" : NULL,
XML_flipV, bFlipV ? "1" : NULL,
XML_rot, nRotation ? I32S( nRotation ) : NULL,
FSEND );
mpFS->singleElementNS( XML_a, XML_off, XML_x, IS( MM100toEMU( rRect.Left() ) ), XML_y, IS( MM100toEMU( rRect.Top() ) ), FSEND );
mpFS->singleElementNS( XML_a, XML_ext, XML_cx, IS( MM100toEMU( rRect.GetWidth() ) ), XML_cy, IS( MM100toEMU( rRect.GetHeight() ) ), FSEND );
mpFS->endElementNS( XML_a, XML_xfrm );
}
void DrawingML::WriteShapeTransformation( Reference< XShape > rXShape, sal_Bool bFlipH, sal_Bool bFlipV, sal_Int32 nRotation )
{
DBG(printf( "write shape transformation\n" ));
awt::Point aPos = rXShape->getPosition();
awt::Size aSize = rXShape->getSize();
WriteTransformation( Rectangle( Point( aPos.X, aPos.Y ), Size( aSize.Width, aSize.Height ) ), bFlipH, bFlipV, nRotation );
}
void DrawingML::WriteRunProperties( Reference< XTextRange > rRun )
{
Reference< XPropertySet > rXPropSet( rRun, UNO_QUERY );
Reference< XPropertyState > rXPropState( rRun, UNO_QUERY );
OUString usLanguage;
PropertyState eState;
sal_Int16 nScriptType = SvtLanguageOptions::GetScriptTypeOfLanguage( Application::GetSettings().GetLanguage() );
sal_Bool bComplex = ( nScriptType == ScriptType::COMPLEX );
const char* bold = NULL;
const char* italic = NULL;
const char* underline = NULL;
sal_Int32 nSize = 1800;
if( GETAD( CharHeight ) )
nSize = (sal_Int32) (100*(*((float*) mAny.getValue())));
if ( ( bComplex && GETAD( CharWeightComplex ) ) || GETAD( CharWeight ) )
if ( *((float*) mAny.getValue()) >= awt::FontWeight::SEMIBOLD )
bold = "1";
if ( ( bComplex && GETAD( CharPostureComplex ) ) || GETAD( CharPosture ) )
switch ( *((awt::FontSlant*) mAny.getValue()) )
{
case awt::FontSlant_OBLIQUE :
case awt::FontSlant_ITALIC :
italic = "1";
break;
default:
break;
}
if ( GETAD( CharUnderline ) )
switch ( *((sal_Int16*) mAny.getValue()) )
{
case awt::FontUnderline::SINGLE :
underline = "sng";
break;
case awt::FontUnderline::DOUBLE :
underline = "dbl";
break;
case awt::FontUnderline::DOTTED :
underline = "dotted";
break;
case awt::FontUnderline::DASH :
underline = "dash";
break;
case awt::FontUnderline::LONGDASH :
underline = "dashLong";
break;
case awt::FontUnderline::DASHDOT :
underline = "dotDash";
break;
case awt::FontUnderline::DASHDOTDOT :
underline = "dotDotDash";
break;
case awt::FontUnderline::WAVE :
underline = "wavy";
break;
case awt::FontUnderline::DOUBLEWAVE :
underline = "wavyDbl";
break;
case awt::FontUnderline::BOLD :
underline = "heavy";
break;
case awt::FontUnderline::BOLDDOTTED :
underline = "dottedHeavy";
break;
case awt::FontUnderline::BOLDDASH :
underline = "dashHeavy";
break;
case awt::FontUnderline::BOLDLONGDASH :
underline = "dashLongHeavy";
break;
case awt::FontUnderline::BOLDDASHDOT :
underline = "dotDashHeavy";
break;
case awt::FontUnderline::BOLDDASHDOTDOT :
underline = "dotDotDashHeavy";
break;
case awt::FontUnderline::BOLDWAVE :
underline = "wavyHeavy";
break;
}
if( GETA( CharLocale ) ) {
com::sun::star::lang::Locale eLocale;
mAny >>= eLocale;
OUStringBuffer usLanguageBuffer = eLocale.Language;
if( eLocale.Country.getLength() ) {
usLanguageBuffer.appendAscii( "-" );
usLanguageBuffer.append( eLocale.Country );
}
if( usLanguageBuffer.getLength() )
usLanguage = usLanguageBuffer.makeStringAndClear();
}
mpFS->startElementNS( XML_a, XML_rPr,
XML_b, bold,
XML_i, italic,
XML_lang, usLanguage.getLength() ? USS( usLanguage ) : NULL,
XML_sz, nSize == 1800 ? NULL : IS( nSize ),
XML_u, underline,
FSEND );
// mso doesn't like text color to be placed after typeface
if( GETAD( CharColor ) ) {
sal_uInt32 color = *((sal_uInt32*) mAny.getValue());
DBG(printf("run color: %x auto: %x\n", static_cast<unsigned int>( color ), static_cast<unsigned int>( COL_AUTO )));
if( color == COL_AUTO ) { // nCharColor depends to the background color
sal_Bool bIsDark = sal_False;
GET( bIsDark, IsBackgroundDark );
color = bIsDark ? 0xffffff : 0x000000;
}
color &= 0xffffff;
// TODO: special handle embossed/engraved
WriteSolidFill( color );
}
if( GETAD( CharFontName ) ) {
const char* typeface = NULL;
const char* pitch = NULL;
const char* charset = NULL;
OUString usTypeface, usPitch, usCharset;
mAny >>= usTypeface;
String aSubstName( GetSubsFontName( usTypeface, SUBSFONT_ONLYONE | SUBSFONT_MS ) );
if( aSubstName.Len() )
typeface = ST( aSubstName );
else
typeface = USS( usTypeface );
mpFS->singleElementNS( XML_a, XML_latin,
XML_typeface, typeface,
XML_pitchFamily, pitch,
XML_charset, charset,
FSEND );
}
if( ( bComplex && GETAD( CharFontNameComplex ) ) || ( !bComplex && GETAD( CharFontNameAsian ) ) ) {
const char* typeface = NULL;
const char* pitch = NULL;
const char* charset = NULL;
OUString usTypeface, usPitch, usCharset;
mAny >>= usTypeface;
String aSubstName( GetSubsFontName( usTypeface, SUBSFONT_ONLYONE | SUBSFONT_MS ) );
if( aSubstName.Len() )
typeface = ST( aSubstName );
else
typeface = USS( usTypeface );
mpFS->singleElementNS( XML_a, bComplex ? XML_cs : XML_ea,
XML_typeface, typeface,
XML_pitchFamily, pitch,
XML_charset, charset,
FSEND );
}
mpFS->endElementNS( XML_a, XML_rPr );
}
const char* DrawingML::GetFieldType( ::com::sun::star::uno::Reference< ::com::sun::star::text::XTextRange > rRun )
{
const char* sType = NULL;
Reference< XPropertySet > rXPropSet( rRun, UNO_QUERY );
String aFieldType;
if( GETA( TextPortionType ) ) {
aFieldType = String( *(::rtl::OUString*)mAny.getValue() );
DBG(printf ("field type: %s\n", ST(aFieldType) ));
}
if( aFieldType == S( "TextField" ) ) {
Reference< XTextField > rXTextField;
GET( rXTextField, TextField );
if( rXTextField.is() ) {
rXPropSet.set( rXTextField, UNO_QUERY );
if( rXPropSet.is() ) {
String aFieldKind( rXTextField->getPresentation( TRUE ) );
DBG(printf ("field kind: %s\n", ST(aFieldKind) ));
if( aFieldKind == S( "Page" ) ) {
return "slidenum";
}
}
}
}
return sType;
}
void DrawingML::GetUUID( OStringBuffer& rBuffer )
{
Sequence< sal_uInt8 > aSeq( 16 );
static char cDigits[17] = "0123456789ABCDEF";
rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True );
int i;
rBuffer.append( '{' );
for( i = 0; i < 4; i++ ) {
rBuffer.append( cDigits[ aSeq[i] >> 4 ] );
rBuffer.append( cDigits[ aSeq[i] && 0xf ] );
}
rBuffer.append( '-' );
for( ; i < 6; i++ ) {
rBuffer.append( cDigits[ aSeq[i] >> 4 ] );
rBuffer.append( cDigits[ aSeq[i] && 0xf ] );
}
rBuffer.append( '-' );
for( ; i < 8; i++ ) {
rBuffer.append( cDigits[ aSeq[i] >> 4 ] );
rBuffer.append( cDigits[ aSeq[i] && 0xf ] );
}
rBuffer.append( '-' );
for( ; i < 10; i++ ) {
rBuffer.append( cDigits[ aSeq[i] >> 4 ] );
rBuffer.append( cDigits[ aSeq[i] && 0xf ] );
}
rBuffer.append( '-' );
for( ; i < 16; i++ ) {
rBuffer.append( cDigits[ aSeq[i] >> 4 ] );
rBuffer.append( cDigits[ aSeq[i] && 0xf ] );
}
rBuffer.append( '}' );
}
void DrawingML::WriteRun( Reference< XTextRange > rRun )
{
const char* sFieldType;
bool bIsField = false;
OUString sText = rRun->getString();
if( sText.getLength() < 1)
return;
if( ( sFieldType = GetFieldType( rRun ) ) ) {
OStringBuffer sUUID(39);
GetUUID( sUUID );
mpFS->startElementNS( XML_a, XML_fld,
XML_id, sUUID.getStr(),
XML_type, sFieldType,
FSEND );
bIsField = true;
} else
mpFS->startElementNS( XML_a, XML_r, FSEND );
WriteRunProperties( rRun );
mpFS->startElementNS( XML_a, XML_t, FSEND );
mpFS->writeEscaped( sText );
mpFS->endElementNS( XML_a, XML_t );
if( bIsField )
mpFS->endElementNS( XML_a, XML_fld );
else
mpFS->endElementNS( XML_a, XML_r );
}
#define AUTONUM(x) \
if( bPBoth ) \
pAutoNumType = #x "ParenBoth"; \
else if( bPBehind ) \
pAutoNumType = #x "ParenR"; \
else if( bSDot ) \
pAutoNumType = #x "Period";
inline static const char* GetAutoNumType( sal_Int16 nNumberingType, bool bSDot, bool bPBehind, bool bPBoth )
{
const char* pAutoNumType = NULL;
switch( (SvxExtNumType)nNumberingType )
{
case SVX_NUM_CHARS_UPPER_LETTER_N :
case SVX_NUM_CHARS_UPPER_LETTER :
AUTONUM( alphaUc );
break;
case SVX_NUM_CHARS_LOWER_LETTER_N :
case SVX_NUM_CHARS_LOWER_LETTER :
AUTONUM( alphaLc );
break;
case SVX_NUM_ROMAN_UPPER :
AUTONUM( romanUc );
break;
case SVX_NUM_ROMAN_LOWER :
AUTONUM( romanLc );
break;
case SVX_NUM_ARABIC :
AUTONUM( arabic )
else
pAutoNumType = "arabicPlain";
break;
default:
break;
}
return pAutoNumType;
}
void DrawingML::WriteParagraphNumbering( Reference< XPropertySet > rXPropSet, sal_Int16 nLevel )
{
if( nLevel >= 0 && GETA( NumberingRules ) )
{
Reference< XIndexAccess > rXIndexAccess;
if ( ( mAny >>= rXIndexAccess ) && nLevel < rXIndexAccess->getCount() )
{
DBG(printf ("numbering rules\n"));
Sequence< PropertyValue > aPropertySequence;
rXIndexAccess->getByIndex( nLevel ) >>= aPropertySequence;
const PropertyValue* pPropValue = aPropertySequence.getArray();
sal_Int32 nPropertyCount = aPropertySequence.getLength();
if ( nPropertyCount ) {
sal_Int16 nNumberingType = -1;
bool bSDot = false;
bool bPBehind = false;
bool bPBoth = false;
sal_Unicode aBulletChar = 0x2022; // a bullet
awt::FontDescriptor aFontDesc;
bool bHasFontDesc = false;
OUString aGraphicURL;
sal_Int16 nBulletRelSize = 0;
for ( sal_Int32 i = 0; i < nPropertyCount; i++ ) {
const void* pValue = pPropValue[ i ].Value.getValue();
if ( pValue ) {
OUString aPropName( pPropValue[ i ].Name );
DBG(printf ("pro name: %s\n", OUStringToOString( aPropName, RTL_TEXTENCODING_UTF8 ).getStr()));
if ( aPropName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "NumberingType" ) ) )
nNumberingType = *( (sal_Int16*)pValue );
else if ( aPropName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Prefix" ) ) ) {
if( *(OUString*)pValue == US( ")" ) )
bPBoth = true;
} else if ( aPropName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Suffix" ) ) ) {
if( *(OUString*)pValue == US( "." ) )
bSDot = true;
else if( *(OUString*)pValue == US( ")" ) )
bPBehind = true;
} else if ( aPropName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "BulletChar" ) ) )
{
aBulletChar = String ( *( (String*)pValue ) ).GetChar( 0 );
//printf ("bullet char: %d\n", aBulletChar.getStr());
}
else if ( aPropName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "BulletFont" ) ) )
{
aFontDesc = *( (awt::FontDescriptor*)pValue );
bHasFontDesc = true;
// Our numbullet dialog has set the wrong textencoding for our "StarSymbol" font,
// instead of a Unicode encoding the encoding RTL_TEXTENCODING_SYMBOL was used.
// Because there might exist a lot of damaged documemts I added this two lines
// which fixes the bullet problem for the export.
if ( aFontDesc.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "StarSymbol" ) ) )
aFontDesc.CharSet = RTL_TEXTENCODING_MS_1252;
} else if ( aPropName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "BulletRelSize" ) ) ) {
nBulletRelSize = *( (sal_Int16*)pValue );
} else if ( aPropName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "GraphicURL" ) ) ) {
aGraphicURL = ( *(OUString*)pValue );
DBG(printf ("graphic url: %s\n", OUStringToOString( aGraphicURL, RTL_TEXTENCODING_UTF8 ).getStr()));
} else if ( aPropName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "GraphicSize" ) ) )
{
if ( pPropValue[ i ].Value.getValueType() == ::getCppuType( (awt::Size*)0) )
{
// don't cast awt::Size to Size as on 64-bits they are not the same.
::com::sun::star::awt::Size aSize;
pPropValue[ i ].Value >>= aSize;
//aBuGraSize.nA = aSize.Width;
//aBuGraSize.nB = aSize.Height;
DBG(printf("graphic size: %dx%d\n", int( aSize.Width ), int( aSize.Height )));
}
}
}
}
const char* pAutoNumType = GetAutoNumType( nNumberingType, bSDot, bPBehind, bPBoth );
if( nLevel >= 0 ) {
if( aGraphicURL.getLength() > 0 ) {
OUString sRelId = WriteImage( aGraphicURL );
mpFS->startElementNS( XML_a, XML_buBlip, FSEND );
mpFS->singleElementNS( XML_a, XML_blip, FSNS( XML_r, XML_embed ), USS( sRelId ), FSEND );
mpFS->endElementNS( XML_a, XML_buBlip );
} else {
if( nBulletRelSize && nBulletRelSize != 100 )
mpFS->singleElementNS( XML_a, XML_buSzPct,
XML_val, IS( 1000*( (sal_Int32)nBulletRelSize ) ), FSEND );
if( bHasFontDesc )
mpFS->singleElementNS( XML_a, XML_buFont,
XML_typeface, OUStringToOString( aFontDesc.Name, RTL_TEXTENCODING_UTF8 ).getStr(),
XML_charset, (aFontDesc.CharSet == awt::CharSet::SYMBOL) ? "2" : NULL,
FSEND );
if( pAutoNumType )
mpFS->singleElementNS( XML_a, XML_buAutoNum, XML_type, pAutoNumType, FSEND );
else {
aBulletChar = SubstituteBullet( aBulletChar, aFontDesc );
mpFS->singleElementNS( XML_a, XML_buChar, XML_char, USS( OUString( aBulletChar ) ), FSEND );
}
}
}
}
}
}
}
const char* DrawingML::GetAlignment( sal_Int32 nAlignment )
{
const char* sAlignment = NULL;
switch( nAlignment ) {
case style::ParagraphAdjust_CENTER:
sAlignment = "ctr";
break;
case style::ParagraphAdjust_RIGHT:
sAlignment = "r";
break;
case style::ParagraphAdjust_BLOCK:
sAlignment = "just";
break;
default:
;
}
return sAlignment;
}
void DrawingML::WriteParagraphProperties( Reference< XTextContent > rParagraph )
{
Reference< XPropertySet > rXPropSet( rParagraph, UNO_QUERY );
Reference< XPropertyState > rXPropState( rParagraph, UNO_QUERY );
if( !rXPropSet.is() || !rXPropState.is() )
return;
sal_Int16 nLevel = -1;
GET( nLevel, NumberingLevel );
sal_Int32 nLeftMargin = 0;
// fix coordinates
//GET( nLeftMargin, ParaLeftMargin );
sal_Int16 nAlignment( style::ParagraphAdjust_LEFT );
GET( nAlignment, ParaAdjust );
if( nLevel != -1
|| nLeftMargin > 0
|| nAlignment != style::ParagraphAdjust_LEFT ) {
mpFS->startElementNS( XML_a, XML_pPr,
XML_lvl, nLevel > 0 ? I32S( nLevel ) : NULL,
XML_marL, nLeftMargin > 0 ? IS( nLeftMargin ) : NULL,
XML_algn, GetAlignment( nAlignment ),
FSEND );
WriteParagraphNumbering( rXPropSet, nLevel );
mpFS->endElementNS( XML_a, XML_pPr );
}
}
void DrawingML::WriteParagraph( Reference< XTextContent > rParagraph )
{
Reference< XEnumerationAccess > access( rParagraph, UNO_QUERY );
if( !access.is() )
return;
Reference< XEnumeration > enumeration( access->createEnumeration() );
if( !enumeration.is() )
return;
mpFS->startElementNS( XML_a, XML_p, FSEND );
sal_Bool bPropertiesWritten = FALSE;
while( enumeration->hasMoreElements() ) {
Reference< XTextRange > run;
Any any ( enumeration->nextElement() );
if (any >>= run) {
if( !bPropertiesWritten && run->getString().getLength() ) {
WriteParagraphProperties( rParagraph );
bPropertiesWritten = TRUE;
}
WriteRun( run );
}
}
mpFS->singleElementNS( XML_a, XML_endParaRPr, FSEND );
mpFS->endElementNS( XML_a, XML_p );
}
void DrawingML::WriteText( Reference< XShape > rXShape )
{
Reference< XText > xXText( rXShape, UNO_QUERY );
Reference< XPropertySet > rXPropSet( rXShape, UNO_QUERY );
if( !xXText.is() )
return;
#define DEFLRINS 254
#define DEFTBINS 127
sal_Int32 nLeft, nRight, nTop, nBottom;
nLeft = nRight = DEFLRINS;
nTop = nBottom = DEFTBINS;
// top inset looks a bit different compared to ppt export
// check if something related doesn't work as expected
GET( nLeft, TextLeftDistance );
GET( nRight, TextRightDistance );
GET( nTop, TextUpperDistance );
GET( nBottom, TextLowerDistance );
TextVerticalAdjust eVerticalAlignment( TextVerticalAdjust_TOP );
const char* sVerticalAlignment = NULL;
GET( eVerticalAlignment, TextVerticalAdjust );
switch( eVerticalAlignment ) {
case TextVerticalAdjust_BOTTOM:
sVerticalAlignment = "b";
break;
case TextVerticalAdjust_CENTER:
sVerticalAlignment = "ctr";
break;
case TextVerticalAdjust_TOP:
default:
;
}
TextHorizontalAdjust eHorizontalAlignment( TextHorizontalAdjust_CENTER );
bool bHorizontalCenter = false;
GET( eHorizontalAlignment, TextHorizontalAdjust );
if( eHorizontalAlignment == TextHorizontalAdjust_CENTER )
bHorizontalCenter = true;
sal_Bool bHasWrap = FALSE;
sal_Bool bWrap = FALSE;
if( GETA( TextWordWrap ) ) {
mAny >>= bWrap;
bHasWrap = TRUE;
//DBG(printf("wrap: %d\n", bWrap));
}
mpFS->singleElementNS( XML_a, XML_bodyPr,
XML_wrap, bHasWrap && !bWrap ? "none" : NULL,
XML_lIns, (nLeft != DEFLRINS) ? IS( MM100toEMU( nLeft ) ) : NULL,
XML_rIns, (nRight != DEFLRINS) ? IS( MM100toEMU( nRight ) ) : NULL,
XML_tIns, (nTop != DEFTBINS) ? IS( MM100toEMU( nTop ) ) : NULL,
XML_bIns, (nBottom != DEFTBINS) ? IS( MM100toEMU( nBottom ) ) : NULL,
XML_anchor, sVerticalAlignment,
XML_anchorCtr, bHorizontalCenter ? "1" : NULL,
FSEND );
Reference< XEnumerationAccess > access( xXText, UNO_QUERY );
if( !access.is() )
return;
Reference< XEnumeration > enumeration( access->createEnumeration() );
if( !enumeration.is() )
return;
while( enumeration->hasMoreElements() ) {
Reference< XTextContent > paragraph;
Any any ( enumeration->nextElement() );
if( any >>= paragraph)
WriteParagraph( paragraph );
}
}
void DrawingML::WritePresetShape( const char* pShape )
{
mpFS->startElementNS( XML_a, XML_prstGeom,
XML_prst, pShape,
FSEND );
mpFS->singleElementNS( XML_a, XML_avLst, FSEND );
mpFS->endElementNS( XML_a, XML_prstGeom );
}
void DrawingML::WritePresetShape( const char* pShape, MSO_SPT eShapeType, sal_Bool bPredefinedHandlesUsed, sal_Int32 nAdjustmentsWhichNeedsToBeConverted, const PropertyValue& rProp )
{
mpFS->startElementNS( XML_a, XML_prstGeom,
XML_prst, pShape,
FSEND );
mpFS->startElementNS( XML_a, XML_avLst, FSEND );
Sequence< drawing::EnhancedCustomShapeAdjustmentValue > aAdjustmentSeq;
if ( rProp.Value >>= aAdjustmentSeq ) {
DBG(printf("adj seq len: %d\n", int( aAdjustmentSeq.getLength() )));
if ( bPredefinedHandlesUsed )
EscherPropertyContainer::LookForPolarHandles( eShapeType, nAdjustmentsWhichNeedsToBeConverted );
sal_Int32 nValue, nLength = aAdjustmentSeq.getLength();
for( sal_Int32 i=0; i < nLength; i++ )
if( EscherPropertyContainer::GetAdjustmentValue( aAdjustmentSeq[ i ], i, nAdjustmentsWhichNeedsToBeConverted, nValue ) )
mpFS->singleElementNS( XML_a, XML_gd,
XML_name, nLength > 1 ? ( OString( "adj" ) + OString::valueOf( i + 1 ) ).getStr() : "adj",
XML_fmla, (OString("val ") + OString::valueOf( nValue )).getStr(),
FSEND );
}
mpFS->endElementNS( XML_a, XML_avLst );
mpFS->endElementNS( XML_a, XML_prstGeom );
}
void DrawingML::WritePolyPolygon( const PolyPolygon& rPolyPolygon )
{
if( rPolyPolygon.Count() < 1 )
return;
mpFS->startElementNS( XML_a, XML_custGeom, FSEND );
mpFS->singleElementNS( XML_a, XML_avLst, FSEND );
mpFS->singleElementNS( XML_a, XML_gdLst, FSEND );
mpFS->singleElementNS( XML_a, XML_ahLst, FSEND );
mpFS->singleElementNS( XML_a, XML_rect,
XML_l, "0",
XML_t, "0",
XML_r, "r",
XML_b, "b",
FSEND );
mpFS->startElementNS( XML_a, XML_pathLst, FSEND );
for( USHORT i = 0; i < rPolyPolygon.Count(); i ++ ) {
const Polygon& rPoly = rPolyPolygon[ i ];
Rectangle aRect( rPoly.GetBoundRect() );
sal_Bool bBezier = FALSE;
mpFS->startElementNS( XML_a, XML_path,
XML_w, I64S( aRect.GetWidth() ),
XML_h, I64S( aRect.GetHeight() ),
FSEND );
if( rPoly.GetSize() > 0 )
{
mpFS->startElementNS( XML_a, XML_moveTo, FSEND );
mpFS->singleElementNS( XML_a, XML_pt,
XML_x, I64S( rPoly[ 0 ].X() - aRect.Left() ),
XML_y, I64S( rPoly[ 0 ].Y() - aRect.Top() ),
FSEND );
mpFS->endElementNS( XML_a, XML_moveTo );
}
for( USHORT j = 1; j < rPoly.GetSize(); j ++ )
{
enum PolyFlags flags = rPoly.GetFlags(j);
if( flags == POLY_CONTROL && !bBezier )
{
mpFS->startElementNS( XML_a, XML_cubicBezTo, FSEND );
bBezier = TRUE;
}
else if( flags == POLY_NORMAL && !bBezier )
mpFS->startElementNS( XML_a, XML_lnTo, FSEND );
mpFS->singleElementNS( XML_a, XML_pt,
XML_x, I64S( rPoly[j].X() - aRect.Left() ),
XML_y, I64S( rPoly[j].Y() - aRect.Top() ),
FSEND );
if( ( flags == POLY_NORMAL || flags == POLY_SYMMTR ) && bBezier )
{
mpFS->endElementNS( XML_a, XML_cubicBezTo );
bBezier = FALSE;
}
else if( flags == POLY_NORMAL && !bBezier )
mpFS->endElementNS( XML_a, XML_lnTo );
else if( bBezier && ( j % 3 ) == 0 )
{
// //a:cubicBezTo can only contain 3 //a:pt elements, so we
// need to break things up...
mpFS->endElementNS( XML_a, XML_cubicBezTo );
mpFS->startElementNS( XML_a, XML_cubicBezTo, FSEND );
}
// switch( rPoly.GetFlags(j) ) {
// case POLY_NORMAL:
// DBG(printf("normal\n"));
// break;
// case POLY_SMOOTH:
// DBG(printf("smooth\n"));
// break;
// case POLY_CONTROL:
// DBG(printf("control\n"));
// break;
// case POLY_SYMMTR:
// DBG(printf("symmtr\n"));
// break;
// }
// DBG(printf("point %ld %ld\n", rPoly[j].X() - aRect.Left(), rPoly[j].Y() - aRect.Top()));
}
mpFS->endElementNS( XML_a, XML_path );
}
mpFS->endElementNS( XML_a, XML_pathLst );
mpFS->endElementNS( XML_a, XML_custGeom );
}
void DrawingML::WriteConnectorConnections( EscherConnectorListEntry& rConnectorEntry, sal_Int32 nStartID, sal_Int32 nEndID )
{
mpFS->singleElementNS( XML_a, XML_stCxn,
XML_id, I32S( nStartID ),
XML_idx, I64S( rConnectorEntry.GetConnectorRule( TRUE ) ),
FSEND );
mpFS->singleElementNS( XML_a, XML_endCxn,
XML_id, I32S( nEndID ),
XML_idx, I64S( rConnectorEntry.GetConnectorRule( FALSE ) ),
FSEND );
}
// from sw/source/filter/ww8/wrtw8num.cxx for default bullets to export to MS intact
static void lcl_SubstituteBullet(String& rNumStr, rtl_TextEncoding& rChrSet, String& rFontName)
{
sal_Unicode cChar = rNumStr.GetChar(0);
StarSymbolToMSMultiFont *pConvert = CreateStarSymbolToMSMultiFont();
String sFont = pConvert->ConvertChar(cChar);
delete pConvert;
if (sFont.Len())
{
rNumStr = static_cast< sal_Unicode >(cChar | 0xF000);
rFontName = sFont;
rChrSet = RTL_TEXTENCODING_SYMBOL;
}
else if ( (rNumStr.GetChar(0) < 0xE000 || rNumStr.GetChar(0) > 0xF8FF) )
{
/*
Ok we can't fit into a known windows unicode font, but
we are not in the private area, so we are a
standardized symbol, so turn off the symbol bit and
let words own font substitution kick in
*/
rChrSet = RTL_TEXTENCODING_UNICODE;
rFontName = ::GetFontToken(rFontName, 0);
}
else
{
/*
Well we don't have an available substition, and we're
in our private area, so give up and show a standard
bullet symbol
*/
rFontName.AssignAscii(RTL_CONSTASCII_STRINGPARAM("Wingdings"));
rNumStr = static_cast< sal_Unicode >(0x6C);
}
}
sal_Unicode DrawingML::SubstituteBullet( sal_Unicode cBulletId, ::com::sun::star::awt::FontDescriptor& rFontDesc )
{
String sNumStr = cBulletId;
if ( rFontDesc.Name.equalsIgnoreAsciiCaseAscii("starsymbol") ||
rFontDesc.Name.equalsIgnoreAsciiCaseAscii("opensymbol") ) {
String sFontName = rFontDesc.Name;
rtl_TextEncoding aCharSet = rFontDesc.CharSet;
lcl_SubstituteBullet( sNumStr, aCharSet, sFontName );
rFontDesc.Name = sFontName;
rFontDesc.CharSet = aCharSet;
}
return sNumStr.GetChar( 0 );
}
}
}