mirror of
https://github.com/DKJone/DKWechatHelper.git
synced 2025-05-27 22:40:51 +08:00
191 lines
8.8 KiB
Objective-C
191 lines
8.8 KiB
Objective-C
// QGVAPMetalUtil.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 "QGVAPMetalUtil.h"
|
||
#import <AVFoundation/AVFoundation.h>
|
||
#import "QGVAPLogger.h"
|
||
#import <UIKit/UIKit.h>
|
||
|
||
NSString *const kVAPAttachmentVertexFunctionName = @"vapAttachment_vertexShader";
|
||
NSString *const kVAPAttachmentFragmentFunctionName = @"vapAttachment_FragmentShader";
|
||
NSString *const kVAPVertexFunctionName = @"vap_vertexShader";
|
||
NSString *const kVAPYUVFragmentFunctionName = @"vap_yuvFragmentShader";
|
||
NSString *const kVAPMaskFragmentFunctionName = @"vap_maskFragmentShader";
|
||
NSString *const kVAPMaskBlurFragmentFunctionName = @"vap_maskBlurFragmentShader";
|
||
|
||
float const kVAPMTLVerticesIdentity[16] = {-1.0, -1.0, 0.0, 1.0, -1.0, 1.0, 0.0, 1.0, 1.0, -1.0, 0.0, 1.0, 1.0, 1.0, 0.0, 1.0};
|
||
float const kVAPMTLTextureCoordinatesIdentity[8] = {0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0};
|
||
float const kVAPMTLTextureCoordinatesFor90[8] = {0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0};
|
||
|
||
void replaceArrayElements(float arr0[], float arr1[], int size) {
|
||
|
||
if ((arr0 == NULL || arr1 == NULL) && size > 0) {
|
||
assert(0);
|
||
}
|
||
if (size < 0) {
|
||
assert(0);
|
||
}
|
||
for (int i = 0; i < size; i++) {
|
||
arr0[i] = arr1[i];
|
||
}
|
||
}
|
||
|
||
//倒N形
|
||
void genMTLVertices(CGRect rect, CGSize containerSize, float vertices[16], BOOL reverse) {
|
||
|
||
if (vertices == NULL) {
|
||
VAP_Error(kQGVAPModuleCommon, @"generateMTLVertices params illegal.");
|
||
assert(0);
|
||
return ;
|
||
}
|
||
if (containerSize.width <= 0 || containerSize.height <= 0) {
|
||
VAP_Error(kQGVAPModuleCommon, @"generateMTLVertices params containerSize illegal.");
|
||
assert(0);
|
||
return ;
|
||
}
|
||
float originX, originY, width, height;
|
||
originX = -1+2*rect.origin.x/containerSize.width;
|
||
originY = 1-2*rect.origin.y/containerSize.height;
|
||
width = 2*rect.size.width/containerSize.width;
|
||
height = 2*rect.size.height/containerSize.height;
|
||
|
||
if (reverse) {
|
||
float tempVertices[] = {originX, originY-height, 0.0, 1.0, originX, originY, 0.0, 1.0, originX+width, originY-height, 0.0, 1.0, originX+width, originY, 0.0, 1.0};
|
||
replaceArrayElements(vertices, tempVertices, 16);
|
||
return ;
|
||
}
|
||
float tempVertices[] = {originX, originY, 0.0, 1.0, originX, originY-height, 0.0, 1.0, originX+width, originY, 0.0, 1.0 , originX+width, originY-height, 0.0, 1.0};
|
||
replaceArrayElements(vertices, tempVertices, 16);
|
||
}
|
||
|
||
//N形
|
||
void genMTLTextureCoordinates(CGRect rect, CGSize containerSize, float coordinates[8], BOOL reverse, NSInteger degree) {
|
||
|
||
//degree预留字段,支持旋转纹理
|
||
if (coordinates == NULL) {
|
||
VAP_Error(kQGVAPModuleCommon, @"generateMTLTextureCoordinates params coordinates illegal.");
|
||
assert(0);
|
||
return ;
|
||
}
|
||
if (containerSize.width <= 0 || containerSize.height <= 0) {
|
||
VAP_Error(kQGVAPModuleCommon, @"generateMTLTextureCoordinates params containerSize illegal.");
|
||
assert(0);
|
||
return ;
|
||
}
|
||
float originX, originY, width, height;
|
||
originX = rect.origin.x/containerSize.width;
|
||
originY = rect.origin.y/containerSize.height;
|
||
width = rect.size.width/containerSize.width;
|
||
height = rect.size.height/containerSize.height;
|
||
|
||
if (reverse) {
|
||
float tempCoordintes[] = {originX, originY, originX, originY+height , originX+width, originY,originX+width, originY+height};
|
||
replaceArrayElements(coordinates, tempCoordintes, 8);
|
||
return ;
|
||
}
|
||
float tempCoordintes[] = {originX, originY+height, originX, originY, originX+width, originY+height, originX+width, originY};
|
||
replaceArrayElements(coordinates, tempCoordintes, 8);
|
||
}
|
||
|
||
CGSize vapSourceSizeForCenterFull(CGSize sourceSize, CGSize renderSize) {
|
||
|
||
//source大小完全包含render大小,直接返回中间部分
|
||
if (sourceSize.width >= renderSize.width && sourceSize.height >= renderSize.height) {
|
||
return sourceSize;
|
||
}
|
||
CGRect rectForAspectFill = vapRectWithContentModeInsideRect(CGRectMake(0, 0, renderSize.width, renderSize.height), sourceSize, UIViewContentModeScaleAspectFill);
|
||
return rectForAspectFill.size;
|
||
}
|
||
|
||
CGRect vapRectForCenterFull(CGSize sourceSize, CGSize renderSize) {
|
||
|
||
//source大小完全包含render大小,直接返回中间部分
|
||
if (sourceSize.width >= renderSize.width && sourceSize.height >= renderSize.height) {
|
||
return CGRectMake((sourceSize.width-renderSize.width)/2.0, (sourceSize.height-renderSize.height)/2.0, renderSize.width, renderSize.height);
|
||
}
|
||
|
||
CGRect rectForAspectFill = vapRectWithContentModeInsideRect(CGRectMake(0, 0, renderSize.width, renderSize.height), sourceSize, UIViewContentModeScaleAspectFill);
|
||
|
||
CGRect intersection = CGRectMake(-rectForAspectFill.origin.x, -rectForAspectFill.origin.y, renderSize.width, renderSize.height);
|
||
return intersection;
|
||
}
|
||
|
||
CGRect vapRectWithContentModeInsideRect(CGRect boundingRect, CGSize aspectRatio, UIViewContentMode contentMode) {
|
||
|
||
if (aspectRatio.width <= 0 || aspectRatio.height <= 0) {
|
||
return boundingRect;
|
||
}
|
||
CGRect desRect = CGRectZero;
|
||
switch (contentMode) {
|
||
case UIViewContentModeScaleToFill: {
|
||
desRect = boundingRect;
|
||
}
|
||
break;
|
||
case UIViewContentModeScaleAspectFit: {
|
||
desRect = AVMakeRectWithAspectRatioInsideRect(aspectRatio, boundingRect);
|
||
}
|
||
break;
|
||
case UIViewContentModeScaleAspectFill: {
|
||
CGFloat ratio = MAX(CGRectGetWidth(boundingRect)/aspectRatio.width, CGRectGetHeight(boundingRect)/aspectRatio.height);
|
||
CGSize contentSize = CGSizeMake(aspectRatio.width*ratio, aspectRatio.height*ratio);
|
||
desRect = CGRectMake(boundingRect.origin.x+(CGRectGetWidth(boundingRect)-contentSize.width)/2.0, boundingRect.origin.y+(CGRectGetHeight(boundingRect)-contentSize.height)/2.0, contentSize.width, contentSize.height);
|
||
}
|
||
break;
|
||
case UIViewContentModeCenter: {
|
||
desRect = CGRectMake(boundingRect.origin.x+(CGRectGetWidth(boundingRect)-aspectRatio.width)/2.0, boundingRect.origin.y+(CGRectGetHeight(boundingRect)-aspectRatio.height)/2.0, aspectRatio.width, aspectRatio.height);
|
||
}
|
||
break;
|
||
case UIViewContentModeTop: {
|
||
desRect = CGRectMake(boundingRect.origin.x+(CGRectGetWidth(boundingRect)-aspectRatio.width)/2.0, boundingRect.origin.y, aspectRatio.width, aspectRatio.height);
|
||
}
|
||
break;
|
||
case UIViewContentModeBottom: {
|
||
desRect = CGRectMake(boundingRect.origin.x+(CGRectGetWidth(boundingRect)-aspectRatio.width)/2.0, boundingRect.origin.y+CGRectGetHeight(boundingRect)-aspectRatio.height, aspectRatio.width, aspectRatio.height);
|
||
}
|
||
break;
|
||
case UIViewContentModeLeft: {
|
||
desRect = CGRectMake(boundingRect.origin.x, boundingRect.origin.y+(CGRectGetHeight(boundingRect)-aspectRatio.height)/2.0, aspectRatio.width, aspectRatio.height);
|
||
}
|
||
break;
|
||
case UIViewContentModeRight: {
|
||
desRect = CGRectMake(boundingRect.origin.x+CGRectGetWidth(boundingRect)-aspectRatio.width, boundingRect.origin.y+(CGRectGetHeight(boundingRect)-aspectRatio.height)/2.0, aspectRatio.width, aspectRatio.height);
|
||
}
|
||
break;
|
||
case UIViewContentModeTopLeft: {
|
||
desRect = CGRectMake(boundingRect.origin.x, boundingRect.origin.y, aspectRatio.width, aspectRatio.height);
|
||
}
|
||
break;
|
||
case UIViewContentModeTopRight: {
|
||
desRect = CGRectMake(boundingRect.origin.x+CGRectGetWidth(boundingRect)-aspectRatio.width, boundingRect.origin.y, aspectRatio.width, aspectRatio.height);
|
||
}
|
||
break;
|
||
case UIViewContentModeBottomLeft: {
|
||
desRect = CGRectMake(boundingRect.origin.x, boundingRect.origin.y+CGRectGetHeight(boundingRect)-aspectRatio.height, aspectRatio.width, aspectRatio.height);
|
||
}
|
||
break;
|
||
case UIViewContentModeBottomRight: {
|
||
desRect = CGRectMake(boundingRect.origin.x+CGRectGetWidth(boundingRect)-aspectRatio.width, boundingRect.origin.y+CGRectGetHeight(boundingRect)-aspectRatio.height, aspectRatio.width, aspectRatio.height);
|
||
}
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
return desRect;
|
||
}
|
||
|
||
@implementation QGVAPMetalUtil
|
||
|
||
@end
|