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