void wxRenderer_DrawScrollbar(wxWindow* WXUNUSED(window), wxDC& dc,
                             const wxRect& rect, wxOrientation orient, int current,
                             wxScrollbarPart focusPart, wxScrollbarPart hoverPart, int max, int step, int flags)
{
    const wxCoord x = rect.x;
    const wxCoord y = rect.y;
    const wxCoord w = rect.width;
    const wxCoord h = rect.height;

    dc.SetBrush( *wxWHITE_BRUSH );
    dc.SetPen( *wxTRANSPARENT_PEN );
    dc.DrawRectangle(rect);
    
    dc.SetBrush( *wxTRANSPARENT_BRUSH );

    HIRect hiRect = CGRectMake( x, y, w, h );

    CGContextRef cgContext = NULL;
    wxGraphicsContext* gc = NULL;
#if wxCHECK_VERSION(2,9,0)
    wxGCDCImpl *impl = dynamic_cast<wxGCDCImpl*> (dc.GetImpl());
    if (impl)
        gc = impl->GetGraphicsContext();
#else
    gc = dc.GetGraphicsContext();
#endif
    if (gc)
        cgContext = (CGContextRef) gc->GetNativeContext();
    
    if (cgContext)
    {
        HIThemeTrackDrawInfo trackInfo;
        trackInfo.version = 0;
        trackInfo.kind = kThemeMediumScrollBar;
        trackInfo.bounds = hiRect;
        trackInfo.min = 0;
        trackInfo.max = max;
        trackInfo.value = current;
        trackInfo.trackInfo.scrollbar.viewsize = step;
        trackInfo.attributes = 0;
        if (orient == wxHORIZONTAL)
            trackInfo.attributes |= kThemeTrackHorizontal;
        trackInfo.enableState = (flags & wxCONTROL_FOCUSED) ? kThemeTrackActive : kThemeTrackInactive;
        trackInfo.trackInfo.scrollbar.pressState = wxScrollbarPartToHIPressedState(focusPart);
        trackInfo.attributes |= kThemeTrackShowThumb;
        
        if (flags & wxCONTROL_DISABLED)
            trackInfo.enableState = kThemeTrackDisabled;
        
        HIThemeDrawTrack(&trackInfo, 0, cgContext, kHIThemeOrientationNormal);
    }
}
BOOL MacWidgetPainter::DrawSlider(const OpRect& rect, BOOL horizontal, double min, double max, double pos, BOOL highlighted, BOOL pressed_knob, OpRect& out_knob_position, OpPoint& out_start_track, OpPoint& out_end_track)
{
	// Opera 11.50: We are going to use special skinned (non-toolkit) sliders for zoom sliders
	// so we are not drawing with our painter in that case
	if (!widget || widget->GetType() == OpTypedObject::WIDGET_TYPE_ZOOM_SLIDER)
		return FALSE;

	OpSkinElement *border_skin = widget->GetBorderSkin()->GetSkinElement();
	if(!g_skin_manager->GetCurrentSkin() || (border_skin && !border_skin->IsNative()))
	{
		return IndpWidgetPainter::DrawSlider(rect, horizontal, min, max, pos, highlighted, pressed_knob, out_knob_position, out_start_track, out_end_track);
	}
	
	CGRect r = {{0, 0}, {rect.width, rect.height}};
	
	CGContextRef context;
	OpBitmap* bitmap = NULL;

	int bmpwidth = rect.width;
	int bmpheight = rect.height;
#ifdef PIXEL_SCALE_RENDERING_SUPPORT
	const PixelScaler& scaler = vd->GetVPScale();
	bmpwidth = TO_DEVICE_PIXEL(scaler, bmpwidth);
	bmpheight = TO_DEVICE_PIXEL(scaler, bmpheight);
#endif // PIXEL_SCALE_RENDERING_SUPPORT

	if(OpStatus::IsSuccess(OpBitmap::Create(&bitmap, bmpwidth, bmpheight, FALSE, TRUE, 0, 0, TRUE)))
	{
		int w = bitmap->Width();
		int h = bitmap->Height();
		int bpl = bitmap->GetBytesPerLine();
		void *image_data = bitmap->GetPointer(OpBitmap::ACCESS_WRITEONLY);
		if (!image_data)
		{
			delete bitmap;
			return FALSE;
		}
		memset(image_data, 0, bpl*h);
		CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
		CGBitmapInfo alpha = kCGBitmapByteOrderVegaInternal;
		context = CGBitmapContextCreate(image_data, w, h, 8, bpl, colorSpace, alpha);
		CGColorSpaceRelease(colorSpace);
		int win_height = rect.height;
		
		float scale = 1.0f;
#ifdef PIXEL_SCALE_RENDERING_SUPPORT
		scale = TO_DEVICE_PIXEL(scaler, scale);
#endif // PIXEL_SCALE_RENDERING_SUPPORT
		CGContextScaleCTM(context, scale, -scale);
		CGContextTranslateCTM(context, 0.0, -win_height);
		
		HIThemeTrackDrawInfo drawInfo;
		
		SInt32 thickness = 0;
		SInt32 shadow = 0;
		if	(noErr == GetThemeMetric(kThemeMetricLargeProgressBarThickness, &thickness) &&
			 (noErr == GetThemeMetric(kThemeMetricProgressBarShadowOutset, &shadow)))
		{
			SInt32 progressHeight = thickness + shadow;
			
			if (horizontal)
			{
				if((r.size.height) > progressHeight)
				{
					float f = (r.size.height - progressHeight);
					r.origin.y += f / 2;
					r.size.height -= f;
				}
			}
			else 
			{
				if((r.size.width) > progressHeight)
				{
					float f = (r.size.width - progressHeight);
					r.origin.x += f / 2;
					r.size.width -= f;
				}			
			}
		}
		else
		{
			if (horizontal)
			{
				float f = (r.size.height / 4) - 1;
				r.origin.y += f / 2;
				r.size.height -= f;
			}
			else
			{
				float f = (r.size.width / 4) - 1;
				r.origin.x += f / 2;
				r.size.width -= f;			
			}
		}
		
		drawInfo.version = 0;
		drawInfo.kind = kThemeSliderSmall;
		drawInfo.bounds = r;
		drawInfo.min = 0;
		drawInfo.max = NUMBER_OF_STEPS;
		if (widget->GetRTL())
			drawInfo.value = (max - pos) / (max - min) * NUMBER_OF_STEPS;
		else
			drawInfo.value = (pos - min) / (max - min) * NUMBER_OF_STEPS;
		drawInfo.attributes = kThemeTrackShowThumb;
		if (horizontal)
		{
			drawInfo.attributes |= kThemeTrackHorizontal;
		}
		else
		{
			drawInfo.attributes |= kThemeTrackRightToLeft;
		}
		drawInfo.enableState = widget->IsEnabled() ? kThemeTrackActive : kThemeTrackInactive;
		drawInfo.trackInfo.slider.thumbDir = kThemeThumbPlain;
		drawInfo.trackInfo.slider.pressState = 0;
		
		if (highlighted)
			drawInfo.attributes |= kThemeTrackHasFocus;

		HIThemeDrawTrack(&drawInfo, NULL, context, kHIThemeOrientationNormal);
		
		HIShapeRef thumb_shape;
		HIRect thumb_bounds, track_bounds;
		HIThemeGetTrackThumbShape(&drawInfo, &thumb_shape);
		HIShapeGetBounds(thumb_shape, &thumb_bounds);
		HIThemeGetTrackBounds(&drawInfo, &track_bounds);
		CFRelease(thumb_shape);
		
		out_knob_position.Set(thumb_bounds.origin.x, thumb_bounds.origin.y, thumb_bounds.size.width, thumb_bounds.size.height);
		out_start_track.Set(track_bounds.origin.x, track_bounds.origin.y);
		out_end_track.Set(track_bounds.origin.x+track_bounds.size.width, track_bounds.origin.y+track_bounds.size.height);
		
		CGContextRelease(context);
		bitmap->ReleasePointer();
		vd->BitmapOut(bitmap, OpRect(0, 0, bitmap->Width(), bitmap->Height()), rect);
		delete bitmap;
	}
	
	return TRUE;
}
BOOL MacWidgetPainter::DrawScrollbar(const OpRect &drawrect)
{
	HIThemeTrackDrawInfo 	drawInfo;
	ThemeTrackPressState 	pressState = 0;
	OpScrollbar 			*scroll = (OpScrollbar*)widget;
	HIShapeRef				thumbRgn;
	OpRect					opBounds = scroll->GetBounds();
		
	CGRect bounds = {{-drawrect.x, -drawrect.y}, {opBounds.width, opBounds.height}};
	
	pressState = (ThemeTrackPressState)scroll->GetHitPart();
	
	// hack to draw correctly, for some reason DrawThemeTrack needs this.
	if(pressState == kThemeTopInsideArrowPressed)
		pressState = kThemeBottomInsideArrowPressed;
	else if(pressState == kThemeBottomInsideArrowPressed)
		pressState = kThemeTopInsideArrowPressed;

	if(scroll->horizontal)
	{
		bounds.size.width++;
	}
	else
	{
		bounds.size.height++;
	}

	OpWindow *rootWindow;
	BOOL inActiveWindow = FALSE;
	if (vd->GetView())
	{
		rootWindow = vd->GetView()->GetContainer()->GetOpView()->GetRootWindow();
		inActiveWindow = rootWindow->IsActiveTopmostWindow() || rootWindow->GetStyle() == OpWindow::STYLE_POPUP;
	}

	drawInfo.version = 0;
	drawInfo.kind = kThemeMediumScrollBar;
	drawInfo.enableState = (scroll->IsEnabled() && inActiveWindow) ? kThemeTrackActive : kThemeTrackInactive;
	drawInfo.attributes = kThemeTrackShowThumb | (scroll->horizontal ? kThemeTrackHorizontal : 0);
	drawInfo.bounds = bounds;
	drawInfo.min = scroll->limit_min;
	drawInfo.max = scroll->limit_max;
	drawInfo.value = scroll->value;
	drawInfo.trackInfo.scrollbar.viewsize = scroll->limit_visible;
	drawInfo.trackInfo.scrollbar.pressState = pressState;
	
	int minSize = g_op_ui_info->GetHorizontalScrollbarHeight();
	if (GetOSVersion() >= 0x1070)
	{
		minSize = 0;
	}
	else if (GetInfo()->GetScrollbarArrowStyle() == ARROWS_AT_BOTTOM_AND_TOP)
	{
		minSize *= 6;
		minSize -= 4;
	}
	else
	{
		minSize *= 4;
	}
	
	// Bail out if smaller than minSize
	if(scroll->horizontal)
	{
		if((bounds.size.width) < minSize)
		{
			return FALSE;
		}
	}
	else
	{
		if((bounds.size.height) < minSize)
		{
			return FALSE;
		}
	}
	
	// Ok, the thumb(knob) could have been changed, let's update
	if(noErr == HIThemeGetTrackThumbShape(&drawInfo, &thumbRgn))
	{
		HIRect thumbRect;
		OpRect thumbOpRect;
		HIShapeGetBounds(thumbRgn, &thumbRect);
		CFRelease(thumbRgn);
		
		thumbOpRect.x = thumbRect.origin.x - bounds.origin.x;
		thumbOpRect.y = thumbRect.origin.y - bounds.origin.y;
		thumbOpRect.width = thumbRect.size.width;
		thumbOpRect.height = thumbRect.size.height;
		
		scroll->SetKnobRect(thumbOpRect);
	}
	
	if (OpStatus::IsError(MacCachedObjectFactory<MacWidgetBitmap, MacWidgetBitmapTraits>::Init()))
		return FALSE;

	int bmpwidth = drawrect.width;
	int bmpheight = drawrect.height;
#ifdef PIXEL_SCALE_RENDERING_SUPPORT
	const PixelScaler& scaler = vd->GetVPScale();
	bmpwidth = TO_DEVICE_PIXEL(scaler, bmpwidth);
	bmpheight = TO_DEVICE_PIXEL(scaler, bmpheight);
#endif // PIXEL_SCALE_RENDERING_SUPPORT

	MacWidgetBitmap* bitmap = MacCachedObjectFactory<MacWidgetBitmap, MacWidgetBitmapTraits>::CreateObject(MacWidgetBitmapTraits::CreateParam(bmpwidth, bmpheight));

	if (!bitmap)
		return FALSE;

	// Set clip and draw
	widget->SetClipRect(drawrect);
	OpBitmap* bmp = bitmap->GetOpBitmap();
	void* image_data = bmp->GetPointer(OpBitmap::ACCESS_WRITEONLY);
	if (!image_data)
	{
		bitmap->DecRef();
		widget->RemoveClipRect();
		return FALSE;
	}
	bitmap->Lock();
	const int bpl = bmp->GetBytesPerLine();
	memset(image_data, 0, bpl * bmp->Height());

	CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
	CGBitmapInfo alpha = kCGBitmapByteOrderVegaInternal;
	// create the context at size of drawrect instead of bitmap itself.
	// we cache the bitmap to prevent create-destroy cycle and reallocation.
	// since we need the bitmap's memory only, we can create a much smaller context within that buffer.
	CGContextRef context = CGBitmapContextCreate(image_data, bmpwidth, bmpheight, 8, bpl, colorSpace, alpha);
	CGColorSpaceRelease(colorSpace);
	if (!context)
	{
		bitmap->DecRef();
		bmp->ReleasePointer(FALSE);
		widget->RemoveClipRect();
		bitmap->Unlock();
		return FALSE;
	}

	const int win_height = drawrect.height;

	CGFloat scale = 1.0f;
#ifdef PIXEL_SCALE_RENDERING_SUPPORT
	scale = CGFloat(scaler.GetScale()) / 100.0f;
#endif // PIXEL_SCALE_RENDERING_SUPPORT
	CGContextScaleCTM(context, scale, -scale);
	CGContextTranslateCTM(context, 0.0f, -win_height);
	
	HIThemeDrawTrack(&drawInfo, NULL, context, kHIThemeOrientationNormal);

	bmp->ReleasePointer();
	vd->BitmapOut(bmp, OpRect(0, 0, bmp->Width(), bmp->Height()), drawrect);
	CGContextRelease(context);

	widget->RemoveClipRect();
	bitmap->Unlock();
	bitmap->DecRef();

	return TRUE;
}
BOOL MacWidgetPainter::DrawProgressbar(const OpRect &drawrect, double percent, INT32 progress_when_total_unknown, OpWidgetString* string, const char *skin_empty, const char *skin_full)
{
	const char *full_skin  = skin_full && *skin_full ? skin_full : "Progress Full Skin";

	OpSkinElement *border_skin = g_skin_manager->GetSkinElement(full_skin);
	if(!g_skin_manager->GetCurrentSkin() || !border_skin || !border_skin->IsNative())
	{
		return IndpWidgetPainter::DrawProgressbar(drawrect, percent, progress_when_total_unknown, string, skin_empty, skin_full);
	}

	UINT32 full_color = g_op_ui_info->GetUICSSColor(CSS_VALUE_HighlightText);

	g_skin_manager->GetTextColor(full_skin, &full_color);
		
	CGRect r = {{0, 0}, {drawrect.width, drawrect.height}};
	
	CGContextRef context;
	OpBitmap* bitmap = NULL;

	int bmpwidth = drawrect.width;
	int bmpheight = drawrect.height;
#ifdef PIXEL_SCALE_RENDERING_SUPPORT
	const PixelScaler& scaler = vd->GetVPScale();
	bmpwidth = TO_DEVICE_PIXEL(scaler, bmpwidth);
	bmpheight = TO_DEVICE_PIXEL(scaler, bmpheight);
#endif // PIXEL_SCALE_RENDERING_SUPPORT

	if(OpStatus::IsSuccess(OpBitmap::Create(&bitmap, bmpwidth, bmpheight, FALSE, TRUE, 0, 0, TRUE)))
	{
		int w = bitmap->Width();
		int h = bitmap->Height();
		int bpl = bitmap->GetBytesPerLine();
		void *image_data = bitmap->GetPointer(OpBitmap::ACCESS_WRITEONLY);
		if (!image_data)
		{
			delete bitmap;
			return FALSE;
		}
		memset(image_data, 0, bpl*h);
		CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
		CGBitmapInfo alpha = kCGBitmapByteOrderVegaInternal;
		context = CGBitmapContextCreate(image_data, w, h, 8, bpl, colorSpace, alpha);
		CGColorSpaceRelease(colorSpace);
		int win_height = drawrect.height;

		float scale = 1.0f;
#ifdef PIXEL_SCALE_RENDERING_SUPPORT
		scale = TO_DEVICE_PIXEL(scaler, scale);
#endif // PIXEL_SCALE_RENDERING_SUPPORT
		CGContextScaleCTM(context, scale, -scale);
		CGContextTranslateCTM(context, 0.0, -win_height);

		if (percent == 0 && progress_when_total_unknown)
		{
			HIThemeTrackDrawInfo drawInfo;
			
			SInt32 thickness = 0;
			SInt32 shadow = 0;
			if	(noErr == GetThemeMetric(kThemeMetricLargeProgressBarThickness, &thickness) &&
				(noErr == GetThemeMetric(kThemeMetricProgressBarShadowOutset, &shadow)))
			{
				SInt32 progressHeight = thickness + shadow;
				
				if((r.size.height) > progressHeight)
				{
					float f = (r.size.height - progressHeight); // / 2;
					r.origin.y += f;
					r.size.height -= f;
				}
			}
			else
			{
				float f = (r.size.height / 4) - 1;
				r.origin.y += f;
				r.size.height -= f;
			}

			drawInfo.version = 0;
			drawInfo.kind = kThemeIndeterminateBarLarge;
			drawInfo.bounds = r;
			drawInfo.min = 0;
			drawInfo.max = 100;
			drawInfo.value = 0;
			drawInfo.attributes = kThemeTrackHorizontal;
			drawInfo.enableState = widget->IsEnabled() ? kThemeTrackActive : kThemeTrackInactive;
			drawInfo.trackInfo.progress.phase = progress_when_total_unknown;
			
			HIThemeDrawTrack(&drawInfo, NULL, context, kHIThemeOrientationNormal);		
		}
		else
		{
			HIThemeTrackDrawInfo drawInfo;
			
			SInt32 thickness = 0;
			SInt32 shadow = 0;
			if	(noErr == GetThemeMetric(kThemeMetricLargeProgressBarThickness, &thickness) &&
				(noErr == GetThemeMetric(kThemeMetricProgressBarShadowOutset, &shadow)))
			{
				SInt32 progressHeight = thickness + shadow;
				
				if((r.size.height) > progressHeight)
				{
					float f = (r.size.height - progressHeight); // / 2;
					r.origin.y += f;
					r.size.height -= f;
				}
			}
			else
			{
				float f = (r.size.height / 4) - 1;
				r.origin.y += f;
				r.size.height -= f;
			}

			drawInfo.version = 0;
			drawInfo.kind = kThemeProgressBarLarge;
			drawInfo.bounds = r;
			drawInfo.min = 0;
			drawInfo.max = 100;
			drawInfo.value = (SInt32)(percent);
			drawInfo.attributes = kThemeTrackHorizontal;
			drawInfo.enableState = widget->IsEnabled() ? kThemeTrackActive : kThemeTrackInactive;
			drawInfo.trackInfo.progress.phase = floorf(GetCurrentEventTime()*16);
			
			HIThemeDrawTrack(&drawInfo, NULL, context, kHIThemeOrientationNormal);
		}
		
		CGContextRelease(context);
		bitmap->ReleasePointer();
		vd->BitmapOut(bitmap, OpRect(0, 0, bitmap->Width(), bitmap->Height()), drawrect);
		delete bitmap;
	}
	
	if (string)
	{
		widget->SetClipRect(drawrect);
		OpRect textRect = drawrect;
		textRect.y -= 1;
		string->Draw(textRect, vd, full_color);
		widget->RemoveClipRect();
	}
	
	return TRUE;
}