123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396 |
- //
- // BLBookletManager.m
- // Booklet
- //
- // Created by 蒋志鹏 on 2018/5/3.
- // Copyright © 2018年 NO1. All rights reserved.
- //
- #import "KMBookletManager.h"
- #import "KMBookletParameterModel.h"
- #import "NSMutableArray+KMOddEvenPartFetch.h"
- NSString *const BLBlankPageCountKey = @"blankPageNum";//空白页面数量key
- NSString *const BLBookletInfoKey = @"bookletInfo";//小册子编号和页数信息key
- @interface KMBookletManager()
- @end
- @implementation KMBookletManager
- - (void)dealloc
- {
- }
- //单例方法
- static KMBookletManager *manager = nil;
- + (instancetype)sharedManager
- {
- static dispatch_once_t onceToken;
- dispatch_once(&onceToken, ^{
- manager = [[KMBookletManager alloc] init];
- });
- return manager;
- }
- //根据参数,生成PDF并回调
- - (void)generateNewPDFWithParameterModel:(KMBookletParameterModel *)parameterModel
- completionHandler:(Booklet_GenerateNewPDFBlock)handle
- {
- //获取数组,如果数组为空,回调错误,不处理
- NSArray *printArr = [self fetchDrawPageArraysWithModel:parameterModel];
- if (printArr.count == 0) {
- if (handle) {
- handle(NO,parameterModel.savePath);
- }
- return;
- }
- //添加,统一后缀名为pdf
- if (!parameterModel.savePath.pathExtension) {
- parameterModel.savePath = [parameterModel.savePath stringByAppendingString:@".pdf"];
- }else{
- NSString *lowString = [parameterModel.savePath.pathExtension lowercaseString];
- if (![lowString isEqualToString:@"pdf"]) {
- parameterModel.savePath = [parameterModel.savePath stringByAppendingString:@".pdf"];
- }else{
- NSMutableString *mNewName = [parameterModel.savePath mutableCopy];
- parameterModel.savePath = [mNewName stringByReplacingOccurrencesOfString:parameterModel.savePath.pathExtension withString:@"pdf"];
- }
- }
-
- //创建画布
- CGRect mediaBox;
- CGContextRef myPDFContext = NULL;
- mediaBox = CGRectMake(0, 0, parameterModel.pageSize.width, parameterModel.pageSize.height);
- CFStringRef ref = (__bridge CFStringRef)parameterModel.savePath;
- myPDFContext = MyPDFContextCreate (&mediaBox, ref);
- //如果画布为空,回调错误,返回
- if (!myPDFContext) {
- if (handle) {
- handle(NO,parameterModel.savePath);
- }
- return;
- }
- CFStringRef myKeys[1];
- CFTypeRef myValues[1];
- myKeys[0] = kCGPDFContextMediaBox;
- myValues[0] = (CFTypeRef) CFDataCreate(NULL,(const UInt8 *)&mediaBox, sizeof (CGRect));
- CFDictionaryRef pageDictionary = CFDictionaryCreate(NULL, (const void **) myKeys,
- (const void **) myValues, 1,
- &kCFTypeDictionaryKeyCallBacks,&kCFTypeDictionaryValueCallBacks);
- //遍历将要打印的数组,打印PDFpage
- for (NSInteger j = 0 ;j <printArr.count;j++ )
- {
- //开始画PDF
- NSArray *subArr = printArr[j];
- CGPDFContextBeginPage(myPDFContext, pageDictionary);
- [self drawPageWithContext:myPDFContext parameterModel:parameterModel printArray:subArr];
- CGContextEndPage(myPDFContext);
- }
- CFRelease(pageDictionary);// 8
- CFRelease(myValues[0]);
- CGPDFContextClose(myPDFContext);
- CGContextRelease(myPDFContext);
- if (handle) {
- handle(YES,parameterModel.savePath);
- }
-
- }
- //获取最终用来绘制的数组
- - (NSArray *)fetchDrawPageArraysWithModel:(KMBookletParameterModel *)parameterModel
- {
- //获取page数组(双面打印时)
- NSMutableArray *printArr = [self regroupBothSidesPrintArrayWithPrimaryArray:parameterModel.pageArray];
- //如果是正面或者背面,那么对数组做处理
- if (parameterModel.printStyle == kBLPrintStyle_FrontOnly) {
- [printArr subArrayWithType:KMSubArrayTypeOdd];
- }else if (parameterModel.printStyle == kBLPrintStyle_BackOnly){
- [printArr subArrayWithType:KMSubArrayTypeEven];
- }
-
- //是否需要交换位置,当为左边,或者为左高的时候,需要交换两个Page的左右位置
- BOOL reverse = NO;
- switch (parameterModel.layoutStyle) {
- case kBLLayoutStyle_left:
- reverse = YES;
- break;
-
- case kBLLayoutStyle_leftTall:
- reverse = YES;
- break;
- default:
- break;
- }
- if (reverse) {
- for (NSMutableArray *arr in printArr) {
- PDFPage *page = [arr.firstObject copy];
- [arr removeObjectAtIndex:0];
- [arr addObject:page];
- }
- }
-
- //需要颠倒顺序如:@[@"1",@"2",@"3"] --> @[@"3",@"2",@"1"];
- if (parameterModel.reversePages) {
- //只有数组个数大于1才有换序的必要
- if (printArr.count > 1) {
- NSMutableArray *reverseArray = [NSMutableArray new];
- for (NSInteger i = printArr.count; i > 0 ; i--) {
- [reverseArray addObject:printArr[i -1]];
- }
- [printArr removeAllObjects];
- [printArr addObjectsFromArray:reverseArray];
- }
- }
-
- //计算最终的数组,页数
- NSMutableArray *newArray = [NSMutableArray new];
- //数组的起点和终点
- NSInteger firstPageIndexPlusOne = 0;
- NSInteger lastPageIndexPlusOne = 0;
- //如果是双面打印,那么就要乘以2
- if (parameterModel.printStyle == kBLPrintStyle_BothSide) {
- firstPageIndexPlusOne = 2 * parameterModel.sheetFromIndex;
- lastPageIndexPlusOne = 2 * parameterModel.sheetEndindex;
- }else{
- firstPageIndexPlusOne = parameterModel.sheetFromIndex;
- lastPageIndexPlusOne = parameterModel.sheetEndindex;
- }
- //提取数组元素
- for (NSInteger i = firstPageIndexPlusOne; i < lastPageIndexPlusOne ; i ++) {
- [newArray addObject:printArr[i]];
- }
-
- [printArr removeAllObjects];
- [printArr addObjectsFromArray:newArray];
-
- return printArr;
- }
- - (void)drawPageWithContext:(CGContextRef) myPDFContext
- parameterModel:(KMBookletParameterModel *)parameterModel
- printArray:(NSArray *)subArr
- {
-
- for (NSInteger i = 0; i < subArr.count; i++) {
- {
- //定义X偏移,Y偏移,缩放比例
- CGFloat xTransform = 0;
- CGFloat yTransform = 0;
- CGFloat scale = 0;
-
- //将用来绘制的PDFPage对象
- PDFPage *page = subArr[i];
-
- //是否需要移除注释
- NSMutableArray *annotations = [NSMutableArray array];
- for (PDFAnnotation *annotation in page.annotations) {
- [annotations addObject:annotation];
- }
-
- if (parameterModel.commentForms == kBookletCommentForms_DocumentOnly) {
- for (PDFAnnotation *annotation in annotations) {
- [annotation.page removeAnnotation:annotation];
- }
- } else if (parameterModel.commentForms == kBookletCommentForms_DocumentAndStamps) {
- for (PDFAnnotation *annotation in annotations) {
- if (![annotation isKindOfClass:[PDFAnnotationStamp class]]) {
- [annotation.page removeAnnotation:annotation];
- }
- }
- }
-
- //page原尺寸
- CGSize originalPageSize = [page boundsForBox:kPDFDisplayBoxCropBox].size;
-
- //自动旋转
- if (parameterModel.autoRotatePage) {
- //旋转规则:如果当前的实际宽高(由宽高和旋转角度得到)的关系是宽大于高,那么要逆时针旋转90度;
- if (page.rotation == 0) {
- CGFloat actualWidth = originalPageSize.width;
- CGFloat actualHeight = originalPageSize.height;
- if (actualWidth > actualHeight) {
- page.rotation = page.rotation - 90;
- }
- }else if (page.rotation == 90){
- CGFloat actualWidth = originalPageSize.height;
- CGFloat actualHeight = originalPageSize.width;
- if (actualWidth > actualHeight) {
- page.rotation = page.rotation -90;
- }
- }else if (page.rotation == 180){
- CGFloat actualWidth = originalPageSize.width;
- CGFloat actualHeight = originalPageSize.height;
- if (actualWidth > actualHeight) {
- page.rotation = page.rotation - 90;
- }
- }else if (page.rotation == 270){
- CGFloat actualWidth = originalPageSize.height;
- CGFloat actualHeight = originalPageSize.width;
- if (actualWidth > actualHeight) {
- page.rotation = page.rotation - 90;
- }
- }
- }
-
- //如果page的旋转角度对180求余还真,那么要将宽高大小交换
- if (page.rotation%180) {
- originalPageSize = CGSizeMake(originalPageSize.height, originalPageSize.width);
- }
-
- //画布大小
- CGSize availableSize = CGSizeMake((parameterModel.pageSize.width - parameterModel.gap)/2, parameterModel.pageSize.height);
- //画布和原来的page宽之比
- CGFloat wRatio = availableSize.width/originalPageSize.width;
- //画布和原来的page高之比
- CGFloat hRatio = availableSize.height/originalPageSize.height;
- //取最小值
- CGFloat ratio = MIN(wRatio, hRatio);
- //如果scale大于1那么等于1(只允许缩小,不可以放大)
- scale = ratio > 1 ? 1 : ratio;
- //在画布上page的实际尺寸
- CGSize realSize = CGSizeMake(originalPageSize.width * scale, originalPageSize.height *scale);
- //画第一张和画第二张x偏移区分
- if (i == 0) {
- xTransform = (availableSize.width - realSize.width)/2;
- }else{
- xTransform = (availableSize.width - realSize.width)/2 + parameterModel.pageSize.width/2 + parameterModel.gap/2;
- }
- //Y偏移
- yTransform = (availableSize.height - realSize.height)/2;
- //画布状态入栈
- CGContextSaveGState(myPDFContext);
- //偏移
- CGContextTranslateCTM(myPDFContext, xTransform, yTransform);
- //缩放
- CGContextScaleCTM(myPDFContext, scale, scale);
- //系统区分,绘制
- if (@available(macOS 10.12, *)) {
- [page drawWithBox:kPDFDisplayBoxCropBox toContext:myPDFContext];
- [page transformContext:myPDFContext forBox:kPDFDisplayBoxCropBox];
- } else {
- [NSGraphicsContext saveGraphicsState];
- [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithGraphicsPort:myPDFContext flipped:YES]];
- [page drawWithBox:kPDFDisplayBoxCropBox];
-
- [NSGraphicsContext restoreGraphicsState];
- [page transformContextForBox:kPDFDisplayBoxCropBox];
- }
- //画布状态出栈
- CGContextRestoreGState(myPDFContext);
- }
- }
-
- }
- //创建一个图形上下文对象
- CGContextRef MyPDFContextCreate (const CGRect *inMediaBox,
- CFStringRef path)
- {
- CGContextRef myOutContext = NULL;
- CFURLRef url;
-
- url = CFURLCreateWithFileSystemPath (NULL, // 1
- path,
- kCFURLPOSIXPathStyle,
- false);
- if (url != NULL) {
- myOutContext = CGPDFContextCreateWithURL (url,// 2
- inMediaBox,
- NULL);
- CFRelease(url);// 3
- }
- return myOutContext;// 4
- }
- #pragma mark - caculate
- - (NSMutableArray *)regroupBothSidesPrintArrayWithPrimaryArray:(NSArray *)primaryArray
- {
-
- NSMutableArray * backArray = [NSMutableArray array];
- NSDictionary *infoDict = [self calculatePagesPerBookletWithBookletNumber:1 totalPage:primaryArray.count];
-
- //小册子对应的页数信息
- NSDictionary *detailInfoDict = infoDict[BLBookletInfoKey];
-
- //空白页数量
- NSInteger blankPageCount = [(NSNumber *)infoDict[BLBlankPageCountKey] integerValue];
-
- NSMutableArray *tempArray = [NSMutableArray arrayWithArray:primaryArray];
- for (NSInteger i = 0; i < blankPageCount; i ++) {
- PDFPage *page = [[PDFPage alloc] init];
- [tempArray addObject:page];
- }
-
- NSInteger sheetCount = [detailInfoDict.allValues.lastObject integerValue];
- for (NSInteger i = 0; i < sheetCount; i ++) {
-
- NSMutableArray *tArr1 = [NSMutableArray new];
- PDFPage *addingPage1 = tempArray[tempArray.count - 2 * i - 1];
- PDFPage *addingPage2 = tempArray[2 * i];
-
- [tArr1 addObject:addingPage2];
- [tArr1 addObject:addingPage1];
- [backArray addObject:tArr1];
-
- NSMutableArray *tArr2 = [NSMutableArray new];
- PDFPage *addingPage3 = tempArray[2 * i + 1];
- PDFPage *addingPage4 = tempArray[tempArray.count - 2 * i -2];
-
- [tArr2 addObject:addingPage4];
- [tArr2 addObject:addingPage3];
- [backArray addObject:tArr2];
-
-
- }
-
- return backArray;
- }
- - (NSDictionary *)calculatePagesPerBookletWithBookletNumber:(NSInteger)bookletNum
- totalPage:(NSInteger)totalPageNum
- {
- NSMutableDictionary *backDict = [NSMutableDictionary dictionary];
- NSMutableDictionary *bookletPageNumInfoDict = [NSMutableDictionary dictionary];
-
- //对4取余,得到最后一个sheet会有多少张page
- NSInteger surplusPages = totalPageNum % 4;
- //总页数(每一页四页)= 总页数/4+是否有余数的bool值
- NSInteger tTotalPageNum = totalPageNum/4 + (surplusPages > 0 ? 1:0);
-
- //平均每一个册子有的页数
- NSInteger averagePageNum = tTotalPageNum / bookletNum;
- //平均分完还剩余多少页
- NSInteger surplusPageNum = tTotalPageNum % bookletNum;
-
- //遍历,给小册子赋值(数量)
- for (NSInteger i = 0; i < bookletNum; i++) {
- [bookletPageNumInfoDict setObject:[NSNumber numberWithInteger:averagePageNum] forKey:[NSString stringWithFormat:@"%ld",i]];
- }
-
- //遍历,给靠前的小册子添加页数
- for (NSInteger j = 0; j < surplusPageNum; j++) {
- [bookletPageNumInfoDict setObject:[NSNumber numberWithInteger:averagePageNum + 1] forKey:[NSString stringWithFormat:@"%ld",j]];
- }
- //空白页数量(分完了之后,最后一个小册子的空白页数量)
- NSInteger blankPageNum = tTotalPageNum * 4 - totalPageNum;
-
- [backDict setObject:[NSNumber numberWithInteger:blankPageNum] forKey:BLBlankPageCountKey];
-
- [backDict setObject:bookletPageNumInfoDict forKey:BLBookletInfoKey];
- return backDict;
-
- }
- @end
|