164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard/* 264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard * Copyright 2012, The Android Open Source Project 364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard * 464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard * Redistribution and use in source and binary forms, with or without 564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard * modification, are permitted provided that the following conditions 664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard * are met: 764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard * * Redistributions of source code must retain the above copyright 864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard * notice, this list of conditions and the following disclaimer. 964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard * * Redistributions in binary form must reproduce the above copyright 1064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard * notice, this list of conditions and the following disclaimer in the 1164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard * documentation and/or other materials provided with the distribution. 1264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard * 1364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY 1464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 1664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 1764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 1864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 1964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 2064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 2164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard */ 2564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard 2664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard#ifndef platform_graphics_context_recording_h 2764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard#define platform_graphics_context_recording_h 2864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard 2964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard#include "PlatformGraphicsContext.h" 3064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard 31b9f38925d3cdae56548c3c18300c2964d207ed4eJohn Reck#include "RecordingContextCanvasProxy.h" 32675402ef4358583f64a2476927a548db4841c856John Reck#include "SkRefCnt.h" 33675402ef4358583f64a2476927a548db4841c856John Reck 3464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roardnamespace WebCore { 351fcb8aa079de156851042d8e041254b7abeecc77John Recknamespace GraphicsOperation { 361fcb8aa079de156851042d8e041254b7abeecc77John Reckclass Operation; 371fcb8aa079de156851042d8e041254b7abeecc77John Reck} 3864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard 3977d974918eff4b56050e9f1c3a78becab1244a04John Reckclass CanvasState; 40d9779adc025ab665fde1c9983e7793e96ab56d4eJohn Reckclass LinearAllocator; 41675402ef4358583f64a2476927a548db4841c856John Reckclass RecordingImpl; 42286b2d175d354558d172f30ca702dc0e05c7602fChris Craikclass PlatformGraphicsContextSkia; 43286b2d175d354558d172f30ca702dc0e05c7602fChris Craikclass RecordingData; 44d9779adc025ab665fde1c9983e7793e96ab56d4eJohn Reck 45675402ef4358583f64a2476927a548db4841c856John Reckclass Recording : public SkRefCnt { 46675402ef4358583f64a2476927a548db4841c856John Reckpublic: 47675402ef4358583f64a2476927a548db4841c856John Reck Recording() 48675402ef4358583f64a2476927a548db4841c856John Reck : m_recording(0) 49675402ef4358583f64a2476927a548db4841c856John Reck {} 50675402ef4358583f64a2476927a548db4841c856John Reck ~Recording(); 51675402ef4358583f64a2476927a548db4841c856John Reck 52675402ef4358583f64a2476927a548db4841c856John Reck void draw(SkCanvas* canvas); 53675402ef4358583f64a2476927a548db4841c856John Reck void setRecording(RecordingImpl* impl); 54675402ef4358583f64a2476927a548db4841c856John Reck RecordingImpl* recording() { return m_recording; } 55675402ef4358583f64a2476927a548db4841c856John Reck 56675402ef4358583f64a2476927a548db4841c856John Reckprivate: 57675402ef4358583f64a2476927a548db4841c856John Reck RecordingImpl* m_recording; 58675402ef4358583f64a2476927a548db4841c856John Reck}; 59675402ef4358583f64a2476927a548db4841c856John Reck 6064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roardclass PlatformGraphicsContextRecording : public PlatformGraphicsContext { 6164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roardpublic: 62675402ef4358583f64a2476927a548db4841c856John Reck PlatformGraphicsContextRecording(Recording* picture); 63b50b15512d5b30dc479751a45cd8a515c172a354John Reck virtual ~PlatformGraphicsContextRecording(); 6464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard virtual bool isPaintingDisabled(); 6564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard 6664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard virtual SkCanvas* recordingCanvas(); 6785fb59060a0fdfcff93ae1c70dd49e0f93e55ab6Chris Craik virtual void setTextOffset(FloatSize offset) { m_textOffset = offset; } 6864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard 6964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard virtual ContextType type() { return RecordingContext; } 7064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard 7164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard // State management 7264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard virtual void beginTransparencyLayer(float opacity); 7364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard virtual void endTransparencyLayer(); 7464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard virtual void save(); 7564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard virtual void restore(); 7664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard 7764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard // State values 7864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard virtual void setAlpha(float alpha); 7964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard virtual void setCompositeOperation(CompositeOperator op); 8053f84f58d9ffe86a4932c979b9863acadb5769efJohn Reck virtual bool setFillColor(const Color& c); 8153f84f58d9ffe86a4932c979b9863acadb5769efJohn Reck virtual bool setFillShader(SkShader* fillShader); 8264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard virtual void setLineCap(LineCap cap); 8364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard virtual void setLineDash(const DashArray& dashes, float dashOffset); 8464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard virtual void setLineJoin(LineJoin join); 8564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard virtual void setMiterLimit(float limit); 8664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard virtual void setShadow(int radius, int dx, int dy, SkColor c); 8764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard virtual void setShouldAntialias(bool useAA); 8853f84f58d9ffe86a4932c979b9863acadb5769efJohn Reck virtual bool setStrokeColor(const Color& c); 8953f84f58d9ffe86a4932c979b9863acadb5769efJohn Reck virtual bool setStrokeShader(SkShader* strokeShader); 9064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard virtual void setStrokeStyle(StrokeStyle style); 9164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard virtual void setStrokeThickness(float f); 9264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard 9364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard // Matrix operations 9464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard virtual void concatCTM(const AffineTransform& affine); 9564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard virtual void rotate(float angleInRadians); 9664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard virtual void scale(const FloatSize& size); 9764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard virtual void translate(float x, float y); 9864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard virtual const SkMatrix& getTotalMatrix(); 9964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard 10064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard // Clipping 10164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard virtual void addInnerRoundedRectClip(const IntRect& rect, int thickness); 10264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard virtual void canvasClip(const Path& path); 10322ddc4a8f76077593fba14c8cafffc74f9170dabJohn Reck virtual bool clip(const FloatRect& rect); 10422ddc4a8f76077593fba14c8cafffc74f9170dabJohn Reck virtual bool clip(const Path& path); 10522ddc4a8f76077593fba14c8cafffc74f9170dabJohn Reck virtual bool clipConvexPolygon(size_t numPoints, const FloatPoint*, bool antialias); 10622ddc4a8f76077593fba14c8cafffc74f9170dabJohn Reck virtual bool clipOut(const IntRect& r); 10722ddc4a8f76077593fba14c8cafffc74f9170dabJohn Reck virtual bool clipOut(const Path& p); 10822ddc4a8f76077593fba14c8cafffc74f9170dabJohn Reck virtual bool clipPath(const Path& pathToClip, WindRule clipRule); 1093718b58e4da76b7025aa5316a51264c5e38f2569John Reck virtual SkIRect getTotalClipBounds() { return enclosingIntRect(mRecordingStateStack.last().mBounds); } 11064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard 11164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard // Drawing 11264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard virtual void clearRect(const FloatRect& rect); 11364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard virtual void drawBitmapPattern(const SkBitmap& bitmap, const SkMatrix& matrix, 11464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard CompositeOperator compositeOp, const FloatRect& destRect); 115285c0572401578498b0ccb0c3da0828544f2d085Chris Craik virtual void drawBitmapRect(const SkBitmap& bitmap, const SkIRect* srcPtr, 1163718b58e4da76b7025aa5316a51264c5e38f2569John Reck const SkRect& dst, CompositeOperator op = CompositeSourceOver); 11764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard virtual void drawConvexPolygon(size_t numPoints, const FloatPoint* points, 11864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard bool shouldAntialias); 11964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard virtual void drawEllipse(const IntRect& rect); 12064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard virtual void drawFocusRing(const Vector<IntRect>& rects, int /* width */, 12164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard int /* offset */, const Color& color); 12264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard virtual void drawHighlightForText(const Font& font, const TextRun& run, 12364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard const FloatPoint& point, int h, 12464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard const Color& backgroundColor, ColorSpace colorSpace, 12564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard int from, int to, bool isActive); 12664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard virtual void drawLine(const IntPoint& point1, const IntPoint& point2); 12764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard virtual void drawLineForText(const FloatPoint& pt, float width); 12864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard virtual void drawLineForTextChecking(const FloatPoint& pt, float width, 129675402ef4358583f64a2476927a548db4841c856John Reck GraphicsContext::TextCheckingLineStyle); 13064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard virtual void drawRect(const IntRect& rect); 13164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard virtual void fillPath(const Path& pathToFill, WindRule fillRule); 13264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard virtual void fillRect(const FloatRect& rect); 13364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard virtual void fillRect(const FloatRect& rect, const Color& color); 13464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard virtual void fillRoundedRect(const IntRect& rect, const IntSize& topLeft, 13564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard const IntSize& topRight, const IntSize& bottomLeft, 13664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard const IntSize& bottomRight, const Color& color); 13764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard virtual void strokeArc(const IntRect& r, int startAngle, int angleSpan); 13864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard virtual void strokePath(const Path& pathToStroke); 13964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard virtual void strokeRect(const FloatRect& rect, float lineWidth); 14064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard 1413718b58e4da76b7025aa5316a51264c5e38f2569John Reck virtual void drawPosText(const void* text, size_t byteLength, 1423718b58e4da76b7025aa5316a51264c5e38f2569John Reck const SkPoint pos[], const SkPaint& paint); 1433718b58e4da76b7025aa5316a51264c5e38f2569John Reck virtual void drawMediaButton(const IntRect& rect, RenderSkinMediaButton::MediaButton buttonType, 1443718b58e4da76b7025aa5316a51264c5e38f2569John Reck bool translucent = false, bool drawBackground = true, 1453718b58e4da76b7025aa5316a51264c5e38f2569John Reck const IntRect& thumb = IntRect()); 146b9f38925d3cdae56548c3c18300c2964d207ed4eJohn Reck 14742326004062d6b846c3050ad03a1e80fa9db425cChris Craik float maxZoomScale() { return m_maxZoomScale; } 148f899e6e3a8952453ea79363d36a4d171eebb0fbbChris Craik bool isEmpty() { return m_isEmpty; } 14964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roardprivate: 15064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard 15164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard virtual bool shadowsIgnoreTransforms() const { 15264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard return false; 15364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard } 15464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard 1557853e9d8b1baa5eac14017534d445e04694a0d58Nicolas Roard void clipState(const FloatRect& clip); 156675402ef4358583f64a2476927a548db4841c856John Reck void appendDrawingOperation(GraphicsOperation::Operation* operation, const FloatRect& bounds); 1571fcb8aa079de156851042d8e041254b7abeecc77John Reck void appendStateOperation(GraphicsOperation::Operation* operation); 15877d974918eff4b56050e9f1c3a78becab1244a04John Reck void pushStateOperation(CanvasState* canvasState); 15977d974918eff4b56050e9f1c3a78becab1244a04John Reck void popStateOperation(); 1606fda3e621352a695b3b6a02c6008d372b7c6febcJohn Reck void pushMatrix(); 1616fda3e621352a695b3b6a02c6008d372b7c6febcJohn Reck void popMatrix(); 162297e0a10e071c3389212e4be467e4833bc3717efJohn Reck IntRect calculateFinalBounds(FloatRect bounds); 163286b2d175d354558d172f30ca702dc0e05c7602fChris Craik IntRect calculateCoveredBounds(FloatRect bounds); 164c0df80bf70ee26fc3ebcdb52f6800cedf75db768John Reck LinearAllocator* heap(); 1651fcb8aa079de156851042d8e041254b7abeecc77John Reck 16664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard SkPicture* mPicture; 1678ad43ea5cc2ec08eaf11619f6c543e14bb5e1506John Reck SkMatrix* mCurrentMatrix; 1681fcb8aa079de156851042d8e041254b7abeecc77John Reck 169675402ef4358583f64a2476927a548db4841c856John Reck Recording* mRecording; 170675402ef4358583f64a2476927a548db4841c856John Reck class RecordingState { 171675402ef4358583f64a2476927a548db4841c856John Reck public: 172bf9a979842284165137a0eac2810b5cfd81346b9Chris Craik RecordingState(CanvasState* state, const RecordingState* parent) 17377d974918eff4b56050e9f1c3a78becab1244a04John Reck : mCanvasState(state) 174675402ef4358583f64a2476927a548db4841c856John Reck , mHasDrawing(false) 175bf9a979842284165137a0eac2810b5cfd81346b9Chris Craik , mHasClip(parent ? parent->mHasClip : false) 176bf9a979842284165137a0eac2810b5cfd81346b9Chris Craik , mOpaqueTrackingDisabled(parent ? parent->mOpaqueTrackingDisabled : false) 177bf9a979842284165137a0eac2810b5cfd81346b9Chris Craik , mBounds(parent ? parent->mBounds : FloatRect()) 178675402ef4358583f64a2476927a548db4841c856John Reck {} 179675402ef4358583f64a2476927a548db4841c856John Reck 180675402ef4358583f64a2476927a548db4841c856John Reck RecordingState(const RecordingState& other) 18177d974918eff4b56050e9f1c3a78becab1244a04John Reck : mCanvasState(other.mCanvasState) 182675402ef4358583f64a2476927a548db4841c856John Reck , mHasDrawing(other.mHasDrawing) 183675402ef4358583f64a2476927a548db4841c856John Reck , mHasClip(other.mHasClip) 184bf9a979842284165137a0eac2810b5cfd81346b9Chris Craik , mOpaqueTrackingDisabled(other.mOpaqueTrackingDisabled) 185675402ef4358583f64a2476927a548db4841c856John Reck , mBounds(other.mBounds) 186675402ef4358583f64a2476927a548db4841c856John Reck {} 187675402ef4358583f64a2476927a548db4841c856John Reck 188bf9a979842284165137a0eac2810b5cfd81346b9Chris Craik void disableOpaqueTracking() { mOpaqueTrackingDisabled = true; } 189286b2d175d354558d172f30ca702dc0e05c7602fChris Craik 190675402ef4358583f64a2476927a548db4841c856John Reck void clip(const FloatRect& rect) 191675402ef4358583f64a2476927a548db4841c856John Reck { 19277d974918eff4b56050e9f1c3a78becab1244a04John Reck if (mHasClip) 19377d974918eff4b56050e9f1c3a78becab1244a04John Reck mBounds.intersect(rect); 19477d974918eff4b56050e9f1c3a78becab1244a04John Reck else { 19577d974918eff4b56050e9f1c3a78becab1244a04John Reck mBounds = rect; 19677d974918eff4b56050e9f1c3a78becab1244a04John Reck mHasClip = true; 19777d974918eff4b56050e9f1c3a78becab1244a04John Reck } 198675402ef4358583f64a2476927a548db4841c856John Reck } 199675402ef4358583f64a2476927a548db4841c856John Reck 20077d974918eff4b56050e9f1c3a78becab1244a04John Reck CanvasState* mCanvasState; 201675402ef4358583f64a2476927a548db4841c856John Reck bool mHasDrawing; 202675402ef4358583f64a2476927a548db4841c856John Reck bool mHasClip; 203bf9a979842284165137a0eac2810b5cfd81346b9Chris Craik bool mOpaqueTrackingDisabled; 204675402ef4358583f64a2476927a548db4841c856John Reck FloatRect mBounds; 205675402ef4358583f64a2476927a548db4841c856John Reck }; 206675402ef4358583f64a2476927a548db4841c856John Reck Vector<RecordingState> mRecordingStateStack; 2076fda3e621352a695b3b6a02c6008d372b7c6febcJohn Reck Vector<SkMatrix> mMatrixStack; 208675402ef4358583f64a2476927a548db4841c856John Reck State* mOperationState; 209f899e6e3a8952453ea79363d36a4d171eebb0fbbChris Craik 21042326004062d6b846c3050ad03a1e80fa9db425cChris Craik float m_maxZoomScale; 211f899e6e3a8952453ea79363d36a4d171eebb0fbbChris Craik bool m_isEmpty; 212b9f38925d3cdae56548c3c18300c2964d207ed4eJohn Reck RecordingContextCanvasProxy m_canvasProxy; 21385fb59060a0fdfcff93ae1c70dd49e0f93e55ab6Chris Craik FloatSize m_textOffset; 21464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard}; 21564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard 21664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard} 21764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard#endif 218