Artifact 074b0a83358164c953dd9088c405c50afa7403e8cdab83b53acd498c54413179:
- Executable file
r38/lisp/csl/cslbase/FXDCNativePrinter.cpp
— part of check-in
[f2fda60abd]
at
2011-09-02 18:13:33
on branch master
— Some historical releases purely for archival purposes
git-svn-id: https://svn.code.sf.net/p/reduce-algebra/code/trunk/historical@1375 2bfe0521-f11c-4a00-b80e-6202646ff360 (user: arthurcnorman@users.sourceforge.net, size: 38162) [annotate] [blame] [check-ins using] [more...]
// // FXDCNativePrinter.cpp // // cf FXDCPrint but this version can use a native WIN32 printer // and also provides richer scaling capabilities. It also // uses FXPostscriptFont when printing Postscript so that it gets // metrics right (at least for the standard 35 fonts). // // Contributed to FOX project by Manuel (address@te...) who // made a deliberate choice not to add a copyright notice, so that // the code could be added to FOX (and hence released under the FOX // relaxed version of the LGPL). // // This version worked on by Arthur Norman mainly to make the // behaviour under Linux more robust, but also to clean up some // oddities etc. and add bits of functionality. /* Signature: 636f80a6 27-Jun-2005 */ #ifdef HAVE_CONFIG_H #include "config.h" #else #define HAVE_LIBFOX 1 #endif #ifdef HAVE_LIBFOX #include <string.h> #include <ctype.h> #include <fx.h> #include <FXDC.h> #include <FXDCPrint.h> #include <FXDCWindow.h> #include "FXPostscriptFont.h" ////////////////////////////////////////////////////////////////////////////// // The following implements two minorish patches to the FXDCPrint class // that make it handle Postscript better for me. I mark the changes // with "@@@" // // define a version of FOX where these patches become unnecessary needed #define PRINT_MAJOR 99 #define PRINT_MINOR 99 #define PRINT_LEVEL 99 #if (FOX_MAJOR<PRINT_MAJOR || (FOX_MAJOR==PRINT_MAJOR && \ (FOX_MINOR<PRINT_MINOR || (FOX_MINOR==PRINT_MINOR && \ (FOX_LEVEL<PRINT_LEVEL))))) class FXAPI FXDCPatchedPrint : public FXDCPrint { public: FXDCPatchedPrint(FXApp* a); ~FXDCPatchedPrint(); FXbool beginPage(FXuint page); // NB not virtual in FXDCPrint virtual void drawText(FXint x,FXint y,const FXchar* string,FXuint len); }; // Construct FXDCPatchedPrint::FXDCPatchedPrint(FXApp* a) : FXDCPrint(a){ } // Destruct FXDCPatchedPrint::~FXDCPatchedPrint(){ } // Generate begin of page FXbool FXDCPatchedPrint::beginPage(FXuint page){ // Output page number outf("%%%%Page: %d %d\n",page,page); // @@@ 2 values after "%%Page:" // Reset page bounding box if(flags&PRINT_NOBOUNDS){ pagebb.xmin= 1000000; pagebb.xmax=-1000000; pagebb.ymin= 1000000; pagebb.ymax=-1000000; outf("%%%%PageBoundingBox: (atend)\n"); } // Use the doc bounding box else{ pagebb.xmin=docbb.xmin; pagebb.xmax=docbb.xmax; pagebb.ymin=docbb.ymin; pagebb.ymax=docbb.ymax; outf("%%%%PageBoundingBox: %d %d %d %d\n",(int)pagebb.xmin,(int)pagebb.ymin,(int)pagebb.xmax,(int)pagebb.ymax); } // Page setup outf("%%%%BeginPageSetup\n"); outf("%%%%EndPageSetup\n"); outf("gsave\n"); // Maybe in landscape? if(flags&PRINT_LANDSCAPE){ outf("%g %g translate\n",mediawidth,0.0); outf("90 rotate\n"); } return TRUE; } // Draw string (only foreground bits) // Contributed by S. Ancelot <sancelot@online.fr> void FXDCPatchedPrint::drawText(FXint x,FXint y,const FXchar* string,FXuint len){ FXfloat xx,yy; tfm(xx,yy,(FXfloat)x,(FXfloat)y); bbox(xx,yy); FXFontDesc fontdesc; font->getFontDesc(fontdesc); outf("gsave /%s findfont\n",font->getName().text()); // @@@ Support fractions of a point in font sizes by using float not int here outf("%g scalefont\n",(double)font->getSize()/10.0); outf("setfont\n"); outf("newpath\n%g %g moveto\n(",xx,yy); for(FXuint i=0; i<len; i++){ if(string[i]=='(') outf("\\050"); else if(string[i]==')') outf("\\051"); else outf("%c",string[i]); } outf(") show\n"); outf("grestore\n"); } // The macro here subverts all FXPrintDC instances that follow into // being the patched variety. #define FXDCPrint FXDCPatchedPrint // end of patches to FXDCPrint. #endif // version check in PRINT_MAJOR, PRINT_MINOR and PRINT_LEVEL ////////////////////////////////////////////////////////////////////////////// #include "FXDCNativePrinter.h" #include "FXPostscriptFont.h" // // When generating Postscript I need font metrics. These can be extracted // from "afm" files that Adobe supply. I have a program "get-adobe-metrics.c" // that can be run on a typical Linux system to extract the (minimal) metric // information that I need here and build a file "font-info.c". By including // that file here I collect info about all the standard Postscript Fonts. // I will not permit a user to use any other fonts than these! // #ifdef WIN32 // // The WIN32 version here works by mapping the printer much as if it // was a window. A Postscript version will generate Postscript directly // from the print requests that the user makes. // class FXAPI FXPrinterVisual : public FXVisual { public: FXPrinterVisual(); void create() { xid=(void *)1; } void detach() { xid=(void *)0; } void destroy() { xid=(void *)0; } FXPixel getPixel(FXColor clr) { return RGB( FXREDVAL(clr), FXGREENVAL(clr), FXBLUEVAL(clr) ); } FXColor getColor(FXPixel pix) { return FXRGB( GetRValue(pix), GetGValue(pix), GetBValue(pix) ); } }; FXPrinterVisual::FXPrinterVisual():FXVisual() { depth=24; numred=numgreen=numblue=256; numcolors=256*256*256; type=(FXVisualType)VISUALTYPE_TRUE; xid=(void *)0; // hPalette = NULL; // not available in FOX 1.1.49 and unclear whether needed here anyway! }; class FXAPI FXPrinterDrawable : public FXDrawable { protected: FXID dc; public: FXPrinterDrawable(FXID gc); FXPrinterDrawable(); ~FXPrinterDrawable(); void SetDC(FXID gc); virtual FXID GetDC() const { return (FXID)dc; } virtual int ReleaseDC(FXID) const { return 0; } }; FXPrinterDrawable::~FXPrinterDrawable() { delete visual; } FXPrinterDrawable::FXPrinterDrawable() { FXPrinterDrawable(0); } FXPrinterDrawable::FXPrinterDrawable(FXID gc) : FXDrawable() { dc = gc; visual=new FXPrinterVisual(); xid=(FXID)1; } void FXPrinterDrawable::SetDC(FXID gc) { dc = (HDC)gc; } #endif // end of WIN32-specific stuff // Construct FXDCNativePrinter::FXDCNativePrinter(FXApp *a):FXDC(a) { #ifdef WIN32 opaque = (FXObject *)NULL; dctype=TYPE_WIN32; #else dctype=TYPE_PS; #endif #ifdef FONT_NOT_VIRTUAL postscriptFont = NULL; #endif pageheight = 0.0; // report this until the print job starts pagewidth = 0.0; fontoffset = 0; // Baseline of font fontScaleBack = 1.0; fontScale = 1.0; PSscale = 1.0; logpixelsx = 72; logpixelsy = 72; scalex = 1.0; scaley = 1.0; unitsx = 72.0; unitsy = 72.0; pdc = (FXDC *)NULL; pagecount=0; } // Destruct FXDCNativePrinter::~FXDCNativePrinter() { } // Generate print job prolog, return TRUE if all is OK FXbool FXDCNativePrinter::beginPrint(FXPrinter &job) { pagecount=0; #ifdef WIN32 // on Windows printing to file uses Postscript but anything direct to // a printer goes via the Windows drivers. if (job.flags&PRINT_DEST_FILE) dctype = TYPE_PS; else dctype=TYPE_WIN32; #else // On other than WIN32 the only print mode supported is Postscript dctype=TYPE_PS; #endif switch (dctype) { #ifdef WIN32 case TYPE_WIN32: devmode_handle=0; FXPrinterDrawable *prn; // TODO: Paper size memset(&devmode, 0, sizeof(devmode)); devmode.dmFields = DM_ORIENTATION | DM_COLOR; devmode.dmSize = sizeof(devmode); devmode.dmOrientation = (job.flags&PRINT_LANDSCAPE) ? DMORIENT_LANDSCAPE : DMORIENT_PORTRAIT; devmode.dmColor = (job.flags&PRINT_COLOR) ? DMCOLOR_COLOR : DMCOLOR_MONOCHROME; char devicename[256]; // Note: Under Win 9x/ME "WINSPOOL" should be replaced by NULL, // but this seems to work anyway! strcpy(devicename, job.name.text()); dc = CreateDC("WINSPOOL", devicename, NULL, &devmode); if (dc==(HANDLE)NULL) return FALSE; // Initialize the members of a DOCINFO structure. memset((void *)&di, 0, sizeof(di)); di.cbSize = sizeof(DOCINFO); di.lpszDocName = "Document"; // FIXME: API to support document name? di.lpszOutput = (LPTSTR) NULL; di.fwType = 0; // Start document if (::StartDoc(dc, &di)==SP_ERROR) { ::DeleteDC(dc); dc=0; return FALSE; } SetMapMode(dc, MM_TEXT); // get pixels per inch, usually 600x600 or 300x300 logpixelsy = ::GetDeviceCaps(dc, LOGPIXELSY); logpixelsx = ::GetDeviceCaps(dc, LOGPIXELSX); #ifdef OLD fontScale = logpixelsy / 96.0; fontScaleBack = 96.0 / logpixelsy; #else // The font size I need to create under Windows will be related to the // pixel-pitch on my output device. My reading of the Windows documentation // is that the scaling shown here is what is wanted, but the alternative // scaling by 96 not 72 was present in the original code so I leave it as // a comment for now in case there is something I do not understand. fontScale = logpixelsy / 72.0; fontScaleBack = 72.0 / logpixelsy; #endif setHorzUnitsInch(72.0); setVertUnitsInch(72.0); // Create drawable prn = new FXPrinterDrawable((FXID)dc); opaque= (FXObject *)prn; FXdouble dx, dy; dx = (FXdouble)job.mediawidth; dy = (FXdouble)job.mediaheight; if (job.flags&PRINT_LANDSCAPE) { FXdouble kk=dx; dx=dy; dy=kk; } pageheight = dy * scaley; /* Store size in pixels */ pagewidth = dx * scalex; prn->resize( (FXint)(scalex * dx) , (FXint)(scaley * dy) ); // Create a WIN32 FXDC from our drawable pdc = (FXDC *)new FXDCWindow(prn); SetTextAlign(dc, TA_TOP|TA_LEFT); // TA_BASLINE fails in some printers pdc->setForeground(FXRGB(0,0,0)); pdc->setBackground(FXRGB(255,255,255)); return TRUE; #endif default: // case TYPE_PS: // Postscript printing delegates to the existing FXDCPrint class. // But note that until metric-returning things in FXFont are virtual // I have a HACK whenever I extract measurements here. pdc = (FXDC *)new FXDCPrint(getApp()); if (((FXDCPrint *)pdc)->beginPrint(job) == 0) return FALSE; logpixelsx = 72; logpixelsy = 72; scalex = 1.0; scaley = 1.0; PSscale = 0.001; // see usage later on for explanation // There is an uncertainty here about who is supposed to be // responsible for margins. The FXPrinter that I was passed has // given me some suggestions but I ignore them here! What is done here // is at least compatible with what is done in the WIN32 case. pagewidth = (FXfloat)job.mediawidth; pageheight = (FXfloat)job.mediaheight; if (job.flags&PRINT_LANDSCAPE) { FXdouble kk=pagewidth; pagewidth=pageheight; pageheight=kk; } // The following 2 lines may not be needed for Postscript printing but // are harmless anyway. pdc->setForeground(FXRGB(0,0,0)); pdc->setBackground(FXRGB(255,255,255)); return TRUE; } } // Generate print job epilog FXbool FXDCNativePrinter::endPrint() { switch (dctype) { #ifdef WIN32 case TYPE_WIN32: // End of Document if (dc!=0) { ::EndDoc(dc); FXDCWindow *pd=(FXDCWindow *)pdc; delete pd; FXPrinterDrawable *prn=(FXPrinterDrawable *)opaque; delete prn; ::DeleteDC(dc); dc=0; opaque=(FXObject *)NULL; pdc=(FXDC*)NULL; } return 1; #endif default: // case TYPE_PS: FXDCPrint *pd=(FXDCPrint *)pdc; FXbool v=pd->endPrint(); delete pd; pdc=(FXDC *)NULL; return v; } } // Generate begin of page FXbool FXDCNativePrinter::beginPage(FXuint page) { switch (dctype) { #ifdef WIN32 case TYPE_WIN32: if (::StartPage(dc)<=0) { endPrint(); return 0; } return 1; #endif default: // case TYPE_PS: // Note that if I had to apply my patch then it gets activated here. FXDCPrint *pd=(FXDCPrint *)pdc; return pd->beginPage(page); } } // Generate end of page FXbool FXDCNativePrinter::endPage() { switch (dctype) { #ifdef WIN32 case TYPE_WIN32: ::EndPage(dc); pagecount++; return TRUE; #endif default: // case TYPE_PS: FXDCPrint *pd=(FXDCPrint *)pdc; return pd->endPage(); } } // Draw a point in the current pen color void FXDCNativePrinter::drawPoint(FXint x, FXint y) { pdc->drawPoint(ScaleX(x), ScaleY(y)); } // I need an array of points, arcs, rectangles into which I can scale things. // By keeping a single array here I can extend it by need in a reasonably // tidy way. static void *dst = NULL; static int dst_buffer_size = 0; #define DST_BUFFER_INCREMENT 128 static void check_dst_buffer(int n, int sz) { int len = n*sz; if (dst_buffer_size >= len) return; if (dst_buffer_size!=0) free((void *)dst); // I keep the buffer size a multiple of 128 bytes, and any time I have to // extend it I round up the needed size to a multiple of that. dst_buffer_size = len + (DST_BUFFER_INCREMENT - len%DST_BUFFER_INCREMENT); void *p = (void *)malloc(len); // my treatment of failure here is somewhat abrupt, and perhaps I should // just do less drawing. But for now I intend to be fierce on this count. if (p == NULL) { fprintf(stderr, "Fatal error: ran out of memory\n"); exit(1); } dst = p; } // Draw points in the current pen color. // Each point's position is relative to the drawable's origin (as usual). void FXDCNativePrinter::drawPoints(const FXPoint* points,FXuint npoints) { check_dst_buffer(npoints, sizeof(FXPoint)); scalePoints((FXPoint *)dst, (FXPoint *)points, npoints); pdc->drawPoints((FXPoint *)dst, npoints); } // Draw points in the current pen color. The first point's position is // relative to the drawable's origin, but each subsequent point's position // is relative to the previous point's position; each FXPoint defines // the relative coordinates. Think LOGO. void FXDCNativePrinter::drawPointsRel(const FXPoint*points,FXuint npoints) { check_dst_buffer(npoints, sizeof(FXPoint)); scalePoints((FXPoint *)dst, (FXPoint *)points, npoints); pdc->drawPointsRel((FXPoint *)dst, npoints); } // Draw a line void FXDCNativePrinter::drawLine(FXint x1, FXint y1, FXint x2, FXint y2) { pdc->drawLine(ScaleX(x1), ScaleY(y1), ScaleX(x2), ScaleY(y2)); } // Draw multiple lines. All points are drawn connected. // Each point is specified relative to Drawable's origin. void FXDCNativePrinter::drawLines(const FXPoint* points, FXuint npoints) { check_dst_buffer(npoints, sizeof(FXPoint)); scalePoints((FXPoint *)dst, (FXPoint *)points, npoints); pdc->drawLines((FXPoint *)dst, npoints); } // Draw multiple lines. All points are drawn connected. // First point's coordinate is relative to drawable's origin, but // subsequent points' coordinates are relative to previous point. void FXDCNativePrinter::drawLinesRel(const FXPoint* points, FXuint npoints) { check_dst_buffer(npoints, sizeof(FXPoint)); scalePoints((FXPoint *)dst, (FXPoint *)points, npoints); pdc->drawLinesRel((FXPoint *)dst, npoints); } // Draw unconnected line segments void FXDCNativePrinter::drawLineSegments(const FXSegment* segments, FXuint nsegments) { check_dst_buffer(nsegments, sizeof(FXSegment)); scaleSegments((FXSegment *)dst, (FXSegment *)segments, nsegments); pdc->drawLineSegments((FXSegment *)dst, nsegments); } // Draw unfilled rectangle void FXDCNativePrinter::drawRectangle(FXint x, FXint y, FXint w, FXint h) { pdc->drawRectangle(ScaleX(x), ScaleY(y), ScaleX(w), ScaleY(h)); } // Draw unfilled rectangles void FXDCNativePrinter::drawRectangles(const FXRectangle* rectangles,FXuint nrectangles) { check_dst_buffer(nrectangles, sizeof(FXRectangle)); scaleRectangles((FXRectangle *)dst, (FXRectangle *)rectangles, nrectangles); pdc->drawRectangles((FXRectangle *)dst, nrectangles); } // Draw arc void FXDCNativePrinter::drawArc(FXint x, FXint y, FXint w, FXint h, FXint ang1, FXint ang2) { pdc->drawArc(ScaleX(x), ScaleY(y), ScaleX(w), ScaleY(h), ang1, ang2); } // Draw arcs void FXDCNativePrinter::drawArcs(const FXArc* arcs,FXuint narcs) { check_dst_buffer(narcs, sizeof(FXArc)); scaleArcs((FXArc *)dst, (FXArc *)arcs, narcs); pdc->drawArcs((FXArc *)dst, narcs); } // Filled rectangle void FXDCNativePrinter::fillRectangle(FXint x, FXint y, FXint w, FXint h) { pdc->fillRectangle(ScaleX(x), ScaleY(y), ScaleX(w), ScaleY(h)); } // Filled rectangles void FXDCNativePrinter::fillRectangles(const FXRectangle* rectangles, FXuint nrectangles) { check_dst_buffer(nrectangles, sizeof(FXRectangle)); scaleRectangles((FXRectangle *)dst, (FXRectangle *)rectangles, nrectangles); pdc->fillRectangles((FXRectangle *)dst, nrectangles); } // Fill arc void FXDCNativePrinter::fillArc(FXint x, FXint y, FXint w, FXint h, FXint ang1, FXint ang2) { pdc->fillArc(ScaleX(x), ScaleY(y), ScaleX(w), ScaleY(h), ang1, ang2); } // Fill arcs void FXDCNativePrinter::fillArcs(const FXArc *arcs, FXuint narcs) { check_dst_buffer(narcs, sizeof(FXArc)); scaleArcs((FXArc *)dst, (FXArc *)arcs, narcs); pdc->fillArcs((FXArc *)dst, narcs); } // Filled simple polygon void FXDCNativePrinter::fillPolygon(const FXPoint* points, FXuint npoints) { check_dst_buffer(npoints, sizeof(FXPoint)); scalePoints((FXPoint *)dst, (FXPoint *)points, npoints); pdc->fillPolygon((FXPoint *)dst, npoints); } // Fill concave polygon void FXDCNativePrinter::fillConcavePolygon(const FXPoint *points, FXuint npoints) { check_dst_buffer(npoints, sizeof(FXPoint)); scalePoints((FXPoint *)dst, (FXPoint *)points, npoints); pdc->fillConcavePolygon((FXPoint *)dst, npoints); } // Fill complex (self-intersecting) polygon void FXDCNativePrinter::fillComplexPolygon(const FXPoint *points, FXuint npoints) { check_dst_buffer(npoints, sizeof(FXPoint)); scalePoints((FXPoint *)dst, (FXPoint *)points, npoints); pdc->fillComplexPolygon((FXPoint *)dst, npoints); } // Filled simple polygon with relative points void FXDCNativePrinter::fillPolygonRel(const FXPoint *points, FXuint npoints) { check_dst_buffer(npoints, sizeof(FXPoint)); scalePoints((FXPoint *)dst, (FXPoint *)points, npoints); pdc->fillPolygonRel((FXPoint *)dst, npoints); } // Fill concave polygon void FXDCNativePrinter::fillConcavePolygonRel(const FXPoint *points, FXuint npoints) { check_dst_buffer(npoints, sizeof(FXPoint)); scalePoints((FXPoint *)dst, (FXPoint *)points, npoints); pdc->fillConcavePolygonRel((FXPoint *)dst, npoints); } // Fill complex (self-intersecting) polygon void FXDCNativePrinter::fillComplexPolygonRel(const FXPoint *points, FXuint npoints) { check_dst_buffer(npoints, sizeof(FXPoint)); scalePoints((FXPoint *)dst, (FXPoint *)points, npoints); pdc->fillComplexPolygonRel((FXPoint *)dst, npoints); } // Draw string (only foreground bits) void FXDCNativePrinter::drawText(FXint x, FXint y, const FXchar *string, FXuint len) { /* TA_BASELINE does not work reliably with printers, so we need to adjust by hand */ pdc->drawText(ScaleX(x), ScaleY(y)-fontoffset, string, len); } // Draw string (both foreground and background bits) void FXDCNativePrinter::drawImageText(FXint x, FXint y, const FXchar*string,FXuint len) { pdc->drawImageText(ScaleX(x), ScaleY(y)-fontoffset, string, len); } // Draw area from source void FXDCNativePrinter::drawArea(const FXDrawable *source, FXint sx, FXint sy, FXint sw, FXint sh, FXint dx, FXint dy) { pdc->drawArea(source, sx, sy, sw, sh, ScaleX(dx), ScaleY(dy)); } // Draw image void FXDCNativePrinter::drawImage(const FXImage *img, FXint dx, FXint dy) { pdc->drawImage(img, ScaleX(dx), ScaleY(dy)); } // Draw bitmap void FXDCNativePrinter::drawBitmap(const FXBitmap *bitmap, FXint dx, FXint dy) { pdc->drawBitmap(bitmap, ScaleX(dx), ScaleY(dy)); } // Draw icon void FXDCNativePrinter::drawIcon(const FXIcon *icon, FXint dx, FXint dy) { pdc->drawIcon(icon, ScaleX(dx), ScaleY(dy)); } // Draw icon shaded void FXDCNativePrinter::drawIconShaded(const FXIcon *icon, FXint dx, FXint dy) { pdc->drawIconShaded(icon, ScaleX(dx), ScaleY(dy)); } // Draw icon sunken void FXDCNativePrinter::drawIconSunken(const FXIcon *icon, FXint dx, FXint dy) { pdc->drawIconSunken(icon, ScaleX(dx), ScaleY(dy)); } // Draw hashed box void FXDCNativePrinter::drawHashBox(FXint x, FXint y, FXint w, FXint h, FXint b) { // FIXME: Scaling border by horizontal resolution, // what when logpixelsx != logpixelsy ?? pdc->drawHashBox(ScaleX(x), ScaleY(y), ScaleX(w), ScaleY(h), ScaleX(b)); } // Set foreground drawing color (brush) void FXDCNativePrinter::setForeground(FXColor clr) { pdc->setForeground(clr); } // Set background drawing color (brush) void FXDCNativePrinter::setBackground(FXColor clr) { pdc->setBackground(clr); } // Set dash pattern void FXDCNativePrinter::setDashes(FXuint dashoffset, const FXchar *dashpattern, FXuint dashlength) { pdc->setDashes(dashoffset, dashpattern, dashlength); } // Set line width void FXDCNativePrinter::setLineWidth(FXuint linewidth) { // FIXME: Scaling by X resolution, what if Xdpi != Ydpi ???? pdc->setLineWidth(ScaleX(linewidth)); } // Set line cap style void FXDCNativePrinter::setLineCap(FXCapStyle capstyle) { pdc->setLineCap(capstyle); } // Set line join style void FXDCNativePrinter::setLineJoin(FXJoinStyle joinstyle) { pdc->setLineJoin(joinstyle); } // Set line style void FXDCNativePrinter::setLineStyle(FXLineStyle linestyle) { pdc->setLineStyle(linestyle); } // Set fill style void FXDCNativePrinter::setFillStyle(FXFillStyle fillstyle) { pdc->setFillStyle(fillstyle); } // Set fill rule void FXDCNativePrinter::setFillRule(FXFillRule fillrule) { pdc->setFillRule(fillrule); } // Set blit function void FXDCNativePrinter::setFunction(FXFunction func) { pdc->setFunction(func); } // Set tile image void FXDCNativePrinter::setTile(FXImage *image, FXint dx, FXint dy) { pdc->setTile(image, dx, dy); // TODO: Check if dx,dy should be scaled } // Set stipple pattern void FXDCNativePrinter::setStipple(FXBitmap *bitmap, FXint dx, FXint dy) { pdc->setStipple(bitmap, dx, dy); // TODO: Check if dx,dy should be scaled } // Set stipple pattern void FXDCNativePrinter::setStipple(FXStipplePattern pat, FXint dx, FXint dy) { pdc->setStipple(pat, dx, dy); // TODO: Check if dx,dy should be scaled } // Set clip rectangle void FXDCNativePrinter::setClipRectangle(FXint x, FXint y, FXint w, FXint h) { pdc->setClipRectangle(ScaleX(x), ScaleY(y), ScaleX(w), ScaleY(h)); } // Set clip rectangle void FXDCNativePrinter::setClipRectangle(const FXRectangle &rectangle) { pdc->setClipRectangle(ScaleX(rectangle.x), ScaleY(rectangle.y), ScaleX(rectangle.w), ScaleY(rectangle.h)); } // Clear clipping void FXDCNativePrinter::clearClipRectangle() { pdc->clearClipRectangle(); } // Set clip mask void FXDCNativePrinter::setClipMask(FXBitmap *bitmap, FXint dx, FXint dy) { pdc->setClipMask(bitmap, dx, dy); // TODO: Check if dx,dy should be scaled } // Clear clip mask void FXDCNativePrinter::clearClipMask() { pdc->clearClipMask(); } // Set font to draw text with void FXDCNativePrinter::setFont(FXFont *fnt) { font=fnt; #if FOX_MAJOR==1 && FOX_MINOR==0 pdc->setTextFont(fnt); #else pdc->setFont(fnt); #endif fontoffset=0; #ifdef FONT_NOT_VIRTUAL if (dctype==TYPE_PS) postscriptFont = (FX::FXPostscriptFont *)font; #endif if (dctype==TYPE_WIN32) fontoffset = font->getFontAscent(); } // Change clip-against-child windows mode void FXDCNativePrinter::clipChildren(FXbool yes) { // Do nothing } // // Now the helper code that scales vectors of stuff for me. // void FXDCNativePrinter::scalePoints(FXPoint *dst, FXPoint *src, FXuint npoints) { for (;npoints>0;npoints--,dst++,src++) { dst->x = ScaleX(src->x); dst->y = ScaleY(src->y); } } void FXDCNativePrinter::scaleRectangles(FXRectangle *dst, FXRectangle *src, FXuint nrectangles) { for (;nrectangles>0;nrectangles--,dst++,src++) { dst->x = ScaleX(src->x); dst->y = ScaleY(src->y); dst->w = ScaleX(src->w); dst->h = ScaleY(src->h); } } void FXDCNativePrinter::scaleSegments(FXSegment *dst, FXSegment *src, FXuint nsegments) { for (;nsegments>0;nsegments--,dst++,src++) { dst->x1 = ScaleX(src->x1); dst->y1 = ScaleY(src->y1); dst->x2 = ScaleX(src->x2); dst->y2 = ScaleY(src->y2); } } void FXDCNativePrinter::scaleArcs(FXArc *dst, FXArc *src, FXuint narcs) { for (;narcs>0;narcs--,dst++,src++) { dst->x = ScaleX(src->x); dst->y = ScaleY(src->y); dst->w = ScaleX(src->w); dst->h = ScaleY(src->h); dst->a = src->a; dst->b = src->b; } } void FXDCNativePrinter::setHorzUnitsInch(FXfloat sx) { scalex = logpixelsx / sx; unitsx = sx; } void FXDCNativePrinter::setVertUnitsInch(FXfloat sy) { scaley = logpixelsy / sy; unitsx = sy; } // Create a font, paying attention to the scaling currently in force. FXFont *FXDCNativePrinter::fntGenerateFont(const FXString &face, FXuint sz, FXuint wt, FXuint sl, FXuint enc, FXuint setw, FXuint h) { return fntDoubleGenerateFont(face, (double)sz, wt, sl, enc, setw, h); } // The next version takes the desired point size as a double not an // int. Because windows printer fonts actually exist at pixel-size based on // printer resolution they can exist in visible sizes that vary much // more finely than integer point sizes would allow one to express. And // both with Postscript and Truetype fonts utterly arbitrary scaling // can be applied. With Postscript my font's size will be specified // internally in decipoints so at least we can have sizes 5.1, 5.2, 5.3 etc. FXFont *FXDCNativePrinter::fntDoubleGenerateFont(const FXString &face, double sz, FXuint wt, FXuint sl, FXuint enc, FXuint setw, FXuint h) { if (dctype == TYPE_WIN32) return new FXFont(getApp(), face, (int)(sz * fontScale), wt, sl, enc, setw, h); else // otherwise I am to generate Postscript { FXFontDesc fdd; memset((void *)&fdd, 0, sizeof(fdd)); strcpy(fdd.face, face.text()); // The whole purpose of constructing via FXFontDesc is to give size in // decipoints not points. I can not use the fontScale trick here without // re-working how FXDCPrint prints things... fdd.size = (int)(10.0*sz + 0.5); fdd.weight = wt; fdd.slant = sl; fdd.encoding = enc; fdd.setwidth = setw; fdd.flags = h; // the explicit FX:: on the next line is needed to allow this code to // compile using both FOX 1.0 and FOX 1.1!!! return new FX::FXPostscriptFont(getApp(), fdd); } } // // Most of the stuff that follows is just delegating actions to an // underlying DC, possibly applying scaling. The scaling is so that the // user can select the (integer-based) unit of measurement... in some cases // the default unit of 1pt (= 1/72in here) would be too coarse. It is // STRONGLY suggested that anybody changing units should use the same // ones for both X and Y, since otherwise indicating sizes for values // not keyed to axis direction (eg line width) gets very questionable indeed. // I think maybe the API would be safer with just a single scaling option // not two. Note also that font sizes are always specified in points // regardless of other options being set. FXString FXDCNativePrinter::fntGetName() { // the font-name returned will be the full Postscript font name. Handing it // back to try to create a new font will NOT be a good idea, since it has // Bold and Italic/Oblique info muddled up in it. return font->getName(); } FXuint FXDCNativePrinter::fntGetSize() { // NOTE that this returns the size in decipoints not points. return (FXuint)(fontScaleBack * (FXfloat)font->getSize()); } // return font size (in points) as a double not an integer, so that // fractional point sizes can be handled better. double FXDCNativePrinter::fntDoubleSize() { // NOTE that this returns the size in decipoints not points. return (double)(fontScaleBack * (FXfloat)font->getSize()); } FXuint FXDCNativePrinter::fntGetWeight() { return font->getWeight(); } FXuint FXDCNativePrinter::fntGetSlant() { return font->getSlant(); } FXuint FXDCNativePrinter::fntGetEncoding() { return font->getEncoding(); } FXuint FXDCNativePrinter::fntGetSetWidth() { return font->getSetWidth(); } FXuint FXDCNativePrinter::fntGetHints() { return font->getHints(); } void FXDCNativePrinter::fntGetFontDesc(FXFontDesc &fontdesc) const { font->getFontDesc(fontdesc); } void FXDCNativePrinter::fntSetFontDesc(const FXFontDesc &fontdesc) { font->setFontDesc(fontdesc); } FXbool FXDCNativePrinter::fntIsFontMono() const { #ifdef FONT_NOT_VIRTUAL if (dctype==TYPE_PS) return postscriptFont->isFontMono(); #endif return font->isFontMono(); } FXbool FXDCNativePrinter::fntHasChar(FXint ch) const { #ifdef FONT_NOT_VIRTUAL if (dctype==TYPE_PS) return postscriptFont->hasChar(ch); #endif return font->hasChar(ch); } FXint FXDCNativePrinter::fntGetMinChar() const { #ifdef FONT_NOT_VIRTUAL if (dctype==TYPE_PS) return postscriptFont->getMinChar(); #endif return (FXint)font->getMinChar(); } FXint FXDCNativePrinter::fntGetMaxChar() const { #ifdef FONT_NOT_VIRTUAL if (dctype==TYPE_PS) return postscriptFont->getMaxChar(); #endif return (FXint)font->getMaxChar(); } // // There is a big ugly issue about fonts and measurements here. For Windows // fonts will have been created internally at some huge point size based // on the actual resolution of the printer. The factor scalex includes // allowance for that and so enough precision is kept. // For Postscript generation the font thinks (at an internal level) that // it is the point size you actually want it to appear at. The effect is // that character heights and widths are often quite small values (eg // for a 10pt pont they are comparable with 10. Returning measurements as // integers in such a case would give severe truncation effects. // To work around this I arrange that the FXPostScriptFont class returns // font measurements scaled by 1000. I have to undo this here. The // multiplication by PSscale is to do that. // // For Postscript generation (and on X) the bearings that I return will be // the maximum values across the font. FXint FXDCNativePrinter::fntLeftBearing(FXchar ch) const { #ifdef FONT_NOT_VIRTUAL if (dctype==TYPE_PS) return (FXint)(PSscale * postscriptFont->leftBearing(ch) / scalex); #endif return (FXint)(PSscale * font->leftBearing(ch) / scalex); } double FXDCNativePrinter::fntDoubleLeftBearing(FXchar ch) const { #ifdef FONT_NOT_VIRTUAL if (dctype==TYPE_PS) return (double)(PSscale * postscriptFont->leftBearing(ch) / scalex); #endif return (double)(PSscale * font->leftBearing(ch) / scalex); } FXint FXDCNativePrinter::fntRightBearing(FXchar ch) const { #ifdef FONT_NOT_VIRTUAL if (dctype==TYPE_PS) return (FXint)(PSscale * postscriptFont->rightBearing(ch) / scalex); #endif return (FXint)(PSscale * font->rightBearing(ch) / scalex); } double FXDCNativePrinter::fntDoubleRightBearing(FXchar ch) const { #ifdef FONT_NOT_VIRTUAL if (dctype==TYPE_PS) return (double)(PSscale * postscriptFont->rightBearing(ch) / scalex); #endif return (double)(PSscale * font->rightBearing(ch) / scalex); } // // If one has left the UnitsInch at its default of 72 then // measurements are only precise to 1pt. This is generally not good // enough when laying out a line. To get better accuracy you can either // reset your units to say 1/3600in or use floating point values here. // FXint FXDCNativePrinter::fntGetFontWidth() const { #ifdef FONT_NOT_VIRTUAL if (dctype==TYPE_PS) return (FXint)(PSscale * postscriptFont->getFontWidth() / scalex); #endif return (FXint)(PSscale * font->getFontWidth() / scalex); } double FXDCNativePrinter::fntDoubleFontWidth() const { #ifdef FONT_NOT_VIRTUAL if (dctype==TYPE_PS) return (double)(PSscale * postscriptFont->getFontWidth() / scalex); #endif return (double)(PSscale * font->getFontWidth() / scalex); } FXint FXDCNativePrinter::fntGetFontHeight() const { #ifdef FONT_NOT_VIRTUAL if (dctype==TYPE_PS) return (FXint)(PSscale * postscriptFont->getFontHeight() / scaley); #endif return (FXint)(PSscale * font->getFontHeight() / scaley); } double FXDCNativePrinter::fntDoubleFontHeight() const { #ifdef FONT_NOT_VIRTUAL if (dctype==TYPE_PS) return (double)(PSscale * postscriptFont->getFontHeight() / scaley); #endif return (double)(PSscale * font->getFontHeight() / scaley); } FXint FXDCNativePrinter::fntGetFontAscent() const { #ifdef FONT_NOT_VIRTUAL if (dctype==TYPE_PS) return (FXint)(PSscale * postscriptFont->getFontAscent() / scaley); #endif return (FXint)(PSscale * font->getFontAscent() / scaley); } double FXDCNativePrinter::fntDoubleFontAscent() const { #ifdef FONT_NOT_VIRTUAL if (dctype==TYPE_PS) return (double)(PSscale * postscriptFont->getFontAscent() / scaley); #endif return (double)(PSscale * font->getFontAscent() / scaley); } FXint FXDCNativePrinter::fntGetFontDescent() const { #ifdef FONT_NOT_VIRTUAL if (dctype==TYPE_PS) return (FXint)(PSscale * postscriptFont->getFontDescent() / scaley); #endif return (FXint)(PSscale * font->getFontDescent() / scaley); } double FXDCNativePrinter::fntDoubleFontDescent() const { #ifdef FONT_NOT_VIRTUAL if (dctype==TYPE_PS) return (double)(PSscale * postscriptFont->getFontDescent() / scaley); #endif return (double)(PSscale * font->getFontDescent() / scaley); } FXint FXDCNativePrinter::fntGetFontLeading() const { #ifdef FONT_NOT_VIRTUAL if (dctype==TYPE_PS) return (FXint)(PSscale * postscriptFont->getFontLeading() / scaley); #endif return (FXint)(PSscale * font->getFontLeading() / scaley); } double FXDCNativePrinter::fntDoubleFontLeading() const { #ifdef FONT_NOT_VIRTUAL if (dctype==TYPE_PS) return (double)(PSscale * postscriptFont->getFontLeading() / scaley); #endif return (FXint)(PSscale * font->getFontLeading() / scaley); } FXint FXDCNativePrinter::fntGetFontSpacing() const { #ifdef FONT_NOT_VIRTUAL if (dctype==TYPE_PS) return (FXint)(PSscale * postscriptFont->getFontSpacing() / scaley); #endif return (FXint)(PSscale * font->getFontSpacing() / scaley); } double FXDCNativePrinter::fntDoubleFontSpacing() const { #ifdef FONT_NOT_VIRTUAL if (dctype==TYPE_PS) return (double)(PSscale * postscriptFont->getFontSpacing() / scaley); #endif return (double)(PSscale * font->getFontSpacing() / scaley); } FXint FXDCNativePrinter::fntGetTextWidth(const FXchar *text, FXuint n) const { #ifdef FONT_NOT_VIRTUAL if (dctype==TYPE_PS) return (FXint)(PSscale * postscriptFont->getTextWidth(text, n) / scalex); #endif return (FXint)(PSscale * font->getTextWidth(text, n) / scalex); } double FXDCNativePrinter::fntDoubleTextWidth(const FXchar *text, FXuint n) const { #ifdef FONT_NOT_VIRTUAL if (dctype==TYPE_PS) return (double)(PSscale * postscriptFont->getTextWidth(text, n) / scalex); #endif return (double)(PSscale * font->getTextWidth(text, n) / scalex); } FXint FXDCNativePrinter::fntGetTextHeight(const FXchar *text, FXuint n) const { #ifdef FONT_NOT_VIRTUAL if (dctype==TYPE_PS) return (FXint)(PSscale * postscriptFont->getTextHeight(text, n) / scaley); #endif return (FXint)(PSscale * font->getTextHeight(text, n) / scaley); } double FXDCNativePrinter::fntDoubleTextHeight(const FXchar *text, FXuint n) const { #ifdef FONT_NOT_VIRTUAL if (dctype==TYPE_PS) return (double)(PSscale * postscriptFont->getTextHeight(text, n) / scaley); #endif return (double)(PSscale * font->getTextHeight(text, n) / scaley); } FXint FXDCNativePrinter::getPageWidth(void) { return (FXint)(pagewidth / scalex); } double FXDCNativePrinter::doublePageWidth(void) { return (double)(pagewidth / scalex); } FXint FXDCNativePrinter::getPageHeight(void) { return (FXint)(pageheight / scaley); } double FXDCNativePrinter::doublePageHeight(void) { return (double)(pageheight / scaley); } #endif /* HAVE_LIBFOX */ // end of FXDCNativePrinter.cpp