upload android base code part8

This commit is contained in:
August 2018-08-08 20:10:12 +08:00
parent 841ae54672
commit 5425409085
57075 changed files with 9846578 additions and 0 deletions

View file

@ -0,0 +1,271 @@
/*
* Copyright (C) 2016 The Android Open Source Project
* Copyright (C) 2016 Mopria Alliance, Inc.
* Copyright (C) 2013 Hewlett-Packard Development Company, L.P.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef _PCLM_GENERATOR
#define _PCLM_GENERATOR
#define SUPPORT_WHITE_STRIPS
#include "common_defines.h"
/*
* Generates a stream of PCLm output.
*
* Public APIs supply data output data into pOutBuffer with length in iOutBufferSize, to be
* delivered to the printer.
*/
class PCLmGenerator {
public:
PCLmGenerator();
~PCLmGenerator();
/*
* Started a PCLm job. Initializes buffers.
*/
int StartJob(void **pOutBuffer, int *iOutBufferSize);
/*
* Ends the PCLm job. Writes trailer, frees buffers and arrays
*/
int EndJob(void **pOutBuffer, int *iOutBufferSize);
/*
* Starts rendering a page of a PCLm job.
*/
int StartPage(PCLmPageSetup *PCLmPageContent, void **pOutBuffer, int *iOutBufferSize);
/*
* Ends rendering a page. Frees scratch buffer.
*/
int EndPage(void **pOutBuffer, int *iOutBufferSize);
/*
* Compresses output buffer in Flate, RLE, or JPEG compression
*/
int Encapsulate(void *pInBuffer, int inBufferSize, int numLines, void **pOutBuffer,
int *iOutBufferSize);
/*
* Returns index of matched media size, else returns index for letter
*/
int GetPclmMediaDimensions(const char *mediaRequested, PCLmPageSetup *myPageInfo);
/*
* Free the supplied output buffer (after EndJob)
*/
void FreeBuffer(void *pBuffer);
private:
/*
* Convert an image from one color space to another.
* Currently, only supports RGB->GRAY
*/
bool colorConvertSource(colorSpaceDisposition srcCS, colorSpaceDisposition dstCS, ubyte *strip,
sint32 stripWidth, sint32 stripHeight);
/*
* Generates the PDF page construct(s), which includes the image information. The /Length
* definition is required for PDF, so we write the stream to a RAM buffer first, then calculate
* the Buffer size, insert the PDF /Length construct, then write the buffer to the PDF file.
*/
void writePDFGrammarPage
(int imageWidth, int imageHeight, int numStrips, colorSpaceDisposition destColorSpace);
/*
* Writes the PDF and PCLm versions to the output buffer as the header
*/
void writePDFGrammarHeader();
/*
* Injects RLE compression strip into the output buffer
*/
int injectRLEStrip(ubyte *RLEBuffer, int numBytes, int imageWidth, int imageHeight,
colorSpaceDisposition destColorSpace, bool);
/*
* Injects zlib compressed strip to the output buffer
*/
int injectLZStrip(ubyte *LZBuffer, int numBytes, int imageWidth, int imageHeight,
colorSpaceDisposition destColorSpace, bool);
/*
* Injects jpeg compressed image to the output buffer
*/
int injectJPEG(char *jpeg_Buff, int imageWidth, int imageHeight, int numCompBytes,
colorSpaceDisposition destColorSpace, bool);
/*
* Initializes the output buffer with buff and size
*/
void initOutBuff(char *buff, sint32 size);
/*
* Writes str to the outputBuffer
*/
void writeStr2OutBuff(char *str);
/*
* Writes buff to the outputBuffer
*/
void write2Buff(ubyte *buff, int buffSize);
/*
* Adds totalBytesWrittenToPCLmFile to the xRefTable for output
*/
int statOutputFileSize();
/*
* Writes file information to the outputbuffer as the trailer.
*/
void writePDFGrammarTrailer(int imageWidth, int imageHeight);
/*
* Injects Adobe RGBCS into the output buffer
*/
bool injectAdobeRGBCS();
/*
* Adds kidObj to KidsArray
*/
bool addKids(sint32 kidObj);
/*
* Adds xRefObj to the xRefTable
*/
bool addXRef(sint32 xRefObj);
/*
* Warning: take extreme care in modifying this unless you understand what is going on. This
* function attempts to fix the xref table, based upon the strips getting inserted in reverse
* order (on the backside page). It does the following:
* 1) Calculates the new object reference size (using tmpArray)
* 2) Adds 2 to the object size to compensate for the offset
* 3) Reorders the Image FileBody and the ImageTransformation, as these are 1 PDF object
* 4) Frees the tmp array
*/
void fixXRef();
/*
* Calls cleanup and returns an error
*/
int errorOutAndCleanUp();
/*
* Cleans up allocatedOutputBuffer, leftoverScanlineBuffer, scratchBuffer, xRefTable, and
* KidsArray
*/
void Cleanup(void);
/*
* Writes job information to the output buffer
*/
void writeJobTicket(void);
/*
* Transforms image for duplexing, writes to output buffer
*/
void injectImageTransform();
#ifdef SUPPORT_WHITE_STRIPS
/*
* Checks if the given buffer is a white strip
*/
bool isWhiteStrip(void *, int);
#endif
/*
* Outputs the string associated with the given bin into returnStr
*/
bool getInputBinString(jobInputBin bin, char *);
/*
* Outputs the string associated with the given bin into returnStr
*/
bool getOutputBin(jobOutputBin bin, char *);
/*
* compress input by identifying repeating bytes (not sequences)
* Compression ratio good for grayscale images, not great on RGB
* Output:
* 1-127: literal run
* 128: end of compression block
* 129-256: repeating byte sequence
*/
int RLEEncodeImage(ubyte *in, ubyte *out, int inLength);
sint32 currStripHeight;
char currMediaName[256];
duplexDispositionEnum currDuplexDisposition;
compressionDisposition currCompressionDisposition;
mediaOrientationDisposition currMediaOrientationDisposition;
renderResolution currRenderResolution;
int currRenderResolutionInteger;
void *allocatedOutputBuffer;
void *leftoverScanlineBuffer;
int mediaWidth;
int mediaHeight;
int mediaWidthInPixels;
int mediaHeightInPixels;
colorSpaceDisposition destColorSpace;
colorSpaceDisposition sourceColorSpace;
int scaleFactor;
jobStateEnum jobOpen;
int currSourceWidth;
int currSourceHeight;
int srcNumComponents;
int dstNumComponents;
int numLeftoverScanlines;
ubyte *scratchBuffer;
int pageCount;
bool reverseOrder;
int outBuffSize;
int currOutBuffSize;
int totalBytesWrittenToPCLmFile;
int totalBytesWrittenToCurrBuff;
char *outBuffPtr;
char *currBuffPtr;
float STANDARD_SCALE;
sint32 objCounter;
sint32 yPosition;
sint32 pageOrigin;
sint32 *KidsArray;
sint32 numKids;
// XRefTable storage
sint32 *xRefTable;
sint32 xRefIndex;
sint32 xRefStart;
char pOutStr[256];
bool adobeRGBCS_firstTime;
bool mirrorBackside;
sint32 topMarginInPix;
sint32 leftMarginInPix;
bool firstStrip;
sint32 numFullInjectedStrips;
sint32 numFullScanlinesToInject;
sint32 numPartialScanlinesToInject;
PCLmSUserSettingsType *m_pPCLmSSettings;
};
#endif // _PCLM_PARSER_

View file

@ -0,0 +1,188 @@
/*
* Copyright (C) 2016 The Android Open Source Project
* Copyright (C) 2016 Mopria Alliance, Inc.
* Copyright (C) 2013 Hewlett-Packard Development Company, L.P.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef PCLM_COMMON_DEFINES
#define PCLM_COMMON_DEFINES
#include <stdbool.h>
#include "wtypes.h"
#define PCLM_Ver 0.98
typedef enum {
RGB,
AdobeRGB,
GRAY,
unknown
} colorSpaceEnum;
typedef enum {
jpeg,
zlib,
rle
} compTypeEnum;
typedef enum {
simplex,
duplex_longEdge,
duplex_shortEdge
} duplexDispositionEnum;
typedef enum {
job_open,
job_closed,
job_errored
} jobStateEnum;
typedef enum {
deviceRGB,
adobeRGB,
grayScale
} colorSpaceDisposition;
typedef enum {
debugOn,
debugOff
} debugDisposition;
typedef enum {
compressRLE,
compressDCT,
compressFlate,
compressDefault,
compressNone
} compressionDisposition;
typedef enum {
portraitOrientation,
landscapeOrientation
} mediaOrientationDisposition;
typedef enum {
res300,
res600,
res1200
} renderResolution;
typedef enum {
top_left,
bottom_right
} pageOriginType;
typedef enum {
color_content,
gray_content,
unknown_content
} pageCromaticContent;
typedef enum {
draft,
normal,
best,
} pageOutputQuality;
typedef enum {
alternate,
alternate_roll,
auto_select,
bottom,
center,
disc,
envelope,
hagaki,
large_capacity,
left,
main_tray,
main_roll,
manual,
middle,
photo,
rear,
right,
side,
top,
tray_1,
tray_2,
tray_3,
tray_4,
tray_5,
tray_N,
} jobInputBin;
typedef enum {
top_output,
middle_output,
bottom_output,
side_output,
center_output,
rear_output,
face_up,
face_down,
large_capacity_output,
stacker_N,
mailbox_N,
tray_1_output,
tray_2_output,
tray_3_output,
tray_4_output,
} jobOutputBin;
typedef struct {
pageCromaticContent userCromaticMode;
pageOutputQuality userPageQuality;
mediaOrientationDisposition userOrientation;
char userMediaType[256];
jobInputBin userInputBin;
int userCopies;
char userDocumentName[256];
jobOutputBin userOutputBin;
} PCLmSUserSettingsType;
typedef struct {
char mediaSizeName[256];
char clientLocale[256];
float mediaHeight;
float mediaWidth;
float sourceHeight;
float sourceWidth;
float mediaWidthOffset;
float mediaHeightOffset;
pageCromaticContent colorContent; // Did the page contain any "real" color
pageOriginType pageOrigin;
compressionDisposition compTypeRequested;
colorSpaceDisposition srcColorSpaceSpefication;
colorSpaceDisposition dstColorSpaceSpefication;
int stripHeight;
renderResolution destinationResolution;
duplexDispositionEnum duplexDisposition;
int scaleFactor;
bool genExtraPage;
bool mirrorBackside;
int mediaWidthInPixels;
int mediaHeightInPixels;
int SourceWidthPixels;
int SourceHeightPixels;
} PCLmPageSetup;
typedef enum {
success = 0,
genericFailure = -1,
} PCLmGenerator_returnType;
#endif

View file

@ -0,0 +1,30 @@
/*
* Copyright (C) 2016 The Android Open Source Project
* Copyright (C) 2016 Mopria Alliance, Inc.
* Copyright (C) 2013 Hewlett-Packard Development Company, L.P.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef _GEN_PCLM_H
#define _GEN_PCLM_H
#include <jpeglib.h>
/*
* Encode JPEG data from imageBuffer into to an output buffer
*/
extern void write_JPEG_Buff(ubyte *outBuff, int quality, int image_width, int image_height,
JSAMPLE *imageBuffer, int resolution, colorSpaceDisposition, int *numCompBytes);
#endif // _GEN_PCLM_H

View file

@ -0,0 +1,128 @@
/*
* Copyright (C) 2016 The Android Open Source Project
* Copyright (C) 2016 Mopria Alliance, Inc.
* Copyright (C) 2013 Hewlett-Packard Development Company, L.P.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdio.h>
#include "common_defines.h"
#include <wprint_debug.h>
extern "C"
{
#include <jpeglib.h>
}
#define TAG "genJPEGStrips"
/*
* Function for setting up the buffer (which we already did)
*/
static void init_buffer(jpeg_compress_struct *) {
}
/*
* Function for handling buffer overlow (should not happen because we allocated a large
* buffer)
*/
static boolean empty_buffer(jpeg_compress_struct *) {
return TRUE;
}
/*
* Function for finalizing the buffer (which we do not need to do)
*/
static void term_buffer(jpeg_compress_struct *) {
}
GLOBAL(void)
write_JPEG_Buff(ubyte *buffPtr, int quality, int image_width, int image_height,
JSAMPLE *imageBuffer, int resolution, colorSpaceDisposition destCS, int *numCompBytes) {
struct jpeg_error_mgr jerr;
// Step 1: allocate and initialize JPEG compression object
struct jpeg_compress_struct cinfo = {
.client_data = NULL, .err = jpeg_std_error(&jerr)
};
// Now we can initialize the JPEG compression object.
jpeg_create_compress(&cinfo);
// Step 2: specify data destination (we will use a memory buffer)
struct jpeg_destination_mgr dm = {
.init_destination = init_buffer, .empty_output_buffer = empty_buffer,
.term_destination = term_buffer, .next_output_byte = buffPtr,
.free_in_buffer = (size_t) image_width * image_height * 3
};
cinfo.dest = &dm;
// Step 3: set parameters for compression
cinfo.image_width = (JDIMENSION) image_width;
cinfo.image_height = (JDIMENSION) image_height;
if (destCS == deviceRGB || destCS == adobeRGB) {
cinfo.in_color_space = JCS_RGB;
cinfo.jpeg_color_space = JCS_RGB;
cinfo.input_components = 3;
} else {
cinfo.in_color_space = JCS_GRAYSCALE;
cinfo.jpeg_color_space = JCS_GRAYSCALE;
cinfo.input_components = 1;
}
jpeg_set_defaults(&cinfo);
/* Now you can set any non-default parameters you wish to.
* Here we just illustrate the use of quality (quantization table) scaling:
*/
jpeg_set_quality(&cinfo, quality, TRUE); // TRUE = limit to baseline-JPEG values
// Set the density so that the JFIF header has the correct settings
cinfo.density_unit = 1; // 1=dots-per-inch, 2=dots per cm
cinfo.X_density = (UINT16) resolution;
cinfo.Y_density = (UINT16) resolution;
// set the rows/columns setting to reflect the resolution
// MCU = Minimum Coded Unit
cinfo.MCUs_per_row = (JDIMENSION) image_width;
cinfo.MCU_rows_in_scan = (JDIMENSION) image_height;
// Step 4: Start compressor
jpeg_start_compress(&cinfo, TRUE);
// Step 5: Write scanlines
int row_stride; // physical row width in image buffer
row_stride = image_width * cinfo.input_components; // JSAMPLEs per row in imageBuffer
JSAMPROW row_pointer[1]; // pointer to JSAMPLE row[s]
while (cinfo.next_scanline < cinfo.image_height) {
row_pointer[0] = &imageBuffer[cinfo.next_scanline * row_stride];
(void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
}
// Step 6: Finish compression
jpeg_finish_compress(&cinfo);
// Step 7: release JPEG compression object
jpeg_destroy_compress(&cinfo);
*numCompBytes = (int) (cinfo.dest->next_output_byte - buffPtr);
LOGD("write_JPEG_Buff: w=%d, h=%d, r=%d, q=%d compressed to %d", image_width, image_height,
resolution, quality, *numCompBytes);
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,177 @@
/*
* Copyright (C) 2016 The Android Open Source Project
* Copyright (C) 2016 Mopria Alliance, Inc.
* Copyright (C) 2013 Hewlett-Packard Development Company, L.P.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __LIB_PCL_H__
#define __LIB_PCL_H__
#include "ifc_print_job.h"
#include "ifc_wprint.h"
#include "lib_wprint.h"
#include "lib_pclm.h"
#include "common_defines.h"
#define _WJOBH_NONE 0
#define STANDARD_SCALE_FOR_PDF 72.0
#define SP_GRAY(Yr, Cbg, Crb) (((Yr<<6) + (Cbg*160) + (Crb<<5)) >> 8)
#define _START_JOB(JOB_INFO, EXT) \
{ \
const ifc_wprint_debug_stream_t* debug_ifc = \
JOB_INFO->wprint_ifc->get_debug_stream_ifc(JOB_INFO->job_handle); \
if (debug_ifc) { \
debug_ifc->debug_start_job(JOB_INFO->job_handle, EXT); \
} \
}
#define _START_PAGE(JOB_INFO, WIDTH, HEIGHT) \
{ \
const ifc_wprint_debug_stream_t* debug_ifc = \
JOB_INFO->wprint_ifc->get_debug_stream_ifc(JOB_INFO->job_handle); \
if (debug_ifc) { \
debug_ifc->debug_start_page(JOB_INFO->job_handle, JOB_INFO->page_number + 1, WIDTH, \
HEIGHT); \
} \
}
#define _PAGE_DATA(JOB_INFO, BUFF, LEN) \
{ \
const ifc_wprint_debug_stream_t* debug_ifc = \
JOB_INFO->wprint_ifc->get_debug_stream_ifc(JOB_INFO->job_handle); \
if (debug_ifc) { \
debug_ifc->debug_page_data(JOB_INFO->job_handle, BUFF, LEN); \
} \
}
#define _END_PAGE(JOB_INFO) \
{ \
const ifc_wprint_debug_stream_t* debug_ifc = \
JOB_INFO->wprint_ifc->get_debug_stream_ifc(JOB_INFO->job_handle); \
if (debug_ifc) { \
debug_ifc->debug_end_page(JOB_INFO->job_handle); \
} \
}
#define _END_JOB(JOB_INFO) \
{ \
const ifc_wprint_debug_stream_t* debug_ifc = \
JOB_INFO->wprint_ifc->get_debug_stream_ifc(JOB_INFO->job_handle); \
if (debug_ifc) { \
debug_ifc->debug_end_job(JOB_INFO->job_handle); \
} \
}
#define _WRITE(JOB_INFO, BUFF, LEN) \
{ \
const ifc_wprint_debug_stream_t* debug_ifc = \
JOB_INFO->wprint_ifc->get_debug_stream_ifc(JOB_INFO->job_handle); \
if (debug_ifc) { \
debug_ifc->debug_job_data(JOB_INFO->job_handle, (const unsigned char *)BUFF, LEN); \
} \
JOB_INFO->print_ifc->send_data(JOB_INFO->print_ifc, BUFF, LEN); \
}
/*
* PCL/PWG job definition
*/
typedef struct {
const ifc_wprint_t *wprint_ifc;
const ifc_print_job_t *print_ifc;
wJob_t job_handle;
uint8 *seed_row, *pcl_buff;
uint8 *halftone_row;
sint16 *error_buf;
int pixel_width, pixel_height;
media_size_t media_size;
int resolution;
int page_number, num_rows;
int send_full_row;
int rows_to_skip;
uint8 monochrome;
int num_components;
int scan_line_width;
float standard_scale;
int strip_height;
int pclm_scan_line_width;
void *pclmgen_obj;
PCLmPageSetup pclm_page_info;
uint8 *pclm_output_buffer;
const char *useragent;
} pcl_job_info_t;
/*
* Interface for PCL and PWG job handling
*/
typedef struct ifc_pcl_st {
/*
* Called once per job at the start of the job. Returns a print job handle that is used
* in other functions of this library. Returns WPRINT_BAD_JOB_HANDLE for errors.
*/
wJob_t (*start_job)(wJob_t job_handle, pcl_job_info_t *job_info, media_size_t media_size,
media_type_t media_type, int resolution, duplex_t duplex,
duplex_dry_time_t dry_time, color_space_t color_space, media_tray_t media_tray,
float top_margin, float left_margin);
/*
* Called once per job at the end of the job. A current print job
* must end for the next one to start. Returns OK or ERROR as the case maybe.
*/
status_t (*end_job)(pcl_job_info_t *job_info);
/*
* Called once per page of the job to indicate start of the page and page metrics.
* Returns running page number starting with 1 or ERROR.
*/
status_t (*start_page)(pcl_job_info_t *job_info,
int pixel_width,
int pixel_height);
/*
* Called once per page of the job to indicate end of the page. Returns OK or ERROR.
*/
status_t (*end_page)(pcl_job_info_t *job_info,
int page_number);
/*
* Called several times a page to send a rectangular swath of RGB data. The array
* rgb_pixels[] must have (num_rows * pixel_width) pixels. bytes_per_row can be used for
* 32-bit aligned rows. Returns OK or ERROR.
*/
status_t (*print_swath)(pcl_job_info_t *job_info, char *rgb_pixels, int start_row, int num_rows,
int bytes_per_row);
/*
* Return true if this interface can cancel a job partway through a page
*/
bool (*canCancelMidPage)(void);
} ifc_pcl_t;
/*
* Connect to the PCLm plugin, returning its interface
*/
ifc_pcl_t *pclm_connect(void);
/*
* Connect to the pwg plugin, returning its interface
*/
ifc_pcl_t *pwg_connect(void);
#endif // __LIB_PCL_H__

View file

@ -0,0 +1,311 @@
/*
* Copyright (C) 2016 The Android Open Source Project
* Copyright (C) 2016 Mopria Alliance, Inc.
* Copyright (C) 2013 Hewlett-Packard Development Company, L.P.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "lib_pcl.h"
#include "wprint_image.h"
#include "pclm_wrapper_api.h"
#include "media.h"
#include "wprint_debug.h"
#define TAG "lib_pclm"
/*
* Store a valid media_size name into media_name
*/
static void _get_pclm_media_size_name(pcl_job_info_t *job_info, media_size_t media_size,
char *media_name) {
int i = 0;
for (i = 0; i < SUPPORTED_MEDIA_SIZE_COUNT; i++) {
if (media_size == SupportedMediaSizes[i].media_size) {
strncpy(media_name, SupportedMediaSizes[i].PCL6Name,
strlen(SupportedMediaSizes[i].PCL6Name));
LOGD("_get_pclm_media_size_name(): match found: %d, %s", media_size, media_name);
break; // we found a match, so break out of loop
}
}
if (i == SUPPORTED_MEDIA_SIZE_COUNT) {
// media size not found, defaulting to letter
LOGD("_get_pclm_media_size_name(): media size, %d, NOT FOUND, setting to letter",
media_size);
_get_pclm_media_size_name(job_info, US_LETTER, media_name);
}
}
/*
* Write a valid media_size into myPageInfo
*/
static void _get_pclm_media_size(pcl_job_info_t *job_info, media_size_t media_size,
PCLmPageSetup *myPageInfo) {
int i = SUPPORTED_MEDIA_SIZE_COUNT;
if (myPageInfo != NULL) {
for (i = 0; i < SUPPORTED_MEDIA_SIZE_COUNT; i++) {
if (media_size == SupportedMediaSizes[i].media_size) {
strncpy(myPageInfo->mediaSizeName, SupportedMediaSizes[i].PCL6Name,
sizeof(myPageInfo->mediaSizeName) - 1);
myPageInfo->mediaWidth = floorf(
_MI_TO_POINTS(SupportedMediaSizes[i].WidthInInches));
myPageInfo->mediaHeight = floorf(
_MI_TO_POINTS(SupportedMediaSizes[i].HeightInInches));
LOGD("_get_pclm_media_size(): match found: %d, %s, width=%f, height=%f",
media_size, SupportedMediaSizes[i].PCL6Name, myPageInfo->mediaWidth,
myPageInfo->mediaHeight);
break; // we found a match, so break out of loop
}
}
}
if (i == SUPPORTED_MEDIA_SIZE_COUNT) {
// media size not found, defaulting to letter
LOGD("_get_pclm_media_size(): media size, %d, NOT FOUND, setting to letter", media_size);
_get_pclm_media_size(job_info, US_LETTER, myPageInfo);
}
}
static wJob_t _start_job(wJob_t job_handle, pcl_job_info_t *job_info, media_size_t media_size,
media_type_t media_type, int resolution, duplex_t duplex, duplex_dry_time_t dry_time,
color_space_t color_space, media_tray_t media_tray, float top_margin,
float left_margin) {
int outBuffSize = 0;
if (job_info == NULL) {
return _WJOBH_NONE;
}
if (job_info->job_handle != _WJOBH_NONE) {
if (job_info->wprint_ifc != NULL) {
LOGD("_start_job() required cleanup");
}
job_info->job_handle = _WJOBH_NONE;
}
if ((job_info->wprint_ifc == NULL) || (job_info->print_ifc == NULL)) {
return _WJOBH_NONE;
}
LOGD("_start_job(), media_size %d, media_type %d, dt %d, %s, media_tray %d margins T %f L %f",
media_size, media_type, dry_time,
(duplex == DUPLEX_MODE_NONE) ? "simplex" : "duplex",
media_tray, top_margin, left_margin);
job_info->job_handle = job_handle;
_START_JOB(job_info, "pdf");
job_info->resolution = resolution;
job_info->media_size = media_size;
job_info->standard_scale = (float) resolution / (float) STANDARD_SCALE_FOR_PDF;
// initialize static variables
job_info->pclm_output_buffer = NULL;
job_info->seed_row = job_info->pcl_buff = NULL; // unused
job_info->pixel_width = job_info->pixel_height = job_info->page_number = job_info->num_rows = 0;
memset((void *) &job_info->pclm_page_info, 0x0, sizeof(PCLmPageSetup));
_get_pclm_media_size_name(job_info, media_size, &job_info->pclm_page_info.mediaSizeName[0]);
if ((left_margin < 0.0f) || (top_margin < 0.0f)) {
job_info->pclm_page_info.mediaWidthOffset = 0.0f;
job_info->pclm_page_info.mediaHeightOffset = 0.0f;
} else {
job_info->pclm_page_info.mediaWidthOffset = (left_margin * (float) STANDARD_SCALE_FOR_PDF);
job_info->pclm_page_info.mediaHeightOffset = (top_margin * (float) STANDARD_SCALE_FOR_PDF);
}
LOGI("_start_job(), mediaHeightOffsets W %f H %f", job_info->pclm_page_info.mediaWidthOffset,
job_info->pclm_page_info.mediaHeightOffset);
job_info->pclm_page_info.pageOrigin = top_left; // REVISIT
job_info->monochrome = (color_space == COLOR_SPACE_MONO);
job_info->pclm_page_info.dstColorSpaceSpefication = deviceRGB;
if (color_space == COLOR_SPACE_MONO) {
job_info->pclm_page_info.dstColorSpaceSpefication = grayScale;
} else if (color_space == COLOR_SPACE_COLOR) {
job_info->pclm_page_info.dstColorSpaceSpefication = deviceRGB;
} else if (color_space == COLOR_SPACE_ADOBE_RGB) {
job_info->pclm_page_info.dstColorSpaceSpefication = adobeRGB;
}
job_info->pclm_page_info.stripHeight = job_info->strip_height;
job_info->pclm_page_info.destinationResolution = res600;
if (resolution == 300) {
job_info->pclm_page_info.destinationResolution = res300;
} else if (resolution == 600) {
job_info->pclm_page_info.destinationResolution = res600;
} else if (resolution == 1200) {
job_info->pclm_page_info.destinationResolution = res1200;
}
if (duplex == DUPLEX_MODE_BOOK) {
job_info->pclm_page_info.duplexDisposition = duplex_longEdge;
} else if (duplex == DUPLEX_MODE_TABLET) {
job_info->pclm_page_info.duplexDisposition = duplex_shortEdge;
} else {
job_info->pclm_page_info.duplexDisposition = simplex;
}
job_info->pclm_page_info.mirrorBackside = false;
job_info->pclmgen_obj = CreatePCLmGen();
PCLmStartJob(job_info->pclmgen_obj, (void **) &job_info->pclm_output_buffer, &outBuffSize);
_WRITE(job_info, (const char *) job_info->pclm_output_buffer, outBuffSize);
return job_info->job_handle;
}
static int _start_page(pcl_job_info_t *job_info, int pixel_width, int pixel_height) {
PCLmPageSetup *page_info = &job_info->pclm_page_info;
ubyte *pclm_output_buff = job_info->pclm_output_buffer;
int outBuffSize = 0;
_START_PAGE(job_info, pixel_width, pixel_height);
page_info->sourceHeight = (float) pixel_height / job_info->standard_scale;
page_info->sourceWidth = (float) pixel_width / job_info->standard_scale;
LOGI("_start_page(), strip height=%d, image width=%d, image height=%d, scaled width=%f, "
"scaled height=%f", page_info->stripHeight, pixel_width, pixel_height,
page_info->sourceWidth, page_info->sourceHeight);
if (job_info->num_components == 3) {
page_info->colorContent = color_content;
page_info->srcColorSpaceSpefication = deviceRGB;
} else {
page_info->colorContent = gray_content;
page_info->srcColorSpaceSpefication = grayScale;
}
/* Note: we could possibly get this value dynamically from device via IPP (ePCL) however,
* current ink devices report RLE as the default compression type, which compresses much
* worse than JPEG or FLATE
*/
page_info->compTypeRequested = compressDCT;
job_info->scan_line_width = pixel_width * job_info->num_components;
int res1 = PCLmGetMediaDimensions(job_info->pclmgen_obj, page_info->mediaSizeName, page_info);
page_info->SourceWidthPixels = MIN(pixel_width, job_info->pclm_page_info.mediaWidthInPixels);
page_info->SourceHeightPixels = pixel_height;
job_info->pclm_scan_line_width =
job_info->pclm_page_info.mediaWidthInPixels * job_info->num_components;
LOGD("PCLmGetMediaDimensions(%d), mediaSizeName=%s, mediaheight=%f, mediawidth=%f, "
"mheightpixels=%d, mwidthpixels=%d", res1, job_info->pclm_page_info.mediaSizeName,
job_info->pclm_page_info.mediaWidth, job_info->pclm_page_info.mediaHeight,
job_info->pclm_page_info.mediaWidthInPixels,
job_info->pclm_page_info.mediaHeightInPixels);
PCLmStartPage(job_info->pclmgen_obj, page_info, (void **) &pclm_output_buff, &outBuffSize);
_WRITE(job_info, (const char *) pclm_output_buff, outBuffSize);
job_info->page_number++;
return job_info->page_number;
}
static int _print_swath(pcl_job_info_t *job_info, char *rgb_pixels, int start_row, int num_rows,
int bytes_per_row) {
int outBuffSize = 0;
_PAGE_DATA(job_info, (const unsigned char *) rgb_pixels, (num_rows * bytes_per_row));
if (job_info->monochrome) {
unsigned char *buff = (unsigned char *) rgb_pixels;
int nbytes = (num_rows * bytes_per_row);
int readIndex, writeIndex;
for (readIndex = writeIndex = 0; readIndex < nbytes; readIndex += BYTES_PER_PIXEL(1)) {
unsigned char gray = SP_GRAY(buff[readIndex + 0], buff[readIndex + 1],
buff[readIndex + 2]);
buff[writeIndex++] = gray;
buff[writeIndex++] = gray;
buff[writeIndex++] = gray;
}
}
LOGD("_print_swath(): page #%d, buffSize=%d, rows %d - %d (%d rows), bytes per row %d",
job_info->page_number, job_info->strip_height * job_info->scan_line_width, start_row,
start_row + num_rows - 1, num_rows, bytes_per_row);
if (job_info->scan_line_width > job_info->pclm_scan_line_width) {
int i;
char *src_pixels = rgb_pixels + job_info->scan_line_width;
char *dest_pixels = rgb_pixels + job_info->pclm_scan_line_width;
for (i = 1; i < num_rows; i++, src_pixels += job_info->scan_line_width,
dest_pixels += job_info->pclm_scan_line_width) {
memmove(dest_pixels, src_pixels, job_info->pclm_scan_line_width);
}
}
/* if the inBufferSize is ever used in genPCLm, change the input parameter to pass in
* image_info->printable_width*num_components*strip_height
* it is currently pixel_width (from _start_page()) * num_components * strip_height
*/
PCLmEncapsulate(job_info->pclmgen_obj, rgb_pixels,
job_info->strip_height * MIN(job_info->scan_line_width, job_info->pclm_scan_line_width),
num_rows, (void **) &job_info->pclm_output_buffer, &outBuffSize);
_WRITE(job_info, (const char *) job_info->pclm_output_buffer, outBuffSize);
return OK;
}
static int _end_page(pcl_job_info_t *job_info, int page_number) {
int outBuffSize = 0;
if (page_number == -1) {
LOGI("_end_page(): writing blank page");
_start_page(job_info, 0, 0);
unsigned char blank_data[1] = {0xFF};
PCLmEncapsulate(job_info->pclmgen_obj, (void *) blank_data, 1, 1,
(void **) &job_info->pclm_output_buffer, &outBuffSize);
_WRITE(job_info, (const char *) job_info->pclm_output_buffer, outBuffSize);
}
LOGI("_end_page()");
PCLmEndPage(job_info->pclmgen_obj, (void **) &job_info->pclm_output_buffer, &outBuffSize);
_WRITE(job_info, (const char *) job_info->pclm_output_buffer, outBuffSize);
_END_PAGE(job_info);
return OK;
}
static int _end_job(pcl_job_info_t *job_info) {
int outBuffSize = 0;
LOGI("_end_job()");
PCLmEndJob(job_info->pclmgen_obj, (void **) &job_info->pclm_output_buffer, &outBuffSize);
_WRITE(job_info, (const char *) job_info->pclm_output_buffer, outBuffSize);
PCLmFreeBuffer(job_info->pclmgen_obj, job_info->pclm_output_buffer);
DestroyPCLmGen(job_info->pclmgen_obj);
_END_JOB(job_info);
return OK;
}
static bool _canCancelMidPage(void) {
return false;
}
static const ifc_pcl_t _pcl_ifc = {
_start_job, _end_job, _start_page, _end_page, _print_swath, _canCancelMidPage
};
ifc_pcl_t *pclm_connect(void) {
return ((ifc_pcl_t *) &_pcl_ifc);
}

View file

@ -0,0 +1,25 @@
/*
* Copyright (C) 2016 The Android Open Source Project
* Copyright (C) 2016 Mopria Alliance, Inc.
* Copyright (C) 2013 Hewlett-Packard Development Company, L.P.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __LIB_PCLM_H__
#define __LIB_PCLM_H__
#include "wtypes.h"
#include "wprint_df_types.h"
#endif // __LIB_PCLM_H__

View file

@ -0,0 +1,407 @@
/*
* Copyright (C) 2016 The Android Open Source Project
* Copyright (C) 2016 Mopria Alliance, Inc.
* Copyright (C) 2013 Hewlett-Packard Development Company, L.P.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <cups/raster.h>
#include "lib_pcl.h"
#include "wprint_image.h"
#include "media.h"
#define TAG "lib_pwg"
#define STANDARD_SCALE_FOR_PDF 72.0
#define _MI_TO_PIXELS(n, res) ((n)*(res)+500)/1000.0
#define _MI_TO_POINTS(n) _MI_TO_PIXELS(n, STANDARD_SCALE_FOR_PDF)
cups_raster_t *ras_out = NULL;
cups_page_header2_t header_pwg;
/*
* Write the PWG header
*/
static void _write_header_pwg(int pixel_width, int pixel_height, cups_page_header2_t *h,
bool monochrome) {
if (h != NULL) {
strcpy(h->MediaClass, "PwgRaster");
strcpy(h->MediaColor, "");
strcpy(h->MediaType, "");
strcpy(h->OutputType, "");
h->AdvanceDistance = 0;
h->AdvanceMedia = CUPS_ADVANCE_FILE;
h->Collate = CUPS_FALSE;
h->CutMedia = CUPS_CUT_NONE;
h->cupsPageSize[0] = (float) ((pixel_width * STANDARD_SCALE_FOR_PDF) / h->HWResolution[0]);
h->cupsPageSize[1] = (float) ((pixel_height * STANDARD_SCALE_FOR_PDF) / h->HWResolution[1]);
h->ImagingBoundingBox[0] = 0;
h->ImagingBoundingBox[1] = 0;
h->ImagingBoundingBox[2] = h->cupsPageSize[0];
h->ImagingBoundingBox[3] = h->cupsPageSize[1];
h->cupsBorderlessScalingFactor = 1.0;
h->InsertSheet = CUPS_FALSE;
h->Jog = CUPS_JOG_NONE;
h->LeadingEdge = CUPS_EDGE_TOP;
h->Margins[0] = 0;
h->Margins[1] = 0;
h->ManualFeed = CUPS_TRUE;
h->MediaPosition = 0;
h->MediaWeight = 0;
h->MirrorPrint = CUPS_FALSE;
h->NegativePrint = CUPS_FALSE;
h->NumCopies = 1;
h->Orientation = CUPS_ORIENT_0;
h->PageSize[0] = (int) h->cupsPageSize[0];
h->PageSize[1] = (int) h->cupsPageSize[1];
h->Separations = CUPS_TRUE;
h->TraySwitch = CUPS_TRUE;
h->Tumble = CUPS_TRUE;
h->cupsWidth = pixel_width;
h->cupsHeight = pixel_height;
h->cupsBitsPerPixel = (monochrome ? 8 : 24);
h->cupsBitsPerColor = 8;
h->cupsColorSpace = (monochrome ? CUPS_CSPACE_SW : CUPS_CSPACE_SRGB);
h->cupsBytesPerLine = (h->cupsBitsPerPixel * pixel_width + 7) / 8;
h->cupsColorOrder = CUPS_ORDER_CHUNKED;
h->cupsCompression = 0;
h->cupsRowCount = 1;
h->cupsRowFeed = 1;
h->cupsRowStep = 1;
h->cupsNumColors = 0;
h->cupsImagingBBox[0] = 0.0;
h->cupsImagingBBox[1] = 0.0;
h->cupsImagingBBox[2] = 0.0;
h->cupsImagingBBox[3] = 0.0;
strcpy(h->cupsMarkerType, "Marker Type");
strcpy(h->cupsRenderingIntent, "Rendering Intent");
strcpy(h->cupsPageSizeName, "Letter");
}
}
/*
* Store the supplied media size into job_info
*/
static void _get_pwg_media_size(pcl_job_info_t *job_info, media_size_t media_size,
PCLmPageSetup *myPageInfo) {
int i = 0;
do {
if (myPageInfo == NULL) {
continue;
}
for (i = 0; i < SUPPORTED_MEDIA_SIZE_COUNT; i++) {
if (media_size == SupportedMediaSizes[i].media_size) {
strncpy(myPageInfo->mediaSizeName, SupportedMediaSizes[i].PCL6Name,
sizeof(myPageInfo->mediaSizeName) - 1);
myPageInfo->mediaWidth = floorf(
_MI_TO_POINTS(SupportedMediaSizes[i].WidthInInches));
myPageInfo->mediaHeight = floorf(
_MI_TO_POINTS(SupportedMediaSizes[i].HeightInInches));
LOGD(" _get_pwg_media_size(): match found: %d, %s, width=%f, height=%f",
media_size, SupportedMediaSizes[i].PCL6Name, myPageInfo->mediaWidth,
myPageInfo->mediaHeight);
break; // we found a match, so break out of loop
}
}
}
while (0);
if (i == SUPPORTED_MEDIA_SIZE_COUNT) {
// media size not found, defaulting to letter
LOGD("_get_pwg_media_size(): media size, %d, NOT FOUND, setting to letter", media_size);
_get_pwg_media_size(job_info, US_LETTER, myPageInfo);
}
}
/*
* Write a buffer to the output stream
*/
static ssize_t _pwg_io_write(void *ctx, unsigned char *buf, size_t bytes) {
pcl_job_info_t *pwg_job_info = (pcl_job_info_t *) ctx;
_WRITE(pwg_job_info, (const char *) buf, bytes);
return bytes;
}
static wJob_t _start_job(wJob_t job_handle, pcl_job_info_t *job_info, media_size_t media_size,
media_type_t media_type, int resolution, duplex_t duplex, duplex_dry_time_t dry_time,
color_space_t color_space, media_tray_t media_tray, float top_margin,
float left_margin) {
if (job_info == NULL) {
return _WJOBH_NONE;
}
if (job_info->job_handle != _WJOBH_NONE) {
if (job_info->wprint_ifc != NULL) {
LOGE("_start_job() required cleanup");
}
job_info->job_handle = _WJOBH_NONE;
}
if ((job_info->wprint_ifc == NULL) || (job_info->print_ifc == NULL)) {
return _WJOBH_NONE;
}
LOGD("_start_job(), media_size %d, media_type %d, dt %d, %s, media_tray %d", media_size,
media_type, dry_time, (duplex == DUPLEX_MODE_NONE) ? "simplex" : "duplex",
media_tray);
job_info->job_handle = job_handle;
_START_JOB(job_info, "pwg");
header_pwg.HWResolution[0] = resolution;
header_pwg.HWResolution[1] = resolution;
job_info->resolution = resolution;
job_info->media_size = media_size;
job_info->standard_scale = (float) resolution / (float) 72;
// initialize static variables
job_info->pclm_output_buffer = NULL;
job_info->seed_row = job_info->pcl_buff = NULL; // unused
job_info->pixel_width = job_info->pixel_height = job_info->page_number = job_info->num_rows = 0;
memset((void *) &job_info->pclm_page_info, 0x0, sizeof(PCLmPageSetup));
_get_pwg_media_size(job_info, media_size, &job_info->pclm_page_info);
if (left_margin < 0.0f || top_margin < 0.0f) {
job_info->pclm_page_info.mediaWidthOffset = 0.0f;
job_info->pclm_page_info.mediaHeightOffset = 0.0f;
} else {
job_info->pclm_page_info.mediaWidthOffset = left_margin;
job_info->pclm_page_info.mediaHeightOffset = top_margin;
}
header_pwg.cupsMediaType = media_size;
job_info->pclm_page_info.pageOrigin = top_left; // REVISIT
job_info->monochrome = (color_space == COLOR_SPACE_MONO);
job_info->pclm_page_info.dstColorSpaceSpefication = deviceRGB;
if (color_space == COLOR_SPACE_MONO) {
header_pwg.cupsColorSpace = CUPS_CSPACE_SW;
job_info->pclm_page_info.dstColorSpaceSpefication = deviceRGB;
} else if (color_space == COLOR_SPACE_COLOR) {
job_info->pclm_page_info.dstColorSpaceSpefication = deviceRGB;
header_pwg.cupsColorSpace = CUPS_CSPACE_SRGB;
} else if (color_space == COLOR_SPACE_ADOBE_RGB) {
job_info->pclm_page_info.dstColorSpaceSpefication = adobeRGB;
header_pwg.cupsColorSpace = CUPS_CSPACE_SRGB;
}
job_info->pclm_page_info.stripHeight = job_info->strip_height;
job_info->pclm_page_info.destinationResolution = res600;
if (resolution == 300) {
job_info->pclm_page_info.destinationResolution = res300;
} else if (resolution == 600) {
job_info->pclm_page_info.destinationResolution = res600;
} else if (resolution == 1200) {
job_info->pclm_page_info.destinationResolution = res1200;
}
if (duplex == DUPLEX_MODE_BOOK) {
job_info->pclm_page_info.duplexDisposition = duplex_longEdge;
header_pwg.Duplex = CUPS_TRUE;
} else if (duplex == DUPLEX_MODE_TABLET) {
job_info->pclm_page_info.duplexDisposition = duplex_shortEdge;
header_pwg.Duplex = CUPS_TRUE;
} else {
job_info->pclm_page_info.duplexDisposition = simplex;
header_pwg.Duplex = CUPS_FALSE;
}
job_info->pclm_page_info.mirrorBackside = false;
header_pwg.OutputFaceUp = CUPS_FALSE;
header_pwg.cupsBitsPerColor = BITS_PER_CHANNEL;
ras_out = cupsRasterOpenIO(_pwg_io_write, (void *) job_info, CUPS_RASTER_WRITE_PWG);
return job_info->job_handle;
}
static int _start_page(pcl_job_info_t *job_info, int pixel_width, int pixel_height) {
PCLmPageSetup *page_info = &job_info->pclm_page_info;
_START_PAGE(job_info, pixel_width, pixel_height);
page_info->sourceHeight = (float) pixel_height / job_info->standard_scale;
page_info->sourceWidth = (float) pixel_width / job_info->standard_scale;
LOGI("_start_page(), strip height=%d, image width=%d, image height=%d, scaled width=%f, "
"scaled height=%f", page_info->stripHeight, pixel_width, pixel_height,
page_info->sourceWidth, page_info->sourceHeight);
if (job_info->num_components == 3) {
page_info->colorContent = color_content;
page_info->srcColorSpaceSpefication = deviceRGB;
} else {
page_info->colorContent = gray_content;
page_info->srcColorSpaceSpefication = grayScale;
}
page_info->colorContent = color_content;
page_info->srcColorSpaceSpefication = deviceRGB;
// REVISIT: possibly get this value dynamically from device via IPP (ePCL)
// however, current ink devices report RLE as the default compression type, which compresses
// much worse than JPEG or FLATE
page_info->compTypeRequested = compressDCT;
job_info->scan_line_width = BYTES_PER_PIXEL(pixel_width);
// Fill up the pwg header
_write_header_pwg(pixel_width, pixel_height, &header_pwg, job_info->monochrome);
LOGI("cupsWidth = %d", header_pwg.cupsWidth);
LOGI("cupsHeight = %d", header_pwg.cupsHeight);
LOGI("cupsPageWidth = %f", header_pwg.cupsPageSize[0]);
LOGI("cupsPageHeight = %f", header_pwg.cupsPageSize[1]);
LOGI("cupsBitsPerColor = %d", header_pwg.cupsBitsPerColor);
LOGI("cupsBitsPerPixel = %d", header_pwg.cupsBitsPerPixel);
LOGI("cupsBytesPerLine = %d", header_pwg.cupsBytesPerLine);
LOGI("cupsColorOrder = %d", header_pwg.cupsColorOrder);
LOGI("cupsColorSpace = %d", header_pwg.cupsColorSpace);
cupsRasterWriteHeader2(ras_out, &header_pwg);
job_info->page_number++;
return job_info->page_number;
}
static int _print_swath(pcl_job_info_t *job_info, char *rgb_pixels, int start_row, int num_rows,
int bytes_per_row) {
int outBuffSize;
_PAGE_DATA(job_info, (const unsigned char *) rgb_pixels, (num_rows * bytes_per_row));
if (job_info->monochrome) {
unsigned char *buff = (unsigned char *) rgb_pixels;
int nbytes = (num_rows * bytes_per_row);
int readIndex, writeIndex;
for (readIndex = writeIndex = 0; readIndex < nbytes; readIndex += BYTES_PER_PIXEL(1)) {
unsigned char gray = SP_GRAY(buff[readIndex + 0], buff[readIndex + 1],
buff[readIndex + 2]);
buff[writeIndex++] = gray;
}
outBuffSize = writeIndex;
} else {
outBuffSize = num_rows * bytes_per_row;
}
LOGD("_print_swath(): page #%d, buffSize=%d, rows %d - %d (%d rows), bytes per row %d",
job_info->page_number, job_info->strip_height * job_info->scan_line_width,
start_row, start_row + num_rows - 1, num_rows, bytes_per_row);
/* If the inBufferSize is ever used in genPCLm, change the input parameter to pass in
* image_info->printable_width*num_components*strip_height. it is currently pixel_width
* (from _start_page()) * num_components * strip_height
*/
if (ras_out != NULL) {
unsigned result = cupsRasterWritePixels(ras_out, (unsigned char *) rgb_pixels, outBuffSize);
LOGD("cupsRasterWritePixels return %d", result);
} else {
LOGD("cupsRasterWritePixels raster is null");
}
return OK;
}
/*
* Allocate and fill a blank page of PackBits data. Writes size into buffer_size. The buffer
* must be free'd by the caller.
*/
unsigned char *_generate_blank_data(int pixel_width, int pixel_height, uint8 monochrome, size_t *buffer_size) {
if (pixel_width == 0 || pixel_height == 0) return NULL;
/* PWG Raster's PackBits-like algorithm allows for a maximum of:
* 256 repeating rows and is encoded using a single octet containing (count - 1)
* 128 repeating color value and is run length encoded using a single octet containing (count - 1)
*/
int rows_full = pixel_height / 256;
int columns_full = pixel_width / 128;
int row_fraction = ((pixel_height % 256) != 0) ? 1 : 0;
int column_fraction = ((pixel_width % 128) != 0) ? 1 : 0;
int column_data_size = 1 + (columns_full + column_fraction) * (monochrome ? 2 : 4);
*buffer_size = (size_t) ((rows_full + row_fraction) * column_data_size);
unsigned char *buffer = (unsigned char *) malloc(*buffer_size);
if (buffer == NULL) return NULL;
int i = 0;
for (int y = 0; y < rows_full + row_fraction; y++) {
// Add row-repeat command
if (y < rows_full) {
buffer[i++] = 0xFF;
} else {
buffer[i++] = (unsigned char) ((pixel_height % 256) - 1);
}
for (int x = 0; x < columns_full + column_fraction; x++) {
// Add column-repeat command
if (x < columns_full) {
buffer[i++] = 0x7F;
} else {
buffer[i++] = (unsigned char) ((pixel_width % 128) - 1);
}
// Pixel color to repeat
buffer[i++] = 0xFF;
if (!monochrome) {
// Add rest of RGB for color output
buffer[i++] = 0xFF;
buffer[i++] = 0xFF;
}
}
}
return buffer;
}
static int _end_page(pcl_job_info_t *job_info, int page_number) {
if (page_number == -1) {
LOGD("lib_pclm: _end_page(): writing blank page");
size_t buffer_size;
unsigned char *buffer;
_start_page(job_info, header_pwg.cupsWidth, header_pwg.cupsHeight);
buffer = _generate_blank_data(header_pwg.cupsWidth, header_pwg.cupsHeight, job_info->monochrome, &buffer_size);
if (buffer == NULL) {
return ERROR;
} else {
_pwg_io_write(job_info, buffer, buffer_size);
free(buffer);
}
}
LOGI("lib_pcwg: _end_page()");
_END_PAGE(job_info);
return OK;
}
static int _end_job(pcl_job_info_t *job_info) {
LOGI("_end_job()");
_END_JOB(job_info);
cupsRasterClose(ras_out);
return OK;
}
static bool _canCancelMidPage(void) {
return false;
}
static const ifc_pcl_t _pcl_ifc = {
_start_job, _end_job, _start_page, _end_page, _print_swath, _canCancelMidPage
};
ifc_pcl_t *pwg_connect(void) {
return ((ifc_pcl_t *) &_pcl_ifc);
}

View file

@ -0,0 +1,43 @@
/*
* Copyright (C) 2016 The Android Open Source Project
* Copyright (C) 2016 Mopria Alliance, Inc.
* Copyright (C) 2013 Hewlett-Packard Development Company, L.P.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __MEDIA_H__
#define __MEDIA_H__
#include "lib_wprint.h"
#define STANDARD_SCALE_FOR_PDF 72.0
#define _MI_TO_PIXELS(n, res) ((n)*(res)+500)/1000.0
#define _MI_TO_POINTS(n) _MI_TO_PIXELS(n, STANDARD_SCALE_FOR_PDF)
#define _MI_TO_100MM(n) (n/1000) * 2540 // Convert 1k inch to 100 mm
#define UNKNOWN_VALUE -1
struct MediaSizeTableElement {
media_size_t media_size;
const char *PCL6Name;
const float WidthInInches; // Width in thousands of an inch
const float HeightInInches; // Height in thousands of an inch
const float WidthInMm; // Width in mm for metric based media sizes or UNKNOWN_VALUE otherwise
const float HeightInMm; // Height in mm for metric based media sizes or UNKNOWN_VALUE otherwise
const char *PWGName;
};
#define SUPPORTED_MEDIA_SIZE_COUNT 15
extern struct MediaSizeTableElement SupportedMediaSizes[SUPPORTED_MEDIA_SIZE_COUNT];
#endif // __MEDIA_H__

View file

@ -0,0 +1,61 @@
/*
* Copyright (C) 2016 The Android Open Source Project
* Copyright (C) 2016 Mopria Alliance, Inc.
* Copyright (C) 2013 Hewlett-Packard Development Company, L.P.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "PCLmGenerator.h"
#include "pclm_wrapper_api.h"
void *CreatePCLmGen() {
return new PCLmGenerator();
}
int PCLmStartJob(void *thisClass, void **pOutBuffer, int *iOutBufferSize) {
return static_cast<PCLmGenerator *>(thisClass)->StartJob(pOutBuffer, iOutBufferSize);
}
int PCLmEndJob(void *thisClass, void **pOutBuffer, int *iOutBufferSize) {
return static_cast<PCLmGenerator *>(thisClass)->EndJob(pOutBuffer, iOutBufferSize);
}
int PCLmStartPage(void *thisClass, PCLmPageSetup *PCLmPageContent, void **pOutBuffer,
int *iOutBufferSize) {
return static_cast<PCLmGenerator *>(thisClass)->StartPage(PCLmPageContent, pOutBuffer,
iOutBufferSize);
}
int PCLmEndPage(void *thisClass, void **pOutBuffer, int *iOutBufferSize) {
return static_cast<PCLmGenerator *>(thisClass)->EndPage(pOutBuffer, iOutBufferSize);
}
int PCLmEncapsulate(void *thisClass, void *pInBuffer, int inBufferSize, int numLines,
void **pOutBuffer, int *iOutBufferSize) {
return static_cast<PCLmGenerator *>(thisClass)->Encapsulate(pInBuffer, inBufferSize, numLines,
pOutBuffer, iOutBufferSize);
}
void PCLmFreeBuffer(void *thisClass, void *pBuffer) {
return static_cast<PCLmGenerator *>(thisClass)->FreeBuffer(pBuffer);
}
void DestroyPCLmGen(void *thisClass) {
delete static_cast<PCLmGenerator *>(thisClass);
}
int PCLmGetMediaDimensions(void *thisClass, const char *mediaRequested, PCLmPageSetup *myPageInfo) {
return static_cast<PCLmGenerator *>(thisClass)->GetPclmMediaDimensions(mediaRequested,
myPageInfo);
}

View file

@ -0,0 +1,48 @@
/*
* Copyright (C) 2016 The Android Open Source Project
* Copyright (C) 2016 Mopria Alliance, Inc.
* Copyright (C) 2013 Hewlett-Packard Development Company, L.P.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "common_defines.h"
#ifndef PCLMWRAPPERAPI_H_
#define PCLMWRAPPERAPI_H_
// uses C calling convention
#ifdef __cplusplus
extern "C" {
#endif
/*
* C mappings for CPP PCLmGenerator APIs
*/
void *CreatePCLmGen();
int PCLmStartJob(void *thisClass, void **pOutBuffer, int *iOutBufferSize);
int PCLmEndJob(void *thisClass, void **pOutBUffer, int *iOutBifferSize);
int PCLmStartPage(void *thisClass, PCLmPageSetup *PCLmPageContent, void **pOutBuffer,
int *iOutBufferSize);
int PCLmEndPage(void *thisClass, void **pOutBuffer, int *iOutBufferSize);
int PCLmEncapsulate(void *thisClass, void *pInBuffer, int inBufferSize, int numLines,
void **pOutBuffer, int *iOutBufferSize);
void PCLmFreeBuffer(void *thisClass, void *pBuffer);
void DestroyPCLmGen(void *thisClass);
int PCLmGetMediaDimensions(void *thisClass, const char *mediaRequested, PCLmPageSetup *myPageInfo);
#ifdef __cplusplus
}
#endif
#endif // PCLMWRAPPERAPI_H_

View file

@ -0,0 +1,168 @@
/*
* Copyright (C) 2016 The Android Open Source Project
* Copyright (C) 2016 Mopria Alliance, Inc.
* Copyright (C) 2013 Hewlett-Packard Development Company, L.P.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <jni.h>
#include <malloc.h>
#include "wprint_mupdf.h"
#include "wprint_debug.h"
#define TAG "pdf_render"
/* Global reference to JVM */
extern JavaVM *_JVM;
/* Local data associated with pdf_render_st instances */
typedef struct pdf_render_st {
/* Public interface. Must be first. */
pdf_render_ifc_t ifc;
/* JNI environment */
JNIEnv *env;
/* true if the env was created for this thread */
bool needDetach;
/* Reference to associated PdfRender object */
jobject obj;
} pdf_render_st_t;
static jclass gPdfRenderClass;
static jmethodID gPdfRenderOpenDocument, gPdfRenderGetPageSize, gPdfRenderRenderPageStripe;
static jclass gSizeDClass;
static jmethodID gSizeDGetHeight, gSizeDGetWidth;
static int openDocument(pdf_render_ifc_t *obj, const char *fileName) {
LOGD("getPageCount %p %s", obj, fileName);
if (!gPdfRenderClass) return ERROR;
pdf_render_st_t *self = (pdf_render_st_t *) obj;
jstring fileNameString = (*self->env)->NewStringUTF(self->env, fileName);
int count = (*self->env)->CallIntMethod(self->env, self->obj, gPdfRenderOpenDocument,
fileNameString);
LOGD("getPageCount %p %s returning %d", obj, fileName, count);
return count;
}
static int getPageAttributes(pdf_render_ifc_t *obj, int page, double *width, double *height) {
LOGD("getPageAttributes %p %d", obj, page);
if (!gPdfRenderClass) return ERROR;
pdf_render_st_t *self = (pdf_render_st_t *) obj;
jobject size = (*self->env)->CallObjectMethod(self->env, self->obj, gPdfRenderGetPageSize,
page);
if (size == NULL) return ERROR;
// Extract width/height and return them
*width = (double) (*self->env)->CallDoubleMethod(self->env, size, gSizeDGetWidth);
*height = (double) (*self->env)->CallDoubleMethod(self->env, size, gSizeDGetHeight);
return OK;
}
static int renderPageStripe(pdf_render_ifc_t *obj, int page, int width, int height, float zoom,
char *buffer) {
LOGD("renderPageStripe %p %d", obj, page);
if (!gPdfRenderClass) return ERROR;
pdf_render_st_t *self = (pdf_render_st_t *) obj;
int bufferSize = width * height * 3;
jobject byteBuffer = (*self->env)->NewDirectByteBuffer(self->env, buffer, bufferSize);
if (!(*self->env)->CallBooleanMethod(self->env, self->obj, gPdfRenderRenderPageStripe, page,
0, width, height, (double) zoom, byteBuffer)) {
return ERROR;
}
(*self->env)->DeleteLocalRef(self->env, byteBuffer);
return OK;
}
static void destroy(pdf_render_ifc_t *obj) {
LOGD("destroy %p", obj);
pdf_render_st_t *self = (pdf_render_st_t *) obj;
(*self->env)->DeleteGlobalRef(self->env, self->obj);
if (self->needDetach) {
(*_JVM)->DetachCurrentThread(_JVM);
}
free(self);
}
void pdf_render_init(JNIEnv *env) {
LOGD("pdf_render_init");
/* Lock down global class references and look up method IDs */
gPdfRenderClass = (*env)->NewGlobalRef(env, (*env)->FindClass(env,
"com/android/bips/jni/PdfRender"));
gPdfRenderOpenDocument = (*env)->GetMethodID(env, gPdfRenderClass, "openDocument",
"(Ljava/lang/String;)I");
gPdfRenderGetPageSize = (*env)->GetMethodID(env, gPdfRenderClass, "getPageSize",
"(I)Lcom/android/bips/jni/SizeD;");
gPdfRenderRenderPageStripe = (*env)->GetMethodID(env, gPdfRenderClass, "renderPageStripe",
"(IIIIDLjava/nio/ByteBuffer;)Z");
gSizeDClass = (*env)->NewGlobalRef(env, (*env)->FindClass(env, "com/android/bips/jni/SizeD"));
gSizeDGetWidth = (*env)->GetMethodID(env, gSizeDClass, "getWidth", "()D");
gSizeDGetHeight = (*env)->GetMethodID(env, gSizeDClass, "getHeight", "()D");
}
void pdf_render_deinit(JNIEnv *env) {
LOGD("pdf_render_deinit");
(*env)->DeleteGlobalRef(env, gPdfRenderClass);
(*env)->DeleteGlobalRef(env, gSizeDClass);
gPdfRenderClass = 0;
}
pdf_render_ifc_t *create_pdf_render_ifc() {
LOGD("create_pdf_render_ifc");
pdf_render_st_t *self;
// Set up the interface
self = (pdf_render_st_t *) malloc(sizeof(pdf_render_st_t));
if (!self) return NULL;
self->ifc.openDocument = openDocument;
self->ifc.getPageAttributes = getPageAttributes;
self->ifc.renderPageStripe = renderPageStripe;
self->ifc.destroy = destroy;
// Get the environment
jint result = (*_JVM)->GetEnv(_JVM, (void **) &self->env, JNI_VERSION_1_6);
if (result == JNI_EDETACHED) {
self->needDetach = true;
if ((*_JVM)->AttachCurrentThread(_JVM, &self->env, NULL) < 0) {
LOGE("AttachCurrentThread failed");
free(self);
return NULL;
}
} else {
self->needDetach = false;
}
// Get the object
jmethodID methodId = (*self->env)->GetStaticMethodID(self->env, gPdfRenderClass, "getInstance",
"(Landroid/content/Context;)Lcom/android/bips/jni/PdfRender;");
jobject instance = (*self->env)->CallStaticObjectMethod(self->env, gPdfRenderClass, methodId,
NULL);
self->obj = (*self->env)->NewGlobalRef(self->env, instance);
return &self->ifc;
}

View file

@ -0,0 +1,532 @@
/*
* Copyright (C) 2016 The Android Open Source Project
* Copyright (C) 2016 Mopria Alliance, Inc.
* Copyright (C) 2013 Hewlett-Packard Development Company, L.P.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "ifc_print_job.h"
#include "lib_pcl.h"
#include "wprint_image.h"
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#ifndef __USE_UNIX98
#define __USE_UNIX98
#endif
#include <pthread.h>
#include <semaphore.h>
#define MAX_SEND_BUFFS (BUFFERED_ROWS / STRIPE_HEIGHT)
#define TAG "plugin_pcl"
typedef enum {
MSG_START_JOB,
MSG_START_PAGE,
MSG_SEND,
MSG_END_JOB,
MSG_END_PAGE,
} msg_id_t;
typedef struct {
msg_id_t id;
union {
struct {
float extra_margin;
int width;
int height;
} start_page;
struct {
char *buffer;
int start_row;
int num_rows;
int bytes_per_row;
} send;
struct {
int page;
char *buffers[MAX_SEND_BUFFS];
int count;
} end_page;
} param;
} msgQ_msg_t;
typedef struct {
wJob_t job_handle;
msg_q_id msgQ;
pthread_t send_tid;
pcl_job_info_t job_info;
wprint_job_params_t *job_params;
sem_t buffs_sem;
ifc_pcl_t *pcl_ifc;
} plugin_data_t;
static const char *_mime_types[] = {
MIME_TYPE_PDF,
NULL};
static const char *_print_formats[] = {
PRINT_FORMAT_PCLM,
PRINT_FORMAT_PWG,
PRINT_FORMAT_PDF,
NULL};
static const char **_get_mime_types(void) {
return _mime_types;
}
static const char **_get_print_formats(void) {
return _print_formats;
}
static void _cleanup_plugin_data(plugin_data_t *priv) {
if (priv != NULL) {
if (priv->msgQ != MSG_Q_INVALID_ID) {
priv->job_info.wprint_ifc->msgQDelete(priv->msgQ);
}
sem_destroy(&priv->buffs_sem);
free(priv);
}
}
/*
* Waits to receive message from the msgQ. Handles messages and sends commands to handle jobs
*/
static void *_send_thread(void *param) {
msgQ_msg_t msg;
plugin_data_t *priv = (plugin_data_t *) param;
while (priv->job_info.wprint_ifc->msgQReceive(priv->msgQ, (char *) &msg, sizeof(msgQ_msg_t),
WAIT_FOREVER) == OK) {
if (msg.id == MSG_START_JOB) {
priv->pcl_ifc->start_job(priv->job_handle, &priv->job_info,
priv->job_params->media_size, priv->job_params->media_type,
priv->job_params->pixel_units, priv->job_params->duplex,
priv->job_params->dry_time, priv->job_params->color_space,
priv->job_params->media_tray, priv->job_params->page_top_margin,
priv->job_params->page_left_margin);
} else if (msg.id == MSG_START_PAGE) {
priv->pcl_ifc->start_page(&priv->job_info, msg.param.start_page.width,
msg.param.start_page.height);
} else if (msg.id == MSG_SEND) {
if (!priv->pcl_ifc->canCancelMidPage() || !priv->job_params->cancelled) {
priv->pcl_ifc->print_swath(&priv->job_info, msg.param.send.buffer,
msg.param.send.start_row, msg.param.send.num_rows,
msg.param.send.bytes_per_row);
}
sem_post(&priv->buffs_sem);
} else if (msg.id == MSG_END_PAGE) {
int i;
priv->pcl_ifc->end_page(&priv->job_info, msg.param.end_page.page);
for (i = 0; i < msg.param.end_page.count; i++) {
if (msg.param.end_page.buffers[i] != NULL) {
free(msg.param.end_page.buffers[i]);
}
}
} else if (msg.id == MSG_END_JOB) {
priv->pcl_ifc->end_job(&priv->job_info);
break;
}
}
return NULL;
}
/*
* Starts pcl thread
*/
static status_t _start_thread(plugin_data_t *param) {
sigset_t allsig, oldsig;
status_t result;
if (param == NULL) {
return ERROR;
}
param->send_tid = pthread_self();
result = OK;
sigfillset(&allsig);
#if CHECK_PTHREAD_SIGMASK_STATUS
result = pthread_sigmask(SIG_SETMASK, &allsig, &oldsig);
#else // CHECK_PTHREAD_SIGMASK_STATUS
pthread_sigmask(SIG_SETMASK, &allsig, &oldsig);
#endif // CHECK_PTHREAD_SIGMASK_STATUS
if (result == OK) {
result = (status_t) pthread_create(&(param->send_tid), 0, _send_thread, (void *) param);
if ((result == ERROR) && (param->send_tid != pthread_self())) {
#if USE_PTHREAD_CANCEL
pthread_cancel(param->send_tid);
#else // else USE_PTHREAD_CANCEL
pthread_kill(param->send_tid, SIGKILL);
#endif // USE_PTHREAD_CANCEL
param->send_tid = pthread_self();
}
}
if (result == OK) {
sched_yield();
#if CHECK_PTHREAD_SIGMASK_STATUS
result = pthread_sigmask(SIG_SETMASK, &oldsig, 0);
#else // CHECK_PTHREAD_SIGMASK_STATUS
pthread_sigmask(SIG_SETMASK, &oldsig, 0);
#endif // CHECK_PTHREAD_SIGMASK_STATUS
}
return result;
}
/*
* Stops pcl thread
*/
static status_t _stop_thread(plugin_data_t *priv) {
status_t result = ERROR;
if (priv == NULL) {
return result;
}
if (!pthread_equal(priv->send_tid, pthread_self())) {
msgQ_msg_t msg;
msg.id = MSG_END_JOB;
priv->job_info.wprint_ifc->msgQSend(
priv->msgQ, (char *) &msg, sizeof(msgQ_msg_t), NO_WAIT, MSG_Q_FIFO);
pthread_join(priv->send_tid, 0);
priv->send_tid = pthread_self();
result = OK;
}
_cleanup_plugin_data(priv);
return result;
}
static int _start_job(wJob_t job_handle, const ifc_wprint_t *wprint_ifc_p,
const ifc_print_job_t *print_ifc_p, wprint_job_params_t *job_params) {
msgQ_msg_t msg;
plugin_data_t *priv = NULL;
do {
if (job_params == NULL) continue;
job_params->plugin_data = NULL;
if ((wprint_ifc_p == NULL) || (print_ifc_p == NULL)) continue;
priv = (plugin_data_t *) malloc(sizeof(plugin_data_t));
if (priv == NULL) continue;
memset(priv, 0, sizeof(plugin_data_t));
priv->job_handle = job_handle;
priv->job_params = job_params;
priv->send_tid = pthread_self();
priv->job_info.job_handle = _WJOBH_NONE;
priv->job_info.print_ifc = (ifc_print_job_t *) print_ifc_p;
priv->job_info.wprint_ifc = (ifc_wprint_t *) wprint_ifc_p;
priv->job_info.strip_height = job_params->strip_height;
priv->job_info.useragent = job_params->useragent;
sem_init(&priv->buffs_sem, 0, MAX_SEND_BUFFS);
switch (job_params->pcl_type) {
case PCLm:
priv->pcl_ifc = pclm_connect();
break;
case PCLPWG:
priv->pcl_ifc = pwg_connect();
break;
default:
break;
}
if (priv->pcl_ifc == NULL) {
LOGE("ERROR: cannot start PCL job, no ifc found");
continue;
}
priv->msgQ = priv->job_info.wprint_ifc->msgQCreate(
(MAX_SEND_BUFFS * 2), sizeof(msgQ_msg_t));
if (priv->msgQ == MSG_Q_INVALID_ID) continue;
if (_start_thread(priv) == ERROR) continue;
job_params->plugin_data = (void *) priv;
msg.id = MSG_START_JOB;
priv->job_info.wprint_ifc->msgQSend(
priv->msgQ, (char *) &msg, sizeof(msgQ_msg_t), NO_WAIT, MSG_Q_FIFO);
return OK;
} while (0);
_cleanup_plugin_data(priv);
return ERROR;
}
static status_t _print_page(wprint_job_params_t *job_params, const char *mime_type,
const char *pathname) {
wprint_image_info_t *image_info;
FILE *imgfile;
status_t result;
int num_rows, height, image_row;
int blank_data;
char *buff;
int i, buff_index, buff_size;
char *buff_pool[MAX_SEND_BUFFS];
int nbytes;
plugin_data_t *priv;
msgQ_msg_t msg;
int image_padding = PAD_PRINT;
if (job_params == NULL) return ERROR;
priv = (plugin_data_t *) job_params->plugin_data;
if (priv == NULL) return ERROR;
switch (job_params->pcl_type) {
case PCLm:
case PCLPWG:
image_padding = PAD_ALL;
break;
default:
break;
}
if (pathname == NULL) {
LOGE("_print_page(): cannot print file with NULL name");
msg.param.end_page.page = -1;
msg.param.end_page.count = 0;
result = ERROR;
} else if (strlen(pathname)) {
image_info = malloc(sizeof(wprint_image_info_t));
if (image_info == NULL) return ERROR;
imgfile = fopen(pathname, "r");
if (imgfile) {
LOGD("_print_page(): fopen succeeded on %s", pathname);
wprint_image_setup(image_info, mime_type, priv->job_info.wprint_ifc,
job_params->pixel_units, job_params->pdf_render_resolution);
wprint_image_init(image_info, pathname, job_params->page_num);
// get the image_info of the input file of specified MIME type
if ((result = wprint_image_get_info(imgfile, image_info)) == OK) {
wprint_rotation_t rotation = ROT_0;
if ((job_params->render_flags & RENDER_FLAG_PORTRAIT_MODE) != 0) {
LOGI("_print_page(): portrait mode");
rotation = ROT_0;
} else if ((job_params->render_flags & RENDER_FLAG_LANDSCAPE_MODE) != 0) {
LOGI("_print_page(): landscape mode");
rotation = ROT_90;
} else if (wprint_image_is_landscape(image_info) &&
((job_params->render_flags & RENDER_FLAG_AUTO_ROTATE) != 0)) {
LOGI("_print_page(): auto mode");
rotation = ROT_90;
}
if ((job_params->render_flags & RENDER_FLAG_CENTER_ON_ORIENTATION) != 0) {
job_params->render_flags &= ~(RENDER_FLAG_CENTER_HORIZONTAL |
RENDER_FLAG_CENTER_VERTICAL);
job_params->render_flags |= ((rotation == ROT_0) ? RENDER_FLAG_CENTER_HORIZONTAL
: RENDER_FLAG_CENTER_VERTICAL);
}
if ((job_params->duplex == DUPLEX_MODE_BOOK) &&
(job_params->page_backside) &&
((job_params->render_flags & RENDER_FLAG_ROTATE_BACK_PAGE) != 0) &&
((job_params->render_flags & RENDER_FLAG_BACK_PAGE_PREROTATED) == 0)) {
rotation = ((rotation == ROT_0) ? ROT_180 : ROT_270);
}
LOGI("_print_page(): rotation = %d", rotation);
wprint_image_set_output_properties(image_info, rotation,
job_params->printable_area_width, job_params->printable_area_height,
job_params->print_top_margin, job_params->print_left_margin,
job_params->print_right_margin, job_params->print_bottom_margin,
job_params->render_flags, job_params->strip_height, MAX_SEND_BUFFS,
image_padding);
// allocate memory for a stripe of data
for (i = 0; i < MAX_SEND_BUFFS; i++) {
buff_pool[i] = NULL;
}
blank_data = MAX_SEND_BUFFS;
buff_size = wprint_image_get_output_buff_size(image_info);
for (i = 0; i < MAX_SEND_BUFFS; i++) {
buff_pool[i] = malloc(buff_size);
if (buff_pool[i] == NULL) {
break;
}
memset(buff_pool[i], 0xff, buff_size);
}
if (i == MAX_SEND_BUFFS) {
msg.id = MSG_START_PAGE;
msg.param.start_page.extra_margin = ((job_params->duplex !=
DUPLEX_MODE_NONE) &&
((job_params->page_num & 0x1) == 0))
? job_params->page_bottom_margin : 0.0f;
msg.param.start_page.width = wprint_image_get_width(image_info);
msg.param.start_page.height = wprint_image_get_height(image_info);
priv->job_info.num_components = image_info->num_components;
priv->job_info.wprint_ifc->msgQSend(priv->msgQ, (char *) &msg,
sizeof(msgQ_msg_t), NO_WAIT, MSG_Q_FIFO);
msg.id = MSG_SEND;
msg.param.send.bytes_per_row = BYTES_PER_PIXEL(wprint_image_get_width(
image_info));
// send blank rows for any offset
buff_index = 0;
num_rows = wprint_image_get_height(image_info);
image_row = 0;
// decode and render each stripe into PCL3 raster format
while ((result != ERROR) && (num_rows > 0)) {
if (priv->pcl_ifc->canCancelMidPage() && job_params->cancelled) {
break;
}
sem_wait(&priv->buffs_sem);
buff = buff_pool[buff_index];
buff_index = ((buff_index + 1) % MAX_SEND_BUFFS);
height = MIN(num_rows, job_params->strip_height);
if (!job_params->cancelled) {
nbytes = wprint_image_decode_stripe(image_info, image_row, &height,
(unsigned char *) buff);
if (blank_data > 0) {
blank_data--;
}
} else if (blank_data < MAX_SEND_BUFFS) {
nbytes = buff_size;
memset(buff, 0xff, buff_size);
blank_data++;
}
if (nbytes > 0) {
msg.param.send.buffer = buff;
msg.param.send.start_row = image_row;
msg.param.send.num_rows = height;
result = priv->job_info.wprint_ifc->msgQSend(priv->msgQ, (char *) &msg,
sizeof(msgQ_msg_t), NO_WAIT, MSG_Q_FIFO);
if (result < 0) {
sem_post(&priv->buffs_sem);
}
image_row += height;
num_rows -= height;
} else {
sem_post(&priv->buffs_sem);
if (nbytes < 0) {
LOGE("_print_page(): ERROR: file appears to be corrupted");
result = CORRUPT;
}
break;
}
}
if ((result == OK) && job_params->cancelled) {
result = CANCELLED;
}
LOGI("_print_page(): sends done, result: %d", result);
// free the buffer and eject the page
msg.param.end_page.page = job_params->page_num;
LOGI("_print_page(): processed %d out of"
" %d rows of page # %d from %s to printer %s %s {%s}",
image_row, wprint_image_get_height(image_info),
job_params->page_num, pathname,
(job_params->last_page) ? "- last page" : "- ",
(job_params->cancelled) ? "- job cancelled"
: ".",
(result == OK) ? "OK" : "ERROR");
} else {
msg.param.end_page.page = -1;
result = ERROR;
LOGE("_print_page(): plugin_pcl cannot allocate memory for image stripe");
}
for (i = 0; i < MAX_SEND_BUFFS; i++) {
msg.param.end_page.buffers[i] = buff_pool[i];
}
msg.param.end_page.count = MAX_SEND_BUFFS;
} else {
msg.param.end_page.page = -1;
msg.param.end_page.count = 0;
result = CORRUPT;
LOGE("_print_page(): file does not appear to be valid");
}
// send the end page message
wprint_image_cleanup(image_info);
fclose(imgfile);
} else {
msg.param.end_page.page = -1;
msg.param.end_page.count = 0;
LOGE("_print_page(): could not open %s", pathname);
result = CORRUPT;
}
free(image_info);
} else {
LOGE("_print_page(): ERROR: filename was empty");
msg.param.end_page.page = -1;
msg.param.end_page.count = 0;
result = ERROR;
}
msg.id = MSG_END_PAGE;
priv->job_info.wprint_ifc->msgQSend(priv->msgQ, (char *) &msg, sizeof(msgQ_msg_t), NO_WAIT,
MSG_Q_FIFO);
return result;
}
/*
* Prints a blank page
*/
static int _print_blank_page(wJob_t job_handle, wprint_job_params_t *job_params) {
msgQ_msg_t msg;
plugin_data_t *priv;
if (job_params == NULL) return ERROR;
priv = (plugin_data_t *) job_params->plugin_data;
if (priv == NULL) return ERROR;
msg.id = MSG_END_PAGE;
msg.param.end_page.page = -1;
msg.param.end_page.count = 0;
priv->job_info.wprint_ifc->msgQSend(priv->msgQ, (char *) &msg, sizeof(msgQ_msg_t), NO_WAIT,
MSG_Q_FIFO);
return OK;
}
static int _end_job(wprint_job_params_t *job_params) {
if (job_params != NULL) {
_stop_thread((plugin_data_t *) job_params->plugin_data);
}
return OK;
}
wprint_plugin_t *libwprintplugin_pcl_reg(void) {
static const wprint_plugin_t _pcl_plugin = {.version = WPRINT_PLUGIN_VERSION(0),
.priority = PRIORITY_LOCAL, .get_mime_types = _get_mime_types,
.get_print_formats = _get_print_formats, .start_job = _start_job,
.print_page = _print_page, .print_blank_page = _print_blank_page, .end_job = _end_job,};
return ((wprint_plugin_t *) &_pcl_plugin);
}

View file

@ -0,0 +1,133 @@
/*
* Copyright (C) 2016 The Android Open Source Project
* Copyright (C) 2016 Mopria Alliance, Inc.
* Copyright (C) 2013 Hewlett-Packard Development Company, L.P.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include "ifc_print_job.h"
#include "wprint_debug.h"
#define TAG "plugin_pdf"
#define BUFF_SIZE 8192
extern int g_API_version;
typedef struct {
const ifc_wprint_t *wprint_ifc;
const ifc_print_job_t *print_ifc;
} plugin_data_t;
static const char *_mime_types[] = {
MIME_TYPE_PDF,
NULL};
static const char *_print_formats[] = {
PRINT_FORMAT_PDF,
NULL};
static const char **_get_mime_types(void) {
return _mime_types;
}
static const char **_get_print_formats(void) {
return _print_formats;
}
static int _start_job(wJob_t job_handle, const ifc_wprint_t *wprint_ifc_p,
const ifc_print_job_t *print_job_ifc_p,
wprint_job_params_t *job_params) {
plugin_data_t *priv;
if (job_params == NULL) return ERROR;
job_params->plugin_data = NULL;
if ((wprint_ifc_p == NULL) || (print_job_ifc_p == NULL)) return ERROR;
priv = (plugin_data_t *) malloc(sizeof(plugin_data_t));
priv->wprint_ifc = (ifc_wprint_t *) wprint_ifc_p;
priv->print_ifc = (ifc_print_job_t *) print_job_ifc_p;
job_params->plugin_data = (void *) priv;
return OK;
}
static int _print_page(wprint_job_params_t *job_params, const char *mime_type,
const char *pathname) {
plugin_data_t *priv;
int fd;
int result = OK;
int rbytes, wbytes, nbytes = 0;
char *buff;
if (job_params == NULL) return ERROR;
priv = (plugin_data_t *) job_params->plugin_data;
if (priv == NULL) return ERROR;
// open the PDF file and dump it to the socket
if (pathname && strlen(pathname)) {
buff = malloc(BUFF_SIZE);
if (buff == NULL) {
return ERROR;
}
fd = open(pathname, O_RDONLY);
if (fd != ERROR) {
rbytes = read(fd, buff, BUFF_SIZE);
while ((rbytes > 0) && !job_params->cancelled) {
wbytes = priv->print_ifc->send_data(priv->print_ifc, buff, rbytes);
if (wbytes == rbytes) {
nbytes += wbytes;
rbytes = read(fd, buff, BUFF_SIZE);
} else {
LOGE("ERROR: write() failed, %s", strerror(errno));
result = ERROR;
break;
}
}
LOGI("dumped %d bytes of %s to printer", nbytes, pathname);
close(fd);
}
free(buff);
}
if ((job_params->page_range != NULL) && (strcmp(job_params->page_range, "") != 0)) {
remove(pathname);
}
return result;
}
static int _end_job(wprint_job_params_t *job_params) {
if (job_params != NULL) {
if (job_params->plugin_data != NULL) {
free(job_params->plugin_data);
}
}
return OK;
}
wprint_plugin_t *libwprintplugin_pdf_reg(void) {
static const wprint_plugin_t _pdf_plugin = {.version = WPRINT_PLUGIN_VERSION(0),
.priority = PRIORITY_PASSTHRU, .get_mime_types = _get_mime_types,
.get_print_formats = _get_print_formats, .start_job = _start_job,
.print_page = _print_page, .print_blank_page = NULL, .end_job = _end_job,};
return ((wprint_plugin_t *) &_pdf_plugin);
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,244 @@
/*
* Copyright (C) 2016 The Android Open Source Project
* Copyright (C) 2016 Mopria Alliance, Inc.
* Copyright (C) 2013 Hewlett-Packard Development Company, L.P.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __WPRINT_IMAGE__
#define __WPRINT_IMAGE__
#include <stdio.h>
#include "mime_types.h"
#include "wprint_scaler.h"
#include "wprint_debug.h"
#include "ifc_wprint.h"
#ifdef __cplusplus
extern "C"
{
#endif
#define BYTES_PER_PIXEL(X) ((X)*3)
#define BITS_PER_CHANNEL 8
/*
* Rotations to apply while decoding
*/
typedef enum {
ROT_0 = 0,
ROT_90,
ROT_180,
ROT_270,
} wprint_rotation_t;
/*
* Location(s) for padding to be applied while decoding
*/
typedef enum {
PAD_TOP = (1 << 0),
PAD_LEFT = (1 << 1),
PAD_RIGHT = (1 << 2),
PAD_BOTTOM = (1 << 3),
} wprint_padding_t;
#define PAD_NONE (0)
#define PAD_PRINT (PAD_TOP | PAD_LEFT)
#define PAD_ALL (PAD_TOP | PAD_LEFT | PAD_RIGHT | PAD_BOTTOM)
#define __DEFINE_WPRINT_PLATFORM_TYPES__
#include "wprint_image_platform.h"
#undef __DEFINE_WPRINT_PLATFORM_TYPES__
/*
* Define an image which can be decoded into a stream
*/
typedef struct {
// file information
const char *mime_type;
FILE *imgfile;
// interfaces
const struct _image_decode_ifc_st *decode_ifc;
const ifc_wprint_t *wprint_ifc;
// image dimensions
unsigned int width;
unsigned int height;
unsigned int sampled_width;
unsigned int sampled_height;
// printable area information
unsigned int printable_width;
unsigned int printable_height;
unsigned int print_resolution;
unsigned int render_flags;
// output information
unsigned int output_width;
unsigned int output_height;
int num_components;
int pdf_render_resolution;
// memory optimization parameters
unsigned int stripe_height;
unsigned int concurrent_stripes;
unsigned int output_rows;
// scaling parameters
unsigned int scaled_sample_size;
unsigned int scaled_width;
unsigned int scaled_height;
int unscaled_start_row;
int unscaled_end_row;
unsigned int unscaled_rows_needed;
unsigned char *unscaled_rows;
unsigned int mixed_memory_needed;
unsigned char *mixed_memory;
unsigned char scaling_needed;
scaler_config_t scaler_config;
// padding parameters
unsigned int output_padding_top;
unsigned int output_padding_bottom;
unsigned int output_padding_left;
unsigned int output_padding_right;
unsigned int padding_options;
// decoding information
wprint_rotation_t rotation;
unsigned int row_offset;
unsigned int col_offset;
int swath_start;
int rows_cached;
unsigned char **output_cache;
int output_swath_start;
decoder_data_t decoder_data;
} wprint_image_info_t;
/*
* Defines an interface for decoding images
*/
typedef struct _image_decode_ifc_st {
/*
* Prepare for decoding of the specified image
*/
void (*init)(wprint_image_info_t *image_info);
/*
* Prepare for decoding of an image
*/
status_t (*get_hdr)(wprint_image_info_t *image_info);
/*
* Supply image data at the specified row
*/
unsigned char *(*decode_row)(wprint_image_info_t *, int row);
/*
* Release all resources related to the image
*/
status_t (*cleanup)(wprint_image_info_t *image_info);
/*
* Return OK if subsampling is supported by this decoder
*/
status_t (*supports_subsampling)(wprint_image_info_t *image_info);
/*
* Return resolution in DPI
*/
int (*native_units)(wprint_image_info_t *image_info);
} image_decode_ifc_t;
/*
* Return the appropriate decoding object corresponding to the image
*/
const image_decode_ifc_t *wprint_image_get_decode_ifc(wprint_image_info_t *image_info);
/*
* Initializes image_info with supplied parameters
*/
void wprint_image_setup(wprint_image_info_t *image_info, const char *mime_type,
const ifc_wprint_t *wprint_ifc, unsigned int output_resolution, int pdf_render_resolution);
/*
* Open an initialized image from a file
*/
status_t wprint_image_get_info(FILE *imgfile, wprint_image_info_t *image_info);
/*
* Configure image_info parameters as supplied
*/
status_t wprint_image_set_output_properties(wprint_image_info_t *image_info,
wprint_rotation_t rotation, unsigned int printable_width, unsigned int printable_height,
unsigned int top_margin, unsigned int left_margin, unsigned int right_margin,
unsigned int bottom_margin, unsigned int render_flags, unsigned int max_decode_stripe,
unsigned int concurrent_stripes, unsigned int padding_options);
/*
* Return true if the image is wider than it is high (landscape orientation)
*/
bool wprint_image_is_landscape(wprint_image_info_t *image_info);
/*
* Return the size required to render the image
*/
int wprint_image_get_output_buff_size(wprint_image_info_t *image_info);
/*
* Return the full image width, including any padding
*/
int wprint_image_get_width(wprint_image_info_t *image_info);
/*
* Return the full image height, including any padding
*/
int wprint_image_get_height(wprint_image_info_t *image_info);
/*
* Decode a single stripe of data into rgb_pixels, storing height rendered and returning
* bytes processed or 0/negative on error.
*/
int wprint_image_decode_stripe(wprint_image_info_t *image_info, int start_row, int *height,
unsigned char *rgb_pixels);
/*
* Compute and allocate memory in preparation for decoding row data, returning the number of rows
*/
int wprint_image_compute_rows_to_cache(wprint_image_info_t *image_info);
/*
* Return the current number of cached rows
*/
int wprint_image_input_rows_cached(wprint_image_info_t *image_info);
/*
* Free all image resources
*/
void wprint_image_cleanup(wprint_image_info_t *image_info);
#ifdef __cplusplus
}
#endif
#define __DEFINE_WPRINT_PLATFORM_METHODS__
#include "wprint_image_platform.h"
#undef __DEFINE_WPRINT_PLATFORM_METHODS__
#endif // __WPRINT_IMAGE__

View file

@ -0,0 +1,46 @@
/*
* Copyright (C) 2016 The Android Open Source Project
* Copyright (C) 2016 Mopria Alliance, Inc.
* Copyright (C) 2013 Hewlett-Packard Development Company, L.P.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <string.h>
#include "wprint_image.h"
#include "wprint_mupdf.h"
const image_decode_ifc_t *wprint_image_get_decode_ifc(wprint_image_info_t *image_info) {
if ((image_info != NULL) && (image_info->mime_type != NULL)) {
// Only PDF will be provided by upper layer
if (strcasecmp(image_info->mime_type, MIME_TYPE_PDF) == 0) {
return wprint_mupdf_decode_ifc;
}
}
return NULL;
}
int wprint_image_init(wprint_image_info_t *image_info, const char *image_url, const int page_num) {
if (image_info == NULL) return ERROR;
image_info->decoder_data.urlPath = image_url;
image_info->decoder_data.page = page_num;
const image_decode_ifc_t *decode_ifc = wprint_image_get_decode_ifc(image_info);
if ((decode_ifc != NULL) && (decode_ifc->init != NULL)) {
decode_ifc->init(image_info);
image_info->decode_ifc = decode_ifc;
return OK;
}
return ERROR;
}

View file

@ -0,0 +1,61 @@
/*
* Copyright (C) 2016 The Android Open Source Project
* Copyright (C) 2016 Mopria Alliance, Inc.
* Copyright (C) 2013 Hewlett-Packard Development Company, L.P.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifdef __cplusplus
extern "C"
{
#endif
#ifdef __DEFINE_WPRINT_PLATFORM_TYPES__
#include <setjmp.h>
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
/*
* Define general data used by image decoders
*/
typedef struct {
const char *urlPath;
unsigned int page;
// PDF data
struct {
void *bitmap_ptr;
void *fz_context_ptr;
void *fz_doc_ptr;
void *fz_page_ptr;
void *fz_pixmap_ptr;
} pdf_info;
} decoder_data_t;
#endif // __DEFINE_WPRINT_PLATFORM_TYPES__
#ifdef __DEFINE_WPRINT_PLATFORM_METHODS__
int wprint_image_init(wprint_image_info_t *image_info, const char *urlPath, int pageNum);
#endif // __DEFINE_WPRINT_PLATFORM_METHODS__
#ifdef __cplusplus
}
#endif

View file

@ -0,0 +1,139 @@
/*
* Copyright (C) 2016 The Android Open Source Project
* Copyright (C) 2016 Mopria Alliance, Inc.
* Copyright (C) 2013 Hewlett-Packard Development Company, L.P.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <time.h>
#include "wprint_mupdf.h"
#include "lib_wprint.h"
#include "ipphelper.h"
#define TAG "wprint_mupdf"
#define MUPDF_DEFAULT_RESOLUTION 72
#define RGB_NUMBER_PIXELS_NUM_COMPONENTS 3
static pdf_render_ifc_t *pdf_render;
static void _mupdf_init(wprint_image_info_t *image_info) {
pdf_render = create_pdf_render_ifc();
}
/* Return current clock time in milliseconds */
static long get_millis() {
struct timespec now;
clock_gettime(CLOCK_MONOTONIC, &now);
return (long) (((int64_t) now.tv_sec * 1000000000LL + now.tv_nsec) / 1000000);
}
static status_t _mupdf_get_hdr(wprint_image_info_t *image_info) {
double pageWidth, pageHeight;
float zoom;
unsigned int imageWidth;
unsigned int imageHeight;
int size;
char *rawBuffer;
status_t result;
int pages;
pages = pdf_render->openDocument(pdf_render, image_info->decoder_data.urlPath);
if (pages < 1) return ERROR;
result = pdf_render->getPageAttributes(pdf_render, image_info->decoder_data.page, &pageWidth,
&pageHeight);
if (result != OK) return result;
const float POINTS_PER_INCH = MUPDF_DEFAULT_RESOLUTION;
zoom = (image_info->pdf_render_resolution) / POINTS_PER_INCH;
imageWidth = (unsigned int) (pageWidth * zoom);
imageHeight = (unsigned int) (pageHeight * zoom);
image_info->width = imageWidth;
image_info->height = imageHeight;
size = imageWidth * imageHeight * 3;
rawBuffer = (char *) malloc((size_t) size);
if (!rawBuffer) return ERROR;
LOGI("Render page=%d w=%.0f h=%.0f res=%d zoom=%0.2f size=%d", image_info->decoder_data.page,
pageWidth, pageHeight, image_info->pdf_render_resolution, zoom, size);
long now = get_millis();
result = pdf_render->renderPageStripe(pdf_render, image_info->decoder_data.page, imageWidth,
imageHeight, zoom, rawBuffer);
if (result != OK) {
free(rawBuffer);
return result;
}
LOGI("Render complete in %ld ms", get_millis() - now);
image_info->decoder_data.pdf_info.fz_pixmap_ptr = rawBuffer;
image_info->decoder_data.pdf_info.bitmap_ptr = malloc(
image_info->width * RGB_NUMBER_PIXELS_NUM_COMPONENTS);
image_info->num_components = RGB_NUMBER_PIXELS_NUM_COMPONENTS;
return OK;
}
static unsigned char *_mupdf_decode_row(wprint_image_info_t *image_info, int row) {
unsigned char *rgbPixels = 0;
if (image_info->swath_start == -1) {
wprint_image_compute_rows_to_cache(image_info);
}
image_info->swath_start = row;
if (NULL != image_info->decoder_data.pdf_info.fz_pixmap_ptr) {
rgbPixels = (unsigned char *) image_info->decoder_data.pdf_info.bitmap_ptr;
memcpy(rgbPixels, (char *) (image_info->decoder_data.pdf_info.fz_pixmap_ptr) +
row * image_info->width * RGB_NUMBER_PIXELS_NUM_COMPONENTS,
image_info->width * RGB_NUMBER_PIXELS_NUM_COMPONENTS);
}
return rgbPixels;
}
static status_t _mupdf_cleanup(wprint_image_info_t *image_info) {
LOGD("MUPDF: _mupdf_cleanup(): Enter");
if (NULL != image_info->decoder_data.pdf_info.fz_pixmap_ptr) {
free(image_info->decoder_data.pdf_info.fz_pixmap_ptr);
image_info->decoder_data.pdf_info.fz_pixmap_ptr = NULL;
}
if (image_info->decoder_data.pdf_info.bitmap_ptr != NULL) {
free(image_info->decoder_data.pdf_info.bitmap_ptr);
}
pdf_render->destroy(pdf_render);
pdf_render = NULL;
return OK;
}
static status_t _mupdf_supports_subsampling(wprint_image_info_t *image_info) {
LOGI("MUPDF: _mupdf_supports_subsampling(): Enter");
return ERROR;
}
static int _mupdf_native_units(wprint_image_info_t *image_info) {
return image_info->pdf_render_resolution;
}
static const image_decode_ifc_t _mupdf_decode_ifc = {&_mupdf_init, &_mupdf_get_hdr,
&_mupdf_decode_row, &_mupdf_cleanup,
&_mupdf_supports_subsampling,
&_mupdf_native_units,};
const image_decode_ifc_t *wprint_mupdf_decode_ifc = &_mupdf_decode_ifc;

View file

@ -0,0 +1,75 @@
/*
* Copyright (C) 2016 The Android Open Source Project
* Copyright (C) 2016 Mopria Alliance, Inc.
* Copyright (C) 2013 Hewlett-Packard Development Company, L.P.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __WPRINT_MUPDF__
#define __WPRINT_MUPDF__
#include <jni.h>
#include "wprint_image.h"
extern const image_decode_ifc_t *wprint_mupdf_decode_ifc;
typedef struct pdf_render_ifc pdf_render_ifc_t;
/*
* Defines an interface for inspecting and rendering PDFs. Note: all methods must be called
* from the same thread that created the interface.
*/
struct pdf_render_ifc {
/*
* Return the page count for the specified file, or 0 on failure.
*/
int (*openDocument)(pdf_render_ifc_t *self, const char *fileName);
/*
* Render a page (1-based) at the specified zoom level into the supplied output buffer. The
* buffer must be large enough to contain width * height * 3 (RGB). Returns success.
*/
status_t (*renderPageStripe)(pdf_render_ifc_t *self, int page, int width,
int height, float zoom, char *buffer);
/*
* Determine the width and height of a particular page (1-based), returning success.
*/
status_t (*getPageAttributes)(pdf_render_ifc_t *self, int page,
double *width, double *height);
/*
* Finally release all resources related to this interface
*/
void (*destroy)(pdf_render_ifc_t *self);
};
/*
* One-time initialization of pdf_render module. pdf_render_deinit must be called later to
* free resources.
*/
void pdf_render_init(JNIEnv *env);
/*
* Deinitialize the pdf_render module (at shutdown)
*/
void pdf_render_deinit(JNIEnv *env);
/*
* Allocate and return a thread-specific pdf_render interface. Caller must eventually
* call destroy on this instance.
*/
pdf_render_ifc_t *create_pdf_render_ifc();
#endif // __WPRINT_MUPDF__

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,113 @@
/*
* Copyright (C) 2016 The Android Open Source Project
* Copyright (C) 2016 Mopria Alliance, Inc.
* Copyright (C) 2013 Hewlett-Packard Development Company, L.P.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef LIB_PHOTO_SCALER_H
#define LIB_PHOTO_SCALER_H
#ifdef __cplusplus
extern "C" {
#endif
#include "wtypes.h"
typedef unsigned char bool_t;
/*
* A 64-bit floating point value
*/
typedef struct float64_s {
uint32 decimal;
uint32 fraction;
} float64_t;
/*
* Mode selected for a scaling operation
*/
typedef enum scaler_modes_e {
PSCALER_SCALE_UP = 1,
PSCALER_SCALE_DOWN = 2,
PSCALER_SCALE_MIXED_XUP = 5,
PSCALER_SCALE_MIXED_YUP = 7,
PSCALER_SCALE_MODE_INVALID
} scaler_mode_t;
/*
* Context structure for a scaling operation
*/
typedef struct scaler_config_s {
uint16 iSrcWidth; // input width (x-axis dimension)
uint16 iSrcHeight; // input height (y-axis dimension)
uint16 iOutWidth; // output width (x-axis dimension)
uint16 iOutHeight; // output height (y-axis dimension)
uint8 *pSrcBuf; // input buffers [plane]
uint16 iSrcBufWidth; // input buffer width (typically source width)
uint8 *pOutBuf; // output buffers [plane]
uint16 iOutBufWidth; // output buffer width
uint8 *pTmpBuf; // mixed axis temp buffer
float64_t fSrcStartRow; // first input row as a float
uint16 iSrcStartRow; // first input row of this slice
uint16 iSrcEndRow; // last input row of this slice
uint16 iOutStartRow; // first output row of this slice
uint16 iOutEndRow; // last output row of this slice
float64_t fSrcStartColumn; // first input column as a float
uint16 iOutStartColumn; // first output column of this slice
float64_t fXfactor; // x_factor_int & x_factor_fract
float64_t fXfactorInv; // x_factor_inv_int & x_factor_inv_fract
float64_t fYfactor; // y_factor_int & y_factor_fract
float64_t fYfactorInv; // y_factor_inv_int & y_factor_inv_fract
scaler_mode_t scaleMode; // scale mode for the current image
} scaler_config_t;
/*
* Called once per job to initialize pscaler_config for specified input/output sizes
*/
extern void scaler_make_image_scaler_tables(uint16 image_input_width, uint16 image_input_buf_width,
uint16 image_output_width, uint16 image_output_buf_width, uint16 image_input_height,
uint16 image_output_height, scaler_config_t *pscaler_config);
/*
* Called once to configure a single image stripe/slice. Must be called after
* scaler_make_image_scaler_tables.
*/
extern void scaler_calculate_scaling_rows(uint16 start_output_row_number,
uint16 end_output_row_number, void *tables_ptr, uint16 *start_input_row_number,
uint16 *end_input_row_number, uint16 *num_output_rows_generated,
uint16 *num_rows_offset_to_start_output_row,
uint32 *mixed_axis_temp_buffer_size_needed);
/*
* Called after each call to scaler_calculate_scaling_rows to produce scaled output
*/
extern void scaler_scale_image_data(uint8 *input_plane, void *tables_ptr,
uint8 *scaled_output_plane, uint8 *temp_buffer_for_mixed_axis_scaling);
#ifdef __cplusplus
}
#endif
#endif // LIB_PHOTO_SCALER_H