1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: atktextattributes.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_vcl.hxx"
34 #include "atktextattributes.hxx"
36 #include <com/sun/star/awt/FontSlant.hpp>
37 #include <com/sun/star/awt/FontStrikeout.hpp>
38 #include <com/sun/star/awt/FontUnderline.hpp>
40 #include <com/sun/star/style/CaseMap.hpp>
41 #include <com/sun/star/style/LineSpacing.hpp>
42 #include <com/sun/star/style/LineSpacingMode.hpp>
43 #include <com/sun/star/style/ParagraphAdjust.hpp>
44 #include <com/sun/star/style/TabAlign.hpp>
45 #include <com/sun/star/style/TabStop.hpp>
47 #include <com/sun/star/text/WritingMode2.hpp>
49 #include "atkwrapper.hxx"
51 #include <com/sun/star/accessibility/XAccessibleComponent.hpp>
53 #include <vcl/svapp.hxx>
54 #include <vcl/outdev.hxx>
59 using namespace ::com::sun::star
;
61 typedef gchar
* (* AtkTextAttrFunc
) ( const uno::Any
& rAny
);
62 typedef bool (* TextPropertyValueFunc
) ( uno::Any
& rAny
, const gchar
* value
);
64 #define STRNCMP_PARAM( s ) s,sizeof( s )-1
67 /*****************************************************************************/
69 static AtkTextAttribute atk_text_attribute_paragraph_style
= ATK_TEXT_ATTR_INVALID
;
70 static AtkTextAttribute atk_text_attribute_font_effect
= ATK_TEXT_ATTR_INVALID
;
71 static AtkTextAttribute atk_text_attribute_decoration
= ATK_TEXT_ATTR_INVALID
;
72 static AtkTextAttribute atk_text_attribute_line_height
= ATK_TEXT_ATTR_INVALID
;
73 static AtkTextAttribute atk_text_attribute_rotation
= ATK_TEXT_ATTR_INVALID
;
74 static AtkTextAttribute atk_text_attribute_shadow
= ATK_TEXT_ATTR_INVALID
;
75 static AtkTextAttribute atk_text_attribute_tab_interval
= ATK_TEXT_ATTR_INVALID
;
76 static AtkTextAttribute atk_text_attribute_tab_stops
= ATK_TEXT_ATTR_INVALID
;
77 static AtkTextAttribute atk_text_attribute_writing_mode
= ATK_TEXT_ATTR_INVALID
;
78 static AtkTextAttribute atk_text_attribute_vertical_align
= ATK_TEXT_ATTR_INVALID
;
80 /*****************************************************************************/
83 * !! IMPORTANT NOTE !! : when adding items to this list, KEEP THE LIST SORTED
84 * and re-arrange the enum values accordingly.
87 enum ExportedAttribute
89 TEXT_ATTRIBUTE_BACKGROUND_COLOR
= 0,
90 TEXT_ATTRIBUTE_CASEMAP
,
91 TEXT_ATTRIBUTE_FOREGROUND_COLOR
,
92 TEXT_ATTRIBUTE_CONTOURED
,
93 TEXT_ATTRIBUTE_CHAR_ESCAPEMENT
,
94 TEXT_ATTRIBUTE_BLINKING
,
95 TEXT_ATTRIBUTE_FONT_NAME
,
96 TEXT_ATTRIBUTE_HEIGHT
,
97 TEXT_ATTRIBUTE_HIDDEN
,
98 TEXT_ATTRIBUTE_KERNING
,
99 TEXT_ATTRIBUTE_LOCALE
,
100 TEXT_ATTRIBUTE_POSTURE
,
101 TEXT_ATTRIBUTE_RELIEF
,
102 TEXT_ATTRIBUTE_ROTATION
,
103 TEXT_ATTRIBUTE_SCALE
,
104 TEXT_ATTRIBUTE_SHADOWED
,
105 TEXT_ATTRIBUTE_STRIKETHROUGH
,
106 TEXT_ATTRIBUTE_UNDERLINE
,
107 TEXT_ATTRIBUTE_WEIGHT
,
108 TEXT_ATTRIBUTE_JUSTIFICATION
,
109 TEXT_ATTRIBUTE_BOTTOM_MARGIN
,
110 TEXT_ATTRIBUTE_FIRST_LINE_INDENT
,
111 TEXT_ATTRIBUTE_LEFT_MARGIN
,
112 TEXT_ATTRIBUTE_LINE_SPACING
,
113 TEXT_ATTRIBUTE_RIGHT_MARGIN
,
114 TEXT_ATTRIBUTE_STYLE_NAME
,
115 TEXT_ATTRIBUTE_TAB_STOPS
,
116 TEXT_ATTRIBUTE_TOP_MARGIN
,
117 TEXT_ATTRIBUTE_WRITING_MODE
,
121 static const char * ExportedTextAttributes
[TEXT_ATTRIBUTE_LAST
] =
123 "CharBackColor", // TEXT_ATTRIBUTE_BACKGROUND_COLOR
124 "CharCaseMap", // TEXT_ATTRIBUTE_CASEMAP
125 "CharColor", // TEXT_ATTRIBUTE_FOREGROUND_COLOR
126 "CharContoured", // TEXT_ATTRIBUTE_CONTOURED
127 "CharEscapement", // TEXT_ATTRIBUTE_CHAR_ESCAPEMENT
128 "CharFlash", // TEXT_ATTRIBUTE_BLINKING
129 "CharFontName", // TEXT_ATTRIBUTE_FONT_NAME
130 "CharHeight", // TEXT_ATTRIBUTE_HEIGHT
131 "CharHidden", // TEXT_ATTRIBUTE_HIDDEN
132 "CharKerning", // TEXT_ATTRIBUTE_KERNING
133 "CharLocale", // TEXT_ATTRIBUTE_LOCALE
134 "CharPosture", // TEXT_ATTRIBUTE_POSTURE
135 "CharRelief", // TEXT_ATTRIBUTE_RELIEF
136 "CharRotation", // TEXT_ATTRIBUTE_ROTATION
137 "CharScaleWidth", // TEXT_ATTRIBUTE_SCALE
138 "CharShadowed", // TEXT_ATTRIBUTE_SHADOWED
139 "CharStrikeout", // TEXT_ATTRIBUTE_STRIKETHROUGH
140 "CharUnderline", // TEXT_ATTRIBUTE_UNDERLINE
141 "CharWeight", // TEXT_ATTRIBUTE_WEIGHT
142 "ParaAdjust", // TEXT_ATTRIBUTE_JUSTIFICATION
143 "ParaBottomMargin", // TEXT_ATTRIBUTE_BOTTOM_MARGIN
144 "ParaFirstLineIndent", // TEXT_ATTRIBUTE_FIRST_LINE_INDENT
145 "ParaLeftMargin", // TEXT_ATTRIBUTE_LEFT_MARGIN
146 "ParaLineSpacing", // TEXT_ATTRIBUTE_LINE_SPACING
147 "ParaRightMargin", // TEXT_ATTRIBUTE_RIGHT_MARGIN
148 "ParaStyleName", // TEXT_ATTRIBUTE_STYLE_NAME
149 "ParaTabStops", // TEXT_ATTRIBUTE_TAB_STOPS
150 "ParaTopMargin", // TEXT_ATTRIBUTE_TOP_MARGIN
151 "WritingMode" // TEXT_ATTRIBUTE_WRITING_MODE
155 /*****************************************************************************/
158 get_value( const uno::Sequence
< beans::PropertyValue
>& rAttributeList
,
159 sal_Int32 nIndex
, AtkTextAttrFunc func
)
162 return func(rAttributeList
[nIndex
].Value
);
167 #define get_bool_value( list, index ) get_value( list, index, Bool2String )
168 #define get_short_value( list, index ) get_value( list, index, Short2String )
169 //#define get_long_value( list, index ) get_value( list, index, Long2String ) pb: not used (warning on linux)
170 #define get_height_value( list, index ) get_value( list, index, Float2String )
171 #define get_justification_value( list, index ) get_value( list, index, Adjust2Justification )
172 #define get_cmm_value( list, index ) get_value( list, index, CMM2UnitString )
173 #define get_scale_width( list, index ) get_value( list, index, Scale2String )
174 #define get_strikethrough_value( list, index ) get_value( list, index, Strikeout2String )
175 #define get_string_value( list, index ) get_value( list, index, GetString )
176 #define get_style_value( list, index ) get_value( list, index, FontSlant2Style )
177 #define get_underline_value( list, index ) get_value( list, index, Underline2String )
178 #define get_variant_value( list, index ) get_value( list, index, CaseMap2String )
179 #define get_weight_value( list, index ) get_value( list, index, Weight2String )
180 #define get_language_string( list, index ) get_value( list, index, Locale2String )
184 dump_value( const uno::Sequence< beans::PropertyValue >& rAttributeList, sal_Int32 nIndex )
188 rtl::OString aName = rtl::OUStringToOString(rAttributeList[nIndex].Name, RTL_TEXTENCODING_UTF8);
190 if( rAttributeList[nIndex].Value.has<sal_Int16> () )
191 OSL_TRACE( "%s = %d (short value)", aName.getStr(),
192 rAttributeList[nIndex].Value.get<sal_Int16> () );
194 else if( rAttributeList[nIndex].Value.has<sal_Int8> () )
195 OSL_TRACE( "%s = %d (byte value)", aName.getStr(),
196 rAttributeList[nIndex].Value.get<sal_Int8> () );
198 else if( rAttributeList[nIndex].Value.has<sal_Bool> () )
199 OSL_TRACE( "%s = %s (bool value)", aName.getStr(),
200 rAttributeList[nIndex].Value.get<sal_Bool> () ? "true" : "false" );
202 else if( rAttributeList[nIndex].Value.has<rtl::OUString> () )
203 OSL_TRACE( "%s = %s", aName.getStr(),
204 rtl::OUStringToOString(rAttributeList[nIndex].Value.get<rtl::OUString> (),
205 RTL_TEXTENCODING_UTF8).getStr() );
213 double toPoint(sal_Int16 n
)
216 return (double) (n
* 72) / 2540;
220 /*****************************************************************************/
224 NullString(const uno::Any&)
231 InvalidValue( uno::Any
&, const gchar
* )
236 /*****************************************************************************/
239 Float2String(const uno::Any
& rAny
)
241 return g_strdup_printf( "%g", rAny
.get
<float>() );
245 String2Float( uno::Any
& rAny
, const gchar
* value
)
249 if( 1 != sscanf( value
, "%g", &fval
) )
252 rAny
= uno::makeAny( fval
);
256 /*****************************************************************************/
260 Short2String(const uno::Any& rAny)
262 return g_strdup_printf( "%d", rAny.get<sal_Int16>() );
266 String2Short( uno::Any& rAny, const gchar * value )
270 if( 1 != sscanf( value, "%d", &lval ) )
273 rAny = uno::makeAny( (sal_Int16) lval );
278 /*****************************************************************************/
279 /* pb: not used (warning on linux)
281 Long2String(const uno::Any& rAny)
283 return g_strdup_printf( "%ld", rAny.get<sal_Int32>() );
287 String2Long( uno::Any& rAny, const gchar * value )
291 if( 1 != sscanf( value, "%ld", &lval ) )
294 rAny = uno::makeAny( lval );
298 /*****************************************************************************/
300 static accessibility::XAccessibleComponent
*
301 getComponent( AtkText
*pText
) throw (uno::RuntimeException
)
303 AtkObjectWrapper
*pWrap
= ATK_OBJECT_WRAPPER( pText
);
306 if( !pWrap
->mpComponent
&& pWrap
->mpContext
)
308 uno::Any any
= pWrap
->mpContext
->queryInterface( accessibility::XAccessibleComponent::static_type(NULL
) );
309 pWrap
->mpComponent
= reinterpret_cast< accessibility::XAccessibleComponent
* > (any
.pReserved
);
310 pWrap
->mpComponent
->acquire();
313 return pWrap
->mpComponent
;
320 get_color_value(const uno::Sequence
< beans::PropertyValue
>& rAttributeList
,
321 const sal_Int32
* pIndexArray
,
322 ExportedAttribute attr
,
325 sal_Int32 nColor
= -1; // AUTOMATIC
326 sal_Int32 nIndex
= pIndexArray
[attr
];
329 nColor
= rAttributeList
[nIndex
].Value
.get
<sal_Int32
>();
332 * Check for color value for 100% alpha white, which means
333 * "automatic". Grab the RGB value from XAccessibleComponent
337 if( (nColor
== -1) && text
)
341 accessibility::XAccessibleComponent
*pComponent
= getComponent( text
);
346 case TEXT_ATTRIBUTE_BACKGROUND_COLOR
:
347 nColor
= pComponent
->getBackground();
349 case TEXT_ATTRIBUTE_FOREGROUND_COLOR
:
350 nColor
= pComponent
->getForeground();
358 catch(const uno::Exception
& e
) {
359 g_warning( "Exception in get[Fore|Back]groundColor()" );
365 sal_uInt8 blue
= nColor
& 0xFF;
366 sal_uInt8 green
= (nColor
>> 8) & 0xFF;
367 sal_uInt8 red
= (nColor
>> 16) & 0xFF;
369 return g_strdup_printf( "%u,%u,%u", red
, green
, blue
);
376 String2Color( uno::Any
& rAny
, const gchar
* value
)
378 int red
, green
, blue
;
380 if( 3 != sscanf( value
, "%d,%d,%d", &red
, &green
, &blue
) )
383 sal_Int32 nColor
= (sal_Int32
) blue
| ( (sal_Int32
) green
<< 8 ) | ( ( sal_Int32
) red
<< 16 );
384 rAny
= uno::makeAny( nColor
);
388 /*****************************************************************************/
391 FontSlant2Style(const uno::Any
& rAny
)
393 const gchar
* value
= NULL
;
395 switch( rAny
.get
<awt::FontSlant
>() )
397 case awt::FontSlant_NONE
:
401 case awt::FontSlant_OBLIQUE
:
405 case awt::FontSlant_ITALIC
:
409 case awt::FontSlant_REVERSE_OBLIQUE
:
410 value
= "reverse oblique";
413 case awt::FontSlant_REVERSE_ITALIC
:
414 value
= "reverse italic";
422 return g_strdup( value
);
428 Style2FontSlant( uno::Any
& rAny
, const gchar
* value
)
430 awt::FontSlant aFontSlant
;
432 if( strncmp( value
, STRNCMP_PARAM( "normal" ) ) )
433 aFontSlant
= awt::FontSlant_NONE
;
434 else if( strncmp( value
, STRNCMP_PARAM( "oblique" ) ) )
435 aFontSlant
= awt::FontSlant_OBLIQUE
;
436 else if( strncmp( value
, STRNCMP_PARAM( "italic" ) ) )
437 aFontSlant
= awt::FontSlant_ITALIC
;
438 else if( strncmp( value
, STRNCMP_PARAM( "reverse oblique" ) ) )
439 aFontSlant
= awt::FontSlant_REVERSE_OBLIQUE
;
440 else if( strncmp( value
, STRNCMP_PARAM( "reverse italic" ) ) )
441 aFontSlant
= awt::FontSlant_REVERSE_ITALIC
;
445 rAny
= uno::makeAny( aFontSlant
);
449 /*****************************************************************************/
452 Weight2String(const uno::Any
& rAny
)
454 return g_strdup_printf( "%g", rAny
.get
<float>() * 4 );
458 String2Weight( uno::Any
& rAny
, const gchar
* value
)
462 if( 1 != sscanf( value
, "%g", &weight
) )
465 rAny
= uno::makeAny( weight
/ 4 );
470 /*****************************************************************************/
473 Adjust2Justification(const uno::Any
& rAny
)
475 const gchar
* value
= NULL
;
477 switch( rAny
.get
<short>() )
479 case style::ParagraphAdjust_LEFT
:
483 case style::ParagraphAdjust_RIGHT
:
487 case style::ParagraphAdjust_BLOCK
:
488 case style::ParagraphAdjust_STRETCH
:
492 case style::ParagraphAdjust_CENTER
:
501 return g_strdup( value
);
507 Justification2Adjust( uno::Any
& rAny
, const gchar
* value
)
509 short nParagraphAdjust
;
511 if( strncmp( value
, STRNCMP_PARAM( "left" ) ) )
512 nParagraphAdjust
= style::ParagraphAdjust_LEFT
;
513 else if( strncmp( value
, STRNCMP_PARAM( "right" ) ) )
514 nParagraphAdjust
= style::ParagraphAdjust_RIGHT
;
515 else if( strncmp( value
, STRNCMP_PARAM( "fill" ) ) )
516 nParagraphAdjust
= style::ParagraphAdjust_BLOCK
;
517 else if( strncmp( value
, STRNCMP_PARAM( "center" ) ) )
518 nParagraphAdjust
= style::ParagraphAdjust_CENTER
;
522 rAny
= uno::makeAny( nParagraphAdjust
);
526 /*****************************************************************************/
528 const gchar
* font_strikethrough
[] = {
529 "none", // FontStrikeout::NONE
530 "single", // FontStrikeout::SINGLE
531 "double", // FontStrikeout::DOUBLE
532 NULL
, // FontStrikeout::DONTKNOW
533 "bold", // FontStrikeout::BOLD
534 "with /", // FontStrikeout::SLASH
535 "with X" // FontStrikeout::X
538 const sal_Int16 n_strikeout_constants
= sizeof(font_strikethrough
) / sizeof(gchar
*);
541 Strikeout2String(const uno::Any
& rAny
)
543 sal_Int16 n
= rAny
.get
<sal_Int16
>();
545 if( n
>= 0 && n
< n_strikeout_constants
)
546 return g_strdup( font_strikethrough
[n
] );
552 String2Strikeout( uno::Any
& rAny
, const gchar
* value
)
554 for( sal_Int16 n
=0; n
< n_strikeout_constants
; ++n
)
556 if( ( NULL
!= font_strikethrough
[n
] ) &&
557 0 == strncmp( value
, font_strikethrough
[n
], strlen( font_strikethrough
[n
] ) ) )
559 rAny
= uno::makeAny( n
);
567 /*****************************************************************************/
570 Underline2String(const uno::Any
& rAny
)
572 const gchar
* value
= NULL
;
574 switch( rAny
.get
<sal_Int16
>() )
576 case awt::FontUnderline::NONE
:
580 case awt::FontUnderline::SINGLE
:
584 case awt::FontUnderline::DOUBLE
:
593 return g_strdup( value
);
599 String2Underline( uno::Any
& rAny
, const gchar
* value
)
603 if( strncmp( value
, STRNCMP_PARAM( "none" ) ) )
604 nUnderline
= awt::FontUnderline::NONE
;
605 else if( strncmp( value
, STRNCMP_PARAM( "single" ) ) )
606 nUnderline
= awt::FontUnderline::SINGLE
;
607 else if( strncmp( value
, STRNCMP_PARAM( "double" ) ) )
608 nUnderline
= awt::FontUnderline::DOUBLE
;
612 rAny
= uno::makeAny( nUnderline
);
616 /*****************************************************************************/
619 GetString(const uno::Any
& rAny
)
621 rtl::OString aFontName
= rtl::OUStringToOString( rAny
.get
< rtl::OUString
> (), RTL_TEXTENCODING_UTF8
);
623 if( aFontName
.getLength() )
624 return g_strdup( aFontName
.getStr() );
630 SetString( uno::Any
& rAny
, const gchar
* value
)
632 rtl::OString
aFontName( value
);
634 if( aFontName
.getLength() )
636 rAny
= uno::makeAny( rtl::OStringToOUString( aFontName
, RTL_TEXTENCODING_UTF8
) );
643 /*****************************************************************************/
645 // @see http://developer.gnome.org/doc/API/2.0/atk/AtkText.html#AtkTextAttribute
649 CMM2UnitString(const uno::Any
& rAny
)
651 double fValue
= rAny
.get
<sal_Int32
>();
652 fValue
= fValue
* 0.01;
654 return g_strdup_printf( "%gmm", fValue
);
658 UnitString2CMM( uno::Any
& rAny
, const gchar
* value
)
660 float fValue
= 0.0; // pb: dont use double here because of warning on linux
662 if( 1 != sscanf( value
, "%gmm", &fValue
) )
665 fValue
= fValue
* 100;
667 rAny
= uno::makeAny( (sal_Int32
) fValue
);
671 /*****************************************************************************/
673 static const gchar
* bool_values
[] = { "true", "false" };
676 Bool2String( const uno::Any
& rAny
)
680 if( rAny
.get
<sal_Bool
>() )
683 return g_strdup( bool_values
[n
] );
687 String2Bool( uno::Any
& rAny
, const gchar
* value
)
691 if( strncmp( value
, STRNCMP_PARAM( "true" ) ) )
693 else if( strncmp( value
, STRNCMP_PARAM( "false" ) ) )
698 rAny
= uno::makeAny(bValue
);
702 /*****************************************************************************/
705 Scale2String( const uno::Any
& rAny
)
707 return g_strdup_printf( "%g", (double) (rAny
.get
< sal_Int16
> ()) / 100 );
711 String2Scale( uno::Any
& rAny
, const gchar
* value
)
715 if( 1 != sscanf( value
, "%lg", &dval
) )
718 rAny
= uno::makeAny((sal_Int16
) (dval
* 100));
722 /*****************************************************************************/
725 CaseMap2String( const uno::Any
& rAny
)
727 const gchar
* value
= NULL
;
729 switch( rAny
.get
<short>() )
731 case style::CaseMap::SMALLCAPS
:
732 value
= "small_caps";
741 return g_strdup( value
);
747 String2CaseMap( uno::Any
& rAny
, const gchar
* value
)
751 if( strncmp( value
, STRNCMP_PARAM( "normal" ) ) )
752 nCaseMap
= style::CaseMap::NONE
;
753 else if( strncmp( value
, STRNCMP_PARAM( "small_caps" ) ) )
754 nCaseMap
= style::CaseMap::SMALLCAPS
;
758 rAny
= uno::makeAny( nCaseMap
);
762 /*****************************************************************************/
764 const gchar
* font_stretch
[] = {
777 Kerning2Stretch(const uno::Any
& rAny
)
779 sal_Int16 n
= rAny
.get
<sal_Int16
>();
782 // No good idea for a mapping - just return the basic info
788 return g_strdup(font_stretch
[i
]);
791 /*****************************************************************************/
794 Locale2String(const uno::Any
& rAny
)
796 lang::Locale aLocale
= rAny
.get
<lang::Locale
> ();
797 return g_strdup_printf( "%s-%s",
798 rtl::OUStringToOString( aLocale
.Language
, RTL_TEXTENCODING_ASCII_US
).getStr(),
799 rtl::OUStringToOString( aLocale
.Country
, RTL_TEXTENCODING_ASCII_US
).toAsciiLowerCase().getStr() );
803 String2Locale( uno::Any
& rAny
, const gchar
* value
)
807 gchar
** str_array
= g_strsplit_set( value
, "-.@", -1 );
808 if( str_array
[0] != NULL
)
812 lang::Locale aLocale
;
814 aLocale
.Language
= rtl::OUString::createFromAscii(str_array
[0]);
815 if( str_array
[1] != NULL
)
817 gchar
* country
= g_ascii_strup(str_array
[1], -1);
818 aLocale
.Country
= rtl::OUString::createFromAscii(country
);
822 rAny
= uno::makeAny(aLocale
);
825 g_strfreev(str_array
);
829 /*****************************************************************************/
831 // @see http://www.w3.org/TR/2002/WD-css3-fonts-20020802/#font-effect-prop
832 static const gchar
* relief
[] = { "none", "emboss", "engrave" };
833 static const gchar
* outline
= "outline";
836 get_font_effect(const uno::Sequence
< beans::PropertyValue
>& rAttributeList
,
837 sal_Int32 nContourIndex
, sal_Int32 nReliefIndex
)
839 if( nContourIndex
!= -1 )
841 if( rAttributeList
[nContourIndex
].Value
.get
<sal_Bool
>() )
842 return g_strdup(outline
);
845 if( nReliefIndex
!= -1 )
847 sal_Int16 n
= rAttributeList
[nReliefIndex
].Value
.get
<sal_Int16
>();
849 return g_strdup(relief
[n
]);
855 /*****************************************************************************/
857 // @see http://www.w3.org/TR/REC-CSS2/text.html#lining-striking-props
864 DECORATION_UNDERLINE
,
865 DECORATION_LINE_THROUGH
869 static const gchar
* decorations
[] = { "none", "blink", "underline", "line-through" };
872 get_text_decoration(const uno::Sequence
< beans::PropertyValue
>& rAttributeList
,
873 sal_Int32 nBlinkIndex
, sal_Int32 nUnderlineIndex
,
874 sal_Int16 nStrikeoutIndex
)
876 gchar
* value_list
[4] = { NULL
, NULL
, NULL
, NULL
};
879 // no property value found
880 if( ( nBlinkIndex
== -1 ) && (nUnderlineIndex
== -1 ) && (nStrikeoutIndex
== -1))
883 if( nBlinkIndex
!= -1 )
885 if( rAttributeList
[nBlinkIndex
].Value
.get
<sal_Bool
>() )
886 value_list
[count
++] = const_cast <gchar
*> (decorations
[DECORATION_BLINK
]);
888 if( nUnderlineIndex
!= -1 )
890 sal_Int16 n
= rAttributeList
[nUnderlineIndex
].Value
.get
<sal_Int16
> ();
891 if( n
!= awt::FontUnderline::NONE
)
892 value_list
[count
++] = const_cast <gchar
*> (decorations
[DECORATION_UNDERLINE
]);
894 if( nStrikeoutIndex
!= -1 )
896 sal_Int16 n
= rAttributeList
[nStrikeoutIndex
].Value
.get
<sal_Int16
> ();
897 if( n
!= awt::FontStrikeout::NONE
&& n
!= awt::FontStrikeout::DONTKNOW
)
898 value_list
[count
++] = const_cast <gchar
*> (decorations
[DECORATION_LINE_THROUGH
]);
902 value_list
[count
++] = const_cast <gchar
*> (decorations
[DECORATION_NONE
]);
904 return g_strjoinv(" ", value_list
);
908 /*****************************************************************************/
910 // @see http://www.w3.org/TR/REC-CSS2/text.html#propdef-text-shadow
912 static const gchar
* shadow_values
[] = { "none", "black" };
915 Bool2Shadow( const uno::Any
& rAny
)
919 if( rAny
.get
<sal_Bool
>() )
922 return g_strdup( shadow_values
[n
] );
925 /*****************************************************************************/
928 Short2Degree( const uno::Any
& rAny
)
930 float f
= rAny
.get
<sal_Int16
>() / 10;
931 return g_strdup_printf( "%g", f
);
934 /*****************************************************************************/
936 const gchar
* directions
[] = { "ltr", "rtl", "rtl", "ltr", "none" };
939 WritingMode2Direction( const uno::Any
& rAny
)
941 sal_Int16 n
= rAny
.get
<sal_Int16
>();
943 if( 0 <= n
&& n
<= text::WritingMode2::PAGE
)
944 return g_strdup(directions
[n
]);
949 // @see http://www.w3.org/TR/2001/WD-css3-text-20010517/#PrimaryTextAdvanceDirection
951 const gchar
* writing_modes
[] = { "lr-tb", "rl-tb", "tb-rl", "tb-lr", "none" };
953 WritingMode2String( const uno::Any
& rAny
)
955 sal_Int16 n
= rAny
.get
<sal_Int16
>();
957 if( 0 <= n
&& n
<= text::WritingMode2::PAGE
)
958 return g_strdup(writing_modes
[n
]);
963 /*****************************************************************************/
965 const char * baseline_values
[] = { "baseline", "sub", "super" };
967 // @see http://www.w3.org/TR/REC-CSS2/visudet.html#propdef-vertical-align
969 Escapement2VerticalAlign( const uno::Any
& rAny
)
971 sal_Int16 n
= rAny
.get
<sal_Int16
>();
974 // Values are in %, 101% means "automatic"
976 ret
= g_strdup(baseline_values
[0]);
978 ret
= g_strdup(baseline_values
[2]);
980 ret
= g_strdup(baseline_values
[1]);
982 ret
= g_strdup_printf( "%d%%", n
);
987 /*****************************************************************************/
989 // @see http://www.w3.org/TR/REC-CSS2/visudet.html#propdef-line-height
991 LineSpacing2LineHeight( const uno::Any
& rAny
)
993 style::LineSpacing ls
;
998 if( ls
.Mode
== style::LineSpacingMode::PROP
)
999 ret
= g_strdup_printf( "%d%%", ls
.Height
);
1000 else if( ls
.Mode
== style::LineSpacingMode::FIX
)
1001 ret
= g_strdup_printf( "%.3gpt", toPoint(ls
.Height
) );
1007 /*****************************************************************************/
1009 // @see http://www.w3.org/People/howcome/t/970224HTMLERB-CSS/WD-tabs-970117.html
1011 TabStopList2String( const uno::Any
& rAny
, bool default_tabs
)
1013 uno::Sequence
< style::TabStop
> theTabStops
;
1016 if( rAny
>>= theTabStops
)
1018 sal_Int32 indexOfTab
= 0;
1019 sal_Int32 numberOfTabs
= theTabStops
.getLength();
1020 sal_Unicode lastFillChar
= (sal_Unicode
) ' ';
1022 for( ; indexOfTab
< numberOfTabs
; ++indexOfTab
)
1024 bool is_default_tab
= (style::TabAlign_DEFAULT
== theTabStops
[indexOfTab
].Alignment
);
1026 if( is_default_tab
!= default_tabs
)
1029 double fValue
= theTabStops
[indexOfTab
].Position
;
1030 fValue
= fValue
* 0.01;
1032 const gchar
* tab_align
= "";
1033 switch( theTabStops
[indexOfTab
].Alignment
)
1035 case style::TabAlign_LEFT
:
1036 tab_align
= "left ";
1038 case style::TabAlign_CENTER
:
1039 tab_align
= "center ";
1041 case style::TabAlign_RIGHT
:
1042 tab_align
= "right ";
1044 case style::TabAlign_DECIMAL
:
1045 tab_align
= "decimal ";
1051 const gchar
* lead_char
= "";
1053 if( theTabStops
[indexOfTab
].FillChar
!= lastFillChar
)
1055 lastFillChar
= theTabStops
[indexOfTab
].FillChar
;
1056 switch (lastFillChar
)
1058 case (sal_Unicode
) ' ':
1059 lead_char
= "blank ";
1062 case (sal_Unicode
) '.':
1063 lead_char
= "dotted ";
1066 case (sal_Unicode
) '-':
1067 lead_char
= "dashed ";
1070 case (sal_Unicode
) '_':
1071 lead_char
= "lined ";
1075 lead_char
= "custom ";
1080 gchar
* tab_str
= g_strdup_printf( "%s%s%gmm", lead_char
, tab_align
, fValue
);
1084 gchar
* old_tab_str
= ret
;
1085 ret
= g_strconcat(old_tab_str
, " ", tab_str
, NULL
/* terminated */);
1086 g_free( old_tab_str
);
1097 TabStops2String( const uno::Any
& rAny
)
1099 return TabStopList2String(rAny
, false);
1103 DefaultTabStops2String( const uno::Any
& rAny
)
1105 return TabStopList2String(rAny
, true);
1108 /*****************************************************************************/
1111 attr_compare(const void *p1
,const void *p2
)
1113 const rtl_uString
* pustr
= (const rtl_uString
*) p1
;
1114 const char * pc
= *((const char **) p2
);
1116 return rtl_ustr_ascii_compare_WithLength(pustr
->buffer
, pustr
->length
, pc
);
1120 find_exported_attributes( sal_Int32
*pArray
,
1121 const com::sun::star::uno::Sequence
< com::sun::star::beans::PropertyValue
>& rAttributeList
)
1123 for( sal_Int32 i
= 0; i
< rAttributeList
.getLength(); i
++ )
1125 const char ** pAttr
= (const char **) bsearch(rAttributeList
[i
].Name
.pData
,
1126 ExportedTextAttributes
, TEXT_ATTRIBUTE_LAST
, sizeof(const char *),
1131 sal_Int32 nIndex
= pAttr
- ExportedTextAttributes
;
1137 /*****************************************************************************/
1139 static AtkAttributeSet
*
1140 attribute_set_prepend( AtkAttributeSet
* attribute_set
,
1141 AtkTextAttribute attribute
,
1146 AtkAttribute
*at
= (AtkAttribute
*) g_malloc( sizeof (AtkAttribute
) );
1147 at
->name
= g_strdup( atk_text_attribute_get_name( attribute
) );
1150 return g_slist_prepend(attribute_set
, at
);
1153 return attribute_set
;
1156 /*****************************************************************************/
1159 attribute_set_new_from_property_values(
1160 const uno::Sequence
< beans::PropertyValue
>& rAttributeList
,
1161 bool run_attributes_only
,
1164 AtkAttributeSet
* attribute_set
= NULL
;
1166 sal_Int32 aIndexList
[TEXT_ATTRIBUTE_LAST
] = { -1 };
1168 // Initialize index array with -1
1169 for( sal_Int32 attr
= 0; attr
< TEXT_ATTRIBUTE_LAST
; ++attr
)
1170 aIndexList
[attr
] = -1;
1172 find_exported_attributes(aIndexList
, rAttributeList
);
1174 attribute_set
= attribute_set_prepend(attribute_set
, ATK_TEXT_ATTR_BG_COLOR
,
1175 get_color_value(rAttributeList
, aIndexList
, TEXT_ATTRIBUTE_BACKGROUND_COLOR
, run_attributes_only
? NULL
: text
) );
1177 attribute_set
= attribute_set_prepend(attribute_set
, ATK_TEXT_ATTR_FG_COLOR
,
1178 get_color_value(rAttributeList
, aIndexList
, TEXT_ATTRIBUTE_FOREGROUND_COLOR
, run_attributes_only
? NULL
: text
) );
1180 attribute_set
= attribute_set_prepend(attribute_set
, ATK_TEXT_ATTR_INVISIBLE
,
1181 get_bool_value(rAttributeList
, aIndexList
[TEXT_ATTRIBUTE_HIDDEN
]));
1183 attribute_set
= attribute_set_prepend(attribute_set
, ATK_TEXT_ATTR_UNDERLINE
,
1184 get_underline_value(rAttributeList
, aIndexList
[TEXT_ATTRIBUTE_UNDERLINE
]));
1186 attribute_set
= attribute_set_prepend(attribute_set
, ATK_TEXT_ATTR_STRIKETHROUGH
,
1187 get_strikethrough_value(rAttributeList
, aIndexList
[TEXT_ATTRIBUTE_STRIKETHROUGH
]));
1189 attribute_set
= attribute_set_prepend(attribute_set
, ATK_TEXT_ATTR_SIZE
,
1190 get_height_value(rAttributeList
, aIndexList
[TEXT_ATTRIBUTE_HEIGHT
]));
1192 attribute_set
= attribute_set_prepend(attribute_set
, ATK_TEXT_ATTR_WEIGHT
,
1193 get_weight_value(rAttributeList
, aIndexList
[TEXT_ATTRIBUTE_WEIGHT
]));
1195 attribute_set
= attribute_set_prepend(attribute_set
, ATK_TEXT_ATTR_FAMILY_NAME
,
1196 get_string_value(rAttributeList
, aIndexList
[TEXT_ATTRIBUTE_FONT_NAME
]));
1198 attribute_set
= attribute_set_prepend(attribute_set
, ATK_TEXT_ATTR_VARIANT
,
1199 get_variant_value(rAttributeList
, aIndexList
[TEXT_ATTRIBUTE_CASEMAP
]));
1201 attribute_set
= attribute_set_prepend(attribute_set
, ATK_TEXT_ATTR_STYLE
,
1202 get_style_value(rAttributeList
, aIndexList
[TEXT_ATTRIBUTE_POSTURE
]));
1204 attribute_set
= attribute_set_prepend(attribute_set
, ATK_TEXT_ATTR_SCALE
,
1205 get_scale_width(rAttributeList
, aIndexList
[TEXT_ATTRIBUTE_SCALE
]));
1207 attribute_set
= attribute_set_prepend(attribute_set
, ATK_TEXT_ATTR_LANGUAGE
,
1208 get_language_string(rAttributeList
, aIndexList
[TEXT_ATTRIBUTE_LOCALE
]));
1210 attribute_set
= attribute_set_prepend(attribute_set
, ATK_TEXT_ATTR_DIRECTION
,
1211 get_value(rAttributeList
, aIndexList
[TEXT_ATTRIBUTE_WRITING_MODE
], WritingMode2Direction
));
1213 attribute_set
= attribute_set_prepend(attribute_set
, ATK_TEXT_ATTR_STRETCH
,
1214 get_value(rAttributeList
, aIndexList
[TEXT_ATTRIBUTE_KERNING
], Kerning2Stretch
));
1216 if( ATK_TEXT_ATTR_INVALID
== atk_text_attribute_font_effect
)
1217 atk_text_attribute_font_effect
= atk_text_attribute_register("font-effect");
1219 attribute_set
= attribute_set_prepend(attribute_set
, atk_text_attribute_font_effect
,
1220 get_font_effect(rAttributeList
, aIndexList
[TEXT_ATTRIBUTE_CONTOURED
], aIndexList
[TEXT_ATTRIBUTE_RELIEF
]));
1222 if( ATK_TEXT_ATTR_INVALID
== atk_text_attribute_decoration
)
1223 atk_text_attribute_decoration
= atk_text_attribute_register("text-decoration");
1225 attribute_set
= attribute_set_prepend(attribute_set
, atk_text_attribute_decoration
,
1226 get_text_decoration(rAttributeList
, aIndexList
[TEXT_ATTRIBUTE_BLINKING
],
1227 aIndexList
[TEXT_ATTRIBUTE_UNDERLINE
], aIndexList
[TEXT_ATTRIBUTE_STRIKETHROUGH
]));
1229 if( ATK_TEXT_ATTR_INVALID
== atk_text_attribute_rotation
)
1230 atk_text_attribute_rotation
= atk_text_attribute_register("text-rotation");
1232 attribute_set
= attribute_set_prepend(attribute_set
, atk_text_attribute_rotation
,
1233 get_value(rAttributeList
, aIndexList
[TEXT_ATTRIBUTE_ROTATION
], Short2Degree
));
1235 if( ATK_TEXT_ATTR_INVALID
== atk_text_attribute_shadow
)
1236 atk_text_attribute_shadow
= atk_text_attribute_register("text-shadow");
1238 attribute_set
= attribute_set_prepend(attribute_set
, atk_text_attribute_shadow
,
1239 get_value(rAttributeList
, aIndexList
[TEXT_ATTRIBUTE_SHADOWED
], Bool2Shadow
));
1241 if( ATK_TEXT_ATTR_INVALID
== atk_text_attribute_writing_mode
)
1242 atk_text_attribute_writing_mode
= atk_text_attribute_register("writing-mode");
1244 attribute_set
= attribute_set_prepend(attribute_set
, atk_text_attribute_writing_mode
,
1245 get_value(rAttributeList
, aIndexList
[TEXT_ATTRIBUTE_WRITING_MODE
], WritingMode2String
));
1247 if( ATK_TEXT_ATTR_INVALID
== atk_text_attribute_vertical_align
)
1248 atk_text_attribute_vertical_align
= atk_text_attribute_register("vertical-align");
1250 attribute_set
= attribute_set_prepend(attribute_set
, atk_text_attribute_vertical_align
,
1251 get_value(rAttributeList
, aIndexList
[TEXT_ATTRIBUTE_CHAR_ESCAPEMENT
], Escapement2VerticalAlign
));
1253 if( run_attributes_only
)
1254 return attribute_set
;
1256 attribute_set
= attribute_set_prepend(attribute_set
, ATK_TEXT_ATTR_LEFT_MARGIN
,
1257 get_cmm_value(rAttributeList
, aIndexList
[TEXT_ATTRIBUTE_LEFT_MARGIN
]));
1259 attribute_set
= attribute_set_prepend(attribute_set
, ATK_TEXT_ATTR_RIGHT_MARGIN
,
1260 get_cmm_value(rAttributeList
, aIndexList
[TEXT_ATTRIBUTE_RIGHT_MARGIN
]));
1262 attribute_set
= attribute_set_prepend(attribute_set
, ATK_TEXT_ATTR_INDENT
,
1263 get_cmm_value(rAttributeList
, aIndexList
[TEXT_ATTRIBUTE_FIRST_LINE_INDENT
]));
1265 attribute_set
= attribute_set_prepend(attribute_set
, ATK_TEXT_ATTR_PIXELS_ABOVE_LINES
,
1266 get_cmm_value(rAttributeList
, aIndexList
[TEXT_ATTRIBUTE_TOP_MARGIN
]));
1268 attribute_set
= attribute_set_prepend(attribute_set
, ATK_TEXT_ATTR_PIXELS_BELOW_LINES
,
1269 get_cmm_value(rAttributeList
, aIndexList
[TEXT_ATTRIBUTE_BOTTOM_MARGIN
]));
1271 attribute_set
= attribute_set_prepend(attribute_set
, ATK_TEXT_ATTR_JUSTIFICATION
,
1272 get_justification_value(rAttributeList
, aIndexList
[TEXT_ATTRIBUTE_JUSTIFICATION
]));
1274 if( ATK_TEXT_ATTR_INVALID
== atk_text_attribute_paragraph_style
)
1275 atk_text_attribute_paragraph_style
= atk_text_attribute_register("paragraph-style");
1277 attribute_set
= attribute_set_prepend(attribute_set
, atk_text_attribute_paragraph_style
,
1278 get_string_value(rAttributeList
, aIndexList
[TEXT_ATTRIBUTE_STYLE_NAME
]));
1280 if( ATK_TEXT_ATTR_INVALID
== atk_text_attribute_line_height
)
1281 atk_text_attribute_line_height
= atk_text_attribute_register("line-height");
1283 attribute_set
= attribute_set_prepend(attribute_set
, atk_text_attribute_line_height
,
1284 get_value(rAttributeList
, aIndexList
[TEXT_ATTRIBUTE_LINE_SPACING
], LineSpacing2LineHeight
));
1286 if( ATK_TEXT_ATTR_INVALID
== atk_text_attribute_tab_interval
)
1287 atk_text_attribute_tab_interval
= atk_text_attribute_register("tab-interval");
1289 attribute_set
= attribute_set_prepend(attribute_set
, atk_text_attribute_tab_interval
,
1290 get_value(rAttributeList
, aIndexList
[TEXT_ATTRIBUTE_TAB_STOPS
], DefaultTabStops2String
));
1292 if( ATK_TEXT_ATTR_INVALID
== atk_text_attribute_tab_stops
)
1293 atk_text_attribute_tab_stops
= atk_text_attribute_register("tab-stops");
1295 attribute_set
= attribute_set_prepend(attribute_set
, atk_text_attribute_tab_stops
,
1296 get_value(rAttributeList
, aIndexList
[TEXT_ATTRIBUTE_TAB_STOPS
], TabStops2String
));
1298 return attribute_set
;
1302 /*****************************************************************************/
1304 struct AtkTextAttrMapping
1307 TextPropertyValueFunc toPropertyValue
;
1310 const AtkTextAttrMapping g_TextAttrMap
[] =
1312 { "", InvalidValue
}, // ATK_TEXT_ATTR_INVALID = 0
1313 { "ParaLeftMargin", UnitString2CMM
}, // ATK_TEXT_ATTR_LEFT_MARGIN
1314 { "ParaRightMargin", UnitString2CMM
}, // ATK_TEXT_ATTR_RIGHT_MARGIN
1315 { "ParaFirstLineIndent", UnitString2CMM
}, // ATK_TEXT_ATTR_INDENT
1316 { "CharHidden", String2Bool
}, // ATK_TEXT_ATTR_INVISIBLE
1317 { "", InvalidValue
}, // ATK_TEXT_ATTR_EDITABLE
1318 { "ParaTopMargin", UnitString2CMM
}, // ATK_TEXT_ATTR_PIXELS_ABOVE_LINES
1319 { "ParaBottomMargin", UnitString2CMM
}, // ATK_TEXT_ATTR_PIXELS_BELOW_LINES
1320 { "", InvalidValue
}, // ATK_TEXT_ATTR_PIXELS_INSIDE_WRAP
1321 { "", InvalidValue
}, // ATK_TEXT_ATTR_BG_FULL_HEIGHT
1322 { "", InvalidValue
}, // ATK_TEXT_ATTR_RISE
1323 { "CharUnderline", String2Underline
}, // ATK_TEXT_ATTR_UNDERLINE
1324 { "CharStrikeout", String2Strikeout
}, // ATK_TEXT_ATTR_STRIKETHROUGH
1325 { "CharHeight", String2Float
}, // ATK_TEXT_ATTR_SIZE
1326 { "CharScaleWidth", String2Scale
}, // ATK_TEXT_ATTR_SCALE
1327 { "CharWeight", String2Weight
}, // ATK_TEXT_ATTR_WEIGHT
1328 { "CharLocale", String2Locale
}, // ATK_TEXT_ATTR_LANGUAGE
1329 { "CharFontName", SetString
}, // ATK_TEXT_ATTR_FAMILY_NAME
1330 { "CharBackColor", String2Color
}, // ATK_TEXT_ATTR_BG_COLOR
1331 { "CharColor", String2Color
}, // ATK_TEXT_ATTR_FG_COLOR
1332 { "", InvalidValue
}, // ATK_TEXT_ATTR_BG_STIPPLE
1333 { "", InvalidValue
}, // ATK_TEXT_ATTR_FG_STIPPLE
1334 { "", InvalidValue
}, // ATK_TEXT_ATTR_WRAP_MODE
1335 { "", InvalidValue
}, // ATK_TEXT_ATTR_DIRECTION
1336 { "ParaAdjust", Justification2Adjust
}, // ATK_TEXT_ATTR_JUSTIFICATION
1337 { "", InvalidValue
}, // ATK_TEXT_ATTR_STRETCH
1338 { "CharCaseMap", String2CaseMap
}, // ATK_TEXT_ATTR_VARIANT
1339 { "CharPosture", Style2FontSlant
} // ATK_TEXT_ATTR_STYLE
1342 static const sal_Int32 g_TextAttrMapSize
= sizeof( g_TextAttrMap
) / sizeof( AtkTextAttrMapping
);
1344 /*****************************************************************************/
1347 attribute_set_map_to_property_values(
1348 AtkAttributeSet
* attribute_set
,
1349 uno::Sequence
< beans::PropertyValue
>& rValueList
)
1351 // Ensure enough space ..
1352 uno::Sequence
< beans::PropertyValue
> aAttributeList (g_TextAttrMapSize
);
1354 sal_Int32 nIndex
= 0;
1355 for( GSList
* item
= attribute_set
; item
!= NULL
; item
= g_slist_next( item
) )
1357 AtkAttribute
* attribute
= (AtkAttribute
*) item
;
1359 AtkTextAttribute text_attr
= atk_text_attribute_for_name( attribute
->name
);
1360 if( text_attr
< g_TextAttrMapSize
)
1362 if( g_TextAttrMap
[text_attr
].name
[0] != '\0' )
1364 if( ! g_TextAttrMap
[text_attr
].toPropertyValue( aAttributeList
[nIndex
].Value
, attribute
->value
) )
1367 aAttributeList
[nIndex
].Name
= rtl::OUString::createFromAscii( g_TextAttrMap
[text_attr
].name
);
1368 aAttributeList
[nIndex
].State
= beans::PropertyState_DIRECT_VALUE
;
1374 // Unsupported text attribute
1379 aAttributeList
.realloc( nIndex
);
1380 rValueList
= aAttributeList
;