what's new
* 动态启动图
* 动态聊天背景
* 支持8.0.1
* 更新越狱包8.0.1
* 更新已注入助手的8.0.1未签名包
* 更新越狱源安装包
This commit is contained in:
DKJone
2021-01-29 16:35:34 +08:00
parent 25a3f7f760
commit 888af8954e
125 changed files with 10144 additions and 40 deletions
@@ -0,0 +1,25 @@
// QGBaseAnimatedImageFrame+Displaying.h
// Tencent is pleased to support the open source community by making vap available.
//
// Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved.
//
// Licensed under the MIT License (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
//
// http://opensource.org/licenses/MIT
//
// Unless required by applicable law or agreed to in writing, software distributed under the License is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
// either express or implied. See the License for the specific language governing permissions and
// limitations under the License.
#import "QGBaseAnimatedImageFrame.h"
@interface QGBaseAnimatedImageFrame (Displaying)
@property (nonatomic, strong) NSDate *startDate; //开始播放的时间
@property (nonatomic, assign) NSTimeInterval decodeTime; //解码时间
- (BOOL)shouldFinishDisplaying; //是否需要结束播放(根据播放时长来决定)
@end
@@ -0,0 +1,34 @@
// QGBaseAnimatedImageFrame+Displaying.m
// Tencent is pleased to support the open source community by making vap available.
//
// Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved.
//
// Licensed under the MIT License (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
//
// http://opensource.org/licenses/MIT
//
// Unless required by applicable law or agreed to in writing, software distributed under the License is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
// either express or implied. See the License for the specific language governing permissions and
// limitations under the License.
#import "QGBaseAnimatedImageFrame+Displaying.h"
#import <objc/runtime.h>
#import "VAPMacros.h"
@implementation QGBaseAnimatedImageFrame (Displaying)
HWDSYNTH_DYNAMIC_PROPERTY_CTYPE(decodeTime, setDecodeTime, NSTimeInterval)
HWDSYNTH_DYNAMIC_PROPERTY_OBJECT(startDate, setStartDate, OBJC_ASSOCIATION_RETAIN);
- (BOOL)shouldFinishDisplaying {
if (!self.startDate) {
return YES;
}
NSTimeInterval timeInterval = [[NSDate date] timeIntervalSinceDate:self.startDate];
//每一个VSYNC16ms
return timeInterval*1000 + 10 >= self.duration;
}
@end
@@ -0,0 +1,25 @@
// QGBaseAnimatedImageFrame.h
// Tencent is pleased to support the open source community by making vap available.
//
// Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved.
//
// Licensed under the MIT License (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
//
// http://opensource.org/licenses/MIT
//
// Unless required by applicable law or agreed to in writing, software distributed under the License is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
// either express or implied. See the License for the specific language governing permissions and
// limitations under the License.
#import <Foundation/Foundation.h>
@interface QGBaseAnimatedImageFrame : NSObject
@property (atomic, assign) NSInteger frameIndex; //当前帧索引
@property (atomic, assign) NSTimeInterval duration; //播放时长
/** pts */
@property (atomic, assign) uint64_t pts;
@end
@@ -0,0 +1,20 @@
// QGBaseAnimatedImageFrame.m
// Tencent is pleased to support the open source community by making vap available.
//
// Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved.
//
// Licensed under the MIT License (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
//
// http://opensource.org/licenses/MIT
//
// Unless required by applicable law or agreed to in writing, software distributed under the License is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
// either express or implied. See the License for the specific language governing permissions and
// limitations under the License.
#import "QGBaseAnimatedImageFrame.h"
@implementation QGBaseAnimatedImageFrame
@end
@@ -0,0 +1,23 @@
// QGBaseDFileInfo.h
// Tencent is pleased to support the open source community by making vap available.
//
// Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved.
//
// Licensed under the MIT License (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
//
// http://opensource.org/licenses/MIT
//
// Unless required by applicable law or agreed to in writing, software distributed under the License is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
// either express or implied. See the License for the specific language governing permissions and
// limitations under the License.
#import <Foundation/Foundation.h>
@interface QGBaseDFileInfo : NSObject
@property (nonatomic, strong) NSString *filePath; //文件路径
@property (atomic, assign) NSInteger occupiedCount; //作用类似retainCount
@end
@@ -0,0 +1,20 @@
// QGBaseDFileInfo.m
// Tencent is pleased to support the open source community by making vap available.
//
// Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved.
//
// Licensed under the MIT License (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
//
// http://opensource.org/licenses/MIT
//
// Unless required by applicable law or agreed to in writing, software distributed under the License is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
// either express or implied. See the License for the specific language governing permissions and
// limitations under the License.
#import "QGBaseDFileInfo.h"
@implementation QGBaseDFileInfo
@end
@@ -0,0 +1,24 @@
// QGMP4AnimatedImageFrame.h
// Tencent is pleased to support the open source community by making vap available.
//
// Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved.
//
// Licensed under the MIT License (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
//
// http://opensource.org/licenses/MIT
//
// Unless required by applicable law or agreed to in writing, software distributed under the License is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
// either express or implied. See the License for the specific language governing permissions and
// limitations under the License.
#import "QGBaseAnimatedImageFrame.h"
#import <CoreVideo/CoreVideo.h>
@interface QGMP4AnimatedImageFrame : QGBaseAnimatedImageFrame
@property (nonatomic, assign) CVPixelBufferRef pixelBuffer;
@property (nonatomic, assign) int defaultFps;
@end
@@ -0,0 +1,28 @@
// QGMP4AnimatedImageFrame.m
// Tencent is pleased to support the open source community by making vap available.
//
// Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved.
//
// Licensed under the MIT License (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
//
// http://opensource.org/licenses/MIT
//
// Unless required by applicable law or agreed to in writing, software distributed under the License is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
// either express or implied. See the License for the specific language governing permissions and
// limitations under the License.
#import "QGMP4AnimatedImageFrame.h"
@implementation QGMP4AnimatedImageFrame
- (void)dealloc {
//释放image buffer
if (self.pixelBuffer) {
CVPixelBufferRelease(self.pixelBuffer);
}
}
@end
@@ -0,0 +1,23 @@
// QGMP4HWDFileInfo.h
// Tencent is pleased to support the open source community by making vap available.
//
// Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved.
//
// Licensed under the MIT License (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
//
// http://opensource.org/licenses/MIT
//
// Unless required by applicable law or agreed to in writing, software distributed under the License is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
// either express or implied. See the License for the specific language governing permissions and
// limitations under the License.
#import "QGBaseDFileInfo.h"
#import "QGMP4Parser.h"
@interface QGMP4HWDFileInfo : QGBaseDFileInfo
@property (nonatomic, strong) QGMP4ParserProxy *mp4Parser;
@end
@@ -0,0 +1,20 @@
// QGMP4HWDFileInfo.m
// Tencent is pleased to support the open source community by making vap available.
//
// Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved.
//
// Licensed under the MIT License (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
//
// http://opensource.org/licenses/MIT
//
// Unless required by applicable law or agreed to in writing, software distributed under the License is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
// either express or implied. See the License for the specific language governing permissions and
// limitations under the License.
#import "QGMP4HWDFileInfo.h"
@implementation QGMP4HWDFileInfo
@end
@@ -0,0 +1,112 @@
// QGVAPConfigModel.h
// Tencent is pleased to support the open source community by making vap available.
//
// Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved.
//
// Licensed under the MIT License (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
//
// http://opensource.org/licenses/MIT
//
// Unless required by applicable law or agreed to in writing, software distributed under the License is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
// either express or implied. See the License for the specific language governing permissions and
// limitations under the License.
#import <Foundation/Foundation.h>
#import <UIKit/UIkit.h>
#import <Metal/Metal.h>
typedef NS_ENUM(NSInteger, QGVAPOrientation){
QGVAPOrientation_None = 0, // 兼容
QGVAPOrientation_Portrait = 1, // 竖屏
QGVAPOrientation_landscape = 2, // 横屏
};
typedef NSString * QGAGAttachmentSourceType NS_EXTENSIBLE_STRING_ENUM;//资源类型
typedef NSString * QGAGAttachmentSourceLoadType NS_EXTENSIBLE_STRING_ENUM;//资源加载类型
typedef NSString * QGAGAttachmentSourceStyle NS_EXTENSIBLE_STRING_ENUM;//字体
typedef NSString * QGAGAttachmentFitType NS_EXTENSIBLE_STRING_ENUM;//资源适配类型
//资源适配类型
UIKIT_EXTERN QGAGAttachmentFitType const kQGAGAttachmentFitTypeFitXY; //按指定尺寸缩放
UIKIT_EXTERN QGAGAttachmentFitType const kQGAGAttachmentFitTypeCenterFull; //默认按资源尺寸展示,如果资源尺寸小于遮罩,则等比缩放至可填满
//资源类型
UIKIT_EXTERN QGAGAttachmentSourceType const kQGAGAttachmentSourceTypeTextStr; //文字
UIKIT_EXTERN QGAGAttachmentSourceType const kQGAGAttachmentSourceTypeImgUrl; //图片
UIKIT_EXTERN QGAGAttachmentSourceType const kQGAGAttachmentSourceTypeText;
UIKIT_EXTERN QGAGAttachmentSourceType const kQGAGAttachmentSourceTypeImg;
UIKIT_EXTERN QGAGAttachmentSourceLoadType const QGAGAttachmentSourceLoadTypeLocal;
UIKIT_EXTERN QGAGAttachmentSourceLoadType const QGAGAttachmentSourceLoadTypeNet;
//字体
UIKIT_EXTERN QGAGAttachmentSourceStyle const kQGAGAttachmentSourceStyleBoldText; //粗体
//https://docs.qq.com/sheet/DTGl0bXdidFVkS3pn?tab=7od8yj&c=C25A0I0
@class QGVAPCommonInfo,QGVAPSourceInfo,QGVAPMergedInfo;
@interface QGVAPConfigModel : NSObject
@property (nonatomic, strong) QGVAPCommonInfo *info;
@property (nonatomic, strong) NSArray<QGVAPSourceInfo *> *resources;
@property (nonatomic, strong) NSDictionary<NSNumber *, NSArray<QGVAPMergedInfo*> *> *mergedConfig; ///@{帧,@[多个融合信息]}
@end
#pragma mark - 整体信息
@interface QGVAPCommonInfo : NSObject
@property (nonatomic, assign) NSInteger version;
@property (nonatomic, assign) NSInteger framesCount;
@property (nonatomic, assign) CGSize size;
@property (nonatomic, assign) CGSize videoSize;
@property (nonatomic, assign) QGVAPOrientation targetOrientaion;
@property (nonatomic, assign) NSInteger fps;
@property (nonatomic, assign) BOOL isMerged;
@property (nonatomic, assign) CGRect alphaAreaRect;
@property (nonatomic, assign) CGRect rgbAreaRect;
@end
#pragma mark - 渲染资源信息
@interface QGVAPSourceInfo : NSObject
//原始信息
@property (nonatomic, strong) QGAGAttachmentSourceType type;
@property (nonatomic, strong) QGAGAttachmentSourceLoadType loadType;
@property (nonatomic, strong) NSString *contentTag;
@property (nonatomic, strong) NSString *contentTagValue;
@property (nonatomic, strong) UIColor *color;
@property (nonatomic, strong) QGAGAttachmentSourceStyle style;
@property (nonatomic, assign) CGSize size;
@property (nonatomic, strong) QGAGAttachmentFitType fitType;
//加载内容
@property (nonatomic, strong) UIImage *sourceImage;
@property (nonatomic, strong) id<MTLTexture> texture;
@property (nonatomic, strong) id<MTLBuffer> colorParamsBuffer;
@end
@interface QGVAPSourceDisplayItem : NSObject
@property (nonatomic, assign) CGRect frame;
@property (nonatomic, strong) QGVAPSourceInfo *sourceInfo;
@end
#pragma mark - 融合信息
@interface QGVAPMergedInfo : NSObject
@property (nonatomic, strong) QGVAPSourceInfo *source;
@property (nonatomic, assign) NSInteger renderIndex;
@property (nonatomic, assign) CGRect renderRect;
@property (nonatomic, assign) BOOL needMask;
@property (nonatomic, assign) CGRect maskRect;
@property (nonatomic, assign) NSInteger maskRotation;
//加载内容
- (id<MTLBuffer>)vertexBufferWithContainerSize:(CGSize)size maskContianerSize:(CGSize)mSize device:(id<MTLDevice>)device;
@end
@@ -0,0 +1,108 @@
// QGVAPConfigModel.m
// Tencent is pleased to support the open source community by making vap available.
//
// Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved.
//
// Licensed under the MIT License (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
//
// http://opensource.org/licenses/MIT
//
// Unless required by applicable law or agreed to in writing, software distributed under the License is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
// either express or implied. See the License for the specific language governing permissions and
// limitations under the License.
#import "QGVAPConfigModel.h"
#import "NSDictionary+VAPUtil.h"
#import "QGVAPMetalUtil.h"
#import "QGVAPLogger.h"
#import "UIDevice+VAPUtil.h"
//资源适配类型
QGAGAttachmentFitType const kQGAGAttachmentFitTypeFitXY = @"fitXY"; //按指定尺寸缩放
QGAGAttachmentFitType const kQGAGAttachmentFitTypeCenterFull = @"centerFull"; //默认按资源尺寸展示,如果资源尺寸小于遮罩,则等比缩放至可填满
//资源类型
QGAGAttachmentSourceType const kQGAGAttachmentSourceTypeTextStr = @"textStr"; //文字
QGAGAttachmentSourceType const kQGAGAttachmentSourceTypeImgUrl = @"imgUrl"; //图片
QGAGAttachmentSourceType const kQGAGAttachmentSourceTypeText = @"txt"; //文字
QGAGAttachmentSourceType const kQGAGAttachmentSourceTypeImg = @"img"; //图片
QGAGAttachmentSourceLoadType const QGAGAttachmentSourceLoadTypeLocal = @"local";
QGAGAttachmentSourceLoadType const QGAGAttachmentSourceLoadTypeNet = @"net";
//字体
QGAGAttachmentSourceStyle const kQGAGAttachmentSourceStyleBoldText = @"b"; //粗体
@implementation QGVAPConfigModel
- (NSString *)description {
return [NSString stringWithFormat:@"<%@: %p> {info:%@, configs:%@}", self.class, self, _info, _mergedConfig];
}
@end
@implementation QGVAPCommonInfo
- (NSString *)description {
return [NSString stringWithFormat:@"<%@: %p> {version:%@, frames:%@, size:(%@,%@), videoSize:(%@,%@) orien:%@, fps:%@, merged:%@, alpha:(%@,%@,%@,%@), rgb:(%@,%@,%@,%@)}", self.class, self, @(_version), @(_framesCount), @(_size.width), @(_size.height), @(_videoSize.width), @(_videoSize.height), @(_targetOrientaion), @(_fps), @(_isMerged), @(_alphaAreaRect.origin.x), @(_alphaAreaRect.origin.y), @(_alphaAreaRect.size.width), @(_alphaAreaRect.size.height), @(_rgbAreaRect.origin.x), @(_rgbAreaRect.origin.y), @(_rgbAreaRect.size.width), @(_rgbAreaRect.size.height)];
}
@end
@implementation QGVAPSourceInfo
- (NSString *)description {
return [NSString stringWithFormat:@"<%@: %p> {type:%@, tag:%@-%@ color:%@, style:%@, size:(%@,%@), fitType:%@}", self.class, self, _type, _contentTag, _contentTagValue, _color, _style, @(_size.width), @(_size.height), _fitType];
}
@end
@implementation QGVAPSourceDisplayItem
@end
@implementation QGVAPMergedInfo
- (id<MTLBuffer>)vertexBufferWithContainerSize:(CGSize)size maskContianerSize:(CGSize)mSize device:(id<MTLDevice>)device {
if (size.width <= 0 || size.height <= 0 || mSize.width <= 0 || mSize.height <= 0) {
VAP_Error(kQGVAPModuleCommon, @"vertexBufferWithContainerSize size error! :%@ - %@", [NSValue valueWithCGSize:size], [NSValue valueWithCGSize:mSize]);
NSAssert(0, @"vertexBufferWithContainerSize size error!");
return nil;
}
const int colunmCountForVertices = 4, colunmCountForCoordinate = 2, vertexDataLength = 32;
float vertices[16], maskCoordinates[8], sourceCoordinates[8];
genMTLVertices(self.renderRect, size, vertices, NO);
genMTLTextureCoordinates(self.maskRect, mSize, maskCoordinates,YES, self.maskRotation);
if ([self.source.fitType isEqualToString:kQGAGAttachmentFitTypeCenterFull]) {
CGRect sourceRect = vapRectForCenterFull(self.source.size, self.renderRect.size);
CGSize sourceSize = vapSourceSizeForCenterFull(self.source.size, self.renderRect.size);
genMTLTextureCoordinates(sourceRect, sourceSize, sourceCoordinates,NO, 0);
} else {
replaceArrayElements(sourceCoordinates, (void*)kVAPMTLTextureCoordinatesIdentity, 8);
}
static float vertexData[vertexDataLength];
int indexForVertexData = 0;
//顶点数据+纹理坐标+遮罩纹理坐标
for (int i = 0; i < 16; i ++) {
vertexData[indexForVertexData++] = ((float*)vertices)[i];
if (i%colunmCountForVertices == colunmCountForVertices-1) {
int row = i/colunmCountForVertices;
vertexData[indexForVertexData++] = ((float*)sourceCoordinates)[row*colunmCountForCoordinate];
vertexData[indexForVertexData++] = ((float*)sourceCoordinates)[row*colunmCountForCoordinate+1];
vertexData[indexForVertexData++] = ((float*)maskCoordinates)[row*colunmCountForCoordinate];
vertexData[indexForVertexData++] = ((float*)maskCoordinates)[row*colunmCountForCoordinate+1];
}
}
NSUInteger allocationSize = vertexDataLength * sizeof(float);
id<MTLBuffer> vertexBuffer = [device newBufferWithBytes:vertexData length:allocationSize options:kDefaultMTLResourceOption];
return vertexBuffer;
}
- (NSString *)description {
return [NSString stringWithFormat:@"<%@: %p> {index:%@, rect:(%@,%@,%@,%@), mask:%@, maskRect:(%@,%@,%@,%@), maskRotation:%@, source:%@}", self.class, self, @(_renderIndex), @(_renderRect.origin.x), @(_renderRect.origin.y), @(_renderRect.size.width), @(_renderRect.size.height), @(_needMask), @(_maskRect.origin.x), @(_maskRect.origin.y), @(_maskRect.size.width), @(_maskRect.size.height), @(_maskRotation), _source];
}
@end
@@ -0,0 +1,40 @@
// QGVAPMaskInfo.h
// Tencent is pleased to support the open source community by making vap available.
//
// Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved.
//
// Licensed under the MIT License (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
//
// http://opensource.org/licenses/MIT
//
// Unless required by applicable law or agreed to in writing, software distributed under the License is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
// either express or implied. See the License for the specific language governing permissions and
// limitations under the License.
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import <Metal/Metal.h>
typedef NSUInteger QGVAPMaskValues;
NS_ASSUME_NONNULL_BEGIN
// 如果要更新data、rect、size必须重新创建QGVAPMaskInfo对象
@interface QGVAPMaskInfo : NSObject
/** mask数据 0/1 Byte */
@property (nonatomic, strong) NSData *data;
/** 采样范围 与datasize单位一致 */
@property (nonatomic, assign) CGRect sampleRect;
/** mask 大小 单位pixel */
@property (nonatomic, assign) CGSize dataSize;
/** 模糊范围,单位pixel */
@property (nonatomic, assign) NSInteger blurLength;
/** mask纹理 */
@property (nonatomic, strong, readonly) id<MTLTexture> texture;
@end
NS_ASSUME_NONNULL_END
@@ -0,0 +1,31 @@
// QGVAPMaskInfo.m
// Tencent is pleased to support the open source community by making vap available.
//
// Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved.
//
// Licensed under the MIT License (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
//
// http://opensource.org/licenses/MIT
//
// Unless required by applicable law or agreed to in writing, software distributed under the License is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
// either express or implied. See the License for the specific language governing permissions and
// limitations under the License.
#import "QGVAPMaskInfo.h"
#import "QGVAPTextureLoader.h"
#import "QGHWDMetalRenderer.h"
@implementation QGVAPMaskInfo
@synthesize texture = _texture;
- (id<MTLTexture>)texture {
if (!_texture) {
_texture = [QGVAPTextureLoader loadTextureWithData:self.data device:kQGHWDMetalRendererDevice width:self.dataSize.width height:self.dataSize.height];
}
return _texture;
}
@end
@@ -0,0 +1,31 @@
// QGVAPTextureLoader.h
// Tencent is pleased to support the open source community by making vap available.
//
// Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved.
//
// Licensed under the MIT License (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
//
// http://opensource.org/licenses/MIT
//
// Unless required by applicable law or agreed to in writing, software distributed under the License is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
// either express or implied. See the License for the specific language governing permissions and
// limitations under the License.
#import <UIKit/UIKit.h>
#import <Metal/Metal.h>
@interface QGVAPTextureLoader : NSObject
+ (id<MTLBuffer>)loadVapColorFillBufferWith:(UIColor *)color device:(id<MTLDevice>)device;
+ (id<MTLTexture>)loadTextureWithImage:(UIImage *)image device:(id<MTLDevice>)device;
+ (id<MTLTexture>)loadTextureWithData:(NSData *)data device:(id<MTLDevice>)device width:(CGFloat)width height:(CGFloat)height;
+ (UIImage *)drawingImageForText:(NSString *)textStr color:(UIColor *)color size:(CGSize)size bold:(BOOL)bold;
+ (UIFont *)getAppropriateFontWith:(NSString *)text rect:(CGRect)fitFrame designedSize:(CGFloat)designedFontSize bold:(BOOL)isBold textSize:(CGSize *)textSize;
@end
@@ -0,0 +1,183 @@
// QGVAPTextureLoader.m
// Tencent is pleased to support the open source community by making vap available.
//
// Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved.
//
// Licensed under the MIT License (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
//
// http://opensource.org/licenses/MIT
//
// Unless required by applicable law or agreed to in writing, software distributed under the License is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
// either express or implied. See the License for the specific language governing permissions and
// limitations under the License.
#import "QGVAPTextureLoader.h"
#import <MetalKit/MetalKit.h>
#import "QGHWDShaderTypes.h"
#import "QGVAPLogger.h"
#import "UIDevice+VAPUtil.h"
@implementation QGVAPTextureLoader
#if TARGET_OS_SIMULATOR//模拟器
+ (id<MTLBuffer>)loadVapColorFillBufferWith:(UIColor *)color device:(id<MTLDevice>)device {return nil;}
+ (id<MTLTexture>)loadTextureWithImage:(UIImage *)image device:(id<MTLDevice>)device {return nil;}
+ (UIImage *)drawingImageForText:(NSString *)textStr color:(UIColor *)color size:(CGSize)size bold:(BOOL)bold {return nil;}
+ (UIFont *)getAppropriateFontWith:(NSString *)text rect:(CGRect)fitFrame designedSize:(CGFloat)designedFontSize bold:(BOOL)isBold textSize:(CGSize *)textSize {return nil;}
#else
+ (id<MTLBuffer>)loadVapColorFillBufferWith:(UIColor *)color device:(id<MTLDevice>)device {
CGFloat red = 0.0, green = 0.0, blue = 0.0, alpha = 0.0;
if (color) {
[color getRed:&red green:&green blue:&blue alpha:&alpha];
}
struct VapAttachmentFragmentParameter colorParams[] = {{color != nil ? 0 : 1, {red, green, blue, alpha}}};
NSUInteger colorParamsSize = sizeof(struct VapAttachmentFragmentParameter);
id<MTLBuffer> buffer = [device newBufferWithBytes:colorParams length:colorParamsSize options:kDefaultMTLResourceOption];
return buffer;
}
+ (id<MTLTexture>)loadTextureWithImage:(UIImage *)image device:(id<MTLDevice>)device {
if (!image) {
VAP_Error(kQGVAPModuleCommon, @"attemp to loadTexture with nil image");
return nil;
}
if (@available(iOS 10.0, *)) {
MTKTextureLoader *loader = [[MTKTextureLoader alloc] initWithDevice:device];
NSError *error = nil;
id<MTLTexture> texture = [loader newTextureWithCGImage:image.CGImage options:@{MTKTextureLoaderOptionOrigin : MTKTextureLoaderOriginFlippedVertically} error:&error];
if (!texture || error) {
VAP_Error(kQGVAPModuleCommon, @"loadTexture error:%@", error);
return nil;
}
return texture;
}
return [self cg_loadTextureWithImage:image device:device];
}
+ (UIImage *)drawingImageForText:(NSString *)textStr color:(UIColor *)color size:(CGSize)size bold:(BOOL)bold {
if (textStr.length == 0) {
VAP_Error(kQGVAPModuleCommon, @"draw text resource fail cuz text is nil !!");
return nil;
}
if (!color) {
color = [UIColor blackColor];
}
CGRect rect = CGRectMake(0, 0, size.width/2.0, size.height/2.0);
CGSize textSize = CGSizeZero;
UIFont *font = [QGVAPTextureLoader getAppropriateFontWith:textStr rect:rect designedSize:rect.size.height*0.8 bold:bold textSize:&textSize];
if (!font) {
VAP_Error(kQGVAPModuleCommon, @"draw text resource:%@ fail cuz font is nil !!", textStr);
return nil;
}
NSMutableParagraphStyle *paragraphStyle = [NSMutableParagraphStyle new];
paragraphStyle.alignment = NSTextAlignmentCenter;
paragraphStyle.lineBreakMode = NSLineBreakByTruncatingTail;
NSDictionary *attr = @{NSFontAttributeName:font, NSParagraphStyleAttributeName:paragraphStyle, NSForegroundColorAttributeName:color};
UIGraphicsBeginImageContextWithOptions(rect.size, NO, [UIScreen mainScreen].scale);
rect.origin.y = (rect.size.height - font.lineHeight)/2.0;
[textStr drawWithRect:rect options:NSStringDrawingUsesLineFragmentOrigin attributes:attr context:nil];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
if (!image) {
VAP_Error(kQGVAPModuleCommon, @"draw text resource:%@ fail cuz UIGraphics fail.", textStr);
return nil;
}
return image;
}
+ (id<MTLTexture>)cg_loadTextureWithImage:(UIImage *)image device:(id<MTLDevice>)device {
CGImageRef imageRef = image.CGImage;
if (!device || imageRef == nil) {
VAP_Error(kQGVAPModuleCommon, @"load texture fail,cuz device/image is nil-device:%@ imaghe%@", device, imageRef);
return nil;
}
CGFloat width = CGImageGetWidth(imageRef), height = CGImageGetHeight(imageRef);
NSInteger bytesPerPixel = 4, bytesPerRow = bytesPerPixel * width, bitsPerComponent = 8;
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
void *rawData = calloc(height * width * bytesPerPixel, sizeof(uint8_t));
if (rawData == nil) {
VAP_Error(kQGVAPModuleCommon, @"load texture fail,cuz alloc mem fail!width:%@ height:%@ bytesPerPixel:%@", @(width), @(height), @(bytesPerPixel));
CGColorSpaceRelease(colorSpace);
colorSpace = NULL;
return nil;
}
CGContextRef context = CGBitmapContextCreate(rawData, width, height, bitsPerComponent, bytesPerRow, colorSpace, kCGImageAlphaPremultipliedLast|kCGImageByteOrder32Big);
CGColorSpaceRelease(colorSpace);
colorSpace = NULL;
if (context == nil) {
VAP_Error(kQGVAPModuleCommon, @"CGBitmapContextCreate error width:%@ height:%@ bitsPerComponent:%@ bytesPerRow:%@", @(width), @(height), @(bitsPerComponent), @(bytesPerRow));
free(rawData);
return nil;
}
CGContextTranslateCTM(context, 0, height);
CGContextScaleCTM(context, 1, -1);
CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef);
MTLTextureDescriptor *textureDescriptor = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatRGBA8Unorm width:width height:height mipmapped:NO];
id<MTLTexture> texture = [device newTextureWithDescriptor:textureDescriptor];
if (!texture) {
VAP_Error(kQGVAPModuleCommon, @"load texture fail,cuz fail getting texture");
free(rawData);
CGContextRelease(context);
return nil;
}
MTLRegion region = MTLRegionMake3D(0, 0, 0, width, height, 1);
[texture replaceRegion:region mipmapLevel:0 withBytes:rawData bytesPerRow:bytesPerRow];
free(rawData);
CGContextRelease(context);
return texture;
}
+ (id<MTLTexture>)loadTextureWithData:(NSData *)data device:(id<MTLDevice>)device width:(CGFloat)width height:(CGFloat)height {
if (!data) {
VAP_Error(kQGVAPModuleCommon, @"attemp to loadTexture with nil data");
return nil;
}
MTLTextureDescriptor *textureDescriptor = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatR8Unorm width:width height:height mipmapped:NO];
id<MTLTexture> texture = [device newTextureWithDescriptor:textureDescriptor];
if (!texture) {
VAP_Error(kQGVAPModuleCommon, @"load texture fail,cuz fail getting texture");
return nil;
}
MTLRegion region = MTLRegionMake3D(0, 0, 0, width, height, 1);
const void *bytes = [data bytes];
[texture replaceRegion:region mipmapLevel:0 withBytes:bytes bytesPerRow:width];
return texture;
}
//根据指定的字符内容和容器大小计算合适的字体
+ (UIFont *)getAppropriateFontWith:(NSString *)text rect:(CGRect)fitFrame designedSize:(CGFloat)designedFontSize bold:(BOOL)isBold textSize:(CGSize *)textSize {
UIFont *designedFont = isBold? [UIFont boldSystemFontOfSize:designedFontSize] : [UIFont systemFontOfSize:designedFontSize];
if (text.length == 0 || CGRectEqualToRect(CGRectZero, fitFrame) || !designedFont) {
*textSize = fitFrame.size;
return designedFont ;
}
CGSize stringSize = [text sizeWithAttributes:@{NSFontAttributeName:designedFont}];
CGFloat fontSize = designedFontSize;
NSInteger remainExcuteCount = 100;
while (stringSize.width > fitFrame.size.width && fontSize > 2.0 && remainExcuteCount > 0) {
fontSize *= 0.9;
remainExcuteCount -= 1;
designedFont = isBold? [UIFont boldSystemFontOfSize:fontSize] : [UIFont systemFontOfSize:fontSize];
stringSize = [text sizeWithAttributes:@{NSFontAttributeName:designedFont}];
}
if (remainExcuteCount < 1 || fontSize < 5.0) {
VAP_Event(kQGVAPModuleCommon, @"data exception content:%@ rect:%@ designedSize:%@ isBold:%@", text, [NSValue valueWithCGRect:fitFrame], @(designedFontSize), @(isBold));
}
*textSize = stringSize;
return designedFont;
}
#endif
@end