This is HitView.c in view mode; [Download] [Up]
/*
* $RCSfile: HitView.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
*/
/***************************************************************
**
** INCLUDES
**
***************************************************************/
#include "Hit.h"
/***************************************************************
**
** FUNCTION: setOrigin
**
** DESCRIPTION: Sets the origin to where it should by using translation and
** updates the saved transformation matrices. Re-initializes
** the matrix and sets it to avoid cumulative roundoff error
**
** PARAMETERS: None
**
** RETURN: None.
**
***************************************************************/
void setOrigin()
{
Point pt;
XPoint xpt;
xpt.x = AppData.originX;
xpt.y = AppData.originY;
convertToOrigDPS(&xpt, &pt);
PSWSetMatrixAndGetTransform(pt.x, pt.y, AppData.scale,
AppData.originX, AppData.originY,
AppData.ctm, AppData.invctm,
&AppData.xOffset, &AppData.yOffset);
} /* setOrigin() */
/***************************************************************
**
** FUNCTION: scrollProc
**
** DESCRIPTION: Callback routine for hitting scroll bars
**
** PARAMETERS: w callback widget ID
** clientData callback client data
** callData callback Motif data structure
**
** RETURN: None.
**
***************************************************************/
void scrollProc (w, clientData, callData)
Widget w;
XtPointer clientData, callData;
{
int x, y;
int deltaX, deltaY;
Widget draw = AppData.drawingArea;
/*
** Get the new values of the scroll bars
*/
XtVaGetValues(AppData.hScroll, XmNvalue, &x, NULL);
XtVaGetValues(AppData.vScroll, XmNvalue, &y, NULL);
/*
** Calculate the delta in the scrolling
*/
deltaX = x - AppData.scrollX;
deltaY = y - AppData.scrollY;
/*
** If we are not already scrolling, and there is some scrolling to do,
** then scroll the pixmap and copy the pixmap to the window
*/
if (deltaX == 0 && deltaY == 0) return;
if (!AppData.scrolling) {
doScroll(deltaX, deltaY);
XCopyArea(XtDisplay(draw), AppData.original,
XtWindow(draw), AppData.gc, 0, 0,
AppData.drawingWidth, AppData.drawingHeight, 0, 0);
}
/*
** Set the scrolling flag; future scrolls will not update the window
** until the current one is done
*/
AppData.scrolling = True;
} /* end scrollProc() */
/***************************************************************
**
** FUNCTION: setViewClip
**
** DESCRIPTION: Set the view clip for scroll updating
**
** PARAMETERS: deltaX X displacement
** deltaY Y displacement
**
** RETURN: None.
**
***************************************************************/
static void setViewClip(deltaX, deltaY)
int deltaX, deltaY;
{
float r[8];
XPoint xll, xur;
Point ll, ur;
/*
** If one of the deltas is 0, then the area to update is just a
** single rectangle.
*/
if (deltaX == 0 || deltaY == 0) {
if (deltaX == 0) {
/*
** Just a single horizontal rectangle
*/
xll.x = 0;
xur.x = AppData.drawingWidth;
if (deltaY > 0) {
xll.y = AppData.drawingHeight;
xur.y = AppData.drawingHeight - deltaY;
} else {
xll.y = -deltaY;
xur.y = 0;
}
} else if (deltaY == 0) {
/*
** Just a single vertical rectangle
*/
xll.y = AppData.drawingHeight;
xur.y = 0;
if (deltaX > 0) {
xll.x = AppData.drawingWidth - deltaX;
xur.x = AppData.drawingWidth;
} else {
xll.x = 0;
xur.x = -deltaX;
}
}
/*
** Convert the rectangle into PS coordinates, and set the view clip
*/
convertToDPS(&xll, &ll);
convertToDPS(&xur, &ur);
PSrectviewclip(ll.x, ll.y, ur.x - ll.x, ur.y - ll.y);
} else {
/*
** Scrolling in both areas, so there are two rectangles. It's
** easiest to do if we let them overlap; fortunately that is
** legal! First do the horizontal rectangle.
*/
xll.x = 0;
xur.x = AppData.drawingWidth;
if (deltaY > 0) {
xll.y = AppData.drawingHeight;
xur.y = AppData.drawingHeight - deltaY;
} else {
xll.y = -deltaY;
xur.y = 0;
}
convertToDPS(&xll, &ll);
convertToDPS(&xur, &ur);
/*
** Store in point array
*/
r[0] = ll.x;
r[1] = ll.y;
r[2] = ur.x - ll.x;
r[3] = ur.y - ll.y;
/*
** Now do vertical rectangle and store in point array
*/
xll.y = AppData.drawingHeight;
xur.y = 0;
if (deltaX > 0) {
xll.x = AppData.drawingWidth - deltaX;
xur.x = AppData.drawingWidth;
} else {
xll.x = 0;
xur.x = -deltaX;
}
convertToDPS(&xll, &ll);
convertToDPS(&xur, &ur);
r[4] = ll.x;
r[5] = ll.y;
r[6] = ur.x - ll.x;
r[7] = ur.y - ll.y;
/*
** Set the view clip to the two rectangles
*/
PSWSetRectViewClip(r, 8);
}
}
/***************************************************************
**
** FUNCTION: doScroll
**
** DESCRIPTION: Scroll the drawing area by some delta
**
** PARAMETERS: deltaX X displacement
** deltaY Y displacement
**
** RETURN: None.
**
***************************************************************/
void doScroll(deltaX, deltaY)
int deltaX, deltaY;
{
/*
** Set the PS origin in the X window to the new settings of
** the scrollbars
*/
AppData.originX -= deltaX;
AppData.originY -= deltaY;
/*
** Update the graphics states for the two buffers to reflect new origin
*/
(void) XDPSSetContextGState(AppData.dpsCtxt, AppData.compGState);
setOrigin();
(void) XDPSUpdateContextGState(AppData.dpsCtxt, AppData.compGState);
(void) XDPSSetContextGState(AppData.dpsCtxt, AppData.origGState);
setOrigin();
(void) XDPSUpdateContextGState(AppData.dpsCtxt, AppData.origGState);
/*
** Update the stored position of the scroll bars
*/
AppData.scrollX += deltaX;
AppData.scrollY += deltaY;
/*
** Either redraw the whole thing or copy and fill in
*/
if (AppData.copyAll) drawSelf();
else {
/*
** Copy visible area to new location
*/
XCopyArea(XtDisplay(AppData.drawingArea), AppData.original,
AppData.original, AppData.gc,
deltaX, deltaY, AppData.drawingWidth,
AppData.drawingHeight, 0, 0);
/*
** Set view clip to fix-up area and redisplay
*/
setViewClip(deltaX, deltaY);
drawSelf();
PSinitviewclip();
}
}
/***************************************************************
**
** FUNCTION: graphicExpose
**
** DESCRIPTION: Callback routine that handles GraphicsExpose and
** NoExpose events. We get one for each copy into the window
** from the pixmap, so they should always be NoExpose events.
** When we get one, call scrollProc to see if we need to
** scroll any more. Not handling further scroll callbacks
** until the event arrives makes scrolling much more responsive.
**
** PARAMETERS: w window widget
** clientData clientdata
** event event information
** goOn continue to dispatch
**
** RETURN: None.
**
***************************************************************/
void graphicExpose (w, clientData, event, goOn)
Widget w;
XtPointer clientData;
XEvent *event;
Boolean *goOn;
{
if (AppData.scrolling) {
AppData.scrolling = False;
scrollProc(w, NULL, NULL);
}
} /* end graphicExpose() */
/***************************************************************
**
** FUNCTION: positionDrawingArea
**
** DESCRIPTION: Routine to position the origin so that the
** point (ix, iy) on the image, in PS coordinates,
** corresponds to the point (vx, vy) on the visible
** window, in X coords.
**
** PARAMETERS:
** ix x coord of point on DPS context (PS coordinates)
** iy y coord of point on DPS context (PS coordinates)
** vx x coors of point on drawing area (X coordinates)
** vy y coors of point on drawing area (X coordinates)
**
** RETURN: None.
**
***************************************************************/
void positionDrawingArea (ix, iy, vx, vy)
float ix;
float iy;
int vx;
int vy;
{
int xoff, yoff;
int hSize, vSize;
float scrollX, scrollY;
AppData.desktop = FALSE;
/* Convert ix, iy into X units */
ix *= ((float) AppData.scaledWidth) / PAGE_WIDTH;
iy *= ((float) AppData.scaledHeight) / PAGE_HEIGHT;
if (AppData.drawingWidth >= AppData.scaledWidth) {
/*
** The scaled width is narrower than the view window, so
** center the picture and set scroll bar to be unscrollable
*/
xoff = (AppData.drawingWidth - AppData.scaledWidth) / 2.0;
scrollX = 0;
hSize = AppData.scaledWidth;
AppData.desktop = TRUE;
} else {
/*
** The scaled width is larger than the view window, so
** turn on the scroll bar, and set up its maximum and
** slider size. Do this by subtracting the view offset from the
** image offset.
*/
scrollX = ix - vx;
scrollX = MAX(scrollX, 0);
scrollX = MIN(scrollX,
AppData.scaledWidth - (int) AppData.drawingWidth);
hSize = AppData.drawingWidth;
xoff = -(int) (scrollX + 0.5);
}
/*
** Now do the same thing for the height. We want to compute the offset
** relative to the lower left corner, but X coordinates are relative
** to the upper left, so the drawing height must be added in. Also, since
** the coordinates go in the other direction, the view offset must be
** added, not subtracted.
*/
if (AppData.drawingHeight >= AppData.scaledHeight) {
yoff = (AppData.drawingHeight - AppData.scaledHeight) / 2.0;
scrollY = AppData.scaledHeight - (int) AppData.drawingHeight;
vSize = AppData.scaledHeight;
vy = AppData.drawingHeight / 2;
AppData.desktop = TRUE;
} else {
scrollY = iy + vy - (int) AppData.drawingHeight;
scrollY = MAX(scrollY, 0);
scrollY = MIN(scrollY,
AppData.scaledHeight - (int) AppData.drawingHeight);
vSize = AppData.drawingHeight;
yoff = -(int) (scrollY + 0.5);
}
/*
** Update the scrollbars
*/
AppData.scrollX = (int) (scrollX + 0.5);
AppData.scrollY = (int) (AppData.scaledHeight -
(int) AppData.drawingHeight - scrollY + 0.5);
XtVaSetValues(AppData.hScroll, XmNmaximum, AppData.scaledWidth,
XmNvalue, AppData.scrollX, XmNsliderSize, hSize, NULL);
XtVaSetValues(AppData.vScroll, XmNmaximum, AppData.scaledHeight,
XmNvalue, AppData.scrollY, XmNsliderSize, vSize, NULL);
/*
** Store the new origin and update the gstates to use this origin
*/
AppData.originX = xoff;
AppData.originY = AppData.drawingHeight - yoff;
(void) XDPSSetContextGState(AppData.dpsCtxt, AppData.compGState);
setOrigin();
(void) XDPSUpdateContextGState(AppData.dpsCtxt, AppData.compGState);
(void) XDPSSetContextGState(AppData.dpsCtxt, AppData.origGState);
setOrigin();
(void) XDPSUpdateContextGState(AppData.dpsCtxt, AppData.origGState);
} /* end positionDrawingArea() */
/***************************************************************
**
** FUNCTION: scaleDrawingArea
**
** DESCRIPTION: Recomputes the scaled drawing size and updates the font
**
** PARAMETERS: None
**
** RETURN: None.
**
***************************************************************/
void scaleDrawingArea ()
{
AppData.scale = (float) AppData.magnify / 100.0;
/*
** Compute the new dimensions that would be needed to hold the entire
** page at the new scale factor
*/
AppData.scaledWidth = PAGE_WIDTH * AppData.origXScale * AppData.scale;
AppData.scaledHeight = PAGE_HEIGHT * AppData.origYScale * AppData.scale;
/*
** Update the saved gstates to make the current font be inversely
** scaled. This keeps the control points from becoming huge or
** tiny.
*/
(void) XDPSSetContextGState(AppData.dpsCtxt, AppData.compGState);
PSselectfont(FontName, CtlPtSize / AppData.scale);
(void) XDPSUpdateContextGState(AppData.dpsCtxt, AppData.compGState);
(void) XDPSSetContextGState(AppData.dpsCtxt, AppData.origGState);
PSselectfont(FontName, CtlPtSize / AppData.scale);
(void) XDPSUpdateContextGState(AppData.dpsCtxt, AppData.origGState);
} /* end scaleDrawingArea() */
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.