void Ctrl::GatherTransparentAreas(Vector<Rect>& area, SystemDraw& w, Rect r, const Rect& clip) { GuiLock __; LTIMING("GatherTransparentAreas"); Point off = r.TopLeft(); Point viewpos = off + GetView().TopLeft(); r.Inflate(overpaint); Rect notr = GetVoidRect(); if(notr.IsEmpty()) notr = GetOpaqueRect(); notr += viewpos; if(!IsShown() || r.IsEmpty() || !clip.Intersects(r) || !w.IsPainting(r)) return; if(notr.IsEmpty()) CombineArea(area, r & clip); else { if(notr != r) { CombineArea(area, clip & Rect(r.left, r.top, notr.left, r.bottom)); CombineArea(area, clip & Rect(notr.right, r.top, r.right, r.bottom)); CombineArea(area, clip & Rect(notr.left, r.top, notr.right, notr.top)); CombineArea(area, clip & Rect(notr.left, notr.bottom, notr.right, r.bottom)); } for(Ctrl *q = firstchild; q; q = q->next) { Point qoff = q->InView() ? viewpos : off; Rect qr = q->GetRect() + qoff; if(clip.Intersects(qr)) q->GatherTransparentAreas(area, w, qr, clip); } } }
void DisplayPopup::Sync() { if(display && ctrl && !ctrl->IsDragAndDropTarget() && !IsDragAndDropTarget()) { Ctrl *top = ctrl->GetTopCtrl(); if(top && top->HasFocusDeep()) { Size sz = display->GetStdSize(value); if(sz.cx + 2 * margin > item.GetWidth() || sz.cy > item.GetHeight()) { slim = item + ctrl->GetScreenView().TopLeft(); if(slim.Contains(GetMousePos())) { // Rect wa = GetWorkArea(); Rect r = item; r.right = max(r.right, r.left + sz.cx + 2 * margin); r.bottom = max(r.bottom, r.top + sz.cy); r.Inflate(1, 1); r.Offset(ctrl->GetScreenView().TopLeft()); SetRect(r); if(!IsOpen()) Ctrl::PopUp(ctrl, true, false, false); Refresh(); return; } } } } if(IsOpen()) Close(); }
void DrawTargetTiled::StrokeRect(const Rect& aRect, const Pattern& aPattern, const StrokeOptions &aStrokeOptions, const DrawOptions& aDrawOptions) { Rect deviceRect = mTransform.TransformBounds(aRect); Margin strokeMargin = MaxStrokeExtents(aStrokeOptions, mTransform); Rect outerRect = deviceRect; outerRect.Inflate(strokeMargin); Rect innerRect; if (mTransform.IsRectilinear()) { // If rects are mapped to rects, we can compute the inner rect // of the stroked rect. innerRect = deviceRect; innerRect.Deflate(strokeMargin); } for (size_t i = 0; i < mTiles.size(); i++) { if (mTiles[i].mClippedOut) { continue; } Rect tileRect(mTiles[i].mTileOrigin.x, mTiles[i].mTileOrigin.y, mTiles[i].mDrawTarget->GetSize().width, mTiles[i].mDrawTarget->GetSize().height); if (outerRect.Intersects(tileRect) && !innerRect.Contains(tileRect)) { mTiles[i].mDrawTarget->StrokeRect(aRect, aPattern, aStrokeOptions, aDrawOptions); } } }
// The logic for this comes from _cairo_stroke_style_max_distance_from_path static Rect PathExtentsToMaxStrokeExtents(const StrokeOptions &aStrokeOptions, const Rect &aRect, const Matrix &aTransform) { double styleExpansionFactor = 0.5f; if (aStrokeOptions.mLineCap == CapStyle::SQUARE) { styleExpansionFactor = M_SQRT1_2; } if (aStrokeOptions.mLineJoin == JoinStyle::MITER && styleExpansionFactor < M_SQRT2 * aStrokeOptions.mMiterLimit) { styleExpansionFactor = M_SQRT2 * aStrokeOptions.mMiterLimit; } styleExpansionFactor *= aStrokeOptions.mLineWidth; double dx = styleExpansionFactor * hypot(aTransform._11, aTransform._21); double dy = styleExpansionFactor * hypot(aTransform._22, aTransform._12); Rect result = aRect; result.Inflate(dx, dy); return result; }
// we paint the background in Painter() because I don't // want to add an artificial Control window just to cover // the whole HWND and paint the background. void Painter::PaintBackground(Graphics *g, Rect r) { // TODO: don't quite get why I need to expand the rectangle, but // sometimes there's a seemingly 1 pixel artifact on the left and // at the top if I don't do this r.Inflate(1,1); ColorData *bgColor = wnd->cachedStyle->bgColor; Brush *br = BrushFromColorData(bgColor, r); g->FillRectangle(br, r); }
void DrawTargetTiled::StrokeLine(const Point& aStart, const Point& aEnd, const Pattern& aPattern, const StrokeOptions &aStrokeOptions, const DrawOptions& aDrawOptions) { Rect lineBounds = Rect(aStart, Size()).UnionEdges(Rect(aEnd, Size())); Rect deviceRect = mTransform.TransformBounds(lineBounds); deviceRect.Inflate(MaxStrokeExtents(aStrokeOptions, mTransform)); for (size_t i = 0; i < mTiles.size(); i++) { if (!mTiles[i].mClippedOut && deviceRect.Intersects(Rect(mTiles[i].mTileOrigin.x, mTiles[i].mTileOrigin.y, mTiles[i].mDrawTarget->GetSize().width, mTiles[i].mDrawTarget->GetSize().height))) { mTiles[i].mDrawTarget->StrokeLine(aStart, aEnd, aPattern, aStrokeOptions, aDrawOptions); } } }
void DrawTargetTiled::Stroke(const Path* aPath, const Pattern& aPattern, const StrokeOptions& aStrokeOptions, const DrawOptions& aDrawOptions) { // Approximate the stroke extents, since Path::GetStrokeExtents can be slow Rect deviceRect = aPath->GetBounds(mTransform); deviceRect.Inflate(MaxStrokeExtents(aStrokeOptions, mTransform)); for (size_t i = 0; i < mTiles.size(); i++) { if (!mTiles[i].mClippedOut && deviceRect.Intersects(Rect(mTiles[i].mTileOrigin.x, mTiles[i].mTileOrigin.y, mTiles[i].mDrawTarget->GetSize().width, mTiles[i].mDrawTarget->GetSize().height))) { mTiles[i].mDrawTarget->Stroke(aPath, aPattern, aStrokeOptions, aDrawOptions); } } }
/*---------------------------------------------------------------------------------------------- Draw an individualbutton cell ----------------------------------------------------------------------------------------------*/ void IconComboPopup::DrawCell(HDC hdc, int ival, bool fHot, bool fOld) { Rect rc; GetCellRect(ival, rc); COLORREF clrBackBtn; switch (((uint)fHot << 1) | (uint)fOld) { case 1: // old // REVIEW (JeffG) ShonK: This is not the right color. There must be some inbetween shade // of gray that is darker then COLOR_3DHIGHLIGHT clrBackBtn = ::GetSysColor(COLOR_3DLIGHT); if (clrBackBtn == ::GetSysColor(COLOR_3DFACE)) clrBackBtn = ::GetSysColor(COLOR_3DHIGHLIGHT); AfGfx::FillSolidRect(hdc, rc, clrBackBtn, false); ::DrawEdge(hdc, &rc, EDGE_ETCHED, BF_RECT); break; case 2: // hot clrBackBtn = ::GetSysColor(COLOR_3DFACE); AfGfx::FillSolidRect(hdc, rc, clrBackBtn); ::DrawEdge(hdc, &rc, m_fMouseDown ? EDGE_SUNKEN : EDGE_RAISED, BF_RECT); break; case 3: // hot and old clrBackBtn = ::GetSysColor(COLOR_3DFACE); AfGfx::FillSolidRect(hdc, rc, clrBackBtn); ::DrawEdge(hdc, &rc, EDGE_ETCHED, BF_RECT); break; default: // neither clrBackBtn = ::GetSysColor(COLOR_3DFACE); AfGfx::FillSolidRect(hdc, rc, clrBackBtn); break; } rc.Inflate(-m_dzsBorder - 1, -m_dzsBorder - 1); ::ImageList_Draw(m_himl, ival, hdc, rc.left, rc.top, ILD_TRANSPARENT); }
static bool GetInsetBoxShadowRects(const Margin& aBlurMargin, const Margin& aInnerMargin, const Rect& aShadowClipRect, const Rect& aDestinationRect, Rect& aOutWhitespaceRect, Rect& aOutOuterRect) { // We always copy (2 * blur radius) + corner radius worth of data to the destination rect // This covers the blend of the path + the actual blur // Need +1 so that we copy the edges correctly as we'll copy // over the min box shadow corners then the +1 for the edges between // Note, the (x,y) coordinates are from the blur margin // since the frame outside the whitespace rect is 1 blur radius extra space. Rect insideWhiteSpace(aBlurMargin.left, aBlurMargin.top, aInnerMargin.LeftRight() + 1, aInnerMargin.TopBottom() + 1); // If the inner white space rect is larger than the shadow clip rect // our approach does not work as we'll just copy one corner // and cover the destination. In those cases, fallback to the destination rect bool useDestRect = (aShadowClipRect.width <= aInnerMargin.LeftRight()) || (aShadowClipRect.height <= aInnerMargin.TopBottom()); if (useDestRect) { aOutWhitespaceRect = aShadowClipRect; aOutOuterRect = aDestinationRect; } else { aOutWhitespaceRect = insideWhiteSpace; aOutOuterRect = aOutWhitespaceRect; aOutOuterRect.Inflate(aBlurMargin); } return useDestRect; }
void gfxAlphaBoxBlur::BlurInsetBox(gfxContext* aDestinationCtx, const Rect& aDestinationRect, const Rect& aShadowClipRect, const IntSize& aBlurRadius, const Color& aShadowColor, const RectCornerRadii* aInnerClipRadii, const Rect& aSkipRect, const Point& aShadowOffset) { if ((aBlurRadius.width == 0 && aBlurRadius.height == 0) || aShadowClipRect.IsEmpty()) { FillDestinationPath(aDestinationCtx, aDestinationRect, aShadowClipRect, aShadowColor, aInnerClipRadii); return; } DrawTarget* destDrawTarget = aDestinationCtx->GetDrawTarget(); Margin innerMargin; Margin blurMargin; GetBlurMargins(aInnerClipRadii, aBlurRadius, blurMargin, innerMargin); Rect whitespaceRect; Rect outerRect; bool useDestRect = GetInsetBoxShadowRects(blurMargin, innerMargin, aShadowClipRect, aDestinationRect, whitespaceRect, outerRect); // Check that the inset margin between the outer and whitespace rects is symmetric, // and that all corner radii are the same, in which case the blur can be mirrored. Margin checkMargin = outerRect - whitespaceRect; bool mirrorCorners = checkMargin.left == checkMargin.right && checkMargin.top == checkMargin.bottom && (!aInnerClipRadii || aInnerClipRadii->AreRadiiSame()); RefPtr<SourceSurface> minBlur = GetInsetBlur(outerRect, whitespaceRect, useDestRect, aShadowColor, aBlurRadius, aInnerClipRadii, destDrawTarget, mirrorCorners); if (!minBlur) { return; } if (useDestRect) { Rect destBlur = aDestinationRect; destBlur.Inflate(blurMargin); if (mirrorCorners) { DrawMirroredBoxShadow(destDrawTarget, minBlur.get(), destBlur); } else { Rect srcBlur(Point(0, 0), Size(minBlur->GetSize())); MOZ_ASSERT(srcBlur.Size() == destBlur.Size()); destDrawTarget->DrawSurface(minBlur, destBlur, srcBlur); } } else { Rect srcOuter(outerRect); Rect srcInner(srcOuter); srcInner.Deflate(blurMargin); // The outer color fill srcInner.Deflate(innerMargin); // The inner whitespace // The shadow clip rect already takes into account the spread radius Rect outerFillRect(aShadowClipRect); outerFillRect.Inflate(blurMargin); FillDestinationPath(aDestinationCtx, aDestinationRect, outerFillRect, aShadowColor); // Inflate once for the frame around the whitespace Rect destRect(aShadowClipRect); destRect.Inflate(blurMargin); // Deflate for the blurred in white space Rect destInnerRect(aShadowClipRect); destInnerRect.Deflate(innerMargin); if (mirrorCorners) { DrawMirroredMinBoxShadow(destDrawTarget, minBlur, destRect, destInnerRect, srcOuter, srcInner, aSkipRect); } else { DrawMinBoxShadow(destDrawTarget, minBlur, destRect, destInnerRect, srcOuter, srcInner, aSkipRect); } } }
void ListControl::GetSubRects(Rect *prcInterior, Rect *prcUpArrow, Rect *prcDownArrow, Rect *prcScrollPosition) { Rect rc = m_rc; if (m_wf & kfLstcBorder) { rc.Inflate(-gcxyBorder * 2, -gcxyBorder * 2); } if (prcScrollPosition != NULL) { prcScrollPosition->SetEmpty(); } if (prcUpArrow != NULL) { prcUpArrow->SetEmpty(); } if (prcDownArrow != NULL) { prcDownArrow->SetEmpty(); } // If all the elements can be displayed without scrolling than the interior // area can fill the whole ListControl Size sizArrow; s_ptbmScrollUpUp->GetSize(&sizArrow); if (rc.Height() / m_cyItem >= m_cli) { if (m_wf & kfLstcKeepInteriorPositioning) { *prcInterior = rc; prcInterior->Inflate(0, -sizArrow.cy); } else { *prcInterior = rc; } return; } if (m_wf & kfLstcScrollPosition) { // Maintain interior positioning (with arrows) so that form // layout doesn't change if this bit is on. prcInterior->Set(rc.left, rc.top + sizArrow.cy, rc.right - gcxyBorder * 3, rc.bottom - sizArrow.cy); if (prcScrollPosition != NULL) { prcScrollPosition->left = rc.right - gcxyBorder * 2; prcScrollPosition->top = prcInterior->top; prcScrollPosition->right = rc.right; prcScrollPosition->bottom = prcInterior->bottom - prcInterior->Height() % m_cyItem; } } else { int xArrow = rc.left + ((rc.Width() - sizArrow.cx) / 2); if (prcUpArrow != NULL) { prcUpArrow->Set(xArrow - sizArrow.cx, rc.top, xArrow + sizArrow.cx * 2, rc.top + sizArrow.cy); } if (prcDownArrow != NULL) { prcDownArrow->Set(xArrow - sizArrow.cx, rc.bottom - sizArrow.cy, xArrow + sizArrow.cx * 2, rc.bottom); } if (prcInterior != NULL) { prcInterior->Set(rc.left, rc.top + sizArrow.cy, rc.right, rc.bottom - sizArrow.cy); } } }