bump product version to 5.0.4.1
[LibreOffice.git] / vcl / unx / gtk / a11y / atktextattributes.cxx
blob283ff59db9e89af17470db588730b67ceda314be
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "atktextattributes.hxx"
22 #include <com/sun/star/awt/FontSlant.hpp>
23 #include <com/sun/star/awt/FontStrikeout.hpp>
24 #include <com/sun/star/awt/FontUnderline.hpp>
26 #include <com/sun/star/style/CaseMap.hpp>
27 #include <com/sun/star/style/LineSpacing.hpp>
28 #include <com/sun/star/style/LineSpacingMode.hpp>
29 #include <com/sun/star/style/ParagraphAdjust.hpp>
30 #include <com/sun/star/style/TabAlign.hpp>
31 #include <com/sun/star/style/TabStop.hpp>
33 #include <com/sun/star/text/WritingMode2.hpp>
35 #include "atkwrapper.hxx"
37 #include <com/sun/star/accessibility/XAccessibleComponent.hpp>
39 #include <vcl/svapp.hxx>
40 #include <vcl/outdev.hxx>
42 #include <stdio.h>
43 #include <string.h>
45 using namespace ::com::sun::star;
47 typedef gchar* (* AtkTextAttrFunc) ( const uno::Any& rAny );
48 typedef bool (* TextPropertyValueFunc) ( uno::Any& rAny, const gchar * value );
50 #define STRNCMP_PARAM( s ) s,sizeof( s )-1
52 /*****************************************************************************/
54 static AtkTextAttribute atk_text_attribute_paragraph_style = ATK_TEXT_ATTR_INVALID;
55 static AtkTextAttribute atk_text_attribute_font_effect = ATK_TEXT_ATTR_INVALID;
56 static AtkTextAttribute atk_text_attribute_decoration = ATK_TEXT_ATTR_INVALID;
57 static AtkTextAttribute atk_text_attribute_line_height = ATK_TEXT_ATTR_INVALID;
58 static AtkTextAttribute atk_text_attribute_rotation = ATK_TEXT_ATTR_INVALID;
59 static AtkTextAttribute atk_text_attribute_shadow = ATK_TEXT_ATTR_INVALID;
60 static AtkTextAttribute atk_text_attribute_tab_interval = ATK_TEXT_ATTR_INVALID;
61 static AtkTextAttribute atk_text_attribute_tab_stops = ATK_TEXT_ATTR_INVALID;
62 static AtkTextAttribute atk_text_attribute_writing_mode = ATK_TEXT_ATTR_INVALID;
63 static AtkTextAttribute atk_text_attribute_vertical_align = ATK_TEXT_ATTR_INVALID;
64 static AtkTextAttribute atk_text_attribute_misspelled = ATK_TEXT_ATTR_INVALID;
65 // #i92232#
66 static AtkTextAttribute atk_text_attribute_tracked_change = ATK_TEXT_ATTR_INVALID;
67 // #i92233#
68 static AtkTextAttribute atk_text_attribute_mm_to_pixel_ratio = ATK_TEXT_ATTR_INVALID;
70 /*****************************************************************************/
72 /**
73 * !! IMPORTANT NOTE !! : when adding items to this list, KEEP THE LIST SORTED
74 * and re-arrange the enum values accordingly.
77 enum ExportedAttribute
79 TEXT_ATTRIBUTE_BACKGROUND_COLOR = 0,
80 TEXT_ATTRIBUTE_CASEMAP,
81 TEXT_ATTRIBUTE_FOREGROUND_COLOR,
82 TEXT_ATTRIBUTE_CONTOURED,
83 TEXT_ATTRIBUTE_CHAR_ESCAPEMENT,
84 TEXT_ATTRIBUTE_BLINKING,
85 TEXT_ATTRIBUTE_FONT_NAME,
86 TEXT_ATTRIBUTE_HEIGHT,
87 TEXT_ATTRIBUTE_HIDDEN,
88 TEXT_ATTRIBUTE_KERNING,
89 TEXT_ATTRIBUTE_LOCALE,
90 TEXT_ATTRIBUTE_POSTURE,
91 TEXT_ATTRIBUTE_RELIEF,
92 TEXT_ATTRIBUTE_ROTATION,
93 TEXT_ATTRIBUTE_SCALE,
94 TEXT_ATTRIBUTE_SHADOWED,
95 TEXT_ATTRIBUTE_STRIKETHROUGH,
96 TEXT_ATTRIBUTE_UNDERLINE,
97 TEXT_ATTRIBUTE_WEIGHT,
98 // #i92233#
99 TEXT_ATTRIBUTE_MM_TO_PIXEL_RATIO,
100 TEXT_ATTRIBUTE_JUSTIFICATION,
101 TEXT_ATTRIBUTE_BOTTOM_MARGIN,
102 TEXT_ATTRIBUTE_FIRST_LINE_INDENT,
103 TEXT_ATTRIBUTE_LEFT_MARGIN,
104 TEXT_ATTRIBUTE_LINE_SPACING,
105 TEXT_ATTRIBUTE_RIGHT_MARGIN,
106 TEXT_ATTRIBUTE_STYLE_NAME,
107 TEXT_ATTRIBUTE_TAB_STOPS,
108 TEXT_ATTRIBUTE_TOP_MARGIN,
109 TEXT_ATTRIBUTE_WRITING_MODE,
110 TEXT_ATTRIBUTE_LAST
113 static const char * ExportedTextAttributes[TEXT_ATTRIBUTE_LAST] =
115 "CharBackColor", // TEXT_ATTRIBUTE_BACKGROUND_COLOR
116 "CharCaseMap", // TEXT_ATTRIBUTE_CASEMAP
117 "CharColor", // TEXT_ATTRIBUTE_FOREGROUND_COLOR
118 "CharContoured", // TEXT_ATTRIBUTE_CONTOURED
119 "CharEscapement", // TEXT_ATTRIBUTE_CHAR_ESCAPEMENT
120 "CharFlash", // TEXT_ATTRIBUTE_BLINKING
121 "CharFontName", // TEXT_ATTRIBUTE_FONT_NAME
122 "CharHeight", // TEXT_ATTRIBUTE_HEIGHT
123 "CharHidden", // TEXT_ATTRIBUTE_HIDDEN
124 "CharKerning", // TEXT_ATTRIBUTE_KERNING
125 "CharLocale", // TEXT_ATTRIBUTE_LOCALE
126 "CharPosture", // TEXT_ATTRIBUTE_POSTURE
127 "CharRelief", // TEXT_ATTRIBUTE_RELIEF
128 "CharRotation", // TEXT_ATTRIBUTE_ROTATION
129 "CharScaleWidth", // TEXT_ATTRIBUTE_SCALE
130 "CharShadowed", // TEXT_ATTRIBUTE_SHADOWED
131 "CharStrikeout", // TEXT_ATTRIBUTE_STRIKETHROUGH
132 "CharUnderline", // TEXT_ATTRIBUTE_UNDERLINE
133 "CharWeight", // TEXT_ATTRIBUTE_WEIGHT
134 // #i92233#
135 "MMToPixelRatio", // TEXT_ATTRIBUTE_MM_TO_PIXEL_RATIO
136 "ParaAdjust", // TEXT_ATTRIBUTE_JUSTIFICATION
137 "ParaBottomMargin", // TEXT_ATTRIBUTE_BOTTOM_MARGIN
138 "ParaFirstLineIndent", // TEXT_ATTRIBUTE_FIRST_LINE_INDENT
139 "ParaLeftMargin", // TEXT_ATTRIBUTE_LEFT_MARGIN
140 "ParaLineSpacing", // TEXT_ATTRIBUTE_LINE_SPACING
141 "ParaRightMargin", // TEXT_ATTRIBUTE_RIGHT_MARGIN
142 "ParaStyleName", // TEXT_ATTRIBUTE_STYLE_NAME
143 "ParaTabStops", // TEXT_ATTRIBUTE_TAB_STOPS
144 "ParaTopMargin", // TEXT_ATTRIBUTE_TOP_MARGIN
145 "WritingMode" // TEXT_ATTRIBUTE_WRITING_MODE
148 /*****************************************************************************/
150 static gchar*
151 get_value( const uno::Sequence< beans::PropertyValue >& rAttributeList,
152 sal_Int32 nIndex, AtkTextAttrFunc func )
154 if( nIndex != -1 )
155 return func(rAttributeList[nIndex].Value);
157 return NULL;
160 #define get_bool_value( list, index ) get_value( list, index, Bool2String )
161 #define get_height_value( list, index ) get_value( list, index, Float2String )
162 #define get_justification_value( list, index ) get_value( list, index, Adjust2Justification )
163 #define get_cmm_value( list, index ) get_value( list, index, CMM2UnitString )
164 #define get_scale_width( list, index ) get_value( list, index, Scale2String )
165 #define get_strikethrough_value( list, index ) get_value( list, index, Strikeout2String )
166 #define get_string_value( list, index ) get_value( list, index, GetString )
167 #define get_style_value( list, index ) get_value( list, index, FontSlant2Style )
168 #define get_underline_value( list, index ) get_value( list, index, Underline2String )
169 #define get_variant_value( list, index ) get_value( list, index, CaseMap2String )
170 #define get_weight_value( list, index ) get_value( list, index, Weight2String )
171 #define get_language_string( list, index ) get_value( list, index, Locale2String )
173 static inline
174 double toPoint(sal_Int16 n)
176 // 100th mm -> pt
177 return (double) (n * 72) / 2540;
180 /*****************************************************************************/
182 static bool
183 InvalidValue( uno::Any&, const gchar * )
185 return false;
188 /*****************************************************************************/
190 static gchar*
191 Float2String(const uno::Any& rAny)
193 return g_strdup_printf( "%g", rAny.get<float>() );
196 static bool
197 String2Float( uno::Any& rAny, const gchar * value )
199 float fval;
201 if( 1 != sscanf( value, "%g", &fval ) )
202 return false;
204 rAny = uno::makeAny( fval );
205 return true;
208 /*****************************************************************************/
210 static accessibility::XAccessibleComponent*
211 getComponent( AtkText *pText ) throw (uno::RuntimeException)
213 AtkObjectWrapper *pWrap = ATK_OBJECT_WRAPPER( pText );
214 if( pWrap )
216 if( !pWrap->mpComponent && pWrap->mpContext )
218 uno::Any any = pWrap->mpContext->queryInterface( cppu::UnoType<accessibility::XAccessibleComponent>::get() );
219 pWrap->mpComponent = static_cast< accessibility::XAccessibleComponent * > (any.pReserved);
220 pWrap->mpComponent->acquire();
223 return pWrap->mpComponent;
226 return NULL;
229 static gchar*
230 get_color_value(const uno::Sequence< beans::PropertyValue >& rAttributeList,
231 const sal_Int32 * pIndexArray,
232 ExportedAttribute attr,
233 AtkText * text)
235 sal_Int32 nColor = -1; // AUTOMATIC
236 sal_Int32 nIndex = pIndexArray[attr];
238 if( nIndex != -1 )
239 nColor = rAttributeList[nIndex].Value.get<sal_Int32>();
242 * Check for color value for 100% alpha white, which means
243 * "automatic". Grab the RGB value from XAccessibleComponent
244 * in this case.
247 if( (nColor == -1) && text )
251 accessibility::XAccessibleComponent *pComponent = getComponent( text );
252 if( pComponent )
254 switch( attr )
256 case TEXT_ATTRIBUTE_BACKGROUND_COLOR:
257 nColor = pComponent->getBackground();
258 break;
259 case TEXT_ATTRIBUTE_FOREGROUND_COLOR:
260 nColor = pComponent->getForeground();
261 break;
262 default:
263 break;
268 catch(const uno::Exception&) {
269 g_warning( "Exception in get[Fore|Back]groundColor()" );
273 if( nColor != -1 )
275 sal_uInt8 blue = nColor & 0xFF;
276 sal_uInt8 green = (nColor >> 8) & 0xFF;
277 sal_uInt8 red = (nColor >> 16) & 0xFF;
279 return g_strdup_printf( "%u,%u,%u", red, green, blue );
282 return NULL;
285 static bool
286 String2Color( uno::Any& rAny, const gchar * value )
288 int red, green, blue;
290 if( 3 != sscanf( value, "%d,%d,%d", &red, &green, &blue ) )
291 return false;
293 sal_Int32 nColor = (sal_Int32) blue | ( (sal_Int32) green << 8 ) | ( ( sal_Int32 ) red << 16 );
294 rAny = uno::makeAny( nColor );
295 return true;
298 /*****************************************************************************/
300 static gchar*
301 FontSlant2Style(const uno::Any& rAny)
303 const gchar * value = NULL;
305 switch( rAny.get<awt::FontSlant>() )
307 case awt::FontSlant_NONE:
308 value = "normal";
309 break;
311 case awt::FontSlant_OBLIQUE:
312 value = "oblique";
313 break;
315 case awt::FontSlant_ITALIC:
316 value = "italic";
317 break;
319 case awt::FontSlant_REVERSE_OBLIQUE:
320 value = "reverse oblique";
321 break;
323 case awt::FontSlant_REVERSE_ITALIC:
324 value = "reverse italic";
325 break;
327 default:
328 break;
331 if( value )
332 return g_strdup( value );
334 return NULL;
337 static bool
338 Style2FontSlant( uno::Any& rAny, const gchar * value )
340 awt::FontSlant aFontSlant;
342 if( strncmp( value, STRNCMP_PARAM( "normal" ) ) )
343 aFontSlant = awt::FontSlant_NONE;
344 else if( strncmp( value, STRNCMP_PARAM( "oblique" ) ) )
345 aFontSlant = awt::FontSlant_OBLIQUE;
346 else if( strncmp( value, STRNCMP_PARAM( "italic" ) ) )
347 aFontSlant = awt::FontSlant_ITALIC;
348 else if( strncmp( value, STRNCMP_PARAM( "reverse oblique" ) ) )
349 aFontSlant = awt::FontSlant_REVERSE_OBLIQUE;
350 else if( strncmp( value, STRNCMP_PARAM( "reverse italic" ) ) )
351 aFontSlant = awt::FontSlant_REVERSE_ITALIC;
352 else
353 return false;
355 rAny = uno::makeAny( aFontSlant );
356 return true;
359 /*****************************************************************************/
361 static gchar*
362 Weight2String(const uno::Any& rAny)
364 return g_strdup_printf( "%g", rAny.get<float>() * 4 );
367 static bool
368 String2Weight( uno::Any& rAny, const gchar * value )
370 float weight;
372 if( 1 != sscanf( value, "%g", &weight ) )
373 return false;
375 rAny = uno::makeAny( weight / 4 );
376 return true;
379 /*****************************************************************************/
381 static gchar*
382 Adjust2Justification(const uno::Any& rAny)
384 const gchar * value = NULL;
386 switch( rAny.get<short>() )
388 case style::ParagraphAdjust_LEFT:
389 value = "left";
390 break;
392 case style::ParagraphAdjust_RIGHT:
393 value = "right";
394 break;
396 case style::ParagraphAdjust_BLOCK:
397 case style::ParagraphAdjust_STRETCH:
398 value = "fill";
399 break;
401 case style::ParagraphAdjust_CENTER:
402 value = "center";
403 break;
405 default:
406 break;
409 if( value )
410 return g_strdup( value );
412 return NULL;
415 static bool
416 Justification2Adjust( uno::Any& rAny, const gchar * value )
418 short nParagraphAdjust;
420 if( strncmp( value, STRNCMP_PARAM( "left" ) ) )
421 nParagraphAdjust = style::ParagraphAdjust_LEFT;
422 else if( strncmp( value, STRNCMP_PARAM( "right" ) ) )
423 nParagraphAdjust = style::ParagraphAdjust_RIGHT;
424 else if( strncmp( value, STRNCMP_PARAM( "fill" ) ) )
425 nParagraphAdjust = style::ParagraphAdjust_BLOCK;
426 else if( strncmp( value, STRNCMP_PARAM( "center" ) ) )
427 nParagraphAdjust = style::ParagraphAdjust_CENTER;
428 else
429 return false;
431 rAny = uno::makeAny( nParagraphAdjust );
432 return true;
435 /*****************************************************************************/
437 const gchar * font_strikethrough[] = {
438 "none", // FontStrikeout::NONE
439 "single", // FontStrikeout::SINGLE
440 "double", // FontStrikeout::DOUBLE
441 NULL, // FontStrikeout::DONTKNOW
442 "bold", // FontStrikeout::BOLD
443 "with /", // FontStrikeout::SLASH
444 "with X" // FontStrikeout::X
447 const sal_Int16 n_strikeout_constants = sizeof(font_strikethrough) / sizeof(gchar*);
449 static gchar*
450 Strikeout2String(const uno::Any& rAny)
452 sal_Int16 n = rAny.get<sal_Int16>();
454 if( n >= 0 && n < n_strikeout_constants )
455 return g_strdup( font_strikethrough[n] );
457 return NULL;
460 static bool
461 String2Strikeout( uno::Any& rAny, const gchar * value )
463 for( sal_Int16 n=0; n < n_strikeout_constants; ++n )
465 if( ( NULL != font_strikethrough[n] ) &&
466 0 == strncmp( value, font_strikethrough[n], strlen( font_strikethrough[n] ) ) )
468 rAny = uno::makeAny( n );
469 return true;
473 return false;
476 /*****************************************************************************/
478 static gchar*
479 Underline2String(const uno::Any& rAny)
481 const gchar * value = NULL;
483 switch( rAny.get<sal_Int16>() )
485 case awt::FontUnderline::NONE:
486 value = "none";
487 break;
489 case awt::FontUnderline::SINGLE:
490 value = "single";
491 break;
493 case awt::FontUnderline::DOUBLE:
494 value = "double";
495 break;
497 default:
498 break;
501 if( value )
502 return g_strdup( value );
504 return NULL;
507 static bool
508 String2Underline( uno::Any& rAny, const gchar * value )
510 short nUnderline;
512 if( strncmp( value, STRNCMP_PARAM( "none" ) ) )
513 nUnderline = awt::FontUnderline::NONE;
514 else if( strncmp( value, STRNCMP_PARAM( "single" ) ) )
515 nUnderline = awt::FontUnderline::SINGLE;
516 else if( strncmp( value, STRNCMP_PARAM( "double" ) ) )
517 nUnderline = awt::FontUnderline::DOUBLE;
518 else
519 return false;
521 rAny = uno::makeAny( nUnderline );
522 return true;
525 /*****************************************************************************/
527 static gchar*
528 GetString(const uno::Any& rAny)
530 OString aFontName = OUStringToOString( rAny.get< OUString > (), RTL_TEXTENCODING_UTF8 );
532 if( !aFontName.isEmpty() )
533 return g_strdup( aFontName.getStr() );
535 return NULL;
538 static bool
539 SetString( uno::Any& rAny, const gchar * value )
541 OString aFontName( value );
543 if( !aFontName.isEmpty() )
545 rAny = uno::makeAny( OStringToOUString( aFontName, RTL_TEXTENCODING_UTF8 ) );
546 return true;
549 return false;
552 /*****************************************************************************/
554 // @see http://developer.gnome.org/doc/API/2.0/atk/AtkText.html#AtkTextAttribute
556 // CMM = 100th of mm
557 static gchar*
558 CMM2UnitString(const uno::Any& rAny)
560 double fValue = rAny.get<sal_Int32>();
561 fValue = fValue * 0.01;
563 return g_strdup_printf( "%gmm", fValue );
566 static bool
567 UnitString2CMM( uno::Any& rAny, const gchar * value )
569 float fValue = 0.0; // pb: dont use double here because of warning on linux
571 if( 1 != sscanf( value, "%gmm", &fValue ) )
572 return false;
574 fValue = fValue * 100;
576 rAny = uno::makeAny( (sal_Int32) fValue);
577 return true;
580 /*****************************************************************************/
582 static const gchar * bool_values[] = { "true", "false" };
584 static gchar *
585 Bool2String( const uno::Any& rAny )
587 int n = 1;
589 if( rAny.get<bool>() )
590 n = 0;
592 return g_strdup( bool_values[n] );
595 static bool
596 String2Bool( uno::Any& rAny, const gchar * value )
598 bool bValue;
600 if( strncmp( value, STRNCMP_PARAM( "true" ) ) )
601 bValue = true;
602 else if( strncmp( value, STRNCMP_PARAM( "false" ) ) )
603 bValue = false;
604 else
605 return false;
607 rAny = uno::makeAny(bValue);
608 return true;
611 /*****************************************************************************/
613 static gchar*
614 Scale2String( const uno::Any& rAny )
616 return g_strdup_printf( "%g", (double) (rAny.get< sal_Int16 > ()) / 100 );
619 static bool
620 String2Scale( uno::Any& rAny, const gchar * value )
622 double dval;
624 if( 1 != sscanf( value, "%lg", &dval ) )
625 return false;
627 rAny = uno::makeAny((sal_Int16) (dval * 100));
628 return true;
631 /*****************************************************************************/
633 static gchar *
634 CaseMap2String( const uno::Any& rAny )
636 const gchar * value;
638 switch( rAny.get<short>() )
640 case style::CaseMap::SMALLCAPS:
641 value = "small_caps";
642 break;
644 default:
645 value = "normal";
646 break;
649 return g_strdup(value);
652 static bool
653 String2CaseMap( uno::Any& rAny, const gchar * value )
655 short nCaseMap;
657 if( strncmp( value, STRNCMP_PARAM( "normal" ) ) )
658 nCaseMap = style::CaseMap::NONE;
659 else if( strncmp( value, STRNCMP_PARAM( "small_caps" ) ) )
660 nCaseMap = style::CaseMap::SMALLCAPS;
661 else
662 return false;
664 rAny = uno::makeAny( nCaseMap );
665 return true;
668 /*****************************************************************************/
670 const gchar * font_stretch[] = {
671 "ultra_condensed",
672 "extra_condensed",
673 "condensed",
674 "semi_condensed",
675 "normal",
676 "semi_expanded",
677 "expanded",
678 "extra_expanded",
679 "ultra_expanded"
682 static gchar*
683 Kerning2Stretch(const uno::Any& rAny)
685 sal_Int16 n = rAny.get<sal_Int16>();
686 int i = 4;
688 // No good idea for a mapping - just return the basic info
689 if( n < 0 )
690 i=2;
691 else if( n > 0 )
692 i=6;
694 return g_strdup(font_stretch[i]);
697 /*****************************************************************************/
699 static gchar*
700 Locale2String(const uno::Any& rAny)
702 /* FIXME-BCP47: support language tags? And why is country lowercase? */
703 lang::Locale aLocale = rAny.get<lang::Locale> ();
704 LanguageTag aLanguageTag( aLocale);
705 return g_strdup_printf( "%s-%s",
706 OUStringToOString( aLanguageTag.getLanguage(), RTL_TEXTENCODING_ASCII_US).getStr(),
707 OUStringToOString( aLanguageTag.getCountry(), RTL_TEXTENCODING_ASCII_US).toAsciiLowerCase().getStr() );
710 static bool
711 String2Locale( uno::Any& rAny, const gchar * value )
713 /* FIXME-BCP47: support language tags? */
714 bool ret = false;
716 gchar ** str_array = g_strsplit_set( value, "-.@", -1 );
717 if( str_array[0] != NULL )
719 ret = true;
721 lang::Locale aLocale;
723 aLocale.Language = OUString::createFromAscii(str_array[0]);
724 if( str_array[1] != NULL )
726 gchar * country = g_ascii_strup(str_array[1], -1);
727 aLocale.Country = OUString::createFromAscii(country);
728 g_free(country);
731 rAny = uno::makeAny(aLocale);
734 g_strfreev(str_array);
735 return ret;
738 /*****************************************************************************/
740 // @see http://www.w3.org/TR/2002/WD-css3-fonts-20020802/#font-effect-prop
741 static const gchar * relief[] = { "none", "emboss", "engrave" };
742 static const gchar * outline = "outline";
744 static gchar *
745 get_font_effect(const uno::Sequence< beans::PropertyValue >& rAttributeList,
746 sal_Int32 nContourIndex, sal_Int32 nReliefIndex)
748 if( nContourIndex != -1 )
750 if( rAttributeList[nContourIndex].Value.get<bool>() )
751 return g_strdup(outline);
754 if( nReliefIndex != -1 )
756 sal_Int16 n = rAttributeList[nReliefIndex].Value.get<sal_Int16>();
757 if( n < 3)
758 return g_strdup(relief[n]);
761 return NULL;
764 /*****************************************************************************/
766 // @see http://www.w3.org/TR/REC-CSS2/text.html#lining-striking-props
768 enum
770 DECORATION_NONE = 0,
771 DECORATION_BLINK,
772 DECORATION_UNDERLINE,
773 DECORATION_LINE_THROUGH
776 static const gchar * decorations[] = { "none", "blink", "underline", "line-through" };
778 static gchar *
779 get_text_decoration(const uno::Sequence< beans::PropertyValue >& rAttributeList,
780 sal_Int32 nBlinkIndex, sal_Int32 nUnderlineIndex,
781 sal_Int16 nStrikeoutIndex)
783 gchar * value_list[4] = { NULL, NULL, NULL, NULL };
784 gint count = 0;
786 // no property value found
787 if( ( nBlinkIndex == -1 ) && (nUnderlineIndex == -1 ) && (nStrikeoutIndex == -1))
788 return NULL;
790 if( nBlinkIndex != -1 )
792 if( rAttributeList[nBlinkIndex].Value.get<bool>() )
793 value_list[count++] = const_cast <gchar *> (decorations[DECORATION_BLINK]);
795 if( nUnderlineIndex != -1 )
797 sal_Int16 n = rAttributeList[nUnderlineIndex].Value.get<sal_Int16> ();
798 if( n != awt::FontUnderline::NONE )
799 value_list[count++] = const_cast <gchar *> (decorations[DECORATION_UNDERLINE]);
801 if( nStrikeoutIndex != -1 )
803 sal_Int16 n = rAttributeList[nStrikeoutIndex].Value.get<sal_Int16> ();
804 if( n != awt::FontStrikeout::NONE && n != awt::FontStrikeout::DONTKNOW )
805 value_list[count++] = const_cast <gchar *> (decorations[DECORATION_LINE_THROUGH]);
808 if( count == 0 )
809 value_list[count++] = const_cast <gchar *> (decorations[DECORATION_NONE]);
811 return g_strjoinv(" ", value_list);
814 /*****************************************************************************/
816 // @see http://www.w3.org/TR/REC-CSS2/text.html#propdef-text-shadow
818 static const gchar * shadow_values[] = { "none", "black" };
820 static gchar *
821 Bool2Shadow( const uno::Any& rAny )
823 int n = 0;
825 if( rAny.get<bool>() )
826 n = 1;
828 return g_strdup( shadow_values[n] );
831 /*****************************************************************************/
833 static gchar *
834 Short2Degree( const uno::Any& rAny )
836 float f = rAny.get<sal_Int16>() / 10.0;
837 return g_strdup_printf( "%g", f );
840 /*****************************************************************************/
842 const gchar * directions[] = { "ltr", "rtl", "rtl", "ltr", "none" };
844 static gchar *
845 WritingMode2Direction( const uno::Any& rAny )
847 sal_Int16 n = rAny.get<sal_Int16>();
849 if( 0 <= n && n <= text::WritingMode2::PAGE )
850 return g_strdup(directions[n]);
852 return NULL;
855 // @see http://www.w3.org/TR/2001/WD-css3-text-20010517/#PrimaryTextAdvanceDirection
857 const gchar * writing_modes[] = { "lr-tb", "rl-tb", "tb-rl", "tb-lr", "none" };
858 static gchar *
859 WritingMode2String( const uno::Any& rAny )
861 sal_Int16 n = rAny.get<sal_Int16>();
863 if( 0 <= n && n <= text::WritingMode2::PAGE )
864 return g_strdup(writing_modes[n]);
866 return NULL;
869 /*****************************************************************************/
871 const char * baseline_values[] = { "baseline", "sub", "super" };
873 // @see http://www.w3.org/TR/REC-CSS2/visudet.html#propdef-vertical-align
874 static gchar *
875 Escapement2VerticalAlign( const uno::Any& rAny )
877 sal_Int16 n = rAny.get<sal_Int16>();
878 gchar * ret = NULL;
880 // Values are in %, 101% means "automatic"
881 if( n == 0 )
882 ret = g_strdup(baseline_values[0]);
883 else if( n == 101 )
884 ret = g_strdup(baseline_values[2]);
885 else if( n == -101 )
886 ret = g_strdup(baseline_values[1]);
887 else
888 ret = g_strdup_printf( "%d%%", n );
890 return ret;
893 /*****************************************************************************/
895 // @see http://www.w3.org/TR/REC-CSS2/visudet.html#propdef-line-height
896 static gchar *
897 LineSpacing2LineHeight( const uno::Any& rAny )
899 style::LineSpacing ls;
900 gchar * ret = NULL;
902 if( rAny >>= ls )
904 if( ls.Mode == style::LineSpacingMode::PROP )
905 ret = g_strdup_printf( "%d%%", ls.Height );
906 else if( ls.Mode == style::LineSpacingMode::FIX )
907 ret = g_strdup_printf( "%.3gpt", toPoint(ls.Height) );
910 return ret;
913 /*****************************************************************************/
915 // @see http://www.w3.org/People/howcome/t/970224HTMLERB-CSS/WD-tabs-970117.html
916 static gchar *
917 TabStopList2String( const uno::Any& rAny, bool default_tabs )
919 uno::Sequence< style::TabStop > theTabStops;
920 gchar * ret = NULL;
922 if( rAny >>= theTabStops)
924 sal_Int32 indexOfTab = 0;
925 sal_Int32 numberOfTabs = theTabStops.getLength();
926 sal_Unicode lastFillChar = (sal_Unicode) ' ';
928 for( ; indexOfTab < numberOfTabs; ++indexOfTab )
930 bool is_default_tab = (style::TabAlign_DEFAULT == theTabStops[indexOfTab].Alignment);
932 if( is_default_tab != default_tabs )
933 continue;
935 double fValue = theTabStops[indexOfTab].Position;
936 fValue = fValue * 0.01;
938 const gchar * tab_align = "";
939 switch( theTabStops[indexOfTab].Alignment )
941 case style::TabAlign_LEFT :
942 tab_align = "left ";
943 break;
944 case style::TabAlign_CENTER :
945 tab_align = "center ";
946 break;
947 case style::TabAlign_RIGHT :
948 tab_align = "right ";
949 break;
950 case style::TabAlign_DECIMAL :
951 tab_align = "decimal ";
952 break;
953 default:
954 break;
957 const gchar * lead_char = "";
959 if( theTabStops[indexOfTab].FillChar != lastFillChar )
961 lastFillChar = theTabStops[indexOfTab].FillChar;
962 switch (lastFillChar)
964 case (sal_Unicode) ' ':
965 lead_char = "blank ";
966 break;
968 case (sal_Unicode) '.':
969 lead_char = "dotted ";
970 break;
972 case (sal_Unicode) '-':
973 lead_char = "dashed ";
974 break;
976 case (sal_Unicode) '_':
977 lead_char = "lined ";
978 break;
980 default:
981 lead_char = "custom ";
982 break;
986 gchar * tab_str = g_strdup_printf( "%s%s%gmm", lead_char, tab_align, fValue );
988 if( ret )
990 gchar * old_tab_str = ret;
991 ret = g_strconcat(old_tab_str, " ", tab_str, (const char*)NULL);
992 g_free( old_tab_str );
994 else
995 ret = tab_str;
999 return ret;
1002 static gchar *
1003 TabStops2String( const uno::Any& rAny )
1005 return TabStopList2String(rAny, false);
1008 static gchar *
1009 DefaultTabStops2String( const uno::Any& rAny )
1011 return TabStopList2String(rAny, true);
1014 /*****************************************************************************/
1016 extern "C" int
1017 attr_compare(const void *p1,const void *p2)
1019 const rtl_uString * pustr = static_cast<const rtl_uString *>(p1);
1020 const char * pc = *static_cast<const char * const *>(p2);
1022 return rtl_ustr_ascii_compare_WithLength(pustr->buffer, pustr->length, pc);
1025 static void
1026 find_exported_attributes( sal_Int32 *pArray,
1027 const com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValue >& rAttributeList )
1029 for( sal_Int32 i = 0; i < rAttributeList.getLength(); i++ )
1031 const char ** pAttr = static_cast<const char **>(bsearch(rAttributeList[i].Name.pData,
1032 ExportedTextAttributes, TEXT_ATTRIBUTE_LAST, sizeof(const char *),
1033 attr_compare));
1035 if( pAttr )
1037 sal_Int32 nIndex = pAttr - ExportedTextAttributes;
1038 pArray[nIndex] = i;
1043 /*****************************************************************************/
1045 static AtkAttributeSet*
1046 attribute_set_prepend( AtkAttributeSet* attribute_set,
1047 AtkTextAttribute attribute,
1048 gchar * value )
1050 if( value )
1052 AtkAttribute *at = static_cast<AtkAttribute *>(g_malloc( sizeof (AtkAttribute) ));
1053 at->name = g_strdup( atk_text_attribute_get_name( attribute ) );
1054 at->value = value;
1056 return g_slist_prepend(attribute_set, at);
1059 return attribute_set;
1062 /*****************************************************************************/
1064 AtkAttributeSet*
1065 attribute_set_new_from_property_values(
1066 const uno::Sequence< beans::PropertyValue >& rAttributeList,
1067 bool run_attributes_only,
1068 AtkText *text)
1070 AtkAttributeSet* attribute_set = NULL;
1072 sal_Int32 aIndexList[TEXT_ATTRIBUTE_LAST] = { -1 };
1074 // Initialize index array with -1
1075 for( sal_Int32 attr = 0; attr < TEXT_ATTRIBUTE_LAST; ++attr )
1076 aIndexList[attr] = -1;
1078 find_exported_attributes(aIndexList, rAttributeList);
1080 attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_BG_COLOR,
1081 get_color_value(rAttributeList, aIndexList, TEXT_ATTRIBUTE_BACKGROUND_COLOR, run_attributes_only ? NULL : text ) );
1083 attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_FG_COLOR,
1084 get_color_value(rAttributeList, aIndexList, TEXT_ATTRIBUTE_FOREGROUND_COLOR, run_attributes_only ? NULL : text) );
1086 attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_INVISIBLE,
1087 get_bool_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_HIDDEN]));
1089 attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_UNDERLINE,
1090 get_underline_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_UNDERLINE]));
1092 attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_STRIKETHROUGH,
1093 get_strikethrough_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_STRIKETHROUGH]));
1095 attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_SIZE,
1096 get_height_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_HEIGHT]));
1098 attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_WEIGHT,
1099 get_weight_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_WEIGHT]));
1101 attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_FAMILY_NAME,
1102 get_string_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_FONT_NAME]));
1104 attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_VARIANT,
1105 get_variant_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_CASEMAP]));
1107 attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_STYLE,
1108 get_style_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_POSTURE]));
1110 attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_SCALE,
1111 get_scale_width(rAttributeList, aIndexList[TEXT_ATTRIBUTE_SCALE]));
1113 attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_LANGUAGE,
1114 get_language_string(rAttributeList, aIndexList[TEXT_ATTRIBUTE_LOCALE]));
1116 attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_DIRECTION,
1117 get_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_WRITING_MODE], WritingMode2Direction));
1119 attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_STRETCH,
1120 get_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_KERNING], Kerning2Stretch));
1122 if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_font_effect )
1123 atk_text_attribute_font_effect = atk_text_attribute_register("font-effect");
1125 attribute_set = attribute_set_prepend(attribute_set, atk_text_attribute_font_effect,
1126 get_font_effect(rAttributeList, aIndexList[TEXT_ATTRIBUTE_CONTOURED], aIndexList[TEXT_ATTRIBUTE_RELIEF]));
1128 if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_decoration )
1129 atk_text_attribute_decoration = atk_text_attribute_register("text-decoration");
1131 attribute_set = attribute_set_prepend(attribute_set, atk_text_attribute_decoration,
1132 get_text_decoration(rAttributeList, aIndexList[TEXT_ATTRIBUTE_BLINKING],
1133 aIndexList[TEXT_ATTRIBUTE_UNDERLINE], aIndexList[TEXT_ATTRIBUTE_STRIKETHROUGH]));
1135 if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_rotation )
1136 atk_text_attribute_rotation = atk_text_attribute_register("text-rotation");
1138 attribute_set = attribute_set_prepend(attribute_set, atk_text_attribute_rotation,
1139 get_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_ROTATION], Short2Degree));
1141 if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_shadow )
1142 atk_text_attribute_shadow = atk_text_attribute_register("text-shadow");
1144 attribute_set = attribute_set_prepend(attribute_set, atk_text_attribute_shadow,
1145 get_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_SHADOWED], Bool2Shadow));
1147 if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_writing_mode )
1148 atk_text_attribute_writing_mode = atk_text_attribute_register("writing-mode");
1150 attribute_set = attribute_set_prepend(attribute_set, atk_text_attribute_writing_mode,
1151 get_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_WRITING_MODE], WritingMode2String));
1153 if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_vertical_align )
1154 atk_text_attribute_vertical_align = atk_text_attribute_register("vertical-align");
1156 attribute_set = attribute_set_prepend(attribute_set, atk_text_attribute_vertical_align,
1157 get_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_CHAR_ESCAPEMENT], Escapement2VerticalAlign));
1159 if( run_attributes_only )
1160 return attribute_set;
1162 attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_LEFT_MARGIN,
1163 get_cmm_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_LEFT_MARGIN]));
1165 attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_RIGHT_MARGIN,
1166 get_cmm_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_RIGHT_MARGIN]));
1168 attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_INDENT,
1169 get_cmm_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_FIRST_LINE_INDENT]));
1171 attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_PIXELS_ABOVE_LINES,
1172 get_cmm_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_TOP_MARGIN]));
1174 attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_PIXELS_BELOW_LINES,
1175 get_cmm_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_BOTTOM_MARGIN]));
1177 attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_JUSTIFICATION,
1178 get_justification_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_JUSTIFICATION]));
1180 if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_paragraph_style )
1181 atk_text_attribute_paragraph_style = atk_text_attribute_register("paragraph-style");
1183 attribute_set = attribute_set_prepend(attribute_set, atk_text_attribute_paragraph_style,
1184 get_string_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_STYLE_NAME]));
1186 if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_line_height )
1187 atk_text_attribute_line_height = atk_text_attribute_register("line-height");
1189 attribute_set = attribute_set_prepend(attribute_set, atk_text_attribute_line_height,
1190 get_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_LINE_SPACING], LineSpacing2LineHeight));
1192 if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_tab_interval )
1193 atk_text_attribute_tab_interval = atk_text_attribute_register("tab-interval");
1195 attribute_set = attribute_set_prepend(attribute_set, atk_text_attribute_tab_interval,
1196 get_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_TAB_STOPS], DefaultTabStops2String));
1198 if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_tab_stops )
1199 atk_text_attribute_tab_stops = atk_text_attribute_register("tab-stops");
1201 attribute_set = attribute_set_prepend(attribute_set, atk_text_attribute_tab_stops,
1202 get_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_TAB_STOPS], TabStops2String));
1204 // #i92233#
1205 if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_mm_to_pixel_ratio )
1206 atk_text_attribute_mm_to_pixel_ratio = atk_text_attribute_register("mm-to-pixel-ratio");
1208 attribute_set = attribute_set_prepend( attribute_set, atk_text_attribute_mm_to_pixel_ratio,
1209 get_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_MM_TO_PIXEL_RATIO], Float2String));
1211 return attribute_set;
1214 AtkAttributeSet*
1215 attribute_set_new_from_extended_attributes(
1216 const css::uno::Reference< css::accessibility::XAccessibleExtendedAttributes >& rExtendedAttributes )
1218 AtkAttributeSet *pSet = NULL;
1220 // extended attributes is a string of colon-separated pairs of property and value,
1221 // with pairs separated by semicolons. Example: "heading-level:2;weight:bold;"
1222 uno::Any anyVal = rExtendedAttributes->getExtendedAttributes();
1223 OUString sExtendedAttrs;
1224 anyVal >>= sExtendedAttrs;
1225 sal_Int32 nIndex = 0;
1228 OUString sProperty = sExtendedAttrs.getToken( 0, ';', nIndex );
1230 sal_Int32 nColonPos = 0;
1231 OString sPropertyName = OUStringToOString( sProperty.getToken( 0, ':', nColonPos ),
1232 RTL_TEXTENCODING_UTF8 );
1233 OString sPropertyValue = OUStringToOString( sProperty.getToken( 0, ':', nColonPos ),
1234 RTL_TEXTENCODING_UTF8 );
1236 pSet = attribute_set_prepend( pSet,
1237 atk_text_attribute_register( sPropertyName.getStr() ),
1238 g_strdup_printf( "%s", sPropertyValue.getStr() ) );
1240 while ( nIndex >= 0 && nIndex < sExtendedAttrs.getLength() );
1242 return pSet;
1245 AtkAttributeSet* attribute_set_prepend_misspelled( AtkAttributeSet* attribute_set )
1247 if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_misspelled )
1248 atk_text_attribute_misspelled = atk_text_attribute_register( "text-spelling" );
1250 attribute_set = attribute_set_prepend( attribute_set, atk_text_attribute_misspelled,
1251 g_strdup_printf( "misspelled" ) );
1253 return attribute_set;
1256 // #i92232#
1257 AtkAttributeSet* attribute_set_prepend_tracked_change_insertion( AtkAttributeSet* attribute_set )
1259 if ( ATK_TEXT_ATTR_INVALID == atk_text_attribute_tracked_change )
1261 atk_text_attribute_tracked_change = atk_text_attribute_register( "text-tracked-change" );
1264 attribute_set = attribute_set_prepend( attribute_set,
1265 atk_text_attribute_tracked_change,
1266 g_strdup_printf( "insertion" ) );
1268 return attribute_set;
1271 AtkAttributeSet* attribute_set_prepend_tracked_change_deletion( AtkAttributeSet* attribute_set )
1273 if ( ATK_TEXT_ATTR_INVALID == atk_text_attribute_tracked_change )
1275 atk_text_attribute_tracked_change = atk_text_attribute_register( "text-tracked-change" );
1278 attribute_set = attribute_set_prepend( attribute_set,
1279 atk_text_attribute_tracked_change,
1280 g_strdup_printf( "deletion" ) );
1282 return attribute_set;
1285 AtkAttributeSet* attribute_set_prepend_tracked_change_formatchange( AtkAttributeSet* attribute_set )
1287 if ( ATK_TEXT_ATTR_INVALID == atk_text_attribute_tracked_change )
1289 atk_text_attribute_tracked_change = atk_text_attribute_register( "text-tracked-change" );
1292 attribute_set = attribute_set_prepend( attribute_set,
1293 atk_text_attribute_tracked_change,
1294 g_strdup_printf( "attribute-change" ) );
1296 return attribute_set;
1299 /*****************************************************************************/
1301 struct AtkTextAttrMapping
1303 const char * name;
1304 TextPropertyValueFunc toPropertyValue;
1307 const AtkTextAttrMapping g_TextAttrMap[] =
1309 { "", InvalidValue }, // ATK_TEXT_ATTR_INVALID = 0
1310 { "ParaLeftMargin", UnitString2CMM }, // ATK_TEXT_ATTR_LEFT_MARGIN
1311 { "ParaRightMargin", UnitString2CMM }, // ATK_TEXT_ATTR_RIGHT_MARGIN
1312 { "ParaFirstLineIndent", UnitString2CMM }, // ATK_TEXT_ATTR_INDENT
1313 { "CharHidden", String2Bool }, // ATK_TEXT_ATTR_INVISIBLE
1314 { "", InvalidValue }, // ATK_TEXT_ATTR_EDITABLE
1315 { "ParaTopMargin", UnitString2CMM }, // ATK_TEXT_ATTR_PIXELS_ABOVE_LINES
1316 { "ParaBottomMargin", UnitString2CMM }, // ATK_TEXT_ATTR_PIXELS_BELOW_LINES
1317 { "", InvalidValue }, // ATK_TEXT_ATTR_PIXELS_INSIDE_WRAP
1318 { "", InvalidValue }, // ATK_TEXT_ATTR_BG_FULL_HEIGHT
1319 { "", InvalidValue }, // ATK_TEXT_ATTR_RISE
1320 { "CharUnderline", String2Underline }, // ATK_TEXT_ATTR_UNDERLINE
1321 { "CharStrikeout", String2Strikeout }, // ATK_TEXT_ATTR_STRIKETHROUGH
1322 { "CharHeight", String2Float }, // ATK_TEXT_ATTR_SIZE
1323 { "CharScaleWidth", String2Scale }, // ATK_TEXT_ATTR_SCALE
1324 { "CharWeight", String2Weight }, // ATK_TEXT_ATTR_WEIGHT
1325 { "CharLocale", String2Locale }, // ATK_TEXT_ATTR_LANGUAGE
1326 { "CharFontName", SetString }, // ATK_TEXT_ATTR_FAMILY_NAME
1327 { "CharBackColor", String2Color }, // ATK_TEXT_ATTR_BG_COLOR
1328 { "CharColor", String2Color }, // ATK_TEXT_ATTR_FG_COLOR
1329 { "", InvalidValue }, // ATK_TEXT_ATTR_BG_STIPPLE
1330 { "", InvalidValue }, // ATK_TEXT_ATTR_FG_STIPPLE
1331 { "", InvalidValue }, // ATK_TEXT_ATTR_WRAP_MODE
1332 { "", InvalidValue }, // ATK_TEXT_ATTR_DIRECTION
1333 { "ParaAdjust", Justification2Adjust }, // ATK_TEXT_ATTR_JUSTIFICATION
1334 { "", InvalidValue }, // ATK_TEXT_ATTR_STRETCH
1335 { "CharCaseMap", String2CaseMap }, // ATK_TEXT_ATTR_VARIANT
1336 { "CharPosture", Style2FontSlant } // ATK_TEXT_ATTR_STYLE
1339 static const sal_Int32 g_TextAttrMapSize = sizeof( g_TextAttrMap ) / sizeof( AtkTextAttrMapping );
1341 /*****************************************************************************/
1343 bool
1344 attribute_set_map_to_property_values(
1345 AtkAttributeSet* attribute_set,
1346 uno::Sequence< beans::PropertyValue >& rValueList )
1348 // Ensure enough space ..
1349 uno::Sequence< beans::PropertyValue > aAttributeList (g_TextAttrMapSize);
1351 sal_Int32 nIndex = 0;
1352 for( GSList * item = attribute_set; item != NULL; item = g_slist_next( item ) )
1354 AtkAttribute* attribute = reinterpret_cast<AtkAttribute *>(item);
1356 AtkTextAttribute text_attr = atk_text_attribute_for_name( attribute->name );
1357 if( text_attr < g_TextAttrMapSize )
1359 if( g_TextAttrMap[text_attr].name[0] != '\0' )
1361 if( ! g_TextAttrMap[text_attr].toPropertyValue( aAttributeList[nIndex].Value, attribute->value) )
1362 return false;
1364 aAttributeList[nIndex].Name = OUString::createFromAscii( g_TextAttrMap[text_attr].name );
1365 aAttributeList[nIndex].State = beans::PropertyState_DIRECT_VALUE;
1366 ++nIndex;
1369 else
1371 // Unsupported text attribute
1372 return false;
1376 aAttributeList.realloc( nIndex );
1377 rValueList = aAttributeList;
1378 return true;
1381 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */