Home | History | Annotate | Download | only in plugins
      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 <sys/types.h>
     20 #include <stdio.h>
     21 #include <stdlib.h>
     22 #include <math.h>
     23 
     24 #include "lib_pcl.h"
     25 #include "wprint_image.h"
     26 
     27 #include "pclm_wrapper_api.h"
     28 
     29 #include "media.h"
     30 #include "wprint_debug.h"
     31 
     32 #define TAG "lib_pclm"
     33 
     34 /*
     35  * Store a valid media_size name into media_name
     36  */
     37 static void _get_pclm_media_size_name(pcl_job_info_t *job_info, media_size_t media_size,
     38         char *media_name) {
     39     int i = 0;
     40     for (i = 0; i < SUPPORTED_MEDIA_SIZE_COUNT; i++) {
     41         if (media_size == SupportedMediaSizes[i].media_size) {
     42             strncpy(media_name, SupportedMediaSizes[i].PCL6Name,
     43                     strlen(SupportedMediaSizes[i].PCL6Name));
     44             LOGD("_get_pclm_media_size_name(): match found: %d, %s", media_size, media_name);
     45             break;  // we found a match, so break out of loop
     46         }
     47     }
     48 
     49     if (i == SUPPORTED_MEDIA_SIZE_COUNT) {
     50         // media size not found, defaulting to letter
     51         LOGD("_get_pclm_media_size_name(): media size, %d, NOT FOUND, setting to letter",
     52                 media_size);
     53         _get_pclm_media_size_name(job_info, US_LETTER, media_name);
     54     }
     55 }
     56 
     57 /*
     58  * Write a valid media_size into myPageInfo
     59  */
     60 static void _get_pclm_media_size(pcl_job_info_t *job_info, media_size_t media_size,
     61         PCLmPageSetup *myPageInfo) {
     62     int i = SUPPORTED_MEDIA_SIZE_COUNT;
     63 
     64     if (myPageInfo != NULL) {
     65         for (i = 0; i < SUPPORTED_MEDIA_SIZE_COUNT; i++) {
     66             if (media_size == SupportedMediaSizes[i].media_size) {
     67                 strncpy(myPageInfo->mediaSizeName, SupportedMediaSizes[i].PCL6Name,
     68                         sizeof(myPageInfo->mediaSizeName) - 1);
     69 
     70                 myPageInfo->mediaWidth = floorf(
     71                         _MI_TO_POINTS(SupportedMediaSizes[i].WidthInInches));
     72                 myPageInfo->mediaHeight = floorf(
     73                         _MI_TO_POINTS(SupportedMediaSizes[i].HeightInInches));
     74 
     75                 LOGD("_get_pclm_media_size(): match found: %d, %s, width=%f, height=%f",
     76                         media_size, SupportedMediaSizes[i].PCL6Name, myPageInfo->mediaWidth,
     77                         myPageInfo->mediaHeight);
     78                 break;  // we found a match, so break out of loop
     79             }
     80         }
     81     }
     82 
     83     if (i == SUPPORTED_MEDIA_SIZE_COUNT) {
     84         // media size not found, defaulting to letter
     85         LOGD("_get_pclm_media_size(): media size, %d, NOT FOUND, setting to letter", media_size);
     86         _get_pclm_media_size(job_info, US_LETTER, myPageInfo);
     87     }
     88 }
     89 
     90 static wJob_t _start_job(wJob_t job_handle, pcl_job_info_t *job_info, media_size_t media_size,
     91         media_type_t media_type, int resolution, duplex_t duplex, duplex_dry_time_t dry_time,
     92         color_space_t color_space, media_tray_t media_tray, float top_margin,
     93         float left_margin) {
     94     int outBuffSize = 0;
     95 
     96     if (job_info == NULL) {
     97         return _WJOBH_NONE;
     98     }
     99 
    100     if (job_info->job_handle != _WJOBH_NONE) {
    101         if (job_info->wprint_ifc != NULL) {
    102             LOGD("_start_job() required cleanup");
    103         }
    104         job_info->job_handle = _WJOBH_NONE;
    105     }
    106 
    107     if ((job_info->wprint_ifc == NULL) || (job_info->print_ifc == NULL)) {
    108         return _WJOBH_NONE;
    109     }
    110 
    111     LOGD("_start_job(), media_size %d, media_type %d, dt %d, %s, media_tray %d margins T %f L %f",
    112             media_size, media_type, dry_time,
    113             (duplex == DUPLEX_MODE_NONE) ? "simplex" : "duplex",
    114             media_tray, top_margin, left_margin);
    115 
    116     job_info->job_handle = job_handle;
    117 
    118     _START_JOB(job_info, "pdf");
    119 
    120     job_info->resolution = resolution;
    121     job_info->media_size = media_size;
    122     job_info->standard_scale = (float) resolution / (float) STANDARD_SCALE_FOR_PDF;
    123 
    124     //  initialize static variables
    125     job_info->pclm_output_buffer = NULL;
    126     job_info->seed_row = job_info->pcl_buff = NULL;    // unused
    127     job_info->pixel_width = job_info->pixel_height = job_info->page_number = job_info->num_rows = 0;
    128 
    129     memset((void *) &job_info->pclm_page_info, 0x0, sizeof(PCLmPageSetup));
    130     _get_pclm_media_size_name(job_info, media_size, &job_info->pclm_page_info.mediaSizeName[0]);
    131 
    132     if ((left_margin < 0.0f) || (top_margin < 0.0f)) {
    133         job_info->pclm_page_info.mediaWidthOffset = 0.0f;
    134         job_info->pclm_page_info.mediaHeightOffset = 0.0f;
    135     } else {
    136         job_info->pclm_page_info.mediaWidthOffset = (left_margin * (float) STANDARD_SCALE_FOR_PDF);
    137         job_info->pclm_page_info.mediaHeightOffset = (top_margin * (float) STANDARD_SCALE_FOR_PDF);
    138     }
    139 
    140     LOGI("_start_job(), mediaHeightOffsets W %f H %f", job_info->pclm_page_info.mediaWidthOffset,
    141             job_info->pclm_page_info.mediaHeightOffset);
    142 
    143     job_info->pclm_page_info.pageOrigin = top_left;    // REVISIT
    144 
    145     job_info->monochrome = (color_space == COLOR_SPACE_MONO);
    146     job_info->pclm_page_info.dstColorSpaceSpefication = deviceRGB;
    147     if (color_space == COLOR_SPACE_MONO) {
    148         job_info->pclm_page_info.dstColorSpaceSpefication = grayScale;
    149     } else if (color_space == COLOR_SPACE_COLOR) {
    150         job_info->pclm_page_info.dstColorSpaceSpefication = deviceRGB;
    151     } else if (color_space == COLOR_SPACE_ADOBE_RGB) {
    152         job_info->pclm_page_info.dstColorSpaceSpefication = adobeRGB;
    153     }
    154 
    155     job_info->pclm_page_info.stripHeight = job_info->strip_height;
    156     job_info->pclm_page_info.destinationResolution = res600;
    157     if (resolution == 300) {
    158         job_info->pclm_page_info.destinationResolution = res300;
    159     } else if (resolution == 600) {
    160         job_info->pclm_page_info.destinationResolution = res600;
    161     } else if (resolution == 1200) {
    162         job_info->pclm_page_info.destinationResolution = res1200;
    163     }
    164 
    165     if (duplex == DUPLEX_MODE_BOOK) {
    166         job_info->pclm_page_info.duplexDisposition = duplex_longEdge;
    167     } else if (duplex == DUPLEX_MODE_TABLET) {
    168         job_info->pclm_page_info.duplexDisposition = duplex_shortEdge;
    169     } else {
    170         job_info->pclm_page_info.duplexDisposition = simplex;
    171     }
    172 
    173     job_info->pclm_page_info.mirrorBackside = false;
    174     job_info->pclmgen_obj = CreatePCLmGen();
    175     PCLmStartJob(job_info->pclmgen_obj, (void **) &job_info->pclm_output_buffer, &outBuffSize);
    176     _WRITE(job_info, (const char *) job_info->pclm_output_buffer, outBuffSize);
    177     return job_info->job_handle;
    178 }
    179 
    180 static int _start_page(pcl_job_info_t *job_info, int pixel_width, int pixel_height) {
    181     PCLmPageSetup *page_info = &job_info->pclm_page_info;
    182     ubyte *pclm_output_buff = job_info->pclm_output_buffer;
    183     int outBuffSize = 0;
    184 
    185     _START_PAGE(job_info, pixel_width, pixel_height);
    186 
    187     page_info->sourceHeight = (float) pixel_height / job_info->standard_scale;
    188     page_info->sourceWidth = (float) pixel_width / job_info->standard_scale;
    189     LOGI("_start_page(), strip height=%d, image width=%d, image height=%d, scaled width=%f, "
    190             "scaled height=%f", page_info->stripHeight, pixel_width, pixel_height,
    191             page_info->sourceWidth, page_info->sourceHeight);
    192 
    193     if (job_info->num_components == 3) {
    194         page_info->colorContent = color_content;
    195         page_info->srcColorSpaceSpefication = deviceRGB;
    196     } else {
    197         page_info->colorContent = gray_content;
    198         page_info->srcColorSpaceSpefication = grayScale;
    199     }
    200 
    201     /* Note: we could possibly get this value dynamically from device via IPP (ePCL) however,
    202      * current ink devices report RLE as the default compression type, which compresses much
    203      * worse than JPEG or FLATE
    204      */
    205     page_info->compTypeRequested = compressDCT;
    206     job_info->scan_line_width = pixel_width * job_info->num_components;
    207     int res1 = PCLmGetMediaDimensions(job_info->pclmgen_obj, page_info->mediaSizeName, page_info);
    208     page_info->SourceWidthPixels = MIN(pixel_width, job_info->pclm_page_info.mediaWidthInPixels);
    209     page_info->SourceHeightPixels = pixel_height;
    210     job_info->pclm_scan_line_width =
    211             job_info->pclm_page_info.mediaWidthInPixels * job_info->num_components;
    212 
    213     LOGD("PCLmGetMediaDimensions(%d), mediaSizeName=%s, mediaWidth=%f, mediaHeight=%f, "
    214             "widthPixels=%d, heightPixels=%d", res1, job_info->pclm_page_info.mediaSizeName,
    215             job_info->pclm_page_info.mediaWidth, job_info->pclm_page_info.mediaHeight,
    216             job_info->pclm_page_info.mediaWidthInPixels,
    217             job_info->pclm_page_info.mediaHeightInPixels);
    218 
    219     PCLmStartPage(job_info->pclmgen_obj, page_info, (void **) &pclm_output_buff, &outBuffSize);
    220     _WRITE(job_info, (const char *) pclm_output_buff, outBuffSize);
    221 
    222     job_info->page_number++;
    223     return job_info->page_number;
    224 }
    225 
    226 static int _print_swath(pcl_job_info_t *job_info, char *rgb_pixels, int start_row, int num_rows,
    227         int bytes_per_row) {
    228     int outBuffSize = 0;
    229     _PAGE_DATA(job_info, (const unsigned char *) rgb_pixels, (num_rows * bytes_per_row));
    230 
    231     if (job_info->monochrome) {
    232         unsigned char *buff = (unsigned char *) rgb_pixels;
    233         int nbytes = (num_rows * bytes_per_row);
    234         int readIndex, writeIndex;
    235         for (readIndex = writeIndex = 0; readIndex < nbytes; readIndex += BYTES_PER_PIXEL(1)) {
    236             unsigned char gray = SP_GRAY(buff[readIndex + 0], buff[readIndex + 1],
    237                     buff[readIndex + 2]);
    238             buff[writeIndex++] = gray;
    239             buff[writeIndex++] = gray;
    240             buff[writeIndex++] = gray;
    241         }
    242     }
    243 
    244     LOGD("_print_swath(): page #%d, buffSize=%d, rows %d - %d (%d rows), bytes per row %d",
    245             job_info->page_number, job_info->strip_height * job_info->scan_line_width, start_row,
    246             start_row + num_rows - 1, num_rows, bytes_per_row);
    247 
    248     if (job_info->scan_line_width > job_info->pclm_scan_line_width) {
    249         int i;
    250         char *src_pixels = rgb_pixels + job_info->scan_line_width;
    251         char *dest_pixels = rgb_pixels + job_info->pclm_scan_line_width;
    252         for (i = 1; i < num_rows; i++, src_pixels += job_info->scan_line_width,
    253                 dest_pixels += job_info->pclm_scan_line_width) {
    254             memmove(dest_pixels, src_pixels, job_info->pclm_scan_line_width);
    255         }
    256     }
    257 
    258     /* if the inBufferSize is ever used in genPCLm, change the input parameter to pass in
    259      * image_info->printable_width*num_components*strip_height
    260      * it is currently pixel_width (from _start_page()) * num_components * strip_height
    261      */
    262     PCLmEncapsulate(job_info->pclmgen_obj, rgb_pixels,
    263             job_info->strip_height * MIN(job_info->scan_line_width, job_info->pclm_scan_line_width),
    264             num_rows, (void **) &job_info->pclm_output_buffer, &outBuffSize);
    265     _WRITE(job_info, (const char *) job_info->pclm_output_buffer, outBuffSize);
    266 
    267     return OK;
    268 }
    269 
    270 static int _end_page(pcl_job_info_t *job_info, int page_number) {
    271     int outBuffSize = 0;
    272 
    273     if (page_number == -1) {
    274         LOGI("_end_page(): writing blank page");
    275         _start_page(job_info, 0, 0);
    276         unsigned char blank_data[1] = {0xFF};
    277         PCLmEncapsulate(job_info->pclmgen_obj, (void *) blank_data, 1, 1,
    278                 (void **) &job_info->pclm_output_buffer, &outBuffSize);
    279         _WRITE(job_info, (const char *) job_info->pclm_output_buffer, outBuffSize);
    280     }
    281     LOGI("_end_page()");
    282     PCLmEndPage(job_info->pclmgen_obj, (void **) &job_info->pclm_output_buffer, &outBuffSize);
    283     _WRITE(job_info, (const char *) job_info->pclm_output_buffer, outBuffSize);
    284     _END_PAGE(job_info);
    285 
    286     return OK;
    287 }
    288 
    289 static int _end_job(pcl_job_info_t *job_info) {
    290     int outBuffSize = 0;
    291 
    292     LOGI("_end_job()");
    293     PCLmEndJob(job_info->pclmgen_obj, (void **) &job_info->pclm_output_buffer, &outBuffSize);
    294     _WRITE(job_info, (const char *) job_info->pclm_output_buffer, outBuffSize);
    295     PCLmFreeBuffer(job_info->pclmgen_obj, job_info->pclm_output_buffer);
    296     DestroyPCLmGen(job_info->pclmgen_obj);
    297     _END_JOB(job_info);
    298     return OK;
    299 }
    300 
    301 static bool _canCancelMidPage(void) {
    302     return false;
    303 }
    304 
    305 static const ifc_pcl_t _pcl_ifc = {
    306     _start_job, _end_job, _start_page, _end_page, _print_swath, _canCancelMidPage
    307 };
    308 
    309 ifc_pcl_t *pclm_connect(void) {
    310     return ((ifc_pcl_t *) &_pcl_ifc);
    311 }