Bug 72087 - major xprint revamp

patch by Roland.Mainz@informatik.med.uni-giessen.de
r=blizzard, sr=shaver, a=asa

NOT PART OF DEFAULT BUILD
This commit is contained in:
bbaetz%cs.mcgill.ca 2001-04-21 17:20:51 +00:00
Родитель c88f0571f4
Коммит 2e000089ba
16 изменённых файлов: 1559 добавлений и 394 удалений

Просмотреть файл

@ -356,11 +356,11 @@ NS_IMETHODIMP nsDeviceContextSpecGTK :: GetPrintMethod(int &aMethod )
nsresult rv;
nsCOMPtr<nsIPref> pPrefs = do_GetService(NS_PREF_CONTRACTID, &rv);
if (NS_SUCCEEDED(rv) && pPrefs) {
PRInt32 method = 0;
PRInt32 method = NS_DEFAULT_PRINT_METHOD;
(void) pPrefs->GetIntPref("print.print_method", &method);
aMethod = method;
} else {
aMethod = 0;
aMethod = NS_DEFAULT_PRINT_METHOD;
}
return NS_OK;
}

Просмотреть файл

@ -275,11 +275,11 @@ NS_IMETHODIMP nsDeviceContextSpecXlib::GetPrintMethod(int &aMethod)
nsresult rv;
nsCOMPtr<nsIPref> pPrefs = do_GetService(NS_PREF_CONTRACTID, &rv);
if (NS_SUCCEEDED(rv) && pPrefs) {
PRInt32 method = 0;
PRInt32 method = NS_DEFAULT_PRINT_METHOD;
(void) pPrefs->GetIntPref("print.print_method", &method);
aMethod = method;
} else {
aMethod = 0;
aMethod = NS_DEFAULT_PRINT_METHOD;
}
return NS_OK;
}

Просмотреть файл

@ -0,0 +1 @@
Makefile

Просмотреть файл

@ -17,6 +17,7 @@
# Rights Reserved.
#
# Contributor(s):
# Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>
#
DEPTH = ../../..
@ -30,9 +31,11 @@ MODULE = layout
LIBRARY_NAME = gfxxprt
IS_COMPONENT = 1
EXTRA_DSO_LIBS = gkgfx
REQUIRES = xpcom string widget view img util dom pref locale uconv unicharutil gfx2
REQUIRES = xpcom string widget view img util dom pref locale uconv unicharutil gfx2 necko
CSRCS = ../xlibrgb/xlibrgb.c \
xprintutil.c \
xprintutil_printtofile.c \
$(NULL)
CPPSRCS = \

Просмотреть файл

@ -18,9 +18,11 @@
* Rights Reserved.
*
* Contributor(s):
* Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>
* Bradley Baetz <bbaetz@cs.mcgill.ca>
*
*/
#include <iostream.h>
#include <unistd.h>
#include "nsDeviceContextXP.h"
#include "nsRenderingContextXP.h"
@ -29,10 +31,10 @@
#include "nsIDeviceContextSpecXPrint.h"
#include "il_util.h"
#include "nspr.h"
#include "nsXPrintContext.h"
static PRLogModuleInfo *nsDeviceContextXPLM = PR_NewLogModule("nsDeviceContextXP");
/*
static NS_DEFINE_IID(kDeviceContextIID, NS_IDEVICE_CONTEXT_IID);
*/
static NS_DEFINE_IID(kIDeviceContextSpecXPIID, NS_IDEVICE_CONTEXT_SPEC_XP_IID);
/** ---------------------------------------------------
@ -40,9 +42,7 @@ static NS_DEFINE_IID(kIDeviceContextSpecXPIID, NS_IDEVICE_CONTEXT_SPEC_XP_IID);
*/
nsDeviceContextXP :: nsDeviceContextXP()
{
NS_INIT_REFCNT();
mSpec = nsnull;
/* Inherited from xlib device context code */
mTwipsToPixels = 1.0;
mPixelsToTwips = 1.0;
@ -53,46 +53,35 @@ nsDeviceContextXP :: nsDeviceContextXP()
mNumCells = 0;
mPrintContext = nsnull;
mWidthFloat = 0.0f;
mWidthFloat = 0.0f;
mHeightFloat = 0.0f;
mWidth = -1;
mWidth = -1;
mHeight = -1;
NS_NewISupportsArray(getter_AddRefs(mFontMetrics));
}
/** ---------------------------------------------------
* See documentation in nsIDeviceContext.h
* @update 12/21/98 dwc
* @update 12/21/98 dwc
*/
nsDeviceContextXP :: ~nsDeviceContextXP()
{
PRInt32 i, n;
nsDeviceContextXP :: ~nsDeviceContextXP() { }
// get rid of the fonts in our mFontMetrics cache
n= mFontMetrics.Count();
for (i = 0; i < n; i++){
nsIFontMetrics* fm = (nsIFontMetrics*) mFontMetrics.ElementAt(i);
fm->Destroy();
NS_RELEASE(fm);
}
mFontMetrics.Clear();
NS_IF_RELEASE(mSpec);
}
NS_IMETHODIMP
nsDeviceContextXP :: SetSpec(nsIDeviceContextSpec* aSpec)
{
nsIDeviceContextSpecXP *psSpec;
nsresult res;
PR_LOG(nsDeviceContextXPLM, PR_LOG_DEBUG, ("nsDeviceContextXP::SetSpec()\n"));
nsCOMPtr<nsIDeviceContextSpecXP> xpSpec;
mSpec = aSpec;
NS_ADDREF(aSpec);
if (mPrintContext == nsnull) {
if (!mPrintContext) {
mPrintContext = new nsXPrintContext();
res = mSpec->QueryInterface(kIDeviceContextSpecXPIID, (void **) &psSpec);
if (res == NS_OK) {
mPrintContext->Init(psSpec);
xpSpec = do_QueryInterface(mSpec);
if (xpSpec) {
mPrintContext->Init(xpSpec);
}
}
@ -126,10 +115,6 @@ nsDeviceContextXP::InitDeviceContextXP(nsIDeviceContext *aCreatingDeviceContext,
mAppUnitsToDevUnits = (a2d / t2d) * mTwipsToPixels;
mDevUnitsToAppUnits = 1.0f / mAppUnitsToDevUnits;
#ifdef XPRINT_ON_SCREEN
mAppUnitsToDevUnits = 1.0;
mDevUnitsToAppUnits = 1.0;
#endif
mScreen = mPrintContext->GetScreen();
mDisplay = mPrintContext->GetDisplay();
@ -146,16 +131,18 @@ NS_IMETHODIMP nsDeviceContextXP :: CreateRenderingContext(nsIRenderingContext *&
{
nsresult rv = NS_ERROR_OUT_OF_MEMORY;
aContext = new nsRenderingContextXP();
if (nsnull != aContext){
NS_ADDREF(aContext);
rv = ((nsRenderingContextXP*) aContext)->Init(this);
nsCOMPtr<nsRenderingContextXP> xpContext;
xpContext = new nsRenderingContextXP();
if (xpContext){
rv = xpContext->Init(this);
}
if (NS_OK != rv){
NS_IF_RELEASE(aContext);
}
return rv;
if (NS_SUCCEEDED(rv)) {
aContext = xpContext;
NS_ADDREF(aContext);
}
return rv;
}
/** ---------------------------------------------------
@ -171,10 +158,10 @@ NS_IMETHODIMP nsDeviceContextXP :: SupportsNativeWidgets(PRBool &aSupportsWidget
* See documentation in nsIDeviceContext.h
*/
NS_IMETHODIMP nsDeviceContextXP :: GetScrollBarDimensions(float &aWidth,
float &aHeight) const
float &aHeight) const
{
// XXX Oh, yeah. These are hard coded.
aWidth = 15 * mPixelsToTwips;
aWidth = 15 * mPixelsToTwips;
aHeight = 15 * mPixelsToTwips;
return NS_OK;
@ -210,16 +197,16 @@ NS_IMETHODIMP nsDeviceContextXP::GetILColorSpace(IL_ColorSpace*& aColorSpace)
IL_AddRefToColorSpace(aColorSpace);
#endif
if(nsnull==mColorSpace) {
if(!mColorSpace) {
IL_RGBBits colorRGBBits;
// Create a 24-bit color space
colorRGBBits.red_shift = 16;
colorRGBBits.red_bits = 8;
colorRGBBits.green_shift = 8;
colorRGBBits.green_bits = 8;
colorRGBBits.blue_shift = 0;
colorRGBBits.blue_bits = 8;
colorRGBBits.red_shift = 16;
colorRGBBits.red_bits = 8;
colorRGBBits.green_shift = 8;
colorRGBBits.green_bits = 8;
colorRGBBits.blue_shift = 0;
colorRGBBits.blue_bits = 8;
mColorSpace = IL_CreateTrueColorSpace(&colorRGBBits, 24);
@ -239,10 +226,21 @@ NS_IMETHODIMP nsDeviceContextXP::GetILColorSpace(IL_ColorSpace*& aColorSpace)
/** ---------------------------------------------------
* See documentation in nsIDeviceContext.h
* @update 12/21/98 dwc
* @update 12/21/98 dwc
*/
NS_IMETHODIMP nsDeviceContextXP :: CheckFontExistence(const nsString& aFontName)
{
PR_LOG(nsDeviceContextXPLM, PR_LOG_DEBUG, ("nsDeviceContextXP::CheckFontExistence()\n"));
/* BUG: this does - unfortunately - not work due missing DISPLAY ptr
* Additionally this is the _wrong_ time to make any assumtions
* about fonts - this info+the correct information is _only_
* available _after_ XpSetContext() - therefore any assumtions
* made here are _wrong_ until we have a vaoid XPContext
* (X11 print context)
*/
#if 0
return nsFontMetricsXP::FamilyExists(aFontName);
#else
char **fnames = nsnull;
PRInt32 namelen = aFontName.Length() + 1;
char *wildstring = (char *)PR_Malloc(namelen + 200);
@ -253,22 +251,27 @@ NS_IMETHODIMP nsDeviceContextXP :: CheckFontExistence(const nsString& aFontName)
XFontStruct *fonts;
nsresult rv = NS_ERROR_FAILURE;
if (nsnull == wildstring)
if (!wildstring)
return NS_ERROR_UNEXPECTED;
if (abs(dpi - 75) < abs(dpi - 100))
#if 0 /* gisburn: this cannot work - Xprint usually operates at >= 300dpi */
if (abs(dpi - 75) < abs(dpi - 100))
dpi = 75;
else
dpi = 100;
#endif
char* fontName = aFontName.ToNewCString();
PR_snprintf(wildstring, namelen + 200,
" -*-%s-*-*-normal-*-*-*-%d-%d-*-*-*-*",
fontName, dpi, dpi);
delete [] fontName;
aFontName.get(), dpi, dpi);
/* applications must not make any assumptions about fonts _before_ XpSetContext() !!! */
NS_ASSERTION((XpGetContext(mDisplay) != None), "Obtaining font information (XListFontsWithInfo()) _before_ XpSetContext()");
fnames = ::XListFontsWithInfo(mDisplay, wildstring, 1, &numnames, &fonts);
PR_LOG(nsDeviceContextXPLM, PR_LOG_DEBUG,
("nsDeviceContextXP::CheckFontExistence: XListFontsWithInfo '%s'=%d\n", wildstring, numnames));
if (numnames > 0)
{
::XFreeFontInfo(fnames, fonts, numnames);
@ -277,10 +280,11 @@ NS_IMETHODIMP nsDeviceContextXP :: CheckFontExistence(const nsString& aFontName)
PR_Free(wildstring);
return NS_OK;
#endif
}
NS_IMETHODIMP nsDeviceContextXP :: GetSystemAttribute(nsSystemAttrID anID,
SystemAttrStruct * aInfo) const
SystemAttrStruct * aInfo) const
{
switch (anID) {
case 0:
@ -295,7 +299,7 @@ NS_IMETHODIMP nsDeviceContextXP :: GetSystemAttribute(nsSystemAttrID anID,
* See documentation in nsIDeviceContext.h
*/
NS_IMETHODIMP nsDeviceContextXP::GetDeviceSurfaceDimensions(PRInt32 &aWidth,
PRInt32 &aHeight)
PRInt32 &aHeight)
{
float width, height;
width = (float) mPrintContext->GetWidth();
@ -304,10 +308,6 @@ NS_IMETHODIMP nsDeviceContextXP::GetDeviceSurfaceDimensions(PRInt32 &aWidth,
// height = height - 200;
aWidth = NSToIntRound(width * mDevUnitsToAppUnits);
aHeight = NSToIntRound(height * mDevUnitsToAppUnits);
#ifdef XPRINT_ON_SCREEN
aWidth = width;
aHeight = height;
#endif
return NS_OK;
}
@ -347,7 +347,7 @@ NS_IMETHODIMP nsDeviceContextXP::BeginDocument(PRUnichar * aTitle)
{
nsresult rv = NS_OK;
if (mPrintContext != nsnull) {
rv = mPrintContext->BeginDocument();
rv = mPrintContext->BeginDocument(aTitle);
}
return rv;
}
@ -360,7 +360,16 @@ NS_IMETHODIMP nsDeviceContextXP::EndDocument(void)
nsresult rv = NS_OK;
if (mPrintContext != nsnull) {
rv = mPrintContext->EndDocument();
// gisburn: mPrintContext cannot be reused between to print
// tasks as the destination print server may be a different one
// or the printer used on the same print server has other
// properties (build-in fonts for example ) than the printer
// previously used
delete mPrintContext;
mPrintContext = nsnull;
}
return rv;
}
@ -378,7 +387,7 @@ NS_IMETHODIMP nsDeviceContextXP::BeginPage(void)
/** ---------------------------------------------------
* See documentation in nsIDeviceContext.h
* @update 12/21/98 dwc
* @update 12/21/98 dwc
*/
NS_IMETHODIMP nsDeviceContextXP::EndPage(void)
{
@ -391,10 +400,10 @@ NS_IMETHODIMP nsDeviceContextXP::EndPage(void)
/** ---------------------------------------------------
* See documentation in nsIDeviceContext.h
* @update 12/21/98 dwc
* @update 12/21/98 dwc
*/
NS_IMETHODIMP nsDeviceContextXP :: ConvertPixel(nscolor aColor,
PRUint32 & aPixel)
PRUint32 & aPixel)
{
aPixel = aColor;
return NS_OK;
@ -424,34 +433,41 @@ NS_IMETHODIMP nsDeviceContextXP::GetDepth(PRUint32& aDepth)
* See documentation in nsIDeviceContext.h
*/
NS_IMETHODIMP nsDeviceContextXP::GetMetricsFor(const nsFont& aFont,
nsIAtom* aLangGroup, nsIFontMetrics *&aMetrics)
nsIAtom* aLangGroup, nsIFontMetrics *&aMetrics)
{
return GetMetricsFor(aFont, aMetrics);
}
NS_IMETHODIMP nsDeviceContextXP::GetMetricsFor(const nsFont& aFont,
nsIFontMetrics *&aMetrics)
nsIFontMetrics *&aMetrics)
{
PRInt32 n,cnt;
PRUint32 n,cnt;
nsresult rv;
// First check our cache
n = mFontMetrics.Count();
rv = mFontMetrics->Count(&n);
if (NS_FAILED(rv))
return rv;
nsCOMPtr<nsIFontMetrics> m;
for (cnt = 0; cnt < n; cnt++){
aMetrics = (nsIFontMetrics*) mFontMetrics.ElementAt(cnt);
const nsFont *font;
aMetrics->GetFont(font);
if (aFont.Equals(*font)){
NS_ADDREF(aMetrics);
return NS_OK;
for (cnt = 0; cnt < n; cnt++) {
if (NS_SUCCEEDED(mFontMetrics->QueryElementAt(cnt,
NS_GET_IID(nsIFontMetrics),
getter_AddRefs(m)))) {
const nsFont* font;
m->GetFont(font);
if (aFont.Equals(*font)) {
aMetrics = m;
NS_ADDREF(aMetrics);
return NS_OK;
}
}
}
// It's not in the cache. Get font metrics and then cache them.
nsIFontMetrics* fm = new nsFontMetricsXP();
if (nsnull == fm) {
nsCOMPtr<nsIFontMetrics> fm = new nsFontMetricsXP();
if (!fm) {
aMetrics = nsnull;
return NS_ERROR_FAILURE;
}
@ -459,24 +475,21 @@ NS_IMETHODIMP nsDeviceContextXP::GetMetricsFor(const nsFont& aFont,
// XXX need to pass real lang group
rv = fm->Init(aFont, nsnull, this);
if (NS_OK != rv) {
if (NS_FAILED(rv)) {
aMetrics = nsnull;
return rv;
}
mFontMetrics.AppendElement(fm);
NS_ADDREF(fm); // this is for the cache
mFontMetrics->AppendElement(fm);
for (cnt = 0; cnt < n; cnt++){
aMetrics = (nsIFontMetrics*) mFontMetrics.ElementAt(cnt);
const nsFont *font;
aMetrics->GetFont(font);
}
NS_ADDREF(fm); // this is for the routine that needs this font
aMetrics = fm;
NS_ADDREF(aMetrics);
return NS_OK;
}
NS_IMETHODIMP
nsDeviceContextXP::GetPrintContext(nsXPrintContext*& aContext) {
aContext = mPrintContext;
//NS_ADDREF(aContext);
return NS_OK;
}

Просмотреть файл

@ -31,16 +31,16 @@
#include "nsIRenderingContext.h"
#include "nsVoidArray.h"
#include "nsIDeviceContextXPrint.h"
#include "nsISupportsArray.h"
class nsXPrintContext;
class nsDeviceContextXP : public DeviceContextImpl,
public nsIDeviceContextXP
class nsDeviceContextXP : public nsIDeviceContextXP
{
public:
nsDeviceContextXP();
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_ISUPPORTS_INHERITED
/**
* This method does nothing since a postscript devicecontext will never be created
@ -57,47 +57,47 @@ public:
NS_IMETHOD GetScrollBarDimensions(float &aWidth, float &aHeight) const;
void SetDrawingSurface(nsDrawingSurface aSurface) { mSurface = aSurface; }
NS_IMETHOD GetDrawingSurface(nsIRenderingContext &aContext, nsDrawingSurface &aSurface);
void SetDrawingSurface(nsDrawingSurface aSurface) { mSurface = aSurface; }
NS_IMETHOD GetDrawingSurface(nsIRenderingContext &aContext, nsDrawingSurface &aSurface);
NS_IMETHOD CheckFontExistence(const nsString& aFontName);
NS_IMETHODIMP GetILColorSpace(IL_ColorSpace*& aColorSpace);
NS_IMETHOD GetDepth(PRUint32& aDepth);
NS_IMETHOD ConvertPixel(nscolor aColor, PRUint32 & aPixel);
NS_IMETHOD CheckFontExistence(const nsString& aFontName);
NS_IMETHODIMP GetILColorSpace(IL_ColorSpace*& aColorSpace);
NS_IMETHOD GetDepth(PRUint32& aDepth);
NS_IMETHOD ConvertPixel(nscolor aColor, PRUint32 & aPixel);
NS_IMETHOD GetDeviceSurfaceDimensions(PRInt32 &aWidth, PRInt32 &aHeight);
NS_IMETHOD GetRect(nsRect &aRect);
NS_IMETHOD GetClientRect(nsRect &aRect);
NS_IMETHOD GetDeviceSurfaceDimensions(PRInt32 &aWidth, PRInt32 &aHeight);
NS_IMETHOD GetRect(nsRect &aRect);
NS_IMETHOD GetClientRect(nsRect &aRect);
NS_IMETHOD GetDeviceContextFor(nsIDeviceContextSpec *aDevice,nsIDeviceContext *&aContext);
NS_IMETHOD GetSystemAttribute(nsSystemAttrID anID, SystemAttrStruct * aInfo) const;
NS_IMETHOD BeginDocument(PRUnichar * aTitle);
NS_IMETHOD EndDocument(void);
NS_IMETHOD BeginPage(void);
NS_IMETHOD EndPage(void);
NS_IMETHOD GetDeviceContextFor(nsIDeviceContextSpec *aDevice,nsIDeviceContext *&aContext);
NS_IMETHOD GetSystemAttribute(nsSystemAttrID anID, SystemAttrStruct * aInfo) const;
NS_IMETHOD BeginDocument(PRUnichar * aTitle);
NS_IMETHOD EndDocument(void);
NS_IMETHOD BeginPage(void);
NS_IMETHOD EndPage(void);
NS_IMETHOD SetSpec(nsIDeviceContextSpec *aSpec);
Display * GetDisplay();
nsXPrintContext *GetPrintContext() { return mPrintContext; }
Display * GetDisplay();
NS_IMETHOD GetPrintContext(nsXPrintContext*& aContext);
NS_IMETHOD GetMetricsFor(const nsFont& aFont, nsIFontMetrics*& aMetrics);
NS_IMETHOD GetMetricsFor(const nsFont& aFont, nsIAtom* aLangGroup, nsIFontMetrics*& aMetrics);
NS_IMETHOD GetMetricsFor(const nsFont& aFont, nsIAtom* aLangGroup,
nsIFontMetrics*& aMetrics);
protected:
virtual ~nsDeviceContextXP();
virtual ~nsDeviceContextXP();
nsDrawingSurface mSurface ;
nsXPrintContext *mPrintContext;
Display *mDisplay;
Screen *mScreen;
PRUint32 mDepth;
nsIDeviceContextSpec *mSpec;
nsDrawingSurface mSurface;
nsXPrintContext *mPrintContext;
Display *mDisplay;
Screen *mScreen;
PRUint32 mDepth;
nsCOMPtr<nsIDeviceContextSpec> mSpec;
float mPixelScale;
nsVoidArray mFontMetrics; // we are not using the normal font cache, this is special for PostScript.
nsCOMPtr<nsISupportsArray> mFontMetrics; // we are not using the normal font cache
private:
void CommonInit(void);
nsPaletteInfo mPaletteInfo;
PRBool mWriteable;
PRUint32 mNumCells;
@ -109,4 +109,4 @@ private:
};
#endif /* nsDeviceContextPS_h___ */
#endif /* !nsDeviceContextPS_h___ */

Просмотреть файл

@ -203,7 +203,7 @@ NS_IMETHODIMP nsFontMetricsXP::Init(const nsFont& aFont, nsIAtom* aLangGroup,
nsAutoString loc(str);
loc.Truncate(2);
loc.ToLowerCase();
if ((loc.Equals(NS_ConvertASCIItoUCS2("ja"))) ||
if ((loc.Equals(NS_ConvertASCIItoUCS2("ja"))) ||
(loc.Equals(NS_ConvertASCIItoUCS2("ko"))) ||
(loc.Equals(NS_ConvertASCIItoUCS2("zh")))) {
// In CJK environments, we want the minimum request to be 16px,
@ -1140,7 +1140,7 @@ static nsFontCharSetMap gCharSetMap[] =
{ "johabs-1", &X11Johab },
{ "johabsh-1", &X11Johab },
{ "ksc5601.1987-0", &KSC5601 },
{ "microsoft-cp1251", &CP1251 },
{ "microsoft-cp1251", &CP1251 },
{ "misc-fontspecific", &Ignore },
{ "sgi-fontspecific", &Ignore },
{ "sun-fontspecific", &Ignore },
@ -1315,7 +1315,11 @@ GetMapFor10646Font(XFontStruct* aFont)
void
nsFontXP::LoadFont(nsFontCharSet* aCharSet, nsFontMetricsXP* aMetrics)
{
// XXX this is slow as dirt.
PR_LOG(FontMetricsXPLM, PR_LOG_DEBUG, ("nsFontXP::LoadFont: loading font '%s'\n", mName));
/* applications must not make any assumptions about fonts _before_ XpSetContext() !!! */
NS_ASSERTION((XpGetContext(aMetrics->mDisplay) != None), "Obtaining font information (XLoadQueryFont()) _before_ XpSetContext()");
// XXX this is slow as dirt
XFontStruct *xlibFont = XLoadQueryFont(aMetrics->mDisplay, mName);
if (xlibFont) {
if (aCharSet->mInfo->mCharSet) {
@ -1324,7 +1328,7 @@ nsFontXP::LoadFont(nsFontCharSet* aCharSet, nsFontMetricsXP* aMetrics)
else {
mMap = GetMapFor10646Font(xlibFont);
if (!mMap) {
XFreeFont(aMetrics->mDisplay, xlibFont);
XFreeFont(aMetrics->mDisplay, xlibFont);
return;
}
}
@ -1389,7 +1393,7 @@ nsFontXPNormal::GetWidth(const PRUnichar* aString, PRUint32 aLength)
XChar2b buf[512];
int ret;
int len = mCharSetInfo->Convert(mCharSetInfo, aString, aLength,
(char*) buf, sizeof(buf));
(char*) buf, sizeof(buf));
// XXX this is slow as dirt.
XFontStruct *font_struct = mFont;
if ((font_struct->min_byte1 == 0) && (font_struct->max_byte1 == 0))
@ -1406,7 +1410,7 @@ nsFontXPNormal::DrawString(nsXPrintContext* aPrintContext,
{
XChar2b buf[512];
int len = mCharSetInfo->Convert(mCharSetInfo, aString, aLength,
(char*) buf, sizeof(buf));
(char*) buf, sizeof(buf));
XFontStruct *font_struct = mFont;
nsFontMetricsXP::SetFont(aPrintContext, font_struct->fid);
if ((font_struct->min_byte1 == 0) && (font_struct->max_byte1 == 0))
@ -1468,18 +1472,18 @@ public:
virtual int GetWidth(const PRUnichar* aString, PRUint32 aLength);
virtual int DrawString(nsXPrintContext* aContext,
nscoord aX,
nscoord aX,
nscoord aY, const PRUnichar* aString,
PRUint32 aLength);
#ifdef MOZ_MATHML
virtual nsresult GetBoundingMetrics(const PRUnichar* aString,
PRUint32 aLength,
nsBoundingMetrics& aBoundingMetrics);
#endif
#endif /* MOZ_MATHML */
virtual PRUint32 Convert(const PRUnichar* aSrc, PRUint32 aSrcLen,
PRUnichar* aDest, PRUint32 aDestLen);
nsFontXP* mSubstituteFont;
nsFontXP *mSubstituteFont;
static int gCount;
static nsISaveAsCharset* gConverter;
@ -2209,6 +2213,8 @@ GetFontNames(char* aPattern)
nsFontFamily* family = nsnull;
int count = 0;
/* applications must not make any assumptions about fonts _before_ XpSetContext() !!! */
NS_ASSERTION((XpGetContext(gDisplay) != None), "Obtaining font information (XListFonts()) _before_ XpSetContext()");
char** list = ::XListFonts(gDisplay, aPattern, INT_MAX, &count);
if ((!list) || (count < 1)) {
return nsnull;

Просмотреть файл

@ -147,32 +147,32 @@ public:
friend void TryFamily(nsFontSearch* aSearch, nsFontFamily* aFamily);
friend struct nsFontXP;
nsFontXP **mLoadedFonts;
PRUint16 mLoadedFontsAlloc;
PRUint16 mLoadedFontsCount;
nsFontXP **mLoadedFonts;
PRUint16 mLoadedFontsAlloc;
PRUint16 mLoadedFontsCount;
int mInFindSubstituteFont;
nsFontXP *mSubstituteFont;
int mInFindSubstituteFont;
nsFontXP *mSubstituteFont;
nsString *mFonts;
PRUint16 mFontsAlloc;
PRUint16 mFontsCount;
PRUint16 mFontsIndex;
nsString *mFonts;
PRUint16 mFontsAlloc;
PRUint16 mFontsCount;
PRUint16 mFontsIndex;
nsString *mGeneric;
int mTriedAllGenerics;
nsCOMPtr<nsIAtom> mLangGroup;
nsString *mGeneric;
int mTriedAllGenerics;
nsCOMPtr<nsIAtom> mLangGroup;
protected:
char *PickAppropriateSize(char **names, XFontStruct *fonts, int cnt, nscoord desired);
void RealizeFont();
Display *mDisplay;
nsIDeviceContext *mDeviceContext;
nsFont *mFont;
XFontStruct *mFontHandle;
XFontStruct *mFontStruct;
nsFontXP *mWesternFont;
Display *mDisplay;
nsIDeviceContext *mDeviceContext;
nsFont *mFont;
XFontStruct *mFontHandle;
XFontStruct *mFontStruct;
nsFontXP *mWesternFont;
nscoord mHeight;
nscoord mLeading;
nscoord mEmHeight;
@ -200,7 +200,7 @@ protected:
#endif /* FONT_SWITCHING */
private:
static Font mLastSetFont;
static Font mLastSetFont;
};
class nsFontEnumeratorXP : public nsIFontEnumerator
@ -211,4 +211,4 @@ public:
NS_DECL_NSIFONTENUMERATOR
};
#endif
#endif /* !nsFontMetricsXP_h__ */

Просмотреть файл

@ -17,7 +17,9 @@
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Contributor(s):
* Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>
*
*/
#ifndef nsIDeviceContextSpecXP_h___
@ -25,12 +27,24 @@
#include "nsISupports.h"
/* make Xprint the default print system if user/admin has set the XPSERVERLIST"
* env var. See Xprt config README (/usr/openwin/server/etc/XpConfig/README)
* for details.
*/
#ifdef DEBUG_gisburn
#define NS_DEFAULT_PRINT_METHOD ((PR_GetEnv("XPSERVERLIST")!=nsnull)?(puts("** using printing=Xprint"),1):(puts("** using printing=PostScript"),0))
#else
#define NS_DEFAULT_PRINT_METHOD ((PR_GetEnv("XPSERVERLIST")!=nsnull)?(1):(0))
#endif /* DEBUG_gisburn */
#define NS_IDEVICE_CONTEXT_SPEC_XP_IID { 0xa4ef8910, 0xdd65, 0x11d2, { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 } }
class nsIDeviceContextSpecXP : public nsISupports
{
public:
NS_DEFINE_STATIC_IID_ACCESSOR(NS_IDEVICE_CONTEXT_SPEC_XP_IID);
/*
* If PR_TRUE, print to printer
* @update

Просмотреть файл

@ -1,4 +1,4 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
@ -21,6 +21,7 @@
*/
#include "nsISupports.h"
#include "nsIDeviceContext.h"
#ifndef __nsIDeviceContextXP_h
#define __nsIDeviceContextXP_h
@ -30,7 +31,9 @@
{0x35efd8b6, 0x13cc, 0x11d3, \
{0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}}
class nsIDeviceContextXP : public nsISupports
class nsXPrintContext;
class nsIDeviceContextXP : public DeviceContextImpl
{
public:
NS_DEFINE_STATIC_IID_ACCESSOR(NS_IDEVICECONTEXTXP_IID);
@ -39,6 +42,12 @@ public:
NS_IMETHOD InitDeviceContextXP(nsIDeviceContext *aCreatingDeviceContext,
nsIDeviceContext *aPrinterContext) = 0;
NS_IMETHOD GetPrintContext(nsXPrintContext*& aContext) = 0;
NS_IMETHOD GetMetricsFor(const nsFont& aFont, nsIFontMetrics*& aMetrics) = 0;
NS_IMETHOD GetMetricsFor(const nsFont& aFont, nsIAtom* aLangGroup,
nsIFontMetrics*& aMetrics) = 0;
};

Просмотреть файл

@ -18,20 +18,33 @@
* Rights Reserved.
*
* Contributor(s):
* Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <strings.h>
#include "xlibrgb.h"
#include "nsXPrintContext.h"
#include "xprintutil.h"
#undef XPRINT_ON_SCREEN
/* DEBUG: use
* % export NSPR_LOG_MODULES=nsXPrintContext:5
* to see these debug messages...
*/
static PRLogModuleInfo *nsXPrintContextLM = PR_NewLogModule("nsXPrintContext");
Display * nsXPrintContext::mDisplay = (Display *)0;
static int xerror_handler(Display *display, XErrorEvent *ev) {
#ifdef __SUNPRO_C
extern "C" /* Make Sun Workshop and other conformant compilers happy... :-) */
#endif
static
int xerror_handler(Display *display, XErrorEvent *ev)
{
/* this should _never_ be happen... but if this happens - debug mode or not - scream !!! */
char errmsg[80];
XGetErrorText(display, ev->error_code, errmsg, 80);
XGetErrorText(display, ev->error_code, errmsg, sizeof(errmsg));
fprintf(stderr, "lib_xprint: Warning (X Error) - %s\n", errmsg);
return 0;
}
@ -41,16 +54,17 @@ static int xerror_handler(Display *display, XErrorEvent *ev) {
*/
nsXPrintContext::nsXPrintContext()
{
mPContext = (XPContext )0;
mPrintServerName = (char *)0;
mPrinterName = (char *)0;
mScreen = (Screen *)0;
mVisual = (Visual *)0;
mGC = (GC )0;
mDrawable = (Drawable )0;
mDepth = 0;
mAlphaPixmap = 0;
mImagePixmap = 0;
PR_LOG(nsXPrintContextLM, PR_LOG_DEBUG, ("nsXPrintContext::nsXPrintContext()\n"));
mPDisplay = (Display *)nsnull;
mPContext = (XPContext)None;
mScreen = (Screen *)nsnull;
mVisual = (Visual *)nsnull;
mGC = (GC)None;
mDrawable = (Drawable)None;
mDepth = 0;
mAlphaPixmap = (Pixmap)None;
mImagePixmap = (Pixmap)None;
}
/** ---------------------------------------------------
@ -58,61 +72,78 @@ nsXPrintContext::nsXPrintContext()
*/
nsXPrintContext::~nsXPrintContext()
{
PR_LOG(nsXPrintContextLM, PR_LOG_DEBUG, ("nsXPrintContext::~nsXPrintContext()\n"));
// end the document
EndDocument();
// Cleanup things allocated along the way
XpDestroyContext(mDisplay, mPContext);
XCloseDisplay(mDisplay);
if( mPDisplay != nsnull )
EndDocument();
}
#ifdef HACK_PRINTONSCREEN
// debug: "print" on display server for quick debugging
// see sleep() in nsXPrintContext::EndDocument()
#define XPRINTONSCREEN (!strcmp("xprint_preview",(aSpec->GetCommand(&buf),buf)))
#endif /* HACK_PRINTONSCREEN */
NS_IMETHODIMP
nsXPrintContext::Init(nsIDeviceContextSpecXP *aSpec)
{
int prefDepth = 8;
#ifdef XPRINT_ON_SCREEN
if (nsnull == mDisplay)
mDisplay = (Display *)XOpenDisplay(NULL);
mScreen = XDefaultScreenOfDisplay(mDisplay);
xlib_rgb_init_with_depth(mDisplay, mScreen, prefDepth);
mScreenNumber = XDefaultScreen(mDisplay);
SetupWindow(0, 0, 1000, 1100);
mPrintResolution = 300;
mTextZoom = 1.0f;
XMapWindow(mDisplay, mDrawable);
#else
char *printservername = (char *)0;
if (!(printservername = getenv("XPDISPLAY"))) {
printservername = strdup("localhost:1");
PR_LOG(nsXPrintContextLM, PR_LOG_DEBUG, ("nsXPrintContext::Init()\n"));
int prefDepth = 24; /* 24 or 8 */
char *buf;
/* print on screen(="normal" Xserver) is "DEBUG" for now...
* maybe usefull for preview, too...
*/
#ifdef HACK_PRINTONSCREEN
if( XPRINTONSCREEN )
{
mPDisplay = (Display *)XOpenDisplay(nsnull);
mScreen = XDefaultScreenOfDisplay(mPDisplay);
xlib_rgb_init_with_depth(mPDisplay, mScreen, prefDepth);
mScreenNumber = XDefaultScreen(mPDisplay);
SetupWindow(0, 0, 1200, 1200);
mPrintResolution = 300;
mTextZoom = 1.0f;
XMapWindow(mPDisplay, mDrawable);
}
if (nsnull == mDisplay) {
if (!(mDisplay = XOpenDisplay(printservername))) {
fprintf(stderr,"failed to open display '%s'\n", printservername);
return NS_ERROR_FAILURE;
}
else
#endif /* HACK_PRINTONSCREEN */
{
unsigned short width, height;
XRectangle rect;
if( NS_FAILED( XPU_TRACE(SetupPrintContext(aSpec)) ) )
return NS_ERROR_FAILURE;
mScreen = XpGetScreenOfContext(mPDisplay, mPContext);
mScreenNumber = XScreenNumberOfScreen(mScreen);
xlib_rgb_init_with_depth(mPDisplay, mScreen, prefDepth);
XpGetPageDimensions(mPDisplay, mPContext, &width, &height, &rect);
SetupWindow(rect.x, rect.y, rect.width, rect.height);
mTextZoom = 2.4f; // should this be printer_DPI / display_DPI ?
XMapWindow(mPDisplay, mDrawable);
}
unsigned short width, height;
XRectangle rect;
SetupPrintContext(aSpec);
mScreen = XpGetScreenOfContext(mDisplay, mPContext);
mScreenNumber = XScreenNumberOfScreen(mScreen);
xlib_rgb_init_with_depth(mDisplay, mScreen, prefDepth);
XpGetPageDimensions(mDisplay, mPContext, &width, &height, &rect);
SetupWindow(rect.x, rect.y, rect.width, rect.height);
// mGC = XDefaultGCOfScreen(mScreen);
mTextZoom = 2.0f;
#endif
mPDisplay = mDisplay;
/* Set error handler and sync
* ToDo: unset handler after all is done - what about handler "stacking" ?
*/
(void)XSetErrorHandler(xerror_handler);
XSynchronize(mDisplay, True);
XSynchronize(mPDisplay, True);
return NS_OK;
}
NS_IMETHODIMP
nsXPrintContext::SetupWindow(int x, int y, int width, int height)
{
PR_LOG(nsXPrintContextLM, PR_LOG_DEBUG,
("nsXPrintContext::SetupWindow: x=%d y=%d width=%d height=%d\n",
x, y, width, height));
XSetWindowAttributes xattributes;
long xattributes_mask;
Window parent_win;
@ -124,154 +155,245 @@ nsXPrintContext::SetupWindow(int x, int y, int width, int height)
mHeight = height;
visual_info = xlib_rgb_get_visual_info();
parent_win = RootWindow(mDisplay, mScreenNumber);
xattributes.background_pixel = WhitePixel (mDisplay, mScreenNumber);
xattributes.border_pixel = BlackPixel (mDisplay, mScreenNumber);
parent_win = RootWindow(mPDisplay, mScreenNumber);
xattributes.background_pixel = WhitePixel (mPDisplay, mScreenNumber);
xattributes.border_pixel = BlackPixel (mPDisplay, mScreenNumber);
xattributes_mask |= CWBorderPixel | CWBackPixel;
#ifdef _USE_PRIMITIVE_CALL_
mVisual = visual_info->visual;
mDepth = visual_info->depth;
mDrawable = (Drawable) XCreateWindow(mDisplay, parent_win, x, y, width,
height, 2,
mDepth, InputOutput, mVisual, xattributes_mask,
&xattributes );
#else
mDrawable = (Drawable)XCreateSimpleWindow(mDisplay,
mDrawable = (Drawable)XCreateSimpleWindow(mPDisplay,
parent_win,
x, y,
width, height,
0, BlackPixel(mDisplay, mScreenNumber),
WhitePixel(mDisplay, mScreenNumber));
mDepth = XDefaultDepth(mDisplay, mScreenNumber);
mVisual = XDefaultVisual(mDisplay, mScreenNumber);
#endif
0, BlackPixel(mPDisplay, mScreenNumber),
WhitePixel(mPDisplay, mScreenNumber));
mDepth = XDefaultDepth(mPDisplay, mScreenNumber);
mVisual = XDefaultVisual(mPDisplay, mScreenNumber);
gcmask = GCBackground | GCForeground | GCFunction ;
gcvalues.background = WhitePixel(mDisplay, mScreenNumber);
gcvalues.foreground = BlackPixel(mDisplay, mScreenNumber);
gcvalues.background = WhitePixel(mPDisplay, mScreenNumber);
gcvalues.foreground = BlackPixel(mPDisplay, mScreenNumber);
gcvalues.function = GXcopy;
mGC = XCreateGC(mDisplay, mDrawable, gcmask, &gcvalues);
return NS_OK;
mGC = XCreateGC(mPDisplay, mDrawable, gcmask, &gcvalues); /* ToDo: Check for error */
return NS_OK;
}
NS_IMETHODIMP
nsXPrintContext::SetupPrintContext(nsIDeviceContextSpecXP *aSpec)
{
XPPrinterList plist;
int plistcnt;
PRBool isAPrinter;
PR_LOG(nsXPrintContextLM, PR_LOG_DEBUG, ("nsXPrintContext::SetupPrintContext()\n"));
int printSize;
float top, bottom, left, right;
char *buf;
char cbuf[128];
const int loglength = 128;
char logname[loglength];
// Get the Attributes
aSpec->GetToPrinter( isAPrinter );
aSpec->GetSize( printSize );
aSpec->GetTopMargin( top );
aSpec->GetBottomMargin( bottom );
aSpec->GetLeftMargin( left );
aSpec->GetRightMargin( right );
aSpec->GetToPrinter(mIsAPrinter);
aSpec->GetSize(printSize);
aSpec->GetTopMargin(top);
aSpec->GetBottomMargin(bottom);
aSpec->GetLeftMargin(left);
aSpec->GetRightMargin(right);
PR_LOG(nsXPrintContextLM, PR_LOG_DEBUG,
("nsXPrintContext::SetupPrintContext: borders top=%f, bottom=%f, left=%f, right=%f\n",
top, bottom, left, right));
/* get destination printer (we need this when printing to file as
* the printer DDX in Xprt generates the data...)
*/
aSpec->GetCommand(&buf);
// Check the output type
if (isAPrinter == PR_TRUE) {
aSpec->GetCommand( &buf );
} else {
aSpec->GetPath( &buf );
/* Are we "printing" to a file instead to the print queue ? */
if (!mIsAPrinter)
{
/* ToDo: Guess a matching file extension of user did not set one - Xprint
* currrently may use %s.ps, %s.pcl, %s.xwd, %s.pdf etc.
* Best idea would be to ask a "datatyping" service (like CDE's datatyping
* functions) what to-do...
*/
aSpec->GetPath(&mPrintFile);
PR_LOG(nsXPrintContextLM, PR_LOG_DEBUG, ("print to file '%s'\n", XPU_NULLXSTR(mPrintFile)));
if( (mPrintFile == nsnull) || (strlen(mPrintFile) == 0) )
return NS_ERROR_FAILURE;
}
plist = XpGetPrinterList(mDisplay, buf, &plistcnt);
mPContext = XpCreateContext(mDisplay, plist[0].name );
XpFreePrinterList(plist);
XpSetContext(mDisplay, mPContext);
/* get printer, either by "name" (foobar) or "name@display" (foobar@gaja:5)
* ToDo: report error to user (dialog)
*/
if( XpuGetPrinter(buf, &mPDisplay, &mPContext) != 1 )
return NS_ERROR_FAILURE;
// Set the Job attribute
if (!getlogin_r(logname, loglength)) {
sprintf(logname, "Mozilla-User");
}
sprintf(cbuf,"*job-owner: %s", logname);
XpSetAttributes(mDisplay, mPContext,
XPJobAttr,(char *)cbuf,XPAttrMerge);
/* set printer context
* WARNING: after this point it is no longer allows to change job attributes
* only after the XpSetContext() call the alllication is allowed to make
* assumptions about available fonts - otherwise you may get the wrong
* ones !!
*/
XPU_TRACE(XpSetContext(mPDisplay, mPContext));
/* get default printer reolution
* (note: if's AFAIK a Xprt configuration error when "default-printer-resolution"
* cannot be obtained - return with an error to avoid the case that we#re working
* with a faulty printer config...
* ToDo: Report error to user (dialog)
*/
if( XpuGetOneLongAttribute(mPDisplay, mPContext, XPDocAttr, "default-printer-resolution", &mPrintResolution) != 1 )
return NS_ERROR_FAILURE;
PR_LOG(nsXPrintContextLM, PR_LOG_DEBUG, ("print resolution %ld\n", (long)mPrintResolution));
/* We want to get events when Xp(Start|End)(Job|Page) requests are processed... */
XpSelectInput(mPDisplay, mPContext, XPPrintMask);
// Set the Document Attributes
// XpSetAttributes(mDisplay,mPContext, XPDocAttr,(char *)"*content-orientation: landscape",XPAttrMerge);
// XpSetAttributes(mPDisplay,mPContext, XPDocAttr,(char *)"*content-orientation: landscape",XPAttrMerge);
mPrintResolution = 300;
return NS_OK;
}
char *print_resolution = XpGetOneAttribute(mDisplay, mPContext, XPDocAttr,
(char *)"default-printer-resolution");
if (print_resolution) {
char *tmp_str = strrchr(print_resolution, ':');
if (tmp_str) {
tmp_str++;
mPrintResolution = atoi(tmp_str);
}
XFree(print_resolution);
}
/* MyConvertUCS2ToLocalEncoding:
* Note that this function is _only_ a _hack_ until RFE 73446
* (http://bugzilla.mozilla.org/show_bug.cgi?id=73446 - "RFE:
* Need NS_ConvertUCS2ToLocalEncoding() and
* NS_ConvertLocalEncodingToUCS2()") gets implemented...
* Below we need COMPOUNT_TEXT which usually is the same as the Xserver's
* local encoding - this hack should at least work for C/POSIX
* and *.UTF-8 locales...
*/
static
const char *MyConvertUCS2ToLocalEncoding( PRUnichar *str )
{
/* Use strdup() to avoid any silly effects...
*/
return PL_strdup(NS_ConvertUCS2toUTF8(str).get());
}
NS_IMETHODIMP
nsXPrintContext::BeginDocument( PRUnichar *aTitle )
{
PR_LOG(nsXPrintContextLM, PR_LOG_DEBUG, ("nsXPrintContext::BeginDocument()\n"));
char *s = nsnull,
*job_title;
if( aTitle != nsnull )
job_title = s = (char *)MyConvertUCS2ToLocalEncoding(aTitle);
else
job_title = "Mozilla document without title";
PR_LOG(nsXPrintContextLM, PR_LOG_DEBUG, ("nsXPrintContext::BeginDocument: document title: '%s'\n", XPU_NULLXSTR(job_title)));
/* Set the Job Attributes */
XpuSetJobTitle(mPDisplay, mPContext, job_title);
if( s != nsnull )
PL_strfree(s);
// Check the output type
if (isAPrinter == PR_TRUE) {
XpStartJob(mDisplay, XPSpool );
} else {
XpStartJob(mDisplay, XPGetData );
if(mIsAPrinter)
{
XPU_TRACE(XpStartJob(mPDisplay, XPSpool));
XPU_TRACE(XpuWaitForPrintNotify(mPDisplay, XPStartJobNotify));
}
else
{
XPU_TRACE(XpStartJob(mPDisplay, XPGetData));
if( XPU_TRACE(mXpuPrintToFileHandle = XpuPrintToFile(mPDisplay, mPContext, mPrintFile)) == nsnull )
{
PR_LOG(nsXPrintContextLM, PR_LOG_DEBUG,
("nsXPrintContext::BeginDocument(): XpuPrintToFile failure %s/(%d)\n",
strerror(errno), errno));
return NS_ERROR_FAILURE;
}
XPU_TRACE(XpuWaitForPrintNotify(mPDisplay, XPStartJobNotify));
}
return NS_OK;
}
NS_IMETHODIMP
nsXPrintContext::BeginDocument()
{
return NS_OK;
}
NS_IMETHODIMP
nsXPrintContext::BeginPage()
{
XpStartPage(mDisplay, mDrawable);
// Move the print window according to the given margin
// XMoveWindow(mDisplay, mDrawable, 100, 100);
// XMoveWindow(mPDisplay, mDrawable, 100, 100);
XPU_TRACE(XpStartPage(mPDisplay, mDrawable));
XPU_TRACE(XpuWaitForPrintNotify(mPDisplay, XPStartPageNotify));
return NS_OK;
}
NS_IMETHODIMP
nsXPrintContext::EndPage()
{
XpEndPage(mDisplay);
XPU_TRACE(XpEndPage(mPDisplay));
XPU_TRACE(XpuWaitForPrintNotify(mPDisplay, XPEndPageNotify));
return NS_OK;
}
NS_IMETHODIMP
nsXPrintContext::EndDocument()
{
XFlush(mDisplay);
XpEndJob(mDisplay);
XPU_TRACE(XpEndJob(mPDisplay));
XPU_TRACE(XpuWaitForPrintNotify(mPDisplay, XPEndJobNotify));
/* Are we printing to a file ? */
if( !mIsAPrinter )
{
NS_ASSERTION(nsnull != mXpuPrintToFileHandle, "mXpuPrintToFileHandle is null.");
if( XPU_TRACE(XpuWaitForPrintFileChild(mXpuPrintToFileHandle)) == XPGetDocFinished )
{
PR_LOG(nsXPrintContextLM, PR_LOG_DEBUG, ("XpuWaitForPrintFileChild returned success.\n"));
}
}
#ifdef HACK_PRINTONSCREEN
/* HACK: sleep 15secs if we're displaying to an "display" server
* see nsXPrintContext::Init and XprintOnScreen macro above - this is only used if
* we are printing to a normal Xserver and not to a Xprint server (e.g. in rare
* rare cases...)
*/
if( XpuCheckExtension(mPDisplay) != 1 )
{
sleep(15);
}
#endif /* HACK_PRINTONSCREEN */
// Cleanup things allocated along the way
XpDestroyContext(mDisplay, mPContext);
// XCloseDisplay(mDisplay);
XpDestroyContext(mPDisplay, mPContext);
mPContext = nsnull;
XCloseDisplay(mPDisplay);
mPDisplay = nsnull;
return NS_OK;
}
NS_IMETHODIMP
nsXPrintContext::DrawImage(nsIImage *aImage,
PRInt32 aSX, PRInt32 aSY, PRInt32 aSWidth, PRInt32 aSHeight,
PRInt32 aDX, PRInt32 aDY, PRInt32 aDWidth, PRInt32 aDHeight)
PRInt32 aSX, PRInt32 aSY, PRInt32 aSWidth, PRInt32 aSHeight,
PRInt32 aDX, PRInt32 aDY, PRInt32 aDWidth, PRInt32 aDHeight)
{
PRUint8 *image_bits = aImage->GetBits();
PRInt32 row_bytes = aImage->GetLineStride();
PRUint8 *image_bits = aImage->GetBits();
PRInt32 row_bytes = aImage->GetLineStride();
// XpSetImageResolution(mDisplay, mPContext, new_res, &prev_res);
xlib_draw_gray_image(mDrawable,
mGC,
aDX, aDY, aDWidth, aDHeight,
XLIB_RGB_DITHER_MAX,
image_bits + row_bytes * aSY + 3 * aDX,
row_bytes);
// XpSetImageResolution(mPDisplay, mPContext, new_res, &prev_res);
xlib_draw_gray_image(mDrawable,
mGC,
aDX, aDY, aDWidth, aDHeight,
XLIB_RGB_DITHER_MAX,
image_bits + row_bytes * aSY + 3 * aDX,
row_bytes);
// XpSetImageResolution(mDisplay, mPContext, prev_res, &new_res);
// XpSetImageResolution(mPDisplay, mPContext, prev_res, &new_res);
return NS_OK;
}
@ -279,47 +401,48 @@ nsXPrintContext::DrawImage(nsIImage *aImage,
// Draw the bitmap, this draw just has destination coordinates
NS_IMETHODIMP
nsXPrintContext::DrawImage(nsIImage *aImage,
PRInt32 aX, PRInt32 aY,
PRInt32 aWidth, PRInt32 aHeight)
PRInt32 aX, PRInt32 aY,
PRInt32 aWidth, PRInt32 aHeight)
{
PRInt32 width = aImage->GetWidth();
PRInt32 height = aImage->GetHeight();
PRUint8 *alphaBits = aImage->GetAlphaBits();
PRInt32 width = aImage->GetWidth();
PRInt32 height = aImage->GetHeight();
PRUint8 *alphaBits = aImage->GetAlphaBits();
PRInt32 alphaRowBytes = aImage->GetAlphaLineStride();
PRUint8 *image_bits = aImage->GetBits();
PRInt32 row_bytes = aImage->GetLineStride();
PRUint8 *image_bits = aImage->GetBits();
PRInt32 row_bytes = aImage->GetLineStride();
// XXX kipp: this is temporary code until we eliminate the
// width/height arguments from the draw method.
if ((aWidth != width) || (aHeight != height)) {
if ((aWidth != width) || (aHeight != height))
{
aWidth = width;
aHeight = height;
}
XImage *x_image = nsnull;
GC gc;
XGCValues gcv;
XImage *x_image = nsnull;
GC gc;
XGCValues gcv;
// Create gc clip-mask on demand
if ((alphaBits != nsnull) && (mAlphaPixmap == 0)) {
if (!mAlphaPixmap) {
mAlphaPixmap = XCreatePixmap(mDisplay,
RootWindow(mDisplay, mScreenNumber),
aWidth, aHeight, 1);
if ((alphaBits != nsnull) && (mAlphaPixmap == None)) {
if (mAlphaPixmap==None) {
mAlphaPixmap = XCreatePixmap(mPDisplay,
RootWindow(mPDisplay, mScreenNumber),
aWidth, aHeight, 1); /* ToDo: Check for error */
}
// Make an image out of the alpha-bits created by the image library
x_image = XCreateImage(mDisplay, mVisual,
1, /* visual depth...1 for bitmaps */
/* Make an image out of the alpha-bits created by the image library (ToDo: check for error) */
x_image = XCreateImage(mPDisplay, mVisual,
1, /* visual depth...1 for bitmaps */
XYPixmap,
0, /* x offset, XXX fix this */
(char *)alphaBits, /* cast away our sign. */
0, /* x offset, XXX fix this */
(char *)alphaBits, /* cast away our sign. */
aWidth,
aHeight,
32,/* bitmap pad */
alphaRowBytes); /* bytes per line */
32, /* bitmap pad */
alphaRowBytes); /* bytes per line */
x_image->bits_per_pixel=1;
x_image->bits_per_pixel = 1;
/* Image library always places pixels left-to-right MSB to LSB */
x_image->bitmap_bit_order = MSBFirst;
@ -341,73 +464,67 @@ nsXPrintContext::DrawImage(nsIImage *aImage,
// the image we just created.
memset(&gcv, 0, sizeof(XGCValues));
gcv.function = GXcopy;
gc = XCreateGC(mDisplay, mAlphaPixmap, GCFunction, &gcv);
gc = XCreateGC(mPDisplay, mAlphaPixmap, GCFunction, &gcv);
XPutImage(mDisplay, mAlphaPixmap, gc, x_image, 0, 0, 0, 0,
XPutImage(mPDisplay, mAlphaPixmap, gc, x_image, 0, 0, 0, 0,
aWidth, aHeight);
XFreeGC(mDisplay, gc);
XFreeGC(mPDisplay, gc);
// Now we are done with the temporary image
x_image->data = 0; /* Don't free the IL_Pixmap's bits. */
XDestroyImage(x_image);
}
if (nsnull == mImagePixmap) {
if (mImagePixmap == None) {
// Create an off screen pixmap to hold the image bits.
mImagePixmap = XCreatePixmap(mDisplay,
RootWindow(mDisplay, mScreenNumber),
aWidth, aHeight,
mDepth);
XSetClipOrigin(mDisplay, mGC, 0, 0);
XSetClipMask(mDisplay, mGC, None);
mImagePixmap = XCreatePixmap(mPDisplay,
RootWindow(mPDisplay, mScreenNumber),
aWidth, aHeight,
mDepth);
XSetClipOrigin(mPDisplay, mGC, 0, 0);
XSetClipMask(mPDisplay, mGC, None);
GC gc;
XGCValues xvalues;
unsigned long xvalues_mask;
xvalues.function = GXcopy;
xvalues.fill_style = FillSolid;
xvalues.arc_mode = ArcPieSlice;
xvalues.subwindow_mode = ClipByChildren;
xvalues.function = GXcopy;
xvalues.fill_style = FillSolid;
xvalues.arc_mode = ArcPieSlice;
xvalues.subwindow_mode = ClipByChildren;
xvalues.graphics_exposures = True;
xvalues_mask = GCFunction | GCFillStyle | GCArcMode | GCSubwindowMode | GCGraphicsExposures;
gc = XCreateGC(mDisplay, mImagePixmap, xvalues_mask, &xvalues);
// XpSetImageResolution(mDisplay, mPContext, new_res, &prev_res);
#ifdef _USE_PRIMITIVE_CALL_
xlib_draw_gray_image(mImagePixmap,
gc,
0, 0, aWidth, aHeight,
XLIB_RGB_DITHER_MAX,
image_bits,
row_bytes);
#else
xlib_draw_rgb_image (mImagePixmap,
gc,
0, 0, aWidth, aHeight,
XLIB_RGB_DITHER_NONE,
image_bits, row_bytes);
#endif
// XpSetImageResolution(mDisplay, mPContext, prev_res, &new_res);
gc = XCreateGC(mPDisplay, mImagePixmap, xvalues_mask, &xvalues);
// XpSetImageResolution(mPDisplay, mPContext, new_res, &prev_res);
xlib_draw_rgb_image(mImagePixmap,
gc,
0, 0, aWidth, aHeight,
XLIB_RGB_DITHER_NONE,
image_bits, row_bytes);
// XpSetImageResolution(mPDisplay, mPContext, prev_res, &new_res);
}
if (nsnull != mAlphaPixmap)
if (mAlphaPixmap != None)
{
// set up the gc to use the alpha pixmap for clipping
XSetClipOrigin(mDisplay, mGC, aX, aY);
XSetClipMask(mDisplay, mGC, mAlphaPixmap);
XSetClipOrigin(mPDisplay, mGC, aX, aY);
XSetClipMask(mPDisplay, mGC, mAlphaPixmap);
}
// copy our off screen pixmap onto the window.
XCopyArea(mDisplay, // display
XCopyArea(mPDisplay, // display
mImagePixmap, // source
mDrawable, // dest
mGC, // GC
0, 0, // xsrc, ysrc
mDrawable, // dest
mGC, // GC
0, 0, // xsrc, ysrc
aWidth, aHeight, // width, height
aX, aY); // xdest, ydest
aX, aY); // xdest, ydest
if (mAlphaPixmap != nsnull) {
XSetClipOrigin(mDisplay, mGC, 0, 0);
XSetClipMask(mDisplay, mGC, None);
if (mAlphaPixmap != None)
{
XSetClipOrigin(mPDisplay, mGC, 0, 0);
XSetClipMask(mPDisplay, mGC, None);
}
return NS_OK;
@ -415,14 +532,16 @@ nsXPrintContext::DrawImage(nsIImage *aImage,
NS_IMETHODIMP nsXPrintContext::GetPrintResolution(int &aPrintResolution) const
{
PR_LOG(nsXPrintContextLM, PR_LOG_DEBUG, ("nsXPrintContext::GetPrintResolution()\n"));
aPrintResolution = mPrintResolution;
return NS_OK;
}
NS_IMETHODIMP nsXPrintContext::SetForegroundColor(nscolor aColor)
{
xlib_rgb_gc_set_foreground(mGC,
NS_RGB(NS_GET_B(aColor), NS_GET_G(aColor), NS_GET_R(aColor)));
NS_RGB(NS_GET_B(aColor), NS_GET_G(aColor), NS_GET_R(aColor)));
return NS_OK;
}

Просмотреть файл

@ -18,6 +18,8 @@
* Rights Reserved.
*
* Contributor(s):
* Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>
*
*/
@ -44,7 +46,7 @@ public:
NS_IMETHOD Init(nsIDeviceContextSpecXP *aSpec);
NS_IMETHOD BeginPage();
NS_IMETHOD EndPage();
NS_IMETHOD BeginDocument();
NS_IMETHOD BeginDocument(PRUnichar * aTitle);
NS_IMETHOD EndDocument();
GC GetGC(void) { return mGC; }
@ -52,8 +54,8 @@ public:
Screen * GetScreen() { return mScreen; }
Visual * GetVisual() { return mVisual; }
int GetDepth() { return mDepth; }
int GetHeight() { return mHeight; }
int GetWidth() { return mWidth; }
int GetHeight() { return mHeight; }
int GetWidth() { return mWidth; }
int GetScreenNumber() { return XScreenNumberOfScreen(mScreen); }
Display * GetDisplay() { return mPDisplay; }
@ -72,30 +74,28 @@ public:
NS_IMETHOD SetForegroundColor(nscolor aColor);
private:
static Display * mDisplay;
Display * mPDisplay;
Screen * mScreen;
Visual * mVisual;
Display *mPDisplay;
Screen *mScreen;
Visual *mVisual;
GC mGC;
Drawable mDrawable;
XImage * mImage;
int mDepth;
int mScreenNumber;
XImage *mImage;
int mDepth;
int mScreenNumber;
Pixmap mAlphaPixmap;
Pixmap mImagePixmap;
int mWidth;
int mHeight;
int mWidth;
int mHeight;
XPContext mPContext;
int mPrintResolution;
float mTextZoom;
char *mPrintServerName;
char *mPrinterName;
char *mAttrPool;
PRBool mIsAPrinter;
char *mPrintFile; /* file to "print" to */
void *mXpuPrintToFileHandle; /* handle for XpuPrintToFile/XpuWaitForPrintFileChild when printing to file */
long mPrintResolution;
float mTextZoom;
NS_IMETHOD SetupWindow(int x, int y, int width, int height);
NS_IMETHOD SetupPrintContext(nsIDeviceContextSpecXP *aSpec);
};
#endif
#endif /* !_XPCONTEXT_H_ */

Просмотреть файл

445
gfx/src/xprint/xprintutil.c Normal file
Просмотреть файл

@ -0,0 +1,445 @@
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (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.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the X11 print system utilities library.
*
* The Initial Developer of the Original Code is Roland Mainz
* <roland.mainz@informatik.med.uni-giessen.de>.
* All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <limits.h>
#include <errno.h>
#define NeedFunctionPrototypes (1) /* is this legal from within an app. !? */
#include <X11/Xlibint.h>
#include <X11/extensions/Print.h>
#include <X11/Intrinsic.h>
#include "xprintutil.h"
/*
** XprintUtil functions start with Xpu
**
*/
int XpuCheckExtension( Display *pdpy )
{
char *display = DisplayString(pdpy);
short major = 0,
minor = 0;
if( XpQueryVersion(pdpy, &major, &minor) != 0 )
{
XPU_DEBUG_ONLY(printf("XpuCheckExtension: XpQueryVersion '%s' %d %d\n", XPU_NULLXSTR(display), (int)major, (int)minor));
return(1);
}
else
{
XPU_DEBUG_ONLY(printf("XpuCheckExtension: XpQueryVersion '%s' returned 0(=Xprint not supported)\n", XPU_NULLXSTR(display)));
}
return(0);
}
char *XpuGetXpServerList( void )
{
/* BUG/TODO: XpServerList resource needs to be sourced first, then append
* contents of XPSERVERLIST, then remove duplicates...
*/
return(getenv("XPSERVERLIST"));
}
static
int XpuGetPrinter2( char *printer, char *display, Display **pdpyptr, XPContext *pcontextptr )
{
Display *pdpy;
XPContext pcontext;
XPU_DEBUG_ONLY(printf("XpuGetPrinter2: probing display '%s' for '%s'\n", XPU_NULLXSTR(display), XPU_NULLXSTR(printer)));
if( (pdpy = XOpenDisplay(display)) != NULL )
{
if( XpuCheckExtension(pdpy) )
{
XPPrinterList list;
int list_count;
/* get list of available printers... */
list = XpGetPrinterList(pdpy, printer, &list_count);
if( list != NULL ) XpFreePrinterList(list);
/* ...and check if printer exists... */
if( (list != NULL) && (list_count > 0) )
{
if( (pcontext = XpCreateContext(pdpy, printer)) != NULL )
{
*pdpyptr = pdpy;
*pcontextptr = pcontext;
return(1);
}
XPU_DEBUG_ONLY(printf("XpuGetPrinter2: could not create print context for '%s'\n", XPU_NULLXSTR(printer)));
}
}
else
{
XPU_DEBUG_ONLY(printf("display '%s' does not support the Xprint extension\n", XPU_NULLXSTR(display)));
}
XCloseDisplay(pdpy);
return(0);
}
else
{
XPU_DEBUG_ONLY(printf("could not open display '%s'\n", XPU_NULLXSTR(display)));
return(0);
}
}
/* acceps "printer" or "printer@display" */
int XpuGetPrinter( char *printername, Display **pdpyptr, XPContext *pcontextptr )
{
Display *pdpy;
XPContext pcontext;
char *s;
char *tok_lasts;
*pdpyptr = NULL;
*pcontextptr = NULL;
XPU_DEBUG_ONLY(printf("XpuGetPrinter: looking for '%s'\n", XPU_NULLXSTR(printername)));
/* strtok_r will modify string - duplicate it first... */
printername = (char *)strdup(printername);
if( (s = (char *)strtok_r(printername, "@", &tok_lasts)) != NULL )
{
char *name = s;
char *display = (char *)strtok_r(NULL, "@", &tok_lasts);
/* if we have a display - open it and grab printer */
if( display != NULL )
{
if( XpuGetPrinter2(name, display, pdpyptr, pcontextptr) )
{
free(printername);
return(1);
}
}
/* if we did not get a display, travel througth all displays */
else
{
char *sl = XpuGetXpServerList();
if( sl != NULL )
{
for( display = (char *)strtok_r(sl, " ", &tok_lasts) ;
display != NULL ;
display = (char *)strtok_r(NULL, " ", &tok_lasts) )
{
if( XpuGetPrinter2(name, display, pdpyptr, pcontextptr) )
{
free(printername);
return(1);
}
}
}
}
}
free(printername);
XPU_DEBUG_ONLY(printf("XpuGetPrinter: failure\n"));
return(0);
}
void XpuSetOneAttribute( Display *pdpy, XPContext pcontext,
XPAttributes type, char *attribute_name, char *value, XPAttrReplacement replacement_rule )
{
char *buffer =
#ifdef XPU_USE_NSPR
PR_Malloc((PRUint32)
#else
Xmalloc(
#endif
strlen(attribute_name)+strlen(value)+8);
if( buffer != NULL )
{
sprintf(buffer, "%s: %s", attribute_name, value);
XpSetAttributes(pdpy, pcontext, type, buffer, replacement_rule);
#ifdef XPU_USE_NSPR
PR_Free
#else
XFree
#endif
(buffer);
}
}
/* enumerate attribute values - work in porgress */
char *XpuEmumerateXpAttributeValue( char *value, void **context )
{
/* BUG: This does not work for quoted attribute values
* A good example is the enumeration of supported paper sizes:
* "{'' {na-letter False {6.3500 209.5500 6.3500 273.0500}} {executive False {6.3500 177.7500 6.3500 260.3500}} {na-legal False {6.3500 209.5500 6.3500 349.2500}} {iso-a4 False {6.3500 203.6500 6.3500 290.6500}} {iso-designated-long False {6.3500 103.6500 6.3500 213.6500}} {na-number-10-envelope False {6.3500 98.4500 6.3500 234.9500}} }"
{''
{
na-letter
False
{6.3500 209.5500 6.3500 273.0500}
}
{
executive
False
{6.3500 177.7500 6.3500 260.3500}
}
{
na-legal
False
{6.3500 209.5500 6.3500 349.2500}
}
{
iso-a4
False
{6.3500 203.6500 6.3500 290.6500}
}
{
iso-designated-long
False
{6.3500 103.6500 6.3500 213.6500}
}
{
na-number-10-envelope
False
{6.3500 98.4500 6.3500 234.9500}
}
}
* ToDo:
* 1. Write a parser which grabs the 1st level of bracket pairs and
* enumerate these items (six items in this example).
* 2. Write enumeration functions for single attribute types with
* complex content.
*/
return( (char *)strtok_r(value, " ", (char **)context) );
}
/* check if attribute value is supported or not */
int XpuCheckSupported( Display *pdpy, XPContext pcontext, XPAttributes type, char *attribute_name, char *query )
{
char *value,
*s;
void *tok_lasts;
value = XpGetOneAttribute(pdpy, pcontext, type, attribute_name);
XPU_DEBUG_ONLY(printf("XpuCheckSupported: XpGetOneAttribute(%s) returned '%s'\n", XPU_NULLXSTR(attribute_name), XPU_NULLXSTR(value)));
if( value != NULL )
{
for( s = XpuEmumerateXpAttributeValue(value, &tok_lasts) ; s != NULL ; s = XpuEmumerateXpAttributeValue(NULL, &tok_lasts) )
{
XPU_DEBUG_ONLY(printf("XpuCheckSupported: probing '%s'=='%s'\n", XPU_NULLXSTR(s), XPU_NULLXSTR(query)));
if( !strcmp(s, query) )
{
XFree(value);
return(1);
}
}
XFree(value);
}
return(0);
}
int XpuSetJobTitle( Display *pdpy, XPContext pcontext, char *title )
{
if( XpuCheckSupported(pdpy, pcontext, XPPrinterAttr, "job-attributes-supported", "job-name") )
{
XpuSetOneAttribute(pdpy, pcontext, XPJobAttr, "*job-name", title, XPAttrMerge);
return(1);
}
else
{
XPU_DEBUG_ONLY(printf("XpuSetJobTitle: XpuCheckSupported failed for '%s'\n", XPU_NULLXSTR(title)));
return(0);
}
}
int XpuSetContentOrientation( Display *pdpy, XPContext pcontext, XPAttributes type, char *orientation )
{
if( XpuCheckSupported(pdpy, pcontext, XPPrinterAttr, "content-orientations-supported", orientation) )
{
XpuSetOneAttribute(pdpy, pcontext, type, "*content-orientation", orientation, XPAttrMerge);
}
else
{
XPU_DEBUG_ONLY(printf("XpuSetContentOrientation: XpuCheckSupported failed for '%s'\n", XPU_NULLXSTR(orientation)));
return(0);
}
}
int XpuGetOneLongAttribute( Display *pdpy, XPContext pcontext, XPAttributes type, char *attribute_name, long *result )
{
char *s = XpGetOneAttribute(pdpy, pcontext, type, attribute_name);
if( (s != NULL) && (strlen(s) > 0) )
{
long tmp;
XPU_DEBUG_ONLY(printf("XpuGetOneLongAttribute: '%s' got '%s'\n", XPU_NULLXSTR(attribute_name), XPU_NULLXSTR(s)));
tmp = strtol(s, (char **)NULL, 10);
if( !(((tmp == 0L) || (tmp == LONG_MIN) || (tmp == LONG_MAX)) &&
((errno == ERANGE) || (errno == EINVAL))) )
{
*result = tmp;
XFree(s);
XPU_DEBUG_ONLY(printf("XpuGetOneLongAttribute: result %ld\n", *result));
return(1);
}
}
if( s != NULL ) XFree(s);
puts("XpuGetOneLongAttribute failed\n");
return(0);
}
double XpuGetXDPI( Screen *pscreen )
{
double xres;
/* from X11R6.5.1/xc/programs/xdpyinfo/xdpyinfo.c:
* there are 2.54 centimeters to an inch; so there are 25.4 millimeters.
*
* dpi = N pixels / (M millimeters / (25.4 millimeters / 1 inch))
* = N pixels / (M inch / 25.4)
* = N * 25.4 pixels / M inch
*/
xres = ((((double) WidthOfScreen(pscreen)) * 25.4) /
((double) WidthMMOfScreen(pscreen)));
return(xres);
}
double XpuGetYDPI( Screen *pscreen )
{
double yres;
/* from X11R6.5.1/xc/programs/xdpyinfo/xdpyinfo.c:
* there are 2.54 centimeters to an inch; so there are 25.4 millimeters.
*
* dpi = N pixels / (M millimeters / (25.4 millimeters / 1 inch))
* = N pixels / (M inch / 25.4)
* = N * 25.4 pixels / M inch
*/
yres = ((((double) HeightOfScreen(pscreen)) * 25.4) /
((double) HeightMMOfScreen(pscreen)));
return(yres);
}
#ifdef DEBUG
/* debug only */
void dumpXpAttributes( Display *pdpy, XPContext pcontext )
{
/* BUG: values from XpuGet*Attributes should be passed to XFree() after use... :-) */
printf("------------------------------------------------\n");
printf("--> Job\n%s\n", XpuGetJobAttributes(pdpy, pcontext));
printf("--> Doc\n%s\n", XpuGetDocAttributes(pdpy, pcontext));
printf("--> Page\n%s\n", XpuGetPageAttributes(pdpy, pcontext));
printf("--> Printer\n%s\n", XpuGetPrinterAttributes(pdpy, pcontext));
printf("--> Server\n%s\n", XpuGetServerAttributes(pdpy, pcontext));
printf("image resolution %d\n", (int)XpGetImageResolution(pdpy, pcontext));
printf("------------------------------------------------\n");
}
#endif /* DEBUG */
/* BUG: Is it really neccesary that this function eats-up all other events ? */
void XpuWaitForPrintNotify( Display *pdpy, int detail )
{
static int event_base_return = -1,
error_base_return = -1;
XEvent ev;
/* get extension event_base if we did not get it yet (and if Xserver does not
* support extension do not wait for events which will never be send... :-)
*/
if( (event_base_return == -1) && (error_base_return == -1) )
{
int myevent_base_return, myerror_base_return;
if( XpQueryExtension(pdpy, &myevent_base_return, &myerror_base_return) == False )
{
XPU_DEBUG_ONLY(printf("XpuWaitForPrintNotify: XpQueryExtension failed\n"));
return;
}
/* be sure we don't get in trouble if two threads try the same thing :-)
* Bug/issue: Is it gurantteed that two different Xprt server's return the same values here ??
*/
event_base_return = myevent_base_return;
error_base_return = myerror_base_return;
}
do
{
XNextEvent(pdpy, &ev);
if( ev.type != (event_base_return+XPPrintNotify) )
{
XPU_DEBUG_ONLY(printf("XpuWaitForPrintNotify: Killing non-PrintNotify event %d/%d while waiting for %d/%d\n",
(int)ev.type, (int)((XPPrintEvent *)(&ev))->detail,
(int)(event_base_return+XPPrintNotify), detail));
}
} while( !((ev.type == (event_base_return+XPPrintNotify)) && (((XPPrintEvent *)(&ev))->detail == detail)) );
}
/* EOF. */

Просмотреть файл

@ -0,0 +1,89 @@
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (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.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the X11 print system utilities library.
*
* The Initial Developer of the Original Code is Roland Mainz
* <roland.mainz@informatik.med.uni-giessen.de>.
* All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*/
/* I don't know how to make this "better" yet... ;-( */
#ifdef USE_MOZILLA_TYPES
#include <prmem.h>
#include <prthread.h>
#define XPU_USE_NSPR 1
#define XPU_USE_THREADS 1
#endif /* USE_MOZILLA_TYPES */
#ifdef DEBUG
/* trace function calls */
#define XPU_TRACE(EX) (puts(#EX),EX)
/* trace function calls in child */
#define XPU_TRACE_CHILD(EX) (puts("child: " #EX),EX)
/* execute function EX only in debug mode */
#define XPU_DEBUG_ONLY(EX) (EX)
#else
#define XPU_TRACE(EX) (EX)
#define XPU_TRACE_CHILD(EX) (EX)
#define XPU_DEBUG_ONLY(EX)
#endif /* DEBUG */
/* debug: replace NULLptrs with "<NULL>" string */
#define XPU_NULLXSTR(s) (((s)!=NULL)?(s):("<NULL>"))
/* prototypes */
_XFUNCPROTOBEGIN
int XpuCheckExtension( Display *pdpy );
char *XpuGetXpServerList( void );
int XpuGetPrinter( char *printername, Display **pdpyptr, XPContext *pcontextptr );
void XpuSetOneAttribute( Display *pdpy, XPContext pcontext,
XPAttributes type, char *attribute_name, char *value, XPAttrReplacement replacement_rule );
char *XpuEmumerateXpAttributeValue( char *value, void **context );
int XpuCheckSupported( Display *pdpy, XPContext pcontext, XPAttributes type, char *attribute_name, char *query );
int XpuSetJobTitle( Display *pdpy, XPContext pcontext, char *title );
int XpuSetContentOrientation( Display *pdpy, XPContext pcontext, XPAttributes type, char *orientation );
int XpuGetOneLongAttribute( Display *pdpy, XPContext pcontext, XPAttributes type, char *attribute_name, long *result );
double XpuGetXDPI( Screen *pscreen );
double XpuGetYDPI( Screen *pscreen );
void dumpXpAttributes( Display *pdpy, XPContext pcontext );
void XpuSetContext( Display *pdpy, XPContext pcontext );
void XpuWaitForPrintNotify( Display *pdpy, int detail );
#define XpuGetJobAttributes( pdpy, pcontext ) XpGetAttributes( (pdpy), (pcontext), XPJobAttr )
#define XpuGetDocAttributes( pdpy, pcontext ) XpGetAttributes( (pdpy), (pcontext), XPDocAttr )
#define XpuGetPageAttributes( pdpy, pcontext ) XpGetAttributes( (pdpy), (pcontext), XPPageAttr )
#define XpuGetPrinterAttributes( pdpy, pcontext ) XpGetAttributes( (pdpy), (pcontext), XPPrinterAttr )
#define XpuGetServerAttributes( pdpy, pcontext ) XpGetAttributes( (pdpy), (pcontext), XPServerAttr )
void *XpuPrintToFile( Display *pdpy, XPContext pcontext, char *filename );
XPGetDocStatus XpuWaitForPrintFileChild( void *handle );
_XFUNCPROTOEND
/* EOF. */

Просмотреть файл

@ -0,0 +1,466 @@
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (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.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the X11 print system utilities library.
*
* The Initial Developer of the Original Code is Roland Mainz
* <roland.mainz@informatik.med.uni-giessen.de>.
* All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <limits.h>
#include <errno.h>
#ifdef XPU_USE_THREADS
#include <time.h>
#include <pthread.h>
#else
#include <wait.h>
#endif /* XPU_USE_THREADS */
#include <unistd.h>
#include <sys/time.h>
#define NeedFunctionPrototypes (1) /* is this legal from within an app. !? */
#include <X11/Xlibint.h>
#include <X11/extensions/Print.h>
#include <X11/Intrinsic.h>
#include "xprintutil.h"
/* local prototypes */
#ifdef DEBUG
static void PrintXPGetDocStatus( XPGetDocStatus status );
#endif
static Bool XNextEventTimeout( Display *display, XEvent *event_return, struct timeval *timeout );
static void MyPrintToFileProc( Display *pdpy, XPContext pcontext, unsigned char *data, unsigned int data_len, XPointer client_data );
static void MyFinishProc( Display *pdpy, XPContext pcontext, XPGetDocStatus status, XPointer client_data );
#ifdef XPU_USE_NSPR
static void PrintToFile_Consumer( void *handle );
#else
static void *PrintToFile_Consumer( void *handle );
#endif
#ifdef DEBUG
/* DEBUG: Print XPGetDocStatus */
static
void PrintXPGetDocStatus( XPGetDocStatus status )
{
switch(status)
{
case XPGetDocFinished: puts("PrintXPGetDocStatus: XPGetDocFinished"); break;
case XPGetDocSecondConsumer: puts("PrintXPGetDocStatus: XPGetDocSecondConsumer"); break;
case XPGetDocError: puts("PrintXPGetDocStatus: XPGetDocError"); break;
default: puts("PrintXPGetDocStatus: <unknown value"); break;
}
}
#endif /* DEBUG */
/* XNextEvent() with timeout */
static
Bool XNextEventTimeout( Display *display, XEvent *event_return, struct timeval *timeout )
{
int res;
fd_set readfds;
int display_fd = ConnectionNumber(display);
/* small shortcut... */
if( timeout == NULL )
{
XNextEvent(display, event_return);
return(True);
}
FD_ZERO(&readfds);
FD_SET(display_fd, &readfds);
/* Note/bug: In the case of internal X events (like used to trigger callbacks
* registered by XpGetDocumentData()&co.) select() will return with "new info"
* - but XNextEvent() below processes these _internal_ events silently - and
* will block if there are no other non-internal events.
* The workaround here is to check with XEventsQueued() if there are non-internal
* events queued - if not select() will be called again - unfortunately we use
* the old timeout here instead of the "remaining" time... (this only would hurt
* if the timeout would be really long - but for current use with values below
* 1/2 secs it does not hurt... =:-)
*/
while( XEventsQueued(display, QueuedAfterFlush) == 0 )
{
res = select(display_fd+1, &readfds, NULL, NULL, timeout);
switch(res)
{
case -1: /* select() error - should not happen */
perror("XNextEventTimeout: select() failure");
return(False);
case 0: /* timeout */
return(False);
}
}
XNextEvent(display, event_return);
return(True);
}
#ifdef XPU_USE_THREADS
/**
** XpuPrintToFile() - threaded version
** Create consumer thread which creates it's own display connection to print server
** (a 2nd display connection/thread is required to avoid deadlocks within Xlib),
** registers (Xlib-internal) consumer callback (via XpGetDocumentData(3Xp)) and
** processes/eats all incoming events via MyPrintToFileProc(). A final call to
** MyPrintToFileProc() cleans-up all stuff and sets the "done" flag.
** Note that these callbacks are called directly by Xlib while waiting for events in
** XNextEvent() because XpGetDocumentData() registeres them as "internal" callbacks,
** e.g. XNextEvent() does _not_ return before/after processing these events !!
**
** Usage:
** XpStartJob(pdpy, XPGetData);
** handle = XpuPrintToFile(pdpy, pcontext, "myfile");
** // render something
** XpEndJob(); // or XpCancelJob()
** status = XpuWaitForPrintFileChild(handle);
**
*/
typedef struct
{
#ifdef XPU_USE_NSPR
PRThread *prthread;
#else
pthread_t tid;
#endif
char *displayname;
Display *pdpy;
XPContext pcontext;
char *file_name;
FILE *file;
XPGetDocStatus status;
Bool done;
} MyPrintFileData;
void *XpuPrintToFile( Display *pdpy, XPContext pcontext, char *filename )
{
MyPrintFileData *mpfd; /* warning: shared between threads !! */
if( (mpfd = malloc(sizeof(MyPrintFileData))) == NULL )
return(NULL);
mpfd->displayname = DisplayString(pdpy);
mpfd->pdpy = NULL;
mpfd->pcontext = pcontext;
mpfd->file_name = filename;
mpfd->file = NULL;
mpfd->status = XPGetDocError;
/* make sure we can open the file for writing */
if( (mpfd->file = fopen(mpfd->file_name, "w")) == NULL )
{
/* fopen() error */
free(mpfd);
return(NULL);
}
/* its important to flush before we start the consumer thread,
* to make sure that the XpStartJob gets through first in the parent
*/
XFlush(pdpy);
#ifdef XPU_USE_NSPR
if( (mpfd->prthread = PR_CreateThread(PR_SYSTEM_THREAD, PrintToFile_Consumer, mpfd, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0)) == NULL )
#else
if( pthread_create(&(mpfd->tid), NULL, PrintToFile_Consumer, mpfd) != 0 )
#endif
{
/* pthread_create() error */
fclose(mpfd->file);
free(mpfd);
return(NULL);
}
/* we're still in the parent */
XPU_DEBUG_ONLY(printf("### parent started consumer thread.\n" ));
return(mpfd);
}
XPGetDocStatus XpuWaitForPrintFileChild( void *handle )
{
MyPrintFileData *mpfd = (MyPrintFileData *)handle;
void *res;
XPGetDocStatus status;
#ifdef XPU_USE_NSPR
if( PR_JoinThread(mpfd->prthread) != PR_SUCCESS )
perror("XpuWaitForPrintFileChild: PR_JoinThread() failure"); /* fixme(later): use NSPR error handling calls... */
#else
if( XPU_TRACE(pthread_join(mpfd->tid, &res)) != 0 )
perror("XpuWaitForPrintFileChild: pthread_join() failure");
#endif
status = mpfd->status;
free(handle);
XPU_DEBUG_ONLY(PrintXPGetDocStatus(status));
return(status);
}
#else /* XPU_USE_THREADS */
/**
** XpuPrintToFile() - fork() version
** Create consumer thread which creates it's own display connection to print server
** (a 2nd display connection/process is required to avoid deadlocks within Xlib),
** registers (Xlib-internal) consumer callback (via XpGetDocumentData(3Xp)) and
** processes/eats all incoming events via MyPrintToFileProc(). A final call to
** MyPrintToFileProc() cleans-up all stuff and sets the "done" flag.
** Note that these callbacks are called directly by Xlib while waiting for events in
** XNextEvent() because XpGetDocumentData() registeres them as "internal" callbacks,
** e.g. XNextEvent() does _not_ return before/after processing these events !!
**
** Usage:
** XpStartJob(pdpy, XPGetData);
** handle = XpuPrintToFile(pdpy, pcontext, "myfile");
** // render something
** XpEndJob(); // or XpCancelJob()
** status = XpuWaitForPrintFileChild(handle);
**
*/
typedef struct
{
pid_t pid;
int pipe[2]; /* child-->parent communication pipe */
char *displayname;
Display *pdpy;
XPContext pcontext;
char *file_name;
FILE *file;
XPGetDocStatus status;
Bool done;
} MyPrintFileData;
void *XpuPrintToFile( Display *pdpy, XPContext pcontext, char *filename )
{
MyPrintFileData *mpfd;
if( (mpfd = malloc(sizeof(MyPrintFileData))) == NULL )
return(NULL);
/* create pipe */
if( pipe(mpfd->pipe) == -1 )
{
/* this should never happen, but... */
perror("XpuPrintToFile: cannot create pipe");
free(mpfd);
return(NULL);
}
mpfd->displayname = DisplayString(pdpy);
mpfd->pcontext = pcontext;
mpfd->file_name = filename;
mpfd->file = NULL;
mpfd->status = XPGetDocError;
/* make sure we can open the file for writing */
if( (mpfd->file = fopen(mpfd->file_name, "w")) == NULL )
{
/* fopen() error */
close(mpfd->pipe[1]);
close(mpfd->pipe[0]);
free(mpfd);
return(NULL);
}
/* its important to flush before we fork, to make sure that the
* XpStartJob gets through first in the parent
*/
XFlush(pdpy);
mpfd->pid = fork();
if( mpfd->pid == 0 )
{
/* we're now in the fork()'ed child */
PrintToFile_Consumer(mpfd);
}
else if( mpfd->pid < 0 )
{
/* fork() error */
close(mpfd->pipe[1]);
close(mpfd->pipe[0]);
fclose(mpfd->file);
free(mpfd);
return(NULL);
}
/* we're still in the parent */
XPU_DEBUG_ONLY(printf("### parent fork()'ed consumer child.\n"));
/* child will write into file - we don't need it anymore here... :-) */
fclose(mpfd->file);
close(mpfd->pipe[1]);
return(mpfd);
}
XPGetDocStatus XpuWaitForPrintFileChild( void *handle )
{
MyPrintFileData *mpfd = (MyPrintFileData *)handle;
siginfo_t res;
XPGetDocStatus status = XPGetDocError; /* used when read() from pipe fails */
if( XPU_TRACE(waitid(P_PID, mpfd->pid, &res, WEXITED)) == -1 )
perror("XpuWaitForPrintFileChild: waitid failure");
/* read the status from the child */
if( read(mpfd->pipe[0], &status, sizeof(XPGetDocStatus)) != sizeof(XPGetDocStatus) )
{
perror("XpuWaitForPrintFileChild: can't read XPGetDocStatus");
}
close(mpfd->pipe[0]);
free(handle);
XPU_DEBUG_ONLY(PrintXPGetDocStatus(status));
return(status);
}
#endif /* XPU_USE_THREADS */
static
void MyPrintToFileProc( Display *pdpy,
XPContext pcontext,
unsigned char *data,
unsigned int data_len,
XPointer client_data )
{
MyPrintFileData *mpfd = (MyPrintFileData *)client_data;
/* write to the file */
XPU_TRACE_CHILD((void)fwrite(data, data_len, 1, mpfd->file)); /* what about error handling ? */
}
static
void MyFinishProc( Display *pdpy,
XPContext pcontext,
XPGetDocStatus status,
XPointer client_data )
{
MyPrintFileData *mpfd = (MyPrintFileData *)client_data;
/* remove the file if not successfull */
if( status != XPGetDocFinished )
{
XPU_DEBUG_ONLY(printf("MyFinishProc: error %d\n", (int)status));
XPU_TRACE_CHILD(remove(mpfd->file_name));
}
XPU_TRACE_CHILD((void)fclose(mpfd->file)); /* what about error handling ? */
mpfd->status = status;
mpfd->done = True;
}
static
#ifdef XPU_USE_NSPR
void PrintToFile_Consumer( void *handle )
#else
void *PrintToFile_Consumer( void *handle )
#endif
{
MyPrintFileData *mpfd = (MyPrintFileData *)handle;
XEvent dummy;
struct timeval timeout;
timeout.tv_sec = 0;
timeout.tv_usec = 100000; /* 1/10 s */
XPU_DEBUG_ONLY(printf("### child running, getting data from '%s'.\n", mpfd->displayname));
/* we cannot reuse fork()'ed display handles - our child needs his own one */
if( (mpfd->pdpy = XPU_TRACE_CHILD(XOpenDisplay(mpfd->displayname))) == NULL )
{
perror("child cannot open display");
#ifdef XPU_USE_NSPR
return;
#else
return(NULL);
#endif
}
mpfd->done = False;
/* register "consumer" callbacks */
if( XPU_TRACE_CHILD(XpGetDocumentData(mpfd->pdpy, mpfd->pcontext,
MyPrintToFileProc, MyFinishProc,
(XPointer)mpfd)) == 0 )
{
XPU_DEBUG_ONLY(printf("XpGetDocumentData cannot register callbacks\n"));
#ifdef XPU_USE_NSPR
return;
#else
return(NULL);
#endif
}
/* loop forever - libXp has registered hidden event callbacks for the consumer
* callbacks - the finishCB will call set the "done" boolean after all...
*/
while( mpfd->done != True )
{
XNextEventTimeout(mpfd->pdpy, &dummy, &timeout);
}
XCloseDisplay(mpfd->pdpy);
#ifdef XPU_USE_THREADS
#ifdef XPU_USE_NSPR
return;
#else
return(NULL);
#endif
#else
/* write the status to the parent */
if( XPU_TRACE_CHILD(write(mpfd->pipe[1], &mpfd->status, sizeof(XPGetDocStatus))) != sizeof(XPGetDocStatus) )
{
perror("PrintToFile_Consumer: can't write XPGetDocStatus");
}
/* we don't do any free's or close's, as we are just
* going to exit, in fact, get out without calling any C++
* destructors, etc., as we don't want anything funny to happen
* to the parent
*/
XPU_TRACE_CHILD(_exit(EXIT_SUCCESS));
#endif /* XPU_USE_THREADS */
}
/* EOF. */