Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : :
30 : : #include "atktextattributes.hxx"
31 : :
32 : : #include <com/sun/star/awt/FontSlant.hpp>
33 : : #include <com/sun/star/awt/FontStrikeout.hpp>
34 : : #include <com/sun/star/awt/FontUnderline.hpp>
35 : :
36 : : #include <com/sun/star/style/CaseMap.hpp>
37 : : #include <com/sun/star/style/LineSpacing.hpp>
38 : : #include <com/sun/star/style/LineSpacingMode.hpp>
39 : : #include <com/sun/star/style/ParagraphAdjust.hpp>
40 : : #include <com/sun/star/style/TabAlign.hpp>
41 : : #include <com/sun/star/style/TabStop.hpp>
42 : :
43 : : #include <com/sun/star/text/WritingMode2.hpp>
44 : :
45 : : #include "atkwrapper.hxx"
46 : :
47 : : #include <com/sun/star/accessibility/XAccessibleComponent.hpp>
48 : :
49 : : #include <vcl/svapp.hxx>
50 : : #include <vcl/outdev.hxx>
51 : :
52 : : #include <stdio.h>
53 : : #include <string.h>
54 : :
55 : : using namespace ::com::sun::star;
56 : :
57 : : typedef gchar* (* AtkTextAttrFunc) ( const uno::Any& rAny );
58 : : typedef bool (* TextPropertyValueFunc) ( uno::Any& rAny, const gchar * value );
59 : :
60 : : #define STRNCMP_PARAM( s ) s,sizeof( s )-1
61 : :
62 : :
63 : : /*****************************************************************************/
64 : :
65 : : static AtkTextAttribute atk_text_attribute_paragraph_style = ATK_TEXT_ATTR_INVALID;
66 : : static AtkTextAttribute atk_text_attribute_font_effect = ATK_TEXT_ATTR_INVALID;
67 : : static AtkTextAttribute atk_text_attribute_decoration = ATK_TEXT_ATTR_INVALID;
68 : : static AtkTextAttribute atk_text_attribute_line_height = ATK_TEXT_ATTR_INVALID;
69 : : static AtkTextAttribute atk_text_attribute_rotation = ATK_TEXT_ATTR_INVALID;
70 : : static AtkTextAttribute atk_text_attribute_shadow = ATK_TEXT_ATTR_INVALID;
71 : : static AtkTextAttribute atk_text_attribute_tab_interval = ATK_TEXT_ATTR_INVALID;
72 : : static AtkTextAttribute atk_text_attribute_tab_stops = ATK_TEXT_ATTR_INVALID;
73 : : static AtkTextAttribute atk_text_attribute_writing_mode = ATK_TEXT_ATTR_INVALID;
74 : : static AtkTextAttribute atk_text_attribute_vertical_align = ATK_TEXT_ATTR_INVALID;
75 : : static AtkTextAttribute atk_text_attribute_misspelled = ATK_TEXT_ATTR_INVALID;
76 : : // #i92232#
77 : : static AtkTextAttribute atk_text_attribute_tracked_change = ATK_TEXT_ATTR_INVALID;
78 : : // #i92233#
79 : : static AtkTextAttribute atk_text_attribute_mm_to_pixel_ratio = ATK_TEXT_ATTR_INVALID;
80 : :
81 : : /*****************************************************************************/
82 : :
83 : : /**
84 : : * !! IMPORTANT NOTE !! : when adding items to this list, KEEP THE LIST SORTED
85 : : * and re-arrange the enum values accordingly.
86 : : */
87 : :
88 : : enum ExportedAttribute
89 : : {
90 : : TEXT_ATTRIBUTE_BACKGROUND_COLOR = 0,
91 : : TEXT_ATTRIBUTE_CASEMAP,
92 : : TEXT_ATTRIBUTE_FOREGROUND_COLOR,
93 : : TEXT_ATTRIBUTE_CONTOURED,
94 : : TEXT_ATTRIBUTE_CHAR_ESCAPEMENT,
95 : : TEXT_ATTRIBUTE_BLINKING,
96 : : TEXT_ATTRIBUTE_FONT_NAME,
97 : : TEXT_ATTRIBUTE_HEIGHT,
98 : : TEXT_ATTRIBUTE_HIDDEN,
99 : : TEXT_ATTRIBUTE_KERNING,
100 : : TEXT_ATTRIBUTE_LOCALE,
101 : : TEXT_ATTRIBUTE_POSTURE,
102 : : TEXT_ATTRIBUTE_RELIEF,
103 : : TEXT_ATTRIBUTE_ROTATION,
104 : : TEXT_ATTRIBUTE_SCALE,
105 : : TEXT_ATTRIBUTE_SHADOWED,
106 : : TEXT_ATTRIBUTE_STRIKETHROUGH,
107 : : TEXT_ATTRIBUTE_UNDERLINE,
108 : : TEXT_ATTRIBUTE_WEIGHT,
109 : : // #i92233#
110 : : TEXT_ATTRIBUTE_MM_TO_PIXEL_RATIO,
111 : : TEXT_ATTRIBUTE_JUSTIFICATION,
112 : : TEXT_ATTRIBUTE_BOTTOM_MARGIN,
113 : : TEXT_ATTRIBUTE_FIRST_LINE_INDENT,
114 : : TEXT_ATTRIBUTE_LEFT_MARGIN,
115 : : TEXT_ATTRIBUTE_LINE_SPACING,
116 : : TEXT_ATTRIBUTE_RIGHT_MARGIN,
117 : : TEXT_ATTRIBUTE_STYLE_NAME,
118 : : TEXT_ATTRIBUTE_TAB_STOPS,
119 : : TEXT_ATTRIBUTE_TOP_MARGIN,
120 : : TEXT_ATTRIBUTE_WRITING_MODE,
121 : : TEXT_ATTRIBUTE_LAST
122 : : };
123 : :
124 : : static const char * ExportedTextAttributes[TEXT_ATTRIBUTE_LAST] =
125 : : {
126 : : "CharBackColor", // TEXT_ATTRIBUTE_BACKGROUND_COLOR
127 : : "CharCaseMap", // TEXT_ATTRIBUTE_CASEMAP
128 : : "CharColor", // TEXT_ATTRIBUTE_FOREGROUND_COLOR
129 : : "CharContoured", // TEXT_ATTRIBUTE_CONTOURED
130 : : "CharEscapement", // TEXT_ATTRIBUTE_CHAR_ESCAPEMENT
131 : : "CharFlash", // TEXT_ATTRIBUTE_BLINKING
132 : : "CharFontName", // TEXT_ATTRIBUTE_FONT_NAME
133 : : "CharHeight", // TEXT_ATTRIBUTE_HEIGHT
134 : : "CharHidden", // TEXT_ATTRIBUTE_HIDDEN
135 : : "CharKerning", // TEXT_ATTRIBUTE_KERNING
136 : : "CharLocale", // TEXT_ATTRIBUTE_LOCALE
137 : : "CharPosture", // TEXT_ATTRIBUTE_POSTURE
138 : : "CharRelief", // TEXT_ATTRIBUTE_RELIEF
139 : : "CharRotation", // TEXT_ATTRIBUTE_ROTATION
140 : : "CharScaleWidth", // TEXT_ATTRIBUTE_SCALE
141 : : "CharShadowed", // TEXT_ATTRIBUTE_SHADOWED
142 : : "CharStrikeout", // TEXT_ATTRIBUTE_STRIKETHROUGH
143 : : "CharUnderline", // TEXT_ATTRIBUTE_UNDERLINE
144 : : "CharWeight", // TEXT_ATTRIBUTE_WEIGHT
145 : : // #i92233#
146 : : "MMToPixelRatio", // TEXT_ATTRIBUTE_MM_TO_PIXEL_RATIO
147 : : "ParaAdjust", // TEXT_ATTRIBUTE_JUSTIFICATION
148 : : "ParaBottomMargin", // TEXT_ATTRIBUTE_BOTTOM_MARGIN
149 : : "ParaFirstLineIndent", // TEXT_ATTRIBUTE_FIRST_LINE_INDENT
150 : : "ParaLeftMargin", // TEXT_ATTRIBUTE_LEFT_MARGIN
151 : : "ParaLineSpacing", // TEXT_ATTRIBUTE_LINE_SPACING
152 : : "ParaRightMargin", // TEXT_ATTRIBUTE_RIGHT_MARGIN
153 : : "ParaStyleName", // TEXT_ATTRIBUTE_STYLE_NAME
154 : : "ParaTabStops", // TEXT_ATTRIBUTE_TAB_STOPS
155 : : "ParaTopMargin", // TEXT_ATTRIBUTE_TOP_MARGIN
156 : : "WritingMode" // TEXT_ATTRIBUTE_WRITING_MODE
157 : : };
158 : :
159 : :
160 : : /*****************************************************************************/
161 : :
162 : : static gchar*
163 : 0 : get_value( const uno::Sequence< beans::PropertyValue >& rAttributeList,
164 : : sal_Int32 nIndex, AtkTextAttrFunc func )
165 : : {
166 : 0 : if( nIndex != -1 )
167 : 0 : return func(rAttributeList[nIndex].Value);
168 : :
169 : 0 : return NULL;
170 : : }
171 : :
172 : : #define get_bool_value( list, index ) get_value( list, index, Bool2String )
173 : : #define get_short_value( list, index ) get_value( list, index, Short2String )
174 : : #define get_height_value( list, index ) get_value( list, index, Float2String )
175 : : #define get_justification_value( list, index ) get_value( list, index, Adjust2Justification )
176 : : #define get_cmm_value( list, index ) get_value( list, index, CMM2UnitString )
177 : : #define get_scale_width( list, index ) get_value( list, index, Scale2String )
178 : : #define get_strikethrough_value( list, index ) get_value( list, index, Strikeout2String )
179 : : #define get_string_value( list, index ) get_value( list, index, GetString )
180 : : #define get_style_value( list, index ) get_value( list, index, FontSlant2Style )
181 : : #define get_underline_value( list, index ) get_value( list, index, Underline2String )
182 : : #define get_variant_value( list, index ) get_value( list, index, CaseMap2String )
183 : : #define get_weight_value( list, index ) get_value( list, index, Weight2String )
184 : : #define get_language_string( list, index ) get_value( list, index, Locale2String )
185 : :
186 : : static inline
187 : 0 : double toPoint(sal_Int16 n)
188 : : {
189 : : // 100th mm -> pt
190 : 0 : return (double) (n * 72) / 2540;
191 : : }
192 : :
193 : :
194 : : /*****************************************************************************/
195 : :
196 : : static bool
197 : 0 : InvalidValue( uno::Any&, const gchar * )
198 : : {
199 : 0 : return false;
200 : : }
201 : :
202 : : /*****************************************************************************/
203 : :
204 : : static gchar*
205 : 0 : Float2String(const uno::Any& rAny)
206 : : {
207 : 0 : return g_strdup_printf( "%g", rAny.get<float>() );
208 : : }
209 : :
210 : : static bool
211 : 0 : String2Float( uno::Any& rAny, const gchar * value )
212 : : {
213 : : float fval;
214 : :
215 : 0 : if( 1 != sscanf( value, "%g", &fval ) )
216 : 0 : return false;
217 : :
218 : 0 : rAny = uno::makeAny( fval );
219 : 0 : return true;
220 : : }
221 : :
222 : : /*****************************************************************************/
223 : :
224 : : static accessibility::XAccessibleComponent*
225 : 0 : getComponent( AtkText *pText ) throw (uno::RuntimeException)
226 : : {
227 : 0 : AtkObjectWrapper *pWrap = ATK_OBJECT_WRAPPER( pText );
228 : 0 : if( pWrap )
229 : : {
230 : 0 : if( !pWrap->mpComponent && pWrap->mpContext )
231 : : {
232 : 0 : uno::Any any = pWrap->mpContext->queryInterface( accessibility::XAccessibleComponent::static_type(NULL) );
233 : 0 : pWrap->mpComponent = reinterpret_cast< accessibility::XAccessibleComponent * > (any.pReserved);
234 : 0 : pWrap->mpComponent->acquire();
235 : : }
236 : :
237 : 0 : return pWrap->mpComponent;
238 : : }
239 : :
240 : 0 : return NULL;
241 : : }
242 : :
243 : : static gchar*
244 : 0 : get_color_value(const uno::Sequence< beans::PropertyValue >& rAttributeList,
245 : : const sal_Int32 * pIndexArray,
246 : : ExportedAttribute attr,
247 : : AtkText * text)
248 : : {
249 : 0 : sal_Int32 nColor = -1; // AUTOMATIC
250 : 0 : sal_Int32 nIndex = pIndexArray[attr];
251 : :
252 : 0 : if( nIndex != -1 )
253 : 0 : nColor = rAttributeList[nIndex].Value.get<sal_Int32>();
254 : :
255 : : /*
256 : : * Check for color value for 100% alpha white, which means
257 : : * "automatic". Grab the RGB value from XAccessibleComponent
258 : : * in this case.
259 : : */
260 : :
261 : 0 : if( (nColor == -1) && text )
262 : : {
263 : : try
264 : : {
265 : 0 : accessibility::XAccessibleComponent *pComponent = getComponent( text );
266 : 0 : if( pComponent )
267 : : {
268 : 0 : switch( attr )
269 : : {
270 : : case TEXT_ATTRIBUTE_BACKGROUND_COLOR:
271 : 0 : nColor = pComponent->getBackground();
272 : 0 : break;
273 : : case TEXT_ATTRIBUTE_FOREGROUND_COLOR:
274 : 0 : nColor = pComponent->getForeground();
275 : 0 : break;
276 : : default:
277 : 0 : break;
278 : : }
279 : : }
280 : : }
281 : :
282 : 0 : catch(const uno::Exception& e) {
283 : 0 : g_warning( "Exception in get[Fore|Back]groundColor()" );
284 : : }
285 : : }
286 : :
287 : 0 : if( nColor != -1 )
288 : : {
289 : 0 : sal_uInt8 blue = nColor & 0xFF;
290 : 0 : sal_uInt8 green = (nColor >> 8) & 0xFF;
291 : 0 : sal_uInt8 red = (nColor >> 16) & 0xFF;
292 : :
293 : 0 : return g_strdup_printf( "%u,%u,%u", red, green, blue );
294 : : }
295 : :
296 : 0 : return NULL;
297 : : }
298 : :
299 : : static bool
300 : 0 : String2Color( uno::Any& rAny, const gchar * value )
301 : : {
302 : : int red, green, blue;
303 : :
304 : 0 : if( 3 != sscanf( value, "%d,%d,%d", &red, &green, &blue ) )
305 : 0 : return false;
306 : :
307 : 0 : sal_Int32 nColor = (sal_Int32) blue | ( (sal_Int32) green << 8 ) | ( ( sal_Int32 ) red << 16 );
308 : 0 : rAny = uno::makeAny( nColor );
309 : 0 : return true;
310 : : }
311 : :
312 : : /*****************************************************************************/
313 : :
314 : : static gchar*
315 : 0 : FontSlant2Style(const uno::Any& rAny)
316 : : {
317 : 0 : const gchar * value = NULL;
318 : :
319 : 0 : switch( rAny.get<awt::FontSlant>() )
320 : : {
321 : : case awt::FontSlant_NONE:
322 : 0 : value = "normal";
323 : 0 : break;
324 : :
325 : : case awt::FontSlant_OBLIQUE:
326 : 0 : value = "oblique";
327 : 0 : break;
328 : :
329 : : case awt::FontSlant_ITALIC:
330 : 0 : value = "italic";
331 : 0 : break;
332 : :
333 : : case awt::FontSlant_REVERSE_OBLIQUE:
334 : 0 : value = "reverse oblique";
335 : 0 : break;
336 : :
337 : : case awt::FontSlant_REVERSE_ITALIC:
338 : 0 : value = "reverse italic";
339 : 0 : break;
340 : :
341 : : default:
342 : 0 : break;
343 : : }
344 : :
345 : 0 : if( value )
346 : 0 : return g_strdup( value );
347 : :
348 : 0 : return NULL;
349 : : }
350 : :
351 : : static bool
352 : 0 : Style2FontSlant( uno::Any& rAny, const gchar * value )
353 : : {
354 : : awt::FontSlant aFontSlant;
355 : :
356 : 0 : if( strncmp( value, STRNCMP_PARAM( "normal" ) ) )
357 : 0 : aFontSlant = awt::FontSlant_NONE;
358 : 0 : else if( strncmp( value, STRNCMP_PARAM( "oblique" ) ) )
359 : 0 : aFontSlant = awt::FontSlant_OBLIQUE;
360 : 0 : else if( strncmp( value, STRNCMP_PARAM( "italic" ) ) )
361 : 0 : aFontSlant = awt::FontSlant_ITALIC;
362 : 0 : else if( strncmp( value, STRNCMP_PARAM( "reverse oblique" ) ) )
363 : 0 : aFontSlant = awt::FontSlant_REVERSE_OBLIQUE;
364 : 0 : else if( strncmp( value, STRNCMP_PARAM( "reverse italic" ) ) )
365 : 0 : aFontSlant = awt::FontSlant_REVERSE_ITALIC;
366 : : else
367 : 0 : return false;
368 : :
369 : 0 : rAny = uno::makeAny( aFontSlant );
370 : 0 : return true;
371 : : }
372 : :
373 : : /*****************************************************************************/
374 : :
375 : : static gchar*
376 : 0 : Weight2String(const uno::Any& rAny)
377 : : {
378 : 0 : return g_strdup_printf( "%g", rAny.get<float>() * 4 );
379 : : }
380 : :
381 : : static bool
382 : 0 : String2Weight( uno::Any& rAny, const gchar * value )
383 : : {
384 : : float weight;
385 : :
386 : 0 : if( 1 != sscanf( value, "%g", &weight ) )
387 : 0 : return false;
388 : :
389 : 0 : rAny = uno::makeAny( weight / 4 );
390 : 0 : return true;
391 : : }
392 : :
393 : :
394 : : /*****************************************************************************/
395 : :
396 : : static gchar*
397 : 0 : Adjust2Justification(const uno::Any& rAny)
398 : : {
399 : 0 : const gchar * value = NULL;
400 : :
401 : 0 : switch( rAny.get<short>() )
402 : : {
403 : : case style::ParagraphAdjust_LEFT:
404 : 0 : value = "left";
405 : 0 : break;
406 : :
407 : : case style::ParagraphAdjust_RIGHT:
408 : 0 : value = "right";
409 : 0 : break;
410 : :
411 : : case style::ParagraphAdjust_BLOCK:
412 : : case style::ParagraphAdjust_STRETCH:
413 : 0 : value = "fill";
414 : 0 : break;
415 : :
416 : : case style::ParagraphAdjust_CENTER:
417 : 0 : value = "center";
418 : 0 : break;
419 : :
420 : : default:
421 : 0 : break;
422 : : }
423 : :
424 : 0 : if( value )
425 : 0 : return g_strdup( value );
426 : :
427 : 0 : return NULL;
428 : : }
429 : :
430 : : static bool
431 : 0 : Justification2Adjust( uno::Any& rAny, const gchar * value )
432 : : {
433 : : short nParagraphAdjust;
434 : :
435 : 0 : if( strncmp( value, STRNCMP_PARAM( "left" ) ) )
436 : 0 : nParagraphAdjust = style::ParagraphAdjust_LEFT;
437 : 0 : else if( strncmp( value, STRNCMP_PARAM( "right" ) ) )
438 : 0 : nParagraphAdjust = style::ParagraphAdjust_RIGHT;
439 : 0 : else if( strncmp( value, STRNCMP_PARAM( "fill" ) ) )
440 : 0 : nParagraphAdjust = style::ParagraphAdjust_BLOCK;
441 : 0 : else if( strncmp( value, STRNCMP_PARAM( "center" ) ) )
442 : 0 : nParagraphAdjust = style::ParagraphAdjust_CENTER;
443 : : else
444 : 0 : return false;
445 : :
446 : 0 : rAny = uno::makeAny( nParagraphAdjust );
447 : 0 : return true;
448 : : }
449 : :
450 : : /*****************************************************************************/
451 : :
452 : : const gchar * font_strikethrough[] = {
453 : : "none", // FontStrikeout::NONE
454 : : "single", // FontStrikeout::SINGLE
455 : : "double", // FontStrikeout::DOUBLE
456 : : NULL, // FontStrikeout::DONTKNOW
457 : : "bold", // FontStrikeout::BOLD
458 : : "with /", // FontStrikeout::SLASH
459 : : "with X" // FontStrikeout::X
460 : : };
461 : :
462 : : const sal_Int16 n_strikeout_constants = sizeof(font_strikethrough) / sizeof(gchar*);
463 : :
464 : : static gchar*
465 : 0 : Strikeout2String(const uno::Any& rAny)
466 : : {
467 : 0 : sal_Int16 n = rAny.get<sal_Int16>();
468 : :
469 : 0 : if( n >= 0 && n < n_strikeout_constants )
470 : 0 : return g_strdup( font_strikethrough[n] );
471 : :
472 : 0 : return NULL;
473 : : }
474 : :
475 : : static bool
476 : 0 : String2Strikeout( uno::Any& rAny, const gchar * value )
477 : : {
478 : 0 : for( sal_Int16 n=0; n < n_strikeout_constants; ++n )
479 : : {
480 : 0 : if( ( NULL != font_strikethrough[n] ) &&
481 : 0 : 0 == strncmp( value, font_strikethrough[n], strlen( font_strikethrough[n] ) ) )
482 : : {
483 : 0 : rAny = uno::makeAny( n );
484 : 0 : return true;
485 : : }
486 : : }
487 : :
488 : 0 : return false;
489 : : }
490 : :
491 : : /*****************************************************************************/
492 : :
493 : : static gchar*
494 : 0 : Underline2String(const uno::Any& rAny)
495 : : {
496 : 0 : const gchar * value = NULL;
497 : :
498 : 0 : switch( rAny.get<sal_Int16>() )
499 : : {
500 : : case awt::FontUnderline::NONE:
501 : 0 : value = "none";
502 : 0 : break;
503 : :
504 : : case awt::FontUnderline::SINGLE:
505 : 0 : value = "single";
506 : 0 : break;
507 : :
508 : : case awt::FontUnderline::DOUBLE:
509 : 0 : value = "double";
510 : 0 : break;
511 : :
512 : : default:
513 : 0 : break;
514 : : }
515 : :
516 : 0 : if( value )
517 : 0 : return g_strdup( value );
518 : :
519 : 0 : return NULL;
520 : : }
521 : :
522 : : static bool
523 : 0 : String2Underline( uno::Any& rAny, const gchar * value )
524 : : {
525 : : short nUnderline;
526 : :
527 : 0 : if( strncmp( value, STRNCMP_PARAM( "none" ) ) )
528 : 0 : nUnderline = awt::FontUnderline::NONE;
529 : 0 : else if( strncmp( value, STRNCMP_PARAM( "single" ) ) )
530 : 0 : nUnderline = awt::FontUnderline::SINGLE;
531 : 0 : else if( strncmp( value, STRNCMP_PARAM( "double" ) ) )
532 : 0 : nUnderline = awt::FontUnderline::DOUBLE;
533 : : else
534 : 0 : return false;
535 : :
536 : 0 : rAny = uno::makeAny( nUnderline );
537 : 0 : return true;
538 : : }
539 : :
540 : : /*****************************************************************************/
541 : :
542 : : static gchar*
543 : 0 : GetString(const uno::Any& rAny)
544 : : {
545 : 0 : rtl::OString aFontName = rtl::OUStringToOString( rAny.get< rtl::OUString > (), RTL_TEXTENCODING_UTF8 );
546 : :
547 : 0 : if( !aFontName.isEmpty() )
548 : 0 : return g_strdup( aFontName.getStr() );
549 : :
550 : 0 : return NULL;
551 : : }
552 : :
553 : : static bool
554 : 0 : SetString( uno::Any& rAny, const gchar * value )
555 : : {
556 : 0 : rtl::OString aFontName( value );
557 : :
558 : 0 : if( !aFontName.isEmpty() )
559 : : {
560 : 0 : rAny = uno::makeAny( rtl::OStringToOUString( aFontName, RTL_TEXTENCODING_UTF8 ) );
561 : 0 : return true;
562 : : }
563 : :
564 : 0 : return false;
565 : : }
566 : :
567 : : /*****************************************************************************/
568 : :
569 : : // @see http://developer.gnome.org/doc/API/2.0/atk/AtkText.html#AtkTextAttribute
570 : :
571 : : // CMM = 100th of mm
572 : : static gchar*
573 : 0 : CMM2UnitString(const uno::Any& rAny)
574 : : {
575 : 0 : double fValue = rAny.get<sal_Int32>();
576 : 0 : fValue = fValue * 0.01;
577 : :
578 : 0 : return g_strdup_printf( "%gmm", fValue );
579 : : }
580 : :
581 : : static bool
582 : 0 : UnitString2CMM( uno::Any& rAny, const gchar * value )
583 : : {
584 : 0 : float fValue = 0.0; // pb: dont use double here because of warning on linux
585 : :
586 : 0 : if( 1 != sscanf( value, "%gmm", &fValue ) )
587 : 0 : return false;
588 : :
589 : 0 : fValue = fValue * 100;
590 : :
591 : 0 : rAny = uno::makeAny( (sal_Int32) fValue);
592 : 0 : return true;
593 : : }
594 : :
595 : : /*****************************************************************************/
596 : :
597 : : static const gchar * bool_values[] = { "true", "false" };
598 : :
599 : : static gchar *
600 : 0 : Bool2String( const uno::Any& rAny )
601 : : {
602 : 0 : int n = 1;
603 : :
604 : 0 : if( rAny.get<sal_Bool>() )
605 : 0 : n = 0;
606 : :
607 : 0 : return g_strdup( bool_values[n] );
608 : : }
609 : :
610 : : static bool
611 : 0 : String2Bool( uno::Any& rAny, const gchar * value )
612 : : {
613 : : sal_Bool bValue;
614 : :
615 : 0 : if( strncmp( value, STRNCMP_PARAM( "true" ) ) )
616 : 0 : bValue = sal_True;
617 : 0 : else if( strncmp( value, STRNCMP_PARAM( "false" ) ) )
618 : 0 : bValue = sal_False;
619 : : else
620 : 0 : return false;
621 : :
622 : 0 : rAny = uno::makeAny(bValue);
623 : 0 : return true;
624 : : }
625 : :
626 : : /*****************************************************************************/
627 : :
628 : : static gchar*
629 : 0 : Scale2String( const uno::Any& rAny )
630 : : {
631 : 0 : return g_strdup_printf( "%g", (double) (rAny.get< sal_Int16 > ()) / 100 );
632 : : }
633 : :
634 : : static bool
635 : 0 : String2Scale( uno::Any& rAny, const gchar * value )
636 : : {
637 : : double dval;
638 : :
639 : 0 : if( 1 != sscanf( value, "%lg", &dval ) )
640 : 0 : return false;
641 : :
642 : 0 : rAny = uno::makeAny((sal_Int16) (dval * 100));
643 : 0 : return true;
644 : : }
645 : :
646 : : /*****************************************************************************/
647 : :
648 : : static gchar *
649 : 0 : CaseMap2String( const uno::Any& rAny )
650 : : {
651 : 0 : const gchar * value = NULL;
652 : :
653 : 0 : switch( rAny.get<short>() )
654 : : {
655 : : case style::CaseMap::SMALLCAPS:
656 : 0 : value = "small_caps";
657 : 0 : break;
658 : :
659 : : default:
660 : 0 : value = "normal";
661 : 0 : break;
662 : : }
663 : :
664 : 0 : if( value )
665 : 0 : return g_strdup( value );
666 : :
667 : 0 : return NULL;
668 : : }
669 : :
670 : : static bool
671 : 0 : String2CaseMap( uno::Any& rAny, const gchar * value )
672 : : {
673 : : short nCaseMap;
674 : :
675 : 0 : if( strncmp( value, STRNCMP_PARAM( "normal" ) ) )
676 : 0 : nCaseMap = style::CaseMap::NONE;
677 : 0 : else if( strncmp( value, STRNCMP_PARAM( "small_caps" ) ) )
678 : 0 : nCaseMap = style::CaseMap::SMALLCAPS;
679 : : else
680 : 0 : return false;
681 : :
682 : 0 : rAny = uno::makeAny( nCaseMap );
683 : 0 : return true;
684 : : }
685 : :
686 : : /*****************************************************************************/
687 : :
688 : : const gchar * font_stretch[] = {
689 : : "ultra_condensed",
690 : : "extra_condensed",
691 : : "condensed",
692 : : "semi_condensed",
693 : : "normal",
694 : : "semi_expanded",
695 : : "expanded",
696 : : "extra_expanded",
697 : : "ultra_expanded"
698 : : };
699 : :
700 : : static gchar*
701 : 0 : Kerning2Stretch(const uno::Any& rAny)
702 : : {
703 : 0 : sal_Int16 n = rAny.get<sal_Int16>();
704 : 0 : int i = 4;
705 : :
706 : : // No good idea for a mapping - just return the basic info
707 : 0 : if( n < 0 )
708 : 0 : i=2;
709 : 0 : else if( n > 0 )
710 : 0 : i=6;
711 : :
712 : 0 : return g_strdup(font_stretch[i]);
713 : : }
714 : :
715 : : /*****************************************************************************/
716 : :
717 : : static gchar*
718 : 0 : Locale2String(const uno::Any& rAny)
719 : : {
720 : 0 : lang::Locale aLocale = rAny.get<lang::Locale> ();
721 : : return g_strdup_printf( "%s-%s",
722 : : rtl::OUStringToOString( aLocale.Language, RTL_TEXTENCODING_ASCII_US).getStr(),
723 : 0 : rtl::OUStringToOString( aLocale.Country, RTL_TEXTENCODING_ASCII_US).toAsciiLowerCase().getStr() );
724 : : }
725 : :
726 : : static bool
727 : 0 : String2Locale( uno::Any& rAny, const gchar * value )
728 : : {
729 : 0 : bool ret = false;
730 : :
731 : 0 : gchar ** str_array = g_strsplit_set( value, "-.@", -1 );
732 : 0 : if( str_array[0] != NULL )
733 : : {
734 : 0 : ret = true;
735 : :
736 : 0 : lang::Locale aLocale;
737 : :
738 : 0 : aLocale.Language = rtl::OUString::createFromAscii(str_array[0]);
739 : 0 : if( str_array[1] != NULL )
740 : : {
741 : 0 : gchar * country = g_ascii_strup(str_array[1], -1);
742 : 0 : aLocale.Country = rtl::OUString::createFromAscii(country);
743 : 0 : g_free(country);
744 : : }
745 : :
746 : 0 : rAny = uno::makeAny(aLocale);
747 : : }
748 : :
749 : 0 : g_strfreev(str_array);
750 : 0 : return ret;
751 : : }
752 : :
753 : : /*****************************************************************************/
754 : :
755 : : // @see http://www.w3.org/TR/2002/WD-css3-fonts-20020802/#font-effect-prop
756 : : static const gchar * relief[] = { "none", "emboss", "engrave" };
757 : : static const gchar * outline = "outline";
758 : :
759 : : static gchar *
760 : 0 : get_font_effect(const uno::Sequence< beans::PropertyValue >& rAttributeList,
761 : : sal_Int32 nContourIndex, sal_Int32 nReliefIndex)
762 : : {
763 : 0 : if( nContourIndex != -1 )
764 : : {
765 : 0 : if( rAttributeList[nContourIndex].Value.get<sal_Bool>() )
766 : 0 : return g_strdup(outline);
767 : : }
768 : :
769 : 0 : if( nReliefIndex != -1 )
770 : : {
771 : 0 : sal_Int16 n = rAttributeList[nReliefIndex].Value.get<sal_Int16>();
772 : 0 : if( n < 3)
773 : 0 : return g_strdup(relief[n]);
774 : : }
775 : :
776 : 0 : return NULL;
777 : : }
778 : :
779 : : /*****************************************************************************/
780 : :
781 : : // @see http://www.w3.org/TR/REC-CSS2/text.html#lining-striking-props
782 : :
783 : :
784 : : enum
785 : : {
786 : : DECORATION_NONE = 0,
787 : : DECORATION_BLINK,
788 : : DECORATION_UNDERLINE,
789 : : DECORATION_LINE_THROUGH
790 : : };
791 : :
792 : :
793 : : static const gchar * decorations[] = { "none", "blink", "underline", "line-through" };
794 : :
795 : : static gchar *
796 : 0 : get_text_decoration(const uno::Sequence< beans::PropertyValue >& rAttributeList,
797 : : sal_Int32 nBlinkIndex, sal_Int32 nUnderlineIndex,
798 : : sal_Int16 nStrikeoutIndex)
799 : : {
800 : 0 : gchar * value_list[4] = { NULL, NULL, NULL, NULL };
801 : 0 : gint count = 0;
802 : :
803 : : // no property value found
804 : 0 : if( ( nBlinkIndex == -1 ) && (nUnderlineIndex == -1 ) && (nStrikeoutIndex == -1))
805 : 0 : return NULL;
806 : :
807 : 0 : if( nBlinkIndex != -1 )
808 : : {
809 : 0 : if( rAttributeList[nBlinkIndex].Value.get<sal_Bool>() )
810 : 0 : value_list[count++] = const_cast <gchar *> (decorations[DECORATION_BLINK]);
811 : : }
812 : 0 : if( nUnderlineIndex != -1 )
813 : : {
814 : 0 : sal_Int16 n = rAttributeList[nUnderlineIndex].Value.get<sal_Int16> ();
815 : 0 : if( n != awt::FontUnderline::NONE )
816 : 0 : value_list[count++] = const_cast <gchar *> (decorations[DECORATION_UNDERLINE]);
817 : : }
818 : 0 : if( nStrikeoutIndex != -1 )
819 : : {
820 : 0 : sal_Int16 n = rAttributeList[nStrikeoutIndex].Value.get<sal_Int16> ();
821 : 0 : if( n != awt::FontStrikeout::NONE && n != awt::FontStrikeout::DONTKNOW )
822 : 0 : value_list[count++] = const_cast <gchar *> (decorations[DECORATION_LINE_THROUGH]);
823 : : }
824 : :
825 : 0 : if( count == 0 )
826 : 0 : value_list[count++] = const_cast <gchar *> (decorations[DECORATION_NONE]);
827 : :
828 : 0 : return g_strjoinv(" ", value_list);
829 : : }
830 : :
831 : :
832 : : /*****************************************************************************/
833 : :
834 : : // @see http://www.w3.org/TR/REC-CSS2/text.html#propdef-text-shadow
835 : :
836 : : static const gchar * shadow_values[] = { "none", "black" };
837 : :
838 : : static gchar *
839 : 0 : Bool2Shadow( const uno::Any& rAny )
840 : : {
841 : 0 : int n = 0;
842 : :
843 : 0 : if( rAny.get<sal_Bool>() )
844 : 0 : n = 1;
845 : :
846 : 0 : return g_strdup( shadow_values[n] );
847 : : }
848 : :
849 : : /*****************************************************************************/
850 : :
851 : : static gchar *
852 : 0 : Short2Degree( const uno::Any& rAny )
853 : : {
854 : 0 : float f = rAny.get<sal_Int16>() / 10;
855 : 0 : return g_strdup_printf( "%g", f );
856 : : }
857 : :
858 : : /*****************************************************************************/
859 : :
860 : : const gchar * directions[] = { "ltr", "rtl", "rtl", "ltr", "none" };
861 : :
862 : : static gchar *
863 : 0 : WritingMode2Direction( const uno::Any& rAny )
864 : : {
865 : 0 : sal_Int16 n = rAny.get<sal_Int16>();
866 : :
867 : 0 : if( 0 <= n && n <= text::WritingMode2::PAGE )
868 : 0 : return g_strdup(directions[n]);
869 : :
870 : 0 : return NULL;
871 : : }
872 : :
873 : : // @see http://www.w3.org/TR/2001/WD-css3-text-20010517/#PrimaryTextAdvanceDirection
874 : :
875 : : const gchar * writing_modes[] = { "lr-tb", "rl-tb", "tb-rl", "tb-lr", "none" };
876 : : static gchar *
877 : 0 : WritingMode2String( const uno::Any& rAny )
878 : : {
879 : 0 : sal_Int16 n = rAny.get<sal_Int16>();
880 : :
881 : 0 : if( 0 <= n && n <= text::WritingMode2::PAGE )
882 : 0 : return g_strdup(writing_modes[n]);
883 : :
884 : 0 : return NULL;
885 : : }
886 : :
887 : : /*****************************************************************************/
888 : :
889 : : const char * baseline_values[] = { "baseline", "sub", "super" };
890 : :
891 : : // @see http://www.w3.org/TR/REC-CSS2/visudet.html#propdef-vertical-align
892 : : static gchar *
893 : 0 : Escapement2VerticalAlign( const uno::Any& rAny )
894 : : {
895 : 0 : sal_Int16 n = rAny.get<sal_Int16>();
896 : 0 : gchar * ret = NULL;
897 : :
898 : : // Values are in %, 101% means "automatic"
899 : 0 : if( n == 0 )
900 : 0 : ret = g_strdup(baseline_values[0]);
901 : 0 : else if( n == 101 )
902 : 0 : ret = g_strdup(baseline_values[2]);
903 : 0 : else if( n == -101 )
904 : 0 : ret = g_strdup(baseline_values[1]);
905 : : else
906 : 0 : ret = g_strdup_printf( "%d%%", n );
907 : :
908 : 0 : return ret;
909 : : }
910 : :
911 : : /*****************************************************************************/
912 : :
913 : : // @see http://www.w3.org/TR/REC-CSS2/visudet.html#propdef-line-height
914 : : static gchar *
915 : 0 : LineSpacing2LineHeight( const uno::Any& rAny )
916 : : {
917 : 0 : style::LineSpacing ls;
918 : 0 : gchar * ret = NULL;
919 : :
920 : 0 : if( rAny >>= ls )
921 : : {
922 : 0 : if( ls.Mode == style::LineSpacingMode::PROP )
923 : 0 : ret = g_strdup_printf( "%d%%", ls.Height );
924 : 0 : else if( ls.Mode == style::LineSpacingMode::FIX )
925 : 0 : ret = g_strdup_printf( "%.3gpt", toPoint(ls.Height) );
926 : : }
927 : :
928 : 0 : return ret;
929 : : }
930 : :
931 : : /*****************************************************************************/
932 : :
933 : : // @see http://www.w3.org/People/howcome/t/970224HTMLERB-CSS/WD-tabs-970117.html
934 : : static gchar *
935 : 0 : TabStopList2String( const uno::Any& rAny, bool default_tabs )
936 : : {
937 : 0 : uno::Sequence< style::TabStop > theTabStops;
938 : 0 : gchar * ret = NULL;
939 : :
940 : 0 : if( rAny >>= theTabStops)
941 : : {
942 : 0 : sal_Int32 indexOfTab = 0;
943 : 0 : sal_Int32 numberOfTabs = theTabStops.getLength();
944 : 0 : sal_Unicode lastFillChar = (sal_Unicode) ' ';
945 : :
946 : 0 : for( ; indexOfTab < numberOfTabs; ++indexOfTab )
947 : : {
948 : 0 : bool is_default_tab = (style::TabAlign_DEFAULT == theTabStops[indexOfTab].Alignment);
949 : :
950 : 0 : if( is_default_tab != default_tabs )
951 : 0 : continue;
952 : :
953 : 0 : double fValue = theTabStops[indexOfTab].Position;
954 : 0 : fValue = fValue * 0.01;
955 : :
956 : 0 : const gchar * tab_align = "";
957 : 0 : switch( theTabStops[indexOfTab].Alignment )
958 : : {
959 : : case style::TabAlign_LEFT :
960 : 0 : tab_align = "left ";
961 : 0 : break;
962 : : case style::TabAlign_CENTER :
963 : 0 : tab_align = "center ";
964 : 0 : break;
965 : : case style::TabAlign_RIGHT :
966 : 0 : tab_align = "right ";
967 : 0 : break;
968 : : case style::TabAlign_DECIMAL :
969 : 0 : tab_align = "decimal ";
970 : 0 : break;
971 : : default:
972 : 0 : break;
973 : : }
974 : :
975 : 0 : const gchar * lead_char = "";
976 : :
977 : 0 : if( theTabStops[indexOfTab].FillChar != lastFillChar )
978 : : {
979 : 0 : lastFillChar = theTabStops[indexOfTab].FillChar;
980 : 0 : switch (lastFillChar)
981 : : {
982 : : case (sal_Unicode) ' ':
983 : 0 : lead_char = "blank ";
984 : 0 : break;
985 : :
986 : : case (sal_Unicode) '.':
987 : 0 : lead_char = "dotted ";
988 : 0 : break;
989 : :
990 : : case (sal_Unicode) '-':
991 : 0 : lead_char = "dashed ";
992 : 0 : break;
993 : :
994 : : case (sal_Unicode) '_':
995 : 0 : lead_char = "lined ";
996 : 0 : break;
997 : :
998 : : default:
999 : 0 : lead_char = "custom ";
1000 : 0 : break;
1001 : : }
1002 : : }
1003 : :
1004 : 0 : gchar * tab_str = g_strdup_printf( "%s%s%gmm", lead_char, tab_align, fValue );
1005 : :
1006 : 0 : if( ret )
1007 : : {
1008 : 0 : gchar * old_tab_str = ret;
1009 : 0 : ret = g_strconcat(old_tab_str, " ", tab_str, (const char*)NULL);
1010 : 0 : g_free( old_tab_str );
1011 : : }
1012 : : else
1013 : 0 : ret = tab_str;
1014 : : }
1015 : : }
1016 : :
1017 : 0 : return ret;
1018 : : }
1019 : :
1020 : : static gchar *
1021 : 0 : TabStops2String( const uno::Any& rAny )
1022 : : {
1023 : 0 : return TabStopList2String(rAny, false);
1024 : : }
1025 : :
1026 : : static gchar *
1027 : 0 : DefaultTabStops2String( const uno::Any& rAny )
1028 : : {
1029 : 0 : return TabStopList2String(rAny, true);
1030 : : }
1031 : :
1032 : : /*****************************************************************************/
1033 : :
1034 : : extern "C" int
1035 : 0 : attr_compare(const void *p1,const void *p2)
1036 : : {
1037 : 0 : const rtl_uString * pustr = (const rtl_uString *) p1;
1038 : 0 : const char * pc = *((const char **) p2);
1039 : :
1040 : 0 : return rtl_ustr_ascii_compare_WithLength(pustr->buffer, pustr->length, pc);
1041 : : }
1042 : :
1043 : : static void
1044 : 0 : find_exported_attributes( sal_Int32 *pArray,
1045 : : const com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValue >& rAttributeList )
1046 : : {
1047 : 0 : for( sal_Int32 i = 0; i < rAttributeList.getLength(); i++ )
1048 : : {
1049 : 0 : const char ** pAttr = (const char **) bsearch(rAttributeList[i].Name.pData,
1050 : : ExportedTextAttributes, TEXT_ATTRIBUTE_LAST, sizeof(const char *),
1051 : 0 : attr_compare);
1052 : :
1053 : 0 : if( pAttr )
1054 : : {
1055 : 0 : sal_Int32 nIndex = pAttr - ExportedTextAttributes;
1056 : 0 : pArray[nIndex] = i;
1057 : : }
1058 : : }
1059 : 0 : }
1060 : :
1061 : : /*****************************************************************************/
1062 : :
1063 : : static AtkAttributeSet*
1064 : 0 : attribute_set_prepend( AtkAttributeSet* attribute_set,
1065 : : AtkTextAttribute attribute,
1066 : : gchar * value )
1067 : : {
1068 : 0 : if( value )
1069 : : {
1070 : 0 : AtkAttribute *at = (AtkAttribute *) g_malloc( sizeof (AtkAttribute) );
1071 : 0 : at->name = g_strdup( atk_text_attribute_get_name( attribute ) );
1072 : 0 : at->value = value;
1073 : :
1074 : 0 : return g_slist_prepend(attribute_set, at);
1075 : : }
1076 : :
1077 : 0 : return attribute_set;
1078 : : }
1079 : :
1080 : : /*****************************************************************************/
1081 : :
1082 : : AtkAttributeSet*
1083 : 0 : attribute_set_new_from_property_values(
1084 : : const uno::Sequence< beans::PropertyValue >& rAttributeList,
1085 : : bool run_attributes_only,
1086 : : AtkText *text)
1087 : : {
1088 : 0 : AtkAttributeSet* attribute_set = NULL;
1089 : :
1090 : 0 : sal_Int32 aIndexList[TEXT_ATTRIBUTE_LAST] = { -1 };
1091 : :
1092 : : // Initialize index array with -1
1093 : 0 : for( sal_Int32 attr = 0; attr < TEXT_ATTRIBUTE_LAST; ++attr )
1094 : 0 : aIndexList[attr] = -1;
1095 : :
1096 : 0 : find_exported_attributes(aIndexList, rAttributeList);
1097 : :
1098 : : attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_BG_COLOR,
1099 : 0 : get_color_value(rAttributeList, aIndexList, TEXT_ATTRIBUTE_BACKGROUND_COLOR, run_attributes_only ? NULL : text ) );
1100 : :
1101 : : attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_FG_COLOR,
1102 : 0 : get_color_value(rAttributeList, aIndexList, TEXT_ATTRIBUTE_FOREGROUND_COLOR, run_attributes_only ? NULL : text) );
1103 : :
1104 : : attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_INVISIBLE,
1105 : 0 : get_bool_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_HIDDEN]));
1106 : :
1107 : : attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_UNDERLINE,
1108 : 0 : get_underline_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_UNDERLINE]));
1109 : :
1110 : : attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_STRIKETHROUGH,
1111 : 0 : get_strikethrough_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_STRIKETHROUGH]));
1112 : :
1113 : : attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_SIZE,
1114 : 0 : get_height_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_HEIGHT]));
1115 : :
1116 : : attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_WEIGHT,
1117 : 0 : get_weight_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_WEIGHT]));
1118 : :
1119 : : attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_FAMILY_NAME,
1120 : 0 : get_string_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_FONT_NAME]));
1121 : :
1122 : : attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_VARIANT,
1123 : 0 : get_variant_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_CASEMAP]));
1124 : :
1125 : : attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_STYLE,
1126 : 0 : get_style_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_POSTURE]));
1127 : :
1128 : : attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_SCALE,
1129 : 0 : get_scale_width(rAttributeList, aIndexList[TEXT_ATTRIBUTE_SCALE]));
1130 : :
1131 : : attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_LANGUAGE,
1132 : 0 : get_language_string(rAttributeList, aIndexList[TEXT_ATTRIBUTE_LOCALE]));
1133 : :
1134 : : attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_DIRECTION,
1135 : 0 : get_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_WRITING_MODE], WritingMode2Direction));
1136 : :
1137 : : attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_STRETCH,
1138 : 0 : get_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_KERNING], Kerning2Stretch));
1139 : :
1140 : 0 : if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_font_effect )
1141 : 0 : atk_text_attribute_font_effect = atk_text_attribute_register("font-effect");
1142 : :
1143 : : attribute_set = attribute_set_prepend(attribute_set, atk_text_attribute_font_effect,
1144 : 0 : get_font_effect(rAttributeList, aIndexList[TEXT_ATTRIBUTE_CONTOURED], aIndexList[TEXT_ATTRIBUTE_RELIEF]));
1145 : :
1146 : 0 : if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_decoration )
1147 : 0 : atk_text_attribute_decoration = atk_text_attribute_register("text-decoration");
1148 : :
1149 : : attribute_set = attribute_set_prepend(attribute_set, atk_text_attribute_decoration,
1150 : : get_text_decoration(rAttributeList, aIndexList[TEXT_ATTRIBUTE_BLINKING],
1151 : 0 : aIndexList[TEXT_ATTRIBUTE_UNDERLINE], aIndexList[TEXT_ATTRIBUTE_STRIKETHROUGH]));
1152 : :
1153 : 0 : if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_rotation )
1154 : 0 : atk_text_attribute_rotation = atk_text_attribute_register("text-rotation");
1155 : :
1156 : : attribute_set = attribute_set_prepend(attribute_set, atk_text_attribute_rotation,
1157 : 0 : get_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_ROTATION], Short2Degree));
1158 : :
1159 : 0 : if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_shadow )
1160 : 0 : atk_text_attribute_shadow = atk_text_attribute_register("text-shadow");
1161 : :
1162 : : attribute_set = attribute_set_prepend(attribute_set, atk_text_attribute_shadow,
1163 : 0 : get_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_SHADOWED], Bool2Shadow));
1164 : :
1165 : 0 : if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_writing_mode )
1166 : 0 : atk_text_attribute_writing_mode = atk_text_attribute_register("writing-mode");
1167 : :
1168 : : attribute_set = attribute_set_prepend(attribute_set, atk_text_attribute_writing_mode,
1169 : 0 : get_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_WRITING_MODE], WritingMode2String));
1170 : :
1171 : 0 : if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_vertical_align )
1172 : 0 : atk_text_attribute_vertical_align = atk_text_attribute_register("vertical-align");
1173 : :
1174 : : attribute_set = attribute_set_prepend(attribute_set, atk_text_attribute_vertical_align,
1175 : 0 : get_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_CHAR_ESCAPEMENT], Escapement2VerticalAlign));
1176 : :
1177 : 0 : if( run_attributes_only )
1178 : 0 : return attribute_set;
1179 : :
1180 : : attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_LEFT_MARGIN,
1181 : 0 : get_cmm_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_LEFT_MARGIN]));
1182 : :
1183 : : attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_RIGHT_MARGIN,
1184 : 0 : get_cmm_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_RIGHT_MARGIN]));
1185 : :
1186 : : attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_INDENT,
1187 : 0 : get_cmm_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_FIRST_LINE_INDENT]));
1188 : :
1189 : : attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_PIXELS_ABOVE_LINES,
1190 : 0 : get_cmm_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_TOP_MARGIN]));
1191 : :
1192 : : attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_PIXELS_BELOW_LINES,
1193 : 0 : get_cmm_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_BOTTOM_MARGIN]));
1194 : :
1195 : : attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_JUSTIFICATION,
1196 : 0 : get_justification_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_JUSTIFICATION]));
1197 : :
1198 : 0 : if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_paragraph_style )
1199 : 0 : atk_text_attribute_paragraph_style = atk_text_attribute_register("paragraph-style");
1200 : :
1201 : : attribute_set = attribute_set_prepend(attribute_set, atk_text_attribute_paragraph_style,
1202 : 0 : get_string_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_STYLE_NAME]));
1203 : :
1204 : 0 : if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_line_height )
1205 : 0 : atk_text_attribute_line_height = atk_text_attribute_register("line-height");
1206 : :
1207 : : attribute_set = attribute_set_prepend(attribute_set, atk_text_attribute_line_height,
1208 : 0 : get_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_LINE_SPACING], LineSpacing2LineHeight));
1209 : :
1210 : 0 : if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_tab_interval )
1211 : 0 : atk_text_attribute_tab_interval = atk_text_attribute_register("tab-interval");
1212 : :
1213 : : attribute_set = attribute_set_prepend(attribute_set, atk_text_attribute_tab_interval,
1214 : 0 : get_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_TAB_STOPS], DefaultTabStops2String));
1215 : :
1216 : 0 : if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_tab_stops )
1217 : 0 : atk_text_attribute_tab_stops = atk_text_attribute_register("tab-stops");
1218 : :
1219 : : attribute_set = attribute_set_prepend(attribute_set, atk_text_attribute_tab_stops,
1220 : 0 : get_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_TAB_STOPS], TabStops2String));
1221 : :
1222 : : // #i92233#
1223 : 0 : if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_mm_to_pixel_ratio )
1224 : 0 : atk_text_attribute_mm_to_pixel_ratio = atk_text_attribute_register("mm-to-pixel-ratio");
1225 : :
1226 : : attribute_set = attribute_set_prepend( attribute_set, atk_text_attribute_mm_to_pixel_ratio,
1227 : 0 : get_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_MM_TO_PIXEL_RATIO], Float2String));
1228 : :
1229 : 0 : return attribute_set;
1230 : : }
1231 : :
1232 : :
1233 : 0 : AtkAttributeSet* attribute_set_prepend_misspelled( AtkAttributeSet* attribute_set )
1234 : : {
1235 : 0 : if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_misspelled )
1236 : 0 : atk_text_attribute_misspelled = atk_text_attribute_register( "text-spelling" );
1237 : :
1238 : : attribute_set = attribute_set_prepend( attribute_set, atk_text_attribute_misspelled,
1239 : 0 : g_strdup_printf( "misspelled" ) );
1240 : :
1241 : 0 : return attribute_set;
1242 : : }
1243 : :
1244 : : // #i92232#
1245 : 0 : AtkAttributeSet* attribute_set_prepend_tracked_change_insertion( AtkAttributeSet* attribute_set )
1246 : : {
1247 : 0 : if ( ATK_TEXT_ATTR_INVALID == atk_text_attribute_tracked_change )
1248 : : {
1249 : 0 : atk_text_attribute_tracked_change = atk_text_attribute_register( "text-tracked-change" );
1250 : : }
1251 : :
1252 : : attribute_set = attribute_set_prepend( attribute_set,
1253 : : atk_text_attribute_tracked_change,
1254 : 0 : g_strdup_printf( "insertion" ) );
1255 : :
1256 : 0 : return attribute_set;
1257 : : }
1258 : :
1259 : 0 : AtkAttributeSet* attribute_set_prepend_tracked_change_deletion( AtkAttributeSet* attribute_set )
1260 : : {
1261 : 0 : if ( ATK_TEXT_ATTR_INVALID == atk_text_attribute_tracked_change )
1262 : : {
1263 : 0 : atk_text_attribute_tracked_change = atk_text_attribute_register( "text-tracked-change" );
1264 : : }
1265 : :
1266 : : attribute_set = attribute_set_prepend( attribute_set,
1267 : : atk_text_attribute_tracked_change,
1268 : 0 : g_strdup_printf( "deletion" ) );
1269 : :
1270 : 0 : return attribute_set;
1271 : : }
1272 : :
1273 : 0 : AtkAttributeSet* attribute_set_prepend_tracked_change_formatchange( AtkAttributeSet* attribute_set )
1274 : : {
1275 : 0 : if ( ATK_TEXT_ATTR_INVALID == atk_text_attribute_tracked_change )
1276 : : {
1277 : 0 : atk_text_attribute_tracked_change = atk_text_attribute_register( "text-tracked-change" );
1278 : : }
1279 : :
1280 : : attribute_set = attribute_set_prepend( attribute_set,
1281 : : atk_text_attribute_tracked_change,
1282 : 0 : g_strdup_printf( "attribute-change" ) );
1283 : :
1284 : 0 : return attribute_set;
1285 : : }
1286 : :
1287 : : /*****************************************************************************/
1288 : :
1289 : : struct AtkTextAttrMapping
1290 : : {
1291 : : const char * name;
1292 : : TextPropertyValueFunc toPropertyValue;
1293 : : };
1294 : :
1295 : : const AtkTextAttrMapping g_TextAttrMap[] =
1296 : : {
1297 : : { "", InvalidValue }, // ATK_TEXT_ATTR_INVALID = 0
1298 : : { "ParaLeftMargin", UnitString2CMM }, // ATK_TEXT_ATTR_LEFT_MARGIN
1299 : : { "ParaRightMargin", UnitString2CMM }, // ATK_TEXT_ATTR_RIGHT_MARGIN
1300 : : { "ParaFirstLineIndent", UnitString2CMM }, // ATK_TEXT_ATTR_INDENT
1301 : : { "CharHidden", String2Bool }, // ATK_TEXT_ATTR_INVISIBLE
1302 : : { "", InvalidValue }, // ATK_TEXT_ATTR_EDITABLE
1303 : : { "ParaTopMargin", UnitString2CMM }, // ATK_TEXT_ATTR_PIXELS_ABOVE_LINES
1304 : : { "ParaBottomMargin", UnitString2CMM }, // ATK_TEXT_ATTR_PIXELS_BELOW_LINES
1305 : : { "", InvalidValue }, // ATK_TEXT_ATTR_PIXELS_INSIDE_WRAP
1306 : : { "", InvalidValue }, // ATK_TEXT_ATTR_BG_FULL_HEIGHT
1307 : : { "", InvalidValue }, // ATK_TEXT_ATTR_RISE
1308 : : { "CharUnderline", String2Underline }, // ATK_TEXT_ATTR_UNDERLINE
1309 : : { "CharStrikeout", String2Strikeout }, // ATK_TEXT_ATTR_STRIKETHROUGH
1310 : : { "CharHeight", String2Float }, // ATK_TEXT_ATTR_SIZE
1311 : : { "CharScaleWidth", String2Scale }, // ATK_TEXT_ATTR_SCALE
1312 : : { "CharWeight", String2Weight }, // ATK_TEXT_ATTR_WEIGHT
1313 : : { "CharLocale", String2Locale }, // ATK_TEXT_ATTR_LANGUAGE
1314 : : { "CharFontName", SetString }, // ATK_TEXT_ATTR_FAMILY_NAME
1315 : : { "CharBackColor", String2Color }, // ATK_TEXT_ATTR_BG_COLOR
1316 : : { "CharColor", String2Color }, // ATK_TEXT_ATTR_FG_COLOR
1317 : : { "", InvalidValue }, // ATK_TEXT_ATTR_BG_STIPPLE
1318 : : { "", InvalidValue }, // ATK_TEXT_ATTR_FG_STIPPLE
1319 : : { "", InvalidValue }, // ATK_TEXT_ATTR_WRAP_MODE
1320 : : { "", InvalidValue }, // ATK_TEXT_ATTR_DIRECTION
1321 : : { "ParaAdjust", Justification2Adjust }, // ATK_TEXT_ATTR_JUSTIFICATION
1322 : : { "", InvalidValue }, // ATK_TEXT_ATTR_STRETCH
1323 : : { "CharCaseMap", String2CaseMap }, // ATK_TEXT_ATTR_VARIANT
1324 : : { "CharPosture", Style2FontSlant } // ATK_TEXT_ATTR_STYLE
1325 : : };
1326 : :
1327 : : static const sal_Int32 g_TextAttrMapSize = sizeof( g_TextAttrMap ) / sizeof( AtkTextAttrMapping );
1328 : :
1329 : : /*****************************************************************************/
1330 : :
1331 : : bool
1332 : 0 : attribute_set_map_to_property_values(
1333 : : AtkAttributeSet* attribute_set,
1334 : : uno::Sequence< beans::PropertyValue >& rValueList )
1335 : : {
1336 : : // Ensure enough space ..
1337 : 0 : uno::Sequence< beans::PropertyValue > aAttributeList (g_TextAttrMapSize);
1338 : :
1339 : 0 : sal_Int32 nIndex = 0;
1340 : 0 : for( GSList * item = attribute_set; item != NULL; item = g_slist_next( item ) )
1341 : : {
1342 : 0 : AtkAttribute* attribute = (AtkAttribute *) item;
1343 : :
1344 : 0 : AtkTextAttribute text_attr = atk_text_attribute_for_name( attribute->name );
1345 : 0 : if( text_attr < g_TextAttrMapSize )
1346 : : {
1347 : 0 : if( g_TextAttrMap[text_attr].name[0] != '\0' )
1348 : : {
1349 : 0 : if( ! g_TextAttrMap[text_attr].toPropertyValue( aAttributeList[nIndex].Value, attribute->value) )
1350 : 0 : return false;
1351 : :
1352 : 0 : aAttributeList[nIndex].Name = rtl::OUString::createFromAscii( g_TextAttrMap[text_attr].name );
1353 : 0 : aAttributeList[nIndex].State = beans::PropertyState_DIRECT_VALUE;
1354 : 0 : ++nIndex;
1355 : : }
1356 : : }
1357 : : else
1358 : : {
1359 : : // Unsupported text attribute
1360 : 0 : return false;
1361 : : }
1362 : : }
1363 : :
1364 : 0 : aAttributeList.realloc( nIndex );
1365 : 0 : rValueList = aAttributeList;
1366 : 0 : return true;
1367 : : }
1368 : :
1369 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|