//----------------------------------------------------------------------------- IPlatformBitmap* CBitmap::getBestPlatformBitmapForScaleFactor (double scaleFactor) const { if (bitmaps.empty ()) return 0; IPlatformBitmap* bestBitmap = bitmaps[0]; double bestDiff = std::abs (scaleFactor - bestBitmap->getScaleFactor ()); VSTGUI_RANGE_BASED_FOR_LOOP (BitmapVector, bitmaps, BitmapPointer, bitmap) if (bitmap->getScaleFactor () == scaleFactor) return bitmap; else if (std::abs (scaleFactor - bitmap->getScaleFactor ()) <= bestDiff && bitmap->getScaleFactor () > bestBitmap->getScaleFactor ()) { bestBitmap = bitmap; bestDiff = std::abs (scaleFactor - bitmap->getScaleFactor ()); } VSTGUI_RANGE_BASED_FOR_LOOP_END return bestBitmap; }
//----------------------------------------------------------------------------- void CGDrawContext::fillRectWithBitmap (CBitmap* bitmap, const CRect& srcRect, const CRect& dstRect, float alpha) { if (bitmap == 0 || alpha == 0.f || srcRect.isEmpty () || dstRect.isEmpty ()) return; if (!(srcRect.left == 0 && srcRect.right == 0 && srcRect.right == bitmap->getWidth () && srcRect.bottom == bitmap->getHeight ())) { // CGContextDrawTiledImage does not work with parts of a bitmap CDrawContext::fillRectWithBitmap(bitmap, srcRect, dstRect, alpha); return; } IPlatformBitmap* platformBitmap = bitmap->getBestPlatformBitmapForScaleFactor (scaleFactor); CPoint bitmapSize = platformBitmap->getSize (); if (srcRect.right > bitmapSize.x || srcRect.bottom > bitmapSize.y) return; CGBitmap* cgBitmap = platformBitmap ? dynamic_cast<CGBitmap*> (platformBitmap) : 0; CGImageRef image = cgBitmap ? cgBitmap->getCGImage () : 0; if (image) { CGContextRef context = beginCGContext (false, true); if (context) { // TODO: Check if this works with retina images CGRect clipRect = CGRectFromCRect (dstRect); clipRect.origin.y = -(clipRect.origin.y) - clipRect.size.height; clipRect = pixelAlligned (clipRect); CGContextClipToRect (context, clipRect); CGRect r = {}; r.size.width = CGImageGetWidth (image); r.size.height = CGImageGetHeight (image); CGContextDrawTiledImage (context, r, image); releaseCGContext (context); } } }
//----------------------------------------------------------------------------- void D2DDrawContext::drawBitmap (CBitmap* bitmap, const CRect& dest, const CPoint& offset, float alpha) { if (renderTarget == 0) return; D2DApplyClip ac (this); if (ac.isEmpty ()) return; double transformedScaleFactor = getScaleFactor (); CGraphicsTransform t = getCurrentTransform (); if (t.m11 == t.m22 && t.m12 == 0 && t.m21 == 0) transformedScaleFactor *= t.m11; IPlatformBitmap* platformBitmap = bitmap->getBestPlatformBitmapForScaleFactor (transformedScaleFactor); D2DBitmap* d2dBitmap = platformBitmap ? dynamic_cast<D2DBitmap*> (platformBitmap) : 0; if (d2dBitmap) { if (d2dBitmap->getSource ()) { ID2D1Bitmap* d2d1Bitmap = D2DBitmapCache::instance ()->getBitmap (d2dBitmap, renderTarget); if (d2d1Bitmap) { double bitmapScaleFactor = platformBitmap->getScaleFactor (); CGraphicsTransform bitmapTransform; bitmapTransform.scale (bitmapScaleFactor, bitmapScaleFactor); Transform transform (*this, bitmapTransform.inverse ()); CRect d (dest); d.makeIntegral (); CRect source (dest); source.offset (-source.left, -source.top); source.offset (offset.x, offset.y); bitmapTransform.transform (source); D2D1_RECT_F sourceRect = makeD2DRect (source); renderTarget->DrawBitmap (d2d1Bitmap, makeD2DRect (d), alpha * currentState.globalAlpha, D2D1_BITMAP_INTERPOLATION_MODE_LINEAR, &sourceRect); } } } }