WebCore/ChangeLog

 12010-03-02 David Levin <levin@chromium.org>
 2
 3 Reviewed by NOBODY (OOPS!).
 4
 5 Need to move items that CanvasRenderingContext2D depends on into CanvasSurface.
 6 https://bugs.webkit.org/show_bug.cgi?id=35453
 7
 8 Prepartory changes to allow for an OffscreenCanvas which may be used in a worker
 9 or outside of the DOM.
 10
 11 No change in functionality, so new tests.
 12
 13 * dom/CanvasSurface.cpp: Moved functionality that CanvasRenderingContext2D depends on
 14 into this class (and removed dependencies on document/html element).
 15 (WebCore::CanvasSurface::CanvasSurface):
 16 (WebCore::CanvasSurface::~CanvasSurface): Put the desctructor in the cpp file
 17 to avoid needing access to ~ImageBuffer in the header file.
 18 (WebCore::CanvasSurface::setSurfaceSize): Does basic items needed
 19 when the size changes. It is protected to force outside callers to go
 20 through HTMLCanvasElement::setSize.
 21 (WebCore::CanvasSurface::toDataURL): Just moved from HTMLCanvasElement and
 22 made a note about a method to fix for worker usage.
 23 (WebCore::CanvasSurface::willDraw): Made this virtual to allow an overide
 24 which uses the renderbox and tracks a dirtyRect.
 25 (WebCore::CanvasSurface::convertLogicalToDevice): Moved and changed to
 26 rely on a member variable for page scale (to avoid using the document).
 27 (WebCore::CanvasSurface::createImageBuffer):
 28 (WebCore::CanvasSurface::drawingContext): Simple move from HTMLCanvasElement.
 29 (WebCore::CanvasSurface::buffer): Ditto.
 30 (WebCore::CanvasSurface::baseTransform): Ditto.
 31 * dom/CanvasSurface.h:
 32 (WebCore::CanvasSurface::width): Simple move from HTMLCanvasElement.
 33 (WebCore::CanvasSurface::height): Ditto.
 34 (WebCore::CanvasSurface::size): Ditto.
 35 (WebCore::CanvasSurface::setOriginTainted): Ditto.
 36 (WebCore::CanvasSurface::originClean): Ditto.
 37 (WebCore::CanvasSurface::hasCreatedImageBuffer): Ditto (with small name change).
 38 * html/HTMLCanvasElement.cpp:
 39 (WebCore::HTMLCanvasElement::HTMLCanvasElement): Pass in the scale factor to CanvasSurface
 40 so it doesn't need the document.
 41 (WebCore::HTMLCanvasElement::willDraw): Moved the relevant portion to CanvasSurface.
 42 (WebCore::HTMLCanvasElement::reset): Small changes due to refactoring.
 43 (WebCore::HTMLCanvasElement::paint): Ditto.
 44 * html/HTMLCanvasElement.h:
 45 (WebCore::HTMLCanvasElement::setSize): Ditto.
 46 * platform/MIMETypeRegistry.cpp:
 47 (WebCore::MIMETypeRegistry::isSupportedImageMIMETypeForEncoding): Added assert
 48 to verify that this is only called on the main thread.
 49 * platform/graphics/Image.cpp:
 50 (WebCore::Image::nullImage): Ditto.
 51 * platform/graphics/cg/ImageBufferCG.cpp:
 52 (WebCore::utiFromMIMEType): Ditto.
 53
1542010-02-26 Adam Barth <abarth@webkit.org>
255
356 Reviewed by Darin Adler.

WebCore/dom/CanvasSurface.cpp

2626#include "config.h"
2727#include "CanvasSurface.h"
2828
 29#include "AffineTransform.h"
 30#include "ExceptionCode.h"
 31#include "FloatRect.h"
 32#include "GraphicsContext.h"
 33#include "ImageBuffer.h"
 34#include "MIMETypeRegistry.h"
 35
2936namespace WebCore {
3037
 38// These values come from the WhatWG spec.
 39const int CanvasSurface::DefaultWidth = 300;
 40const int CanvasSurface::DefaultHeight = 150;
 41
 42// Firefox limits width/height to 32767 pixels, but slows down dramatically before it
 43// reaches that limit. We limit by area instead, giving us larger maximum dimensions,
 44// in exchange for a smaller maximum canvas size.
 45const float CanvasSurface::MaxCanvasArea = 32768 * 8192; // Maximum canvas area in CSS pixels
 46
 47CanvasSurface::CanvasSurface(float pageScaleFactor)
 48 : m_size(DefaultWidth, DefaultHeight)
 49 , m_pageScaleFactor(pageScaleFactor)
 50 , m_originClean(true)
 51 , m_hasCreatedImageBuffer(false)
 52{
 53}
 54
 55CanvasSurface::~CanvasSurface()
 56{
 57}
 58
 59void CanvasSurface::setSurfaceSize(const IntSize& size)
 60{
 61 m_size = size;
 62 m_hasCreatedImageBuffer = false;
 63 m_imageBuffer.clear();
 64}
 65
 66String CanvasSurface::toDataURL(const String& mimeType, ExceptionCode& ec)
 67{
 68 if (!m_originClean) {
 69 ec = SECURITY_ERR;
 70 return String();
 71 }
 72
 73 if (m_size.isEmpty() || !buffer())
 74 return String("data:,");
 75
 76 // FIXME: Make isSupportedImageMIMETypeForEncoding threadsafe (to allow this method to be used on a worker thread).
 77 if (mimeType.isNull() || !MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType))
 78 return buffer()->toDataURL("image/png");
 79
 80 return buffer()->toDataURL(mimeType);
 81}
 82
 83void CanvasSurface::willDraw(const FloatRect&)
 84{
 85 if (m_imageBuffer)
 86 m_imageBuffer->clearImage();
 87}
 88
 89IntRect CanvasSurface::convertLogicalToDevice(const FloatRect& logicalRect) const
 90{
 91 return IntRect(convertLogicalToDevice(logicalRect.location()), convertLogicalToDevice(logicalRect.size()));
 92}
 93
 94IntSize CanvasSurface::convertLogicalToDevice(const FloatSize& logicalSize) const
 95{
 96 float wf = ceilf(logicalSize.width() * m_pageScaleFactor);
 97 float hf = ceilf(logicalSize.height() * m_pageScaleFactor);
 98
 99 if (!(wf >= 1 && hf >= 1 && wf * hf <= MaxCanvasArea))
 100 return IntSize();
 101
 102 return IntSize(static_cast<unsigned>(wf), static_cast<unsigned>(hf));
 103}
 104
 105IntPoint CanvasSurface::convertLogicalToDevice(const FloatPoint& logicalPos) const
 106{
 107 float xf = logicalPos.x() * m_pageScaleFactor;
 108 float yf = logicalPos.y() * m_pageScaleFactor;
 109
 110 return IntPoint(static_cast<unsigned>(xf), static_cast<unsigned>(yf));
 111}
 112
 113void CanvasSurface::createImageBuffer() const
 114{
 115 ASSERT(!m_imageBuffer);
 116
 117 m_hasCreatedImageBuffer = true;
 118
 119 FloatSize unscaledSize(width(), height());
 120 IntSize size = convertLogicalToDevice(unscaledSize);
 121 if (!size.width() || !size.height())
 122 return;
 123
 124 m_imageBuffer = ImageBuffer::create(size);
 125 // The convertLogicalToDevice MaxCanvasArea check should prevent common cases
 126 // where ImageBuffer::create() returns 0, however we could still be low on memory.
 127 if (!m_imageBuffer)
 128 return;
 129 m_imageBuffer->context()->scale(FloatSize(size.width() / unscaledSize.width(), size.height() / unscaledSize.height()));
 130 m_imageBuffer->context()->setShadowsIgnoreTransforms(true);
 131}
 132
 133GraphicsContext* CanvasSurface::drawingContext() const
 134{
 135 return buffer() ? m_imageBuffer->context() : 0;
 136}
 137
 138ImageBuffer* CanvasSurface::buffer() const
 139{
 140 if (!m_hasCreatedImageBuffer)
 141 createImageBuffer();
 142 return m_imageBuffer.get();
 143}
 144
 145AffineTransform CanvasSurface::baseTransform() const
 146{
 147 ASSERT(m_hasCreatedImageBuffer);
 148 FloatSize unscaledSize(width(), height());
 149 IntSize size = convertLogicalToDevice(unscaledSize);
 150 AffineTransform transform;
 151 if (size.width() && size.height())
 152 transform.scaleNonUniform(size.width() / unscaledSize.width(), size.height() / unscaledSize.height());
 153 transform.multiply(m_imageBuffer->baseTransform());
 154 return transform;
 155}
 156
31157} // namespace WebCore

WebCore/dom/CanvasSurface.h

2626#ifndef CanvasSurface_h
2727#define CanvasSurface_h
2828
 29#include "AffineTransform.h"
 30#include "IntSize.h"
 31
 32#include <wtf/OwnPtr.h>
2933#include <wtf/Noncopyable.h>
3034
3135namespace WebCore {
3236
 37class AffineTransform;
 38class FloatPoint;
 39class FloatRect;
 40class FloatSize;
 41class GraphicsContext;
 42class ImageBuffer;
 43class IntPoint;
 44class String;
 45
 46typedef int ExceptionCode;
 47
3348class CanvasSurface : public Noncopyable {
3449public:
 50 CanvasSurface(float pageScaleFactor);
 51 virtual ~CanvasSurface();
 52
 53 int width() const { return m_size.width(); }
 54 int height() const { return m_size.height(); }
 55
 56 String toDataURL(const String& mimeType, ExceptionCode&);
 57
 58 const IntSize& size() const { return m_size; }
 59
 60 virtual void willDraw(const FloatRect&);
 61
 62 GraphicsContext* drawingContext() const;
 63
 64 ImageBuffer* buffer() const;
 65
 66 IntRect convertLogicalToDevice(const FloatRect&) const;
 67 IntSize convertLogicalToDevice(const FloatSize&) const;
 68 IntPoint convertLogicalToDevice(const FloatPoint&) const;
 69
 70 void setOriginTainted() { m_originClean = false; }
 71 bool originClean() const { return m_originClean; }
 72
 73 AffineTransform baseTransform() const;
 74
 75protected:
 76 void setSurfaceSize(const IntSize&);
 77 bool hasCreatedImageBuffer() const { return m_hasCreatedImageBuffer; }
 78
 79 static const int DefaultWidth;
 80 static const int DefaultHeight;
3581
3682private:
 83 void createImageBuffer() const;
 84
 85 static const float MaxCanvasArea;
 86
 87 IntSize m_size;
 88
 89 float m_pageScaleFactor;
 90 bool m_originClean;
 91
 92 // m_createdImageBuffer means we tried to malloc the buffer. We didn't necessarily get it.
 93 mutable bool m_hasCreatedImageBuffer;
 94 mutable OwnPtr<ImageBuffer> m_imageBuffer;
3795};
3896
3997} // namespace WebCore

WebCore/html/HTMLCanvasElement.cpp

2828#include "HTMLCanvasElement.h"
2929
3030#include "CanvasContextAttributes.h"
31 #include "CanvasGradient.h"
32 #include "CanvasPattern.h"
3331#include "CanvasRenderingContext2D.h"
3432#if ENABLE(3D_CANVAS)
3533#include "WebGLContextAttributes.h"
3634#include "WebGLRenderingContext.h"
3735#endif
 36#include "CanvasGradient.h"
 37#include "CanvasPattern.h"
3838#include "CanvasStyle.h"
3939#include "Chrome.h"
4040#include "Document.h"
41 #include "ExceptionCode.h"
4241#include "Frame.h"
4342#include "GraphicsContext.h"
4443#include "HTMLNames.h"
4544#include "ImageBuffer.h"
46 #include "MIMETypeRegistry.h"
4745#include "MappedAttribute.h"
4846#include "Page.h"
4947#include "RenderHTMLCanvas.h"

@@namespace WebCore {
5553
5654using namespace HTMLNames;
5755
58 // These values come from the WhatWG spec.
59 static const int defaultWidth = 300;
60 static const int defaultHeight = 150;
61 
62 // Firefox limits width/height to 32767 pixels, but slows down dramatically before it
63 // reaches that limit. We limit by area instead, giving us larger maximum dimensions,
64 // in exchange for a smaller maximum canvas size.
65 const float HTMLCanvasElement::MaxCanvasArea = 32768 * 8192; // Maximum canvas area in CSS pixels
66 
6756HTMLCanvasElement::HTMLCanvasElement(const QualifiedName& tagName, Document* doc)
6857 : HTMLElement(tagName, doc)
69  , m_size(defaultWidth, defaultHeight)
 58 , CanvasSurface(doc->frame() ? doc->frame()->page()->chrome()->scaleFactor() : 1)
7059 , m_observer(0)
71  , m_originClean(true)
7260 , m_ignoreReset(false)
73  , m_createdImageBuffer(false)
7461{
7562 ASSERT(hasTagName(canvasTag));
7663}

@@void HTMLCanvasElement::setWidth(int value)
133120 setAttribute(widthAttr, String::number(value));
134121}
135122
136 String HTMLCanvasElement::toDataURL(const String& mimeType, ExceptionCode& ec)
137 {
138  if (!m_originClean) {
139  ec = SECURITY_ERR;
140  return String();
141  }
142 
143  if (m_size.isEmpty() || !buffer())
144  return String("data:,");
145 
146  if (mimeType.isNull() || !MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType))
147  return buffer()->toDataURL("image/png");
148 
149  return buffer()->toDataURL(mimeType);
150 }
151 
152123CanvasRenderingContext* HTMLCanvasElement::getContext(const String& type, CanvasContextAttributes* attrs)
153124{
154125 // A Canvas can either be "2D" or "webgl" but never both. If you request a 2D canvas and the existing

@@CanvasRenderingContext* HTMLCanvasElement::getContext(const String& type, Canvas
193164
194165void HTMLCanvasElement::willDraw(const FloatRect& rect)
195166{
196  if (m_imageBuffer)
197  m_imageBuffer->clearImage();
198 
 167 CanvasSurface::willDraw(rect);
 168
199169 if (RenderBox* ro = renderBox()) {
200170 FloatRect destRect = ro->contentBoxRect();
201  FloatRect r = mapRect(rect, FloatRect(0, 0, m_size.width(), m_size.height()), destRect);
 171 FloatRect r = mapRect(rect, FloatRect(0, 0, size().width(), size().height()), destRect);
202172 r.intersect(destRect);
203173 if (m_dirtyRect.contains(r))
204174 return;

@@void HTMLCanvasElement::reset()
219189 bool ok;
220190 int w = getAttribute(widthAttr).toInt(&ok);
221191 if (!ok)
222  w = defaultWidth;
 192 w = DefaultWidth;
223193 int h = getAttribute(heightAttr).toInt(&ok);
224194 if (!ok)
225  h = defaultHeight;
 195 h = DefaultHeight;
226196
227  IntSize oldSize = m_size;
228  m_size = IntSize(w, h);
 197 IntSize oldSize = size();
 198 setSurfaceSize(IntSize(w, h));
229199
230200#if ENABLE(3D_CANVAS)
231201 if (m_context && m_context->is3d())
232202 static_cast<WebGLRenderingContext*>(m_context.get())->reshape(width(), height());
233203#endif
234204
235  bool hadImageBuffer = m_createdImageBuffer;
236  m_createdImageBuffer = false;
237  m_imageBuffer.clear();
 205 bool hadImageBuffer = hasCreatedImageBuffer();
238206 if (m_context && m_context->is2d())
239207 static_cast<CanvasRenderingContext2D*>(m_context.get())->reset();
240208
241209 if (RenderObject* renderer = this->renderer()) {
242210 if (m_rendererIsCanvas) {
243  if (oldSize != m_size)
 211 if (oldSize != size())
244212 toRenderHTMLCanvas(renderer)->canvasSizeChanged();
245213 if (hadImageBuffer)
246214 renderer->repaint();

@@void HTMLCanvasElement::paint(GraphicsContext* context, const IntRect& r)
267235 }
268236#endif
269237
270  if (m_imageBuffer) {
271  Image* image = m_imageBuffer->image();
272  if (image)
273  context->drawImage(image, DeviceColorSpace, r);
 238 if (hasCreatedImageBuffer()) {
 239 ImageBuffer* imageBuffer = buffer();
 240 if (imageBuffer) {
 241 Image* image = imageBuffer->image();
 242 if (image)
 243 context->drawImage(image, DeviceColorSpace, r);
 244 }
274245 }
275246
276247#if ENABLE(3D_CANVAS)

@@void HTMLCanvasElement::paint(GraphicsContext* context, const IntRect& r)
279250#endif
280251}
281252
282 IntRect HTMLCanvasElement::convertLogicalToDevice(const FloatRect& logicalRect) const
283 {
284  return IntRect(convertLogicalToDevice(logicalRect.location()), convertLogicalToDevice(logicalRect.size()));
285 }
286 
287 IntSize HTMLCanvasElement::convertLogicalToDevice(const FloatSize& logicalSize) const
288 {
289  float pageScaleFactor = document()->frame() ? document()->frame()->page()->chrome()->scaleFactor() : 1.0f;
290  float wf = ceilf(logicalSize.width() * pageScaleFactor);
291  float hf = ceilf(logicalSize.height() * pageScaleFactor);
292 
293  if (!(wf >= 1 && hf >= 1 && wf * hf <= MaxCanvasArea))
294  return IntSize();
295 
296  return IntSize(static_cast<unsigned>(wf), static_cast<unsigned>(hf));
297 }
298 
299 IntPoint HTMLCanvasElement::convertLogicalToDevice(const FloatPoint& logicalPos) const
300 {
301  float pageScaleFactor = document()->frame() ? document()->frame()->page()->chrome()->scaleFactor() : 1.0f;
302  float xf = logicalPos.x() * pageScaleFactor;
303  float yf = logicalPos.y() * pageScaleFactor;
304 
305  return IntPoint(static_cast<unsigned>(xf), static_cast<unsigned>(yf));
306 }
307 
308 void HTMLCanvasElement::createImageBuffer() const
309 {
310  ASSERT(!m_imageBuffer);
311 
312  m_createdImageBuffer = true;
313 
314  FloatSize unscaledSize(width(), height());
315  IntSize size = convertLogicalToDevice(unscaledSize);
316  if (!size.width() || !size.height())
317  return;
318 
319  m_imageBuffer = ImageBuffer::create(size);
320  // The convertLogicalToDevice MaxCanvasArea check should prevent common cases
321  // where ImageBuffer::create() returns NULL, however we could still be low on memory.
322  if (!m_imageBuffer)
323  return;
324  m_imageBuffer->context()->scale(FloatSize(size.width() / unscaledSize.width(), size.height() / unscaledSize.height()));
325  m_imageBuffer->context()->setShadowsIgnoreTransforms(true);
326 }
327 
328 GraphicsContext* HTMLCanvasElement::drawingContext() const
329 {
330  return buffer() ? m_imageBuffer->context() : 0;
331 }
332 
333 ImageBuffer* HTMLCanvasElement::buffer() const
334 {
335  if (!m_createdImageBuffer)
336  createImageBuffer();
337  return m_imageBuffer.get();
338 }
339 
340 AffineTransform HTMLCanvasElement::baseTransform() const
341 {
342  ASSERT(m_createdImageBuffer);
343  FloatSize unscaledSize(width(), height());
344  IntSize size = convertLogicalToDevice(unscaledSize);
345  AffineTransform transform;
346  if (size.width() && size.height())
347  transform.scaleNonUniform(size.width() / unscaledSize.width(), size.height() / unscaledSize.height());
348  transform.multiply(m_imageBuffer->baseTransform());
349  return transform;
350 }
351 
352253#if ENABLE(3D_CANVAS)
353254bool HTMLCanvasElement::is3D() const
354255{

WebCore/html/HTMLCanvasElement.h

2727#ifndef HTMLCanvasElement_h
2828#define HTMLCanvasElement_h
2929
30 #include "AffineTransform.h"
3130#include "CanvasSurface.h"
3231#include "FloatRect.h"
3332#include "HTMLElement.h"

@@namespace WebCore {
4039
4140class CanvasContextAttributes;
4241class CanvasRenderingContext;
43 class FloatPoint;
44 class FloatRect;
45 class FloatSize;
4642class GraphicsContext;
4743class HTMLCanvasElement;
48 class ImageBuffer;
49 class IntPoint;
5044class IntSize;
5145
5246class CanvasObserver {

@@public:
6357 HTMLCanvasElement(const QualifiedName&, Document*);
6458 virtual ~HTMLCanvasElement();
6559
66  int width() const { return m_size.width(); }
67  int height() const { return m_size.height(); }
6860 void setWidth(int);
6961 void setHeight(int);
7062
71  String toDataURL(const String& mimeType, ExceptionCode&);
72 
7363 CanvasRenderingContext* getContext(const String&, CanvasContextAttributes* attributes = 0);
7464
75  const IntSize& size() const { return m_size; }
76  void setSize(const IntSize& size)
 65 void setSize(const IntSize& newSize)
7766 {
78  if (size == m_size)
 67 if (newSize == size())
7968 return;
8069 m_ignoreReset = true;
81  setWidth(size.width());
82  setHeight(size.height());
 70 setWidth(newSize.width());
 71 setHeight(newSize.height());
8372 m_ignoreReset = false;
8473 reset();
8574 }
8675
87  void willDraw(const FloatRect&);
 76 virtual void willDraw(const FloatRect&);
8877
8978 void paint(GraphicsContext*, const IntRect&);
9079
91  GraphicsContext* drawingContext() const;
92 
93  ImageBuffer* buffer() const;
94 
95  IntRect convertLogicalToDevice(const FloatRect&) const;
96  IntSize convertLogicalToDevice(const FloatSize&) const;
97  IntPoint convertLogicalToDevice(const FloatPoint&) const;
98 
99  void setOriginTainted() { m_originClean = false; }
100  bool originClean() const { return m_originClean; }
101 
10280 void setObserver(CanvasObserver* observer) { m_observer = observer; }
10381
104  AffineTransform baseTransform() const;
105 
10682 CanvasRenderingContext* renderingContext() const { return m_context.get(); }
10783
10884#if ENABLE(3D_CANVAS)

@@private:
11894 virtual void parseMappedAttribute(MappedAttribute*);
11995 virtual RenderObject* createRenderer(RenderArena*, RenderStyle*);
12096
121  void createImageBuffer() const;
12297 void reset();
12398
124  static const float MaxCanvasArea;
125 
12699 bool m_rendererIsCanvas;
127100
128101 OwnPtr<CanvasRenderingContext> m_context;
129  IntSize m_size;
130102 CanvasObserver* m_observer;
131103
132  bool m_originClean;
133104 bool m_ignoreReset;
134105 FloatRect m_dirtyRect;
135 
136  // m_createdImageBuffer means we tried to malloc the buffer. We didn't necessarily get it.
137  mutable bool m_createdImageBuffer;
138  mutable OwnPtr<ImageBuffer> m_imageBuffer;
139106};
140107
141108} //namespace

WebCore/platform/MIMETypeRegistry.cpp

@@bool MIMETypeRegistry::isSupportedImageResourceMIMEType(const String& mimeType)
369369
370370bool MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(const String& mimeType)
371371{
 372 ASSERT(isMainThread());
 373
372374 if (mimeType.isEmpty())
373375 return false;
374376 if (!supportedImageMIMETypesForEncoding)

WebCore/platform/graphics/Image.cpp

@@Image::~Image()
5353
5454Image* Image::nullImage()
5555{
 56 ASSERT(isMainThread());
5657 DEFINE_STATIC_LOCAL(RefPtr<Image>, nullImage, (BitmapImage::create()));;
5758 return nullImage.get();
5859}

WebCore/platform/graphics/cg/ImageBufferCG.cpp

3838#include <wtf/Assertions.h>
3939#include <wtf/OwnArrayPtr.h>
4040#include <wtf/RetainPtr.h>
 41#include <wtf/Threading.h>
4142#include <math.h>
4243
4344using namespace std;

@@static RetainPtr<CFStringRef> utiFromMIMEType(const String& mimeType)
254255 RetainPtr<CFStringRef> mimeTypeCFString(AdoptCF, mimeType.createCFString());
255256 return RetainPtr<CFStringRef>(AdoptCF, UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType, mimeTypeCFString.get(), 0));
256257#else
 258 ASSERT(isMainThread()); // It is unclear if CFSTR is threadsafe.
 259
257260 // FIXME: Add Windows support for all the supported UTIs when a way to convert from MIMEType to UTI reliably is found.
258261 // For now, only support PNG, JPEG, and GIF. See <rdar://problem/6095286>.
259262 static const CFStringRef kUTTypePNG = CFSTR("public.png");