RenderDemoDlg::RenderDemoDlg() : DialogOp(RenderDemoDlg::IDD, RenderDemoDlg::Mode) { // Set the 2 colours that we can toggle between First = DocColour(255,0,250); Second = DocColour(0,255,255); ShowFirst = TRUE; }
BOOL CDRFilter::AddAttributesToArrowheadPath(NodePath *P, DocColour *Col, INT32 LineWidth, LineCapType Cap, JointType Join) { if(P->InkPath.IsFilled) { // it's a filled path, so it need to be filled with the colour and have no line // colour SetPathFilled(TRUE); if(!SetLineColour(DocColour(COLOUR_TRANS)) || !SetFillColour(*Col)) return FALSE; } else { // it's not a filled colour, so don't fill it and stroke it with the line width and colour if(!SetLineColour(*Col) || !SetLineWidth(LineWidth) || !SetLineCap(Cap) || !SetJoinType(Join)) return FALSE; } // apply the attributes to the object // If not filled, then set the ignore bit on the fill attribute. // if (P->InkPath.IsFilled == FALSE) // CurrentAttrs[ATTR_FILLGEOMETRY].Ignore = TRUE; // else CurrentAttrs[ATTR_FILLGEOMETRY].Ignore = FALSE; // Add attributes to the path, if they are different from the default... BOOL Result = AttributeManager::ApplyBasedOnDefaults(P, CurrentAttrs); // DeleteCurrentAttrs(); // SetUpCurrentAttrs(); // Enable the fill attribute again CurrentAttrs[ATTR_FILLGEOMETRY].Ignore = FALSE; return Result; }
void SGDisplayDATATYPE::HandleRedraw(SGRedrawInfo *RedrawInfo, SGMiscInfo *MiscInfo) { // First, inform the system that we are about to start rendering this item StartRendering(RedrawInfo, MiscInfo); DocRect MyRect(FormatRect); // Get my redraw position from the cached FormatRect RenderRegion *Renderer = RedrawInfo->Renderer; INT32 OnePixel = (INT32) DevicePixels(MiscInfo, 1); INT32 TwoPixels = (INT32) DevicePixels(MiscInfo, 2); Renderer->SetLineWidth(0); Renderer->SetLineColour(RedrawInfo->Transparent); // First, render the icon at the left end of our rectangle DocRect IconRect(MyRect); IconRect.hi.x = IconRect.lo.x + IconRect.Height(); // Make it a square MyRect.lo.x = IconRect.hi.x + TwoPixels; // And exclude it from 'MyRect' // Redraw the icon GridLockRect(MiscInfo, &IconRect); // Ensure it maps exactly to specific pixels IconRect.Inflate(-OnePixel, -OnePixel); // Leave a bit of space around the edge Renderer->SetFillColour(DocColour(COLOUR_RED)); Renderer->DrawRect(&IconRect); GridLockRect(MiscInfo, &MyRect); // Ensure the new 'MyRect' is pixel-grid-aligned // Set up the colours for rendering our text, and fill the background if selected if (Flags.Selected) { // Fill the entire background with the 'selected' colour, so we don't // get gaps between bits of text or uneven rectangles in multiple selections Renderer->SetFillColour(RedrawInfo->SelBackground); Renderer->DrawRect(&MyRect); Renderer->SetFixedSystemTextColours(&RedrawInfo->SelForeground, &RedrawInfo->SelBackground); } else Renderer->SetFixedSystemTextColours(&RedrawInfo->Foreground, &RedrawInfo->Background); MyRect.lo.x += SG_GapBeforeText; // Leave a small gap before text begins // And render the text String_256 MyText; GetNameText(&MyText); Renderer->DrawFixedSystemText(&MyText, MyRect); // Finally, inform the system that we have completed rendering this item StopRendering(RedrawInfo, MiscInfo); }
BOOL LoadBrushDirect::OnLoadDocument(Document* pDoc) { ERROR3IF(pDoc==NULL,"No doc pointer during PrintMarksMan::ConvertAllDocColours!"); Node *CurNode = Node::DocFindFirstDepthFirst(pDoc); Node *NextNode; while (CurNode !=NULL) { // We may be about to chop this node out of the tree, so get the next node now NextNode = CurNode->DocFindNextDepthFirst(); // Use to scan the colour fields of the attribute. UINT32 Context = 0; DocColour *pColour; if (CurNode->IsAnAttribute()) { NodeAttribute *pNodeAttr = (NodeAttribute *) CurNode; // Get the next colour field from the attribute pColour = pNodeAttr->EnumerateColourFields(Context++); while (pColour != NULL) { // For each colour field, make sure the colour is a local DocColour so that // the sub-tree is entirely stand-alone if (pColour->FindParentIndexedColour() != NULL) { ColourGeneric ColDef; ColourContext *cc = ColourManager::GetColourContext(pColour->GetColourModel()); ERROR3IF(cc == NULL, "Can't find colour context?!"); // Get the IndexedColour definition as a standalone colour definition cc->ConvertColour(pColour->FindParentIndexedColour(), &ColDef); // Make the DocColour into a simple standalone "lookalike" of the parent colour *pColour = DocColour(pColour->GetColourModel(), &ColDef); } pColour = pNodeAttr->EnumerateColourFields(Context++); } } CurNode = NextNode; } // All is well we hope. return TRUE; }
void ColourPlate::SetPlateInfo(ColourContext *Parent, ColourPlateType TheType, BOOL MonochromePlate, BOOL NegatePlate) { ERROR3IF(TheType == COLOURPLATE_SPOT, "Spot plates must be constructed with the Spot Colour constructor"); InitObject(TheType); Monochrome = MonochromePlate; Negate = NegatePlate; Spot = DocColour(COLOUR_BLACK); if (Parent != NULL) Parent->ColourPlateHasChanged(); }
void ColourDragInformation::InitObject(void) { // Init member variables TheColour = DocColour(COLOUR_TRANS); pParentDoc = NULL; ColourName = TEXT(""); LibColIsSpot = FALSE; // Set up a few things about this drag DoesSolidDrag = TRUE; // offset of colour swatch from the pointer SolidDragOffset.x = -14; SolidDragOffset.y = 4; // size of the solid drag redraw SolidDragSize.x = CellSize; SolidDragSize.y = CellSize; }
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); } }
BOOL BitmapExportDocument::Init(KernelBitmap* pBitmap, const DocRect& RectToExport) { // Don't attach any CCamDoc. if (!Document::Init(0)) return(FALSE); Node *pSpread = FindFirstSpread(); ERROR3IF(pSpread == NULL, "No Spread in document!"); Node *pLayer = pSpread->FindFirstChild(); ERROR3IF(pLayer == NULL, "No Spread-child in document!"); // Store away the rectangle ExportRect = RectToExport; // Now scan the children of the first spread until we find a layer, or run out of nodes while (pLayer != NULL && !pLayer->IsLayer()) pLayer = pLayer->FindNext(); if (pLayer == NULL) // No Layer, so we'd better add one for ourselves { String_256 LayerID = String_256(_R(IDS_K_CLIPINT_LAYERNAME)); pLayer = new Layer(pSpread, LASTCHILD, LayerID); if (pLayer == NULL) return(InitFailed()); } // Create a new NodeRect NodeRect* pRectNode = new NodeRect(pLayer, FIRSTCHILD); // Failed so cleanup and exit if (pRectNode == NULL) return(InitFailed()); // Initilaise the node if (!pRectNode->SetUpPath(6,6)) return(InitFailed()); // Create the rectangle pRectNode->CreateShape(ExportRect); // Give the rectangle a line colour #if 0 // This memory leaks a StrokeColourAttribute StrokeColourAttribute* pAttrValue = new StrokeColourAttribute(DocColour(COLOUR_TRANS)); if (pAttrValue == NULL) return(InitFailed()); NodeAttribute* pAttr = pAttrValue->MakeNode(); if (pAttr == NULL) return(InitFailed()); // Attach the attribute to the rectangle pAttr->AttachNode(pRectNode, FIRSTCHILD); #else // Do what ApplyDefaultBitmapAttrs does Node* pLineColAttr = new AttrStrokeColour(); if (pLineColAttr == NULL) return(InitFailed()); DocColour none(COLOUR_NONE); ((AttrFillGeometry*)pLineColAttr)->SetStartColour(&none); pLineColAttr->AttachNode(pRectNode, FIRSTCHILD); #endif // Create a NodeBitmap (don't attach it to the tree straight away 'cos we // have to put the attributes on it first) pBitmapNode = new NodeBitmap(); if (pBitmapNode == NULL) return(InitFailed()); if (!pBitmapNode->SetUpPath(6,6)) return(InitFailed()); pBitmapNode->CreateShape(ExportRect); if (!SetBitmap(pBitmap)) return(InitFailed()); // Set the bitmap's attributes // This must be done before the NodeBitmap is inserted into the tree if (!pBitmapNode->ApplyDefaultBitmapAttrs(NULL)) return(InitFailed()); // Attach it to the tree as the next sibling of the rectangle pBitmapNode->AttachNode(pRectNode, NEXT); // Success... return(TRUE); }
BOOL CDRFilter::SetLineAttr(cdrfOffsetHeader *Object) { if(Version == CDRVERSION_3) { return SetLineAttr3(Object); } // find the reference... DWORD *pReference = (DWORD *)FindDataInObject(Object, cdrfOBJOFFSETTYPE_LINE); // if the pointer to the reference is zero, then the reference is probably // within some random style definition if(pReference == 0) { // OK, try and find a style number within the style reference WORD *pStyleReference = (WORD *)FindDataInObject(Object, cdrfOBJOFFSETTYPE_STYLE); if(pStyleReference != 0) { // OK, see if we can find a the style... cdrfStyle *pStyle; INT32 StyleSize; if((pStyle = (cdrfStyle *)Styles.Find(*pStyleReference, &StyleSize)) != 0) { // OK, got a style... now find a fill reference within it pReference = (DWORD *)FindDataInObject(&pStyle->Header, cdrfSTYLEOFFSETTYPE_OUTLINE); } } } cdrfOutline *Out; INT32 OutSize; if(pReference == 0 || (Out = (cdrfOutline *)Outlines.Find(*pReference, &OutSize)) == 0 || OutSize < sizeof(cdrfOutline)) { // if no outline data, or outline definitions couldn't be found, or outline // definition is too small, set up the default line attributes if(!SetLineWidth(cdrfOUTLINE_DEFAULT_WIDTH)) return FALSE; PColourCMYK cmyk; cmyk.Cyan = cmyk.Magenta = cmyk.Yellow = 0; cmyk.Key = 255; DocColour Col; Col.SetCMYKValue(&cmyk); if(!SetLineColour(Col)) return FALSE; return TRUE; } // check that this thingy should have an outline if((CDRDATA_WORD(Out->Flags) & cdrfOUTLINEFLAGS_NOOUTLINE) != 0) { if (!SetLineColour(DocColour(COLOUR_TRANS))) return FALSE; return TRUE; } // convert the line colour DocColour Col; ConvertColour(&Out->Colour, &Col); // find the line width INT32 LineWidth = CDRDATA_WORD(Out->LineThickness) * CDRCOORDS_TO_MILLIPOINTS; if(LineWidth > MAX_LINE_WIDTH) LineWidth = MAX_LINE_WIDTH; // find the join type JointType JType; switch(CDRDATA_WORD(Out->JoinStyle)) { case cdrfJOINSTYLE_SQUARE: JType = MitreJoin; break; case cdrfJOINSTYLE_ROUNDED: JType = RoundJoin; break; default: case cdrfJOINSTYLE_BEVEL: JType = BevelledJoin; break; } // set the cap style LineCapType CType; switch(CDRDATA_WORD(Out->EndStyle)) { case cdrfENDSTYLE_BUTT: CType = LineCapButt; break; case cdrfENDSTYLE_ROUNDED: CType = LineCapRound; break; default: case cdrfENDSTYLE_SQUARE: CType = LineCapSquare; break; } // set the dash pattern DashRec Dash; DashElement DashArray[cdrfMAX_DASH_ELEMENTS]; if(CDRDATA_WORD(Out->NDashSegments) > 0 && (CDRDATA_WORD(Out->Flags) & cdrfOUTLINEFLAGS_NODASH) == 0) { // set a dash pattern INT32 NSeg = CDRDATA_WORD(Out->NDashSegments); if(NSeg > cdrfMAX_DASH_ELEMENTS) NSeg = cdrfMAX_DASH_ELEMENTS; INT32 l; for(l = 0; l < NSeg; l++) { DashArray[l] = CDRDATA_WORD(Out->DashSegments[l]) * LineWidth; } Dash.Elements = NSeg; Dash.DashStart = 0; Dash.ElementData = DashArray; Dash.LineWidth = LineWidth; Dash.ScaleWithLineWidth = TRUE; Dash.DashID = -1; } else { // no dash pattern Dash = SD_SOLID; } // set the attributes if(!SetLineWidth(LineWidth) || !SetLineColour(Col) || !SetJoinType(JType) || !SetLineCap(CType) || !SetDashPattern(Dash)) return FALSE; // check for arrowheads if(CDRDATA_DWORD(Out->StartArrowReference) != 0 || CDRDATA_DWORD(Out->EndArrowReference) != 0) { // apply the attributes to the object // If not filled, then set the ignore bit on the fill attribute. if (ObjFilled == FALSE) CurrentAttrs[ATTR_FILLGEOMETRY].Ignore = TRUE; // Add attributes to the path, if they are different from the default... AttributeManager::ApplyBasedOnDefaults(pMadeNode, CurrentAttrs); // DeleteCurrentAttrs(); // SetUpCurrentAttrs(); // Enable the fill attribute again CurrentAttrs[ATTR_FILLGEOMETRY].Ignore = FALSE; // ensure that the attributes won't be applied again AttrsAlreadyApplied = TRUE; // apply arrow heads to the path AddArrowheadsToPath(CDRDATA_DWORD(Out->StartArrowReference), CDRDATA_DWORD(Out->EndArrowReference), &Col, LineWidth, CType, JType); } return TRUE; }
BOOL CDRFilter::SetLineAttr3(cdrfOffsetHeader *Object) { cdrfOutlineV3 *Out = (cdrfOutlineV3 *)FindDataInObject(Object, cdrfOBJOFFSETTYPE_LINE); if(Out == 0) { // if no outline data, or outline definitions couldn't be found, or outline // definition is too small, set up the default line attributes if(!SetLineWidth(cdrfOUTLINE_DEFAULT_WIDTH)) return FALSE; PColourCMYK cmyk; cmyk.Cyan = cmyk.Magenta = cmyk.Yellow = 0; cmyk.Key = 255; DocColour Col; Col.SetCMYKValue(&cmyk); if(!SetLineColour(Col)) return FALSE; return TRUE; } // check that this thingy should have an outline if((Out->Flags & cdrfOUTLINEFLAGSV3_STROKED) == 0) { if (!SetLineColour(DocColour(COLOUR_TRANS))) return FALSE; return TRUE; } // convert the line colour DocColour Col; ConvertColour((cdrfColour *)&Out->Colour, &Col); // find the line width INT32 LineWidth = CDRDATA_WORD(Out->LineThickness) * CDRCOORDS_TO_MILLIPOINTS; if(LineWidth > MAX_LINE_WIDTH) LineWidth = MAX_LINE_WIDTH; // find the join type JointType JType; switch(CDRDATA_WORD(Out->JoinStyle)) { case cdrfJOINSTYLE_SQUARE: JType = MitreJoin; break; case cdrfJOINSTYLE_ROUNDED: JType = RoundJoin; break; default: case cdrfJOINSTYLE_BEVEL: JType = BevelledJoin; break; } // set the cap style LineCapType CType; switch(Out->EndStyle) // byte { case cdrfENDSTYLE_BUTT: CType = LineCapButt; break; case cdrfENDSTYLE_ROUNDED: CType = LineCapRound; break; default: case cdrfENDSTYLE_SQUARE: CType = LineCapSquare; break; } // set the dash pattern /* DashRec Dash; DashElement DashArray[cdrfMAX_DASH_ELEMENTS]; if((ObjectFlagsV3 & cdrfOBJFLAGSV3_NODASH) == 0 && Out->NDashSegments > 0) // byte { // set a dash pattern INT32 NSeg = CDRDATA_WORD(Out->NDashSegments); if(NSeg > cdrfMAX_DASH_ELEMENTS) NSeg = cdrfMAX_DASH_ELEMENTS; INT32 l; for(l = 0; l < NSeg; l++) { DashArray[l] = Out->DashSegments[l] * LineWidth; // byte } Dash.Elements = NSeg; Dash.DashStart = 0; Dash.ElementData = DashArray; Dash.LineWidth = LineWidth; Dash.ScaleWithLineWidth = TRUE; Dash.DashID = -1; } else { // no dash pattern Dash = SD_SOLID; } */ // set the attributes if(!SetLineWidth(LineWidth) || !SetLineColour(Col) || !SetJoinType(JType) || !SetLineCap(CType)/* || !SetDashPattern(Dash)*/) return FALSE; // check for arrowheads if(CDRDATA_DWORD(Out->StartArrowReference) != 0 || CDRDATA_DWORD(Out->EndArrowReference) != 0) { // apply the attributes to the object // If not filled, then set the ignore bit on the fill attribute. if (ObjFilled == FALSE) CurrentAttrs[ATTR_FILLGEOMETRY].Ignore = TRUE; // Add attributes to the path, if they are different from the default... AttributeManager::ApplyBasedOnDefaults(pMadeNode, CurrentAttrs); // Enable the fill attribute again CurrentAttrs[ATTR_FILLGEOMETRY].Ignore = FALSE; // ensure that the attributes won't be applied again AttrsAlreadyApplied = TRUE; // apply arrow heads to the path AddArrowheadsToPath(CDRDATA_DWORD(Out->StartArrowReference), CDRDATA_DWORD(Out->EndArrowReference), &Col, LineWidth, CType, JType); } return TRUE; }
BOOL PathProcessorStrokeAirbrush::RenderAirBrush(Path *pPath, GRenderBitmap *pRegion, INT32 LineWidth, INT32 NumSteps, ValueFunction *pvValueFunction, RenderRegion *pDestRegion, PathShape ShapePath) { PORTNOTETRACE("other","PathProcessorStrokeAirbrush::RenderAirBrush - do nothing"); #ifndef EXCLUDE_FROM_XARALX if(pPath == NULL || pRegion == NULL || NumSteps <= 0) { ERROR3("PathProcessorStrokeAirbrush::RenderAirBrush given dodgy params"); return FALSE; } // Fill the holes pRegion->SetWindingRule(NonZeroWinding); // Precalculate the trapezoid structure for stroking with TrapsList *pTrapezoids = PrepareTrapsForStroke(pPath, pDestRegion, LineWidth); if (pTrapezoids == NULL) return FALSE; INT32 LastIntensity = 255; // Use the previously obtained number of steps for the graduation for(INT32 i = NumSteps; i > 0; i--) { INT32 Intensity = 0; // What intensity should we use ? if(pvValueFunction == NULL) { // A linear ramp Intensity = (255 * i) / NumSteps; } else { // Use the value function double Position = (double)i / (double)NumSteps; Intensity = (INT32)((1.0 - pvValueFunction->GetValue(Position)) * 255.0); } // Bit dodgy for 1st stroke, but then it shouldn't be the same as the last if(LastIntensity != Intensity) { LastIntensity = Intensity; if(Intensity != 255) { // --- Create the stroke outline by calling our helper function INT32 ThisWidth = (LineWidth * i) / NumSteps; Path *pOutput = CreateVarWidthStroke(pPath, pDestRegion, ThisWidth, pTrapezoids); if(pOutput != NULL) { ColourFillAttribute *pFillAttr = NULL; FillMappingAttribute *pMapAttr = NULL; if(pDestRegion != NULL) { // Obtain the object's transparent fill geometry TranspFillAttribute *pTransAttr = (TranspFillAttribute *) pDestRegion->GetCurrentAttribute(ATTR_TRANSPFILLGEOMETRY); if (pTransAttr == NULL) { // There is no transparency on this object - just use a flat transparency pFillAttr = new FlatFillAttribute; if (pFillAttr) pFillAttr->SetStartColour(&DocColour(Intensity, Intensity, Intensity)); } else { // Get a non-transparent version of the fill geometry pFillAttr = pTransAttr->MakeSimilarNonTranspFillGeometry(1.0 - ((double)(Intensity) / 255.0)); // Convert a fill mapping TranspFillMappingAttribute *pTransMapAttr = (TranspFillMappingAttribute *) pDestRegion->GetCurrentAttribute(ATTR_TRANSPFILLMAPPING); if(pTransMapAttr != NULL) pMapAttr = pTransMapAttr->MakeSimilarNonTranspFillMapping(); } } // Setup region and draw path into it if(pFillAttr != NULL) { pRegion->SetFillGeometry(pFillAttr, TRUE); if(pMapAttr != NULL) pRegion->SetFillMapping(pMapAttr, TRUE); } else pRegion->SetFillColour(DocColour(Intensity, Intensity, Intensity)); pRegion->DrawPath(pOutput, NULL, ShapePath); delete pOutput; } } } } delete pTrapezoids; return TRUE; #else return FALSE; #endif }
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 }
void ArrangeAlignment::RedrawDiagram(ReDrawInfoType* ExtraInfo) { // objects drawn in the render region must be relatively large in the given coord space // else Gavin's curve flattening results in visible straight lines // so every dimension is scaled by scale INT32 scale=1000; // make a render region DocRect VirtRendRect; VirtRendRect.lo.x=-1*scale; VirtRendRect.lo.y=-2*scale; VirtRendRect.hi.x=(DiagWidth +1)*scale; VirtRendRect.hi.y=(DiagHeight+2)*scale; RenderRegion* pRender=CreateGRenderRegion(&VirtRendRect,ExtraInfo); if (pRender!=NULL) { pRender->SaveContext(); // currently this must be set here before any colour tables calculated Quality AntiAliasQuality(Quality::QualityMax); QualityAttribute AntiAliasQualityAttr(AntiAliasQuality); pRender->SetQuality(&AntiAliasQualityAttr,FALSE); // Render the background rectangle DialogColourInfo RedrawColours; pRender->SetLineColour(RedrawColours.DialogBack()); pRender->SetFillColour(RedrawColours.DialogBack()); pRender->DrawRect(&VirtRendRect); // declared at this scope else RestoreContext() dies! RadialFillAttribute Fill; // set up some defaults used by all objects Fill.MakeElliptical(); Fill.Colour=DocColour(255,255,255); pRender->SetLineColour(BLACK); pRender->SetLineWidth(0); for (INT32 i=0; i<DiagRects; i++) { // reverse order in which objets are rendered (now filled!) INT32 j=DiagRects-1-i; // set fill colour of each object switch (j) { case 0: Fill.EndColour=DocColour(255,255,0); break; case 1: Fill.EndColour=DocColour(0,0,255); break; case 2: Fill.EndColour=DocColour(255,0,0); break; case 3: Fill.EndColour=DocColour(0,160,0); break; default: Fill.EndColour=DocColour(0,0,0); break; } // get bound rect of object to be drawn INT32 x=DiagRectX[Align.h][j].lo*scale; INT32 w=DiagRectX[Align.h][j].hi*scale-x; INT32 y=DiagRectY[Align.v][j].lo*scale; INT32 h=DiagRectY[Align.v][j].hi*scale-y; // create shape and fill geometries Path shape; shape.Initialise(16,8); shape.IsFilled=TRUE; shape.FindStartOfPath(); switch (j) { case 0: { // create a rectangle shape.InsertMoveTo(DocCoord(x,y)); shape.InsertLineTo(DocCoord(x,y+h)); shape.InsertLineTo(DocCoord(x+w,y+h)); shape.InsertLineTo(DocCoord(x+w,y)); shape.InsertLineTo(DocCoord(x,y)); // // create a radial fill // Fill.StartPoint=DocCoord(x+w*3/16,y+h*3/4); // Fill.EndPoint =DocCoord(x+w*3/8,y+h/2); // Fill.EndPoint2 =DocCoord(x+w*3/8,y+h); break; } case 1: { // create a pseudo ellipse shape.InsertMoveTo( DocCoord(x,y+h/2)); shape.InsertCurveTo(DocCoord(x,y+h*3/4), DocCoord(x+w/4,y+h), DocCoord(x+w/2,y+h)); shape.InsertCurveTo(DocCoord(x+w*3/4,y+h),DocCoord(x+w,y+h*3/4),DocCoord(x+w,y+h/2)); shape.InsertCurveTo(DocCoord(x+w,y+h/4), DocCoord(x+w*3/4,y), DocCoord(x+w/2,y)); shape.InsertCurveTo(DocCoord(x+w/4,y), DocCoord(x,y+h/4), DocCoord(x,y+h/2)); // // create a radial fill // Fill.StartPoint=DocCoord(x+w*3/8,y+h*5/8); // Fill.EndPoint =DocCoord(x+w*6/8,y+h/4); // Fill.EndPoint2 =DocCoord(x+w*6/8,y+h); break; } default: { // create a rounded rectangle shape.InsertMoveTo( DocCoord(x,y+h/2)); shape.InsertCurveTo(DocCoord(x,y+h), DocCoord(x,y+h), DocCoord(x+w/2,y+h)); shape.InsertCurveTo(DocCoord(x+w,y+h),DocCoord(x+w,y+h),DocCoord(x+w,y+h/2)); shape.InsertCurveTo(DocCoord(x+w,y), DocCoord(x+w,y), DocCoord(x+w/2,y)); shape.InsertCurveTo(DocCoord(x,y), DocCoord(x,y), DocCoord(x,y+h/2)); // // create a radial fill // Fill.StartPoint=DocCoord(x+w*3/16,y+h*3/4); // Fill.EndPoint =DocCoord(x+w*3/8,y+h/2); // Fill.EndPoint2 =DocCoord(x+w*3/8,y+h); break; } } // pRender->SetFillGeometry(&Fill,FALSE); pRender->SetFillColour(Fill.EndColour); pRender->DrawPath(&shape); } pRender->RestoreContext(); DestroyGRenderRegion(pRender); // also blt's to screen } }
void RenderDemoDlg::RenderControl(ReDrawInfoType* ExtraInfo) { // Go get a render region DocRect VirtualSize(-ExtraInfo->dx/2, -ExtraInfo->dy/2, ExtraInfo->dx/2, ExtraInfo->dy/2); RenderRegion* pRender = CreateGRenderRegion(&VirtualSize, ExtraInfo); if (pRender!=NULL) { DialogColourInfo RedrawColours; // Get a supplier for default dlg colours // Render stuff in here // Build a Linear fill attribute LinearFillAttribute MyGradFill; MyGradFill.Colour = DocColour(255, 255, 0); MyGradFill.EndColour = DocColour(0, 255, 255); MyGradFill.StartPoint = DocCoord(0, ExtraInfo->dy); MyGradFill.EndPoint = DocCoord(ExtraInfo->dx, 0); // Build a path Path InkPath; InkPath.Initialise(12,12); InkPath.FindStartOfPath(); // Get the coords used to build a shape INT32 dx = ExtraInfo->dx / 2; INT32 dy = ExtraInfo->dy / 2; INT32 Midx = ExtraInfo->dx / 4; INT32 Midy = ExtraInfo->dy / 4; // build a circle in the middle of the control InkPath.InsertMoveTo(DocCoord(Midx, dy)); InkPath.InsertCurveTo(DocCoord(Midx+Midx/2, dy), DocCoord(dx, Midy+Midy/2), DocCoord(dx, Midy)); InkPath.InsertCurveTo(DocCoord(dx, Midy-Midy/2), DocCoord(Midx+Midx/2, 0), DocCoord(Midx, 0)); InkPath.InsertCurveTo(DocCoord(Midx-Midx/2, 0), DocCoord(0, Midy-Midy/2), DocCoord(0, Midy)); InkPath.InsertCurveTo(DocCoord(0, Midy+Midy/2), DocCoord(Midx-Midx/2, dy), DocCoord(Midx, dy)); InkPath.IsFilled = TRUE; // A Grey colour [...hmmm, it's not a very grey grey any more... oragnge more like] DocColour Grey(255,200,0); // Render the attributes and the a rectangle pRender->SaveContext(); pRender->SetLineColour(Grey); // Draw a rectangle to fill in the background - Fill with Dialogue Background colour DocRect DrawMe(0, 0, ExtraInfo->dx, ExtraInfo->dy); pRender->SetFillColour(RedrawColours.DialogBack()); pRender->DrawRect(&VirtualSize); // Draw some shapes and stuff pRender->SetFillGeometry(&MyGradFill, FALSE); pRender->DrawPath(&InkPath); // Build a path Path TriPath; TriPath.Initialise(12,12); TriPath.FindStartOfPath(); // build a circle in the middle of the control TriPath.InsertMoveTo(VirtualSize.lo); TriPath.InsertLineTo(DocCoord(VirtualSize.hi.x, VirtualSize.lo.y)); TriPath.InsertLineTo(DocCoord(0, VirtualSize.hi.y)); TriPath.InsertLineTo(VirtualSize.lo); TriPath.IsFilled = TRUE; LinearFillAttribute MyTriFill; MyTriFill.Colour = ShowFirst ? First : Second; MyTriFill.EndColour = DocColour(0,0,0); MyTriFill.StartPoint = DocCoord(ExtraInfo->dx, 0); MyTriFill.EndPoint = DocCoord(0, ExtraInfo->dy); pRender->SetFillGeometry(&MyTriFill, FALSE); pRender->DrawPath(&TriPath); pRender->RestoreContext(); // Get rid of the render region DestroyGRenderRegion(pRender); } // and animate it! if (ShowFirst) { INT32 Red, Green, Blue; First.GetRGBValue(&Red, &Green, &Blue); if (Blue>0) { // Set the colour back again Blue -= 10; First.SetRGBValue(Red, Green, Blue); // redraw it InvalidateGadget(_R(IDC_REDRAW_ME)); } } else { // Set the colour back to how it was First.SetRGBValue(255, 0, 250); } }