Exemple #1
0
void wxSVGCanvasCairo::DrawCanvasPath(wxSVGCanvasPathCairo& canvasPath, wxSVGMatrix& matrix,
		const wxCSSStyleDeclaration& style, wxSVGSVGElement& svgElem) {
	// check Filter
	if (style.GetFilter().GetCSSPrimitiveType() == wxCSS_URI && style.GetFilter().GetStringValue().length() > 1) {
		wxString filterId = style.GetFilter().GetStringValue().substr(1);
		wxSVGElement* filterElem = (wxSVGElement*) svgElem.GetElementById(filterId);
		// feGaussianBlur
		if (filterElem && filterElem->GetDtd() == wxSVG_FILTER_ELEMENT && filterElem->GetFirstChild() != NULL
				&& ((wxSVGSVGElement*) filterElem->GetFirstChild())->GetDtd() == wxSVG_FEGAUSSIANBLUR_ELEMENT) {
			float stdX = ((wxSVGFEGaussianBlurElement*) filterElem->GetFirstChild())->GetStdDeviationX().GetAnimVal();
			float stdY = ((wxSVGFEGaussianBlurElement*) filterElem->GetFirstChild())->GetStdDeviationY().GetAnimVal();
			if (stdX <= 0 || stdY <= 0)
				return;
			int dx = int(floor(stdX * 3 * sqrt(2 * M_PI) / 4 + 0.5));
			int dy = int(floor(stdY * 3 * sqrt(2 * M_PI) / 4 + 0.5));
			
			wxSVGRect rect = canvasPath.GetResultBBox(style, matrix.Inverse());
			rect.SetX(rect.GetX() - 2*dx);
			rect.SetY(rect.GetY() - 2*dy);
			rect.SetWidth(rect.GetWidth() + 4*dx);
			rect.SetHeight(rect.GetHeight() + 4*dy);
			
			int width = (int) rect.GetWidth();
			int height = (int) rect.GetHeight();
			cairo_surface_t* surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
			cairo_t* cr = cairo_create(surface);
			wxSVGMatrix matrix2 = wxSVGMatrix(1, 0, 0, 1, - rect.GetX(), - rect.GetY()).Multiply(matrix);
			DrawPath(cr, canvasPath, matrix2, style, svgElem);
			gaussianBlur(surface, dx, dy);
			
			// draw surface
			cairo_save(m_cr);
			SetMatrix(m_cr, wxSVGMatrix(1, 0, 0, 1, rect.GetX(), rect.GetY()));
			cairo_set_source_surface(m_cr, surface, 0, 0);
			cairo_rectangle(m_cr, 0, 0, width, height);
			cairo_paint(m_cr); // fill the rectangle using the pattern
			cairo_new_path(m_cr);
			cairo_restore(m_cr);
			
			cairo_destroy(cr);
			cairo_surface_destroy(surface);
			return;
		}
	}
	DrawPath(m_cr, canvasPath, matrix, style, svgElem);
}
unsigned int wxSVGCanvas::GetGradientStops(const wxSVGSVGElement& svgElem, wxSVGGradientElement* gradElem, float opacity) {
	if (gradElem == NULL)
		return 0;

	// Search for the most referenced gradient (we assume that this is the one that contain stops)
	while (true) {
		wxString grad_href = gradElem->GetHref();
		if (grad_href.length() <= 1 || grad_href.GetChar(0) != wxT('#'))
			break;
		wxSVGElement* tmp = (wxSVGSVGElement*) svgElem.GetElementById(grad_href.substr(1));
		if (tmp == NULL || (tmp->GetDtd() != wxSVG_LINEARGRADIENT_ELEMENT
				&& tmp->GetDtd() != wxSVG_RADIALGRADIENT_ELEMENT))
			break;
		gradElem = (wxSVGGradientElement*) tmp;
	}

	// Count number of stop element
	wxSVGStopElement* stop_elem = (wxSVGStopElement*) gradElem->GetChildren();
	unsigned int stop_count = 0;
	while (stop_elem) {
		if (stop_elem->GetDtd() == wxSVG_STOP_ELEMENT)
			stop_count++;
		stop_elem = (wxSVGStopElement*) stop_elem->GetNext();
	}
	if (stop_count == 0)
		return 0;

	// Allocate enough stops
	AllocateGradientStops(stop_count);
	
	// Fill the stops
	stop_elem = (wxSVGStopElement*) gradElem->GetChildren();
	int i = 0;
	while (stop_elem) {
		if (stop_elem->GetDtd() == wxSVG_STOP_ELEMENT)
			SetStopValue(i++, stop_elem->GetOffset(), stop_elem->GetStopOpacity() * opacity,
					stop_elem->GetStopColor().GetRGBColor());
		stop_elem = (wxSVGStopElement*) stop_elem->GetNext();
	}
	return stop_count;
}
Exemple #3
0
unsigned int wxSVGCanvas::GetGradientStops(const wxSVGSVGElement& svgElem, wxSVGGradientElement* gradElem, float opacity) {
	if (gradElem == NULL)
		return 0;

	// Search for the most referenced gradient (we assume that this is the one that contain stops)
	while (true) {
		wxString grad_href = gradElem->GetHref();
		if (grad_href.length() <= 1 || grad_href.GetChar(0) != wxT('#'))
			break;
		wxSVGElement* tmp = (wxSVGSVGElement*) svgElem.GetElementById(grad_href.substr(1));
		if (tmp == NULL || (tmp->GetDtd() != wxSVG_LINEARGRADIENT_ELEMENT
				&& tmp->GetDtd() != wxSVG_RADIALGRADIENT_ELEMENT))
			break;
		gradElem = (wxSVGGradientElement*) tmp;
	}

	// Count number of stop element
	wxSVGStopElement* stop_elem = (wxSVGStopElement*) gradElem->GetChildren();
	unsigned int stop_count = 0;
	while (stop_elem) {
		if (stop_elem->GetDtd() == wxSVG_STOP_ELEMENT)
			stop_count++;
		stop_elem = (wxSVGStopElement*) stop_elem->GetNext();
	}
	if (stop_count == 0)
		return 0;

	// Allocate enough stops
	AllocateGradientStops(stop_count);
	
	// Fill the stops
	stop_elem = (wxSVGStopElement*) gradElem->GetChildren();
	int i = 0;
	while (stop_elem) {
		if (stop_elem->GetDtd() == wxSVG_STOP_ELEMENT) {
		        wxSVGColor color = stop_elem->GetStopColor();
		        // no color, default is black
		        if (color.GetColorType() == wxSVG_COLORTYPE_UNKNOWN)
                                color = wxSVGColor(0,0,0);
			SetStopValue(i++, stop_elem->GetOffset(), stop_elem->GetStopOpacity() * opacity,
				color.GetRGBColor());
		stop_elem = (wxSVGStopElement*) stop_elem->GetNext();
	}
	return stop_count;
}

void wxSVGCanvas::GetLinearGradientVector(wxSVGPoint& p1, wxSVGPoint& p2, const wxSVGLinearGradientElement& gradElem,
		wxSVGCanvasPath& path) {
    p1.SetX(gradElem.GetX1().GetAnimVal());
	p1.SetY(gradElem.GetY1().GetAnimVal());
	p2.SetX(gradElem.GetX2().GetAnimVal());
	p2.SetY(gradElem.GetY2().GetAnimVal());
    
    if (gradElem.GetGradientUnits().GetAnimVal() == wxSVG_UNIT_TYPE_UNKNOWN ||
        gradElem.GetGradientUnits().GetAnimVal() == wxSVG_UNIT_TYPE_OBJECTBOUNDINGBOX)
    {
        wxSVGRect bbox = path.GetBBox();
        p1.SetX(bbox.GetX() + p1.GetX()*bbox.GetWidth());
        p1.SetY(bbox.GetY() + p1.GetY()*bbox.GetHeight());
        p2.SetX(bbox.GetX() + p2.GetX()*bbox.GetWidth());
        p2.SetY(bbox.GetY() + p2.GetY()*bbox.GetHeight());
    }
    
	// Compute gradient transformation matrix
    wxSVGMatrix lg_matrix;
	const wxSVGTransformList& transforms =  gradElem.GetGradientTransform().GetAnimVal();
	for (int i=0; i<(int)transforms.Count(); i++)
        lg_matrix = lg_matrix.Multiply(transforms[i].GetMatrix());
	
	p1 = p1.MatrixTransform(lg_matrix);
	p2 = p2.MatrixTransform(lg_matrix);
}
Exemple #4
0
void wxSVGCanvasCairo::DrawCanvasImage(wxSVGCanvasImage& canvasImage, cairo_surface_t* cairoSurface,
		wxSVGMatrix& matrix, const wxCSSStyleDeclaration& style, wxSVGSVGElement& svgElem) {
	if (cairoSurface == NULL)
		return;
	
	cairo_save(m_cr);
	
	// ClipPath
	if (style.GetClipPath().GetCSSPrimitiveType() == wxCSS_URI && style.GetClipPath().GetStringValue().length() > 1) {
		wxString clipPathId = style.GetClipPath().GetStringValue().substr(1);
		wxSVGClipPathElement* clipPathElem = (wxSVGClipPathElement*) svgElem.GetElementById(clipPathId);
		if (clipPathElem && clipPathElem->GetDtd() == wxSVG_CLIPPATH_ELEMENT) {
			clipPathElem->SetOwnerSVGElement(&svgElem);
			clipPathElem->SetViewportElement(&svgElem);
			wxSVGMatrix clipMatrix(matrix);
			clipPathElem->UpdateMatrix(clipMatrix);
			SetClipPath(clipPathElem, clipMatrix);
		}
	}
	
	SetMatrix(m_cr, matrix);
	
	// scale context
	double x = canvasImage.m_x;
	double y = canvasImage.m_y;
	double scaleX = canvasImage.m_width / canvasImage.m_image.GetWidth();
	double scaleY = canvasImage.m_height / canvasImage.m_image.GetHeight();
	wxSVG_PRESERVEASPECTRATIO align = canvasImage.GetPreserveAspectRatio().GetAlign();
	bool alignX = false;
	if (align > wxSVG_PRESERVEASPECTRATIO_NONE) {
		scaleY = canvasImage.m_height / canvasImage.GetDefaultHeight();
		if (canvasImage.GetPreserveAspectRatio().GetMeetOrSlice() != wxSVG_MEETORSLICE_SLICE) {
			alignX = scaleX > scaleY;
		} else {
			cairo_rectangle(m_cr, x, y, canvasImage.m_width, canvasImage.m_height);
			cairo_clip(m_cr);
			alignX = scaleX < scaleY;
		}
		if (alignX) {
			scaleX = scaleY;
			if (align == wxSVG_PRESERVEASPECTRATIO_XMIDYMIN
					|| align == wxSVG_PRESERVEASPECTRATIO_XMIDYMID
					|| align == wxSVG_PRESERVEASPECTRATIO_XMIDYMAX)
				x += (canvasImage.m_width - canvasImage.GetDefaultWidth() * scaleX) / 2;
			else if (align == wxSVG_PRESERVEASPECTRATIO_XMAXYMIN
					|| align == wxSVG_PRESERVEASPECTRATIO_XMAXYMID
					|| align == wxSVG_PRESERVEASPECTRATIO_XMAXYMAX)
				x += canvasImage.m_width - canvasImage.GetDefaultWidth() * scaleX;
		} else {
			scaleY = scaleX;
			if (align == wxSVG_PRESERVEASPECTRATIO_XMINYMID
					|| align == wxSVG_PRESERVEASPECTRATIO_XMIDYMID
					|| align == wxSVG_PRESERVEASPECTRATIO_XMAXYMID)
				y += (canvasImage.m_height - canvasImage.GetDefaultHeight() * scaleY) / 2;
			else if (align == wxSVG_PRESERVEASPECTRATIO_XMINYMAX
					|| align == wxSVG_PRESERVEASPECTRATIO_XMIDYMAX
					|| align == wxSVG_PRESERVEASPECTRATIO_XMAXYMAX)
				y += canvasImage.m_height - canvasImage.GetDefaultHeight() * scaleY;
		}
		scaleY = scaleY * canvasImage.GetDefaultHeight() / canvasImage.m_image.GetHeight();
	}
	cairo_translate(m_cr, x, y);
	cairo_scale(m_cr, scaleX, scaleY);
	
	// prepare to draw the image
	cairo_set_source_surface(m_cr, cairoSurface, 0, 0);
	
	// use the original size here since the context is scaled already...
	cairo_rectangle(m_cr, 0, 0, canvasImage.m_image.GetWidth(), canvasImage.m_image.GetHeight());
	// paint
	if (style.GetMask().GetCSSPrimitiveType() == wxCSS_URI && style.GetMask().GetStringValue().length() > 1) {
		wxString maskId = style.GetMask().GetStringValue().substr(1);
		wxSVGMaskElement* maskElem = (wxSVGMaskElement*) svgElem.GetElementById(maskId);
		if (maskElem && maskElem->GetDtd() == wxSVG_MASK_ELEMENT) {
			maskElem->SetOwnerSVGElement(&svgElem);
			maskElem->SetViewportElement(&svgElem);
			cairo_surface_t* surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
					svgElem.GetWidth().GetAnimVal()/scaleX, svgElem.GetHeight().GetAnimVal()/scaleY);
			cairo_t* cr = cairo_create(surface);
			wxSVGMatrix maskMatrix;
			maskMatrix = maskMatrix.Translate(x, y).ScaleNonUniform(scaleX, scaleY).Inverse();
			DrawMask(cr, maskElem, maskMatrix, style, svgElem);
			cairo_mask_surface(m_cr, surface, 0, 0);
			cairo_destroy(cr);
			cairo_surface_destroy(surface);
		}
	} else {
		cairo_paint_with_alpha(m_cr, style.GetOpacity());
	}
	cairo_new_path(m_cr);
	
	// clean up
	cairo_restore(m_cr);
}
Exemple #5
0
void wxSVGCanvasCairo::DrawMask(cairo_t* cr, wxSVGElement* maskElem, const wxSVGMatrix& matrix,
		const wxCSSStyleDeclaration& style, wxSVGSVGElement& svgElem) {
	SetMatrix(cr, matrix);
	wxSVGElement* elem = (wxSVGElement*) (maskElem->GetFirstChild());
	while (elem != NULL) {
		elem->SetOwnerSVGElement(maskElem->GetOwnerSVGElement());
		elem->SetViewportElement(maskElem->GetViewportElement());
		wxSVGDocument* doc = (wxSVGDocument*) elem->GetOwnerDocument();
		wxSVGCanvasItem* canvasItem = NULL;
		wxCSSStyleDeclaration resStyle = style;
		switch (elem->GetDtd()) {
		case wxSVG_G_ELEMENT: {
			wxSVGGElement* gElement = (wxSVGGElement*) elem;
			if (gElement->GetVisibility() == wxCSS_VALUE_HIDDEN)
				break;
			resStyle.Add(((wxSVGGElement*) elem)->GetStyle());
			DrawMask(cr, elem, matrix, resStyle, svgElem);
			break;
		}
		case wxSVG_LINE_ELEMENT: {
			wxSVGLineElement* element = (wxSVGLineElement*) elem;
			if (element->GetVisibility() == wxCSS_VALUE_HIDDEN)
				break;
			canvasItem = doc->GetCanvas()->CreateItem(element);
			resStyle.Add(element->GetStyle());
			resStyle.Add(element->GetAnimStyle());
			break;
		}
		case wxSVG_POLYLINE_ELEMENT: {
			wxSVGPolylineElement* element = (wxSVGPolylineElement*) elem;
			if (element->GetVisibility() == wxCSS_VALUE_HIDDEN)
				break;
			canvasItem = doc->GetCanvas()->CreateItem(element);
			resStyle.Add(element->GetStyle());
			resStyle.Add(element->GetAnimStyle());
			break;
		}
		case wxSVG_POLYGON_ELEMENT: {
			wxSVGPolygonElement* element = (wxSVGPolygonElement*) elem;
			if (element->GetVisibility() == wxCSS_VALUE_HIDDEN)
				break;
			canvasItem = doc->GetCanvas()->CreateItem(element);
			resStyle.Add(element->GetStyle());
			resStyle.Add(element->GetAnimStyle());
			break;
		}
		case wxSVG_RECT_ELEMENT: {
			wxSVGRectElement* element = (wxSVGRectElement*) elem;
			if (element->GetVisibility() == wxCSS_VALUE_HIDDEN)
				break;
			canvasItem = doc->GetCanvas()->CreateItem(element);
			resStyle.Add(element->GetStyle());
			resStyle.Add(element->GetAnimStyle());
			break;
		}
		case wxSVG_CIRCLE_ELEMENT: {
			wxSVGCircleElement* element = (wxSVGCircleElement*) elem;
			if (element->GetVisibility() == wxCSS_VALUE_HIDDEN)
				break;
			canvasItem = doc->GetCanvas()->CreateItem(element);
			resStyle.Add(element->GetStyle());
			resStyle.Add(element->GetAnimStyle());
			break;
		}
		case wxSVG_ELLIPSE_ELEMENT: {
			wxSVGEllipseElement* element = (wxSVGEllipseElement*) elem;
			if (element->GetVisibility() == wxCSS_VALUE_HIDDEN)
				break;
			canvasItem = doc->GetCanvas()->CreateItem(element);
			resStyle.Add(element->GetStyle());
			resStyle.Add(element->GetAnimStyle());
			break;
		}
		case wxSVG_PATH_ELEMENT: {
			wxSVGPathElement* element = (wxSVGPathElement*) elem;
			if (element->GetVisibility() == wxCSS_VALUE_HIDDEN)
				break;
			canvasItem = doc->GetCanvas()->CreateItem(element);
			resStyle.Add(element->GetStyle());
			resStyle.Add(element->GetAnimStyle());
			break;
		}
		case wxSVG_USE_ELEMENT: {
			wxSVGUseElement* element = (wxSVGUseElement*) elem;
			if (element->GetVisibility() == wxCSS_VALUE_HIDDEN)
				break;
			resStyle.Add(element->GetStyle());
			resStyle.Add(element->GetAnimStyle());
			// get ref element
			wxString href = element->GetHref();
			if (href.length() == 0 || href.GetChar(0) != wxT('#'))
				break;
			href.Remove(0, 1);
			wxSVGElement* refElem = (wxSVGElement*) maskElem->GetOwnerSVGElement()->GetElementById(href);
			if (!refElem)
				break;

			// create shadow tree
			wxSVGGElement* gElem = new wxSVGGElement();
			gElem->SetOwnerDocument(elem->GetOwnerDocument());
			gElem->SetOwnerSVGElement(maskElem->GetOwnerSVGElement());
			gElem->SetViewportElement(maskElem->GetViewportElement());
			gElem->SetStyle(element->GetStyle());
			if (element->GetX().GetAnimVal().GetUnitType() != wxSVG_LENGTHTYPE_UNKNOWN)
				gElem->Translate(element->GetX().GetAnimVal(), element->GetY().GetAnimVal());
			if (refElem->GetDtd() == wxSVG_SYMBOL_ELEMENT || refElem->GetDtd() == wxSVG_SVG_ELEMENT) {
				wxSVGSVGElement* svgElem;
				if (refElem->GetDtd() == wxSVG_SVG_ELEMENT)
					svgElem = (wxSVGSVGElement*) refElem->CloneNode();
				else {
					svgElem = new wxSVGSVGElement();
					wxSvgXmlElement* child = refElem->GetChildren();
					while (child) {
						svgElem->AddChild(child->CloneNode());
						child = child->GetNext();
					}
					svgElem->SetViewBox(((wxSVGSymbolElement*) refElem)->GetViewBox());
					svgElem->SetPreserveAspectRatio(((wxSVGSymbolElement*) refElem)->GetPreserveAspectRatio());
				}
				if (element->GetWidth().GetAnimVal().GetUnitType() != wxSVG_LENGTHTYPE_UNKNOWN)
					svgElem->SetWidth(element->GetWidth().GetAnimVal());
				if (element->GetHeight().GetAnimVal().GetUnitType() != wxSVG_LENGTHTYPE_UNKNOWN)
					svgElem->SetHeight(element->GetHeight().GetAnimVal());
				gElem->AddChild(svgElem);
			} else
				gElem->AddChild(refElem->CloneNode());
			// render
			DrawMask(cr, gElem, matrix, resStyle, svgElem);
			// delete shadow tree
			delete gElem;
			break;
		}
		default:
			break;
		}
		if (canvasItem != NULL) {
			DrawPath(cr, ((wxSVGCanvasPathCairo&) *canvasItem), matrix, resStyle, svgElem);
			delete canvasItem;
		}
		elem = (wxSVGElement*) elem->GetNextSibling();
	}
}