Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
7643 views
1
#include "common.h"
2
#import "MuPrintPageRenderer.h"
3
4
const int MaxStripPixels = 1024*1024;
5
6
@implementation MuPrintPageRenderer
7
{
8
MuDocRef *docRef;
9
}
10
11
-(id) initWithDocRef:(MuDocRef *)aDocRef
12
{
13
self = [super init];
14
if (self)
15
{
16
docRef = [aDocRef retain];
17
}
18
return self;
19
}
20
21
-(void) dealloc
22
{
23
[docRef release];
24
[super dealloc];
25
}
26
27
-(NSInteger) numberOfPages
28
{
29
__block NSInteger npages = 0;
30
dispatch_sync(queue, ^{
31
fz_try(ctx)
32
{
33
npages = fz_count_pages(ctx, docRef->doc);
34
}
35
fz_catch(ctx);
36
});
37
return npages;
38
}
39
40
static fz_page *getPage(fz_document *doc, NSInteger pageIndex)
41
{
42
__block fz_page *page = NULL;
43
44
dispatch_sync(queue, ^{
45
fz_try(ctx)
46
{
47
page = fz_load_page(ctx, doc, (int)pageIndex);
48
}
49
fz_catch(ctx)
50
{
51
printf("Failed to load page\n");
52
}
53
});
54
55
return page;
56
}
57
58
static CGSize getPageSize(fz_document *doc, fz_page *page)
59
{
60
__block CGSize size = {0.0,0.0};
61
62
dispatch_sync(queue, ^{
63
fz_try(ctx)
64
{
65
fz_rect bounds;
66
fz_bound_page(ctx, page, &bounds);
67
size.width = bounds.x1 - bounds.x0;
68
size.height = bounds.y1 - bounds.y0;
69
}
70
fz_catch(ctx)
71
{
72
printf("Failed to find page bounds\n");
73
}
74
});
75
76
return size;
77
}
78
79
static fz_pixmap *createPixMap(CGSize size)
80
{
81
__block fz_pixmap *pix = NULL;
82
83
dispatch_sync(queue, ^{
84
fz_try(ctx)
85
{
86
pix = fz_new_pixmap(ctx, fz_device_rgb(ctx), size.width, size.height);
87
}
88
fz_catch(ctx)
89
{
90
printf("Failed to create pixmap\n");
91
}
92
});
93
94
return pix;
95
}
96
97
static void freePage(fz_document *doc, fz_page *page)
98
{
99
dispatch_sync(queue, ^{
100
fz_drop_page(ctx, page);
101
});
102
}
103
104
static void renderPage(fz_document *doc, fz_page *page, fz_pixmap *pix, fz_matrix *ctm)
105
{
106
dispatch_sync(queue, ^{
107
fz_device *dev = NULL;
108
fz_var(dev);
109
fz_try(ctx)
110
{
111
dev = fz_new_draw_device(ctx, pix);
112
fz_clear_pixmap_with_value(ctx, pix, 0xFF);
113
fz_run_page(ctx, page, dev, ctm, NULL);
114
}
115
fz_always(ctx)
116
{
117
fz_drop_device(ctx, dev);
118
}
119
fz_catch(ctx)
120
{
121
printf("Failed to render page\n");
122
}
123
});
124
}
125
126
-(void) drawPageAtIndex:(NSInteger)pageIndex inRect:(CGRect)printableRect
127
{
128
fz_page *page = NULL;
129
fz_pixmap *pix = NULL;
130
CGDataProviderRef dataref = NULL;
131
CGImageRef img = NULL;
132
CGContextRef cgctx = UIGraphicsGetCurrentContext();
133
float dpi = 300.0;
134
float ppi = 72.0;
135
136
if (!cgctx) return;
137
138
CGSize paperSize = self.paperRect.size;
139
page = getPage(docRef->doc, pageIndex);
140
if (page == NULL) return;
141
142
CGSize pageSize = getPageSize(docRef->doc, page);
143
if (pageSize.width == 0.0 || pageSize.height == 0.0)
144
goto exit;
145
146
CGSize scale = fitPageToScreen(pageSize, paperSize);
147
pageSize.width *= scale.width;
148
pageSize.height *= scale.height;
149
150
CGSize pageSizePix = {roundf(pageSize.width * dpi / ppi), roundf(pageSize.height * dpi /ppi)};
151
int max_strip_height = MaxStripPixels / (int)pageSizePix.width;
152
if (pageSizePix.height > max_strip_height)
153
pageSizePix.height = max_strip_height;
154
CGSize stripSize = {pageSize.width, pageSizePix.height * ppi / dpi};
155
156
float cursor = 0.0;
157
158
while (cursor < pageSize.height)
159
{
160
// Overlap strips by 1 point
161
if (cursor > 0.0)
162
cursor -= 1.0;
163
164
pix = createPixMap(pageSizePix);
165
if (!pix)
166
goto exit;
167
168
dataref = CreateWrappedPixmap(pix);
169
if (dataref == NULL)
170
goto exit;
171
172
img = CreateCGImageWithPixmap(pix, dataref);
173
if (img == NULL)
174
goto exit;
175
176
fz_matrix ctm;
177
fz_scale(&ctm, dpi / ppi, -dpi / ppi);
178
fz_pre_translate(&ctm, 0, -stripSize.height-cursor);
179
fz_pre_scale(&ctm, scale.width, scale.height);
180
181
renderPage(docRef->doc, page, pix, &ctm);
182
183
CGRect rect = {{0.0,cursor},stripSize};
184
CGContextDrawImage(cgctx, rect, img);
185
186
CGImageRelease(img);
187
img = NULL;
188
CGDataProviderRelease(dataref); // releases pix
189
dataref = NULL;
190
191
cursor += stripSize.height;
192
}
193
194
exit:
195
freePage(docRef->doc, page);
196
CGImageRelease(img);
197
CGDataProviderRelease(dataref); //releases pix
198
}
199
200
@end
201
202