/* * Author: William Chia-Wei Cheng (bill.cheng@acm.org) * * Copyright (C) 2001-2006, William Chia-Wei Cheng. * * This file may be distributed under the terms of the Q Public License * as defined by Trolltech AS of Norway and appearing in the file * LICENSE.QPL included in the packaging of this file. * * THIS FILE IS PROVIDED AS IS WITH NO WARRANTY OF ANY KIND, INCLUDING * THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * @(#)$Header: /mm2/home/cvs/bc-src/tgif/polygon.c,v 1.5 2006/02/10 23:21:20 william Exp $ */ #define _INCLUDE_FROM_POLYGON_C_ #include "tgifdefs.h" #include "arc.e" #include "attr.e" #include "auxtext.e" #include "box.e" #include "cmd.e" #include "color.e" #include "choice.e" #include "cursor.e" #include "cutpaste.e" #include "dialog.e" #include "drawing.e" #include "dup.e" #include "grid.e" #include "file.e" #include "mainloop.e" #include "mark.e" #include "msg.e" #include "obj.e" #include "pattern.e" #include "poly.e" #include "polygon.e" #include "ps.e" #include "raster.e" #include "rect.e" #include "ruler.e" #include "select.e" #include "setup.e" #include "spline.e" #include "strtbl.e" #include "util.e" #include "xpixmap.e" int polygonDrawn=FALSE; XPoint *MakePolygonVertex(XOff, YOff, NumVs, Vs) int XOff, YOff, NumVs; register IntPoint *Vs; { register XPoint *v; register int i; int real_x_off, real_y_off; real_x_off = (zoomedIn ? XOff : (XOff>>zoomScale)<>zoomScale)<detail.g->width_spec; double dw=GetWidthInDouble(Width, width_spec, &w_is_int); if (Fill != (-1) && Pen == (-1)) { /* dumping the fill */ switch (Fill) { case SOLIDPAT: fprintf(FP, " %s\n", gPsCmd[PS_EOFILL]); break; case BACKPAT: if (!TransPat) { fprintf(FP, " 1 %s %s\n", gPsCmd[PS_SETGRAY], gPsCmd[PS_EOFILL]); } break; default: if (colorDump || !useGray) { if (preDumpSetup) PSUseColorPattern(); fprintf(FP, " %s %s\n", gPsCmd[PS_EOCLIP], gPsCmd[PS_NEWPATH]); for (i=0; i < 3; i++) fprintf(FP, " "); DumpPatFill(FP, Fill, 8, ObjPtr->bbox, 0, TRUE); } else { GrayCheck(Fill); for (i=0; i < 3; i++) fprintf(FP, " "); fprintf(FP, "%s %s\n", GrayStr(Fill), gPsCmd[PS_SETGRAY]); fprintf(FP, " %s\n", gPsCmd[PS_EOFILL]); } break; } } else if (Fill == (-1) && Pen != (-1)) { /* dumping the pen */ if (ObjPtr->ctm != NULL) { fprintf(FP, " %s\n", &(gPsCmd[PS_TGIFSETMATRIX])[1]); } if (w_is_int) { if (Width != 1) { fprintf(FP, " %1d %s\n", Width, gPsCmd[PS_SETLINEWIDTH]); } } else { fprintf(FP, " %.3f %s\n", dw, gPsCmd[PS_SETLINEWIDTH]); } if (Dash != 0) { fprintf(FP, " ["); for (i = 0; i < dashListLength[Dash]-1; i++) { fprintf(FP, "%1d ", (int)(dashList[Dash][i])); } fprintf(FP, "%1d] 0 %s\n", (int)(dashList[Dash][dashListLength[Dash]-1]), gPsCmd[PS_SETDASH]); } switch (Pen) { case SOLIDPAT: fprintf(FP, " %s\n", gPsCmd[PS_STROKE]); break; case BACKPAT: if (!TransPat) { fprintf(FP, " 1 %s %s 0 %s\n", gPsCmd[PS_SETGRAY], gPsCmd[PS_STROKE], gPsCmd[PS_SETGRAY]); } break; default: if (colorDump || !useGray) { if (preDumpSetup) PSUseColorPattern(); fprintf(FP, " %s\n", gPsCmd[PS_FLATTENPATH]); for (i=0; i < 3; i++) fprintf(FP, " "); DumpPatFill(FP, Pen, 8, ObjPtr->bbox, 0, TRUE); } else { GrayCheck(Pen); fprintf(FP, " %s %s\n", GrayStr(Pen), gPsCmd[PS_SETGRAY]); fprintf(FP, " %s\n", gPsCmd[PS_STROKE]); } break; } } } void DumpPolygonObj(FP, ObjPtr) FILE *FP; struct ObjRec *ObjPtr; { IntPoint *v=ObjPtr->detail.g->vlist, *intv; int num_pts=ObjPtr->detail.g->n; int trans_pat, fill, width, pen, curved, dash, color_index, intn; char *smooth; trans_pat = ObjPtr->trans_pat; fill = ObjPtr->detail.g->fill; width = ObjPtr->detail.g->width; pen = ObjPtr->detail.g->pen; curved = ObjPtr->detail.g->curved; dash = ObjPtr->detail.g->dash; intv = ObjPtr->detail.g->intvlist; intn = ObjPtr->detail.g->intn; smooth = ObjPtr->detail.g->smooth; if ((fill == NONEPAT || (trans_pat && fill == BACKPAT)) && (pen == NONEPAT || (trans_pat && pen == BACKPAT))) { return; } fprintf(FP, "%% POLYGON/CLOSED-SPLINE\n"); color_index = ObjPtr->color; DumpRGBColorLine(FP, color_index, 0, TRUE); if (ObjPtr->ctm != NULL) { float m[6]; fprintf(FP, "%s\n", gPsCmd[PS_GSAVE]); m[CTM_SX] = ((float)ObjPtr->ctm->m[CTM_SX])/((float)1000.0); m[CTM_SY] = ((float)ObjPtr->ctm->m[CTM_SY])/((float)1000.0); m[CTM_SIN] = ((float)ObjPtr->ctm->m[CTM_SIN])/((float)1000.0); m[CTM_MSIN] = ((float)ObjPtr->ctm->m[CTM_MSIN])/((float)1000.0); fprintf(FP, " %1d %1d %s\n", ObjPtr->x, ObjPtr->y, gPsCmd[PS_TRANSLATE]); fprintf(FP, " [%.3f %.3f %.3f %.3f %1d %1d] %s\n", m[CTM_SX], m[CTM_SIN], m[CTM_MSIN], m[CTM_SY], ObjPtr->ctm->t[CTM_TX], ObjPtr->ctm->t[CTM_TY], gPsCmd[PS_CONCAT]); fprintf(FP, " %1d %s %1d %s %s\n", ObjPtr->x, gPsCmd[PS_NEG], ObjPtr->y, gPsCmd[PS_NEG], gPsCmd[PS_TRANSLATE]); } if (curved != LT_INTSPLINE) { DumpJustPolygonPath(FP, v, num_pts, smooth, curved); } else { DumpJustPolygonPath(FP, intv, intn, smooth, curved); } fprintf(FP, "%s\n", gPsCmd[PS_GSAVE]); if (fill != NONEPAT) { if (curved != LT_INTSPLINE) { if ((colorDump || !useGray) && fill > BACKPAT && !trans_pat) { DumpPolygonPath(FP, ObjPtr, v, num_pts, width, (-1), BACKPAT, 0, trans_pat); fprintf(FP, "%s\n", gPsCmd[PS_GRESTORE]); fprintf(FP, "%s\n", gPsCmd[PS_GSAVE]); } DumpPolygonPath(FP, ObjPtr, v, num_pts, width, (-1), fill, 0, trans_pat); } else { if ((colorDump || !useGray) && fill > BACKPAT && !trans_pat) { DumpPolygonPath(FP, ObjPtr, intv, intn, width, (-1), BACKPAT, 0, trans_pat); fprintf(FP, "%s\n", gPsCmd[PS_GRESTORE]); fprintf(FP, "%s\n", gPsCmd[PS_GSAVE]); } DumpPolygonPath(FP, ObjPtr, intv, intn, width, (-1), fill, 0, trans_pat); } } if (pen != NONEPAT) { fprintf(FP, "%s\n", gPsCmd[PS_GRESTORE]); fprintf(FP, "%s\n", gPsCmd[PS_GSAVE]); if (curved != LT_INTSPLINE) { if ((colorDump || !useGray) && pen > BACKPAT && !trans_pat) { DumpPolygonPath(FP, ObjPtr, v, num_pts, width, BACKPAT, (-1), 0, trans_pat); fprintf(FP, "%s\n", gPsCmd[PS_GRESTORE]); fprintf(FP, "%s\n", gPsCmd[PS_GSAVE]); } DumpPolygonPath(FP, ObjPtr, v, num_pts, width, pen, (-1), dash, trans_pat); } else { if ((colorDump || !useGray) && pen > BACKPAT && !trans_pat) { DumpPolygonPath(FP, ObjPtr, intv, intn, width, BACKPAT, (-1), 0, trans_pat); fprintf(FP, "%s\n", gPsCmd[PS_GRESTORE]); fprintf(FP, "%s\n", gPsCmd[PS_GSAVE]); } DumpPolygonPath(FP, ObjPtr, intv, intn, width, pen, (-1), dash, trans_pat); } } fprintf(FP, "%s\n", gPsCmd[PS_GRESTORE]); if (ObjPtr->ctm != NULL) fprintf(FP, "%s\n", gPsCmd[PS_GRESTORE]); fprintf(FP, "\n"); } int NeedsToCachePolygonObj(ObjPtr) struct ObjRec *ObjPtr; { return (ObjPtr->ctm != NULL); } static void MakeCachedPolygon(ObjPtr) struct ObjRec *ObjPtr; { register int i; struct PolygonRec *polygon_ptr=ObjPtr->detail.g; IntPoint *v=polygon_ptr->vlist, *pv=NULL, *pv1=NULL; int num_pts=polygon_ptr->n, num_pts1=0; if (ObjPtr->ctm == NULL) return; if (polygon_ptr->rotated_vlist != NULL) free(polygon_ptr->rotated_vlist); polygon_ptr->rotated_n = 0; polygon_ptr->rotated_vlist = NULL; pv = (IntPoint*)malloc((num_pts+1)*sizeof(IntPoint)); if (pv == NULL) { FailAllocMessage(); return; } for (i=0; i < num_pts; i++) { int x, y; TransformPointThroughCTM(v[i].x-ObjPtr->x, v[i].y-ObjPtr->y, ObjPtr->ctm, &x, &y); pv[i].x = x+ObjPtr->x; pv[i].y = y+ObjPtr->y; } if (polygon_ptr->curved != LT_INTSPLINE) { polygon_ptr->rotated_vlist = MakeMultiSplinePolygonVertex( &(polygon_ptr->rotated_n), ObjPtr->detail.g->smooth, drawOrigX, drawOrigY, num_pts, pv); } else { polygon_ptr->rotated_vlist = MakeIntSplinePolygonVertex( &(polygon_ptr->rotated_n), &(num_pts1), &(pv1), drawOrigX, drawOrigY, num_pts, pv); free(pv1); } free(pv); } void DrawPolygonObj(Win, XOff, YOff, ObjPtr) Window Win; int XOff, YOff; struct ObjRec *ObjPtr; { struct PolygonRec *polygon_ptr=ObjPtr->detail.g; XPoint *v; int trans_pat, fill, width, pen, dash, pixel, num_pts; XGCValues values; trans_pat = ObjPtr->trans_pat; fill = polygon_ptr->fill; width = polygon_ptr->width; pen = polygon_ptr->pen; dash = polygon_ptr->dash; pixel = colorPixels[ObjPtr->color]; if (NeedsToCachePolygonObj(ObjPtr) && polygon_ptr->rotated_vlist==NULL) { MakeCachedPolygon(ObjPtr); } if (userDisableRedraw) return; if ((fill == NONEPAT || (trans_pat && fill == BACKPAT)) && (pen == NONEPAT || (trans_pat && pen == BACKPAT))) { return; } v = polygon_ptr->svlist; num_pts = polygon_ptr->sn; if (fill != 0) { values.foreground = GetDrawingBgPixel(fill, pixel); values.function = GXcopy; values.fill_style = (trans_pat ? FillStippled : FillOpaqueStippled); values.stipple = patPixmap[fill]; XChangeGC(mainDisplay, drawGC, GCForeground | GCFunction | GCFillStyle | GCStipple, &values); if (ObjPtr->ctm == NULL) { XFillPolygon(mainDisplay, Win, drawGC, v, num_pts, Complex, CoordModeOrigin); } else { XFillPolygon(mainDisplay, Win, drawGC, polygon_ptr->rotated_vlist, polygon_ptr->rotated_n, Complex, CoordModeOrigin); } } if (pen == NONEPAT) return; values.foreground = GetDrawingBgPixel(pen, pixel); values.function = GXcopy; values.fill_style = (trans_pat ? FillStippled : FillOpaqueStippled); values.stipple = patPixmap[pen]; values.line_width = ZOOMED_SIZE(width); #ifdef NO_THIN_LINE if (values.line_width < 1) values.line_width = 1; #endif values.join_style = JoinBevel; if (dash != 0) { XSetDashes(mainDisplay, drawGC, 0, dashList[dash], dashListLength[dash]); values.line_style = LineOnOffDash; } else { values.line_style = LineSolid; } XChangeGC(mainDisplay, drawGC, GCForeground | GCFunction | GCFillStyle | GCStipple | GCLineWidth | GCLineStyle | GCJoinStyle, &values); if (ObjPtr->ctm == NULL) { XDrawLines(mainDisplay, Win, drawGC, v, num_pts, CoordModeOrigin); } else { XDrawLines(mainDisplay, Win, drawGC, polygon_ptr->rotated_vlist, polygon_ptr->rotated_n, CoordModeOrigin); } values.join_style = JoinMiter; XChangeGC(mainDisplay, drawGC, GCJoinStyle, &values); } #define CREATE_RELATIVE (FALSE) #define CREATE_ABSOLUTE (TRUE) void CreatePolygonObj(NumPts, CreateAbsolute) int NumPts; int CreateAbsolute; { register int i; struct PtRec *pt_ptr, *next_pt; struct PolygonRec *polygon_ptr; struct ObjRec *obj_ptr; IntPoint *v; int width, w, ltx, lty, rbx, rby; char *smooth=NULL; polygon_ptr = (struct PolygonRec *)malloc(sizeof(struct PolygonRec)); if (polygon_ptr == NULL) FailAllocMessage(); memset(polygon_ptr, 0, sizeof(struct PolygonRec)); polygon_ptr->n = NumPts; v = (IntPoint*)malloc((NumPts+1)*sizeof(IntPoint)); if (v == NULL) FailAllocMessage(); if (curSpline != LT_INTSPLINE) { smooth = (char*)malloc((NumPts+1)*sizeof(char)); if (smooth == NULL) FailAllocMessage(); } pt_ptr = lastPtPtr; ltx = rbx = pt_ptr->x; lty = rby = pt_ptr->y; for (i=NumPts-1; i >= 0; i--, lastPtPtr = next_pt) { next_pt = lastPtPtr->next; v[i].x = CreateAbsolute ? lastPtPtr->x : ABS_X(lastPtPtr->x); v[i].y = CreateAbsolute ? lastPtPtr->y : ABS_Y(lastPtPtr->y); if (curSpline != LT_INTSPLINE) { if (lastPtPtr->x < ltx) ltx = lastPtPtr->x; if (lastPtPtr->y < lty) lty = lastPtPtr->y; if (lastPtPtr->x > rbx) rbx = lastPtPtr->x; if (lastPtPtr->y > rby) rby = lastPtPtr->y; smooth[i] = (curSpline != LT_STRAIGHT); } free(lastPtPtr); } numPtsInPoly = 0; lastPtPtr = NULL; polygon_ptr->vlist = v; polygon_ptr->smooth = smooth; polygon_ptr->svlist = NULL; polygon_ptr->intvlist = NULL; polygon_ptr->fill = objFill; polygon_ptr->width = width = curWidthOfLine[lineWidth]; UtilStrCpyN(polygon_ptr->width_spec, sizeof(polygon_ptr->width_spec), curWidthOfLineSpec[lineWidth]); polygon_ptr->pen = penPat; polygon_ptr->curved = curSpline; polygon_ptr->dash = curDash; polygon_ptr->rotated_n = 0; polygon_ptr->rotated_vlist = NULL; obj_ptr = (struct ObjRec *)malloc(sizeof(struct ObjRec)); if (obj_ptr == NULL) FailAllocMessage(); memset(obj_ptr, 0, sizeof(struct ObjRec)); obj_ptr->detail.g = polygon_ptr; obj_ptr->color = colorIndex; obj_ptr->type = OBJ_POLYGON; if (CreateAbsolute) { obj_ptr->bbox.ltx = obj_ptr->obbox.ltx = obj_ptr->x = ltx; obj_ptr->bbox.lty = obj_ptr->obbox.lty = obj_ptr->y = lty; obj_ptr->bbox.rbx = obj_ptr->obbox.rbx = rbx; obj_ptr->bbox.rby = obj_ptr->obbox.rby = rby; } else { obj_ptr->bbox.ltx = obj_ptr->obbox.ltx = obj_ptr->x = ABS_X(ltx); obj_ptr->bbox.lty = obj_ptr->obbox.lty = obj_ptr->y = ABS_Y(lty); obj_ptr->bbox.rbx = obj_ptr->obbox.rbx = ABS_X(rbx); obj_ptr->bbox.rby = obj_ptr->obbox.rby = ABS_Y(rby); } w = HALF_W(width); obj_ptr->bbox.ltx -= w; obj_ptr->bbox.lty -= w; obj_ptr->bbox.rbx += w; obj_ptr->bbox.rby += w; obj_ptr->id = objId++; obj_ptr->dirty = FALSE; obj_ptr->rotation = 0; obj_ptr->locked = FALSE; obj_ptr->fattr = obj_ptr->lattr = NULL; obj_ptr->ctm = NULL; obj_ptr->invisible = FALSE; obj_ptr->trans_pat = transPat; AdjObjSplineVs(obj_ptr); if (curSpline != LT_INTSPLINE) { UpdPolyBBox(obj_ptr, polygon_ptr->n, polygon_ptr->vlist); } else { UpdPolyBBox(obj_ptr, polygon_ptr->intn, polygon_ptr->intvlist); } AdjObjBBox(obj_ptr); AddObj(NULL, topObj, obj_ptr); } void ResetCreatePolygon() { numPtsInPoly = 0; lastPtPtr = NULL; } void AddPtToCreatePolygon(AbsX, AbsY) int AbsX, AbsY; { struct PtRec *pt_ptr=(struct PtRec *)malloc(sizeof(struct PtRec)); if (pt_ptr == NULL) FailAllocMessage(); memset(pt_ptr, 0, sizeof(struct PtRec)); pt_ptr->next = lastPtPtr; numPtsInPoly++; lastPtPtr = pt_ptr; pt_ptr->x = AbsX; pt_ptr->y = AbsY; } #define POLYGON_DRAW (FALSE) #define POLYGON_ERASE (TRUE) #define POLYGON_CLICK (FALSE) #define POLYGON_DRAG (TRUE) #define POLYGON_STARTSHOW 0 #define POLYGON_DOSHOW 1 #define POLYGON_ENDSHOW 2 static void DoPolygonMeasureCursor(start, num_pts, x, y, dx, dy, erase, drag, closed) int start, num_pts, x, y, dx, dy, erase, drag, closed; { static IntPoint first_pt={0,0}, prev_prev_pt={0,0}, prev_pt={0,0}; char buf[80], w_buf[80], h_buf[80], x_buf[80], y_buf[80], a_buf[80]; int angle2=0; if (erase == POLYGON_DRAW && drag == POLYGON_CLICK) { if (num_pts == 1) { first_pt.x = prev_pt.x = prev_prev_pt.x = x; first_pt.y = prev_pt.y = prev_prev_pt.y = y; } else { prev_prev_pt.x = prev_pt.x; prev_prev_pt.y = prev_pt.y; prev_pt.x = x; prev_pt.y = y; } } if (x == prev_pt.x && y == prev_pt.y) { strcpy(a_buf, "0"); } else if (num_pts == 1) { PointsToArc(prev_pt.x, prev_pt.y, prev_pt.x+100, prev_pt.y, x, y, ARC_CCW, FALSE, NULL, NULL, NULL, NULL, NULL, &angle2); if (angle2 > 180*64) angle2=(360*64)-angle2; FormatAngle(angle2, a_buf); } else if (closed) { if (x == first_pt.x && y == first_pt.y) { strcpy(a_buf, "0"); } else { PointsToArc(x, y, first_pt.x, first_pt.y, prev_pt.x, prev_pt.y, ARC_CCW, FALSE, NULL, NULL, NULL, NULL, NULL, &angle2); if (angle2 > 180*64) angle2=(360*64)-angle2; FormatAngle(angle2, a_buf); } } else { PointsToArc(prev_pt.x, prev_pt.y, prev_prev_pt.x, prev_prev_pt.y, x, y, ARC_CCW, FALSE, NULL, NULL, NULL, NULL, NULL, &angle2); if (angle2 > 180*64) angle2=(360*64)-angle2; FormatAngle(angle2, a_buf); } PixelToMeasurementUnit(w_buf, dx); PixelToMeasurementUnit(h_buf, dy); PixelToMeasurementUnit(x_buf, x); PixelToMeasurementUnit(y_buf, y); sprintf(buf, "w=%s\nh=%s\nx=%s\ny=%s\nangle=%s", w_buf, h_buf, x_buf, y_buf, a_buf); x = OFFSET_X(x); y = OFFSET_Y(y); switch (start) { case POLYGON_STARTSHOW: StartShowMeasureCursor(x, y, buf, TRUE); break; case POLYGON_DOSHOW: ShowMeasureCursor(x, y, buf, TRUE); break; case POLYGON_ENDSHOW: EndShowMeasureCursor(x, y, buf, TRUE); break; } } static XComposeStatus c_stat; static void ContinuePolygon(OrigX, OrigY) int OrigX, OrigY; /* OrigX and OrigY are screen coordinates (scaled and translated). */ { register int i; XEvent input, ev; XButtonEvent *button_ev; XMotionEvent *motion_ev; KeySym key_sym; int start_polygon_x=OrigX, start_polygon_y=OrigY; int end_x, end_y, grid_x, grid_y, done=FALSE; int saved_x, saved_y, closed=FALSE, abort=FALSE; int num_pts=1, n=2, sn=0, max_n=40, intn=0; int ltx=OrigX, lty=OrigY, rbx=OrigX, rby=OrigY; struct PtRec *pt_ptr; XPoint *sv=NULL; IntPoint *pv=NULL, *cntrlv=NULL; SetXorDrawGC(xorColorPixels[colorIndex]); grid_x = end_x = saved_x = OrigX; grid_y = end_y = saved_y = OrigY; if (curSpline != LT_STRAIGHT && splineRubberband) { pv = (IntPoint*)malloc((max_n+1)*sizeof(IntPoint)); if (pv == NULL) FailAllocMessage(); pv[0].x = pv[1].x = pv[2].x = ABS_X(OrigX); pv[0].y = pv[1].y = pv[2].y = ABS_Y(OrigY); switch (curSpline) { case LT_SPLINE: sv = MakeSplinePolygonVertex(&sn, drawOrigX, drawOrigY, n+1, pv); break; case LT_INTSPLINE: sv = MakeIntSplinePolygonVertex(&sn, &intn, &cntrlv, drawOrigX, drawOrigY, n+1, pv); for (i=0; i < sn; i++) { if (sv[i].x < ltx) ltx = sv[i].x; if (sv[i].y < lty) lty = sv[i].y; if (sv[i].x > rbx) rbx = sv[i].x; if (sv[i].y > rby) rby = sv[i].y; } break; } } SaveStatusStrings(); SetMouseStatus(TgLoadCachedString(CSTID_ADD_A_VERTEX), TgLoadCachedString(CSTID_CLOSE_POLYGON_SPLINE), TgLoadCachedString(CSTID_CLOSE_POLYGON_SPLINE)); DoPolygonMeasureCursor(POLYGON_STARTSHOW, num_pts, ABS_X(grid_x), ABS_Y(grid_y), 0, 0, POLYGON_DRAW, POLYGON_CLICK, closed); if (!debugNoPointerGrab) { XGrabPointer(mainDisplay, drawWindow, FALSE, PointerMotionMask | ButtonPressMask, GrabModeAsync, GrabModeAsync, None, handCursor, CurrentTime); } while (!done) { XNextEvent(mainDisplay, &input); if (input.type == Expose || input.type == VisibilityNotify) { ExposeEventHandler(&input, TRUE); SetXorDrawGC(xorColorPixels[colorIndex]); } else if ((!(shiftForDiagMouseMove && DiagEventCheck(&input))) && (input.type == KeyPress || input.type == KeyRelease)) { char s[80]; int has_ch=FALSE; has_ch = XLookupString(&(input.xkey), s, sizeof(s), &key_sym, &c_stat); if (num_pts != 1 && !(curSpline != LT_STRAIGHT && splineRubberband) && (key_sym == XK_Control_L || key_sym == XK_Control_R)) { XDrawLine(mainDisplay, drawWindow, drawGC, saved_x, saved_y, grid_x, grid_y); /* erase */ DoPolygonMeasureCursor(POLYGON_DOSHOW, num_pts, ABS_X(grid_x), ABS_Y(grid_y), ABS_SIZE(abs(grid_x-OrigX)), ABS_SIZE(abs(grid_y-OrigY)), POLYGON_ERASE, POLYGON_DRAG, closed); if (ControlKeyPressedEvent(&input)) { closed = TRUE; } else { closed = FALSE; } /* draw */ DoPolygonMeasureCursor(POLYGON_DOSHOW, num_pts, ABS_X(grid_x), ABS_Y(grid_y), ABS_SIZE(abs(grid_x-OrigX)), ABS_SIZE(abs(grid_y-OrigY)), POLYGON_DRAW, POLYGON_DRAG, closed); } else if (CharIsESC(&(input.xkey), s, key_sym, &has_ch)) { /* erase */ DoPolygonMeasureCursor(POLYGON_ENDSHOW, num_pts, ABS_X(grid_x), ABS_Y(grid_y), ABS_SIZE(abs(grid_x-OrigX)), ABS_SIZE(abs(grid_y-OrigY)), POLYGON_ERASE, POLYGON_CLICK, closed); abort = TRUE; done = TRUE; } } else if (input.type == MotionNotify || (shiftForDiagMouseMove && DiagEventCheck(&input) && (input.type == KeyPress || input.type == KeyRelease))) { unsigned int event_state=0; /* erase */ DoPolygonMeasureCursor(POLYGON_DOSHOW, num_pts, ABS_X(grid_x), ABS_Y(grid_y), ABS_SIZE(abs(grid_x-OrigX)), ABS_SIZE(abs(grid_y-OrigY)), POLYGON_ERASE, POLYGON_DRAG, closed); if (curSpline != LT_STRAIGHT && splineRubberband) { XDrawLines(mainDisplay, drawWindow, drawGC, sv, sn, CoordModeOrigin); if (num_pts != 1 && closed) { XDrawLine(mainDisplay, drawWindow, drawGC, saved_x, saved_y, grid_x, grid_y); } } else { XDrawLine(mainDisplay, drawWindow, drawGC, OrigX, OrigY, grid_x, grid_y); if (num_pts != 1 && closed) { XDrawLine(mainDisplay, drawWindow, drawGC, saved_x, saved_y, grid_x, grid_y); } } if (input.type == KeyPress || input.type == KeyRelease) { end_x = grid_x; end_y = grid_y; event_state = input.xkey.state; } else { motion_ev = &(input.xmotion); end_x = motion_ev->x; end_y = motion_ev->y; event_state = motion_ev->state; } if (shiftForDiagMouseMove && DiagEventCheck(&input)) { if (input.type == KeyRelease) { end_x = input.xkey.x; end_y = input.xkey.y; } else { DiagGridXY(OrigX, OrigY, &end_x, &end_y); } } GridXY(end_x, end_y, &grid_x, &grid_y); MarkRulers(grid_x, grid_y); if (curSpline != LT_STRAIGHT && splineRubberband) { if (sv != NULL) free(sv); pv[n-1].x = ABS_X(grid_x); pv[n-1].y = ABS_Y(grid_y); switch (curSpline) { case LT_SPLINE: sv = MakeSplinePolygonVertex(&sn,drawOrigX,drawOrigY,n+1,pv); break; case LT_INTSPLINE: if (cntrlv != NULL) free(cntrlv); sv = MakeIntSplinePolygonVertex(&sn, &intn, &cntrlv, drawOrigX, drawOrigY, n+1, pv); for (i=0; i < sn; i++) { if (sv[i].x < ltx) ltx = sv[i].x; if (sv[i].y < lty) lty = sv[i].y; if (sv[i].x > rbx) rbx = sv[i].x; if (sv[i].y > rby) rby = sv[i].y; } break; } XDrawLines(mainDisplay, drawWindow, drawGC, sv, sn, CoordModeOrigin); } else { if (num_pts != 1) { if (event_state & ControlMask) { XDrawLine(mainDisplay, drawWindow, drawGC, saved_x, saved_y, grid_x, grid_y); closed = TRUE; } else { closed = FALSE; } } XDrawLine(mainDisplay, drawWindow, drawGC, OrigX, OrigY, grid_x, grid_y); } /* draw */ DoPolygonMeasureCursor(POLYGON_DOSHOW, num_pts, ABS_X(grid_x), ABS_Y(grid_y), ABS_SIZE(abs(grid_x-OrigX)), ABS_SIZE(abs(grid_y-OrigY)), POLYGON_DRAW, POLYGON_DRAG, closed); while (XCheckMaskEvent(mainDisplay, PointerMotionMask, &ev)) ; } else if (input.type == ButtonPress) { /* erase */ DoPolygonMeasureCursor(POLYGON_ENDSHOW, num_pts, ABS_X(grid_x), ABS_Y(grid_y), ABS_SIZE(abs(grid_x-OrigX)), ABS_SIZE(abs(grid_y-OrigY)), POLYGON_ERASE, POLYGON_DRAG, closed); button_ev = &(input.xbutton); end_x = button_ev->x; end_y = button_ev->y; if (shiftForDiagMouseMove && DiagEventCheck(&input)) { DiagGridXY(OrigX, OrigY, &end_x, &end_y); } GridXY(end_x, end_y, &grid_x, &grid_y); if ((grid_x != OrigX || grid_y != OrigY) && (button_ev->button == Button1 || num_pts != 1)) { num_pts++; pt_ptr = (struct PtRec *)malloc(sizeof(struct PtRec)); if (pt_ptr == NULL) FailAllocMessage(); pt_ptr->next = lastPtPtr; lastPtPtr = pt_ptr; pt_ptr->x = grid_x; pt_ptr->y = grid_y; if (curSpline != LT_STRAIGHT && splineRubberband) { if (n >= max_n-3) { max_n += 40; pv = (IntPoint*)realloc(pv, sizeof(IntPoint)*max_n+1); if (pv == NULL) FailAllocMessage(); } XDrawLines(mainDisplay, drawWindow, drawGC, sv, sn, CoordModeOrigin); free(sv); pv[n].x = ABS_X(grid_x); pv[n].y = ABS_Y(grid_y); n++; pv[n].x = pv[0].x; pv[n].y = pv[0].y; switch (curSpline) { case LT_SPLINE: sv = MakeSplinePolygonVertex(&sn, drawOrigX, drawOrigY, n+1, pv); break; case LT_INTSPLINE: if (cntrlv != NULL) free(cntrlv); sv = MakeIntSplinePolygonVertex(&sn, &intn, &cntrlv, drawOrigX, drawOrigY, n+1, pv); for (i=0; i < sn; i++) { if (sv[i].x < ltx) ltx = sv[i].x; if (sv[i].y < lty) lty = sv[i].y; if (sv[i].x > rbx) rbx = sv[i].x; if (sv[i].y > rby) rby = sv[i].y; } break; } XDrawLines(mainDisplay, drawWindow, drawGC, sv, sn, CoordModeOrigin); } } if (num_pts == 2 && closed && button_ev->button == Button1 && !(curSpline != LT_STRAIGHT && splineRubberband)) { XDrawLine(mainDisplay, drawWindow, drawGC, OrigX, OrigY, grid_x, grid_y); } if (grid_x == start_polygon_x && grid_y == start_polygon_y) { if (curSpline != LT_STRAIGHT && splineRubberband) { XDrawLines(mainDisplay, drawWindow, drawGC, sv, sn, CoordModeOrigin); } else { XDrawLine(mainDisplay, drawWindow, drawGC, OrigX, OrigY, grid_x, grid_y); if (num_pts != 1 && closed) { XDrawLine(mainDisplay, drawWindow, drawGC, saved_x, saved_y, grid_x, grid_y); } if (num_pts < 4) { XDrawLine(mainDisplay, drawWindow, drawGC, saved_x, saved_y, OrigX, OrigY); } } done = TRUE; } else { switch(button_ev->button) { case Button1: OrigX = grid_x; OrigY = grid_y; /* draw */ DoPolygonMeasureCursor(POLYGON_STARTSHOW, num_pts, ABS_X(grid_x), ABS_Y(grid_y), 0, 0, POLYGON_DRAW, POLYGON_CLICK, closed); break; case Button2: case Button3: if (curSpline != LT_STRAIGHT && splineRubberband) { XDrawLines(mainDisplay, drawWindow, drawGC, sv, sn, CoordModeOrigin); } else { XDrawLine(mainDisplay, drawWindow, drawGC, OrigX, OrigY, grid_x, grid_y); if (num_pts != 1 && closed) { XDrawLine(mainDisplay, drawWindow, drawGC, saved_x, saved_y, grid_x, grid_y); } if (num_pts < 3) { XDrawLine(mainDisplay, drawWindow, drawGC, saved_x, saved_y, OrigX, OrigY); } } if (num_pts == 1) { done = TRUE; break; } num_pts++; pt_ptr = (struct PtRec *)malloc(sizeof(struct PtRec)); if (pt_ptr == NULL) FailAllocMessage(); pt_ptr->next = lastPtPtr; lastPtPtr = pt_ptr; pt_ptr->x = start_polygon_x; pt_ptr->y = start_polygon_y; done = TRUE; break; } } } } XUngrabPointer(mainDisplay, CurrentTime); RestoreStatusStrings(); SetMouseStatus(NULL, NULL, NULL); Msg(""); if (curSpline != LT_STRAIGHT && splineRubberband) { free(pv); free(sv); if (curSpline == LT_INTSPLINE && cntrlv != NULL) free(cntrlv); } if (!abort && num_pts > 3) { CreatePolygonObj(num_pts, CREATE_RELATIVE); RecordNewObjCmd(); RedrawAnArea(botObj, topObj->bbox.ltx-GRID_ABS_SIZE(1), topObj->bbox.lty-GRID_ABS_SIZE(1), topObj->bbox.rbx+GRID_ABS_SIZE(1), topObj->bbox.rby+GRID_ABS_SIZE(1)); polygonDrawn = TRUE; SetFileModified(TRUE); } else { struct PtRec *pt_ptr, *next_pt; if (curSpline != LT_INTSPLINE) { ltx = rbx = grid_x; lty = rby = grid_y; } for (pt_ptr=lastPtPtr; pt_ptr != NULL; pt_ptr=next_pt) { next_pt = pt_ptr->next; if (curSpline != LT_INTSPLINE) { if (pt_ptr->x < ltx) ltx = pt_ptr->x; if (pt_ptr->y < lty) lty = pt_ptr->y; if (pt_ptr->x > rbx) rbx = pt_ptr->x; if (pt_ptr->y > rby) rby = pt_ptr->y; } free(pt_ptr); } RedrawAnArea(botObj, ABS_X(ltx)-GRID_ABS_SIZE(1), ABS_Y(lty)-GRID_ABS_SIZE(1), ABS_X(rbx)+GRID_ABS_SIZE(1), ABS_Y(rby)+GRID_ABS_SIZE(1)); numPtsInPoly = 0; lastPtPtr = NULL; polygonDrawn = FALSE; } } void DrawPolygon(input) XEvent *input; { XButtonEvent *button_ev; int mouse_x, mouse_y, grid_x, grid_y; if (input->type != ButtonPress) return; button_ev = &(input->xbutton); if (button_ev->button == Button1) { mouse_x = button_ev->x; mouse_y = button_ev->y; GridXY(mouse_x, mouse_y, &grid_x, &grid_y); numPtsInPoly = 1; lastPtPtr = (struct PtRec *)malloc(sizeof(struct PtRec)); if (lastPtPtr == NULL) FailAllocMessage(); lastPtPtr->x = grid_x; lastPtPtr->y = grid_y; lastPtPtr->next = NULL; ContinuePolygon(grid_x, grid_y); } } void SelectAndHighLightNewObjects(PrevTopObj) struct ObjRec *PrevTopObj; { register struct ObjRec *obj_ptr; register struct SelRec *sel_ptr; if (topSel != NULL) { HighLightReverse(); RemoveAllSel(); } for (obj_ptr=topObj; obj_ptr != PrevTopObj; obj_ptr=obj_ptr->next) { sel_ptr = (struct SelRec *)malloc(sizeof(struct SelRec)); if (sel_ptr == NULL) FailAllocMessage(); sel_ptr->obj = obj_ptr; sel_ptr->prev = sel_ptr->next = NULL; AddSel(botSel, NULL, sel_ptr); } UpdSelBBox(); HighLightForward(); } void InputPolygonPts() { char inbuf[MAXSTRING+1]; int more_polygon=FALSE, num_polygons=0; int started_composite=FALSE; struct ObjRec *saved_top_obj=topObj; MakeQuiescent(); XSync(mainDisplay, False); do { int len, ok=TRUE, num_pts=0; int first_x=0, first_y=0, eof=TRUE; struct PtRec *pt_ptr; more_polygon = FALSE; numPtsInPoly = 0; lastPtPtr = NULL; printf("%s\n", TgLoadString(STID_INPUT_PAIRS_OF_POINTS_POLYGON)); printf("> "); fflush(stdout); while (ok && fgets(inbuf, MAXSTRING, stdin) != NULL) { if (strcmp(inbuf, ";\n") == 0) { eof = FALSE; more_polygon = TRUE; break; } if (strcmp(inbuf, ".\n") == 0) { eof = FALSE; break; } len = strlen(inbuf); if (len > 0) { char *c_ptr=strtok(inbuf," ,\t\n"), *c_ptr1=NULL; if (c_ptr != NULL) c_ptr1 = strtok(NULL," ,\t\n"); if (c_ptr1 != NULL) while (strchr(" ,\t\n", *c_ptr1)) c_ptr1++; while (c_ptr != NULL && c_ptr1 != NULL) { num_pts++; pt_ptr = (struct PtRec *)malloc(sizeof(struct PtRec)); if (pt_ptr == NULL) FailAllocMessage(); pt_ptr->next = lastPtPtr; if (sscanf(c_ptr, "%d", &pt_ptr->x) != 1 || sscanf(c_ptr1, "%d", &pt_ptr->y) != 1) { ok = FALSE; MsgBox(TgLoadString(STID_READ_INT_ERR_FOR_POLYGON_PTS), TOOL_NAME, INFO_MB); XSync(mainDisplay, False); break; } if (lastPtPtr == NULL) { first_x = pt_ptr->x; first_y = pt_ptr->y; } lastPtPtr = pt_ptr; c_ptr = strtok(NULL," ,\t\n"); if (c_ptr != NULL) c_ptr1 = strtok(NULL," ,\t\n"); if (c_ptr1 != NULL) while (strchr(" ,\t\n", *c_ptr1)) c_ptr1++; } if (c_ptr != NULL) { ok = FALSE; MsgBox(TgLoadString(STID_READ_INT_ERR_FOR_POLYGON_PTS), TOOL_NAME, INFO_MB); XSync(mainDisplay, False); } } printf("> "); fflush(stdout); } printf("\n"); if (eof) rewind(stdin); if (ok && num_pts > 2) { num_polygons++; if (lastPtPtr->x != first_x || lastPtPtr->y != first_y) { num_pts++; pt_ptr = (struct PtRec *)malloc(sizeof(struct PtRec)); if (pt_ptr == NULL) FailAllocMessage(); pt_ptr->next = lastPtPtr; pt_ptr->x = first_x; pt_ptr->y = first_y; lastPtPtr = pt_ptr; } CreatePolygonObj(num_pts, CREATE_ABSOLUTE); if (more_polygon || num_polygons > 1) { if (num_polygons <= 1) { StartCompositeCmd(); started_composite = TRUE; } RecordNewObjCmd(); numRedrawBBox = 0; topObj->tmp_parent = NULL; DrawObj(drawWindow, topObj); } else { RecordNewObjCmd(); RedrawAnArea(botObj, topObj->bbox.ltx-GRID_ABS_SIZE(1), topObj->bbox.lty-GRID_ABS_SIZE(1), topObj->bbox.rbx+GRID_ABS_SIZE(1), topObj->bbox.rby+GRID_ABS_SIZE(1)); SelectTopObj(); SetFileModified(TRUE); justDupped = FALSE; } } if (ok && num_pts <= 2) { MsgBox(TgLoadString(STID_TOO_FEW_POINTERS_ENTERED), TOOL_NAME, INFO_MB); XSync(mainDisplay, False); } for ( ; lastPtPtr != NULL; lastPtPtr=pt_ptr) { pt_ptr = lastPtPtr->next; free(pt_ptr); } } while (more_polygon); if (num_polygons > 1 || started_composite) { SelectAndHighLightNewObjects(saved_top_obj); GroupSelObj(TRUE, TRUE, TRUE); EndCompositeCmd(); SetFileModified(TRUE); justDupped = FALSE; } } static void AddToLastPoint(XOff, YOff) int XOff, YOff; { struct PtRec *pt_ptr=(struct PtRec *)malloc(sizeof(struct PtRec)); if (pt_ptr == NULL) FailAllocMessage(); pt_ptr->next = lastPtPtr; numPtsInPoly++; lastPtPtr = pt_ptr; pt_ptr->x = XOff; pt_ptr->y = YOff; } void GetBoundingBox() { struct SelRec *sel_ptr, *tmp_top_sel=NULL, *tmp_bot_sel=NULL; int num_created=0; if (topSel == NULL) { MsgBox(TgLoadCachedString(CSTID_NO_OBJ_SELECTED), TOOL_NAME, INFO_MB); return; } if (curChoice == VERTEXMODE) SetCurChoice(NOTHING); tmp_top_sel = tmp_bot_sel = NULL; HighLightReverse(); StartCompositeCmd(); for (sel_ptr=botSel; sel_ptr != NULL; sel_ptr=sel_ptr->prev) { struct ObjRec *obj_ptr=sel_ptr->obj; struct SelRec *new_sel_ptr; if (obj_ptr->ctm == NULL) { struct BBRec *p_obbox=(&obj_ptr->obbox); AddToLastPoint(p_obbox->ltx, p_obbox->lty); AddToLastPoint(p_obbox->ltx, p_obbox->rby); AddToLastPoint(p_obbox->rbx, p_obbox->rby); AddToLastPoint(p_obbox->rbx, p_obbox->lty); AddToLastPoint(p_obbox->ltx, p_obbox->lty); CreatePolygonObj(5, CREATE_ABSOLUTE); } else { int i; numPtsInPoly = 0; lastPtPtr = NULL; for (i=0; i < 5; i++) { AddToLastPoint(obj_ptr->rotated_obbox[i].x, obj_ptr->rotated_obbox[i].y); } CreatePolygonObj(5, CREATE_RELATIVE); } new_sel_ptr = (struct SelRec *)malloc(sizeof(struct SelRec)); if (new_sel_ptr == NULL) FailAllocMessage(); new_sel_ptr->obj = topObj; new_sel_ptr->next = NULL; new_sel_ptr->prev = NULL; PrepareToRecord(CMD_NEW, NULL, NULL, 0); RecordCmd(CMD_NEW, NULL, new_sel_ptr, new_sel_ptr, 1); new_sel_ptr->next = tmp_top_sel; if (tmp_top_sel == NULL) { tmp_bot_sel = new_sel_ptr; } else { tmp_top_sel->prev = new_sel_ptr; } tmp_top_sel = new_sel_ptr; num_created++; } EndCompositeCmd(); RemoveAllSel(); topSel = tmp_top_sel; botSel = tmp_bot_sel; UpdSelBBox(); RedrawAnArea(botObj, selLtX-GRID_ABS_SIZE(1), selLtY-GRID_ABS_SIZE(1), selRbX+GRID_ABS_SIZE(1), selRbY+GRID_ABS_SIZE(1)); HighLightForward(); justDupped = FALSE; SetFileModified(TRUE); } void SavePolygonObj(FP, ObjPtr) FILE *FP; struct ObjRec *ObjPtr; { register int i, n; int count; struct PolygonRec *polygon_ptr=ObjPtr->detail.g; n = polygon_ptr->n; if (fprintf(FP, "polygon('%s','',%1d,[\n\t", colorMenuItems[ObjPtr->color], polygon_ptr->n) == EOF) { writeFileFailed = TRUE; } for (i=0, count = 0; i < n-1; i++) { if (fprintf(FP, "%1d,%1d,", polygon_ptr->vlist[i].x, polygon_ptr->vlist[i].y) == EOF) { writeFileFailed = TRUE; } if (++count == 8) { count = 0; if (fprintf(FP, "\n\t") == EOF) writeFileFailed = TRUE; } } if (fprintf(FP, "%1d,%1d],", polygon_ptr->vlist[n-1].x, polygon_ptr->vlist[n-1].y) == EOF) writeFileFailed = TRUE; if (fprintf(FP, "%1d,%1d,%1d,%1d,%1d,%1d,%1d,%1d,%1d,%1d,'%s',%1d,", polygon_ptr->fill, polygon_ptr->width, polygon_ptr->pen, polygon_ptr->curved, ObjPtr->id, polygon_ptr->dash, ObjPtr->rotation, ObjPtr->locked, ObjPtr->ctm!=NULL, ObjPtr->invisible, polygon_ptr->width_spec, ObjPtr->trans_pat) == EOF) { writeFileFailed = TRUE; } if (fprintf(FP, "\n \"") == EOF) writeFileFailed = TRUE; SaveSmoothHinge(FP, polygon_ptr->curved, polygon_ptr->n, polygon_ptr->smooth); if (fprintf(FP, "\",") == EOF) writeFileFailed = TRUE; if (ObjPtr->ctm != NULL && fprintf(FP, "[\n\t%1d,%1d,%1d,%1d,%1d,%1d,%g,%g,%g,%g,%1d,%1d],", ObjPtr->x, ObjPtr->y, ObjPtr->orig_obbox.ltx, ObjPtr->orig_obbox.lty, ObjPtr->orig_obbox.rbx, ObjPtr->orig_obbox.rby, ObjPtr->ctm->m[CTM_SX], ObjPtr->ctm->m[CTM_SIN], ObjPtr->ctm->m[CTM_MSIN], ObjPtr->ctm->m[CTM_SY], ObjPtr->ctm->t[CTM_TX], ObjPtr->ctm->t[CTM_TY]) == EOF) { writeFileFailed = TRUE; } if (serializingFile) SaveCreatorID(FP, ObjPtr, " "); SaveAttrs(FP, ObjPtr->lattr); if (fprintf(FP, ")") == EOF) writeFileFailed = TRUE; } void ReadPolygonObj(FP, Inbuf, ObjPtr) FILE *FP; char *Inbuf; struct ObjRec **ObjPtr; { register int i; struct PolygonRec *polygon_ptr; IntPoint *v; char color_str[40], bg_color_str[40], *s, inbuf[MAXSTRING]; int num_pts, ltx=0, lty=0, rbx=0, rby=0, x, y, id=0; int trans_pat=FALSE, fill, width, pen, w, new_alloc, locked=FALSE; int curved, dash, initialized, rotation, count; int real_x=0, real_y=0, transformed=FALSE, invisible=FALSE; char *smooth=NULL, width_spec[40]; struct XfrmMtrxRec *ctm=NULL; struct BBRec orig_obbox; *ObjPtr = NULL; s = FindChar((int)'(', Inbuf); s = ParseStr(s, (int)',', color_str, sizeof(color_str)); if (fileVersion >= 37) { s = ParseStr(s, (int)',', bg_color_str, sizeof(bg_color_str)); } InitScan(s, "\t\n, []"); if (GETINT("polygon", num_pts, "number of points") == INVALID) { return; } if (num_pts <= 0) { (void)sprintf(gszMsgBox, TgLoadString(STID_INVALID_NUM_PTS_IN_POLYGON), scanFileName, scanLineNum); if (PRTGIF) { fprintf(stderr, "%s\n", gszMsgBox); } else { Msg(gszMsgBox); } return; } *ObjPtr = (struct ObjRec *)malloc(sizeof(struct ObjRec)); if (*ObjPtr == NULL) FailAllocMessage(); memset(*ObjPtr, 0, sizeof(struct ObjRec)); polygon_ptr = (struct PolygonRec *)malloc(sizeof(struct PolygonRec)); if (polygon_ptr == NULL) FailAllocMessage(); memset(polygon_ptr, 0, sizeof(struct PolygonRec)); if (num_pts < 3) { v = (IntPoint*)malloc(5*sizeof(IntPoint)); if (v == NULL) FailAllocMessage(); smooth = (char*)malloc(5*sizeof(char)); if (smooth == NULL) FailAllocMessage(); } else { v = (IntPoint*)malloc((num_pts+1)*sizeof(IntPoint)); if (v == NULL) FailAllocMessage(); smooth = (char*)malloc((num_pts+1)*sizeof(char)); if (smooth == NULL) FailAllocMessage(); } initialized = FALSE; *width_spec = '\0'; if (fileVersion <= 13) { for (i=0; i < num_pts; i++) { if (GETINT("polygon", x, "x") == INVALID || GETINT("polygon", y, "y") == INVALID) { free(*ObjPtr); free(polygon_ptr); free(v); *ObjPtr = NULL; return; } v[i].x = x; v[i].y = y; if (!initialized) { initialized = TRUE; ltx = rbx = x; lty = rby = y; } else { if (x < ltx) ltx = x; if (y < lty) lty = y; if (x > rbx) rbx = x; if (y > rby) rby = y; } } } else { fgets(inbuf, MAXSTRING, FP); scanLineNum++; s = inbuf; InitScan(s, "\t\n, []"); for (i=0, count = 0; i < num_pts; i++) { if (GETINT("polygon", x, "x") == INVALID || GETINT("polygon", y, "y") == INVALID) { free(*ObjPtr); free(polygon_ptr); free(v); *ObjPtr = NULL; return; } v[i].x = x; v[i].y = y; if (!initialized) { initialized = TRUE; ltx = rbx = x; lty = rby = y; } else { if (x < ltx) ltx = x; if (y < lty) lty = y; if (x > rbx) rbx = x; if (y > rby) rby = y; } if (++count == 8 && i != num_pts-1) { count = 0; fgets(inbuf, MAXSTRING, FP); scanLineNum++; s = inbuf; InitScan(s, "\t\n, []"); } } } switch (num_pts) { case 1: sprintf(gszMsgBox, TgLoadCachedString(CSTID_SNGL_PT_POLYGON_CONVERTED), v[0].x, v[0].y); if (PRTGIF) { fprintf(stderr, "%s\n", gszMsgBox); } else { Msg(gszMsgBox); } v[3].x = v[2].x = v[1].x = v[0].x; v[3].y = v[2].y = v[1].y = v[0].y; num_pts = 4; break; case 2: sprintf(gszMsgBox, TgLoadCachedString(CSTID_TWO_PT_POLYGON_CONVERTED), v[0].x, v[0].y, v[1].x, v[1].y); if (PRTGIF) { fprintf(stderr, "%s\n", gszMsgBox); } else { Msg(gszMsgBox); } v[3].x = v[2].x = v[0].x; v[3].y = v[2].y = v[0].y; num_pts = 4; break; case 3: sprintf(gszMsgBox, TgLoadCachedString(CSTID_TWO_PT_POLYGON_CONVERTED), v[0].x, v[0].y, v[1].x, v[1].y); if (PRTGIF) { fprintf(stderr, "%s\n", gszMsgBox); } else { Msg(gszMsgBox); } v[3].x = v[2].x = v[0].x; v[3].y = v[2].y = v[0].y; num_pts = 4; break; } polygon_ptr->n = num_pts; dash = 0; rotation = 0; if (fileVersion <= 3) { if (GETINT("polygon", fill, "fill") == INVALID || GETINT("polygon", width, "width") == INVALID || GETINT("polygon", pen, "pen") == INVALID) { free(*ObjPtr); free(polygon_ptr); free(v); *ObjPtr = NULL; return; } if (width == LINE_CURVED) { width = 0; curved = TRUE; } else { curved = FALSE; } switch (width) { case 1: width = 3; break; case 2: width = 6; break; } id = objId++; } else if (fileVersion <= 5) { if (GETINT("polygon", fill, "fill") == INVALID || GETINT("polygon", width, "width") == INVALID || GETINT("polygon", pen, "pen") == INVALID || GETINT("polygon", curved, "curved") == INVALID) { free(*ObjPtr); free(polygon_ptr); free(v); *ObjPtr = NULL; return; } switch (width) { case 1: width = 3; break; case 2: width = 6; break; } id = objId++; } else if (fileVersion <= 7) { if (GETINT("polygon", fill, "fill") == INVALID || GETINT("polygon", width, "width") == INVALID || GETINT("polygon", pen, "pen") == INVALID || GETINT("polygon", curved, "curved") == INVALID) { free(*ObjPtr); free(polygon_ptr); free(v); *ObjPtr = NULL; return; } id = objId++; } else if (fileVersion <= 8) { if (GETINT("polygon", fill, "fill") == INVALID || GETINT("polygon", width, "width") == INVALID || GETINT("polygon", pen, "pen") == INVALID || GETINT("polygon", curved, "curved") == INVALID || GETINT("polygon", id, "id") == INVALID) { free(*ObjPtr); free(polygon_ptr); free(v); *ObjPtr = NULL; return; } if (id >= objId) objId = id+1; } else if (fileVersion <= 13) { if (GETINT("polygon", fill, "fill") == INVALID || GETINT("polygon", width, "width") == INVALID || GETINT("polygon", pen, "pen") == INVALID || GETINT("polygon", curved, "curved") == INVALID || GETINT("polygon", id, "id") == INVALID || GETINT("polygon", dash, "dash") == INVALID) { free(*ObjPtr); free(polygon_ptr); free(v); *ObjPtr = NULL; return; } if (id >= objId) objId = id+1; } else if (fileVersion <= 25) { if (GETINT("polygon", fill, "fill") == INVALID || GETINT("polygon", width, "width") == INVALID || GETINT("polygon", pen, "pen") == INVALID || GETINT("polygon", curved, "curved") == INVALID || GETINT("polygon", id, "id") == INVALID || GETINT("polygon", dash, "dash") == INVALID || GETINT("polygon", rotation, "rotation") == INVALID) { free(*ObjPtr); free(polygon_ptr); free(v); *ObjPtr = NULL; return; } if (id >= objId) objId = id+1; } else if (fileVersion <= 32) { if (GETINT("polygon", fill, "fill") == INVALID || GETINT("polygon", width, "width") == INVALID || GETINT("polygon", pen, "pen") == INVALID || GETINT("polygon", curved, "curved") == INVALID || GETINT("polygon", id, "id") == INVALID || GETINT("polygon", dash, "dash") == INVALID || GETINT("polygon", rotation, "rotation") == INVALID || GETINT("polygon", locked, "locked") == INVALID) { free(*ObjPtr); free(polygon_ptr); free(v); *ObjPtr = NULL; return; } if (id >= objId) objId = id+1; } else if (fileVersion <= 34) { if (GETINT("polygon", fill, "fill") == INVALID || GETINT("polygon", width, "width") == INVALID || GETINT("polygon", pen, "pen") == INVALID || GETINT("polygon", curved, "curved") == INVALID || GETINT("polygon", id, "id") == INVALID || GETINT("polygon", dash, "dash") == INVALID || GETINT("polygon", rotation, "rotation") == INVALID || GETINT("polygon", locked, "locked") == INVALID || GETINT("polygon", transformed, "transformed") == INVALID || GETINT("polygon", invisible, "invisible") == INVALID || GETSTR("polygon", width_spec, "width_spec") == INVALID) { free(*ObjPtr); free(polygon_ptr); free(v); *ObjPtr = NULL; return; } if (id >= objId) objId = id+1; UtilRemoveQuotes(width_spec); } else { if (GETINT("polygon", fill, "fill") == INVALID || GETINT("polygon", width, "width") == INVALID || GETINT("polygon", pen, "pen") == INVALID || GETINT("polygon", curved, "curved") == INVALID || GETINT("polygon", id, "id") == INVALID || GETINT("polygon", dash, "dash") == INVALID || GETINT("polygon", rotation, "rotation") == INVALID || GETINT("polygon", locked, "locked") == INVALID || GETINT("polygon", transformed, "transformed") == INVALID || GETINT("polygon", invisible, "invisible") == INVALID || GETSTR("polygon", width_spec, "width_spec") == INVALID || GETINT("polygon", trans_pat, "trans_pat") == INVALID) { free(*ObjPtr); free(polygon_ptr); free(v); *ObjPtr = NULL; return; } if (id >= objId) objId = id+1; UtilRemoveQuotes(width_spec); } if (fileVersion <= 16 && width <= 6) width = origWidthOfLine[width]; if (fileVersion <= 25 && curved > 1) curved = 0; if (curved == LT_INTSPLINE && smooth != NULL) { free(smooth); smooth = NULL; } if (fileVersion <= 30) { switch (curved) { case LT_STRAIGHT: for (i=0; i < num_pts; i++) smooth[i] = FALSE; break; case LT_SPLINE: for (i=0; i < num_pts; i++) smooth[i] = TRUE; break; } } else if (!ReadSmoothHinge(FP, curved, num_pts, smooth)) { free(*ObjPtr); free(polygon_ptr); free(v); *ObjPtr = NULL; return; } if (fileVersion >= 33 && transformed) { fgets(inbuf, MAXSTRING, FP); scanLineNum++; InitScan(inbuf, "\t\n, "); ctm = (struct XfrmMtrxRec *)malloc(sizeof(struct XfrmMtrxRec)); if (ctm == NULL) FailAllocMessage(); if (GETINT("polygon", real_x, "real_x") == INVALID || GETINT("polygon", real_y, "real_y") == INVALID || GETINT("polygon", orig_obbox.ltx, "orig_obbox.ltx") == INVALID || GETINT("polygon", orig_obbox.lty, "orig_obbox.lty") == INVALID || GETINT("polygon", orig_obbox.rbx, "orig_obbox.rbx") == INVALID || GETINT("polygon", orig_obbox.rby, "orig_obbox.rby") == INVALID || GETDBL("polygon", ctm->m[CTM_SX], "CTM_SX") == INVALID || GETDBL("polygon", ctm->m[CTM_SIN], "CTM_SIN") == INVALID || GETDBL("polygon", ctm->m[CTM_MSIN], "CTM_MSIN") == INVALID || GETDBL("polygon", ctm->m[CTM_SY], "CTM_SY") == INVALID || GETINT("polygon", ctm->t[CTM_TX], "CTM_TX") == INVALID || GETINT("polygon", ctm->t[CTM_TY], "CTM_TY") == INVALID) { free(*ObjPtr); free(polygon_ptr); free(v); *ObjPtr = NULL; free(ctm); return; } } if (fileVersion <= 32) { sprintf(width_spec, "%1d", width); } fill = UpgradePenFill(fill); pen = UpgradePenFill(pen); polygon_ptr->fill = fill; polygon_ptr->width = width; UtilStrCpyN(polygon_ptr->width_spec, sizeof(polygon_ptr->width_spec), width_spec); polygon_ptr->pen = pen; polygon_ptr->curved = curved; polygon_ptr->dash = dash; polygon_ptr->vlist = v; polygon_ptr->smooth = smooth; polygon_ptr->svlist = NULL; polygon_ptr->intvlist = NULL; polygon_ptr->rotated_n = 0; polygon_ptr->rotated_vlist = NULL; (*ObjPtr)->x = ltx; (*ObjPtr)->y = lty; (*ObjPtr)->color = QuickFindColorIndex(*ObjPtr, color_str, &new_alloc, TRUE); (*ObjPtr)->dirty = FALSE; (*ObjPtr)->id = id; (*ObjPtr)->rotation = rotation; (*ObjPtr)->locked = locked; (*ObjPtr)->type = OBJ_POLYGON; (*ObjPtr)->obbox.ltx = ltx; (*ObjPtr)->obbox.lty = lty; (*ObjPtr)->obbox.rbx = rbx; (*ObjPtr)->obbox.rby = rby; w = HALF_W(width); (*ObjPtr)->bbox.ltx = ltx - w; (*ObjPtr)->bbox.lty = lty - w; (*ObjPtr)->bbox.rbx = rbx + w; (*ObjPtr)->bbox.rby = rby + w; (*ObjPtr)->detail.g = polygon_ptr; (*ObjPtr)->ctm = ctm; (*ObjPtr)->invisible = invisible; (*ObjPtr)->trans_pat = trans_pat; if (ctm != NULL) { memcpy(&(*ObjPtr)->orig_obbox, &orig_obbox, sizeof(struct BBRec)); (*ObjPtr)->x = real_x; (*ObjPtr)->y = real_y; GetTransformedOBBoxOffsetVs(*ObjPtr, (*ObjPtr)->rotated_obbox); } AdjObjCache(*ObjPtr); AdjObjSplineVs(*ObjPtr); if (polygon_ptr->curved != LT_INTSPLINE) { UpdPolyBBox(*ObjPtr, polygon_ptr->n, polygon_ptr->vlist); } else { UpdPolyBBox(*ObjPtr, polygon_ptr->intn, polygon_ptr->intvlist); } } void SetPolygonPropMask(ObjPtr, plMask, plSkip, pProp) struct ObjRec *ObjPtr; long *plMask, *plSkip; struct PropertiesRec *pProp; { struct PolygonRec *polygon_ptr=ObjPtr->detail.g; SetCTMPropertyMask(ObjPtr->ctm, plMask, plSkip, pProp); SetIntPropertyMask(PROP_MASK_COLOR, ObjPtr->color, colorMenuItems[ObjPtr->color], plMask, plSkip, pProp); SetIntPropertyMask(PROP_MASK_WIDTH, polygon_ptr->width, polygon_ptr->width_spec, plMask, plSkip, pProp); SetIntPropertyMask(PROP_MASK_TRANSPAT, ObjPtr->trans_pat, NULL, plMask, plSkip, pProp); SetIntPropertyMask(PROP_MASK_FILL, polygon_ptr->fill, NULL, plMask, plSkip, pProp); SetIntPropertyMask(PROP_MASK_PEN, polygon_ptr->pen, NULL, plMask, plSkip, pProp); SetIntPropertyMask(PROP_MASK_DASH, polygon_ptr->dash, NULL, plMask, plSkip, pProp); SetIntPropertyMask(PROP_MASK_CURVED, polygon_ptr->curved, NULL, plMask, plSkip, pProp); } void FreePolygonObj(ObjPtr) struct ObjRec *ObjPtr; { if (ObjPtr->detail.g->intvlist != NULL) free(ObjPtr->detail.g->intvlist); if (ObjPtr->detail.g->svlist != NULL) free(ObjPtr->detail.g->svlist); if (ObjPtr->detail.g->rotated_vlist != NULL) { free(ObjPtr->detail.g->rotated_vlist); } free(ObjPtr->detail.g->vlist); if (ObjPtr->detail.g->smooth != NULL) free(ObjPtr->detail.g->smooth); free(ObjPtr->detail.g); free(ObjPtr); }