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
28static pdf_render_ifc_t *pdf_render;
29
30static 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 */
35static 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
41static 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
94static 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
111static 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
125static status_t _mupdf_supports_subsampling(wprint_image_info_t *image_info) {
126    LOGI("MUPDF: _mupdf_supports_subsampling(): Enter");
127    return ERROR;
128}
129
130static int _mupdf_native_units(wprint_image_info_t *image_info) {
131    return image_info->pdf_render_resolution;
132}
133
134static 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
139const image_decode_ifc_t *wprint_mupdf_decode_ifc = &_mupdf_decode_ifc;