This is ScrollXDPS.c in view mode; [Download] [Up]
/* * $RCSfile: ScrollXDPS.c,v $ * * Copyright (C) 1992 by Adobe Systems Incorporated. * All rights reserved. * * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, * provided that the above copyright notices appear in all copies and that * both those copyright notices and this permission notice appear in * supporting documentation and that the name of Adobe Systems * Incorporated not be used in advertising or publicity pertaining to * distribution of the software without specific, written prior * permission. If any portion of this software is changed, it cannot be * marketed under Adobe's trademarks and/or copyrights unless Adobe, in * its sole discretion, approves by a prior writing the quality of the * resulting implementation. * * ADOBE MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THE SOFTWARE FOR * ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. * ADOBE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL * IMPLIED WARRANTIES OF MERCHANTABILITY FITNESS FOR A PARTICULAR PURPOSE AND * NON-INFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL ADOBE BE LIABLE * TO YOU OR ANY OTHER PARTY FOR ANY SPECIAL, INDIRECT, OR CONSEQUENTIAL * DAMAGES OR ANY DAMAGES WHATSOEVER WHETHER IN AN ACTION OF CONTRACT, * NEGLIGENCE, STRICT LIABILITY OR ANY OTHER ACTION ARISING OUT OF OR IN * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ADOBE WILL NOT * PROVIDE ANY TRAINING OR OTHER SUPPORT FOR THE SOFTWARE. * * PostScript, Display PostScript, and Adobe are trademarks of Adobe Systems * Incorporated registered in the U.S.A. and other countries. * * Author: Adobe Systems Incorporated */ #include "Scroll.h" /*************************************************************** ** ** FUNCTION: initDPSContext ** ** DESCRIPTION: Initializes the main window's DPS Context; ** the main window must have been initialized. ** ** PARAMETERS: None. ** ** RETURN: None. ** ***************************************************************/ void initDPSContext() { Display *dpy = XtDisplay(AppData.time); XPoint xpt; Point pt1, pt2; Pixmap p; int depth; int i; /* ** Create the DPSContext in which rendering will occur */ AppData.dpsCtxt = XDPSGetSharedContext(dpy); (void) XDPSSetEventDelivery(dpy, dps_event_pass_through); if (AppData.dpsCtxt == NULL) { printf("Couldn't create a Display PostScript context.\n"); exit(1); } XDPSChainTextContext (AppData.dpsCtxt, AppData.trace); /* ** Set the default DPSContext */ DPSSetContext(AppData.dpsCtxt); XtVaGetValues(AppData.autoDrawingArea, XtNdepth, &depth, NULL); p = XCreatePixmap(dpy, RootWindowOfScreen(XtScreen(AppData.autoDrawingArea)), 1, 1, depth); XDPSSetContextDrawable(AppData.dpsCtxt, p, 1); PSWGetTransform(AppData.ctm, AppData.invctm, &AppData.xOffset, &AppData.yOffset); for (i = 0; i < 6; i++) AppData.origInvctm[i] = AppData.invctm[i]; xpt.x = 0; xpt.y = 100; convertToDPS(&xpt, &pt1); xpt.x = 100; xpt.y = 0; convertToDPS(&xpt, &pt2); AppData.origXScale = ABS(100.0 / (pt2.x - pt1.x)); AppData.origYScale = ABS(100.0 / (pt2.y - pt1.y)); AppData.scaledWidth = PAGE_WIDTH * AppData.origXScale * AppData.scale; AppData.scaledHeight = PAGE_HEIGHT * AppData.origYScale * AppData.scale; XFreePixmap(dpy, p); } /* end initDPSContext() */ /*************************************************************** ** ** FUNCTION: pathRectIntersects ** ** DESCRIPTION: Checks whether the bounding box of the path, offset ** by the translation, intersects the clip rectangle ** ** PARAMETERS: pathBBox The path bounding box ** clipRect The clip rectangle ** tx, ty Translation applied to path ** ** RETURN: Whether intersection occurs ** ***************************************************************/ static Boolean pathRectIntersects(pathBBox, clipRect, tx, ty) float *pathBBox; float *clipRect; float tx, ty; { float urx, ury; /* ** Clip rectangles are x/y/w/h, not llx/lly/urx/ury */ urx = clipRect[0] + clipRect[2]; ury = clipRect[1] + clipRect[3]; return pathBBox[0]+tx <= urx && pathBBox[2]+tx >= clipRect[0] && pathBBox[1]+ty <= ury && pathBBox[3]+ty >= clipRect[1]; } /* end pathRectIntersects() */ /*************************************************************** ** ** FUNCTION: pathPathIntersects ** ** DESCRIPTION: Checks whether the two path bboxes intersect ** ** PARAMETERS: b1 First bbox ** b2 Second bbox ** ** RETURN: Wether intersection occurs ** ***************************************************************/ static Boolean pathPathIntersects(b1, b2) float *b1, *b2; { return b1[0] <= b2[2] && b1[2] >= b2[0] && b1[1] <= b2[3] && b1[3] >= b2[1]; } /* end pathPathIntersects() */ /*************************************************************** ** ** Saved and wire-frame graphics parameters ** ***************************************************************/ static GraphicParams currentParams; static Boolean firstPath; static GraphicParams wireParams = { PATH_TYPE_STROKE, COLOR_MODEL_GRAY, 0.0, /* gray */ 0.0, 0.0, 0.0, /* reg, green, blue */ 0, /* linewidth */ 10, /* miter limit */ 0, /* line join */ 0 /* line cap */ }; /*************************************************************** ** ** FUNCTION: checkGraphicsParameters ** ** DESCRIPTION: Checks whether any of the graphics parameters differ from ** the saved ones. ** ** PARAMETERS: g New graphics parameters ** ** RETURN: Whether there are differences ** ***************************************************************/ static Boolean checkGraphicsParams(g) register GraphicParams *g; { #define NE(param) (g->param != currentParams.param) if (firstPath) return False; if (NE(path_type) || NE(color_type) || NE(linewidth) || NE(miterlimit) || NE(linejoin) || NE(linecap)) return True; if (g->color_type == COLOR_MODEL_GRAY) { if (NE(gray)) return True; } else { if (NE(red) || NE(green) || NE(blue)) return True; } return False; #undef NE } /* end checkGraphicsParams() */ /*************************************************************** ** ** FUNCTION: setGraphicsParams ** ** DESCRIPTION: Sets the graphics parameters, either completely or ** selectively. Updates saved graphics parameters ** ** PARAMETERS: g New graphics parameters ** ** RETURN: None. ** ***************************************************************/ static void setGraphicsParams(g) register GraphicParams *g; { #define NE(param) (g->param != currentParams.param) #define SET(param) (currentParams.param = g->param) if (firstPath || !AppData.optimizeChanges) { firstPath = False; currentParams = *g; PSWSetGraphicsParams(g->color_type, g->gray, g->red, g->green, g->blue, g->linewidth, g->miterlimit, g->linejoin, g->linecap); } else { SET(path_type); if (NE(color_type)) { if (g->color_type == COLOR_MODEL_GRAY) { PSsetgray(g->gray); SET(gray); } else { PSsetrgbcolor(g->red, g->green, g->blue); SET(red); SET(green); SET(blue); } SET(color_type); } else { if (g->color_type == COLOR_MODEL_GRAY) { if (NE(gray)) { PSsetgray(g->gray); SET(gray); } } else if (NE(red) || NE(green) || NE(blue)) { PSsetrgbcolor(g->red, g->green, g->blue); SET(red); SET(green); SET(blue); } } if (NE(linewidth)) { PSsetlinewidth(g->linewidth); SET(linewidth); } if (NE(miterlimit)) { PSsetmiterlimit(g->miterlimit); SET(miterlimit); } if (NE(linejoin)) { PSsetlinejoin(g->linejoin); SET(linejoin); } if (NE(linecap)) { PSsetlinecap(g->linecap); SET(linecap); } } #undef NE #undef SET } /* end setGraphicsParams() */ /*************************************************************** ** ** FUNCTION: drawUsingPathOps ** ** DESCRIPTION: Draws a user path using Level 1 operators ** ** PARAMETERS: p The user path ** action The user path operator ** ** RETURN: None. ** ***************************************************************/ static void drawUsingPathOps(p, action) UserPath *p; unsigned char action; { register float *f = p->pts; float f0, f1, f2, f3, f4, f5; int i; PSnewpath(); for (i = 0; i < p->num_ops - 1; i++) { switch (p->ops[i+1]) { /* ** No arcs are left in distilled files */ case dps_moveto: f0 = *f++; f1 = *f++; PSmoveto(f0, f1); break; case dps_rmoveto: f0 = *f++; f1 = *f++; PSrmoveto(f0, f1); break; case dps_lineto: f0 = *f++; f1 = *f++; PSlineto(f0, f1); break; case dps_rlineto: f0 = *f++; f1 = *f++; PSrlineto(f0, f1); break; case dps_curveto: f0 = *f++; f1 = *f++; f2 = *f++; f3 = *f++; f4 = *f++; f5 = *f++; PScurveto(f0, f1, f2, f3, f4, f5); break; case dps_rcurveto: f0 = *f++; f1 = *f++; f2 = *f++; f3 = *f++; f4 = *f++; f5 = *f++; PScurveto(f0, f1, f2, f3, f4, f5); break; case dps_closepath: PSclosepath(); break; } } switch (action) { case PATH_TYPE_FILL: PSfill(); break; case PATH_TYPE_STROKE: PSstroke(); break; case PATH_TYPE_CLIP: PSclip(); break; } } /* end drawUsingPathOps() */ /*************************************************************** ** ** FUNCTION: flushSavedUserPath ** ** DESCRIPTION: Executes the saved user path, and then resets the ** saved path to be empty ** ** PARAMETERS: None. ** ** RETURN: None. ** ***************************************************************/ static UserPath savePath; static DPSUserPathAction saveAction; static void flushSavedUserPath() { UserPath *p = &savePath; if (p->num_ops == 0) return; PSDoUserPath((DPSPointer) p->pts, p->num_pts, dps_float, p->ops, p->num_ops, (DPSPointer) p->bbox, saveAction); if (saveAction == dps_uappend) PSclip(); savePath.num_pts = 0; savePath.num_ops = 0; savePath.bbox[0] = savePath.bbox[1] = 99999; savePath.bbox[2] = savePath.bbox[3] = -99999; } /* end flushSavedUserPath() */ /*************************************************************** ** ** FUNCTION: addToUserPath ** ** DESCRIPTION: Adds the path to the saved user path. If it would ** overflow the saved path, flush the saved path first ** ** PARAMETERS: pts Points of path ** num_pts Number of points ** ops Path construction operators ** num_ops Number of operators ** bbox Path bbox ** action Path action ** ** RETURN: None. ** ***************************************************************/ static void addToUserPath(pts, num_pts, ops, num_ops, bbox, action) float *pts; int num_pts; DPSUserPathOp *ops; int num_ops; float *bbox; DPSUserPathAction action; { int i; /* ** Allocate the saved path if the first time through */ if (savePath.pts == NULL) { savePath.pts = (float *) XtMalloc(PTS_UPATH_BUFFER * sizeof(float)); savePath.ops = (DPSUserPathOp *) XtMalloc(OPS_UPATH_BUFFER * sizeof(DPSUserPathOp)); savePath.bbox[0] = savePath.bbox[1] = 99999; savePath.bbox[2] = savePath.bbox[3] = -99999; } /* ** If this would overflow the buffers, flush the saved path */ if (num_pts + savePath.num_pts > PTS_UPATH_BUFFER || num_ops + savePath.num_ops > OPS_UPATH_BUFFER) flushSavedUserPath(); /* ** If not a stroke operation, old and new paths must not intersect */ if (action != dps_ustroke && savePath.num_ops > 0) { if (pathPathIntersects(bbox, savePath.bbox)) { flushSavedUserPath(); } } /* ** If this is not the first path in the saved path, skip the ucache */ if (savePath.num_ops > 0 && ops[0] == dps_ucache) { ops++; num_ops--; } /* ** Copy points and operators to saved path */ for (i = 0; i < num_pts; i++) savePath.pts[savePath.num_pts+i] = pts[i]; for (i = 0; i < num_ops; i++) savePath.ops[savePath.num_ops+i] = ops[i]; savePath.num_pts += num_pts; savePath.num_ops += num_ops; saveAction = action; /* ** Update saved path bbox */ if (bbox[0] < savePath.bbox[0]) savePath.bbox[0] = bbox[0]; if (bbox[1] < savePath.bbox[1]) savePath.bbox[1] = bbox[1]; if (bbox[2] > savePath.bbox[2]) savePath.bbox[2] = bbox[2]; if (bbox[3] > savePath.bbox[3]) savePath.bbox[3] = bbox[3]; } /* end addToUserPath() */ /*************************************************************** ** ** FUNCTION: drawPath ** ** DESCRIPTION: Draws a user path ** ** PARAMETERS: p User path ** action Path type ** ** RETURN: None. ** ***************************************************************/ static void drawPath(p, action) UserPath *p; unsigned char action; { DPSUserPathAction act; int i; /* ** If not using user paths, draw with Level 1 operators */ if (AppData.drawStrategy == draw_paths) { drawUsingPathOps(p, action); return; } /* ** Convert action to user path operator */ switch (action) { case PATH_TYPE_FILL: act = dps_ufill; break; case PATH_TYPE_STROKE: act = dps_ustroke; break; case PATH_TYPE_CLIP: act = dps_uappend; PSnewpath(); break; } /* ** If not caching, skip the ucache operator */ if (AppData.drawStrategy == draw_cache) i = 0; else i = 1; /* ** Either add the points to the saved path or draw the path */ if (AppData.consolidate) { addToUserPath(p->pts, p->num_pts, p->ops + i, p->num_ops - i, p->bbox, act); } else { PSDoUserPath((DPSPointer) p->pts, p->num_pts, dps_float, p->ops + i, p->num_ops - i, (DPSPointer) p->bbox, act); if (action == PATH_TYPE_CLIP) PSclip(); } } /* drawPath() */ /*************************************************************** ** ** FUNCTION: drawPicture ** ** DESCRIPTION: Draws the saved picture ** ** PARAMETERS: clipList Clipping rectangles ** clipLen Number of clipping rectangles ** ** RETURN: None. ** ***************************************************************/ static void drawPicture(clipList, clipLen) float *clipList; int clipLen; { Page *p = &AppData.picture; float width, height; float tx, ty; Graphic *g; GraphicParams *gp; int i; PSWDrawFrame(0, 0, (int) PAGE_WIDTH, (int) PAGE_HEIGHT); /* ** Compute dimensions of saved picture and translate it to center ** it in the page */ width = p->bounds.ur.x - p->bounds.ll.x; if (width < 0) width = 0; height = p->bounds.ur.y - p->bounds.ll.y; if (height < 0) height = 0; tx = (PAGE_WIDTH - width) / 2 - p->bounds.ll.x; ty = (PAGE_HEIGHT - height) / 2 - p->bounds.ll.y; PStranslate(tx, ty); PSinitclip(); /* ** If not doing clipping in the client, ignore clipping rectangles */ if (!AppData.clientClipping) clipLen = 0; firstPath = True; for (g = p->qHead; g != NULL; g = g->next) { /* ** If reinitialize clip, flush saved paths first */ if (g->parms.path_type == PATH_TYPE_INITCLIP) { flushSavedUserPath(); PSinitclip(); continue; } /* ** If clipping, check to see if path intersects any clipping rectangle */ if (clipLen != 0 && clipList != NULL) { for (i = 0; i < clipLen; i++) { if (pathRectIntersects(g->path.bbox, clipList+(i*4), tx, ty)) goto DRAW_IT; } /* ** If path is completely outside viewing area, and it's a clip ** path, flush until we come to an initclip */ if (g->parms.path_type == PATH_TYPE_CLIP) { while (g->next != NULL && g->next->parms.path_type != PATH_TYPE_INITCLIP) { g = g->next; } } continue; } DRAW_IT: /* ** If drawing wire frame, use the wire frame parameters */ if (AppData.wireFrame) gp = &wireParams; else gp = &g->parms; /* ** If consolidating and using user paths, check if any graphics ** parameters have changed. Flush saved path if so */ if (AppData.consolidate && AppData.drawStrategy != draw_paths && checkGraphicsParams(gp)) flushSavedUserPath(); /* ** Update graphics parameters and draw the path */ setGraphicsParams(gp); drawPath(&g->path, gp->path_type); } /* ** Draw the last buffered path */ if (AppData.consolidate) flushSavedUserPath(); PStranslate(-tx, -ty); } /* end drawPicture() */ /*************************************************************** ** ** FUNCTION: markStartTime ** ** DESCRIPTION: routine to set the start time of the DPS drawing method ** ** PARAMETERS: startTime pointer where current time is stored ** ** RETURN: None. ** ***************************************************************/ static void markStartTime(startTime) struct timeval *startTime; { struct timezone timeZone; gettimeofday (startTime, &timeZone); } /* end markStartTime() */ /*************************************************************** ** ** FUNCTION: getElapsedTime ** ** DESCRIPTION: Returns milliseconds since startTime ** ** PARAMETERS: startTime pointer to start time ** ** RETURN: elapsed time since the start in milliseconds ** ***************************************************************/ static long getElapsedTime (startTime) struct timeval *startTime; { struct timezone timeZone; struct timeval finishTime; long elapsedSeconds, elapsedMicroseconds; gettimeofday (&finishTime, &timeZone); elapsedSeconds = finishTime.tv_sec - startTime->tv_sec; elapsedMicroseconds = finishTime.tv_usec - startTime->tv_usec; return ((long)(elapsedSeconds * 1000 + (elapsedMicroseconds/1000))); } /* end getElapsedtime() */ /*************************************************************** ** ** FUNCTION: convertClipsToUserSpace ** ** DESCRIPTION: Converts X clip list to user space ** ** PARAMETERS: xClipList Current clipping rectangles (in X coords) ** dpsClipCount Number of rectangles in dpsClipList ** xClipCount Number of rectangles in xClipList ** ** RETURN: dpsClipList Clipping rectangles in user space ** ***************************************************************/ static void convertClipsToUserSpace(xClipList, dpsClipList, xClipLen, dpsClipLen) int *xClipList; float **dpsClipList; int xClipLen; int *dpsClipLen; { Point pt; XPoint xpt; register int i; if (*dpsClipLen < xClipLen) { *dpsClipList = (float *) XtRealloc((XtPointer) *dpsClipList, xClipLen * 4 * sizeof(float)); *dpsClipLen = xClipLen; } for (i = 0; i < xClipLen; i++) { xpt.x = xClipList[i*4]; xpt.y = xClipList[i*4+1]; convertToDPS(&xpt, &pt); (*dpsClipList)[i*4] = pt.x; (*dpsClipList)[i*4+1] = pt.y; xpt.x = xClipList[i*4] + xClipList[i*4+2]; xpt.y = xClipList[i*4+1] - xClipList[i*4+3]; convertToDPS(&xpt, &pt); (*dpsClipList)[i*4+2] = pt.x - (*dpsClipList)[i*4]; (*dpsClipList)[i*4+3] = pt.y - (*dpsClipList)[i*4+1]; } } /* end convertClipsToUserSpace() */ /*************************************************************** ** ** FUNCTION: checkWatchEvent ** ** DESCRIPTION: Auxilliary routine for update buffer; checks whether ** the passed event is a GraphicsExpose or NoExpose event ** on the drawable passed as an arg. ** ** PARAMETERS: dpy Display pointer ** e X Event pointer ** arg Client data (drawable to check) ** ** RETURN: Whether event matches. ** ***************************************************************/ static Bool checkWatchEvent(dpy, e, arg) Display *dpy; XEvent *e; char *arg; { return (e->xany.window == (Window) arg && (e->type == GraphicsExpose || e->type == NoExpose)); } /*************************************************************** ** ** FUNCTION: updateBuffer ** ** DESCRIPTION: Updates the backing pixmap after drawing with ** "watch progress" ** ** PARAMETERS: clipList Current clipping rectangles (in X coords) ** clipLen Number of rectangles in clipList ** ** RETURN: None. ** ***************************************************************/ static void updateBuffer(clipList, clipLen) int *clipList; int clipLen; { Drawable d = AppData.buf; Display *dpy = XtDisplay(AppData.currentDraw); static int *bboxList = NULL; static int bboxLen = 0, bboxCount = 0; static float *dpsClipList = NULL; static int clipCount = 0; int i; XEvent e; if (AppData.lastXdelta != 0 || AppData.lastYdelta != 0) { /* ** Copy visible area to new location */ XCopyArea(dpy, d, d, AppData.gc, AppData.lastXdelta, AppData.lastYdelta, AppData.drawingWidth, AppData.drawingHeight, 0, 0); } DPSWaitContext(AppData.dpsCtxt); /* ** That did a sync...get rid of all GraphicsExpose and NoExpose events ** for the pixmap */ while (XCheckIfEvent(dpy, &e, checkWatchEvent, (char *) AppData.buf)) {} for (i = 0; i < clipLen; i++) { XCopyArea(dpy, XtWindow(AppData.currentDraw), d, AppData.gc, clipList[i*4], clipList[i*4+1] - clipList[i*4+3], clipList[i*4+2], clipList[i*4+3], clipList[i*4], clipList[i*4+1] - clipList[i*4+3]); } while (clipLen > 0) { XIfEvent(dpy, &e, checkWatchEvent, (char *) AppData.buf); if (e.type == GraphicsExpose) { addExposureToBBox(&bboxList, &bboxLen, &bboxCount, (XExposeEvent *) &e); if (e.xexpose.count == 0) clipLen--; } else clipLen--; } if (bboxCount > 0) { convertClipsToUserSpace(bboxList, &dpsClipList, bboxCount/4, &clipCount); PSWSetRectViewClip(dpsClipList, bboxCount); drawPicture(dpsClipList, bboxCount / 4); bboxCount = 0; } } /* end updateBuffer() */ /*************************************************************** ** ** FUNCTION: drawSelf ** ** DESCRIPTION: Times and draws the current picture ** ** PARAMETERS: clipList Current clipping rectangles (in X coords) ** clipLen Number of rectangles in clipList ** ** RETURN: None. ** ***************************************************************/ void drawSelf(xClipList, clipLen) int *xClipList; int clipLen; { struct timeval t; static float *dpsClipList = NULL; static int clipCount = 0; convertClipsToUserSpace(xClipList, &dpsClipList, clipLen, &clipCount); PSWSetRectViewClip(dpsClipList, clipLen * 4); setWaitCursor(); DPSWaitContext(AppData.dpsCtxt); markStartTime(&t); if (AppData.showDrawing && !(AppData.scrollStrategy & SCROLL_REDRAW)) { PSgsave(); PSWSetMatrixAndOffset(XtWindow(AppData.currentDraw), AppData.ctm, AppData.xOffset, AppData.yOffset); drawPicture(dpsClipList, clipLen); PSgrestore(); updateBuffer(xClipList, clipLen); } else drawPicture(dpsClipList, clipLen); PSinitviewclip(); DPSWaitContext(AppData.dpsCtxt); showTime(getElapsedTime(&t)); clearWaitCursor(); } /* end drawSelf() */ /*************************************************************** ** ** FUNCTION: convertToX ** ** DESCRIPTION: Convert user space to X coordinates. ** ** PARAMETERS: pXPt points to the target XPoint struct; ** pUPt points to the target Point struct; ** ** RETURN: None ** ***************************************************************/ void convertToX (pXPt, pUPt) XPoint *pXPt; Point *pUPt; { pXPt->x = AppData.ctm[A_COEFF] * pUPt->x + AppData.ctm[C_COEFF] * pUPt->y + AppData.ctm[TX_CONS] + AppData.xOffset; pXPt->y = AppData.ctm[B_COEFF] * pUPt->x + AppData.ctm[D_COEFF] * pUPt->y + AppData.ctm[TY_CONS] + AppData.yOffset; } /* end convertToX() */ /*************************************************************** ** ** FUNCTION: convertToDPS ** ** DESCRIPTION: Convert X coordinates to user space ** ** PARAMETERS: pXPt points to the target XPoint struct; ** pUPt points to the target Point struct; ** ** RETURN: None ** ***************************************************************/ void convertToDPS(pXPt, pUPt) XPoint *pXPt; Point *pUPt; { int ix, iy; ix = pXPt->x - AppData.xOffset; iy = pXPt->y - AppData.yOffset; pUPt->x = AppData.invctm[A_COEFF] * ix + AppData.invctm[C_COEFF] * iy + AppData.invctm[TX_CONS]; pUPt->y = AppData.invctm[B_COEFF] * ix + AppData.invctm[D_COEFF] * iy + AppData.invctm[TY_CONS]; } /* end convertToDPS() */ /*************************************************************** ** ** FUNCTION: convertToOrigDPS ** ** DESCRIPTION: Convert X coordinates to user space using the original ** transformation matrix ** ** PARAMETERS: pXPt points to the target XPoint struct; ** pUPt points to the target Point struct; ** ** RETURN: None ** ***************************************************************/ void convertToOrigDPS(pXPt, pUPt) XPoint *pXPt; Point *pUPt; { int ix, iy; ix = pXPt->x - AppData.xOffset; iy = pXPt->y - AppData.yOffset; pUPt->x = AppData.origInvctm[A_COEFF] * ix + AppData.origInvctm[C_COEFF] * iy + AppData.origInvctm[TX_CONS]; pUPt->y = AppData.origInvctm[B_COEFF] * ix + AppData.origInvctm[D_COEFF] * iy + AppData.origInvctm[TY_CONS]; } /* end convertToOrigDPS() */
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.