From e294771354a0b06dbac6d0b6a172dfea52fa3479 Mon Sep 17 00:00:00 2001 From: Darcy Liu Date: Wed, 27 Feb 2013 09:30:18 +0800 Subject: [PATCH] add CoreTextArc --- CoreTextArc.zip | Bin 0 -> 51723 bytes CoreTextArc/ArcView.c | 479 ++++++++++++++++++ CoreTextArc/ArcView.h | 95 ++++ CoreTextArc/Controls.c | 233 +++++++++ CoreTextArc/Controls.h | 99 ++++ .../CoreTextArc.app/Contents/Info.plist | 24 + .../Contents/MacOS/CoreTextArc | Bin 0 -> 61316 bytes CoreTextArc/CoreTextArc.app/Contents/PkgInfo | 1 + .../Resources/English.lproj/InfoPlist.strings | Bin 0 -> 204 bytes .../English.lproj/Localizable.strings | Bin 0 -> 122 bytes .../English.lproj/main.nib/classes.nib | 4 + .../Resources/English.lproj/main.nib/info.nib | 22 + .../English.lproj/main.nib/objects.xib | 421 +++++++++++++++ .../Contents/Resources/Read Me.rtf | 35 ++ .../CoreTextArc.xcodeproj/project.pbxproj | 286 +++++++++++ CoreTextArc/CoreTextArc_Prefix.pch | 51 ++ CoreTextArc/English.lproj/InfoPlist.strings | Bin 0 -> 204 bytes CoreTextArc/English.lproj/Localizable.strings | Bin 0 -> 122 bytes .../English.lproj/main.nib/classes.nib | 4 + CoreTextArc/English.lproj/main.nib/info.nib | 22 + .../English.lproj/main.nib/objects.xib | 421 +++++++++++++++ CoreTextArc/Fonts.c | 153 ++++++ CoreTextArc/Fonts.h | 61 +++ CoreTextArc/Info.plist | 26 + CoreTextArc/Read Me.rtf | 35 ++ CoreTextArc/main.c | 388 ++++++++++++++ 26 files changed, 2860 insertions(+) create mode 100644 CoreTextArc.zip create mode 100644 CoreTextArc/ArcView.c create mode 100644 CoreTextArc/ArcView.h create mode 100644 CoreTextArc/Controls.c create mode 100644 CoreTextArc/Controls.h create mode 100644 CoreTextArc/CoreTextArc.app/Contents/Info.plist create mode 100755 CoreTextArc/CoreTextArc.app/Contents/MacOS/CoreTextArc create mode 100644 CoreTextArc/CoreTextArc.app/Contents/PkgInfo create mode 100644 CoreTextArc/CoreTextArc.app/Contents/Resources/English.lproj/InfoPlist.strings create mode 100644 CoreTextArc/CoreTextArc.app/Contents/Resources/English.lproj/Localizable.strings create mode 100644 CoreTextArc/CoreTextArc.app/Contents/Resources/English.lproj/main.nib/classes.nib create mode 100644 CoreTextArc/CoreTextArc.app/Contents/Resources/English.lproj/main.nib/info.nib create mode 100644 CoreTextArc/CoreTextArc.app/Contents/Resources/English.lproj/main.nib/objects.xib create mode 100644 CoreTextArc/CoreTextArc.app/Contents/Resources/Read Me.rtf create mode 100644 CoreTextArc/CoreTextArc.xcodeproj/project.pbxproj create mode 100644 CoreTextArc/CoreTextArc_Prefix.pch create mode 100644 CoreTextArc/English.lproj/InfoPlist.strings create mode 100644 CoreTextArc/English.lproj/Localizable.strings create mode 100644 CoreTextArc/English.lproj/main.nib/classes.nib create mode 100644 CoreTextArc/English.lproj/main.nib/info.nib create mode 100644 CoreTextArc/English.lproj/main.nib/objects.xib create mode 100644 CoreTextArc/Fonts.c create mode 100644 CoreTextArc/Fonts.h create mode 100644 CoreTextArc/Info.plist create mode 100644 CoreTextArc/Read Me.rtf create mode 100644 CoreTextArc/main.c diff --git a/CoreTextArc.zip b/CoreTextArc.zip new file mode 100644 index 0000000000000000000000000000000000000000..43968275ec60e507b14626c8ced4f8b5c0b3e206 GIT binary patch literal 51723 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 literal 0 HcmV?d00001 diff --git a/CoreTextArc/ArcView.c b/CoreTextArc/ArcView.c new file mode 100644 index 00000000..ff047c86 --- /dev/null +++ b/CoreTextArc/ArcView.c @@ -0,0 +1,479 @@ +/* + + File: ArcView.c + + Abstract: Defines and implements the ArcView custom HIView subclass to + draw text on a curve and illustrate best practices with CoreText. + + Version: 1.0 + + Disclaimer: IMPORTANT: This Apple software is supplied to you by + Apple Inc. ("Apple") in consideration of your agreement to the + following terms, and your use, installation, modification or + redistribution of this Apple software constitutes acceptance of these + terms. If you do not agree with these terms, please do not use, + install, modify or redistribute this Apple software. + + In consideration of your agreement to abide by the following terms, and + subject to these terms, Apple grants you a personal, non-exclusive + license, under Apple's copyrights in this original Apple software (the + "Apple Software"), to use, reproduce, modify and redistribute the Apple + Software, with or without modifications, in source and/or binary forms; + provided that if you redistribute the Apple Software in its entirety and + without modifications, you must retain this notice and the following + text and disclaimers in all such redistributions of the Apple Software. + Neither the name, trademarks, service marks or logos of Apple Inc. + may be used to endorse or promote products derived from the Apple + Software without specific prior written permission from Apple. Except + as expressly stated in this notice, no other rights or licenses, express + or implied, are granted by Apple herein, including but not limited to + any patent rights that may be infringed by your derivative works or by + other works in which the Apple Software may be incorporated. + + The Apple Software is provided by Apple on an "AS IS" basis. APPLE + MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION + THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND + OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. + + IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, + MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED + AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), + STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Copyright (C) 2007 Apple Inc. All Rights Reserved. + + */ + +#include "ArcView.h" + +#define ARCVIEW_DEFAULT_FONT_NAME CFSTR("Didot") +#define ARCVIEW_DEFAULT_FONT_SIZE 64.0 +#define ARCVIEW_DEFAULT_RADIUS 150.0 + +struct ArcView { + HIObjectRef object; + CTFontRef font; // retained + CFStringRef string; // retained + CGFloat radius; + OptionBits options; + + CGContextRef context; // not retained +}; + +typedef struct GlyphArcInfo { + CGFloat width; + CGFloat angle; // in radians +} GlyphArcInfo; + +static CTFontRef ArcViewCreateDefaultFont(void); + +static void ArcViewDispose(ArcView *arcView); +static ArcView *ArcViewCreate(HIObjectRef object); + +static void PrepareGlyphArcInfo(CTLineRef line, CFIndex glyphCount, GlyphArcInfo *glyphArcInfo); +static CFAttributedStringRef ArcViewCreateAttributedString(ArcView *arcView); + +static OSStatus ArcViewEventHandler(EventHandlerCallRef inCaller, EventRef inEvent, void* inRefcon); + +static HIObjectClassRef sArcViewClass = NULL; + +// Register the arc view class. This should be done very early, before the nib is loaded. +OSStatus ArcViewRegisterClass(void) +{ + static const EventTypeSpec kArcViewEvents[] = { + { kEventClassHIObject, kEventHIObjectConstruct }, + { kEventClassHIObject, kEventHIObjectDestruct }, + { kEventClassControl, kEventControlDraw } + }; + + return HIObjectRegisterSubclass(kArcViewClassID, kHIViewClassID, 0, (EventHandlerUPP)ArcViewEventHandler, GetEventTypeCount(kArcViewEvents), kArcViewEvents, NULL, &sArcViewClass); +} + +// Convenience to get the arc view for the specified window. +ArcView *GetArcViewForWindow(HIWindowRef window) +{ + static const HIViewID arcID = { kArcViewControlSignature, kArcViewControlID }; + HIViewRef view; + + verify_noerr(HIViewFindByID(HIViewGetRoot(window), arcID, &view)); + + return HIObjectDynamicCast((HIObjectRef)view, kArcViewClassID); +} + +// Set the font for the arc view. This properly releases the existing font and marks the view as needing display. +void ArcViewSetFont(ArcView *arcView, CTFontRef font) +{ + if (arcView->font != font) { + if (arcView->font != NULL) + CFRelease(arcView->font); + arcView->font = (CTFontRef)CFRetain(font); + + HIViewSetNeedsDisplay((HIViewRef)arcView->object, true); + } +} + +// Get the current font. +CTFontRef ArcViewGetFont(const ArcView *arcView) +{ + return arcView->font; +} + +// Set the content string for the arc view. This properly releases the existing string and marks the view as needing display. +void ArcViewSetString(ArcView *arcView, CFStringRef string) +{ + if (arcView->string != string) { + if (arcView->string != NULL) + CFRelease(arcView->string); + arcView->string = (CFStringRef)CFRetain(string); + + HIViewSetNeedsDisplay((HIViewRef)arcView->object, true); + } +} + +// Get the current content string. +CFStringRef ArcViewGetString(const ArcView *arcView) +{ + return arcView->string; +} + +// Set the state for the specified option(s) +void ArcViewSetOptions(ArcView *arcView, ArcViewOptions optionsMask, Boolean state) +{ + if (state) { + arcView->options |= optionsMask; + } else { + arcView->options &= ~optionsMask; + } + HIViewSetNeedsDisplay((HIViewRef)arcView->object, true); +} + +// Returns true if specified options are enabled +Boolean ArcViewGetOptions(ArcView *arcView, ArcViewOptions optionsMask) +{ + return (arcView->options & optionsMask) == optionsMask; +} + +// Draw the view in the provided context. This should not be called directly as it draws in response events. +void ArcViewDraw(ArcView *arcView, CGContextRef context) +{ + HIRect bounds; + CFIndex glyphCount; + GlyphArcInfo * glyphArcInfo; + + // Don't draw if we don't have a font or string + if (arcView->font == NULL || arcView->string == NULL) + return; + + verify_noerr(HIViewGetBounds((HIViewRef)arcView->object, &bounds)); + + // Transform HIView coordinates to Quartz coordinates + CGContextTranslateCTM(context, 0, bounds.size.height); + CGContextScaleCTM(context, 1.0, -1.0); + + // Draw a white background + CGContextSetFillColorWithColor(context, CGColorGetConstantColor(kCGColorWhite)); + CGContextFillRect(context, bounds); + + // Create the attributed string + CFAttributedStringRef attrString = ArcViewCreateAttributedString(arcView); + assert(attrString != NULL); + + CTLineRef line = CTLineCreateWithAttributedString(attrString); + CFRelease(attrString); + assert(line != NULL); + + glyphCount = CTLineGetGlyphCount(line); + if (glyphCount == 0) { + CFRelease(line); + return; + } + + glyphArcInfo = (GlyphArcInfo*)calloc(glyphCount, sizeof(GlyphArcInfo)); + PrepareGlyphArcInfo(line, glyphCount, glyphArcInfo); + + // Move the origin from the lower left of the view nearer to its center. + CGContextSaveGState(context); + CGContextTranslateCTM(context, CGRectGetMidX(bounds), CGRectGetMidY(bounds) - arcView->radius / 2.0); + + // Stroke the arc in red for verification. + CGContextBeginPath(context); + CGContextAddArc(context, 0.0, 0.0, arcView->radius, M_PI, 0.0, 1); + CGContextSetRGBStrokeColor(context, 1.0, 0.0, 0.0, 1.0); + CGContextStrokePath(context); + + // Rotate the context 90 degrees counterclockwise. + CGContextRotateCTM(context, M_PI_2); + + // Now for the actual drawing. The angle offset for each glyph relative to the previous glyph has already been calculated; with that information in hand, draw those glyphs overstruck and centered over one another, making sure to rotate the context after each glyph so the glyphs are spread along a semicircular path. + CGPoint textPosition = CGPointMake(0.0, arcView->radius); + CGContextSetTextPosition(context, textPosition.x, textPosition.y); + + CFArrayRef runArray = CTLineGetGlyphRuns(line); + CFIndex runCount = CFArrayGetCount(runArray); + + CFIndex glyphOffset = 0; + CFIndex runIndex = 0; + for (; runIndex < runCount; runIndex++) { + CTRunRef run = (CTRunRef)CFArrayGetValueAtIndex(runArray, runIndex); + CFIndex runGlyphCount = CTRunGetGlyphCount(run); + Boolean drawSubstitutedGlyphsManually = false; + CTFontRef runFont = CFDictionaryGetValue(CTRunGetAttributes(run), kCTFontAttributeName); + + // Determine if we need to draw substituted glyphs manually. Do so if the runFont is not the same as the overall font. + if ((arcView->options & kArcViewDimSubstitutedGlyphsOption) !=0 && !CFEqual(arcView->font, runFont)) { + drawSubstitutedGlyphsManually = true; + } + + CFIndex runGlyphIndex = 0; + for (; runGlyphIndex < runGlyphCount; runGlyphIndex++) { + CFRange glyphRange = CFRangeMake(runGlyphIndex, 1); + CGContextRotateCTM(context, -(glyphArcInfo[runGlyphIndex + glyphOffset].angle)); + + // Center this glyph by moving left by half its width. + CGFloat glyphWidth = glyphArcInfo[runGlyphIndex + glyphOffset].width; + CGFloat halfGlyphWidth = glyphWidth / 2.0; + CGPoint positionForThisGlyph = CGPointMake(textPosition.x - halfGlyphWidth, textPosition.y); + + // Glyphs are positioned relative to the text position for the line, so offset text position leftwards by this glyph's width in preparation for the next glyph. + textPosition.x -= glyphWidth; + + CGAffineTransform textMatrix = CTRunGetTextMatrix(run); + textMatrix.tx = positionForThisGlyph.x; + textMatrix.ty = positionForThisGlyph.y; + CGContextSetTextMatrix(context, textMatrix); + + if (!drawSubstitutedGlyphsManually) { + CTRunDraw(run, context, glyphRange); + } + else { + // We need to draw the glyphs manually in this case because we are effectively applying a graphics operation by setting the context fill color. Normally we would use kCTForegroundColorAttributeName, but this does not apply as we don't know the ranges for the colors in advance, and we wanted demonstrate how to manually draw. + CGFontRef cgFont = CTFontCopyGraphicsFont(runFont, NULL); + CGGlyph glyph; + CGPoint position; + + CTRunGetGlyphs(run, glyphRange, &glyph); + CTRunGetPositions(run, glyphRange, &position); + + CGContextSetFont(context, cgFont); + CGContextSetFontSize(context, CTFontGetSize(runFont)); + CGContextSetRGBFillColor(context, 0.25, 0.25, 0.25, 0.5); + CGContextShowGlyphsAtPositions(context, &glyph, &position, 1); + + CFRelease(cgFont); + } + + // Draw the glyph bounds + if ((arcView->options & kArcViewShowGlyphBoundsOption) != 0) { + CGRect glyphBounds = CTRunGetImageBounds(run, context, glyphRange); + + CGContextSetRGBStrokeColor(context, 0.0, 0.0, 1.0, 1.0); + CGContextStrokeRect(context, glyphBounds); + } + // Draw the bounding boxes defined by the line metrics + if ((arcView->options & kArcViewShowLineMetricsOption) != 0) { + CGRect lineMetrics; + CGFloat ascent, descent; + + CTRunGetTypographicBounds(run, glyphRange, &ascent, &descent, NULL); + + // The glyph is centered around the y-axis + lineMetrics.origin.x = -halfGlyphWidth; + lineMetrics.origin.y = positionForThisGlyph.y - descent; + lineMetrics.size.width = glyphWidth; + lineMetrics.size.height = ascent + descent; + + CGContextSetRGBStrokeColor(context, 0.0, 1.0, 0.0, 1.0); + CGContextStrokeRect(context, lineMetrics); + } + } + + glyphOffset += runGlyphCount; + } + + CGContextRestoreGState(context); + + free(glyphArcInfo); + CFRelease(line); +} + +// Handles events for the ArcView HIObject subclass. The only event we really care about is the control drawing event to trigger drawing of content. +static OSStatus ArcViewEventHandler(EventHandlerCallRef inCaller, EventRef inEvent, void* inRefcon) +{ + OSStatus result = eventNotHandledErr; + ArcView *arcView = (ArcView *)inRefcon; + OSType class = GetEventClass(inEvent); + UInt32 kind = GetEventKind(inEvent); + + switch (class) { + case kEventClassHIObject: + { + switch (kind) { + case kEventHIObjectConstruct: + { + HIObjectRef object; + + // Get the HIObject from the event + result = GetEventParameter(inEvent, kEventParamHIObjectInstance, typeHIObjectRef, NULL, sizeof(HIObjectRef), NULL, &object); + require_noerr(result, ParameterMissing); + + // Create the ArcView + arcView = ArcViewCreate(object); + require_action(arcView != NULL, CantCreateArcView, result = memFullErr); + + // Set the ArcView as the data for the object + verify_noerr(SetEventParameter(inEvent, kEventParamHIObjectInstance, typeVoidPtr, sizeof(void *), &arcView)); + break; + } + case kEventHIObjectDestruct: + { + // Dispose the ArcView + ArcViewDispose(arcView); + break; + } + default: + break; + } + break; + } + case kEventClassControl: + { + switch (kind) { + case kEventControlDraw: + { + CGContextRef context; + + // Get the context from the event + verify_noerr(GetEventParameter(inEvent, kEventParamCGContextRef, typeCGContextRef, NULL, sizeof(CGContextRef), NULL, &context)); + + // Draw the ArcView + ArcViewDraw(arcView, context); + break; + } + default: + break; + } + break; + } + default: + break; + } +CantCreateArcView: +ParameterMissing: + return result; +} + +// Create an attributed string with the current font and string. +static CFAttributedStringRef ArcViewCreateAttributedString(ArcView *arcView) +{ + assert(arcView->font != NULL); + + int zero = 0; + CFNumberRef number = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &zero); + + const CFStringRef keys[] = { + kCTFontAttributeName, + kCTLigatureAttributeName + }; + const CFTypeRef values[] = { + arcView->font, + number + }; + + // Create our attributes + CFDictionaryRef attributes = CFDictionaryCreate(kCFAllocatorDefault, (const void**)&keys, (const void**)&values, sizeof(keys)/sizeof(keys[0]), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + assert(attributes != NULL); + + CFRelease(number); + + // Create the attributed string + CFAttributedStringRef attrString = CFAttributedStringCreate(kCFAllocatorDefault, arcView->string, attributes); + CFRelease(attributes); + + return attrString; +} + +// Precompute glyph positioning information +static void PrepareGlyphArcInfo(CTLineRef line, CFIndex glyphCount, GlyphArcInfo *glyphArcInfo) +{ + CFArrayRef runArray = CTLineGetGlyphRuns(line); + CFIndex runCount = CFArrayGetCount(runArray); + + // Examine each run in the line, updating glyphOffset to track how far along the run is in terms of glyphCount. + CFIndex glyphOffset = 0; + CFIndex runIndex = 0; + for (; runIndex < runCount; runIndex++) { + CTRunRef run = (CTRunRef)CFArrayGetValueAtIndex(runArray, runIndex); + CFIndex runGlyphCount = CTRunGetGlyphCount(run); + + // Ask for the width of each glyph in turn. + CFIndex runGlyphIndex = 0; + for (; runGlyphIndex < runGlyphCount; runGlyphIndex++) { + glyphArcInfo[runGlyphIndex + glyphOffset].width = CTRunGetTypographicBounds(run, CFRangeMake(runGlyphIndex, 1), NULL, NULL, NULL); + } + + glyphOffset += runGlyphCount; + } + + double lineLength = CTLineGetTypographicBounds(line, NULL, NULL, NULL); + + CGFloat prevHalfWidth = glyphArcInfo[0].width / 2.0; + glyphArcInfo[0].angle = (prevHalfWidth / lineLength) * M_PI; + + // Divide the arc into slices such that each one covers the distance from one glyph's center to the next. + CFIndex lineGlyphIndex = 1; + for (; lineGlyphIndex < glyphCount; lineGlyphIndex++) { + CGFloat halfWidth = glyphArcInfo[lineGlyphIndex].width / 2.0; + CGFloat prevCenterToCenter = prevHalfWidth + halfWidth; + + glyphArcInfo[lineGlyphIndex].angle = (prevCenterToCenter / lineLength) * M_PI; + + prevHalfWidth = halfWidth; + } +} + +// Create a default font +static CTFontRef ArcViewCreateDefaultFont(void) +{ + return CTFontCreateWithName(ARCVIEW_DEFAULT_FONT_NAME, ARCVIEW_DEFAULT_FONT_SIZE, NULL); +} + +// Create the ArcView object +static ArcView *ArcViewCreate(HIObjectRef object) +{ + ArcView *arcView = NULL; + + require(object != NULL, ParameterMissing); + + arcView = (ArcView *)malloc(sizeof(ArcView)); + require(arcView != NULL, MallocFailed); + + arcView->object = object; + + arcView->font = ArcViewCreateDefaultFont(); + + arcView->string = NULL; + + arcView->radius = ARCVIEW_DEFAULT_RADIUS; + + arcView->options = 0; + +MallocFailed: +ParameterMissing: + return arcView; +} + +// Dispose of the ArcView object +static void ArcViewDispose(ArcView *arcView) +{ + if (arcView->font != NULL) + CFRelease(arcView->font); + if (arcView->string != NULL) + CFRelease(arcView->string); + + free(arcView); +} diff --git a/CoreTextArc/ArcView.h b/CoreTextArc/ArcView.h new file mode 100644 index 00000000..5bf0b0ce --- /dev/null +++ b/CoreTextArc/ArcView.h @@ -0,0 +1,95 @@ +/* + + File: ArcView.h + + Abstract: Declares the interface for the ArcView custom class that uses + CoreText to draw text on a curve. + + Version: 1.0 + + Disclaimer: IMPORTANT: This Apple software is supplied to you by + Apple Inc. ("Apple") in consideration of your agreement to the + following terms, and your use, installation, modification or + redistribution of this Apple software constitutes acceptance of these + terms. If you do not agree with these terms, please do not use, + install, modify or redistribute this Apple software. + + In consideration of your agreement to abide by the following terms, and + subject to these terms, Apple grants you a personal, non-exclusive + license, under Apple's copyrights in this original Apple software (the + "Apple Software"), to use, reproduce, modify and redistribute the Apple + Software, with or without modifications, in source and/or binary forms; + provided that if you redistribute the Apple Software in its entirety and + without modifications, you must retain this notice and the following + text and disclaimers in all such redistributions of the Apple Software. + Neither the name, trademarks, service marks or logos of Apple Inc. + may be used to endorse or promote products derived from the Apple + Software without specific prior written permission from Apple. Except + as expressly stated in this notice, no other rights or licenses, express + or implied, are granted by Apple herein, including but not limited to + any patent rights that may be infringed by your derivative works or by + other works in which the Apple Software may be incorporated. + + The Apple Software is provided by Apple on an "AS IS" basis. APPLE + MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION + THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND + OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. + + IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, + MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED + AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), + STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Copyright (C) 2007 Apple Inc. All Rights Reserved. + + */ + +#include + +enum { + kArcViewControlSignature = 'arcv', + kArcViewControlID = 0 +}; + +#define kArcViewClassID CFSTR("com.apple.example.arcview") + +typedef struct ArcView ArcView; + +// Register the arc view class. This should be done very early, before the nib is loaded. +OSStatus ArcViewRegisterClass(void); + +// Convenience to get the arc view for the specified window. +ArcView *GetArcViewForWindow(HIWindowRef window); + +// Set the font for the arc view. This properly releases the existing font and marks the view as needing display. +void ArcViewSetFont(ArcView *arcView, CTFontRef font); + +// Set the content string for the arc view. This properly releases the existing string and marks the view as needing display. +void ArcViewSetString(ArcView *arcView, CFStringRef string); + +// Get the current font. +CTFontRef ArcViewGetFont(const ArcView *arcView); + +// Get the current content string. +CFStringRef ArcViewGetString(const ArcView *arcView); + +// Draw the view in the provided context. This should not be called directly as it draws in response events. +void ArcViewDraw(ArcView *arcView, CGContextRef context); + +enum { + kArcViewShowGlyphBoundsOption = 1 << 0, + kArcViewShowLineMetricsOption = 1 << 1, + kArcViewDimSubstitutedGlyphsOption = 1 << 2, +}; +typedef UInt32 ArcViewOptions; + +// Set the state for the specified option(s) +void ArcViewSetOptions(ArcView *arcView, ArcViewOptions optionsMask, Boolean state); + +// Returns true if specified options are enabled +Boolean ArcViewGetOptions(ArcView *arcView, ArcViewOptions optionsMask); diff --git a/CoreTextArc/Controls.c b/CoreTextArc/Controls.c new file mode 100644 index 00000000..24b81b35 --- /dev/null +++ b/CoreTextArc/Controls.c @@ -0,0 +1,233 @@ +/* + + File: Controls.c + + Abstract: Defines utility functions for managing controls in the + application user interface. + + Version: 1.0 + + Disclaimer: IMPORTANT: This Apple software is supplied to you by + Apple Inc. ("Apple") in consideration of your agreement to the + following terms, and your use, installation, modification or + redistribution of this Apple software constitutes acceptance of these + terms. If you do not agree with these terms, please do not use, + install, modify or redistribute this Apple software. + + In consideration of your agreement to abide by the following terms, and + subject to these terms, Apple grants you a personal, non-exclusive + license, under Apple's copyrights in this original Apple software (the + "Apple Software"), to use, reproduce, modify and redistribute the Apple + Software, with or without modifications, in source and/or binary forms; + provided that if you redistribute the Apple Software in its entirety and + without modifications, you must retain this notice and the following + text and disclaimers in all such redistributions of the Apple Software. + Neither the name, trademarks, service marks or logos of Apple Inc. + may be used to endorse or promote products derived from the Apple + Software without specific prior written permission from Apple. Except + as expressly stated in this notice, no other rights or licenses, express + or implied, are granted by Apple herein, including but not limited to + any patent rights that may be infringed by your derivative works or by + other works in which the Apple Software may be incorporated. + + The Apple Software is provided by Apple on an "AS IS" basis. APPLE + MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION + THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND + OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. + + IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, + MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED + AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), + STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Copyright (C) 2007 Apple Inc. All Rights Reserved. + + */ + +#include "Controls.h" +#include "ArcView.h" + +// Initializes the text field with the default localized string +void InitializeTextField(HIWindowRef window) +{ + CFStringRef string = CFCopyLocalizedString(CFSTR("Curvaceous Type"), CFSTR("Default string")); + static HIViewID viewID = { kEditTextControlSignature, kEditTextControlID }; + HIViewRef view; + OSStatus err; + + // Use the front window if none specified + if (window == NULL) + window = FrontNonFloatingWindow(); + + // Get the control + err = HIViewFindByID(HIViewGetRoot(window), viewID, &view); + require_noerr(err, CantGetControl); + + // Get the text from the control + verify_noerr(HIViewSetText(view, string)); + +CantGetControl: ; +} + +// Gets the current text from the edit text control in the specified window and sets it to the arc view. +void UpdateText(HIWindowRef window) +{ + static HIViewID viewID = { kEditTextControlSignature, kEditTextControlID }; + HIViewRef view; + OSStatus err; + CFStringRef string; + + // Use the front window if none specified + if (window == NULL) + window = FrontNonFloatingWindow(); + + // Get the control + err = HIViewFindByID(HIViewGetRoot(window), viewID, &view); + require_noerr(err, CantGetControl); + + // Get the text from the control + string = HIViewCopyText(view); + + if (string != NULL) { + // Set the text to the arc view of the same window + ArcView *arcView = GetArcViewForWindow(window); + ArcViewSetString(arcView, string); + + CFRelease(string); + } + +CantGetControl: ; +} + +// Keeps the font controls in sync with the current font. It's important when provided style controls (eg. Bold, Italic) as we are, that they are kept in sync with the font. If the current font cannot be made bold, then the bold control should be disabled. If it is bold, the control should be checked. Likewise for italic. We leave updates of the menu items to another function. +void UpdateFontControls(HIWindowRef window) +{ + ArcView *arcView; + CTFontRef font; + CTFontSymbolicTraits traits; + HIViewRef view; + HIViewID viewID; + + // If we weren't passed a window, use the front window + if (window == NULL) + window = FrontNonFloatingWindow(); + + // Get the view for the window + arcView = GetArcViewForWindow(window); + + // Get the current font and traits + font = ArcViewGetFont(arcView); + traits = CTFontGetSymbolicTraits(font); + + // Get the bold font checkbox control + viewID.signature = kBoldFontControlSignature; + viewID.id = kBoldFontControlID; + verify_noerr(HIViewFindByID(HIViewGetRoot(window), viewID, &view)); + + // Disable the bold checkbox if we can't toggle the trait + HIViewSetEnabled(view, CanToggleFontTrait(font, kCTFontBoldTrait)); + + // Set the value for the checkbox based on the current traits + if ((traits & kCTFontBoldTrait) != 0) + HIViewSetValue(view, kControlCheckBoxCheckedValue); + else + HIViewSetValue(view, kControlCheckBoxUncheckedValue); + + // Get the italic font checkbox control + viewID.signature = kItalicFontControlSignature; + viewID.id = kItalicFontControlID; + verify_noerr(HIViewFindByID(HIViewGetRoot(window), viewID, &view)); + + // Disable the bold checkbox if we can't toggle the trait + HIViewSetEnabled(view, CanToggleFontTrait(font, kCTFontItalicTrait)); + + // Set the value for the checkbox based on the current traits + if ((traits & kCTFontItalicTrait) != 0) + HIViewSetValue(view, kControlCheckBoxCheckedValue); + else + HIViewSetValue(view, kControlCheckBoxUncheckedValue); +} + +enum { + kShowFontsMenuItemIndex = 1, + kHideFontsMenuItemIndex = 2, + kBoldMenuItemIndex = 3, + kItalicMenuItemIndex = 4 +}; + +// Updates the font menu items in the Format menu to keep them in sync with the current font selection. We use two individual menu items to show and hide the Fonts window. Based on the visibility of the fonts window we hide one of thse items. Like UpdateFontControls we need to keep the bold and italic menu items in sync with the capabilities of the font. +void UpdateFormatMenu(MenuRef menu) +{ + CTFontRef font; + ArcView * arcView; + CTFontSymbolicTraits traits; + + // The menu is always based on the front most window + arcView = GetArcViewForWindow(FrontNonFloatingWindow()); + assert(arcView != NULL); + + // Get the current font and traits + font = ArcViewGetFont(arcView); + traits = CTFontGetSymbolicTraits(font); + + if (FPIsFontPanelVisible()) { + // Fonts window is visible. Hide "Show Fonts" and show "Hide Fonts" + ChangeMenuItemAttributes(menu, kShowFontsMenuItemIndex, kMenuItemAttrHidden, 0); + ChangeMenuItemAttributes(menu, kHideFontsMenuItemIndex, 0, kMenuItemAttrHidden); + } else { + // Fonts window is not visible. Show "Show Fonts" and hide "Hide Fonts" + ChangeMenuItemAttributes(menu, kShowFontsMenuItemIndex, 0, kMenuItemAttrHidden); + ChangeMenuItemAttributes(menu, kHideFontsMenuItemIndex, kMenuItemAttrHidden, 0); + } + + // Check the menu item if the font has the bold trait + CheckMenuItem(menu, kBoldMenuItemIndex, ((traits & kCTFontBoldTrait) != 0)); + + // Disable the item if we can't toggle the bold trait + if (!CanToggleFontTrait(font, kCTFontBoldTrait)) { + ChangeMenuItemAttributes(menu, kBoldMenuItemIndex, kMenuItemAttrDisabled, 0); + } else { + ChangeMenuItemAttributes(menu, kBoldMenuItemIndex, 0, kMenuItemAttrDisabled); + } + + // Check the menu item if the font has the italic trait + CheckMenuItem(menu, kItalicMenuItemIndex, ((traits & kCTFontItalicTrait) != 0)); + + // Disable the item if we can't toggle the italic trait + if (!CanToggleFontTrait(font, kCTFontItalicTrait)) { + ChangeMenuItemAttributes(menu, kItalicMenuItemIndex, kMenuItemAttrDisabled, 0); + } else { + ChangeMenuItemAttributes(menu, kItalicMenuItemIndex, 0, kMenuItemAttrDisabled); + } +} + +// Update the font panel with the currently selected font. It's important to do this when we activate the window and display the font panel. The act of calling SetFontInfoForSelection with the event target of the specified window is important to direct future font selection events to that window. This could be a specific control if we wanted to handle font selections on a control by control basis. +void UpdateFontPanel(HIWindowRef window) +{ + ArcView *arcView; + CTFontRef font; + CTFontDescriptorRef descriptor; + + // Use the front window if none specified + if (window == NULL) + window = FrontNonFloatingWindow(); + + // Get the arc view + arcView = GetArcViewForWindow(window); + + // Get the current font + font = ArcViewGetFont(arcView); + + descriptor = CTFontCopyFontDescriptor(font); + verify(descriptor != NULL); + + // Set the font to the font panel, specifying the window as the event target + verify_noerr(SetFontInfoForSelection(kFontSelectionCoreTextType, 1, (void *)&descriptor, GetWindowEventTarget(window))); + CFRelease(descriptor); +} + diff --git a/CoreTextArc/Controls.h b/CoreTextArc/Controls.h new file mode 100644 index 00000000..54bff0be --- /dev/null +++ b/CoreTextArc/Controls.h @@ -0,0 +1,99 @@ +/* + + File: Controls.h + + Abstract: Declares utility functions for managing controls in the + application user interface. + + Version: 1.0 + + Disclaimer: IMPORTANT: This Apple software is supplied to you by + Apple Inc. ("Apple") in consideration of your agreement to the + following terms, and your use, installation, modification or + redistribution of this Apple software constitutes acceptance of these + terms. If you do not agree with these terms, please do not use, + install, modify or redistribute this Apple software. + + In consideration of your agreement to abide by the following terms, and + subject to these terms, Apple grants you a personal, non-exclusive + license, under Apple's copyrights in this original Apple software (the + "Apple Software"), to use, reproduce, modify and redistribute the Apple + Software, with or without modifications, in source and/or binary forms; + provided that if you redistribute the Apple Software in its entirety and + without modifications, you must retain this notice and the following + text and disclaimers in all such redistributions of the Apple Software. + Neither the name, trademarks, service marks or logos of Apple Inc. + may be used to endorse or promote products derived from the Apple + Software without specific prior written permission from Apple. Except + as expressly stated in this notice, no other rights or licenses, express + or implied, are granted by Apple herein, including but not limited to + any patent rights that may be infringed by your derivative works or by + other works in which the Apple Software may be incorporated. + + The Apple Software is provided by Apple on an "AS IS" basis. APPLE + MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION + THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND + OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. + + IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, + MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED + AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), + STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Copyright (C) 2007 Apple Inc. All Rights Reserved. + + */ + +#include + +enum { + // Format menu ID + kFormatMenuID = 104, + // Edit text field control info + kEditTextControlSignature = 'etxt', + kEditTextControlID = 0, + + // Font style controls + // Bold checkbox control info + kBoldFontControlSignature = 'bold', + kBoldFontControlID = 0, + kHICommandBoldFont = 'bold', + // Italic checkbox control info + kItalicFontControlSignature = 'ital', + kItalicFontControlID = 0, + kHICommandItalicFont = 'ital', + + // Arc View options controls + // Show glyph bounds option checkbox control info + kGlyphBoundsOptionControlSignature = 'sgbo', + kIGlyphBoundsOptionControlID = 0, + kHICommandShowGlyphBounds = 'sgbo', + // Show line metrics option checkbox control info + kLineMetricsOptionControlSignature = 'slmo', + kLineMetricsOptionControlID = 0, + kHICommandShowLineMetrics = 'slmo', + // Dim substituted glyphs option checkbox control info + kDimSubstitutedGlyphsControlSignature = 'dsgo', + kDimSubstitutedGlyphsControlID = 0, + kHICommandDimSubstitutedGlyphs = 'dsgo', +}; + +// Initializes the text field with the default localized string +void InitializeTextField(HIWindowRef window); + +// Gets the current text from the edit text control in the specified window and sets it to the arc view. +void UpdateText(HIWindowRef window); + +// Keeps the font controls in sync with the current font. +void UpdateFontControls(HIWindowRef window); + +// Updates the font menu items in the Format menu to keep them in sync with the current font selection. +void UpdateFormatMenu(MenuRef menu); + +// Update the font panel with the currently selected font. +void UpdateFontPanel(HIWindowRef window); diff --git a/CoreTextArc/CoreTextArc.app/Contents/Info.plist b/CoreTextArc/CoreTextArc.app/Contents/Info.plist new file mode 100644 index 00000000..91bf7092 --- /dev/null +++ b/CoreTextArc/CoreTextArc.app/Contents/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + CoreTextArc + CFBundleIdentifier + com.yourcompany.CoreTextArc + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + CoreTextArc + CFBundlePackageType + APPL + CFBundleSignature + ???? + CFBundleVersion + 1.0 + CSResourcesFileMapped + + + diff --git a/CoreTextArc/CoreTextArc.app/Contents/MacOS/CoreTextArc b/CoreTextArc/CoreTextArc.app/Contents/MacOS/CoreTextArc new file mode 100755 index 0000000000000000000000000000000000000000..97dd4e45f83b05a8edfe88005e4923877f2f5591 GIT binary patch literal 61316 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 + + + + IBDocumentLocation + 69 87 356 240 0 0 1920 1178 + IBFramework Version + 461.0 + IBLastKnownRelativeProjectPath + ../../CoreTextArc.xcodeproj + IBOldestOS + 5 + IBOpenObjects + + 166 + + IBSystem Version + 9A445 + targetFramework + IBCarbonFramework + + diff --git a/CoreTextArc/CoreTextArc.app/Contents/Resources/English.lproj/main.nib/objects.xib b/CoreTextArc/CoreTextArc.app/Contents/Resources/English.lproj/main.nib/objects.xib new file mode 100644 index 00000000..e4eb5d87 --- /dev/null +++ b/CoreTextArc/CoreTextArc.app/Contents/Resources/English.lproj/main.nib/objects.xib @@ -0,0 +1,421 @@ + + + IBCarbonFramework + + + + + + main + + + CoreTextArc + + CoreTextArc + 101 + + + About CoreTextArc + 0 + abou + + + _NSAppleMenu + + + + File + + File + 102 + + + New + n + new + + + Open… + o + open + + + TRUE + + + Close + w + clos + + + Save + s + save + + + Save As… + S + svas + + + Revert + r + rvrt + + + TRUE + + + Page Setup… + P + page + + + Print… + p + prnt + + + + + + Edit + + Edit + 103 + + + Undo + z + undo + + + Redo + Z + redo + + + TRUE + + + Cut + x + cut + + + Copy + c + copy + + + Paste + v + past + + + Delete + clea + + + Select All + a + sall + + + TRUE + + + Special Characters… + chrp + + + + + + TRUE + Format + + Format + 104 + + + TRUE + Show Fonts + t + shfp + + + TRUE + TRUE + Hide Fonts + t + shfp + + + TRUE + Bold + b + bold + + + TRUE + Italic + i + ital + + + + + + Window + + Window + 105 + + + TRUE + Minimize + m + mini + + + TRUE + Minimize All + m + 1572864 + mina + + + Zoom + zoom + + + TRUE + + + TRUE + Bring All to Front + bfrt + + + TRUE + Arrange in Front + 1572864 + frnt + + + _NSWindowsMenu + + + + _NSMainMenu + + + + + + + + + + + + + + + + + + + + + + + + + 113 211 500 691 + Window + + 0 0 387 480 + 0 0 480 387 + + + 290 66 306 274 + 66 290 208 16 + etxt + etxt + TRUE + TRUE + + + 20 20 279 460 + 20 20 440 259 + arcv + com.apple.example.arcview + + + 317 62 335 110 + 62 317 48 18 + bold + Bold + bold + + + 341 62 359 112 + 62 341 50 18 + ital + Italic + ital + + + 289 20 305 56 + 20 289 36 16 + Text: + + + 317 20 333 56 + 20 317 36 16 + Font: + + + 285 293 367 460 + 293 285 167 82 + + + 306 309 322 433 + 16 21 124 16 + sgbo + TRUE + 1 + Show glyph bounds + sgbo + + + 346 309 362 453 + 16 61 144 16 + sdgo + TRUE + 1 + Dim substituted glyphs + dsgo + + + 326 309 342 422 + 16 41 113 16 + slmo + TRUE + 1 + Show line metrics + slmo + + + Options + + + + FALSE + FALSE + FALSE + FALSE + TRUE + TRUE + 1 + FALSE + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + File's Owner + + MainWindow + + MenuBar + + + 222 + diff --git a/CoreTextArc/CoreTextArc.app/Contents/Resources/Read Me.rtf b/CoreTextArc/CoreTextArc.app/Contents/Resources/Read Me.rtf new file mode 100644 index 00000000..5b1df324 --- /dev/null +++ b/CoreTextArc/CoreTextArc.app/Contents/Resources/Read Me.rtf @@ -0,0 +1,35 @@ +{\rtf1\ansi\ansicpg1252\cocoartf909\cocoasubrtf300 +{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\margl1440\margr1440\vieww9000\viewh8400\viewkind0 +\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\ql\qnatural\pardirnatural + +\f0\b\fs36 \cf0 CoreTextArc\ + +\b0\fs24 Version 1.0\ +\pard\tx864\pardeftab864\ql\qnatural\pardirnatural +\cf0 Copyright (C) 2007 Apple Inc. All Rights Reserved.\ +\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\ql\qnatural\pardirnatural +\cf0 \ +CoreTextArc illustrates the integration and best-practices of CoreText within a Carbon application. The application will draw text along a curve using CoreText API, and integrate with the font panel, an edit text control, and checkboxes to allow user control. The main concepts illustrated in this documentation are text drawing, font creation, string content creation, font panel integration, font capability reporting, font conversion, and metrics access using appropriate CoreText and related API. This sample comes packaged as a single Xcode project (CoreTextArc.xcodeproj) with a single target (CoreTextArc).\ +\ +CoreTextArc:\ +This target contains the sample application and will build all associated sources and resources as a universal binary.\ +\ +main.c\ +Application and window event handler implementations.\ +\ +ArcView.c/h\ +ArcView custom subclass of HIView that handles the drawing of text along a curve with CoreText. Provides data accessors, drawing routine, even handling, and convenience functions.\ +\ +Controls.c/h\ +Utility functions for maintaining the state of controls in the UI and menu items in the Format menu.\ +\ +Fonts.c/h\ +Provides integration with the font panel and routines for interacting with fonts.\ +\ +main.nib\ +Applications nib file defining the basic user interface.\ +\ +Localizable.string\ +Localizable strings used as default string for the edit text and ArcView controls.} \ No newline at end of file diff --git a/CoreTextArc/CoreTextArc.xcodeproj/project.pbxproj b/CoreTextArc/CoreTextArc.xcodeproj/project.pbxproj new file mode 100644 index 00000000..d94bc951 --- /dev/null +++ b/CoreTextArc/CoreTextArc.xcodeproj/project.pbxproj @@ -0,0 +1,286 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 43; + objects = { + +/* Begin PBXBuildFile section */ + 8D0C4E8D0486CD37000505A6 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 0867D6AAFE840B52C02AAC07 /* InfoPlist.strings */; }; + 8D0C4E8E0486CD37000505A6 /* main.nib in Resources */ = {isa = PBXBuildFile; fileRef = 02345980000FD03B11CA0E72 /* main.nib */; }; + 8D0C4E900486CD37000505A6 /* main.c in Sources */ = {isa = PBXBuildFile; fileRef = 20286C2BFDCF999611CA2CEA /* main.c */; settings = {ATTRIBUTES = (); }; }; + 8D0C4E920486CD37000505A6 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 20286C33FDCF999611CA2CEA /* Carbon.framework */; }; + D8A028E40C10D25000941EA1 /* Read Me.rtf in Resources */ = {isa = PBXBuildFile; fileRef = D8A028E30C10D25000941EA1 /* Read Me.rtf */; }; + D8AE3CE90BFA1F8300FCB32D /* ArcView.c in Sources */ = {isa = PBXBuildFile; fileRef = D8AE3CE80BFA1F8300FCB32D /* ArcView.c */; }; + D8CC1AE30BFD134E007ECCB2 /* Fonts.c in Sources */ = {isa = PBXBuildFile; fileRef = D8CC1AE20BFD134E007ECCB2 /* Fonts.c */; }; + D8CC1AE60BFD13E1007ECCB2 /* Controls.c in Sources */ = {isa = PBXBuildFile; fileRef = D8CC1AE50BFD13E1007ECCB2 /* Controls.c */; }; + D8FD314B0BFE553200763CF8 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = D8FD31490BFE553200763CF8 /* Localizable.strings */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 0867D6ABFE840B52C02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = ""; }; + 1870340FFE93FCAF11CA0CD7 /* English */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = English; path = English.lproj/main.nib; sourceTree = ""; }; + 20286C2BFDCF999611CA2CEA /* main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = main.c; sourceTree = ""; }; + 20286C33FDCF999611CA2CEA /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = /System/Library/Frameworks/Carbon.framework; sourceTree = ""; }; + 32DBCF6D0370B57F00C91783 /* CoreTextArc_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CoreTextArc_Prefix.pch; sourceTree = ""; }; + 4A9504C8FFE6A3BC11CA0CBA /* ApplicationServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ApplicationServices.framework; path = /System/Library/Frameworks/ApplicationServices.framework; sourceTree = ""; }; + 4A9504CAFFE6A41611CA0CBA /* CoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreServices.framework; path = /System/Library/Frameworks/CoreServices.framework; sourceTree = ""; }; + 8D0C4E960486CD37000505A6 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; + 8D0C4E970486CD37000505A6 /* CoreTextArc.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = CoreTextArc.app; sourceTree = BUILT_PRODUCTS_DIR; }; + D8A028E30C10D25000941EA1 /* Read Me.rtf */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; path = "Read Me.rtf"; sourceTree = ""; }; + D8AE3CE70BFA1F8300FCB32D /* ArcView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ArcView.h; sourceTree = ""; }; + D8AE3CE80BFA1F8300FCB32D /* ArcView.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ArcView.c; sourceTree = ""; }; + D8CC1AE10BFD134E007ECCB2 /* Fonts.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Fonts.h; sourceTree = ""; }; + D8CC1AE20BFD134E007ECCB2 /* Fonts.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = Fonts.c; sourceTree = ""; }; + D8CC1AE40BFD13E1007ECCB2 /* Controls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Controls.h; sourceTree = ""; }; + D8CC1AE50BFD13E1007ECCB2 /* Controls.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = Controls.c; sourceTree = ""; }; + D8FD314A0BFE553200763CF8 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/Localizable.strings; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 8D0C4E910486CD37000505A6 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 8D0C4E920486CD37000505A6 /* Carbon.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 195DF8CFFE9D517E11CA2CBB /* Products */ = { + isa = PBXGroup; + children = ( + 8D0C4E970486CD37000505A6 /* CoreTextArc.app */, + ); + name = Products; + sourceTree = ""; + }; + 20286C29FDCF999611CA2CEA /* CoreTextArc */ = { + isa = PBXGroup; + children = ( + D8A028E30C10D25000941EA1 /* Read Me.rtf */, + 20286C2AFDCF999611CA2CEA /* Sources */, + 20286C2CFDCF999611CA2CEA /* Resources */, + 20286C32FDCF999611CA2CEA /* External Frameworks and Libraries */, + 195DF8CFFE9D517E11CA2CBB /* Products */, + ); + name = CoreTextArc; + sourceTree = ""; + }; + 20286C2AFDCF999611CA2CEA /* Sources */ = { + isa = PBXGroup; + children = ( + 32DBCF6D0370B57F00C91783 /* CoreTextArc_Prefix.pch */, + 20286C2BFDCF999611CA2CEA /* main.c */, + D8AE3CE70BFA1F8300FCB32D /* ArcView.h */, + D8AE3CE80BFA1F8300FCB32D /* ArcView.c */, + D8CC1AE40BFD13E1007ECCB2 /* Controls.h */, + D8CC1AE50BFD13E1007ECCB2 /* Controls.c */, + D8CC1AE10BFD134E007ECCB2 /* Fonts.h */, + D8CC1AE20BFD134E007ECCB2 /* Fonts.c */, + ); + name = Sources; + sourceTree = ""; + }; + 20286C2CFDCF999611CA2CEA /* Resources */ = { + isa = PBXGroup; + children = ( + D8FD31490BFE553200763CF8 /* Localizable.strings */, + 8D0C4E960486CD37000505A6 /* Info.plist */, + 0867D6AAFE840B52C02AAC07 /* InfoPlist.strings */, + 02345980000FD03B11CA0E72 /* main.nib */, + ); + name = Resources; + sourceTree = ""; + }; + 20286C32FDCF999611CA2CEA /* External Frameworks and Libraries */ = { + isa = PBXGroup; + children = ( + 20286C33FDCF999611CA2CEA /* Carbon.framework */, + 4A9504CAFFE6A41611CA0CBA /* CoreServices.framework */, + 4A9504C8FFE6A3BC11CA0CBA /* ApplicationServices.framework */, + ); + name = "External Frameworks and Libraries"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 8D0C4E890486CD37000505A6 /* CoreTextArc */ = { + isa = PBXNativeTarget; + buildConfigurationList = C0E91AC508A95435008D54AB /* Build configuration list for PBXNativeTarget "CoreTextArc" */; + buildPhases = ( + 8D0C4E8C0486CD37000505A6 /* Resources */, + 8D0C4E8F0486CD37000505A6 /* Sources */, + 8D0C4E910486CD37000505A6 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = CoreTextArc; + productInstallPath = "$(HOME)/Applications"; + productName = CoreTextArc; + productReference = 8D0C4E970486CD37000505A6 /* CoreTextArc.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 20286C28FDCF999611CA2CEA /* Project object */ = { + isa = PBXProject; + buildConfigurationList = C0E91AC908A95435008D54AB /* Build configuration list for PBXProject "CoreTextArc" */; + compatibilityVersion = "Xcode 3.0"; + hasScannedForEncodings = 1; + mainGroup = 20286C29FDCF999611CA2CEA /* CoreTextArc */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 8D0C4E890486CD37000505A6 /* CoreTextArc */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 8D0C4E8C0486CD37000505A6 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 8D0C4E8D0486CD37000505A6 /* InfoPlist.strings in Resources */, + 8D0C4E8E0486CD37000505A6 /* main.nib in Resources */, + D8FD314B0BFE553200763CF8 /* Localizable.strings in Resources */, + D8A028E40C10D25000941EA1 /* Read Me.rtf in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 8D0C4E8F0486CD37000505A6 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 8D0C4E900486CD37000505A6 /* main.c in Sources */, + D8AE3CE90BFA1F8300FCB32D /* ArcView.c in Sources */, + D8CC1AE30BFD134E007ECCB2 /* Fonts.c in Sources */, + D8CC1AE60BFD13E1007ECCB2 /* Controls.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 02345980000FD03B11CA0E72 /* main.nib */ = { + isa = PBXVariantGroup; + children = ( + 1870340FFE93FCAF11CA0CD7 /* English */, + ); + name = main.nib; + sourceTree = ""; + }; + 0867D6AAFE840B52C02AAC07 /* InfoPlist.strings */ = { + isa = PBXVariantGroup; + children = ( + 0867D6ABFE840B52C02AAC07 /* English */, + ); + name = InfoPlist.strings; + sourceTree = ""; + }; + D8FD31490BFE553200763CF8 /* Localizable.strings */ = { + isa = PBXVariantGroup; + children = ( + D8FD314A0BFE553200763CF8 /* English */, + ); + name = Localizable.strings; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + C0E91AC608A95435008D54AB /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_MODEL_TUNING = G5; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = CoreTextArc_Prefix.pch; + GCC_PREPROCESSOR_DEFINITIONS = "DEBUG=1"; + INFOPLIST_FILE = Info.plist; + INSTALL_PATH = "$(HOME)/Applications"; + PRODUCT_NAME = CoreTextArc; + SDKROOTS = ""; + WRAPPER_EXTENSION = app; + ZERO_LINK = YES; + }; + name = Debug; + }; + C0E91AC708A95435008D54AB /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = ( + ppc, + i386, + ); + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_MODEL_TUNING = G5; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = CoreTextArc_Prefix.pch; + INFOPLIST_FILE = Info.plist; + INSTALL_PATH = "$(HOME)/Applications"; + PRODUCT_NAME = CoreTextArc; + SDKROOTS = ""; + WRAPPER_EXTENSION = app; + }; + name = Release; + }; + C0E91ACA08A95435008D54AB /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + PREBINDING = NO; + SDKROOTS = "$(DEVELOPER_SDK_DIR)/MacOSX10.5.sdk"; + }; + name = Debug; + }; + C0E91ACB08A95435008D54AB /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + PREBINDING = NO; + SDKROOTS = "$(DEVELOPER_SDK_DIR)/MacOSX10.5.sdk"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + C0E91AC508A95435008D54AB /* Build configuration list for PBXNativeTarget "CoreTextArc" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C0E91AC608A95435008D54AB /* Debug */, + C0E91AC708A95435008D54AB /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C0E91AC908A95435008D54AB /* Build configuration list for PBXProject "CoreTextArc" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C0E91ACA08A95435008D54AB /* Debug */, + C0E91ACB08A95435008D54AB /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 20286C28FDCF999611CA2CEA /* Project object */; +} diff --git a/CoreTextArc/CoreTextArc_Prefix.pch b/CoreTextArc/CoreTextArc_Prefix.pch new file mode 100644 index 00000000..d521e77f --- /dev/null +++ b/CoreTextArc/CoreTextArc_Prefix.pch @@ -0,0 +1,51 @@ +/* + + File: CoreTextArc_Prefix.pch + + Abstract: Prefix header. + + Version: 1.0 + + Disclaimer: IMPORTANT: This Apple software is supplied to you by + Apple Inc. ("Apple") in consideration of your agreement to the + following terms, and your use, installation, modification or + redistribution of this Apple software constitutes acceptance of these + terms. If you do not agree with these terms, please do not use, + install, modify or redistribute this Apple software. + + In consideration of your agreement to abide by the following terms, and + subject to these terms, Apple grants you a personal, non-exclusive + license, under Apple's copyrights in this original Apple software (the + "Apple Software"), to use, reproduce, modify and redistribute the Apple + Software, with or without modifications, in source and/or binary forms; + provided that if you redistribute the Apple Software in its entirety and + without modifications, you must retain this notice and the following + text and disclaimers in all such redistributions of the Apple Software. + Neither the name, trademarks, service marks or logos of Apple Inc. + may be used to endorse or promote products derived from the Apple + Software without specific prior written permission from Apple. Except + as expressly stated in this notice, no other rights or licenses, express + or implied, are granted by Apple herein, including but not limited to + any patent rights that may be infringed by your derivative works or by + other works in which the Apple Software may be incorporated. + + The Apple Software is provided by Apple on an "AS IS" basis. APPLE + MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION + THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND + OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. + + IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, + MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED + AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), + STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Copyright (C) 2007 Apple Inc. All Rights Reserved. + + */ + +#include diff --git a/CoreTextArc/English.lproj/InfoPlist.strings b/CoreTextArc/English.lproj/InfoPlist.strings new file mode 100644 index 0000000000000000000000000000000000000000..948e12b991d433e9dc3ebc46350cb859c5bc1e07 GIT binary patch literal 204 zcmW-a%?`m}5Jk`0Q#6*1sMuJDl?@3NJb)A}LVwaCsW + + + + IBDocumentLocation + 69 87 356 240 0 0 1920 1178 + IBFramework Version + 461.0 + IBLastKnownRelativeProjectPath + ../../CoreTextArc.xcodeproj + IBOldestOS + 5 + IBOpenObjects + + 166 + + IBSystem Version + 9A445 + targetFramework + IBCarbonFramework + + diff --git a/CoreTextArc/English.lproj/main.nib/objects.xib b/CoreTextArc/English.lproj/main.nib/objects.xib new file mode 100644 index 00000000..e4eb5d87 --- /dev/null +++ b/CoreTextArc/English.lproj/main.nib/objects.xib @@ -0,0 +1,421 @@ + + + IBCarbonFramework + + + + + + main + + + CoreTextArc + + CoreTextArc + 101 + + + About CoreTextArc + 0 + abou + + + _NSAppleMenu + + + + File + + File + 102 + + + New + n + new + + + Open… + o + open + + + TRUE + + + Close + w + clos + + + Save + s + save + + + Save As… + S + svas + + + Revert + r + rvrt + + + TRUE + + + Page Setup… + P + page + + + Print… + p + prnt + + + + + + Edit + + Edit + 103 + + + Undo + z + undo + + + Redo + Z + redo + + + TRUE + + + Cut + x + cut + + + Copy + c + copy + + + Paste + v + past + + + Delete + clea + + + Select All + a + sall + + + TRUE + + + Special Characters… + chrp + + + + + + TRUE + Format + + Format + 104 + + + TRUE + Show Fonts + t + shfp + + + TRUE + TRUE + Hide Fonts + t + shfp + + + TRUE + Bold + b + bold + + + TRUE + Italic + i + ital + + + + + + Window + + Window + 105 + + + TRUE + Minimize + m + mini + + + TRUE + Minimize All + m + 1572864 + mina + + + Zoom + zoom + + + TRUE + + + TRUE + Bring All to Front + bfrt + + + TRUE + Arrange in Front + 1572864 + frnt + + + _NSWindowsMenu + + + + _NSMainMenu + + + + + + + + + + + + + + + + + + + + + + + + + 113 211 500 691 + Window + + 0 0 387 480 + 0 0 480 387 + + + 290 66 306 274 + 66 290 208 16 + etxt + etxt + TRUE + TRUE + + + 20 20 279 460 + 20 20 440 259 + arcv + com.apple.example.arcview + + + 317 62 335 110 + 62 317 48 18 + bold + Bold + bold + + + 341 62 359 112 + 62 341 50 18 + ital + Italic + ital + + + 289 20 305 56 + 20 289 36 16 + Text: + + + 317 20 333 56 + 20 317 36 16 + Font: + + + 285 293 367 460 + 293 285 167 82 + + + 306 309 322 433 + 16 21 124 16 + sgbo + TRUE + 1 + Show glyph bounds + sgbo + + + 346 309 362 453 + 16 61 144 16 + sdgo + TRUE + 1 + Dim substituted glyphs + dsgo + + + 326 309 342 422 + 16 41 113 16 + slmo + TRUE + 1 + Show line metrics + slmo + + + Options + + + + FALSE + FALSE + FALSE + FALSE + TRUE + TRUE + 1 + FALSE + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + File's Owner + + MainWindow + + MenuBar + + + 222 + diff --git a/CoreTextArc/Fonts.c b/CoreTextArc/Fonts.c new file mode 100644 index 00000000..5d508b49 --- /dev/null +++ b/CoreTextArc/Fonts.c @@ -0,0 +1,153 @@ +/* + + File: Fonts.h + + Abstract: Defines utility functions for interacting with fonts in the + application. + + Version: 1.0 + + Disclaimer: IMPORTANT: This Apple software is supplied to you by + Apple Inc. ("Apple") in consideration of your agreement to the + following terms, and your use, installation, modification or + redistribution of this Apple software constitutes acceptance of these + terms. If you do not agree with these terms, please do not use, + install, modify or redistribute this Apple software. + + In consideration of your agreement to abide by the following terms, and + subject to these terms, Apple grants you a personal, non-exclusive + license, under Apple's copyrights in this original Apple software (the + "Apple Software"), to use, reproduce, modify and redistribute the Apple + Software, with or without modifications, in source and/or binary forms; + provided that if you redistribute the Apple Software in its entirety and + without modifications, you must retain this notice and the following + text and disclaimers in all such redistributions of the Apple Software. + Neither the name, trademarks, service marks or logos of Apple Inc. + may be used to endorse or promote products derived from the Apple + Software without specific prior written permission from Apple. Except + as expressly stated in this notice, no other rights or licenses, express + or implied, are granted by Apple herein, including but not limited to + any patent rights that may be infringed by your derivative works or by + other works in which the Apple Software may be incorporated. + + The Apple Software is provided by Apple on an "AS IS" basis. APPLE + MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION + THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND + OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. + + IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, + MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED + AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), + STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Copyright (C) 2007 Apple Inc. All Rights Reserved. + + */ + +#include "Fonts.h" +#include "ArcView.h" + +// Change the font based on the font selection event from the Fonts window. +void ChangeFont(EventRef inEvent, HIWindowRef window) +{ + CTFontDescriptorRef descriptor, newDescriptor; + CGFloat size; + + OSStatus err; + ArcView *arcView; + + // Use the front window if none specified. + if (window == NULL) + window = FrontNonFloatingWindow(); + + arcView = GetArcViewForWindow(window); + + // Get the original font descriptor from the view + descriptor = CTFontCopyFontDescriptor(ArcViewGetFont(arcView)); + size = CTFontGetSize(ArcViewGetFont(arcView)); + + err = GetEventParameter(inEvent, kEventParamCTFontDescriptor, typeCTFontDescriptorRef, NULL, sizeof(newDescriptor), NULL, &newDescriptor); + if (err == noErr && newDescriptor != NULL) { + CFDictionaryRef newAttributes = CTFontDescriptorCopyAttributes(newDescriptor); + + // Merge the changes from the font panel with our current font. The font panel is smart enough to provide the necessary items to update the font correctly, and CoreText merges the necessary attributes such as variations and features. + newDescriptor = CTFontDescriptorCreateCopyWithAttributes(descriptor, newAttributes); + + CFRelease(newAttributes); + CFRelease(descriptor); + descriptor = newDescriptor; + } // Create our new font from the descriptor + + if (descriptor != NULL) { + CTFontRef font = CTFontCreateWithFontDescriptor(descriptor, 0., NULL); + + // Set the font to the view + ArcViewSetFont(arcView, font); + + CFRelease(descriptor); + CFRelease(font); + } +} + +// Toggles the specified trait of the font for the view in the specified window. +void ToggleFontTrait(HIWindowRef window, CTFontSymbolicTraits trait) +{ + ArcView *arcView; + CTFontSymbolicTraits origTraits; + CTFontRef convertedFont; + CTFontRef font; + + // Use the front window if none specified + if (window == NULL) + window = FrontNonFloatingWindow(); + + arcView = GetArcViewForWindow(window); + + // Get the current font and traits + font = ArcViewGetFont(arcView); + origTraits = CTFontGetSymbolicTraits(font); + + // Add or remove the trait depending on whether the font currently has it or not. Note that the mask is always the trait(s) we are modifying and the trait value is the value we want to assign to the traits. Traits are a bitmask. + if ((origTraits & trait) == 0) { + convertedFont = CTFontCreateCopyWithSymbolicTraits(font, 0., NULL, trait, trait); + } else { + convertedFont = CTFontCreateCopyWithSymbolicTraits(font, 0., NULL, 0, trait); + } + // If we got a new font, set it to the view + if (convertedFont != NULL) { + ArcViewSetFont(arcView, convertedFont); + + CFRelease(convertedFont); + } +} + +// Check to see if the font can toggle the specified trait. This is accomplished by attempting to switch the trait's value to the opposite of the current value. +Boolean CanToggleFontTrait(CTFontRef font, CTFontSymbolicTraits trait) +{ + Boolean result = false; + CTFontSymbolicTraits origTraits; + CTFontRef convertedFont; + + // Get the original traits + origTraits = CTFontGetSymbolicTraits(font); + + // Try to add or remove the trait depending on whether the font currently has it or not. Note that the mask is always the trait(s) we are modifying and the trait value is the value we want to assign to the traits. Traits are a bitmask. + if ((origTraits & trait) == 0) { + convertedFont = CTFontCreateCopyWithSymbolicTraits(font, 0., NULL, trait, trait); + } else { + convertedFont = CTFontCreateCopyWithSymbolicTraits(font, 0., NULL, 0, trait); + } + if (convertedFont != NULL) { + // Success, release the font and return true + CFRelease(convertedFont); + result = true; + } + return result; +} + + diff --git a/CoreTextArc/Fonts.h b/CoreTextArc/Fonts.h new file mode 100644 index 00000000..bf693bd8 --- /dev/null +++ b/CoreTextArc/Fonts.h @@ -0,0 +1,61 @@ +/* + + File: Fonts.h + + Abstract: Declares utility functions for interacting with fonts in the + application. + + Version: 1.0 + + Disclaimer: IMPORTANT: This Apple software is supplied to you by + Apple Inc. ("Apple") in consideration of your agreement to the + following terms, and your use, installation, modification or + redistribution of this Apple software constitutes acceptance of these + terms. If you do not agree with these terms, please do not use, + install, modify or redistribute this Apple software. + + In consideration of your agreement to abide by the following terms, and + subject to these terms, Apple grants you a personal, non-exclusive + license, under Apple's copyrights in this original Apple software (the + "Apple Software"), to use, reproduce, modify and redistribute the Apple + Software, with or without modifications, in source and/or binary forms; + provided that if you redistribute the Apple Software in its entirety and + without modifications, you must retain this notice and the following + text and disclaimers in all such redistributions of the Apple Software. + Neither the name, trademarks, service marks or logos of Apple Inc. + may be used to endorse or promote products derived from the Apple + Software without specific prior written permission from Apple. Except + as expressly stated in this notice, no other rights or licenses, express + or implied, are granted by Apple herein, including but not limited to + any patent rights that may be infringed by your derivative works or by + other works in which the Apple Software may be incorporated. + + The Apple Software is provided by Apple on an "AS IS" basis. APPLE + MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION + THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND + OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. + + IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, + MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED + AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), + STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Copyright (C) 2007 Apple Inc. All Rights Reserved. + + */ + +#include + +// Change the font based on the font selection event from the Fonts window. +void ChangeFont(EventRef inEvent, HIWindowRef window); + +// Toggles the specified trait of the font for the view in the specified window. +void ToggleFontTrait(HIWindowRef window, CTFontSymbolicTraits trait); + +// Check to see if the font can toggle the specified trait. +Boolean CanToggleFontTrait(CTFontRef font, CTFontSymbolicTraits trait); diff --git a/CoreTextArc/Info.plist b/CoreTextArc/Info.plist new file mode 100644 index 00000000..5d224cb6 --- /dev/null +++ b/CoreTextArc/Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIconFile + + CFBundleIdentifier + com.yourcompany.CoreTextArc + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + APPL + CFBundleSignature + ???? + CFBundleVersion + 1.0 + CSResourcesFileMapped + + + diff --git a/CoreTextArc/Read Me.rtf b/CoreTextArc/Read Me.rtf new file mode 100644 index 00000000..5b1df324 --- /dev/null +++ b/CoreTextArc/Read Me.rtf @@ -0,0 +1,35 @@ +{\rtf1\ansi\ansicpg1252\cocoartf909\cocoasubrtf300 +{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\margl1440\margr1440\vieww9000\viewh8400\viewkind0 +\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\ql\qnatural\pardirnatural + +\f0\b\fs36 \cf0 CoreTextArc\ + +\b0\fs24 Version 1.0\ +\pard\tx864\pardeftab864\ql\qnatural\pardirnatural +\cf0 Copyright (C) 2007 Apple Inc. All Rights Reserved.\ +\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\ql\qnatural\pardirnatural +\cf0 \ +CoreTextArc illustrates the integration and best-practices of CoreText within a Carbon application. The application will draw text along a curve using CoreText API, and integrate with the font panel, an edit text control, and checkboxes to allow user control. The main concepts illustrated in this documentation are text drawing, font creation, string content creation, font panel integration, font capability reporting, font conversion, and metrics access using appropriate CoreText and related API. This sample comes packaged as a single Xcode project (CoreTextArc.xcodeproj) with a single target (CoreTextArc).\ +\ +CoreTextArc:\ +This target contains the sample application and will build all associated sources and resources as a universal binary.\ +\ +main.c\ +Application and window event handler implementations.\ +\ +ArcView.c/h\ +ArcView custom subclass of HIView that handles the drawing of text along a curve with CoreText. Provides data accessors, drawing routine, even handling, and convenience functions.\ +\ +Controls.c/h\ +Utility functions for maintaining the state of controls in the UI and menu items in the Format menu.\ +\ +Fonts.c/h\ +Provides integration with the font panel and routines for interacting with fonts.\ +\ +main.nib\ +Applications nib file defining the basic user interface.\ +\ +Localizable.string\ +Localizable strings used as default string for the edit text and ArcView controls.} \ No newline at end of file diff --git a/CoreTextArc/main.c b/CoreTextArc/main.c new file mode 100644 index 00000000..95aa9260 --- /dev/null +++ b/CoreTextArc/main.c @@ -0,0 +1,388 @@ +/* + + File: main.c + + Abstract: Implements application and window event handlers. Derived from + Carbon C Application standard project. + + Version: 1.0 + + Disclaimer: IMPORTANT: This Apple software is supplied to you by + Apple Inc. ("Apple") in consideration of your agreement to the + following terms, and your use, installation, modification or + redistribution of this Apple software constitutes acceptance of these + terms. If you do not agree with these terms, please do not use, + install, modify or redistribute this Apple software. + + In consideration of your agreement to abide by the following terms, and + subject to these terms, Apple grants you a personal, non-exclusive + license, under Apple's copyrights in this original Apple software (the + "Apple Software"), to use, reproduce, modify and redistribute the Apple + Software, with or without modifications, in source and/or binary forms; + provided that if you redistribute the Apple Software in its entirety and + without modifications, you must retain this notice and the following + text and disclaimers in all such redistributions of the Apple Software. + Neither the name, trademarks, service marks or logos of Apple Inc. + may be used to endorse or promote products derived from the Apple + Software without specific prior written permission from Apple. Except + as expressly stated in this notice, no other rights or licenses, express + or implied, are granted by Apple herein, including but not limited to + any patent rights that may be infringed by your derivative works or by + other works in which the Apple Software may be incorporated. + + The Apple Software is provided by Apple on an "AS IS" basis. APPLE + MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION + THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND + OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. + + IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, + MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED + AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), + STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Copyright (C) 2007 Apple Inc. All Rights Reserved. + + */ + +#include +#include "ArcView.h" +#include "Controls.h" +#include "Fonts.h" + +static OSStatus AppEventHandler(EventHandlerCallRef inCaller, EventRef inEvent, void* inRefcon); +static OSStatus HandleNew(); +static OSStatus WindowEventHandler(EventHandlerCallRef inCaller, EventRef inEvent, void* inRefcon); + +static IBNibRef sNibRef; + +//-------------------------------------------------------------------------------------------- +int main(int argc, char* argv[]) +{ + OSStatus err; + static const EventTypeSpec kAppEvents[] = + { + { kEventClassCommand, kEventCommandProcess } + }; + + // Register our custom HIObject class before we load the nib + verify_noerr(ArcViewRegisterClass()); + + // Create a Nib reference, passing the name of the nib file (without the .nib extension). + // CreateNibReference only searches into the application bundle. + err = CreateNibReference(CFSTR("main"), &sNibRef); + require_noerr(err, CantGetNibRef); + + // Once the nib reference is created, set the menu bar. "MainMenu" is the name of the menu bar + // object. This name is set in InterfaceBuilder when the nib is created. + err = SetMenuBarFromNib(sNibRef, CFSTR("MenuBar")); + require_noerr(err, CantSetMenuBar); + + // Install our handler for common commands on the application target + InstallApplicationEventHandler(NewEventHandlerUPP(AppEventHandler), + GetEventTypeCount(kAppEvents), kAppEvents, + 0, NULL); + + // Create a new window. A full-fledged application would do this from an AppleEvent handler + // for kAEOpenApplication. + HandleNew(); + + // Run the event loop + RunApplicationEventLoop(); + +CantSetMenuBar: +CantGetNibRef: + return err; +} + +//-------------------------------------------------------------------------------------------- +static OSStatus +AppEventHandler(EventHandlerCallRef inCaller, EventRef inEvent, void* inRefcon) +{ + OSStatus result = eventNotHandledErr; + OSType class = GetEventClass(inEvent); + UInt32 kind = GetEventKind(inEvent); + + switch (class) + { + case kEventClassCommand: + { + HICommandExtended cmd; + verify_noerr(GetEventParameter(inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(cmd), NULL, &cmd)); + + switch (kind) + { + case kEventCommandProcess: + switch (cmd.commandID) + { + case kHICommandNew: + result = HandleNew(); + break; + default: + break; + } + break; + default: + break; + } + break; + } + default: + break; + } + + return result; +} + +//-------------------------------------------------------------------------------------------- +DEFINE_ONE_SHOT_HANDLER_GETTER(WindowEventHandler) + +//-------------------------------------------------------------------------------------------- +static OSStatus +HandleNew() +{ + OSStatus err; + HIWindowRef window; + HIViewRef view; + HIViewID viewID; + + // Window events + static const EventTypeSpec kWindowEvents[] = + { + { kEventClassCommand, kEventCommandProcess }, + { kEventClassWindow, kEventWindowActivated }, + { kEventClassMenu, kEventMenuEnableItems }, + { kEventClassFont, kEventFontSelection } + }; + + // Control events + static const EventTypeSpec kTextFieldEvents[] = + { + { kEventClassTextField, kEventTextAccepted }, + { kEventClassTextField, kEventTextDidChange } + }; + + // Create a window. "MainWindow" is the name of the window object. This name is set in + // InterfaceBuilder when the nib is created. + err = CreateWindowFromNib(sNibRef, CFSTR("MainWindow"), &window); + require_noerr(err, CantCreateWindow); + + // Install a window event handler on the window. + InstallWindowEventHandler(window, GetWindowEventHandlerUPP(), + GetEventTypeCount(kWindowEvents), kWindowEvents, + window, (void *)window); + + viewID.signature = kEditTextControlSignature; + viewID.id = kEditTextControlID; + + // Get the control + err = HIViewFindByID(HIViewGetRoot(window), viewID, &view); + require_noerr(err, CantGetControl); + + // Install a control event handler. We use the window handler for convenience as the control + // is in the window and there is only one event. + InstallControlEventHandler(view, GetWindowEventHandlerUPP(), + GetEventTypeCount(kTextFieldEvents), kTextFieldEvents, + view, (void *)view); + + // Initialize the text + InitializeTextField(window); + + // Update the text in the window + UpdateText(window); + + // Update the font for the window + UpdateFontControls(window); + UpdateFontPanel(window); + +CantGetControl: + // Position new windows in a staggered arrangement on the main screen + RepositionWindow(window, NULL, kWindowCascadeOnMainScreen); + + // The window was created hidden, so show it + ShowWindow(window); + +CantCreateWindow: + return err; +} + +//-------------------------------------------------------------------------------------------- +static OSStatus +WindowEventHandler(EventHandlerCallRef inCaller, EventRef inEvent, void* inRefcon) +{ + OSStatus err = eventNotHandledErr; + OSType class = GetEventClass(inEvent); + UInt32 kind = GetEventKind(inEvent); + + switch (class) + { + case kEventClassCommand: + { + HICommandExtended cmd; + verify_noerr(GetEventParameter(inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(cmd), NULL, &cmd)); + + // Get the window for the control in the command + HIWindowRef window = HIViewGetWindow(cmd.source.control); + + switch (kind) + { + case kEventCommandProcess: + { + switch (cmd.commandID) + { + // Add your own command-handling cases here + case kHICommandBoldFont: + { + // Make the font bold + ToggleFontTrait(window, kCTFontBoldTrait); + // Update the font interface elements + UpdateFontControls(window); + UpdateFontPanel(window); + err = noErr; // Handled the event + break; + } + case kHICommandItalicFont: + { + // Make the font italic + ToggleFontTrait(window, kCTFontItalicTrait); + // Update the font interface elements + UpdateFontControls(window); + UpdateFontPanel(window); + err = noErr; // Handled the event + break; + } + case kHICommandShowHideFontPanel: + { + // Update the font panel when it is displayed + UpdateFontPanel(window); + // Don't handle the event + break; + } + // ArcView options + case kHICommandShowGlyphBounds: + { + Boolean state = (HIViewGetValue(cmd.source.control) == kControlCheckBoxCheckedValue); + ArcViewSetOptions(GetArcViewForWindow(window), kArcViewShowGlyphBoundsOption, state); + err = noErr; // Handled the event + break; + } + case kHICommandShowLineMetrics: + { + Boolean state = (HIViewGetValue(cmd.source.control) == kControlCheckBoxCheckedValue); + ArcViewSetOptions(GetArcViewForWindow(window), kArcViewShowLineMetricsOption, state); + err = noErr; // Handled the event + break; + } + case kHICommandDimSubstitutedGlyphs: + { + Boolean state = (HIViewGetValue(cmd.source.control) == kControlCheckBoxCheckedValue); + ArcViewSetOptions(GetArcViewForWindow(window), kArcViewDimSubstitutedGlyphsOption, state); + err = noErr; // Handled the event + break; + } + default: + break; + } + break; + } + default: + break; + } + break; + } + case kEventClassWindow: + { + switch (kind) { + case kEventWindowActivated: + { + HIWindowRef window; + // Get the window from the event + verify_noerr(GetEventParameter(inEvent, kEventParamDirectObject, typeWindowRef, NULL, sizeof(window), NULL, &window)); + + // Update the text + UpdateText(window); + // Update the font interfaces + UpdateFontControls(window); + UpdateFontPanel(window); + break; + } + default: + break; + } + break; + } + case kEventClassMenu: + { + switch (kind) { + case kEventMenuEnableItems: + { + MenuRef menu; + + // Get the menu for the event + verify_noerr(GetEventParameter(inEvent, kEventParamDirectObject, typeMenuRef, NULL, sizeof(menu), NULL, &menu)); + // Update the format menu. This will validate the font trait items, and swap the Show/Hide Fonts items. + if (GetMenuID(menu) == kFormatMenuID) { + UpdateFormatMenu(menu); + } + break; + } + default: + break; + } + break; + } + case kEventClassFont: + { + switch (kind) { + case kEventFontSelection: + { + // Change the font for the event + ChangeFont(inEvent, (HIWindowRef)inRefcon); + // Update the font interface + UpdateFontControls((HIWindowRef)inRefcon); + break; + } + default: + break; + } + break; + } + case kEventClassTextField: + { + switch (kind) + { + case kEventTextAccepted: + { + // Get the window from the control in the refcon + HIWindowRef window = HIViewGetWindow((HIViewRef)inRefcon); + // Update text on end editing + UpdateText(window); + break; + } + case kEventTextDidChange: + { + // Get the window from the control in the refcon + HIWindowRef window = HIViewGetWindow((HIViewRef)inRefcon); + CFRange range; + + // Check to see if we have an inline hole. If there is an unconfirmed range, we have an inline hole and don't want to update the text until the text is confirmed. + if (GetEventParameter(inEvent, kEventParamUnconfirmedRange, typeCFRange, NULL, sizeof(CFRange), NULL, &range) != noErr) + UpdateText(window); + break; + } + default: + break; + } + break; + } + default: + break; + } + + return err; +} +