1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  * Copyright (C) 2016 Mopria Alliance, Inc.
4  * Copyright (C) 2013 Hewlett-Packard Development Company, L.P.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *      http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 
19 #include <time.h>
20 #include "wprint_mupdf.h"
21 #include "lib_wprint.h"
22 #include "ipphelper.h"
23 
24 #define TAG "wprint_mupdf"
25 #define MUPDF_DEFAULT_RESOLUTION 72
26 #define RGB_NUMBER_PIXELS_NUM_COMPONENTS 3
27 
28 static pdf_render_ifc_t *pdf_render;
29 
_mupdf_init(wprint_image_info_t * image_info)30 static void _mupdf_init(wprint_image_info_t *image_info) {
31     pdf_render = create_pdf_render_ifc();
32 }
33 
34 /* Return current clock time in milliseconds */
get_millis()35 static long get_millis() {
36     struct timespec now;
37     clock_gettime(CLOCK_MONOTONIC, &now);
38     return (long) (((int64_t) now.tv_sec * 1000000000LL + now.tv_nsec) / 1000000);
39 }
40 
_mupdf_get_hdr(wprint_image_info_t * image_info)41 static status_t _mupdf_get_hdr(wprint_image_info_t *image_info) {
42     double pageWidth, pageHeight;
43     float zoom;
44     unsigned int imageWidth;
45     unsigned int imageHeight;
46     int size;
47     char *rawBuffer;
48     status_t result;
49     int pages;
50 
51     pages = pdf_render->openDocument(pdf_render, image_info->decoder_data.urlPath);
52     if (pages < 1) return ERROR;
53 
54     result = pdf_render->getPageAttributes(pdf_render, image_info->decoder_data.page, &pageWidth,
55             &pageHeight);
56     if (result != OK) return result;
57 
58     const float POINTS_PER_INCH = MUPDF_DEFAULT_RESOLUTION;
59     zoom = (image_info->pdf_render_resolution) / POINTS_PER_INCH;
60 
61     imageWidth = (unsigned int) (pageWidth * zoom);
62     imageHeight = (unsigned int) (pageHeight * zoom);
63 
64     image_info->width = imageWidth;
65     image_info->height = imageHeight;
66 
67     size = imageWidth * imageHeight * 3;
68 
69     rawBuffer = (char *) malloc((size_t) size);
70     if (!rawBuffer) return ERROR;
71 
72     LOGI("Render page=%d w=%.0f h=%.0f res=%d zoom=%0.2f size=%d", image_info->decoder_data.page,
73             pageWidth, pageHeight, image_info->pdf_render_resolution, zoom, size);
74 
75     long now = get_millis();
76 
77     result = pdf_render->renderPageStripe(pdf_render, image_info->decoder_data.page, imageWidth,
78             imageHeight, zoom, rawBuffer);
79     if (result != OK) {
80         free(rawBuffer);
81         return result;
82     }
83 
84     LOGI("Render complete in %ld ms", get_millis() - now);
85 
86     image_info->decoder_data.pdf_info.fz_pixmap_ptr = rawBuffer;
87     image_info->decoder_data.pdf_info.bitmap_ptr = malloc(
88             image_info->width * RGB_NUMBER_PIXELS_NUM_COMPONENTS);
89     image_info->num_components = RGB_NUMBER_PIXELS_NUM_COMPONENTS;
90 
91     return OK;
92 }
93 
_mupdf_decode_row(wprint_image_info_t * image_info,int row)94 static unsigned char *_mupdf_decode_row(wprint_image_info_t *image_info, int row) {
95     unsigned char *rgbPixels = 0;
96 
97     if (image_info->swath_start == -1) {
98         wprint_image_compute_rows_to_cache(image_info);
99     }
100 
101     image_info->swath_start = row;
102     if (NULL != image_info->decoder_data.pdf_info.fz_pixmap_ptr) {
103         rgbPixels = (unsigned char *) image_info->decoder_data.pdf_info.bitmap_ptr;
104         memcpy(rgbPixels, (char *) (image_info->decoder_data.pdf_info.fz_pixmap_ptr) +
105                         row * image_info->width * RGB_NUMBER_PIXELS_NUM_COMPONENTS,
106                 image_info->width * RGB_NUMBER_PIXELS_NUM_COMPONENTS);
107     }
108     return rgbPixels;
109 }
110 
_mupdf_cleanup(wprint_image_info_t * image_info)111 static status_t _mupdf_cleanup(wprint_image_info_t *image_info) {
112     LOGD("MUPDF: _mupdf_cleanup(): Enter");
113     if (NULL != image_info->decoder_data.pdf_info.fz_pixmap_ptr) {
114         free(image_info->decoder_data.pdf_info.fz_pixmap_ptr);
115         image_info->decoder_data.pdf_info.fz_pixmap_ptr = NULL;
116     }
117     if (image_info->decoder_data.pdf_info.bitmap_ptr != NULL) {
118         free(image_info->decoder_data.pdf_info.bitmap_ptr);
119     }
120     pdf_render->destroy(pdf_render);
121     pdf_render = NULL;
122     return OK;
123 }
124 
_mupdf_supports_subsampling(wprint_image_info_t * image_info)125 static status_t _mupdf_supports_subsampling(wprint_image_info_t *image_info) {
126     LOGI("MUPDF: _mupdf_supports_subsampling(): Enter");
127     return ERROR;
128 }
129 
_mupdf_native_units(wprint_image_info_t * image_info)130 static int _mupdf_native_units(wprint_image_info_t *image_info) {
131     return image_info->pdf_render_resolution;
132 }
133 
134 static const image_decode_ifc_t _mupdf_decode_ifc = {&_mupdf_init, &_mupdf_get_hdr,
135         &_mupdf_decode_row, &_mupdf_cleanup,
136         &_mupdf_supports_subsampling,
137         &_mupdf_native_units,};
138 
139 const image_decode_ifc_t *wprint_mupdf_decode_ifc = &_mupdf_decode_ifc;