void gfxRect::RoundOut() { gfxFloat x0 = NS_floor(X()); gfxFloat y0 = NS_floor(Y()); gfxFloat x1 = NS_ceil(XMost()); gfxFloat y1 = NS_ceil(YMost()); pos.x = x0; pos.y = y0; size.width = x1 - x0; size.height = y1 - y0; }
already_AddRefed<gfxContext> gfxCachedTempSurface::Get(gfxASurface::gfxContentType aContentType, const gfxRect& aRect, gfxASurface* aSimilarTo) { if (mSurface) { /* Verify the current buffer is valid for this purpose */ if (mSize.width < aRect.width || mSize.height < aRect.height || mSurface->GetContentType() != aContentType) { mSurface = nsnull; } else { NS_ASSERTION(mType == aSimilarTo->GetType(), "Unexpected surface type change"); } } PRBool cleared = PR_FALSE; if (!mSurface) { mSize = gfxIntSize(PRInt32(NS_ceil(aRect.width)), PRInt32(NS_ceil(aRect.height))); mSurface = aSimilarTo->CreateSimilarSurface(aContentType, mSize); if (!mSurface) return nsnull; cleared = PR_TRUE; #ifdef DEBUG mType = aSimilarTo->GetType(); #endif } mSurface->SetDeviceOffset(-aRect.TopLeft()); nsRefPtr<gfxContext> ctx = new gfxContext(mSurface); ctx->Rectangle(aRect); ctx->Clip(); if (!cleared && aContentType != gfxASurface::CONTENT_COLOR) { ctx->SetOperator(gfxContext::OPERATOR_CLEAR); ctx->Paint(); ctx->SetOperator(gfxContext::OPERATOR_OVER); } CachedSurfaceExpirationTracker::MarkSurfaceUsed(this); return ctx.forget(); }
HDC gfxWindowsNativeDrawing::BeginNativeDrawing() { if (mRenderState == RENDER_STATE_INIT) { nsRefPtr<gfxASurface> surf = mContext->CurrentSurface(&mDeviceOffset.x, &mDeviceOffset.y); if (!surf || surf->CairoStatus()) return nsnull; gfxMatrix m = mContext->CurrentMatrix(); if (!m.HasNonTranslation()) mTransformType = TRANSLATION_ONLY; else if (m.HasNonAxisAlignedTransform()) mTransformType = COMPLEX; else mTransformType = AXIS_ALIGNED_SCALE; // if this is a native win32 surface, we don't have to // redirect rendering to our own HDC; in some cases, // we may be able to use the HDC from the surface directly. if ((surf->GetType() == gfxASurface::SurfaceTypeWin32 || surf->GetType() == gfxASurface::SurfaceTypeWin32Printing) && (surf->GetContentType() == gfxASurface::CONTENT_COLOR || (surf->GetContentType() == gfxASurface::CONTENT_COLOR_ALPHA && (mNativeDrawFlags & CAN_DRAW_TO_COLOR_ALPHA)))) { // grab the DC. This can fail if there is a complex clipping path, // in which case we'll have to fall back. mWinSurface = static_cast<gfxWindowsSurface*>(static_cast<gfxASurface*>(surf.get())); mDC = mWinSurface->GetDCWithClip(mContext); if (mDC) { if (mTransformType == TRANSLATION_ONLY) { mRenderState = RENDER_STATE_NATIVE_DRAWING; mTranslation = m.GetTranslation(); } else if (((mTransformType == AXIS_ALIGNED_SCALE) && (mNativeDrawFlags & CAN_AXIS_ALIGNED_SCALE)) || (mNativeDrawFlags & CAN_COMPLEX_TRANSFORM)) { mWorldTransform.eM11 = (FLOAT) m.xx; mWorldTransform.eM12 = (FLOAT) m.yx; mWorldTransform.eM21 = (FLOAT) m.xy; mWorldTransform.eM22 = (FLOAT) m.yy; mWorldTransform.eDx = (FLOAT) m.x0; mWorldTransform.eDy = (FLOAT) m.y0; mRenderState = RENDER_STATE_NATIVE_DRAWING; } } } // If we couldn't do native drawing, then we have to do two-buffer drawing // and do alpha recovery if (mRenderState == RENDER_STATE_INIT) { mRenderState = RENDER_STATE_ALPHA_RECOVERY_BLACK; // We round out our native rect here, that way the snapping will // happen correctly. mNativeRect.RoundOut(); // we only do the scale bit if we can do an axis aligned // scale; otherwise we scale (if necessary) after // rendering with cairo. Note that if we're doing alpha recovery, // we cannot do a full complex transform with win32 (I mean, we could, but // it would require more code that's not here.) if (mTransformType == TRANSLATION_ONLY || !(mNativeDrawFlags & CAN_AXIS_ALIGNED_SCALE)) { mScale = gfxSize(1.0, 1.0); // Add 1 to the surface size; it's guaranteed to not be incorrect, // and it fixes bug 382458 // There's probably a better fix, but I haven't figured out // the root cause of the problem. mTempSurfaceSize = gfxIntSize((PRInt32) NS_ceil(mNativeRect.Width() + 1), (PRInt32) NS_ceil(mNativeRect.Height() + 1)); } else { // figure out the scale factors mScale = m.ScaleFactors(PR_TRUE); mWorldTransform.eM11 = (FLOAT) mScale.width; mWorldTransform.eM12 = 0.0f; mWorldTransform.eM21 = 0.0f; mWorldTransform.eM22 = (FLOAT) mScale.height; mWorldTransform.eDx = 0.0f; mWorldTransform.eDy = 0.0f; // See comment above about "+1" mTempSurfaceSize = gfxIntSize((PRInt32) NS_ceil(mNativeRect.Width() * mScale.width + 1), (PRInt32) NS_ceil(mNativeRect.Height() * mScale.height + 1)); } } } if (mRenderState == RENDER_STATE_NATIVE_DRAWING) { // we can just do native drawing directly to the context's surface // do we need to use SetWorldTransform? if (mTransformType != TRANSLATION_ONLY) { SetGraphicsMode(mDC, GM_ADVANCED); GetWorldTransform(mDC, &mOldWorldTransform); SetWorldTransform(mDC, &mWorldTransform); } GetViewportOrgEx(mDC, &mOrigViewportOrigin); SetViewportOrgEx(mDC, mOrigViewportOrigin.x + (int)mDeviceOffset.x, mOrigViewportOrigin.y + (int)mDeviceOffset.y, NULL); return mDC; } else if (mRenderState == RENDER_STATE_ALPHA_RECOVERY_BLACK || mRenderState == RENDER_STATE_ALPHA_RECOVERY_WHITE) { // we're going to use mWinSurface to create our temporary surface here // get us a RGB24 DIB; DIB is important, because // we can later call GetImageSurface on it. mWinSurface = new gfxWindowsSurface(mTempSurfaceSize); mDC = mWinSurface->GetDC(); RECT r = { 0, 0, mTempSurfaceSize.width, mTempSurfaceSize.height }; if (mRenderState == RENDER_STATE_ALPHA_RECOVERY_BLACK) FillRect(mDC, &r, (HBRUSH)GetStockObject(BLACK_BRUSH)); else FillRect(mDC, &r, (HBRUSH)GetStockObject(WHITE_BRUSH)); if ((mTransformType != TRANSLATION_ONLY) && (mNativeDrawFlags & CAN_AXIS_ALIGNED_SCALE)) { SetGraphicsMode(mDC, GM_ADVANCED); SetWorldTransform(mDC, &mWorldTransform); } return mDC; } else { NS_ERROR("Bogus render state!"); return nsnull; } }