1323de322SAndrew Rist/**************************************************************
2cdf0e10cSrcweir *
3323de322SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one
4323de322SAndrew Rist * or more contributor license agreements.  See the NOTICE file
5323de322SAndrew Rist * distributed with this work for additional information
6323de322SAndrew Rist * regarding copyright ownership.  The ASF licenses this file
7323de322SAndrew Rist * to you under the Apache License, Version 2.0 (the
8323de322SAndrew Rist * "License"); you may not use this file except in compliance
9323de322SAndrew Rist * with the License.  You may obtain a copy of the License at
10323de322SAndrew Rist *
11323de322SAndrew Rist *   http://www.apache.org/licenses/LICENSE-2.0
12323de322SAndrew Rist *
13323de322SAndrew Rist * Unless required by applicable law or agreed to in writing,
14323de322SAndrew Rist * software distributed under the License is distributed on an
15323de322SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16323de322SAndrew Rist * KIND, either express or implied.  See the License for the
17323de322SAndrew Rist * specific language governing permissions and limitations
18323de322SAndrew Rist * under the License.
19323de322SAndrew Rist *
20323de322SAndrew Rist *************************************************************/
21323de322SAndrew Rist
22323de322SAndrew Rist
23cdf0e10cSrcweir
24cdf0e10cSrcweir// MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir#include "precompiled_vcl.hxx"
26cdf0e10cSrcweir
27cdf0e10cSrcweir#include "aqua/salinst.h"
28631849f9SHerbert Dürr#include "aqua/salgdi.h"
29cdf0e10cSrcweir
30cdf0e10cSrcweir#include "aqua11ytextattributeswrapper.h"
31cdf0e10cSrcweir
32cdf0e10cSrcweir#include <com/sun/star/accessibility/AccessibleTextType.hpp>
33cdf0e10cSrcweir#include <com/sun/star/awt/FontUnderline.hpp>
34cdf0e10cSrcweir#include <com/sun/star/awt/FontWeight.hpp>
35cdf0e10cSrcweir#include <com/sun/star/awt/FontStrikeout.hpp>
36cdf0e10cSrcweir
37631849f9SHerbert Dürrnamespace css_awt = ::com::sun::star::awt;
38cdf0e10cSrcweirusing namespace ::com::sun::star::accessibility;
39cdf0e10cSrcweirusing namespace ::com::sun::star::beans;
40cdf0e10cSrcweirusing namespace ::com::sun::star::lang;
41cdf0e10cSrcweirusing namespace ::com::sun::star::uno;
42cdf0e10cSrcweirusing namespace ::rtl;
43cdf0e10cSrcweir
44cdf0e10cSrcweir@implementation AquaA11yTextAttributesWrapper : NSObject
45cdf0e10cSrcweir
46cdf0e10cSrcweir+(int)convertUnderlineStyle:(PropertyValue)property {
47cdf0e10cSrcweir    int underlineStyle = NSNoUnderlineStyle;
48cdf0e10cSrcweir    sal_Int16 value = 0;
49cdf0e10cSrcweir    property.Value >>= value;
50631849f9SHerbert Dürr    if ( value != ::css_awt::FontUnderline::NONE
51631849f9SHerbert Dürr      && value != ::css_awt::FontUnderline::DONTKNOW) {
52cdf0e10cSrcweir        underlineStyle = NSSingleUnderlineStyle;
53cdf0e10cSrcweir    }
54cdf0e10cSrcweir    return underlineStyle;
55cdf0e10cSrcweir}
56cdf0e10cSrcweir
57cdf0e10cSrcweir+(int)convertBoldStyle:(PropertyValue)property {
58cdf0e10cSrcweir    int boldStyle = 0;
59cdf0e10cSrcweir    float value = 0;
60cdf0e10cSrcweir    property.Value >>= value;
61631849f9SHerbert Dürr    if ( value == ::css_awt::FontWeight::SEMIBOLD
62631849f9SHerbert Dürr      || value == ::css_awt::FontWeight::BOLD
63631849f9SHerbert Dürr      || value == ::css_awt::FontWeight::ULTRABOLD
64631849f9SHerbert Dürr      || value == ::css_awt::FontWeight::BLACK ) {
65cdf0e10cSrcweir        boldStyle = NSBoldFontMask;
66cdf0e10cSrcweir    }
67cdf0e10cSrcweir    return boldStyle;
68cdf0e10cSrcweir}
69cdf0e10cSrcweir
70cdf0e10cSrcweir+(int)convertItalicStyle:(PropertyValue)property {
71cdf0e10cSrcweir    int italicStyle = 0;
722d077219SHerbert Dürr    const sal_Int16 value = property.Value.get< ::css_awt::FontSlant>();
73631849f9SHerbert Dürr    if ( value == ::css_awt::FontSlant_ITALIC ) {
74cdf0e10cSrcweir        italicStyle = NSItalicFontMask;
75cdf0e10cSrcweir    }
76cdf0e10cSrcweir    return italicStyle;
77cdf0e10cSrcweir}
78cdf0e10cSrcweir
79cdf0e10cSrcweir+(BOOL)isStrikethrough:(PropertyValue)property {
80cdf0e10cSrcweir    BOOL strikethrough = NO;
81cdf0e10cSrcweir    sal_Int16 value = 0;
82cdf0e10cSrcweir    property.Value >>= value;
83631849f9SHerbert Dürr    if ( value != ::css_awt::FontStrikeout::NONE
84631849f9SHerbert Dürr      && value != ::css_awt::FontStrikeout::DONTKNOW ) {
85cdf0e10cSrcweir        strikethrough = YES;
86cdf0e10cSrcweir    }
87cdf0e10cSrcweir    return strikethrough;
88cdf0e10cSrcweir}
89cdf0e10cSrcweir
90cdf0e10cSrcweir+(BOOL)convertBoolean:(PropertyValue)property {
91cdf0e10cSrcweir    BOOL myBoolean = NO;
92cdf0e10cSrcweir    bool value = sal_False;
93cdf0e10cSrcweir    property.Value >>= value;
94cdf0e10cSrcweir    if ( value ) {
95cdf0e10cSrcweir        myBoolean = YES;
96cdf0e10cSrcweir    }
97cdf0e10cSrcweir    return myBoolean;
98cdf0e10cSrcweir}
99cdf0e10cSrcweir
100cdf0e10cSrcweir+(NSNumber *)convertShort:(PropertyValue)property {
101cdf0e10cSrcweir    sal_Int16 value = 0;
102cdf0e10cSrcweir    property.Value >>= value;
103cdf0e10cSrcweir    return [ NSNumber numberWithShort: value ];
104cdf0e10cSrcweir}
105cdf0e10cSrcweir
106631849f9SHerbert Dürr+(void)addColor:(SalColor)nSalColor forAttribute:(NSString *)attribute andRange:(NSRange)range toString:(NSMutableAttributedString *)string {
107631849f9SHerbert Dürr	if( nSalColor == COL_TRANSPARENT )
108631849f9SHerbert Dürr		return;
109631849f9SHerbert Dürr	const RGBAColor aRGBAColor( nSalColor);
110631849f9SHerbert Dürr	CGColorRef aColorRef = CGColorCreate ( CGColorSpaceCreateWithName ( kCGColorSpaceGenericRGB ), aRGBAColor.AsArray() );
111631849f9SHerbert Dürr	[ string addAttribute: attribute value: (id) aColorRef range: range ];
112631849f9SHerbert Dürr	CGColorRelease( aColorRef );
113cdf0e10cSrcweir}
114cdf0e10cSrcweir
115cdf0e10cSrcweir+(void)addFont:(NSFont *)font toString:(NSMutableAttributedString *)string forRange:(NSRange)range {
116cdf0e10cSrcweir    if ( font != nil ) {
117cdf0e10cSrcweir        NSDictionary * fontDictionary = [ NSDictionary dictionaryWithObjectsAndKeys:
118cdf0e10cSrcweir            [ font fontName ], NSAccessibilityFontNameKey,
119cdf0e10cSrcweir            [ font familyName ], NSAccessibilityFontFamilyKey,
120cdf0e10cSrcweir            [ font displayName ], NSAccessibilityVisibleNameKey,
121cdf0e10cSrcweir            [ NSNumber numberWithFloat: [ font pointSize ] ], NSAccessibilityFontSizeKey,
122cdf0e10cSrcweir            nil
123cdf0e10cSrcweir        ];
124cdf0e10cSrcweir        [ string addAttribute: NSAccessibilityFontTextAttribute
125cdf0e10cSrcweir                value: fontDictionary
126cdf0e10cSrcweir                range: range
127cdf0e10cSrcweir        ];
128cdf0e10cSrcweir    }
129cdf0e10cSrcweir}
130cdf0e10cSrcweir
131cdf0e10cSrcweir+(void)applyAttributesFrom:(Sequence < PropertyValue >)attributes toString:(NSMutableAttributedString *)string forRange:(NSRange)range storeDefaultsTo:(AquaA11yWrapper *)wrapperStore getDefaultsFrom:(AquaA11yWrapper *)wrapper {
132cdf0e10cSrcweir    NSAutoreleasePool * pool = [ [ NSAutoreleasePool alloc ] init ];
133cdf0e10cSrcweir    // constants
134cdf0e10cSrcweir    static const OUString attrUnderline = OUString::createFromAscii("CharUnderline");
135cdf0e10cSrcweir    static const OUString attrBold = OUString::createFromAscii("CharWeight");
136cdf0e10cSrcweir    static const OUString attrFontname = OUString::createFromAscii("CharFontName");
137cdf0e10cSrcweir    static const OUString attrItalic = OUString::createFromAscii("CharPosture");
138cdf0e10cSrcweir    static const OUString attrHeight = OUString::createFromAscii("CharHeight");
139cdf0e10cSrcweir    static const OUString attrStrikethrough = OUString::createFromAscii("CharStrikeout");
140cdf0e10cSrcweir    static const OUString attrShadow = OUString::createFromAscii("CharShadowed");
141cdf0e10cSrcweir    static const OUString attrUnderlineColor = OUString::createFromAscii("CharUnderlineColor");
142cdf0e10cSrcweir    static const OUString attrUnderlineHasColor = OUString::createFromAscii("CharUnderlineHasColor");
143cdf0e10cSrcweir    static const OUString attrForegroundColor = OUString::createFromAscii("CharColor");
144cdf0e10cSrcweir    static const OUString attrBackgroundColor = OUString::createFromAscii("CharBackColor");
145cdf0e10cSrcweir    static const OUString attrSuperscript = OUString::createFromAscii("CharEscapement");
146cdf0e10cSrcweir    // vars
147cdf0e10cSrcweir    OUString fontname;
148cdf0e10cSrcweir    int fonttraits = 0;
149cdf0e10cSrcweir    float fontsize = 0.0;
150cdf0e10cSrcweir    sal_Int32 underlineColor = 0;
151cdf0e10cSrcweir    BOOL underlineHasColor = NO;
152cdf0e10cSrcweir    // add attributes to string
153cdf0e10cSrcweir    for ( int attrIndex = 0; attrIndex < attributes.getLength(); attrIndex++ ) {
154cdf0e10cSrcweir        PropertyValue property = attributes [ attrIndex ];
155cdf0e10cSrcweir        // TODO: NSAccessibilityMisspelledTextAttribute, NSAccessibilityAttachmentTextAttribute, NSAccessibilityLinkTextAttribute
156cdf0e10cSrcweir        // NSAccessibilityStrikethroughColorTextAttribute is unsupported by UNP-API
157cdf0e10cSrcweir        if ( property.Value.hasValue() ) {
158cdf0e10cSrcweir            if ( property.Name.equals ( attrUnderline ) ) {
159cdf0e10cSrcweir                int style = [ AquaA11yTextAttributesWrapper convertUnderlineStyle: property ];
160cdf0e10cSrcweir                if ( style != NSNoUnderlineStyle ) {
161cdf0e10cSrcweir                    [ string addAttribute: NSAccessibilityUnderlineTextAttribute value: [ NSNumber numberWithInt: style ] range: range ];
162cdf0e10cSrcweir                }
163cdf0e10cSrcweir            } else if ( property.Name.equals ( attrFontname ) ) {
164cdf0e10cSrcweir                property.Value >>= fontname;
165cdf0e10cSrcweir            } else if ( property.Name.equals ( attrBold ) ) {
166cdf0e10cSrcweir                fonttraits |= [ AquaA11yTextAttributesWrapper convertBoldStyle: property ];
167cdf0e10cSrcweir            } else if ( property.Name.equals ( attrItalic ) ) {
168cdf0e10cSrcweir                fonttraits |= [ AquaA11yTextAttributesWrapper convertItalicStyle: property ];
169cdf0e10cSrcweir            } else if ( property.Name.equals ( attrHeight ) ) {
170cdf0e10cSrcweir                property.Value >>= fontsize;
171cdf0e10cSrcweir            } else if ( property.Name.equals ( attrStrikethrough ) ) {
172cdf0e10cSrcweir                if ( [ AquaA11yTextAttributesWrapper isStrikethrough: property ] ) {
173cdf0e10cSrcweir                    [ string addAttribute: NSAccessibilityStrikethroughTextAttribute value: [ NSNumber numberWithBool: YES ] range: range ];
174cdf0e10cSrcweir                }
175cdf0e10cSrcweir            } else if ( property.Name.equals ( attrShadow ) ) {
176cdf0e10cSrcweir                if ( [ AquaA11yTextAttributesWrapper convertBoolean: property ] ) {
177cdf0e10cSrcweir                    [ string addAttribute: NSAccessibilityShadowTextAttribute value: [ NSNumber numberWithBool: YES ] range: range ];
178cdf0e10cSrcweir                }
179cdf0e10cSrcweir            } else if ( property.Name.equals ( attrUnderlineColor ) ) {
180cdf0e10cSrcweir                property.Value >>= underlineColor;
181cdf0e10cSrcweir            } else if ( property.Name.equals ( attrUnderlineHasColor ) ) {
182cdf0e10cSrcweir                underlineHasColor = [ AquaA11yTextAttributesWrapper convertBoolean: property ];
183cdf0e10cSrcweir            } else if ( property.Name.equals ( attrForegroundColor ) ) {
184cdf0e10cSrcweir                [ AquaA11yTextAttributesWrapper addColor: property.Value.get<sal_Int32>() forAttribute: NSAccessibilityForegroundColorTextAttribute andRange: range toString: string ];
185cdf0e10cSrcweir            } else if ( property.Name.equals ( attrBackgroundColor ) ) {
186cdf0e10cSrcweir                [ AquaA11yTextAttributesWrapper addColor: property.Value.get<sal_Int32>() forAttribute: NSAccessibilityBackgroundColorTextAttribute andRange: range toString: string ];
187cdf0e10cSrcweir            } else if ( property.Name.equals ( attrSuperscript ) ) {
188cdf0e10cSrcweir                // values < zero mean subscript
189cdf0e10cSrcweir                // values > zero mean superscript
190cdf0e10cSrcweir                // this is true for both NSAccessibility-API and UNO-API
191cdf0e10cSrcweir                NSNumber * number = [ AquaA11yTextAttributesWrapper convertShort: property ];
192cdf0e10cSrcweir                if ( [ number shortValue ] != 0 ) {
193cdf0e10cSrcweir                    [ string addAttribute: NSAccessibilitySuperscriptTextAttribute value: number range: range ];
194cdf0e10cSrcweir                }
195cdf0e10cSrcweir            }
196cdf0e10cSrcweir        }
197cdf0e10cSrcweir    }
198cdf0e10cSrcweir    // add underline information
199cdf0e10cSrcweir    if ( underlineHasColor ) {
200cdf0e10cSrcweir        [ AquaA11yTextAttributesWrapper addColor: underlineColor forAttribute: NSAccessibilityUnderlineColorTextAttribute andRange: range toString: string ];
201cdf0e10cSrcweir    }
202cdf0e10cSrcweir    // add font information
203cdf0e10cSrcweir    if ( wrapperStore != nil ) { // default
204cdf0e10cSrcweir        [ wrapperStore setDefaultFontname: CreateNSString ( fontname ) ];
205cdf0e10cSrcweir        [ wrapperStore setDefaultFontsize: fontsize ];
206cdf0e10cSrcweir        NSFont * font = [ [ NSFontManager sharedFontManager ] fontWithFamily: CreateNSString ( fontname ) traits: fonttraits weight: 0 size: fontsize ];
207cdf0e10cSrcweir        [ AquaA11yTextAttributesWrapper addFont: font toString: string forRange: range ];
208cdf0e10cSrcweir    } else if ( wrapper != nil && fonttraits != 0 ) { // attribute run and bold and/or italic was found
209cdf0e10cSrcweir        NSFont * font = [ [ NSFontManager sharedFontManager ] fontWithFamily: [ wrapper defaultFontname ] traits: fonttraits weight: 0 size: [ wrapper defaultFontsize ] ];
210cdf0e10cSrcweir        [ AquaA11yTextAttributesWrapper addFont: font toString: string forRange: range ];
211cdf0e10cSrcweir    }
212cdf0e10cSrcweir    [ pool release ];
213cdf0e10cSrcweir}
214cdf0e10cSrcweir
215cdf0e10cSrcweir+(NSMutableAttributedString *)createAttributedStringForElement:(AquaA11yWrapper *)wrapper inOrigRange:(id)origRange {
216cdf0e10cSrcweir    static const Sequence < OUString > emptySequence;
217cdf0e10cSrcweir    // vars
218cdf0e10cSrcweir    NSMutableAttributedString * string = nil;
219cdf0e10cSrcweir    int loc = [ origRange rangeValue ].location;
220cdf0e10cSrcweir    int len = [ origRange rangeValue ].length;
221cdf0e10cSrcweir    int endIndex = loc + len;
222cdf0e10cSrcweir    int currentIndex = loc;
223cdf0e10cSrcweir    try {
224cdf0e10cSrcweir        NSString * myString = CreateNSString ( [ wrapper accessibleText ] -> getText() ); // TODO: dirty fix for i87817
225cdf0e10cSrcweir        string = [ [ NSMutableAttributedString alloc ] initWithString: CreateNSString ( [ wrapper accessibleText ] -> getTextRange ( loc, loc + len ) ) ];
226cdf0e10cSrcweir        if ( [ wrapper accessibleTextAttributes ] != nil && [myString characterAtIndex:0] != 57361) { // TODO: dirty fix for i87817
227cdf0e10cSrcweir            [ string beginEditing ];
228cdf0e10cSrcweir            // add default attributes for whole string
229cdf0e10cSrcweir            Sequence < PropertyValue > defaultAttributes = [ wrapper accessibleTextAttributes ] -> getDefaultAttributes ( emptySequence );
230*1eb28822SHerbert Dürr            NSRange offsetRange = NSMakeRange ( 0, len );
231*1eb28822SHerbert Dürr            [ AquaA11yTextAttributesWrapper applyAttributesFrom: defaultAttributes toString: string forRange: offsetRange storeDefaultsTo: wrapper getDefaultsFrom: nil ];
232cdf0e10cSrcweir            // add attributes for attribute run(s)
233cdf0e10cSrcweir            while ( currentIndex < endIndex ) {
234cdf0e10cSrcweir                TextSegment textSegment = [ wrapper accessibleText ] -> getTextAtIndex ( currentIndex, AccessibleTextType::ATTRIBUTE_RUN );
235cdf0e10cSrcweir                int endOfRange = endIndex > textSegment.SegmentEnd ? textSegment.SegmentEnd : endIndex;
236*1eb28822SHerbert Dürr                NSRange rangeForAttributeRun = NSMakeRange ( currentIndex-loc, endOfRange - currentIndex );
237cdf0e10cSrcweir                // add run attributes
238cdf0e10cSrcweir                Sequence < PropertyValue > attributes = [ wrapper accessibleTextAttributes ] -> getRunAttributes ( currentIndex, emptySequence );
239cdf0e10cSrcweir                [ AquaA11yTextAttributesWrapper applyAttributesFrom: attributes toString: string forRange: rangeForAttributeRun storeDefaultsTo: nil getDefaultsFrom: wrapper ];
240cdf0e10cSrcweir                currentIndex = textSegment.SegmentEnd;
241cdf0e10cSrcweir            }
242cdf0e10cSrcweir            [ string endEditing ];
243cdf0e10cSrcweir        }
244cdf0e10cSrcweir    } catch ( IllegalArgumentException & e ) {
245cdf0e10cSrcweir        // empty
246cdf0e10cSrcweir    } catch ( IndexOutOfBoundsException & e ) {
247cdf0e10cSrcweir        // empty
248cdf0e10cSrcweir    } catch ( RuntimeException& ) {
249cdf0e10cSrcweir        // at least don't crash
250cdf0e10cSrcweir    }
251cdf0e10cSrcweir    return string;
252cdf0e10cSrcweir}
253cdf0e10cSrcweir
254cdf0e10cSrcweir@end
255