KernelBitmap* GalleryLineDragInfo::GetSolidDragMask() { // Note we abuse this call (like our base class abuses this call) to create the bitmap // itself. We don't use DragMask itself anymore (i.e. it stays NULL) if (!DragMask && !TheBitmap) { DocView *View = DocView::GetCurrent(); if (View == NULL) { return NULL; } Spread *pSpread = View->FindEnclosingSpread(OilCoord(0,0)); if (pSpread == NULL) { return NULL; } // Find the size of the rendered item. DocRect ClipRegion(0,0, 750*100, 750*50); // ClipRegion.lo.x = ClipRegion.lo.y = 0; // SourceItem->GetSize(c_eLineAttrDragTextPos, &ClipRegion.hi.x, &ClipRegion.hi.y); Matrix ConvertMatrix; FIXED16 ViewScale = 1; wxScreenDC DisplayDC; double dpi = (double) OSRenderRegion::GetFixedDCPPI(DisplayDC).GetWidth(); GRenderBitmap* pMaskRegion = new GRenderBitmap(ClipRegion, ConvertMatrix, ViewScale, 32, dpi); pMaskRegion->SetDoCompression(TRUE); // misnamed call to indicate we want transparency pMaskRegion->AttachDevice(View, &DisplayDC, pSpread); // Make a Mask Bitmap pMaskRegion->StartRender(); SourceItem->Render(pMaskRegion, ClipRegion, c_eLineAttrDragTextPos); pMaskRegion->StopRender(); OILBitmap* pOilMaskBmp = pMaskRegion->ExtractBitmap(); TheBitmap = new KernelBitmap(pOilMaskBmp, TRUE); delete pMaskRegion; } return BitmapDragInformation::GetSolidDragMask(); }
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 }
KernelBitmap* SGNameDrag::MakeImage(UINT32 nDepth) { // If there's no current View, or no Spread, then fail. DocView* pView = DocView::GetCurrent(); if (pView == 0) return 0; Spread* pSpread = pView->FindEnclosingSpread(OilCoord(0, 0)); if (pSpread == 0) return 0; // Create a device context for the display. CDC sdc; sdc.CreateDC("DISPLAY", 0, 0, 0); // Calculate the size of the rendering and set up the rendering matrix etc. Matrix matConvert; FIXED16 fxScale = 1; INT32 nSel = NameGallery::Instance()->GetSelectedItemCount(); DocRect drClip(0, 0, SG_DefaultNameText, nSel * SG_DefaultSmallIcon); // Work out the destination bitmap's characteristics. double dpi = (double) GetDeviceCaps(sdc.m_hDC, LOGPIXELSX); if (nDepth == 0) nDepth = GetDeviceCaps(sdc.m_hDC, BITSPIXEL) * GetDeviceCaps(sdc.m_hDC, PLANES); // Create a render region with the given properties of the display etc. GRenderBitmap* pRenderer = new GRenderBitmap(drClip, matConvert, fxScale, nDepth, dpi); ERRORIF(pRenderer == 0, _R(IDE_NOMORE_MEMORY), 0); pRenderer->AttachDevice(pView, &sdc, pSpread); pRenderer->StartRender(); pRenderer->SaveContext(); // Blank the background. pRenderer->SetLineWidth(0); pRenderer->SetLineColour(COLOUR_WHITE); pRenderer->SetFillColour(COLOUR_WHITE); pRenderer->DrawRect(&drClip); // Render the item's name. DocColour dcText(COLOUR_BLACK), dcBack(COLOUR_WHITE); pRenderer->SetFixedSystemTextColours(&dcText, &dcBack); String_256 strName; m_pSourceItem->GetNameText(&strName); pRenderer->DrawFixedSystemText(&strName, drClip); // Create a kernel bitmap from the OIL bitmap and return it. pRenderer->RestoreContext(); pRenderer->StopRender(); OILBitmap* pOilMaskBmp = pRenderer->ExtractBitmap(); delete pRenderer; KernelBitmap* pkb = new KernelBitmap(pOilMaskBmp, TRUE); ERRORIF(pkb == 0, _R(IDE_NOMORE_MEMORY), 0); return pkb; }