top level:
[WebKit-https.git] / WebKit / Misc.subproj / WebKitNSStringExtras.m
1 /*
2     WebKitNSStringExtras.m
3     Copyright 2002, Apple, Inc. All rights reserved.
4 */
5
6 #import "WebKitNSStringExtras.h"
7
8 #import <WebKit/WebNSObjectExtras.h>
9 #import <WebKit/WebTextRenderer.h>
10 #import <WebKit/WebTextRendererFactory.h>
11
12 #import <Foundation/NSString_NSURLExtras.h>
13 #import <unicode/uchar.h>
14
15 @implementation NSString (WebKitExtras)
16
17 static BOOL canUseFastRenderer(const UniChar *buffer, unsigned length)
18 {
19     unsigned i;
20     for (i = 0; i < length; i++) {
21         UCharDirection direction = u_charDirection(buffer[i]);
22         if (direction == U_RIGHT_TO_LEFT || direction > U_WHITE_SPACE_NEUTRAL) {
23             return NO;
24         }
25     }
26     return YES;
27 }
28
29 - (void)_web_drawAtPoint:(NSPoint)point font:(NSFont *)font textColor:(NSColor *)textColor;
30 {
31     unsigned length = [self length];
32     UniChar *buffer = (UniChar *)malloc(sizeof(UniChar) * length);
33
34     [self getCharacters:buffer];
35     
36     if (canUseFastRenderer(buffer, length)){
37         WebTextRenderer *renderer = [[WebTextRendererFactory sharedFactory] rendererWithFont:font usingPrinterFont:NO];
38
39         WebCoreTextRun run;
40         WebCoreInitializeTextRun (&run, buffer, length, 0, length);
41         WebCoreTextStyle style;
42         WebCoreInitializeEmptyTextStyle(&style);
43         style.applyRunRounding = NO;
44         style.applyWordRounding = NO;
45         style.textColor = textColor;
46         WebCoreTextGeometry geometry;
47         WebCoreInitializeEmptyTextGeometry(&geometry);
48         geometry.point = point;
49         [renderer drawRun:&run style:&style geometry:&geometry];
50     }
51     else {
52         // WebTextRenderer assumes drawing from baseline.
53         if ([[NSView focusView] isFlipped])
54             point.y -= [font ascender];
55         else {
56             point.y += [font descender];
57         }
58         [self drawAtPoint:point withAttributes:[NSDictionary dictionaryWithObjectsAndKeys:font, NSFontAttributeName, textColor, NSForegroundColorAttributeName, nil]];
59     }
60
61     free(buffer);
62 }
63
64 - (void)_web_drawDoubledAtPoint:(NSPoint)textPoint
65              withTopColor:(NSColor *)topColor
66               bottomColor:(NSColor *)bottomColor
67                      font:(NSFont *)font
68 {
69     // turn off font smoothing so translucent text draws correctly (Radar 3118455)
70     [NSGraphicsContext saveGraphicsState];
71     CGContextSetShouldSmoothFonts([[NSGraphicsContext currentContext] graphicsPort], false);
72     [self _web_drawAtPoint:textPoint
73                       font:font
74                  textColor:bottomColor];
75
76     textPoint.y += 1;
77     [self _web_drawAtPoint:textPoint
78                       font:font
79                  textColor:topColor];
80     [NSGraphicsContext restoreGraphicsState];
81 }
82
83 - (float)_web_widthWithFont:(NSFont *)font
84 {
85     unsigned length = [self length];
86     float width;
87     UniChar *buffer = (UniChar *)malloc(sizeof(UniChar) * length);
88
89     [self getCharacters:buffer];
90
91     if (canUseFastRenderer(buffer, length)){
92         WebTextRenderer *renderer = [[WebTextRendererFactory sharedFactory] rendererWithFont:font usingPrinterFont:NO];
93
94         WebCoreTextRun run;
95         WebCoreInitializeTextRun (&run, buffer, length, 0, length);
96         WebCoreTextStyle style;
97         WebCoreInitializeEmptyTextStyle(&style);
98         style.applyRunRounding = NO;
99         style.applyWordRounding = NO;
100         width = [renderer floatWidthForRun:&run style:&style widths: 0];
101     }
102     else {
103         width = [self sizeWithAttributes:[NSDictionary dictionaryWithObjectsAndKeys:font, NSFontAttributeName, nil]].width;
104     }
105     
106     free(buffer);
107     
108     return width;
109 }
110
111 - (NSString *)_web_stringByAbbreviatingWithTildeInPath
112 {
113     NSString *resolvedHomeDirectory = [NSHomeDirectory() stringByResolvingSymlinksInPath];
114     NSString *path;
115     
116     if ([self hasPrefix:resolvedHomeDirectory]) {
117         NSString *relativePath = [self substringFromIndex:[resolvedHomeDirectory length]];
118         path = [NSHomeDirectory() stringByAppendingPathComponent:relativePath];
119     } else {
120         path = self;
121     }
122         
123     return [path stringByAbbreviatingWithTildeInPath];
124 }
125
126 - (NSString *)_web_stringByStrippingReturnCharacters
127 {
128     NSMutableString *newString = [[self mutableCopy] autorelease];
129     [newString replaceOccurrencesOfString:@"\r" withString:@"" options:NSLiteralSearch range:NSMakeRange(0, [newString length])];
130     [newString replaceOccurrencesOfString:@"\n" withString:@"" options:NSLiteralSearch range:NSMakeRange(0, [newString length])];
131     return newString;
132 }
133
134 + (NSStringEncoding)_web_encodingForResource:(Handle)resource
135 {
136     short resRef = HomeResFile(resource);
137     if (ResError() != noErr) {
138         return NSMacOSRomanStringEncoding;
139     }
140     
141     // Get the FSRef for the current resource file
142     FSRef fref;
143     OSStatus error = FSGetForkCBInfo(resRef, 0, NULL, NULL, NULL, &fref, NULL);
144     if (error != noErr) {
145         return NSMacOSRomanStringEncoding;
146     }
147     
148     CFURLRef URL = CFURLCreateFromFSRef(NULL, &fref);
149     if (URL == NULL) {
150         return NSMacOSRomanStringEncoding;
151     }
152     
153     NSString *path = [(NSURL *)URL path];
154     CFRelease(URL);
155     
156     // Get the lproj directory name
157     path = [path stringByDeletingLastPathComponent];
158     if (![[path pathExtension] _web_isCaseInsensitiveEqualToString:@"lproj"]) {
159         return NSMacOSRomanStringEncoding;
160     }
161     
162     NSString *directoryName = [[path stringByDeletingPathExtension] lastPathComponent];
163     CFStringRef locale = CFLocaleCreateCanonicalLocaleIdentifierFromString(NULL, (CFStringRef)directoryName);
164     if (locale == NULL) {
165         return NSMacOSRomanStringEncoding;
166     }
167             
168     LangCode lang;
169     RegionCode region;
170     error = LocaleStringToLangAndRegionCodes([(NSString *)locale UTF8String], &lang, &region);
171     CFRelease(locale);
172     if (error != noErr) {
173         return NSMacOSRomanStringEncoding;
174     }
175     
176     TextEncoding encoding;
177     error = UpgradeScriptInfoToTextEncoding(kTextScriptDontCare, lang, region, NULL, &encoding);
178     if (error != noErr) {
179         return NSMacOSRomanStringEncoding;
180     }
181     
182     return CFStringConvertEncodingToNSStringEncoding(encoding);
183 }
184
185 @end