BOOL OpNudge::IsNudgeOK(BOOL dx,BOOL dy) { // Get the selection SelRange* pSel = GetApplication()->FindSelection(); ERROR2IF(pSel == NULL,FALSE,"Awooga, NULL sel range"); // Find out the bounding rectangle of the selection DocRect BoundingRect = pSel->GetBoundingRect(); // Find out the Pasteboard rect DocRect PasteRect; Spread* pSpread = pOurDoc->GetSelectedSpread(); if (pSpread==NULL) PasteRect = BoundingRect; else { // Try to make the pasteboard grow if necessary to include the new object position // This is very quick if the pasteboard is large enough already. pSpread->ExpandPasteboardToInclude(BoundingRect); // And re-read the bounding rectangle of the selection, as the pasteboard resize may have // caused the origin of our entire coordinate space to have moved! Argh! BoundingRect = pSel->GetBoundingRect(); // BoundingRect.Translate(dx,dy); // This is in Document Coords, so we need to convert it PasteRect = pSpread->GetPasteboardRect(); pSpread->DocCoordToSpreadCoord(&PasteRect); } // Assume the nudge will be OK. BOOL NudgeOK = TRUE; if (PasteRect.ContainsRect(BoundingRect)) { // Untranslated bounds fit inside pasteboard rect, so we must complain if the bounds // do not fit *after* translation // Translate the bounds by the nudge values BoundingRect.Translate(dx,dy); // Do the translated bounds still fit entirely in the pasteboard rect? NudgeOK = PasteRect.ContainsRect(BoundingRect); } else { // The original bounds overlap the pasteboard rect, so we must complain if the user // nudges the bounds completely out of sight if (PasteRect.IsIntersectedWith(BoundingRect)) { // The original bounds intersect with the pasteboard rect BoundingRect.Translate(dx,dy); // Only allow the nudge if the translated bounds still overlap with the spread. NudgeOK = PasteRect.IsIntersectedWith(BoundingRect); } } // If the nudge is OK, we may need to scroll the DocView? /* Jim, 12/9/96 - removed this because we don't want to scroll to show opn nudges if (NudgeOK) { DocCoord Coord(0,0); // If nudging left or right, pick the min or max X coord if (dx != 0) { if (dx < 0) Coord.x = BoundingRect.lox; else Coord.x = BoundingRect.hix; } // If nudging up or down, pick the max or min Y coord if (dy != 0) { if (dy < 0) Coord.y = BoundingRect.loy; else Coord.y = BoundingRect.hiy; } // If we have picked a coord, ensure that this coord is visible in the selected spread // of the selected DocView if (Coord != DocCoord(0,0)) { DocView* pDocView = DocView::GetSelected(); if (pDocView != NULL) pDocView->ScrollToShow(&Coord); } } */ return NudgeOK; }
BOOL BitmapExportDocument::SetBitmap(KernelBitmap* pBitmap) { TRACEUSER( "Gerry", _T("BitmapExportDocument::SetBitmap()\n")); ERROR2IF(pBitmap == NULL, FALSE, "NULL bitmap passed to SetBitmap()\n"); ERROR2IF(pBitmapNode == NULL, FALSE, "pBitmapNode is NULL in SetBitmap()\n"); // Attach the bitmap to our node // // Note: Neville 18/9/97 // If the bitmap is a lone bitmap i.e. not attached to any document, then we // must attach it properly to this document so that it gets cleaned out // rather than memory leaking. If not, then we are just temporarily using // the bitmap and so everything should be ok. We need to work in the following // situations:- // - Selecting multiple bitmaps in the bitmap gallery and saving as animated GIF. // Here we are passed a list of bitmaps which are already in use in the source // document. // - Making a new clipart index for bitmaps. Here we are passed a brand spanking // new bitmap which is not on any lists. This used to memory leak. BitmapList* pBmpList = pBitmap->GetParentBitmapList(); if (pBmpList != NULL) { // This will memory leak a kernel bitmap each time if it is not on a parent // document list. You will also end up with a KernelBitmap which contains // a deleted ActualBitmap pointer, which is very bad! pBitmapNode->GetBitmapRef()->SetBitmap(pBitmap); } else { // This is the same technique that the BaseBitmapFilter uses and so must be correct! pBitmapNode->GetBitmapRef()->Attach(pBitmap, this); if (pBitmapNode->GetBitmap() != pBitmap) { // It didn't use the bitmap we gave it, so we can delete it delete pBitmap; } } BitmapInfo Info; pBitmapNode->GetBitmap()->ActualBitmap->GetInfo(&Info); // Calculate the rectangle for this bitmap // We make it as large as possible (within the ExportRect) // without changing the aspect ration INT32 RectWidth = ExportRect.Width(); INT32 RectHeight = ExportRect.Height(); double xScale = (double) RectWidth / (double) Info.RecommendedWidth; double yScale = (double) RectHeight / (double) Info.RecommendedHeight; DocRect BitmapRect; BitmapRect.lo.x = 0; BitmapRect.lo.y = 0; if (xScale < yScale) { // Bitmap will be full width BitmapRect.hi.x = RectWidth; BitmapRect.hi.y = (INT32) ((double) Info.RecommendedHeight * xScale); // Center the bitmap vertically in the rectangle BitmapRect.Translate(0, (RectHeight - BitmapRect.Height()) / 2); } else { // Bitmap will be full height BitmapRect.hi.x = (INT32) ((double) Info.RecommendedWidth * yScale); BitmapRect.hi.y = RectHeight; // Center the bitmap horizontally in the rectangle BitmapRect.Translate((RectWidth - BitmapRect.Width()) / 2, 0); } // Delete the node's path // Because CreateShape inserts a rectangle at the beginning of the path pBitmapNode->InkPath.DeleteFromElement(0); // And create the shape pBitmapNode->CreateShape(BitmapRect); return(TRUE); }
BOOL FreeHandEPSFilter::ProcessToken() { // Decode the command, and execute it... switch (Token) { // state saving case EPSC_vms: if(!Import_gsave()) return FALSE; break; case EPSC_vmr: if(!Import_grestore()) return FALSE; break; case EPSC_vmrs: if(!Import_grestore()) return FALSE; if(!Import_gsave()) return FALSE; break; // tokens to ignore case EPSC_FREEHAND_IGNOREDTOKEN: break; // tokens which should be ignored and one entry discarded case EPSC_load: // the load part of a fill - discard the /clipper before it case EPSC_fhsetspreadallow: if(!Stack.Discard(1)) goto EPSError; break; case EPSC_concat: if(!Stack.DiscardArray()) goto EPSError; break; // complex paths... case EPSC_eomode: { INT32 ComplexStart; if(!Stack.Pop(&ComplexStart)) goto EPSError; // is this a start of a complex path? if(ComplexStart != TRUE) { ComplexPathMode = FALSE; } else { HadFirstOfComplexPath = FALSE; ComplexPathMode = TRUE; } } break; case EPSC_true: Stack.Push((INT32)TRUE); break; case EPSC_false: Stack.Push((INT32)FALSE); break; case EPSC_u: HadFirstOfComplexPath = FALSE; return EPSFilter::ProcessToken(); break; // colours case EPSC_Ka: case EPSC_ka: { DocColour Colour; if(PopColour(&Colour)) { // Remember this colour for future objects if (Token == EPSC_ka) { if (!SetFillColour(Colour)) goto NoMemory; } else { if (!SetLineColour(Colour)) goto NoMemory; } } else // Invalid colour operands goto EPSError; } break; case EPSC_Xa: case EPSC_xa: { DocColour Colour; if(PopNamedColour(&Colour)) { // Remember this colour for future objects if (Token == EPSC_xa) { if (!SetFillColour(Colour)) goto NoMemory; } else { if (!SetLineColour(Colour)) goto NoMemory; } } else // Invalid colour operands goto EPSError; } break; case EPSC_H: if(ComplexPathMode) { // in complex path mode - make this a filled one, not a discarded one Token = EPSC_S; } return EPSFilter::ProcessToken(); break; case EPSC_h: if(ComplexPathMode) { // in complex path mode - modify and process Token = EPSC_s; return EPSFilter::ProcessToken(); break; } // the hidden path closing operator - a grad fill thingy will follow shortly maybe... // this will prevent it being processed now, although it may get processed later on. HadhToken = TRUE; break; // for clipping masks, do some funky stuff case EPSC_q: // if there's a pending grad fill... if(DoingGradFill) { if(pPath != 0) { // right then, make a copy of the path... NodePath *pPathClone; if(!pPath->NodeCopy((Node **)&pPathClone)) { goto NoMemory; } // copy the flags EPSFlagsDefn EPSFlagsClone = EPSFlags; // send a token to finish and fill the path... Token = (pInkPath->IsFilled)?EPSC_f:EPSC_s; if(!EPSFilter::ProcessToken()) return FALSE; // restore the old fill if(!RestoreCurrentFill()) goto NoMemory; // restore the copy of the path pPath = pPathClone; pInkPath = &pPath->InkPath; // restore the flags EPSFlags = EPSFlagsClone; // definately want to send an h HadhToken = TRUE; } // done the grad fill DoingGradFill = FALSE; // restore the old token Token = EPSC_q; } // clipping started - have we got an h token to send? if(HadhToken) FHEF_SENDh // process this return EPSFilter::ProcessToken(); break; // for now, if there's no path, don't return a W case EPSC_W: if(pPath == 0) { // OK, now we want to get the last path we created, make a copy of it and then install it as the current one if(pLastPathSeen == 0) goto EPSError; // make a copy of it NodePath *pClone; if(!pLastPathSeen->NodeCopy((Node **)&pClone)) goto NoMemory; // delete it's attributes pClone->DeleteChildren(pClone->FindFirstChild()); // make it the current path pPath = pClone; pInkPath = &pPath->InkPath; ThePathType = PATH_NORMAL; EPSFlags.NoAttributes = TRUE; } if(pPath != 0) return EPSFilter::ProcessToken(); break; // we may need to modify path closing things if we're doing a grad fill case EPSC_s: case EPSC_S: if(Token == EPSC_S) { // if we've had an h token but no grad fill, send the h now if(HadhToken) FHEF_SENDh // if we've got a grad fill, modify the token we got if(DoingGradFill) Token = EPSC_b; } // process the possily modified token normally HadhToken = FALSE; return EPSFilter::ProcessToken(); break; // modify path closing for grad fills. case EPSC_n: if(DoingGradFill) { Token = EPSC_f; // we want to fill the thing HadhToken = FALSE; return EPSFilter::ProcessToken(); break; } HadhToken = FALSE; // ignore h's as this is another end path thingy... if(pPath != 0) return EPSFilter::ProcessToken(); break; // unset the had h token for other path closing things case EPSC_N: case EPSC_F: case EPSC_f: case EPSC_B: case EPSC_b: HadhToken = FALSE; return EPSFilter::ProcessToken(); break; // interested in path element things to switch off grad fills case EPSC_m: if(InText) { // if we're doing some text, discard the moveto command if(!Stack.Discard(2)) goto EPSError; break; } case EPSC_l: case EPSC_L: case EPSC_c: case EPSC_C: case EPSC_v: case EPSC_V: case EPSC_y: case EPSC_Y: // maybe we need an h token to be sent if(HadhToken) FHEF_SENDh // stop grad fill if(DoingGradFill) { // turn the grad fill state off DoingGradFill = FALSE; // restore the old fill type RestoreCurrentFill(); } return EPSFilter::ProcessToken(); break; case EPSC_recfill: { // get the colours DocColour StartColour, EndColour; if(!PopColour(&EndColour) || !PopColour(&StartColour)) goto EPSError; // discard the fill type thingy - we can only do colours if(!DiscardFillSubType()) goto EPSError; // OK, now a few coords DocCoord Centre; double Angle; DocRect BBox; if(!Stack.PopCoordPair(&BBox.hi) || !Stack.PopCoordPair(&BBox.lo) || !Stack.Pop(&Angle) || !Stack.PopCoordPair(&Centre)) goto EPSError; // munge the angle a little and get it into radians Angle += 225; Angle = (Angle * (2 * PI)) / 360; // see if we can get a more accurate BBox if(pPath != 0) { BBox = pPath->GetBoundingRect(); Centre.x = BBox.lo.x + (BBox.Width() / 2); Centre.y = BBox.lo.y + (BBox.Height() / 2); } // OK, we've got all the stuff we need to do some niceness on it BBox.Translate(0 - Centre.x, 0 - Centre.y); DocCoord StartPoint, EndPoint; StartPoint.x = Centre.x + (INT32)(((double)BBox.lo.x * cos(Angle)) - ((double)BBox.lo.y * sin(Angle))); StartPoint.y = Centre.y + (INT32)(((double)BBox.lo.x * sin(Angle)) + ((double)BBox.lo.y * cos(Angle))); EndPoint.x = Centre.x + (INT32)(((double)BBox.hi.x * cos(Angle)) - ((double)BBox.hi.y * sin(Angle))); EndPoint.y = Centre.y + (INT32)(((double)BBox.hi.x * sin(Angle)) + ((double)BBox.hi.y * cos(Angle))); // store current fill attribute SaveCurrentFill(); // set the fill if(!SetLinearFill(StartColour, EndColour, StartPoint, EndPoint)) goto NoMemory; // say we're doing a grad fill DoingGradFill = TRUE; HadhToken = FALSE; // absorb this } break; case EPSC_radfill: { // get the colours DocColour StartColour, EndColour; if(!PopColour(&StartColour) || !PopColour(&EndColour)) goto EPSError; // get the radius and centre coordinate DocCoord Centre; INT32 Radius; if(!Stack.PopCoord(&Radius) || !Stack.PopCoordPair(&Centre)) goto EPSError; // store current fill attribute SaveCurrentFill(); // set the fill DocCoord EndPoint(Centre.x + Radius, Centre.y); if(!SetRadialFill(StartColour, EndColour, Centre, EndPoint)) goto NoMemory; // say we're doing a grad fill DoingGradFill = TRUE; HadhToken = FALSE; } break; case EPSC_BeginSetup: // there's probably a colour list or something in that there setup thingy - search for the spots token { BOOL Found = FALSE; while(Found == FALSE) { if(!EPSFile->GetToken()) return FALSE; if(EPSFile->GetTokenType() == TOKEN_NORMAL) { if(camStrcmp(TokenBuf, _T("spots")) == 0) { // check to see if the array is about to start if(!EPSFile->GetToken()) return FALSE; if(TokenBuf[0] == '[') { TRACEUSER( "Ben", _T("Found spots\n")); Found = TRUE; } } } if(camStrncmp(TokenBuf, _T("%%EndSetup"), 10) == 0) { TRACEUSER( "Ben", _T("Met end of setup without finding spots\n")); break; } if(EPSFile->eof()) goto EPSError; } if(Found == TRUE) { InColours = TRUE; } } break; case EPSC_def: if(InColours) { // finished the colours... TRACEUSER( "Ben", _T("Finished spot colours\n")); // scan for the end of the setup section BOOL Found = FALSE; while(Found == FALSE) { if(!EPSFile->GetToken()) return FALSE; if(EPSFile->GetTokenType() == TOKEN_COMMENT) { if(camStrncmp(TokenBuf, _T("%%EndSetup"), 10) == 0) { TRACEUSER( "Ben", _T("Found end of setup\n")); Found = TRUE; } } if(EPSFile->eof()) goto EPSError; } // get the ] off the stack EPSCommand Ignored; Stack.PopCmd(&Ignored); // empty it... Stack.DeleteAll (); InColours = FALSE; } else { // probably a font type thingy - empty the stack including commands Stack.DeleteAll (); } break; case EPSC_newcmykcustomcolor: // OK, here's a named colour... add it to those known { // discard some random thingy if(!Stack.Discard()) goto EPSError; // get the name String_64 ColourName; if(!Stack.Pop(&ColourName)) goto EPSError; // get the components double C, M, Y, K; if(!Stack.Pop(&K) || !Stack.Pop(&Y) || !Stack.Pop(&M) || !Stack.Pop(&C)) goto EPSError; // make the new colour ColourCMYK Colour; Colour.Cyan = C; Colour.Magenta = M; Colour.Yellow = Y; Colour.Key = K; // add it if(!pNewColours->AddColour(&ColourName, &Colour)) goto NoMemory; // add it to the list of colours // this is a bit of a bodge, but never mind. Shouldn't be that bad. IndexedColour *TheNewColour = pNewColours->GetColour(ColourName); if(TheNewColour == 0) goto NoMemory; // add it to the list of colours // enough space? if((ColourArrayEntries + 1) >= ColourArraySize) { TRACEUSER( "Ben", _T("Extening colour array\n")); IndexedColour **NewPtr = (IndexedColour **)CCRealloc(ColourArray, (ColourArraySize + FHEF_COLOURARRAY_CHUNK) * sizeof(IndexedColour *)); if(NewPtr == 0) goto NoMemory; ColourArray = NewPtr; ColourArraySize += FHEF_COLOURARRAY_CHUNK; } // add ColourArray[ColourArrayEntries] = TheNewColour; ColourArrayEntries++; } break; // ignore text stuff case EPSC_makesetfont: if(!Stack.DiscardArray()) goto EPSError; if(!Stack.Discard(1)) goto EPSError; InText = TRUE; break; case EPSC_ts: if(!Stack.Discard(6)) goto EPSError; break; case EPSC_stob: case EPSC_sts: Stack.DeleteAll (); InText = FALSE; break; default: // Token not understood - pass on to base class return EPSFilter::ProcessToken(); } // No errors encountered while parsing this token and its operands. return TRUE; // Error handlers: EPSError: HandleEPSError(); return FALSE; NoMemory: HandleNoMemory(); return FALSE; }