upload android base code part8
This commit is contained in:
parent
841ae54672
commit
5425409085
57075 changed files with 9846578 additions and 0 deletions
|
@ -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_
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
@ -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__
|
|
@ -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);
|
||||
}
|
|
@ -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__
|
|
@ -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);
|
||||
}
|
|
@ -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__
|
|
@ -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);
|
||||
}
|
|
@ -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_
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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
|
@ -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__
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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;
|
|
@ -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
|
@ -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
|
Loading…
Add table
Add a link
Reference in a new issue