Beispiel #1
0
void 
Border::Render (cairo_t *cr, Region *region, bool path_only)
{
	Brush *background = GetBackground ();
	Brush *border_brush = GetBorderBrush ();

	cairo_save (cr);
	if (!path_only)
		RenderLayoutClip (cr);

	CornerRadius r = *GetCornerRadius ();
	CornerRadius *round =  &r;
	Thickness thickness = *GetBorderThickness ();
	Rect paint_border = extents;
	Rect paint_background = paint_border.GrowBy (-thickness);

	CornerRadius inner_adjusted = *round;
	inner_adjusted.topLeft = MAX (round->topLeft - MAX (thickness.left, thickness.top) * .5, 0);
	inner_adjusted.topRight = MAX (round->topRight - MAX (thickness.right, thickness.top) * .5, 0);
	inner_adjusted.bottomRight = MAX (round->bottomRight - MAX (thickness.right, thickness.bottom) * .5, 0);
	inner_adjusted.bottomLeft = MAX (round->bottomLeft - MAX (thickness.left, thickness.bottom) * .5, 0);

	CornerRadius outer_adjusted = *round;
	outer_adjusted.topLeft = outer_adjusted.topLeft ? MAX (round->topLeft + MAX (thickness.left, thickness.top) * .5, 0) : 0;
	outer_adjusted.topRight = outer_adjusted.topRight ? MAX (round->topRight + MAX (thickness.right, thickness.top) * .5, 0) : 0;
	outer_adjusted.bottomRight = outer_adjusted.bottomRight ? MAX (round->bottomRight + MAX (thickness.right, thickness.bottom) * .5, 0) : 0;
	outer_adjusted.bottomLeft = outer_adjusted.bottomLeft ? MAX (round->bottomLeft + MAX (thickness.left, thickness.bottom) * .5, 0) : 0;

	/* 
	 * NOTE filling this way can leave alpha artifacts between the border fill and bg fill
	 * but some simple inspection of the ms results make me think that is what happens there
	 * too.
	 */
	cairo_new_path (cr);
	cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD);

	if (border_brush && !paint_border.IsEmpty ()) {
		border_brush->SetupBrush (cr, paint_border);

		paint_border.Draw (cr, &outer_adjusted);
		paint_background.Draw (cr, &inner_adjusted);

		if (!path_only)
			border_brush->Fill (cr);
	}

	if (background && !paint_background.IsEmpty ()) {
		background->SetupBrush (cr, paint_background);

		paint_background.Draw (cr, &inner_adjusted);

		if (!path_only)
			background->Fill (cr);
	}
	
	cairo_restore (cr);
}
Beispiel #2
0
void
Grid::PostRender (Context *ctx, Region *region, bool skip_children)
{
	// render our chidren if we need to
	if (!skip_children) {
		VisualTreeWalker walker = VisualTreeWalker (this, ZForward, false);
		while (UIElement *child = walker.Step ())
			child->DoRender (ctx, region);
	}
	
	if (GetShowGridLines () && ctx->IsMutable ()) {
		double offset = 0;
		double dash = 4;
		ColumnDefinitionCollection *cols = GetColumnDefinitionsNoAutoCreate ();
		RowDefinitionCollection *rows = GetRowDefinitionsNoAutoCreate ();
		cairo_t *cr = ctx->Cairo ();
		int col_count = cols ? cols->GetCount () : 0;
		int row_count = rows ? rows->GetCount () : 0;
		
		cairo_save (cr);
		RenderLayoutClip (cr);
		cairo_set_line_width(cr, 1.0);
		// Initially render a blue color
		cairo_set_dash (cr, &dash, 1, offset);
		cairo_set_source_rgb (cr, 0.4, 0.4, 1.0);
		cairo_new_path (cr);

		// Draw gridlines between each pair of columns/rows
		for (int count = 0; count < 2; count++) {
			for (int i = 0, offset = 0; i < col_count - 1; i++) {
				ColumnDefinition *def = cols->GetValueAt (i)->AsColumnDefinition ();
				offset += def->GetActualWidth ();
				cairo_move_to (cr, offset, 0);
				cairo_line_to (cr, offset, GetActualHeight ());
			}
			
			for (int i = 0, offset = 0; i < row_count - 1; i++) {
				RowDefinition *def = rows->GetValueAt (i)->AsRowDefinition ();
				offset += def->GetActualHeight ();
				cairo_move_to (cr, 0, offset);
				cairo_line_to (cr, GetActualWidth (), offset);
			}
			
			cairo_stroke (cr);
			
			// For the second pass render a yellow color in the gaps between the previous dashes
			cairo_set_dash (cr, &dash, 1, dash);
			cairo_set_source_rgb (cr, 1.0, 1.0, 0.3);
		}
		cairo_restore (cr);
	}		

	// Chain up, but skip children since we've already rendered them here.
	UIElement::PostRender (ctx, region, true);
}
Beispiel #3
0
void
Image::Render (cairo_t *cr, Region *region, bool path_only)
{
	ImageSource *source = GetSource ();
	cairo_pattern_t *pattern = NULL;
	cairo_matrix_t matrix;
	
	if (!source)
		return;

	source->Lock ();

	cairo_save (cr);
       
	Size specified (GetActualWidth (), GetActualHeight ());
	Size stretched = ApplySizeConstraints (specified);
	bool adjust = specified != GetRenderSize ();

	if (GetStretch () != StretchUniformToFill)
		specified = specified.Min (stretched);

	Rect paint = Rect (0, 0, specified.width, specified.height);
	
	if (!path_only) {
		Rect image = Rect (0, 0, source->GetPixelWidth (), source->GetPixelHeight ());

		if (GetStretch () == StretchNone)
			paint = paint.Union (image);

		if (image.width == 0.0 && image.height == 0.0)
			goto cleanup;

		pattern = cairo_pattern_create_for_surface (source->GetSurface (cr));
		image_brush_compute_pattern_matrix (&matrix, paint.width, paint.height, 
						    image.width, image.height,
						    GetStretch (), 
						    AlignmentXCenter, AlignmentYCenter, NULL, NULL);
		
		cairo_pattern_set_matrix (pattern, &matrix);
#if MAKE_EVERYTHING_SLOW_AND_BUGGY
		cairo_pattern_set_extend (pattern, CAIRO_EXTEND_PAD);
#endif
		if (cairo_pattern_status (pattern) == CAIRO_STATUS_SUCCESS) {
			cairo_set_source (cr, pattern);
		}
		cairo_pattern_destroy (pattern);
	}

	if (adjust) {
		// FIXME: Propagate error properly
		MoonError error;
		specified = MeasureOverrideWithError (specified, &error);
		paint = Rect ((stretched.width - specified.width) * 0.5, (stretched.height - specified.height) * 0.5, specified.width, specified.height);
	}
	
	if (!path_only)
		RenderLayoutClip (cr);

	paint = paint.Intersection (Rect (0, 0, stretched.width, stretched.height));
	paint.Draw (cr);
	
	if (!path_only)
		cairo_fill (cr);

cleanup:
	cairo_restore (cr);
	source->Unlock ();
}