NodeRegularShape * OpBackground::DoCreateRectangle(Spread * pSpread) { ERROR2IF(pSpread == NULL,FALSE,"OpBackground::DoCreateRectangle Bad params error!"); if (pSpread == NULL) return NULL; // This assumes that we have already checked to see if there is a page covering rectangle // already present on this layer. // Create a new rectangle node on the layer NodeRegularShape *pShape = new NodeRegularShape; if (pShape != NULL) { BOOL ok = pShape->SetUpShape(); if (!ok) { // Do something sensible in here delete pShape; return NULL; } // We want to make the rectangle the same size as the current union of // all the pages on the current spread DocRect Rect; pSpread->GetPagesRect(&Rect); /* // We must expand the rectangle by a single pixel as the page redraw // draws a single pixel line around the outside. const MILLIPOINT pixel = (MILLIPOINT)(72000.0/96.0); Rect.Inflate(pixel); */ const INT32 CornerRadius = 0; // No curvature if (pShape->MakeRectangle(Rect.Width(), Rect.Height(), CornerRadius)) { // Translate centre from 0,0 to required position relative to page INT32 XTrans = Rect.lo.x + (Rect.Width()/2); INT32 YTrans = Rect.lo.y + (Rect.Height()/2); Trans2DMatrix Trans(XTrans, YTrans); pShape->Transform(Trans); // finish off the shape pShape->InvalidateBoundingRect(); } } return pShape; }
Chapter* DocCoord::FindEnclosingChapter(Document *pDocument, DocCoord* ChapterPos, XLONG* ChapterDepth, View *pView) { Chapter* CurrentChapter = Node::FindFirstChapter(pDocument); // Search all chapters *ChapterDepth = 0; DocRect CurrentChaptersPasteboardRect; while (CurrentChapter != NULL) { CurrentChaptersPasteboardRect = CurrentChapter->GetPasteboardRect(TRUE, pView); if (CurrentChaptersPasteboardRect.ContainsRectCoord(*this)) { // Chapter position is the top left hand corner of the chapters pasteboard ChapterPos->x = CurrentChaptersPasteboardRect.LowCorner().x; ChapterPos->y = CurrentChaptersPasteboardRect.HighCorner().y; return (CurrentChapter); } (*ChapterDepth) += CurrentChaptersPasteboardRect.Height(); CurrentChapter = CurrentChapter->FindNextChapter(); } // The DocCoord was not found in any chapter ERROR3("DocCoord::FindEnclosingChapter: Coord wasn't in any chapter. See the function help for debugging tips"); return(NULL); }
XLONG Chapter::GetChapterDepth() { XLONG Depth = 0; // Loop through document tree calculating the logical coordinate offset for the // current chapter // Chapter *pChapter = Node::FindFirstChapter(FindOwnerDoc()); Node* pNode = FindParent(); ERROR2IF(!(pNode->IsNodeDocument()), 0, "Parent of Chapter is not NodeDocument"); Chapter *pChapter = (Chapter*)pNode->FindFirstChild(CC_RUNTIME_CLASS(Chapter)); ENSURE(pChapter != NULL, "Couldn't find first chapter in Chapter::GetChapterDepth"); while ((pChapter != NULL) && (pChapter != this)) { ENSURE(pChapter->IsKindOf(CC_RUNTIME_CLASS(Chapter)), "Chapter's sibling is not a Chapter"); const DocRect ChapRect = pChapter->GetPasteboardRect(); // Accumulate logical offset Depth += ChapRect.Height(); pChapter = (Chapter *) pChapter->FindNext(); } return Depth; }
/******************************************************************************************** > BOOL MakeBitmapFilter::FindCentreInsertionPosition(Spread** Spread, DocCoord* Position) Author: Will_Cowling (Xara Group Ltd) <*****@*****.**> (from Simon) Created: 12/6/96 Inputs: - Outputs: Spread: The spread to place the clipboard objects on Position:The centre of the view (Spread coords) Purpose: Finds the centre insertion position for clipboard objects ********************************************************************************************/ BOOL MakeBitmapFilter::FindCentreInsertionPosition(Spread** Spread, DocCoord* Position) { // --------------------------------------------------------------------------------- // Find out which spread is in the centre of the view // this is the spread that the pasted objects will be placed on // Obtain the current DocView DocView* CurDocView = DocView::GetCurrent(); ENSURE(CurDocView != NULL, "The current DocView is NULL"); if (CurDocView == NULL) return FALSE; // No DocView // Get the view rect WorkRect WrkViewRect = CurDocView->GetViewRect(); if (WrkViewRect.IsEmpty() || (!WrkViewRect.IsValid()) ) return FALSE; // Defensive // Determine the centre of the view WorkCoord WrkCentreOfView; WrkCentreOfView.x = WrkViewRect.lox + (WrkViewRect.Width()/2); WrkCentreOfView.y = WrkViewRect.loy + (WrkViewRect.Height()/2); // FindEnclosing spread requires an OilCoord OilCoord OilCentreOfView = WrkCentreOfView.ToOil(CurDocView->GetScrollOffsets()); // Find out which spread to insert the pasteboard objects onto (*Spread) = CurDocView->FindEnclosingSpread(OilCentreOfView); if ((*Spread) == NULL) return FALSE; // There is no spread // Phew // --------------------------------------------------------------------------------- // Now lets find the spread coordinate of the centre of the view DocRect DocViewRect = CurDocView->GetDocViewRect(*Spread); if ( DocViewRect.IsEmpty() || (!DocViewRect.IsValid()) ) { ERROR3("DocViewRect is invalid"); return FALSE; // Defensive } // Find the centre of the DocViewRect DocCoord DocCentreOfView; DocCentreOfView.x = DocViewRect.lox + (DocViewRect.Width()/2); DocCentreOfView.y = DocViewRect.loy + (DocViewRect.Height()/2); // -------------------------------------------------------------------------------- // Now convert from DocCoords to spread coords DocRect PhysSpreadRect = (*Spread)->GetPasteboardRect(); (*Position).x = DocCentreOfView.x - PhysSpreadRect.lo.x; (*Position).y = DocCentreOfView.y - PhysSpreadRect.lo.y; return TRUE; }
/******************************************************************************************** > BOOL TipsDlg::DrawBitmap(ResourceID BitmapID, DocRect& RedrawRect) Author: Colin_Barfoot (Xara Group Ltd) <*****@*****.**> Created: 08/08/96 Inputs: BitmapID : the resource id of the bitmap to draw RedrawRect : the rectangle in which to draw it Returns: TRUE if drawn OK FALSE otherwise Purpose: Renders the given bitmap in the given rectangle ********************************************************************************************/ BOOL TipsDlg::DrawBitmap(ResourceID BitmapID, DocRect& RedrawRect) { OILBitmap *pOILBitmap = OILBitmap::Create(); if (pOILBitmap == NULL) { return FALSE; } if (!pOILBitmap->LoadBitmap(BitmapID)) { return FALSE; } // Centre the bitmap within the RedrawRect UINT32 bitmapWidth = pOILBitmap->GetRecommendedWidth(); UINT32 bitmapHeight = pOILBitmap->GetRecommendedHeight(); UINT32 xOffset = RedrawRect.lo.x + (RedrawRect.Width() - bitmapWidth) / 2; UINT32 yOffset = RedrawRect.lo.y + (RedrawRect.Height() - bitmapHeight) / 2; DocCoord lowCorner(xOffset, yOffset); DocRect bitmapRect(lowCorner, bitmapWidth, bitmapHeight); KernelBitmap bitmap(pOILBitmap, TRUE); // Now we need to create a temporary NodeBitmap, which we will // use to render the bitmap preview. NodeBitmap* dummyNode = new NodeBitmap(); if (dummyNode == NULL) { return FALSE; } // Set the NodeBitmap path to be our RedrawRect and attach the Bitmap to it. dummyNode->SetUpPath(); dummyNode->CreateShape(bitmapRect); dummyNode->GetBitmapRef()->SetBitmap(&bitmap); // Now render the bitmap preview dummyNode->Render(m_pRenderer); delete dummyNode; // All OK return TRUE; }
double CamelotWebFilter::GetSimilarPathTolerance(NodePath* pPath) { double Tolerance = 0.0; if (pPath != NULL) { // Don't get attribute-related bounds because the path might not be in the tree // (e.g. it may be generated by the 'convert text to outlines' system which keeps // all paths created from text stories in out-of-line groups) // The TRUE parameter means don't bother with attributes DocRect Rect = pPath->GetBoundingRect(TRUE); INT32 MaxDist = min(Rect.Width(),Rect.Height()); Tolerance = double(MaxDist)*0.01; if (Tolerance > GetWebSimilarPathTolerence()) Tolerance = GetWebSimilarPathTolerence(); } return Tolerance; }
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 MakeBitmapFilter::InsertBitmapIntoDocument(UndoableOperation *pOp, KernelBitmap* KernelBmp, Document* DestDoc) Author: Will_Cowling (Xara Group Ltd) <*****@*****.**> Created: 11/6/96 Purpose: Exports the current selection as a bitmap, via the virtual fns of the inherited class. Returns: TRUE if worked, FALSE if failed. SeeAlso: GetExportOptions; PrepareToExport; ExportRenderNodes; CleanUpAfterExport; ********************************************************************************************/ BOOL MakeBitmapFilter::InsertBitmapIntoDocument(UndoableOperation *pOp, KernelBitmap* KernelBmp, Document* DestDoc) { Spread *pSpread; DocCoord Origin; // Remember the selection rect, before we change it DocRect SelRect = GetApplication()->FindSelection()->GetBoundingRect(); // For now, position Draw objects on 1st page of spread 1 PORTNOTE("spread", "Multi-spread warning!") pSpread = GetFirstSpread(DestDoc); Page *pPage = (Page *) pSpread->FindFirstPageInSpread(); ERROR3IF(!pPage->IsKindOf(CC_RUNTIME_CLASS(Page)), "MakeBitmapFilter::InsertBitmapIntoDocument: Could not find first Page"); // Use bottom left of page as origin DocRect PageRect = pPage->GetPageRect(); Origin.x = PageRect.lo.x; Origin.y = PageRect.hi.y; // Get a new NodeBitmap object to import into. NodeBitmap *pNodeBitmap = new NodeBitmap; if ((pNodeBitmap == NULL) || (!pNodeBitmap->SetUpPath(12,12))) return FALSE; // Attach the Imported Bitmap to our Node pNodeBitmap->GetBitmapRef()->Attach(KernelBmp, DestDoc); //GetDocument()); if (pNodeBitmap->GetBitmap() != KernelBmp) delete KernelBmp; // It didn't use the bitmap we gave it, so we can delete it // Import worked - try to add the bitmap object into the tree. // First, set the rectangle to the right size for the bitmap... BitmapInfo Info; pNodeBitmap->GetBitmap()->ActualBitmap->GetInfo(&Info); DocRect BoundsRect; BoundsRect.lo = Origin; BoundsRect.hi.x = BoundsRect.lo.x + Info.RecommendedWidth; BoundsRect.hi.y = BoundsRect.lo.y + Info.RecommendedHeight; // And set this in our bitmap node pNodeBitmap->CreateShape(BoundsRect); // Make sure that there is a layer to put the bitmap onto if (!MakeSureLayerExists(DestDoc)) { // There is no layer and one could not be made, so we will have to fail delete pNodeBitmap; return FALSE; } // Set the default attrs // This MUST be done before the NodeBitmap is Inserted into the tree if (!pNodeBitmap->ApplyDefaultBitmapAttrs(pOp)) return FALSE; // Insert the node, but don't invalidate its region if (!pOp->DoInsertNewNode(pNodeBitmap, pSpread, FALSE)) { // It didn't work - delete the sub-tree we just created, and report error. delete pNodeBitmap; return FALSE; } // bitmap is currently positioned so its bottom left hand // corner is at the top left of the page // By default we'll move it down so the top-left of the bitmap is on the top-left of the page INT32 XTranslate = 0; INT32 YTranslate = -Info.RecommendedHeight; ClickModifiers ClickMods = ClickModifiers::GetClickModifiers(); if (ClickMods.Adjust && !SelRect.IsEmpty()) { // If shift is down, then we'll try and place the bitmap exactly on top of the selection DocCoord SelectionCentre(SelRect.lo.x + (SelRect.Width()/2), SelRect.lo.y + (SelRect.Height()/2)); XTranslate = SelectionCentre.x - Origin.x - (Info.RecommendedWidth/2); YTranslate = SelectionCentre.y - Origin.y - (Info.RecommendedHeight/2); } else { // Otherwise we'll try and centre it within the current view Spread* pCurrentSpread; DocCoord ViewCentre; if (FindCentreInsertionPosition(&pCurrentSpread, &ViewCentre)) { /* Karim 19/01/2000 * Ensure that the bmp is pixel-aligned as close to the centre as possible. * XTranslate = ViewCentre.x - Origin.x - (Info.RecommendedWidth/2); YTranslate = ViewCentre.y - Origin.y - (Info.RecommendedHeight/2); /**/ DocCoord PixAlignBmpOrigin( ViewCentre.x - Info.RecommendedWidth/2, ViewCentre.y - Info.RecommendedHeight/2 ); INT32 FullDPI = GRenderRegion::GetDefaultDPI(); MILLIPOINT PixWidth = (INT32)((IN_MP_VAL / (double)FullDPI) + 0.5); PixAlignBmpOrigin.x -= PixAlignBmpOrigin.x % PixWidth; PixAlignBmpOrigin.y -= PixAlignBmpOrigin.y % PixWidth; XTranslate = PixAlignBmpOrigin.x - Origin.x; YTranslate = PixAlignBmpOrigin.y - Origin.y; } } Trans2DMatrix Xlate(XTranslate, YTranslate); pNodeBitmap->Transform(Xlate); // Ensure Sel Bounds are correct after translation GetApplication()->UpdateSelection(); return TRUE; }
/******************************************************************************************** > BOOL MakeBitmapFilter::DoCreateBitmap(Operation *pOp, Document *pDoc, KernelBitmap** ppBitmap) Author: Will_Cowling (Xara Group Ltd) <*****@*****.**> Created: 11/6/96 Purpose: Exports the current selection as a bitmap, via the virtual fns of the inherited class. Returns: TRUE if worked, FALSE if failed. SeeAlso: GetExportOptions; PrepareToExport; ExportRenderNodes; CleanUpAfterExport; ********************************************************************************************/ BOOL MakeBitmapFilter::DoCreateBitmap(Operation *pOp, Document *pDoc, KernelBitmap** ppBitmap) { ERROR3IF(ppBitmap == NULL, "NULL bitmap pointer passed to MakeBitmapFilter::DoCreateBitmap"); if (ppBitmap == NULL) return FALSE; pTheBitmap = NULL; *ppBitmap = NULL; // Set the bitmap pointer to null just in case, usually only used by DoExportBitmap pExportBitmap = NULL; // Get pointer to the spread to export. PORTNOTE("spread", "Multi-spread warning!") pSpread = GetFirstSpread(pDoc); // remember the document in the class variable TheDocument = pDoc; // We must now check if there is a selection present so that we can set up whether the // user gets the choice of exporting the selection, drawing or spread if there is a // selection present OR just a choice between the spread or drawing if no selection is // present. // If have a caret selected in a text story then the selection will be almost zero so trap // this case as well. RangeControl rg = GetApplication()->FindSelection()->GetRangeControlFlags(); rg.PromoteToParent = TRUE; GetApplication()->FindSelection()->Range::SetRangeControl(rg); SelRange Rng(*(GetApplication()->FindSelection())); // now, run through the selection selecting all nodes under all compound nodes // if we don't do this then all compound nodes aren't rendered correctly with transparent // bitmaps Node * pNode = Rng.FindFirst(FALSE); while (pNode) { pNode->SetSelected(FALSE); pNode->SetSelected(TRUE); pNode = Rng.FindNext(pNode, FALSE); } rg.PromoteToParent = FALSE; GetApplication()->FindSelection()->Range::SetRangeControl(rg); GetApplication()->UpdateSelection(); DocRect ClipRect = GetApplication()->FindSelection()->GetBoundingRect(); SelectionType Selection = DRAWING; if ( ClipRect.IsEmpty() || ClipRect.Width() < MinExportSize || ClipRect.Height() < MinExportSize) Selection = DRAWING; // no selection present, so choose drawing by default else Selection = SELECTION; // selection present, so choose this by default if (Selection != SELECTION) { BOOL UseDrawingBounds = TRUE; SelRange* pSel = GetApplication()->FindSelection(); if (pSel && pSel->Count()==1) { // Only one thing selected ... Is it the Text Caret per chance ? Node* pSelNode = pSel->FindFirst(); if (pSelNode && pSelNode->IsAVisibleTextNode()) { VisibleTextNode* pTextNode = (VisibleTextNode*)pSelNode; if (pTextNode->IsACaret()) { // Aha! It's the Caret that's selected. // We'll use the bounds of the parent text line instead then ... Node* pTextLine = pTextNode->FindParent(); ERROR3IF(!IS_A(pTextLine, TextLine), "Caret doesn't have a parent text line in DoCreateBitmap"); // Get the bounds of the text line ClipRect = ((TextLine*)pTextLine)->GetBoundingRect(); Selection = SELECTION; UseDrawingBounds = FALSE; } } } if (UseDrawingBounds) { // Work out the size of the rectangle encompassing the drawing (visible layers only) ClipRect = GetSizeOfDrawing(pSpread); } } // Create somewhere to put the user options and fill them up MakeBitmapExportOptions* pMakeBmpExportOptions = (MakeBitmapExportOptions*)CreateExportOptions(); if (pMakeBmpExportOptions == NULL) { Error::SetError(_R(IDS_OUT_OF_MEMORY)); return FALSE; } pMakeBmpExportOptions->RetrieveDefaults(); pMakeBmpExportOptions->SetDepth(32); // create bmp copies shoulda always default to being 32 bit pMakeBmpExportOptions->SetSelectionType(Selection); // Set the BaseBitmapFilter member so we can use base class functionality - blurghh SetExportOptions(pMakeBmpExportOptions); BOOL ok = GetExportOptions( (BitmapExportOptions*)pMakeBmpExportOptions ); BOOL IsAnimation = BmapPrevDlg::m_pExportOptions == NULL; BaseBitmapFilter * pNewFilter = this; BitmapExportOptions * pExportOptions = BmapPrevDlg::m_pExportOptions; if (!IsAnimation) { pNewFilter = pExportOptions->FindBitmapFilterForTheseExportOptions(); // from the exporting point of view we should always have been using png options // set them to the png options for the export part if (pNewFilter) pNewFilter->SetExportOptions(pExportOptions); // gets the real export options that the prevdlg has set up for us BmapPrevDlg::m_pExportOptions = NULL; // take responsibility for this data } else { // the animation export didn't bring up the dlg so never set BmapPrevDlg::m_pExportOptions // so continue with these options pExportOptions = (BitmapExportOptions*)pMakeBmpExportOptions; } SetExportOptions(pExportOptions); if (!ok) { SetExportOptions(NULL); // deletes the filter ptr and nulls it delete pExportOptions; return FALSE; // if cancelled } //////////////// SMFIX pExportOptions->MarkValid(); SetDepthToRender(pExportOptions->GetDepth()); // Set up device context and render region for this export. // This will show a progress hourglass for the objects being rendered // THis will now also write the data out to file via our ExportRenderNodes function if (!PrepareToExport(pSpread, pExportOptions->GetDepth(), pExportOptions->GetDPI(), pExportOptions->GetSelectionType(), pExportOptions->GetDither())) { pNewFilter->SetExportOptions(NULL); SetExportOptions(NULL); delete pExportOptions; CleanUpAfterExport(); return FALSE; } RenderInStrips = FALSE; if (!ExportRender(ExportRegion)) { pNewFilter->SetExportOptions(NULL); // deletes the filter ptr and nulls it SetExportOptions(NULL); delete pExportOptions; CleanUpAfterExport(); return FALSE; } // Now get the converted 32Bit BMP pTheBitmap = GetTheBitmap(pExportOptions); // if we`ve got a transparency index AND we`ve got a 32 Bit Render region with alpha channel info // then we can quickly do if(pExportOptions->GetDepth() <= 8 && pExportOptions->GetTransparencyIndex() != -1 && pTheBitmap) { // What we do now is to go throught the bitmap setting the relavent pixels to transparent // depending on the alpha channel info held in the 32 bit version. if(!ApplyTransparentColoursToBitmap(pTheBitmap,pExportOptions)) { pNewFilter->SetExportOptions(NULL); // deletes the filter ptr and nulls it return FALSE; } // Now make sure the bitmap knows that it has a transparent colour! pTheBitmap->SetTransparencyIndex(pExportOptions->GetTransparencyIndex()); } // Set pointer to the bitmap we have created *ppBitmap = pTheBitmap; pNewFilter->SetExportOptions(NULL); // deletes the filter ptr and nulls it SetExportOptions(NULL); delete pExportOptions; CleanUpAfterExport(); return *ppBitmap != NULL; //////////////// SMFIX }
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; }
BOOL OpBackground::FixBackgroundLayer(Layer * pBackgroundLayer, const DocRect& NewPagesRect, const DocRect& OldPagesRect) { ERROR2IF(pBackgroundLayer == NULL,FALSE,"OpBackground::FixBackgroundLayer Bad params!"); //BOOL ok = TRUE; // There should be a rectangle on the page encompassing the old position of the pages // so go and try and find it NodeRegularShape * pShape = FindPageRectangle(pBackgroundLayer, OldPagesRect); // If no rectangle is found then something might be slightly wrong. Should we error? if (pShape) { const INT32 CornerRadius = 0; // No curvature if (pShape->MakeRectangle(NewPagesRect.Width(), NewPagesRect.Height(), CornerRadius)) { // Translate centre from 0,0 to required position relative to page INT32 XTrans = NewPagesRect.lo.x + (NewPagesRect.Width()/2); INT32 YTrans = NewPagesRect.lo.y + (NewPagesRect.Height()/2); Trans2DMatrix Trans(XTrans, YTrans); pShape->Transform(Trans); // finish off the shape pShape->InvalidateBoundingRect(); } // Find any bitmap fills and fix up the fill origin etc. Node * pNode = pShape->FindFirstChild(); while (pNode != NULL) { // Only check and fix bitmap colour fill attributes of the regular shape nodes if (pNode->IS_KIND_OF(AttrBitmapColourFill)) { // Convert the pointer to the correct type AttrBitmapColourFill * pBitmapFillAttr = (AttrBitmapColourFill*)pNode; // Set the coordinates of the fill end points // We want to start the fill at the top left of the regular shape // The bounding rect should be roughly what we want DocRect Rect = pShape->GetBoundingRect(TRUE, FALSE); KernelBitmap * pBitmap = ((AttrFillGeometry*)pBitmapFillAttr)->GetBitmap(); // Get the size of the bitmap taking into account its DPI INT32 Width = pBitmap->GetRecommendedWidth(); INT32 Height = pBitmap->GetRecommendedHeight(); // You would think that the handles on the fill correspond to where you place them // but oh now the displayed handles are shown at different points. So instead of // positioning the start in the centre of the bitmap, you need to position it bottom left // The End should be centre and right but needs to be bottom right. // The End2 should be centre and top but needs to be top left. // We want the start point to be half the height of the bitmap below this //DocCoord Start(Rect.lo.x + Width/2, Rect.hi.y - Height/2); DocCoord Start(Rect.lo.x, Rect.hi.y - Height); // We want the other end point to be same height as the centre point // but on the far right of the rectangle i.e the full width across //DocCoord End(Rect.lo.x + Width, Rect.hi.y - Height/2); DocCoord End(Rect.lo.x + Width, Rect.hi.y - Height); // We want the end point to be middle and top of the rectangle //DocCoord End2(Rect.lo.x + Width/2, Rect.hi.y); DocCoord End2(Rect.lo.x, Rect.hi.y); ((AttrFillGeometry*)pBitmapFillAttr)->SetStartPoint(&Start); ((AttrFillGeometry*)pBitmapFillAttr)->SetEndPoint(&End); ((AttrFillGeometry*)pBitmapFillAttr)->SetEndPoint2(&End2); } pNode = pNode->FindNext(); } } return TRUE; }