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); }
void OpDragBox::DragPointerMove(DocCoord dcMousePos, ClickModifiers cmods, Spread* pSpread, BOOL bSolidDrag) { // If the mouse has moved to another spread than translate its position into the // new spread's coordinate system. if (pSpread != m_pStartSpread && pSpread != NULL) { dcMousePos = MakeRelativeToSpread(m_pStartSpread, pSpread, dcMousePos); } // Calculate the new drag rectangle. DocRect drNewDragBox = CalcDragBox(m_dcStartPos, dcMousePos); ERROR3IF(!drNewDragBox.IsValid(), "Invalid drag box in OpDragBox::DragPointerMove"); // Call the appropriate update function, according to whether we are drawing solid // drag boxes or unfilled drag boxes. if (m_fDoSolidDragBoxes) { UpdateSolidDragBox(drNewDragBox); } else { UpdateUnfilledDragBox(drNewDragBox); } // Update our record of the last drag box and call the derived class. if (!OnPointerMoved(m_pStartSpread, m_drLastDragBox = drNewDragBox, cmods)) { // Cancel the drag and operation. EndDrag(); End(); } }
void NodeBrush::RenderObjectBlobs(RenderRegion* pRegion) { #if !defined(EXCLUDE_FROM_RALPH) // Find out about the groups bounding rect DocRect BoundingRect = GetBoundingRect(); // Inflate the bounds by the width of a blob DocRect TempRect; GetApplication()->GetBlobManager()->GetBlobRect(BoundingRect.lo,&TempRect); INT32 Delta = ((TempRect.hi.x - TempRect.lo.x)*3)/4; BoundingRect.Inflate(Delta); // Find out where to draw the blobs DocCoord Low = BoundingRect.LowCorner(); DocCoord High = BoundingRect.HighCorner(); // Set the colours of the blobs pRegion->SetFillColour(COLOUR_UNSELECTEDBLOB); pRegion->SetLineColour(COLOUR_NONE); // Draw all the blobs pRegion->DrawBlob(Low, BT_UNSELECTED); pRegion->DrawBlob(High, BT_UNSELECTED); pRegion->DrawBlob(DocCoord(Low.x, High.y), BT_UNSELECTED); pRegion->DrawBlob(DocCoord(High.x, Low.y), BT_UNSELECTED); // for some reason the NBP is never called, there is probably a // proper fix for this but I don't have time right now, so render // the nodeblend path here m_pNodeBrushPath->RenderObjectBlobs(pRegion); #endif }
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 NodeSimpleShape::IsNearControlHandle(DocCoord Coord, INT32* CoordNum) { #if !defined(EXCLUDE_FROM_RALPH) // Find the blob manager BlobManager* pBlobMgr = GetApplication()->GetBlobManager(); if (pBlobMgr==NULL) return FALSE; // Find out about the size of a blob DocRect BlobRect; pBlobMgr->GetBlobRect(Coord, &BlobRect); // Check to see if it is near any of the blobs for (INT32 i=0; i<4; i++) { // Check for collision with the control points if (BlobRect.ContainsCoord(Parallel[i])) { // Tell them which control point it waas over *CoordNum = i; // we have used that click up, so tell the world return TRUE; } } #endif // was not over any of the control points return FALSE; }
void LibraryFile::DoScrollRedraw(void) { // Scroll / redraw the newly added groups... if(FirstLibraryAdded != NULL && LastLibraryAdded != NULL) { SGLibGroup *FirstGroup = FirstLibraryAdded->ParentGroup; SGLibGroup *SecondGroup = LastLibraryAdded->ParentGroup; if(FirstGroup != NULL && SecondGroup != NULL) { // Redraw whatever we need to and reformat the gallery ready for poking... ParentGallery->ReformatAndRedrawIfNecessary(); // Calculate where the new folders are... DocRect ScrollToRect; FirstGroup->GetFormatRect(&ScrollToRect); if(SecondGroup != FirstGroup) { DocRect TempRect; FirstGroup->GetFormatRect(&TempRect); ScrollToRect = ScrollToRect.Union(TempRect); } // Actually do the scroll... ParentGallery->ScrollToShow(&ScrollToRect, TRUE); } } }
/******************************************************************************************** > 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 NativePrefsDlg::InitDialog () { ERROR2IF ( mpParams == NULL, FALSE, "NativePrefsDlg::InitDialog called after duff initialisation?!" ); //First, do we have a selection? Application *pApp = GetApplication(); ERROR2IF(pApp == NULL, FALSE,"NativePrefsDlg::InitDialog - no application!"); SelRange *pRange = pApp->FindSelection(); ERROR2IF(pRange == NULL, FALSE,"NativePrefsDlg::InitDialog - no selection range!"); DocRect ClipRect = pRange->GetBoundingRect(); BOOL fThereIsASelection=!ClipRect.IsEmpty(); //Now, is there a selection? if (fThereIsASelection) { // Yes. So ungrey both the buttons for selecting the nodes to export. EnableGadget(_R(IDC_NATIVEOPTS_SELECT), TRUE); EnableGadget(_R(IDC_NATIVEOPTS_DRAWING), TRUE); //Now, which of those buttons should be selected? switch ( mpParams->GetExportSel () ) { case SELECTION: // Choose the export pair of buttons. SetLongGadgetValue(_R(IDC_NATIVEOPTS_SELECT), FALSE); SetLongGadgetValue(_R(IDC_NATIVEOPTS_DRAWING), TRUE); break; default: case DRAWING: // Choose the export pair of buttons. SetLongGadgetValue(_R(IDC_NATIVEOPTS_SELECT), TRUE); SetLongGadgetValue(_R(IDC_NATIVEOPTS_DRAWING), FALSE); break; } } else { //No. So grey the SELECTION button and ungrey //the DRAWING button EnableGadget(_R(IDC_NATIVEOPTS_SELECT), FALSE); EnableGadget(_R(IDC_NATIVEOPTS_DRAWING), TRUE); // And we must select the DRAWING button for the export area controls. SetLongGadgetValue(_R(IDC_NATIVEOPTS_SELECT), TRUE); SetLongGadgetValue(_R(IDC_NATIVEOPTS_DRAWING), FALSE); } return TRUE; }
Trans2DMatrix* BlendHelpers::GetRotateMatrix(NodeRenderableBounded* pNode,double Angle) { Trans2DMatrix* pMatrix = NULL; if (pNode != NULL && fmod(Angle,360.0) != 0.0) { DocRect BoundsStart = pNode->GetBoundingRect(); DocCoord Centre = BoundsStart.Centre(); pMatrix = new Trans2DMatrix(Centre,Angle); } return pMatrix; }
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; }
void OpDragBox::UpdateSolidDragBox(const DocRect& drNewDragBox) { // Set up four update rectangles. We will xor none, some, or all of these rectangles to // produce the new drag box. DocRect drUpdate[4]; INT32 nHowMany; // Find the intersection of the last and new rectangles. We will exclude this from // any xoring as it is already xored. DocRect drCommonDragBox = drNewDragBox.Intersection(m_drLastDragBox); // Calculate the rectangles that need to be xored to change the last into the new // drag box. This depends on how they overlap. if (drCommonDragBox.IsEmpty()) { // There's no intersection between the last drag box and the new drag box, even // though they share a common corner. So xor the full extent of both drag rects. drUpdate[0] = m_drLastDragBox; drUpdate[1] = drNewDragBox; nHowMany = 2; } else if (drNewDragBox.ContainsRect(m_drLastDragBox)) { // The new drag rect completely contains the last one, so clip out the last. nHowMany = ((DocRect&) drNewDragBox).SplitRect(m_drLastDragBox, drUpdate); } else if (m_drLastDragBox.ContainsRect(drNewDragBox)) { // The last drag rect completely contains the new one, so clip out the new. nHowMany = m_drLastDragBox.SplitRect(drNewDragBox, drUpdate); } else { // The drag rectangles overlap but neither completely contains the other, so set // the xor rectangles to be each drag rectangle less the common drag rectangle. nHowMany = m_drLastDragBox.SplitRect(drCommonDragBox, &drUpdate[0]); nHowMany += ((DocRect&) drNewDragBox).SplitRect(drCommonDragBox, &drUpdate[nHowMany]); } // Sanity check. ERROR3IF(nHowMany < 0 || nHowMany > 4, "Wrong number of split rects in OpDragBox::UpdateSolidDragBox\n"); // Draw the xor rects. for (INT32 i = 0; i < nHowMany; i++) { DrawXorRect(drUpdate[i], m_pStartSpread, drUpdate[i]); } }
BOOL PrintPSRenderRegion::WriteClipRegion(KernelDC *pDC, const DocRect& Rect) { if (!Rect.IsValid() || Rect.IsEmpty()) return TRUE; DocCoord c0,c1; c0=Rect.lo; c1=Rect.hi; BOOL ok = pDC->OutputCoord(c0); ok = ok && pDC->OutputCoord(c1); ok = ok && pDC->OutputToken(TEXT("Cp")); ok = ok && pDC->OutputNewLine(); return ok; }
void LiveEffectsTool::OnMouseMove(DocCoord Coord, Spread* pSpread, ClickModifiers mods) { // Stub out this function if the tool isn't wanted #ifndef NO_ADVANCED_TOOLS // We are interested in any selected paths that the cursor is over // we will also be needing the current docview SelRange* Selected = GetApplication()->FindSelection(); Node* pNode = Selected->FindFirst(); // Check to see if the selection is on the same spread as the mouse if (pNode!=NULL) { // Get the spread and return if it is different from the one with the cursor Spread* pNodeSpread = pNode->FindParentSpread(); if (pNodeSpread!=pSpread) return; } // Find the Blob manager, so we can find out how big a rect to use BlobManager* pBlobMgr = GetApplication()->GetBlobManager(); if (pBlobMgr==NULL) return; // Find the Rect round the mouse pos that counts as a hit DocRect BlobRect; pBlobMgr->GetBlobRect(Coord, &BlobRect); // Work out the square of the distance that we will count as 'close' to the line INT32 Range = BlobRect.Width() / 2; Range *= Range; // // loop through the selection // while (pNode!=NULL) // { // // Now find the next selected node // pNode = Selected->FindNext(pNode); // } // We did not find anything good, so set the cursor to the normal one ChangeCursor(pNormalCursor); // And set the status bar text StatusMsg.Load(_R(IDS_LIVEEFFECTSTART), Tool::GetModuleID(GetID())); GetApplication()->UpdateStatusBarText(&StatusMsg); #endif // NO_ADVANCED_TOOLS }
/******************************************************************************************** > 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; }
DocRect NodeBrush::GetBlobBoundingRect() { #if !defined(EXCLUDE_FROM_RALPH) // Find the base class blob bounding rectangle DocRect Rect = NodeGroup::GetBlobBoundingRect(); // inflate it by the width of a blob (plus a bit) DocRect TempRect; GetApplication()->GetBlobManager()->GetBlobRect(Rect.lo,&TempRect); INT32 Delta = ((TempRect.hi.x - TempRect.lo.x)*1)/1; Rect.Inflate(Delta); return Rect; #else return DocRect(0,0,0,0); #endif }
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; }
SubtreeRenderState NodeEffect::RenderSubtree(RenderRegion* pRender, Node** ppNextNode, BOOL bClip) { if (pRender == NULL) // If no render region supplied, assume we need to be rendered return SUBTREE_ROOTANDCHILDREN; // Go find out about my bounding rectangle DocRect BoundingRect = GetBoundingRect(); DocRect ClipRect = pRender->GetClipRect(); if (bClip && !ClipRect.IsIntersectedWith(BoundingRect)) // If not within the clipping rect then return SUBTREE_NORENDER; // Don't render us or our children // Ask Helper function to set up cacheing for me... // AMB wonders whethere this was commented out during porting - 20051212 // if (RenderCached(pRender)) // If we can find a cached bitmap for this node and render it // { // return SUBTREE_NORENDER; // Then tell the renderer to move on without doing any more... // } return SUBTREE_ROOTANDCHILDREN; // Else we must render ourselves and our children }
DocRect NodeSimpleShape::GetBlobBoundingRect() { #if !defined(EXCLUDE_FROM_RALPH) // Find the Shapes bounding rectangle DocRect Rect = GetBoundingRect(); // Find the blob manager BlobManager* pBlobMgr = GetApplication()->GetBlobManager(); // And if we can find the current view, add on the size of a selection blob if (pBlobMgr!= NULL) { // Wee need to add in each of the blobs. there is a blob on each corner // of the parallelogram DocRect BlobSize; pBlobMgr->GetBlobRect(Parallel[0], &BlobSize); Rect = Rect.Union(BlobSize); // Next corner of the parallelogram pBlobMgr->GetBlobRect(Parallel[1], &BlobSize); Rect = Rect.Union(BlobSize); // and the next pBlobMgr->GetBlobRect(Parallel[2], &BlobSize); Rect = Rect.Union(BlobSize); // and the last one pBlobMgr->GetBlobRect(Parallel[3], &BlobSize); Rect = Rect.Union(BlobSize); } // Make sure we include the Bounds of our children IncludeChildrensBoundingRects(&Rect); // return the rectangle with the blobs included return Rect; #else return DocRect(0,0,0,0); #endif }
void BitmapExportPaletteControl::RenderPalette(DocRect *pPaletteSize, RenderRegion *pRender, INT32 controlHeight, DocRect* pClipRect) { INT32 nColours = m_Palette.GetNumberOfColours(); // See if the background needs rendering if (nColours < m_NumberOfColoursAtLastRedraw) RenderGrey(pPaletteSize, pRender); m_NumberOfColoursAtLastRedraw = nColours; pRender->SetLineColour(COLOUR_BLACK); DocRect cell; // Draw each cell in turn for (INT32 i = 0; i < nColours; ++i) { GetRectForCell(i, &cell, controlHeight); if (cell.IsIntersectedWith(*pClipRect)) { BYTE r, g, b; r = m_Palette.GetRed(i); g = m_Palette.GetGreen(i); b = m_Palette.GetBlue(i); DrawCell(&cell, DocColour(r, g, b), m_Palette.GetFlags(i), pRender, IsColourWebSafe(r, g, b), i == m_SelectedCell); } } // Draw the mouse over high light if (m_MouseOverCell != INVALID_COLOUR_VALUE) { GetRectForCell(m_MouseOverCell, &cell, controlHeight); pRender->SetFillColour(COLOUR_TRANS); pRender->SetLineColour(COLOUR_WHITE); pRender->DrawRect(&cell); } }
void OpDragBox::DrawXorRect(const DocRect& drClip, Spread* pspdXor, const DocRect& drXor) const { // Check if we have nothing to do. if (drXor.IsEmpty()) return; // Ask the derived class what colour its drag box is. If we are doing solid drags we // want to use the same colour to fill the box as well, otherwise we fill with no colour. StockColour scLineColour = GetBoxColour(); StockColour scFillColour = (m_fDoSolidDragBoxes) ? scLineColour : COLOUR_NONE; // Xor the rect on all supplied render-regions. RenderRegion* pRegion = DocView::RenderOnTop(&((DocRect&) drClip), pspdXor, ClippedEOR); while (pRegion != NULL) { // Set the line and fill colours. pRegion->SetLineColour(scLineColour); pRegion->SetFillColour(scFillColour); // Draw the xored drag box and go on to the next render-region. pRegion->DrawDragRect(&((DocRect&) drXor)); pRegion = DocView::GetNextOnTop(&((DocRect&) drClip)); } }
void PathProcessorStrokeAirbrush::ProcessPath(Path *pPath, RenderRegion *pRender, PathShape ShapePath) { PORTNOTETRACE("other","PathProcessorStrokeAirbrush::ProcessPath - do nothing"); #ifndef EXCLUDE_FROM_XARALX ERROR3IF(pPath == NULL || pRender == NULL, "Illegal NULL Params"); // --- If the provided path is not stroked, then we'll just pass it straight through // We also don't touch it if we're doing EOR rendering, or click regions // BLOCK { StrokeColourAttribute *pStrokeColour = (StrokeColourAttribute *) pRender->GetCurrentAttribute(ATTR_STROKECOLOUR); if (pRender->DrawingMode != DM_COPYPEN || pRender->IsHitDetect() || !pPath->IsStroked || pStrokeColour == NULL || pStrokeColour->Colour.IsTransparent()) { pRender->DrawPath(pPath, this, ShapePath); return; } } // --- If the quality is set low, strokes are just rendered as centrelines // BLOCK { QualityAttribute *pQuality = (QualityAttribute *) pRender->GetCurrentAttribute(ATTR_QUALITY); if (pQuality != NULL && pQuality->QualityValue.GetLineQuality() != Quality::FullLine) { pRender->DrawPath(pPath, this, ShapePath); return; } } // --- If the attribute which created us is not the current StrokeType attribute, then // we have been overridden by a different stroke type, so we do nothing. // BLOCK { StrokeTypeAttrValue *pTypeAttr = (StrokeTypeAttrValue *) pRender->GetCurrentAttribute(ATTR_STROKETYPE); if (pTypeAttr != NULL && pTypeAttr != GetParentAttr()) { pRender->DrawPath(pPath, this, ShapePath); return; } } // --- Get the current line width from the render region // In case of failure, we initialise with suitable defaults INT32 LineWidth = 5000; // BLOCK { LineWidthAttribute *pWidthAttr = (LineWidthAttribute *) pRender->GetCurrentAttribute(ATTR_LINEWIDTH); if (pWidthAttr != NULL) LineWidth = pWidthAttr->LineWidth; } // Obtain an optimal number of steps for the line // When printing, we do heaps of steps to get top quality out the other end View *pView = pRender->GetRenderView(); ERROR3IF(pView == NULL, "No render view?!"); INT32 NumSteps = MaxAirbrushSteps; if (!pRender->IsPrinting()) GetNumSteps(pView, LineWidth); // --- Now, create a transparency mask bitmap for the airbrush Spread *pSpread = pRender->GetRenderSpread(); // ERROR3IF(pSpread == NULL, "No render spread!?"); // This can happen, rendering into a gallery // Get the render region's clip rectangle in Spread Coords. We don't need to // render anything bigger than this size, so it is the upper limit on our bitmap area. DocRect ClipRegion = pRender->GetClipRect(); // Intersect this with the path bounding rectangle to get the actual region we need to redraw // The smaller this is, the faster we go and the less memory we use. //DocRect PathRect = pPath->GetBoundingRect(); DocRect PathRect = pPath->GetBlobRect(); PathRect.Inflate(LineWidth); BOOL Intersects = ClipRegion.IsIntersectedWith(PathRect); if(!Intersects) { // Don't bother drawing anything - it's clipped out return; } ClipRegion = ClipRegion.Intersection(PathRect); // Round the ClipRegion edges up so they all lie exactly on screen pixel boundaries. // If we don't do this, then there can be a sub-pixel rounding error between the ClipRegion // and the actual bitmap size, so that the bitmap is scaled slightly when we plot it. // By making sure it's pixelised, we guarantee that the bitmap & clipregion are exactly equal sizes. // (It doesn't matter if the bitmap is a bit bigger than necessary) ClipRegion.Inflate(pRender->GetScaledPixelWidth()); ClipRegion.lo.Pixelise(pView); ClipRegion.hi.Pixelise(pView); // Get the current view's rendering matrix and view scale Matrix ConvMatrix = pRender->GetMatrix();//pView->ConstructRenderingMatrix(pSpread); FIXED16 ViewScale = pView->GetViewScale(); // Generate a 256-colour greyscale palette LOGPALETTE *pPalette = MakeGreyScalePalette(); if(pPalette == NULL) { pRender->DrawPath(pPath, this, ShapePath); return; } // Work out the DPI to use. Rather than just asking for PixelWidth or DPI from the // render region, we have to do a load of non-object-oriented stuff instead... double dpi = 96.0; if (pRender->IsPrinting()) { // we are printing, so ask the print options PrintControl *pPrintControl = pView->GetPrintControl(); if (pPrintControl != NULL) dpi = (double) pPrintControl->GetDotsPerInch(); } else if (IS_A(pRender, CamelotEPSRenderRegion)) { // Use DPI as set in EPS export options dialog. dpi = (double) EPSFilter::XSEPSExportDPI; } else { ERROR3IF(pRender->GetPixelWidth() <= 0, "Stupid (<1 millipoint) Pixel Width!"); if (pRender->GetPixelWidth() > 0) dpi = (double) (72000.0 / (double)pRender->GetPixelWidth()); } GRenderBitmap *pMaskRegion = new GRenderBitmap(ClipRegion, ConvMatrix, ViewScale, 8, dpi, pRender->IsPrinting(), XARADITHER_ORDERED_GREY, pPalette, FALSE); if (pMaskRegion == NULL) { pRender->DrawPath(pPath, this, ShapePath); return; } BOOL PathIsFilled = FALSE; // Will be set TRUE if this path should be filled at the bottom of the function //BLOCK { // Change the GDraw context in this render region so as to preserve the state // of the main render region. This is because GRenderRegions currently use // a single static GDrawContext! This also sets it up with a nice greyscale palette // so that we get the output we desire. pMaskRegion->UseGreyscaleContextDangerous(); // Attach our DC to the view and render region... if (pMaskRegion->AttachDevice(pView, NULL, pSpread)) { pMaskRegion->StartRender(); // We must save & restore the attribute state around all our rendering because // attributes otherwise stay on the renderstack until we delete the RndRgn, and as our // ones are on the program stack, they will have ceased to exist before then, which // makes for a wicked explosion. pMaskRegion->SaveContext(); ///////////////////////////////////////////////////////////////////////////////////// // --- Main Airbrush rendering loop // Make sure we've got an intensity function to use. This will create a new one if necessary ValueFunction *pvValueFunction = GetIntensityFunction(); if (pvValueFunction == NULL) { ERROR3("Failed to set an intensity function on an airbrush stroke"); pRender->DrawPath(pPath, this, ShapePath); return; } if(!RenderAirBrush(pPath, pMaskRegion, LineWidth, NumSteps, pvValueFunction, pRender, ShapePath)) { // Airbrush failed - just render the path without the airbrush effect pRender->DrawPath(pPath, this, ShapePath); return; } pMaskRegion->RestoreContext(); // --- ClipRect test code ///////////////////////////////////////////////////////////////////////////////////// // --- We have drawn the airbrushed stroke - now, if the path is filled, we // will render the filled area, so that in semi-transparent cases, the // stroke will not "show through" from behind the filled area. if (pPath->IsFilled) { ColourFillAttribute *pCFAttr = (ColourFillAttribute *) pRender->GetCurrentAttribute(ATTR_FILLGEOMETRY); if (pCFAttr != NULL && (!pCFAttr->Colour.IsTransparent() || pCFAttr->IsABitmapFill())) { PathIsFilled = TRUE; pMaskRegion->SaveContext(); ColourFillAttribute *pFillAttr = NULL; FillMappingAttribute *pMapAttr = NULL; // Obtain the object's transparent fill geometry TranspFillAttribute *pTransAttr = (TranspFillAttribute *) pRender->GetCurrentAttribute(ATTR_TRANSPFILLGEOMETRY); if (pTransAttr != NULL) { // Get a non-transparent version of the fill geometry pFillAttr = pTransAttr->MakeSimilarNonTranspFillGeometry(1.0); // Convert a fill mapping TranspFillMappingAttribute *pTransMapAttr = (TranspFillMappingAttribute *) pRender->GetCurrentAttribute(ATTR_TRANSPFILLMAPPING); if(pTransMapAttr != NULL) pMapAttr = pTransMapAttr->MakeSimilarNonTranspFillMapping(); } // Setup region and draw path into it if (pFillAttr != NULL) { pMaskRegion->SetFillGeometry(pFillAttr, TRUE); if(pMapAttr != NULL) pMaskRegion->SetFillMapping(pMapAttr, TRUE); } else pMaskRegion->SetFillColour(DocColour(0, 0, 0)); pMaskRegion->SetLineColour(DocColour(COLOUR_TRANS)); pMaskRegion->DrawPath(pPath, NULL, ShapePath); pMaskRegion->RestoreContext(); } } pMaskRegion->StopRender(); } pMaskRegion->StopUsingGreyscaleContextDangerous(); } // Extract the transparency mask bitmap from the render region OILBitmap *pOilBmp = pMaskRegion->ExtractBitmap(); // We no longer need the RenderRegion, so scrap it. delete pMaskRegion; pMaskRegion = NULL; pPalette = NULL; // Now, render a rectangle to the output render region, using the transparency mask if (pOilBmp == NULL) return; KernelBitmap *pMask = new KernelBitmap(pOilBmp, TRUE); if (pMask != NULL) { // Make sure the bitmap knows it's already a greyscale, else it will spend a lot of // time "converting" itself to a greyscale, and what's more, corrupting the grey levels // so that 255 (invisible) becomes 254 (slightly visible). Arrrrrgh! pMask->SetAsGreyscale(); // Create a transparency attribute from our mask bitmap BitmapTranspFillAttribute Trans; // We don't call pTrans->AttachBitmap because it seems to be stupid, and causes ructions // when we try to attach a temporary bitmap. We thus do the same thing, but avoiding // its attempts to automatically screw us about. Trans.BitmapRef.Detach(); Trans.BitmapRef.SetBitmap(pMask); Trans.SetStartPoint(&ClipRegion.lo); DocCoord EndPoint(ClipRegion.hi.x, ClipRegion.lo.y); Trans.SetEndPoint(&EndPoint); DocCoord EndPoint2(ClipRegion.lo.x, ClipRegion.hi.y); Trans.SetEndPoint2(&EndPoint2); UINT32 TValue = 0; Trans.SetStartTransp(&TValue); TValue = 255; Trans.SetEndTransp(&TValue); // Use the same transparency type as is set on the object being rendered (if any) { TranspFillAttribute *pTransAttr = (TranspFillAttribute *) pRender->GetCurrentAttribute(ATTR_TRANSPFILLGEOMETRY); if (pTransAttr != NULL) Trans.SetTranspType(pTransAttr->GetTranspType()); else Trans.SetTranspType(TT_Mix); // By default, we'll use Mix transparency } // --- OK, we finally got here! Render the stroke, using the transparency mask we just made pRender->SaveContext(); Trans.Render(pRender); // Render the path. If it is filled, then we render the entire thing (fill & stroke) using // the current fill geometry (to get a shadow/feather effect) if (PathIsFilled) { // Render the entire thing (fill & stroke) in one go. We render a rectangle over the cliprect // so that we do everything in one go (we can't render the fill &7 stroke separately, or // the transparency will overlap & it'll look wrong) pRender->SetLineColour(DocColour(COLOUR_TRANS)); // Don't render a line Path Rect; Rect.Initialise(); Rect.AddMoveTo(ClipRegion.lo); Rect.AddLineTo(DocCoord(ClipRegion.hix, ClipRegion.loy)); Rect.AddLineTo(ClipRegion.hi); Rect.AddLineTo(DocCoord(ClipRegion.lox, ClipRegion.hiy)); Rect.AddLineTo(ClipRegion.lo); Rect.IsFilled = TRUE; Rect.IsStroked = FALSE; pRender->DrawPath(&Rect, this, ShapePath); } else { // Otherwise, create a filled-outline path for the entire stroke, and render it // !!!!****ToDo - for now, strokes always render flat-filled with the stroke colour StrokeColourAttribute *pStrokeColour = (StrokeColourAttribute *) pRender->GetCurrentAttribute(ATTR_STROKECOLOUR); if (pStrokeColour != NULL) pRender->SetFillColour(pStrokeColour->Colour); // Fill the holes pRender->SetWindingRule(NonZeroWinding); Path *pOutput = CreateVarWidthStroke(pPath, pRender, LineWidth); if (pOutput != NULL) { pRender->DrawPath(pOutput, NULL, ShapePath); delete pOutput; pOutput = NULL; } } pRender->RestoreContext(); // Delete the kernel bitmap. This auto-deletes the OIL bitmap for us delete pMask; } #endif }
AttrFillGeometry* FillGeometryNudger::MutateFill(AttrFillGeometry* FillToMutate) { if (!FillToMutate->IsVisible() || FillToMutate->GetSelectionCount() == 0) return NULL; // Make a copy of this Fill to change AttrFillGeometry* NewFill = (AttrFillGeometry*)FillToMutate->SimpleCopy(); if (NewFill == NULL) return NULL; // Construct the translation matrix Trans2DMatrix TransMat(X_NudgeDistance, Y_NudgeDistance); BOOL isARampBlob = FALSE; // And apply it to the fill NewFill->TransformSelectedControlPoints(TransMat, &isARampBlob); if (LastNudgeType == FillToMutate->GetRuntimeClass()) { BOOL IsSame = TRUE; if (FillToMutate->GetStartPoint() && *FillToMutate->GetStartPoint() != LastNudgeStart) IsSame = FALSE; if (FillToMutate->GetEndPoint() && *FillToMutate->GetEndPoint() != LastNudgeEnd) IsSame = FALSE; if (FillToMutate->GetEndPoint2() && *FillToMutate->GetEndPoint2() != LastNudgeEnd2) IsSame = FALSE; if (IsSame) return NewFill; } Node *pNode = FillToMutate; while ((pNode != NULL) && !pNode->IsSpread()) pNode = pNode->FindParent(); if (pNode == NULL) return NewFill; // We're not really in the tree Spread* pSpread = (Spread*)pNode; DocRect OldBounds = FillToMutate->GetBlobBoundingRect(); DocRect NewBounds = NewFill->GetBlobBoundingRect(); DocRect Bounds = OldBounds.Union(NewBounds); RenderRegion* pRegion = DocView::RenderOnTop(&Bounds, pSpread, UnclippedEOR); while (pRegion) { if (!isARampBlob) { // MUST do a full redraw of the fill blobs FillToMutate->RenderFillBlobs(pRegion); NewFill->RenderFillBlobs(pRegion); } else { FillToMutate->DisableRampRedraw (); FillToMutate->RenderFillBlobs(pRegion); FillToMutate->EnableRampRedraw (); NewFill->DisableRampRedraw (); NewFill->RenderFillBlobs(pRegion); NewFill->EnableRampRedraw (); } // Get the Next render region pRegion = DocView::GetNextOnTop(&Bounds); } AttrFillGeometry::LastRenderedMesh = NULL; LastNudgeType = FillToMutate->GetRuntimeClass(); if (FillToMutate->GetStartPoint()) LastNudgeStart = *FillToMutate->GetStartPoint(); if (FillToMutate->GetEndPoint()) LastNudgeEnd = *FillToMutate->GetEndPoint(); if (FillToMutate->GetEndPoint2()) LastNudgeEnd2 = *FillToMutate->GetEndPoint2(); return NewFill; }
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; }
/******************************************************************************************** > void BitmapExportPaletteControl::DrawCell(DocRect *pCellRect, DocColour colour, INT32 flags, RenderRegion *pRender, bool webSafe, bool selected, bool highlight) Author: Jonathan_Payne (Xara Group Ltd) <*****@*****.**> Created: 12/12/2000 Purpose: Draw a palette cell with the given options Inputs: pCellRect - The rect to draw the palette cell in colour - The colour of the palette entry to draw flags - The flags of that palette entry (locked, transparency, etc) pRender - The render region to render with (tested with an OS rr) webSafe - Is the colour web safe (ie do we draw the web safe mark) selected - Do we draw the cell as the selected cell? ********************************************************************************************/ void BitmapExportPaletteControl::DrawCell(DocRect *pCellRect, DocColour colour, INT32 flags, RenderRegion *pRender, bool webSafe, bool selected) { pRender->SetLineColour(COLOUR_BLACK); pRender->SetFillColour(colour); pRender->DrawRect(pCellRect); if (selected) { pRender->SetFillColour(COLOUR_TRANS); DocRect cell = *pCellRect; // make temp copy // Draw the outer line in white pRender->SetLineColour(COLOUR_WHITE); cell.Inflate(-1 * m_nPixelSize); pRender->DrawRect(&cell); // Draw the inner line in black pRender->SetLineColour(COLOUR_BLACK); cell.Inflate(-1 * m_nPixelSize); pRender->DrawRect(&cell); } if (flags & DELETED_COLOUR) { // Draw a mark to show that this palette entry has been deleted // Draw a black line from top left to bottom right pRender->SetLineColour(COLOUR_BLACK); pRender->DrawLine( DocCoord(pCellRect->lo.x, pCellRect->hi.y + m_nPixelSize), DocCoord(pCellRect->hi.x + m_nPixelSize, pCellRect->lo.y)); // Draw a white line from top right to bottom left pRender->SetLineColour(COLOUR_WHITE); pRender->DrawLine( DocCoord(pCellRect->hi.x + m_nPixelSize, pCellRect->hi.y + m_nPixelSize), DocCoord(pCellRect->lo.x + m_nPixelSize, pCellRect->lo.y + m_nPixelSize)); return; // Stop before rending any other marks } if (flags & LOCKED_COLOUR) { // Draw a mark to show that this palette entry has been // edited by the user. pRender->SetLineColour(COLOUR_BLACK); pRender->SetFillColour(COLOUR_WHITE); // Draw a rectangle in the bottom left corner of the cell DocRect markRect; markRect.hi.x = pCellRect->lo.x + m_nPixelSize * 2; markRect.lo.x = pCellRect->lo.x; markRect.hi.y = pCellRect->lo.y + m_nPixelSize * 2; markRect.lo.y = pCellRect->lo.y; pRender->DrawRect(&markRect); } if (flags & TRANSPARENT_COLOUR) { // Draw a mark to show that this palette entry is transparent pRender->SetLineColour(COLOUR_BLACK); pRender->SetFillColour(COLOUR_WHITE); // Draw a rectangle in the top left corner of the cell DocRect markRect; markRect.hi.x = pCellRect->lo.x + m_nPixelSize * 2; markRect.lo.x = pCellRect->lo.x; markRect.hi.y = pCellRect->hi.y; markRect.lo.y = pCellRect->hi.y - m_nPixelSize * 2; pRender->DrawRect(&markRect); } if (webSafe) { // Draw a mark to show that this palette entry is web-safe pRender->SetLineColour(COLOUR_BLACK); pRender->SetFillColour(COLOUR_WHITE); DocRect markRect = *pCellRect; markRect.Inflate(-4 * m_nPixelSize); pRender->DrawRect(&markRect); } }
/******************************************************************************************** > 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 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); }
void PathProcessorStrokeVector::ProcessPath(Path *pPath, RenderRegion *pRender, PathShape ShapePath) { PORTNOTETRACE("other","PathProcessorStrokeVector::ProcessPath - do nothing"); #ifndef EXCLUDE_FROM_XARALX ERROR3IF(pPath == NULL || pRender == NULL, "Illegal NULL Params"); // Get the RenderRegion SubRenderContext and see if we're returning part-way through a background render VectorStrokeSubRenderContext *pSubRenderContext = (VectorStrokeSubRenderContext *)pRender->GetSubRenderState(); if (pSubRenderContext != NULL && !IS_A(pSubRenderContext, VectorStrokeSubRenderContext)) { // We can't use the sub render context, because it's not ours! pSubRenderContext = NULL; } // --- If we don't have a valid stroke definition, then get the base class to render // the stroke as a simple flat-filled stroke. StrokeDefinition *pStrokeDef = StrokeComponent::FindStroke(StrokeID); if (pStrokeDef == NULL) { PathProcessorStroke::ProcessPath(pPath, pRender); return; } // --- See if we have to create a new SubRenderContext, or if we can use the one passed in. // We always store all relevant variables in a SubRenderContext object so that we can easily // return control to the RenderRegion without having to copy lots of local values in/out. const BOOL CreateSubRenderContext = (pSubRenderContext == NULL); if (CreateSubRenderContext) { pSubRenderContext = new VectorStrokeSubRenderContext; if (pSubRenderContext == NULL) { pRender->DrawPath(pPath, this, ShapePath); return; } // --- If the provided path is not stroked, then we'll just pass it straight through // We also don't touch it if we're doing EOR rendering, or click hit detection if (!pPath->IsStroked || pRender->DrawingMode != DM_COPYPEN || pRender->IsHitDetect()) { delete pSubRenderContext; pRender->DrawPath(pPath, this, ShapePath); return; } // --- If the quality is set low, or if the current stroke attribute is not our "parent" // attribute (so we're not the "current" stroker) then strokes are just rendered as centrelines // BLOCK { QualityAttribute *pQuality = (QualityAttribute *) pRender->GetCurrentAttribute(ATTR_QUALITY); StrokeTypeAttrValue *pTypeAttr = (StrokeTypeAttrValue *) pRender->GetCurrentAttribute(ATTR_STROKETYPE); if ((pQuality != NULL && pQuality->QualityValue.GetLineQuality() != Quality::FullLine) || (pTypeAttr != NULL && pTypeAttr != GetParentAttr())) { delete pSubRenderContext; pRender->DrawPath(pPath, this, ShapePath); return; } } // --- We don't expect the input path to be stroked AND filled on entry ERROR3IF(pPath->IsFilled, "PathProcessor expected RenderRegion to handle IsFilled case"); // --- Get the current line width & Join Style from the render region // BLOCK { LineWidthAttribute *pWidthAttr = (LineWidthAttribute *) pRender->GetCurrentAttribute(ATTR_LINEWIDTH); if (pWidthAttr != NULL) pSubRenderContext->LineWidth = pWidthAttr->LineWidth; JoinTypeAttribute *pJoinAttr = (JoinTypeAttribute *) pRender->GetCurrentAttribute(ATTR_JOINTYPE); if (pJoinAttr != NULL) pSubRenderContext->JoinStyle = pJoinAttr->JoinType; } } // --- Create a new path to be rendered in place of the provided path // Note that I use a large allocation size so that reallocation need not be done // frequently, which also helps reduce memory fragmentation. Path *pOutput = new Path; if (pOutput == NULL) { if (!pRender->IsSubRenderStateLocked()) pRender->SetSubRenderState(NULL); delete pSubRenderContext; pRender->DrawPath(pPath, this, ShapePath); return; } pOutput->Initialise(128, 128); // --- Find our Variable Width function if (CreateSubRenderContext) { // --- Get the variable line width descriptor from the render region VariableWidthAttrValue *pVarWidthAttr = (VariableWidthAttrValue *) pRender->GetCurrentAttribute(ATTR_VARWIDTH); if (pVarWidthAttr != NULL) pSubRenderContext->pValFunc = pVarWidthAttr->GetWidthFunction(); } ValueFunction *pValFunc = pSubRenderContext->pValFunc; // If we couldn't find a proper value function, then we'll default to constant-width. // We keep a static Constant function around always, because it's thread-safe and because // that saves us the overhead of creating and deleting it on the stack each time we're called static ValueFunctionConstant Constant(1.0); if (pValFunc == NULL) pValFunc = &Constant; // --- Find our brush clipart tree Node *pBrush = pStrokeDef->GetStrokeTree(); ERROR3IF(!IS_A(pBrush, Spread), "Brush does not start with a Spread Node!"); DocRect BrushBounds = ((Spread *)pBrush)->GetBoundingRect(); // Get a PathStroker to map paths onto the destination stroke with PathStrokerVector Stroker(pValFunc, pSubRenderContext->LineWidth, LineCapButt, &BrushBounds); // Work out if this is a repeating stroke, and if so, how often it repeats if (CreateSubRenderContext) { if (pStrokeDef->IsRepeating()) { // The repeat distance is calculated as a number of millipoints per repeat of the // stroke, such that it retains the correct aspect ratio. That is, the ratio of // brush width to height is the same as RepeatDist to LineWidth pSubRenderContext->RepeatDist = (INT32) (Stroker.GetScaleFactor() * (double)BrushBounds.Width()); if (pSubRenderContext->RepeatDist < 1000) // I absolutely refuse to repeat it more than pSubRenderContext->RepeatDist = 1000; // once every 1pt, as this is plenty small enough // Suss the path length out ProcessLength GenerateLength(100); double Length = 0; BOOL ok = GenerateLength.PathLength(pPath, &Length); // Ask the stroke def for its number of brush repeats - 0 means work it out INT32 NumberOfRepeats = pStrokeDef->NumRepeats(); if(NumberOfRepeats == 0 && pSubRenderContext->RepeatDist > 0) { // Work out the optimal number of repeats along the path NumberOfRepeats = (INT32)(floor((Length/pSubRenderContext->RepeatDist) + 0.5)); } // Don't got dividing by zero now... if(NumberOfRepeats <= 0) NumberOfRepeats = 1; // Alter the repeat distance to accomodate this number of repeats pSubRenderContext->RepeatDist = (INT32)(Length / (double)NumberOfRepeats); } // Generate the set of trapezoids for the dest path ProcessPathToTrapezoids GenerateTraps(100); pSubRenderContext->pOutputTraps = new TrapsList(pSubRenderContext->RepeatDist); BOOL Failed = (pSubRenderContext->pOutputTraps == NULL); if (!Failed && !GenerateTraps.Init(pPath, pSubRenderContext->pOutputTraps)) Failed = TRUE; ProcessFlags PFlags(TRUE, FALSE, FALSE); // Flags are: Flatten, !QuantiseLines, !QuantiseAll if (!Failed && !GenerateTraps.Process(PFlags, TrapTravel_Parametric, pSubRenderContext->JoinStyle)) Failed = TRUE; if (Failed) { pRender->DrawPath(pPath, this, ShapePath); if (!pRender->IsSubRenderStateLocked()) pRender->SetSubRenderState(NULL); delete pSubRenderContext; return; } } ERROR3IF(pSubRenderContext->pOutputTraps == NULL || pValFunc == NULL, "Vector stroke SubRenderContext was not properly uninitialised!"); // --- Handle background rendering. We always store all critical information in a SubRenderContext. // If we have to break into rendering because of background rendering, we give the context to the RndRgn // to keep for next time. However, when we finish rendering everything, we need to clean up - we will // assume that we'll make it to the end, and chnage this variable if we get interrupted. BOOL DeleteSubRenderContext = TRUE; // Lock the sub-render context so that nobody "inside" the brush uses it const BOOL SRContextLocked = pRender->IsSubRenderStateLocked(); if (!SRContextLocked) pRender->LockSubRenderState(TRUE); // --- Now "render" the brush clipart tree via our Stroker for ( ; pSubRenderContext->Index < pSubRenderContext->pOutputTraps->GetNumTraps() && DeleteSubRenderContext; pSubRenderContext->Index++) { // Find the trapezoid edge list for this pass TrapEdgeList *pEdgeList = pSubRenderContext->pOutputTraps->GetTrapEdgeList(pSubRenderContext->Index); if (pEdgeList->GetNumEdges() < 2) { ERROR3("No map traps when stroking! Subpath stripped\n"); continue; } // And render away pRender->SaveContext(); Node* pNode = pBrush->FindFirstForUnclippedInkRender(pRender); while (pNode) { // Prepare the stroker to stroke this sub-stroke Stroker.PrepareToStroke(pEdgeList); if (pNode->IsAnAttribute()) { // If we are overriding the fill/transparency with the one applied to the stroke, // then we simply throw away all fill/transparency attributes as we render // (We do this on the fly rather than as we make the brush so that the user can // toggle this mode on and off at any time if they change their mind) BOOL RenderIt = TRUE; if ( (pStrokeDef->OverrideFill() && ((NodeAttribute *)pNode)->IsAColourFill()) || (pStrokeDef->OverrideFill() && ((NodeAttribute *)pNode)->IsAStrokeColour()) || (pStrokeDef->OverrideTrans() && ((NodeAttribute *)pNode)->IsAStrokeTransp()) || (pStrokeDef->OverrideTrans() && ((NodeAttribute *)pNode)->IsATranspFill()) ) { RenderIt = FALSE; } if (RenderIt) { // We must modify all attributes to lie in the destination stroke. // This includes fill/trans geometry endpoints, line widths, and // also possibly modifying transparency levels to allow a flat transparency // to be applied to the whole stroke. AttributeValue *pAttrValue = ((NodeAttribute *)pNode)->GetAttributeValue(); AttributeValue *pNewValue = pAttrValue->MouldIntoStroke(&Stroker, 1.0); //****!!!!TODO - Just above, we have the chance to handle transparency better // - we could at least scale all transparencies by passing a flat scale factor into // the MouldIntoStroke call. if (pNewValue != NULL) pNewValue->Render(pRender, TRUE); // The RndRgn will delete this when it's done with else pNode->Render(pRender); // No change, so render the original attribute } } else if (pNode->IsNodePath()) { // Stroke the trapezoids into the output path pOutput->ClearPath(); if (!Stroker.StrokePath(&((NodePath *)pNode)->InkPath, pOutput)) break; pRender->SetWindingRule(NonZeroWinding); pRender->DrawPath(pOutput, this, ShapePath); } // else // TRACEUSER( "Jason", _T("\nBrush node %s not rendered\n"), pNode->GetRuntimeClass()->m_lpszClassName); pNode = pNode->FindNextForUnclippedInkRender(pRender); } pRender->RestoreContext(); // --- Now check if we should break into rendering for background rendering purposes // If the Sub-render-context is locked, then we're inside a blend or something, and it's too dangerous // for us to store our sub-render state, so we have no choice but to render until we finish. // BLOCK if (!SRContextLocked && IS_A(pRender, GRenderDIB)) { View *pView = pRender->GetRenderView(); if (pView != NULL && !pRender->RenderTreeCanContinue()) { // We have been interrupted by the background redraw system. // We will immediately exit, storing our SubRenderContext away into the // RenderRegion for the next time it calls us (see below). DeleteSubRenderContext = FALSE; // Drop through and let the loop condition handle exit } } } // If we locked the sub-render context, then we must restore it if (!SRContextLocked) pRender->LockSubRenderState(FALSE); // If we have finished rendering everything, then we vape our sub render context. // (We even check if we were interrupted just as we finished the final iteration) if (DeleteSubRenderContext || pSubRenderContext->Index >= pSubRenderContext->pOutputTraps->GetNumTraps()) { if (!SRContextLocked) pRender->SetSubRenderState(NULL); delete pSubRenderContext; pSubRenderContext = NULL; } else { if (!SRContextLocked) pRender->SetSubRenderState(pSubRenderContext); } delete pOutput; pOutput = NULL; #endif }
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 ColourDragInformation::OnPageDrop(ViewDragTarget* pDragTarget) { PageDropInfo ThePageDropInfo; ((ViewDragTarget*)pDragTarget)->GetDropInfo(&ThePageDropInfo); DocCoord DragPos = ThePageDropInfo.DropPos; ObjectDragTarget TargetType = ThePageDropInfo.TargetHit; NodeRenderableInk* ThisNode = ThePageDropInfo.pObjectHit; // DMc 4/10/99 // test for dragging & dropping onto a bevel/shadow/other compound node which // is grouped if (ThisNode) { if (ThisNode->FindParent()) { if (!ThisNode->FindParent()->PromoteHitTestOnChildrenToMe()) { // any compounds with their 'promotehittest' stuff set above me ? Node * pNode = ThisNode->FindParent(); while (pNode) { if (pNode->IsAnObject()) { if (pNode->PromoteHitTestOnChildrenToMe()) { ThisNode = (NodeRenderableInk *)pNode; } } pNode = pNode->FindParent(); } } } } NodeAttribute *Attrib = NULL; // Get a colour to apply to the Selected doc IndexedColour *IxColToApply = GetColourForDocument(NULL); // And make a DocColour to apply DocColour ColourToApply(COLOUR_TRANS); if (IxColToApply != NULL) ColourToApply.MakeRefToIndexedColour(IxColToApply); if (TargetType == LINE_TARGET) // apply a stroke colour { // Apply a stroke colour to the object(s) we have been dropped onto Attrib = new AttrStrokeColourChange; if (Attrib == NULL) return FALSE; ((AttrStrokeColourChange *)Attrib)->SetStartColour(&ColourToApply); AttributeManager::ApplyAttribToNode(ThisNode, Attrib); } else { // Apply a fill colour to the object(s) we have been dropped onto // This always used to be the case. If there were no objects then we // just set the current fill colour to be the new one. // Now, if no objects are the target then apply a page background colour // otherwise if control is held down set the current fill colour. BOOL Constrain = FALSE; // get object bounds DocRect pSimpleBounds; if (ThisNode) pSimpleBounds = ThisNode->GetBoundingRect(); else { pSimpleBounds.MakeEmpty(); // See if the control key is pressed Constrain = KeyPress::IsConstrainPressed(); } // No node(s) are targetted so see if the constrain key is pressed or not if (ThisNode == NULL && Constrain) { // Use the colour to set the background // We should use the document given to us by the page info class OpBackgroundParam Param; Param.pDocColour = &ColourToApply; Param.pDoc = ThePageDropInfo.pDoc; Param.pSpread = ThePageDropInfo.pSpread; // Obtain a pointer to the op descriptor for the create operation OpDescriptor* pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_BACKGROUND); // Invoke the operation, passing in our parameters pOpDesc->Invoke(&Param); } else { // Apply the colour either to the targetted node(s) or as the current // fill colour, if no nodes are targetted. Attrib = new AttrColourDrop(DragPos, pSimpleBounds, ColourToApply); if (Attrib == NULL) return FALSE; if (ThisNode) ((AttrColourDrop*)Attrib)->SetObjectDroppedOn(ThisNode); AttributeManager::ApplyAttribToNode(ThisNode, Attrib); } } 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; }