#include <ppairbsh.h>
Inheritance diagram for PathProcessorStrokeAirbrush:
Public Member Functions | |
PathProcessorStrokeAirbrush () | |
~PathProcessorStrokeAirbrush () | |
Destructor. | |
virtual void | ProcessPath (Path *pPath, RenderRegion *pRender, PathShape ShapePath=PATHSHAPE_PATH) |
Called by the RenderRegion to apply the path processing operation to the given path. | |
virtual BOOL | WillChangeFillAndStrokeSeparately (void) |
Called by the RenderRegion to determine if this PathProcessorStrokeAirbrush affects the "fill" and "stroke" portions of the path separately. (Generally speaking, only fill/stroke providers will cause these two different "bits" of a path to be rendered separately). This call is made BEFORE this Processor's ProcessPath function will be called. | |
virtual BOOL | IsDifferent (PathProcessorStroke *pOther) |
Equality operator. | |
virtual PathProcessorStroke * | Clone (void) |
To copy PathProcessorStrokeAirbrush or derived-class object. | |
virtual BOOL | NeedsTransparency () const |
ValueFunction * | GetIntensityFunction (void) |
Sets the intensity function which will be used when rendering this airbrush. The function controls the intensity (opacity) of the airbrush at Position values where Position 0.0 represents the airbrush centreline, and 1.0 represents the maximum width. | |
void | SetIntensityFunction (ValueFunction *pFunc) |
Sets the intensity function which will be used when rendering this airbrush. The function controls the intensity (opacity) of the airbrush at Position values where Position 0.0 represents the airbrush centreline, and 1.0 represents the maximum width. | |
Protected Member Functions | |
virtual INT32 | GetNumSteps (View *pView, INT32 LineWidth) |
To get the number of steps for an airbrush stroke. | |
LOGPALETTE * | MakeGreyScalePalette (void) |
Obtain a greyscale palette. | |
virtual BOOL | RenderAirBrush (Path *pPath, GRenderBitmap *pRegion, INT32 LineWidth, INT32 NumSteps, ValueFunction *pvValueFunction, RenderRegion *pDestRegion, PathShape ShapePath) |
Main Airbrush rendering loop. | |
Private Member Functions | |
CC_DECLARE_DYNAMIC (PathProcessorStrokeAirbrush) | |
Private Attributes | |
ValueFunction * | pIntensityFunction |
Friends | |
class | RenderRegion |
This can be used to "filter" almost any rendering, but is mainly intended for use by stroke and fill providers, which replace input paths with more suitable shapes to be rendered.
Definition at line 132 of file ppairbsh.h.
|
Definition at line 139 of file ppairbsh.h. 00139 { pIntensityFunction = NULL; };
|
|
Destructor.
Definition at line 142 of file ppairbsh.cpp. 00143 { 00144 if (pIntensityFunction != NULL) 00145 delete pIntensityFunction; 00146 }
|
|
|
|
To copy PathProcessorStrokeAirbrush or derived-class object.
Reimplemented from PathProcessorStroke. Definition at line 614 of file ppairbsh.cpp. 00615 { 00616 // Clone this object - this can be done by just creating a new one 00617 PathProcessorStrokeAirbrush *pClone = new PathProcessorStrokeAirbrush; 00618 00619 if (pClone != NULL) 00620 { 00621 // And copy the (base class) parent-attribute pointer so we know when our 00622 // parent attribute is "current" in the render region. 00623 pClone->SetParentAttr(GetParentAttr()); 00624 00625 // And copy our intensity function, if any 00626 if (pIntensityFunction != NULL) 00627 { 00628 ValueFunction *pNewFunc = pIntensityFunction->Clone(); 00629 pClone->SetIntensityFunction(pNewFunc); // This is OK if it's NULL 00630 } 00631 } 00632 00633 return(pClone); 00634 }
|
|
Sets the intensity function which will be used when rendering this airbrush. The function controls the intensity (opacity) of the airbrush at Position values where Position 0.0 represents the airbrush centreline, and 1.0 represents the maximum width.
Definition at line 871 of file ppairbsh.cpp. 00872 { 00873 if (pIntensityFunction == NULL) 00874 pIntensityFunction = new ValueFunctionRampS(1.0, 0.0); 00875 00876 return(pIntensityFunction); 00877 }
|
|
To get the number of steps for an airbrush stroke.
Definition at line 651 of file ppairbsh.cpp. 00652 { 00653 if(pView == NULL) 00654 return 1; 00655 00656 // Find out how many millipoints 1 pixel is 00657 const INT32 spw = pView->GetScaledPixelWidth().MakeLong(); 00658 const INT32 sph = pView->GetScaledPixelHeight().MakeLong(); 00659 const MILLIPOINT OnePixel = min(spw, sph); 00660 TRACEUSER( "Richard", _T("1 pixel = %d\n"), OnePixel); 00661 00662 if (OnePixel <= 0) 00663 return(1); 00664 00665 // Now work out how many steps to render. The fewer steps, the faster we go, but this 00666 // trades off against quality. Because we start in the centre and increase in both 00667 // directions, we need to divide line width by the size of 2 pixels to get a step per pixel. 00668 // However, 3 is used because it means each ring of the airbrush is 1.5 pixels wider than the 00669 // last, which, with anti-aliasing, gives a very smooth effect. Going up to 4 makes each one 00670 // 2 pixels, and you can begin to see tree-ring effects in the airbrush. 00671 INT32 NumSteps = (INT32)(LineWidth / (OnePixel * 3)); 00672 00673 // Limit it to a sensible range 00674 if(NumSteps < 1) 00675 NumSteps = 1; 00676 if(NumSteps > MaxAirbrushSteps) 00677 NumSteps = MaxAirbrushSteps; 00678 00679 TRACEUSER( "Richard", _T("NumSteps = %d\n"), NumSteps); 00680 00681 return NumSteps; 00682 }
|
|
Equality operator.
Reimplemented from PathProcessorStroke. Definition at line 580 of file ppairbsh.cpp. 00581 { 00582 ERROR3IF(pOther == NULL, "Illegal NULL param"); 00583 00584 if (GetRuntimeClass() != pOther->GetRuntimeClass()) 00585 return(TRUE); 00586 00587 PathProcessorStrokeAirbrush *pOtherAir = (PathProcessorStrokeAirbrush *)pOther; 00588 00589 ValueFunction *pMyFunc = GetIntensityFunction(); 00590 ValueFunction *pOtherFunc = pOtherAir->GetIntensityFunction(); 00591 if (pMyFunc == NULL || pOtherFunc == NULL) 00592 return(TRUE); 00593 00594 // We're the same if we share the same intensity function 00595 return(pMyFunc->IsDifferent(pOtherFunc)); 00596 }
|
|
Obtain a greyscale palette.
Definition at line 699 of file ppairbsh.cpp. 00700 { 00701 static BYTE Pal[sizeof(LOGPALETTE) + 256*sizeof(PALETTEENTRY)]; 00702 static LOGPALETTE *pPal = NULL; 00703 00704 if (pPal == NULL) // Only fill in the palette the first time we're called 00705 { 00706 pPal = (LOGPALETTE *) Pal; 00707 00708 pPal->palVersion = 0x300; 00709 pPal->palNumEntries = 256; 00710 for (INT32 i = 0; i < 256; i++) 00711 { 00712 pPal->palPalEntry[i].peRed = i; 00713 pPal->palPalEntry[i].peGreen = i; 00714 pPal->palPalEntry[i].peBlue = i; 00715 pPal->palPalEntry[i].peFlags = 0; 00716 } 00717 } 00718 00719 return pPal; 00720 }
|
|
Reimplemented from PathProcessorStroke. Definition at line 156 of file ppairbsh.h. 00156 {return TRUE;};
|
|
Called by the RenderRegion to apply the path processing operation to the given path.
Notes: * When rendering a path, always pass in your 'this' pointer to RenderRegion::DrawPath, so that you don't start an infinite recursion! To stop rendering of the path, simply return without calling the RR To render this path unchanged, simply call directly back to the RR: pRender->DrawPath(pPath, this); Only affect the fill of this path if pPath->IsFilled Only affect the stroke of this path if pPath->IsStroked If converting a path into a "filled path" for stroking, the output path should be rendered with IsStroked=FALSE or it'll get a line around the outside! Reimplemented from PathProcessorStroke. Definition at line 214 of file ppairbsh.cpp. 00217 { 00218 PORTNOTETRACE("other","PathProcessorStrokeAirbrush::ProcessPath - do nothing"); 00219 #ifndef EXCLUDE_FROM_XARALX 00220 ERROR3IF(pPath == NULL || pRender == NULL, "Illegal NULL Params"); 00221 00222 // --- If the provided path is not stroked, then we'll just pass it straight through 00223 // We also don't touch it if we're doing EOR rendering, or click regions 00224 // BLOCK 00225 { 00226 StrokeColourAttribute *pStrokeColour = (StrokeColourAttribute *) pRender->GetCurrentAttribute(ATTR_STROKECOLOUR); 00227 if (pRender->DrawingMode != DM_COPYPEN || pRender->IsHitDetect() 00228 || !pPath->IsStroked || pStrokeColour == NULL || pStrokeColour->Colour.IsTransparent()) 00229 { 00230 pRender->DrawPath(pPath, this, ShapePath); 00231 return; 00232 } 00233 } 00234 00235 // --- If the quality is set low, strokes are just rendered as centrelines 00236 // BLOCK 00237 { 00238 QualityAttribute *pQuality = (QualityAttribute *) pRender->GetCurrentAttribute(ATTR_QUALITY); 00239 if (pQuality != NULL && pQuality->QualityValue.GetLineQuality() != Quality::FullLine) 00240 { 00241 pRender->DrawPath(pPath, this, ShapePath); 00242 return; 00243 } 00244 } 00245 00246 // --- If the attribute which created us is not the current StrokeType attribute, then 00247 // we have been overridden by a different stroke type, so we do nothing. 00248 // BLOCK 00249 { 00250 StrokeTypeAttrValue *pTypeAttr = (StrokeTypeAttrValue *) pRender->GetCurrentAttribute(ATTR_STROKETYPE); 00251 if (pTypeAttr != NULL && pTypeAttr != GetParentAttr()) 00252 { 00253 pRender->DrawPath(pPath, this, ShapePath); 00254 return; 00255 } 00256 } 00257 00258 // --- Get the current line width from the render region 00259 // In case of failure, we initialise with suitable defaults 00260 INT32 LineWidth = 5000; 00261 // BLOCK 00262 { 00263 LineWidthAttribute *pWidthAttr = (LineWidthAttribute *) pRender->GetCurrentAttribute(ATTR_LINEWIDTH); 00264 if (pWidthAttr != NULL) 00265 LineWidth = pWidthAttr->LineWidth; 00266 } 00267 00268 // Obtain an optimal number of steps for the line 00269 // When printing, we do heaps of steps to get top quality out the other end 00270 View *pView = pRender->GetRenderView(); 00271 ERROR3IF(pView == NULL, "No render view?!"); 00272 00273 INT32 NumSteps = MaxAirbrushSteps; 00274 if (!pRender->IsPrinting()) 00275 GetNumSteps(pView, LineWidth); 00276 00277 // --- Now, create a transparency mask bitmap for the airbrush 00278 Spread *pSpread = pRender->GetRenderSpread(); 00279 // ERROR3IF(pSpread == NULL, "No render spread!?"); // This can happen, rendering into a gallery 00280 00281 // Get the render region's clip rectangle in Spread Coords. We don't need to 00282 // render anything bigger than this size, so it is the upper limit on our bitmap area. 00283 DocRect ClipRegion = pRender->GetClipRect(); 00284 00285 // Intersect this with the path bounding rectangle to get the actual region we need to redraw 00286 // The smaller this is, the faster we go and the less memory we use. 00287 //DocRect PathRect = pPath->GetBoundingRect(); 00288 DocRect PathRect = pPath->GetBlobRect(); 00289 PathRect.Inflate(LineWidth); 00290 00291 BOOL Intersects = ClipRegion.IsIntersectedWith(PathRect); 00292 if(!Intersects) 00293 { 00294 // Don't bother drawing anything - it's clipped out 00295 return; 00296 } 00297 00298 ClipRegion = ClipRegion.Intersection(PathRect); 00299 00300 // Round the ClipRegion edges up so they all lie exactly on screen pixel boundaries. 00301 // If we don't do this, then there can be a sub-pixel rounding error between the ClipRegion 00302 // and the actual bitmap size, so that the bitmap is scaled slightly when we plot it. 00303 // By making sure it's pixelised, we guarantee that the bitmap & clipregion are exactly equal sizes. 00304 // (It doesn't matter if the bitmap is a bit bigger than necessary) 00305 ClipRegion.Inflate(pRender->GetScaledPixelWidth()); 00306 ClipRegion.lo.Pixelise(pView); 00307 ClipRegion.hi.Pixelise(pView); 00308 00309 // Get the current view's rendering matrix and view scale 00310 Matrix ConvMatrix = pRender->GetMatrix();//pView->ConstructRenderingMatrix(pSpread); 00311 FIXED16 ViewScale = pView->GetViewScale(); 00312 00313 // Generate a 256-colour greyscale palette 00314 LOGPALETTE *pPalette = MakeGreyScalePalette(); 00315 if(pPalette == NULL) 00316 { 00317 pRender->DrawPath(pPath, this, ShapePath); 00318 return; 00319 } 00320 00321 // Work out the DPI to use. Rather than just asking for PixelWidth or DPI from the 00322 // render region, we have to do a load of non-object-oriented stuff instead... 00323 double dpi = 96.0; 00324 if (pRender->IsPrinting()) 00325 { 00326 // we are printing, so ask the print options 00327 PrintControl *pPrintControl = pView->GetPrintControl(); 00328 if (pPrintControl != NULL) 00329 dpi = (double) pPrintControl->GetDotsPerInch(); 00330 } 00331 else if (IS_A(pRender, CamelotEPSRenderRegion)) 00332 { 00333 // Use DPI as set in EPS export options dialog. 00334 dpi = (double) EPSFilter::XSEPSExportDPI; 00335 } 00336 else 00337 { 00338 ERROR3IF(pRender->GetPixelWidth() <= 0, "Stupid (<1 millipoint) Pixel Width!"); 00339 if (pRender->GetPixelWidth() > 0) 00340 dpi = (double) (72000.0 / (double)pRender->GetPixelWidth()); 00341 } 00342 00343 GRenderBitmap *pMaskRegion = new GRenderBitmap(ClipRegion, ConvMatrix, ViewScale, 8, dpi, 00344 pRender->IsPrinting(), XARADITHER_ORDERED_GREY, 00345 pPalette, FALSE); 00346 if (pMaskRegion == NULL) 00347 { 00348 pRender->DrawPath(pPath, this, ShapePath); 00349 return; 00350 } 00351 00352 BOOL PathIsFilled = FALSE; // Will be set TRUE if this path should be filled at the bottom of the function 00353 00354 //BLOCK 00355 { 00356 // Change the GDraw context in this render region so as to preserve the state 00357 // of the main render region. This is because GRenderRegions currently use 00358 // a single static GDrawContext! This also sets it up with a nice greyscale palette 00359 // so that we get the output we desire. 00360 pMaskRegion->UseGreyscaleContextDangerous(); 00361 00362 // Attach our DC to the view and render region... 00363 if (pMaskRegion->AttachDevice(pView, NULL, pSpread)) 00364 { 00365 pMaskRegion->StartRender(); 00366 00367 // We must save & restore the attribute state around all our rendering because 00368 // attributes otherwise stay on the renderstack until we delete the RndRgn, and as our 00369 // ones are on the program stack, they will have ceased to exist before then, which 00370 // makes for a wicked explosion. 00371 pMaskRegion->SaveContext(); 00372 00374 // --- Main Airbrush rendering loop 00375 00376 // Make sure we've got an intensity function to use. This will create a new one if necessary 00377 ValueFunction *pvValueFunction = GetIntensityFunction(); 00378 if (pvValueFunction == NULL) 00379 { 00380 ERROR3("Failed to set an intensity function on an airbrush stroke"); 00381 pRender->DrawPath(pPath, this, ShapePath); 00382 return; 00383 } 00384 00385 00386 if(!RenderAirBrush(pPath, pMaskRegion, LineWidth, NumSteps, pvValueFunction, 00387 pRender, ShapePath)) 00388 { 00389 // Airbrush failed - just render the path without the airbrush effect 00390 pRender->DrawPath(pPath, this, ShapePath); 00391 return; 00392 } 00393 00394 pMaskRegion->RestoreContext(); 00395 00396 // --- ClipRect test code 00397 00399 00400 00401 // --- We have drawn the airbrushed stroke - now, if the path is filled, we 00402 // will render the filled area, so that in semi-transparent cases, the 00403 // stroke will not "show through" from behind the filled area. 00404 if (pPath->IsFilled) 00405 { 00406 ColourFillAttribute *pCFAttr = (ColourFillAttribute *) pRender->GetCurrentAttribute(ATTR_FILLGEOMETRY); 00407 if (pCFAttr != NULL && (!pCFAttr->Colour.IsTransparent() || pCFAttr->IsABitmapFill())) 00408 { 00409 PathIsFilled = TRUE; 00410 00411 pMaskRegion->SaveContext(); 00412 00413 ColourFillAttribute *pFillAttr = NULL; 00414 FillMappingAttribute *pMapAttr = NULL; 00415 00416 // Obtain the object's transparent fill geometry 00417 TranspFillAttribute *pTransAttr = (TranspFillAttribute *) pRender->GetCurrentAttribute(ATTR_TRANSPFILLGEOMETRY); 00418 if (pTransAttr != NULL) 00419 { 00420 // Get a non-transparent version of the fill geometry 00421 pFillAttr = pTransAttr->MakeSimilarNonTranspFillGeometry(1.0); 00422 00423 // Convert a fill mapping 00424 TranspFillMappingAttribute *pTransMapAttr = (TranspFillMappingAttribute *) pRender->GetCurrentAttribute(ATTR_TRANSPFILLMAPPING); 00425 if(pTransMapAttr != NULL) 00426 pMapAttr = pTransMapAttr->MakeSimilarNonTranspFillMapping(); 00427 } 00428 00429 // Setup region and draw path into it 00430 if (pFillAttr != NULL) 00431 { 00432 pMaskRegion->SetFillGeometry(pFillAttr, TRUE); 00433 00434 if(pMapAttr != NULL) 00435 pMaskRegion->SetFillMapping(pMapAttr, TRUE); 00436 } 00437 else 00438 pMaskRegion->SetFillColour(DocColour(0, 0, 0)); 00439 00440 pMaskRegion->SetLineColour(DocColour(COLOUR_TRANS)); 00441 pMaskRegion->DrawPath(pPath, NULL, ShapePath); 00442 00443 pMaskRegion->RestoreContext(); 00444 } 00445 } 00446 00447 pMaskRegion->StopRender(); 00448 } 00449 00450 pMaskRegion->StopUsingGreyscaleContextDangerous(); 00451 } 00452 00453 // Extract the transparency mask bitmap from the render region 00454 OILBitmap *pOilBmp = pMaskRegion->ExtractBitmap(); 00455 00456 // We no longer need the RenderRegion, so scrap it. 00457 delete pMaskRegion; 00458 pMaskRegion = NULL; 00459 pPalette = NULL; 00460 00461 // Now, render a rectangle to the output render region, using the transparency mask 00462 if (pOilBmp == NULL) 00463 return; 00464 00465 KernelBitmap *pMask = new KernelBitmap(pOilBmp, TRUE); 00466 00467 if (pMask != NULL) 00468 { 00469 // Make sure the bitmap knows it's already a greyscale, else it will spend a lot of 00470 // time "converting" itself to a greyscale, and what's more, corrupting the grey levels 00471 // so that 255 (invisible) becomes 254 (slightly visible). Arrrrrgh! 00472 pMask->SetAsGreyscale(); 00473 00474 // Create a transparency attribute from our mask bitmap 00475 BitmapTranspFillAttribute Trans; 00476 00477 // We don't call pTrans->AttachBitmap because it seems to be stupid, and causes ructions 00478 // when we try to attach a temporary bitmap. We thus do the same thing, but avoiding 00479 // its attempts to automatically screw us about. 00480 Trans.BitmapRef.Detach(); 00481 Trans.BitmapRef.SetBitmap(pMask); 00482 00483 Trans.SetStartPoint(&ClipRegion.lo); 00484 DocCoord EndPoint(ClipRegion.hi.x, ClipRegion.lo.y); 00485 Trans.SetEndPoint(&EndPoint); 00486 DocCoord EndPoint2(ClipRegion.lo.x, ClipRegion.hi.y); 00487 Trans.SetEndPoint2(&EndPoint2); 00488 00489 UINT32 TValue = 0; 00490 Trans.SetStartTransp(&TValue); 00491 TValue = 255; 00492 Trans.SetEndTransp(&TValue); 00493 00494 // Use the same transparency type as is set on the object being rendered (if any) 00495 { 00496 TranspFillAttribute *pTransAttr = (TranspFillAttribute *) pRender->GetCurrentAttribute(ATTR_TRANSPFILLGEOMETRY); 00497 00498 if (pTransAttr != NULL) 00499 Trans.SetTranspType(pTransAttr->GetTranspType()); 00500 else 00501 Trans.SetTranspType(TT_Mix); // By default, we'll use Mix transparency 00502 00503 } 00504 00505 // --- OK, we finally got here! Render the stroke, using the transparency mask we just made 00506 pRender->SaveContext(); 00507 00508 Trans.Render(pRender); 00509 00510 // Render the path. If it is filled, then we render the entire thing (fill & stroke) using 00511 // the current fill geometry (to get a shadow/feather effect) 00512 if (PathIsFilled) 00513 { 00514 // Render the entire thing (fill & stroke) in one go. We render a rectangle over the cliprect 00515 // so that we do everything in one go (we can't render the fill &7 stroke separately, or 00516 // the transparency will overlap & it'll look wrong) 00517 pRender->SetLineColour(DocColour(COLOUR_TRANS)); // Don't render a line 00518 00519 Path Rect; 00520 Rect.Initialise(); 00521 Rect.AddMoveTo(ClipRegion.lo); 00522 Rect.AddLineTo(DocCoord(ClipRegion.hix, ClipRegion.loy)); 00523 Rect.AddLineTo(ClipRegion.hi); 00524 Rect.AddLineTo(DocCoord(ClipRegion.lox, ClipRegion.hiy)); 00525 Rect.AddLineTo(ClipRegion.lo); 00526 Rect.IsFilled = TRUE; 00527 Rect.IsStroked = FALSE; 00528 pRender->DrawPath(&Rect, this, ShapePath); 00529 } 00530 else 00531 { 00532 // Otherwise, create a filled-outline path for the entire stroke, and render it 00533 // !!!!****ToDo - for now, strokes always render flat-filled with the stroke colour 00534 StrokeColourAttribute *pStrokeColour = (StrokeColourAttribute *) pRender->GetCurrentAttribute(ATTR_STROKECOLOUR); 00535 if (pStrokeColour != NULL) 00536 pRender->SetFillColour(pStrokeColour->Colour); 00537 00538 // Fill the holes 00539 pRender->SetWindingRule(NonZeroWinding); 00540 00541 Path *pOutput = CreateVarWidthStroke(pPath, pRender, LineWidth); 00542 if (pOutput != NULL) 00543 { 00544 pRender->DrawPath(pOutput, NULL, ShapePath); 00545 delete pOutput; 00546 pOutput = NULL; 00547 } 00548 } 00549 00550 pRender->RestoreContext(); 00551 00552 // Delete the kernel bitmap. This auto-deletes the OIL bitmap for us 00553 delete pMask; 00554 } 00555 #endif 00556 }
|
|
Main Airbrush rendering loop.
Definition at line 746 of file ppairbsh.cpp. 00749 { 00750 PORTNOTETRACE("other","PathProcessorStrokeAirbrush::RenderAirBrush - do nothing"); 00751 #ifndef EXCLUDE_FROM_XARALX 00752 if(pPath == NULL || pRegion == NULL || NumSteps <= 0) 00753 { 00754 ERROR3("PathProcessorStrokeAirbrush::RenderAirBrush given dodgy params"); 00755 return FALSE; 00756 } 00757 00758 // Fill the holes 00759 pRegion->SetWindingRule(NonZeroWinding); 00760 00761 // Precalculate the trapezoid structure for stroking with 00762 TrapsList *pTrapezoids = PrepareTrapsForStroke(pPath, pDestRegion, LineWidth); 00763 if (pTrapezoids == NULL) 00764 return FALSE; 00765 00766 INT32 LastIntensity = 255; 00767 00768 // Use the previously obtained number of steps for the graduation 00769 for(INT32 i = NumSteps; i > 0; i--) 00770 { 00771 INT32 Intensity = 0; 00772 00773 // What intensity should we use ? 00774 if(pvValueFunction == NULL) 00775 { 00776 // A linear ramp 00777 Intensity = (255 * i) / NumSteps; 00778 } 00779 else 00780 { 00781 // Use the value function 00782 double Position = (double)i / (double)NumSteps; 00783 Intensity = (INT32)((1.0 - pvValueFunction->GetValue(Position)) * 255.0); 00784 } 00785 00786 // Bit dodgy for 1st stroke, but then it shouldn't be the same as the last 00787 if(LastIntensity != Intensity) 00788 { 00789 LastIntensity = Intensity; 00790 00791 if(Intensity != 255) 00792 { 00793 // --- Create the stroke outline by calling our helper function 00794 INT32 ThisWidth = (LineWidth * i) / NumSteps; 00795 00796 Path *pOutput = CreateVarWidthStroke(pPath, pDestRegion, ThisWidth, pTrapezoids); 00797 if(pOutput != NULL) 00798 { 00799 ColourFillAttribute *pFillAttr = NULL; 00800 FillMappingAttribute *pMapAttr = NULL; 00801 00802 if(pDestRegion != NULL) 00803 { 00804 // Obtain the object's transparent fill geometry 00805 TranspFillAttribute *pTransAttr = (TranspFillAttribute *) pDestRegion->GetCurrentAttribute(ATTR_TRANSPFILLGEOMETRY); 00806 if (pTransAttr == NULL) 00807 { 00808 // There is no transparency on this object - just use a flat transparency 00809 pFillAttr = new FlatFillAttribute; 00810 if (pFillAttr) 00811 pFillAttr->SetStartColour(&DocColour(Intensity, Intensity, Intensity)); 00812 } 00813 else 00814 { 00815 // Get a non-transparent version of the fill geometry 00816 pFillAttr = pTransAttr->MakeSimilarNonTranspFillGeometry(1.0 - ((double)(Intensity) / 255.0)); 00817 00818 // Convert a fill mapping 00819 TranspFillMappingAttribute *pTransMapAttr = (TranspFillMappingAttribute *) pDestRegion->GetCurrentAttribute(ATTR_TRANSPFILLMAPPING); 00820 if(pTransMapAttr != NULL) 00821 pMapAttr = pTransMapAttr->MakeSimilarNonTranspFillMapping(); 00822 } 00823 } 00824 00825 // Setup region and draw path into it 00826 if(pFillAttr != NULL) 00827 { 00828 pRegion->SetFillGeometry(pFillAttr, TRUE); 00829 00830 if(pMapAttr != NULL) 00831 pRegion->SetFillMapping(pMapAttr, TRUE); 00832 } 00833 else 00834 pRegion->SetFillColour(DocColour(Intensity, Intensity, Intensity)); 00835 00836 pRegion->DrawPath(pOutput, NULL, ShapePath); 00837 delete pOutput; 00838 } 00839 } 00840 } 00841 } 00842 00843 delete pTrapezoids; 00844 00845 return TRUE; 00846 #else 00847 return FALSE; 00848 #endif 00849 }
|
|
Sets the intensity function which will be used when rendering this airbrush. The function controls the intensity (opacity) of the airbrush at Position values where Position 0.0 represents the airbrush centreline, and 1.0 represents the maximum width.
Definition at line 901 of file ppairbsh.cpp. 00902 { 00903 if (pIntensityFunction != NULL) 00904 delete pIntensityFunction; 00905 00906 pIntensityFunction = pFunc; 00907 }
|
|
Called by the RenderRegion to determine if this PathProcessorStrokeAirbrush affects the "fill" and "stroke" portions of the path separately. (Generally speaking, only fill/stroke providers will cause these two different "bits" of a path to be rendered separately). This call is made BEFORE this Processor's ProcessPath function will be called.
Notes: Base class implementation returns FALSE. Derived Stroke and Fill processors (such as this one) override this method to return TRUE. Reimplemented from PathProcessorStroke. Definition at line 173 of file ppairbsh.cpp. 00174 { 00175 return(FALSE); 00176 }
|
|
Reimplemented from PathProcessorStroke. Definition at line 134 of file ppairbsh.h. |
|
Definition at line 178 of file ppairbsh.h. |