+static void $drawLabel$(NSString *label, CGRect rect, NSString *style, NSString *custom) {
+ bool ellipsis(false);
+ CGFloat max = rect.size.width - 11, width;
+ width:
+ width = [(ellipsis ? [label stringByAppendingString:@"..."] : label) sizeWithStyle:style forWidth:320].width;
+
+ if (width > max) {
+ size_t length([label length]);
+ CGFloat spacing((width - max) / (length - 1));
+
+ if (spacing > 1.25) {
+ ellipsis = true;
+ label = [label substringToIndex:(length - 1)];
+ goto width;
+ }
+
+ style = [style stringByAppendingString:[NSString stringWithFormat:@"letter-spacing: -%f; ", spacing]];
+ }
+
+ if (ellipsis)
+ label = [label stringByAppendingString:@"..."];
+
+ if (custom != nil)
+ style = [style stringByAppendingString:custom];
+
+ CGSize size = [label sizeWithStyle:style forWidth:rect.size.width];
+ [label drawAtPoint:CGPointMake((rect.size.width - size.width) / 2 + rect.origin.x, rect.origin.y) withStyle:style];
+}
+
+static struct WBStringDrawingState {
+ WBStringDrawingState *next_;
+ unsigned count_;
+ NSString *base_;
+ NSString *info_;
+} *stringDrawingState_;
+
+extern "C" CGColorSpaceRef CGContextGetFillColorSpace(CGContextRef);
+extern "C" void CGContextGetFillColor(CGContextRef, CGFloat[]);
+
+static NSString *WBColorMarkup(size_t number, const CGFloat *components) {
+ CGFloat r, g, b, a;
+
+ switch (number) {
+ case 1:
+ r = components[0];
+ g = components[0];
+ b = components[0];
+ a = components[1];
+ break;
+
+ case 3:
+ r = components[0];
+ g = components[1];
+ b = components[2];
+ a = components[3];
+ break;
+
+ default:
+ return @"";
+ }
+
+ return [NSString stringWithFormat:@"color: rgba(%g, %g, %g, %g)", r * 255, g * 255, b * 255, a];
+}
+
+static NSString *WBColorMarkup() {
+ CGContextRef context(UIGraphicsGetCurrentContext());
+ //NSLog(@"XXX:1:%p", context);
+ if (context == NULL)
+ return @"";
+
+ CGColorSpaceRef space(CGContextGetFillColorSpace(context));
+ //NSLog(@"XXX:2:%p", space);
+ if (space == NULL)
+ return @"";
+
+ size_t number(CGColorSpaceGetNumberOfComponents(space));
+ //NSLog(@"XXX:3:%u", number);
+ if (number == 0)
+ return @"";
+
+ CGFloat components[number + 1];
+ CGContextGetFillColor(context, components);
+ return WBColorMarkup(number, components);
+}
+
+static NSString *WBColorMarkup(UIColor *uicolor) {
+ if (uicolor == nil)
+ return @"";
+ CGColorRef cgcolor([uicolor CGColor]);
+ if (cgcolor == NULL)
+ return @"";
+
+ CGColorSpaceRef space(CGColorGetColorSpace(cgcolor));
+ //NSLog(@"XXX:2:%p", space);
+ if (space == NULL)
+ return @"";
+
+ size_t number(CGColorGetNumberOfComponents(cgcolor));
+ //NSLog(@"XXX:3:%u", number);
+ if (number == 0)
+ return @"";
+
+ const CGFloat *components(CGColorGetComponents(cgcolor));
+ return WBColorMarkup(number, components);
+}
+
+extern "C" NSString *NSStringFromCGPoint(CGPoint rect);
+
+MSInstanceMessage6(CGSize, NSString, drawAtPoint,forWidth,withFont,lineBreakMode,letterSpacing,includeEmoji, CGPoint, point, CGFloat, width, UIFont *, font, UILineBreakMode, mode, CGFloat, spacing, BOOL, emoji) {
+ //NSLog(@"XXX: @\"%@\" %@ %g \"%@\" %u %g %u", self, NSStringFromCGPoint(point), width, font, mode, spacing, emoji);
+
+ WBStringDrawingState *state(stringDrawingState_);
+ if (state == NULL)
+ return MSOldCall(point, width, font, mode, spacing, emoji);
+
+ if (state->count_ != 0 && --state->count_ == 0)
+ stringDrawingState_ = state->next_;
+ if (state->info_ == nil)
+ return MSOldCall(point, width, font, mode, spacing, emoji);
+
+ NSString *info([Info_ objectForKey:state->info_]);
+ if (info == nil)
+ return MSOldCall(point, width, font, mode, spacing, emoji);
+
+ NSString *base(state->base_ ?: @"");
+ NSString *extra([NSString stringWithFormat:@"letter-spacing: %gpx", spacing]);
+ [self drawAtPoint:point withStyle:[NSString stringWithFormat:@"%@;%@;%@;%@;%@", [font markupDescription], WBColorMarkup(), extra, base, info]];
+ return CGSizeZero;
+}
+
+extern "C" NSString *NSStringFromCGRect(CGRect rect);
+
+MSInstanceMessageHook7(CGSize, NSString, _drawInRect,withFont,lineBreakMode,alignment,lineSpacing,includeEmoji,truncationRect, CGRect, rect, UIFont *, font, UILineBreakMode, mode, UITextAlignment, alignment, float, spacing, BOOL, emoji, CGRect, truncation) {
+ //NSLog(@"XXX: @\"%@\" %@ \"%@\" %u %u %g %u %@", self, NSStringFromCGRect(rect), font, mode, alignment, spacing, emoji, NSStringFromCGRect(truncation));
+
+ WBStringDrawingState *state(stringDrawingState_);
+ if (state == NULL)
+ return MSOldCall(rect, font, mode, alignment, spacing, emoji, truncation);
+
+ if (state->count_ != 0 && --state->count_ == 0)
+ stringDrawingState_ = state->next_;
+ if (state->info_ == nil)
+ return MSOldCall(rect, font, mode, alignment, spacing, emoji, truncation);
+
+ NSString *info([Info_ objectForKey:state->info_]);
+ if (info == nil)
+ return MSOldCall(rect, font, mode, alignment, spacing, emoji, truncation);
+
+ NSString *textAlign;
+ switch (alignment) {
+ default:
+ case UITextAlignmentLeft:
+ textAlign = @"left";
+ break;
+ case UITextAlignmentCenter:
+ textAlign = @"center";
+ break;
+ case UITextAlignmentRight:
+ textAlign = @"right";
+ break;
+ }
+
+ NSString *base(state->base_ ?: @"");
+ NSString *extra([NSString stringWithFormat:@"text-align: %@", textAlign]);
+
+ if (true)
+ $drawLabel$(self, rect, [NSString stringWithFormat:@"%@;%@;%@", [font markupDescription], WBColorMarkup(), base], info);
+ else
+ [self drawInRect:rect withStyle:[NSString stringWithFormat:@"%@;%@;%@;%@;%@", [font markupDescription], WBColorMarkup(), extra, base, info]];
+
+ return CGSizeZero;
+}
+
+MSInstanceMessage2(void, NSString, drawInRect,withAttributes, CGRect, rect, NSDictionary *, attributes) {
+ //NSLog(@"XXX: *\"%@\" %@", self, attributes);
+
+ WBStringDrawingState *state(stringDrawingState_);
+ if (state == NULL)
+ return MSOldCall(rect, attributes);
+
+ if (state->count_ != 0 && --state->count_ == 0)
+ stringDrawingState_ = state->next_;
+ if (state->info_ == nil)
+ return MSOldCall(rect, attributes);
+
+ NSString *info([Info_ objectForKey:state->info_]);
+ if (info == nil)
+ return MSOldCall(rect, attributes);
+
+ NSString *base(state->base_ ?: @"");
+
+ UIFont *font([attributes objectForKey:@"NSFont"]);
+ UIColor *color([attributes objectForKey:@"NSColor"]);
+
+ [self drawInRect:rect withStyle:[NSString stringWithFormat:@"%@;%@;%@;%@", [font markupDescription], WBColorMarkup(color), base, info]];
+}
+
+extern "C" NSString *NSStringFromCGSize(CGSize size);
+
+MSInstanceMessage4(CGRect, NSString, boundingRectWithSize,options,attributes,context, CGSize, size, NSInteger, options, NSDictionary *, attributes, id, context) {
+ //NSLog(@"XXX: $\"%@\" %@ 0x%x %@ %@", self, NSStringFromCGSize(size), unsigned(options), attributes, context);
+
+ WBStringDrawingState *state(stringDrawingState_);
+ if (state == NULL)
+ return MSOldCall(size, options, attributes, context);
+
+ if (state->count_ != 0 && --state->count_ == 0)
+ stringDrawingState_ = state->next_;
+ if (state->info_ == nil)
+ return MSOldCall(size, options, attributes, context);
+
+ NSString *info([Info_ objectForKey:state->info_]);
+ if (info == nil)
+ return MSOldCall(size, options, attributes, context);
+
+ NSString *base(state->base_ ?: @"");
+
+ UIFont *font([attributes objectForKey:@"NSFont"]);
+ UIColor *color([attributes objectForKey:@"NSColor"]);
+
+ return (CGRect) {{0, 0}, [self sizeWithStyle:[NSString stringWithFormat:@"%@;%@;%@;%@", [font markupDescription], WBColorMarkup(color), base, info] forWidth:size.width]};
+}
+
+MSInstanceMessage4(CGSize, NSString, sizeWithFont,forWidth,lineBreakMode,letterSpacing, UIFont *, font, CGFloat, width, UILineBreakMode, mode, CGFloat, spacing) {
+ //NSLog(@"XXX: #\"%@\" \"%@\" %g %u %g", self, font, width, mode, spacing);
+
+ WBStringDrawingState *state(stringDrawingState_);
+ if (state == NULL)
+ return MSOldCall(font, width, mode, spacing);
+
+ if (state->count_ != 0 && --state->count_ == 0)
+ stringDrawingState_ = state->next_;
+ if (state->info_ == nil)
+ return MSOldCall(font, width, mode, spacing);
+
+ NSString *info([Info_ objectForKey:state->info_]);
+ if (info == nil)
+ return MSOldCall(font, width, mode, spacing);
+
+ NSString *base(state->base_ ?: @"");
+ NSString *extra([NSString stringWithFormat:@"letter-spacing: %gpx", spacing]);
+ return [self sizeWithStyle:[NSString stringWithFormat:@"%@;%@;%@;%@;%@", [font markupDescription], WBColorMarkup(), extra, base, info] forWidth:width];
+}
+
+MSInstanceMessage1(CGSize, NSString, sizeWithFont, UIFont *, font) {
+ //NSLog(@"XXX: ?\"%@\"", self);
+
+ WBStringDrawingState *state(stringDrawingState_);
+ if (state == NULL)
+ return MSOldCall(font);
+
+ if (state->count_ != 0 && --state->count_ == 0)
+ stringDrawingState_ = state->next_;
+ if (state->info_ == nil)
+ return MSOldCall(font);
+
+ NSString *info([Info_ objectForKey:state->info_]);
+ if (info == nil)
+ return MSOldCall(font);
+
+ NSString *base(state->base_ ?: @"");
+ return [self sizeWithStyle:[NSString stringWithFormat:@"%@;%@;%@;%@", [font markupDescription], WBColorMarkup(), base, info] forWidth:65535];
+}
+
+MSClassMessageHook2(id, SBIconBadgeView, checkoutAccessoryImagesForIcon,location, id, icon, int, location) {
+ WBStringDrawingState badgeState = {NULL, 0, @""
+ , @"BadgeStyle"};
+
+ stringDrawingState_ = &badgeState;
+
+ id images(MSOldCall(icon, location));
+
+ stringDrawingState_ = NULL;
+ return images;
+}
+
+MSClassMessageHook2(UIImage *, SBIconAccessoryImage, checkoutAccessoryImageForIcon,location, id, icon, int, location) {
+ if ([self _imageClassForIcon:icon location:location] != $SBIconBadgeImage)
+ return MSOldCall(icon, location);
+
+ WBStringDrawingState badgeState = {NULL, 0, @""
+ , @"BadgeStyle"};
+
+ stringDrawingState_ = &badgeState;
+
+ UIImage *image(MSOldCall(icon, location));
+
+ stringDrawingState_ = NULL;
+ return image;
+}
+
+MSInstanceMessageHook1(UIImage *, SBIconBadgeFactory, checkoutBadgeImageForText, NSString *, text) {
+ WBStringDrawingState badgeState = {NULL, 0, @""
+ , @"BadgeStyle"};
+
+ stringDrawingState_ = &badgeState;
+
+ UIImage *image(MSOldCall(text));
+
+ stringDrawingState_ = NULL;
+ return image;
+}
+
+MSInstanceMessageHook1(UIImage *, SBCalendarApplicationIcon, generateIconImage, int, type) {
+ WBStringDrawingState dayState = {NULL, 2, @""
+ // XXX: this is only correct on an iPod dock
+ "text-shadow: rgba(0, 0, 0, 0.2) -1px -1px 2px;"
+ , @"CalendarIconDayStyle"};
+
+ WBStringDrawingState wtfState = {&dayState, 1, nil, nil};
+
+ WBStringDrawingState sizeState = {
+ kCFCoreFoundationVersionNumber > 800 ? &wtfState : &dayState
+ , 7, nil, nil};
+
+ WBStringDrawingState dateState = {&sizeState, 2, @""
+ , @"CalendarIconDateStyle"};
+
+ stringDrawingState_ = &dateState;
+
+ UIImage *image(MSOldCall(type));
+
+ stringDrawingState_ = NULL;
+ return image;
+}
+
+MSInstanceMessageHook1(UIImage *, UIStatusBarTimeItemView, contentsImageForStyle, int, style) {
+ WBStringDrawingState timeState = {NULL, 0, @""
+ , @"TimeStyle"};
+
+ stringDrawingState_ = &timeState;
+
+ UIImage *image(MSOldCall(style));
+
+ stringDrawingState_ = NULL;
+ return image;
+}
+