blob: ac411dc803d6db760f968ed5ff9b75c36769c523 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.
*/
/**
* @author Aleksei V. Ivaschenko
*/
/*
* This file contains implementations of native methods of
* GDIClient and PSInterpreter.
* Defines the entry point for the DLL application.
*/
#include "print.h"
#include "org_apache_harmony_x_print_GDIClient.h"
#include "org_apache_harmony_x_print_PSInterpreter.h"
#include "org_apache_harmony_x_print_Win32PrintServiceProvider.h"
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
return TRUE;
}
//----------------- ServiceFinder functions -----------------------------------
/*
* TODO: support older systems.
*/
char * GetDefaultPrintService() {
char *buffer = new char[MAX_PATH];
DWORD buffer_size = MAX_PATH;
if (GetDefaultPrinter(buffer, &buffer_size)) {
return buffer;
} else {
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
delete[] buffer;
buffer = new char[buffer_size];
if (GetDefaultPrinter(buffer, &buffer_size)) {
return buffer;
}
}
}
return NULL;
}
char ** GetPrintServices(DWORD *count) {
unsigned char * pPrinterEnum = NULL;
DWORD cbNeeded, cReturned;
if (!EnumPrinters(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS,
NULL, 4, pPrinterEnum, 0, &cbNeeded, &cReturned)) {
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
pPrinterEnum = new unsigned char[cbNeeded];
if (EnumPrinters(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS,
NULL, 4, pPrinterEnum, cbNeeded, &cbNeeded, &cReturned)) {
PRINTER_INFO_4 *printers = (PRINTER_INFO_4 *)pPrinterEnum;
char ** names = new char *[cReturned];
for (DWORD i = 0; i < cReturned; i++) {
names[i] = new char[strlen(printers[i].pPrinterName) + 1];
strcpy(names[i], printers[i].pPrinterName);
}
*count = cReturned;
return names;
}
}
}
return NULL;
}
JNIEXPORT jobjectArray JNICALL Java_org_apache_harmony_x_print_Win32PrintServiceProvider_findPrintServices
(JNIEnv *env, jclass owner) {
jobjectArray result = NULL;
DWORD services = 0;
char ** names = GetPrintServices(&services);
if (services > 0) {
jclass jstring_class = env->FindClass("java/lang/String");
result = env->NewObjectArray(services, jstring_class, jstring());
for (DWORD i = 0; i < services; i++) {
jstring name = env->NewStringUTF(names[i]);
env->SetObjectArrayElement(result, i, name);
env->DeleteLocalRef(name);
}
}
return result;
}
JNIEXPORT jstring JNICALL Java_org_apache_harmony_x_print_Win32PrintServiceProvider_findDefaultPrintService
(JNIEnv *env, jclass owner) {
char *serviceUTF = GetDefaultPrintService();
jstring service = NULL;
if (serviceUTF != NULL) {
service = env->NewStringUTF(serviceUTF);
delete[] serviceUTF;
}
return service;
}
//----------------- PrintService flavors --------------------------------------
JNIEXPORT jboolean JNICALL Java_org_apache_harmony_x_print_GDIClient_checkPostScript
(JNIEnv *env, jclass owner, jstring printerName) {
const char *printer = env->GetStringUTFChars(printerName, 0);
jboolean res = JNI_FALSE;
HDC prndc = CreateDC(NULL, printer, NULL, NULL);
if (prndc != NULL) {
DWORD esc = POSTSCRIPT_PASSTHROUGH;
if (ExtEscape(prndc, QUERYESCSUPPORT, sizeof(esc), (LPCSTR)&esc, 0, NULL) != 0) {
return JNI_TRUE;
}
esc = GETTECHNOLOGY;
if (ExtEscape(prndc, QUERYESCSUPPORT, sizeof(esc), (LPCSTR)&esc, 0, NULL) != 0) {
char *tech = new char[MAX_PATH + 1];
if (ExtEscape(prndc, esc, 0, NULL, MAX_PATH, tech) > 0) {
char *lower = strlwr(tech);
if (strstr(lower, "postscript") != NULL) {
return JNI_TRUE;
}
}
}
}
DeleteDC(prndc);
return res;
}
//----------------- PrintService attribute functions --------------------------
PRINTER_INFO_2 *GetPrinterInfo(const char *name) {
PRINTER_INFO_2 *result = NULL;
char *editableName = new char[strlen(name) + 1];
strcpy(editableName, name);
HANDLE hPrinter;
if (OpenPrinter(editableName, &hPrinter, NULL)) {
unsigned char *buffer = NULL;
DWORD cbNeeded;
if (!GetPrinter(hPrinter, 2, buffer, 0, &cbNeeded)) {
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
buffer = new unsigned char[cbNeeded];
if (GetPrinter(hPrinter, 2, buffer, cbNeeded, &cbNeeded)) {
result = (PRINTER_INFO_2 *)buffer;
}
}
}
}
delete[] editableName;
return result;
}
JNIEXPORT jboolean JNICALL Java_org_apache_harmony_x_print_GDIClient_getColorSupported
(JNIEnv *env, jclass owner, jstring printerName) {
const char *name = env->GetStringUTFChars(printerName, 0);
jboolean result = JNI_FALSE;
PRINTER_INFO_2 *info = GetPrinterInfo(name);
if (info != NULL) {
if (DeviceCapabilities(name, info->pPortName, DC_COLORDEVICE, NULL, NULL) == 1) {
result = JNI_TRUE;
}
free(info);
}
return result;
}
JNIEXPORT jint JNICALL Java_org_apache_harmony_x_print_GDIClient_getPagesPerMinute
(JNIEnv *env, jclass owner, jstring printerName) {
const char *name = env->GetStringUTFChars(printerName, 0);
jint result = 0;
PRINTER_INFO_2 *info = GetPrinterInfo(name);
if (info != NULL) {
info->pDevMode->dmColor = DMCOLOR_MONOCHROME;
result = DeviceCapabilities(name, info->pPortName, DC_PRINTRATEPPM, NULL, info->pDevMode);
free(info);
}
return result;
}
JNIEXPORT jint JNICALL Java_org_apache_harmony_x_print_GDIClient_getPagesPerMinuteColor
(JNIEnv *env, jclass owner, jstring printerName) {
const char *name = env->GetStringUTFChars(printerName, 0);
jint result = 0;
PRINTER_INFO_2 *info = GetPrinterInfo(name);
if (info != NULL) {
info->pDevMode->dmColor = DMCOLOR_COLOR;
result = DeviceCapabilities(name, info->pPortName, DC_PRINTRATEPPM, NULL, info->pDevMode);
free(info);
}
return result;
}
JNIEXPORT jint JNICALL Java_org_apache_harmony_x_print_GDIClient_getPrinterIsAcceptingJobs
(JNIEnv *env, jclass owner, jstring printerName) {
const char *name = env->GetStringUTFChars(printerName, 0);
jint result = -1;
PRINTER_INFO_2 *info = GetPrinterInfo(name);
if (info != NULL) {
if (info->Status & (PRINTER_STATUS_ERROR |
PRINTER_STATUS_NO_TONER |
PRINTER_STATUS_NOT_AVAILABLE |
PRINTER_STATUS_OFFLINE |
PRINTER_STATUS_OUT_OF_MEMORY |
PRINTER_STATUS_OUTPUT_BIN_FULL |
PRINTER_STATUS_PAPER_JAM |
PRINTER_STATUS_PAGE_PUNT |
PRINTER_STATUS_PAPER_OUT |
PRINTER_STATUS_PAPER_PROBLEM |
PRINTER_STATUS_PAUSED |
PRINTER_STATUS_PENDING_DELETION |
PRINTER_STATUS_USER_INTERVENTION)) {
result = 0;
} else {
result = 1;
}
free(info);
}
return result;
}
JNIEXPORT jstring JNICALL Java_org_apache_harmony_x_print_GDIClient_getPrinterLocation
(JNIEnv *env, jclass owner, jstring printerName) {
const char *name = env->GetStringUTFChars(printerName, 0);
jstring result = NULL;
PRINTER_INFO_2 *info = GetPrinterInfo(name);
if (info != NULL) {
if (info->pLocation != NULL && strcmp(info->pLocation, "") != 0) {
result = env->NewStringUTF(info->pLocation);
}
free(info);
}
return result;
}
JNIEXPORT jint JNICALL Java_org_apache_harmony_x_print_GDIClient_getQueuedJobCount
(JNIEnv *env, jclass owner, jstring printerName) {
const char *name = env->GetStringUTFChars(printerName, 0);
jint result = -1;
PRINTER_INFO_2 *info = GetPrinterInfo(name);
if (info != NULL) {
result = info->cJobs;
free(info);
}
return result;
}
//----------------- Print request attribute functions -------------------------
JNIEXPORT jint JNICALL Java_org_apache_harmony_x_print_GDIClient_getCopiesSupported
(JNIEnv *env, jclass owner, jstring printerName) {
const char *name = env->GetStringUTFChars(printerName, 0);
jint result = 0;
PRINTER_INFO_2 *info = GetPrinterInfo(name);
if (info != NULL) {
result = DeviceCapabilities(name, info->pPortName, DC_COPIES, NULL, NULL);
free(info);
}
return result;
}
JNIEXPORT jboolean JNICALL Java_org_apache_harmony_x_print_GDIClient_getSidesSupported
(JNIEnv *env, jclass owner, jstring printerName) {
const char *name = env->GetStringUTFChars(printerName, 0);
jboolean result = JNI_FALSE;
PRINTER_INFO_2 *info = GetPrinterInfo(name);
if (info != NULL) {
if (DeviceCapabilities(name, info->pPortName, DC_DUPLEX, NULL, NULL) == 1) {
result = JNI_TRUE;
}
free(info);
}
return result;
}
JNIEXPORT jobjectArray JNICALL Java_org_apache_harmony_x_print_GDIClient_getMediaSizesSupported
(JNIEnv *env, jclass owner, jstring printerName) {
const char *name = env->GetStringUTFChars(printerName, 0);
jobjectArray result = NULL;
PRINTER_INFO_2 *info = GetPrinterInfo(name);
if (info != NULL) {
int numSizes = DeviceCapabilities(name, info->pPortName, DC_PAPERSIZE, NULL, NULL);
if (numSizes > 0) {
POINT *sizes = new POINT[numSizes];
int numSizes = DeviceCapabilities(name, info->pPortName, DC_PAPERSIZE, (LPSTR)sizes, NULL);
if (numSizes > 0) {
jclass IntArrayClass = env->FindClass("[I");
result = env->NewObjectArray(numSizes, IntArrayClass, NULL);
for (int i = 0; i < numSizes; i++) {
jintArray size = env->NewIntArray(2);
int *nativeArray = new int[2];
nativeArray[0] = sizes[i].x;
nativeArray[1] = sizes[i].y;
env->SetIntArrayRegion(size, 0, 2, (jint *)nativeArray);
env->SetObjectArrayElement(result, i, size);
}
}
}
#ifdef PRINTING_DEBUG
int count = DeviceCapabilities(name, info->pPortName, DC_PAPERS, NULL, NULL);
if( count > 0 ) {
printf("\n\n");
WORD *papers = new WORD[count];
count = DeviceCapabilities(name, info->pPortName, DC_PAPERS, (LPSTR)papers, NULL);
printf("Found %d paper types.\n", count);
for (int i = 0; i < count; i++) {
printf("%d: %d\n", i+1, papers[i]);
}
delete [] papers;
}
int cnames = DeviceCapabilities(name, info->pPortName, DC_PAPERNAMES, NULL, NULL);
if( cnames > 0 ) {
printf("\n\n");
char (*papernames)[64] = new char[cnames][64];
cnames = DeviceCapabilities(name, info->pPortName, DC_PAPERNAMES, (LPSTR)papernames, NULL);
printf("Found %d paper names.\n", cnames);
for (int i = 0; i < cnames; i++) {
printf("%d: %s\n", i+1, papernames[i]);
}
delete [] papernames;
}
#endif /* PRINTING_DEBUG */
free(info);
}
return result;
}
JNIEXPORT jobjectArray JNICALL Java_org_apache_harmony_x_print_GDIClient_getMediaNames
(JNIEnv *env, jclass owner, jstring printerName) {
const char *name = env->GetStringUTFChars(printerName, 0);
jobjectArray result = NULL;
PRINTER_INFO_2 *info = GetPrinterInfo(name);
if (info != NULL) {
int numNamesFirst = DeviceCapabilities(name, info->pPortName, DC_PAPERNAMES, NULL, NULL);
if (numNamesFirst > 0) {
char *buffer = new char[65 * numNamesFirst];
int numNames = DeviceCapabilities(name, info->pPortName, DC_PAPERNAMES, (LPSTR)buffer, NULL);
if (numNames == numNamesFirst) {
jclass jstring_class = env->FindClass("java/lang/String");
result = env->NewObjectArray(numNames, jstring_class, jstring());
for (int i = 0; i < numNames; i++) {
char *name = buffer + i*64;
jstring jname = env->NewStringUTF(name);
env->SetObjectArrayElement(result, i, jname);
env->DeleteLocalRef(jname);
}
}
delete[] buffer;
}
free(info);
}
return result;
}
JNIEXPORT jintArray JNICALL Java_org_apache_harmony_x_print_GDIClient_getMediaIDs
(JNIEnv *env, jclass owner, jstring printerName) {
const char *name = env->GetStringUTFChars(printerName, 0);
jintArray result = NULL;
PRINTER_INFO_2 *info = GetPrinterInfo(name);
if (info != NULL) {
int numPapersFirst = DeviceCapabilities(name, info->pPortName, DC_PAPERS, NULL, NULL);
if (numPapersFirst > 0) {
WORD *ids = new WORD[numPapersFirst];
int numPapers = DeviceCapabilities(name, info->pPortName, DC_PAPERS, (LPSTR)ids, NULL);
if (numPapers == numPapersFirst) {
result = env->NewIntArray(numPapers);
int *intIDs = new int[numPapers];
for (int i = 0; i < numPapers; i++) {
intIDs[i] = (int)ids[i];
}
env->SetIntArrayRegion(result, 0, numPapers, (jint *)intIDs);
delete[] intIDs;
}
delete[] ids;
}
free(info);
}
return result;
}
JNIEXPORT jboolean JNICALL Java_org_apache_harmony_x_print_GDIClient_getCollateSupported
(JNIEnv *env, jclass owner, jstring printerName) {
const char *name = env->GetStringUTFChars(printerName, 0);
jboolean result = JNI_FALSE;
PRINTER_INFO_2 *info = GetPrinterInfo(name);
if (info != NULL) {
if (DeviceCapabilities(name, info->pPortName, DC_COLLATE, NULL, NULL) == 1) {
result = JNI_TRUE;
}
free(info);
}
return result;
}
JNIEXPORT jintArray JNICALL Java_org_apache_harmony_x_print_GDIClient_getResolutionsSupported
(JNIEnv *env, jclass owner, jstring printerName) {
const char *name = env->GetStringUTFChars(printerName, 0);
jintArray resolutions = NULL;
PRINTER_INFO_2 *info = GetPrinterInfo(name);
if (info != NULL) {
int count = DeviceCapabilities(name, info->pPortName, DC_ENUMRESOLUTIONS, NULL, NULL);
if (count > 0) {
LONG *nativeArray = new LONG[count * 2];
resolutions = env->NewIntArray(count * 2);
if (DeviceCapabilities(name, info->pPortName, DC_ENUMRESOLUTIONS, (LPSTR)nativeArray, NULL) > 0) {
jint *intArray = new jint[count * 2];
for (int i = 0; i < count * 2; i++) {
intArray[i] = (jint)((int)nativeArray[i]);
}
env->SetIntArrayRegion(resolutions, 0, count * 2, intArray);
delete[] intArray;
}
delete[] nativeArray;
}
free(info);
}
return resolutions;
}
JNIEXPORT jboolean JNICALL Java_org_apache_harmony_x_print_GDIClient_getOrientationSupported
(JNIEnv *env, jclass owner, jstring printerName) {
const char *name = env->GetStringUTFChars(printerName, 0);
jboolean result = JNI_FALSE;
PRINTER_INFO_2 *info = GetPrinterInfo(name);
if (info != NULL) {
int orientation = DeviceCapabilities(name, info->pPortName, DC_ORIENTATION, NULL, NULL);
if (orientation == 0 || orientation == 90 || orientation == 270) {
result = JNI_TRUE;
}
free(info);
}
return result;
}
//----------------- Common DocPrintJob and PS interpreter structures ----------
#define ATTRIBUTE_UNION_SIZE 8
typedef struct _PrintRequestAttributes {
int Copies;
int Sides;
int PaperID;
int Collate;
int Chromaticity;
int Orientation;
int XResolution;
int YResolution;
} PrintRequestAttributes;
typedef union _AttributesUnion {
int numbers[ATTRIBUTE_UNION_SIZE];
PrintRequestAttributes fields;
} AttributesUnion;
//----------------- DocPrintJob functions -------------------------------------
#ifdef PRINTING_DEBUG
FILE *file = NULL;
#endif /* PRINTING_DEBUG */
JNIEXPORT jint JNICALL Java_org_apache_harmony_x_print_GDIClient_startDocPrinter
(JNIEnv *env, jclass owner, jstring printerName, jintArray printAttributes, jstring jobName, jstring destination) {
const char *printer = env->GetStringUTFChars(printerName, 0);
const char *jn = env->GetStringUTFChars(jobName, 0);
char *jname = new char[strlen(jn) + 1];
char *fname = NULL;
strcpy(jname, jn);
if (destination != NULL) {
const char *fn = env->GetStringUTFChars(destination, 0);
fname = new char[strlen(fn) + 1];
strcpy(fname, fn);
}
AttributesUnion attributes;
jboolean isCopy = JNI_FALSE;
int *numbers = (int *)env->GetIntArrayElements(printAttributes, &isCopy);
for (int i = 0; i < ATTRIBUTE_UNION_SIZE; i++) {
attributes.numbers[i] = numbers[i];
}
jint res = 0;
HANDLE hPrinter = NULL;
if (OpenPrinter((LPTSTR)printer, &hPrinter, NULL) != 0) {
DOC_INFO_1 dinfo;
dinfo.pDocName = jname;
dinfo.pDatatype = "RAW";
dinfo.pOutputFile = fname;
DEVMODE *pDevMode = NULL;
int size = DocumentProperties(NULL, hPrinter, NULL, pDevMode, NULL, 0);
pDevMode = (DEVMODE *)malloc(size);
// if (DocumentProperties(NULL, hPrinter, NULL, pDevMode, NULL, DM_PROMPT) == IDOK) {
if (DocumentProperties(NULL, hPrinter, NULL, pDevMode, NULL, DM_OUT_BUFFER) == IDOK) {
#ifdef PRINTING_DEBUG
printf("DEVMODE received successfuly!\n");
#endif /* PRINTING_DEBUG */
if (attributes.fields.Copies > 0) {
pDevMode->dmCopies = (short)attributes.fields.Copies;
pDevMode->dmFields |= DM_COPIES;
}
if (attributes.fields.Sides > 0) {
pDevMode->dmDuplex = (short)attributes.fields.Sides;
pDevMode->dmFields |= DM_DUPLEX;
}
if (attributes.fields.PaperID > 0) {
pDevMode->dmPaperSize = (short)attributes.fields.PaperID;
pDevMode->dmFields |= DM_PAPERSIZE;
}
if (DocumentProperties(NULL, hPrinter, NULL,
pDevMode, pDevMode,
DM_IN_BUFFER | DM_OUT_BUFFER) == IDOK) {
}
} else {
#ifdef PRINTING_DEBUG
printf("Can't get initial DEVMODE.\n");
#endif /* PRINTING_DEBUG */
}
if (StartDocPrinter(hPrinter, 1, (LPBYTE)&dinfo) != 0) {
res = *((int *)&hPrinter);
}
}
#ifdef PRINTING_DEBUG
if (res == 0) {
DWORD error = GetLastError();
printf("Error occurred while starting: %d.\n", error);
}
if (res != 0) {
file = fopen("C:\\from_Native.ps", "wb+");
}
#endif /* PRINTING_DEBUG */
return res;
}
JNIEXPORT jboolean JNICALL Java_org_apache_harmony_x_print_GDIClient_writePrinter
(JNIEnv *env, jclass owner, jbyteArray array, jint size, jint printerID) {
HANDLE hPrinter = *((HANDLE *)&printerID);
if (hPrinter != NULL) {
signed char *data;
data = (signed char *)env->GetByteArrayElements(array, NULL);
#ifdef PRINTING_DEBUG
if (file != NULL) {
fwrite(data, sizeof(signed char), size, file);
}
#endif /* PRINTING_DEBUG */
DWORD written = 0;
if (WritePrinter(hPrinter, data, size, &written) != 0) {
env->ReleaseByteArrayElements(array, (jbyte *)data, JNI_ABORT);
return JNI_TRUE;
}
}
#ifdef PRINTING_DEBUG
if (res == JNI_FALSE) {
DWORD error = GetLastError();
printf("Error occurred while transfering data to printer: %d.\n", error);
}
#endif /* PRINTING_DEBUG */
return JNI_FALSE;
}
JNIEXPORT jboolean JNICALL Java_org_apache_harmony_x_print_GDIClient_endDocPrinter
(JNIEnv *env, jclass owner, jint printerID) {
HANDLE hPrinter = *((HANDLE *)&printerID);
#ifdef PRINTING_DEBUG
if (file != NULL) {
fclose(file);
file = NULL;
}
#endif /* PRINTING_DEBUG */
if (hPrinter != NULL) {
if (EndDocPrinter(hPrinter) != 0) {
ClosePrinter(hPrinter);
hPrinter = NULL;
return JNI_TRUE;
}
}
#ifdef PRINTING_DEBUG
if (res == JNI_FALSE) {
DWORD error = GetLastError();
printf("Error occurred while ending: %d.\n", error);
}
#endif /* PRINTING_DEBUG */
return JNI_FALSE;
}
//----------------- Interpreter functions -------------------------------------
#define MAX_PRINTER_CONTEXTS 20
HDC printerDCs[] = { NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL };
int psWidths[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
int psHeights[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
int getFreePDCID() {
for (int i = 0; i < MAX_PRINTER_CONTEXTS; i++) {
if (printerDCs[i] == NULL) {
return i;
}
}
return -1;
}
int obtainPrinterDC(const char *printer, int psWidth, int psHeight) {
int pdcID = getFreePDCID();
if (pdcID < 0) {
return -1;
}
printerDCs[pdcID] = CreateDC("WINSPOOL", printer, NULL, NULL); // In win 9x/Me "WINSPOOL" should not be used.
if (printerDCs[pdcID] == NULL) {
return -1;
}
psWidths[pdcID] = psWidth;
psHeights[pdcID] = psHeight;
return pdcID;
}
void releasePrinterDC(const int pdcID) {
if (pdcID >= 0) {
DeleteDC(printerDCs[pdcID]);
printerDCs[pdcID] = NULL;
psWidths[pdcID] = 0;
psHeights[pdcID] = 0;
}
}
void setAttributes(const char *printer, const int pdcID, AttributesUnion attributes) {
HDC pdc = printerDCs[pdcID];
if (pdc != NULL) {
DEVMODE *pDevMode = NULL;
HANDLE hPrinter;
if (OpenPrinter((LPTSTR)printer, &hPrinter, NULL) != 0) {
int size = DocumentProperties(NULL, hPrinter, NULL, pDevMode, NULL, 0);
pDevMode = (DEVMODE *)malloc(size);
if (DocumentProperties(NULL, hPrinter, NULL, pDevMode, NULL, DM_OUT_BUFFER) == IDOK) {
pDevMode->dmFields = 0;
if (attributes.fields.PaperID > 0) {
pDevMode->dmPaperSize = (short)attributes.fields.PaperID;
pDevMode->dmFields |= DM_PAPERSIZE;
}
if (attributes.fields.Copies > 0) {
pDevMode->dmCopies = (short)attributes.fields.Copies;
pDevMode->dmFields |= DM_COPIES;
}
if (attributes.fields.Collate > 0) {
if (attributes.fields.Collate == 1) {
pDevMode->dmCollate = DMCOLLATE_TRUE;
} else {
pDevMode->dmCollate = DMCOLLATE_FALSE;
}
pDevMode->dmFields |= DM_COLLATE;
}
if (attributes.fields.Sides > 0) {
pDevMode->dmDuplex = (short)attributes.fields.Sides;
pDevMode->dmFields |= DM_DUPLEX;
}
if (attributes.fields.Chromaticity > 0) {
if (attributes.fields.Chromaticity == 1) {
pDevMode->dmColor = DMCOLOR_MONOCHROME;
} else {
pDevMode->dmColor = DMCOLOR_COLOR;
}
pDevMode->dmFields |= DM_COLOR;
}
if (attributes.fields.Orientation > 0) {
if (attributes.fields.Orientation == 2) {
pDevMode->dmOrientation = DMORIENT_LANDSCAPE;
} else {
pDevMode->dmOrientation = DMORIENT_PORTRAIT;
}
pDevMode->dmFields |= DM_ORIENTATION;
}
if (attributes.fields.XResolution > 0) {
pDevMode->dmPrintQuality = (short)attributes.fields.XResolution;
pDevMode->dmFields |= DM_PRINTQUALITY;
}
if (attributes.fields.YResolution > 0) {
pDevMode->dmYResolution = (short)attributes.fields.YResolution;
pDevMode->dmFields |= DM_YRESOLUTION;
}
if (pDevMode->dmFields != 0) {
#ifdef PRINTING_DEBUG
printf("Setting up print attributes.\n");
#endif /* PRINTING_DEBUG */
ResetDC(pdc, pDevMode);
}
}
ClosePrinter(hPrinter);
}
}
}
int startDocument(const int pdcID, const char *jname, const char *fname) {
HDC pdc = printerDCs[pdcID];
if (pdc != NULL) {
DOCINFO info;
info.cbSize = sizeof(DOCINFO);
info.lpszDocName = jname;
info.lpszDatatype = NULL;
info.lpszOutput = fname;
info.fwType = 0;
if (StartDoc(pdc, &info) > 0) {
return JNI_TRUE;
}
}
return JNI_FALSE;
}
int startPage(const int pdcID) {
HDC pdc = printerDCs[pdcID];
if (pdc != NULL) {
if (StartPage(pdc) > 0) {
return JNI_TRUE;
}
}
return JNI_FALSE;
}
int finishPage(const int pdcID) {
HDC pdc = printerDCs[pdcID];
if (pdc != NULL) {
if (EndPage(pdc) > 0) {
return JNI_TRUE;
}
}
return JNI_FALSE;
}
int finishDocument(const int pdcID) {
HDC pdc = printerDCs[pdcID];
if (pdc != NULL) {
if (EndDoc(pdc) > 0) {
releasePrinterDC(pdcID);
return JNI_TRUE;
}
}
return JNI_FALSE;
}
int transDoubleX(const int pdcID, jdouble x) {
HDC pdc = printerDCs[pdcID];
if (pdc != NULL) {
double width = (double)GetDeviceCaps(pdc, HORZRES);
double k = width / psWidths[pdcID];
return (int)(x * k);
}
return (int)x;
}
int transDoubleY(const int pdcID, jdouble y) {
HDC pdc = printerDCs[pdcID];
if (pdc != NULL) {
double height = (double)GetDeviceCaps(pdc, VERTRES);
double k = height / psHeights[pdcID];
return (int)(y * k);
}
return (int)y;
}
int client_LineTo(const int pdcID, int x, int y) {
HDC pdc = printerDCs[pdcID];
if (pdc != NULL) {
if (LineTo(pdc, x, y) > 0) {
return JNI_TRUE;
}
}
return JNI_FALSE;
}
int client_MoveTo(const int pdcID, int x, int y) {
HDC pdc = printerDCs[pdcID];
if (pdc != NULL) {
if (MoveToEx(pdc, x, y, NULL) > 0) {
return JNI_TRUE;
}
}
return JNI_FALSE;
}
int client_Arc(const int pdcID, int x, int y, int r, float alpha, float beta) {
HDC pdc = printerDCs[pdcID];
if (pdc != NULL) {
if (AngleArc(pdc, x, y, r, alpha, beta) > 0) {
return JNI_TRUE;
}
}
return JNI_FALSE;
}
int client_SetColor(const int pdcID, double red, double green, double blue) {
HDC pdc = printerDCs[pdcID];
if (pdc != NULL) {
int r = (int)(255.0 * red);
int g = (int)(255.0 * green);
int b = (int)(255.0 * blue);
HPEN pen = CreatePen(PS_SOLID, 0, RGB(r, g, b));
HPEN oldPen = (HPEN)SelectObject(pdc, pen);
if (oldPen != NULL) {
DeleteObject(oldPen);
HBRUSH brush = CreateSolidBrush(RGB(r, g, b));
HBRUSH oldBrush = (HBRUSH)SelectObject(pdc, brush);
if (oldBrush != NULL) {
DeleteObject(oldBrush);
if (SetTextColor(pdc, RGB(r, g, b)) != CLR_INVALID) {
return JNI_TRUE;
}
}
}
}
return JNI_FALSE;
}
int client_BeginPath(const int pdcID) {
HDC pdc = printerDCs[pdcID];
if (pdc != NULL) {
if (BeginPath(pdc)) {
return JNI_TRUE;
}
}
return JNI_FALSE;
}
int client_ClosePath(const int pdcID) {
HDC pdc = printerDCs[pdcID];
if (pdc != NULL) {
if (CloseFigure(pdc)) {
if (EndPath(pdc)) {
return JNI_TRUE;
}
}
}
return JNI_FALSE;
}
int client_StrokePath(const int pdcID) {
HDC pdc = printerDCs[pdcID];
if (pdc != NULL) {
if (StrokePath(pdc)) {
return JNI_TRUE;
}
}
return JNI_FALSE;
}
int client_FillPath(const int pdcID) {
HDC pdc = printerDCs[pdcID];
if (pdc != NULL) {
if (FillPath(pdc)) {
return JNI_TRUE;
}
}
return JNI_FALSE;
}
int client_DrawImage(const int pdcID, int x, int y, int sw, int sh, int *data, int w, int h) {
HDC pdc = printerDCs[pdcID];
if (pdc != NULL) {
HDC screen = GetDC(NULL);
HDC bmpdc = CreateCompatibleDC(screen);
HBITMAP bmp = NULL;
if ((bmp = CreateBitmap(w, h, 1, 32, (void *)data)) != NULL) {
SelectObject(bmpdc, bmp);
// SetStretchBltMode(pdc, COLORONCOLOR);
if (StretchBlt(pdc, x, y,
sw, sh,
bmpdc, 0, 0, w, h, SRCCOPY) != 0) {
DeleteObject(bmp);
DeleteDC(bmpdc);
return JNI_TRUE;
}
}
}
return JNI_FALSE;
}
int client_DrawText(const int pdcID, const char *text) {
HDC pdc = printerDCs[pdcID];
if (pdc != NULL) {
POINT point;
if (MoveToEx(pdc, 0, 0, &point)) {
if (TextOut(pdc, point.x, point.y, text, (int)strlen(text))) {
if (MoveToEx(pdc, point.x, point.y, NULL)) {
return JNI_TRUE;
}
}
}
}
return JNI_FALSE;
}
JNIEXPORT jint JNICALL Java_org_apache_harmony_x_print_PSInterpreter_obtainServiceID
(JNIEnv *env, jclass owner, jstring printerName, jint width, jint height) {
const char *printer = env->GetStringUTFChars(printerName, 0);
return obtainPrinterDC(printer, (int)width, (int)height);
}
JNIEXPORT void JNICALL Java_org_apache_harmony_x_print_PSInterpreter_releaseServiceID
(JNIEnv *env, jclass owner, jint serviceID) {
releasePrinterDC((int)serviceID);
}
JNIEXPORT jboolean JNICALL Java_org_apache_harmony_x_print_PSInterpreter_startDocument
(JNIEnv *env, jclass owner, jstring printerName, jint serviceID,
jintArray printAttributes, jstring jobName, jstring destination) {
const char *printer = env->GetStringUTFChars(printerName, 0);
const char *jname = env->GetStringUTFChars(jobName, 0);
const char *fname = NULL;
if (destination != NULL) {
fname = env->GetStringUTFChars(destination, 0);
}
AttributesUnion attributes;
jboolean isCopy = JNI_FALSE;
int *numbers = (int *)env->GetIntArrayElements(printAttributes, &isCopy);
for (int i = 0; i < ATTRIBUTE_UNION_SIZE; i++) {
attributes.numbers[i] = numbers[i];
}
setAttributes(printer, (int)serviceID, attributes);
return (jboolean)startDocument((int)serviceID, jname, fname);
}
JNIEXPORT jboolean JNICALL Java_org_apache_harmony_x_print_PSInterpreter_startPage
(JNIEnv *env, jclass owner, jint serviceID) {
return (jboolean)startPage((int)serviceID);
}
JNIEXPORT jboolean JNICALL Java_org_apache_harmony_x_print_PSInterpreter_endPage
(JNIEnv *env, jclass owner, jint serviceID) {
return (jboolean)finishPage((int)serviceID);
}
JNIEXPORT jboolean JNICALL Java_org_apache_harmony_x_print_PSInterpreter_endDocument
(JNIEnv *env, jclass owner, jint serviceID) {
return (jboolean)finishDocument((int)serviceID);
}
JNIEXPORT jboolean JNICALL Java_org_apache_harmony_x_print_PSInterpreter_setRGBColor
(JNIEnv *env, jclass owner, jint serviceID, jdouble red, jdouble green, jdouble blue) {
return (jboolean)client_SetColor((int)serviceID, (double)red, (double)green, (double)blue);
}
JNIEXPORT jboolean JNICALL Java_org_apache_harmony_x_print_PSInterpreter_moveTo
(JNIEnv *env, jclass owner, jint serviceID, jdouble x, jdouble y) {
return (jboolean)client_MoveTo((int)serviceID, transDoubleX(serviceID, x), transDoubleY(serviceID, psHeights[(int)serviceID] - y));
}
JNIEXPORT jboolean JNICALL Java_org_apache_harmony_x_print_PSInterpreter_lineTo
(JNIEnv *env, jclass owner, jint serviceID, jdouble x, jdouble y) {
return (jboolean)client_LineTo((int)serviceID, transDoubleX(serviceID, x), transDoubleY(serviceID, psHeights[(int)serviceID] - y));
}
JNIEXPORT jboolean JNICALL Java_org_apache_harmony_x_print_PSInterpreter_drawArc
(JNIEnv *env, jclass owner, jint serviceID, jdouble x, jdouble y, jdouble r, jdouble alpha, jdouble beta) {
return (jboolean)client_Arc((int)serviceID, transDoubleX(serviceID, x), transDoubleY(serviceID, psHeights[(int)serviceID] - y),
transDoubleX(serviceID, r), (float)alpha, (float)beta);
}
JNIEXPORT jboolean JNICALL Java_org_apache_harmony_x_print_PSInterpreter_beginPath
(JNIEnv *env, jclass owner, jint serviceID) {
return (jboolean)client_BeginPath((int)serviceID);
}
JNIEXPORT jboolean JNICALL Java_org_apache_harmony_x_print_PSInterpreter_closePath
(JNIEnv *env, jclass owner, jint serviceID) {
return (jboolean)client_ClosePath((int)serviceID);
}
JNIEXPORT jboolean JNICALL Java_org_apache_harmony_x_print_PSInterpreter_strokePath
(JNIEnv *env, jclass owner, jint serviceID) {
return (jboolean)client_StrokePath((int)serviceID);
}
JNIEXPORT jboolean JNICALL Java_org_apache_harmony_x_print_PSInterpreter_fillPath
(JNIEnv *env, jclass owner, jint serviceID) {
return (jboolean)client_FillPath((int)serviceID);
}
JNIEXPORT jboolean JNICALL Java_org_apache_harmony_x_print_PSInterpreter_drawImage
(JNIEnv *env, jclass owner, jint serviceID, jdouble x, jdouble y,
jdouble sw, jdouble sh, jintArray data, jint w, jint h) {
int *bits;
if (data != NULL) {
bits = (int *)env->GetIntArrayElements(data, NULL);
} else {
return JNI_FALSE;
}
jboolean result = (jboolean)client_DrawImage((int)serviceID,
transDoubleX(serviceID, x), transDoubleY(serviceID, psHeights[(int)serviceID] - y),
transDoubleX(serviceID, sw), transDoubleY(serviceID, sh),
bits, (int)w, (int)h);
env->ReleaseIntArrayElements(data, (jint *)bits, JNI_ABORT);
return result;
}
JNIEXPORT jboolean JNICALL Java_org_apache_harmony_x_print_PSInterpreter_drawText
(JNIEnv *env, jclass owner, jint serviceID, jstring text) {
const char *string = env->GetStringUTFChars(text, 0);
return client_DrawText((int)serviceID, string);
}
JNIEXPORT jboolean JNICALL Java_org_apache_harmony_x_print_PSInterpreter_clipPath
(JNIEnv *env, jclass owner, jint serviceID) {
return JNI_TRUE;
}
JNIEXPORT jboolean JNICALL Java_org_apache_harmony_x_print_PSInterpreter_rotate
(JNIEnv *env, jclass owner, jint serviceID, jdouble alpha) {
return JNI_TRUE;
}
JNIEXPORT jboolean JNICALL Java_org_apache_harmony_x_print_PSInterpreter_setFont
(JNIEnv *env, jclass owner, jint serviceID, jstring font) {
const char *name = env->GetStringUTFChars(font, 0);
return JNI_TRUE;
}