Skip to content

Instantly share code, notes, and snippets.

@mikeash mikeash/xcode.sh
Created Sep 15, 2017

Embed
What would you like to do?
Convince Xcode 9 not to smooth its source code font
#!/bin/bash
# Exit the script immediately on error
set -e
# We'll work in /tmp
cd /tmp
# Clone mach_override unless we already have it
if [ ! -d mach_override ]; then
git clone https://github.com/rentzsch/mach_override
fi
# ============================
# Compile the override library
# ============================
clang -dynamiclib -framework Cocoa -x objective-c -o monacoize.dylib -I. mach_override/mach_override.c mach_override/libudis86/*.c /dev/stdin <<"SOURCE"
#import <Cocoa/Cocoa.h>
#import <dlfcn.h>
#import <objc/runtime.h>
#import "mach_override/mach_override.h"
// SourceEditor.SourceEditorLineLayer.init(attributedString: __ObjC.NSAttributedString, referencedLine: SourceEditor.SourceEditorLineIdentifier, lineLayoutManager: SourceEditor.LineLayoutManager, fontSmoothingAttributes: SourceEditor.SourceEditorFontSmoothingAttributes, textRenderingColorSpace: Swift.Optional<__ObjC.CGColorSpace>, images: Swift.Array<(image: __ObjC.CGImage, columnRange: Swift.Range<Swift.Int>)>) -> SourceEditor.SourceEditorLineLayer
#define ARGS void *a, void *b, void *c, void *d, unsigned *fontSmoothingAttributes, void *e, void *f
void *(*originalLineLayerInit)(ARGS);
void *replacementLineLayerInit(ARGS) {
*fontSmoothingAttributes = 0;
return originalLineLayerInit(a, b, c, d, fontSmoothingAttributes, e, f);
}
CTTypesetterRef (*originalCTTypesetterCreateWithAttributedString)(CFAttributedStringRef string);
CTTypesetterRef replacementCTTypesetterCreateWithAttributedString(CFAttributedStringRef string) {
CFMutableAttributedStringRef mutable = CFAttributedStringCreateMutableCopy(NULL, 0, string);
CFRange range = CFRangeMake(0, CFAttributedStringGetLength(mutable));
CFAttributedStringSetAttribute(mutable, range, kCTKernAttributeName, (void *)@0.75);
CTTypesetterRef result = originalCTTypesetterCreateWithAttributedString(mutable);
CFRelease(mutable);
return result;
}
void LoadMonacoize(void *lineLayerInit) {
fprintf(stderr, "lineLayerInit = %p\n", lineLayerInit);
mach_error_t result = mach_override_ptr(lineLayerInit, replacementLineLayerInit, (void **)&originalLineLayerInit);
if(result != 0) {
fprintf(stderr, "ERROR %d TRYING TO OVERRIDE LayerInit\n", result);
}
result = mach_override_ptr(CTTypesetterCreateWithAttributedString, replacementCTTypesetterCreateWithAttributedString, (void **)&originalCTTypesetterCreateWithAttributedString);
if(result != 0) {
fprintf(stderr, "ERROR %d TRYING TO OVERRIDE CTTypesetter\n", result);
}
}
SOURCE
# =======================
# End of override library
# =======================
# =================================================
# Run Xcode in lldb and invoke the override library
# =================================================
lldb /Applications/Xcode.app -s <(cat <<"COMMANDS"
b SourceEditor.SourceEditorLayoutManager.makeLineLayerForLine
break command add
expr (void *)dlopen("/tmp/monacoize.dylib", 0x8)
expr void *$fptr = (void *)(void (*)(void))_T012SourceEditor0aB9LineLayerCACSo18NSAttributedStringC010attributedF0_AA0abC10IdentifierV010referencedC0AA0C13LayoutManager_p04linejK0AA0aB23FontSmoothingAttributesV04fontnO0So12CGColorSpaceCSg018textRenderingColorR0SaySo7CGImageC5image_s5RangeVySiG06columnX0tG6imagestcfc
expr (void)LoadMonacoize($fptr)
br del 1
cont
DONE
run
cont
exit
COMMANDS
)
# ======================
# End of lldb invocation
# ======================
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.