// // RiveFactory.m // RiveRuntime // // Created by Maxwell Talbot on 08/11/2023. // Copyright © 2023 Rive. All rights reserved. // #import #import #import #import #import #if WITH_RIVE_TEXT #import #import #if TARGET_OS_IPHONE #import #endif #endif #if WITH_RIVE_TEXT static rive::rcp riveFontFromNativeFont(id font, bool useSystemShaper) { uint16_t weight = 400; if ([font conformsToProtocol:@protocol(RiveWeightProvider)]) { weight = [font riveWeightValue]; } uint8_t width = 100; if ([font conformsToProtocol:@protocol(RiveFontWidthProvider)]) { width = [font riveFontWidthValue]; } CTFontRef ctFont = (__bridge CTFontRef)font; return HBFont::FromSystem((void*)ctFont, useSystemShaper, weight, width); } #endif @implementation RiveRenderImage { rive::rcp instance; // note: we do NOT own this, so don't delete it } - (instancetype)initWithImage:(rive::rcp)image { if (self = [super init]) { instance = image; return self; } else { return nil; } } - (instancetype)initWithData:(NSData*)data { RenderContext* context = [[RenderContextManager shared] newDefaultContext]; RiveFactory* factory = [[RiveFactory alloc] initWithFactory:[context factory]]; auto renderImage = [factory decodeImage:data]; auto image = [renderImage instance]; if (image == nullptr || image.get() == nullptr) { return nil; } return [[RiveRenderImage alloc] initWithImage:image]; } - (rive::rcp)instance { return instance; } @end #ifdef WITH_RIVE_AUDIO @implementation RiveAudio { rive::rcp instance; // note: we do NOT own this, so don't delete it } - (instancetype)initWithAudio:(rive::rcp)audio { if (self = [super init]) { instance = audio; return self; } else { return nil; } } - (rive::rcp)instance { return instance; } @end #endif /* * RiveFactory */ @implementation RiveFactory { rive::Factory* instance; // note: we do NOT own this, so don't delete it } // Creates a new RiveFactory from a cpp RiveFactory - (instancetype)initWithFactory:(rive::Factory*)factory { if (self = [super init]) { instance = factory; return self; } else { return nil; } } - (RiveRenderImage*)decodeImage:(nonnull NSData*)data { UInt8* bytes = (UInt8*)[data bytes]; return [[RiveRenderImage alloc] initWithImage:instance->decodeImage( rive::Span(bytes, [data length]))]; } #ifdef WITH_RIVE_TEXT - (RiveFont*)decodeFont:(nonnull NSData*)data { UInt8* bytes = (UInt8*)[data bytes]; return [[RiveFont alloc] initWithFont:instance->decodeFont( rive::Span(bytes, [data length]))]; } #if TARGET_OS_IPHONE - (RiveFont*)decodeUIFont:(UIFont*)font { return [[RiveFont alloc] initWithFont:riveFontFromNativeFont(font, true)]; } #else - (RiveFont*)decodeNSFont:(NSFont*)font { return [[RiveFont alloc] initWithFont:riveFontFromNativeFont(font, true)]; } #endif #endif #ifdef WITH_RIVE_AUDIO - (RiveAudio*)decodeAudio:(nonnull NSData*)data { UInt8* bytes = (UInt8*)[data bytes]; return [[RiveAudio alloc] initWithAudio:instance->decodeAudio( rive::Span(bytes, [data length]))]; } #endif @end