diff options
author | Steve Block <steveblock@google.com> | 2009-10-08 17:19:54 +0100 |
---|---|---|
committer | Steve Block <steveblock@google.com> | 2009-10-20 00:41:58 +0100 |
commit | 231d4e3152a9c27a73b6ac7badbe6be673aa3ddf (patch) | |
tree | a6c7e2d6cd7bfa7011cc39abbb436142d7a4a7c8 /WebCore/platform/graphics/wince | |
parent | e196732677050bd463301566a68a643b6d14b907 (diff) | |
download | external_webkit-231d4e3152a9c27a73b6ac7badbe6be673aa3ddf.zip external_webkit-231d4e3152a9c27a73b6ac7badbe6be673aa3ddf.tar.gz external_webkit-231d4e3152a9c27a73b6ac7badbe6be673aa3ddf.tar.bz2 |
Merge webkit.org at R49305 : Automatic merge by git.
Change-Id: I8968561bc1bfd72b8923b7118d3728579c6dbcc7
Diffstat (limited to 'WebCore/platform/graphics/wince')
-rw-r--r-- | WebCore/platform/graphics/wince/ColorWince.cpp | 38 | ||||
-rw-r--r-- | WebCore/platform/graphics/wince/FontCustomPlatformData.cpp | 12 | ||||
-rw-r--r-- | WebCore/platform/graphics/wince/FontCustomPlatformData.h | 6 | ||||
-rw-r--r-- | WebCore/platform/graphics/wince/GradientWince.cpp | 52 | ||||
-rw-r--r-- | WebCore/platform/graphics/wince/ImageBufferData.h | 34 | ||||
-rw-r--r-- | WebCore/platform/graphics/wince/ImageBufferWince.cpp | 246 | ||||
-rw-r--r-- | WebCore/platform/graphics/wince/MediaPlayerPrivateWince.h | 129 | ||||
-rw-r--r-- | WebCore/platform/graphics/wince/MediaPlayerProxy.cpp | 145 | ||||
-rw-r--r-- | WebCore/platform/graphics/wince/MediaPlayerProxy.h | 70 | ||||
-rw-r--r-- | WebCore/platform/graphics/wince/PathWince.cpp | 163 | ||||
-rw-r--r-- | WebCore/platform/graphics/wince/PlatformPathWince.cpp | 810 | ||||
-rw-r--r-- | WebCore/platform/graphics/wince/PlatformPathWince.h | 178 | ||||
-rw-r--r-- | WebCore/platform/graphics/wince/WinceGraphicsExtras.h | 39 |
13 files changed, 1916 insertions, 6 deletions
diff --git a/WebCore/platform/graphics/wince/ColorWince.cpp b/WebCore/platform/graphics/wince/ColorWince.cpp new file mode 100644 index 0000000..820b9d2 --- /dev/null +++ b/WebCore/platform/graphics/wince/ColorWince.cpp @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2007-2008 Torch Mobile, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include "config.h" +#include "Color.h" + +#include "NotImplemented.h" + +namespace WebCore { + +Color focusRingColor() +{ + return Color(0, 0, 0); +} + +void setFocusRingColorChangeFunction(void (*)()) +{ + notImplemented(); +} + +} // namespace WebCore diff --git a/WebCore/platform/graphics/wince/FontCustomPlatformData.cpp b/WebCore/platform/graphics/wince/FontCustomPlatformData.cpp index 7c6853c..699ff25 100644 --- a/WebCore/platform/graphics/wince/FontCustomPlatformData.cpp +++ b/WebCore/platform/graphics/wince/FontCustomPlatformData.cpp @@ -33,6 +33,11 @@ static CustomFontCache* g_customFontCache = 0; bool renameFont(SharedBuffer* fontData, const String& fontName); +void setCustomFontCache(CustomFontCache* cache) +{ + g_customFontCache = cache; +} + FontCustomPlatformData::~FontCustomPlatformData() { if (g_customFontCache && !m_name.isEmpty()) @@ -66,11 +71,12 @@ static String createUniqueFontName() return fontName.replace('/', '_'); } -FontCustomPlatformData* createFontCustomPlatformData(CachedFont* cachedFont) +FontCustomPlatformData* createFontCustomPlatformData(const SharedBuffer* buffer) { - if (g_customFontCache && cachedFont->CachedResource::data()) { + if (g_customFontCache) { String fontName = createUniqueFontName(); - if (renameFont(cachedFont->CachedResource::data(), fontName) && g_customFontCache->registerFont(fontName, cachedFont)) + RefPtr<SharedBuffer> localBuffer = SharedBuffer::create(buffer->data(), buffer->size()); + if (renameFont(localBuffer.get(), fontName) && g_customFontCache->registerFont(fontName, localBuffer.get())) return new FontCustomPlatformData(fontName); } return 0; diff --git a/WebCore/platform/graphics/wince/FontCustomPlatformData.h b/WebCore/platform/graphics/wince/FontCustomPlatformData.h index b1f64a0..89d1fdd 100644 --- a/WebCore/platform/graphics/wince/FontCustomPlatformData.h +++ b/WebCore/platform/graphics/wince/FontCustomPlatformData.h @@ -32,7 +32,7 @@ namespace WebCore { class CustomFontCache { public: - virtual bool registerFont(const String& fontName, CachedFont*) = 0; + virtual bool registerFont(const String& fontName, const SharedBuffer*) = 0; virtual void unregisterFont(const String& fontName) = 0; }; @@ -48,8 +48,8 @@ namespace WebCore { String m_name; }; - FontCustomPlatformData* createFontCustomPlatformData(CachedFont*); - + FontCustomPlatformData* createFontCustomPlatformData(const SharedBuffer*); + void setCustomFontCache(CustomFontCache*); } #endif diff --git a/WebCore/platform/graphics/wince/GradientWince.cpp b/WebCore/platform/graphics/wince/GradientWince.cpp new file mode 100644 index 0000000..49fa970 --- /dev/null +++ b/WebCore/platform/graphics/wince/GradientWince.cpp @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2009 Torch Mobile, Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#include "config.h" +#include "Gradient.h" + +#include "GraphicsContext.h" + +namespace WebCore { + +void Gradient::platformDestroy() +{ +} + +static inline bool compareStops(const Gradient::ColorStop& a, const Gradient::ColorStop& b) +{ + return a.stop < b.stop; +} + +const Vector<Gradient::ColorStop>& Gradient::getStops() const +{ + if (!m_stopsSorted) { + if (m_stops.size()) + std::stable_sort(m_stops.begin(), m_stops.end(), compareStops); + m_stopsSorted = true; + } + return m_stops; +} + +void Gradient::fill(GraphicsContext* c, const FloatRect& r) +{ + c->fillRect(r, this); +} + +} diff --git a/WebCore/platform/graphics/wince/ImageBufferData.h b/WebCore/platform/graphics/wince/ImageBufferData.h new file mode 100644 index 0000000..01b7d06 --- /dev/null +++ b/WebCore/platform/graphics/wince/ImageBufferData.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2009 Torch Mobile, Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef ImageBufferData_h +#define ImageBufferData_h + +namespace WebCore { + + class IntSize; + class ImageBufferData { + public: + ImageBufferData(const IntSize& size); + RefPtr<SharedBitmap> m_bitmap; + }; + +} // namespace WebCore + +#endif // ImageBufferData_h diff --git a/WebCore/platform/graphics/wince/ImageBufferWince.cpp b/WebCore/platform/graphics/wince/ImageBufferWince.cpp new file mode 100644 index 0000000..3417f5f --- /dev/null +++ b/WebCore/platform/graphics/wince/ImageBufferWince.cpp @@ -0,0 +1,246 @@ +/* + * Copyright (C) 2009 Torch Mobile, Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" +#include "ImageBuffer.h" + +#include "Base64.h" +#include "GraphicsContext.h" +#include "Image.h" +#include "ImageData.h" +#include "JPEGEncoder.h" +#include "PNGEncoder.h" +#include "SharedBitmap.h" + +namespace WebCore { + +class BufferedImage: public Image { + +public: + BufferedImage(const ImageBufferData* data) + : m_data(data) + { + } + + virtual IntSize size() const { return IntSize(m_data->m_bitmap->width(), m_data->m_bitmap->height()); } + virtual void destroyDecodedData(bool destroyAll = true) {} + virtual unsigned decodedSize() const { return 0; } + virtual void draw(GraphicsContext*, const FloatRect& dstRect, const FloatRect& srcRect, CompositeOperator); + virtual void drawPattern(GraphicsContext*, const FloatRect& srcRect, const TransformationMatrix& patternTransform, + const FloatPoint& phase, CompositeOperator, const FloatRect& destRect); + + const ImageBufferData* m_data; +}; + +void BufferedImage::draw(GraphicsContext* ctxt, const FloatRect& dstRect, const FloatRect& srcRect, CompositeOperator compositeOp) +{ + IntRect intDstRect = enclosingIntRect(dstRect); + IntRect intSrcRect(srcRect); + m_data->m_bitmap->draw(ctxt, intDstRect, intSrcRect, compositeOp); +} + +void BufferedImage::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRectIn, const TransformationMatrix& patternTransform, + const FloatPoint& phase, CompositeOperator op, const FloatRect& destRect) +{ + m_data->m_bitmap->drawPattern(ctxt, tileRectIn, patternTransform, phase, op, destRect, size()); +} + +ImageBufferData::ImageBufferData(const IntSize& size) +: m_bitmap(SharedBitmap::createInstance(false, size.width(), size.height(), false)) +{ + // http://www.w3.org/TR/2009/WD-html5-20090212/the-canvas-element.html#canvaspixelarray + // "When the canvas is initialized it must be set to fully transparent black." + m_bitmap->resetPixels(true); + m_bitmap->setHasAlpha(true); +} + +ImageBuffer::ImageBuffer(const IntSize& size, ImageColorSpace colorSpace, bool& success) + : m_data(size) + , m_size(size) +{ + // FIXME: colorSpace is not used + UNUSED_PARAM(colorSpace); + + m_context.set(new GraphicsContext(0)); + m_context->setBitmap(m_data.m_bitmap); + success = true; +} + +ImageBuffer::~ImageBuffer() +{ +} + +GraphicsContext* ImageBuffer::context() const +{ + return m_context.get(); +} + +Image* ImageBuffer::image() const +{ + if (!m_image) + m_image = adoptRef(new BufferedImage(&m_data)); + + return m_image.get(); +} + +template <bool premultiplied> PassRefPtr<ImageData> +static getImageData(const IntRect& rect, const SharedBitmap* bitmap) +{ + PassRefPtr<ImageData> imageData = ImageData::create(rect.width(), rect.height()); + + const unsigned char* src = static_cast<const unsigned char*>(bitmap->bytes()); + if (!src) + return imageData; + + IntRect sourceRect(0, 0, bitmap->width(), bitmap->height()); + sourceRect.intersect(rect); + if (sourceRect.isEmpty()) + return imageData; + + unsigned char* dst = imageData->data()->data()->data(); + memset(dst, 0, imageData->data()->data()->length()); + src += (sourceRect.y() * bitmap->width() + sourceRect.x()) * 4; + dst += ((sourceRect.y() - rect.y()) * imageData->width() + sourceRect.x() - rect.x()) * 4; + int bytesToCopy = sourceRect.width() * 4; + int srcSkip = (bitmap->width() - sourceRect.width()) * 4; + int dstSkip = (imageData->width() - sourceRect.width()) * 4; + const unsigned char* dstEnd = dst + sourceRect.height() * imageData->width() * 4; + while (dst < dstEnd) { + const unsigned char* dstRowEnd = dst + bytesToCopy; + while (dst < dstRowEnd) { + // Convert ARGB little endian to RGBA big endian + int blue = *src++; + int green = *src++; + int red = *src++; + int alpha = *src++; + if (premultiplied) { + *dst++ = static_cast<unsigned char>((red * alpha + 254) / 255); + *dst++ = static_cast<unsigned char>((green * alpha + 254) / 255); + *dst++ = static_cast<unsigned char>((blue * alpha + 254) / 255); + *dst++ = static_cast<unsigned char>(alpha); + } else { + *dst++ = static_cast<unsigned char>(red); + *dst++ = static_cast<unsigned char>(green); + *dst++ = static_cast<unsigned char>(blue); + *dst++ = static_cast<unsigned char>(alpha); + ++src; + } + } + src += srcSkip; + dst += dstSkip; + } + + return imageData; +} + +PassRefPtr<ImageData> ImageBuffer::getUnmultipliedImageData(const IntRect& rect) const +{ + return getImageData<false>(rect, m_data.m_bitmap.get()); +} + +PassRefPtr<ImageData> ImageBuffer::getPremultipliedImageData(const IntRect& rect) const +{ + return getImageData<true>(rect, m_data.m_bitmap.get()); +} + +template <bool premultiplied> +static void putImageData(ImageData* source, const IntRect& sourceRect, const IntPoint& destPoint, SharedBitmap* bitmap) +{ + unsigned char* dst = (unsigned char*)bitmap->bytes(); + if (!dst) + return; + + IntRect destRect(destPoint, sourceRect.size()); + destRect.intersect(IntRect(0, 0, bitmap->width(), bitmap->height())); + + if (destRect.isEmpty()) + return; + + const unsigned char* src = source->data()->data()->data(); + dst += (destRect.y() * bitmap->width() + destRect.x()) * 4; + src += (sourceRect.y() * source->width() + sourceRect.x()) * 4; + int bytesToCopy = destRect.width() * 4; + int dstSkip = (bitmap->width() - destRect.width()) * 4; + int srcSkip = (source->width() - destRect.width()) * 4; + const unsigned char* dstEnd = dst + destRect.height() * bitmap->width() * 4; + while (dst < dstEnd) { + const unsigned char* dstRowEnd = dst + bytesToCopy; + while (dst < dstRowEnd) { + // Convert RGBA big endian to ARGB little endian + int red = *src++; + int green = *src++; + int blue = *src++; + int alpha = *src++; + if (premultiplied) { + *dst++ = static_cast<unsigned char>(blue * 255 / alpha); + *dst++ = static_cast<unsigned char>(green * 255 / alpha); + *dst++ = static_cast<unsigned char>(red * 255 / alpha); + *dst++ = static_cast<unsigned char>(alpha); + } else { + *dst++ = static_cast<unsigned char>(blue); + *dst++ = static_cast<unsigned char>(green); + *dst++ = static_cast<unsigned char>(red); + *dst++ = static_cast<unsigned char>(alpha); + } + } + src += srcSkip; + dst += dstSkip; + } +} + +void ImageBuffer::putUnmultipliedImageData(ImageData* source, const IntRect& sourceRect, const IntPoint& destPoint) +{ + putImageData<false>(source, sourceRect, destPoint, m_data.m_bitmap.get()); +} + +void ImageBuffer::putPremultipliedImageData(ImageData* source, const IntRect& sourceRect, const IntPoint& destPoint) +{ + putImageData<true>(source, sourceRect, destPoint, m_data.m_bitmap.get()); +} + +String ImageBuffer::toDataURL(const String& mimeType) const +{ + if (!m_data.m_bitmap->bytes()) + return "data:,"; + + Vector<char> output; + const char* header; + if (mimeType.lower() == "image/png") { + if (!compressBitmapToPng(m_data.m_bitmap.get(), output)) + return "data:,"; + header = "data:image/png;base64,"; + } else { + if (!compressBitmapToJpeg(m_data.m_bitmap.get(), output)) + return "data:,"; + header = "data:image/jpeg;base64,"; + } + + Vector<char> base64; + base64Encode(output, base64); + + output.clear(); + + Vector<char> url; + url.append(header, strlen(header)); + url.append(base64); + + return String(url.data(), url.size()); +} + +} diff --git a/WebCore/platform/graphics/wince/MediaPlayerPrivateWince.h b/WebCore/platform/graphics/wince/MediaPlayerPrivateWince.h new file mode 100644 index 0000000..2d6c358 --- /dev/null +++ b/WebCore/platform/graphics/wince/MediaPlayerPrivateWince.h @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef MediaPlayerPrivateWince_h +#define MediaPlayerPrivateWince_h + +#if ENABLE(VIDEO) + +#include "MediaPlayerPrivate.h" +#include "Timer.h" +#include <wtf/OwnPtr.h> + +namespace WebCore { + + class GraphicsContext; + class IntSize; + class IntRect; + class String; + + class MediaPlayerPrivate : public MediaPlayerPrivateInterface { + public: + static void registerMediaEngine(MediaEngineRegistrar); + + ~MediaPlayerPrivate(); + + IntSize naturalSize() const; + bool hasVideo() const; + + void load(const String& url); + void cancelLoad(); + + void play(); + void pause(); + + bool paused() const; + bool seeking() const; + + float duration() const; + float currentTime() const; + void seek(float time); + void setEndTime(float); + + void setRate(float); + void setVolume(float); + + int dataRate() const; + + MediaPlayer::NetworkState networkState() const { return m_networkState; } + MediaPlayer::ReadyState readyState() const { return m_readyState; } + + PassRefPtr<TimeRanges> buffered() const; + float maxTimeSeekable() const; + unsigned bytesLoaded() const; + bool totalBytesKnown() const; + unsigned totalBytes() const; + + void setVisible(bool); + void setSize(const IntSize&); + + void loadStateChanged(); + void didEnd(); + + void paint(GraphicsContext*, const IntRect&); + + private: + MediaPlayerPrivate(MediaPlayer*); + + void updateStates(); + void doSeek(); + void cancelSeek(); + void seekTimerFired(Timer<MediaPlayerPrivate>*); + float maxTimeLoaded() const; + void sawUnsupportedTracks(); +#if ENABLE(PLUGIN_PROXY_FOR_VIDEO) + void setMediaPlayerProxy(WebMediaPlayerProxy*); + void setPoster(const String& url); + void deliverNotification(MediaPlayerProxyNotificationType); +#endif + + // engine support + static MediaPlayerPrivateInterface* create(MediaPlayer*); + static void getSupportedTypes(HashSet<String>& types); + static MediaPlayer::SupportsType supportsType(const String& type, const String& codecs); + static bool isAvailable(); + + MediaPlayer* m_player; + float m_seekTo; + float m_endTime; + Timer<MediaPlayerPrivate> m_seekTimer; + MediaPlayer::NetworkState m_networkState; + MediaPlayer::ReadyState m_readyState; + unsigned m_enabledTrackCount; + unsigned m_totalTrackCount; + bool m_hasUnsupportedTracks; + bool m_startedPlaying; + bool m_isStreaming; +#if ENABLE(PLUGIN_PROXY_FOR_VIDEO) + WebMediaPlayerProxy* m_proxy; +#endif + }; + +} + +#endif + +#endif diff --git a/WebCore/platform/graphics/wince/MediaPlayerProxy.cpp b/WebCore/platform/graphics/wince/MediaPlayerProxy.cpp new file mode 100644 index 0000000..9673d18 --- /dev/null +++ b/WebCore/platform/graphics/wince/MediaPlayerProxy.cpp @@ -0,0 +1,145 @@ +/* + * Copyright (C) 2009 Torch Mobile, Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#if ENABLE(VIDEO) + +#include "config.h" +#include "MediaPlayerProxy.h" + +#include "c_class.h" +#include "c_instance.h" +#include "c_runtime.h" +#include "DocumentLoader.h" +#include "HTMLPlugInElement.h" +#include "HTMLVideoElement.h" +#include "JSDOMBinding.h" +#include "JSPluginElementFunctions.h" +#include "MediaPlayer.h" +#include "Node.h" +#include "npruntime_impl.h" +#include "PlatformString.h" +#include "PluginView.h" +#include "RenderPartObject.h" +#include "RenderWidget.h" +#include "runtime.h" +#include <runtime/Identifier.h> +#include "Widget.h" + +using namespace JSC; + +namespace WebCore { + +using namespace Bindings; +using namespace HTMLNames; + +WebMediaPlayerProxy::WebMediaPlayerProxy(MediaPlayer* player) + : m_mediaPlayer(player) + , m_init(false) + , m_hasSentResponseToPlugin(false) +{ + if (!m_init) + initEngine(); +} + +WebMediaPlayerProxy::~WebMediaPlayerProxy() +{ + m_instance.release(); +} + +ScriptInstance WebMediaPlayerProxy::pluginInstance() +{ + if (!m_instance) { + RenderObject* r = element()->renderer(); + if (!r || !r->isWidget()) + return 0; + + Frame* frame = element()->document()->frame(); + + RenderWidget* renderWidget = static_cast<RenderWidget*>(element()->renderer()); + if (renderWidget && renderWidget->widget()) + m_instance = frame->script()->createScriptInstanceForWidget(renderWidget->widget()); + } + + return m_instance; +} + +void WebMediaPlayerProxy::load(const String& url) +{ + if (!m_init) + initEngine(); + if (m_init) + invokeMethod("play"); +} + +void WebMediaPlayerProxy::initEngine() +{ + HTMLMediaElement* element = static_cast<HTMLMediaElement*>(m_mediaPlayer->mediaPlayerClient()); + String url = element->initialURL(); + + if (url.isEmpty()) + return; + + Frame* frame = element->document()->frame(); + Vector<String> paramNames; + Vector<String> paramValues; + String serviceType; + + // add all attributes set on the embed object + if (NamedNodeMap* attributes = element->attributes()) { + for (unsigned i = 0; i < attributes->length(); ++i) { + Attribute* it = attributes->attributeItem(i); + paramNames.append(it->name().localName().string()); + paramValues.append(it->value().string()); + } + } + serviceType = "application/x-mplayer2"; + frame->loader()->requestObject(static_cast<RenderPartObject*>(element->renderer()), url, nullAtom, serviceType, paramNames, paramValues); + m_init = true; + +} + +HTMLMediaElement* WebMediaPlayerProxy::element() +{ + return static_cast<HTMLMediaElement*>(m_mediaPlayer->mediaPlayerClient()); + +} + +void WebMediaPlayerProxy::invokeMethod(const String& methodName) +{ + Frame* frame = element()->document()->frame(); + RootObject *root = frame->script()->bindingRootObject(); + if (!root) + return; + ExecState *exec = root->globalObject()->globalExec(); + Instance* instance = pluginInstance().get(); + if (!instance) + return; + + instance->begin(); + Class *aClass = instance->getClass(); + Identifier iden(exec, methodName); + MethodList methodList = aClass->methodsNamed(iden, instance); + ArgList args; + instance->invokeMethod(exec, methodList , args); + instance->end(); +} + +} + +#endif diff --git a/WebCore/platform/graphics/wince/MediaPlayerProxy.h b/WebCore/platform/graphics/wince/MediaPlayerProxy.h new file mode 100644 index 0000000..05f9b21 --- /dev/null +++ b/WebCore/platform/graphics/wince/MediaPlayerProxy.h @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2009 Torch Mobile, Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef MediaPlayerProxy_h +#define MediaPlayerProxy_h + +#if ENABLE(VIDEO) + +#include "ScriptInstance.h" + +namespace WebCore { + + class IntRect; + class IntSize; + class String; + class MediaPlayer; + class PluginView; + class HTMLMediaElement; + + enum MediaPlayerProxyNotificationType { + MediaPlayerNotificationPlayPauseButtonPressed, + Idle, + Loading, + Loaded, + FormatError, + NetworkError, + DecodeError + }; + + class WebMediaPlayerProxy { + public: + WebMediaPlayerProxy(MediaPlayer* player); + ~WebMediaPlayerProxy(); + + MediaPlayer* mediaPlayer() {return m_mediaPlayer;} + void initEngine(); + void load(const String& url); + HTMLMediaElement* element(); + void invokeMethod(const String& methodName); + ScriptInstance pluginInstance(); + + private: + MediaPlayer* m_mediaPlayer; + bool m_init; + WebCore::PluginView* m_pluginView; + bool m_hasSentResponseToPlugin; + ScriptInstance m_instance; + }; + +} +#endif // ENABLE(VIDEO) + +#endif diff --git a/WebCore/platform/graphics/wince/PathWince.cpp b/WebCore/platform/graphics/wince/PathWince.cpp new file mode 100644 index 0000000..7589ccb --- /dev/null +++ b/WebCore/platform/graphics/wince/PathWince.cpp @@ -0,0 +1,163 @@ +/* + * Copyright (C) 2007-2009 Torch Mobile, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" +#include "Path.h" + +#include "FloatRect.h" +#include "NotImplemented.h" +#include "PlatformPathWince.h" +#include "PlatformString.h" +#include "TransformationMatrix.h" +#include <wtf/OwnPtr.h> + +namespace WebCore { + +Path::Path() + : m_path(new PlatformPath()) +{ +} + +Path::Path(const Path& other) + : m_path(new PlatformPath(*other.m_path)) +{ +} + +Path::~Path() +{ + delete m_path; +} + +Path& Path::operator=(const Path& other) +{ + if (&other != this) { + delete m_path; + m_path = new PlatformPath(*other.m_path); + } + return *this; +} + +bool Path::contains(const FloatPoint& point, WindRule rule) const +{ + return m_path->contains(point, rule); +} + +void Path::translate(const FloatSize& size) +{ + m_path->translate(size); +} + +FloatRect Path::boundingRect() const +{ + return m_path->boundingRect(); +} + +void Path::moveTo(const FloatPoint& point) +{ + m_path->moveTo(point); +} + +void Path::addLineTo(const FloatPoint& point) +{ + m_path->addLineTo(point); +} + +void Path::addQuadCurveTo(const FloatPoint& cp, const FloatPoint& p) +{ + m_path->addQuadCurveTo(cp, p); +} + +void Path::addBezierCurveTo(const FloatPoint& cp1, const FloatPoint& cp2, const FloatPoint& p) +{ + m_path->addBezierCurveTo(cp1, cp2, p); +} + +void Path::addArcTo(const FloatPoint& p1, const FloatPoint& p2, float radius) +{ + m_path->addArcTo(p1, p2, radius); +} + +void Path::closeSubpath() +{ + m_path->closeSubpath(); +} + +void Path::addArc(const FloatPoint& p, float r, float sar, float ear, bool anticlockwise) +{ + m_path->addEllipse(p, r, r, sar, ear, anticlockwise); +} + +void Path::addRect(const FloatRect& r) +{ + m_path->addRect(r); +} + +void Path::addEllipse(const FloatRect& r) +{ + m_path->addEllipse(r); +} + +void Path::clear() +{ + m_path->clear(); +} + +bool Path::isEmpty() const +{ + return m_path->isEmpty(); +} + +String Path::debugString() const +{ + return m_path->debugString(); +} + +void Path::apply(void* info, PathApplierFunction function) const +{ + m_path->apply(info, function); +} + +void Path::transform(const TransformationMatrix& t) +{ + m_path->transform(t); +} + +FloatRect Path::strokeBoundingRect(StrokeStyleApplier *) +{ + notImplemented(); + return FloatRect(); +} + +bool Path::strokeContains(StrokeStyleApplier*, const FloatPoint&) const +{ + notImplemented(); + return false; +} + +bool Path::hasCurrentPoint() const +{ + // Not sure if this is correct. At the meantime, we do what other ports + // do. + // See https://bugs.webkit.org/show_bug.cgi?id=27266, + // https://bugs.webkit.org/show_bug.cgi?id=27187, and + // http://trac.webkit.org/changeset/45873 + return !isEmpty(); +} + +} diff --git a/WebCore/platform/graphics/wince/PlatformPathWince.cpp b/WebCore/platform/graphics/wince/PlatformPathWince.cpp new file mode 100644 index 0000000..66fad50 --- /dev/null +++ b/WebCore/platform/graphics/wince/PlatformPathWince.cpp @@ -0,0 +1,810 @@ +/* + * Copyright (C) 2007-2009 Torch Mobile, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" +#include "PlatformPathWince.h" + +#include "FloatRect.h" +#include "GraphicsContext.h" +#include "Path.h" +#include "PlatformString.h" +#include "TransformationMatrix.h" +#include "WinceGraphicsExtras.h" +#include <wtf/MathExtras.h> +#include <wtf/OwnPtr.h> + +#include <windows.h> + +namespace WebCore { + +// Implemented in GraphicsContextWince.cpp +void getEllipsePointByAngle(double angle, double a, double b, float& x, float& y); + +static void quadCurve(int segments, Vector<PathPoint>& pts, const PathPoint* control) +{ + const float step = 1.0 / segments; + register float tA = 0.0; + register float tB = 1.0; + + float c1x = control[0].x(); + float c1y = control[0].y(); + float c2x = control[1].x(); + float c2y = control[1].y(); + float c3x = control[2].x(); + float c3y = control[2].y(); + + const int offset = pts.size(); + pts.resize(offset + segments); + PathPoint pp; + pp.m_x = c1x; + pp.m_y = c1y; + + for (int i = 1; i < segments; ++i) { + tA += step; + tB -= step; + + const float a = tB * tB; + const float b = 2.0 * tA * tB; + const float c = tA * tA; + + pp.m_x = c1x * a + c2x * b + c3x * c; + pp.m_y = c1y * a + c2y * b + c3y * c; + + pts[offset + i - 1] = pp; + } + + pp.m_x = c3x; + pp.m_y = c3y; + pts[offset + segments - 1] = pp; +} + +static inline void bezier(int segments, Vector<PathPoint>& pts, const PathPoint* control) +{ + const float step = 1.0 / segments; + register float tA = 0.0; + register float tB = 1.0; + + float c1x = control[0].x(); + float c1y = control[0].y(); + float c2x = control[1].x(); + float c2y = control[1].y(); + float c3x = control[2].x(); + float c3y = control[2].y(); + float c4x = control[3].x(); + float c4y = control[3].y(); + + const int offset = pts.size(); + pts.resize(offset + segments); + PathPoint pp; + pp.m_x = c1x; + pp.m_y = c1y; + + for (int i = 1; i < segments; ++i) { + tA += step; + tB -= step; + const float tAsq = tA * tA; + const float tBsq = tB * tB; + + const float a = tBsq * tB; + const float b = 3.0 * tA * tBsq; + const float c = 3.0 * tB * tAsq; + const float d = tAsq * tA; + + pp.m_x = c1x * a + c2x * b + c3x * c + c4x * d; + pp.m_y = c1y * a + c2y * b + c3y * c + c4y * d; + + pts[offset + i - 1] = pp; + } + + pp.m_x = c4x; + pp.m_y = c4y; + pts[offset + segments - 1] = pp; +} + +static bool containsPoint(const FloatRect& r, const FloatPoint& p) +{ + return p.x() >= r.x() && p.y() >= r.y() && p.x() < r.right() && p.y() < r.bottom(); +} + +static void normalizeAngle(float& angle) +{ + angle = fmod(angle, 2 * piFloat); + if (angle < 0) + angle += 2 * piFloat; + if (angle < 0.00001f) + angle = 0; +} + +static void transformArcPoint(float& x, float& y, const FloatPoint& c) +{ + x += c.x(); + y += c.y(); +} + +static void inflateRectToContainPoint(FloatRect& r, float x, float y) +{ + if (r.isEmpty()) { + r.setX(x); + r.setY(y); + r.setSize(FloatSize(1, 1)); + return; + } + if (x < r.x()) { + r.setWidth(r.right() - x); + r.setX(x); + } else { + float w = x - r.x() + 1; + if (w > r.width()) + r.setWidth(w); + } + if (y < r.y()) { + r.setHeight(r.bottom() - y); + r.setY(y); + } else { + float h = y - r.y() + 1; + if (h > r.height()) + r.setHeight(h); + } +} + +// return 0-based value: 0 - first Quadrant ( 0 - 90 degree) +static inline int quadrant(const PathPoint& point, const PathPoint& origin) +{ + return point.m_x < origin.m_x ? + (point.m_y < origin.m_y ? 2 : 1) + : (point.m_y < origin.m_y ? 3 : 0); +} + +static inline bool isQuadrantOnLeft(int q) { return q == 1 || q == 2; } +static inline bool isQuadrantOnRight(int q) { return q == 0 || q == 3; } +static inline bool isQuadrantOnTop(int q) { return q == 2 || q == 3; } +static inline bool isQuadrantOnBottom(int q) { return q == 0 || q == 1; } + +static inline int nextQuadrant(int q) { return q == 3 ? 0 : q + 1; } +static inline int quadrantDiff(int q1, int q2) +{ + int d = q1 - q2; + while (d < 0) + d += 4; + return d; +} + +struct PathVector { + float m_x; + float m_y; + + PathVector() : m_x(0), m_y(0) {} + PathVector(float x, float y) : m_x(x), m_y(y) {} + double angle() const { return atan2(m_y, m_x); } + operator double () const { return angle(); } + double length() const { return _hypot(m_x, m_y); } +}; + +PathVector operator-(const PathPoint& p1, const PathPoint& p2) +{ + return PathVector(p1.m_x - p2.m_x, p1.m_y - p2.m_y); +} + +static void addArcPoint(PathPolygon& poly, const PathPoint& center, const PathPoint& radius, double angle) +{ + PathPoint p; + getEllipsePointByAngle(angle, radius.m_x, radius.m_y, p.m_x, p.m_y); + transformArcPoint(p.m_x, p.m_y, center); + if (poly.isEmpty() || poly.last() != p) + poly.append(p); +} + +static void addArcPoints(PathPolygon& poly, const PlatformPathElement::ArcTo& data) +{ + const PathPoint& startPoint = poly.last(); + double curAngle = startPoint - data.m_center; + double endAngle = data.m_end - data.m_center; + double angleStep = 2. / std::max(data.m_radius.m_x, data.m_radius.m_y); + if (data.m_clockwise) { + if (endAngle <= curAngle || startPoint == data.m_end) + endAngle += 2 * piDouble; + } else { + angleStep = -angleStep; + if (endAngle >= curAngle || startPoint == data.m_end) + endAngle -= 2 * piDouble; + } + + for (curAngle += angleStep; data.m_clockwise ? curAngle < endAngle : curAngle > endAngle; curAngle += angleStep) + addArcPoint(poly, data.m_center, data.m_radius, curAngle); + + if (poly.isEmpty() || poly.last() != data.m_end) + poly.append(data.m_end); +} + +static void drawPolygons(HDC dc, const Vector<PathPolygon>& polygons, bool fill, const TransformationMatrix* transformation) +{ + MemoryAllocationCanFail canFail; + for (Vector<PathPolygon>::const_iterator i = polygons.begin(); i != polygons.end(); ++i) { + int npoints = i->size(); + if (!npoints) + continue; + + POINT* winPoints = 0; + if (fill) { + if (npoints > 2) + winPoints = new POINT[npoints + 1]; + } else + winPoints = new POINT[npoints]; + + if (winPoints) { + if (transformation) { + for (int i2 = 0; i2 < npoints; ++i2) { + FloatPoint trPoint = transformation->mapPoint(i->at(i2)); + winPoints[i2].x = stableRound(trPoint.x()); + winPoints[i2].y = stableRound(trPoint.y()); + } + } else { + for (int i2 = 0; i2 < npoints; ++i2) { + winPoints[i2].x = stableRound(i->at(i2).x()); + winPoints[i2].y = stableRound(i->at(i2).y()); + } + } + + if (fill && winPoints[npoints - 1] != winPoints[0]) { + winPoints[npoints].x = winPoints[0].x; + winPoints[npoints].y = winPoints[0].y; + ++npoints; + } + + if (fill) + ::Polygon(dc, winPoints, npoints); + else + ::Polyline(dc, winPoints, npoints); + delete[] winPoints; + } + } +} + + +int PlatformPathElement::numControlPoints() const +{ + switch (m_type) { + case PathMoveTo: + case PathLineTo: + return 1; + case PathQuadCurveTo: + case PathArcTo: + return 2; + case PathBezierCurveTo: + return 3; + default: + ASSERT(m_type == PathCloseSubpath); + return 0; + } +} + +int PlatformPathElement::numPoints() const +{ + switch (m_type) { + case PathMoveTo: + case PathLineTo: + case PathArcTo: + return 1; + case PathQuadCurveTo: + return 2; + case PathBezierCurveTo: + return 3; + default: + ASSERT(m_type == PathCloseSubpath); + return 0; + } +} + +void PathPolygon::move(const FloatSize& offset) +{ + for (Vector<PathPoint>::iterator i = begin(); i < end(); ++i) + i->move(offset); +} + +void PathPolygon::transform(const TransformationMatrix& t) +{ + for (Vector<PathPoint>::iterator i = begin(); i < end(); ++i) + *i = t.mapPoint(*i); +} + +bool PathPolygon::contains(const FloatPoint& point) const +{ + if (size() < 3) + return false; + + // Test intersections between the polygon and the vertical line: x = point.x() + + int intersected = 0; + const PathPoint* point1 = &last(); + Vector<PathPoint>::const_iterator last = end(); + // wasNegative: -1 means unknown, 0 means false, 1 means true. + int wasNegative = -1; + for (Vector<PathPoint>::const_iterator i = begin(); i != last; ++i) { + const PathPoint& point2 = *i; + if (point1->x() != point.x()) { + if (point2.x() == point.x()) { + // We are getting on the vertical line + wasNegative = point1->x() < point.x() ? 1 : 0; + } else if (point2.x() < point.x() != point1->x() < point.x()) { + float y = (point2.y() - point1->y()) / (point2.x() - point1->x()) * (point.x() - point1->x()) + point1->y(); + if (y >= point.y()) + ++intersected; + } + } else { + // We were on the vertical line + + // handle special case + if (point1->y() == point.y()) + return true; + + if (point1->y() > point.y()) { + if (point2.x() == point.x()) { + // see if the point is on this segment + if (point2.y() <= point.y()) + return true; + + // We are still on the line + } else { + // We are leaving the line now. + // We have to get back to see which side we come from. If we come from + // the same side we are leaving, no intersection should be counted + if (wasNegative < 0) { + Vector<PathPoint>::const_iterator jLast = i; + Vector<PathPoint>::const_iterator j = i; + do { + if (j == begin()) + j = last; + else + --j; + if (j->x() != point.x()) { + if (j->x() > point.x()) + wasNegative = 0; + else + wasNegative = 1; + break; + } + } while (j != jLast); + + if (wasNegative < 0) + return false; + } + if (wasNegative ? point2.x() > point.x() : point2.x() < point.x()) + ++intersected; + } + } else if (point2.x() == point.x() && point2.y() >= point.y()) + return true; + } + point1 = &point2; + } + + return intersected & 1; +} + +void PlatformPathElement::move(const FloatSize& offset) +{ + int n = numControlPoints(); + for (int i = 0; i < n; ++i) + m_data.m_points[i].move(offset); +} + +void PlatformPathElement::transform(const TransformationMatrix& t) +{ + int n = numControlPoints(); + for (int i = 0; i < n; ++i) { + FloatPoint p = t.mapPoint(m_data.m_points[i]); + m_data.m_points[i].set(p.x(), p.y()); + } +} + +void PlatformPathElement::inflateRectToContainMe(FloatRect& r, const FloatPoint& lastPoint) const +{ + if (m_type == PathArcTo) { + const ArcTo& data = m_data.m_arcToData; + PathPoint startPoint; + startPoint = lastPoint; + PathPoint endPoint = data.m_end; + if (!data.m_clockwise) + std::swap(startPoint, endPoint); + + int q0 = quadrant(startPoint, data.m_center); + int q1 = quadrant(endPoint, data.m_center); + bool containsExtremes[4] = { false }; // bottom, left, top, right + static const PathPoint extremeVectors[4] = { { 0, 1 }, { -1, 0 }, { 0, -1 }, { 1, 0 } }; + if (q0 == q1) { + if (startPoint.m_x == endPoint.m_x || isQuadrantOnBottom(q0) != startPoint.m_x > endPoint.m_x) { + for (int i = 0; i < 4; ++i) + containsExtremes[i] = true; + } + } else { + int extreme = q0; + int diff = quadrantDiff(q1, q0); + for (int i = 0; i < diff; ++i) { + containsExtremes[extreme] = true; + extreme = nextQuadrant(extreme); + } + } + + inflateRectToContainPoint(r, startPoint.m_x, startPoint.m_y); + inflateRectToContainPoint(r, endPoint.m_x, endPoint.m_y); + for (int i = 0; i < 4; ++i) { + if (containsExtremes[i]) + inflateRectToContainPoint(r, data.m_center.m_x + data.m_radius.m_x * extremeVectors[i].m_x, data.m_center.m_y + data.m_radius.m_y * extremeVectors[i].m_y); + } + } else { + int n = numPoints(); + for (int i = 0; i < n; ++i) + inflateRectToContainPoint(r, m_data.m_points[i].m_x, m_data.m_points[i].m_y); + } +} + +PathElementType PlatformPathElement::type() const +{ + switch (m_type) { + case PathMoveTo: + return PathElementMoveToPoint; + case PathLineTo: + return PathElementAddLineToPoint; + case PathArcTo: + // FIXME: there's no arcTo type for PathElement + return PathElementAddLineToPoint; + // return PathElementAddQuadCurveToPoint; + case PathQuadCurveTo: + return PathElementAddQuadCurveToPoint; + case PathBezierCurveTo: + return PathElementAddCurveToPoint; + default: + ASSERT(m_type == PathCloseSubpath); + return PathElementCloseSubpath; + } +} + +PlatformPath::PlatformPath() + : m_penLifted(true) +{ + m_currentPoint.clear(); +} + +void PlatformPath::ensureSubpath() +{ + if (m_penLifted) { + m_penLifted = false; + m_subpaths.append(PathPolygon()); + m_subpaths.last().append(m_currentPoint); + } else + ASSERT(!m_subpaths.isEmpty()); +} + +void PlatformPath::addToSubpath(const PlatformPathElement& e) +{ + if (e.platformType() == PlatformPathElement::PathMoveTo) { + m_penLifted = true; + m_currentPoint = e.pointAt(0); + } else if (e.platformType() == PlatformPathElement::PathCloseSubpath) { + m_penLifted = true; + if (!m_subpaths.isEmpty()) { + if (m_currentPoint != m_subpaths.last()[0]) { + // According to W3C, we have to draw a line from current point to the initial point + m_subpaths.last().append(m_subpaths.last()[0]); + m_currentPoint = m_subpaths.last()[0]; + } + } else + m_currentPoint.clear(); + } else { + ensureSubpath(); + switch (e.platformType()) { + case PlatformPathElement::PathLineTo: + m_subpaths.last().append(e.pointAt(0)); + break; + case PlatformPathElement::PathArcTo: + addArcPoints(m_subpaths.last(), e.arcTo()); + break; + case PlatformPathElement::PathQuadCurveTo: + { + PathPoint control[] = { + m_currentPoint, + e.pointAt(0), + e.pointAt(1), + }; + // FIXME: magic number? + quadCurve(50, m_subpaths.last(), control); + } + break; + case PlatformPathElement::PathBezierCurveTo: + { + PathPoint control[] = { + m_currentPoint, + e.pointAt(0), + e.pointAt(1), + e.pointAt(2), + }; + // FIXME: magic number? + bezier(100, m_subpaths.last(), control); + } + break; + default: + ASSERT_NOT_REACHED(); + break; + } + m_currentPoint = m_subpaths.last().last(); + } +} + +void PlatformPath::append(const PlatformPathElement& e) +{ + e.inflateRectToContainMe(m_boundingRect, lastPoint()); + addToSubpath(e); + m_elements.append(e); +} + +void PlatformPath::append(const PlatformPath& p) +{ + const PlatformPathElements& e = p.elements(); + for (PlatformPathElements::const_iterator it(e.begin()); it != e.end(); ++it) { + addToSubpath(*it); + it->inflateRectToContainMe(m_boundingRect, lastPoint()); + m_elements.append(*it); + } +} + +void PlatformPath::clear() +{ + m_elements.clear(); + m_boundingRect = FloatRect(); + m_subpaths.clear(); + m_currentPoint.clear(); + m_penLifted = true; +} + +void PlatformPath::strokePath(HDC dc, const TransformationMatrix* transformation) const +{ + drawPolygons(dc, m_subpaths, false, transformation); +} + +void PlatformPath::fillPath(HDC dc, const TransformationMatrix* transformation) const +{ + HGDIOBJ oldPen = SelectObject(dc, GetStockObject(NULL_PEN)); + drawPolygons(dc, m_subpaths, true, transformation); + SelectObject(dc, oldPen); +} + +void PlatformPath::translate(const FloatSize& size) +{ + for (PlatformPathElements::iterator it(m_elements.begin()); it != m_elements.end(); ++it) + it->move(size); + + m_boundingRect.move(size); + for (Vector<PathPolygon>::iterator it = m_subpaths.begin(); it != m_subpaths.end(); ++it) + it->move(size); +} + +void PlatformPath::transform(const TransformationMatrix& t) +{ + for (PlatformPathElements::iterator it(m_elements.begin()); it != m_elements.end(); ++it) + it->transform(t); + + m_boundingRect = t.mapRect(m_boundingRect); + for (Vector<PathPolygon>::iterator it = m_subpaths.begin(); it != m_subpaths.end(); ++it) + it->transform(t); +} + +bool PlatformPath::contains(const FloatPoint& point, WindRule rule) const +{ + // optimization: check the bounding rect first + if (!containsPoint(m_boundingRect, point)) + return false; + + for (Vector<PathPolygon>::const_iterator i = m_subpaths.begin(); i != m_subpaths.end(); ++i) { + if (i->contains(point)) + return true; + } + + return false; +} + +void PlatformPath::moveTo(const FloatPoint& point) +{ + PlatformPathElement::MoveTo data = { { point.x(), point.y() } }; + PlatformPathElement pe(data); + append(pe); +} + +void PlatformPath::addLineTo(const FloatPoint& point) +{ + PlatformPathElement::LineTo data = { { point.x(), point.y() } }; + PlatformPathElement pe(data); + append(pe); +} + +void PlatformPath::addQuadCurveTo(const FloatPoint& cp, const FloatPoint& p) +{ + PlatformPathElement::QuadCurveTo data = { { cp.x(), cp.y() }, { p.x(), p.y() } }; + PlatformPathElement pe(data); + append(pe); +} + +void PlatformPath::addBezierCurveTo(const FloatPoint& cp1, const FloatPoint& cp2, const FloatPoint& p) +{ + PlatformPathElement::BezierCurveTo data = { { cp1.x(), cp1.y() }, { cp2.x(), cp2.y() }, { p.x(), p.y() } }; + PlatformPathElement pe(data); + append(pe); +} + +void PlatformPath::addArcTo(const FloatPoint& fp1, const FloatPoint& fp2, float radius) +{ + const PathPoint& p0 = m_currentPoint; + PathPoint p1; + p1 = fp1; + PathPoint p2; + p2 = fp2; + if (!radius || p0 == p1 || p1 == p2) { + addLineTo(p1); + return; + } + + PathVector v01 = p0 - p1; + PathVector v21 = p2 - p1; + + // sin(A - B) = sin(A) * cos(B) - sin(B) * cos(A) + double cross = v01.m_x * v21.m_y - v01.m_y * v21.m_x; + + if (fabs(cross) < 1E-10) { + // on one line + addLineTo(p1); + return; + } + + double d01 = v01.length(); + double d21 = v21.length(); + double angle = (piDouble - abs(asin(cross / (d01 * d21)))) * 0.5; + double span = radius * tan(angle); + double rate = span / d01; + PathPoint startPoint; + startPoint.m_x = p1.m_x + v01.m_x * rate; + startPoint.m_y = p1.m_y + v01.m_y * rate; + + addLineTo(startPoint); + + PathPoint endPoint; + rate = span / d21; + endPoint.m_x = p1.m_x + v21.m_x * rate; + endPoint.m_y = p1.m_y + v21.m_y * rate; + + PathPoint midPoint; + midPoint.m_x = (startPoint.m_x + endPoint.m_x) * 0.5; + midPoint.m_y = (startPoint.m_y + endPoint.m_y) * 0.5; + + PathVector vm1 = midPoint - p1; + double dm1 = vm1.length(); + double d = _hypot(radius, span); + + PathPoint centerPoint; + rate = d / dm1; + centerPoint.m_x = p1.m_x + vm1.m_x * rate; + centerPoint.m_y = p1.m_y + vm1.m_y * rate; + + PlatformPathElement::ArcTo data = { + endPoint, + centerPoint, + { radius, radius }, + cross < 0 + }; + PlatformPathElement pe(data); + append(pe); +} + +void PlatformPath::closeSubpath() +{ + PlatformPathElement pe; + append(pe); +} + +// add a circular arc centred at p with radius r from start angle sar (radians) to end angle ear +void PlatformPath::addEllipse(const FloatPoint& p, float a, float b, float sar, float ear, bool anticlockwise) +{ + float startX, startY, endX, endY; + + normalizeAngle(sar); + normalizeAngle(ear); + + getEllipsePointByAngle(sar, a, b, startX, startY); + getEllipsePointByAngle(ear, a, b, endX, endY); + + transformArcPoint(startX, startY, p); + transformArcPoint(endX, endY, p); + + FloatPoint start(startX, startY); + moveTo(start); + + PlatformPathElement::ArcTo data = { { endX, endY }, { p.x(), p.y() }, { a, b }, !anticlockwise }; + PlatformPathElement pe(data); + append(pe); +} + + +void PlatformPath::addRect(const FloatRect& r) +{ + moveTo(r.location()); + + float right = r.right() - 1; + float bottom = r.bottom() - 1; + addLineTo(FloatPoint(right, r.y())); + addLineTo(FloatPoint(right, bottom)); + addLineTo(FloatPoint(r.x(), bottom)); + addLineTo(r.location()); +} + +void PlatformPath::addEllipse(const FloatRect& r) +{ + FloatSize radius(r.width() * 0.5, r.height() * 0.5); + addEllipse(r.location() + radius, radius.width(), radius.height(), 0, 0, true); +} + +String PlatformPath::debugString() const +{ + String ret; + for (PlatformPathElements::const_iterator i(m_elements.begin()); i != m_elements.end(); ++i) { + switch (i->platformType()) { + case PlatformPathElement::PathMoveTo: + case PlatformPathElement::PathLineTo: + ret += String::format("M %f %f\n", i->pointAt(0).m_x, i->pointAt(0).m_y); + break; + case PlatformPathElement::PathArcTo: + ret += String::format("A %f %f %f %f %f %f %c\n" + , i->arcTo().m_end.m_x, i->arcTo().m_end.m_y + , i->arcTo().m_center.m_x, i->arcTo().m_center.m_y + , i->arcTo().m_radius.m_x, i->arcTo().m_radius.m_y + , i->arcTo().m_clockwise? 'Y' : 'N'); + break; + case PlatformPathElement::PathQuadCurveTo: + ret += String::format("Q %f %f %f %f\n" + , i->pointAt(0).m_x, i->pointAt(0).m_y + , i->pointAt(1).m_x, i->pointAt(1).m_y); + break; + case PlatformPathElement::PathBezierCurveTo: + ret += String::format("B %f %f %f %f %f %f\n" + , i->pointAt(0).m_x, i->pointAt(0).m_y + , i->pointAt(1).m_x, i->pointAt(1).m_y + , i->pointAt(2).m_x, i->pointAt(2).m_y); + break; + default: + ASSERT(i->platformType() == PlatformPathElement::PathCloseSubpath); + ret += "S\n"; + break; + } + } + + return ret; +} + +void PlatformPath::apply(void* info, PathApplierFunction function) const +{ + PathElement pelement; + FloatPoint points[3]; + pelement.points = points; + + for (PlatformPathElements::const_iterator it(m_elements.begin()); it != m_elements.end(); ++it) { + pelement.type = it->type(); + int n = it->numPoints(); + for (int i = 0; i < n; ++i) + points[i] = it->pointAt(i); + function(info, &pelement); + } +} + +} // namespace Webcore diff --git a/WebCore/platform/graphics/wince/PlatformPathWince.h b/WebCore/platform/graphics/wince/PlatformPathWince.h new file mode 100644 index 0000000..fca00a7 --- /dev/null +++ b/WebCore/platform/graphics/wince/PlatformPathWince.h @@ -0,0 +1,178 @@ +/* + * Copyright (C) 2007-2009 Torch Mobile, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef PlatformPathWince_h +#define PlatformPathWince_h + +namespace WebCore { + + class GraphicsContext; + + struct PathPoint { + float m_x; + float m_y; + const float& x() const { return m_x; } + const float& y() const { return m_y; } + void set(float x, float y) + { + m_x = x; + m_y = y; + }; + operator FloatPoint() const { return FloatPoint(m_x, m_y); } + void move(const FloatSize& offset) + { + m_x += offset.width(); + m_y += offset.height(); + } + PathPoint& operator=(const FloatPoint& p) + { + m_x = p.x(); + m_y = p.y(); + return *this; + } + void clear() { m_x = m_y = 0; } + }; + + struct PathPolygon: public Vector<PathPoint> { + void move(const FloatSize& offset); + void transform(const TransformationMatrix& t); + bool contains(const FloatPoint& point) const; + }; + + class PlatformPathElement { + public: + enum PlaformPathElementType { + PathMoveTo, + PathLineTo, + PathArcTo, + PathQuadCurveTo, + PathBezierCurveTo, + PathCloseSubpath, + }; + + struct MoveTo { + PathPoint m_end; + }; + + struct LineTo { + PathPoint m_end; + }; + + struct ArcTo { + PathPoint m_end; + PathPoint m_center; + PathPoint m_radius; + bool m_clockwise; + }; + + struct QuadCurveTo { + PathPoint m_point0; + PathPoint m_point1; + }; + + struct BezierCurveTo { + PathPoint m_point0; + PathPoint m_point1; + PathPoint m_point2; + }; + + PlatformPathElement(): m_type(PathCloseSubpath) { m_data.m_points[0].set(0, 0); } + PlatformPathElement(const MoveTo& data): m_type(PathMoveTo) { m_data.m_moveToData = data; } + PlatformPathElement(const LineTo& data): m_type(PathLineTo) { m_data.m_lineToData = data; } + PlatformPathElement(const ArcTo& data): m_type(PathArcTo) { m_data.m_arcToData = data; } + PlatformPathElement(const QuadCurveTo& data): m_type(PathQuadCurveTo) { m_data.m_quadCurveToData = data; } + PlatformPathElement(const BezierCurveTo& data): m_type(PathBezierCurveTo) { m_data.m_bezierCurveToData = data; } + + const MoveTo& moveTo() const { return m_data.m_moveToData; } + const LineTo& lineTo() const { return m_data.m_lineToData; } + const ArcTo& arcTo() const { return m_data.m_arcToData; } + const QuadCurveTo& quadCurveTo() const { return m_data.m_quadCurveToData; } + const BezierCurveTo& bezierCurveTo() const { return m_data.m_bezierCurveToData; } + const PathPoint& lastPoint() const + { + int n = numPoints(); + return n > 1 ? m_data.m_points[n - 1] : m_data.m_points[0]; + } + const PathPoint& pointAt(int index) const { return m_data.m_points[index]; } + int numPoints() const; + int numControlPoints() const; + void move(const FloatSize& offset); + void transform(const TransformationMatrix& t); + PathElementType type() const; + PlaformPathElementType platformType() const { return m_type; } + void inflateRectToContainMe(FloatRect& r, const FloatPoint& lastPoint) const; + + private: + PlaformPathElementType m_type; + union { + MoveTo m_moveToData; + LineTo m_lineToData; + ArcTo m_arcToData; + QuadCurveTo m_quadCurveToData; + BezierCurveTo m_bezierCurveToData; + PathPoint m_points[4]; + } m_data; + }; + + typedef Vector<PlatformPathElement> PlatformPathElements; + + class PlatformPath { + public: + PlatformPath(); + const PlatformPathElements& elements() const { return m_elements; } + void append(const PlatformPathElement& e); + void append(const PlatformPath& p); + void clear(); + bool isEmpty() const { return m_elements.isEmpty(); } + + void strokePath(HDC, const TransformationMatrix* tr) const; + void fillPath(HDC, const TransformationMatrix* tr) const; + FloatPoint lastPoint() const { return m_elements.isEmpty() ? FloatPoint(0, 0) : m_elements.last().lastPoint(); } + + const FloatRect& boundingRect() const { return m_boundingRect; } + bool contains(const FloatPoint& point, WindRule rule) const; + void translate(const FloatSize& size); + void transform(const TransformationMatrix& t); + + void moveTo(const FloatPoint&); + void addLineTo(const FloatPoint&); + void addQuadCurveTo(const FloatPoint& controlPoint, const FloatPoint& point); + void addBezierCurveTo(const FloatPoint& controlPoint1, const FloatPoint& controlPoint2, const FloatPoint&); + void addArcTo(const FloatPoint&, const FloatPoint&, float radius); + void closeSubpath(); + void addEllipse(const FloatPoint& p, float a, float b, float sar, float ear, bool anticlockwise); + void addRect(const FloatRect& r); + void addEllipse(const FloatRect& r); + String debugString() const; + void apply(void* info, PathApplierFunction function) const; + + private: + void ensureSubpath(); + void addToSubpath(const PlatformPathElement& e); + + PlatformPathElements m_elements; + FloatRect m_boundingRect; + Vector<PathPolygon> m_subpaths; + PathPoint m_currentPoint; + bool m_penLifted; + }; + +} + +#endif // PlatformPathWince_h diff --git a/WebCore/platform/graphics/wince/WinceGraphicsExtras.h b/WebCore/platform/graphics/wince/WinceGraphicsExtras.h new file mode 100644 index 0000000..2a6fae1 --- /dev/null +++ b/WebCore/platform/graphics/wince/WinceGraphicsExtras.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2007-2009 Torch Mobile, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef WinceGraphicsExtras_h +#define WinceGraphicsExtras_h + +// This file is used to contain small utilities used by WINCE graphics code. + +namespace WebCore { + // Always round to same direction. 0.5 is rounded to 1, + // and -0.5 (0.5 - 1) is rounded to 0 (1 - 1), so that it + // is consistent when transformation shifts. + static inline int stableRound(double d) + { + if (d > 0) + return static_cast<int>(d + 0.5); + + int i = static_cast<int>(d); + return i - d > 0.5 ? i - 1 : i; + } +} + +#endif WinceGraphicsExtras_h |