diff --git a/dlls/mshtml/Makefile.in b/dlls/mshtml/Makefile.in
index 0844307249e..3abed0a5705 100644
--- a/dlls/mshtml/Makefile.in
+++ b/dlls/mshtml/Makefile.in
@@ -57,6 +57,7 @@ C_SRCS = \
secmgr.c \
selection.c \
service.c \
+ svg.c \
task.c \
txtrange.c \
view.c \
diff --git a/dlls/mshtml/htmlelem.c b/dlls/mshtml/htmlelem.c
index a46938016a6..aa1fc5bc202 100644
--- a/dlls/mshtml/htmlelem.c
+++ b/dlls/mshtml/htmlelem.c
@@ -5891,16 +5891,24 @@ HRESULT HTMLElement_Create(HTMLDocumentNode *doc, nsIDOMNode *nsnode, BOOL use_g
tag = get_tag_desc(tag_name);
if(tag) {
hres = tag->constructor(doc, nselem, &elem);
- }else if(use_generic) {
- hres = HTMLGenericElement_Create(doc, nselem, &elem);
}else {
- elem = heap_alloc_zero(sizeof(HTMLElement));
- if(elem) {
- elem->node.vtbl = &HTMLElementImplVtbl;
- HTMLElement_Init(elem, doc, nselem, &HTMLElement_dispex);
- hres = S_OK;
+ nsIDOMSVGElement *svg_element;
+
+ nsres = nsIDOMElement_QueryInterface(nselem, &IID_nsIDOMSVGElement, (void**)&svg_element);
+ if(NS_SUCCEEDED(nsres)) {
+ hres = create_svg_element(doc, svg_element, tag_name, &elem);
+ nsIDOMSVGElement_Release(svg_element);
+ }else if(use_generic) {
+ hres = HTMLGenericElement_Create(doc, nselem, &elem);
}else {
- hres = E_OUTOFMEMORY;
+ elem = heap_alloc_zero(sizeof(HTMLElement));
+ if(elem) {
+ elem->node.vtbl = &HTMLElementImplVtbl;
+ HTMLElement_Init(elem, doc, nselem, &HTMLElement_dispex);
+ hres = S_OK;
+ }else {
+ hres = E_OUTOFMEMORY;
+ }
}
}
diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h
index 26037f0fe71..f8d08835f2a 100644
--- a/dlls/mshtml/mshtml_private.h
+++ b/dlls/mshtml/mshtml_private.h
@@ -246,7 +246,8 @@ typedef struct EventTarget EventTarget;
XIID(IHTMLXMLHttpRequest) \
XIID(IHTMLXMLHttpRequestFactory) \
XIID(IOmHistory) \
- XIID(IOmNavigator)
+ XIID(IOmNavigator) \
+ XIID(ISVGElement)
typedef enum {
#define XIID(iface) iface ## _tid,
@@ -1071,6 +1072,8 @@ HRESULT HTMLTextAreaElement_Create(HTMLDocumentNode*,nsIDOMElement*,HTMLElement*
HRESULT HTMLTitleElement_Create(HTMLDocumentNode*,nsIDOMElement*,HTMLElement**) DECLSPEC_HIDDEN;
HRESULT HTMLGenericElement_Create(HTMLDocumentNode*,nsIDOMElement*,HTMLElement**) DECLSPEC_HIDDEN;
+HRESULT create_svg_element(HTMLDocumentNode*,nsIDOMSVGElement*,const WCHAR*,HTMLElement**) DECLSPEC_HIDDEN;
+
void HTMLDOMNode_Init(HTMLDocumentNode*,HTMLDOMNode*,nsIDOMNode*,dispex_static_data_t*) DECLSPEC_HIDDEN;
void HTMLElement_Init(HTMLElement*,HTMLDocumentNode*,nsIDOMElement*,dispex_static_data_t*) DECLSPEC_HIDDEN;
diff --git a/dlls/mshtml/svg.c b/dlls/mshtml/svg.c
new file mode 100644
index 00000000000..bada820f9de
--- /dev/null
+++ b/dlls/mshtml/svg.c
@@ -0,0 +1,225 @@
+/*
+ * Copyright 2019 Jacek Caban for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include
+#include
+#include
+
+#define COBJMACROS
+
+#include "windef.h"
+#include "winbase.h"
+#include "winuser.h"
+#include "winreg.h"
+#include "ole2.h"
+#include "mshtmdid.h"
+
+#include "wine/debug.h"
+
+#include "mshtml_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
+
+struct SVGElement {
+ HTMLElement element;
+ ISVGElement ISVGElement_iface;
+};
+
+static inline SVGElement *impl_from_ISVGElement(ISVGElement *iface)
+{
+ return CONTAINING_RECORD(iface, SVGElement, ISVGElement_iface);
+}
+
+static HRESULT WINAPI SVGElement_QueryInterface(ISVGElement *iface,
+ REFIID riid, void **ppv)
+{
+ SVGElement *This = impl_from_ISVGElement(iface);
+
+ return IHTMLDOMNode_QueryInterface(&This->element.node.IHTMLDOMNode_iface, riid, ppv);
+}
+
+static ULONG WINAPI SVGElement_AddRef(ISVGElement *iface)
+{
+ SVGElement *This = impl_from_ISVGElement(iface);
+
+ return IHTMLDOMNode_AddRef(&This->element.node.IHTMLDOMNode_iface);
+}
+
+static ULONG WINAPI SVGElement_Release(ISVGElement *iface)
+{
+ SVGElement *This = impl_from_ISVGElement(iface);
+
+ return IHTMLDOMNode_Release(&This->element.node.IHTMLDOMNode_iface);
+}
+
+static HRESULT WINAPI SVGElement_GetTypeInfoCount(ISVGElement *iface, UINT *pctinfo)
+{
+ SVGElement *This = impl_from_ISVGElement(iface);
+ return IDispatchEx_GetTypeInfoCount(&This->element.node.event_target.dispex.IDispatchEx_iface, pctinfo);
+}
+
+static HRESULT WINAPI SVGElement_GetTypeInfo(ISVGElement *iface, UINT iTInfo,
+ LCID lcid, ITypeInfo **ppTInfo)
+{
+ SVGElement *This = impl_from_ISVGElement(iface);
+ return IDispatchEx_GetTypeInfo(&This->element.node.event_target.dispex.IDispatchEx_iface, iTInfo, lcid,
+ ppTInfo);
+}
+
+static HRESULT WINAPI SVGElement_GetIDsOfNames(ISVGElement *iface, REFIID riid,
+ LPOLESTR *rgszNames, UINT cNames,
+ LCID lcid, DISPID *rgDispId)
+{
+ SVGElement *This = impl_from_ISVGElement(iface);
+ return IDispatchEx_GetIDsOfNames(&This->element.node.event_target.dispex.IDispatchEx_iface, riid, rgszNames,
+ cNames, lcid, rgDispId);
+}
+
+static HRESULT WINAPI SVGElement_Invoke(ISVGElement *iface, DISPID dispIdMember,
+ REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
+ VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
+{
+ SVGElement *This = impl_from_ISVGElement(iface);
+ return IDispatchEx_Invoke(&This->element.node.event_target.dispex.IDispatchEx_iface, dispIdMember, riid,
+ lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
+}
+
+static HRESULT WINAPI SVGElement_put_xmlbase(ISVGElement *iface, BSTR v)
+{
+ SVGElement *This = impl_from_ISVGElement(iface);
+ FIXME("(%p)->(%s)\n", This, debugstr_w(v));
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI SVGElement_get_xmlbase(ISVGElement *iface, BSTR *p)
+{
+ SVGElement *This = impl_from_ISVGElement(iface);
+ FIXME("(%p)->(%p)\n", This, p);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI SVGElement_putref_ownerSVGElement(ISVGElement *iface, ISVGSVGElement *v)
+{
+ SVGElement *This = impl_from_ISVGElement(iface);
+ FIXME("(%p)->(%p)\n", This, v);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI SVGElement_get_ownerSVGElement(ISVGElement *iface, ISVGSVGElement **p)
+{
+ SVGElement *This = impl_from_ISVGElement(iface);
+ FIXME("(%p)->(%p)\n", This, p);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI SVGElement_putref_viewportElement(ISVGElement *iface, ISVGElement *v)
+{
+ SVGElement *This = impl_from_ISVGElement(iface);
+ FIXME("(%p)->(%p)\n", This, v);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI SVGElement_get_viewportElement(ISVGElement *iface, ISVGElement **p)
+{
+ SVGElement *This = impl_from_ISVGElement(iface);
+ FIXME("(%p)->(%p)\n", This, p);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI SVGElement_putref_focusable(ISVGElement *iface, ISVGAnimatedEnumeration *v)
+{
+ SVGElement *This = impl_from_ISVGElement(iface);
+ FIXME("(%p)->(%p)\n", This, v);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI SVGElement_get_focusable(ISVGElement *iface, ISVGAnimatedEnumeration **p)
+{
+ SVGElement *This = impl_from_ISVGElement(iface);
+ FIXME("(%p)->(%p)\n", This, p);
+ return E_NOTIMPL;
+}
+
+static const ISVGElementVtbl SVGElementVtbl = {
+ SVGElement_QueryInterface,
+ SVGElement_AddRef,
+ SVGElement_Release,
+ SVGElement_GetTypeInfoCount,
+ SVGElement_GetTypeInfo,
+ SVGElement_GetIDsOfNames,
+ SVGElement_Invoke,
+ SVGElement_put_xmlbase,
+ SVGElement_get_xmlbase,
+ SVGElement_putref_ownerSVGElement,
+ SVGElement_get_ownerSVGElement,
+ SVGElement_putref_viewportElement,
+ SVGElement_get_viewportElement,
+ SVGElement_putref_focusable,
+ SVGElement_get_focusable
+};
+
+static inline SVGElement *SVGElement_from_HTMLDOMNode(HTMLDOMNode *iface)
+{
+ return CONTAINING_RECORD(iface, SVGElement, element.node);
+}
+
+static HRESULT SVGElement_QI(HTMLDOMNode *iface, REFIID riid, void **ppv)
+{
+ SVGElement *This = SVGElement_from_HTMLDOMNode(iface);
+
+ TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
+
+ if(IsEqualGUID(&IID_ISVGElement, riid))
+ *ppv = &This->ISVGElement_iface;
+ else
+ return HTMLElement_QI(&This->element.node, riid, ppv);
+
+ IUnknown_AddRef((IUnknown*)*ppv);
+ return S_OK;
+}
+
+static const NodeImplVtbl SVGElementImplVtbl = {
+ &CLSID_SVGElement,
+ SVGElement_QI,
+ HTMLElement_destructor,
+ HTMLElement_cpc,
+ HTMLElement_clone,
+ NULL,
+ HTMLElement_get_attr_col,
+};
+
+static void init_svg_element(SVGElement *svg_element, HTMLDocumentNode *doc, nsIDOMSVGElement *nselem)
+{
+ if(!svg_element->element.node.vtbl)
+ svg_element->element.node.vtbl = &SVGElementImplVtbl;
+ svg_element->ISVGElement_iface.lpVtbl = &SVGElementVtbl;
+ HTMLElement_Init(&svg_element->element, doc, (nsIDOMElement*)nselem, NULL);
+}
+
+HRESULT create_svg_element(HTMLDocumentNode *doc, nsIDOMSVGElement *dom_element, const WCHAR *tag_name, HTMLElement **elem)
+{
+ SVGElement *svg_element;
+
+ svg_element = heap_alloc_zero(sizeof(*svg_element));
+ if(!svg_element)
+ return E_OUTOFMEMORY;
+
+ init_svg_element(svg_element, doc, dom_element);
+ *elem = &svg_element->element;
+ return S_OK;
+}
diff --git a/dlls/mshtml/tests/dom.c b/dlls/mshtml/tests/dom.c
index c3d11bee460..2a7f11fecaf 100644
--- a/dlls/mshtml/tests/dom.c
+++ b/dlls/mshtml/tests/dom.c
@@ -442,6 +442,18 @@ static const IID * const generic_iids[] = {
NULL
};
+static const IID * const svg_iids[] = {
+ ELEM_IFACES,
+ &IID_ISVGElement,
+ NULL
+};
+
+static const IID * const circle_iids[] = {
+ ELEM_IFACES,
+ &IID_ISVGElement,
+ NULL
+};
+
static const IID * const style_iids[] = {
&IID_IUnknown,
&IID_IDispatch,
@@ -531,8 +543,8 @@ static const elem_type_info_t elem_type_infos[] = {
{"LABEL", label_iids, &DIID_DispHTMLLabelElement, &CLSID_HTMLLabelElement},
{"BUTTON", button_iids, &DIID_DispHTMLButtonElement, &CLSID_HTMLButtonElement},
{"AREA", area_iids, &DIID_DispHTMLAreaElement, &CLSID_HTMLAreaElement},
- {"svg", elem_iids, NULL},
- {"circle", elem_iids, NULL}
+ {"svg", svg_iids, NULL},
+ {"circle", circle_iids, NULL}
};
static int strcmp_wa(LPCWSTR strw, const char *stra)
diff --git a/include/mshtml.idl b/include/mshtml.idl
index 92493a1bdd2..7cc9e93af2f 100644
--- a/include/mshtml.idl
+++ b/include/mshtml.idl
@@ -16201,6 +16201,22 @@ methods:
WINE_IHTMLELEMENT_DISPINTERFACE_DECL;
}
+/*****************************************************************************
+ * SVGElement coclass
+ */
+[
+ noncreatable,
+ uuid(30510564-98b5-11cf-bb82-00aa00bdce0b)
+]
+coclass SVGElement
+{
+ [default] dispinterface DispSVGElement;
+ [source, default] dispinterface HTMLElementEvents;
+ [source] dispinterface HTMLElementEvents2;
+ interface ISVGElement;
+ interface IHTMLElement;
+}
+
/*****************************************************************************
* ISVGLength interface
*/