Ejemplo n.º 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);
}
Ejemplo n.º 2
0
void wxSVGCanvasCairo::DrawMarker(const wxString& uri, wxSVGMark::Type type, wxSVGCanvasPathCairo& canvasPath,
		const wxSVGMatrix& matrix, const wxCSSStyleDeclaration& style, wxSVGSVGElement& svgElem) {
	wxSVGMarkerElement* markerElem = GetMarkerElement(svgElem, uri);
	if (markerElem == NULL || markerElem->GetMarkerWidth().GetAnimVal() <= 0
				|| markerElem->GetMarkerHeight().GetAnimVal() <= 0)
		return;
	vector<wxSVGMark> markPoints = canvasPath.GetMarkPoints();
	for (vector<wxSVGMark>::iterator it = markPoints.begin(); it != markPoints.end(); it++) {
		if (it->type != type)
			continue;
		wxSVGMark& markPoint = *it;
		double scaleX = matrix.GetA() * style.GetStrokeWidth();
		double scaleY = matrix.GetD() * style.GetStrokeWidth();
		markerElem->SetOwnerSVGElement(&svgElem);
		markerElem->SetViewportElement(&svgElem);
		cairo_surface_t* surface = cairo_image_surface_create(
				CAIRO_FORMAT_ARGB32,
				lround(markerElem->GetMarkerWidth().GetAnimVal() * scaleX),
				lround(markerElem->GetMarkerHeight().GetAnimVal() * scaleY));
		cairo_t* cr = cairo_create(surface);
		wxSVGMatrix markerMatrix;
		markerMatrix = markerMatrix.ScaleNonUniform(scaleX, scaleY);
		wxCSSStyleDeclaration style;
		DrawMask(cr, markerElem, markerMatrix, style, svgElem);
		// draw surface
		cairo_save(m_cr);
		double refX = markerElem->GetRefX().GetAnimVal() * style.GetStrokeWidth();
		double refY = markerElem->GetRefY().GetAnimVal() * style.GetStrokeWidth();
		wxSVGPoint point(markPoint.x - refX, markPoint.y - refY);
		point = point.MatrixTransform(matrix);
		wxSVGMatrix m;
		m = m.Translate(point.GetX(), point.GetY());
		if (markPoint.angle != 0) {
			refX = markerElem->GetRefX().GetAnimVal() * scaleX;
			refY = markerElem->GetRefY().GetAnimVal() * scaleY;
			m = m.Translate(refX, refY).Rotate(markPoint.angle / M_PI * 180).Translate(-refX, -refY);
		}
		SetMatrix(m_cr, m);
		cairo_set_source_surface(m_cr, surface, 0, 0);
		cairo_paint(m_cr);
		cairo_restore(m_cr);
		cairo_destroy(cr);
		cairo_surface_destroy(surface);
	}
}
wxSVGRect wxSVGCanvasPathCairo::GetResultBBox(const wxCSSStyleDeclaration& style, const wxSVGMatrix& matrix) {
	if (&matrix) {
		cairo_matrix_t m;
		cairo_matrix_init(&m, matrix.GetA(), matrix.GetB(), matrix.GetC(), matrix.GetD(), matrix.GetE(), matrix.GetF());
		cairo_set_matrix(m_cr, &m);
	}
	ApplyStrokeStyle(m_cr, style);
	double x1, y1, x2, y2;
	if (style.GetStrokeWidth() > 0)
		cairo_stroke_extents(m_cr, &x1, &y1, &x2, &y2);
	else
		cairo_fill_extents(m_cr, &x1, &y1, &x2, &y2);
	if (&matrix) {
		cairo_matrix_t mat;
		cairo_matrix_init(&mat, 1, 0, 0, 1, 0, 0);
		cairo_set_matrix(m_cr, &mat);
	}
	return wxSVGRect(x1, y1, x2 - x1, y2 - y1);
}
Ejemplo n.º 4
0
void wxSVGCanvasPathCairo::ApplyStrokeStyle(cairo_t* cr, const wxCSSStyleDeclaration& style) {
	cairo_set_line_width(cr, style.GetStrokeWidth());
	switch (style.GetStrokeLinecap()) {
	case wxCSS_VALUE_ROUND:
		cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND);
		break;
	case wxCSS_VALUE_SQUARE:
		cairo_set_line_cap(cr, CAIRO_LINE_CAP_SQUARE);
		break;
	case wxCSS_VALUE_BUTT:
	default:
		cairo_set_line_cap(cr, CAIRO_LINE_CAP_BUTT);
		break;
	}
	switch (style.GetStrokeLinejoin()) {
	case wxCSS_VALUE_BEVEL:
		cairo_set_line_join(cr, CAIRO_LINE_JOIN_BEVEL);
		break;
	case wxCSS_VALUE_ROUND:
		cairo_set_line_join(cr, CAIRO_LINE_JOIN_ROUND);
		break;
	case wxCSS_VALUE_MITER:
	default:
		cairo_set_line_join(cr, CAIRO_LINE_JOIN_MITER);
		break;
	}
	if (style.GetStrokeDasharray().GetLength() > 0) {
		double* dashed = new double[style.GetStrokeDasharray().GetLength()];
		for (int i = 0; i < style.GetStrokeDasharray().GetLength(); i++) {
			dashed[i] = style.GetStrokeDasharray().Item(i).GetFloatValue();
		}
		cairo_set_dash(cr, dashed, style.GetStrokeDasharray().GetLength(), 0.0);
		delete dashed;
	} else
		cairo_set_dash(cr, NULL, 0, 0);
}
Ejemplo n.º 5
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);
}
Ejemplo n.º 6
0
void wxSVGCanvasCairo::DrawPath(cairo_t* cr, wxSVGCanvasPathCairo& canvasPath, const wxSVGMatrix& matrix,
		const wxCSSStyleDeclaration& style, wxSVGSVGElement& svgElem) {
	SetMatrix(cr, matrix);
	
	// Filling
	if (canvasPath.GetFill() && style.GetFill().Ok() && style.GetFill().GetPaintType() != wxSVG_PAINTTYPE_NONE) {
		cairo_path_t* path = canvasPath.GetPath();
		cairo_append_path(cr, path);
		SetPaint(cr, style.GetFill(), style.GetOpacity()*style.GetFillOpacity(), canvasPath, svgElem, matrix);
		cairo_fill(cr);
		cairo_path_destroy(path);
	}
	
	// Stroking
	if (style.GetStroke().Ok() && style.GetStrokeWidth() > 0
			&& style.GetStroke().GetPaintType() != wxSVG_PAINTTYPE_NONE) {
		cairo_path_t* path = canvasPath.GetPath();
		cairo_append_path(cr, path);
		SetPaint(cr, style.GetStroke(), style.GetOpacity()*style.GetStrokeOpacity(), canvasPath, svgElem, matrix);
		wxSVGCanvasPathCairo::ApplyStrokeStyle(cr, style);
		cairo_stroke(cr);
		cairo_path_destroy(path);
	}
	
	// marker
	if (style.HasMarkerStart()) {
		DrawMarker(style.GetMarkerStart().GetStringValue(), wxSVGMark::START, canvasPath, matrix, style, svgElem);
	}
	if (style.HasMarkerMid()) {
		DrawMarker(style.GetMarkerMid().GetStringValue(), wxSVGMark::MID, canvasPath, matrix, style, svgElem);
	}
	if (style.HasMarkerEnd()) {
		DrawMarker(style.GetMarkerEnd().GetStringValue(), wxSVGMark::END, canvasPath, matrix, style, svgElem);
	}
}
Ejemplo n.º 7
0
void wxSVGCanvasTextCairo::InitText(const wxString& text, const wxCSSStyleDeclaration& style, wxSVGMatrix* matrix) {
	BeginChar(matrix);
	
	// create path from text
	cairo_t* cr = ((wxSVGCanvasPathCairo*) m_char->path)->GetCr();
	
#if defined(__WXMSW__) || defined(__WXMAC__)
	int size = (int) style.GetFontSize();
	int fstyle = style.GetFontStyle() == wxCSS_VALUE_ITALIC ? wxFONTSTYLE_ITALIC
			: (style.GetFontStyle() == wxCSS_VALUE_OBLIQUE ? wxFONTSTYLE_SLANT : wxFONTSTYLE_NORMAL);
	wxFontWeight weight = style.GetFontWeight() == wxCSS_VALUE_BOLD ? wxFONTWEIGHT_BOLD
			: style.GetFontWeight() == wxCSS_VALUE_BOLDER ? wxFONTWEIGHT_MAX
			: style.GetFontWeight() == wxCSS_VALUE_LIGHTER ? wxFONTWEIGHT_LIGHT : wxFONTWEIGHT_NORMAL;
	wxFont fnt(size, wxFONTFAMILY_DEFAULT, fstyle, weight, false, style.GetFontFamily());
#ifdef __WXMSW__
	HFONT hfont = (HFONT) fnt.GetResourceHandle();
	cairo_set_font_face(cr, cairo_win32_font_face_create_for_hfont(hfont));
#else
	CGFontRef cgFont = fnt.OSXGetCGFont();
	cairo_set_font_face(cr, cairo_quartz_font_face_create_for_cgfont(cgFont));
#endif	
	cairo_set_font_size(cr, style.GetFontSize());
	
	cairo_font_extents_t fextents;
	cairo_font_extents(cr, &fextents);
	
	double maxWidth = 0;
	if (style.GetTextAnchor() == wxCSS_VALUE_MIDDLE || style.GetTextAnchor() == wxCSS_VALUE_END) {
		wxStringTokenizer tokenzr(text, wxT("\n"));
		while (tokenzr.HasMoreTokens()) {
			wxString token = tokenzr.GetNextToken();
			cairo_text_extents_t extents;
			cairo_text_extents(cr, (const char*) token.utf8_str(), &extents);
			if (maxWidth < extents.width)
				maxWidth = extents.width;
		}
	}
	
	wxStringTokenizer tokenzr(text, wxT("\n"));
	double x_advance = 0;
	double width = 0;
	double height = 0;
	double y = 0;
	while (tokenzr.HasMoreTokens()) {
		wxString token = tokenzr.GetNextToken();
		
		// get text extents
		cairo_text_extents_t extents;
		cairo_text_extents(cr, (const char*) token.utf8_str(), &extents);
		double x = style.GetTextAnchor() == wxCSS_VALUE_END ? maxWidth - extents.width
				: style.GetTextAnchor() == wxCSS_VALUE_MIDDLE ? (maxWidth - extents.width) / 2 : 0;
		
		m_char->path->MoveTo(m_tx + x, m_ty + y);
		cairo_text_path(cr, (const char*) token.utf8_str());
		
		if (x_advance < extents.x_advance)
			x_advance = extents.x_advance;
		if (width < extents.width)
			width = extents.width;
		height += fextents.height;
		if (tokenzr.HasMoreTokens())
			y += fextents.height;
	}
	
	// set bbox
	m_char->bbox = wxSVGRect(m_tx, m_ty, width, height);
	
	// increase current position (m_tx)
	if (style.GetTextAnchor() == wxCSS_VALUE_MIDDLE || style.GetTextAnchor() == wxCSS_VALUE_END) {
		wxSVGRect bbox = m_char->path->GetResultBBox(style);
		m_tx += x_advance > bbox.GetWidth() ? x_advance : bbox.GetWidth();
	} else
		m_tx += x_advance;
#else
	PangoLayout* layout = pango_cairo_create_layout(cr);
	PangoFontDescription* font = pango_font_description_new();
	pango_font_description_set_family(font, style.GetFontFamily().ToAscii());
	pango_font_description_set_weight(font, style.GetFontWeight() == wxCSS_VALUE_BOLD ? PANGO_WEIGHT_BOLD
			: PANGO_WEIGHT_NORMAL);
	pango_font_description_set_style(font, style.GetFontStyle() == wxCSS_VALUE_ITALIC ? PANGO_STYLE_ITALIC
			: (style.GetFontStyle() == wxCSS_VALUE_OBLIQUE ? PANGO_STYLE_OBLIQUE : PANGO_STYLE_NORMAL));
	pango_font_description_set_absolute_size(font, style.GetFontSize() * PANGO_SCALE);

	PangoContext* ctx = pango_layout_get_context(layout);
	PangoFont* f = pango_context_load_font(ctx, font);
	if (f == NULL)
		pango_font_description_set_style(font, PANGO_STYLE_NORMAL);
	pango_layout_set_font_description(layout, font);
	
	if (style.GetTextAnchor() != wxCSS_VALUE_START)
		pango_layout_set_alignment(layout, style.GetTextAnchor() == wxCSS_VALUE_MIDDLE ? PANGO_ALIGN_CENTER : PANGO_ALIGN_RIGHT);
	pango_layout_set_text(layout, (const char*) text.utf8_str(), -1);
	
	int baseline = pango_layout_get_baseline(layout);
	m_char->path->MoveTo(m_tx, m_ty - ((double)baseline / PANGO_SCALE));
	pango_cairo_layout_path(cr, layout);
	
	// set bbox and increase current position (m_tx)
	int lwidth, lheight;
	pango_layout_get_size(layout, &lwidth, &lheight);
	double width = ((double)lwidth / PANGO_SCALE);
	double height = ((double)lheight / PANGO_SCALE);
	m_char->bbox = wxSVGRect(m_tx, m_ty, width, height);
	if (style.GetTextAnchor() == wxCSS_VALUE_MIDDLE || style.GetTextAnchor() == wxCSS_VALUE_END) {
		wxSVGRect bbox = m_char->path->GetResultBBox(style);
		m_tx += width > bbox.GetWidth() ? width : bbox.GetWidth();
	} else
		m_tx += width;
		
	g_object_unref(layout);
	pango_font_description_free(font);
#endif
}