summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBaligh Uddin <baligh@google.com>2013-11-01 16:01:52 -0700
committerBaligh Uddin <baligh@google.com>2013-11-01 16:01:52 -0700
commit658e3185acf0d232cb2a568a8430297369b59898 (patch)
treed3aa0c50c4c4b08d550b7b95061b12545c948d2a
parentf0c91a53b03ff18d8c7fbd8a019a28c4331c6f3f (diff)
parent425017857b2c8efbc272d8a977d5c009ac6f7ec4 (diff)
downloadinclude-idea133.tar.gz
Merge remote-tracking branch 'origin/kitkat-dev'chromium_org-pre-replicationidea133
-rw-r--r--animator/SkAnimator.h500
-rw-r--r--animator/SkAnimatorView.h39
-rw-r--r--config/SkUserConfig.h205
-rw-r--r--config/sk_stdint.h23
-rw-r--r--core/Sk64.h230
-rwxr-xr-xcore/SkAdvancedTypefaceMetrics.h157
-rw-r--r--core/SkAnnotation.h128
-rw-r--r--core/SkBitmap.h820
-rw-r--r--core/SkBlitRow.h104
-rw-r--r--core/SkBounder.h93
-rw-r--r--core/SkCanvas.h1179
-rw-r--r--core/SkChecksum.h135
-rw-r--r--core/SkChunkAlloc.h68
-rw-r--r--core/SkClipStack.h471
-rw-r--r--core/SkColor.h169
-rw-r--r--core/SkColorFilter.h134
-rw-r--r--core/SkColorPriv.h867
-rw-r--r--core/SkColorShader.h69
-rw-r--r--core/SkColorTable.h112
-rw-r--r--core/SkComposeShader.h58
-rw-r--r--core/SkData.h151
-rw-r--r--core/SkDataSet.h88
-rw-r--r--core/SkDataTable.h184
-rw-r--r--core/SkDeque.h138
-rw-r--r--core/SkDevice.h468
-rw-r--r--core/SkDeviceProperties.h112
-rw-r--r--core/SkDither.h198
-rw-r--r--core/SkDocument.h98
-rw-r--r--core/SkDraw.h141
-rw-r--r--core/SkDrawFilter.h55
-rw-r--r--core/SkDrawLooper.h76
-rw-r--r--core/SkEmptyShader.h43
-rw-r--r--core/SkEndian.h195
-rw-r--r--core/SkError.h86
-rw-r--r--core/SkFixed.h291
-rw-r--r--core/SkFlate.h52
-rw-r--r--core/SkFlattenable.h86
-rw-r--r--core/SkFlattenableBuffers.h175
-rw-r--r--core/SkFlattenableSerialization.h19
-rw-r--r--core/SkFloatBits.h138
-rw-r--r--core/SkFloatingPoint.h99
-rw-r--r--core/SkFontHost.h133
-rw-r--r--core/SkFontLCDConfig.h58
-rw-r--r--core/SkGeometry.h307
-rw-r--r--core/SkGraphics.h115
-rw-r--r--core/SkImage.h131
-rw-r--r--core/SkImageDecoder.h560
-rw-r--r--core/SkImageEncoder.h100
-rw-r--r--core/SkImageFilter.h173
-rw-r--r--core/SkImageFilterUtils.h38
-rw-r--r--core/SkImageTypes.h39
-rw-r--r--core/SkInstCnt.h133
-rw-r--r--core/SkLineClipper.h47
-rw-r--r--core/SkMallocPixelRef.h51
-rw-r--r--core/SkMask.h161
-rw-r--r--core/SkMaskFilter.h179
-rw-r--r--core/SkMath.h176
-rw-r--r--core/SkMatrix.h674
-rw-r--r--core/SkMetaData.h175
-rw-r--r--core/SkOSFile.h159
-rw-r--r--core/SkPackBits.h79
-rw-r--r--core/SkPaint.h1105
-rw-r--r--core/SkPaintOptionsAndroid.h129
-rw-r--r--core/SkPath.h1008
-rw-r--r--core/SkPathEffect.h204
-rw-r--r--core/SkPathMeasure.h109
-rw-r--r--core/SkPicture.h278
-rw-r--r--core/SkPixelRef.h243
-rw-r--r--core/SkPoint.h516
-rw-r--r--core/SkPostConfig.h393
-rw-r--r--core/SkPreConfig.h261
-rw-r--r--core/SkRRect.h295
-rw-r--r--core/SkRasterizer.h44
-rw-r--r--core/SkReader32.h158
-rw-r--r--core/SkRect.h790
-rw-r--r--core/SkRefCnt.h274
-rw-r--r--core/SkRegion.h446
-rw-r--r--core/SkScalar.h341
-rw-r--r--core/SkScalarCompare.h38
-rw-r--r--core/SkShader.h377
-rw-r--r--core/SkSize.h110
-rw-r--r--core/SkStream.h467
-rw-r--r--core/SkString.h265
-rw-r--r--core/SkStringUtils.h23
-rw-r--r--core/SkStrokeRec.h92
-rw-r--r--core/SkSurface.h158
-rw-r--r--core/SkTArray.h506
-rw-r--r--core/SkTDArray.h368
-rw-r--r--core/SkTDStack.h110
-rw-r--r--core/SkTDict.h161
-rw-r--r--core/SkTInternalLList.h272
-rw-r--r--core/SkTLazy.h182
-rw-r--r--core/SkTRegistry.h56
-rw-r--r--core/SkTScopedPtr.h76
-rw-r--r--core/SkTSearch.h146
-rw-r--r--core/SkTemplates.h457
-rw-r--r--core/SkThread.h68
-rw-r--r--core/SkThread_platform.h194
-rw-r--r--core/SkTileGridPicture.h56
-rw-r--r--core/SkTime.h64
-rw-r--r--core/SkTrace.h45
-rw-r--r--core/SkTypeface.h336
-rw-r--r--core/SkTypes.h607
-rw-r--r--core/SkUnPreMultiply.h56
-rw-r--r--core/SkUnitMapper.h35
-rw-r--r--core/SkUtils.h117
-rw-r--r--core/SkWeakRefCnt.h159
-rw-r--r--core/SkWriter32.h303
-rw-r--r--core/SkXfermode.h280
-rw-r--r--device/xps/SkConstexprMath.h54
-rw-r--r--device/xps/SkXPSDevice.h324
-rw-r--r--effects/Sk1DPathEffect.h79
-rw-r--r--effects/Sk2DPathEffect.h104
-rw-r--r--effects/SkArithmeticMode.h34
-rw-r--r--effects/SkAvoidXfermode.h65
-rw-r--r--effects/SkBicubicImageFilter.h56
-rw-r--r--effects/SkBitmapSource.h31
-rw-r--r--effects/SkBlurDrawLooper.h70
-rw-r--r--effects/SkBlurImageFilter.h39
-rw-r--r--effects/SkBlurMaskFilter.h61
-rwxr-xr-xeffects/SkColorFilterImageFilter.h42
-rw-r--r--effects/SkColorMatrix.h50
-rw-r--r--effects/SkColorMatrixFilter.h56
-rw-r--r--effects/SkComposeImageFilter.h31
-rw-r--r--effects/SkCornerPathEffect.h41
-rw-r--r--effects/SkDashPathEffect.h70
-rw-r--r--effects/SkDiscretePathEffect.h40
-rw-r--r--effects/SkDisplacementMapEffect.h58
-rw-r--r--effects/SkDrawExtraPathEffect.h15
-rw-r--r--effects/SkDropShadowImageFilter.h26
-rw-r--r--effects/SkEmbossMaskFilter.h49
-rw-r--r--effects/SkGradientShader.h147
-rw-r--r--effects/SkKernel33MaskFilter.h62
-rw-r--r--effects/SkLayerDrawLooper.h139
-rw-r--r--effects/SkLayerRasterizer.h52
-rw-r--r--effects/SkLerpXfermode.h46
-rw-r--r--effects/SkLightingImageFilter.h92
-rw-r--r--effects/SkMagnifierImageFilter.h38
-rw-r--r--effects/SkMatrixConvolutionImageFilter.h86
-rwxr-xr-xeffects/SkMergeImageFilter.h46
-rw-r--r--effects/SkMorphologyImageFilter.h75
-rw-r--r--effects/SkOffsetImageFilter.h33
-rw-r--r--effects/SkPaintFlagsDrawFilter.h24
-rw-r--r--effects/SkPerlinNoiseShader.h111
-rw-r--r--effects/SkPixelXorXfermode.h38
-rw-r--r--effects/SkPorterDuff.h81
-rw-r--r--effects/SkRectShaderImageFilter.h43
-rw-r--r--effects/SkStippleMaskFilter.h42
-rw-r--r--effects/SkTableColorFilter.h36
-rw-r--r--effects/SkTableMaskFilter.h63
-rwxr-xr-xeffects/SkTestImageFilters.h27
-rw-r--r--effects/SkTransparentShader.h37
-rw-r--r--effects/SkXfermodeImageFilter.h51
-rw-r--r--gpu/GrAARectRenderer.h114
-rw-r--r--gpu/GrBackendEffectFactory.h86
-rw-r--r--gpu/GrClipData.h54
-rw-r--r--gpu/GrColor.h127
-rw-r--r--gpu/GrConfig.h387
-rw-r--r--gpu/GrContext.h1021
-rw-r--r--gpu/GrContextFactory.h172
-rw-r--r--gpu/GrDrawEffect.h51
-rw-r--r--gpu/GrEffect.h345
-rw-r--r--gpu/GrEffectStage.h223
-rw-r--r--gpu/GrEffectUnitTest.h101
-rw-r--r--gpu/GrFontScaler.h38
-rw-r--r--gpu/GrGlyph.h78
-rw-r--r--gpu/GrKey.h43
-rw-r--r--gpu/GrNoncopyable.h30
-rw-r--r--gpu/GrOvalRenderer.h55
-rw-r--r--gpu/GrPaint.h254
-rw-r--r--gpu/GrPathRendererChain.h83
-rw-r--r--gpu/GrPoint.h30
-rw-r--r--gpu/GrRect.h30
-rw-r--r--gpu/GrRefCnt.h33
-rw-r--r--gpu/GrRenderTarget.h171
-rw-r--r--gpu/GrResource.h117
-rw-r--r--gpu/GrSurface.h134
-rw-r--r--gpu/GrTBackendEffectFactory.h78
-rw-r--r--gpu/GrTextContext.h57
-rw-r--r--gpu/GrTexture.h213
-rw-r--r--gpu/GrTextureAccess.h188
-rw-r--r--gpu/GrTypes.h630
-rw-r--r--gpu/GrTypesPriv.h169
-rw-r--r--gpu/GrUserConfig.h37
-rw-r--r--gpu/SkGpuDevice.h194
-rw-r--r--gpu/SkGr.h101
-rw-r--r--gpu/SkGrPixelRef.h70
-rw-r--r--gpu/SkGrTexturePixelRef.h19
-rw-r--r--gpu/gl/GrGLConfig.h194
-rw-r--r--gpu/gl/GrGLConfig_chrome.h44
-rw-r--r--gpu/gl/GrGLExtensions.h49
-rw-r--r--gpu/gl/GrGLFunctions.h231
-rw-r--r--gpu/gl/GrGLInterface.h329
-rw-r--r--gpu/gl/SkANGLEGLContext.h49
-rw-r--r--gpu/gl/SkDebugGLContext.h26
-rw-r--r--gpu/gl/SkGLContextHelper.h77
-rw-r--r--gpu/gl/SkMesaGLContext.h50
-rw-r--r--gpu/gl/SkNativeGLContext.h85
-rw-r--r--gpu/gl/SkNullGLContext.h26
-rw-r--r--images/SkForceLinking.h20
-rw-r--r--images/SkImageRef.h104
-rw-r--r--images/SkImageRef_GlobalPool.h61
-rw-r--r--images/SkImages.h14
-rw-r--r--images/SkMovie.h80
-rw-r--r--images/SkPageFlipper.h62
-rw-r--r--lazy/SkBitmapFactory.h99
-rw-r--r--lazy/SkImageCache.h132
-rw-r--r--lazy/SkLruImageCache.h91
-rw-r--r--lazy/SkPurgeableImageCache.h47
-rw-r--r--pathops/SkPathOps.h57
-rw-r--r--pdf/SkPDFDevice.h315
-rw-r--r--pdf/SkPDFDocument.h105
-rw-r--r--pipe/SkGPipe.h168
-rw-r--r--ports/SkFontConfigInterface.h111
-rw-r--r--ports/SkFontMgr.h112
-rw-r--r--ports/SkFontStyle.h70
-rw-r--r--ports/SkHarfBuzzFont.h42
-rw-r--r--ports/SkTypeface_android.h72
-rw-r--r--ports/SkTypeface_mac.h29
-rw-r--r--ports/SkTypeface_win.h39
-rw-r--r--svg/SkSVGAttribute.h42
-rw-r--r--svg/SkSVGBase.h25
-rw-r--r--svg/SkSVGPaintState.h89
-rw-r--r--svg/SkSVGParser.h74
-rw-r--r--svg/SkSVGTypes.h40
-rw-r--r--text/SkTextLayout.h60
-rw-r--r--utils/SkBoundaryPatch.h66
-rw-r--r--utils/SkCamera.h175
-rw-r--r--utils/SkCanvasStateUtils.h76
-rw-r--r--utils/SkCondVar.h68
-rw-r--r--utils/SkCountdown.h36
-rw-r--r--utils/SkCubicInterval.h22
-rw-r--r--utils/SkCullPoints.h71
-rw-r--r--utils/SkDebugUtils.h94
-rw-r--r--utils/SkDeferredCanvas.h256
-rw-r--r--utils/SkDumpCanvas.h168
-rw-r--r--utils/SkInterpolator.h131
-rw-r--r--utils/SkJSON.h285
-rw-r--r--utils/SkLayer.h130
-rw-r--r--utils/SkLua.h63
-rw-r--r--utils/SkLuaCanvas.h83
-rw-r--r--utils/SkMatrix44.h405
-rw-r--r--utils/SkMeshUtils.h50
-rw-r--r--utils/SkNWayCanvas.h91
-rw-r--r--utils/SkNinePatch.h33
-rw-r--r--utils/SkNullCanvas.h20
-rw-r--r--utils/SkParse.h36
-rw-r--r--utils/SkParsePaint.h26
-rw-r--r--utils/SkParsePath.h23
-rw-r--r--utils/SkPathUtils.h40
-rw-r--r--utils/SkPictureUtils.h31
-rw-r--r--utils/SkProxyCanvas.h93
-rw-r--r--utils/SkRTConf.h172
-rw-r--r--utils/SkRandom.h323
-rw-r--r--utils/SkRunnable.h17
-rw-r--r--utils/SkThreadPool.h51
-rw-r--r--utils/SkUnitMappers.h55
-rw-r--r--utils/SkWGL.h117
-rwxr-xr-xutils/ios/SkStream_NSData.h41
-rw-r--r--utils/mac/SkCGUtils.h67
-rw-r--r--utils/win/SkAutoCoInitialize.h30
-rw-r--r--utils/win/SkHRESULT.h54
-rw-r--r--utils/win/SkIStream.h131
-rw-r--r--utils/win/SkTScopedComPtr.h76
-rw-r--r--views/SkApplication.h19
-rw-r--r--views/SkBGViewArtist.h33
-rw-r--r--views/SkEvent.h284
-rw-r--r--views/SkEventSink.h112
-rw-r--r--views/SkKey.h62
-rw-r--r--views/SkOSMenu.h182
-rw-r--r--views/SkOSWindow_Android.h53
-rw-r--r--views/SkOSWindow_Mac.h58
-rw-r--r--views/SkOSWindow_NaCl.h52
-rw-r--r--views/SkOSWindow_SDL.h44
-rw-r--r--views/SkOSWindow_Unix.h82
-rw-r--r--views/SkOSWindow_Win.h101
-rwxr-xr-xviews/SkOSWindow_iOS.h50
-rw-r--r--views/SkStackViewLayout.h88
-rw-r--r--views/SkSystemEventTypes.h25
-rw-r--r--views/SkTextBox.h77
-rw-r--r--views/SkTouchGesture.h77
-rw-r--r--views/SkView.h405
-rw-r--r--views/SkViewInflate.h71
-rw-r--r--views/SkWidget.h412
-rw-r--r--views/SkWindow.h121
-rw-r--r--views/android/AndroidKeyToSkKey.h35
-rw-r--r--views/animated/SkBorderView.h40
-rw-r--r--views/animated/SkImageView.h68
-rw-r--r--views/animated/SkProgressBarView.h50
-rw-r--r--views/animated/SkScrollBarView.h44
-rw-r--r--views/animated/SkWidgetViews.h309
-rw-r--r--views/unix/XkeysToSkKeys.h38
-rw-r--r--views/unix/keysym2ucs.h15
-rw-r--r--xml/SkBML_WXMLParser.h46
-rw-r--r--xml/SkBML_XMLParser.h31
-rw-r--r--xml/SkDOM.h91
-rw-r--r--xml/SkJS.h39
-rw-r--r--xml/SkXMLParser.h155
-rw-r--r--xml/SkXMLWriter.h85
299 files changed, 43497 insertions, 0 deletions
diff --git a/animator/SkAnimator.h b/animator/SkAnimator.h
new file mode 100644
index 0000000..9bb3642
--- /dev/null
+++ b/animator/SkAnimator.h
@@ -0,0 +1,500 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkAnimator_DEFINED
+#define SkAnimator_DEFINED
+
+#include "SkScalar.h"
+#include "SkKey.h"
+#include "SkEventSink.h"
+
+class SkAnimateMaker;
+class SkCanvas;
+class SkDisplayable;
+class SkEvent;
+class SkExtras;
+struct SkMemberInfo;
+class SkPaint;
+struct SkRect;
+class SkStream;
+class SkTypedArray;
+class SkXMLParserError;
+class SkDOM;
+struct SkDOMNode;
+
+/** SkElementType is the type of element: a rectangle, a color, an animator, and so on.
+ This enum is incomplete and will be fleshed out in a future release */
+enum SkElementType {
+ kElementDummyType
+};
+/** SkFieldType is the type of field: a scalar, a string, an integer, a boolean, and so on.
+ This enum is incomplete and will be fleshed out in a future release */
+enum SkFieldType {
+ kFieldDummyType
+};
+
+/** \class SkAnimator
+
+ The SkAnimator class decodes an XML stream into a display list. The
+ display list can be drawn statically as a picture, or can drawn
+ different elements at different times to form a moving animation.
+
+ SkAnimator does not read the system time on its own; it relies on the
+ caller to pass the current time. The caller can pause, speed up, or
+ reverse the animation by varying the time passed in.
+
+ The XML describing the display list must conform to the schema
+ described by SkAnimateSchema.xsd.
+
+ The XML must contain an <event> element to draw. Usually, it contains
+ an <event kind="onload" /> block to add some drawing elements to the
+ display list when the document is first decoded.
+
+ Here's an "Hello World" XML sample:
+
+ <screenplay>
+ <event kind="onload" >
+ <text text="Hello World" y="20" />
+ </event>
+ </screenplay>
+
+ To read and draw this sample:
+
+ // choose one of these two
+ SkAnimator animator; // declare an animator instance on the stack
+ // SkAnimator* animator = new SkAnimator() // or one could instantiate the class
+
+ // choose one of these three
+ animator.decodeMemory(buffer, size); // to read from RAM
+ animator.decodeStream(stream); // to read from a user-defined stream (e.g., a zip file)
+ animator.decodeURI(filename); // to read from a web location, or from a local text file
+
+ // to draw to the current window:
+ SkCanvas canvas(getBitmap()); // create a canvas
+ animator.draw(canvas, &paint, 0); // draw the scene
+*/
+class SkAnimator : public SkEventSink {
+public:
+ SkAnimator();
+ virtual ~SkAnimator();
+
+ /** Add a drawable extension to the graphics engine. Experimental.
+ @param extras A derived class that implements methods that identify and instantiate the class
+ */
+ void addExtras(SkExtras* extras);
+
+ /** Read in XML from a stream, and append it to the current
+ animator. Returns false if an error was encountered.
+ Error diagnostics are stored in fErrorCode and fLineNumber.
+ @param stream The stream to append.
+ @return true if the XML was parsed successfully.
+ */
+ bool appendStream(SkStream* stream);
+
+ /** Read in XML from memory. Returns true if the file can be
+ read without error. Returns false if an error was encountered.
+ Error diagnostics are stored in fErrorCode and fLineNumber.
+ @param buffer The XML text as UTF-8 characters.
+ @param size The XML text length in bytes.
+ @return true if the XML was parsed successfully.
+ */
+ bool decodeMemory(const void* buffer, size_t size);
+
+ /** Read in XML from a stream. Returns true if the file can be
+ read without error. Returns false if an error was encountered.
+ Error diagnostics are stored in fErrorCode and fLineNumber.
+ @param stream The stream containg the XML text as UTF-8 characters.
+ @return true if the XML was parsed successfully.
+ */
+ virtual bool decodeStream(SkStream* stream);
+
+ /** Parse the DOM tree starting at the specified node. Returns true if it can be
+ parsed without error. Returns false if an error was encountered.
+ Error diagnostics are stored in fErrorCode and fLineNumber.
+ @return true if the DOM was parsed successfully.
+ */
+ virtual bool decodeDOM(const SkDOM&, const SkDOMNode*);
+
+ /** Read in XML from a URI. Returns true if the file can be
+ read without error. Returns false if an error was encountered.
+ Error diagnostics are stored in fErrorCode and fLineNumber.
+ @param uri The complete url path to be read (either ftp, http or https).
+ @return true if the XML was parsed successfully.
+ */
+ bool decodeURI(const char uri[]);
+
+ /** Pass a char event, usually a keyboard symbol, to the animator.
+ This triggers events of the form <event kind="keyChar" key="... />
+ @param ch The character to match against <event> element "key"
+ attributes.
+ @return true if the event was dispatched successfully.
+ */
+ bool doCharEvent(SkUnichar ch);
+
+ /** Experimental:
+ Pass a mouse click event along with the mouse coordinates to
+ the animator. This triggers events of the form <event kind="mouseDown" ... />
+ and other mouse events.
+ @param state The mouse state, described by SkView::Click::State : values are
+ down == 0, moved == 1, up == 2
+ @param x The x-position of the mouse
+ @param y The y-position of the mouse
+ @return true if the event was dispatched successfully.
+ */
+ bool doClickEvent(int state, SkScalar x, SkScalar y);
+
+ /** Pass a meta-key event, such as an arrow , to the animator.
+ This triggers events of the form <event kind="keyPress" code="... />
+ @param code The key to match against <event> element "code"
+ attributes.
+ @return true if the event was dispatched successfully.
+ */
+ bool doKeyEvent(SkKey code);
+ bool doKeyUpEvent(SkKey code);
+
+ /** Send an event to the animator. The animator's clock is set
+ relative to the current time.
+ @return true if the event was dispatched successfully.
+ */
+ bool doUserEvent(const SkEvent& evt);
+
+ /** The possible results from the draw function.
+ */
+ enum DifferenceType {
+ kNotDifferent,
+ kDifferent,
+ kPartiallyDifferent
+ };
+ /** Draws one frame of the animation. The first call to draw always
+ draws the initial frame of the animation. Subsequent calls draw
+ the offset into the animation by
+ subtracting the initial time from the current time.
+ @param canvas The canvas to draw into.
+ @param paint The paint to draw with.
+ @param time The offset into the current animation.
+ @return kNotDifferent if there are no active animations; kDifferent if there are active animations; and
+ kPartiallyDifferent if the document contains an active <bounds> element that specifies a minimal
+ redraw area.
+ */
+ DifferenceType draw(SkCanvas* canvas, SkPaint* paint, SkMSec time);
+
+ /** Draws one frame of the animation, using a new Paint each time.
+ The first call to draw always
+ draws the initial frame of the animation. Subsequent calls draw
+ the offset into the animation by
+ subtracting the initial time from the current time.
+ @param canvas The canvas to draw into.
+ @param time The offset into the current animation.
+ @return kNotDifferent if there are no active animations; kDifferent if there are active animations; and
+ kPartiallyDifferent if the document contains an active <bounds> element that specifies a minimal
+ redraw area.
+ */
+ DifferenceType draw(SkCanvas* canvas, SkMSec time);
+
+ /** Experimental:
+ Helper to choose whether to return a SkView::Click handler.
+ @param x ignored
+ @param y ignored
+ @return true if a mouseDown event handler is enabled.
+ */
+ bool findClickEvent(SkScalar x, SkScalar y);
+
+
+ /** Get the nested animator associated with this element, if any.
+ Use this to access a movie's event sink, to send events to movies.
+ @param element the value returned by getElement
+ @return the internal animator.
+ */
+ const SkAnimator* getAnimator(const SkDisplayable* element) const;
+
+ /** Returns the scalar value of the specified element's attribute[index]
+ @param element the value returned by getElement
+ @param field the value returned by getField
+ @param index the array entry
+ @return the integer value to retrieve, or SK_NaN32 if unsuccessful
+ */
+ int32_t getArrayInt(const SkDisplayable* element, const SkMemberInfo* field, int index);
+
+ /** Returns the scalar value of the specified element's attribute[index]
+ @param elementID is the value of the id attribute in the XML of this element
+ @param fieldName specifies the name of the attribute
+ @param index the array entry
+ @return the integer value to retrieve, or SK_NaN32 if unsuccessful
+ */
+ int32_t getArrayInt(const char* elementID, const char* fieldName, int index);
+
+ /** Returns the scalar value of the specified element's attribute[index]
+ @param element the value returned by getElement
+ @param field the value returned by getField
+ @param index the array entry
+ @return the scalar value to retrieve, or SK_ScalarNaN if unsuccessful
+ */
+ SkScalar getArrayScalar(const SkDisplayable* element, const SkMemberInfo* field, int index);
+
+ /** Returns the scalar value of the specified element's attribute[index]
+ @param elementID is the value of the id attribute in the XML of this element
+ @param fieldName specifies the name of the attribute
+ @param index the array entry
+ @return the scalar value to retrieve, or SK_ScalarNaN if unsuccessful
+ */
+ SkScalar getArrayScalar(const char* elementID, const char* fieldName, int index);
+
+ /** Returns the string value of the specified element's attribute[index]
+ @param element is a value returned by getElement
+ @param field is a value returned by getField
+ @param index the array entry
+ @return the string value to retrieve, or null if unsuccessful
+ */
+ const char* getArrayString(const SkDisplayable* element, const SkMemberInfo* field, int index);
+
+ /** Returns the string value of the specified element's attribute[index]
+ @param elementID is the value of the id attribute in the XML of this element
+ @param fieldName specifies the name of the attribute
+ @param index the array entry
+ @return the string value to retrieve, or null if unsuccessful
+ */
+ const char* getArrayString(const char* elementID, const char* fieldName, int index);
+
+ /** Returns the XML element corresponding to the given ID.
+ @param elementID is the value of the id attribute in the XML of this element
+ @return the element matching the ID, or null if the element can't be found
+ */
+ const SkDisplayable* getElement(const char* elementID);
+
+ /** Returns the element type corresponding to the XML element.
+ The element type matches the element name; for instance, <line> returns kElement_LineType
+ @param element is a value returned by getElement
+ @return element type, or 0 if the element can't be found
+ */
+ SkElementType getElementType(const SkDisplayable* element);
+
+ /** Returns the element type corresponding to the given ID.
+ @param elementID is the value of the id attribute in the XML of this element
+ @return element type, or 0 if the element can't be found
+ */
+ SkElementType getElementType(const char* elementID);
+
+ /** Returns the XML field of the named attribute in the XML element.
+ @param element is a value returned by getElement
+ @param fieldName is the attribute to return
+ @return the attribute matching the fieldName, or null if the element can't be found
+ */
+ const SkMemberInfo* getField(const SkDisplayable* element, const char* fieldName);
+
+ /** Returns the XML field of the named attribute in the XML element matching the elementID.
+ @param elementID is the value of the id attribute in the XML of this element
+ @param fieldName is the attribute to return
+ @return the attribute matching the fieldName, or null if the element can't be found
+ */
+ const SkMemberInfo* getField(const char* elementID, const char* fieldName);
+
+ /** Returns the value type coresponding to the element's attribute.
+ The value type matches the XML schema: and may be kField_BooleanType, kField_ScalarType, etc.
+ @param field is a value returned by getField
+ @return the attribute type, or 0 if the element can't be found
+ */
+ SkFieldType getFieldType(const SkMemberInfo* field);
+
+ /** Returns the value type coresponding to the element's attribute.
+ @param elementID is the value of the id attribute in the XML of this element
+ @param fieldName specifies the name of the attribute
+ @return the attribute type, or 0 if the element can't be found
+ */
+ SkFieldType getFieldType(const char* elementID, const char* fieldName);
+
+ /** Returns the recommended animation interval. Returns zero if no
+ interval is specified.
+ */
+ SkMSec getInterval();
+
+ /** Returns the partial rectangle to invalidate after drawing. Call after draw() returns
+ kIsPartiallyDifferent to do a mimimal inval(). */
+ void getInvalBounds(SkRect* inval);
+
+ /** Returns the details of any error encountered while parsing the XML.
+ */
+ const SkXMLParserError* getParserError();
+
+ /** Returns the details of any error encountered while parsing the XML as string.
+ */
+ const char* getParserErrorString();
+
+ /** Returns the scalar value of the specified element's attribute
+ @param element is a value returned by getElement
+ @param field is a value returned by getField
+ @return the integer value to retrieve, or SK_NaN32 if not found
+ */
+ int32_t getInt(const SkDisplayable* element, const SkMemberInfo* field);
+
+ /** Returns the scalar value of the specified element's attribute
+ @param elementID is the value of the id attribute in the XML of this element
+ @param fieldName specifies the name of the attribute
+ @return the integer value to retrieve, or SK_NaN32 if not found
+ */
+ int32_t getInt(const char* elementID, const char* fieldName);
+
+ /** Returns the scalar value of the specified element's attribute
+ @param element is a value returned by getElement
+ @param field is a value returned by getField
+ @return the scalar value to retrieve, or SK_ScalarNaN if not found
+ */
+ SkScalar getScalar(const SkDisplayable* element, const SkMemberInfo* field);
+
+ /** Returns the scalar value of the specified element's attribute
+ @param elementID is the value of the id attribute in the XML of this element
+ @param fieldName specifies the name of the attribute
+ @return the scalar value to retrieve, or SK_ScalarNaN if not found
+ */
+ SkScalar getScalar(const char* elementID, const char* fieldName);
+
+ /** Returns the string value of the specified element's attribute
+ @param element is a value returned by getElement
+ @param field is a value returned by getField
+ @return the string value to retrieve, or null if not found
+ */
+ const char* getString(const SkDisplayable* element, const SkMemberInfo* field);
+
+ /** Returns the string value of the specified element's attribute
+ @param elementID is the value of the id attribute in the XML of this element
+ @param fieldName specifies the name of the attribute
+ @return the string value to retrieve, or null if not found
+ */
+ const char* getString(const char* elementID, const char* fieldName);
+
+ /** Gets the file default directory of the URL base path set explicitly or by reading the last URL. */
+ const char* getURIBase();
+
+ /** Resets the animator to a newly created state with no animation data. */
+ void initialize();
+
+ /** Experimental. Resets any active animations so that the next time passed is treated as
+ time zero. */
+ void reset();
+
+ /** Sets the scalar value of the specified element's attribute
+ @param elementID is the value of the id attribute in the XML of this element
+ @param fieldName specifies the name of the attribute
+ @param array is the c-style array of integers
+ @param count is the length of the array
+ @return true if the value was set successfully
+ */
+ bool setArrayInt(const char* elementID, const char* fieldName, const int* array, int count);
+
+ /** Sets the scalar value of the specified element's attribute
+ @param elementID is the value of the id attribute in the XML of this element
+ @param fieldName specifies the name of the attribute
+ @param array is the c-style array of strings
+ @param count is the length of the array
+ @return true if the value was set successfully
+ */
+ bool setArrayString(const char* elementID, const char* fieldName, const char** array, int count);
+
+ /** Sets the scalar value of the specified element's attribute
+ @param elementID is the value of the id attribute in the XML of this element
+ @param fieldName specifies the name of the attribute
+ @param data the integer value to set
+ @return true if the value was set successfully
+ */
+ bool setInt(const char* elementID, const char* fieldName, int32_t data);
+
+ /** Sets the scalar value of the specified element's attribute
+ @param elementID is the value of the id attribute in the XML of this element
+ @param fieldName specifies the name of the attribute
+ @param data the scalar value to set
+ @return true if the value was set successfully
+ */
+ bool setScalar(const char* elementID, const char* fieldName, SkScalar data);
+
+ /** Sets the string value of the specified element's attribute
+ @param elementID is the value of the id attribute in the XML of this element
+ @param fieldName specifies the name of the attribute
+ @param data the string value to set
+ @return true if the value was set successfully
+ */
+ bool setString(const char* elementID, const char* fieldName, const char* data);
+
+ /** Sets the file default directory of the URL base path
+ @param path the directory path
+ */
+ void setURIBase(const char* path);
+
+ typedef void* Handler;
+ // This guy needs to be exported to java, so don't make it virtual
+ void setHostHandler(Handler handler) {
+ this->onSetHostHandler(handler);
+ }
+
+ /** \class Timeline
+ Returns current time to animator. To return a custom timeline, create a child
+ class and override the getMSecs method.
+ */
+ class Timeline {
+ public:
+ virtual ~Timeline() {}
+
+ /** Returns the current time in milliseconds */
+ virtual SkMSec getMSecs() const = 0;
+ };
+
+ /** Sets a user class to return the current time to the animator.
+ Optional; if not called, the system clock will be used by calling SkTime::GetMSecs instead.
+ @param callBack the time function
+ */
+ void setTimeline(const Timeline& );
+
+ static void Init(bool runUnitTests);
+ static void Term();
+
+ /** The event sink events generated by the animation are posted to.
+ Screenplay also posts an inval event to this event sink after processing an
+ event to force a redraw.
+ @param target the event sink id
+ */
+ void setHostEventSinkID(SkEventSinkID hostID);
+ SkEventSinkID getHostEventSinkID() const;
+
+ // helper
+ void setHostEventSink(SkEventSink* sink) {
+ this->setHostEventSinkID(sink ? sink->getSinkID() : 0);
+ }
+
+ virtual void setJavaOwner(Handler owner);
+
+#ifdef SK_DEBUG
+ virtual void eventDone(const SkEvent& evt);
+ virtual bool isTrackingEvents();
+ static bool NoLeaks();
+#endif
+
+protected:
+ virtual void onSetHostHandler(Handler handler);
+ virtual void onEventPost(SkEvent*, SkEventSinkID);
+ virtual void onEventPostTime(SkEvent*, SkEventSinkID, SkMSec time);
+
+private:
+// helper functions for setters
+ bool setArray(SkDisplayable* element, const SkMemberInfo* field, SkTypedArray array);
+ bool setArray(const char* elementID, const char* fieldName, SkTypedArray array);
+ bool setInt(SkDisplayable* element, const SkMemberInfo* field, int32_t data);
+ bool setScalar(SkDisplayable* element, const SkMemberInfo* field, SkScalar data);
+ bool setString(SkDisplayable* element, const SkMemberInfo* field, const char* data);
+
+ virtual bool onEvent(const SkEvent&);
+ SkAnimateMaker* fMaker;
+ friend class SkAnimateMaker;
+ friend class SkAnimatorScript;
+ friend class SkAnimatorScript2;
+ friend class SkApply;
+ friend class SkDisplayMovie;
+ friend class SkDisplayType;
+ friend class SkPost;
+ friend class SkXMLAnimatorWriter;
+};
+
+#endif
diff --git a/animator/SkAnimatorView.h b/animator/SkAnimatorView.h
new file mode 100644
index 0000000..2b2c61b
--- /dev/null
+++ b/animator/SkAnimatorView.h
@@ -0,0 +1,39 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkAnimatorView_DEFINED
+#define SkAnimatorView_DEFINED
+
+#include "SkView.h"
+#include "SkAnimator.h"
+
+class SkAnimatorView : public SkView {
+public:
+ SkAnimatorView();
+ virtual ~SkAnimatorView();
+
+ SkAnimator* getAnimator() const { return fAnimator; }
+
+ bool decodeFile(const char path[]);
+ bool decodeMemory(const void* buffer, size_t size);
+ bool decodeStream(SkStream* stream);
+
+protected:
+ // overrides
+ virtual bool onEvent(const SkEvent&);
+ virtual void onDraw(SkCanvas*);
+ virtual void onInflate(const SkDOM&, const SkDOM::Node*);
+
+private:
+ SkAnimator* fAnimator;
+
+ typedef SkView INHERITED;
+};
+
+#endif
diff --git a/config/SkUserConfig.h b/config/SkUserConfig.h
new file mode 100644
index 0000000..236a99a
--- /dev/null
+++ b/config/SkUserConfig.h
@@ -0,0 +1,205 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkUserConfig_DEFINED
+#define SkUserConfig_DEFINED
+
+/* SkTypes.h, the root of the public header files, does the following trick:
+
+ #include "SkPreConfig.h"
+ #include "SkUserConfig.h"
+ #include "SkPostConfig.h"
+
+ SkPreConfig.h runs first, and it is responsible for initializing certain
+ skia defines.
+
+ SkPostConfig.h runs last, and its job is to just check that the final
+ defines are consistent (i.e. that we don't have mutually conflicting
+ defines).
+
+ SkUserConfig.h (this file) runs in the middle. It gets to change or augment
+ the list of flags initially set in preconfig, and then postconfig checks
+ that everything still makes sense.
+
+ Below are optional defines that add, subtract, or change default behavior
+ in Skia. Your port can locally edit this file to enable/disable flags as
+ you choose, or these can be delared on your command line (i.e. -Dfoo).
+
+ By default, this include file will always default to having all of the flags
+ commented out, so including it will have no effect.
+*/
+
+///////////////////////////////////////////////////////////////////////////////
+
+/* Scalars (the fractional value type in skia) can be implemented either as
+ floats or 16.16 integers (fixed). Exactly one of these two symbols must be
+ defined.
+*/
+//#define SK_SCALAR_IS_FLOAT
+//#define SK_SCALAR_IS_FIXED
+
+
+/* For some performance-critical scalar operations, skia will optionally work
+ around the standard float operators if it knows that the CPU does not have
+ native support for floats. If your environment uses software floating point,
+ define this flag.
+ */
+//#define SK_SOFTWARE_FLOAT
+
+
+/* Skia has lots of debug-only code. Often this is just null checks or other
+ parameter checking, but sometimes it can be quite intrusive (e.g. check that
+ each 32bit pixel is in premultiplied form). This code can be very useful
+ during development, but will slow things down in a shipping product.
+
+ By default, these mutually exclusive flags are defined in SkPreConfig.h,
+ based on the presence or absence of NDEBUG, but that decision can be changed
+ here.
+ */
+//#define SK_DEBUG
+//#define SK_RELEASE
+
+/* Skia has certain debug-only code that is extremely intensive even for debug
+ builds. This code is useful for diagnosing specific issues, but is not
+ generally applicable, therefore it must be explicitly enabled to avoid
+ the performance impact. By default these flags are undefined, but can be
+ enabled by uncommenting them below.
+ */
+//#define SK_DEBUG_GLYPH_CACHE
+//#define SK_DEBUG_PATH
+
+/* To assist debugging, Skia provides an instance counting utility in
+ include/core/SkInstCount.h. This flag turns on and off that utility to
+ allow instance count tracking in either debug or release builds. By
+ default it is enabled in debug but disabled in release.
+ */
+//#define SK_ENABLE_INST_COUNT 1
+
+/* If, in debugging mode, Skia needs to stop (presumably to invoke a debugger)
+ it will call SK_CRASH(). If this is not defined it, it is defined in
+ SkPostConfig.h to write to an illegal address
+ */
+//#define SK_CRASH() *(int *)(uintptr_t)0 = 0
+
+
+/* preconfig will have attempted to determine the endianness of the system,
+ but you can change these mutually exclusive flags here.
+ */
+//#define SK_CPU_BENDIAN
+//#define SK_CPU_LENDIAN
+
+/* Most compilers use the same bit endianness for bit flags in a byte as the
+ system byte endianness, and this is the default. If for some reason this
+ needs to be overridden, specify which of the mutually exclusive flags to
+ use. For example, some atom processors in certain configurations have big
+ endian byte order but little endian bit orders.
+*/
+//#define SK_UINT8_BITFIELD_BENDIAN
+//#define SK_UINT8_BITFIELD_LENDIAN
+
+
+/* Some compilers don't support long long for 64bit integers. If yours does
+ not, define this to the appropriate type.
+ */
+//#define SkLONGLONG int64_t
+
+
+/* To write debug messages to a console, skia will call SkDebugf(...) following
+ printf conventions (e.g. const char* format, ...). If you want to redirect
+ this to something other than printf, define yours here
+ */
+//#define SkDebugf(...) MyFunction(__VA_ARGS__)
+
+/*
+ * To specify a different default font cache limit, define this. If this is
+ * undefined, skia will use a built-in value.
+ */
+//#define SK_DEFAULT_FONT_CACHE_LIMIT (1024 * 1024)
+
+/*
+ * To specify the default size of the image cache, undefine this and set it to
+ * the desired value (in bytes). SkGraphics.h as a runtime API to set this
+ * value as well. If this is undefined, a built-in value will be used.
+ */
+//#define SK_DEFAULT_IMAGE_CACHE_LIMIT (1024 * 1024)
+
+/* If zlib is available and you want to support the flate compression
+ algorithm (used in PDF generation), define SK_ZLIB_INCLUDE to be the
+ include path. Alternatively, define SK_SYSTEM_ZLIB to use the system zlib
+ library specified as "#include <zlib.h>".
+ */
+//#define SK_ZLIB_INCLUDE <zlib.h>
+//#define SK_SYSTEM_ZLIB
+
+/* Define this to allow PDF scalars above 32k. The PDF/A spec doesn't allow
+ them, but modern PDF interpreters should handle them just fine.
+ */
+//#define SK_ALLOW_LARGE_PDF_SCALARS
+
+/* Define this to provide font subsetter in PDF generation.
+ */
+//#define SK_SFNTLY_SUBSETTER "sfntly/subsetter/font_subsetter.h"
+
+/* Define this to set the upper limit for text to support LCD. Values that
+ are very large increase the cost in the font cache and draw slower, without
+ improving readability. If this is undefined, Skia will use its default
+ value (e.g. 48)
+ */
+//#define SK_MAX_SIZE_FOR_LCDTEXT 48
+
+/* If SK_DEBUG is defined, then you can optionally define SK_SUPPORT_UNITTEST
+ which will run additional self-tests at startup. These can take a long time,
+ so this flag is optional.
+ */
+#ifdef SK_DEBUG
+//#define SK_SUPPORT_UNITTEST
+#endif
+
+/* If your system embeds skia and has complex event logging, define this
+ symbol to name a file that maps the following macros to your system's
+ equivalents:
+ SK_TRACE_EVENT0(event)
+ SK_TRACE_EVENT1(event, name1, value1)
+ SK_TRACE_EVENT2(event, name1, value1, name2, value2)
+ src/utils/SkDebugTrace.h has a trivial implementation that writes to
+ the debug output stream. If SK_USER_TRACE_INCLUDE_FILE is not defined,
+ SkTrace.h will define the above three macros to do nothing.
+*/
+//#undef SK_USER_TRACE_INCLUDE_FILE
+
+/* Change the ordering to work in X windows.
+ */
+#ifdef SK_SAMPLES_FOR_X
+ #define SK_R32_SHIFT 16
+ #define SK_G32_SHIFT 8
+ #define SK_B32_SHIFT 0
+ #define SK_A32_SHIFT 24
+#endif
+
+
+/* Determines whether to build code that supports the GPU backend. Some classes
+ that are not GPU-specific, such as SkShader subclasses, have optional code
+ that is used allows them to interact with the GPU backend. If you'd like to
+ omit this code set SK_SUPPORT_GPU to 0. This also allows you to omit the gpu
+ directories from your include search path when you're not building the GPU
+ backend. Defaults to 1 (build the GPU code).
+ */
+//#define SK_SUPPORT_GPU 1
+
+
+/* The PDF generation code uses Path Ops to generate inverse fills and complex
+ * clipping paths, but at this time, Path Ops is not release ready yet. So,
+ * the code is hidden behind this #define guard. If you are feeling adventurous
+ * and want the latest and greatest PDF generation code, uncomment the #define.
+ * When Path Ops is release ready, the define guards and this user config
+ * define should be removed entirely.
+ */
+//#define SK_PDF_USE_PATHOPS
+
+#endif
diff --git a/config/sk_stdint.h b/config/sk_stdint.h
new file mode 100644
index 0000000..360755e
--- /dev/null
+++ b/config/sk_stdint.h
@@ -0,0 +1,23 @@
+
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#ifndef sk_stdint_DEFINED
+#define sk_stdint_DEFINED
+
+typedef signed char int8_t;
+typedef unsigned char uint8_t;
+typedef short int16_t;
+typedef unsigned short uint16_t;
+typedef int int32_t;
+typedef unsigned uint32_t;
+typedef long long int64_t;
+typedef unsigned long long uint64_t;
+
+typedef int64_t intmax_t;
+typedef uint64_t uintmax_t;
+
+#endif
diff --git a/core/Sk64.h b/core/Sk64.h
new file mode 100644
index 0000000..6db3001
--- /dev/null
+++ b/core/Sk64.h
@@ -0,0 +1,230 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef Sk64_DEFINED
+#define Sk64_DEFINED
+
+#include "SkFixed.h"
+
+/** \class Sk64
+
+ Sk64 is a 64-bit math package that does not require long long support from the compiler.
+*/
+struct SK_API Sk64 {
+ int32_t fHi; //!< the high 32 bits of the number (including sign)
+ uint32_t fLo; //!< the low 32 bits of the number
+
+ /** Returns non-zero if the Sk64 can be represented as a signed 32 bit integer
+ */
+ SkBool is32() const { return fHi == ((int32_t)fLo >> 31); }
+
+ /** Returns non-zero if the Sk64 cannot be represented as a signed 32 bit integer
+ */
+ SkBool is64() const { return fHi != ((int32_t)fLo >> 31); }
+
+ /** Returns non-zero if the Sk64 can be represented as a signed 48 bit integer. Used to know
+ if we can shift the value down by 16 to treat it as a SkFixed.
+ */
+ SkBool isFixed() const;
+
+ /** Return the signed 32 bit integer equivalent. Asserts that is32() returns non-zero.
+ */
+ int32_t get32() const { SkASSERT(this->is32()); return (int32_t)fLo; }
+
+ /** Return the number >> 16. Asserts that this does not loose any significant high bits.
+ */
+ SkFixed getFixed() const {
+ SkASSERT(this->isFixed());
+
+ uint32_t sum = fLo + (1 << 15);
+ int32_t hi = fHi;
+ if (sum < fLo) {
+ hi += 1;
+ }
+ return (hi << 16) | (sum >> 16);
+ }
+
+ /** Return the number >> 30. Asserts that this does not loose any
+ significant high bits.
+ */
+ SkFract getFract() const;
+
+ /** Returns the square-root of the number as a signed 32 bit value. */
+ int32_t getSqrt() const;
+
+ /** Returns the number of leading zeros of the absolute value of this.
+ Will return in the range [0..64]
+ */
+ int getClzAbs() const;
+
+ /** Returns non-zero if the number is zero */
+ SkBool isZero() const { return (fHi | fLo) == 0; }
+
+ /** Returns non-zero if the number is non-zero */
+ SkBool nonZero() const { return fHi | fLo; }
+
+ /** Returns non-zero if the number is negative (number < 0) */
+ SkBool isNeg() const { return (uint32_t)fHi >> 31; }
+
+ /** Returns non-zero if the number is positive (number > 0) */
+ SkBool isPos() const { return ~(fHi >> 31) & (fHi | fLo); }
+
+ /** Returns -1,0,+1 based on the sign of the number */
+ int getSign() const { return (fHi >> 31) | Sk32ToBool(fHi | fLo); }
+
+ /** Negate the number */
+ void negate();
+
+ /** If the number < 0, negate the number
+ */
+ void abs();
+
+ /** Returns the number of bits needed to shift the Sk64 to the right
+ in order to make it fit in a signed 32 bit integer.
+ */
+ int shiftToMake32() const;
+
+ /** Set the number to zero */
+ void setZero() { fHi = fLo = 0; }
+
+ /** Set the high and low 32 bit values of the number */
+ void set(int32_t hi, uint32_t lo) { fHi = hi; fLo = lo; }
+
+ /** Set the number to the specified 32 bit integer */
+ void set(int32_t a) { fHi = a >> 31; fLo = a; }
+
+ /** Set the number to the product of the two 32 bit integers */
+ void setMul(int32_t a, int32_t b);
+
+ /** extract 32bits after shifting right by bitCount.
+ Note: itCount must be [0..63].
+ Asserts that no significant high bits were lost.
+ */
+ int32_t getShiftRight(unsigned bitCount) const;
+
+ /** Shift the number left by the specified number of bits.
+ @param bits How far to shift left, must be [0..63]
+ */
+ void shiftLeft(unsigned bits);
+
+ /** Shift the number right by the specified number of bits.
+ @param bits How far to shift right, must be [0..63]. This
+ performs an arithmetic right-shift (sign extending).
+ */
+ void shiftRight(unsigned bits);
+
+ /** Shift the number right by the specified number of bits, but
+ round the result.
+ @param bits How far to shift right, must be [0..63]. This
+ performs an arithmetic right-shift (sign extending).
+ */
+ void roundRight(unsigned bits);
+
+ /** Add the specified 32 bit integer to the number */
+ void add(int32_t lo) {
+ int32_t hi = lo >> 31; // 0 or -1
+ uint32_t sum = fLo + (uint32_t)lo;
+
+ fHi = fHi + hi + (sum < fLo);
+ fLo = sum;
+ }
+
+ /** Add the specified Sk64 to the number */
+ void add(int32_t hi, uint32_t lo) {
+ uint32_t sum = fLo + lo;
+
+ fHi = fHi + hi + (sum < fLo);
+ fLo = sum;
+ }
+
+ /** Add the specified Sk64 to the number */
+ void add(const Sk64& other) { this->add(other.fHi, other.fLo); }
+
+ /** Subtract the specified Sk64 from the number. (*this) = (*this) - num
+ */
+ void sub(const Sk64& num);
+
+ /** Subtract the number from the specified Sk64. (*this) = num - (*this)
+ */
+ void rsub(const Sk64& num);
+
+ /** Multiply the number by the specified 32 bit integer
+ */
+ void mul(int32_t);
+
+ enum DivOptions {
+ kTrunc_DivOption, //!< truncate the result when calling div()
+ kRound_DivOption //!< round the result when calling div()
+ };
+
+ /** Divide the number by the specified 32 bit integer, using the specified
+ divide option (either truncate or round).
+ */
+ void div(int32_t, DivOptions);
+
+ /** return (this + other >> 16) as a 32bit result */
+ SkFixed addGetFixed(const Sk64& other) const {
+ return this->addGetFixed(other.fHi, other.fLo);
+ }
+
+ /** return (this + Sk64(hi, lo) >> 16) as a 32bit result */
+ SkFixed addGetFixed(int32_t hi, uint32_t lo) const {
+#ifdef SK_DEBUG
+ Sk64 tmp(*this);
+ tmp.add(hi, lo);
+#endif
+
+ uint32_t sum = fLo + lo;
+ hi += fHi + (sum < fLo);
+ lo = sum;
+
+ sum = lo + (1 << 15);
+ if (sum < lo)
+ hi += 1;
+
+ hi = (hi << 16) | (sum >> 16);
+ SkASSERT(hi == tmp.getFixed());
+ return hi;
+ }
+
+ /** Return the result of dividing the number by denom, treating the answer
+ as a SkFixed. (*this) << 16 / denom. It is an error for denom to be 0.
+ */
+ SkFixed getFixedDiv(const Sk64& denom) const;
+
+ friend bool operator==(const Sk64& a, const Sk64& b) {
+ return a.fHi == b.fHi && a.fLo == b.fLo;
+ }
+
+ friend bool operator!=(const Sk64& a, const Sk64& b) {
+ return a.fHi != b.fHi || a.fLo != b.fLo;
+ }
+
+ friend bool operator<(const Sk64& a, const Sk64& b) {
+ return a.fHi < b.fHi || (a.fHi == b.fHi && a.fLo < b.fLo);
+ }
+
+ friend bool operator<=(const Sk64& a, const Sk64& b) {
+ return a.fHi < b.fHi || (a.fHi == b.fHi && a.fLo <= b.fLo);
+ }
+
+ friend bool operator>(const Sk64& a, const Sk64& b) {
+ return a.fHi > b.fHi || (a.fHi == b.fHi && a.fLo > b.fLo);
+ }
+
+ friend bool operator>=(const Sk64& a, const Sk64& b) {
+ return a.fHi > b.fHi || (a.fHi == b.fHi && a.fLo >= b.fLo);
+ }
+
+#ifdef SkLONGLONG
+ SkLONGLONG getLongLong() const;
+#endif
+};
+
+#endif
diff --git a/core/SkAdvancedTypefaceMetrics.h b/core/SkAdvancedTypefaceMetrics.h
new file mode 100755
index 0000000..acfd86e
--- /dev/null
+++ b/core/SkAdvancedTypefaceMetrics.h
@@ -0,0 +1,157 @@
+
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkAdvancedTypefaceMetrics_DEFINED
+#define SkAdvancedTypefaceMetrics_DEFINED
+
+#include "SkRect.h"
+#include "SkRefCnt.h"
+#include "SkString.h"
+#include "SkTDArray.h"
+#include "SkTemplates.h"
+#include "SkTScopedPtr.h"
+
+/** \class SkAdvancedTypefaceMetrics
+
+ The SkAdvancedTypefaceMetrics class is used by the PDF backend to correctly
+ embed typefaces. This class is filled in with information about a given
+ typeface by the SkFontHost class.
+*/
+
+class SkAdvancedTypefaceMetrics : public SkRefCnt {
+public:
+ SK_DECLARE_INST_COUNT(SkAdvancedTypefaceMetrics)
+
+ SkString fFontName;
+
+ enum FontType {
+ kType1_Font,
+ kType1CID_Font,
+ kCFF_Font,
+ kTrueType_Font,
+ kOther_Font,
+ kNotEmbeddable_Font
+ };
+ // The type of the underlying font program. This field determines which
+ // of the following fields are valid. If it is kOther_Font or
+ // kNotEmbeddable_Font, the per glyph information will never be populated.
+ FontType fType;
+
+ // fMultiMaster may be true for Type1_Font or CFF_Font.
+ bool fMultiMaster;
+ uint16_t fLastGlyphID; // The last valid glyph ID in the font.
+ uint16_t fEmSize; // The size of the em box (defines font units).
+
+ // These enum values match the values used in the PDF file format.
+ enum StyleFlags {
+ kFixedPitch_Style = 0x00001,
+ kSerif_Style = 0x00002,
+ kScript_Style = 0x00008,
+ kItalic_Style = 0x00040,
+ kAllCaps_Style = 0x10000,
+ kSmallCaps_Style = 0x20000,
+ kForceBold_Style = 0x40000
+ };
+ uint16_t fStyle; // Font style characteristics.
+ int16_t fItalicAngle; // Counterclockwise degrees from vertical of the
+ // dominant vertical stroke for an Italic face.
+ // The following fields are all in font units.
+ int16_t fAscent; // Max height above baseline, not including accents.
+ int16_t fDescent; // Max depth below baseline (negative).
+ int16_t fStemV; // Thickness of dominant vertical stem.
+ int16_t fCapHeight; // Height (from baseline) of top of flat capitals.
+
+ SkIRect fBBox; // The bounding box of all glyphs (in font units).
+
+ // The type of advance data wanted.
+ enum PerGlyphInfo {
+ kNo_PerGlyphInfo = 0x0, // Don't populate any per glyph info.
+ kHAdvance_PerGlyphInfo = 0x1, // Populate horizontal advance data.
+ kVAdvance_PerGlyphInfo = 0x2, // Populate vertical advance data.
+ kGlyphNames_PerGlyphInfo = 0x4, // Populate glyph names (Type 1 only).
+ kToUnicode_PerGlyphInfo = 0x8 // Populate ToUnicode table, ignored
+ // for Type 1 fonts
+ };
+
+ template <typename Data>
+ struct AdvanceMetric {
+ enum MetricType {
+ kDefault, // Default advance: fAdvance.count = 1
+ kRange, // Advances for a range: fAdvance.count = fEndID-fStartID
+ kRun // fStartID-fEndID have same advance: fAdvance.count = 1
+ };
+ MetricType fType;
+ uint16_t fStartId;
+ uint16_t fEndId;
+ SkTDArray<Data> fAdvance;
+ SkTScopedPtr<AdvanceMetric<Data> > fNext;
+ };
+
+ struct VerticalMetric {
+ int16_t fVerticalAdvance;
+ int16_t fOriginXDisp; // Horiz. displacement of the secondary origin.
+ int16_t fOriginYDisp; // Vert. displacement of the secondary origin.
+ };
+ typedef AdvanceMetric<int16_t> WidthRange;
+ typedef AdvanceMetric<VerticalMetric> VerticalAdvanceRange;
+
+ // This is indexed by glyph id.
+ SkTScopedPtr<WidthRange> fGlyphWidths;
+ // Only used for Vertical CID fonts.
+ SkTScopedPtr<VerticalAdvanceRange> fVerticalMetrics;
+
+ // The names of each glyph, only populated for postscript fonts.
+ SkTScopedPtr<SkAutoTArray<SkString> > fGlyphNames;
+
+ // The mapping from glyph to Unicode, only populated if
+ // kToUnicode_PerGlyphInfo is passed to GetAdvancedTypefaceMetrics.
+ SkTDArray<SkUnichar> fGlyphToUnicode;
+
+private:
+ typedef SkRefCnt INHERITED;
+};
+
+namespace skia_advanced_typeface_metrics_utils {
+
+template <typename Data>
+void resetRange(SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* range,
+ int startId);
+
+template <typename Data>
+SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* appendRange(
+ SkTScopedPtr<SkAdvancedTypefaceMetrics::AdvanceMetric<Data> >* nextSlot,
+ int startId);
+
+template <typename Data>
+void finishRange(
+ SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* range,
+ int endId,
+ typename SkAdvancedTypefaceMetrics::AdvanceMetric<Data>::MetricType
+ type);
+
+/** Retrieve advance data for glyphs. Used by the PDF backend. It calls
+ underlying platform dependent API getAdvance to acquire the data.
+ @param num_glyphs Total number of glyphs in the given font.
+ @param glyphIDs For per-glyph info, specify subset of the font by
+ giving glyph ids. Each integer represents a glyph
+ id. Passing NULL means all glyphs in the font.
+ @param glyphIDsCount Number of elements in subsetGlyphIds. Ignored if
+ glyphIDs is NULL.
+*/
+template <typename Data, typename FontHandle>
+SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* getAdvanceData(
+ FontHandle fontHandle,
+ int num_glyphs,
+ const uint32_t* glyphIDs,
+ uint32_t glyphIDsCount,
+ bool (*getAdvance)(FontHandle fontHandle, int gId, Data* data));
+
+} // namespace skia_advanced_typeface_metrics_utils
+
+#endif
diff --git a/core/SkAnnotation.h b/core/SkAnnotation.h
new file mode 100644
index 0000000..18ee1cd
--- /dev/null
+++ b/core/SkAnnotation.h
@@ -0,0 +1,128 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkAnnotation_DEFINED
+#define SkAnnotation_DEFINED
+
+#include "SkFlattenable.h"
+
+class SkData;
+class SkDataSet;
+class SkStream;
+class SkWStream;
+struct SkPoint;
+
+/**
+ * Experimental class for annotating draws. Do not use directly yet.
+ * Use helper functions at the bottom of this file for now.
+ */
+class SkAnnotation : public SkFlattenable {
+public:
+ enum Flags {
+ // If set, the associated drawing primitive should not be drawn
+ kNoDraw_Flag = 1 << 0,
+ };
+
+ SkAnnotation(SkDataSet*, uint32_t flags);
+ virtual ~SkAnnotation();
+
+ uint32_t getFlags() const { return fFlags; }
+ SkDataSet* getDataSet() const { return fDataSet; }
+
+ bool isNoDraw() const { return SkToBool(fFlags & kNoDraw_Flag); }
+
+ /**
+ * Helper for search the annotation's dataset.
+ */
+ SkData* find(const char name[]) const;
+
+ SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkAnnotation)
+
+protected:
+ SkAnnotation(SkFlattenableReadBuffer&);
+ virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
+
+private:
+ SkDataSet* fDataSet;
+ uint32_t fFlags;
+
+ void writeToStream(SkWStream*) const;
+ void readFromStream(SkStream*);
+
+ typedef SkFlattenable INHERITED;
+};
+
+/**
+ * Experimental collection of predefined Keys into the Annotation dictionary
+ */
+class SkAnnotationKeys {
+public:
+ /**
+ * Returns the canonical key whose payload is a URL
+ */
+ static const char* URL_Key();
+
+ /**
+ * Returns the canonical key whose payload is the name of a destination to
+ * be defined.
+ */
+ static const char* Define_Named_Dest_Key();
+
+ /**
+ * Returns the canonical key whose payload is the name of a destination to
+ * be linked to.
+ */
+ static const char* Link_Named_Dest_Key();
+};
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Experimental helper functions to use Annotations
+//
+
+struct SkRect;
+class SkCanvas;
+
+/**
+ * Experimental!
+ *
+ * Annotate the canvas by associating the specified URL with the
+ * specified rectangle (in local coordinates, just like drawRect). If the
+ * backend of this canvas does not support annotations, this call is
+ * safely ignored.
+ *
+ * The caller is responsible for managing its ownership of the SkData.
+ */
+SK_API void SkAnnotateRectWithURL(SkCanvas*, const SkRect&, SkData*);
+
+/**
+ * Experimental!
+ *
+ * Annotate the canvas by associating a name with the specified point.
+ *
+ * If the backend of this canvas does not support annotations, this call is
+ * safely ignored.
+ *
+ * The caller is responsible for managing its ownership of the SkData.
+ */
+SK_API void SkAnnotateNamedDestination(SkCanvas*, const SkPoint&, SkData*);
+
+/**
+ * Experimental!
+ *
+ * Annotate the canvas by making the specified rectangle link to a named
+ * destination.
+ *
+ * If the backend of this canvas does not support annotations, this call is
+ * safely ignored.
+ *
+ * The caller is responsible for managing its ownership of the SkData.
+ */
+SK_API void SkAnnotateLinkToDestination(SkCanvas*, const SkRect&, SkData*);
+
+
+#endif
diff --git a/core/SkBitmap.h b/core/SkBitmap.h
new file mode 100644
index 0000000..887169c
--- /dev/null
+++ b/core/SkBitmap.h
@@ -0,0 +1,820 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkBitmap_DEFINED
+#define SkBitmap_DEFINED
+
+#include "Sk64.h"
+#include "SkColor.h"
+#include "SkColorTable.h"
+#include "SkPoint.h"
+#include "SkRefCnt.h"
+
+struct SkIRect;
+struct SkRect;
+class SkPaint;
+class SkPixelRef;
+class SkRegion;
+class SkString;
+
+class GrTexture;
+
+/** \class SkBitmap
+
+ The SkBitmap class specifies a raster bitmap. A bitmap has an integer width
+ and height, and a format (config), and a pointer to the actual pixels.
+ Bitmaps can be drawn into a SkCanvas, but they are also used to specify the
+ target of a SkCanvas' drawing operations.
+ A const SkBitmap exposes getAddr(), which lets a caller write its pixels;
+ the constness is considered to apply to the bitmap's configuration, not
+ its contents.
+*/
+class SK_API SkBitmap {
+public:
+ class Allocator;
+
+ enum Config {
+ kNo_Config, //!< bitmap has not been configured
+ /**
+ * 1-bit per pixel, (0 is transparent, 1 is opaque)
+ * Valid as a destination (target of a canvas), but not valid as a src.
+ * i.e. you can draw into a 1-bit bitmap, but you cannot draw from one.
+ */
+ kA1_Config,
+ kA8_Config, //!< 8-bits per pixel, with only alpha specified (0 is transparent, 0xFF is opaque)
+ kIndex8_Config, //!< 8-bits per pixel, using SkColorTable to specify the colors
+ kRGB_565_Config, //!< 16-bits per pixel, (see SkColorPriv.h for packing)
+ kARGB_4444_Config, //!< 16-bits per pixel, (see SkColorPriv.h for packing)
+ kARGB_8888_Config, //!< 32-bits per pixel, (see SkColorPriv.h for packing)
+ };
+
+ // do not add this to the Config enum, otherwise the compiler will let us
+ // pass this as a valid parameter for Config.
+ enum {
+ kConfigCount = kARGB_8888_Config + 1
+ };
+
+ /**
+ * Default construct creates a bitmap with zero width and height, and no pixels.
+ * Its config is set to kNo_Config.
+ */
+ SkBitmap();
+
+ /**
+ * Copy the settings from the src into this bitmap. If the src has pixels
+ * allocated, they will be shared, not copied, so that the two bitmaps will
+ * reference the same memory for the pixels. If a deep copy is needed,
+ * where the new bitmap has its own separate copy of the pixels, use
+ * deepCopyTo().
+ */
+ SkBitmap(const SkBitmap& src);
+
+ ~SkBitmap();
+
+ /** Copies the src bitmap into this bitmap. Ownership of the src bitmap's pixels remains
+ with the src bitmap.
+ */
+ SkBitmap& operator=(const SkBitmap& src);
+ /** Swap the fields of the two bitmaps. This routine is guaranteed to never fail or throw.
+ */
+ // This method is not exported to java.
+ void swap(SkBitmap& other);
+
+ /** Return true iff the bitmap has empty dimensions.
+ */
+ bool empty() const { return 0 == fWidth || 0 == fHeight; }
+
+ /** Return true iff the bitmap has no pixelref. Note: this can return true even if the
+ dimensions of the bitmap are > 0 (see empty()).
+ */
+ bool isNull() const { return NULL == fPixelRef; }
+
+ /** Return the config for the bitmap.
+ */
+ Config config() const { return (Config)fConfig; }
+ /** DEPRECATED, use config()
+ */
+ Config getConfig() const { return this->config(); }
+ /** Return the bitmap's width, in pixels.
+ */
+ int width() const { return fWidth; }
+ /** Return the bitmap's height, in pixels.
+ */
+ int height() const { return fHeight; }
+ /** Return the number of bytes between subsequent rows of the bitmap.
+ */
+ size_t rowBytes() const { return fRowBytes; }
+
+ /** Return the shift amount per pixel (i.e. 0 for 1-byte per pixel, 1 for
+ 2-bytes per pixel configs, 2 for 4-bytes per pixel configs). Return 0
+ for configs that are not at least 1-byte per pixel (e.g. kA1_Config
+ or kNo_Config)
+ */
+ int shiftPerPixel() const { return fBytesPerPixel >> 1; }
+
+ /** Return the number of bytes per pixel based on the config. If the config
+ does not have at least 1 byte per (e.g. kA1_Config) then 0 is returned.
+ */
+ int bytesPerPixel() const { return fBytesPerPixel; }
+
+ /** Return the rowbytes expressed as a number of pixels (like width and
+ height). Note, for 1-byte per pixel configs like kA8_Config, this will
+ return the same as rowBytes(). Is undefined for configs that are less
+ than 1-byte per pixel (e.g. kA1_Config)
+ */
+ int rowBytesAsPixels() const { return fRowBytes >> (fBytesPerPixel >> 1); }
+
+ /** Return the address of the pixels for this SkBitmap.
+ */
+ void* getPixels() const { return fPixels; }
+
+ /** Return the byte size of the pixels, based on the height and rowBytes.
+ Note this truncates the result to 32bits. Call getSize64() to detect
+ if the real size exceeds 32bits.
+ */
+ size_t getSize() const { return fHeight * fRowBytes; }
+
+ /** Return the number of bytes from the pointer returned by getPixels()
+ to the end of the allocated space in the buffer. Required in
+ cases where extractSubset has been called.
+ */
+ size_t getSafeSize() const ;
+
+ /** Return the byte size of the pixels, based on the height and rowBytes.
+ This routine is slightly slower than getSize(), but does not truncate
+ the answer to 32bits.
+ */
+ Sk64 getSize64() const {
+ Sk64 size;
+ size.setMul(fHeight, fRowBytes);
+ return size;
+ }
+
+ /** Same as getSafeSize(), but does not truncate the answer to 32bits.
+ */
+ Sk64 getSafeSize64() const ;
+
+ /** Returns true if this bitmap is marked as immutable, meaning that the
+ contents of its pixels will not change for the lifetime of the bitmap.
+ */
+ bool isImmutable() const;
+
+ /** Marks this bitmap as immutable, meaning that the contents of its
+ pixels will not change for the lifetime of the bitmap and of the
+ underlying pixelref. This state can be set, but it cannot be
+ cleared once it is set. This state propagates to all other bitmaps
+ that share the same pixelref.
+ */
+ void setImmutable();
+
+ /** Returns true if the bitmap is opaque (has no translucent/transparent pixels).
+ */
+ bool isOpaque() const;
+
+ /** Specify if this bitmap's pixels are all opaque or not. Is only meaningful for configs
+ that support per-pixel alpha (RGB32, A1, A8).
+ */
+ void setIsOpaque(bool);
+
+ /** Returns true if the bitmap is volatile (i.e. should not be cached by devices.)
+ */
+ bool isVolatile() const;
+
+ /** Specify whether this bitmap is volatile. Bitmaps are not volatile by
+ default. Temporary bitmaps that are discarded after use should be
+ marked as volatile. This provides a hint to the device that the bitmap
+ should not be cached. Providing this hint when appropriate can
+ improve performance by avoiding unnecessary overhead and resource
+ consumption on the device.
+ */
+ void setIsVolatile(bool);
+
+ /** Reset the bitmap to its initial state (see default constructor). If we are a (shared)
+ owner of the pixels, that ownership is decremented.
+ */
+ void reset();
+
+ /** Given a config and a width, this computes the optimal rowBytes value. This is called automatically
+ if you pass 0 for rowBytes to setConfig().
+ */
+ static size_t ComputeRowBytes(Config c, int width);
+
+ /** Return the bytes-per-pixel for the specified config. If the config is
+ not at least 1-byte per pixel, return 0, including for kNo_Config.
+ */
+ static int ComputeBytesPerPixel(Config c);
+
+ /** Return the shift-per-pixel for the specified config. If the config is
+ not at least 1-byte per pixel, return 0, including for kNo_Config.
+ */
+ static int ComputeShiftPerPixel(Config c) {
+ return ComputeBytesPerPixel(c) >> 1;
+ }
+
+ static Sk64 ComputeSize64(Config, int width, int height);
+ static size_t ComputeSize(Config, int width, int height);
+
+ /**
+ * This will brute-force return true if all of the pixels in the bitmap
+ * are opaque. If it fails to read the pixels, or encounters an error,
+ * it will return false.
+ *
+ * Since this can be an expensive operation, the bitmap stores a flag for
+ * this (isOpaque, setIsOpaque). Only call this if you need to compute this
+ * value from "unknown" pixels.
+ */
+ static bool ComputeIsOpaque(const SkBitmap&);
+
+ /**
+ * Calls ComputeIsOpaque, and passes its result to setIsOpaque().
+ */
+ void computeAndSetOpaquePredicate() {
+ this->setIsOpaque(ComputeIsOpaque(*this));
+ }
+
+ /**
+ * Return the bitmap's bounds [0, 0, width, height] as an SkRect
+ */
+ void getBounds(SkRect* bounds) const;
+ void getBounds(SkIRect* bounds) const;
+
+ /** Set the bitmap's config and dimensions. If rowBytes is 0, then
+ ComputeRowBytes() is called to compute the optimal value. This resets
+ any pixel/colortable ownership, just like reset().
+ */
+ void setConfig(Config, int width, int height, size_t rowBytes = 0);
+ /** Use this to assign a new pixel address for an existing bitmap. This
+ will automatically release any pixelref previously installed. Only call
+ this if you are handling ownership/lifetime of the pixel memory.
+
+ If the bitmap retains a reference to the colortable (assuming it is
+ not null) it will take care of incrementing the reference count.
+
+ @param pixels Address for the pixels, managed by the caller.
+ @param ctable ColorTable (or null) that matches the specified pixels
+ */
+ void setPixels(void* p, SkColorTable* ctable = NULL);
+
+ /** Copies the bitmap's pixels to the location pointed at by dst and returns
+ true if possible, returns false otherwise.
+
+ In the case when the dstRowBytes matches the bitmap's rowBytes, the copy
+ may be made faster by copying over the dst's per-row padding (for all
+ rows but the last). By setting preserveDstPad to true the caller can
+ disable this optimization and ensure that pixels in the padding are not
+ overwritten.
+
+ Always returns false for RLE formats.
+
+ @param dst Location of destination buffer.
+ @param dstSize Size of destination buffer. Must be large enough to hold
+ pixels using indicated stride.
+ @param dstRowBytes Width of each line in the buffer. If 0, uses
+ bitmap's internal stride.
+ @param preserveDstPad Must we preserve padding in the dst
+ */
+ bool copyPixelsTo(void* const dst, size_t dstSize, size_t dstRowBytes = 0,
+ bool preserveDstPad = false) const;
+
+ /** Use the standard HeapAllocator to create the pixelref that manages the
+ pixel memory. It will be sized based on the current width/height/config.
+ If this is called multiple times, a new pixelref object will be created
+ each time.
+
+ If the bitmap retains a reference to the colortable (assuming it is
+ not null) it will take care of incrementing the reference count.
+
+ @param ctable ColorTable (or null) to use with the pixels that will
+ be allocated. Only used if config == Index8_Config
+ @return true if the allocation succeeds. If not the pixelref field of
+ the bitmap will be unchanged.
+ */
+ bool allocPixels(SkColorTable* ctable = NULL) {
+ return this->allocPixels(NULL, ctable);
+ }
+
+ /** Use the specified Allocator to create the pixelref that manages the
+ pixel memory. It will be sized based on the current width/height/config.
+ If this is called multiple times, a new pixelref object will be created
+ each time.
+
+ If the bitmap retains a reference to the colortable (assuming it is
+ not null) it will take care of incrementing the reference count.
+
+ @param allocator The Allocator to use to create a pixelref that can
+ manage the pixel memory for the current
+ width/height/config. If allocator is NULL, the standard
+ HeapAllocator will be used.
+ @param ctable ColorTable (or null) to use with the pixels that will
+ be allocated. Only used if config == Index8_Config.
+ If it is non-null and the config is not Index8, it will
+ be ignored.
+ @return true if the allocation succeeds. If not the pixelref field of
+ the bitmap will be unchanged.
+ */
+ bool allocPixels(Allocator* allocator, SkColorTable* ctable);
+
+ /** Return the current pixelref object, if any
+ */
+ SkPixelRef* pixelRef() const { return fPixelRef; }
+ /** Return the offset into the pixelref, if any. Will return 0 if there is
+ no pixelref installed.
+ */
+ size_t pixelRefOffset() const { return fPixelRefOffset; }
+ /** Assign a pixelref and optional offset. Pixelrefs are reference counted,
+ so the existing one (if any) will be unref'd and the new one will be
+ ref'd.
+ */
+ SkPixelRef* setPixelRef(SkPixelRef* pr, size_t offset = 0);
+
+ /** Call this to ensure that the bitmap points to the current pixel address
+ in the pixelref. Balance it with a call to unlockPixels(). These calls
+ are harmless if there is no pixelref.
+ */
+ void lockPixels() const;
+ /** When you are finished access the pixel memory, call this to balance a
+ previous call to lockPixels(). This allows pixelrefs that implement
+ cached/deferred image decoding to know when there are active clients of
+ a given image.
+ */
+ void unlockPixels() const;
+
+ /**
+ * Some bitmaps can return a copy of their pixels for lockPixels(), but
+ * that copy, if modified, will not be pushed back. These bitmaps should
+ * not be used as targets for a raster device/canvas (since all pixels
+ * modifications will be lost when unlockPixels() is called.)
+ */
+ bool lockPixelsAreWritable() const;
+
+ /** Call this to be sure that the bitmap is valid enough to be drawn (i.e.
+ it has non-null pixels, and if required by its config, it has a
+ non-null colortable. Returns true if all of the above are met.
+ */
+ bool readyToDraw() const {
+ return this->getPixels() != NULL &&
+ (this->config() != kIndex8_Config || NULL != fColorTable);
+ }
+
+ /** Returns the pixelRef's texture, or NULL
+ */
+ GrTexture* getTexture() const;
+
+ /** Return the bitmap's colortable, if it uses one (i.e. fConfig is
+ kIndex8_Config) and the pixels are locked.
+ Otherwise returns NULL. Does not affect the colortable's
+ reference count.
+ */
+ SkColorTable* getColorTable() const { return fColorTable; }
+
+ /** Returns a non-zero, unique value corresponding to the pixels in our
+ pixelref. Each time the pixels are changed (and notifyPixelsChanged
+ is called), a different generation ID will be returned. Finally, if
+ their is no pixelRef then zero is returned.
+ */
+ uint32_t getGenerationID() const;
+
+ /** Call this if you have changed the contents of the pixels. This will in-
+ turn cause a different generation ID value to be returned from
+ getGenerationID().
+ */
+ void notifyPixelsChanged() const;
+
+ /**
+ * Fill the entire bitmap with the specified color.
+ * If the bitmap's config does not support alpha (e.g. 565) then the alpha
+ * of the color is ignored (treated as opaque). If the config only supports
+ * alpha (e.g. A1 or A8) then the color's r,g,b components are ignored.
+ */
+ void eraseColor(SkColor c) const {
+ this->eraseARGB(SkColorGetA(c), SkColorGetR(c), SkColorGetG(c),
+ SkColorGetB(c));
+ }
+
+ /**
+ * Fill the entire bitmap with the specified color.
+ * If the bitmap's config does not support alpha (e.g. 565) then the alpha
+ * of the color is ignored (treated as opaque). If the config only supports
+ * alpha (e.g. A1 or A8) then the color's r,g,b components are ignored.
+ */
+ void eraseARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) const;
+
+ // DEPRECATED -- call eraseColor or eraseARGB
+ void eraseRGB(U8CPU r, U8CPU g, U8CPU b) const {
+ this->eraseARGB(0xFF, r, g, b);
+ }
+
+ /**
+ * Fill the specified area of this bitmap with the specified color.
+ * If the bitmap's config does not support alpha (e.g. 565) then the alpha
+ * of the color is ignored (treated as opaque). If the config only supports
+ * alpha (e.g. A1 or A8) then the color's r,g,b components are ignored.
+ */
+ void eraseArea(const SkIRect& area, SkColor c) const;
+
+ /** Scroll (a subset of) the contents of this bitmap by dx/dy. If there are
+ no pixels allocated (i.e. getPixels() returns null) the method will
+ still update the inval region (if present). If the bitmap is immutable,
+ do nothing and return false.
+
+ @param subset The subset of the bitmap to scroll/move. To scroll the
+ entire contents, specify [0, 0, width, height] or just
+ pass null.
+ @param dx The amount to scroll in X
+ @param dy The amount to scroll in Y
+ @param inval Optional (may be null). Returns the area of the bitmap that
+ was scrolled away. E.g. if dx = dy = 0, then inval would
+ be set to empty. If dx >= width or dy >= height, then
+ inval would be set to the entire bounds of the bitmap.
+ @return true if the scroll was doable. Will return false if the bitmap
+ uses an unsupported config for scrolling (only kA8,
+ kIndex8, kRGB_565, kARGB_4444, kARGB_8888 are supported).
+ If no pixels are present (i.e. getPixels() returns false)
+ inval will still be updated, and true will be returned.
+ */
+ bool scrollRect(const SkIRect* subset, int dx, int dy,
+ SkRegion* inval = NULL) const;
+
+ /**
+ * Return the SkColor of the specified pixel. In most cases this will
+ * require un-premultiplying the color. Alpha only configs (A1 and A8)
+ * return black with the appropriate alpha set. The value is undefined
+ * for kNone_Config or if x or y are out of bounds, or if the bitmap
+ * does not have any pixels (or has not be locked with lockPixels()).
+ */
+ SkColor getColor(int x, int y) const;
+
+ /** Returns the address of the specified pixel. This performs a runtime
+ check to know the size of the pixels, and will return the same answer
+ as the corresponding size-specific method (e.g. getAddr16). Since the
+ check happens at runtime, it is much slower than using a size-specific
+ version. Unlike the size-specific methods, this routine also checks if
+ getPixels() returns null, and returns that. The size-specific routines
+ perform a debugging assert that getPixels() is not null, but they do
+ not do any runtime checks.
+ */
+ void* getAddr(int x, int y) const;
+
+ /** Returns the address of the pixel specified by x,y for 32bit pixels.
+ * In debug build, this asserts that the pixels are allocated and locked,
+ * and that the config is 32-bit, however none of these checks are performed
+ * in the release build.
+ */
+ inline uint32_t* getAddr32(int x, int y) const;
+
+ /** Returns the address of the pixel specified by x,y for 16bit pixels.
+ * In debug build, this asserts that the pixels are allocated and locked,
+ * and that the config is 16-bit, however none of these checks are performed
+ * in the release build.
+ */
+ inline uint16_t* getAddr16(int x, int y) const;
+
+ /** Returns the address of the pixel specified by x,y for 8bit pixels.
+ * In debug build, this asserts that the pixels are allocated and locked,
+ * and that the config is 8-bit, however none of these checks are performed
+ * in the release build.
+ */
+ inline uint8_t* getAddr8(int x, int y) const;
+
+ /** Returns the address of the byte containing the pixel specified by x,y
+ * for 1bit pixels.
+ * In debug build, this asserts that the pixels are allocated and locked,
+ * and that the config is 1-bit, however none of these checks are performed
+ * in the release build.
+ */
+ inline uint8_t* getAddr1(int x, int y) const;
+
+ /** Returns the color corresponding to the pixel specified by x,y for
+ * colortable based bitmaps.
+ * In debug build, this asserts that the pixels are allocated and locked,
+ * that the config is kIndex8, and that the colortable is allocated,
+ * however none of these checks are performed in the release build.
+ */
+ inline SkPMColor getIndex8Color(int x, int y) const;
+
+ /** Set dst to be a setset of this bitmap. If possible, it will share the
+ pixel memory, and just point into a subset of it. However, if the config
+ does not support this, a local copy will be made and associated with
+ the dst bitmap. If the subset rectangle, intersected with the bitmap's
+ dimensions is empty, or if there is an unsupported config, false will be
+ returned and dst will be untouched.
+ @param dst The bitmap that will be set to a subset of this bitmap
+ @param subset The rectangle of pixels in this bitmap that dst will
+ reference.
+ @return true if the subset copy was successfully made.
+ */
+ bool extractSubset(SkBitmap* dst, const SkIRect& subset) const;
+
+ /** Makes a deep copy of this bitmap, respecting the requested config,
+ * and allocating the dst pixels on the cpu.
+ * Returns false if either there is an error (i.e. the src does not have
+ * pixels) or the request cannot be satisfied (e.g. the src has per-pixel
+ * alpha, and the requested config does not support alpha).
+ * @param dst The bitmap to be sized and allocated
+ * @param c The desired config for dst
+ * @param allocator Allocator used to allocate the pixelref for the dst
+ * bitmap. If this is null, the standard HeapAllocator
+ * will be used.
+ * @return true if the copy could be made.
+ */
+ bool copyTo(SkBitmap* dst, Config c, Allocator* allocator = NULL) const;
+
+ /** Makes a deep copy of this bitmap, respecting the requested config, and
+ * with custom allocation logic that will keep the copied pixels
+ * in the same domain as the source: If the src pixels are allocated for
+ * the cpu, then so will the dst. If the src pixels are allocated on the
+ * gpu (typically as a texture), the it will do the same for the dst.
+ * If the request cannot be fulfilled, returns false and dst is unmodified.
+ */
+ bool deepCopyTo(SkBitmap* dst, Config c) const;
+
+ /** Returns true if this bitmap can be deep copied into the requested config
+ by calling copyTo().
+ */
+ bool canCopyTo(Config newConfig) const;
+
+ /**
+ * DEPRECATED -- will be replaced with API on SkPaint
+ */
+ void buildMipMap(bool forceRebuild = false);
+
+#ifdef SK_BUILD_FOR_ANDROID
+ bool hasHardwareMipMap() const {
+ return (fFlags & kHasHardwareMipMap_Flag) != 0;
+ }
+
+ void setHasHardwareMipMap(bool hasHardwareMipMap) {
+ if (hasHardwareMipMap) {
+ fFlags |= kHasHardwareMipMap_Flag;
+ } else {
+ fFlags &= ~kHasHardwareMipMap_Flag;
+ }
+ }
+#endif
+
+ bool extractAlpha(SkBitmap* dst) const {
+ return this->extractAlpha(dst, NULL, NULL, NULL);
+ }
+
+ bool extractAlpha(SkBitmap* dst, const SkPaint* paint,
+ SkIPoint* offset) const {
+ return this->extractAlpha(dst, paint, NULL, offset);
+ }
+
+ /** Set dst to contain alpha layer of this bitmap. If destination bitmap
+ fails to be initialized, e.g. because allocator can't allocate pixels
+ for it, dst will not be modified and false will be returned.
+
+ @param dst The bitmap to be filled with alpha layer
+ @param paint The paint to draw with
+ @param allocator Allocator used to allocate the pixelref for the dst
+ bitmap. If this is null, the standard HeapAllocator
+ will be used.
+ @param offset If not null, it is set to top-left coordinate to position
+ the returned bitmap so that it visually lines up with the
+ original
+ */
+ bool extractAlpha(SkBitmap* dst, const SkPaint* paint, Allocator* allocator,
+ SkIPoint* offset) const;
+
+ /** The following two functions provide the means to both flatten and
+ unflatten the bitmap AND its pixels into the provided buffer.
+ It is recommended that you do not call these functions directly,
+ but instead call the write/readBitmap functions on the respective
+ buffers as they can optimize the recording process and avoid recording
+ duplicate bitmaps and pixelRefs.
+ */
+ void flatten(SkFlattenableWriteBuffer&) const;
+ void unflatten(SkFlattenableReadBuffer&);
+
+ SkDEBUGCODE(void validate() const;)
+
+ class Allocator : public SkRefCnt {
+ public:
+ SK_DECLARE_INST_COUNT(Allocator)
+
+ /** Allocate the pixel memory for the bitmap, given its dimensions and
+ config. Return true on success, where success means either setPixels
+ or setPixelRef was called. The pixels need not be locked when this
+ returns. If the config requires a colortable, it also must be
+ installed via setColorTable. If false is returned, the bitmap and
+ colortable should be left unchanged.
+ */
+ virtual bool allocPixelRef(SkBitmap*, SkColorTable*) = 0;
+ private:
+ typedef SkRefCnt INHERITED;
+ };
+
+ /** Subclass of Allocator that returns a pixelref that allocates its pixel
+ memory from the heap. This is the default Allocator invoked by
+ allocPixels().
+ */
+ class HeapAllocator : public Allocator {
+ public:
+ virtual bool allocPixelRef(SkBitmap*, SkColorTable*);
+ };
+
+ class RLEPixels {
+ public:
+ RLEPixels(int width, int height);
+ virtual ~RLEPixels();
+
+ uint8_t* packedAtY(int y) const {
+ SkASSERT((unsigned)y < (unsigned)fHeight);
+ return fYPtrs[y];
+ }
+
+ // called by subclasses during creation
+ void setPackedAtY(int y, uint8_t* addr) {
+ SkASSERT((unsigned)y < (unsigned)fHeight);
+ fYPtrs[y] = addr;
+ }
+
+ private:
+ uint8_t** fYPtrs;
+ int fHeight;
+ };
+
+ SkDEVCODE(void toString(SkString* str) const;)
+
+private:
+ struct MipMap;
+ mutable MipMap* fMipMap;
+
+ mutable SkPixelRef* fPixelRef;
+ mutable size_t fPixelRefOffset;
+ mutable int fPixelLockCount;
+ // either user-specified (in which case it is not treated as mutable)
+ // or a cache of the returned value from fPixelRef->lockPixels()
+ mutable void* fPixels;
+ mutable SkColorTable* fColorTable; // only meaningful for kIndex8
+
+ enum Flags {
+ kImageIsOpaque_Flag = 0x01,
+ kImageIsVolatile_Flag = 0x02,
+ kImageIsImmutable_Flag = 0x04,
+#ifdef SK_BUILD_FOR_ANDROID
+ /* A hint for the renderer responsible for drawing this bitmap
+ * indicating that it should attempt to use mipmaps when this bitmap
+ * is drawn scaled down.
+ */
+ kHasHardwareMipMap_Flag = 0x08,
+#endif
+ };
+
+ uint32_t fRowBytes;
+ uint32_t fWidth;
+ uint32_t fHeight;
+ uint8_t fConfig;
+ uint8_t fFlags;
+ uint8_t fBytesPerPixel; // based on config
+
+ void internalErase(const SkIRect&, U8CPU a, U8CPU r, U8CPU g, U8CPU b)const;
+
+ /* Internal computations for safe size.
+ */
+ static Sk64 ComputeSafeSize64(Config config,
+ uint32_t width,
+ uint32_t height,
+ size_t rowBytes);
+ static size_t ComputeSafeSize(Config config,
+ uint32_t width,
+ uint32_t height,
+ size_t rowBytes);
+
+ /* Unreference any pixelrefs or colortables
+ */
+ void freePixels();
+ void updatePixelsFromRef() const;
+
+ static SkFixed ComputeMipLevel(SkFixed sx, SkFixed dy);
+
+ /** Given scale factors sx, sy, determine the miplevel available in the
+ bitmap, and return it (this is the amount to shift matrix iterators
+ by). If dst is not null, it is set to the correct level.
+ */
+ int extractMipLevel(SkBitmap* dst, SkFixed sx, SkFixed sy);
+ bool hasMipMap() const;
+ void freeMipMap();
+
+ friend struct SkBitmapProcState;
+};
+
+class SkAutoLockPixels : public SkNoncopyable {
+public:
+ SkAutoLockPixels(const SkBitmap& bm, bool doLock = true) : fBitmap(bm) {
+ fDidLock = doLock;
+ if (doLock) {
+ bm.lockPixels();
+ }
+ }
+ ~SkAutoLockPixels() {
+ if (fDidLock) {
+ fBitmap.unlockPixels();
+ }
+ }
+
+private:
+ const SkBitmap& fBitmap;
+ bool fDidLock;
+};
+
+/** Helper class that performs the lock/unlockColors calls on a colortable.
+ The destructor will call unlockColors(false) if it has a bitmap's colortable
+*/
+class SkAutoLockColors : public SkNoncopyable {
+public:
+ /** Initialize with no bitmap. Call lockColors(bitmap) to lock bitmap's
+ colortable
+ */
+ SkAutoLockColors() : fCTable(NULL), fColors(NULL) {}
+ /** Initialize with bitmap, locking its colortable if present
+ */
+ explicit SkAutoLockColors(const SkBitmap& bm) {
+ fCTable = bm.getColorTable();
+ fColors = fCTable ? fCTable->lockColors() : NULL;
+ }
+ /** Initialize with a colortable (may be null)
+ */
+ explicit SkAutoLockColors(SkColorTable* ctable) {
+ fCTable = ctable;
+ fColors = ctable ? ctable->lockColors() : NULL;
+ }
+ ~SkAutoLockColors() {
+ if (fCTable) {
+ fCTable->unlockColors(false);
+ }
+ }
+
+ /** Return the currently locked colors, or NULL if no bitmap's colortable
+ is currently locked.
+ */
+ const SkPMColor* colors() const { return fColors; }
+
+ /** Locks the table and returns is colors (assuming ctable is not null) and
+ unlocks the previous table if one was present
+ */
+ const SkPMColor* lockColors(SkColorTable* ctable) {
+ if (fCTable) {
+ fCTable->unlockColors(false);
+ }
+ fCTable = ctable;
+ fColors = ctable ? ctable->lockColors() : NULL;
+ return fColors;
+ }
+
+ const SkPMColor* lockColors(const SkBitmap& bm) {
+ return this->lockColors(bm.getColorTable());
+ }
+
+private:
+ SkColorTable* fCTable;
+ const SkPMColor* fColors;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+inline uint32_t* SkBitmap::getAddr32(int x, int y) const {
+ SkASSERT(fPixels);
+ SkASSERT(fConfig == kARGB_8888_Config);
+ SkASSERT((unsigned)x < fWidth && (unsigned)y < fHeight);
+ return (uint32_t*)((char*)fPixels + y * fRowBytes + (x << 2));
+}
+
+inline uint16_t* SkBitmap::getAddr16(int x, int y) const {
+ SkASSERT(fPixels);
+ SkASSERT(fConfig == kRGB_565_Config || fConfig == kARGB_4444_Config);
+ SkASSERT((unsigned)x < fWidth && (unsigned)y < fHeight);
+ return (uint16_t*)((char*)fPixels + y * fRowBytes + (x << 1));
+}
+
+inline uint8_t* SkBitmap::getAddr8(int x, int y) const {
+ SkASSERT(fPixels);
+ SkASSERT(fConfig == kA8_Config || fConfig == kIndex8_Config);
+ SkASSERT((unsigned)x < fWidth && (unsigned)y < fHeight);
+ return (uint8_t*)fPixels + y * fRowBytes + x;
+}
+
+inline SkPMColor SkBitmap::getIndex8Color(int x, int y) const {
+ SkASSERT(fPixels);
+ SkASSERT(fConfig == kIndex8_Config);
+ SkASSERT((unsigned)x < fWidth && (unsigned)y < fHeight);
+ SkASSERT(fColorTable);
+ return (*fColorTable)[*((const uint8_t*)fPixels + y * fRowBytes + x)];
+}
+
+// returns the address of the byte that contains the x coordinate
+inline uint8_t* SkBitmap::getAddr1(int x, int y) const {
+ SkASSERT(fPixels);
+ SkASSERT(fConfig == kA1_Config);
+ SkASSERT((unsigned)x < fWidth && (unsigned)y < fHeight);
+ return (uint8_t*)fPixels + y * fRowBytes + (x >> 3);
+}
+
+#endif
diff --git a/core/SkBlitRow.h b/core/SkBlitRow.h
new file mode 100644
index 0000000..5011342
--- /dev/null
+++ b/core/SkBlitRow.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkBlitRow_DEFINED
+#define SkBlitRow_DEFINED
+
+#include "SkBitmap.h"
+#include "SkColor.h"
+
+class SkBlitRow {
+public:
+ enum Flags16 {
+ //! If set, the alpha parameter will be != 255
+ kGlobalAlpha_Flag = 0x01,
+ //! If set, the src colors may have alpha != 255
+ kSrcPixelAlpha_Flag = 0x02,
+ //! If set, the resulting 16bit colors should be dithered
+ kDither_Flag = 0x04
+ };
+
+ /** Function pointer that reads a scanline of src SkPMColors, and writes
+ a corresponding scanline of 16bit colors (specific format based on the
+ config passed to the Factory.
+
+ The x,y params are useful just for dithering
+
+ @param alpha A global alpha to be applied to all of the src colors
+ @param x The x coordinate of the beginning of the scanline
+ @param y THe y coordinate of the scanline
+ */
+ typedef void (*Proc)(uint16_t* dst,
+ const SkPMColor* src,
+ int count, U8CPU alpha, int x, int y);
+
+ static Proc Factory(unsigned flags, SkBitmap::Config);
+
+ ///////////// D32 version
+
+ enum Flags32 {
+ kGlobalAlpha_Flag32 = 1 << 0,
+ kSrcPixelAlpha_Flag32 = 1 << 1
+ };
+
+ /** Function pointer that blends 32bit colors onto a 32bit destination.
+ @param dst array of dst 32bit colors
+ @param src array of src 32bit colors (w/ or w/o alpha)
+ @param count number of colors to blend
+ @param alpha global alpha to be applied to all src colors
+ */
+ typedef void (*Proc32)(uint32_t* dst,
+ const SkPMColor* src,
+ int count, U8CPU alpha);
+
+ static Proc32 Factory32(unsigned flags32);
+
+ /** Function pointer that blends a single color with a row of 32-bit colors
+ onto a 32-bit destination
+ */
+ typedef void (*ColorProc)(SkPMColor* dst, const SkPMColor* src, int count,
+ SkPMColor color);
+
+ /** Blend a single color onto a row of S32 pixels, writing the result
+ into a row of D32 pixels. src and dst may be the same memory, but
+ if they are not, they may not overlap.
+ */
+ static void Color32(SkPMColor dst[], const SkPMColor src[],
+ int count, SkPMColor color);
+
+ //! Public entry-point to return a blit function ptr
+ static ColorProc ColorProcFactory();
+
+ /** Function pointer that blends a single color onto a 32-bit rectangle. */
+ typedef void (*ColorRectProc)(SkPMColor* dst, int width, int height,
+ size_t rowBytes, SkPMColor color);
+
+ /** Blend a single color into a rectangle of D32 pixels. */
+ static void ColorRect32(SkPMColor* dst, int width, int height,
+ size_t rowBytes, SkPMColor color);
+
+ //! Public entry-point to return a blit function ptr
+ static ColorRectProc ColorRectProcFactory();
+
+ /** These static functions are called by the Factory and Factory32
+ functions, and should return either NULL, or a
+ platform-specific function-ptr to be used in place of the
+ system default.
+ */
+
+ static Proc32 PlatformProcs32(unsigned flags);
+ static Proc PlatformProcs565(unsigned flags);
+ static ColorProc PlatformColorProc();
+
+private:
+ enum {
+ kFlags16_Mask = 7,
+ kFlags32_Mask = 3
+ };
+};
+
+#endif
diff --git a/core/SkBounder.h b/core/SkBounder.h
new file mode 100644
index 0000000..7368d09
--- /dev/null
+++ b/core/SkBounder.h
@@ -0,0 +1,93 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkBounder_DEFINED
+#define SkBounder_DEFINED
+
+#include "SkTypes.h"
+#include "SkRefCnt.h"
+#include "SkPoint.h"
+
+struct SkGlyph;
+struct SkIRect;
+struct SkPoint;
+struct SkRect;
+class SkPaint;
+class SkPath;
+class SkRegion;
+
+/** \class SkBounder
+
+ Base class for intercepting the device bounds of shapes before they are drawn.
+ Install a subclass of this in your canvas.
+*/
+class SkBounder : public SkRefCnt {
+public:
+ SK_DECLARE_INST_COUNT(SkBounder)
+
+ SkBounder();
+
+ /* Call to perform a clip test before calling onIRect.
+ Returns the result from onIRect.
+ */
+ bool doIRect(const SkIRect&);
+ bool doIRectGlyph(const SkIRect& , int x, int y, const SkGlyph&);
+
+protected:
+ /** Override in your subclass. This is called with the device bounds of an
+ object (text, geometry, image) just before it is drawn. If your method
+ returns false, the drawing for that shape is aborted. If your method
+ returns true, drawing continues. The bounds your method receives have already
+ been transformed in to device coordinates, and clipped to the current clip.
+ */
+ virtual bool onIRect(const SkIRect&) {
+ return false;
+ }
+
+ /** Passed to onIRectGlyph with the information about the current glyph.
+ LSB and RSB are fixed-point (16.16) coordinates of the start and end
+ of the glyph's advance
+ */
+ struct GlyphRec {
+ SkIPoint fLSB; //!< fixed-point left-side-bearing of the glyph
+ SkIPoint fRSB; //!< fixed-point right-side-bearing of the glyph
+ uint16_t fGlyphID;
+ uint16_t fFlags; //!< currently set to 0
+ };
+
+ /** Optionally, override in your subclass to receive the glyph ID when
+ text drawing supplies the device bounds of the object.
+ */
+ virtual bool onIRectGlyph(const SkIRect& r, const GlyphRec&) {
+ return onIRect(r);
+ }
+
+ /** Called after each shape has been drawn. The default implementation does
+ nothing, but your override could use this notification to signal itself
+ that the offscreen being rendered into needs to be updated to the screen.
+ */
+ virtual void commit();
+
+private:
+ bool doHairline(const SkPoint&, const SkPoint&, const SkPaint&);
+ bool doRect(const SkRect&, const SkPaint&);
+ bool doPath(const SkPath&, const SkPaint&, bool doFill);
+ void setClip(const SkRegion* clip) { fClip = clip; }
+
+ const SkRegion* fClip;
+ friend class SkAutoBounderCommit;
+ friend class SkDraw;
+ friend class SkDrawIter;
+ friend struct Draw1Glyph;
+ friend class SkMaskFilter;
+
+ typedef SkRefCnt INHERITED;
+};
+
+#endif
diff --git a/core/SkCanvas.h b/core/SkCanvas.h
new file mode 100644
index 0000000..b4853f7
--- /dev/null
+++ b/core/SkCanvas.h
@@ -0,0 +1,1179 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkCanvas_DEFINED
+#define SkCanvas_DEFINED
+
+#include "SkTypes.h"
+#include "SkBitmap.h"
+#include "SkDeque.h"
+#include "SkClipStack.h"
+#include "SkPaint.h"
+#include "SkRefCnt.h"
+#include "SkPath.h"
+#include "SkRegion.h"
+#include "SkScalarCompare.h"
+#include "SkXfermode.h"
+
+class SkBounder;
+class SkDevice;
+class SkDraw;
+class SkDrawFilter;
+class SkMetaData;
+class SkPicture;
+class SkRRect;
+class SkSurface_Base;
+
+/** \class SkCanvas
+
+ A Canvas encapsulates all of the state about drawing into a device (bitmap).
+ This includes a reference to the device itself, and a stack of matrix/clip
+ values. For any given draw call (e.g. drawRect), the geometry of the object
+ being drawn is transformed by the concatenation of all the matrices in the
+ stack. The transformed geometry is clipped by the intersection of all of
+ the clips in the stack.
+
+ While the Canvas holds the state of the drawing device, the state (style)
+ of the object being drawn is held by the Paint, which is provided as a
+ parameter to each of the draw() methods. The Paint holds attributes such as
+ color, typeface, textSize, strokeWidth, shader (e.g. gradients, patterns),
+ etc.
+*/
+class SK_API SkCanvas : public SkRefCnt {
+public:
+ SK_DECLARE_INST_COUNT(SkCanvas)
+
+ SkCanvas();
+
+ /** Construct a canvas with the specified device to draw into.
+
+ @param device Specifies a device for the canvas to draw into.
+ */
+ explicit SkCanvas(SkDevice* device);
+
+ /** Deprecated - Construct a canvas with the specified bitmap to draw into.
+ @param bitmap Specifies a bitmap for the canvas to draw into. Its
+ structure are copied to the canvas.
+ */
+ explicit SkCanvas(const SkBitmap& bitmap);
+ virtual ~SkCanvas();
+
+ SkMetaData& getMetaData();
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ /**
+ * Trigger the immediate execution of all pending draw operations.
+ */
+ void flush();
+
+ /**
+ * Return the width/height of the underlying device. The current drawable
+ * area may be small (due to clipping or saveLayer). For a canvas with
+ * no device, 0,0 will be returned.
+ */
+ SkISize getDeviceSize() const;
+
+ /** Return the canvas' device object, which may be null. The device holds
+ the bitmap of the pixels that the canvas draws into. The reference count
+ of the returned device is not changed by this call.
+ */
+ SkDevice* getDevice() const;
+
+ /**
+ * saveLayer() can create another device (which is later drawn onto
+ * the previous device). getTopDevice() returns the top-most device current
+ * installed. Note that this can change on other calls like save/restore,
+ * so do not access this device after subsequent canvas calls.
+ * The reference count of the device is not changed.
+ *
+ * @param updateMatrixClip If this is true, then before the device is
+ * returned, we ensure that its has been notified about the current
+ * matrix and clip. Note: this happens automatically when the device
+ * is drawn to, but is optional here, as there is a small perf hit
+ * sometimes.
+ */
+ SkDevice* getTopDevice(bool updateMatrixClip = false) const;
+
+ /**
+ * Shortcut for getDevice()->createCompatibleDevice(...).
+ * If getDevice() == NULL, this method does nothing, and returns NULL.
+ */
+ SkDevice* createCompatibleDevice(SkBitmap::Config config,
+ int width, int height,
+ bool isOpaque);
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ /**
+ * This enum can be used with read/writePixels to perform a pixel ops to or
+ * from an 8888 config other than Skia's native config (SkPMColor). There
+ * are three byte orders supported: native, BGRA, and RGBA. Each has a
+ * premultiplied and unpremultiplied variant.
+ *
+ * Components of a 8888 pixel can be packed/unpacked from a 32bit word using
+ * either byte offsets or shift values. Byte offsets are endian-invariant
+ * while shifts are not. BGRA and RGBA configs are defined by byte
+ * orderings. The native config is defined by shift values (SK_A32_SHIFT,
+ * ..., SK_B32_SHIFT).
+ */
+ enum Config8888 {
+ /**
+ * Skia's native order specified by:
+ * SK_A32_SHIFT, SK_R32_SHIFT, SK_G32_SHIFT, and SK_B32_SHIFT
+ *
+ * kNative_Premul_Config8888 is equivalent to SkPMColor
+ * kNative_Unpremul_Config8888 has the same component order as SkPMColor
+ * but is not premultiplied.
+ */
+ kNative_Premul_Config8888,
+ kNative_Unpremul_Config8888,
+ /**
+ * low byte to high byte: B, G, R, A.
+ */
+ kBGRA_Premul_Config8888,
+ kBGRA_Unpremul_Config8888,
+ /**
+ * low byte to high byte: R, G, B, A.
+ */
+ kRGBA_Premul_Config8888,
+ kRGBA_Unpremul_Config8888
+ };
+
+ /**
+ * On success (returns true), copy the canvas pixels into the bitmap.
+ * On failure, the bitmap parameter is left unchanged and false is
+ * returned.
+ *
+ * The canvas' pixels are converted to the bitmap's config. The only
+ * supported config is kARGB_8888_Config, though this is likely to be
+ * relaxed in the future. The meaning of config kARGB_8888_Config is
+ * modified by the enum param config8888. The default value interprets
+ * kARGB_8888_Config as SkPMColor
+ *
+ * If the bitmap has pixels already allocated, the canvas pixels will be
+ * written there. If not, bitmap->allocPixels() will be called
+ * automatically. If the bitmap is backed by a texture readPixels will
+ * fail.
+ *
+ * The actual pixels written is the intersection of the canvas' bounds, and
+ * the rectangle formed by the bitmap's width,height and the specified x,y.
+ * If bitmap pixels extend outside of that intersection, they will not be
+ * modified.
+ *
+ * Other failure conditions:
+ * * If the canvas is backed by a non-raster device (e.g. PDF) then
+ * readPixels will fail.
+ * * If bitmap is texture-backed then readPixels will fail. (This may be
+ * relaxed in the future.)
+ *
+ * Example that reads the entire canvas into a bitmap using the native
+ * SkPMColor:
+ * SkISize size = canvas->getDeviceSize();
+ * bitmap->setConfig(SkBitmap::kARGB_8888_Config, size.fWidth,
+ * size.fHeight);
+ * if (canvas->readPixels(bitmap, 0, 0)) {
+ * // use the pixels
+ * }
+ */
+ bool readPixels(SkBitmap* bitmap,
+ int x, int y,
+ Config8888 config8888 = kNative_Premul_Config8888);
+
+ /**
+ * DEPRECATED: This will be removed as soon as webkit is no longer relying
+ * on it. The bitmap is resized to the intersection of srcRect and the
+ * canvas bounds. New pixels are always allocated on success. Bitmap is
+ * unmodified on failure.
+ */
+ bool readPixels(const SkIRect& srcRect, SkBitmap* bitmap);
+
+ /**
+ * Similar to draw sprite, this method will copy the pixels in bitmap onto
+ * the canvas, with the top/left corner specified by (x, y). The canvas'
+ * pixel values are completely replaced: there is no blending.
+ *
+ * Currently if bitmap is backed by a texture this is a no-op. This may be
+ * relaxed in the future.
+ *
+ * If the bitmap has config kARGB_8888_Config then the config8888 param
+ * will determines how the pixel valuess are intepreted. If the bitmap is
+ * not kARGB_8888_Config then this parameter is ignored.
+ *
+ * Note: If you are recording drawing commands on this canvas to
+ * SkPicture, writePixels() is ignored!
+ */
+ void writePixels(const SkBitmap& bitmap,
+ int x, int y,
+ Config8888 config8888 = kNative_Premul_Config8888);
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ enum SaveFlags {
+ /** save the matrix state, restoring it on restore() */
+ kMatrix_SaveFlag = 0x01,
+ /** save the clip state, restoring it on restore() */
+ kClip_SaveFlag = 0x02,
+ /** the layer needs to support per-pixel alpha */
+ kHasAlphaLayer_SaveFlag = 0x04,
+ /** the layer needs to support 8-bits per color component */
+ kFullColorLayer_SaveFlag = 0x08,
+ /** the layer should clip against the bounds argument */
+ kClipToLayer_SaveFlag = 0x10,
+
+ // helper masks for common choices
+ kMatrixClip_SaveFlag = 0x03,
+ kARGB_NoClipLayer_SaveFlag = 0x0F,
+ kARGB_ClipLayer_SaveFlag = 0x1F
+ };
+
+ /** This call saves the current matrix, clip, and drawFilter, and pushes a
+ copy onto a private stack. Subsequent calls to translate, scale,
+ rotate, skew, concat or clipRect, clipPath, and setDrawFilter all
+ operate on this copy.
+ When the balancing call to restore() is made, the previous matrix, clip,
+ and drawFilter are restored.
+ @return The value to pass to restoreToCount() to balance this save()
+ */
+ virtual int save(SaveFlags flags = kMatrixClip_SaveFlag);
+
+ /** This behaves the same as save(), but in addition it allocates an
+ offscreen bitmap. All drawing calls are directed there, and only when
+ the balancing call to restore() is made is that offscreen transfered to
+ the canvas (or the previous layer).
+ @param bounds (may be null) This rect, if non-null, is used as a hint to
+ limit the size of the offscreen, and thus drawing may be
+ clipped to it, though that clipping is not guaranteed to
+ happen. If exact clipping is desired, use clipRect().
+ @param paint (may be null) This is copied, and is applied to the
+ offscreen when restore() is called
+ @param flags LayerFlags
+ @return The value to pass to restoreToCount() to balance this save()
+ */
+ virtual int saveLayer(const SkRect* bounds, const SkPaint* paint,
+ SaveFlags flags = kARGB_ClipLayer_SaveFlag);
+
+ /** This behaves the same as save(), but in addition it allocates an
+ offscreen bitmap. All drawing calls are directed there, and only when
+ the balancing call to restore() is made is that offscreen transfered to
+ the canvas (or the previous layer).
+ @param bounds (may be null) This rect, if non-null, is used as a hint to
+ limit the size of the offscreen, and thus drawing may be
+ clipped to it, though that clipping is not guaranteed to
+ happen. If exact clipping is desired, use clipRect().
+ @param alpha This is applied to the offscreen when restore() is called.
+ @param flags LayerFlags
+ @return The value to pass to restoreToCount() to balance this save()
+ */
+ int saveLayerAlpha(const SkRect* bounds, U8CPU alpha,
+ SaveFlags flags = kARGB_ClipLayer_SaveFlag);
+
+ /** This call balances a previous call to save(), and is used to remove all
+ modifications to the matrix/clip/drawFilter state since the last save
+ call.
+ It is an error to call restore() more times than save() was called.
+ */
+ virtual void restore();
+
+ /** Returns the number of matrix/clip states on the SkCanvas' private stack.
+ This will equal # save() calls - # restore() calls.
+ */
+ int getSaveCount() const;
+
+ /** Efficient way to pop any calls to save() that happened after the save
+ count reached saveCount. It is an error for saveCount to be less than
+ getSaveCount()
+ @param saveCount The number of save() levels to restore from
+ */
+ void restoreToCount(int saveCount);
+
+ /** Returns true if drawing is currently going to a layer (from saveLayer)
+ * rather than to the root device.
+ */
+ virtual bool isDrawingToLayer() const;
+
+ /** Preconcat the current matrix with the specified translation
+ @param dx The distance to translate in X
+ @param dy The distance to translate in Y
+ returns true if the operation succeeded (e.g. did not overflow)
+ */
+ virtual bool translate(SkScalar dx, SkScalar dy);
+
+ /** Preconcat the current matrix with the specified scale.
+ @param sx The amount to scale in X
+ @param sy The amount to scale in Y
+ returns true if the operation succeeded (e.g. did not overflow)
+ */
+ virtual bool scale(SkScalar sx, SkScalar sy);
+
+ /** Preconcat the current matrix with the specified rotation.
+ @param degrees The amount to rotate, in degrees
+ returns true if the operation succeeded (e.g. did not overflow)
+ */
+ virtual bool rotate(SkScalar degrees);
+
+ /** Preconcat the current matrix with the specified skew.
+ @param sx The amount to skew in X
+ @param sy The amount to skew in Y
+ returns true if the operation succeeded (e.g. did not overflow)
+ */
+ virtual bool skew(SkScalar sx, SkScalar sy);
+
+ /** Preconcat the current matrix with the specified matrix.
+ @param matrix The matrix to preconcatenate with the current matrix
+ @return true if the operation succeeded (e.g. did not overflow)
+ */
+ virtual bool concat(const SkMatrix& matrix);
+
+ /** Replace the current matrix with a copy of the specified matrix.
+ @param matrix The matrix that will be copied into the current matrix.
+ */
+ virtual void setMatrix(const SkMatrix& matrix);
+
+ /** Helper for setMatrix(identity). Sets the current matrix to identity.
+ */
+ void resetMatrix();
+
+ /**
+ * Modify the current clip with the specified rectangle.
+ * @param rect The rect to combine with the current clip
+ * @param op The region op to apply to the current clip
+ * @param doAntiAlias true if the clip should be antialiased
+ * @return true if the canvas' clip is non-empty
+ */
+ virtual bool clipRect(const SkRect& rect,
+ SkRegion::Op op = SkRegion::kIntersect_Op,
+ bool doAntiAlias = false);
+
+ /**
+ * Modify the current clip with the specified SkRRect.
+ * @param rrect The rrect to combine with the current clip
+ * @param op The region op to apply to the current clip
+ * @param doAntiAlias true if the clip should be antialiased
+ * @return true if the canvas' clip is non-empty
+ */
+ virtual bool clipRRect(const SkRRect& rrect,
+ SkRegion::Op op = SkRegion::kIntersect_Op,
+ bool doAntiAlias = false);
+
+ /**
+ * Modify the current clip with the specified path.
+ * @param path The path to combine with the current clip
+ * @param op The region op to apply to the current clip
+ * @param doAntiAlias true if the clip should be antialiased
+ * @return true if the canvas' new clip is non-empty
+ */
+ virtual bool clipPath(const SkPath& path,
+ SkRegion::Op op = SkRegion::kIntersect_Op,
+ bool doAntiAlias = false);
+
+ /** EXPERIMENTAL -- only used for testing
+ Set to false to force clips to be hard, even if doAntiAlias=true is
+ passed to clipRect or clipPath.
+ */
+ void setAllowSoftClip(bool allow) {
+ fAllowSoftClip = allow;
+ }
+
+ /** EXPERIMENTAL -- only used for testing
+ Set to simplify clip stack using path ops.
+ */
+ void setAllowSimplifyClip(bool allow) {
+ fAllowSimplifyClip = allow;
+ }
+
+ /** Modify the current clip with the specified region. Note that unlike
+ clipRect() and clipPath() which transform their arguments by the current
+ matrix, clipRegion() assumes its argument is already in device
+ coordinates, and so no transformation is performed.
+ @param deviceRgn The region to apply to the current clip
+ @param op The region op to apply to the current clip
+ @return true if the canvas' new clip is non-empty
+ */
+ virtual bool clipRegion(const SkRegion& deviceRgn,
+ SkRegion::Op op = SkRegion::kIntersect_Op);
+
+ /** Helper for clipRegion(rgn, kReplace_Op). Sets the current clip to the
+ specified region. This does not intersect or in any other way account
+ for the existing clip region.
+ @param deviceRgn The region to copy into the current clip.
+ @return true if the new clip region is non-empty
+ */
+ bool setClipRegion(const SkRegion& deviceRgn) {
+ return this->clipRegion(deviceRgn, SkRegion::kReplace_Op);
+ }
+
+ /** Return true if the specified rectangle, after being transformed by the
+ current matrix, would lie completely outside of the current clip. Call
+ this to check if an area you intend to draw into is clipped out (and
+ therefore you can skip making the draw calls).
+ @param rect the rect to compare with the current clip
+ @return true if the rect (transformed by the canvas' matrix) does not
+ intersect with the canvas' clip
+ */
+ bool quickReject(const SkRect& rect) const;
+
+ /** Return true if the specified path, after being transformed by the
+ current matrix, would lie completely outside of the current clip. Call
+ this to check if an area you intend to draw into is clipped out (and
+ therefore you can skip making the draw calls). Note, for speed it may
+ return false even if the path itself might not intersect the clip
+ (i.e. the bounds of the path intersects, but the path does not).
+ @param path The path to compare with the current clip
+ @return true if the path (transformed by the canvas' matrix) does not
+ intersect with the canvas' clip
+ */
+ bool quickReject(const SkPath& path) const;
+
+ /** Return true if the horizontal band specified by top and bottom is
+ completely clipped out. This is a conservative calculation, meaning
+ that it is possible that if the method returns false, the band may still
+ in fact be clipped out, but the converse is not true. If this method
+ returns true, then the band is guaranteed to be clipped out.
+ @param top The top of the horizontal band to compare with the clip
+ @param bottom The bottom of the horizontal and to compare with the clip
+ @return true if the horizontal band is completely clipped out (i.e. does
+ not intersect the current clip)
+ */
+ bool quickRejectY(SkScalar top, SkScalar bottom) const {
+ SkASSERT(SkScalarToCompareType(top) <= SkScalarToCompareType(bottom));
+ const SkRectCompareType& clipR = this->getLocalClipBoundsCompareType();
+ // In the case where the clip is empty and we are provided with a
+ // negative top and positive bottom parameter then this test will return
+ // false even though it will be clipped. We have chosen to exclude that
+ // check as it is rare and would result double the comparisons.
+ return SkScalarToCompareType(top) >= clipR.fBottom
+ || SkScalarToCompareType(bottom) <= clipR.fTop;
+ }
+
+ /** Return the bounds of the current clip (in local coordinates) in the
+ bounds parameter, and return true if it is non-empty. This can be useful
+ in a way similar to quickReject, in that it tells you that drawing
+ outside of these bounds will be clipped out.
+ */
+ bool getClipBounds(SkRect* bounds) const;
+
+ /** Return the bounds of the current clip, in device coordinates; returns
+ true if non-empty. Maybe faster than getting the clip explicitly and
+ then taking its bounds.
+ */
+ bool getClipDeviceBounds(SkIRect* bounds) const;
+
+
+ /** Fill the entire canvas' bitmap (restricted to the current clip) with the
+ specified ARGB color, using the specified mode.
+ @param a the alpha component (0..255) of the color to fill the canvas
+ @param r the red component (0..255) of the color to fill the canvas
+ @param g the green component (0..255) of the color to fill the canvas
+ @param b the blue component (0..255) of the color to fill the canvas
+ @param mode the mode to apply the color in (defaults to SrcOver)
+ */
+ void drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b,
+ SkXfermode::Mode mode = SkXfermode::kSrcOver_Mode);
+
+ /** Fill the entire canvas' bitmap (restricted to the current clip) with the
+ specified color and mode.
+ @param color the color to draw with
+ @param mode the mode to apply the color in (defaults to SrcOver)
+ */
+ void drawColor(SkColor color,
+ SkXfermode::Mode mode = SkXfermode::kSrcOver_Mode);
+
+ /**
+ * This erases the entire drawing surface to the specified color,
+ * irrespective of the clip. It does not blend with the previous pixels,
+ * but always overwrites them.
+ *
+ * It is roughly equivalent to the following:
+ * canvas.save();
+ * canvas.clipRect(hugeRect, kReplace_Op);
+ * paint.setColor(color);
+ * paint.setXfermodeMode(kSrc_Mode);
+ * canvas.drawPaint(paint);
+ * canvas.restore();
+ * though it is almost always much more efficient.
+ */
+ virtual void clear(SkColor);
+
+ /**
+ * Fill the entire canvas' bitmap (restricted to the current clip) with the
+ * specified paint.
+ * @param paint The paint used to fill the canvas
+ */
+ virtual void drawPaint(const SkPaint& paint);
+
+ enum PointMode {
+ /** drawPoints draws each point separately */
+ kPoints_PointMode,
+ /** drawPoints draws each pair of points as a line segment */
+ kLines_PointMode,
+ /** drawPoints draws the array of points as a polygon */
+ kPolygon_PointMode
+ };
+
+ /** Draw a series of points, interpreted based on the PointMode mode. For
+ all modes, the count parameter is interpreted as the total number of
+ points. For kLine mode, count/2 line segments are drawn.
+ For kPoint mode, each point is drawn centered at its coordinate, and its
+ size is specified by the paint's stroke-width. It draws as a square,
+ unless the paint's cap-type is round, in which the points are drawn as
+ circles.
+ For kLine mode, each pair of points is drawn as a line segment,
+ respecting the paint's settings for cap/join/width.
+ For kPolygon mode, the entire array is drawn as a series of connected
+ line segments.
+ Note that, while similar, kLine and kPolygon modes draw slightly
+ differently than the equivalent path built with a series of moveto,
+ lineto calls, in that the path will draw all of its contours at once,
+ with no interactions if contours intersect each other (think XOR
+ xfermode). drawPoints always draws each element one at a time.
+ @param mode PointMode specifying how to draw the array of points.
+ @param count The number of points in the array
+ @param pts Array of points to draw
+ @param paint The paint used to draw the points
+ */
+ virtual void drawPoints(PointMode mode, size_t count, const SkPoint pts[],
+ const SkPaint& paint);
+
+ /** Helper method for drawing a single point. See drawPoints() for a more
+ details.
+ */
+ void drawPoint(SkScalar x, SkScalar y, const SkPaint& paint);
+
+ /** Draws a single pixel in the specified color.
+ @param x The X coordinate of which pixel to draw
+ @param y The Y coordiante of which pixel to draw
+ @param color The color to draw
+ */
+ void drawPoint(SkScalar x, SkScalar y, SkColor color);
+
+ /** Draw a line segment with the specified start and stop x,y coordinates,
+ using the specified paint. NOTE: since a line is always "framed", the
+ paint's Style is ignored.
+ @param x0 The x-coordinate of the start point of the line
+ @param y0 The y-coordinate of the start point of the line
+ @param x1 The x-coordinate of the end point of the line
+ @param y1 The y-coordinate of the end point of the line
+ @param paint The paint used to draw the line
+ */
+ void drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1,
+ const SkPaint& paint);
+
+ /** Draw the specified rectangle using the specified paint. The rectangle
+ will be filled or stroked based on the Style in the paint.
+ @param rect The rect to be drawn
+ @param paint The paint used to draw the rect
+ */
+ virtual void drawRect(const SkRect& rect, const SkPaint& paint);
+
+ /** Draw the specified rectangle using the specified paint. The rectangle
+ will be filled or framed based on the Style in the paint.
+ @param rect The rect to be drawn
+ @param paint The paint used to draw the rect
+ */
+ void drawIRect(const SkIRect& rect, const SkPaint& paint)
+ {
+ SkRect r;
+ r.set(rect); // promotes the ints to scalars
+ this->drawRect(r, paint);
+ }
+
+ /** Draw the specified rectangle using the specified paint. The rectangle
+ will be filled or framed based on the Style in the paint.
+ @param left The left side of the rectangle to be drawn
+ @param top The top side of the rectangle to be drawn
+ @param right The right side of the rectangle to be drawn
+ @param bottom The bottom side of the rectangle to be drawn
+ @param paint The paint used to draw the rect
+ */
+ void drawRectCoords(SkScalar left, SkScalar top, SkScalar right,
+ SkScalar bottom, const SkPaint& paint);
+
+ /** Draw the specified oval using the specified paint. The oval will be
+ filled or framed based on the Style in the paint.
+ @param oval The rectangle bounds of the oval to be drawn
+ @param paint The paint used to draw the oval
+ */
+ virtual void drawOval(const SkRect& oval, const SkPaint&);
+
+ /**
+ * Draw the specified RRect using the specified paint The rrect will be filled or stroked
+ * based on the Style in the paint.
+ *
+ * @param rrect The round-rect to draw
+ * @param paint The paint used to draw the round-rect
+ */
+ virtual void drawRRect(const SkRRect& rrect, const SkPaint& paint);
+
+ /** Draw the specified circle using the specified paint. If radius is <= 0,
+ then nothing will be drawn. The circle will be filled
+ or framed based on the Style in the paint.
+ @param cx The x-coordinate of the center of the cirle to be drawn
+ @param cy The y-coordinate of the center of the cirle to be drawn
+ @param radius The radius of the cirle to be drawn
+ @param paint The paint used to draw the circle
+ */
+ void drawCircle(SkScalar cx, SkScalar cy, SkScalar radius,
+ const SkPaint& paint);
+
+ /** Draw the specified arc, which will be scaled to fit inside the
+ specified oval. If the sweep angle is >= 360, then the oval is drawn
+ completely. Note that this differs slightly from SkPath::arcTo, which
+ treats the sweep angle mod 360.
+ @param oval The bounds of oval used to define the shape of the arc
+ @param startAngle Starting angle (in degrees) where the arc begins
+ @param sweepAngle Sweep angle (in degrees) measured clockwise
+ @param useCenter true means include the center of the oval. For filling
+ this will draw a wedge. False means just use the arc.
+ @param paint The paint used to draw the arc
+ */
+ void drawArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle,
+ bool useCenter, const SkPaint& paint);
+
+ /** Draw the specified round-rect using the specified paint. The round-rect
+ will be filled or framed based on the Style in the paint.
+ @param rect The rectangular bounds of the roundRect to be drawn
+ @param rx The x-radius of the oval used to round the corners
+ @param ry The y-radius of the oval used to round the corners
+ @param paint The paint used to draw the roundRect
+ */
+ void drawRoundRect(const SkRect& rect, SkScalar rx, SkScalar ry,
+ const SkPaint& paint);
+
+ /** Draw the specified path using the specified paint. The path will be
+ filled or framed based on the Style in the paint.
+ @param path The path to be drawn
+ @param paint The paint used to draw the path
+ */
+ virtual void drawPath(const SkPath& path, const SkPaint& paint);
+
+ /** Draw the specified bitmap, with its top/left corner at (x,y), using the
+ specified paint, transformed by the current matrix. Note: if the paint
+ contains a maskfilter that generates a mask which extends beyond the
+ bitmap's original width/height, then the bitmap will be drawn as if it
+ were in a Shader with CLAMP mode. Thus the color outside of the original
+ width/height will be the edge color replicated.
+ @param bitmap The bitmap to be drawn
+ @param left The position of the left side of the bitmap being drawn
+ @param top The position of the top side of the bitmap being drawn
+ @param paint The paint used to draw the bitmap, or NULL
+ */
+ virtual void drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
+ const SkPaint* paint = NULL);
+
+ /** Draw the specified bitmap, with the specified matrix applied (before the
+ canvas' matrix is applied).
+ @param bitmap The bitmap to be drawn
+ @param src Optional: specify the subset of the bitmap to be drawn
+ @param dst The destination rectangle where the scaled/translated
+ image will be drawn
+ @param paint The paint used to draw the bitmap, or NULL
+ */
+ virtual void drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src,
+ const SkRect& dst,
+ const SkPaint* paint);
+
+ void drawBitmapRect(const SkBitmap& bitmap, const SkRect& dst,
+ const SkPaint* paint) {
+ this->drawBitmapRectToRect(bitmap, NULL, dst, paint);
+ }
+
+ void drawBitmapRect(const SkBitmap& bitmap, const SkIRect* isrc,
+ const SkRect& dst, const SkPaint* paint = NULL) {
+ SkRect realSrcStorage;
+ SkRect* realSrcPtr = NULL;
+ if (isrc) {
+ realSrcStorage.set(*isrc);
+ realSrcPtr = &realSrcStorage;
+ }
+ this->drawBitmapRectToRect(bitmap, realSrcPtr, dst, paint);
+ }
+
+ virtual void drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& m,
+ const SkPaint* paint = NULL);
+
+ /**
+ * Draw the bitmap stretched differentially to fit into dst.
+ * center is a rect within the bitmap, and logically divides the bitmap
+ * into 9 sections (3x3). For example, if the middle pixel of a [5x5]
+ * bitmap is the "center", then the center-rect should be [2, 2, 3, 3].
+ *
+ * If the dst is >= the bitmap size, then...
+ * - The 4 corners are not stretched at all.
+ * - The sides are stretched in only one axis.
+ * - The center is stretched in both axes.
+ * Else, for each axis where dst < bitmap,
+ * - The corners shrink proportionally
+ * - The sides (along the shrink axis) and center are not drawn
+ */
+ virtual void drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
+ const SkRect& dst, const SkPaint* paint = NULL);
+
+ /** Draw the specified bitmap, with its top/left corner at (x,y),
+ NOT transformed by the current matrix. Note: if the paint
+ contains a maskfilter that generates a mask which extends beyond the
+ bitmap's original width/height, then the bitmap will be drawn as if it
+ were in a Shader with CLAMP mode. Thus the color outside of the original
+ width/height will be the edge color replicated.
+ @param bitmap The bitmap to be drawn
+ @param left The position of the left side of the bitmap being drawn
+ @param top The position of the top side of the bitmap being drawn
+ @param paint The paint used to draw the bitmap, or NULL
+ */
+ virtual void drawSprite(const SkBitmap& bitmap, int left, int top,
+ const SkPaint* paint = NULL);
+
+ /** Draw the text, with origin at (x,y), using the specified paint.
+ The origin is interpreted based on the Align setting in the paint.
+ @param text The text to be drawn
+ @param byteLength The number of bytes to read from the text parameter
+ @param x The x-coordinate of the origin of the text being drawn
+ @param y The y-coordinate of the origin of the text being drawn
+ @param paint The paint used for the text (e.g. color, size, style)
+ */
+ virtual void drawText(const void* text, size_t byteLength, SkScalar x,
+ SkScalar y, const SkPaint& paint);
+
+ /** Draw the text, with each character/glyph origin specified by the pos[]
+ array. The origin is interpreted by the Align setting in the paint.
+ @param text The text to be drawn
+ @param byteLength The number of bytes to read from the text parameter
+ @param pos Array of positions, used to position each character
+ @param paint The paint used for the text (e.g. color, size, style)
+ */
+ virtual void drawPosText(const void* text, size_t byteLength,
+ const SkPoint pos[], const SkPaint& paint);
+
+ /** Draw the text, with each character/glyph origin specified by the x
+ coordinate taken from the xpos[] array, and the y from the constY param.
+ The origin is interpreted by the Align setting in the paint.
+ @param text The text to be drawn
+ @param byteLength The number of bytes to read from the text parameter
+ @param xpos Array of x-positions, used to position each character
+ @param constY The shared Y coordinate for all of the positions
+ @param paint The paint used for the text (e.g. color, size, style)
+ */
+ virtual void drawPosTextH(const void* text, size_t byteLength,
+ const SkScalar xpos[], SkScalar constY,
+ const SkPaint& paint);
+
+ /** Draw the text, with origin at (x,y), using the specified paint, along
+ the specified path. The paint's Align setting determins where along the
+ path to start the text.
+ @param text The text to be drawn
+ @param byteLength The number of bytes to read from the text parameter
+ @param path The path the text should follow for its baseline
+ @param hOffset The distance along the path to add to the text's
+ starting position
+ @param vOffset The distance above(-) or below(+) the path to
+ position the text
+ @param paint The paint used for the text
+ */
+ void drawTextOnPathHV(const void* text, size_t byteLength,
+ const SkPath& path, SkScalar hOffset,
+ SkScalar vOffset, const SkPaint& paint);
+
+ /** Draw the text, with origin at (x,y), using the specified paint, along
+ the specified path. The paint's Align setting determins where along the
+ path to start the text.
+ @param text The text to be drawn
+ @param byteLength The number of bytes to read from the text parameter
+ @param path The path the text should follow for its baseline
+ @param matrix (may be null) Applied to the text before it is
+ mapped onto the path
+ @param paint The paint used for the text
+ */
+ virtual void drawTextOnPath(const void* text, size_t byteLength,
+ const SkPath& path, const SkMatrix* matrix,
+ const SkPaint& paint);
+
+#ifdef SK_BUILD_FOR_ANDROID
+ /** Draw the text on path, with each character/glyph origin specified by the pos[]
+ array. The origin is interpreted by the Align setting in the paint.
+ @param text The text to be drawn
+ @param byteLength The number of bytes to read from the text parameter
+ @param pos Array of positions, used to position each character
+ @param paint The paint used for the text (e.g. color, size, style)
+ @param path The path to draw on
+ @param matrix The canvas matrix
+ */
+ void drawPosTextOnPath(const void* text, size_t byteLength,
+ const SkPoint pos[], const SkPaint& paint,
+ const SkPath& path, const SkMatrix* matrix);
+#endif
+
+ /** Draw the picture into this canvas. This method effective brackets the
+ playback of the picture's draw calls with save/restore, so the state
+ of this canvas will be unchanged after this call.
+ @param picture The recorded drawing commands to playback into this
+ canvas.
+ */
+ virtual void drawPicture(SkPicture& picture);
+
+ enum VertexMode {
+ kTriangles_VertexMode,
+ kTriangleStrip_VertexMode,
+ kTriangleFan_VertexMode
+ };
+
+ /** Draw the array of vertices, interpreted as triangles (based on mode).
+ @param vmode How to interpret the array of vertices
+ @param vertexCount The number of points in the vertices array (and
+ corresponding texs and colors arrays if non-null)
+ @param vertices Array of vertices for the mesh
+ @param texs May be null. If not null, specifies the coordinate
+ in _texture_ space (not uv space) for each vertex.
+ @param colors May be null. If not null, specifies a color for each
+ vertex, to be interpolated across the triangle.
+ @param xmode Used if both texs and colors are present. In this
+ case the colors are combined with the texture using mode,
+ before being drawn using the paint. If mode is null, then
+ kModulate_Mode is used.
+ @param indices If not null, array of indices to reference into the
+ vertex (texs, colors) array.
+ @param indexCount number of entries in the indices array (if not null)
+ @param paint Specifies the shader/texture if present.
+ */
+ virtual void drawVertices(VertexMode vmode, int vertexCount,
+ const SkPoint vertices[], const SkPoint texs[],
+ const SkColor colors[], SkXfermode* xmode,
+ const uint16_t indices[], int indexCount,
+ const SkPaint& paint);
+
+ /** Send a blob of data to the canvas.
+ For canvases that draw, this call is effectively a no-op, as the data
+ is not parsed, but just ignored. However, this call exists for
+ subclasses like SkPicture's recording canvas, that can store the data
+ and then play it back later (via another call to drawData).
+ */
+ virtual void drawData(const void* data, size_t length) {
+ // do nothing. Subclasses may do something with the data
+ }
+
+ /** Add comments. beginCommentGroup/endCommentGroup open/close a new group.
+ Each comment added via addComment is notionally attached to its
+ enclosing group. Top-level comments simply belong to no group.
+ */
+ virtual void beginCommentGroup(const char* description) {
+ // do nothing. Subclasses may do something
+ }
+ virtual void addComment(const char* kywd, const char* value) {
+ // do nothing. Subclasses may do something
+ }
+ virtual void endCommentGroup() {
+ // do nothing. Subclasses may do something
+ }
+
+
+ //////////////////////////////////////////////////////////////////////////
+
+ /** Get the current bounder object.
+ The bounder's reference count is unchaged.
+ @return the canva's bounder (or NULL).
+ */
+ SkBounder* getBounder() const { return fBounder; }
+
+ /** Set a new bounder (or NULL).
+ Pass NULL to clear any previous bounder.
+ As a convenience, the parameter passed is also returned.
+ If a previous bounder exists, its reference count is decremented.
+ If bounder is not NULL, its reference count is incremented.
+ @param bounder the new bounder (or NULL) to be installed in the canvas
+ @return the set bounder object
+ */
+ virtual SkBounder* setBounder(SkBounder* bounder);
+
+ /** Get the current filter object. The filter's reference count is not
+ affected. The filter is saved/restored, just like the matrix and clip.
+ @return the canvas' filter (or NULL).
+ */
+ SkDrawFilter* getDrawFilter() const;
+
+ /** Set the new filter (or NULL). Pass NULL to clear any existing filter.
+ As a convenience, the parameter is returned. If an existing filter
+ exists, its refcnt is decrement. If the new filter is not null, its
+ refcnt is incremented. The filter is saved/restored, just like the
+ matrix and clip.
+ @param filter the new filter (or NULL)
+ @return the new filter
+ */
+ virtual SkDrawFilter* setDrawFilter(SkDrawFilter* filter);
+
+ //////////////////////////////////////////////////////////////////////////
+
+ /** Return the current matrix on the canvas.
+ This does not account for the translate in any of the devices.
+ @return The current matrix on the canvas.
+ */
+ const SkMatrix& getTotalMatrix() const;
+
+ enum ClipType {
+ kEmpty_ClipType = 0,
+ kRect_ClipType,
+ kComplex_ClipType
+ };
+
+ /** Returns a description of the total clip; may be cheaper than
+ getting the clip and querying it directly.
+ */
+ ClipType getClipType() const;
+
+ /** Return the current device clip (concatenation of all clip calls).
+ * This does not account for the translate in any of the devices.
+ * @return the current device clip (concatenation of all clip calls).
+ *
+ * DEPRECATED -- call getClipDeviceBounds() instead.
+ */
+ const SkRegion& getTotalClip() const;
+
+ /** Return the clip stack. The clip stack stores all the individual
+ * clips organized by the save/restore frame in which they were
+ * added.
+ * @return the current clip stack ("list" of individual clip elements)
+ */
+ const SkClipStack* getClipStack() const {
+ return &fClipStack;
+ }
+
+ class ClipVisitor {
+ public:
+ virtual ~ClipVisitor();
+ virtual void clipRect(const SkRect&, SkRegion::Op, bool antialias) = 0;
+ virtual void clipPath(const SkPath&, SkRegion::Op, bool antialias) = 0;
+ };
+
+ /**
+ * Replays the clip operations, back to front, that have been applied to
+ * the canvas, calling the appropriate method on the visitor for each
+ * clip. All clips have already been transformed into device space.
+ */
+ void replayClips(ClipVisitor*) const;
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ /** After calling saveLayer(), there can be any number of devices that make
+ up the top-most drawing area. LayerIter can be used to iterate through
+ those devices. Note that the iterator is only valid until the next API
+ call made on the canvas. Ownership of all pointers in the iterator stays
+ with the canvas, so none of them should be modified or deleted.
+ */
+ class SK_API LayerIter /*: SkNoncopyable*/ {
+ public:
+ /** Initialize iterator with canvas, and set values for 1st device */
+ LayerIter(SkCanvas*, bool skipEmptyClips);
+ ~LayerIter();
+
+ /** Return true if the iterator is done */
+ bool done() const { return fDone; }
+ /** Cycle to the next device */
+ void next();
+
+ // These reflect the current device in the iterator
+
+ SkDevice* device() const;
+ const SkMatrix& matrix() const;
+ const SkRegion& clip() const;
+ const SkPaint& paint() const;
+ int x() const;
+ int y() const;
+
+ private:
+ // used to embed the SkDrawIter object directly in our instance, w/o
+ // having to expose that class def to the public. There is an assert
+ // in our constructor to ensure that fStorage is large enough
+ // (though needs to be a compile-time-assert!). We use intptr_t to work
+ // safely with 32 and 64 bit machines (to ensure the storage is enough)
+ intptr_t fStorage[32];
+ class SkDrawIter* fImpl; // this points at fStorage
+ SkPaint fDefaultPaint;
+ bool fDone;
+ };
+
+protected:
+ // Returns the canvas to be used by DrawIter. Default implementation
+ // returns this. Subclasses that encapsulate an indirect canvas may
+ // need to overload this method. The impl must keep track of this, as it
+ // is not released or deleted by the caller.
+ virtual SkCanvas* canvasForDrawIter();
+
+ // Clip rectangle bounds. Called internally by saveLayer.
+ // returns false if the entire rectangle is entirely clipped out
+ bool clipRectBounds(const SkRect* bounds, SaveFlags flags,
+ SkIRect* intersection);
+
+ // Called by child classes that override clipPath and clipRRect to only
+ // track fast conservative clip bounds, rather than exact clips.
+ bool updateClipConservativelyUsingBounds(const SkRect&, SkRegion::Op,
+ bool inverseFilled);
+
+ // notify our surface (if we have one) that we are about to draw, so it
+ // can perform copy-on-write or invalidate any cached images
+ void predrawNotify();
+
+ /** DEPRECATED -- use constructor(device)
+
+ Marked as 'protected' to avoid new clients using this before we can
+ completely remove it.
+
+ Specify a device for this canvas to draw into. If it is not null, its
+ reference count is incremented. If the canvas was already holding a
+ device, its reference count is decremented. The new device is returned.
+ */
+ virtual SkDevice* setDevice(SkDevice* device);
+
+private:
+ class MCRec;
+
+ SkClipStack fClipStack;
+ SkDeque fMCStack;
+ // points to top of stack
+ MCRec* fMCRec;
+ // the first N recs that can fit here mean we won't call malloc
+ uint32_t fMCRecStorage[32];
+
+ SkBounder* fBounder;
+ int fSaveLayerCount; // number of successful saveLayer calls
+
+ SkMetaData* fMetaData;
+
+ SkSurface_Base* fSurfaceBase;
+ SkSurface_Base* getSurfaceBase() const { return fSurfaceBase; }
+ void setSurfaceBase(SkSurface_Base* sb) {
+ fSurfaceBase = sb;
+ }
+ friend class SkSurface_Base;
+ friend class SkSurface_Gpu;
+
+ bool fDeviceCMDirty; // cleared by updateDeviceCMCache()
+ void updateDeviceCMCache();
+
+ friend class SkDrawIter; // needs setupDrawForLayerDevice()
+ friend class AutoDrawLooper;
+
+ SkDevice* createLayerDevice(SkBitmap::Config, int width, int height,
+ bool isOpaque);
+
+ SkDevice* init(SkDevice*);
+
+ // internal methods are not virtual, so they can safely be called by other
+ // canvas apis, without confusing subclasses (like SkPictureRecording)
+ void internalDrawBitmap(const SkBitmap&, const SkMatrix& m, const SkPaint* paint);
+ void internalDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src,
+ const SkRect& dst, const SkPaint* paint);
+ void internalDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
+ const SkRect& dst, const SkPaint* paint);
+ void internalDrawPaint(const SkPaint& paint);
+ int internalSaveLayer(const SkRect* bounds, const SkPaint* paint,
+ SaveFlags, bool justForImageFilter);
+ void internalDrawDevice(SkDevice*, int x, int y, const SkPaint*);
+
+ // shared by save() and saveLayer()
+ int internalSave(SaveFlags flags);
+ void internalRestore();
+ static void DrawRect(const SkDraw& draw, const SkPaint& paint,
+ const SkRect& r, SkScalar textSize);
+ static void DrawTextDecorations(const SkDraw& draw, const SkPaint& paint,
+ const char text[], size_t byteLength,
+ SkScalar x, SkScalar y);
+
+ /* These maintain a cache of the clip bounds in local coordinates,
+ (converted to 2s-compliment if floats are slow).
+ */
+ mutable SkRectCompareType fLocalBoundsCompareType;
+ mutable bool fLocalBoundsCompareTypeDirty;
+ bool fAllowSoftClip;
+ bool fAllowSimplifyClip;
+
+ const SkRectCompareType& getLocalClipBoundsCompareType() const {
+ if (fLocalBoundsCompareTypeDirty) {
+ this->computeLocalClipBoundsCompareType();
+ fLocalBoundsCompareTypeDirty = false;
+ }
+ return fLocalBoundsCompareType;
+ }
+ void computeLocalClipBoundsCompareType() const;
+
+
+ class AutoValidateClip : ::SkNoncopyable {
+ public:
+ explicit AutoValidateClip(SkCanvas* canvas) : fCanvas(canvas) {
+ fCanvas->validateClip();
+ }
+ ~AutoValidateClip() { fCanvas->validateClip(); }
+
+ private:
+ const SkCanvas* fCanvas;
+ };
+
+#ifdef SK_DEBUG
+ void validateClip() const;
+#else
+ void validateClip() const {}
+#endif
+
+ typedef SkRefCnt INHERITED;
+};
+
+/** Stack helper class to automatically call restoreToCount() on the canvas
+ when this object goes out of scope. Use this to guarantee that the canvas
+ is restored to a known state.
+*/
+class SkAutoCanvasRestore : SkNoncopyable {
+public:
+ SkAutoCanvasRestore(SkCanvas* canvas, bool doSave) : fCanvas(canvas) {
+ SkASSERT(canvas);
+ fSaveCount = canvas->getSaveCount();
+ if (doSave) {
+ canvas->save();
+ }
+ }
+ ~SkAutoCanvasRestore() {
+ if (fCanvas) {
+ fCanvas->restoreToCount(fSaveCount);
+ }
+ }
+
+ /**
+ * Perform the restore now, instead of waiting for the destructor. Will
+ * only do this once.
+ */
+ void restore() {
+ if (fCanvas) {
+ fCanvas->restoreToCount(fSaveCount);
+ fCanvas = NULL;
+ }
+ }
+
+private:
+ SkCanvas* fCanvas;
+ int fSaveCount;
+};
+
+/** Stack helper class to automatically open and close a comment block
+ */
+class SkAutoCommentBlock : SkNoncopyable {
+public:
+ SkAutoCommentBlock(SkCanvas* canvas, const char* description) {
+ fCanvas = canvas;
+ if (NULL != fCanvas) {
+ fCanvas->beginCommentGroup(description);
+ }
+ }
+
+ ~SkAutoCommentBlock() {
+ if (NULL != fCanvas) {
+ fCanvas->endCommentGroup();
+ }
+ }
+
+private:
+ SkCanvas* fCanvas;
+};
+
+#endif
diff --git a/core/SkChecksum.h b/core/SkChecksum.h
new file mode 100644
index 0000000..bf3228f
--- /dev/null
+++ b/core/SkChecksum.h
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkChecksum_DEFINED
+#define SkChecksum_DEFINED
+
+#include "SkTypes.h"
+
+/**
+ * Computes a 32bit checksum from a blob of 32bit aligned data. This is meant
+ * to be very very fast, as it is used internally by the font cache, in
+ * conjuction with the entire raw key. This algorithm does not generate
+ * unique values as well as others (e.g. MD5) but it performs much faster.
+ * Skia's use cases can survive non-unique values (since the entire key is
+ * always available). Clients should only be used in circumstances where speed
+ * over uniqueness is at a premium.
+ */
+class SkChecksum : SkNoncopyable {
+private:
+ /*
+ * Our Rotate and Mash helpers are meant to automatically do the right
+ * thing depending if sizeof(uintptr_t) is 4 or 8.
+ */
+ enum {
+ ROTR = 17,
+ ROTL = sizeof(uintptr_t) * 8 - ROTR,
+ HALFBITS = sizeof(uintptr_t) * 4
+ };
+
+ static inline uintptr_t Mash(uintptr_t total, uintptr_t value) {
+ return ((total >> ROTR) | (total << ROTL)) ^ value;
+ }
+
+public:
+
+ /**
+ * Calculate 32-bit Murmur hash (murmur3).
+ * This should take 2-3x longer than SkChecksum::Compute, but is a considerably better hash.
+ * See en.wikipedia.org/wiki/MurmurHash.
+ *
+ * @param data Memory address of the data block to be processed. Must be 32-bit aligned.
+ * @param size Size of the data block in bytes. Must be a multiple of 4.
+ * @param seed Initial hash seed. (optional)
+ * @return hash result
+ */
+ static uint32_t Murmur3(const uint32_t* data, size_t bytes, uint32_t seed=0) {
+ SkASSERT(SkIsAlign4(bytes));
+ const size_t words = bytes/4;
+
+ uint32_t hash = seed;
+ for (size_t i = 0; i < words; i++) {
+ uint32_t k = data[i];
+ k *= 0xcc9e2d51;
+ k = (k << 15) | (k >> 17);
+ k *= 0x1b873593;
+
+ hash ^= k;
+ hash = (hash << 13) | (hash >> 19);
+ hash *= 5;
+ hash += 0xe6546b64;
+ }
+ hash ^= bytes;
+ hash ^= hash >> 16;
+ hash *= 0x85ebca6b;
+ hash ^= hash >> 13;
+ hash *= 0xc2b2ae35;
+ hash ^= hash >> 16;
+ return hash;
+ }
+
+ /**
+ * Compute a 32-bit checksum for a given data block
+ *
+ * WARNING: this algorithm is tuned for efficiency, not backward/forward
+ * compatibility. It may change at any time, so a checksum generated with
+ * one version of the Skia code may not match a checksum generated with
+ * a different version of the Skia code.
+ *
+ * @param data Memory address of the data block to be processed. Must be
+ * 32-bit aligned.
+ * @param size Size of the data block in bytes. Must be a multiple of 4.
+ * @return checksum result
+ */
+ static uint32_t Compute(const uint32_t* data, size_t size) {
+ SkASSERT(SkIsAlign4(size));
+
+ /*
+ * We want to let the compiler use 32bit or 64bit addressing and math
+ * so we use uintptr_t as our magic type. This makes the code a little
+ * more obscure (we can't hard-code 32 or 64 anywhere, but have to use
+ * sizeof()).
+ */
+ uintptr_t result = 0;
+ const uintptr_t* ptr = reinterpret_cast<const uintptr_t*>(data);
+
+ /*
+ * count the number of quad element chunks. This takes into account
+ * if we're on a 32bit or 64bit arch, since we use sizeof(uintptr_t)
+ * to compute how much to shift-down the size.
+ */
+ size_t n4 = size / (sizeof(uintptr_t) << 2);
+ for (size_t i = 0; i < n4; ++i) {
+ result = Mash(result, *ptr++);
+ result = Mash(result, *ptr++);
+ result = Mash(result, *ptr++);
+ result = Mash(result, *ptr++);
+ }
+ size &= ((sizeof(uintptr_t) << 2) - 1);
+
+ data = reinterpret_cast<const uint32_t*>(ptr);
+ const uint32_t* stop = data + (size >> 2);
+ while (data < stop) {
+ result = Mash(result, *data++);
+ }
+
+ /*
+ * smash us down to 32bits if we were 64. Note that when uintptr_t is
+ * 32bits, this code-path should go away, but I still got a warning
+ * when I wrote
+ * result ^= result >> 32;
+ * since >>32 is undefined for 32bit ints, hence the wacky HALFBITS
+ * define.
+ */
+ if (8 == sizeof(result)) {
+ result ^= result >> HALFBITS;
+ }
+ return static_cast<uint32_t>(result);
+ }
+};
+
+#endif
diff --git a/core/SkChunkAlloc.h b/core/SkChunkAlloc.h
new file mode 100644
index 0000000..e13e2b9
--- /dev/null
+++ b/core/SkChunkAlloc.h
@@ -0,0 +1,68 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkChunkAlloc_DEFINED
+#define SkChunkAlloc_DEFINED
+
+#include "SkTypes.h"
+
+class SkChunkAlloc : SkNoncopyable {
+public:
+ SkChunkAlloc(size_t minSize);
+ ~SkChunkAlloc();
+
+ /**
+ * Free up all allocated blocks. This invalidates all returned
+ * pointers.
+ */
+ void reset();
+
+ enum AllocFailType {
+ kReturnNil_AllocFailType,
+ kThrow_AllocFailType
+ };
+
+ void* alloc(size_t bytes, AllocFailType);
+ void* allocThrow(size_t bytes) {
+ return this->alloc(bytes, kThrow_AllocFailType);
+ }
+
+ /** Call this to unalloc the most-recently allocated ptr by alloc(). On
+ success, the number of bytes freed is returned, or 0 if the block could
+ not be unallocated. This is a hint to the underlying allocator that
+ the previous allocation may be reused, but the implementation is free
+ to ignore this call (and return 0).
+ */
+ size_t unalloc(void* ptr);
+
+ size_t totalCapacity() const { return fTotalCapacity; }
+ size_t totalUsed() const { return fTotalUsed; }
+ int blockCount() const { return fBlockCount; }
+
+ /**
+ * Returns true if the specified address is within one of the chunks, and
+ * has at least 1-byte following the address (i.e. if addr points to the
+ * end of a chunk, then contains() will return false).
+ */
+ bool contains(const void* addr) const;
+
+private:
+ struct Block;
+
+ Block* fBlock;
+ size_t fMinSize;
+ size_t fChunkSize;
+ size_t fTotalCapacity;
+ size_t fTotalUsed; // will be <= fTotalCapacity
+ int fBlockCount;
+
+ Block* newBlock(size_t bytes, AllocFailType ftype);
+};
+
+#endif
diff --git a/core/SkClipStack.h b/core/SkClipStack.h
new file mode 100644
index 0000000..145552d
--- /dev/null
+++ b/core/SkClipStack.h
@@ -0,0 +1,471 @@
+
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#ifndef SkClipStack_DEFINED
+#define SkClipStack_DEFINED
+
+#include "SkDeque.h"
+#include "SkPath.h"
+#include "SkRect.h"
+#include "SkRegion.h"
+#include "SkTDArray.h"
+
+
+// Because a single save/restore state can have multiple clips, this class
+// stores the stack depth (fSaveCount) and clips (fDeque) separately.
+// Each clip in fDeque stores the stack state to which it belongs
+// (i.e., the fSaveCount in force when it was added). Restores are thus
+// implemented by removing clips from fDeque that have an fSaveCount larger
+// then the freshly decremented count.
+class SK_API SkClipStack {
+public:
+ enum BoundsType {
+ // The bounding box contains all the pixels that can be written to
+ kNormal_BoundsType,
+ // The bounding box contains all the pixels that cannot be written to.
+ // The real bound extends out to infinity and all the pixels outside
+ // of the bound can be written to. Note that some of the pixels inside
+ // the bound may also be writeable but all pixels that cannot be
+ // written to are guaranteed to be inside.
+ kInsideOut_BoundsType
+ };
+
+ class Element {
+ public:
+ enum Type {
+ //!< This element makes the clip empty (regardless of previous elements).
+ kEmpty_Type,
+ //!< This element combines a rect with the current clip using a set operation
+ kRect_Type,
+ //!< This element combines a path with the current clip using a set operation
+ kPath_Type,
+ };
+
+ Element() {
+ this->initCommon(0, SkRegion::kReplace_Op, false);
+ this->setEmpty();
+ }
+
+ Element(const SkRect& rect, SkRegion::Op op, bool doAA) {
+ this->initRect(0, rect, op, doAA);
+ }
+
+ Element(const SkPath& path, SkRegion::Op op, bool doAA) {
+ this->initPath(0, path, op, doAA);
+ }
+
+ bool operator== (const Element& element) const {
+ if (this == &element) {
+ return true;
+ }
+ if (fOp != element.fOp ||
+ fType != element.fType ||
+ fDoAA != element.fDoAA ||
+ fSaveCount != element.fSaveCount) {
+ return false;
+ }
+ switch (fType) {
+ case kPath_Type:
+ return fPath == element.fPath;
+ case kRect_Type:
+ return fRect == element.fRect;
+ case kEmpty_Type:
+ return true;
+ default:
+ SkDEBUGFAIL("Unexpected type.");
+ return false;
+ }
+ }
+ bool operator!= (const Element& element) const { return !(*this == element); }
+
+ //!< Call to get the type of the clip element.
+ Type getType() const { return fType; }
+
+ //!< Call if getType() is kPath to get the path.
+ const SkPath& getPath() const { return fPath; }
+
+ //!< Call if getType() is kRect to get the rect.
+ const SkRect& getRect() const { return fRect; }
+
+ //!< Call if getType() is not kEmpty to get the set operation used to combine this element.
+ SkRegion::Op getOp() const { return fOp; }
+
+ /** If getType() is not kEmpty this indicates whether the clip shape should be anti-aliased
+ when it is rasterized. */
+ bool isAA() const { return fDoAA; }
+
+ //!< Inverts the fill of the clip shape. Note that a kEmpty element remains kEmpty.
+ void invertShapeFillType();
+
+ //!< Sets the set operation represented by the element.
+ void setOp(SkRegion::Op op) { fOp = op; }
+
+ /** The GenID can be used by clip stack clients to cache representations of the clip. The
+ ID corresponds to the set of clip elements up to and including this element within the
+ stack not to the element itself. That is the same clip path in different stacks will
+ have a different ID since the elements produce different clip result in the context of
+ their stacks. */
+ int32_t getGenID() const { return fGenID; }
+
+ /**
+ * Gets the bounds of the clip element, either the rect or path bounds. (Whether the shape
+ * is inverse filled is not considered.)
+ */
+ const SkRect& getBounds() const {
+ static const SkRect kEmpty = { 0, 0, 0, 0 };
+ switch (fType) {
+ case kRect_Type:
+ return fRect;
+ case kPath_Type:
+ return fPath.getBounds();
+ case kEmpty_Type:
+ return kEmpty;
+ default:
+ SkDEBUGFAIL("Unexpected type.");
+ return kEmpty;
+ }
+ }
+
+ /**
+ * Conservatively checks whether the clip shape contains the rect param. (Whether the shape
+ * is inverse filled is not considered.)
+ */
+ bool contains(const SkRect& rect) const {
+ switch (fType) {
+ case kRect_Type:
+ return fRect.contains(rect);
+ case kPath_Type:
+ return fPath.conservativelyContainsRect(rect);
+ case kEmpty_Type:
+ return false;
+ default:
+ SkDEBUGFAIL("Unexpected type.");
+ return false;
+ }
+ }
+
+ /**
+ * Is the clip shape inverse filled.
+ */
+ bool isInverseFilled() const {
+ return kPath_Type == fType && fPath.isInverseFillType();
+ }
+
+ private:
+ friend class SkClipStack;
+
+ SkPath fPath;
+ SkRect fRect;
+ int fSaveCount; // save count of stack when this element was added.
+ SkRegion::Op fOp;
+ Type fType;
+ bool fDoAA;
+
+ /* fFiniteBoundType and fFiniteBound are used to incrementally update the clip stack's
+ bound. When fFiniteBoundType is kNormal_BoundsType, fFiniteBound represents the
+ conservative bounding box of the pixels that aren't clipped (i.e., any pixels that can be
+ drawn to are inside the bound). When fFiniteBoundType is kInsideOut_BoundsType (which
+ occurs when a clip is inverse filled), fFiniteBound represents the conservative bounding
+ box of the pixels that _are_ clipped (i.e., any pixels that cannot be drawn to are inside
+ the bound). When fFiniteBoundType is kInsideOut_BoundsType the actual bound is the
+ infinite plane. This behavior of fFiniteBoundType and fFiniteBound is required so that we
+ can capture the cancelling out of the extensions to infinity when two inverse filled
+ clips are Booleaned together. */
+ SkClipStack::BoundsType fFiniteBoundType;
+ SkRect fFiniteBound;
+
+ // When element is applied to the previous elements in the stack is the result known to be
+ // equivalent to a single rect intersection? IIOW, is the clip effectively a rectangle.
+ bool fIsIntersectionOfRects;
+
+ int fGenID;
+
+ Element(int saveCount) {
+ this->initCommon(saveCount, SkRegion::kReplace_Op, false);
+ this->setEmpty();
+ }
+
+ Element(int saveCount, const SkRect& rect, SkRegion::Op op, bool doAA) {
+ this->initRect(saveCount, rect, op, doAA);
+ }
+
+ Element(int saveCount, const SkPath& path, SkRegion::Op op, bool doAA) {
+ this->initPath(saveCount, path, op, doAA);
+ }
+
+ void initCommon(int saveCount, SkRegion::Op op, bool doAA) {
+ fSaveCount = saveCount;
+ fOp = op;
+ fDoAA = doAA;
+ // A default of inside-out and empty bounds means the bounds are effectively void as it
+ // indicates that nothing is known to be outside the clip.
+ fFiniteBoundType = kInsideOut_BoundsType;
+ fFiniteBound.setEmpty();
+ fIsIntersectionOfRects = false;
+ fGenID = kInvalidGenID;
+ }
+
+ void initRect(int saveCount, const SkRect& rect, SkRegion::Op op, bool doAA) {
+ fRect = rect;
+ fType = kRect_Type;
+ this->initCommon(saveCount, op, doAA);
+ }
+
+ void initPath(int saveCount, const SkPath& path, SkRegion::Op op, bool doAA) {
+ fPath = path;
+ fType = kPath_Type;
+ this->initCommon(saveCount, op, doAA);
+ }
+
+ void setEmpty() {
+ fType = kEmpty_Type;
+ fFiniteBound.setEmpty();
+ fFiniteBoundType = kNormal_BoundsType;
+ fIsIntersectionOfRects = false;
+ fRect.setEmpty();
+ fPath.reset();
+ fGenID = kEmptyGenID;
+ }
+
+ // All Element methods below are only used within SkClipStack.cpp
+ inline void checkEmpty() const;
+ inline bool canBeIntersectedInPlace(int saveCount, SkRegion::Op op) const;
+ /* This method checks to see if two rect clips can be safely merged into one. The issue here
+ is that to be strictly correct all the edges of the resulting rect must have the same
+ anti-aliasing. */
+ bool rectRectIntersectAllowed(const SkRect& newR, bool newAA) const;
+ /** Determines possible finite bounds for the Element given the previous element of the
+ stack */
+ void updateBoundAndGenID(const Element* prior);
+ // The different combination of fill & inverse fill when combining bounding boxes
+ enum FillCombo {
+ kPrev_Cur_FillCombo,
+ kPrev_InvCur_FillCombo,
+ kInvPrev_Cur_FillCombo,
+ kInvPrev_InvCur_FillCombo
+ };
+ // per-set operation functions used by updateBoundAndGenID().
+ inline void combineBoundsDiff(FillCombo combination, const SkRect& prevFinite);
+ inline void combineBoundsXOR(int combination, const SkRect& prevFinite);
+ inline void combineBoundsUnion(int combination, const SkRect& prevFinite);
+ inline void combineBoundsIntersection(int combination, const SkRect& prevFinite);
+ inline void combineBoundsRevDiff(int combination, const SkRect& prevFinite);
+ };
+
+ SkClipStack();
+ SkClipStack(const SkClipStack& b);
+ explicit SkClipStack(const SkRect& r);
+ explicit SkClipStack(const SkIRect& r);
+ ~SkClipStack();
+
+ SkClipStack& operator=(const SkClipStack& b);
+ bool operator==(const SkClipStack& b) const;
+ bool operator!=(const SkClipStack& b) const { return !(*this == b); }
+
+ void reset();
+
+ int getSaveCount() const { return fSaveCount; }
+ void save();
+ void restore();
+
+ /**
+ * getBounds places the current finite bound in its first parameter. In its
+ * second, it indicates which kind of bound is being returned. If
+ * 'canvFiniteBound' is a normal bounding box then it encloses all writeable
+ * pixels. If 'canvFiniteBound' is an inside out bounding box then it
+ * encloses all the un-writeable pixels and the true/normal bound is the
+ * infinite plane. isIntersectionOfRects is an optional parameter
+ * that is true if 'canvFiniteBound' resulted from an intersection of rects.
+ */
+ void getBounds(SkRect* canvFiniteBound,
+ BoundsType* boundType,
+ bool* isIntersectionOfRects = NULL) const;
+
+ /**
+ * Takes an input rect in device space and conservatively clips it to the
+ * clip-stack. If false is returned then the rect does not intersect the
+ * clip and is unmodified.
+ */
+ bool intersectRectWithClip(SkRect* devRect) const;
+
+ /**
+ * Returns true if the input rect in device space is entirely contained
+ * by the clip. A return value of false does not guarantee that the rect
+ * is not contained by the clip.
+ */
+ bool quickContains(const SkRect& devRect) const;
+
+ void clipDevRect(const SkIRect& ir, SkRegion::Op op) {
+ SkRect r;
+ r.set(ir);
+ this->clipDevRect(r, op, false);
+ }
+ void clipDevRect(const SkRect&, SkRegion::Op, bool doAA);
+ void clipDevPath(const SkPath&, SkRegion::Op, bool doAA);
+ // An optimized version of clipDevRect(emptyRect, kIntersect, ...)
+ void clipEmpty();
+
+ /**
+ * isWideOpen returns true if the clip state corresponds to the infinite
+ * plane (i.e., draws are not limited at all)
+ */
+ bool isWideOpen() const;
+
+ /**
+ * Add a callback function that will be called whenever a clip state
+ * is no longer viable. This will occur whenever restore
+ * is called or when a clipDevRect or clipDevPath call updates the
+ * clip within an existing save/restore state. Each clip state is
+ * represented by a unique generation ID.
+ */
+ typedef void (*PFPurgeClipCB)(int genID, void* data);
+ void addPurgeClipCallback(PFPurgeClipCB callback, void* data) const;
+
+ /**
+ * Remove a callback added earlier via addPurgeClipCallback
+ */
+ void removePurgeClipCallback(PFPurgeClipCB callback, void* data) const;
+
+ /**
+ * The generation ID has three reserved values to indicate special
+ * (potentially ignorable) cases
+ */
+ static const int32_t kInvalidGenID = 0;
+ static const int32_t kEmptyGenID = 1; // no pixels writeable
+ static const int32_t kWideOpenGenID = 2; // all pixels writeable
+
+ int32_t getTopmostGenID() const;
+
+public:
+ class Iter {
+ public:
+ enum IterStart {
+ kBottom_IterStart = SkDeque::Iter::kFront_IterStart,
+ kTop_IterStart = SkDeque::Iter::kBack_IterStart
+ };
+
+ /**
+ * Creates an uninitialized iterator. Must be reset()
+ */
+ Iter();
+
+ Iter(const SkClipStack& stack, IterStart startLoc);
+
+ /**
+ * Return the clip element for this iterator. If next()/prev() returns NULL, then the
+ * iterator is done.
+ */
+ const Element* next();
+ const Element* prev();
+
+ /**
+ * Moves the iterator to the topmost element with the specified RegionOp and returns that
+ * element. If no clip element with that op is found, the first element is returned.
+ */
+ const Element* skipToTopmost(SkRegion::Op op);
+
+ /**
+ * Restarts the iterator on a clip stack.
+ */
+ void reset(const SkClipStack& stack, IterStart startLoc);
+
+ private:
+ const SkClipStack* fStack;
+ SkDeque::Iter fIter;
+ };
+
+ /**
+ * The B2TIter iterates from the bottom of the stack to the top.
+ * It inherits privately from Iter to prevent access to reverse iteration.
+ */
+ class B2TIter : private Iter {
+ public:
+ B2TIter() {}
+
+ /**
+ * Wrap Iter's 2 parameter ctor to force initialization to the
+ * beginning of the deque/bottom of the stack
+ */
+ B2TIter(const SkClipStack& stack)
+ : INHERITED(stack, kBottom_IterStart) {
+ }
+
+ using Iter::next;
+
+ /**
+ * Wrap Iter::reset to force initialization to the
+ * beginning of the deque/bottom of the stack
+ */
+ void reset(const SkClipStack& stack) {
+ this->INHERITED::reset(stack, kBottom_IterStart);
+ }
+
+ private:
+
+ typedef Iter INHERITED;
+ };
+
+ /**
+ * GetConservativeBounds returns a conservative bound of the current clip.
+ * Since this could be the infinite plane (if inverse fills were involved) the
+ * maxWidth and maxHeight parameters can be used to limit the returned bound
+ * to the expected drawing area. Similarly, the offsetX and offsetY parameters
+ * allow the caller to offset the returned bound to account for translated
+ * drawing areas (i.e., those resulting from a saveLayer). For finite bounds,
+ * the translation (+offsetX, +offsetY) is applied before the clamp to the
+ * maximum rectangle: [0,maxWidth) x [0,maxHeight).
+ * isIntersectionOfRects is an optional parameter that is true when
+ * 'devBounds' is the result of an intersection of rects. In this case
+ * 'devBounds' is the exact answer/clip.
+ */
+ void getConservativeBounds(int offsetX,
+ int offsetY,
+ int maxWidth,
+ int maxHeight,
+ SkRect* devBounds,
+ bool* isIntersectionOfRects = NULL) const;
+
+private:
+ friend class Iter;
+
+ SkDeque fDeque;
+ int fSaveCount;
+
+ // Generation ID for the clip stack. This is incremented for each
+ // clipDevRect and clipDevPath call. 0 is reserved to indicate an
+ // invalid ID.
+ static int32_t gGenID;
+
+ struct ClipCallbackData {
+ PFPurgeClipCB fCallback;
+ void* fData;
+
+ friend bool operator==(const ClipCallbackData& a,
+ const ClipCallbackData& b) {
+ return a.fCallback == b.fCallback && a.fData == b.fData;
+ }
+ };
+
+ mutable SkTDArray<ClipCallbackData> fCallbackData;
+
+ /**
+ * Restore the stack back to the specified save count.
+ */
+ void restoreTo(int saveCount);
+
+ /**
+ * Invoke all the purge callbacks passing in element's generation ID.
+ */
+ void purgeClip(Element* element);
+
+ /**
+ * Return the next unique generation ID.
+ */
+ static int32_t GetNextGenID();
+};
+
+#endif
diff --git a/core/SkColor.h b/core/SkColor.h
new file mode 100644
index 0000000..7faeca7
--- /dev/null
+++ b/core/SkColor.h
@@ -0,0 +1,169 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkColor_DEFINED
+#define SkColor_DEFINED
+
+#include "SkScalar.h"
+
+/** \file SkColor.h
+
+ Types and macros for colors
+*/
+
+/** 8-bit type for an alpha value. 0xFF is 100% opaque, 0x00 is 100% transparent.
+*/
+typedef uint8_t SkAlpha;
+/** 32 bit ARGB color value, not premultiplied. The color components are always in
+ a known order. This is different from SkPMColor, which has its bytes in a configuration
+ dependent order, to match the format of kARGB32 bitmaps. SkColor is the type used to
+ specify colors in SkPaint and in gradients.
+*/
+typedef uint32_t SkColor;
+
+/** Return a SkColor value from 8 bit component values
+*/
+static inline SkColor SkColorSetARGBInline(U8CPU a, U8CPU r, U8CPU g, U8CPU b)
+{
+ SkASSERT(a <= 255 && r <= 255 && g <= 255 && b <= 255);
+
+ return (a << 24) | (r << 16) | (g << 8) | (b << 0);
+}
+
+#define SkColorSetARGBMacro(a, r, g, b) \
+ static_cast<SkColor>( \
+ (static_cast<U8CPU>(a) << 24) | \
+ (static_cast<U8CPU>(r) << 16) | \
+ (static_cast<U8CPU>(g) << 8) | \
+ (static_cast<U8CPU>(b) << 0))
+
+/** gcc will generate static initializers for code of this form:
+ * static const SkColor kMyColor = SkColorSetARGB(0xFF, 0x01, 0x02, 0x03)
+ * if SkColorSetARGB() is a static inline, but not if it's a macro.
+ */
+#if defined(NDEBUG)
+#define SkColorSetARGB(a, r, g, b) SkColorSetARGBMacro(a, r, g, b)
+#else
+#define SkColorSetARGB(a, r, g, b) SkColorSetARGBInline(a, r, g, b)
+#endif
+
+/** Return a SkColor value from 8 bit component values, with an implied value
+ of 0xFF for alpha (fully opaque)
+*/
+#define SkColorSetRGB(r, g, b) SkColorSetARGB(0xFF, r, g, b)
+
+/** return the alpha byte from a SkColor value */
+#define SkColorGetA(color) (((color) >> 24) & 0xFF)
+/** return the red byte from a SkColor value */
+#define SkColorGetR(color) (((color) >> 16) & 0xFF)
+/** return the green byte from a SkColor value */
+#define SkColorGetG(color) (((color) >> 8) & 0xFF)
+/** return the blue byte from a SkColor value */
+#define SkColorGetB(color) (((color) >> 0) & 0xFF)
+
+static inline SkColor SkColorSetA(SkColor c, U8CPU a) {
+ return (c & 0x00FFFFFF) | (a << 24);
+}
+
+// common colors
+
+#define SK_AlphaTRANSPARENT 0x00 //!< transparent SkAlpha value
+#define SK_AlphaOPAQUE 0xFF //!< opaque SkAlpha value
+
+#define SK_ColorTRANSPARENT 0x00000000 //!< transparent SkColor value
+
+#define SK_ColorBLACK 0xFF000000 //!< black SkColor value
+#define SK_ColorDKGRAY 0xFF444444 //!< dark gray SkColor value
+#define SK_ColorGRAY 0xFF888888 //!< gray SkColor value
+#define SK_ColorLTGRAY 0xFFCCCCCC //!< light gray SkColor value
+#define SK_ColorWHITE 0xFFFFFFFF //!< white SkColor value
+
+#define SK_ColorRED 0xFFFF0000 //!< red SkColor value
+#define SK_ColorGREEN 0xFF00FF00 //!< green SkColor value
+#define SK_ColorBLUE 0xFF0000FF //!< blue SkColor value
+#define SK_ColorYELLOW 0xFFFFFF00 //!< yellow SkColor value
+#define SK_ColorCYAN 0xFF00FFFF //!< cyan SkColor value
+#define SK_ColorMAGENTA 0xFFFF00FF //!< magenta SkColor value
+
+////////////////////////////////////////////////////////////////////////
+
+/** Convert RGB components to HSV.
+ hsv[0] is Hue [0 .. 360)
+ hsv[1] is Saturation [0...1]
+ hsv[2] is Value [0...1]
+ @param red red component value [0..255]
+ @param green green component value [0..255]
+ @param blue blue component value [0..255]
+ @param hsv 3 element array which holds the resulting HSV components.
+*/
+SK_API void SkRGBToHSV(U8CPU red, U8CPU green, U8CPU blue, SkScalar hsv[3]);
+
+/** Convert the argb color to its HSV components.
+ hsv[0] is Hue [0 .. 360)
+ hsv[1] is Saturation [0...1]
+ hsv[2] is Value [0...1]
+ @param color the argb color to convert. Note: the alpha component is ignored.
+ @param hsv 3 element array which holds the resulting HSV components.
+*/
+static inline void SkColorToHSV(SkColor color, SkScalar hsv[3])
+{
+ SkRGBToHSV(SkColorGetR(color), SkColorGetG(color), SkColorGetB(color), hsv);
+}
+
+/** Convert HSV components to an ARGB color. The alpha component is passed through unchanged.
+ hsv[0] is Hue [0 .. 360)
+ hsv[1] is Saturation [0...1]
+ hsv[2] is Value [0...1]
+ If hsv values are out of range, they are pinned.
+ @param alpha the alpha component of the returned argb color.
+ @param hsv 3 element array which holds the input HSV components.
+ @return the resulting argb color
+*/
+SK_API SkColor SkHSVToColor(U8CPU alpha, const SkScalar hsv[3]);
+
+/** Convert HSV components to an ARGB color. The alpha component set to 0xFF.
+ hsv[0] is Hue [0 .. 360)
+ hsv[1] is Saturation [0...1]
+ hsv[2] is Value [0...1]
+ If hsv values are out of range, they are pinned.
+ @param hsv 3 element array which holds the input HSV components.
+ @return the resulting argb color
+*/
+static inline SkColor SkHSVToColor(const SkScalar hsv[3])
+{
+ return SkHSVToColor(0xFF, hsv);
+}
+
+////////////////////////////////////////////////////////////////////////
+
+/** 32 bit ARGB color value, premultiplied. The byte order for this value is
+ configuration dependent, matching the format of kARGB32 bitmaps. This is different
+ from SkColor, which is nonpremultiplied, and is always in the same byte order.
+*/
+typedef uint32_t SkPMColor;
+
+/** Return a SkPMColor value from unpremultiplied 8 bit component values
+*/
+SK_API SkPMColor SkPreMultiplyARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b);
+/** Return a SkPMColor value from a SkColor value. This is done by multiplying the color
+ components by the color's alpha, and by arranging the bytes in a configuration
+ dependent order, to match the format of kARGB32 bitmaps.
+*/
+SK_API SkPMColor SkPreMultiplyColor(SkColor c);
+
+/** Define a function pointer type for combining two premultiplied colors
+*/
+typedef SkPMColor (*SkXfermodeProc)(SkPMColor src, SkPMColor dst);
+
+/** Define a function pointer type for combining a premultiplied src color
+ and a 16bit device color.
+*/
+typedef uint16_t (*SkXfermodeProc16)(SkPMColor src, uint16_t dst);
+
+#endif
diff --git a/core/SkColorFilter.h b/core/SkColorFilter.h
new file mode 100644
index 0000000..6359563
--- /dev/null
+++ b/core/SkColorFilter.h
@@ -0,0 +1,134 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkColorFilter_DEFINED
+#define SkColorFilter_DEFINED
+
+#include "SkColor.h"
+#include "SkFlattenable.h"
+#include "SkXfermode.h"
+
+class SkBitmap;
+class GrEffectRef;
+class GrContext;
+
+class SK_API SkColorFilter : public SkFlattenable {
+public:
+ SK_DECLARE_INST_COUNT(SkColorFilter)
+
+ /**
+ * If the filter can be represented by a source color plus Mode, this
+ * returns true, and sets (if not NULL) the color and mode appropriately.
+ * If not, this returns false and ignores the parameters.
+ */
+ virtual bool asColorMode(SkColor* color, SkXfermode::Mode* mode) const;
+
+ /**
+ * If the filter can be represented by a 5x4 matrix, this
+ * returns true, and sets the matrix appropriately.
+ * If not, this returns false and ignores the parameter.
+ */
+ virtual bool asColorMatrix(SkScalar matrix[20]) const;
+
+ /**
+ * If the filter can be represented by per-component table, return true,
+ * and if table is not null, copy the bitmap containing the table into it.
+ *
+ * The table bitmap will be in SkBitmap::kA8_Config. Each row corresponding
+ * to each component in ARGB order. e.g. row[0] == alpha, row[1] == red,
+ * etc. To transform a color, you (logically) perform the following:
+ *
+ * a' = *table.getAddr8(a, 0);
+ * r' = *table.getAddr8(r, 1);
+ * g' = *table.getAddr8(g, 2);
+ * b' = *table.getAddr8(b, 3);
+ *
+ * The original component value is the horizontal index for a given row,
+ * and the stored value at that index is the new value for that component.
+ */
+ virtual bool asComponentTable(SkBitmap* table) const;
+
+ /** Called with a scanline of colors, as if there was a shader installed.
+ The implementation writes out its filtered version into result[].
+ Note: shader and result may be the same buffer.
+ @param src array of colors, possibly generated by a shader
+ @param count the number of entries in the src[] and result[] arrays
+ @param result written by the filter
+ */
+ virtual void filterSpan(const SkPMColor src[], int count,
+ SkPMColor result[]) const = 0;
+ /** Called with a scanline of colors, as if there was a shader installed.
+ The implementation writes out its filtered version into result[].
+ Note: shader and result may be the same buffer.
+ @param src array of colors, possibly generated by a shader
+ @param count the number of entries in the src[] and result[] arrays
+ @param result written by the filter
+ */
+ virtual void filterSpan16(const uint16_t shader[], int count,
+ uint16_t result[]) const;
+
+ enum Flags {
+ /** If set the filter methods will not change the alpha channel of the
+ colors.
+ */
+ kAlphaUnchanged_Flag = 0x01,
+ /** If set, this subclass implements filterSpan16(). If this flag is
+ set, then kAlphaUnchanged_Flag must also be set.
+ */
+ kHasFilter16_Flag = 0x02
+ };
+
+ /** Returns the flags for this filter. Override in subclasses to return
+ custom flags.
+ */
+ virtual uint32_t getFlags() const { return 0; }
+
+ /**
+ * Apply this colorfilter to the specified SkColor. This routine handles
+ * converting to SkPMColor, calling the filter, and then converting back
+ * to SkColor. This method is not virtual, but will call filterSpan()
+ * which is virtual.
+ */
+ SkColor filterColor(SkColor) const;
+
+ /** Create a colorfilter that uses the specified color and mode.
+ If the Mode is DST, this function will return NULL (since that
+ mode will have no effect on the result).
+ @param c The source color used with the specified mode
+ @param mode The xfermode mode that is applied to each color in
+ the colorfilter's filterSpan[16,32] methods
+ @return colorfilter object that applies the src color and mode,
+ or NULL if the mode will have no effect.
+ */
+ static SkColorFilter* CreateModeFilter(SkColor c, SkXfermode::Mode mode);
+
+ /** Create a colorfilter that multiplies the RGB channels by one color, and
+ then adds a second color, pinning the result for each component to
+ [0..255]. The alpha components of the mul and add arguments
+ are ignored.
+ */
+ static SkColorFilter* CreateLightingFilter(SkColor mul, SkColor add);
+
+ /** A subclass may implement this factory function to work with the GPU backend. If the return
+ is non-NULL then the caller owns a ref on the returned object.
+ */
+ virtual GrEffectRef* asNewEffect(GrContext*) const;
+
+ SkDEVCODE(virtual void toString(SkString* str) const = 0;)
+
+ SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP()
+protected:
+ SkColorFilter() {}
+ SkColorFilter(SkFlattenableReadBuffer& rb) : INHERITED(rb) {}
+
+private:
+ typedef SkFlattenable INHERITED;
+};
+
+#endif
diff --git a/core/SkColorPriv.h b/core/SkColorPriv.h
new file mode 100644
index 0000000..fe4377f
--- /dev/null
+++ b/core/SkColorPriv.h
@@ -0,0 +1,867 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkColorPriv_DEFINED
+#define SkColorPriv_DEFINED
+
+// turn this own for extra debug checking when blending onto 565
+#ifdef SK_DEBUG
+ #define CHECK_FOR_565_OVERFLOW
+#endif
+
+#include "SkColor.h"
+#include "SkMath.h"
+
+///@{
+/** See ITU-R Recommendation BT.709 at http://www.itu.int/rec/R-REC-BT.709/ .*/
+#define SK_ITU_BT709_LUM_COEFF_R (0.2126f)
+#define SK_ITU_BT709_LUM_COEFF_G (0.7152f)
+#define SK_ITU_BT709_LUM_COEFF_B (0.0722f)
+///@}
+
+///@{
+/** A float value which specifies this channel's contribution to luminance. */
+#define SK_LUM_COEFF_R SK_ITU_BT709_LUM_COEFF_R
+#define SK_LUM_COEFF_G SK_ITU_BT709_LUM_COEFF_G
+#define SK_LUM_COEFF_B SK_ITU_BT709_LUM_COEFF_B
+///@}
+
+/** Computes the luminance from the given r, g, and b in accordance with
+ SK_LUM_COEFF_X. For correct results, r, g, and b should be in linear space.
+*/
+static inline U8CPU SkComputeLuminance(U8CPU r, U8CPU g, U8CPU b) {
+ //The following is
+ //r * SK_LUM_COEFF_R + g * SK_LUM_COEFF_G + b * SK_LUM_COEFF_B
+ //with SK_LUM_COEFF_X in 1.8 fixed point (rounding adjusted to sum to 256).
+ return (r * 54 + g * 183 + b * 19) >> 8;
+}
+
+/** Turn 0..255 into 0..256 by adding 1 at the half-way point. Used to turn a
+ byte into a scale value, so that we can say scale * value >> 8 instead of
+ alpha * value / 255.
+
+ In debugging, asserts that alpha is 0..255
+*/
+static inline unsigned SkAlpha255To256(U8CPU alpha) {
+ SkASSERT(SkToU8(alpha) == alpha);
+ // this one assues that blending on top of an opaque dst keeps it that way
+ // even though it is less accurate than a+(a>>7) for non-opaque dsts
+ return alpha + 1;
+}
+
+/** Multiplify value by 0..256, and shift the result down 8
+ (i.e. return (value * alpha256) >> 8)
+ */
+#define SkAlphaMul(value, alpha256) (SkMulS16(value, alpha256) >> 8)
+
+// The caller may want negative values, so keep all params signed (int)
+// so we don't accidentally slip into unsigned math and lose the sign
+// extension when we shift (in SkAlphaMul)
+static inline int SkAlphaBlend(int src, int dst, int scale256) {
+ SkASSERT((unsigned)scale256 <= 256);
+ return dst + SkAlphaMul(src - dst, scale256);
+}
+
+/**
+ * Returns (src * alpha + dst * (255 - alpha)) / 255
+ *
+ * This is more accurate than SkAlphaBlend, but slightly slower
+ */
+static inline int SkAlphaBlend255(S16CPU src, S16CPU dst, U8CPU alpha) {
+ SkASSERT((int16_t)src == src);
+ SkASSERT((int16_t)dst == dst);
+ SkASSERT((uint8_t)alpha == alpha);
+
+ int prod = SkMulS16(src - dst, alpha) + 128;
+ prod = (prod + (prod >> 8)) >> 8;
+ return dst + prod;
+}
+
+#define SK_R16_BITS 5
+#define SK_G16_BITS 6
+#define SK_B16_BITS 5
+
+#define SK_R16_SHIFT (SK_B16_BITS + SK_G16_BITS)
+#define SK_G16_SHIFT (SK_B16_BITS)
+#define SK_B16_SHIFT 0
+
+#define SK_R16_MASK ((1 << SK_R16_BITS) - 1)
+#define SK_G16_MASK ((1 << SK_G16_BITS) - 1)
+#define SK_B16_MASK ((1 << SK_B16_BITS) - 1)
+
+#define SkGetPackedR16(color) (((unsigned)(color) >> SK_R16_SHIFT) & SK_R16_MASK)
+#define SkGetPackedG16(color) (((unsigned)(color) >> SK_G16_SHIFT) & SK_G16_MASK)
+#define SkGetPackedB16(color) (((unsigned)(color) >> SK_B16_SHIFT) & SK_B16_MASK)
+
+#define SkR16Assert(r) SkASSERT((unsigned)(r) <= SK_R16_MASK)
+#define SkG16Assert(g) SkASSERT((unsigned)(g) <= SK_G16_MASK)
+#define SkB16Assert(b) SkASSERT((unsigned)(b) <= SK_B16_MASK)
+
+static inline uint16_t SkPackRGB16(unsigned r, unsigned g, unsigned b) {
+ SkASSERT(r <= SK_R16_MASK);
+ SkASSERT(g <= SK_G16_MASK);
+ SkASSERT(b <= SK_B16_MASK);
+
+ return SkToU16((r << SK_R16_SHIFT) | (g << SK_G16_SHIFT) | (b << SK_B16_SHIFT));
+}
+
+#define SK_R16_MASK_IN_PLACE (SK_R16_MASK << SK_R16_SHIFT)
+#define SK_G16_MASK_IN_PLACE (SK_G16_MASK << SK_G16_SHIFT)
+#define SK_B16_MASK_IN_PLACE (SK_B16_MASK << SK_B16_SHIFT)
+
+/** Expand the 16bit color into a 32bit value that can be scaled all at once
+ by a value up to 32. Used in conjunction with SkCompact_rgb_16.
+*/
+static inline uint32_t SkExpand_rgb_16(U16CPU c) {
+ SkASSERT(c == (uint16_t)c);
+
+ return ((c & SK_G16_MASK_IN_PLACE) << 16) | (c & ~SK_G16_MASK_IN_PLACE);
+}
+
+/** Compress an expanded value (from SkExpand_rgb_16) back down to a 16bit
+ color value. The computation yields only 16bits of valid data, but we claim
+ to return 32bits, so that the compiler won't generate extra instructions to
+ "clean" the top 16bits. However, the top 16 can contain garbage, so it is
+ up to the caller to safely ignore them.
+*/
+static inline U16CPU SkCompact_rgb_16(uint32_t c) {
+ return ((c >> 16) & SK_G16_MASK_IN_PLACE) | (c & ~SK_G16_MASK_IN_PLACE);
+}
+
+/** Scale the 16bit color value by the 0..256 scale parameter.
+ The computation yields only 16bits of valid data, but we claim
+ to return 32bits, so that the compiler won't generate extra instructions to
+ "clean" the top 16bits.
+*/
+static inline U16CPU SkAlphaMulRGB16(U16CPU c, unsigned scale) {
+ return SkCompact_rgb_16(SkExpand_rgb_16(c) * (scale >> 3) >> 5);
+}
+
+// this helper explicitly returns a clean 16bit value (but slower)
+#define SkAlphaMulRGB16_ToU16(c, s) (uint16_t)SkAlphaMulRGB16(c, s)
+
+/** Blend src and dst 16bit colors by the 0..256 scale parameter.
+ The computation yields only 16bits of valid data, but we claim
+ to return 32bits, so that the compiler won't generate extra instructions to
+ "clean" the top 16bits.
+*/
+static inline U16CPU SkBlendRGB16(U16CPU src, U16CPU dst, int srcScale) {
+ SkASSERT((unsigned)srcScale <= 256);
+
+ srcScale >>= 3;
+
+ uint32_t src32 = SkExpand_rgb_16(src);
+ uint32_t dst32 = SkExpand_rgb_16(dst);
+ return SkCompact_rgb_16(dst32 + ((src32 - dst32) * srcScale >> 5));
+}
+
+static inline void SkBlendRGB16(const uint16_t src[], uint16_t dst[],
+ int srcScale, int count) {
+ SkASSERT(count > 0);
+ SkASSERT((unsigned)srcScale <= 256);
+
+ srcScale >>= 3;
+
+ do {
+ uint32_t src32 = SkExpand_rgb_16(*src++);
+ uint32_t dst32 = SkExpand_rgb_16(*dst);
+ *dst++ = SkCompact_rgb_16(dst32 + ((src32 - dst32) * srcScale >> 5));
+ } while (--count > 0);
+}
+
+#ifdef SK_DEBUG
+ static inline U16CPU SkRGB16Add(U16CPU a, U16CPU b) {
+ SkASSERT(SkGetPackedR16(a) + SkGetPackedR16(b) <= SK_R16_MASK);
+ SkASSERT(SkGetPackedG16(a) + SkGetPackedG16(b) <= SK_G16_MASK);
+ SkASSERT(SkGetPackedB16(a) + SkGetPackedB16(b) <= SK_B16_MASK);
+
+ return a + b;
+ }
+#else
+ #define SkRGB16Add(a, b) ((a) + (b))
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+
+#define SK_A32_BITS 8
+#define SK_R32_BITS 8
+#define SK_G32_BITS 8
+#define SK_B32_BITS 8
+
+#define SK_A32_MASK ((1 << SK_A32_BITS) - 1)
+#define SK_R32_MASK ((1 << SK_R32_BITS) - 1)
+#define SK_G32_MASK ((1 << SK_G32_BITS) - 1)
+#define SK_B32_MASK ((1 << SK_B32_BITS) - 1)
+
+#define SkGetPackedA32(packed) ((uint32_t)((packed) << (24 - SK_A32_SHIFT)) >> 24)
+#define SkGetPackedR32(packed) ((uint32_t)((packed) << (24 - SK_R32_SHIFT)) >> 24)
+#define SkGetPackedG32(packed) ((uint32_t)((packed) << (24 - SK_G32_SHIFT)) >> 24)
+#define SkGetPackedB32(packed) ((uint32_t)((packed) << (24 - SK_B32_SHIFT)) >> 24)
+
+#define SkA32Assert(a) SkASSERT((unsigned)(a) <= SK_A32_MASK)
+#define SkR32Assert(r) SkASSERT((unsigned)(r) <= SK_R32_MASK)
+#define SkG32Assert(g) SkASSERT((unsigned)(g) <= SK_G32_MASK)
+#define SkB32Assert(b) SkASSERT((unsigned)(b) <= SK_B32_MASK)
+
+#ifdef SK_DEBUG
+ static inline void SkPMColorAssert(SkPMColor c) {
+ unsigned a = SkGetPackedA32(c);
+ unsigned r = SkGetPackedR32(c);
+ unsigned g = SkGetPackedG32(c);
+ unsigned b = SkGetPackedB32(c);
+
+ SkA32Assert(a);
+ SkASSERT(r <= a);
+ SkASSERT(g <= a);
+ SkASSERT(b <= a);
+ }
+#else
+ #define SkPMColorAssert(c)
+#endif
+
+/**
+ * Pack the components into a SkPMColor, checking (in the debug version) that
+ * the components are 0..255, and are already premultiplied (i.e. alpha >= color)
+ */
+static inline SkPMColor SkPackARGB32(U8CPU a, U8CPU r, U8CPU g, U8CPU b) {
+ SkA32Assert(a);
+ SkASSERT(r <= a);
+ SkASSERT(g <= a);
+ SkASSERT(b <= a);
+
+ return (a << SK_A32_SHIFT) | (r << SK_R32_SHIFT) |
+ (g << SK_G32_SHIFT) | (b << SK_B32_SHIFT);
+}
+
+/**
+ * Abstract 4-byte interpolation, implemented on top of SkPMColor
+ * utility functions. Third parameter controls blending of the first two:
+ * (src, dst, 0) returns dst
+ * (src, dst, 0xFF) returns src
+ * srcWeight is [0..256], unlike SkFourByteInterp which takes [0..255]
+ */
+static inline SkPMColor SkFourByteInterp256(SkPMColor src, SkPMColor dst,
+ unsigned scale) {
+ unsigned a = SkAlphaBlend(SkGetPackedA32(src), SkGetPackedA32(dst), scale);
+ unsigned r = SkAlphaBlend(SkGetPackedR32(src), SkGetPackedR32(dst), scale);
+ unsigned g = SkAlphaBlend(SkGetPackedG32(src), SkGetPackedG32(dst), scale);
+ unsigned b = SkAlphaBlend(SkGetPackedB32(src), SkGetPackedB32(dst), scale);
+
+ return SkPackARGB32(a, r, g, b);
+}
+
+/**
+ * Abstract 4-byte interpolation, implemented on top of SkPMColor
+ * utility functions. Third parameter controls blending of the first two:
+ * (src, dst, 0) returns dst
+ * (src, dst, 0xFF) returns src
+ */
+static inline SkPMColor SkFourByteInterp(SkPMColor src, SkPMColor dst,
+ U8CPU srcWeight) {
+ unsigned scale = SkAlpha255To256(srcWeight);
+ return SkFourByteInterp256(src, dst, scale);
+}
+
+/**
+ * 32b optimized version; currently appears to be 10% faster even on 64b
+ * architectures than an equivalent 64b version and 30% faster than
+ * SkFourByteInterp(). Third parameter controls blending of the first two:
+ * (src, dst, 0) returns dst
+ * (src, dst, 256) returns src
+ * ** Does not match the results of SkFourByteInterp256() because we use
+ * a more accurate scale computation!
+ * TODO: migrate Skia function to using an accurate 255->266 alpha
+ * conversion.
+ */
+static inline SkPMColor SkFastFourByteInterp256(SkPMColor src,
+ SkPMColor dst,
+ unsigned scale) {
+ SkASSERT(scale <= 256);
+
+ // Reorders ARGB to AG-RB in order to reduce the number of operations.
+ const uint32_t mask = 0xFF00FF;
+ uint32_t src_rb = src & mask;
+ uint32_t src_ag = (src >> 8) & mask;
+ uint32_t dst_rb = dst & mask;
+ uint32_t dst_ag = (dst >> 8) & mask;
+
+ uint32_t ret_rb = src_rb * scale + (256 - scale) * dst_rb;
+ uint32_t ret_ag = src_ag * scale + (256 - scale) * dst_ag;
+
+ return (ret_ag & ~mask) | ((ret_rb & ~mask) >> 8);
+}
+
+static inline SkPMColor SkFastFourByteInterp(SkPMColor src,
+ SkPMColor dst,
+ U8CPU srcWeight) {
+ SkASSERT(srcWeight <= 255);
+ // scale = srcWeight + (srcWeight >> 7) is more accurate than
+ // scale = srcWeight + 1, but 7% slower
+ return SkFastFourByteInterp256(src, dst, srcWeight + (srcWeight >> 7));
+}
+
+/**
+ * Same as SkPackARGB32, but this version guarantees to not check that the
+ * values are premultiplied in the debug version.
+ */
+static inline SkPMColor SkPackARGB32NoCheck(U8CPU a, U8CPU r, U8CPU g, U8CPU b) {
+ return (a << SK_A32_SHIFT) | (r << SK_R32_SHIFT) |
+ (g << SK_G32_SHIFT) | (b << SK_B32_SHIFT);
+}
+
+static inline
+SkPMColor SkPremultiplyARGBInline(U8CPU a, U8CPU r, U8CPU g, U8CPU b) {
+ SkA32Assert(a);
+ SkR32Assert(r);
+ SkG32Assert(g);
+ SkB32Assert(b);
+
+ if (a != 255) {
+ r = SkMulDiv255Round(r, a);
+ g = SkMulDiv255Round(g, a);
+ b = SkMulDiv255Round(b, a);
+ }
+ return SkPackARGB32(a, r, g, b);
+}
+
+SK_API extern const uint32_t gMask_00FF00FF;
+
+static inline uint32_t SkAlphaMulQ(uint32_t c, unsigned scale) {
+ uint32_t mask = gMask_00FF00FF;
+
+ uint32_t rb = ((c & mask) * scale) >> 8;
+ uint32_t ag = ((c >> 8) & mask) * scale;
+ return (rb & mask) | (ag & ~mask);
+}
+
+static inline SkPMColor SkPMSrcOver(SkPMColor src, SkPMColor dst) {
+ return src + SkAlphaMulQ(dst, SkAlpha255To256(255 - SkGetPackedA32(src)));
+}
+
+static inline SkPMColor SkBlendARGB32(SkPMColor src, SkPMColor dst, U8CPU aa) {
+ SkASSERT((unsigned)aa <= 255);
+
+ unsigned src_scale = SkAlpha255To256(aa);
+ unsigned dst_scale = SkAlpha255To256(255 - SkAlphaMul(SkGetPackedA32(src), src_scale));
+
+ return SkAlphaMulQ(src, src_scale) + SkAlphaMulQ(dst, dst_scale);
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////
+// Convert a 32bit pixel to a 16bit pixel (no dither)
+
+#define SkR32ToR16_MACRO(r) ((unsigned)(r) >> (SK_R32_BITS - SK_R16_BITS))
+#define SkG32ToG16_MACRO(g) ((unsigned)(g) >> (SK_G32_BITS - SK_G16_BITS))
+#define SkB32ToB16_MACRO(b) ((unsigned)(b) >> (SK_B32_BITS - SK_B16_BITS))
+
+#ifdef SK_DEBUG
+ static inline unsigned SkR32ToR16(unsigned r) {
+ SkR32Assert(r);
+ return SkR32ToR16_MACRO(r);
+ }
+ static inline unsigned SkG32ToG16(unsigned g) {
+ SkG32Assert(g);
+ return SkG32ToG16_MACRO(g);
+ }
+ static inline unsigned SkB32ToB16(unsigned b) {
+ SkB32Assert(b);
+ return SkB32ToB16_MACRO(b);
+ }
+#else
+ #define SkR32ToR16(r) SkR32ToR16_MACRO(r)
+ #define SkG32ToG16(g) SkG32ToG16_MACRO(g)
+ #define SkB32ToB16(b) SkB32ToB16_MACRO(b)
+#endif
+
+#define SkPacked32ToR16(c) (((unsigned)(c) >> (SK_R32_SHIFT + SK_R32_BITS - SK_R16_BITS)) & SK_R16_MASK)
+#define SkPacked32ToG16(c) (((unsigned)(c) >> (SK_G32_SHIFT + SK_G32_BITS - SK_G16_BITS)) & SK_G16_MASK)
+#define SkPacked32ToB16(c) (((unsigned)(c) >> (SK_B32_SHIFT + SK_B32_BITS - SK_B16_BITS)) & SK_B16_MASK)
+
+static inline U16CPU SkPixel32ToPixel16(SkPMColor c) {
+ unsigned r = ((c >> (SK_R32_SHIFT + (8 - SK_R16_BITS))) & SK_R16_MASK) << SK_R16_SHIFT;
+ unsigned g = ((c >> (SK_G32_SHIFT + (8 - SK_G16_BITS))) & SK_G16_MASK) << SK_G16_SHIFT;
+ unsigned b = ((c >> (SK_B32_SHIFT + (8 - SK_B16_BITS))) & SK_B16_MASK) << SK_B16_SHIFT;
+ return r | g | b;
+}
+
+static inline U16CPU SkPack888ToRGB16(U8CPU r, U8CPU g, U8CPU b) {
+ return (SkR32ToR16(r) << SK_R16_SHIFT) |
+ (SkG32ToG16(g) << SK_G16_SHIFT) |
+ (SkB32ToB16(b) << SK_B16_SHIFT);
+}
+
+#define SkPixel32ToPixel16_ToU16(src) SkToU16(SkPixel32ToPixel16(src))
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Fast dither from 32->16
+
+#define SkShouldDitherXY(x, y) (((x) ^ (y)) & 1)
+
+static inline uint16_t SkDitherPack888ToRGB16(U8CPU r, U8CPU g, U8CPU b) {
+ r = ((r << 1) - ((r >> (8 - SK_R16_BITS) << (8 - SK_R16_BITS)) | (r >> SK_R16_BITS))) >> (8 - SK_R16_BITS);
+ g = ((g << 1) - ((g >> (8 - SK_G16_BITS) << (8 - SK_G16_BITS)) | (g >> SK_G16_BITS))) >> (8 - SK_G16_BITS);
+ b = ((b << 1) - ((b >> (8 - SK_B16_BITS) << (8 - SK_B16_BITS)) | (b >> SK_B16_BITS))) >> (8 - SK_B16_BITS);
+
+ return SkPackRGB16(r, g, b);
+}
+
+static inline uint16_t SkDitherPixel32ToPixel16(SkPMColor c) {
+ return SkDitherPack888ToRGB16(SkGetPackedR32(c), SkGetPackedG32(c), SkGetPackedB32(c));
+}
+
+/* Return c in expanded_rgb_16 format, but also scaled up by 32 (5 bits)
+ It is now suitable for combining with a scaled expanded_rgb_16 color
+ as in SkSrcOver32To16().
+ We must do this 565 high-bit replication, in order for the subsequent add
+ to saturate properly (and not overflow). If we take the 8 bits as is, it is
+ possible to overflow.
+*/
+static inline uint32_t SkPMColorToExpanded16x5(SkPMColor c) {
+ unsigned sr = SkPacked32ToR16(c);
+ unsigned sg = SkPacked32ToG16(c);
+ unsigned sb = SkPacked32ToB16(c);
+
+ sr = (sr << 5) | sr;
+ sg = (sg << 5) | (sg >> 1);
+ sb = (sb << 5) | sb;
+ return (sr << 11) | (sg << 21) | (sb << 0);
+}
+
+/* SrcOver the 32bit src color with the 16bit dst, returning a 16bit value
+ (with dirt in the high 16bits, so caller beware).
+*/
+static inline U16CPU SkSrcOver32To16(SkPMColor src, uint16_t dst) {
+ unsigned sr = SkGetPackedR32(src);
+ unsigned sg = SkGetPackedG32(src);
+ unsigned sb = SkGetPackedB32(src);
+
+ unsigned dr = SkGetPackedR16(dst);
+ unsigned dg = SkGetPackedG16(dst);
+ unsigned db = SkGetPackedB16(dst);
+
+ unsigned isa = 255 - SkGetPackedA32(src);
+
+ dr = (sr + SkMul16ShiftRound(dr, isa, SK_R16_BITS)) >> (8 - SK_R16_BITS);
+ dg = (sg + SkMul16ShiftRound(dg, isa, SK_G16_BITS)) >> (8 - SK_G16_BITS);
+ db = (sb + SkMul16ShiftRound(db, isa, SK_B16_BITS)) >> (8 - SK_B16_BITS);
+
+ return SkPackRGB16(dr, dg, db);
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////
+// Convert a 16bit pixel to a 32bit pixel
+
+static inline unsigned SkR16ToR32(unsigned r) {
+ return (r << (8 - SK_R16_BITS)) | (r >> (2 * SK_R16_BITS - 8));
+}
+
+static inline unsigned SkG16ToG32(unsigned g) {
+ return (g << (8 - SK_G16_BITS)) | (g >> (2 * SK_G16_BITS - 8));
+}
+
+static inline unsigned SkB16ToB32(unsigned b) {
+ return (b << (8 - SK_B16_BITS)) | (b >> (2 * SK_B16_BITS - 8));
+}
+
+#define SkPacked16ToR32(c) SkR16ToR32(SkGetPackedR16(c))
+#define SkPacked16ToG32(c) SkG16ToG32(SkGetPackedG16(c))
+#define SkPacked16ToB32(c) SkB16ToB32(SkGetPackedB16(c))
+
+static inline SkPMColor SkPixel16ToPixel32(U16CPU src) {
+ SkASSERT(src == SkToU16(src));
+
+ unsigned r = SkPacked16ToR32(src);
+ unsigned g = SkPacked16ToG32(src);
+ unsigned b = SkPacked16ToB32(src);
+
+ SkASSERT((r >> (8 - SK_R16_BITS)) == SkGetPackedR16(src));
+ SkASSERT((g >> (8 - SK_G16_BITS)) == SkGetPackedG16(src));
+ SkASSERT((b >> (8 - SK_B16_BITS)) == SkGetPackedB16(src));
+
+ return SkPackARGB32(0xFF, r, g, b);
+}
+
+// similar to SkPixel16ToPixel32, but returns SkColor instead of SkPMColor
+static inline SkColor SkPixel16ToColor(U16CPU src) {
+ SkASSERT(src == SkToU16(src));
+
+ unsigned r = SkPacked16ToR32(src);
+ unsigned g = SkPacked16ToG32(src);
+ unsigned b = SkPacked16ToB32(src);
+
+ SkASSERT((r >> (8 - SK_R16_BITS)) == SkGetPackedR16(src));
+ SkASSERT((g >> (8 - SK_G16_BITS)) == SkGetPackedG16(src));
+ SkASSERT((b >> (8 - SK_B16_BITS)) == SkGetPackedB16(src));
+
+ return SkColorSetRGB(r, g, b);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+typedef uint16_t SkPMColor16;
+
+// Put in OpenGL order (r g b a)
+#define SK_A4444_SHIFT 0
+#define SK_R4444_SHIFT 12
+#define SK_G4444_SHIFT 8
+#define SK_B4444_SHIFT 4
+
+#define SkA32To4444(a) ((unsigned)(a) >> 4)
+#define SkR32To4444(r) ((unsigned)(r) >> 4)
+#define SkG32To4444(g) ((unsigned)(g) >> 4)
+#define SkB32To4444(b) ((unsigned)(b) >> 4)
+
+static inline U8CPU SkReplicateNibble(unsigned nib) {
+ SkASSERT(nib <= 0xF);
+ return (nib << 4) | nib;
+}
+
+#define SkA4444ToA32(a) SkReplicateNibble(a)
+#define SkR4444ToR32(r) SkReplicateNibble(r)
+#define SkG4444ToG32(g) SkReplicateNibble(g)
+#define SkB4444ToB32(b) SkReplicateNibble(b)
+
+#define SkGetPackedA4444(c) (((unsigned)(c) >> SK_A4444_SHIFT) & 0xF)
+#define SkGetPackedR4444(c) (((unsigned)(c) >> SK_R4444_SHIFT) & 0xF)
+#define SkGetPackedG4444(c) (((unsigned)(c) >> SK_G4444_SHIFT) & 0xF)
+#define SkGetPackedB4444(c) (((unsigned)(c) >> SK_B4444_SHIFT) & 0xF)
+
+#define SkPacked4444ToA32(c) SkReplicateNibble(SkGetPackedA4444(c))
+#define SkPacked4444ToR32(c) SkReplicateNibble(SkGetPackedR4444(c))
+#define SkPacked4444ToG32(c) SkReplicateNibble(SkGetPackedG4444(c))
+#define SkPacked4444ToB32(c) SkReplicateNibble(SkGetPackedB4444(c))
+
+#ifdef SK_DEBUG
+static inline void SkPMColor16Assert(U16CPU c) {
+ unsigned a = SkGetPackedA4444(c);
+ unsigned r = SkGetPackedR4444(c);
+ unsigned g = SkGetPackedG4444(c);
+ unsigned b = SkGetPackedB4444(c);
+
+ SkASSERT(a <= 0xF);
+ SkASSERT(r <= a);
+ SkASSERT(g <= a);
+ SkASSERT(b <= a);
+}
+#else
+#define SkPMColor16Assert(c)
+#endif
+
+static inline unsigned SkAlpha15To16(unsigned a) {
+ SkASSERT(a <= 0xF);
+ return a + (a >> 3);
+}
+
+#ifdef SK_DEBUG
+ static inline int SkAlphaMul4(int value, int scale) {
+ SkASSERT((unsigned)scale <= 0x10);
+ return value * scale >> 4;
+ }
+#else
+ #define SkAlphaMul4(value, scale) ((value) * (scale) >> 4)
+#endif
+
+static inline unsigned SkR4444ToR565(unsigned r) {
+ SkASSERT(r <= 0xF);
+ return (r << (SK_R16_BITS - 4)) | (r >> (8 - SK_R16_BITS));
+}
+
+static inline unsigned SkG4444ToG565(unsigned g) {
+ SkASSERT(g <= 0xF);
+ return (g << (SK_G16_BITS - 4)) | (g >> (8 - SK_G16_BITS));
+}
+
+static inline unsigned SkB4444ToB565(unsigned b) {
+ SkASSERT(b <= 0xF);
+ return (b << (SK_B16_BITS - 4)) | (b >> (8 - SK_B16_BITS));
+}
+
+static inline SkPMColor16 SkPackARGB4444(unsigned a, unsigned r,
+ unsigned g, unsigned b) {
+ SkASSERT(a <= 0xF);
+ SkASSERT(r <= a);
+ SkASSERT(g <= a);
+ SkASSERT(b <= a);
+
+ return (SkPMColor16)((a << SK_A4444_SHIFT) | (r << SK_R4444_SHIFT) |
+ (g << SK_G4444_SHIFT) | (b << SK_B4444_SHIFT));
+}
+
+extern const uint16_t gMask_0F0F;
+
+static inline U16CPU SkAlphaMulQ4(U16CPU c, unsigned scale) {
+ SkASSERT(scale <= 16);
+
+ const unsigned mask = 0xF0F; //gMask_0F0F;
+
+#if 0
+ unsigned rb = ((c & mask) * scale) >> 4;
+ unsigned ag = ((c >> 4) & mask) * scale;
+ return (rb & mask) | (ag & ~mask);
+#else
+ c = (c & mask) | ((c & (mask << 4)) << 12);
+ c = c * scale >> 4;
+ return (c & mask) | ((c >> 12) & (mask << 4));
+#endif
+}
+
+/** Expand the SkPMColor16 color into a 32bit value that can be scaled all at
+ once by a value up to 16. Used in conjunction with SkCompact_4444.
+*/
+static inline uint32_t SkExpand_4444(U16CPU c) {
+ SkASSERT(c == (uint16_t)c);
+
+ const unsigned mask = 0xF0F; //gMask_0F0F;
+ return (c & mask) | ((c & ~mask) << 12);
+}
+
+/** Compress an expanded value (from SkExpand_4444) back down to a SkPMColor16.
+ NOTE: this explicitly does not clean the top 16 bits (which may be garbage).
+ It does this for speed, since if it is being written directly to 16bits of
+ memory, the top 16bits will be ignored. Casting the result to uint16_t here
+ would add 2 more instructions, slow us down. It is up to the caller to
+ perform the cast if needed.
+*/
+static inline U16CPU SkCompact_4444(uint32_t c) {
+ const unsigned mask = 0xF0F; //gMask_0F0F;
+ return (c & mask) | ((c >> 12) & ~mask);
+}
+
+static inline uint16_t SkSrcOver4444To16(SkPMColor16 s, uint16_t d) {
+ unsigned sa = SkGetPackedA4444(s);
+ unsigned sr = SkR4444ToR565(SkGetPackedR4444(s));
+ unsigned sg = SkG4444ToG565(SkGetPackedG4444(s));
+ unsigned sb = SkB4444ToB565(SkGetPackedB4444(s));
+
+ // To avoid overflow, we have to clear the low bit of the synthetic sg
+ // if the src alpha is <= 7.
+ // to see why, try blending 0x4444 on top of 565-white and watch green
+ // overflow (sum == 64)
+ sg &= ~(~(sa >> 3) & 1);
+
+ unsigned scale = SkAlpha15To16(15 - sa);
+ unsigned dr = SkAlphaMul4(SkGetPackedR16(d), scale);
+ unsigned dg = SkAlphaMul4(SkGetPackedG16(d), scale);
+ unsigned db = SkAlphaMul4(SkGetPackedB16(d), scale);
+
+#if 0
+ if (sg + dg > 63) {
+ SkDebugf("---- SkSrcOver4444To16 src=%x dst=%x scale=%d, sg=%d dg=%d\n", s, d, scale, sg, dg);
+ }
+#endif
+ return SkPackRGB16(sr + dr, sg + dg, sb + db);
+}
+
+static inline uint16_t SkBlend4444To16(SkPMColor16 src, uint16_t dst, int scale16) {
+ SkASSERT((unsigned)scale16 <= 16);
+
+ return SkSrcOver4444To16(SkAlphaMulQ4(src, scale16), dst);
+}
+
+static inline uint16_t SkBlend4444(SkPMColor16 src, SkPMColor16 dst, int scale16) {
+ SkASSERT((unsigned)scale16 <= 16);
+
+ uint32_t src32 = SkExpand_4444(src) * scale16;
+ // the scaled srcAlpha is the bottom byte
+#ifdef SK_DEBUG
+ {
+ unsigned srcA = SkGetPackedA4444(src) * scale16;
+ SkASSERT(srcA == (src32 & 0xFF));
+ }
+#endif
+ unsigned dstScale = SkAlpha255To256(255 - (src32 & 0xFF)) >> 4;
+ uint32_t dst32 = SkExpand_4444(dst) * dstScale;
+ return SkCompact_4444((src32 + dst32) >> 4);
+}
+
+static inline SkPMColor SkPixel4444ToPixel32(U16CPU c) {
+ uint32_t d = (SkGetPackedA4444(c) << SK_A32_SHIFT) |
+ (SkGetPackedR4444(c) << SK_R32_SHIFT) |
+ (SkGetPackedG4444(c) << SK_G32_SHIFT) |
+ (SkGetPackedB4444(c) << SK_B32_SHIFT);
+ return d | (d << 4);
+}
+
+static inline SkPMColor16 SkPixel32ToPixel4444(SkPMColor c) {
+ return (((c >> (SK_A32_SHIFT + 4)) & 0xF) << SK_A4444_SHIFT) |
+ (((c >> (SK_R32_SHIFT + 4)) & 0xF) << SK_R4444_SHIFT) |
+ (((c >> (SK_G32_SHIFT + 4)) & 0xF) << SK_G4444_SHIFT) |
+ (((c >> (SK_B32_SHIFT + 4)) & 0xF) << SK_B4444_SHIFT);
+}
+
+// cheap 2x2 dither
+static inline SkPMColor16 SkDitherARGB32To4444(U8CPU a, U8CPU r,
+ U8CPU g, U8CPU b) {
+ // to ensure that we stay a legal premultiplied color, we take the max()
+ // of the truncated and dithered alpha values. If we didn't, cases like
+ // SkDitherARGB32To4444(0x31, 0x2E, ...) would generate SkPackARGB4444(2, 3, ...)
+ // which is not legal premultiplied, since a < color
+ unsigned dithered_a = ((a << 1) - ((a >> 4 << 4) | (a >> 4))) >> 4;
+ a = SkMax32(a >> 4, dithered_a);
+ // these we just dither in place
+ r = ((r << 1) - ((r >> 4 << 4) | (r >> 4))) >> 4;
+ g = ((g << 1) - ((g >> 4 << 4) | (g >> 4))) >> 4;
+ b = ((b << 1) - ((b >> 4 << 4) | (b >> 4))) >> 4;
+
+ return SkPackARGB4444(a, r, g, b);
+}
+
+static inline SkPMColor16 SkDitherPixel32To4444(SkPMColor c) {
+ return SkDitherARGB32To4444(SkGetPackedA32(c), SkGetPackedR32(c),
+ SkGetPackedG32(c), SkGetPackedB32(c));
+}
+
+/* Assumes 16bit is in standard RGBA order.
+ Transforms a normal ARGB_8888 into the same byte order as
+ expanded ARGB_4444, but keeps each component 8bits
+*/
+static inline uint32_t SkExpand_8888(SkPMColor c) {
+ return (((c >> SK_R32_SHIFT) & 0xFF) << 24) |
+ (((c >> SK_G32_SHIFT) & 0xFF) << 8) |
+ (((c >> SK_B32_SHIFT) & 0xFF) << 16) |
+ (((c >> SK_A32_SHIFT) & 0xFF) << 0);
+}
+
+/* Undo the operation of SkExpand_8888, turning the argument back into
+ a SkPMColor.
+*/
+static inline SkPMColor SkCompact_8888(uint32_t c) {
+ return (((c >> 24) & 0xFF) << SK_R32_SHIFT) |
+ (((c >> 8) & 0xFF) << SK_G32_SHIFT) |
+ (((c >> 16) & 0xFF) << SK_B32_SHIFT) |
+ (((c >> 0) & 0xFF) << SK_A32_SHIFT);
+}
+
+/* Like SkExpand_8888, this transforms a pmcolor into the expanded 4444 format,
+ but this routine just keeps the high 4bits of each component in the low
+ 4bits of the result (just like a newly expanded PMColor16).
+*/
+static inline uint32_t SkExpand32_4444(SkPMColor c) {
+ return (((c >> (SK_R32_SHIFT + 4)) & 0xF) << 24) |
+ (((c >> (SK_G32_SHIFT + 4)) & 0xF) << 8) |
+ (((c >> (SK_B32_SHIFT + 4)) & 0xF) << 16) |
+ (((c >> (SK_A32_SHIFT + 4)) & 0xF) << 0);
+}
+
+// takes two values and alternamtes them as part of a memset16
+// used for cheap 2x2 dithering when the colors are opaque
+void sk_dither_memset16(uint16_t dst[], uint16_t value, uint16_t other, int n);
+
+///////////////////////////////////////////////////////////////////////////////
+
+static inline int SkUpscale31To32(int value) {
+ SkASSERT((unsigned)value <= 31);
+ return value + (value >> 4);
+}
+
+static inline int SkBlend32(int src, int dst, int scale) {
+ SkASSERT((unsigned)src <= 0xFF);
+ SkASSERT((unsigned)dst <= 0xFF);
+ SkASSERT((unsigned)scale <= 32);
+ return dst + ((src - dst) * scale >> 5);
+}
+
+static inline SkPMColor SkBlendLCD16(int srcA, int srcR, int srcG, int srcB,
+ SkPMColor dst, uint16_t mask) {
+ if (mask == 0) {
+ return dst;
+ }
+
+ /* We want all of these in 5bits, hence the shifts in case one of them
+ * (green) is 6bits.
+ */
+ int maskR = SkGetPackedR16(mask) >> (SK_R16_BITS - 5);
+ int maskG = SkGetPackedG16(mask) >> (SK_G16_BITS - 5);
+ int maskB = SkGetPackedB16(mask) >> (SK_B16_BITS - 5);
+
+ // Now upscale them to 0..32, so we can use blend32
+ maskR = SkUpscale31To32(maskR);
+ maskG = SkUpscale31To32(maskG);
+ maskB = SkUpscale31To32(maskB);
+
+ // srcA has been upscaled to 256 before passed into this function
+ maskR = maskR * srcA >> 8;
+ maskG = maskG * srcA >> 8;
+ maskB = maskB * srcA >> 8;
+
+ int dstR = SkGetPackedR32(dst);
+ int dstG = SkGetPackedG32(dst);
+ int dstB = SkGetPackedB32(dst);
+
+ // LCD blitting is only supported if the dst is known/required
+ // to be opaque
+ return SkPackARGB32(0xFF,
+ SkBlend32(srcR, dstR, maskR),
+ SkBlend32(srcG, dstG, maskG),
+ SkBlend32(srcB, dstB, maskB));
+}
+
+static inline SkPMColor SkBlendLCD16Opaque(int srcR, int srcG, int srcB,
+ SkPMColor dst, uint16_t mask,
+ SkPMColor opaqueDst) {
+ if (mask == 0) {
+ return dst;
+ }
+
+ if (0xFFFF == mask) {
+ return opaqueDst;
+ }
+
+ /* We want all of these in 5bits, hence the shifts in case one of them
+ * (green) is 6bits.
+ */
+ int maskR = SkGetPackedR16(mask) >> (SK_R16_BITS - 5);
+ int maskG = SkGetPackedG16(mask) >> (SK_G16_BITS - 5);
+ int maskB = SkGetPackedB16(mask) >> (SK_B16_BITS - 5);
+
+ // Now upscale them to 0..32, so we can use blend32
+ maskR = SkUpscale31To32(maskR);
+ maskG = SkUpscale31To32(maskG);
+ maskB = SkUpscale31To32(maskB);
+
+ int dstR = SkGetPackedR32(dst);
+ int dstG = SkGetPackedG32(dst);
+ int dstB = SkGetPackedB32(dst);
+
+ // LCD blitting is only supported if the dst is known/required
+ // to be opaque
+ return SkPackARGB32(0xFF,
+ SkBlend32(srcR, dstR, maskR),
+ SkBlend32(srcG, dstG, maskG),
+ SkBlend32(srcB, dstB, maskB));
+}
+
+static inline void SkBlitLCD16Row(SkPMColor dst[], const uint16_t mask[],
+ SkColor src, int width, SkPMColor) {
+ int srcA = SkColorGetA(src);
+ int srcR = SkColorGetR(src);
+ int srcG = SkColorGetG(src);
+ int srcB = SkColorGetB(src);
+
+ srcA = SkAlpha255To256(srcA);
+
+ for (int i = 0; i < width; i++) {
+ dst[i] = SkBlendLCD16(srcA, srcR, srcG, srcB, dst[i], mask[i]);
+ }
+}
+
+static inline void SkBlitLCD16OpaqueRow(SkPMColor dst[], const uint16_t mask[],
+ SkColor src, int width,
+ SkPMColor opaqueDst) {
+ int srcR = SkColorGetR(src);
+ int srcG = SkColorGetG(src);
+ int srcB = SkColorGetB(src);
+
+ for (int i = 0; i < width; i++) {
+ dst[i] = SkBlendLCD16Opaque(srcR, srcG, srcB, dst[i], mask[i],
+ opaqueDst);
+ }
+}
+
+#endif
diff --git a/core/SkColorShader.h b/core/SkColorShader.h
new file mode 100644
index 0000000..c379068
--- /dev/null
+++ b/core/SkColorShader.h
@@ -0,0 +1,69 @@
+
+/*
+ * Copyright 2007 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkColorShader_DEFINED
+#define SkColorShader_DEFINED
+
+#include "SkShader.h"
+
+/** \class SkColorShader
+ A Shader that represents a single color. In general, this effect can be
+ accomplished by just using the color field on the paint, but if an
+ actual shader object is needed, this provides that feature.
+*/
+class SK_API SkColorShader : public SkShader {
+public:
+ /** Create a ColorShader that will inherit its color from the Paint
+ at draw time.
+ */
+ SkColorShader();
+
+ /** Create a ColorShader that ignores the color in the paint, and uses the
+ specified color. Note: like all shaders, at draw time the paint's alpha
+ will be respected, and is applied to the specified color.
+ */
+ SkColorShader(SkColor c);
+
+ virtual ~SkColorShader();
+
+ virtual uint32_t getFlags() SK_OVERRIDE;
+ virtual uint8_t getSpan16Alpha() const SK_OVERRIDE;
+ virtual bool isOpaque() const SK_OVERRIDE;
+ virtual bool setContext(const SkBitmap& device, const SkPaint& paint,
+ const SkMatrix& matrix) SK_OVERRIDE;
+ virtual void shadeSpan(int x, int y, SkPMColor span[], int count) SK_OVERRIDE;
+ virtual void shadeSpan16(int x, int y, uint16_t span[], int count) SK_OVERRIDE;
+ virtual void shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) SK_OVERRIDE;
+
+ // we return false for this, use asAGradient
+ virtual BitmapType asABitmap(SkBitmap* outTexture,
+ SkMatrix* outMatrix,
+ TileMode xy[2]) const SK_OVERRIDE;
+
+ virtual GradientType asAGradient(GradientInfo* info) const SK_OVERRIDE;
+
+ SK_DEVELOPER_TO_STRING()
+ SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkColorShader)
+
+protected:
+ SkColorShader(SkFlattenableReadBuffer&);
+ virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
+
+private:
+
+ SkColor fColor; // ignored if fInheritColor is true
+ SkPMColor fPMColor; // cached after setContext()
+ uint32_t fFlags; // cached after setContext()
+ uint16_t fColor16; // cached after setContext()
+ SkBool8 fInheritColor;
+
+ typedef SkShader INHERITED;
+};
+
+#endif
diff --git a/core/SkColorTable.h b/core/SkColorTable.h
new file mode 100644
index 0000000..f8d1ccf
--- /dev/null
+++ b/core/SkColorTable.h
@@ -0,0 +1,112 @@
+
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkColorTable_DEFINED
+#define SkColorTable_DEFINED
+
+#include "SkColor.h"
+#include "SkFlattenable.h"
+
+/** \class SkColorTable
+
+ SkColorTable holds an array SkPMColors (premultiplied 32-bit colors) used by
+ 8-bit bitmaps, where the bitmap bytes are interpreted as indices into the colortable.
+*/
+class SkColorTable : public SkFlattenable {
+public:
+ SK_DECLARE_INST_COUNT(SkColorTable)
+
+ /** Makes a deep copy of colors.
+ */
+ SkColorTable(const SkColorTable& src);
+ /** Preallocates the colortable to have 'count' colors, which
+ * are initially set to 0.
+ */
+ explicit SkColorTable(int count);
+ SkColorTable(const SkPMColor colors[], int count);
+ virtual ~SkColorTable();
+
+ enum Flags {
+ kColorsAreOpaque_Flag = 0x01 //!< if set, all of the colors in the table are opaque (alpha==0xFF)
+ };
+ /** Returns the flag bits for the color table. These can be changed with setFlags().
+ */
+ unsigned getFlags() const { return fFlags; }
+ /** Set the flags for the color table. See the Flags enum for possible values.
+ */
+ void setFlags(unsigned flags);
+
+ bool isOpaque() const { return (fFlags & kColorsAreOpaque_Flag) != 0; }
+ void setIsOpaque(bool isOpaque);
+
+ /** Returns the number of colors in the table.
+ */
+ int count() const { return fCount; }
+
+ /** Returns the specified color from the table. In the debug build, this asserts that
+ the index is in range (0 <= index < count).
+ */
+ SkPMColor operator[](int index) const {
+ SkASSERT(fColors != NULL && (unsigned)index < fCount);
+ return fColors[index];
+ }
+
+ /** Specify the number of colors in the color table. This does not initialize the colors
+ to any value, just allocates memory for them. To initialize the values, either call
+ setColors(array, count), or follow setCount(count) with a call to
+ lockColors()/{set the values}/unlockColors(true).
+ */
+// void setColors(int count) { this->setColors(NULL, count); }
+// void setColors(const SkPMColor[], int count);
+
+ /** Return the array of colors for reading and/or writing. This must be
+ balanced by a call to unlockColors(changed?), telling the colortable if
+ the colors were changed during the lock.
+ */
+ SkPMColor* lockColors() {
+ SkDEBUGCODE(sk_atomic_inc(&fColorLockCount);)
+ return fColors;
+ }
+ /** Balancing call to lockColors(). If the colors have been changed, pass true.
+ */
+ void unlockColors(bool changed);
+
+ /** Similar to lockColors(), lock16BitCache() returns the array of
+ RGB16 colors that mirror the 32bit colors. However, this function
+ will return null if kColorsAreOpaque_Flag is not set.
+ Also, unlike lockColors(), the returned array here cannot be modified.
+ */
+ const uint16_t* lock16BitCache();
+ /** Balancing call to lock16BitCache().
+ */
+ void unlock16BitCache() {
+ SkASSERT(f16BitCacheLockCount > 0);
+ SkDEBUGCODE(f16BitCacheLockCount -= 1);
+ }
+
+ SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkColorTable)
+
+protected:
+ explicit SkColorTable(SkFlattenableReadBuffer&);
+ void flatten(SkFlattenableWriteBuffer&) const;
+
+private:
+ SkPMColor* fColors;
+ uint16_t* f16BitCache;
+ uint16_t fCount;
+ uint8_t fFlags;
+ SkDEBUGCODE(int fColorLockCount;)
+ SkDEBUGCODE(int f16BitCacheLockCount;)
+
+ void inval16BitCache();
+
+ typedef SkFlattenable INHERITED;
+};
+
+#endif
diff --git a/core/SkComposeShader.h b/core/SkComposeShader.h
new file mode 100644
index 0000000..524161b
--- /dev/null
+++ b/core/SkComposeShader.h
@@ -0,0 +1,58 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkComposeShader_DEFINED
+#define SkComposeShader_DEFINED
+
+#include "SkShader.h"
+
+class SkXfermode;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+/** \class SkComposeShader
+ This subclass of shader returns the coposition of two other shaders, combined by
+ a xfermode.
+*/
+class SK_API SkComposeShader : public SkShader {
+public:
+ /** Create a new compose shader, given shaders A, B, and a combining xfermode mode.
+ When the xfermode is called, it will be given the result from shader A as its
+ "dst", and the result of from shader B as its "src".
+ mode->xfer32(sA_result, sB_result, ...)
+ @param shaderA The colors from this shader are seen as the "dst" by the xfermode
+ @param shaderB The colors from this shader are seen as the "src" by the xfermode
+ @param mode The xfermode that combines the colors from the two shaders. If mode
+ is null, then SRC_OVER is assumed.
+ */
+ SkComposeShader(SkShader* sA, SkShader* sB, SkXfermode* mode = NULL);
+ virtual ~SkComposeShader();
+
+ virtual bool setContext(const SkBitmap&, const SkPaint&,
+ const SkMatrix&) SK_OVERRIDE;
+ virtual void endContext() SK_OVERRIDE;
+ virtual void shadeSpan(int x, int y, SkPMColor[], int count) SK_OVERRIDE;
+
+ SK_DEVELOPER_TO_STRING()
+ SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkComposeShader)
+
+protected:
+ SkComposeShader(SkFlattenableReadBuffer& );
+ virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
+
+private:
+
+ SkShader* fShaderA;
+ SkShader* fShaderB;
+ SkXfermode* fMode;
+
+ typedef SkShader INHERITED;
+};
+
+#endif
diff --git a/core/SkData.h b/core/SkData.h
new file mode 100644
index 0000000..6f883c8
--- /dev/null
+++ b/core/SkData.h
@@ -0,0 +1,151 @@
+
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+
+#ifndef SkData_DEFINED
+#define SkData_DEFINED
+
+#include "SkFlattenable.h"
+
+struct SkFILE;
+
+/**
+ * SkData holds an immutable data buffer. Not only is the data immutable,
+ * but the actual ptr that is returned (by data() or bytes()) is guaranteed
+ * to always be the same for the life of this instance.
+ */
+class SK_API SkData : public SkFlattenable {
+public:
+ SK_DECLARE_INST_COUNT(SkData)
+
+ /**
+ * Returns the number of bytes stored.
+ */
+ size_t size() const { return fSize; }
+
+ bool isEmpty() const { return 0 == fSize; }
+
+ /**
+ * Returns the ptr to the data.
+ */
+ const void* data() const { return fPtr; }
+
+ /**
+ * Like data(), returns a read-only ptr into the data, but in this case
+ * it is cast to uint8_t*, to make it easy to add an offset to it.
+ */
+ const uint8_t* bytes() const {
+ return reinterpret_cast<const uint8_t*>(fPtr);
+ }
+
+ /**
+ * Helper to copy a range of the data into a caller-provided buffer.
+ * Returns the actual number of bytes copied, after clamping offset and
+ * length to the size of the data. If buffer is NULL, it is ignored, and
+ * only the computed number of bytes is returned.
+ */
+ size_t copyRange(size_t offset, size_t length, void* buffer) const;
+
+ /**
+ * Returns true if these two objects have the same length and contents,
+ * effectively returning 0 == memcmp(...)
+ */
+ bool equals(const SkData* other) const;
+
+ /**
+ * Function that, if provided, will be called when the SkData goes out
+ * of scope, allowing for custom allocation/freeing of the data.
+ */
+ typedef void (*ReleaseProc)(const void* ptr, size_t length, void* context);
+
+ /**
+ * Create a new dataref by copying the specified data
+ */
+ static SkData* NewWithCopy(const void* data, size_t length);
+
+ /**
+ * Create a new dataref by copying the specified c-string
+ * (a null-terminated array of bytes). The returned SkData will have size()
+ * equal to strlen(cstr) + 1. If cstr is NULL, it will be treated the same
+ * as "".
+ */
+ static SkData* NewWithCString(const char cstr[]);
+
+ /**
+ * Create a new dataref, taking the data ptr as is, and using the
+ * releaseproc to free it. The proc may be NULL.
+ */
+ static SkData* NewWithProc(const void* data, size_t length,
+ ReleaseProc proc, void* context);
+
+ /**
+ * Create a new dataref from a pointer allocated by malloc. The Data object
+ * takes ownership of that allocation, and will handling calling sk_free.
+ */
+ static SkData* NewFromMalloc(const void* data, size_t length);
+
+ /**
+ * Create a new dataref the file with the specified path.
+ * If the file cannot be opened, this returns NULL.
+ */
+ static SkData* NewFromFileName(const char path[]);
+
+ /**
+ * Create a new dataref from a SkFILE.
+ * This does not take ownership of the SkFILE, nor close it.
+ * The caller is free to close the SkFILE at its convenience.
+ * The SkFILE must be open for reading only.
+ * Returns NULL on failure.
+ */
+ static SkData* NewFromFILE(SkFILE* f);
+
+ /**
+ * Create a new dataref from a file descriptor.
+ * This does not take ownership of the file descriptor, nor close it.
+ * The caller is free to close the file descriptor at its convenience.
+ * The file descriptor must be open for reading only.
+ * Returns NULL on failure.
+ */
+ static SkData* NewFromFD(int fd);
+
+ /**
+ * Create a new dataref using a subset of the data in the specified
+ * src dataref.
+ */
+ static SkData* NewSubset(const SkData* src, size_t offset, size_t length);
+
+ /**
+ * Returns a new empty dataref (or a reference to a shared empty dataref).
+ * New or shared, the caller must see that unref() is eventually called.
+ */
+ static SkData* NewEmpty();
+
+ SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkData)
+
+protected:
+ SkData(SkFlattenableReadBuffer&);
+ virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
+
+private:
+ ReleaseProc fReleaseProc;
+ void* fReleaseProcContext;
+
+ const void* fPtr;
+ size_t fSize;
+
+ SkData(const void* ptr, size_t size, ReleaseProc, void* context);
+ virtual ~SkData();
+
+ typedef SkFlattenable INHERITED;
+};
+
+/** Typedef of SkAutoTUnref<SkData> for automatically unref-ing a SkData. */
+typedef SkAutoTUnref<SkData> SkAutoDataUnref;
+
+#endif
diff --git a/core/SkDataSet.h b/core/SkDataSet.h
new file mode 100644
index 0000000..2e5d96e
--- /dev/null
+++ b/core/SkDataSet.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkDataSet_DEFINED
+#define SkDataSet_DEFINED
+
+#include "SkData.h"
+#include "SkFlattenable.h"
+
+class SkStream;
+class SkWStream;
+
+class SkDataSet : public SkFlattenable {
+public:
+ /**
+ * Returns a new empty dataset. Note: since SkDataSet is immutable, this
+ * "new" set may be the same one that was returned before, but each
+ * returned object must have its reference-count balanced regardless.
+ *
+ * SkDataSet* empty = SkDataSet::NewEmpty();
+ * ...
+ * empty->unref();
+ */
+ static SkDataSet* NewEmpty();
+
+ struct Pair {
+ const char* fKey;
+ SkData* fValue;
+ };
+
+ SkDataSet(const char key[], SkData* value);
+ SkDataSet(const Pair[], int count);
+ virtual ~SkDataSet();
+
+ bool isEmpty() const { return 0 == fCount; }
+ int count() const { return fCount; }
+ SkData* find(const char name[]) const;
+
+ class Iter {
+ public:
+ Iter(const SkDataSet& ds) {
+ fPair = ds.fPairs;
+ fStop = ds.fPairs + ds.fCount;
+ }
+
+ const char* key() const {
+ SkASSERT(!this->done());
+ return fPair->fKey;
+ }
+
+ SkData* value() const {
+ SkASSERT(!this->done());
+ return fPair->fValue;
+ }
+
+ bool done() const { return fPair >= fStop; }
+ void next() {
+ SkASSERT(!this->done());
+ fPair += 1;
+ }
+
+ private:
+ const SkDataSet::Pair* fPair;
+ const SkDataSet::Pair* fStop;
+ };
+
+ explicit SkDataSet(SkStream*);
+ void writeToStream(SkWStream*) const;
+
+ SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDataSet)
+
+protected:
+ SkDataSet(SkFlattenableReadBuffer&);
+ virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
+
+private:
+ int32_t fCount;
+ uint32_t fKeySize;
+ Pair* fPairs;
+
+ typedef SkFlattenable INHERITED;
+};
+
+#endif
diff --git a/core/SkDataTable.h b/core/SkDataTable.h
new file mode 100644
index 0000000..cb74c3c
--- /dev/null
+++ b/core/SkDataTable.h
@@ -0,0 +1,184 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkDataTable_DEFINED
+#define SkDataTable_DEFINED
+
+#include "SkChunkAlloc.h"
+#include "SkData.h"
+#include "SkFlattenable.h"
+#include "SkString.h"
+#include "SkTDArray.h"
+
+/**
+ * Like SkData, SkDataTable holds an immutable data buffer. The data buffer is
+ * organized into a table of entries, each with a length, so the entries are
+ * not required to all be the same size.
+ */
+class SK_API SkDataTable : public SkFlattenable {
+public:
+ SK_DECLARE_INST_COUNT(SkDataTable)
+
+ /**
+ * Returns true if the table is empty (i.e. has no entries).
+ */
+ bool isEmpty() const { return 0 == fCount; }
+
+ /**
+ * Return the number of entries in the table. 0 for an empty table
+ */
+ int count() const { return fCount; }
+
+ /**
+ * Return the size of the index'th entry in the table. The caller must
+ * ensure that index is valid for this table.
+ */
+ size_t atSize(int index) const;
+
+ /**
+ * Return a pointer to the data of the index'th entry in the table.
+ * The caller must ensure that index is valid for this table.
+ *
+ * @param size If non-null, this returns the byte size of this entry. This
+ * will be the same value that atSize(index) would return.
+ */
+ const void* at(int index, size_t* size = NULL) const;
+
+ template <typename T>
+ const T* atT(int index, size_t* size = NULL) const {
+ return reinterpret_cast<const T*>(this->at(index, size));
+ }
+
+ /**
+ * Returns the index'th entry as a c-string, and assumes that the trailing
+ * null byte had been copied into the table as well.
+ */
+ const char* atStr(int index) const {
+ size_t size;
+ const char* str = this->atT<const char>(index, &size);
+ SkASSERT(strlen(str) + 1 == size);
+ return str;
+ }
+
+ typedef void (*FreeProc)(void* context);
+
+ static SkDataTable* NewEmpty();
+
+ /**
+ * Return a new DataTable that contains a copy of the data stored in each
+ * "array".
+ *
+ * @param ptrs array of points to each element to be copied into the table.
+ * @param sizes array of byte-lengths for each entry in the corresponding
+ * ptrs[] array.
+ * @param count the number of array elements in ptrs[] and sizes[] to copy.
+ */
+ static SkDataTable* NewCopyArrays(const void * const * ptrs,
+ const size_t sizes[], int count);
+
+ /**
+ * Return a new table that contains a copy of the data in array.
+ *
+ * @param array contiguous array of data for all elements to be copied.
+ * @param elemSize byte-length for a given element.
+ * @param count the number of entries to be copied out of array. The number
+ * of bytes that will be copied is count * elemSize.
+ */
+ static SkDataTable* NewCopyArray(const void* array, size_t elemSize,
+ int count);
+
+ static SkDataTable* NewArrayProc(const void* array, size_t elemSize,
+ int count, FreeProc proc, void* context);
+
+ SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDataTable)
+
+protected:
+ SkDataTable(SkFlattenableReadBuffer&);
+ virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
+
+private:
+ struct Dir {
+ const void* fPtr;
+ uintptr_t fSize;
+ };
+
+ int fCount;
+ size_t fElemSize;
+ union {
+ const Dir* fDir;
+ const char* fElems;
+ } fU;
+
+ FreeProc fFreeProc;
+ void* fFreeProcContext;
+
+ SkDataTable();
+ SkDataTable(const void* array, size_t elemSize, int count,
+ FreeProc, void* context);
+ SkDataTable(const Dir*, int count, FreeProc, void* context);
+ virtual ~SkDataTable();
+
+ friend class SkDataTableBuilder; // access to Dir
+
+ typedef SkFlattenable INHERITED;
+};
+
+/**
+ * Helper class that allows for incrementally building up the data needed to
+ * create a SkDataTable.
+ */
+class SK_API SkDataTableBuilder : SkNoncopyable {
+public:
+ SkDataTableBuilder(size_t minChunkSize);
+ ~SkDataTableBuilder();
+
+ int count() const { return fDir.count(); }
+ size_t minChunkSize() const { return fMinChunkSize; }
+
+ /**
+ * Forget any previously appended entries, setting count() back to 0.
+ */
+ void reset(size_t minChunkSize);
+ void reset() {
+ this->reset(fMinChunkSize);
+ }
+
+ /**
+ * Copy size-bytes from data, and append it to the growing SkDataTable.
+ */
+ void append(const void* data, size_t size);
+
+ /**
+ * Helper version of append() passes strlen() + 1 for the size,
+ * so the trailing-zero will be copied as well.
+ */
+ void appendStr(const char str[]) {
+ this->append(str, strlen(str) + 1);
+ }
+
+ /**
+ * Helper version of append() passes string.size() + 1 for the size,
+ * so the trailing-zero will be copied as well.
+ */
+ void appendString(const SkString& string) {
+ this->append(string.c_str(), string.size() + 1);
+ }
+
+ /**
+ * Return an SkDataTable from the accumulated entries that were added by
+ * calls to append(). This call also clears any accumluated entries from
+ * this builder, so its count() will be 0 after this call.
+ */
+ SkDataTable* detachDataTable();
+
+private:
+ SkTDArray<SkDataTable::Dir> fDir;
+ SkChunkAlloc* fHeap;
+ size_t fMinChunkSize;
+};
+
+#endif
diff --git a/core/SkDeque.h b/core/SkDeque.h
new file mode 100644
index 0000000..eef335d
--- /dev/null
+++ b/core/SkDeque.h
@@ -0,0 +1,138 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkDeque_DEFINED
+#define SkDeque_DEFINED
+
+#include "SkTypes.h"
+
+/*
+ * The deque class works by blindly creating memory space of a specified element
+ * size. It manages the memory as a doubly linked list of blocks each of which
+ * can contain multiple elements. Pushes and pops add/remove blocks from the
+ * beginning/end of the list as necessary while each block tracks the used
+ * portion of its memory.
+ * One behavior to be aware of is that the pops do not immediately remove an
+ * empty block from the beginning/end of the list (Presumably so push/pop pairs
+ * on the block boundaries don't cause thrashing). This can result in the first/
+ * last element not residing in the first/last block.
+ */
+class SK_API SkDeque : SkNoncopyable {
+public:
+ /**
+ * elemSize specifies the size of each individual element in the deque
+ * allocCount specifies how many elements are to be allocated as a block
+ */
+ explicit SkDeque(size_t elemSize, int allocCount = 1);
+ SkDeque(size_t elemSize, void* storage, size_t storageSize, int allocCount = 1);
+ ~SkDeque();
+
+ bool empty() const { return 0 == fCount; }
+ int count() const { return fCount; }
+ size_t elemSize() const { return fElemSize; }
+
+ const void* front() const { return fFront; }
+ const void* back() const { return fBack; }
+
+ void* front() {
+ return (void*)((const SkDeque*)this)->front();
+ }
+
+ void* back() {
+ return (void*)((const SkDeque*)this)->back();
+ }
+
+ /**
+ * push_front and push_back return a pointer to the memory space
+ * for the new element
+ */
+ void* push_front();
+ void* push_back();
+
+ void pop_front();
+ void pop_back();
+
+private:
+ struct Block;
+
+public:
+ class Iter {
+ public:
+ enum IterStart {
+ kFront_IterStart,
+ kBack_IterStart
+ };
+
+ /**
+ * Creates an uninitialized iterator. Must be reset()
+ */
+ Iter();
+
+ Iter(const SkDeque& d, IterStart startLoc);
+ void* next();
+ void* prev();
+
+ void reset(const SkDeque& d, IterStart startLoc);
+
+ private:
+ SkDeque::Block* fCurBlock;
+ char* fPos;
+ size_t fElemSize;
+ };
+
+ // Inherit privately from Iter to prevent access to reverse iteration
+ class F2BIter : private Iter {
+ public:
+ F2BIter() {}
+
+ /**
+ * Wrap Iter's 2 parameter ctor to force initialization to the
+ * beginning of the deque
+ */
+ F2BIter(const SkDeque& d) : INHERITED(d, kFront_IterStart) {}
+
+ using Iter::next;
+
+ /**
+ * Wrap Iter::reset to force initialization to the beginning of the
+ * deque
+ */
+ void reset(const SkDeque& d) {
+ this->INHERITED::reset(d, kFront_IterStart);
+ }
+
+ private:
+ typedef Iter INHERITED;
+ };
+
+private:
+ // allow unit test to call numBlocksAllocated
+ friend class DequeUnitTestHelper;
+
+ void* fFront;
+ void* fBack;
+
+ Block* fFrontBlock;
+ Block* fBackBlock;
+ size_t fElemSize;
+ void* fInitialStorage;
+ int fCount; // number of elements in the deque
+ int fAllocCount; // number of elements to allocate per block
+
+ Block* allocateBlock(int allocCount);
+ void freeBlock(Block* block);
+
+ /**
+ * This returns the number of chunk blocks allocated by the deque. It
+ * can be used to gauge the effectiveness of the selected allocCount.
+ */
+ int numBlocksAllocated() const;
+};
+
+#endif
diff --git a/core/SkDevice.h b/core/SkDevice.h
new file mode 100644
index 0000000..f39e5dd
--- /dev/null
+++ b/core/SkDevice.h
@@ -0,0 +1,468 @@
+
+/*
+ * Copyright 2010 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkDevice_DEFINED
+#define SkDevice_DEFINED
+
+#include "SkRefCnt.h"
+#include "SkBitmap.h"
+#include "SkCanvas.h"
+#include "SkColor.h"
+#include "SkDeviceProperties.h"
+
+class SkClipStack;
+class SkDraw;
+struct SkIRect;
+class SkMatrix;
+class SkMetaData;
+class SkRegion;
+
+class GrRenderTarget;
+
+class SK_API SkDevice : public SkRefCnt {
+public:
+ SK_DECLARE_INST_COUNT(SkDevice)
+
+ /**
+ * Construct a new device with the specified bitmap as its backend. It is
+ * valid for the bitmap to have no pixels associated with it. In that case,
+ * any drawing to this device will have no effect.
+ */
+ SkDevice(const SkBitmap& bitmap);
+
+ /**
+ * Construct a new device with the specified bitmap as its backend. It is
+ * valid for the bitmap to have no pixels associated with it. In that case,
+ * any drawing to this device will have no effect.
+ */
+ SkDevice(const SkBitmap& bitmap, const SkDeviceProperties& deviceProperties);
+
+ /**
+ * Create a new raster device and have the pixels be automatically
+ * allocated. The rowBytes of the device will be computed automatically
+ * based on the config and the width.
+ *
+ * @param config The desired config for the pixels. If the request cannot
+ * be met, the closest matching support config will be used.
+ * @param width width (in pixels) of the device
+ * @param height height (in pixels) of the device
+ * @param isOpaque Set to true if it is known that all of the pixels will
+ * be drawn to opaquely. Used as an accelerator when drawing
+ * these pixels to another device.
+ */
+ SkDevice(SkBitmap::Config config, int width, int height, bool isOpaque = false);
+
+ /**
+ * Create a new raster device and have the pixels be automatically
+ * allocated. The rowBytes of the device will be computed automatically
+ * based on the config and the width.
+ *
+ * @param config The desired config for the pixels. If the request cannot
+ * be met, the closest matching support config will be used.
+ * @param width width (in pixels) of the device
+ * @param height height (in pixels) of the device
+ * @param isOpaque Set to true if it is known that all of the pixels will
+ * be drawn to opaquely. Used as an accelerator when drawing
+ * these pixels to another device.
+ * @param deviceProperties Properties which affect compositing.
+ */
+ SkDevice(SkBitmap::Config config, int width, int height, bool isOpaque,
+ const SkDeviceProperties& deviceProperties);
+
+ virtual ~SkDevice();
+
+ /**
+ * Creates a device that is of the same type as this device (e.g. SW-raster,
+ * GPU, or PDF). The backing store for this device is created automatically
+ * (e.g. offscreen pixels or FBO or whatever is appropriate).
+ *
+ * @param width width of the device to create
+ * @param height height of the device to create
+ * @param isOpaque performance hint, set to true if you know that you will
+ * draw into this device such that all of the pixels will
+ * be opaque.
+ */
+ SkDevice* createCompatibleDevice(SkBitmap::Config config,
+ int width, int height,
+ bool isOpaque);
+
+ SkMetaData& getMetaData();
+
+ enum Capabilities {
+ kGL_Capability = 0x1, //!< mask indicating GL support
+ kVector_Capability = 0x2, //!< mask indicating a vector representation
+ kAll_Capabilities = 0x3
+ };
+ virtual uint32_t getDeviceCapabilities() { return 0; }
+
+ /** Return the width of the device (in pixels).
+ */
+ virtual int width() const { return fBitmap.width(); }
+ /** Return the height of the device (in pixels).
+ */
+ virtual int height() const { return fBitmap.height(); }
+
+ /** Return the image properties of the device. */
+ virtual const SkDeviceProperties& getDeviceProperties() const {
+ //Currently, all the properties are leaky.
+ return fLeakyProperties;
+ }
+
+ /**
+ * Return the bounds of the device in the coordinate space of the root
+ * canvas. The root device will have its top-left at 0,0, but other devices
+ * such as those associated with saveLayer may have a non-zero origin.
+ */
+ void getGlobalBounds(SkIRect* bounds) const;
+
+ /** Returns true if the device's bitmap's config treats every pixels as
+ implicitly opaque.
+ */
+ bool isOpaque() const { return fBitmap.isOpaque(); }
+
+ /** Return the bitmap config of the device's pixels
+ */
+ SkBitmap::Config config() const { return fBitmap.getConfig(); }
+
+ /** Return the bitmap associated with this device. Call this each time you need
+ to access the bitmap, as it notifies the subclass to perform any flushing
+ etc. before you examine the pixels.
+ @param changePixels set to true if the caller plans to change the pixels
+ @return the device's bitmap
+ */
+ const SkBitmap& accessBitmap(bool changePixels);
+
+ /**
+ * DEPRECATED: This will be made protected once WebKit stops using it.
+ * Instead use Canvas' writePixels method.
+ *
+ * Similar to draw sprite, this method will copy the pixels in bitmap onto
+ * the device, with the top/left corner specified by (x, y). The pixel
+ * values in the device are completely replaced: there is no blending.
+ *
+ * Currently if bitmap is backed by a texture this is a no-op. This may be
+ * relaxed in the future.
+ *
+ * If the bitmap has config kARGB_8888_Config then the config8888 param
+ * will determines how the pixel valuess are intepreted. If the bitmap is
+ * not kARGB_8888_Config then this parameter is ignored.
+ */
+ virtual void writePixels(const SkBitmap& bitmap, int x, int y,
+ SkCanvas::Config8888 config8888 = SkCanvas::kNative_Premul_Config8888);
+
+ /**
+ * Return the device's associated gpu render target, or NULL.
+ */
+ virtual GrRenderTarget* accessRenderTarget() { return NULL; }
+
+
+ /**
+ * Return the device's origin: its offset in device coordinates from
+ * the default origin in its canvas' matrix/clip
+ */
+ const SkIPoint& getOrigin() const { return fOrigin; }
+
+ /**
+ * onAttachToCanvas is invoked whenever a device is installed in a canvas
+ * (i.e., setDevice, saveLayer (for the new device created by the save),
+ * and SkCanvas' SkDevice & SkBitmap -taking ctors). It allows the
+ * devices to prepare for drawing (e.g., locking their pixels, etc.)
+ */
+ virtual void onAttachToCanvas(SkCanvas*) {
+ SkASSERT(!fAttachedToCanvas);
+ this->lockPixels();
+#ifdef SK_DEBUG
+ fAttachedToCanvas = true;
+#endif
+ };
+
+ /**
+ * onDetachFromCanvas notifies a device that it will no longer be drawn to.
+ * It gives the device a chance to clean up (e.g., unlock its pixels). It
+ * is invoked from setDevice (for the displaced device), restore and
+ * possibly from SkCanvas' dtor.
+ */
+ virtual void onDetachFromCanvas() {
+ SkASSERT(fAttachedToCanvas);
+ this->unlockPixels();
+#ifdef SK_DEBUG
+ fAttachedToCanvas = false;
+#endif
+ };
+
+protected:
+ enum Usage {
+ kGeneral_Usage,
+ kSaveLayer_Usage // <! internal use only
+ };
+
+ struct TextFlags {
+ uint32_t fFlags; // SkPaint::getFlags()
+ SkPaint::Hinting fHinting;
+ };
+
+ /**
+ * Device may filter the text flags for drawing text here. If it wants to
+ * make a change to the specified values, it should write them into the
+ * textflags parameter (output) and return true. If the paint is fine as
+ * is, then ignore the textflags parameter and return false.
+ *
+ * The baseclass SkDevice filters based on its depth and blitters.
+ */
+ virtual bool filterTextFlags(const SkPaint& paint, TextFlags*);
+
+ /**
+ *
+ * DEPRECATED: This will be removed in a future change. Device subclasses
+ * should use the matrix and clip from the SkDraw passed to draw functions.
+ *
+ * Called with the correct matrix and clip before this device is drawn
+ * to using those settings. If your subclass overrides this, be sure to
+ * call through to the base class as well.
+ *
+ * The clipstack is another view of the clip. It records the actual
+ * geometry that went into building the region. It is present for devices
+ * that want to parse it, but is not required: the region is a complete
+ * picture of the current clip. (i.e. if you regionize all of the geometry
+ * in the clipstack, you will arrive at an equivalent region to the one
+ * passed in).
+ */
+ virtual void setMatrixClip(const SkMatrix&, const SkRegion&,
+ const SkClipStack&);
+
+ /** Clears the entire device to the specified color (including alpha).
+ * Ignores the clip.
+ */
+ virtual void clear(SkColor color);
+
+ /**
+ * Deprecated name for clear.
+ */
+ void eraseColor(SkColor eraseColor) { this->clear(eraseColor); }
+
+ /** These are called inside the per-device-layer loop for each draw call.
+ When these are called, we have already applied any saveLayer operations,
+ and are handling any looping from the paint, and any effects from the
+ DrawFilter.
+ */
+ virtual void drawPaint(const SkDraw&, const SkPaint& paint);
+ virtual void drawPoints(const SkDraw&, SkCanvas::PointMode mode, size_t count,
+ const SkPoint[], const SkPaint& paint);
+ virtual void drawRect(const SkDraw&, const SkRect& r,
+ const SkPaint& paint);
+ virtual void drawOval(const SkDraw&, const SkRect& oval,
+ const SkPaint& paint);
+ virtual void drawRRect(const SkDraw&, const SkRRect& rr,
+ const SkPaint& paint);
+
+ /**
+ * If pathIsMutable, then the implementation is allowed to cast path to a
+ * non-const pointer and modify it in place (as an optimization). Canvas
+ * may do this to implement helpers such as drawOval, by placing a temp
+ * path on the stack to hold the representation of the oval.
+ *
+ * If prePathMatrix is not null, it should logically be applied before any
+ * stroking or other effects. If there are no effects on the paint that
+ * affect the geometry/rasterization, then the pre matrix can just be
+ * pre-concated with the current matrix.
+ */
+ virtual void drawPath(const SkDraw&, const SkPath& path,
+ const SkPaint& paint,
+ const SkMatrix* prePathMatrix = NULL,
+ bool pathIsMutable = false);
+ virtual void drawBitmap(const SkDraw&, const SkBitmap& bitmap,
+ const SkMatrix& matrix, const SkPaint& paint);
+ virtual void drawSprite(const SkDraw&, const SkBitmap& bitmap,
+ int x, int y, const SkPaint& paint);
+
+ /**
+ * The default impl. will create a bitmap-shader from the bitmap,
+ * and call drawRect with it.
+ */
+ virtual void drawBitmapRect(const SkDraw&, const SkBitmap&,
+ const SkRect* srcOrNull, const SkRect& dst,
+ const SkPaint& paint);
+
+ /**
+ * Does not handle text decoration.
+ * Decorations (underline and stike-thru) will be handled by SkCanvas.
+ */
+ virtual void drawText(const SkDraw&, const void* text, size_t len,
+ SkScalar x, SkScalar y, const SkPaint& paint);
+ virtual void drawPosText(const SkDraw&, const void* text, size_t len,
+ const SkScalar pos[], SkScalar constY,
+ int scalarsPerPos, const SkPaint& paint);
+ virtual void drawTextOnPath(const SkDraw&, const void* text, size_t len,
+ const SkPath& path, const SkMatrix* matrix,
+ const SkPaint& paint);
+#ifdef SK_BUILD_FOR_ANDROID
+ virtual void drawPosTextOnPath(const SkDraw& draw, const void* text, size_t len,
+ const SkPoint pos[], const SkPaint& paint,
+ const SkPath& path, const SkMatrix* matrix);
+#endif
+ virtual void drawVertices(const SkDraw&, SkCanvas::VertexMode, int vertexCount,
+ const SkPoint verts[], const SkPoint texs[],
+ const SkColor colors[], SkXfermode* xmode,
+ const uint16_t indices[], int indexCount,
+ const SkPaint& paint);
+ /** The SkDevice passed will be an SkDevice which was returned by a call to
+ onCreateCompatibleDevice on this device with kSaveLayer_Usage.
+ */
+ virtual void drawDevice(const SkDraw&, SkDevice*, int x, int y,
+ const SkPaint&);
+
+ /**
+ * On success (returns true), copy the device pixels into the bitmap.
+ * On failure, the bitmap parameter is left unchanged and false is
+ * returned.
+ *
+ * The device's pixels are converted to the bitmap's config. The only
+ * supported config is kARGB_8888_Config, though this is likely to be
+ * relaxed in the future. The meaning of config kARGB_8888_Config is
+ * modified by the enum param config8888. The default value interprets
+ * kARGB_8888_Config as SkPMColor
+ *
+ * If the bitmap has pixels already allocated, the device pixels will be
+ * written there. If not, bitmap->allocPixels() will be called
+ * automatically. If the bitmap is backed by a texture readPixels will
+ * fail.
+ *
+ * The actual pixels written is the intersection of the device's bounds,
+ * and the rectangle formed by the bitmap's width,height and the specified
+ * x,y. If bitmap pixels extend outside of that intersection, they will not
+ * be modified.
+ *
+ * Other failure conditions:
+ * * If the device is not a raster device (e.g. PDF) then readPixels will
+ * fail.
+ * * If bitmap is texture-backed then readPixels will fail. (This may be
+ * relaxed in the future.)
+ */
+ bool readPixels(SkBitmap* bitmap,
+ int x, int y,
+ SkCanvas::Config8888 config8888);
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ /** Update as needed the pixel value in the bitmap, so that the caller can
+ access the pixels directly. Note: only the pixels field should be
+ altered. The config/width/height/rowbytes must remain unchanged.
+ @param bitmap The device's bitmap
+ @return Echo the bitmap parameter, or an alternate (shadow) bitmap
+ maintained by the subclass.
+ */
+ virtual const SkBitmap& onAccessBitmap(SkBitmap*);
+
+ SkPixelRef* getPixelRef() const { return fBitmap.pixelRef(); }
+ // just for subclasses, to assign a custom pixelref
+ SkPixelRef* setPixelRef(SkPixelRef* pr, size_t offset) {
+ fBitmap.setPixelRef(pr, offset);
+ return pr;
+ }
+
+ /**
+ * Implements readPixels API. The caller will ensure that:
+ * 1. bitmap has pixel config kARGB_8888_Config.
+ * 2. bitmap has pixels.
+ * 3. The rectangle (x, y, x + bitmap->width(), y + bitmap->height()) is
+ * contained in the device bounds.
+ */
+ virtual bool onReadPixels(const SkBitmap& bitmap,
+ int x, int y,
+ SkCanvas::Config8888 config8888);
+
+ /** Called when this device is installed into a Canvas. Balanaced by a call
+ to unlockPixels() when the device is removed from a Canvas.
+ */
+ virtual void lockPixels();
+ virtual void unlockPixels();
+
+ /**
+ * Returns true if the device allows processing of this imagefilter. If
+ * false is returned, then the filter is ignored. This may happen for
+ * some subclasses that do not support pixel manipulations after drawing
+ * has occurred (e.g. printing). The default implementation returns true.
+ */
+ virtual bool allowImageFilter(SkImageFilter*);
+
+ /**
+ * Override and return true for filters that the device can handle
+ * intrinsically. Doing so means that SkCanvas will pass-through this
+ * filter to drawSprite and drawDevice (and potentially filterImage).
+ * Returning false means the SkCanvas will have apply the filter itself,
+ * and just pass the resulting image to the device.
+ */
+ virtual bool canHandleImageFilter(SkImageFilter*);
+
+ /**
+ * Related (but not required) to canHandleImageFilter, this method returns
+ * true if the device could apply the filter to the src bitmap and return
+ * the result (and updates offset as needed).
+ * If the device does not recognize or support this filter,
+ * it just returns false and leaves result and offset unchanged.
+ */
+ virtual bool filterImage(SkImageFilter*, const SkBitmap&, const SkMatrix&,
+ SkBitmap* result, SkIPoint* offset);
+
+ // This is equal kBGRA_Premul_Config8888 or kRGBA_Premul_Config8888 if
+ // either is identical to kNative_Premul_Config8888. Otherwise, -1.
+ static const SkCanvas::Config8888 kPMColorAlias;
+
+private:
+ friend class SkCanvas;
+ friend struct DeviceCM; //for setMatrixClip
+ friend class SkDraw;
+ friend class SkDrawIter;
+ friend class SkDeviceFilteredPaint;
+ friend class SkDeviceImageFilterProxy;
+
+ friend class SkSurface_Raster;
+ // used to change the backend's pixels (and possibly config/rowbytes)
+ // but cannot change the width/height, so there should be no change to
+ // any clip information.
+ void replaceBitmapBackendForRasterSurface(const SkBitmap&);
+
+ // just called by SkCanvas when built as a layer
+ void setOrigin(int x, int y) { fOrigin.set(x, y); }
+ // just called by SkCanvas for saveLayer
+ SkDevice* createCompatibleDeviceForSaveLayer(SkBitmap::Config config,
+ int width, int height,
+ bool isOpaque);
+
+ /**
+ * Subclasses should override this to implement createCompatibleDevice.
+ */
+ virtual SkDevice* onCreateCompatibleDevice(SkBitmap::Config config,
+ int width, int height,
+ bool isOpaque,
+ Usage usage);
+
+ /** Causes any deferred drawing to the device to be completed.
+ */
+ virtual void flush() {}
+
+ SkBitmap fBitmap;
+ SkIPoint fOrigin;
+ SkMetaData* fMetaData;
+ /**
+ * Leaky properties are those which the device should be applying but it isn't.
+ * These properties will be applied by the draw, when and as it can.
+ * If the device does handle a property, that property should be set to the identity value
+ * for that property, effectively making it non-leaky.
+ */
+ SkDeviceProperties fLeakyProperties;
+
+#ifdef SK_DEBUG
+ bool fAttachedToCanvas;
+#endif
+
+ typedef SkRefCnt INHERITED;
+};
+
+#endif
diff --git a/core/SkDeviceProperties.h b/core/SkDeviceProperties.h
new file mode 100644
index 0000000..fd573f4
--- /dev/null
+++ b/core/SkDeviceProperties.h
@@ -0,0 +1,112 @@
+#ifndef SkDeviceProperties_DEFINED
+#define SkDeviceProperties_DEFINED
+
+#ifndef SK_GAMMA_EXPONENT
+ #define SK_GAMMA_EXPONENT (2.2f)
+#endif
+
+#ifdef SK_GAMMA_SRGB
+ #undef SK_GAMMA_EXPONENT
+ #define SK_GAMMA_EXPONENT (0.0f)
+#endif
+
+//TODO: get everyone to stop using SkFontLCDConfig::SetSubpixel* and remove this import.
+#include "SkFontLCDConfig.h"
+
+struct SkDeviceProperties {
+ struct Geometry {
+ /** The orientation of the pixel specifies the interpretation of the
+ * layout. If the orientation is horizontal, the layout is interpreted as
+ * left to right. It the orientation is vertical, the layout is
+ * interpreted top to bottom (rotated 90deg cw from horizontal).
+ */
+ enum Orientation {
+ kUnknown_Orientation = 0x0,
+ kKnown_Orientation = 0x2,
+
+ kHorizontal_Orientation = 0x2, //!< this is the default
+ kVertical_Orientation = 0x3,
+
+ kOrientationMask = 0x3,
+ };
+
+ /** The layout of the pixel specifies its subpixel geometry.
+ *
+ * kUnknown_Layout means that the subpixel elements are not spatially
+ * separated in any known or usable fashion.
+ */
+ enum Layout {
+ kUnknown_Layout = 0x0,
+ kKnown_Layout = 0x8,
+
+ kRGB_Layout = 0x8, //!< this is the default
+ kBGR_Layout = 0xC,
+
+ kLayoutMask = 0xC,
+ };
+
+ Orientation getOrientation() {
+ return static_cast<Orientation>(fGeometry & kOrientationMask);
+ }
+ Layout getLayout() {
+ return static_cast<Layout>(fGeometry & kLayoutMask);
+ }
+
+ bool isOrientationKnown() {
+ return SkToBool(fGeometry & kKnown_Orientation);
+ }
+ bool isLayoutKnown() {
+ return SkToBool(fGeometry & kKnown_Layout);
+ }
+
+ private:
+ //TODO: get everyone to stop using SkFontLCDConfig::SetSubpixel* and replace these calls with constants.
+ static Orientation fromOldOrientation(SkFontLCDConfig::LCDOrientation orientation) {
+ switch (orientation) {
+ case SkFontLCDConfig::kHorizontal_LCDOrientation: return kHorizontal_Orientation;
+ case SkFontLCDConfig::kVertical_LCDOrientation: return kVertical_Orientation;
+ default: return kUnknown_Orientation;
+ }
+ }
+ static Layout fromOldLayout(SkFontLCDConfig::LCDOrder order) {
+ switch (order) {
+ case SkFontLCDConfig::kRGB_LCDOrder: return kRGB_Layout;
+ case SkFontLCDConfig::kBGR_LCDOrder: return kBGR_Layout;
+ default: return kUnknown_Layout;
+ }
+ }
+ public:
+ static Geometry MakeDefault() {
+ Orientation orientation = fromOldOrientation(SkFontLCDConfig::GetSubpixelOrientation()); //kHorizontal_Orientation
+ Layout layout = fromOldLayout(SkFontLCDConfig::GetSubpixelOrder()); //kRGB_Layout
+ Geometry ret = { SkToU8(orientation | layout) };
+ return ret;
+ }
+
+ static Geometry Make(Orientation orientation, Layout layout) {
+ Geometry ret = { SkToU8(orientation | layout) };
+ return ret;
+ }
+
+ uint8_t fGeometry;
+ };
+
+ static SkDeviceProperties MakeDefault() {
+ SkDeviceProperties ret = { Geometry::MakeDefault(), SK_GAMMA_EXPONENT };
+ return ret;
+ }
+
+ static SkDeviceProperties Make(Geometry geometry, SkScalar gamma) {
+ SkDeviceProperties ret = { geometry, gamma };
+ return ret;
+ }
+
+ /** Each pixel of an image will have some number of channels.
+ * Can the layout of those channels be exploited? */
+ Geometry fGeometry;
+
+ /** Represents the color space of the image. This is a woefully inadequate beginning. */
+ SkScalar fGamma;
+};
+
+#endif
diff --git a/core/SkDither.h b/core/SkDither.h
new file mode 100644
index 0000000..d82b416
--- /dev/null
+++ b/core/SkDither.h
@@ -0,0 +1,198 @@
+
+/*
+ * Copyright 2008 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkDither_DEFINED
+#define SkDither_DEFINED
+
+#include "SkColorPriv.h"
+
+#define SK_DitherValueMax4444 15
+#define SK_DitherValueMax565 7
+
+/* need to use macros for bit-counts for each component, and then
+ move these into SkColorPriv.h
+*/
+
+#define SkDITHER_R32_FOR_565_MACRO(r, d) (r + d - (r >> 5))
+#define SkDITHER_G32_FOR_565_MACRO(g, d) (g + (d >> 1) - (g >> 6))
+#define SkDITHER_B32_FOR_565_MACRO(b, d) (b + d - (b >> 5))
+
+#define SkDITHER_A32_FOR_4444_MACRO(a, d) (a + 15 - (a >> 4))
+#define SkDITHER_R32_FOR_4444_MACRO(r, d) (r + d - (r >> 4))
+#define SkDITHER_G32_FOR_4444_MACRO(g, d) (g + d - (g >> 4))
+#define SkDITHER_B32_FOR_4444_MACRO(b, d) (b + d - (b >> 4))
+
+#ifdef SK_DEBUG
+ inline unsigned SkDITHER_R32_FOR_565(unsigned r, unsigned d)
+ {
+ SkASSERT(d <= SK_DitherValueMax565);
+ SkA32Assert(r);
+ r = SkDITHER_R32_FOR_565_MACRO(r, d);
+ SkA32Assert(r);
+ return r;
+ }
+ inline unsigned SkDITHER_G32_FOR_565(unsigned g, unsigned d)
+ {
+ SkASSERT(d <= SK_DitherValueMax565);
+ SkG32Assert(g);
+ g = SkDITHER_G32_FOR_565_MACRO(g, d);
+ SkG32Assert(g);
+ return g;
+ }
+ inline unsigned SkDITHER_B32_FOR_565(unsigned b, unsigned d)
+ {
+ SkASSERT(d <= SK_DitherValueMax565);
+ SkB32Assert(b);
+ b = SkDITHER_B32_FOR_565_MACRO(b, d);
+ SkB32Assert(b);
+ return b;
+ }
+#else
+ #define SkDITHER_R32_FOR_565(r, d) SkDITHER_R32_FOR_565_MACRO(r, d)
+ #define SkDITHER_G32_FOR_565(g, d) SkDITHER_G32_FOR_565_MACRO(g, d)
+ #define SkDITHER_B32_FOR_565(b, d) SkDITHER_B32_FOR_565_MACRO(b, d)
+#endif
+
+#define SkDITHER_R32To565(r, d) SkR32ToR16(SkDITHER_R32_FOR_565(r, d))
+#define SkDITHER_G32To565(g, d) SkG32ToG16(SkDITHER_G32_FOR_565(g, d))
+#define SkDITHER_B32To565(b, d) SkB32ToB16(SkDITHER_B32_FOR_565(b, d))
+
+#define SkDITHER_A32To4444(a, d) SkA32To4444(SkDITHER_A32_FOR_4444_MACRO(a, d))
+#define SkDITHER_R32To4444(r, d) SkR32To4444(SkDITHER_R32_FOR_4444_MACRO(r, d))
+#define SkDITHER_G32To4444(g, d) SkG32To4444(SkDITHER_G32_FOR_4444_MACRO(g, d))
+#define SkDITHER_B32To4444(b, d) SkB32To4444(SkDITHER_B32_FOR_4444_MACRO(b, d))
+
+static inline SkPMColor SkDitherARGB32For565(SkPMColor c, unsigned dither)
+{
+ SkASSERT(dither <= SK_DitherValueMax565);
+
+ unsigned sa = SkGetPackedA32(c);
+ dither = SkAlphaMul(dither, SkAlpha255To256(sa));
+
+ unsigned sr = SkGetPackedR32(c);
+ unsigned sg = SkGetPackedG32(c);
+ unsigned sb = SkGetPackedB32(c);
+ sr = SkDITHER_R32_FOR_565(sr, dither);
+ sg = SkDITHER_G32_FOR_565(sg, dither);
+ sb = SkDITHER_B32_FOR_565(sb, dither);
+
+ return SkPackARGB32(sa, sr, sg, sb);
+}
+
+static inline SkPMColor SkDitherRGB32For565(SkPMColor c, unsigned dither)
+{
+ SkASSERT(dither <= SK_DitherValueMax565);
+
+ unsigned sr = SkGetPackedR32(c);
+ unsigned sg = SkGetPackedG32(c);
+ unsigned sb = SkGetPackedB32(c);
+ sr = SkDITHER_R32_FOR_565(sr, dither);
+ sg = SkDITHER_G32_FOR_565(sg, dither);
+ sb = SkDITHER_B32_FOR_565(sb, dither);
+
+ return SkPackARGB32(0xFF, sr, sg, sb);
+}
+
+static inline uint16_t SkDitherRGBTo565(U8CPU r, U8CPU g, U8CPU b,
+ unsigned dither)
+{
+ SkASSERT(dither <= SK_DitherValueMax565);
+ r = SkDITHER_R32To565(r, dither);
+ g = SkDITHER_G32To565(g, dither);
+ b = SkDITHER_B32To565(b, dither);
+ return SkPackRGB16(r, g, b);
+}
+
+static inline uint16_t SkDitherRGB32To565(SkPMColor c, unsigned dither)
+{
+ SkASSERT(dither <= SK_DitherValueMax565);
+
+ unsigned sr = SkGetPackedR32(c);
+ unsigned sg = SkGetPackedG32(c);
+ unsigned sb = SkGetPackedB32(c);
+ sr = SkDITHER_R32To565(sr, dither);
+ sg = SkDITHER_G32To565(sg, dither);
+ sb = SkDITHER_B32To565(sb, dither);
+
+ return SkPackRGB16(sr, sg, sb);
+}
+
+static inline uint16_t SkDitherARGB32To565(U8CPU sa, SkPMColor c, unsigned dither)
+{
+ SkASSERT(dither <= SK_DitherValueMax565);
+ dither = SkAlphaMul(dither, SkAlpha255To256(sa));
+
+ unsigned sr = SkGetPackedR32(c);
+ unsigned sg = SkGetPackedG32(c);
+ unsigned sb = SkGetPackedB32(c);
+ sr = SkDITHER_R32To565(sr, dither);
+ sg = SkDITHER_G32To565(sg, dither);
+ sb = SkDITHER_B32To565(sb, dither);
+
+ return SkPackRGB16(sr, sg, sb);
+}
+
+///////////////////////// 4444
+
+static inline SkPMColor16 SkDitherARGB32To4444(U8CPU a, U8CPU r, U8CPU g,
+ U8CPU b, unsigned dither)
+{
+ dither = SkAlphaMul(dither, SkAlpha255To256(a));
+
+ a = SkDITHER_A32To4444(a, dither);
+ r = SkDITHER_R32To4444(r, dither);
+ g = SkDITHER_G32To4444(g, dither);
+ b = SkDITHER_B32To4444(b, dither);
+
+ return SkPackARGB4444(a, r, g, b);
+}
+
+static inline SkPMColor16 SkDitherARGB32To4444(SkPMColor c, unsigned dither)
+{
+ unsigned a = SkGetPackedA32(c);
+ unsigned r = SkGetPackedR32(c);
+ unsigned g = SkGetPackedG32(c);
+ unsigned b = SkGetPackedB32(c);
+
+ dither = SkAlphaMul(dither, SkAlpha255To256(a));
+
+ a = SkDITHER_A32To4444(a, dither);
+ r = SkDITHER_R32To4444(r, dither);
+ g = SkDITHER_G32To4444(g, dither);
+ b = SkDITHER_B32To4444(b, dither);
+
+ return SkPackARGB4444(a, r, g, b);
+}
+
+// TODO: need dither routines for 565 -> 4444
+
+// this toggles between a 4x4 and a 1x4 array
+//#define ENABLE_DITHER_MATRIX_4X4
+
+#ifdef ENABLE_DITHER_MATRIX_4X4
+ extern const uint8_t gDitherMatrix_4Bit_4X4[4][4];
+ extern const uint8_t gDitherMatrix_3Bit_4X4[4][4];
+
+ #define DITHER_4444_SCAN(y) const uint8_t* dither_scan = gDitherMatrix_4Bit_4X4[(y) & 3]
+ #define DITHER_565_SCAN(y) const uint8_t* dither_scan = gDitherMatrix_3Bit_4X4[(y) & 3]
+
+ #define DITHER_VALUE(x) dither_scan[(x) & 3]
+#else
+ extern const uint16_t gDitherMatrix_4Bit_16[4];
+ extern const uint16_t gDitherMatrix_3Bit_16[4];
+
+ #define DITHER_4444_SCAN(y) const uint16_t dither_scan = gDitherMatrix_4Bit_16[(y) & 3]
+ #define DITHER_565_SCAN(y) const uint16_t dither_scan = gDitherMatrix_3Bit_16[(y) & 3]
+
+ #define DITHER_VALUE(x) ((dither_scan >> (((x) & 3) << 2)) & 0xF)
+#endif
+
+#define DITHER_INC_X(x) ++(x)
+
+#endif
diff --git a/core/SkDocument.h b/core/SkDocument.h
new file mode 100644
index 0000000..bbed64a
--- /dev/null
+++ b/core/SkDocument.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkDocument_DEFINED
+#define SkDocument_DEFINED
+
+#include "SkRect.h"
+#include "SkRefCnt.h"
+
+class SkCanvas;
+class SkWStream;
+
+/**
+ * High-level API for creating a document-based canvas. To use..
+ *
+ * 1. Create a document, specifying a stream to store the output.
+ * 2. For each "page" of content:
+ * a. canvas = doc->beginPage(...)
+ * b. draw_my_content(canvas);
+ * c. doc->endPage();
+ * 3. Close the document with doc->close().
+ */
+class SkDocument : public SkRefCnt {
+public:
+ SK_DECLARE_INST_COUNT(SkDocument)
+
+ /**
+ * Create a PDF-backed document, writing the results into a file.
+ * If there is an error trying to create the doc, returns NULL.
+ */
+ static SkDocument* CreatePDF(const char filename[]);
+
+ /**
+ * Create a PDF-backed document, writing the results into a stream.
+ * If there is an error trying to create the doc, returns NULL.
+ *
+ * The document may write to the stream at anytime during its lifetime,
+ * until either close() is called or the document is deleted. Once close()
+ * has been called, and all of the data has been written to the stream,
+ * if there is a Done proc provided, it will be called with the stream.
+ * The proc can delete the stream, or whatever it needs to do.
+ */
+ static SkDocument* CreatePDF(SkWStream*, void (*Done)(SkWStream*) = NULL);
+
+ /**
+ * Begin a new page for the document, returning the canvas that will draw
+ * into the page. The document owns this canvas, and it will go out of
+ * scope when endPage() or close() is called, or the document is deleted.
+ */
+ SkCanvas* beginPage(SkScalar width, SkScalar height,
+ const SkRect* content = NULL);
+
+ /**
+ * Call endPage() when the content for the current page has been drawn
+ * (into the canvas returned by beginPage()). After this call the canvas
+ * returned by beginPage() will be out-of-scope.
+ */
+ void endPage();
+
+ /**
+ * Call close() when all pages have been drawn. This will close the file
+ * or stream holding the document's contents. After close() the document
+ * can no longer add new pages. Deleting the document will automatically
+ * call close() if need be.
+ */
+ void close();
+
+protected:
+ SkDocument(SkWStream*, void (*)(SkWStream*));
+ // note: subclasses must call close() in their destructor, as the base class
+ // cannot do this for them.
+ virtual ~SkDocument();
+
+ virtual SkCanvas* onBeginPage(SkScalar width, SkScalar height,
+ const SkRect& content) = 0;
+ virtual void onEndPage() = 0;
+ virtual void onClose(SkWStream*) = 0;
+
+ enum State {
+ kBetweenPages_State,
+ kInPage_State,
+ kClosed_State
+ };
+ State getState() const { return fState; }
+
+private:
+ SkWStream* fStream;
+ void (*fDoneProc)(SkWStream*);
+ State fState;
+
+ typedef SkRefCnt INHERITED;
+};
+
+#endif
diff --git a/core/SkDraw.h b/core/SkDraw.h
new file mode 100644
index 0000000..8642f0a
--- /dev/null
+++ b/core/SkDraw.h
@@ -0,0 +1,141 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkDraw_DEFINED
+#define SkDraw_DEFINED
+
+#include "SkCanvas.h"
+#include "SkMask.h"
+#include "SkPaint.h"
+
+class SkBitmap;
+class SkBounder;
+class SkClipStack;
+class SkDevice;
+class SkMatrix;
+class SkPath;
+class SkRegion;
+class SkRasterClip;
+struct SkDrawProcs;
+struct SkRect;
+
+class SkDraw {
+public:
+ SkDraw();
+ SkDraw(const SkDraw& src);
+
+ void drawPaint(const SkPaint&) const;
+ void drawPoints(SkCanvas::PointMode, size_t count, const SkPoint[],
+ const SkPaint&, bool forceUseDevice = false) const;
+ void drawRect(const SkRect&, const SkPaint&) const;
+ /**
+ * To save on mallocs, we allow a flag that tells us that srcPath is
+ * mutable, so that we don't have to make copies of it as we transform it.
+ *
+ * If prePathMatrix is not null, it should logically be applied before any
+ * stroking or other effects. If there are no effects on the paint that
+ * affect the geometry/rasterization, then the pre matrix can just be
+ * pre-concated with the current matrix.
+ */
+ void drawPath(const SkPath& srcPath, const SkPaint&,
+ const SkMatrix* prePathMatrix, bool pathIsMutable) const;
+ void drawBitmap(const SkBitmap&, const SkMatrix&, const SkPaint&) const;
+ void drawSprite(const SkBitmap&, int x, int y, const SkPaint&) const;
+ void drawText(const char text[], size_t byteLength, SkScalar x,
+ SkScalar y, const SkPaint& paint) const;
+ void drawPosText(const char text[], size_t byteLength,
+ const SkScalar pos[], SkScalar constY,
+ int scalarsPerPosition, const SkPaint& paint) const;
+ void drawTextOnPath(const char text[], size_t byteLength,
+ const SkPath&, const SkMatrix*, const SkPaint&) const;
+#ifdef SK_BUILD_FOR_ANDROID
+ void drawPosTextOnPath(const char text[], size_t byteLength,
+ const SkPoint pos[], const SkPaint& paint,
+ const SkPath& path, const SkMatrix* matrix) const;
+#endif
+ void drawVertices(SkCanvas::VertexMode mode, int count,
+ const SkPoint vertices[], const SkPoint textures[],
+ const SkColor colors[], SkXfermode* xmode,
+ const uint16_t indices[], int ptCount,
+ const SkPaint& paint) const;
+
+ void drawPath(const SkPath& src, const SkPaint& paint) const {
+ this->drawPath(src, paint, NULL, false);
+ }
+
+ /** Helper function that creates a mask from a path and an optional maskfilter.
+ Note however, that the resulting mask will not have been actually filtered,
+ that must be done afterwards (by calling filterMask). The maskfilter is provided
+ solely to assist in computing the mask's bounds (if the mode requests that).
+ */
+ static bool DrawToMask(const SkPath& devPath, const SkIRect* clipBounds,
+ const SkMaskFilter*, const SkMatrix* filterMatrix,
+ SkMask* mask, SkMask::CreateMode mode,
+ SkPaint::Style style);
+
+ enum RectType {
+ kHair_RectType,
+ kFill_RectType,
+ kStroke_RectType,
+ kPath_RectType
+ };
+
+ /**
+ * Based on the paint's style, strokeWidth, and the matrix, classify how
+ * to draw the rect. If no special-case is available, returns
+ * kPath_RectType.
+ *
+ * Iff RectType == kStroke_RectType, then strokeSize is set to the device
+ * width and height of the stroke.
+ */
+ static RectType ComputeRectType(const SkPaint&, const SkMatrix&,
+ SkPoint* strokeSize);
+
+private:
+ void drawText_asPaths(const char text[], size_t byteLength,
+ SkScalar x, SkScalar y, const SkPaint&) const;
+ void drawDevMask(const SkMask& mask, const SkPaint&) const;
+ void drawBitmapAsMask(const SkBitmap&, const SkPaint&) const;
+
+ void drawPosText_asPaths(const char text[], size_t byteLength,
+ const SkScalar pos[], SkScalar constY,
+ int scalarsPerPosition, const SkPaint&) const;
+
+ /**
+ * Return the current clip bounds, in local coordinates, with slop to account
+ * for antialiasing or hairlines (i.e. device-bounds outset by 1, and then
+ * run through the inverse of the matrix).
+ *
+ * If the matrix cannot be inverted, or the current clip is empty, return
+ * false and ignore bounds parameter.
+ */
+ bool SK_WARN_UNUSED_RESULT
+ computeConservativeLocalClipBounds(SkRect* bounds) const;
+
+ static bool ShouldDrawTextAsPaths(const SkPaint&, const SkMatrix&);
+
+public:
+ const SkBitmap* fBitmap; // required
+ const SkMatrix* fMatrix; // required
+ const SkRegion* fClip; // DEPRECATED
+ const SkRasterClip* fRC; // required
+
+ const SkClipStack* fClipStack; // optional
+ SkDevice* fDevice; // optional
+ SkBounder* fBounder; // optional
+ SkDrawProcs* fProcs; // optional
+
+#ifdef SK_DEBUG
+ void validate() const;
+#else
+ void validate() const {}
+#endif
+};
+
+#endif
diff --git a/core/SkDrawFilter.h b/core/SkDrawFilter.h
new file mode 100644
index 0000000..52cbba9
--- /dev/null
+++ b/core/SkDrawFilter.h
@@ -0,0 +1,55 @@
+
+/*
+ * Copyright 2011 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkDrawFilter_DEFINED
+#define SkDrawFilter_DEFINED
+
+#include "SkRefCnt.h"
+
+class SkCanvas;
+class SkPaint;
+
+/**
+ * Right before something is being draw, filter() is called with the
+ * paint. The filter may modify the paint as it wishes, which will then be
+ * used for the actual drawing. Note: this modification only lasts for the
+ * current draw, as a temporary copy of the paint is used.
+ */
+class SK_API SkDrawFilter : public SkRefCnt {
+public:
+ SK_DECLARE_INST_COUNT(SkDrawFilter)
+
+ enum Type {
+ kPaint_Type,
+ kPoint_Type,
+ kLine_Type,
+ kBitmap_Type,
+ kRect_Type,
+ kRRect_Type,
+ kOval_Type,
+ kPath_Type,
+ kText_Type,
+ };
+
+ enum {
+ kTypeCount = kText_Type + 1
+ };
+
+ /**
+ * Called with the paint that will be used to draw the specified type.
+ * The implementation may modify the paint as they wish. If filter()
+ * returns false, the draw will be skipped.
+ */
+ virtual bool filter(SkPaint*, Type) = 0;
+
+private:
+ typedef SkRefCnt INHERITED;
+};
+
+#endif
diff --git a/core/SkDrawLooper.h b/core/SkDrawLooper.h
new file mode 100644
index 0000000..2faf28b
--- /dev/null
+++ b/core/SkDrawLooper.h
@@ -0,0 +1,76 @@
+
+/*
+ * Copyright 2011 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkDrawLooper_DEFINED
+#define SkDrawLooper_DEFINED
+
+#include "SkFlattenable.h"
+
+class SkCanvas;
+class SkPaint;
+struct SkRect;
+class SkString;
+
+/** \class SkDrawLooper
+ Subclasses of SkDrawLooper can be attached to a SkPaint. Where they are,
+ and something is drawn to a canvas with that paint, the looper subclass will
+ be called, allowing it to modify the canvas and/or paint for that draw call.
+ More than that, via the next() method, the looper can modify the draw to be
+ invoked multiple times (hence the name loop-er), allow it to perform effects
+ like shadows or frame/fills, that require more than one pass.
+*/
+class SK_API SkDrawLooper : public SkFlattenable {
+public:
+ SK_DECLARE_INST_COUNT(SkDrawLooper)
+
+ /**
+ * Called right before something is being drawn. This will be followed by
+ * calls to next() until next() returns false.
+ */
+ virtual void init(SkCanvas*) = 0;
+
+ /**
+ * Called in a loop (after init()). Each time true is returned, the object
+ * is drawn (possibly with a modified canvas and/or paint). When false is
+ * finally returned, drawing for the object stops.
+ *
+ * On each call, the paint will be in its original state, but the canvas
+ * will be as it was following the previous call to next() or init().
+ *
+ * The implementation must ensure that, when next() finally returns false,
+ * that the canvas has been restored to the state it was initially, before
+ * init() was first called.
+ */
+ virtual bool next(SkCanvas*, SkPaint* paint) = 0;
+
+ /**
+ * The fast bounds functions are used to enable the paint to be culled early
+ * in the drawing pipeline. If a subclass can support this feature it must
+ * return true for the canComputeFastBounds() function. If that function
+ * returns false then computeFastBounds behavior is undefined otherwise it
+ * is expected to have the following behavior. Given the parent paint and
+ * the parent's bounding rect the subclass must fill in and return the
+ * storage rect, where the storage rect is with the union of the src rect
+ * and the looper's bounding rect.
+ */
+ virtual bool canComputeFastBounds(const SkPaint& paint);
+ virtual void computeFastBounds(const SkPaint& paint,
+ const SkRect& src, SkRect* dst);
+
+ SkDEVCODE(virtual void toString(SkString* str) const = 0;)
+
+protected:
+ SkDrawLooper() {}
+ SkDrawLooper(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {}
+
+private:
+ typedef SkFlattenable INHERITED;
+};
+
+#endif
diff --git a/core/SkEmptyShader.h b/core/SkEmptyShader.h
new file mode 100644
index 0000000..08c131d
--- /dev/null
+++ b/core/SkEmptyShader.h
@@ -0,0 +1,43 @@
+
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+
+#ifndef SkEmptyShader_DEFINED
+#define SkEmptyShader_DEFINED
+
+#include "SkShader.h"
+
+/**
+ * \class SkEmptyShader
+ * A Shader that always draws nothing. Its setContext always returns false,
+ * so it never expects that its shadeSpan() methods will get called.
+ */
+class SK_API SkEmptyShader : public SkShader {
+public:
+ SkEmptyShader() {}
+
+ virtual uint32_t getFlags() SK_OVERRIDE;
+ virtual uint8_t getSpan16Alpha() const SK_OVERRIDE;
+ virtual bool setContext(const SkBitmap&, const SkPaint&,
+ const SkMatrix&) SK_OVERRIDE;
+ virtual void shadeSpan(int x, int y, SkPMColor span[], int count) SK_OVERRIDE;
+ virtual void shadeSpan16(int x, int y, uint16_t span[], int count) SK_OVERRIDE;
+ virtual void shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) SK_OVERRIDE;
+
+ SK_DEVELOPER_TO_STRING()
+ SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkEmptyShader)
+
+protected:
+ SkEmptyShader(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {}
+
+private:
+ typedef SkShader INHERITED;
+};
+
+#endif
diff --git a/core/SkEndian.h b/core/SkEndian.h
new file mode 100644
index 0000000..6eba297
--- /dev/null
+++ b/core/SkEndian.h
@@ -0,0 +1,195 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkEndian_DEFINED
+#define SkEndian_DEFINED
+
+#include "SkTypes.h"
+
+/** \file SkEndian.h
+
+ Macros and helper functions for handling 16 and 32 bit values in
+ big and little endian formats.
+*/
+
+#if defined(SK_CPU_LENDIAN) && defined(SK_CPU_BENDIAN)
+ #error "can't have both LENDIAN and BENDIAN defined"
+#endif
+
+#if !defined(SK_CPU_LENDIAN) && !defined(SK_CPU_BENDIAN)
+ #error "need either LENDIAN or BENDIAN defined"
+#endif
+
+/** Swap the two bytes in the low 16bits of the parameters.
+ e.g. 0x1234 -> 0x3412
+*/
+static inline uint16_t SkEndianSwap16(U16CPU value) {
+ SkASSERT(value == (uint16_t)value);
+ return static_cast<uint16_t>((value >> 8) | (value << 8));
+}
+template<uint16_t N> struct SkTEndianSwap16 {
+ static const uint16_t value = static_cast<uint16_t>((N >> 8) | ((N & 0xFF) << 8));
+};
+
+/** Vector version of SkEndianSwap16(), which swaps the
+ low two bytes of each value in the array.
+*/
+static inline void SkEndianSwap16s(uint16_t array[], int count) {
+ SkASSERT(count == 0 || array != NULL);
+
+ while (--count >= 0) {
+ *array = SkEndianSwap16(*array);
+ array += 1;
+ }
+}
+
+/** Reverse all 4 bytes in a 32bit value.
+ e.g. 0x12345678 -> 0x78563412
+*/
+static inline uint32_t SkEndianSwap32(uint32_t value) {
+ return ((value & 0xFF) << 24) |
+ ((value & 0xFF00) << 8) |
+ ((value & 0xFF0000) >> 8) |
+ (value >> 24);
+}
+template<uint32_t N> struct SkTEndianSwap32 {
+ static const uint32_t value = ((N & 0xFF) << 24) |
+ ((N & 0xFF00) << 8) |
+ ((N & 0xFF0000) >> 8) |
+ (N >> 24);
+};
+
+/** Vector version of SkEndianSwap32(), which swaps the
+ bytes of each value in the array.
+*/
+static inline void SkEndianSwap32s(uint32_t array[], int count) {
+ SkASSERT(count == 0 || array != NULL);
+
+ while (--count >= 0) {
+ *array = SkEndianSwap32(*array);
+ array += 1;
+ }
+}
+
+/** Reverse all 8 bytes in a 64bit value.
+ e.g. 0x1122334455667788 -> 0x8877665544332211
+*/
+static inline uint64_t SkEndianSwap64(uint64_t value) {
+ return (((value & 0x00000000000000FFULL) << (8*7)) |
+ ((value & 0x000000000000FF00ULL) << (8*5)) |
+ ((value & 0x0000000000FF0000ULL) << (8*3)) |
+ ((value & 0x00000000FF000000ULL) << (8*1)) |
+ ((value & 0x000000FF00000000ULL) >> (8*1)) |
+ ((value & 0x0000FF0000000000ULL) >> (8*3)) |
+ ((value & 0x00FF000000000000ULL) >> (8*5)) |
+ ((value) >> (8*7)));
+}
+template<uint64_t N> struct SkTEndianSwap64 {
+ static const uint64_t value = (((N & 0x00000000000000FFULL) << (8*7)) |
+ ((N & 0x000000000000FF00ULL) << (8*5)) |
+ ((N & 0x0000000000FF0000ULL) << (8*3)) |
+ ((N & 0x00000000FF000000ULL) << (8*1)) |
+ ((N & 0x000000FF00000000ULL) >> (8*1)) |
+ ((N & 0x0000FF0000000000ULL) >> (8*3)) |
+ ((N & 0x00FF000000000000ULL) >> (8*5)) |
+ ((N) >> (8*7)));
+};
+
+/** Vector version of SkEndianSwap64(), which swaps the
+ bytes of each value in the array.
+*/
+static inline void SkEndianSwap64s(uint64_t array[], int count) {
+ SkASSERT(count == 0 || array != NULL);
+
+ while (--count >= 0) {
+ *array = SkEndianSwap64(*array);
+ array += 1;
+ }
+}
+
+#ifdef SK_CPU_LENDIAN
+ #define SkEndian_SwapBE16(n) SkEndianSwap16(n)
+ #define SkEndian_SwapBE32(n) SkEndianSwap32(n)
+ #define SkEndian_SwapBE64(n) SkEndianSwap64(n)
+ #define SkEndian_SwapLE16(n) (n)
+ #define SkEndian_SwapLE32(n) (n)
+ #define SkEndian_SwapLE64(n) (n)
+
+ #define SkTEndian_SwapBE16(n) SkTEndianSwap16<n>::value
+ #define SkTEndian_SwapBE32(n) SkTEndianSwap32<n>::value
+ #define SkTEndian_SwapBE64(n) SkTEndianSwap64<n>::value
+ #define SkTEndian_SwapLE16(n) (n)
+ #define SkTEndian_SwapLE32(n) (n)
+ #define SkTEndian_SwapLE64(n) (n)
+#else // SK_CPU_BENDIAN
+ #define SkEndian_SwapBE16(n) (n)
+ #define SkEndian_SwapBE32(n) (n)
+ #define SkEndian_SwapBE64(n) (n)
+ #define SkEndian_SwapLE16(n) SkEndianSwap16(n)
+ #define SkEndian_SwapLE32(n) SkEndianSwap32(n)
+ #define SkEndian_SwapLE64(n) SkEndianSwap64(n)
+
+ #define SkTEndian_SwapBE16(n) (n)
+ #define SkTEndian_SwapBE32(n) (n)
+ #define SkTEndian_SwapBE64(n) (n)
+ #define SkTEndian_SwapLE16(n) SkTEndianSwap16<n>::value
+ #define SkTEndian_SwapLE32(n) SkTEndianSwap32<n>::value
+ #define SkTEndian_SwapLE64(n) SkTEndianSwap64<n>::value
+#endif
+
+// When a bytestream is embedded in a 32-bit word, how far we need to
+// shift the word to extract each byte from the low 8 bits by anding with 0xff.
+#ifdef SK_CPU_LENDIAN
+ #define SkEndian_Byte0Shift 0
+ #define SkEndian_Byte1Shift 8
+ #define SkEndian_Byte2Shift 16
+ #define SkEndian_Byte3Shift 24
+#else // SK_CPU_BENDIAN
+ #define SkEndian_Byte0Shift 24
+ #define SkEndian_Byte1Shift 16
+ #define SkEndian_Byte2Shift 8
+ #define SkEndian_Byte3Shift 0
+#endif
+
+
+#if defined(SK_UINT8_BITFIELD_LENDIAN) && defined(SK_UINT8_BITFIELD_BENDIAN)
+ #error "can't have both bitfield LENDIAN and BENDIAN defined"
+#endif
+
+#if !defined(SK_UINT8_BITFIELD_LENDIAN) && !defined(SK_UINT8_BITFIELD_BENDIAN)
+ #ifdef SK_CPU_LENDIAN
+ #define SK_UINT8_BITFIELD_LENDIAN
+ #else
+ #define SK_UINT8_BITFIELD_BENDIAN
+ #endif
+#endif
+
+#ifdef SK_UINT8_BITFIELD_LENDIAN
+ #define SK_UINT8_BITFIELD(f0, f1, f2, f3, f4, f5, f6, f7) \
+ SK_OT_BYTE f0 : 1; \
+ SK_OT_BYTE f1 : 1; \
+ SK_OT_BYTE f2 : 1; \
+ SK_OT_BYTE f3 : 1; \
+ SK_OT_BYTE f4 : 1; \
+ SK_OT_BYTE f5 : 1; \
+ SK_OT_BYTE f6 : 1; \
+ SK_OT_BYTE f7 : 1;
+#else
+ #define SK_UINT8_BITFIELD(f0, f1, f2, f3, f4, f5, f6, f7) \
+ SK_OT_BYTE f7 : 1; \
+ SK_OT_BYTE f6 : 1; \
+ SK_OT_BYTE f5 : 1; \
+ SK_OT_BYTE f4 : 1; \
+ SK_OT_BYTE f3 : 1; \
+ SK_OT_BYTE f2 : 1; \
+ SK_OT_BYTE f1 : 1; \
+ SK_OT_BYTE f0 : 1;
+#endif
+
+#endif
diff --git a/core/SkError.h b/core/SkError.h
new file mode 100644
index 0000000..c5af460
--- /dev/null
+++ b/core/SkError.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkError_DEFINED
+#define SkError_DEFINED
+
+
+/** \file SkError.h
+*/
+
+enum SkError {
+ /** All is well
+ */
+ kNoError_SkError=0,
+
+ /** User argument passed to Skia function was invalid: NULL when that’s
+ * not allowed, out of numeric range, bad enum, or violating some
+ * other general precondition.
+ */
+ kInvalidArgument_SkError,
+
+ /** User tried to perform some operation in a state when the operation
+ * was not legal, or the operands make no sense (e.g., asking for
+ * pixels from an SkPictureCanvas). Other examples might be
+ * inset()’ing a rectangle to make it degenerate (negative width/height).
+ */
+ kInvalidOperation_SkError,
+
+ /** Probably not needed right now, but in the future we could have opaque
+ * handles for SkPictures floating around, and it would be a good idea
+ * to anticipate this kind of issue.
+ */
+ kInvalidHandle_SkError,
+
+ /** This is probably not possible because paint surely has defaults for
+ * everything, but perhaps a paint can get into a bad state somehow.
+ */
+ kInvalidPaint_SkError,
+
+ /** Skia was unable to allocate memory to perform some task.
+ */
+ kOutOfMemory_SkError,
+
+ /** Skia failed while trying to consume some external resource.
+ */
+ kParseError_SkError
+};
+
+/** Return the current per-thread error code. Error codes are "sticky"; they
+ * are not not reset by subsequent successful operations.
+ */
+SkError SkGetLastError();
+
+/** Clear the current per-thread error code back to kNoError_SkError.
+ */
+void SkClearLastError();
+
+/** Type for callback functions to be invoked whenever an error is registered.
+ * Callback functions take the error code being set, as well as a context
+ * argument that is provided when the callback is registered.
+ */
+typedef void (*SkErrorCallbackFunction)(SkError, void *);
+
+/** Set the current per-thread error callback.
+ *
+ * @param cb The callback function to be invoked. Passing NULL
+ * for cb will revert to the default error callback which
+ * does nothing on release builds, but on debug builds will
+ * print an informative error message to the screen.
+ * @param context An arbitrary pointer that will be passed to
+ * the provided callback function.
+ */
+void SkSetErrorCallback(SkErrorCallbackFunction cb, void *context);
+
+/** Get a human-readable description of the last (per-thread) error that
+ * occurred. The returned error message will include not only a human
+ * readable version of the error code, but also information about the
+ * conditions that led to the error itself.
+ */
+const char *SkGetLastErrorString();
+
+#endif /* SkError_DEFINED */
diff --git a/core/SkFixed.h b/core/SkFixed.h
new file mode 100644
index 0000000..acfbe9a
--- /dev/null
+++ b/core/SkFixed.h
@@ -0,0 +1,291 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkFixed_DEFINED
+#define SkFixed_DEFINED
+
+#include "SkTypes.h"
+
+/** \file SkFixed.h
+
+ Types and macros for 16.16 fixed point
+*/
+
+/** 32 bit signed integer used to represent fractions values with 16 bits to the right of the decimal point
+*/
+typedef int32_t SkFixed;
+#define SK_Fixed1 (1 << 16)
+#define SK_FixedHalf (1 << 15)
+#define SK_FixedMax (0x7FFFFFFF)
+#define SK_FixedMin (-SK_FixedMax)
+#define SK_FixedNaN ((int) 0x80000000)
+#define SK_FixedPI (0x3243F)
+#define SK_FixedSqrt2 (92682)
+#define SK_FixedTanPIOver8 (0x6A0A)
+#define SK_FixedRoot2Over2 (0xB505)
+
+#define SkFixedToFloat(x) ((x) * 1.5258789e-5f)
+#if 1
+ #define SkFloatToFixed(x) ((SkFixed)((x) * SK_Fixed1))
+#else
+ // pins over/under flows to max/min int32 (slower than just a cast)
+ static inline SkFixed SkFloatToFixed(float x) {
+ int64_t n = x * SK_Fixed1;
+ return (SkFixed)n;
+ }
+#endif
+
+#ifdef SK_DEBUG
+ static inline SkFixed SkFloatToFixed_Check(float x) {
+ int64_t n64 = (int64_t)(x * SK_Fixed1);
+ SkFixed n32 = (SkFixed)n64;
+ SkASSERT(n64 == n32);
+ return n32;
+ }
+#else
+ #define SkFloatToFixed_Check(x) SkFloatToFixed(x)
+#endif
+
+#define SkFixedToDouble(x) ((x) * 1.5258789e-5)
+#define SkDoubleToFixed(x) ((SkFixed)((x) * SK_Fixed1))
+
+/** 32 bit signed integer used to represent fractions values with 30 bits to the right of the decimal point
+*/
+typedef int32_t SkFract;
+#define SK_Fract1 (1 << 30)
+#define Sk_FracHalf (1 << 29)
+#define SK_FractPIOver180 (0x11DF46A)
+
+#define SkFractToFloat(x) ((float)(x) * 0.00000000093132257f)
+#define SkFloatToFract(x) ((SkFract)((x) * SK_Fract1))
+
+/** Converts an integer to a SkFixed, asserting that the result does not overflow
+ a 32 bit signed integer
+*/
+#ifdef SK_DEBUG
+ inline SkFixed SkIntToFixed(int n)
+ {
+ SkASSERT(n >= -32768 && n <= 32767);
+ return n << 16;
+ }
+#else
+ // force the cast to SkFixed to ensure that the answer is signed (like the debug version)
+ #define SkIntToFixed(n) (SkFixed)((n) << 16)
+#endif
+
+/** Converts a SkFixed to a SkFract, asserting that the result does not overflow
+ a 32 bit signed integer
+*/
+#ifdef SK_DEBUG
+ inline SkFract SkFixedToFract(SkFixed x)
+ {
+ SkASSERT(x >= (-2 << 16) && x <= (2 << 16) - 1);
+ return x << 14;
+ }
+#else
+ #define SkFixedToFract(x) ((x) << 14)
+#endif
+
+/** Returns the signed fraction of a SkFixed
+*/
+inline SkFixed SkFixedFraction(SkFixed x)
+{
+ SkFixed mask = x >> 31 << 16;
+ return (x & 0xFFFF) | mask;
+}
+
+/** Converts a SkFract to a SkFixed
+*/
+#define SkFractToFixed(x) ((x) >> 14)
+
+#define SkFixedRoundToInt(x) (((x) + SK_FixedHalf) >> 16)
+#define SkFixedCeilToInt(x) (((x) + SK_Fixed1 - 1) >> 16)
+#define SkFixedFloorToInt(x) ((x) >> 16)
+
+#define SkFixedRoundToFixed(x) (((x) + SK_FixedHalf) & 0xFFFF0000)
+#define SkFixedCeilToFixed(x) (((x) + SK_Fixed1 - 1) & 0xFFFF0000)
+#define SkFixedFloorToFixed(x) ((x) & 0xFFFF0000)
+
+// DEPRECATED
+#define SkFixedFloor(x) SkFixedFloorToInt(x)
+#define SkFixedCeil(x) SkFixedCeilToInt(x)
+#define SkFixedRound(x) SkFixedRoundToInt(x)
+
+#define SkFixedAbs(x) SkAbs32(x)
+#define SkFixedAve(a, b) (((a) + (b)) >> 1)
+
+SkFixed SkFixedMul_portable(SkFixed, SkFixed);
+SkFract SkFractMul_portable(SkFract, SkFract);
+inline SkFixed SkFixedSquare_portable(SkFixed value)
+{
+ uint32_t a = SkAbs32(value);
+ uint32_t ah = a >> 16;
+ uint32_t al = a & 0xFFFF;
+ SkFixed result = ah * a + al * ah + (al * al >> 16);
+ if (result >= 0)
+ return result;
+ else // Overflow.
+ return SK_FixedMax;
+}
+
+#define SkFixedDiv(numer, denom) SkDivBits(numer, denom, 16)
+SkFixed SkFixedDivInt(int32_t numer, int32_t denom);
+SkFixed SkFixedMod(SkFixed numer, SkFixed denom);
+#define SkFixedInvert(n) SkDivBits(SK_Fixed1, n, 16)
+SkFixed SkFixedFastInvert(SkFixed n);
+#define SkFixedSqrt(n) SkSqrtBits(n, 23)
+SkFixed SkFixedMean(SkFixed a, SkFixed b); //*< returns sqrt(x*y)
+int SkFixedMulCommon(SkFixed, int , int bias); // internal used by SkFixedMulFloor, SkFixedMulCeil, SkFixedMulRound
+
+#define SkFractDiv(numer, denom) SkDivBits(numer, denom, 30)
+#define SkFractSqrt(n) SkSqrtBits(n, 30)
+
+SkFixed SkFixedSinCos(SkFixed radians, SkFixed* cosValueOrNull);
+#define SkFixedSin(radians) SkFixedSinCos(radians, NULL)
+inline SkFixed SkFixedCos(SkFixed radians)
+{
+ SkFixed cosValue;
+ (void)SkFixedSinCos(radians, &cosValue);
+ return cosValue;
+}
+SkFixed SkFixedTan(SkFixed radians);
+SkFixed SkFixedASin(SkFixed);
+SkFixed SkFixedACos(SkFixed);
+SkFixed SkFixedATan2(SkFixed y, SkFixed x);
+SkFixed SkFixedExp(SkFixed);
+SkFixed SkFixedLog(SkFixed);
+
+#define SK_FixedNearlyZero (SK_Fixed1 >> 12)
+
+inline bool SkFixedNearlyZero(SkFixed x, SkFixed tolerance = SK_FixedNearlyZero)
+{
+ SkASSERT(tolerance > 0);
+ return SkAbs32(x) < tolerance;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////
+// Now look for ASM overrides for our portable versions (should consider putting this in its own file)
+
+#ifdef SkLONGLONG
+ inline SkFixed SkFixedMul_longlong(SkFixed a, SkFixed b)
+ {
+ return (SkFixed)((SkLONGLONG)a * b >> 16);
+ }
+ inline SkFract SkFractMul_longlong(SkFract a, SkFract b)
+ {
+ return (SkFract)((SkLONGLONG)a * b >> 30);
+ }
+ inline SkFixed SkFixedSquare_longlong(SkFixed value)
+ {
+ return (SkFixed)((SkLONGLONG)value * value >> 16);
+ }
+ #define SkFixedMul(a,b) SkFixedMul_longlong(a,b)
+ #define SkFractMul(a,b) SkFractMul_longlong(a,b)
+ #define SkFixedSquare(a) SkFixedSquare_longlong(a)
+#endif
+
+#if defined(SK_CPU_ARM)
+ /* This guy does not handle NaN or other obscurities, but is faster than
+ than (int)(x*65536)
+ */
+ inline SkFixed SkFloatToFixed_arm(float x)
+ {
+ register int32_t y, z;
+ asm("movs %1, %3, lsl #1 \n"
+ "mov %2, #0x8E \n"
+ "sub %1, %2, %1, lsr #24 \n"
+ "mov %2, %3, lsl #8 \n"
+ "orr %2, %2, #0x80000000 \n"
+ "mov %1, %2, lsr %1 \n"
+ "it cs \n"
+ "rsbcs %1, %1, #0 \n"
+ : "=r"(x), "=&r"(y), "=&r"(z)
+ : "r"(x)
+ : "cc"
+ );
+ return y;
+ }
+ inline SkFixed SkFixedMul_arm(SkFixed x, SkFixed y)
+ {
+ register int32_t t;
+ asm("smull %0, %2, %1, %3 \n"
+ "mov %0, %0, lsr #16 \n"
+ "orr %0, %0, %2, lsl #16 \n"
+ : "=r"(x), "=&r"(y), "=r"(t)
+ : "r"(x), "1"(y)
+ :
+ );
+ return x;
+ }
+ inline SkFixed SkFixedMulAdd_arm(SkFixed x, SkFixed y, SkFixed a)
+ {
+ register int32_t t;
+ asm("smull %0, %3, %1, %4 \n"
+ "add %0, %2, %0, lsr #16 \n"
+ "add %0, %0, %3, lsl #16 \n"
+ : "=r"(x), "=&r"(y), "=&r"(a), "=r"(t)
+ : "%r"(x), "1"(y), "2"(a)
+ :
+ );
+ return x;
+ }
+ inline SkFixed SkFractMul_arm(SkFixed x, SkFixed y)
+ {
+ register int32_t t;
+ asm("smull %0, %2, %1, %3 \n"
+ "mov %0, %0, lsr #30 \n"
+ "orr %0, %0, %2, lsl #2 \n"
+ : "=r"(x), "=&r"(y), "=r"(t)
+ : "r"(x), "1"(y)
+ :
+ );
+ return x;
+ }
+ #undef SkFixedMul
+ #undef SkFractMul
+ #define SkFixedMul(x, y) SkFixedMul_arm(x, y)
+ #define SkFractMul(x, y) SkFractMul_arm(x, y)
+ #define SkFixedMulAdd(x, y, a) SkFixedMulAdd_arm(x, y, a)
+
+ #undef SkFloatToFixed
+ #define SkFloatToFixed(x) SkFloatToFixed_arm(x)
+#endif
+
+/////////////////////// Now define our macros to the portable versions if they weren't overridden
+
+#ifndef SkFixedSquare
+ #define SkFixedSquare(x) SkFixedSquare_portable(x)
+#endif
+#ifndef SkFixedMul
+ #define SkFixedMul(x, y) SkFixedMul_portable(x, y)
+#endif
+#ifndef SkFractMul
+ #define SkFractMul(x, y) SkFractMul_portable(x, y)
+#endif
+#ifndef SkFixedMulAdd
+ #define SkFixedMulAdd(x, y, a) (SkFixedMul(x, y) + (a))
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+
+typedef int64_t SkFixed48;
+
+#define SkIntToFixed48(x) ((SkFixed48)(x) << 48)
+#define SkFixed48ToInt(x) ((int)((x) >> 48))
+#define SkFixedToFixed48(x) ((SkFixed48)(x) << 32)
+#define SkFixed48ToFixed(x) ((SkFixed)((x) >> 32))
+#define SkFloatToFixed48(x) ((SkFixed48)((x) * (65536.0f * 65536.0f * 65536.0f)))
+
+#ifdef SK_SCALAR_IS_FLOAT
+ #define SkScalarToFixed48(x) SkFloatToFixed48(x)
+#else
+ #define SkScalarToFixed48(x) SkFixedToFixed48(x)
+#endif
+
+#endif
diff --git a/core/SkFlate.h b/core/SkFlate.h
new file mode 100644
index 0000000..e4c1417
--- /dev/null
+++ b/core/SkFlate.h
@@ -0,0 +1,52 @@
+
+/*
+ * Copyright 2010 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkFlate_DEFINED
+#define SkFlate_DEFINED
+
+#include "SkTypes.h"
+
+class SkData;
+class SkWStream;
+class SkStream;
+
+/** \class SkFlate
+ A class to provide access to the flate compression algorithm.
+*/
+class SkFlate {
+public:
+ /** Indicates if the flate algorithm is available.
+ */
+ static bool HaveFlate();
+
+ /**
+ * Use the flate compression algorithm to compress the data in src,
+ * putting the result into dst. Returns false if an error occurs.
+ */
+ static bool Deflate(SkStream* src, SkWStream* dst);
+
+ /**
+ * Use the flate compression algorithm to compress the data in src,
+ * putting the result into dst. Returns false if an error occurs.
+ */
+ static bool Deflate(const void* src, size_t len, SkWStream* dst);
+
+ /**
+ * Use the flate compression algorithm to compress the data,
+ * putting the result into dst. Returns false if an error occurs.
+ */
+ static bool Deflate(const SkData*, SkWStream* dst);
+
+ /** Use the flate compression algorithm to decompress the data in src,
+ putting the result into dst. Returns false if an error occurs.
+ */
+ static bool Inflate(SkStream* src, SkWStream* dst);
+};
+
+#endif
diff --git a/core/SkFlattenable.h b/core/SkFlattenable.h
new file mode 100644
index 0000000..0b21abc
--- /dev/null
+++ b/core/SkFlattenable.h
@@ -0,0 +1,86 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkFlattenable_DEFINED
+#define SkFlattenable_DEFINED
+
+#include "SkRefCnt.h"
+
+class SkFlattenableReadBuffer;
+class SkFlattenableWriteBuffer;
+
+#define SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(flattenable) \
+ SkFlattenable::Registrar(#flattenable, flattenable::CreateProc);
+
+#define SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP() static void InitializeFlattenables();
+
+#define SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(flattenable) \
+ void flattenable::InitializeFlattenables() {
+
+#define SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END \
+ }
+
+#define SK_DECLARE_UNFLATTENABLE_OBJECT() \
+ virtual Factory getFactory() SK_OVERRIDE { return NULL; }; \
+
+#define SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(flattenable) \
+ virtual Factory getFactory() SK_OVERRIDE { return CreateProc; } \
+ static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) { \
+ return SkNEW_ARGS(flattenable, (buffer)); \
+ }
+
+/** \class SkFlattenable
+
+ SkFlattenable is the base class for objects that need to be flattened
+ into a data stream for either transport or as part of the key to the
+ font cache.
+ */
+class SK_API SkFlattenable : public SkRefCnt {
+public:
+ SK_DECLARE_INST_COUNT(SkFlattenable)
+
+ typedef SkFlattenable* (*Factory)(SkFlattenableReadBuffer&);
+
+ SkFlattenable() {}
+
+ /** Implement this to return a factory function pointer that can be called
+ to recreate your class given a buffer (previously written to by your
+ override of flatten().
+ */
+ virtual Factory getFactory() = 0;
+
+ static Factory NameToFactory(const char name[]);
+ static const char* FactoryToName(Factory);
+ static void Register(const char name[], Factory);
+
+ class Registrar {
+ public:
+ Registrar(const char name[], Factory factory) {
+ SkFlattenable::Register(name, factory);
+ }
+ };
+
+protected:
+ SkFlattenable(SkFlattenableReadBuffer&) {}
+ /** Override this to write data specific to your subclass into the buffer,
+ being sure to call your super-class' version first. This data will later
+ be passed to your Factory function, returned by getFactory().
+ */
+ virtual void flatten(SkFlattenableWriteBuffer&) const;
+
+private:
+ static void InitializeFlattenables();
+
+ friend class SkGraphics;
+ friend class SkFlattenableWriteBuffer;
+
+ typedef SkRefCnt INHERITED;
+};
+
+#endif
diff --git a/core/SkFlattenableBuffers.h b/core/SkFlattenableBuffers.h
new file mode 100644
index 0000000..03c03f3
--- /dev/null
+++ b/core/SkFlattenableBuffers.h
@@ -0,0 +1,175 @@
+
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkFlattenableBuffers_DEFINED
+#define SkFlattenableBuffers_DEFINED
+
+#include "SkColor.h"
+#include "SkPaint.h"
+#include "SkPoint.h"
+
+class SkBitmap;
+class SkFlattenable;
+struct SkIRect;
+class SkMatrix;
+class SkOrderedReadBuffer;
+class SkOrderedWriteBuffer;
+class SkPath;
+class SkPixelRef;
+struct SkRect;
+class SkRefCnt;
+class SkRegion;
+class SkStream;
+class SkString;
+class SkTypeface;
+class SkWStream;
+
+class SkFlattenableReadBuffer {
+public:
+ SkFlattenableReadBuffer();
+ virtual ~SkFlattenableReadBuffer();
+
+ bool isOrderedBinaryBuffer() { return NULL != getOrderedBinaryBuffer(); }
+ virtual SkOrderedReadBuffer* getOrderedBinaryBuffer() { return NULL; }
+
+ enum Flags {
+ kCrossProcess_Flag = 1 << 0,
+ kScalarIsFloat_Flag = 1 << 1,
+ kPtrIs64Bit_Flag = 1 << 2,
+ };
+
+ void setFlags(uint32_t flags) { fFlags = flags; }
+ uint32_t getFlags() const { return fFlags; }
+
+ bool isCrossProcess() const { return SkToBool(fFlags & kCrossProcess_Flag); }
+ bool isScalarFloat() const { return SkToBool(fFlags & kScalarIsFloat_Flag); }
+ bool isPtr64Bit() const { return SkToBool(fFlags & kPtrIs64Bit_Flag); }
+
+ // primitives
+ virtual bool readBool() = 0;
+ virtual SkColor readColor() = 0;
+ virtual SkFixed readFixed() = 0;
+ virtual int32_t readInt() = 0;
+ virtual SkScalar readScalar() = 0;
+ virtual uint32_t readUInt() = 0;
+ virtual int32_t read32() = 0;
+
+ // strings -- the caller is responsible for freeing the string contents
+ virtual void readString(SkString* string) = 0;
+ virtual void* readEncodedString(size_t* length, SkPaint::TextEncoding encoding) = 0;
+
+ // common data structures
+ virtual SkFlattenable* readFlattenable() = 0;
+ virtual void readPoint(SkPoint* point) = 0;
+ virtual void readMatrix(SkMatrix* matrix) = 0;
+ virtual void readIRect(SkIRect* rect) = 0;
+ virtual void readRect(SkRect* rect) = 0;
+ virtual void readRegion(SkRegion* region) = 0;
+ virtual void readPath(SkPath* path) = 0;
+
+ // binary data and arrays
+ virtual uint32_t readByteArray(void* value) = 0;
+ virtual uint32_t readColorArray(SkColor* colors) = 0;
+ virtual uint32_t readIntArray(int32_t* values) = 0;
+ virtual uint32_t readPointArray(SkPoint* points) = 0;
+ virtual uint32_t readScalarArray(SkScalar* values) = 0;
+
+ /** This helper peeks into the buffer and reports back the length of the next array in
+ * the buffer but does not change the state of the buffer.
+ */
+ virtual uint32_t getArrayCount() = 0;
+
+ // helper functions
+ virtual void* readFunctionPtr();
+ virtual void readPaint(SkPaint* paint);
+
+ virtual void readBitmap(SkBitmap* bitmap) = 0;
+ virtual SkTypeface* readTypeface() = 0;
+
+ // helper function for classes with const SkPoint members
+ SkPoint readPoint() {
+ SkPoint point;
+ this->readPoint(&point);
+ return point;
+ }
+
+ template <typename T> T* readFlattenableT() {
+ return static_cast<T*>(this->readFlattenable());
+ }
+
+private:
+ uint32_t fFlags;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+class SkFlattenableWriteBuffer {
+public:
+ SkFlattenableWriteBuffer();
+ virtual ~SkFlattenableWriteBuffer();
+
+ virtual bool isOrderedBinaryBuffer() { return false; }
+ virtual SkOrderedWriteBuffer* getOrderedBinaryBuffer() { sk_throw(); return NULL; }
+
+ // primitives
+ virtual void writeByteArray(const void* data, size_t size) = 0;
+ virtual void writeBool(bool value) = 0;
+ virtual void writeFixed(SkFixed value) = 0;
+ virtual void writeScalar(SkScalar value) = 0;
+ virtual void writeScalarArray(const SkScalar* value, uint32_t count) = 0;
+ virtual void writeInt(int32_t value) = 0;
+ virtual void writeIntArray(const int32_t* value, uint32_t count) = 0;
+ virtual void writeUInt(uint32_t value) = 0;
+ virtual void write32(int32_t value) = 0; // printf in hex
+ virtual void writeString(const char* value) = 0;
+ virtual void writeEncodedString(const void* value, size_t byteLength,
+ SkPaint::TextEncoding encoding) = 0;
+
+ // common data structures
+ virtual void writeFlattenable(SkFlattenable* flattenable) = 0;
+ virtual void writeColor(const SkColor& color) = 0;
+ virtual void writeColorArray(const SkColor* color, uint32_t count) = 0;
+ virtual void writePoint(const SkPoint& point) = 0;
+ virtual void writePointArray(const SkPoint* points, uint32_t count) = 0;
+ virtual void writeMatrix(const SkMatrix& matrix) = 0;
+ virtual void writeIRect(const SkIRect& rect) = 0;
+ virtual void writeRect(const SkRect& rect) = 0;
+ virtual void writeRegion(const SkRegion& region) = 0;
+ virtual void writePath(const SkPath& path) = 0;
+ virtual size_t writeStream(SkStream* stream, size_t length) = 0;
+
+ // helper functions
+ virtual void writeFunctionPtr(void* ptr);
+ virtual void writePaint(const SkPaint& paint);
+
+ virtual void writeBitmap(const SkBitmap& bitmap) = 0;
+ virtual void writeTypeface(SkTypeface* typeface) = 0;
+
+ virtual bool writeToStream(SkWStream*) = 0;
+
+ enum Flags {
+ kCrossProcess_Flag = 0x01,
+ };
+
+ uint32_t getFlags() const { return fFlags; }
+ void setFlags(uint32_t flags) { fFlags = flags; }
+
+ bool isCrossProcess() const {
+ return SkToBool(fFlags & kCrossProcess_Flag);
+ }
+
+ bool persistTypeface() const { return (fFlags & kCrossProcess_Flag) != 0; }
+
+protected:
+ // A helper function so that each subclass does not have to be a friend of SkFlattenable
+ void flattenObject(SkFlattenable* obj, SkFlattenableWriteBuffer& buffer);
+
+ uint32_t fFlags;
+};
+
+#endif
diff --git a/core/SkFlattenableSerialization.h b/core/SkFlattenableSerialization.h
new file mode 100644
index 0000000..2ed244c
--- /dev/null
+++ b/core/SkFlattenableSerialization.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkFlattenableSerialization_DEFINED
+#define SkFlattenableSerialization_DEFINED
+
+#include "SkTypes.h"
+
+class SkData;
+class SkFlattenable;
+
+SK_API SkData* SkSerializeFlattenable(SkFlattenable*);
+SK_API SkFlattenable* SkDeserializeFlattenable(const void* data, size_t size);
+
+#endif
diff --git a/core/SkFloatBits.h b/core/SkFloatBits.h
new file mode 100644
index 0000000..a1196ca
--- /dev/null
+++ b/core/SkFloatBits.h
@@ -0,0 +1,138 @@
+
+/*
+ * Copyright 2008 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkFloatBits_DEFINED
+#define SkFloatBits_DEFINED
+
+#include "SkTypes.h"
+
+/** Convert a sign-bit int (i.e. float interpreted as int) into a 2s compliement
+ int. This also converts -0 (0x80000000) to 0. Doing this to a float allows
+ it to be compared using normal C operators (<, <=, etc.)
+*/
+static inline int32_t SkSignBitTo2sCompliment(int32_t x) {
+ if (x < 0) {
+ x &= 0x7FFFFFFF;
+ x = -x;
+ }
+ return x;
+}
+
+/** Convert a 2s compliment int to a sign-bit (i.e. int interpreted as float).
+ This undoes the result of SkSignBitTo2sCompliment().
+ */
+static inline int32_t Sk2sComplimentToSignBit(int32_t x) {
+ int sign = x >> 31;
+ // make x positive
+ x = (x ^ sign) - sign;
+ // set the sign bit as needed
+ x |= sign << 31;
+ return x;
+}
+
+/** Given the bit representation of a float, return its value cast to an int.
+ If the value is out of range, or NaN, return return +/- SK_MaxS32
+*/
+int32_t SkFloatBits_toIntCast(int32_t floatBits);
+
+/** Given the bit representation of a float, return its floor as an int.
+ If the value is out of range, or NaN, return return +/- SK_MaxS32
+ */
+SK_API int32_t SkFloatBits_toIntFloor(int32_t floatBits);
+
+/** Given the bit representation of a float, return it rounded to an int.
+ If the value is out of range, or NaN, return return +/- SK_MaxS32
+ */
+SK_API int32_t SkFloatBits_toIntRound(int32_t floatBits);
+
+/** Given the bit representation of a float, return its ceiling as an int.
+ If the value is out of range, or NaN, return return +/- SK_MaxS32
+ */
+SK_API int32_t SkFloatBits_toIntCeil(int32_t floatBits);
+
+
+union SkFloatIntUnion {
+ float fFloat;
+ int32_t fSignBitInt;
+};
+
+// Helper to see a float as its bit pattern (w/o aliasing warnings)
+static inline int32_t SkFloat2Bits(float x) {
+ SkFloatIntUnion data;
+ data.fFloat = x;
+ return data.fSignBitInt;
+}
+
+// Helper to see a bit pattern as a float (w/o aliasing warnings)
+static inline float SkBits2Float(int32_t floatAsBits) {
+ SkFloatIntUnion data;
+ data.fSignBitInt = floatAsBits;
+ return data.fFloat;
+}
+
+/** Return the float as a 2s compliment int. Just to be used to compare floats
+ to each other or against positive float-bit-constants (like 0). This does
+ not return the int equivalent of the float, just something cheaper for
+ compares-only.
+ */
+static inline int32_t SkFloatAs2sCompliment(float x) {
+ return SkSignBitTo2sCompliment(SkFloat2Bits(x));
+}
+
+/** Return the 2s compliment int as a float. This undos the result of
+ SkFloatAs2sCompliment
+ */
+static inline float Sk2sComplimentAsFloat(int32_t x) {
+ return SkBits2Float(Sk2sComplimentToSignBit(x));
+}
+
+/** Return x cast to a float (i.e. (float)x)
+*/
+float SkIntToFloatCast(int x);
+float SkIntToFloatCast_NoOverflowCheck(int x);
+
+/** Return the float cast to an int.
+ If the value is out of range, or NaN, return +/- SK_MaxS32
+*/
+static inline int32_t SkFloatToIntCast(float x) {
+ return SkFloatBits_toIntCast(SkFloat2Bits(x));
+}
+
+/** Return the floor of the float as an int.
+ If the value is out of range, or NaN, return +/- SK_MaxS32
+*/
+static inline int32_t SkFloatToIntFloor(float x) {
+ return SkFloatBits_toIntFloor(SkFloat2Bits(x));
+}
+
+/** Return the float rounded to an int.
+ If the value is out of range, or NaN, return +/- SK_MaxS32
+*/
+static inline int32_t SkFloatToIntRound(float x) {
+ return SkFloatBits_toIntRound(SkFloat2Bits(x));
+}
+
+/** Return the ceiling of the float as an int.
+ If the value is out of range, or NaN, return +/- SK_MaxS32
+*/
+static inline int32_t SkFloatToIntCeil(float x) {
+ return SkFloatBits_toIntCeil(SkFloat2Bits(x));
+}
+
+// Scalar wrappers for float-bit routines
+
+#ifdef SK_SCALAR_IS_FLOAT
+ #define SkScalarAs2sCompliment(x) SkFloatAs2sCompliment(x)
+ #define Sk2sComplimentAsScalar(x) Sk2sComplimentAsFloat(x)
+#else
+ #define SkScalarAs2sCompliment(x) (x)
+ #define Sk2sComplimentAsScalar(x) (x)
+#endif
+
+#endif
diff --git a/core/SkFloatingPoint.h b/core/SkFloatingPoint.h
new file mode 100644
index 0000000..44a3eef
--- /dev/null
+++ b/core/SkFloatingPoint.h
@@ -0,0 +1,99 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkFloatingPoint_DEFINED
+#define SkFloatingPoint_DEFINED
+
+#include "SkTypes.h"
+
+#include <math.h>
+#include <float.h>
+#include "SkFloatBits.h"
+
+// C++98 cmath std::pow seems to be the earliest portable way to get float pow.
+// However, on Linux including cmath undefines isfinite.
+// http://gcc.gnu.org/bugzilla/show_bug.cgi?id=14608
+static inline float sk_float_pow(float base, float exp) {
+ return powf(base, exp);
+}
+
+static inline float sk_float_copysign(float x, float y) {
+ int32_t xbits = SkFloat2Bits(x);
+ int32_t ybits = SkFloat2Bits(y);
+ return SkBits2Float((xbits & 0x7FFFFFFF) | (ybits & 0x80000000));
+}
+
+#ifdef SK_BUILD_FOR_WINCE
+ #define sk_float_sqrt(x) (float)::sqrt(x)
+ #define sk_float_sin(x) (float)::sin(x)
+ #define sk_float_cos(x) (float)::cos(x)
+ #define sk_float_tan(x) (float)::tan(x)
+ #define sk_float_acos(x) (float)::acos(x)
+ #define sk_float_asin(x) (float)::asin(x)
+ #define sk_float_atan2(y,x) (float)::atan2(y,x)
+ #define sk_float_abs(x) (float)::fabs(x)
+ #define sk_float_mod(x,y) (float)::fmod(x,y)
+ #define sk_float_exp(x) (float)::exp(x)
+ #define sk_float_log(x) (float)::log(x)
+ #define sk_float_floor(x) (float)::floor(x)
+ #define sk_float_ceil(x) (float)::ceil(x)
+#else
+ #define sk_float_sqrt(x) sqrtf(x)
+ #define sk_float_sin(x) sinf(x)
+ #define sk_float_cos(x) cosf(x)
+ #define sk_float_tan(x) tanf(x)
+ #define sk_float_floor(x) floorf(x)
+ #define sk_float_ceil(x) ceilf(x)
+#ifdef SK_BUILD_FOR_MAC
+ #define sk_float_acos(x) static_cast<float>(acos(x))
+ #define sk_float_asin(x) static_cast<float>(asin(x))
+#else
+ #define sk_float_acos(x) acosf(x)
+ #define sk_float_asin(x) asinf(x)
+#endif
+ #define sk_float_atan2(y,x) atan2f(y,x)
+ #define sk_float_abs(x) fabsf(x)
+ #define sk_float_mod(x,y) fmodf(x,y)
+ #define sk_float_exp(x) expf(x)
+ #define sk_float_log(x) logf(x)
+#endif
+
+#ifdef SK_BUILD_FOR_WIN
+ #define sk_float_isfinite(x) _finite(x)
+ #define sk_float_isnan(x) _isnan(x)
+ static inline int sk_float_isinf(float x) {
+ int32_t bits = SkFloat2Bits(x);
+ return (bits << 1) == (0xFF << 24);
+ }
+#else
+ #define sk_float_isfinite(x) isfinite(x)
+ #define sk_float_isnan(x) isnan(x)
+ #define sk_float_isinf(x) isinf(x)
+#endif
+
+#define sk_double_isnan(a) sk_float_isnan(a)
+
+#ifdef SK_USE_FLOATBITS
+ #define sk_float_floor2int(x) SkFloatToIntFloor(x)
+ #define sk_float_round2int(x) SkFloatToIntRound(x)
+ #define sk_float_ceil2int(x) SkFloatToIntCeil(x)
+#else
+ #define sk_float_floor2int(x) (int)sk_float_floor(x)
+ #define sk_float_round2int(x) (int)sk_float_floor((x) + 0.5f)
+ #define sk_float_ceil2int(x) (int)sk_float_ceil(x)
+#endif
+
+extern const uint32_t gIEEENotANumber;
+extern const uint32_t gIEEEInfinity;
+extern const uint32_t gIEEENegativeInfinity;
+
+#define SK_FloatNaN (*SkTCast<const float*>(&gIEEENotANumber))
+#define SK_FloatInfinity (*SkTCast<const float*>(&gIEEEInfinity))
+#define SK_FloatNegativeInfinity (*SkTCast<const float*>(&gIEEENegativeInfinity))
+#endif
diff --git a/core/SkFontHost.h b/core/SkFontHost.h
new file mode 100644
index 0000000..e847b76
--- /dev/null
+++ b/core/SkFontHost.h
@@ -0,0 +1,133 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkFontHost_DEFINED
+#define SkFontHost_DEFINED
+
+#include "SkTypeface.h"
+
+//#define SK_FONTHOST_USES_FONTMGR
+
+class SkDescriptor;
+class SkScalerContext;
+struct SkScalerContextRec;
+class SkStream;
+class SkWStream;
+
+/** \class SkFontHost
+
+ This class is ported to each environment. It is responsible for bridging
+ the gap between the (sort of) abstract class SkTypeface and the
+ platform-specific implementation that provides access to font files.
+
+ One basic task is for each create (subclass of) SkTypeface, the FontHost is
+ responsible for assigning a uniqueID. The ID should be unique for the
+ underlying font file/data, not unique per typeface instance. Thus it is
+ possible/common to request a typeface for the same font more than once
+ (e.g. asking for the same font by name several times). The FontHost may
+ return seperate typeface instances in that case, or it may choose to use a
+ cache and return the same instance (but calling typeface->ref(), since the
+ caller is always responsible for calling unref() on each instance that is
+ returned). Either way, the fontID for those instance(s) will be the same.
+ In addition, the fontID should never be set to 0. That value is used as a
+ sentinel to indicate no-font-id.
+
+ The major aspects are:
+ 1) Given either a name/style, return a subclass of SkTypeface that
+ references the closest matching font available on the host system.
+ 2) Given the data for a font (either in a stream or a file name), return
+ a typeface that allows access to that data.
+ 3) Each typeface instance carries a 32bit ID for its corresponding font.
+ SkFontHost turns that ID into a stream to access the font's data.
+ 4) Given a font ID, return a subclass of SkScalerContext, which connects a
+ font scaler (e.g. freetype or other) to the font's data.
+ 5) Utilites to manage the font cache (budgeting) and gamma correction
+*/
+class SK_API SkFontHost {
+public:
+ /** LCDs either have their color elements arranged horizontally or
+ vertically. When rendering subpixel glyphs we need to know which way
+ round they are.
+
+ Note, if you change this after startup, you'll need to flush the glyph
+ cache because it'll have the wrong type of masks cached.
+
+ @deprecated use SkPixelGeometry instead.
+ */
+ enum LCDOrientation {
+ kHorizontal_LCDOrientation = 0, //!< this is the default
+ kVertical_LCDOrientation = 1
+ };
+
+ /** @deprecated set on Device creation. */
+ static void SetSubpixelOrientation(LCDOrientation orientation);
+ /** @deprecated get from Device. */
+ static LCDOrientation GetSubpixelOrientation();
+
+ /** LCD color elements can vary in order. For subpixel text we need to know
+ the order which the LCDs uses so that the color fringes are in the
+ correct place.
+
+ Note, if you change this after startup, you'll need to flush the glyph
+ cache because it'll have the wrong type of masks cached.
+
+ kNONE_LCDOrder means that the subpixel elements are not spatially
+ separated in any usable fashion.
+
+ @deprecated use SkPixelGeometry instead.
+ */
+ enum LCDOrder {
+ kRGB_LCDOrder = 0, //!< this is the default
+ kBGR_LCDOrder = 1,
+ kNONE_LCDOrder = 2
+ };
+
+ /** @deprecated set on Device creation. */
+ static void SetSubpixelOrder(LCDOrder order);
+ /** @deprecated get from Device. */
+ static LCDOrder GetSubpixelOrder();
+
+private:
+ /** Return a new, closest matching typeface given either an existing family
+ (specified by a typeface in that family) or by a familyName and a
+ requested style.
+ 1) If familyFace is null, use familyName.
+ 2) If familyName is null, use data (UTF-16 to cover).
+ 3) If all are null, return the default font that best matches style
+ */
+ static SkTypeface* CreateTypeface(const SkTypeface* familyFace,
+ const char familyName[],
+ SkTypeface::Style style);
+
+ /** Return a new typeface given the data buffer. If the data does not
+ represent a valid font, returns null.
+
+ If a typeface instance is returned, the caller is responsible for
+ calling unref() on the typeface when they are finished with it.
+
+ The returned typeface may or may not have called ref() on the stream
+ parameter. If the typeface has not called ref(), then it may have made
+ a copy of the releveant data. In either case, the caller is still
+ responsible for its refcnt ownership of the stream.
+ */
+ static SkTypeface* CreateTypefaceFromStream(SkStream*);
+
+ /** Return a new typeface from the specified file path. If the file does not
+ represent a valid font, this returns null. If a typeface is returned,
+ the caller is responsible for calling unref() when it is no longer used.
+ */
+ static SkTypeface* CreateTypefaceFromFile(const char path[]);
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ friend class SkScalerContext;
+ friend class SkTypeface;
+};
+
+#endif
diff --git a/core/SkFontLCDConfig.h b/core/SkFontLCDConfig.h
new file mode 100644
index 0000000..03ee09f
--- /dev/null
+++ b/core/SkFontLCDConfig.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkFontLCDConfig_DEFINED
+#define SkFontLCDConfig_DEFINED
+
+#include "SkTypes.h"
+
+class SkFontLCDConfig {
+public:
+ /** LCDs either have their color elements arranged horizontally or
+ vertically. When rendering subpixel glyphs we need to know which way
+ round they are.
+
+ Note, if you change this after startup, you'll need to flush the glyph
+ cache because it'll have the wrong type of masks cached.
+
+ @deprecated use SkPixelGeometry instead.
+ */
+ enum LCDOrientation {
+ kHorizontal_LCDOrientation = 0, //!< this is the default
+ kVertical_LCDOrientation = 1
+ };
+
+ /** @deprecated set on Device creation. */
+ static void SetSubpixelOrientation(LCDOrientation orientation);
+ /** @deprecated get from Device. */
+ static LCDOrientation GetSubpixelOrientation();
+
+ /** LCD color elements can vary in order. For subpixel text we need to know
+ the order which the LCDs uses so that the color fringes are in the
+ correct place.
+
+ Note, if you change this after startup, you'll need to flush the glyph
+ cache because it'll have the wrong type of masks cached.
+
+ kNONE_LCDOrder means that the subpixel elements are not spatially
+ separated in any usable fashion.
+
+ @deprecated use SkPixelGeometry instead.
+ */
+ enum LCDOrder {
+ kRGB_LCDOrder = 0, //!< this is the default
+ kBGR_LCDOrder = 1,
+ kNONE_LCDOrder = 2
+ };
+
+ /** @deprecated set on Device creation. */
+ static void SetSubpixelOrder(LCDOrder order);
+ /** @deprecated get from Device. */
+ static LCDOrder GetSubpixelOrder();
+};
+
+#endif
diff --git a/core/SkGeometry.h b/core/SkGeometry.h
new file mode 100644
index 0000000..d7836db
--- /dev/null
+++ b/core/SkGeometry.h
@@ -0,0 +1,307 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkGeometry_DEFINED
+#define SkGeometry_DEFINED
+
+#include "SkMatrix.h"
+
+/** An XRay is a half-line that runs from the specific point/origin to
+ +infinity in the X direction. e.g. XRay(3,5) is the half-line
+ (3,5)....(infinity, 5)
+ */
+typedef SkPoint SkXRay;
+
+/** Given a line segment from pts[0] to pts[1], and an xray, return true if
+ they intersect. Optional outgoing "ambiguous" argument indicates
+ whether the answer is ambiguous because the query occurred exactly at
+ one of the endpoints' y coordinates, indicating that another query y
+ coordinate is preferred for robustness.
+*/
+bool SkXRayCrossesLine(const SkXRay& pt, const SkPoint pts[2],
+ bool* ambiguous = NULL);
+
+/** Given a quadratic equation Ax^2 + Bx + C = 0, return 0, 1, 2 roots for the
+ equation.
+*/
+int SkFindUnitQuadRoots(SkScalar A, SkScalar B, SkScalar C, SkScalar roots[2]);
+
+///////////////////////////////////////////////////////////////////////////////
+
+/** Set pt to the point on the src quadratic specified by t. t must be
+ 0 <= t <= 1.0
+*/
+void SkEvalQuadAt(const SkPoint src[3], SkScalar t, SkPoint* pt,
+ SkVector* tangent = NULL);
+void SkEvalQuadAtHalf(const SkPoint src[3], SkPoint* pt,
+ SkVector* tangent = NULL);
+
+/** Given a src quadratic bezier, chop it at the specified t value,
+ where 0 < t < 1, and return the two new quadratics in dst:
+ dst[0..2] and dst[2..4]
+*/
+void SkChopQuadAt(const SkPoint src[3], SkPoint dst[5], SkScalar t);
+
+/** Given a src quadratic bezier, chop it at the specified t == 1/2,
+ The new quads are returned in dst[0..2] and dst[2..4]
+*/
+void SkChopQuadAtHalf(const SkPoint src[3], SkPoint dst[5]);
+
+/** Given the 3 coefficients for a quadratic bezier (either X or Y values), look
+ for extrema, and return the number of t-values that are found that represent
+ these extrema. If the quadratic has no extrema betwee (0..1) exclusive, the
+ function returns 0.
+ Returned count tValues[]
+ 0 ignored
+ 1 0 < tValues[0] < 1
+*/
+int SkFindQuadExtrema(SkScalar a, SkScalar b, SkScalar c, SkScalar tValues[1]);
+
+/** Given 3 points on a quadratic bezier, chop it into 1, 2 beziers such that
+ the resulting beziers are monotonic in Y. This is called by the scan converter.
+ Depending on what is returned, dst[] is treated as follows
+ 0 dst[0..2] is the original quad
+ 1 dst[0..2] and dst[2..4] are the two new quads
+*/
+int SkChopQuadAtYExtrema(const SkPoint src[3], SkPoint dst[5]);
+int SkChopQuadAtXExtrema(const SkPoint src[3], SkPoint dst[5]);
+
+/** Given 3 points on a quadratic bezier, if the point of maximum
+ curvature exists on the segment, returns the t value for this
+ point along the curve. Otherwise it will return a value of 0.
+*/
+float SkFindQuadMaxCurvature(const SkPoint src[3]);
+
+/** Given 3 points on a quadratic bezier, divide it into 2 quadratics
+ if the point of maximum curvature exists on the quad segment.
+ Depending on what is returned, dst[] is treated as follows
+ 1 dst[0..2] is the original quad
+ 2 dst[0..2] and dst[2..4] are the two new quads
+ If dst == null, it is ignored and only the count is returned.
+*/
+int SkChopQuadAtMaxCurvature(const SkPoint src[3], SkPoint dst[5]);
+
+/** Given 3 points on a quadratic bezier, use degree elevation to
+ convert it into the cubic fitting the same curve. The new cubic
+ curve is returned in dst[0..3].
+*/
+SK_API void SkConvertQuadToCubic(const SkPoint src[3], SkPoint dst[4]);
+
+///////////////////////////////////////////////////////////////////////////////
+
+/** Convert from parametric from (pts) to polynomial coefficients
+ coeff[0]*T^3 + coeff[1]*T^2 + coeff[2]*T + coeff[3]
+*/
+void SkGetCubicCoeff(const SkPoint pts[4], SkScalar cx[4], SkScalar cy[4]);
+
+/** Set pt to the point on the src cubic specified by t. t must be
+ 0 <= t <= 1.0
+*/
+void SkEvalCubicAt(const SkPoint src[4], SkScalar t, SkPoint* locOrNull,
+ SkVector* tangentOrNull, SkVector* curvatureOrNull);
+
+/** Given a src cubic bezier, chop it at the specified t value,
+ where 0 < t < 1, and return the two new cubics in dst:
+ dst[0..3] and dst[3..6]
+*/
+void SkChopCubicAt(const SkPoint src[4], SkPoint dst[7], SkScalar t);
+/** Given a src cubic bezier, chop it at the specified t values,
+ where 0 < t < 1, and return the new cubics in dst:
+ dst[0..3],dst[3..6],...,dst[3*t_count..3*(t_count+1)]
+*/
+void SkChopCubicAt(const SkPoint src[4], SkPoint dst[], const SkScalar t[],
+ int t_count);
+
+/** Given a src cubic bezier, chop it at the specified t == 1/2,
+ The new cubics are returned in dst[0..3] and dst[3..6]
+*/
+void SkChopCubicAtHalf(const SkPoint src[4], SkPoint dst[7]);
+
+/** Given the 4 coefficients for a cubic bezier (either X or Y values), look
+ for extrema, and return the number of t-values that are found that represent
+ these extrema. If the cubic has no extrema betwee (0..1) exclusive, the
+ function returns 0.
+ Returned count tValues[]
+ 0 ignored
+ 1 0 < tValues[0] < 1
+ 2 0 < tValues[0] < tValues[1] < 1
+*/
+int SkFindCubicExtrema(SkScalar a, SkScalar b, SkScalar c, SkScalar d,
+ SkScalar tValues[2]);
+
+/** Given 4 points on a cubic bezier, chop it into 1, 2, 3 beziers such that
+ the resulting beziers are monotonic in Y. This is called by the scan converter.
+ Depending on what is returned, dst[] is treated as follows
+ 0 dst[0..3] is the original cubic
+ 1 dst[0..3] and dst[3..6] are the two new cubics
+ 2 dst[0..3], dst[3..6], dst[6..9] are the three new cubics
+ If dst == null, it is ignored and only the count is returned.
+*/
+int SkChopCubicAtYExtrema(const SkPoint src[4], SkPoint dst[10]);
+int SkChopCubicAtXExtrema(const SkPoint src[4], SkPoint dst[10]);
+
+/** Given a cubic bezier, return 0, 1, or 2 t-values that represent the
+ inflection points.
+*/
+int SkFindCubicInflections(const SkPoint src[4], SkScalar tValues[2]);
+
+/** Return 1 for no chop, 2 for having chopped the cubic at a single
+ inflection point, 3 for having chopped at 2 inflection points.
+ dst will hold the resulting 1, 2, or 3 cubics.
+*/
+int SkChopCubicAtInflections(const SkPoint src[4], SkPoint dst[10]);
+
+int SkFindCubicMaxCurvature(const SkPoint src[4], SkScalar tValues[3]);
+int SkChopCubicAtMaxCurvature(const SkPoint src[4], SkPoint dst[13],
+ SkScalar tValues[3] = NULL);
+
+/** Given a monotonic cubic bezier, determine whether an xray intersects the
+ cubic.
+ By definition the cubic is open at the starting point; in other
+ words, if pt.fY is equivalent to cubic[0].fY, and pt.fX is to the
+ left of the curve, the line is not considered to cross the curve,
+ but if it is equal to cubic[3].fY then it is considered to
+ cross.
+ Optional outgoing "ambiguous" argument indicates whether the answer is
+ ambiguous because the query occurred exactly at one of the endpoints' y
+ coordinates, indicating that another query y coordinate is preferred
+ for robustness.
+ */
+bool SkXRayCrossesMonotonicCubic(const SkXRay& pt, const SkPoint cubic[4],
+ bool* ambiguous = NULL);
+
+/** Given an arbitrary cubic bezier, return the number of times an xray crosses
+ the cubic. Valid return values are [0..3]
+ By definition the cubic is open at the starting point; in other
+ words, if pt.fY is equivalent to cubic[0].fY, and pt.fX is to the
+ left of the curve, the line is not considered to cross the curve,
+ but if it is equal to cubic[3].fY then it is considered to
+ cross.
+ Optional outgoing "ambiguous" argument indicates whether the answer is
+ ambiguous because the query occurred exactly at one of the endpoints' y
+ coordinates or at a tangent point, indicating that another query y
+ coordinate is preferred for robustness.
+ */
+int SkNumXRayCrossingsForCubic(const SkXRay& pt, const SkPoint cubic[4],
+ bool* ambiguous = NULL);
+
+///////////////////////////////////////////////////////////////////////////////
+
+enum SkRotationDirection {
+ kCW_SkRotationDirection,
+ kCCW_SkRotationDirection
+};
+
+/** Maximum number of points needed in the quadPoints[] parameter for
+ SkBuildQuadArc()
+*/
+#define kSkBuildQuadArcStorage 17
+
+/** Given 2 unit vectors and a rotation direction, fill out the specified
+ array of points with quadratic segments. Return is the number of points
+ written to, which will be { 0, 3, 5, 7, ... kSkBuildQuadArcStorage }
+
+ matrix, if not null, is appled to the points before they are returned.
+*/
+int SkBuildQuadArc(const SkVector& unitStart, const SkVector& unitStop,
+ SkRotationDirection, const SkMatrix*, SkPoint quadPoints[]);
+
+// experimental
+struct SkConic {
+ SkPoint fPts[3];
+ SkScalar fW;
+
+ void set(const SkPoint pts[3], SkScalar w) {
+ memcpy(fPts, pts, 3 * sizeof(SkPoint));
+ fW = w;
+ }
+
+ /**
+ * Given a t-value [0...1] return its position and/or tangent.
+ * If pos is not null, return its position at the t-value.
+ * If tangent is not null, return its tangent at the t-value. NOTE the
+ * tangent value's length is arbitrary, and only its direction should
+ * be used.
+ */
+ void evalAt(SkScalar t, SkPoint* pos, SkVector* tangent = NULL) const;
+ void chopAt(SkScalar t, SkConic dst[2]) const;
+ void chop(SkConic dst[2]) const;
+
+ void computeAsQuadError(SkVector* err) const;
+ bool asQuadTol(SkScalar tol) const;
+
+ /**
+ * return the power-of-2 number of quads needed to approximate this conic
+ * with a sequence of quads. Will be >= 0.
+ */
+ int computeQuadPOW2(SkScalar tol) const;
+
+ /**
+ * Chop this conic into N quads, stored continguously in pts[], where
+ * N = 1 << pow2. The amount of storage needed is (1 + 2 * N)
+ */
+ int chopIntoQuadsPOW2(SkPoint pts[], int pow2) const;
+
+ bool findXExtrema(SkScalar* t) const;
+ bool findYExtrema(SkScalar* t) const;
+ bool chopAtXExtrema(SkConic dst[2]) const;
+ bool chopAtYExtrema(SkConic dst[2]) const;
+
+ void computeTightBounds(SkRect* bounds) const;
+ void computeFastBounds(SkRect* bounds) const;
+};
+
+#include "SkTemplates.h"
+
+/**
+ * Help class to allocate storage for approximating a conic with N quads.
+ */
+class SkAutoConicToQuads {
+public:
+ SkAutoConicToQuads() : fQuadCount(0) {}
+
+ /**
+ * Given a conic and a tolerance, return the array of points for the
+ * approximating quad(s). Call countQuads() to know the number of quads
+ * represented in these points.
+ *
+ * The quads are allocated to share end-points. e.g. if there are 4 quads,
+ * there will be 9 points allocated as follows
+ * quad[0] == pts[0..2]
+ * quad[1] == pts[2..4]
+ * quad[2] == pts[4..6]
+ * quad[3] == pts[6..8]
+ */
+ const SkPoint* computeQuads(const SkConic& conic, SkScalar tol) {
+ int pow2 = conic.computeQuadPOW2(tol);
+ fQuadCount = 1 << pow2;
+ SkPoint* pts = fStorage.reset(1 + 2 * fQuadCount);
+ conic.chopIntoQuadsPOW2(pts, pow2);
+ return pts;
+ }
+
+ const SkPoint* computeQuads(const SkPoint pts[3], SkScalar weight,
+ SkScalar tol) {
+ SkConic conic;
+ conic.set(pts, weight);
+ return computeQuads(conic, tol);
+ }
+
+ int countQuads() const { return fQuadCount; }
+
+private:
+ enum {
+ kQuadCount = 8, // should handle most conics
+ kPointCount = 1 + 2 * kQuadCount,
+ };
+ SkAutoSTMalloc<kPointCount, SkPoint> fStorage;
+ int fQuadCount; // #quads for current usage
+};
+
+#endif
diff --git a/core/SkGraphics.h b/core/SkGraphics.h
new file mode 100644
index 0000000..c876042
--- /dev/null
+++ b/core/SkGraphics.h
@@ -0,0 +1,115 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkGraphics_DEFINED
+#define SkGraphics_DEFINED
+
+#include "SkTypes.h"
+
+class SK_API SkGraphics {
+public:
+ /**
+ * Call this at process initialization time if your environment does not
+ * permit static global initializers that execute code. Note that
+ * Init() is not thread-safe.
+ */
+ static void Init();
+
+ /**
+ * Call this to release any memory held privately, such as the font cache.
+ */
+ static void Term();
+
+ /**
+ * Return the version numbers for the library. If the parameter is not
+ * null, it is set to the version number.
+ */
+ static void GetVersion(int32_t* major, int32_t* minor, int32_t* patch);
+
+ /**
+ * Return the max number of bytes that should be used by the font cache.
+ * If the cache needs to allocate more, it will purge previous entries.
+ * This max can be changed by calling SetFontCacheLimit().
+ */
+ static size_t GetFontCacheLimit();
+
+ /**
+ * Specify the max number of bytes that should be used by the font cache.
+ * If the cache needs to allocate more, it will purge previous entries.
+ *
+ * This function returns the previous setting, as if GetFontCacheLimit()
+ * had be called before the new limit was set.
+ */
+ static size_t SetFontCacheLimit(size_t bytes);
+
+ /**
+ * Return the number of bytes currently used by the font cache.
+ */
+ static size_t GetFontCacheUsed();
+
+ /**
+ * For debugging purposes, this will attempt to purge the font cache. It
+ * does not change the limit, but will cause subsequent font measures and
+ * draws to be recreated, since they will no longer be in the cache.
+ */
+ static void PurgeFontCache();
+
+ static size_t GetImageCacheBytesUsed();
+ static size_t GetImageCacheByteLimit();
+ static size_t SetImageCacheByteLimit(size_t newLimit);
+
+ /**
+ * Applications with command line options may pass optional state, such
+ * as cache sizes, here, for instance:
+ * font-cache-limit=12345678
+ *
+ * The flags format is name=value[;name=value...] with no spaces.
+ * This format is subject to change.
+ */
+ static void SetFlags(const char* flags);
+
+ /**
+ * Return the max number of bytes that should be used by the thread-local
+ * font cache.
+ * If the cache needs to allocate more, it will purge previous entries.
+ * This max can be changed by calling SetFontCacheLimit().
+ *
+ * If this thread has never called SetTLSFontCacheLimit, or has called it
+ * with 0, then this thread is using the shared font cache. In that case,
+ * this function will always return 0, and the caller may want to call
+ * GetFontCacheLimit.
+ */
+ static size_t GetTLSFontCacheLimit();
+
+ /**
+ * Specify the max number of bytes that should be used by the thread-local
+ * font cache. If this value is 0, then this thread will use the shared
+ * global font cache.
+ */
+ static void SetTLSFontCacheLimit(size_t bytes);
+
+private:
+ /** This is automatically called by SkGraphics::Init(), and must be
+ implemented by the host OS. This allows the host OS to register a callback
+ with the C++ runtime to call SkGraphics::FreeCaches()
+ */
+ static void InstallNewHandler();
+};
+
+class SkAutoGraphics {
+public:
+ SkAutoGraphics() {
+ SkGraphics::Init();
+ }
+ ~SkAutoGraphics() {
+ SkGraphics::Term();
+ }
+};
+
+#endif
diff --git a/core/SkImage.h b/core/SkImage.h
new file mode 100644
index 0000000..871d461
--- /dev/null
+++ b/core/SkImage.h
@@ -0,0 +1,131 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkImage_DEFINED
+#define SkImage_DEFINED
+
+#include "SkImageEncoder.h"
+#include "SkRefCnt.h"
+#include "SkScalar.h"
+
+class SkData;
+class SkCanvas;
+class SkPaint;
+class SkShader;
+class GrContext;
+class GrTexture;
+
+// need for TileMode
+#include "SkShader.h"
+
+/**
+ * SkImage is an abstraction for drawing a rectagle of pixels, though the
+ * particular type of image could be actually storing its data on the GPU, or
+ * as drawing commands (picture or PDF or otherwise), ready to be played back
+ * into another canvas.
+ *
+ * The content of SkImage is always immutable, though the actual storage may
+ * change, if for example that image can be re-created via encoded data or
+ * other means.
+ */
+class SK_API SkImage : public SkRefCnt {
+public:
+ SK_DECLARE_INST_COUNT(SkImage)
+
+ enum ColorType {
+ kAlpha_8_ColorType,
+ kRGB_565_ColorType,
+ kRGBA_8888_ColorType,
+ kBGRA_8888_ColorType,
+ kPMColor_ColorType,
+
+ kLastEnum_ColorType = kPMColor_ColorType
+ };
+
+ enum AlphaType {
+ kIgnore_AlphaType,
+ kOpaque_AlphaType,
+ kPremul_AlphaType,
+ kUnpremul_AlphaType,
+
+ kLastEnum_AlphaType = kUnpremul_AlphaType
+ };
+
+ struct Info {
+ int fWidth;
+ int fHeight;
+ ColorType fColorType;
+ AlphaType fAlphaType;
+ };
+
+ static SkImage* NewRasterCopy(const Info&, const void* pixels, size_t rowBytes);
+ static SkImage* NewRasterData(const Info&, SkData* pixels, size_t rowBytes);
+ static SkImage* NewEncodedData(SkData*);
+
+ /**
+ * GrTexture is a more logical parameter for this factory, but its
+ * interactions with scratch cache still has issues, so for now we take
+ * SkBitmap instead. This will be changed in the future. skbug.com/1449
+ */
+ static SkImage* NewTexture(const SkBitmap&);
+
+ int width() const { return fWidth; }
+ int height() const { return fHeight; }
+ uint32_t uniqueID() const { return fUniqueID; }
+
+ /**
+ * Return the GrTexture that stores the image pixels. Calling getTexture
+ * does not affect the reference count of the GrTexture object.
+ * Will return NULL if the image does not use a texture.
+ */
+ GrTexture* getTexture();
+
+ SkShader* newShaderClamp() const;
+ SkShader* newShader(SkShader::TileMode, SkShader::TileMode) const;
+
+ void draw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*);
+
+ /**
+ * Draw the image, cropped to the src rect, to the dst rect of a canvas.
+ * If src is larger than the bounds of the image, the rest of the image is
+ * filled with transparent black pixels.
+ *
+ * See SkCanvas::drawBitmapRectToRect for similar behavior.
+ */
+ void draw(SkCanvas*, const SkRect* src, const SkRect& dst, const SkPaint*);
+
+ /**
+ * Encode the image's pixels and return the result as a new SkData, which
+ * the caller must manage (i.e. call unref() when they are done).
+ *
+ * If the image type cannot be encoded, or the requested encoder type is
+ * not supported, this will return NULL.
+ */
+ SkData* encode(SkImageEncoder::Type t = SkImageEncoder::kPNG_Type,
+ int quality = 80) const;
+
+protected:
+ SkImage(int width, int height) :
+ fWidth(width),
+ fHeight(height),
+ fUniqueID(NextUniqueID()) {
+
+ SkASSERT(width >= 0);
+ SkASSERT(height >= 0);
+ }
+
+private:
+ const int fWidth;
+ const int fHeight;
+ const uint32_t fUniqueID;
+
+ static uint32_t NextUniqueID();
+
+ typedef SkRefCnt INHERITED;
+};
+
+#endif
diff --git a/core/SkImageDecoder.h b/core/SkImageDecoder.h
new file mode 100644
index 0000000..7bdaaa8
--- /dev/null
+++ b/core/SkImageDecoder.h
@@ -0,0 +1,560 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkImageDecoder_DEFINED
+#define SkImageDecoder_DEFINED
+
+#include "SkBitmap.h"
+#include "SkBitmapFactory.h"
+#include "SkImage.h"
+#include "SkRect.h"
+#include "SkRefCnt.h"
+#include "SkTypes.h"
+
+class SkStream;
+
+/** \class SkImageDecoder
+
+ Base class for decoding compressed images into a SkBitmap
+*/
+class SkImageDecoder : public SkNoncopyable {
+public:
+ virtual ~SkImageDecoder();
+
+ enum Format {
+ kUnknown_Format,
+ kBMP_Format,
+ kGIF_Format,
+ kICO_Format,
+ kJPEG_Format,
+ kPNG_Format,
+ kWBMP_Format,
+ kWEBP_Format,
+
+ kLastKnownFormat = kWEBP_Format,
+ };
+
+ /** Return the format of image this decoder can decode. If this decoder can decode multiple
+ formats, kUnknown_Format will be returned.
+ */
+ virtual Format getFormat() const;
+
+ /** Return the format of the SkStream or kUnknown_Format if it cannot be determined. Rewinds the
+ stream before returning.
+ */
+ static Format GetStreamFormat(SkStream*);
+
+ /** Return a readable string of the Format provided.
+ */
+ static const char* GetFormatName(Format);
+
+ /** Return a readable string of the value returned by getFormat().
+ */
+ const char* getFormatName() const;
+
+ /** Returns true if the decoder should try to dither the resulting image.
+ The default setting is true.
+ */
+ bool getDitherImage() const { return fDitherImage; }
+
+ /** Set to true if the the decoder should try to dither the resulting image.
+ The default setting is true.
+ */
+ void setDitherImage(bool dither) { fDitherImage = dither; }
+
+ /** Returns true if the decoder should try to decode the
+ resulting image to a higher quality even at the expense of
+ the decoding speed.
+ */
+ bool getPreferQualityOverSpeed() const { return fPreferQualityOverSpeed; }
+
+ /** Set to true if the the decoder should try to decode the
+ resulting image to a higher quality even at the expense of
+ the decoding speed.
+ */
+ void setPreferQualityOverSpeed(bool qualityOverSpeed) {
+ fPreferQualityOverSpeed = qualityOverSpeed;
+ }
+
+ /** Set to true to require the decoder to return a bitmap with unpremultiplied
+ colors. The default is false, meaning the resulting bitmap will have its
+ colors premultiplied.
+ NOTE: Passing true to this function may result in a bitmap which cannot
+ be properly used by Skia.
+ */
+ void setRequireUnpremultipliedColors(bool request) {
+ fRequireUnpremultipliedColors = request;
+ }
+
+ /** Returns true if the decoder will only return bitmaps with unpremultiplied
+ colors.
+ */
+ bool getRequireUnpremultipliedColors() const { return fRequireUnpremultipliedColors; }
+
+ /** \class Peeker
+
+ Base class for optional callbacks to retrieve meta/chunk data out of
+ an image as it is being decoded.
+ */
+ class Peeker : public SkRefCnt {
+ public:
+ SK_DECLARE_INST_COUNT(Peeker)
+
+ /** Return true to continue decoding, or false to indicate an error, which
+ will cause the decoder to not return the image.
+ */
+ virtual bool peek(const char tag[], const void* data, size_t length) = 0;
+ private:
+ typedef SkRefCnt INHERITED;
+ };
+
+ Peeker* getPeeker() const { return fPeeker; }
+ Peeker* setPeeker(Peeker*);
+
+ /** \class Chooser
+
+ Base class for optional callbacks to choose an image from a format that
+ contains multiple images.
+ */
+ class Chooser : public SkRefCnt {
+ public:
+ SK_DECLARE_INST_COUNT(Chooser)
+
+ virtual void begin(int count) {}
+ virtual void inspect(int index, SkBitmap::Config config, int width, int height) {}
+ /** Return the index of the subimage you want, or -1 to choose none of them.
+ */
+ virtual int choose() = 0;
+
+ private:
+ typedef SkRefCnt INHERITED;
+ };
+
+ Chooser* getChooser() const { return fChooser; }
+ Chooser* setChooser(Chooser*);
+
+ /**
+ @Deprecated. Use the struct version instead.
+
+ This optional table describes the caller's preferred config based on
+ information about the src data. For this table, the src attributes are
+ described in terms of depth (index (8), 16, 32/24) and if there is
+ per-pixel alpha. These inputs combine to create an index into the
+ pref[] table, which contains the caller's preferred config for that
+ input, or kNo_Config if there is no preference.
+
+ To specify no preference, call setPrefConfigTable(NULL), which is
+ the default.
+
+ Note, it is still at the discretion of the codec as to what output
+ config is actually returned, as it may not be able to support the
+ caller's preference.
+
+ Here is how the index into the table is computed from the src:
+ depth [8, 16, 32/24] -> 0, 2, 4
+ alpha [no, yes] -> 0, 1
+ The two index values are OR'd together.
+ src: 8-index, no-alpha -> 0
+ src: 8-index, yes-alpha -> 1
+ src: 16bit, no-alpha -> 2 // e.g. 565
+ src: 16bit, yes-alpha -> 3 // e.g. 1555
+ src: 32/24, no-alpha -> 4
+ src: 32/24, yes-alpha -> 5
+ */
+ void setPrefConfigTable(const SkBitmap::Config pref[6]);
+
+ /**
+ * Optional table describing the caller's preferred config based on
+ * information about the src data. Each field should be set to the
+ * preferred config for a src described in the name of the field. The
+ * src attributes are described in terms of depth (8-index,
+ * 8bit-grayscale, or 8-bits/component) and whether there is per-pixel
+ * alpha (does not apply to grayscale). If the caller has no preference
+ * for a particular src type, its slot should be set to kNo_Config.
+ *
+ * NOTE ABOUT PREFERRED CONFIGS:
+ * If a config is preferred, either using a pref table or as a parameter
+ * to some flavor of decode, it is still at the discretion of the codec
+ * as to what output config is actually returned, as it may not be able
+ * to support the caller's preference.
+ *
+ * If a bitmap is decoded into SkBitmap::A8_Config, the resulting bitmap
+ * will either be a conversion of the grayscale in the case of a
+ * grayscale source or the alpha channel in the case of a source with
+ * an alpha channel.
+ */
+ struct PrefConfigTable {
+ SkBitmap::Config fPrefFor_8Index_NoAlpha_src;
+ SkBitmap::Config fPrefFor_8Index_YesAlpha_src;
+ SkBitmap::Config fPrefFor_8Gray_src;
+ SkBitmap::Config fPrefFor_8bpc_NoAlpha_src;
+ SkBitmap::Config fPrefFor_8bpc_YesAlpha_src;
+ };
+
+ /**
+ * Set an optional table for specifying the caller's preferred config
+ * based on information about the src data.
+ *
+ * The default is no preference, which will assume the config set by
+ * decode is preferred.
+ */
+ void setPrefConfigTable(const PrefConfigTable&);
+
+ /**
+ * Do not use a PrefConfigTable to determine the output config. This
+ * is the default, so there is no need to call unless a PrefConfigTable
+ * was previously set.
+ */
+ void resetPrefConfigTable() { fUsePrefTable = false; }
+
+ SkBitmap::Allocator* getAllocator() const { return fAllocator; }
+ SkBitmap::Allocator* setAllocator(SkBitmap::Allocator*);
+
+ // sample-size, if set to > 1, tells the decoder to return a smaller than
+ // original bitmap, sampling 1 pixel for every size pixels. e.g. if sample
+ // size is set to 3, then the returned bitmap will be 1/3 as wide and high,
+ // and will contain 1/9 as many pixels as the original.
+ // Note: this is a hint, and the codec may choose to ignore this, or only
+ // approximate the sample size.
+ int getSampleSize() const { return fSampleSize; }
+ void setSampleSize(int size);
+
+ /** Reset the sampleSize to its default of 1
+ */
+ void resetSampleSize() { this->setSampleSize(1); }
+
+ /** Decoding is synchronous, but for long decodes, a different thread can
+ call this method safely. This sets a state that the decoders will
+ periodically check, and if they see it changed to cancel, they will
+ cancel. This will result in decode() returning false. However, there is
+ no guarantee that the decoder will see the state change in time, so
+ it is possible that cancelDecode() will be called, but will be ignored
+ and decode() will return true (assuming no other problems were
+ encountered).
+
+ This state is automatically reset at the beginning of decode().
+ */
+ void cancelDecode() {
+ // now the subclass must query shouldCancelDecode() to be informed
+ // of the request
+ fShouldCancelDecode = true;
+ }
+
+ /** Passed to the decode method. If kDecodeBounds_Mode is passed, then
+ only the bitmap's width/height/config need be set. If kDecodePixels_Mode
+ is passed, then the bitmap must have pixels or a pixelRef.
+ */
+ enum Mode {
+ kDecodeBounds_Mode, //!< only return width/height/config in bitmap
+ kDecodePixels_Mode //!< return entire bitmap (including pixels)
+ };
+
+ /** Given a stream, decode it into the specified bitmap.
+ If the decoder can decompress the image, it calls bitmap.setConfig(),
+ and then if the Mode is kDecodePixels_Mode, call allocPixelRef(),
+ which will allocated a pixelRef. To access the pixel memory, the codec
+ needs to call lockPixels/unlockPixels on the
+ bitmap. It can then set the pixels with the decompressed image.
+ * If the image cannot be decompressed, return false. After the
+ * decoding, the function converts the decoded config in bitmap
+ * to pref if possible. Whether a conversion is feasible is
+ * tested by Bitmap::canCopyTo(pref).
+
+ If an SkBitmap::Allocator is installed via setAllocator, it will be
+ used to allocate the pixel memory. A clever allocator can be used
+ to allocate the memory from a cache, volatile memory, or even from
+ an existing bitmap's memory.
+
+ If a Peeker is installed via setPeeker, it may be used to peek into
+ meta data during the decode.
+
+ If a Chooser is installed via setChooser, it may be used to select
+ which image to return from a format that contains multiple images.
+ */
+ bool decode(SkStream*, SkBitmap* bitmap, SkBitmap::Config pref, Mode);
+ bool decode(SkStream* stream, SkBitmap* bitmap, Mode mode) {
+ return this->decode(stream, bitmap, SkBitmap::kNo_Config, mode);
+ }
+
+ /**
+ * Given a stream, build an index for doing tile-based decode.
+ * The built index will be saved in the decoder, and the image size will
+ * be returned in width and height.
+ *
+ * Return true for success or false on failure.
+ */
+ bool buildTileIndex(SkStream*, int *width, int *height);
+
+ /**
+ * Decode a rectangle subset in the image.
+ * The method can only be called after buildTileIndex().
+ *
+ * Return true for success.
+ * Return false if the index is never built or failing in decoding.
+ */
+ bool decodeSubset(SkBitmap* bm, const SkIRect& subset, SkBitmap::Config pref);
+
+ /**
+ * @Deprecated
+ * Use decodeSubset instead.
+ */
+ bool decodeRegion(SkBitmap* bitmap, const SkIRect& rect, SkBitmap::Config pref) {
+ return this->decodeSubset(bitmap, rect, pref);
+ }
+
+ /** Given a stream, this will try to find an appropriate decoder object.
+ If none is found, the method returns NULL.
+ */
+ static SkImageDecoder* Factory(SkStream*);
+
+ /** Decode the image stored in the specified file, and store the result
+ in bitmap. Return true for success or false on failure.
+
+ @param prefConfig If the PrefConfigTable is not set, prefer this config.
+ See NOTE ABOUT PREFERRED CONFIGS.
+
+ @param format On success, if format is non-null, it is set to the format
+ of the decoded file. On failure it is ignored.
+ */
+ static bool DecodeFile(const char file[], SkBitmap* bitmap,
+ SkBitmap::Config prefConfig, Mode,
+ Format* format = NULL);
+ static bool DecodeFile(const char file[], SkBitmap* bitmap) {
+ return DecodeFile(file, bitmap, SkBitmap::kNo_Config,
+ kDecodePixels_Mode, NULL);
+ }
+ /** Decode the image stored in the specified memory buffer, and store the
+ result in bitmap. Return true for success or false on failure.
+
+ @param prefConfig If the PrefConfigTable is not set, prefer this config.
+ See NOTE ABOUT PREFERRED CONFIGS.
+
+ @param format On success, if format is non-null, it is set to the format
+ of the decoded buffer. On failure it is ignored.
+ */
+ static bool DecodeMemory(const void* buffer, size_t size, SkBitmap* bitmap,
+ SkBitmap::Config prefConfig, Mode,
+ Format* format = NULL);
+ static bool DecodeMemory(const void* buffer, size_t size, SkBitmap* bitmap){
+ return DecodeMemory(buffer, size, bitmap, SkBitmap::kNo_Config,
+ kDecodePixels_Mode, NULL);
+ }
+
+ /**
+ * Decode memory.
+ * @param info Output parameter. Returns info about the encoded image.
+ * @param target Contains the address of pixel memory to decode into
+ * (which must be large enough to hold the width in info) and
+ * the row bytes to use. If NULL, returns info and does not
+ * decode pixels.
+ * @return bool Whether the function succeeded.
+ *
+ * Sample usage:
+ * <code>
+ * // Determine the image's info: width/height/config
+ * SkImage::Info info;
+ * bool success = DecodeMemoryToTarget(src, size, &info, NULL);
+ * if (!success) return;
+ * // Allocate space for the result:
+ * SkBitmapFactory::Target target;
+ * target.fAddr = malloc/other allocation
+ * target.fRowBytes = ...
+ * // Now decode the actual pixels into target. &info is optional,
+ * // and could be NULL
+ * success = DecodeMemoryToTarget(src, size, &info, &target);
+ * </code>
+ */
+ static bool DecodeMemoryToTarget(const void* buffer, size_t size, SkImage::Info* info,
+ const SkBitmapFactory::Target* target);
+
+ /** Decode the image stored in the specified SkStream, and store the result
+ in bitmap. Return true for success or false on failure.
+
+ @param prefConfig If the PrefConfigTable is not set, prefer this config.
+ See NOTE ABOUT PREFERRED CONFIGS.
+
+ @param format On success, if format is non-null, it is set to the format
+ of the decoded stream. On failure it is ignored.
+ */
+ static bool DecodeStream(SkStream* stream, SkBitmap* bitmap,
+ SkBitmap::Config prefConfig, Mode,
+ Format* format = NULL);
+ static bool DecodeStream(SkStream* stream, SkBitmap* bitmap) {
+ return DecodeStream(stream, bitmap, SkBitmap::kNo_Config,
+ kDecodePixels_Mode, NULL);
+ }
+
+ /** Return the default config for the running device.
+ Currently this used as a suggestion to image decoders that need to guess
+ what config they should decode into.
+ Default is kNo_Config, but this can be changed with SetDeviceConfig()
+ */
+ static SkBitmap::Config GetDeviceConfig();
+ /** Set the default config for the running device.
+ Currently this used as a suggestion to image decoders that need to guess
+ what config they should decode into.
+ Default is kNo_Config.
+ This can be queried with GetDeviceConfig()
+ */
+ static void SetDeviceConfig(SkBitmap::Config);
+
+protected:
+ // must be overridden in subclasses. This guy is called by decode(...)
+ virtual bool onDecode(SkStream*, SkBitmap* bitmap, Mode) = 0;
+
+ // If the decoder wants to support tiled based decoding,
+ // this method must be overridden. This guy is called by buildTileIndex(...)
+ virtual bool onBuildTileIndex(SkStream*, int *width, int *height) {
+ return false;
+ }
+
+ // If the decoder wants to support tiled based decoding,
+ // this method must be overridden. This guy is called by decodeRegion(...)
+ virtual bool onDecodeSubset(SkBitmap* bitmap, const SkIRect& rect) {
+ return false;
+ }
+
+ /*
+ * Crop a rectangle from the src Bitmap to the dest Bitmap. src and dst are
+ * both sampled by sampleSize from an original Bitmap.
+ *
+ * @param dst the destination bitmap.
+ * @param src the source bitmap that is sampled by sampleSize from the
+ * original bitmap.
+ * @param sampleSize the sample size that src is sampled from the original bitmap.
+ * @param (dstX, dstY) the upper-left point of the dest bitmap in terms of
+ * the coordinate in the original bitmap.
+ * @param (width, height) the width and height of the unsampled dst.
+ * @param (srcX, srcY) the upper-left point of the src bitmap in terms of
+ * the coordinate in the original bitmap.
+ * @return bool Whether or not it succeeded.
+ */
+ bool cropBitmap(SkBitmap *dst, SkBitmap *src, int sampleSize,
+ int dstX, int dstY, int width, int height,
+ int srcX, int srcY);
+
+ /**
+ * Copy all fields on this decoder to the other decoder. Used by subclasses
+ * to decode a subimage using a different decoder, but with the same settings.
+ */
+ void copyFieldsToOther(SkImageDecoder* other);
+
+ /**
+ * Return the default preference being used by the current or latest call to
+ * decode.
+ */
+ SkBitmap::Config getDefaultPref() { return fDefaultPref; }
+
+ /** Can be queried from within onDecode, to see if the user (possibly in
+ a different thread) has requested the decode to cancel. If this returns
+ true, your onDecode() should stop and return false.
+ Each subclass needs to decide how often it can query this, to balance
+ responsiveness with performance.
+
+ Calling this outside of onDecode() may return undefined values.
+ */
+
+public:
+ bool shouldCancelDecode() const { return fShouldCancelDecode; }
+
+protected:
+ SkImageDecoder();
+
+ // helper function for decoders to handle the (common) case where there is only
+ // once choice available in the image file.
+ bool chooseFromOneChoice(SkBitmap::Config config, int width, int height) const;
+
+ /* Helper for subclasses. Call this to allocate the pixel memory given the bitmap's
+ width/height/rowbytes/config. Returns true on success. This method handles checking
+ for an optional Allocator.
+ */
+ bool allocPixelRef(SkBitmap*, SkColorTable*) const;
+
+ /**
+ * The raw data of the src image.
+ */
+ enum SrcDepth {
+ // Color-indexed.
+ kIndex_SrcDepth,
+ // Grayscale in 8 bits.
+ k8BitGray_SrcDepth,
+ // 8 bits per component. Used for 24 bit if there is no alpha.
+ k32Bit_SrcDepth,
+ };
+ /** The subclass, inside onDecode(), calls this to determine the config of
+ the returned bitmap. SrcDepth and hasAlpha reflect the raw data of the
+ src image. This routine returns the caller's preference given
+ srcDepth and hasAlpha, or kNo_Config if there is no preference.
+
+ Note: this also takes into account GetDeviceConfig(), so the subclass
+ need not call that.
+ */
+ SkBitmap::Config getPrefConfig(SrcDepth, bool hasAlpha) const;
+
+private:
+ Peeker* fPeeker;
+ Chooser* fChooser;
+ SkBitmap::Allocator* fAllocator;
+ int fSampleSize;
+ SkBitmap::Config fDefaultPref; // use if fUsePrefTable is false
+ PrefConfigTable fPrefTable; // use if fUsePrefTable is true
+ bool fDitherImage;
+ bool fUsePrefTable;
+ mutable bool fShouldCancelDecode;
+ bool fPreferQualityOverSpeed;
+ bool fRequireUnpremultipliedColors;
+};
+
+/** Calling newDecoder with a stream returns a new matching imagedecoder
+ instance, or NULL if none can be found. The caller must manage its ownership
+ of the stream as usual, calling unref() when it is done, as the returned
+ decoder may have called ref() (and if so, the decoder is responsible for
+ balancing its ownership when it is destroyed).
+ */
+class SkImageDecoderFactory : public SkRefCnt {
+public:
+ SK_DECLARE_INST_COUNT(SkImageDecoderFactory)
+
+ virtual SkImageDecoder* newDecoder(SkStream*) = 0;
+
+private:
+ typedef SkRefCnt INHERITED;
+};
+
+class SkDefaultImageDecoderFactory : SkImageDecoderFactory {
+public:
+ // calls SkImageDecoder::Factory(stream)
+ virtual SkImageDecoder* newDecoder(SkStream* stream) {
+ return SkImageDecoder::Factory(stream);
+ }
+};
+
+// This macro declares a global (i.e., non-class owned) creation entry point
+// for each decoder (e.g., CreateJPEGImageDecoder)
+#define DECLARE_DECODER_CREATOR(codec) \
+ SkImageDecoder *Create ## codec ();
+
+// This macro defines the global creation entry point for each decoder. Each
+// decoder implementation that registers with the decoder factory must call it.
+#define DEFINE_DECODER_CREATOR(codec) \
+ SkImageDecoder *Create ## codec () { \
+ return SkNEW( Sk ## codec ); \
+ }
+
+// All the decoders known by Skia. Note that, depending on the compiler settings,
+// not all of these will be available
+DECLARE_DECODER_CREATOR(BMPImageDecoder);
+DECLARE_DECODER_CREATOR(GIFImageDecoder);
+DECLARE_DECODER_CREATOR(ICOImageDecoder);
+DECLARE_DECODER_CREATOR(JPEGImageDecoder);
+DECLARE_DECODER_CREATOR(PNGImageDecoder);
+DECLARE_DECODER_CREATOR(WBMPImageDecoder);
+DECLARE_DECODER_CREATOR(WEBPImageDecoder);
+
+#endif
diff --git a/core/SkImageEncoder.h b/core/SkImageEncoder.h
new file mode 100644
index 0000000..b990aff
--- /dev/null
+++ b/core/SkImageEncoder.h
@@ -0,0 +1,100 @@
+
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#ifndef SkImageEncoder_DEFINED
+#define SkImageEncoder_DEFINED
+
+#include "SkTypes.h"
+
+class SkBitmap;
+class SkData;
+class SkWStream;
+
+class SkImageEncoder {
+public:
+ enum Type {
+ kUnknown_Type,
+ kBMP_Type,
+ kGIF_Type,
+ kICO_Type,
+ kJPEG_Type,
+ kPNG_Type,
+ kWBMP_Type,
+ kWEBP_Type,
+ };
+ static SkImageEncoder* Create(Type);
+
+ virtual ~SkImageEncoder();
+
+ /* Quality ranges from 0..100 */
+ enum {
+ kDefaultQuality = 80
+ };
+
+ /**
+ * Encode bitmap 'bm', returning the results in an SkData, at quality level
+ * 'quality' (which can be in range 0-100). If the bitmap cannot be
+ * encoded, return null. On success, the caller is responsible for
+ * calling unref() on the data when they are finished.
+ */
+ SkData* encodeData(const SkBitmap&, int quality);
+
+ /**
+ * Encode bitmap 'bm' in the desired format, writing results to
+ * file 'file', at quality level 'quality' (which can be in range
+ * 0-100). Returns false on failure.
+ */
+ bool encodeFile(const char file[], const SkBitmap& bm, int quality);
+
+ /**
+ * Encode bitmap 'bm' in the desired format, writing results to
+ * stream 'stream', at quality level 'quality' (which can be in
+ * range 0-100). Returns false on failure.
+ */
+ bool encodeStream(SkWStream* stream, const SkBitmap& bm, int quality);
+
+ static SkData* EncodeData(const SkBitmap&, Type, int quality);
+ static bool EncodeFile(const char file[], const SkBitmap&, Type,
+ int quality);
+ static bool EncodeStream(SkWStream*, const SkBitmap&, Type,
+ int quality);
+
+protected:
+ /**
+ * Encode bitmap 'bm' in the desired format, writing results to
+ * stream 'stream', at quality level 'quality' (which can be in
+ * range 0-100).
+ *
+ * This must be overridden by each SkImageEncoder implementation.
+ */
+ virtual bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality) = 0;
+};
+
+// This macro declares a global (i.e., non-class owned) creation entry point
+// for each encoder (e.g., CreateJPEGImageEncoder)
+#define DECLARE_ENCODER_CREATOR(codec) \
+ SkImageEncoder *Create ## codec ();
+
+// This macro defines the global creation entry point for each encoder. Each
+// encoder implementation that registers with the encoder factory must call it.
+#define DEFINE_ENCODER_CREATOR(codec) \
+ SkImageEncoder *Create ## codec () { \
+ return SkNEW( Sk ## codec ); \
+ }
+
+// All the encoders known by Skia. Note that, depending on the compiler settings,
+// not all of these will be available
+/** An ARGBImageEncoder will always write out
+ * bitmap.width() * bitmap.height() * 4
+ * bytes.
+ */
+DECLARE_ENCODER_CREATOR(ARGBImageEncoder);
+DECLARE_ENCODER_CREATOR(JPEGImageEncoder);
+DECLARE_ENCODER_CREATOR(PNGImageEncoder);
+DECLARE_ENCODER_CREATOR(WEBPImageEncoder);
+
+#endif
diff --git a/core/SkImageFilter.h b/core/SkImageFilter.h
new file mode 100644
index 0000000..01b3e0b
--- /dev/null
+++ b/core/SkImageFilter.h
@@ -0,0 +1,173 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkImageFilter_DEFINED
+#define SkImageFilter_DEFINED
+
+#include "SkFlattenable.h"
+#include "SkRect.h"
+
+class SkBitmap;
+class SkColorFilter;
+class SkDevice;
+class SkMatrix;
+struct SkIPoint;
+class SkShader;
+class GrEffectRef;
+class GrTexture;
+
+/**
+ * Base class for image filters. If one is installed in the paint, then
+ * all drawing occurs as usual, but it is as if the drawing happened into an
+ * offscreen (before the xfermode is applied). This offscreen bitmap will
+ * then be handed to the imagefilter, who in turn creates a new bitmap which
+ * is what will finally be drawn to the device (using the original xfermode).
+ */
+class SK_API SkImageFilter : public SkFlattenable {
+public:
+ SK_DECLARE_INST_COUNT(SkImageFilter)
+
+ class Proxy {
+ public:
+ virtual ~Proxy() {};
+
+ virtual SkDevice* createDevice(int width, int height) = 0;
+ // returns true if the proxy can handle this filter natively
+ virtual bool canHandleImageFilter(SkImageFilter*) = 0;
+ // returns true if the proxy handled the filter itself. if this returns
+ // false then the filter's code will be called.
+ virtual bool filterImage(SkImageFilter*, const SkBitmap& src,
+ const SkMatrix& ctm,
+ SkBitmap* result, SkIPoint* offset) = 0;
+ };
+
+ /**
+ * Request a new (result) image to be created from the src image.
+ * If the src has no pixels (isNull()) then the request just wants to
+ * receive the config and width/height of the result.
+ *
+ * The matrix is the current matrix on the canvas.
+ *
+ * Offset is the amount to translate the resulting image relative to the
+ * src when it is drawn.
+ *
+ * If the result image cannot be created, return false, in which case both
+ * the result and offset parameters will be ignored by the caller.
+ */
+ bool filterImage(Proxy*, const SkBitmap& src, const SkMatrix& ctm,
+ SkBitmap* result, SkIPoint* offset);
+
+ /**
+ * Given the src bounds of an image, this returns the bounds of the result
+ * image after the filter has been applied.
+ */
+ bool filterBounds(const SkIRect& src, const SkMatrix& ctm, SkIRect* dst);
+
+ /**
+ * Returns true if the filter can be expressed a single-pass
+ * GrEffect, used to process this filter on the GPU, or false if
+ * not.
+ *
+ * If effect is non-NULL, a new GrEffect instance is stored
+ * in it. The caller assumes ownership of the stage, and it is up to the
+ * caller to unref it.
+ *
+ * The effect can assume its vertexCoords space maps 1-to-1 with texels
+ * in the texture. "offset" is the delta between the source and
+ * destination rect's origins, when cropped processing is being performed.
+ */
+ virtual bool asNewEffect(GrEffectRef** effect, GrTexture*, const SkIPoint& offset) const;
+
+ /**
+ * Returns true if the filter can be processed on the GPU. This is most
+ * often used for multi-pass effects, where intermediate results must be
+ * rendered to textures. For single-pass effects, use asNewEffect().
+ * The default implementation returns asNewEffect(NULL, NULL).
+ */
+ virtual bool canFilterImageGPU() const;
+
+ /**
+ * Process this image filter on the GPU. This is most often used for
+ * multi-pass effects, where intermediate results must be rendered to
+ * textures. For single-pass effects, use asNewEffect(). src is the
+ * source image for processing, as a texture-backed bitmap. result is
+ * the destination bitmap, which should contain a texture-backed pixelref
+ * on success. offset is the amount to translate the resulting image
+ * relative to the src when it is drawn. The default implementation does
+ * single-pass processing using asNewEffect().
+ */
+ virtual bool filterImageGPU(Proxy*, const SkBitmap& src, const SkMatrix& ctm,
+ SkBitmap* result, SkIPoint* offset);
+
+ /**
+ * Returns whether this image filter is a color filter and puts the color filter into the
+ * "filterPtr" parameter if it can. Does nothing otherwise.
+ * If this returns false, then the filterPtr is unchanged.
+ * If this returns true, then if filterPtr is not null, it must be set to a ref'd colorfitler
+ * (i.e. it may not be set to NULL).
+ */
+ virtual bool asColorFilter(SkColorFilter** filterPtr) const;
+
+ /**
+ * Returns the number of inputs this filter will accept (some inputs can
+ * be NULL).
+ */
+ int countInputs() const { return fInputCount; }
+
+ /**
+ * Returns the input filter at a given index, or NULL if no input is
+ * connected. The indices used are filter-specific.
+ */
+ SkImageFilter* getInput(int i) const {
+ SkASSERT(i < fInputCount);
+ return fInputs[i];
+ }
+
+ /**
+ * Returns the crop rectangle of this filter. This is set at construction
+ * time, and determines which pixels from the input image will
+ * be processed. The size of this rectangle should be used as the size
+ * of the destination image. The origin of this rect should be used to
+ * offset access to the input images, and should also be added to the
+ * "offset" parameter in onFilterImage and filterImageGPU(). (The latter
+ * ensures that the resulting buffer is drawn in the correct location.)
+ */
+ const SkIRect& cropRect() const { return fCropRect; }
+
+protected:
+ SkImageFilter(int inputCount, SkImageFilter** inputs, const SkIRect* cropRect = NULL);
+
+ // Convenience constructor for 1-input filters.
+ explicit SkImageFilter(SkImageFilter* input, const SkIRect* cropRect = NULL);
+
+ // Convenience constructor for 2-input filters.
+ SkImageFilter(SkImageFilter* input1, SkImageFilter* input2, const SkIRect* cropRect = NULL);
+
+ virtual ~SkImageFilter();
+
+ explicit SkImageFilter(SkFlattenableReadBuffer& rb);
+
+ virtual void flatten(SkFlattenableWriteBuffer& wb) const SK_OVERRIDE;
+
+ // Default impl returns false
+ virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&,
+ SkBitmap* result, SkIPoint* offset);
+ // Default impl copies src into dst and returns true
+ virtual bool onFilterBounds(const SkIRect&, const SkMatrix&, SkIRect*);
+
+ // Sets rect to the intersection of rect and the crop rect. If there
+ // is no overlap, returns false and leaves rect unchanged.
+ bool applyCropRect(SkIRect* rect) const;
+
+private:
+ typedef SkFlattenable INHERITED;
+ int fInputCount;
+ SkImageFilter** fInputs;
+ SkIRect fCropRect;
+};
+
+#endif
diff --git a/core/SkImageFilterUtils.h b/core/SkImageFilterUtils.h
new file mode 100644
index 0000000..b3921cd
--- /dev/null
+++ b/core/SkImageFilterUtils.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2013 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkImageFilterUtils_DEFINED
+#define SkImageFilterUtils_DEFINED
+
+#if SK_SUPPORT_GPU
+
+#include "SkImageFilter.h"
+
+class SkBitmap;
+class GrTexture;
+class SkImageFilter;
+
+class SK_API SkImageFilterUtils {
+public:
+ /**
+ * Wrap the given texture in a texture-backed SkBitmap.
+ */
+ static bool WrapTexture(GrTexture* texture, int width, int height, SkBitmap* result);
+
+ /**
+ * Recursively evaluate the given filter on the GPU. If filter is NULL,
+ * this function returns src. If the filter has no GPU implementation, it
+ * will be processed in software and uploaded to the GPU.
+ */
+ static bool GetInputResultGPU(SkImageFilter* filter, SkImageFilter::Proxy* proxy,
+ const SkBitmap& src, const SkMatrix& ctm, SkBitmap* result,
+ SkIPoint* offset);
+};
+
+#endif
+
+#endif
diff --git a/core/SkImageTypes.h b/core/SkImageTypes.h
new file mode 100644
index 0000000..541c388
--- /dev/null
+++ b/core/SkImageTypes.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkImageTypes_DEFINED
+#define SkImageTypes_DEFINED
+
+#include "SkTypes.h"
+
+enum SkColorType {
+ kAlpha_8_SkColorType,
+ kRGB_565_SkColorType,
+// kRGBA_8888_SkColorType,
+// kBGRA_8888_SkColorType,
+ kPMColor_SkColorType,
+
+ kLastEnum_SkColorType = kPMColor_SkColorType
+};
+
+enum SkAlphaType {
+// kIgnore_SkAlphaType,
+ kOpaque_SkAlphaType,
+// kUnpremul_SkAlphaType,
+ kPremul_SkAlphaType,
+
+ kLastEnum_SkAlphaType = kPremul_SkAlphaType
+};
+
+struct SkImageInfo {
+ int fWidth;
+ int fHeight;
+ SkColorType fColorType;
+ SkAlphaType fAlphaType;
+};
+
+#endif
diff --git a/core/SkInstCnt.h b/core/SkInstCnt.h
new file mode 100644
index 0000000..cab8ebb
--- /dev/null
+++ b/core/SkInstCnt.h
@@ -0,0 +1,133 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkInstCnt_DEFINED
+#define SkInstCnt_DEFINED
+
+/*
+ * The instance counting system consists of three macros that create the
+ * instance counting machinery. A class is added to the system by adding:
+ * SK_DECLARE_INST_COUNT at the top of its declaration for derived classes
+ * SK_DECLARE_INST_COUNT_ROOT at the top of its declaration for a root class
+ * SK_DEFINE_INST_COUNT at the top of its .cpp file (for both kinds).
+ * At the end of an application a call to all the "root" objects'
+ * CheckInstanceCount methods should be made
+ */
+#include "SkTypes.h"
+
+#if SK_ENABLE_INST_COUNT
+#include "SkTArray.h"
+#include "SkThread_platform.h"
+
+extern bool gPrintInstCount;
+
+// The non-root classes just register themselves with their parent
+#define SK_DECLARE_INST_COUNT(className) \
+ SK_DECLARE_INST_COUNT_INTERNAL(className, \
+ INHERITED::AddInstChild(CheckInstanceCount);,\
+ /**/)
+
+#define SK_DECLARE_INST_COUNT_TEMPLATE(className) \
+ SK_DECLARE_INST_COUNT_INTERNAL(className, \
+ INHERITED::AddInstChild(CheckInstanceCount);, \
+ typename)
+
+// The root classes registers a function to print out the memory stats when
+// the app ends
+#define SK_DECLARE_INST_COUNT_ROOT(className) \
+ SK_DECLARE_INST_COUNT_INTERNAL(className, atexit(exitPrint);, /**/)
+
+#define SK_DECLARE_INST_COUNT_INTERNAL(className, initStep, templateType) \
+ class SkInstanceCountHelper { \
+ public: \
+ typedef int (*PFCheckInstCnt)(int level, bool cleanUp); \
+ SkInstanceCountHelper() { \
+ if (!gInited) { \
+ initStep \
+ gChildren = new SkTArray<PFCheckInstCnt>; \
+ gInited = true; \
+ } \
+ sk_atomic_inc(&gInstanceCount); \
+ } \
+ \
+ SkInstanceCountHelper(const SkInstanceCountHelper&) { \
+ sk_atomic_inc(&gInstanceCount); \
+ } \
+ \
+ ~SkInstanceCountHelper() { \
+ sk_atomic_dec(&gInstanceCount); \
+ } \
+ \
+ static int32_t gInstanceCount; \
+ static bool gInited; \
+ static SkTArray<PFCheckInstCnt>* gChildren; \
+ } fInstanceCountHelper; \
+ \
+ static int32_t GetInstanceCount() { \
+ return SkInstanceCountHelper::gInstanceCount; \
+ } \
+ \
+ static void exitPrint() { \
+ CheckInstanceCount(0, true); \
+ } \
+ \
+ static int CheckInstanceCount(int level = 0, bool cleanUp = false) { \
+ if (gPrintInstCount && 0 != SkInstanceCountHelper::gInstanceCount) {\
+ SkDebugf("%*c Leaked %s: %d\n", \
+ 4*level, ' ', #className, \
+ SkInstanceCountHelper::gInstanceCount); \
+ } \
+ if (NULL == SkInstanceCountHelper::gChildren) { \
+ return SkInstanceCountHelper::gInstanceCount; \
+ } \
+ int childCount = SkInstanceCountHelper::gChildren->count(); \
+ int count = SkInstanceCountHelper::gInstanceCount; \
+ for (int i = 0; i < childCount; ++i) { \
+ count -= (*(*SkInstanceCountHelper::gChildren)[i])(level+1, cleanUp); \
+ } \
+ SkASSERT(count >= 0); \
+ if (gPrintInstCount && childCount > 0 && count > 0) { \
+ SkDebugf("%*c Leaked ???: %d\n", 4*(level + 1), ' ', count); \
+ } \
+ if (cleanUp) { \
+ delete SkInstanceCountHelper::gChildren; \
+ SkInstanceCountHelper::gChildren = NULL; \
+ } \
+ return SkInstanceCountHelper::gInstanceCount; \
+ } \
+ \
+ static void AddInstChild(templateType SkInstanceCountHelper::PFCheckInstCnt \
+ childCheckInstCnt) { \
+ if (CheckInstanceCount != childCheckInstCnt && \
+ NULL != SkInstanceCountHelper::gChildren) { \
+ SkInstanceCountHelper::gChildren->push_back(childCheckInstCnt); \
+ } \
+ }
+
+#define SK_DEFINE_INST_COUNT(className) \
+ int32_t className::SkInstanceCountHelper::gInstanceCount = 0; \
+ bool className::SkInstanceCountHelper::gInited = false; \
+ SkTArray<className::SkInstanceCountHelper::PFCheckInstCnt>* \
+ className::SkInstanceCountHelper::gChildren = NULL;
+
+#define SK_DEFINE_INST_COUNT_TEMPLATE(templateInfo, className) \
+ templateInfo int32_t className::SkInstanceCountHelper::gInstanceCount = 0;\
+ templateInfo bool className::SkInstanceCountHelper::gInited = false; \
+ templateInfo \
+ SkTArray<typename className::SkInstanceCountHelper::PFCheckInstCnt>*\
+ className::SkInstanceCountHelper::gChildren = NULL;
+
+#else
+#define SK_DECLARE_INST_COUNT(className)
+#define SK_DECLARE_INST_COUNT_TEMPLATE(className)
+#define SK_DECLARE_INST_COUNT_ROOT(className)
+#define SK_DEFINE_INST_COUNT(className)
+#define SK_DEFINE_INST_COUNT_TEMPLATE(templateInfo, className)
+#endif
+
+#endif // SkInstCnt_DEFINED
diff --git a/core/SkLineClipper.h b/core/SkLineClipper.h
new file mode 100644
index 0000000..8026890
--- /dev/null
+++ b/core/SkLineClipper.h
@@ -0,0 +1,47 @@
+
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#ifndef SkLineClipper_DEFINED
+#define SkLineClipper_DEFINED
+
+#include "SkRect.h"
+#include "SkPoint.h"
+
+class SkLineClipper {
+public:
+ enum {
+ kMaxPoints = 4,
+ kMaxClippedLineSegments = kMaxPoints - 1
+ };
+
+ /* Clip the line pts[0]...pts[1] against clip, ignoring segments that
+ lie completely above or below the clip. For portions to the left or
+ right, turn those into vertical line segments that are aligned to the
+ edge of the clip.
+
+ Return the number of line segments that result, and store the end-points
+ of those segments sequentially in lines as follows:
+ 1st segment: lines[0]..lines[1]
+ 2nd segment: lines[1]..lines[2]
+ 3rd segment: lines[2]..lines[3]
+ */
+ static int ClipLine(const SkPoint pts[2], const SkRect& clip,
+ SkPoint lines[kMaxPoints]);
+
+ /* Intersect the line segment against the rect. If there is a non-empty
+ resulting segment, return true and set dst[] to that segment. If not,
+ return false and ignore dst[].
+
+ ClipLine is specialized for scan-conversion, as it adds vertical
+ segments on the sides to show where the line extended beyond the
+ left or right sides. IntersectLine does not.
+ */
+ static bool IntersectLine(const SkPoint src[2], const SkRect& clip,
+ SkPoint dst[2]);
+};
+
+#endif
diff --git a/core/SkMallocPixelRef.h b/core/SkMallocPixelRef.h
new file mode 100644
index 0000000..2241a51
--- /dev/null
+++ b/core/SkMallocPixelRef.h
@@ -0,0 +1,51 @@
+
+/*
+ * Copyright 2008 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkMallocPixelRef_DEFINED
+#define SkMallocPixelRef_DEFINED
+
+#include "SkPixelRef.h"
+
+/** We explicitly use the same allocator for our pixels that SkMask does,
+ so that we can freely assign memory allocated by one class to the other.
+*/
+class SkMallocPixelRef : public SkPixelRef {
+public:
+ /** Allocate the specified buffer for pixels. The memory is freed when the
+ last owner of this pixelref is gone. If addr is NULL, sk_malloc_throw()
+ is called to allocate it.
+ */
+ SkMallocPixelRef(void* addr, size_t size, SkColorTable* ctable, bool ownPixels = true);
+ virtual ~SkMallocPixelRef();
+
+ //! Return the allocation size for the pixels
+ size_t getSize() const { return fSize; }
+ void* getAddr() const { return fStorage; }
+
+ SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkMallocPixelRef)
+
+protected:
+ // overrides from SkPixelRef
+ virtual void* onLockPixels(SkColorTable**);
+ virtual void onUnlockPixels();
+
+ SkMallocPixelRef(SkFlattenableReadBuffer& buffer);
+ virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
+
+private:
+ void* fStorage;
+ size_t fSize;
+ SkColorTable* fCTable;
+ bool fOwnPixels;
+
+ typedef SkPixelRef INHERITED;
+};
+
+
+#endif
diff --git a/core/SkMask.h b/core/SkMask.h
new file mode 100644
index 0000000..7155184
--- /dev/null
+++ b/core/SkMask.h
@@ -0,0 +1,161 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkMask_DEFINED
+#define SkMask_DEFINED
+
+#include "SkRect.h"
+
+/** \class SkMask
+ SkMask is used to describe alpha bitmaps, either 1bit, 8bit, or
+ the 3-channel 3D format. These are passed to SkMaskFilter objects.
+*/
+struct SkMask {
+ enum Format {
+ kBW_Format, //!< 1bit per pixel mask (e.g. monochrome)
+ kA8_Format, //!< 8bits per pixel mask (e.g. antialiasing)
+ k3D_Format, //!< 3 8bit per pixl planes: alpha, mul, add
+ kARGB32_Format, //!< SkPMColor
+ kLCD16_Format, //!< 565 alpha for r/g/b
+ kLCD32_Format //!< 888 alpha for r/g/b
+ };
+
+ enum {
+ kCountMaskFormats = kLCD32_Format + 1
+ };
+
+ uint8_t* fImage;
+ SkIRect fBounds;
+ uint32_t fRowBytes;
+ Format fFormat;
+
+ /** Returns true if the mask is empty: i.e. it has an empty bounds.
+ */
+ bool isEmpty() const { return fBounds.isEmpty(); }
+
+ /** Return the byte size of the mask, assuming only 1 plane.
+ Does not account for k3D_Format. For that, use computeTotalImageSize().
+ If there is an overflow of 32bits, then returns 0.
+ */
+ size_t computeImageSize() const;
+
+ /** Return the byte size of the mask, taking into account
+ any extra planes (e.g. k3D_Format).
+ If there is an overflow of 32bits, then returns 0.
+ */
+ size_t computeTotalImageSize() const;
+
+ /** Returns the address of the byte that holds the specified bit.
+ Asserts that the mask is kBW_Format, and that x,y are in range.
+ x,y are in the same coordiate space as fBounds.
+ */
+ uint8_t* getAddr1(int x, int y) const {
+ SkASSERT(kBW_Format == fFormat);
+ SkASSERT(fBounds.contains(x, y));
+ SkASSERT(fImage != NULL);
+ return fImage + ((x - fBounds.fLeft) >> 3) + (y - fBounds.fTop) * fRowBytes;
+ }
+
+ /** Returns the address of the specified byte.
+ Asserts that the mask is kA8_Format, and that x,y are in range.
+ x,y are in the same coordiate space as fBounds.
+ */
+ uint8_t* getAddr8(int x, int y) const {
+ SkASSERT(kA8_Format == fFormat);
+ SkASSERT(fBounds.contains(x, y));
+ SkASSERT(fImage != NULL);
+ return fImage + x - fBounds.fLeft + (y - fBounds.fTop) * fRowBytes;
+ }
+
+ /**
+ * Return the address of the specified 16bit mask. In the debug build,
+ * this asserts that the mask's format is kLCD16_Format, and that (x,y)
+ * are contained in the mask's fBounds.
+ */
+ uint16_t* getAddrLCD16(int x, int y) const {
+ SkASSERT(kLCD16_Format == fFormat);
+ SkASSERT(fBounds.contains(x, y));
+ SkASSERT(fImage != NULL);
+ uint16_t* row = (uint16_t*)(fImage + (y - fBounds.fTop) * fRowBytes);
+ return row + (x - fBounds.fLeft);
+ }
+
+ /**
+ * Return the address of the specified 32bit mask. In the debug build,
+ * this asserts that the mask's format is kLCD32_Format, and that (x,y)
+ * are contained in the mask's fBounds.
+ */
+ uint32_t* getAddrLCD32(int x, int y) const {
+ SkASSERT(kLCD32_Format == fFormat);
+ SkASSERT(fBounds.contains(x, y));
+ SkASSERT(fImage != NULL);
+ uint32_t* row = (uint32_t*)(fImage + (y - fBounds.fTop) * fRowBytes);
+ return row + (x - fBounds.fLeft);
+ }
+
+ /**
+ * Return the address of the specified 32bit mask. In the debug build,
+ * this asserts that the mask's format is 32bits, and that (x,y)
+ * are contained in the mask's fBounds.
+ */
+ uint32_t* getAddr32(int x, int y) const {
+ SkASSERT(kLCD32_Format == fFormat || kARGB32_Format == fFormat);
+ SkASSERT(fBounds.contains(x, y));
+ SkASSERT(fImage != NULL);
+ uint32_t* row = (uint32_t*)(fImage + (y - fBounds.fTop) * fRowBytes);
+ return row + (x - fBounds.fLeft);
+ }
+
+ /**
+ * Returns the address of the specified pixel, computing the pixel-size
+ * at runtime based on the mask format. This will be slightly slower than
+ * using one of the routines where the format is implied by the name
+ * e.g. getAddr8 or getAddrLCD32.
+ *
+ * x,y must be contained by the mask's bounds (this is asserted in the
+ * debug build, but not checked in the release build.)
+ *
+ * This should not be called with kBW_Format, as it will give unspecified
+ * results (and assert in the debug build).
+ */
+ void* getAddr(int x, int y) const;
+
+ static uint8_t* AllocImage(size_t bytes);
+ static void FreeImage(void* image);
+
+ enum CreateMode {
+ kJustComputeBounds_CreateMode, //!< compute bounds and return
+ kJustRenderImage_CreateMode, //!< render into preallocate mask
+ kComputeBoundsAndRenderImage_CreateMode //!< compute bounds, alloc image and render into it
+ };
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+/**
+ * \class SkAutoMaskImage
+ *
+ * Stack class used to manage the fImage buffer in a SkMask.
+ * When this object loses scope, the buffer is freed with SkMask::FreeImage().
+ */
+class SkAutoMaskFreeImage {
+public:
+ SkAutoMaskFreeImage(uint8_t* maskImage) {
+ fImage = maskImage;
+ }
+
+ ~SkAutoMaskFreeImage() {
+ SkMask::FreeImage(fImage);
+ }
+
+private:
+ uint8_t* fImage;
+};
+
+#endif
diff --git a/core/SkMaskFilter.h b/core/SkMaskFilter.h
new file mode 100644
index 0000000..fda1289
--- /dev/null
+++ b/core/SkMaskFilter.h
@@ -0,0 +1,179 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkMaskFilter_DEFINED
+#define SkMaskFilter_DEFINED
+
+#include "SkFlattenable.h"
+#include "SkMask.h"
+#include "SkPaint.h"
+
+class SkBitmap;
+class SkBlitter;
+class SkBounder;
+class SkMatrix;
+class SkPath;
+class SkRasterClip;
+
+/** \class SkMaskFilter
+
+ SkMaskFilter is the base class for object that perform transformations on
+ an alpha-channel mask before drawing it. A subclass of SkMaskFilter may be
+ installed into a SkPaint. Once there, each time a primitive is drawn, it
+ is first scan converted into a SkMask::kA8_Format mask, and handed to the
+ filter, calling its filterMask() method. If this returns true, then the
+ new mask is used to render into the device.
+
+ Blur and emboss are implemented as subclasses of SkMaskFilter.
+*/
+class SK_API SkMaskFilter : public SkFlattenable {
+public:
+ SK_DECLARE_INST_COUNT(SkMaskFilter)
+
+ SkMaskFilter() {}
+
+ /** Returns the format of the resulting mask that this subclass will return
+ when its filterMask() method is called.
+ */
+ virtual SkMask::Format getFormat() const = 0;
+
+ /** Create a new mask by filter the src mask.
+ If src.fImage == null, then do not allocate or create the dst image
+ but do fill out the other fields in dstMask.
+ If you do allocate a dst image, use SkMask::AllocImage()
+ If this returns false, dst mask is ignored.
+ @param dst the result of the filter. If src.fImage == null, dst should not allocate its image
+ @param src the original image to be filtered.
+ @param matrix the CTM
+ @param margin if not null, return the buffer dx/dy need when calculating the effect. Used when
+ drawing a clipped object to know how much larger to allocate the src before
+ applying the filter. If returning false, ignore this parameter.
+ @return true if the dst mask was correctly created.
+ */
+ virtual bool filterMask(SkMask* dst, const SkMask& src, const SkMatrix&,
+ SkIPoint* margin) const;
+
+#if SK_SUPPORT_GPU
+ /**
+ * Returns true if the filter can be expressed a single-pass
+ * GrEffect, used to process this filter on the GPU, or false if
+ * not.
+ *
+ * If effect is non-NULL, a new GrEffect instance is stored
+ * in it. The caller assumes ownership of the stage, and it is up to the
+ * caller to unref it.
+ */
+ virtual bool asNewEffect(GrEffectRef** effect, GrTexture*) const;
+
+ /**
+ * Returns true if the filter can be processed on the GPU. This is most
+ * often used for multi-pass effects, where intermediate results must be
+ * rendered to textures. For single-pass effects, use asNewEffect().
+ *
+ * 'maskRect' returns the device space portion of the mask the the filter
+ * needs. The mask passed into 'filterMaskGPU' should have the same extent
+ * as 'maskRect' but be translated to the upper-left corner of the mask
+ * (i.e., (maskRect.fLeft, maskRect.fTop) appears at (0, 0) in the mask).
+ */
+ virtual bool canFilterMaskGPU(const SkRect& devBounds,
+ const SkIRect& clipBounds,
+ const SkMatrix& ctm,
+ SkRect* maskRect) const;
+
+ /**
+ * Perform this mask filter on the GPU. This is most often used for
+ * multi-pass effects, where intermediate results must be rendered to
+ * textures. For single-pass effects, use asNewEffect(). 'src' is the
+ * source image for processing, as a texture-backed bitmap. 'result' is
+ * the destination bitmap, which should contain a texture-backed pixelref
+ * on success. 'maskRect' should be the rect returned from canFilterMaskGPU.
+ */
+ bool filterMaskGPU(GrContext* context,
+ const SkBitmap& src,
+ const SkRect& maskRect,
+ SkBitmap* result) const;
+
+ /**
+ * This flavor of 'filterMaskGPU' provides a more direct means of accessing
+ * the filtering capabilities. Setting 'canOverwriteSrc' can allow some
+ * filters to skip the allocation of an additional texture.
+ */
+ virtual bool filterMaskGPU(GrTexture* src,
+ const SkRect& maskRect,
+ GrTexture** result,
+ bool canOverwriteSrc) const;
+#endif
+
+ /**
+ * The fast bounds function is used to enable the paint to be culled early
+ * in the drawing pipeline. This function accepts the current bounds of the
+ * paint as its src param and the filter adjust those bounds using its
+ * current mask and returns the result using the dest param. Callers are
+ * allowed to provide the same struct for both src and dest so each
+ * implementation must accomodate that behavior.
+ *
+ * The default impl calls filterMask with the src mask having no image,
+ * but subclasses may override this if they can compute the rect faster.
+ */
+ virtual void computeFastBounds(const SkRect& src, SkRect* dest) const;
+
+ SkDEVCODE(virtual void toString(SkString* str) const = 0;)
+
+protected:
+ // empty for now, but lets get our subclass to remember to init us for the future
+ SkMaskFilter(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {}
+
+ enum FilterReturn {
+ kFalse_FilterReturn,
+ kTrue_FilterReturn,
+ kUnimplemented_FilterReturn
+ };
+
+ struct NinePatch {
+ SkMask fMask; // fBounds must have [0,0] in its top-left
+ SkIRect fOuterRect; // width/height must be >= fMask.fBounds'
+ SkIPoint fCenter; // identifies center row/col for stretching
+ };
+
+ /**
+ * Override if your subclass can filter a rect, and return the answer as
+ * a ninepatch mask to be stretched over the returned outerRect. On success
+ * return kTrue_FilterReturn. On failure (e.g. out of memory) return
+ * kFalse_FilterReturn. If the normal filterMask() entry-point should be
+ * called (the default) return kUnimplemented_FilterReturn.
+ *
+ * By convention, the caller will take the center rol/col from the returned
+ * mask as the slice it can replicate horizontally and vertically as we
+ * stretch the mask to fit inside outerRect. It is an error for outerRect
+ * to be smaller than the mask's bounds. This would imply that the width
+ * and height of the mask should be odd. This is not required, just that
+ * the caller will call mask.fBounds.centerX() and centerY() to find the
+ * strips that will be replicated.
+ */
+ virtual FilterReturn filterRectsToNine(const SkRect[], int count,
+ const SkMatrix&,
+ const SkIRect& clipBounds,
+ NinePatch*) const;
+
+private:
+ friend class SkDraw;
+
+ /** Helper method that, given a path in device space, will rasterize it into a kA8_Format mask
+ and then call filterMask(). If this returns true, the specified blitter will be called
+ to render that mask. Returns false if filterMask() returned false.
+ This method is not exported to java.
+ */
+ bool filterPath(const SkPath& devPath, const SkMatrix& devMatrix,
+ const SkRasterClip&, SkBounder*, SkBlitter* blitter,
+ SkPaint::Style style) const;
+
+ typedef SkFlattenable INHERITED;
+};
+
+#endif
diff --git a/core/SkMath.h b/core/SkMath.h
new file mode 100644
index 0000000..078c8fc
--- /dev/null
+++ b/core/SkMath.h
@@ -0,0 +1,176 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkMath_DEFINED
+#define SkMath_DEFINED
+
+#include "SkTypes.h"
+
+/**
+ * Computes numer1 * numer2 / denom in full 64 intermediate precision.
+ * It is an error for denom to be 0. There is no special handling if
+ * the result overflows 32bits.
+ */
+int32_t SkMulDiv(int32_t numer1, int32_t numer2, int32_t denom);
+
+/**
+ * Computes (numer1 << shift) / denom in full 64 intermediate precision.
+ * It is an error for denom to be 0. There is no special handling if
+ * the result overflows 32bits.
+ */
+int32_t SkDivBits(int32_t numer, int32_t denom, int shift);
+
+/**
+ * Return the integer square root of value, with a bias of bitBias
+ */
+int32_t SkSqrtBits(int32_t value, int bitBias);
+
+/** Return the integer square root of n, treated as a SkFixed (16.16)
+ */
+#define SkSqrt32(n) SkSqrtBits(n, 15)
+
+///////////////////////////////////////////////////////////////////////////////
+
+//! Returns the number of leading zero bits (0...32)
+int SkCLZ_portable(uint32_t);
+
+#ifndef SkCLZ
+ #if defined(_MSC_VER) && _MSC_VER >= 1400
+ #include <intrin.h>
+
+ static inline int SkCLZ(uint32_t mask) {
+ if (mask) {
+ DWORD index;
+ _BitScanReverse(&index, mask);
+ return index ^ 0x1F;
+ } else {
+ return 32;
+ }
+ }
+ #elif defined(SK_CPU_ARM) || defined(__GNUC__) || defined(__clang__)
+ static inline int SkCLZ(uint32_t mask) {
+ // __builtin_clz(0) is undefined, so we have to detect that case.
+ return mask ? __builtin_clz(mask) : 32;
+ }
+ #else
+ #define SkCLZ(x) SkCLZ_portable(x)
+ #endif
+#endif
+
+/**
+ * Returns (value < 0 ? 0 : value) efficiently (i.e. no compares or branches)
+ */
+static inline int SkClampPos(int value) {
+ return value & ~(value >> 31);
+}
+
+/** Given an integer and a positive (max) integer, return the value
+ * pinned against 0 and max, inclusive.
+ * @param value The value we want returned pinned between [0...max]
+ * @param max The positive max value
+ * @return 0 if value < 0, max if value > max, else value
+ */
+static inline int SkClampMax(int value, int max) {
+ // ensure that max is positive
+ SkASSERT(max >= 0);
+ if (value < 0) {
+ value = 0;
+ }
+ if (value > max) {
+ value = max;
+ }
+ return value;
+}
+
+/**
+ * Returns the smallest power-of-2 that is >= the specified value. If value
+ * is already a power of 2, then it is returned unchanged. It is undefined
+ * if value is <= 0.
+ */
+static inline int SkNextPow2(int value) {
+ SkASSERT(value > 0);
+ return 1 << (32 - SkCLZ(value - 1));
+}
+
+/**
+ * Returns the log2 of the specified value, were that value to be rounded up
+ * to the next power of 2. It is undefined to pass 0. Examples:
+ * SkNextLog2(1) -> 0
+ * SkNextLog2(2) -> 1
+ * SkNextLog2(3) -> 2
+ * SkNextLog2(4) -> 2
+ * SkNextLog2(5) -> 3
+ */
+static inline int SkNextLog2(uint32_t value) {
+ SkASSERT(value != 0);
+ return 32 - SkCLZ(value - 1);
+}
+
+/**
+ * Returns true if value is a power of 2. Does not explicitly check for
+ * value <= 0.
+ */
+static inline bool SkIsPow2(int value) {
+ return (value & (value - 1)) == 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+/**
+ * SkMulS16(a, b) multiplies a * b, but requires that a and b are both int16_t.
+ * With this requirement, we can generate faster instructions on some
+ * architectures.
+ */
+#ifdef SK_ARM_HAS_EDSP
+ static inline int32_t SkMulS16(S16CPU x, S16CPU y) {
+ SkASSERT((int16_t)x == x);
+ SkASSERT((int16_t)y == y);
+ int32_t product;
+ asm("smulbb %0, %1, %2 \n"
+ : "=r"(product)
+ : "r"(x), "r"(y)
+ );
+ return product;
+ }
+#else
+ #ifdef SK_DEBUG
+ static inline int32_t SkMulS16(S16CPU x, S16CPU y) {
+ SkASSERT((int16_t)x == x);
+ SkASSERT((int16_t)y == y);
+ return x * y;
+ }
+ #else
+ #define SkMulS16(x, y) ((x) * (y))
+ #endif
+#endif
+
+/**
+ * Return a*b/((1 << shift) - 1), rounding any fractional bits.
+ * Only valid if a and b are unsigned and <= 32767 and shift is > 0 and <= 8
+ */
+static inline unsigned SkMul16ShiftRound(U16CPU a, U16CPU b, int shift) {
+ SkASSERT(a <= 32767);
+ SkASSERT(b <= 32767);
+ SkASSERT(shift > 0 && shift <= 8);
+ unsigned prod = SkMulS16(a, b) + (1 << (shift - 1));
+ return (prod + (prod >> shift)) >> shift;
+}
+
+/**
+ * Return a*b/255, rounding any fractional bits.
+ * Only valid if a and b are unsigned and <= 32767.
+ */
+static inline U8CPU SkMulDiv255Round(U16CPU a, U16CPU b) {
+ SkASSERT(a <= 32767);
+ SkASSERT(b <= 32767);
+ unsigned prod = SkMulS16(a, b) + 128;
+ return (prod + (prod >> 8)) >> 8;
+}
+
+#endif
diff --git a/core/SkMatrix.h b/core/SkMatrix.h
new file mode 100644
index 0000000..f148e39
--- /dev/null
+++ b/core/SkMatrix.h
@@ -0,0 +1,674 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkMatrix_DEFINED
+#define SkMatrix_DEFINED
+
+#include "SkRect.h"
+
+class SkString;
+
+#ifdef SK_SCALAR_IS_FLOAT
+ typedef SkScalar SkPersp;
+ #define SkScalarToPersp(x) (x)
+ #define SkPerspToScalar(x) (x)
+#else
+ typedef SkFract SkPersp;
+ #define SkScalarToPersp(x) SkFixedToFract(x)
+ #define SkPerspToScalar(x) SkFractToFixed(x)
+#endif
+
+/** \class SkMatrix
+
+ The SkMatrix class holds a 3x3 matrix for transforming coordinates.
+ SkMatrix does not have a constructor, so it must be explicitly initialized
+ using either reset() - to construct an identity matrix, or one of the set
+ functions (e.g. setTranslate, setRotate, etc.).
+*/
+class SK_API SkMatrix {
+public:
+ /** Enum of bit fields for the mask return by getType().
+ Use this to identify the complexity of the matrix.
+ */
+ enum TypeMask {
+ kIdentity_Mask = 0,
+ kTranslate_Mask = 0x01, //!< set if the matrix has translation
+ kScale_Mask = 0x02, //!< set if the matrix has X or Y scale
+ kAffine_Mask = 0x04, //!< set if the matrix skews or rotates
+ kPerspective_Mask = 0x08 //!< set if the matrix is in perspective
+ };
+
+ /** Returns a bitfield describing the transformations the matrix may
+ perform. The bitfield is computed conservatively, so it may include
+ false positives. For example, when kPerspective_Mask is true, all
+ other bits may be set to true even in the case of a pure perspective
+ transform.
+ */
+ TypeMask getType() const {
+ if (fTypeMask & kUnknown_Mask) {
+ fTypeMask = this->computeTypeMask();
+ }
+ // only return the public masks
+ return (TypeMask)(fTypeMask & 0xF);
+ }
+
+ /** Returns true if the matrix is identity.
+ */
+ bool isIdentity() const {
+ return this->getType() == 0;
+ }
+
+ /** Returns true if will map a rectangle to another rectangle. This can be
+ true if the matrix is identity, scale-only, or rotates a multiple of
+ 90 degrees.
+ */
+ bool rectStaysRect() const {
+ if (fTypeMask & kUnknown_Mask) {
+ fTypeMask = this->computeTypeMask();
+ }
+ return (fTypeMask & kRectStaysRect_Mask) != 0;
+ }
+ // alias for rectStaysRect()
+ bool preservesAxisAlignment() const { return this->rectStaysRect(); }
+
+ /**
+ * Returns true if the matrix contains perspective elements.
+ */
+ bool hasPerspective() const {
+ return SkToBool(this->getPerspectiveTypeMaskOnly() &
+ kPerspective_Mask);
+ }
+
+ /** Returns true if the matrix contains only translation, rotation or uniform scale
+ Returns false if other transformation types are included or is degenerate
+ */
+ bool isSimilarity(SkScalar tol = SK_ScalarNearlyZero) const;
+
+ /** Returns true if the matrix contains only translation, rotation or scale
+ (non-uniform scale is allowed).
+ Returns false if other transformation types are included or is degenerate
+ */
+ bool preservesRightAngles(SkScalar tol = SK_ScalarNearlyZero) const;
+
+ enum {
+ kMScaleX,
+ kMSkewX,
+ kMTransX,
+ kMSkewY,
+ kMScaleY,
+ kMTransY,
+ kMPersp0,
+ kMPersp1,
+ kMPersp2
+ };
+
+ /** Affine arrays are in column major order
+ because that's how PDF and XPS like it.
+ */
+ enum {
+ kAScaleX,
+ kASkewY,
+ kASkewX,
+ kAScaleY,
+ kATransX,
+ kATransY
+ };
+
+ SkScalar operator[](int index) const {
+ SkASSERT((unsigned)index < 9);
+ return fMat[index];
+ }
+
+ SkScalar get(int index) const {
+ SkASSERT((unsigned)index < 9);
+ return fMat[index];
+ }
+
+ SkScalar getScaleX() const { return fMat[kMScaleX]; }
+ SkScalar getScaleY() const { return fMat[kMScaleY]; }
+ SkScalar getSkewY() const { return fMat[kMSkewY]; }
+ SkScalar getSkewX() const { return fMat[kMSkewX]; }
+ SkScalar getTranslateX() const { return fMat[kMTransX]; }
+ SkScalar getTranslateY() const { return fMat[kMTransY]; }
+ SkPersp getPerspX() const { return fMat[kMPersp0]; }
+ SkPersp getPerspY() const { return fMat[kMPersp1]; }
+
+ SkScalar& operator[](int index) {
+ SkASSERT((unsigned)index < 9);
+ this->setTypeMask(kUnknown_Mask);
+ return fMat[index];
+ }
+
+ void set(int index, SkScalar value) {
+ SkASSERT((unsigned)index < 9);
+ fMat[index] = value;
+ this->setTypeMask(kUnknown_Mask);
+ }
+
+ void setScaleX(SkScalar v) { this->set(kMScaleX, v); }
+ void setScaleY(SkScalar v) { this->set(kMScaleY, v); }
+ void setSkewY(SkScalar v) { this->set(kMSkewY, v); }
+ void setSkewX(SkScalar v) { this->set(kMSkewX, v); }
+ void setTranslateX(SkScalar v) { this->set(kMTransX, v); }
+ void setTranslateY(SkScalar v) { this->set(kMTransY, v); }
+ void setPerspX(SkPersp v) { this->set(kMPersp0, v); }
+ void setPerspY(SkPersp v) { this->set(kMPersp1, v); }
+
+ void setAll(SkScalar scaleX, SkScalar skewX, SkScalar transX,
+ SkScalar skewY, SkScalar scaleY, SkScalar transY,
+ SkPersp persp0, SkPersp persp1, SkPersp persp2) {
+ fMat[kMScaleX] = scaleX;
+ fMat[kMSkewX] = skewX;
+ fMat[kMTransX] = transX;
+ fMat[kMSkewY] = skewY;
+ fMat[kMScaleY] = scaleY;
+ fMat[kMTransY] = transY;
+ fMat[kMPersp0] = persp0;
+ fMat[kMPersp1] = persp1;
+ fMat[kMPersp2] = persp2;
+ this->setTypeMask(kUnknown_Mask);
+ }
+
+ /** Set the matrix to identity
+ */
+ void reset();
+ // alias for reset()
+ void setIdentity() { this->reset(); }
+
+ /** Set the matrix to translate by (dx, dy).
+ */
+ void setTranslate(SkScalar dx, SkScalar dy);
+ void setTranslate(const SkVector& v) { this->setTranslate(v.fX, v.fY); }
+
+ /** Set the matrix to scale by sx and sy, with a pivot point at (px, py).
+ The pivot point is the coordinate that should remain unchanged by the
+ specified transformation.
+ */
+ void setScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py);
+ /** Set the matrix to scale by sx and sy.
+ */
+ void setScale(SkScalar sx, SkScalar sy);
+ /** Set the matrix to scale by 1/divx and 1/divy. Returns false and doesn't
+ touch the matrix if either divx or divy is zero.
+ */
+ bool setIDiv(int divx, int divy);
+ /** Set the matrix to rotate by the specified number of degrees, with a
+ pivot point at (px, py). The pivot point is the coordinate that should
+ remain unchanged by the specified transformation.
+ */
+ void setRotate(SkScalar degrees, SkScalar px, SkScalar py);
+ /** Set the matrix to rotate about (0,0) by the specified number of degrees.
+ */
+ void setRotate(SkScalar degrees);
+ /** Set the matrix to rotate by the specified sine and cosine values, with
+ a pivot point at (px, py). The pivot point is the coordinate that
+ should remain unchanged by the specified transformation.
+ */
+ void setSinCos(SkScalar sinValue, SkScalar cosValue,
+ SkScalar px, SkScalar py);
+ /** Set the matrix to rotate by the specified sine and cosine values.
+ */
+ void setSinCos(SkScalar sinValue, SkScalar cosValue);
+ /** Set the matrix to skew by sx and sy, with a pivot point at (px, py).
+ The pivot point is the coordinate that should remain unchanged by the
+ specified transformation.
+ */
+ void setSkew(SkScalar kx, SkScalar ky, SkScalar px, SkScalar py);
+ /** Set the matrix to skew by sx and sy.
+ */
+ void setSkew(SkScalar kx, SkScalar ky);
+ /** Set the matrix to the concatenation of the two specified matrices,
+ returning true if the the result can be represented. Either of the
+ two matrices may also be the target matrix. *this = a * b;
+ */
+ bool setConcat(const SkMatrix& a, const SkMatrix& b);
+
+ /** Preconcats the matrix with the specified translation.
+ M' = M * T(dx, dy)
+ */
+ bool preTranslate(SkScalar dx, SkScalar dy);
+ /** Preconcats the matrix with the specified scale.
+ M' = M * S(sx, sy, px, py)
+ */
+ bool preScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py);
+ /** Preconcats the matrix with the specified scale.
+ M' = M * S(sx, sy)
+ */
+ bool preScale(SkScalar sx, SkScalar sy);
+ /** Preconcats the matrix with the specified rotation.
+ M' = M * R(degrees, px, py)
+ */
+ bool preRotate(SkScalar degrees, SkScalar px, SkScalar py);
+ /** Preconcats the matrix with the specified rotation.
+ M' = M * R(degrees)
+ */
+ bool preRotate(SkScalar degrees);
+ /** Preconcats the matrix with the specified skew.
+ M' = M * K(kx, ky, px, py)
+ */
+ bool preSkew(SkScalar kx, SkScalar ky, SkScalar px, SkScalar py);
+ /** Preconcats the matrix with the specified skew.
+ M' = M * K(kx, ky)
+ */
+ bool preSkew(SkScalar kx, SkScalar ky);
+ /** Preconcats the matrix with the specified matrix.
+ M' = M * other
+ */
+ bool preConcat(const SkMatrix& other);
+
+ /** Postconcats the matrix with the specified translation.
+ M' = T(dx, dy) * M
+ */
+ bool postTranslate(SkScalar dx, SkScalar dy);
+ /** Postconcats the matrix with the specified scale.
+ M' = S(sx, sy, px, py) * M
+ */
+ bool postScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py);
+ /** Postconcats the matrix with the specified scale.
+ M' = S(sx, sy) * M
+ */
+ bool postScale(SkScalar sx, SkScalar sy);
+ /** Postconcats the matrix by dividing it by the specified integers.
+ M' = S(1/divx, 1/divy, 0, 0) * M
+ */
+ bool postIDiv(int divx, int divy);
+ /** Postconcats the matrix with the specified rotation.
+ M' = R(degrees, px, py) * M
+ */
+ bool postRotate(SkScalar degrees, SkScalar px, SkScalar py);
+ /** Postconcats the matrix with the specified rotation.
+ M' = R(degrees) * M
+ */
+ bool postRotate(SkScalar degrees);
+ /** Postconcats the matrix with the specified skew.
+ M' = K(kx, ky, px, py) * M
+ */
+ bool postSkew(SkScalar kx, SkScalar ky, SkScalar px, SkScalar py);
+ /** Postconcats the matrix with the specified skew.
+ M' = K(kx, ky) * M
+ */
+ bool postSkew(SkScalar kx, SkScalar ky);
+ /** Postconcats the matrix with the specified matrix.
+ M' = other * M
+ */
+ bool postConcat(const SkMatrix& other);
+
+ enum ScaleToFit {
+ /**
+ * Scale in X and Y independently, so that src matches dst exactly.
+ * This may change the aspect ratio of the src.
+ */
+ kFill_ScaleToFit,
+ /**
+ * Compute a scale that will maintain the original src aspect ratio,
+ * but will also ensure that src fits entirely inside dst. At least one
+ * axis (X or Y) will fit exactly. kStart aligns the result to the
+ * left and top edges of dst.
+ */
+ kStart_ScaleToFit,
+ /**
+ * Compute a scale that will maintain the original src aspect ratio,
+ * but will also ensure that src fits entirely inside dst. At least one
+ * axis (X or Y) will fit exactly. The result is centered inside dst.
+ */
+ kCenter_ScaleToFit,
+ /**
+ * Compute a scale that will maintain the original src aspect ratio,
+ * but will also ensure that src fits entirely inside dst. At least one
+ * axis (X or Y) will fit exactly. kEnd aligns the result to the
+ * right and bottom edges of dst.
+ */
+ kEnd_ScaleToFit
+ };
+
+ /** Set the matrix to the scale and translate values that map the source
+ rectangle to the destination rectangle, returning true if the the result
+ can be represented.
+ @param src the source rectangle to map from.
+ @param dst the destination rectangle to map to.
+ @param stf the ScaleToFit option
+ @return true if the matrix can be represented by the rectangle mapping.
+ */
+ bool setRectToRect(const SkRect& src, const SkRect& dst, ScaleToFit stf);
+
+ /** Set the matrix such that the specified src points would map to the
+ specified dst points. count must be within [0..4].
+ @param src The array of src points
+ @param dst The array of dst points
+ @param count The number of points to use for the transformation
+ @return true if the matrix was set to the specified transformation
+ */
+ bool setPolyToPoly(const SkPoint src[], const SkPoint dst[], int count);
+
+ /** If this matrix can be inverted, return true and if inverse is not null,
+ set inverse to be the inverse of this matrix. If this matrix cannot be
+ inverted, ignore inverse and return false
+ */
+ bool SK_WARN_UNUSED_RESULT invert(SkMatrix* inverse) const {
+ // Allow the trivial case to be inlined.
+ if (this->isIdentity()) {
+ if (NULL != inverse) {
+ inverse->reset();
+ }
+ return true;
+ }
+ return this->invertNonIdentity(inverse);
+ }
+
+ /** Fills the passed array with affine identity values
+ in column major order.
+ @param affine The array to fill with affine identity values.
+ Must not be NULL.
+ */
+ static void SetAffineIdentity(SkScalar affine[6]);
+
+ /** Fills the passed array with the affine values in column major order.
+ If the matrix is a perspective transform, returns false
+ and does not change the passed array.
+ @param affine The array to fill with affine values. Ignored if NULL.
+ */
+ bool asAffine(SkScalar affine[6]) const;
+
+ /** Apply this matrix to the array of points specified by src, and write
+ the transformed points into the array of points specified by dst.
+ dst[] = M * src[]
+ @param dst Where the transformed coordinates are written. It must
+ contain at least count entries
+ @param src The original coordinates that are to be transformed. It
+ must contain at least count entries
+ @param count The number of points in src to read, and then transform
+ into dst.
+ */
+ void mapPoints(SkPoint dst[], const SkPoint src[], int count) const;
+
+ /** Apply this matrix to the array of points, overwriting it with the
+ transformed values.
+ dst[] = M * pts[]
+ @param pts The points to be transformed. It must contain at least
+ count entries
+ @param count The number of points in pts.
+ */
+ void mapPoints(SkPoint pts[], int count) const {
+ this->mapPoints(pts, pts, count);
+ }
+
+ /** Like mapPoints but with custom byte stride between the points. Stride
+ * should be a multiple of sizeof(SkScalar).
+ */
+ void mapPointsWithStride(SkPoint pts[], size_t stride, int count) const {
+ SkASSERT(stride >= sizeof(SkPoint));
+ SkASSERT(0 == stride % sizeof(SkScalar));
+ for (int i = 0; i < count; ++i) {
+ this->mapPoints(pts, pts, 1);
+ pts = (SkPoint*)((intptr_t)pts + stride);
+ }
+ }
+
+ /** Like mapPoints but with custom byte stride between the points.
+ */
+ void mapPointsWithStride(SkPoint dst[], SkPoint src[],
+ size_t stride, int count) const {
+ SkASSERT(stride >= sizeof(SkPoint));
+ SkASSERT(0 == stride % sizeof(SkScalar));
+ for (int i = 0; i < count; ++i) {
+ this->mapPoints(dst, src, 1);
+ src = (SkPoint*)((intptr_t)src + stride);
+ dst = (SkPoint*)((intptr_t)dst + stride);
+ }
+ }
+
+ void mapXY(SkScalar x, SkScalar y, SkPoint* result) const {
+ SkASSERT(result);
+ this->getMapXYProc()(*this, x, y, result);
+ }
+
+ /** Apply this matrix to the array of vectors specified by src, and write
+ the transformed vectors into the array of vectors specified by dst.
+ This is similar to mapPoints, but ignores any translation in the matrix.
+ @param dst Where the transformed coordinates are written. It must
+ contain at least count entries
+ @param src The original coordinates that are to be transformed. It
+ must contain at least count entries
+ @param count The number of vectors in src to read, and then transform
+ into dst.
+ */
+ void mapVectors(SkVector dst[], const SkVector src[], int count) const;
+
+ /** Apply this matrix to the array of vectors specified by src, and write
+ the transformed vectors into the array of vectors specified by dst.
+ This is similar to mapPoints, but ignores any translation in the matrix.
+ @param vecs The vectors to be transformed. It must contain at least
+ count entries
+ @param count The number of vectors in vecs.
+ */
+ void mapVectors(SkVector vecs[], int count) const {
+ this->mapVectors(vecs, vecs, count);
+ }
+
+ /** Apply this matrix to the src rectangle, and write the transformed
+ rectangle into dst. This is accomplished by transforming the 4 corners
+ of src, and then setting dst to the bounds of those points.
+ @param dst Where the transformed rectangle is written.
+ @param src The original rectangle to be transformed.
+ @return the result of calling rectStaysRect()
+ */
+ bool mapRect(SkRect* dst, const SkRect& src) const;
+
+ /** Apply this matrix to the rectangle, and write the transformed rectangle
+ back into it. This is accomplished by transforming the 4 corners of
+ rect, and then setting it to the bounds of those points
+ @param rect The rectangle to transform.
+ @return the result of calling rectStaysRect()
+ */
+ bool mapRect(SkRect* rect) const {
+ return this->mapRect(rect, *rect);
+ }
+
+ /** Return the mean radius of a circle after it has been mapped by
+ this matrix. NOTE: in perspective this value assumes the circle
+ has its center at the origin.
+ */
+ SkScalar mapRadius(SkScalar radius) const;
+
+ typedef void (*MapXYProc)(const SkMatrix& mat, SkScalar x, SkScalar y,
+ SkPoint* result);
+
+ static MapXYProc GetMapXYProc(TypeMask mask) {
+ SkASSERT((mask & ~kAllMasks) == 0);
+ return gMapXYProcs[mask & kAllMasks];
+ }
+
+ MapXYProc getMapXYProc() const {
+ return GetMapXYProc(this->getType());
+ }
+
+ typedef void (*MapPtsProc)(const SkMatrix& mat, SkPoint dst[],
+ const SkPoint src[], int count);
+
+ static MapPtsProc GetMapPtsProc(TypeMask mask) {
+ SkASSERT((mask & ~kAllMasks) == 0);
+ return gMapPtsProcs[mask & kAllMasks];
+ }
+
+ MapPtsProc getMapPtsProc() const {
+ return GetMapPtsProc(this->getType());
+ }
+
+ /** If the matrix can be stepped in X (not complex perspective)
+ then return true and if step[XY] is not null, return the step[XY] value.
+ If it cannot, return false and ignore step.
+ */
+ bool fixedStepInX(SkScalar y, SkFixed* stepX, SkFixed* stepY) const;
+
+ /** Efficient comparison of two matrices. It distinguishes between zero and
+ * negative zero. It will return false when the sign of zero values is the
+ * only difference between the two matrices. It considers NaN values to be
+ * equal to themselves. So a matrix full of NaNs is "cheap equal" to
+ * another matrix full of NaNs iff the NaN values are bitwise identical
+ * while according to strict the strict == test a matrix with a NaN value
+ * is equal to nothing, including itself.
+ */
+ bool cheapEqualTo(const SkMatrix& m) const {
+ return 0 == memcmp(fMat, m.fMat, sizeof(fMat));
+ }
+
+#ifdef SK_SCALAR_IS_FIXED
+ friend bool operator==(const SkMatrix& a, const SkMatrix& b) {
+ return a.cheapEqualTo(b);
+ }
+#else
+ friend bool operator==(const SkMatrix& a, const SkMatrix& b);
+#endif
+ friend bool operator!=(const SkMatrix& a, const SkMatrix& b) {
+ return !(a == b);
+ }
+
+ enum {
+ // writeTo/readFromMemory will never return a value larger than this
+ kMaxFlattenSize = 9 * sizeof(SkScalar) + sizeof(uint32_t)
+ };
+ // return the number of bytes written, whether or not buffer is null
+ uint32_t writeToMemory(void* buffer) const;
+ // return the number of bytes read
+ uint32_t readFromMemory(const void* buffer);
+
+ SkDEVCODE(void dump() const;)
+ SkDEVCODE(void toString(SkString*) const;)
+
+ /**
+ * Calculates the maximum stretching factor of the matrix. If the matrix has
+ * perspective -1 is returned.
+ *
+ * @return maximum strecthing factor
+ */
+ SkScalar getMaxStretch() const;
+
+ /**
+ * Return a reference to a const identity matrix
+ */
+ static const SkMatrix& I();
+
+ /**
+ * Return a reference to a const matrix that is "invalid", one that could
+ * never be used.
+ */
+ static const SkMatrix& InvalidMatrix();
+
+ /**
+ * Testing routine; the matrix's type cache should never need to be
+ * manually invalidated during normal use.
+ */
+ void dirtyMatrixTypeCache() {
+ this->setTypeMask(kUnknown_Mask);
+ }
+
+private:
+ enum {
+ /** Set if the matrix will map a rectangle to another rectangle. This
+ can be true if the matrix is scale-only, or rotates a multiple of
+ 90 degrees.
+
+ This bit will be set on identity matrices
+ */
+ kRectStaysRect_Mask = 0x10,
+
+ /** Set if the perspective bit is valid even though the rest of
+ the matrix is Unknown.
+ */
+ kOnlyPerspectiveValid_Mask = 0x40,
+
+ kUnknown_Mask = 0x80,
+
+ kORableMasks = kTranslate_Mask |
+ kScale_Mask |
+ kAffine_Mask |
+ kPerspective_Mask,
+
+ kAllMasks = kTranslate_Mask |
+ kScale_Mask |
+ kAffine_Mask |
+ kPerspective_Mask |
+ kRectStaysRect_Mask
+ };
+
+ SkScalar fMat[9];
+ mutable uint32_t fTypeMask;
+
+ uint8_t computeTypeMask() const;
+ uint8_t computePerspectiveTypeMask() const;
+
+ void setTypeMask(int mask) {
+ // allow kUnknown or a valid mask
+ SkASSERT(kUnknown_Mask == mask || (mask & kAllMasks) == mask ||
+ ((kUnknown_Mask | kOnlyPerspectiveValid_Mask) & mask)
+ == (kUnknown_Mask | kOnlyPerspectiveValid_Mask));
+ fTypeMask = SkToU8(mask);
+ }
+
+ void orTypeMask(int mask) {
+ SkASSERT((mask & kORableMasks) == mask);
+ fTypeMask = SkToU8(fTypeMask | mask);
+ }
+
+ void clearTypeMask(int mask) {
+ // only allow a valid mask
+ SkASSERT((mask & kAllMasks) == mask);
+ fTypeMask &= ~mask;
+ }
+
+ TypeMask getPerspectiveTypeMaskOnly() const {
+ if ((fTypeMask & kUnknown_Mask) &&
+ !(fTypeMask & kOnlyPerspectiveValid_Mask)) {
+ fTypeMask = this->computePerspectiveTypeMask();
+ }
+ return (TypeMask)(fTypeMask & 0xF);
+ }
+
+ /** Returns true if we already know that the matrix is identity;
+ false otherwise.
+ */
+ bool isTriviallyIdentity() const {
+ if (fTypeMask & kUnknown_Mask) {
+ return false;
+ }
+ return ((fTypeMask & 0xF) == 0);
+ }
+
+ bool SK_WARN_UNUSED_RESULT invertNonIdentity(SkMatrix* inverse) const;
+
+ static bool Poly2Proc(const SkPoint[], SkMatrix*, const SkPoint& scale);
+ static bool Poly3Proc(const SkPoint[], SkMatrix*, const SkPoint& scale);
+ static bool Poly4Proc(const SkPoint[], SkMatrix*, const SkPoint& scale);
+
+ static void Identity_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);
+ static void Trans_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);
+ static void Scale_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);
+ static void ScaleTrans_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);
+ static void Rot_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);
+ static void RotTrans_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);
+ static void Persp_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);
+
+ static const MapXYProc gMapXYProcs[];
+
+ static void Identity_pts(const SkMatrix&, SkPoint[], const SkPoint[], int);
+ static void Trans_pts(const SkMatrix&, SkPoint dst[], const SkPoint[], int);
+ static void Scale_pts(const SkMatrix&, SkPoint dst[], const SkPoint[], int);
+ static void ScaleTrans_pts(const SkMatrix&, SkPoint dst[], const SkPoint[],
+ int count);
+ static void Rot_pts(const SkMatrix&, SkPoint dst[], const SkPoint[], int);
+ static void RotTrans_pts(const SkMatrix&, SkPoint dst[], const SkPoint[],
+ int count);
+ static void Persp_pts(const SkMatrix&, SkPoint dst[], const SkPoint[], int);
+
+ static const MapPtsProc gMapPtsProcs[];
+
+ friend class SkPerspIter;
+};
+
+#endif
diff --git a/core/SkMetaData.h b/core/SkMetaData.h
new file mode 100644
index 0000000..5db437c
--- /dev/null
+++ b/core/SkMetaData.h
@@ -0,0 +1,175 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkMetaData_DEFINED
+#define SkMetaData_DEFINED
+
+#include "SkScalar.h"
+
+class SkRefCnt;
+
+class SK_API SkMetaData {
+public:
+ /**
+ * Used to manage the life-cycle of a ptr in the metadata. This is option
+ * in setPtr, and is only invoked when either copying one metadata to
+ * another, or when the metadata is destroyed.
+ *
+ * setPtr(name, ptr, proc) {
+ * fPtr = proc(ptr, true);
+ * }
+ *
+ * copy: A = B {
+ * A.fPtr = B.fProc(B.fPtr, true);
+ * }
+ *
+ * ~SkMetaData {
+ * fProc(fPtr, false);
+ * }
+ */
+ typedef void* (*PtrProc)(void* ptr, bool doRef);
+
+ /**
+ * Implements PtrProc for SkRefCnt pointers
+ */
+ static void* RefCntProc(void* ptr, bool doRef);
+
+ SkMetaData();
+ SkMetaData(const SkMetaData& src);
+ ~SkMetaData();
+
+ SkMetaData& operator=(const SkMetaData& src);
+
+ void reset();
+
+ bool findS32(const char name[], int32_t* value = NULL) const;
+ bool findScalar(const char name[], SkScalar* value = NULL) const;
+ const SkScalar* findScalars(const char name[], int* count,
+ SkScalar values[] = NULL) const;
+ const char* findString(const char name[]) const;
+ bool findPtr(const char name[], void** value = NULL, PtrProc* = NULL) const;
+ bool findBool(const char name[], bool* value = NULL) const;
+ const void* findData(const char name[], size_t* byteCount = NULL) const;
+
+ bool hasS32(const char name[], int32_t value) const {
+ int32_t v;
+ return this->findS32(name, &v) && v == value;
+ }
+ bool hasScalar(const char name[], SkScalar value) const {
+ SkScalar v;
+ return this->findScalar(name, &v) && v == value;
+ }
+ bool hasString(const char name[], const char value[]) const {
+ const char* v = this->findString(name);
+ return (v == NULL && value == NULL) ||
+ (v != NULL && value != NULL && !strcmp(v, value));
+ }
+ bool hasPtr(const char name[], void* value) const {
+ void* v;
+ return this->findPtr(name, &v) && v == value;
+ }
+ bool hasBool(const char name[], bool value) const {
+ bool v;
+ return this->findBool(name, &v) && v == value;
+ }
+ bool hasData(const char name[], const void* data, size_t byteCount) const {
+ size_t len;
+ const void* ptr = this->findData(name, &len);
+ return NULL != ptr && len == byteCount && !memcmp(ptr, data, len);
+ }
+
+ void setS32(const char name[], int32_t value);
+ void setScalar(const char name[], SkScalar value);
+ SkScalar* setScalars(const char name[], int count, const SkScalar values[] = NULL);
+ void setString(const char name[], const char value[]);
+ void setPtr(const char name[], void* value, PtrProc proc = NULL);
+ void setBool(const char name[], bool value);
+ // the data is copied from the input pointer.
+ void setData(const char name[], const void* data, size_t byteCount);
+
+ bool removeS32(const char name[]);
+ bool removeScalar(const char name[]);
+ bool removeString(const char name[]);
+ bool removePtr(const char name[]);
+ bool removeBool(const char name[]);
+ bool removeData(const char name[]);
+
+ // helpers for SkRefCnt
+ bool findRefCnt(const char name[], SkRefCnt** ptr = NULL) {
+ return this->findPtr(name, reinterpret_cast<void**>(ptr));
+ }
+ bool hasRefCnt(const char name[], SkRefCnt* ptr) {
+ return this->hasPtr(name, ptr);
+ }
+ void setRefCnt(const char name[], SkRefCnt* ptr) {
+ this->setPtr(name, ptr, RefCntProc);
+ }
+ bool removeRefCnt(const char name[]) {
+ return this->removePtr(name);
+ }
+
+ enum Type {
+ kS32_Type,
+ kScalar_Type,
+ kString_Type,
+ kPtr_Type,
+ kBool_Type,
+ kData_Type,
+
+ kTypeCount
+ };
+
+ struct Rec;
+ class Iter;
+ friend class Iter;
+
+ class Iter {
+ public:
+ Iter() : fRec(NULL) {}
+ Iter(const SkMetaData&);
+
+ /** Reset the iterator, so that calling next() will return the first
+ data element. This is done implicitly in the constructor.
+ */
+ void reset(const SkMetaData&);
+
+ /** Each time next is called, it returns the name of the next data element,
+ or null when there are no more elements. If non-null is returned, then the
+ element's type is returned (if not null), and the number of data values
+ is returned in count (if not null).
+ */
+ const char* next(Type*, int* count);
+
+ private:
+ Rec* fRec;
+ };
+
+public:
+ struct Rec {
+ Rec* fNext;
+ uint16_t fDataCount; // number of elements
+ uint8_t fDataLen; // sizeof a single element
+ uint8_t fType;
+
+ const void* data() const { return (this + 1); }
+ void* data() { return (this + 1); }
+ const char* name() const { return (const char*)this->data() + fDataLen * fDataCount; }
+ char* name() { return (char*)this->data() + fDataLen * fDataCount; }
+
+ static Rec* Alloc(size_t);
+ static void Free(Rec*);
+ };
+ Rec* fRec;
+
+ const Rec* find(const char name[], Type) const;
+ void* set(const char name[], const void* data, size_t len, Type, int count);
+ bool remove(const char name[], Type);
+};
+
+#endif
diff --git a/core/SkOSFile.h b/core/SkOSFile.h
new file mode 100644
index 0000000..b75fe6c
--- /dev/null
+++ b/core/SkOSFile.h
@@ -0,0 +1,159 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+// TODO: add unittests for all these operations
+
+#ifndef SkOSFile_DEFINED
+#define SkOSFile_DEFINED
+
+#include "SkString.h"
+
+#if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_UNIX) || defined(SK_BUILD_FOR_ANDROID) || defined(SK_BUILD_FOR_IOS)
+ #include <dirent.h>
+#endif
+
+#include <stddef.h> // ptrdiff_t
+
+struct SkFILE;
+
+enum SkFILE_Flags {
+ kRead_SkFILE_Flag = 0x01,
+ kWrite_SkFILE_Flag = 0x02
+};
+
+#ifdef _WIN32
+const static char SkPATH_SEPARATOR = '\\';
+#else
+const static char SkPATH_SEPARATOR = '/';
+#endif
+
+SkFILE* sk_fopen(const char path[], SkFILE_Flags);
+void sk_fclose(SkFILE*);
+
+size_t sk_fgetsize(SkFILE*);
+/** Return true if the file could seek back to the beginning
+*/
+bool sk_frewind(SkFILE*);
+
+size_t sk_fread(void* buffer, size_t byteCount, SkFILE*);
+size_t sk_fwrite(const void* buffer, size_t byteCount, SkFILE*);
+
+char* sk_fgets(char* str, int size, SkFILE* f);
+
+void sk_fflush(SkFILE*);
+
+bool sk_fseek(SkFILE*, size_t);
+bool sk_fmove(SkFILE*, long);
+size_t sk_ftell(SkFILE*);
+
+/** Maps a file into memory. Returns the address and length on success, NULL otherwise.
+ * The mapping is read only.
+ * When finished with the mapping, free the returned pointer with sk_fmunmap.
+ */
+void* sk_fmmap(SkFILE* f, size_t* length);
+
+/** Maps a file descriptor into memory. Returns the address and length on success, NULL otherwise.
+ * The mapping is read only.
+ * When finished with the mapping, free the returned pointer with sk_fmunmap.
+ */
+void* sk_fdmmap(int fd, size_t* length);
+
+/** Unmaps a file previously mapped by sk_fmmap or sk_fdmmap.
+ * The length parameter must be the same as returned from sk_fmmap.
+ */
+void sk_fmunmap(const void* addr, size_t length);
+
+/** Returns true if the two point at the exact same filesystem object. */
+bool sk_fidentical(SkFILE* a, SkFILE* b);
+
+/** Returns the underlying file descriptor for the given file.
+ * The return value will be < 0 on failure.
+ */
+int sk_fileno(SkFILE* f);
+
+// Returns true if something (file, directory, ???) exists at this path.
+bool sk_exists(const char *path);
+
+// Returns true if a directory exists at this path.
+bool sk_isdir(const char *path);
+
+// Have we reached the end of the file?
+int sk_feof(SkFILE *);
+
+
+// Create a new directory at this path; returns true if successful.
+// If the directory already existed, this will return true.
+// Description of the error, if any, will be written to stderr.
+bool sk_mkdir(const char* path);
+
+class SkOSFile {
+public:
+ class Iter {
+ public:
+ Iter();
+ Iter(const char path[], const char suffix[] = NULL);
+ ~Iter();
+
+ void reset(const char path[], const char suffix[] = NULL);
+ /** If getDir is true, only returns directories.
+ Results are undefined if true and false calls are
+ interleaved on a single iterator.
+ */
+ bool next(SkString* name, bool getDir = false);
+
+ private:
+#ifdef SK_BUILD_FOR_WIN
+ HANDLE fHandle;
+ uint16_t* fPath16;
+#elif defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_UNIX) || defined(SK_BUILD_FOR_ANDROID) || defined(SK_BUILD_FOR_IOS)
+ DIR* fDIR;
+ SkString fPath, fSuffix;
+#endif
+ };
+};
+
+class SkUTF16_Str {
+public:
+ SkUTF16_Str(const char src[]);
+ ~SkUTF16_Str()
+ {
+ sk_free(fStr);
+ }
+ const uint16_t* get() const { return fStr; }
+
+private:
+ uint16_t* fStr;
+};
+
+/**
+ * Functions for modifying SkStrings which represent paths on the filesystem.
+ */
+class SkOSPath {
+public:
+ /**
+ * Assembles rootPath and relativePath into a single path, like this:
+ * rootPath/relativePath.
+ * It is okay to call with a NULL rootPath and/or relativePath. A path
+ * separator will still be inserted.
+ *
+ * Uses SkPATH_SEPARATOR, to work on all platforms.
+ */
+ static SkString SkPathJoin(const char *rootPath, const char *relativePath);
+
+ /**
+ * Return the name of the file, ignoring the directory structure.
+ * Behaves like python's os.path.basename. If the fullPath is
+ * /dir/subdir/, an empty string is returned.
+ * @param fullPath Full path to the file.
+ * @return SkString The basename of the file - anything beyond the
+ * final slash, or the full name if there is no slash.
+ */
+ static SkString SkBasename(const char* fullPath);
+};
+#endif
diff --git a/core/SkPackBits.h b/core/SkPackBits.h
new file mode 100644
index 0000000..f0614a0
--- /dev/null
+++ b/core/SkPackBits.h
@@ -0,0 +1,79 @@
+
+/*
+ * Copyright 2008 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkPackBits_DEFINED
+#define SkPackBits_DEFINED
+
+#include "SkTypes.h"
+
+class SkPackBits {
+public:
+ /** Given the number of 16bit values that will be passed to Pack16,
+ returns the worst-case size needed for the dst[] buffer.
+ */
+ static size_t ComputeMaxSize16(int count);
+
+ /** Given the number of 8bit values that will be passed to Pack8,
+ returns the worst-case size needed for the dst[] buffer.
+ */
+ static size_t ComputeMaxSize8(int count);
+
+ /** Write the src array into a packed format. The packing process may end
+ up writing more bytes than it read, so dst[] must be large enough.
+ @param src Input array of 16bit values
+ @param count Number of entries in src[]
+ @param dst Buffer (allocated by caller) to write the packed data
+ into
+ @return the number of bytes written to dst[]
+ */
+ static size_t Pack16(const uint16_t src[], int count, uint8_t dst[]);
+
+ /** Write the src array into a packed format. The packing process may end
+ up writing more bytes than it read, so dst[] must be large enough.
+ @param src Input array of 8bit values
+ @param count Number of entries in src[]
+ @param dst Buffer (allocated by caller) to write the packed data
+ into
+ @return the number of bytes written to dst[]
+ */
+ static size_t Pack8(const uint8_t src[], int count, uint8_t dst[]);
+
+ /** Unpack the data in src[], and expand it into dst[]. The src[] data was
+ written by a previous call to Pack16.
+ @param src Input data to unpack, previously created by Pack16.
+ @param srcSize Number of bytes of src to unpack
+ @param dst Buffer (allocated by caller) to expand the src[] into.
+ @return the number of dst elements (not bytes) written into dst.
+ */
+ static int Unpack16(const uint8_t src[], size_t srcSize, uint16_t dst[]);
+
+ /** Unpack the data in src[], and expand it into dst[]. The src[] data was
+ written by a previous call to Pack8.
+ @param src Input data to unpack, previously created by Pack8.
+ @param srcSize Number of bytes of src to unpack
+ @param dst Buffer (allocated by caller) to expand the src[] into.
+ @return the number of bytes written into dst.
+ */
+ static int Unpack8(const uint8_t src[], size_t srcSize, uint8_t dst[]);
+
+ /** Unpack the data from src[], skip the first dstSkip bytes, then write
+ dstWrite bytes into dst[]. The src[] data was written by a previous
+ call to Pack8. Return the number of bytes actually writtten into dst[]
+ @param src Input data to unpack, previously created by Pack8.
+ @param dst Buffer (allocated by caller) to expand the src[] into.
+ @param dstSkip Number of bytes of unpacked src to skip before writing
+ into dst
+ @param dstWrite Number of bytes of unpacked src to write into dst (after
+ skipping dstSkip bytes)
+ */
+ static void Unpack8(uint8_t dst[], size_t dstSkip, size_t dstWrite,
+ const uint8_t src[]);
+};
+
+#endif
diff --git a/core/SkPaint.h b/core/SkPaint.h
new file mode 100644
index 0000000..fa0c61e
--- /dev/null
+++ b/core/SkPaint.h
@@ -0,0 +1,1105 @@
+
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkPaint_DEFINED
+#define SkPaint_DEFINED
+
+#include "SkColor.h"
+#include "SkDrawLooper.h"
+#include "SkMatrix.h"
+#include "SkXfermode.h"
+#ifdef SK_BUILD_FOR_ANDROID
+#include "SkPaintOptionsAndroid.h"
+#endif
+
+class SkAnnotation;
+class SkAutoGlyphCache;
+class SkColorFilter;
+class SkDescriptor;
+struct SkDeviceProperties;
+class SkFlattenableReadBuffer;
+class SkFlattenableWriteBuffer;
+struct SkGlyph;
+struct SkRect;
+class SkGlyphCache;
+class SkImageFilter;
+class SkMaskFilter;
+class SkPath;
+class SkPathEffect;
+struct SkPoint;
+class SkRasterizer;
+class SkShader;
+class SkTypeface;
+
+typedef const SkGlyph& (*SkDrawCacheProc)(SkGlyphCache*, const char**,
+ SkFixed x, SkFixed y);
+
+typedef const SkGlyph& (*SkMeasureCacheProc)(SkGlyphCache*, const char**);
+
+#define kBicubicFilterBitmap_Flag kHighQualityFilterBitmap_Flag
+
+/** \class SkPaint
+
+ The SkPaint class holds the style and color information about how to draw
+ geometries, text and bitmaps.
+*/
+
+class SK_API SkPaint {
+ enum {
+ // DEPRECATED -- use setFilterLevel instead
+ kFilterBitmap_Flag = 0x02, // temporary flag
+ // DEPRECATED -- use setFilterLevel instead
+ kHighQualityFilterBitmap_Flag = 0x4000, // temporary flag
+ // DEPRECATED -- use setFilterLevel instead
+ kHighQualityDownsampleBitmap_Flag = 0x8000, // temporary flag
+ };
+public:
+ SkPaint();
+ SkPaint(const SkPaint& paint);
+ ~SkPaint();
+
+ SkPaint& operator=(const SkPaint&);
+
+ SK_API friend bool operator==(const SkPaint& a, const SkPaint& b);
+ friend bool operator!=(const SkPaint& a, const SkPaint& b) {
+ return !(a == b);
+ }
+
+ void flatten(SkFlattenableWriteBuffer&) const;
+ void unflatten(SkFlattenableReadBuffer&);
+
+ /** Restores the paint to its initial settings.
+ */
+ void reset();
+
+ /** Specifies the level of hinting to be performed. These names are taken
+ from the Gnome/Cairo names for the same. They are translated into
+ Freetype concepts the same as in cairo-ft-font.c:
+ kNo_Hinting -> FT_LOAD_NO_HINTING
+ kSlight_Hinting -> FT_LOAD_TARGET_LIGHT
+ kNormal_Hinting -> <default, no option>
+ kFull_Hinting -> <same as kNormalHinting, unless we are rendering
+ subpixel glyphs, in which case TARGET_LCD or
+ TARGET_LCD_V is used>
+ */
+ enum Hinting {
+ kNo_Hinting = 0,
+ kSlight_Hinting = 1,
+ kNormal_Hinting = 2, //!< this is the default
+ kFull_Hinting = 3
+ };
+
+ Hinting getHinting() const {
+ return static_cast<Hinting>(fHinting);
+ }
+
+ void setHinting(Hinting hintingLevel);
+
+ /** Specifies the bit values that are stored in the paint's flags.
+ */
+ enum Flags {
+ kAntiAlias_Flag = 0x01, //!< mask to enable antialiasing
+ kDither_Flag = 0x04, //!< mask to enable dithering
+ kUnderlineText_Flag = 0x08, //!< mask to enable underline text
+ kStrikeThruText_Flag = 0x10, //!< mask to enable strike-thru text
+ kFakeBoldText_Flag = 0x20, //!< mask to enable fake-bold text
+ kLinearText_Flag = 0x40, //!< mask to enable linear-text
+ kSubpixelText_Flag = 0x80, //!< mask to enable subpixel text positioning
+ kDevKernText_Flag = 0x100, //!< mask to enable device kerning text
+ kLCDRenderText_Flag = 0x200, //!< mask to enable subpixel glyph renderering
+ kEmbeddedBitmapText_Flag = 0x400, //!< mask to enable embedded bitmap strikes
+ kAutoHinting_Flag = 0x800, //!< mask to force Freetype's autohinter
+ kVerticalText_Flag = 0x1000,
+ kGenA8FromLCD_Flag = 0x2000, // hack for GDI -- do not use if you can help it
+ // when adding extra flags, note that the fFlags member is specified
+ // with a bit-width and you'll have to expand it.
+
+ kAllFlags = 0xFFFF
+ };
+
+ /** Return the paint's flags. Use the Flag enum to test flag values.
+ @return the paint's flags (see enums ending in _Flag for bit masks)
+ */
+ uint32_t getFlags() const { return fFlags; }
+
+ /** Set the paint's flags. Use the Flag enum to specific flag values.
+ @param flags The new flag bits for the paint (see Flags enum)
+ */
+ void setFlags(uint32_t flags);
+
+ /** Helper for getFlags(), returning true if kAntiAlias_Flag bit is set
+ @return true if the antialias bit is set in the paint's flags.
+ */
+ bool isAntiAlias() const {
+ return SkToBool(this->getFlags() & kAntiAlias_Flag);
+ }
+
+ /** Helper for setFlags(), setting or clearing the kAntiAlias_Flag bit
+ @param aa true to enable antialiasing, false to disable it
+ */
+ void setAntiAlias(bool aa);
+
+ /** Helper for getFlags(), returning true if kDither_Flag bit is set
+ @return true if the dithering bit is set in the paint's flags.
+ */
+ bool isDither() const {
+ return SkToBool(this->getFlags() & kDither_Flag);
+ }
+
+ /** Helper for setFlags(), setting or clearing the kDither_Flag bit
+ @param dither true to enable dithering, false to disable it
+ */
+ void setDither(bool dither);
+
+ /** Helper for getFlags(), returning true if kLinearText_Flag bit is set
+ @return true if the lineartext bit is set in the paint's flags
+ */
+ bool isLinearText() const {
+ return SkToBool(this->getFlags() & kLinearText_Flag);
+ }
+
+ /** Helper for setFlags(), setting or clearing the kLinearText_Flag bit
+ @param linearText true to set the linearText bit in the paint's flags,
+ false to clear it.
+ */
+ void setLinearText(bool linearText);
+
+ /** Helper for getFlags(), returning true if kSubpixelText_Flag bit is set
+ @return true if the lineartext bit is set in the paint's flags
+ */
+ bool isSubpixelText() const {
+ return SkToBool(this->getFlags() & kSubpixelText_Flag);
+ }
+
+ /**
+ * Helper for setFlags(), setting or clearing the kSubpixelText_Flag.
+ * @param subpixelText true to set the subpixelText bit in the paint's
+ * flags, false to clear it.
+ */
+ void setSubpixelText(bool subpixelText);
+
+ bool isLCDRenderText() const {
+ return SkToBool(this->getFlags() & kLCDRenderText_Flag);
+ }
+
+ /**
+ * Helper for setFlags(), setting or clearing the kLCDRenderText_Flag.
+ * Note: antialiasing must also be on for lcd rendering
+ * @param lcdText true to set the LCDRenderText bit in the paint's flags,
+ * false to clear it.
+ */
+ void setLCDRenderText(bool lcdText);
+
+ bool isEmbeddedBitmapText() const {
+ return SkToBool(this->getFlags() & kEmbeddedBitmapText_Flag);
+ }
+
+ /** Helper for setFlags(), setting or clearing the kEmbeddedBitmapText_Flag bit
+ @param useEmbeddedBitmapText true to set the kEmbeddedBitmapText bit in the paint's flags,
+ false to clear it.
+ */
+ void setEmbeddedBitmapText(bool useEmbeddedBitmapText);
+
+ bool isAutohinted() const {
+ return SkToBool(this->getFlags() & kAutoHinting_Flag);
+ }
+
+ /** Helper for setFlags(), setting or clearing the kAutoHinting_Flag bit
+ @param useAutohinter true to set the kEmbeddedBitmapText bit in the
+ paint's flags,
+ false to clear it.
+ */
+ void setAutohinted(bool useAutohinter);
+
+ bool isVerticalText() const {
+ return SkToBool(this->getFlags() & kVerticalText_Flag);
+ }
+
+ /**
+ * Helper for setting or clearing the kVerticalText_Flag bit in
+ * setFlags(...).
+ *
+ * If this bit is set, then advances are treated as Y values rather than
+ * X values, and drawText will places its glyphs vertically rather than
+ * horizontally.
+ */
+ void setVerticalText(bool);
+
+ /** Helper for getFlags(), returning true if kUnderlineText_Flag bit is set
+ @return true if the underlineText bit is set in the paint's flags.
+ */
+ bool isUnderlineText() const {
+ return SkToBool(this->getFlags() & kUnderlineText_Flag);
+ }
+
+ /** Helper for setFlags(), setting or clearing the kUnderlineText_Flag bit
+ @param underlineText true to set the underlineText bit in the paint's
+ flags, false to clear it.
+ */
+ void setUnderlineText(bool underlineText);
+
+ /** Helper for getFlags(), returns true if kStrikeThruText_Flag bit is set
+ @return true if the strikeThruText bit is set in the paint's flags.
+ */
+ bool isStrikeThruText() const {
+ return SkToBool(this->getFlags() & kStrikeThruText_Flag);
+ }
+
+ /** Helper for setFlags(), setting or clearing the kStrikeThruText_Flag bit
+ @param strikeThruText true to set the strikeThruText bit in the
+ paint's flags, false to clear it.
+ */
+ void setStrikeThruText(bool strikeThruText);
+
+ /** Helper for getFlags(), returns true if kFakeBoldText_Flag bit is set
+ @return true if the kFakeBoldText_Flag bit is set in the paint's flags.
+ */
+ bool isFakeBoldText() const {
+ return SkToBool(this->getFlags() & kFakeBoldText_Flag);
+ }
+
+ /** Helper for setFlags(), setting or clearing the kFakeBoldText_Flag bit
+ @param fakeBoldText true to set the kFakeBoldText_Flag bit in the paint's
+ flags, false to clear it.
+ */
+ void setFakeBoldText(bool fakeBoldText);
+
+ /** Helper for getFlags(), returns true if kDevKernText_Flag bit is set
+ @return true if the kernText bit is set in the paint's flags.
+ */
+ bool isDevKernText() const {
+ return SkToBool(this->getFlags() & kDevKernText_Flag);
+ }
+
+ /** Helper for setFlags(), setting or clearing the kKernText_Flag bit
+ @param kernText true to set the kKernText_Flag bit in the paint's
+ flags, false to clear it.
+ */
+ void setDevKernText(bool devKernText);
+
+ enum FilterLevel {
+ kNone_FilterLevel,
+ kLow_FilterLevel,
+ kMedium_FilterLevel,
+ kHigh_FilterLevel
+ };
+
+ /**
+ * Return the filter level. This affects the quality (and performance) of
+ * drawing scaled images.
+ */
+ FilterLevel getFilterLevel() const;
+
+ /**
+ * Set the filter level. This affects the quality (and performance) of
+ * drawing scaled images.
+ */
+ void setFilterLevel(FilterLevel);
+
+ /**
+ * DEPRECATED: use setFilterLevel instead.
+ * If the predicate is true, set the filterLevel to Low, else set it to
+ * None.
+ */
+ void setFilterBitmap(bool doFilter) {
+ this->setFilterLevel(doFilter ? kLow_FilterLevel : kNone_FilterLevel);
+ }
+
+ /**
+ * DEPRECATED: call getFilterLevel() instead.
+ * Returns true if getFilterLevel() returns anything other than None.
+ */
+ bool isFilterBitmap() const {
+ return kNone_FilterLevel != this->getFilterLevel();
+ }
+
+ /** Styles apply to rect, oval, path, and text.
+ Bitmaps are always drawn in "fill", and lines are always drawn in
+ "stroke".
+
+ Note: strokeandfill implicitly draws the result with
+ SkPath::kWinding_FillType, so if the original path is even-odd, the
+ results may not appear the same as if it was drawn twice, filled and
+ then stroked.
+ */
+ enum Style {
+ kFill_Style, //!< fill the geometry
+ kStroke_Style, //!< stroke the geometry
+ kStrokeAndFill_Style, //!< fill and stroke the geometry
+ };
+ enum {
+ kStyleCount = kStrokeAndFill_Style + 1
+ };
+
+ /** Return the paint's style, used for controlling how primitives'
+ geometries are interpreted (except for drawBitmap, which always assumes
+ kFill_Style).
+ @return the paint's Style
+ */
+ Style getStyle() const { return (Style)fStyle; }
+
+ /** Set the paint's style, used for controlling how primitives'
+ geometries are interpreted (except for drawBitmap, which always assumes
+ Fill).
+ @param style The new style to set in the paint
+ */
+ void setStyle(Style style);
+
+ /** Return the paint's color. Note that the color is a 32bit value
+ containing alpha as well as r,g,b. This 32bit value is not
+ premultiplied, meaning that its alpha can be any value, regardless of
+ the values of r,g,b.
+ @return the paint's color (and alpha).
+ */
+ SkColor getColor() const { return fColor; }
+
+ /** Set the paint's color. Note that the color is a 32bit value containing
+ alpha as well as r,g,b. This 32bit value is not premultiplied, meaning
+ that its alpha can be any value, regardless of the values of r,g,b.
+ @param color The new color (including alpha) to set in the paint.
+ */
+ void setColor(SkColor color);
+
+ /** Helper to getColor() that just returns the color's alpha value.
+ @return the alpha component of the paint's color.
+ */
+ uint8_t getAlpha() const { return SkToU8(SkColorGetA(fColor)); }
+
+ /** Helper to setColor(), that only assigns the color's alpha value,
+ leaving its r,g,b values unchanged.
+ @param a set the alpha component (0..255) of the paint's color.
+ */
+ void setAlpha(U8CPU a);
+
+ /** Helper to setColor(), that takes a,r,g,b and constructs the color value
+ using SkColorSetARGB()
+ @param a The new alpha component (0..255) of the paint's color.
+ @param r The new red component (0..255) of the paint's color.
+ @param g The new green component (0..255) of the paint's color.
+ @param b The new blue component (0..255) of the paint's color.
+ */
+ void setARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b);
+
+ /** Return the width for stroking.
+ <p />
+ A value of 0 strokes in hairline mode.
+ Hairlines always draw 1-pixel wide, regardless of the matrix.
+ @return the paint's stroke width, used whenever the paint's style is
+ Stroke or StrokeAndFill.
+ */
+ SkScalar getStrokeWidth() const { return fWidth; }
+
+ /** Set the width for stroking.
+ Pass 0 to stroke in hairline mode.
+ Hairlines always draw 1-pixel wide, regardless of the matrix.
+ @param width set the paint's stroke width, used whenever the paint's
+ style is Stroke or StrokeAndFill.
+ */
+ void setStrokeWidth(SkScalar width);
+
+ /** Return the paint's stroke miter value. This is used to control the
+ behavior of miter joins when the joins angle is sharp.
+ @return the paint's miter limit, used whenever the paint's style is
+ Stroke or StrokeAndFill.
+ */
+ SkScalar getStrokeMiter() const { return fMiterLimit; }
+
+ /** Set the paint's stroke miter value. This is used to control the
+ behavior of miter joins when the joins angle is sharp. This value must
+ be >= 0.
+ @param miter set the miter limit on the paint, used whenever the
+ paint's style is Stroke or StrokeAndFill.
+ */
+ void setStrokeMiter(SkScalar miter);
+
+ /** Cap enum specifies the settings for the paint's strokecap. This is the
+ treatment that is applied to the beginning and end of each non-closed
+ contour (e.g. lines).
+ */
+ enum Cap {
+ kButt_Cap, //!< begin/end contours with no extension
+ kRound_Cap, //!< begin/end contours with a semi-circle extension
+ kSquare_Cap, //!< begin/end contours with a half square extension
+
+ kCapCount,
+ kDefault_Cap = kButt_Cap
+ };
+
+ /** Join enum specifies the settings for the paint's strokejoin. This is
+ the treatment that is applied to corners in paths and rectangles.
+ */
+ enum Join {
+ kMiter_Join, //!< connect path segments with a sharp join
+ kRound_Join, //!< connect path segments with a round join
+ kBevel_Join, //!< connect path segments with a flat bevel join
+
+ kJoinCount,
+ kDefault_Join = kMiter_Join
+ };
+
+ /** Return the paint's stroke cap type, controlling how the start and end
+ of stroked lines and paths are treated.
+ @return the line cap style for the paint, used whenever the paint's
+ style is Stroke or StrokeAndFill.
+ */
+ Cap getStrokeCap() const { return (Cap)fCapType; }
+
+ /** Set the paint's stroke cap type.
+ @param cap set the paint's line cap style, used whenever the paint's
+ style is Stroke or StrokeAndFill.
+ */
+ void setStrokeCap(Cap cap);
+
+ /** Return the paint's stroke join type.
+ @return the paint's line join style, used whenever the paint's style is
+ Stroke or StrokeAndFill.
+ */
+ Join getStrokeJoin() const { return (Join)fJoinType; }
+
+ /** Set the paint's stroke join type.
+ @param join set the paint's line join style, used whenever the paint's
+ style is Stroke or StrokeAndFill.
+ */
+ void setStrokeJoin(Join join);
+
+ /**
+ * Applies any/all effects (patheffect, stroking) to src, returning the
+ * result in dst. The result is that drawing src with this paint will be
+ * the same as drawing dst with a default paint (at least from the
+ * geometric perspective).
+ *
+ * @param src input path
+ * @param dst output path (may be the same as src)
+ * @param cullRect If not null, the dst path may be culled to this rect.
+ * @return true if the path should be filled, or false if it should be
+ * drawn with a hairline (width == 0)
+ */
+ bool getFillPath(const SkPath& src, SkPath* dst,
+ const SkRect* cullRect = NULL) const;
+
+ /** Get the paint's shader object.
+ <p />
+ The shader's reference count is not affected.
+ @return the paint's shader (or NULL)
+ */
+ SkShader* getShader() const { return fShader; }
+
+ /** Set or clear the shader object.
+ * Shaders specify the source color(s) for what is being drawn. If a paint
+ * has no shader, then the paint's color is used. If the paint has a
+ * shader, then the shader's color(s) are use instead, but they are
+ * modulated by the paint's alpha. This makes it easy to create a shader
+ * once (e.g. bitmap tiling or gradient) and then change its transparency
+ * w/o having to modify the original shader... only the paint's alpha needs
+ * to be modified.
+ * <p />
+ * Pass NULL to clear any previous shader.
+ * As a convenience, the parameter passed is also returned.
+ * If a previous shader exists, its reference count is decremented.
+ * If shader is not NULL, its reference count is incremented.
+ * @param shader May be NULL. The shader to be installed in the paint
+ * @return shader
+ */
+ SkShader* setShader(SkShader* shader);
+
+ /** Get the paint's colorfilter. If there is a colorfilter, its reference
+ count is not changed.
+ @return the paint's colorfilter (or NULL)
+ */
+ SkColorFilter* getColorFilter() const { return fColorFilter; }
+
+ /** Set or clear the paint's colorfilter, returning the parameter.
+ <p />
+ If the paint already has a filter, its reference count is decremented.
+ If filter is not NULL, its reference count is incremented.
+ @param filter May be NULL. The filter to be installed in the paint
+ @return filter
+ */
+ SkColorFilter* setColorFilter(SkColorFilter* filter);
+
+ /** Get the paint's xfermode object.
+ <p />
+ The xfermode's reference count is not affected.
+ @return the paint's xfermode (or NULL)
+ */
+ SkXfermode* getXfermode() const { return fXfermode; }
+
+ /** Set or clear the xfermode object.
+ <p />
+ Pass NULL to clear any previous xfermode.
+ As a convenience, the parameter passed is also returned.
+ If a previous xfermode exists, its reference count is decremented.
+ If xfermode is not NULL, its reference count is incremented.
+ @param xfermode May be NULL. The new xfermode to be installed in the
+ paint
+ @return xfermode
+ */
+ SkXfermode* setXfermode(SkXfermode* xfermode);
+
+ /** Create an xfermode based on the specified Mode, and assign it into the
+ paint, returning the mode that was set. If the Mode is SrcOver, then
+ the paint's xfermode is set to null.
+ */
+ SkXfermode* setXfermodeMode(SkXfermode::Mode);
+
+ /** Get the paint's patheffect object.
+ <p />
+ The patheffect reference count is not affected.
+ @return the paint's patheffect (or NULL)
+ */
+ SkPathEffect* getPathEffect() const { return fPathEffect; }
+
+ /** Set or clear the patheffect object.
+ <p />
+ Pass NULL to clear any previous patheffect.
+ As a convenience, the parameter passed is also returned.
+ If a previous patheffect exists, its reference count is decremented.
+ If patheffect is not NULL, its reference count is incremented.
+ @param effect May be NULL. The new patheffect to be installed in the
+ paint
+ @return effect
+ */
+ SkPathEffect* setPathEffect(SkPathEffect* effect);
+
+ /** Get the paint's maskfilter object.
+ <p />
+ The maskfilter reference count is not affected.
+ @return the paint's maskfilter (or NULL)
+ */
+ SkMaskFilter* getMaskFilter() const { return fMaskFilter; }
+
+ /** Set or clear the maskfilter object.
+ <p />
+ Pass NULL to clear any previous maskfilter.
+ As a convenience, the parameter passed is also returned.
+ If a previous maskfilter exists, its reference count is decremented.
+ If maskfilter is not NULL, its reference count is incremented.
+ @param maskfilter May be NULL. The new maskfilter to be installed in
+ the paint
+ @return maskfilter
+ */
+ SkMaskFilter* setMaskFilter(SkMaskFilter* maskfilter);
+
+ // These attributes are for text/fonts
+
+ /** Get the paint's typeface object.
+ <p />
+ The typeface object identifies which font to use when drawing or
+ measuring text. The typeface reference count is not affected.
+ @return the paint's typeface (or NULL)
+ */
+ SkTypeface* getTypeface() const { return fTypeface; }
+
+ /** Set or clear the typeface object.
+ <p />
+ Pass NULL to clear any previous typeface.
+ As a convenience, the parameter passed is also returned.
+ If a previous typeface exists, its reference count is decremented.
+ If typeface is not NULL, its reference count is incremented.
+ @param typeface May be NULL. The new typeface to be installed in the
+ paint
+ @return typeface
+ */
+ SkTypeface* setTypeface(SkTypeface* typeface);
+
+ /** Get the paint's rasterizer (or NULL).
+ <p />
+ The raster controls how paths/text are turned into alpha masks.
+ @return the paint's rasterizer (or NULL)
+ */
+ SkRasterizer* getRasterizer() const { return fRasterizer; }
+
+ /** Set or clear the rasterizer object.
+ <p />
+ Pass NULL to clear any previous rasterizer.
+ As a convenience, the parameter passed is also returned.
+ If a previous rasterizer exists in the paint, its reference count is
+ decremented. If rasterizer is not NULL, its reference count is
+ incremented.
+ @param rasterizer May be NULL. The new rasterizer to be installed in
+ the paint.
+ @return rasterizer
+ */
+ SkRasterizer* setRasterizer(SkRasterizer* rasterizer);
+
+ SkImageFilter* getImageFilter() const { return fImageFilter; }
+ SkImageFilter* setImageFilter(SkImageFilter*);
+
+ SkAnnotation* getAnnotation() const { return fAnnotation; }
+ SkAnnotation* setAnnotation(SkAnnotation*);
+
+ /**
+ * Returns true if there is an annotation installed on this paint, and
+ * the annotation specifics no-drawing.
+ */
+ bool isNoDrawAnnotation() const {
+ return SkToBool(fPrivFlags & kNoDrawAnnotation_PrivFlag);
+ }
+
+ /**
+ * Return the paint's SkDrawLooper (if any). Does not affect the looper's
+ * reference count.
+ */
+ SkDrawLooper* getLooper() const { return fLooper; }
+
+ /**
+ * Set or clear the looper object.
+ * <p />
+ * Pass NULL to clear any previous looper.
+ * As a convenience, the parameter passed is also returned.
+ * If a previous looper exists in the paint, its reference count is
+ * decremented. If looper is not NULL, its reference count is
+ * incremented.
+ * @param looper May be NULL. The new looper to be installed in the paint.
+ * @return looper
+ */
+ SkDrawLooper* setLooper(SkDrawLooper* looper);
+
+ enum Align {
+ kLeft_Align,
+ kCenter_Align,
+ kRight_Align,
+ };
+ enum {
+ kAlignCount = 3
+ };
+
+ /** Return the paint's Align value for drawing text.
+ @return the paint's Align value for drawing text.
+ */
+ Align getTextAlign() const { return (Align)fTextAlign; }
+
+ /** Set the paint's text alignment.
+ @param align set the paint's Align value for drawing text.
+ */
+ void setTextAlign(Align align);
+
+ /** Return the paint's text size.
+ @return the paint's text size.
+ */
+ SkScalar getTextSize() const { return fTextSize; }
+
+ /** Set the paint's text size. This value must be > 0
+ @param textSize set the paint's text size.
+ */
+ void setTextSize(SkScalar textSize);
+
+ /** Return the paint's horizontal scale factor for text. The default value
+ is 1.0.
+ @return the paint's scale factor in X for drawing/measuring text
+ */
+ SkScalar getTextScaleX() const { return fTextScaleX; }
+
+ /** Set the paint's horizontal scale factor for text. The default value
+ is 1.0. Values > 1.0 will stretch the text wider. Values < 1.0 will
+ stretch the text narrower.
+ @param scaleX set the paint's scale factor in X for drawing/measuring
+ text.
+ */
+ void setTextScaleX(SkScalar scaleX);
+
+ /** Return the paint's horizontal skew factor for text. The default value
+ is 0.
+ @return the paint's skew factor in X for drawing text.
+ */
+ SkScalar getTextSkewX() const { return fTextSkewX; }
+
+ /** Set the paint's horizontal skew factor for text. The default value
+ is 0. For approximating oblique text, use values around -0.25.
+ @param skewX set the paint's skew factor in X for drawing text.
+ */
+ void setTextSkewX(SkScalar skewX);
+
+#ifdef SK_SUPPORT_HINTING_SCALE_FACTOR
+ /** Return the paint's scale factor used for correctly rendering
+ glyphs in high DPI mode without text subpixel positioning.
+ @return the scale factor used for rendering glyphs in high DPI mode.
+ */
+ SkScalar getHintingScaleFactor() const { return fHintingScaleFactor; }
+
+ /** Set the paint's scale factor used for correctly rendering
+ glyphs in high DPI mode without text subpixel positioning.
+ @param the scale factor used for rendering glyphs in high DPI mode.
+ */
+ void setHintingScaleFactor(SkScalar hintingScaleFactor);
+#endif
+
+ /** Describes how to interpret the text parameters that are passed to paint
+ methods like measureText() and getTextWidths().
+ */
+ enum TextEncoding {
+ kUTF8_TextEncoding, //!< the text parameters are UTF8
+ kUTF16_TextEncoding, //!< the text parameters are UTF16
+ kUTF32_TextEncoding, //!< the text parameters are UTF32
+ kGlyphID_TextEncoding //!< the text parameters are glyph indices
+ };
+
+ TextEncoding getTextEncoding() const { return (TextEncoding)fTextEncoding; }
+
+ void setTextEncoding(TextEncoding encoding);
+
+ struct FontMetrics {
+ SkScalar fTop; //!< The greatest distance above the baseline for any glyph (will be <= 0)
+ SkScalar fAscent; //!< The recommended distance above the baseline (will be <= 0)
+ SkScalar fDescent; //!< The recommended distance below the baseline (will be >= 0)
+ SkScalar fBottom; //!< The greatest distance below the baseline for any glyph (will be >= 0)
+ SkScalar fLeading; //!< The recommended distance to add between lines of text (will be >= 0)
+ SkScalar fAvgCharWidth; //!< the average charactor width (>= 0)
+ SkScalar fMaxCharWidth; //!< the max charactor width (>= 0)
+ SkScalar fXMin; //!< The minimum bounding box x value for all glyphs
+ SkScalar fXMax; //!< The maximum bounding box x value for all glyphs
+ SkScalar fXHeight; //!< the height of an 'x' in px, or 0 if no 'x' in face
+ };
+
+ /** Return the recommend spacing between lines (which will be
+ fDescent - fAscent + fLeading).
+ If metrics is not null, return in it the font metrics for the
+ typeface/pointsize/etc. currently set in the paint.
+ @param metrics If not null, returns the font metrics for the
+ current typeface/pointsize/etc setting in this
+ paint.
+ @param scale If not 0, return width as if the canvas were scaled
+ by this value
+ @param return the recommended spacing between lines
+ */
+ SkScalar getFontMetrics(FontMetrics* metrics, SkScalar scale = 0) const;
+
+ /** Return the recommend line spacing. This will be
+ fDescent - fAscent + fLeading
+ */
+ SkScalar getFontSpacing() const { return this->getFontMetrics(NULL, 0); }
+
+ /** Convert the specified text into glyph IDs, returning the number of
+ glyphs ID written. If glyphs is NULL, it is ignore and only the count
+ is returned.
+ */
+ int textToGlyphs(const void* text, size_t byteLength,
+ uint16_t glyphs[]) const;
+
+ /** Return true if all of the specified text has a corresponding non-zero
+ glyph ID. If any of the code-points in the text are not supported in
+ the typeface (i.e. the glyph ID would be zero), then return false.
+
+ If the text encoding for the paint is kGlyph_TextEncoding, then this
+ returns true if all of the specified glyph IDs are non-zero.
+ */
+ bool containsText(const void* text, size_t byteLength) const;
+
+ /** Convert the glyph array into Unichars. Unconvertable glyphs are mapped
+ to zero. Note: this does not look at the text-encoding setting in the
+ paint, only at the typeface.
+ */
+ void glyphsToUnichars(const uint16_t glyphs[], int count,
+ SkUnichar text[]) const;
+
+ /** Return the number of drawable units in the specified text buffer.
+ This looks at the current TextEncoding field of the paint. If you also
+ want to have the text converted into glyph IDs, call textToGlyphs
+ instead.
+ */
+ int countText(const void* text, size_t byteLength) const {
+ return this->textToGlyphs(text, byteLength, NULL);
+ }
+
+ /** Return the width of the text. This will return the vertical measure
+ * if isVerticalText() is true, in which case the returned value should
+ * be treated has a height instead of a width.
+ *
+ * @param text The text to be measured
+ * @param length Number of bytes of text to measure
+ * @param bounds If not NULL, returns the bounds of the text,
+ * relative to (0, 0).
+ * @param scale If not 0, return width as if the canvas were scaled
+ * by this value
+ * @return The advance width of the text
+ */
+ SkScalar measureText(const void* text, size_t length,
+ SkRect* bounds, SkScalar scale = 0) const;
+
+ /** Return the width of the text. This will return the vertical measure
+ * if isVerticalText() is true, in which case the returned value should
+ * be treated has a height instead of a width.
+ *
+ * @param text Address of the text
+ * @param length Number of bytes of text to measure
+ * @return The advance width of the text
+ */
+ SkScalar measureText(const void* text, size_t length) const {
+ return this->measureText(text, length, NULL, 0);
+ }
+
+ /** Specify the direction the text buffer should be processed in breakText()
+ */
+ enum TextBufferDirection {
+ /** When measuring text for breakText(), begin at the start of the text
+ buffer and proceed forward through the data. This is the default.
+ */
+ kForward_TextBufferDirection,
+ /** When measuring text for breakText(), begin at the end of the text
+ buffer and proceed backwards through the data.
+ */
+ kBackward_TextBufferDirection
+ };
+
+ /** Return the number of bytes of text that were measured. If
+ * isVerticalText() is true, then the vertical advances are used for
+ * the measurement.
+ *
+ * @param text The text to be measured
+ * @param length Number of bytes of text to measure
+ * @param maxWidth Maximum width. Only the subset of text whose accumulated
+ * widths are <= maxWidth are measured.
+ * @param measuredWidth Optional. If non-null, this returns the actual
+ * width of the measured text.
+ * @param tbd Optional. The direction the text buffer should be
+ * traversed during measuring.
+ * @return The number of bytes of text that were measured. Will be
+ * <= length.
+ */
+ size_t breakText(const void* text, size_t length, SkScalar maxWidth,
+ SkScalar* measuredWidth = NULL,
+ TextBufferDirection tbd = kForward_TextBufferDirection)
+ const;
+
+ /** Return the advances for the text. These will be vertical advances if
+ * isVerticalText() returns true.
+ *
+ * @param text the text
+ * @param byteLength number of bytes to of text
+ * @param widths If not null, returns the array of advances for
+ * the glyphs. If not NULL, must be at least a large
+ * as the number of unichars in the specified text.
+ * @param bounds If not null, returns the bounds for each of
+ * character, relative to (0, 0)
+ * @return the number of unichars in the specified text.
+ */
+ int getTextWidths(const void* text, size_t byteLength, SkScalar widths[],
+ SkRect bounds[] = NULL) const;
+
+ /** Return the path (outline) for the specified text.
+ Note: just like SkCanvas::drawText, this will respect the Align setting
+ in the paint.
+ */
+ void getTextPath(const void* text, size_t length, SkScalar x, SkScalar y,
+ SkPath* path) const;
+
+ void getPosTextPath(const void* text, size_t length,
+ const SkPoint pos[], SkPath* path) const;
+
+#ifdef SK_BUILD_FOR_ANDROID
+ const SkGlyph& getUnicharMetrics(SkUnichar, const SkMatrix*);
+ const SkGlyph& getGlyphMetrics(uint16_t, const SkMatrix*);
+ const void* findImage(const SkGlyph&, const SkMatrix*);
+
+ uint32_t getGenerationID() const;
+ void setGenerationID(uint32_t generationID);
+
+ /** Returns the base glyph count for the strike associated with this paint
+ */
+ unsigned getBaseGlyphCount(SkUnichar text) const;
+
+ const SkPaintOptionsAndroid& getPaintOptionsAndroid() const {
+ return fPaintOptionsAndroid;
+ }
+ void setPaintOptionsAndroid(const SkPaintOptionsAndroid& options);
+#endif
+
+ // returns true if the paint's settings (e.g. xfermode + alpha) resolve to
+ // mean that we need not draw at all (e.g. SrcOver + 0-alpha)
+ bool nothingToDraw() const;
+
+ ///////////////////////////////////////////////////////////////////////////
+ // would prefer to make these private...
+
+ /** Returns true if the current paint settings allow for fast computation of
+ bounds (i.e. there is nothing complex like a patheffect that would make
+ the bounds computation expensive.
+ */
+ bool canComputeFastBounds() const {
+ if (this->getLooper()) {
+ return this->getLooper()->canComputeFastBounds(*this);
+ }
+ return !this->getRasterizer();
+ }
+
+ /** Only call this if canComputeFastBounds() returned true. This takes a
+ raw rectangle (the raw bounds of a shape), and adjusts it for stylistic
+ effects in the paint (e.g. stroking). If needed, it uses the storage
+ rect parameter. It returns the adjusted bounds that can then be used
+ for quickReject tests.
+
+ The returned rect will either be orig or storage, thus the caller
+ should not rely on storage being set to the result, but should always
+ use the retured value. It is legal for orig and storage to be the same
+ rect.
+
+ e.g.
+ if (paint.canComputeFastBounds()) {
+ SkRect r, storage;
+ path.computeBounds(&r, SkPath::kFast_BoundsType);
+ const SkRect& fastR = paint.computeFastBounds(r, &storage);
+ if (canvas->quickReject(fastR, ...)) {
+ // don't draw the path
+ }
+ }
+ */
+ const SkRect& computeFastBounds(const SkRect& orig, SkRect* storage) const {
+ SkPaint::Style style = this->getStyle();
+ // ultra fast-case: filling with no effects that affect geometry
+ if (kFill_Style == style) {
+ uintptr_t effects = reinterpret_cast<uintptr_t>(this->getLooper());
+ effects |= reinterpret_cast<uintptr_t>(this->getMaskFilter());
+ effects |= reinterpret_cast<uintptr_t>(this->getPathEffect());
+ if (!effects) {
+ return orig;
+ }
+ }
+
+ return this->doComputeFastBounds(orig, storage, style);
+ }
+
+ const SkRect& computeFastStrokeBounds(const SkRect& orig,
+ SkRect* storage) const {
+ return this->doComputeFastBounds(orig, storage, kStroke_Style);
+ }
+
+ // Take the style explicitly, so the caller can force us to be stroked
+ // without having to make a copy of the paint just to change that field.
+ const SkRect& doComputeFastBounds(const SkRect& orig, SkRect* storage,
+ Style) const;
+
+ /**
+ * Return a matrix that applies the paint's text values: size, scale, skew
+ */
+ static SkMatrix* SetTextMatrix(SkMatrix* matrix, SkScalar size,
+ SkScalar scaleX, SkScalar skewX) {
+ matrix->setScale(size * scaleX, size);
+ if (skewX) {
+ matrix->postSkew(skewX, 0);
+ }
+ return matrix;
+ }
+
+ SkMatrix* setTextMatrix(SkMatrix* matrix) const {
+ return SetTextMatrix(matrix, fTextSize, fTextScaleX, fTextSkewX);
+ }
+
+ SkDEVCODE(void toString(SkString*) const;)
+
+private:
+ SkTypeface* fTypeface;
+ SkScalar fTextSize;
+ SkScalar fTextScaleX;
+ SkScalar fTextSkewX;
+#ifdef SK_SUPPORT_HINTING_SCALE_FACTOR
+ SkScalar fHintingScaleFactor;
+#endif
+
+ SkPathEffect* fPathEffect;
+ SkShader* fShader;
+ SkXfermode* fXfermode;
+ SkMaskFilter* fMaskFilter;
+ SkColorFilter* fColorFilter;
+ SkRasterizer* fRasterizer;
+ SkDrawLooper* fLooper;
+ SkImageFilter* fImageFilter;
+ SkAnnotation* fAnnotation;
+
+ SkColor fColor;
+ SkScalar fWidth;
+ SkScalar fMiterLimit;
+ // all of these bitfields should add up to 32
+ unsigned fFlags : 16;
+ unsigned fTextAlign : 2;
+ unsigned fCapType : 2;
+ unsigned fJoinType : 2;
+ unsigned fStyle : 2;
+ unsigned fTextEncoding : 2; // 3 values
+ unsigned fHinting : 2;
+ unsigned fPrivFlags : 4; // these are not flattened/unflattened
+
+ enum PrivFlags {
+ kNoDrawAnnotation_PrivFlag = 1 << 0,
+ };
+
+ SkDrawCacheProc getDrawCacheProc() const;
+ SkMeasureCacheProc getMeasureCacheProc(TextBufferDirection dir,
+ bool needFullMetrics) const;
+
+ SkScalar measure_text(SkGlyphCache*, const char* text, size_t length,
+ int* count, SkRect* bounds) const;
+
+ SkGlyphCache* detachCache(const SkDeviceProperties* deviceProperties, const SkMatrix*) const;
+
+ void descriptorProc(const SkDeviceProperties* deviceProperties, const SkMatrix* deviceMatrix,
+ void (*proc)(SkTypeface*, const SkDescriptor*, void*),
+ void* context, bool ignoreGamma = false) const;
+
+ static void Term();
+
+ enum {
+ /* This is the size we use when we ask for a glyph's path. We then
+ * post-transform it as we draw to match the request.
+ * This is done to try to re-use cache entries for the path.
+ *
+ * This value is somewhat arbitrary. In theory, it could be 1, since
+ * we store paths as floats. However, we get the path from the font
+ * scaler, and it may represent its paths as fixed-point (or 26.6),
+ * so we shouldn't ask for something too big (might overflow 16.16)
+ * or too small (underflow 26.6).
+ *
+ * This value could track kMaxSizeForGlyphCache, assuming the above
+ * constraints, but since we ask for unhinted paths, the two values
+ * need not match per-se.
+ */
+ kCanonicalTextSizeForPaths = 64,
+
+ /*
+ * Above this size (taking into account CTM and textSize), we never use
+ * the cache for bits or metrics (we might overflow), so we just ask
+ * for a caononical size and post-transform that.
+ */
+ kMaxSizeForGlyphCache = 256,
+ };
+
+ static bool TooBigToUseCache(const SkMatrix& ctm, const SkMatrix& textM);
+
+ bool tooBigToUseCache() const;
+ bool tooBigToUseCache(const SkMatrix& ctm) const;
+
+ // Set flags/hinting/textSize up to use for drawing text as paths.
+ // Returns scale factor to restore the original textSize, since will will
+ // have change it to kCanonicalTextSizeForPaths.
+ SkScalar setupForAsPaths();
+
+ static SkScalar MaxCacheSize2() {
+ static const SkScalar kMaxSize = SkIntToScalar(kMaxSizeForGlyphCache);
+ static const SkScalar kMag2Max = kMaxSize * kMaxSize;
+ return kMag2Max;
+ }
+
+ friend class SkAutoGlyphCache;
+ friend class SkCanvas;
+ friend class SkDraw;
+ friend class SkGraphics; // So Term() can be called.
+ friend class SkPDFDevice;
+ friend class SkTextToPathIter;
+ friend class SkCanonicalizePaint;
+
+#ifdef SK_BUILD_FOR_ANDROID
+ SkPaintOptionsAndroid fPaintOptionsAndroid;
+
+ // In order for the == operator to work properly this must be the last field
+ // in the struct so that we can do a memcmp to this field's offset.
+ uint32_t fGenerationID;
+#endif
+};
+
+#endif
diff --git a/core/SkPaintOptionsAndroid.h b/core/SkPaintOptionsAndroid.h
new file mode 100644
index 0000000..78e4386
--- /dev/null
+++ b/core/SkPaintOptionsAndroid.h
@@ -0,0 +1,129 @@
+
+/*
+ * Copyright 2012 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkPaintOptionsAndroid_DEFINED
+#define SkPaintOptionsAndroid_DEFINED
+
+#include "SkTypes.h"
+#include "SkString.h"
+
+#ifdef SK_BUILD_FOR_ANDROID
+
+class SkFlattenableReadBuffer;
+class SkFlattenableWriteBuffer;
+
+/** \class SkLanguage
+
+ The SkLanguage class represents a human written language, and is used by
+ text draw operations to determine which glyph to draw when drawing
+ characters with variants (ie Han-derived characters).
+*/
+class SkLanguage {
+public:
+ SkLanguage() { }
+ SkLanguage(const SkString& tag) : fTag(tag) { }
+ SkLanguage(const char* tag) : fTag(tag) { }
+ SkLanguage(const char* tag, size_t len) : fTag(tag, len) { }
+ SkLanguage(const SkLanguage& b) : fTag(b.fTag) { }
+
+ /** Gets a BCP 47 language identifier for this SkLanguage.
+ @return a BCP 47 language identifier representing this language
+ */
+ const SkString& getTag() const { return fTag; }
+
+ /** Performs BCP 47 fallback to return an SkLanguage one step more general.
+ @return an SkLanguage one step more general
+ */
+ SkLanguage getParent() const;
+
+ bool operator==(const SkLanguage& b) const {
+ return fTag == b.fTag;
+ }
+ bool operator!=(const SkLanguage& b) const {
+ return fTag != b.fTag;
+ }
+ SkLanguage& operator=(const SkLanguage& b) {
+ fTag = b.fTag;
+ return *this;
+ }
+
+private:
+ //! BCP 47 language identifier
+ SkString fTag;
+};
+
+class SkPaintOptionsAndroid {
+public:
+ SkPaintOptionsAndroid() {
+ fFontVariant = kDefault_Variant;
+ fUseFontFallbacks = false;
+ }
+
+ SkPaintOptionsAndroid& operator=(const SkPaintOptionsAndroid& b) {
+ fLanguage = b.fLanguage;
+ fFontVariant = b.fFontVariant;
+ fUseFontFallbacks = b.fUseFontFallbacks;
+ return *this;
+ }
+
+ bool operator!=(const SkPaintOptionsAndroid& b) const {
+ return fLanguage != b.fLanguage ||
+ fFontVariant != b.fFontVariant ||
+ fUseFontFallbacks != b.fUseFontFallbacks;
+ }
+
+ void flatten(SkFlattenableWriteBuffer&) const;
+ void unflatten(SkFlattenableReadBuffer&);
+
+ /** Return the paint's language value used for drawing text.
+ @return the paint's language value used for drawing text.
+ */
+ const SkLanguage& getLanguage() const { return fLanguage; }
+
+ /** Set the paint's language value used for drawing text.
+ @param language set the paint's language value for drawing text.
+ */
+ void setLanguage(const SkLanguage& language) { fLanguage = language; }
+ void setLanguage(const char* languageTag) { fLanguage = SkLanguage(languageTag); }
+
+
+ enum FontVariant {
+ kDefault_Variant = 0x01, // Currently setting yourself to Default gives you Compact Variant
+ kCompact_Variant = 0x02,
+ kElegant_Variant = 0x04,
+ kLast_Variant = kElegant_Variant,
+ };
+
+ /** Return the font variant
+ @return the font variant used by this paint object
+ */
+ FontVariant getFontVariant() const { return fFontVariant; }
+
+ /** Set the font variant
+ @param fontVariant set the paint's font variant for choosing fonts
+ */
+ void setFontVariant(FontVariant fontVariant) {
+ SkASSERT((unsigned)fontVariant <= kLast_Variant);
+ fFontVariant = fontVariant;
+ }
+
+ bool isUsingFontFallbacks() const { return fUseFontFallbacks; }
+
+ void setUseFontFallbacks(bool useFontFallbacks) {
+ fUseFontFallbacks = useFontFallbacks;
+ }
+
+private:
+ SkLanguage fLanguage;
+ FontVariant fFontVariant;
+ bool fUseFontFallbacks;
+};
+
+#endif // #ifdef SK_BUILD_FOR_ANDROID
+#endif // #ifndef SkPaintOptionsAndroid_DEFINED
diff --git a/core/SkPath.h b/core/SkPath.h
new file mode 100644
index 0000000..be15a63
--- /dev/null
+++ b/core/SkPath.h
@@ -0,0 +1,1008 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkPath_DEFINED
+#define SkPath_DEFINED
+
+#include "SkInstCnt.h"
+#include "SkMatrix.h"
+#include "SkTDArray.h"
+#include "SkRefCnt.h"
+
+#ifdef SK_BUILD_FOR_ANDROID
+#define GEN_ID_INC fGenerationID++
+#define GEN_ID_PTR_INC(ptr) (ptr)->fGenerationID++
+#else
+#define GEN_ID_INC
+#define GEN_ID_PTR_INC(ptr)
+#endif
+
+class SkReader32;
+class SkWriter32;
+class SkAutoPathBoundsUpdate;
+class SkString;
+class SkPathRef;
+class SkRRect;
+
+/** \class SkPath
+
+ The SkPath class encapsulates compound (multiple contour) geometric paths
+ consisting of straight line segments, quadratic curves, and cubic curves.
+*/
+class SK_API SkPath {
+public:
+ SK_DECLARE_INST_COUNT_ROOT(SkPath);
+
+ SkPath();
+ SkPath(const SkPath&); // Copies fGenerationID on Android.
+ ~SkPath();
+
+ SkPath& operator=(const SkPath&); // Increments fGenerationID on Android.
+ friend SK_API bool operator==(const SkPath&, const SkPath&);
+ friend bool operator!=(const SkPath& a, const SkPath& b) {
+ return !(a == b);
+ }
+
+ enum FillType {
+ /** Specifies that "inside" is computed by a non-zero sum of signed
+ edge crossings
+ */
+ kWinding_FillType,
+ /** Specifies that "inside" is computed by an odd number of edge
+ crossings
+ */
+ kEvenOdd_FillType,
+ /** Same as Winding, but draws outside of the path, rather than inside
+ */
+ kInverseWinding_FillType,
+ /** Same as EvenOdd, but draws outside of the path, rather than inside
+ */
+ kInverseEvenOdd_FillType
+ };
+
+ /** Return the path's fill type. This is used to define how "inside" is
+ computed. The default value is kWinding_FillType.
+
+ @return the path's fill type
+ */
+ FillType getFillType() const { return (FillType)fFillType; }
+
+ /** Set the path's fill type. This is used to define how "inside" is
+ computed. The default value is kWinding_FillType.
+
+ @param ft The new fill type for this path
+ */
+ void setFillType(FillType ft) {
+ fFillType = SkToU8(ft);
+ GEN_ID_INC;
+ }
+
+ /** Returns true if the filltype is one of the Inverse variants */
+ bool isInverseFillType() const { return IsInverseFillType((FillType)fFillType); }
+
+ /**
+ * Toggle between inverse and normal filltypes. This reverse the return
+ * value of isInverseFillType()
+ */
+ void toggleInverseFillType() {
+ fFillType ^= 2;
+ GEN_ID_INC;
+ }
+
+ enum Convexity {
+ kUnknown_Convexity,
+ kConvex_Convexity,
+ kConcave_Convexity
+ };
+
+ /**
+ * Return the path's convexity, as stored in the path. If it is currently unknown,
+ * then this function will attempt to compute the convexity (and cache the result).
+ */
+ Convexity getConvexity() const {
+ if (kUnknown_Convexity != fConvexity) {
+ return static_cast<Convexity>(fConvexity);
+ } else {
+ return this->internalGetConvexity();
+ }
+ }
+
+ /**
+ * Return the currently cached value for convexity, even if that is set to
+ * kUnknown_Convexity. Note: getConvexity() will automatically call
+ * ComputeConvexity and cache its return value if the current setting is
+ * kUnknown.
+ */
+ Convexity getConvexityOrUnknown() const { return (Convexity)fConvexity; }
+
+ /**
+ * Store a convexity setting in the path. There is no automatic check to
+ * see if this value actually agrees with the return value that would be
+ * computed by getConvexity().
+ *
+ * Note: even if this is set to a "known" value, if the path is later
+ * changed (e.g. lineTo(), addRect(), etc.) then the cached value will be
+ * reset to kUnknown_Convexity.
+ */
+ void setConvexity(Convexity);
+
+ /**
+ * DEPRECATED: use getConvexity()
+ * Returns true if the path is flagged as being convex. This is not a
+ * confirmed by any analysis, it is just the value set earlier.
+ */
+ bool isConvex() const {
+ return kConvex_Convexity == this->getConvexity();
+ }
+
+ /**
+ * DEPRECATED: use setConvexity()
+ * Set the isConvex flag to true or false. Convex paths may draw faster if
+ * this flag is set, though setting this to true on a path that is in fact
+ * not convex can give undefined results when drawn. Paths default to
+ * isConvex == false
+ */
+ void setIsConvex(bool isConvex) {
+ this->setConvexity(isConvex ? kConvex_Convexity : kConcave_Convexity);
+ }
+
+ /** Returns true if the path is an oval.
+ *
+ * @param rect returns the bounding rect of this oval. It's a circle
+ * if the height and width are the same.
+ *
+ * @return true if this path is an oval.
+ * Tracking whether a path is an oval is considered an
+ * optimization for performance and so some paths that are in
+ * fact ovals can report false.
+ */
+ bool isOval(SkRect* rect) const;
+
+ /** Clear any lines and curves from the path, making it empty. This frees up
+ internal storage associated with those segments.
+ */
+ void reset();
+
+ /** Similar to reset(), in that all lines and curves are removed from the
+ path. However, any internal storage for those lines/curves is retained,
+ making reuse of the path potentially faster.
+ */
+ void rewind();
+
+ /** Returns true if the path is empty (contains no lines or curves)
+
+ @return true if the path is empty (contains no lines or curves)
+ */
+ bool isEmpty() const;
+
+ /**
+ * Returns true if all of the points in this path are finite, meaning there
+ * are no infinities and no NaNs.
+ */
+ bool isFinite() const {
+ if (fBoundsIsDirty) {
+ this->computeBounds();
+ }
+ return SkToBool(fIsFinite);
+ }
+
+ /** Test a line for zero length
+
+ @return true if the line is of zero length; otherwise false.
+ */
+ static bool IsLineDegenerate(const SkPoint& p1, const SkPoint& p2) {
+ return p1.equalsWithinTolerance(p2);
+ }
+
+ /** Test a quad for zero length
+
+ @return true if the quad is of zero length; otherwise false.
+ */
+ static bool IsQuadDegenerate(const SkPoint& p1, const SkPoint& p2,
+ const SkPoint& p3) {
+ return p1.equalsWithinTolerance(p2) &&
+ p2.equalsWithinTolerance(p3);
+ }
+
+ /** Test a cubic curve for zero length
+
+ @return true if the cubic is of zero length; otherwise false.
+ */
+ static bool IsCubicDegenerate(const SkPoint& p1, const SkPoint& p2,
+ const SkPoint& p3, const SkPoint& p4) {
+ return p1.equalsWithinTolerance(p2) &&
+ p2.equalsWithinTolerance(p3) &&
+ p3.equalsWithinTolerance(p4);
+ }
+
+ /**
+ * Returns true if the path specifies a single line (i.e. it contains just
+ * a moveTo and a lineTo). If so, and line[] is not null, it sets the 2
+ * points in line[] to the end-points of the line. If the path is not a
+ * line, returns false and ignores line[].
+ */
+ bool isLine(SkPoint line[2]) const;
+
+ /** Returns true if the path specifies a rectangle. If so, and if rect is
+ not null, set rect to the bounds of the path. If the path does not
+ specify a rectangle, return false and ignore rect.
+
+ @param rect If not null, returns the bounds of the path if it specifies
+ a rectangle
+ @return true if the path specifies a rectangle
+ */
+ bool isRect(SkRect* rect) const;
+
+ /** Return the number of points in the path
+ */
+ int countPoints() const;
+
+ /** Return the point at the specified index. If the index is out of range
+ (i.e. is not 0 <= index < countPoints()) then the returned coordinates
+ will be (0,0)
+ */
+ SkPoint getPoint(int index) const;
+
+ /** Returns the number of points in the path. Up to max points are copied.
+
+ @param points If not null, receives up to max points
+ @param max The maximum number of points to copy into points
+ @return the actual number of points in the path
+ */
+ int getPoints(SkPoint points[], int max) const;
+
+ /** Return the number of verbs in the path
+ */
+ int countVerbs() const;
+
+ /** Returns the number of verbs in the path. Up to max verbs are copied. The
+ verbs are copied as one byte per verb.
+
+ @param verbs If not null, receives up to max verbs
+ @param max The maximum number of verbs to copy into verbs
+ @return the actual number of verbs in the path
+ */
+ int getVerbs(uint8_t verbs[], int max) const;
+
+ //! Swap contents of this and other. Guaranteed not to throw
+ void swap(SkPath& other);
+
+ /** Returns the bounds of the path's points. If the path contains 0 or 1
+ points, the bounds is set to (0,0,0,0), and isEmpty() will return true.
+ Note: this bounds may be larger than the actual shape, since curves
+ do not extend as far as their control points.
+ */
+ const SkRect& getBounds() const {
+ if (fBoundsIsDirty) {
+ this->computeBounds();
+ }
+ return fBounds;
+ }
+
+ /** Calling this will, if the internal cache of the bounds is out of date,
+ update it so that subsequent calls to getBounds will be instantaneous.
+ This also means that any copies or simple transformations of the path
+ will inherit the cached bounds.
+ */
+ void updateBoundsCache() const {
+ // for now, just calling getBounds() is sufficient
+ this->getBounds();
+ }
+
+ /**
+ * Does a conservative test to see whether a rectangle is inside a path. Currently it only
+ * will ever return true for single convex contour paths. The empty-status of the rect is not
+ * considered (e.g. a rect that is a point can be inside a path). Points or line segments where
+ * the rect edge touches the path border are not considered containment violations.
+ */
+ bool conservativelyContainsRect(const SkRect& rect) const;
+
+ // Construction methods
+
+ /** Hint to the path to prepare for adding more points. This can allow the
+ path to more efficiently grow its storage.
+
+ @param extraPtCount The number of extra points the path should
+ preallocate for.
+ */
+ void incReserve(unsigned extraPtCount);
+
+ /** Set the beginning of the next contour to the point (x,y).
+
+ @param x The x-coordinate of the start of a new contour
+ @param y The y-coordinate of the start of a new contour
+ */
+ void moveTo(SkScalar x, SkScalar y);
+
+ /** Set the beginning of the next contour to the point
+
+ @param p The start of a new contour
+ */
+ void moveTo(const SkPoint& p) {
+ this->moveTo(p.fX, p.fY);
+ }
+
+ /** Set the beginning of the next contour relative to the last point on the
+ previous contour. If there is no previous contour, this is treated the
+ same as moveTo().
+
+ @param dx The amount to add to the x-coordinate of the end of the
+ previous contour, to specify the start of a new contour
+ @param dy The amount to add to the y-coordinate of the end of the
+ previous contour, to specify the start of a new contour
+ */
+ void rMoveTo(SkScalar dx, SkScalar dy);
+
+ /** Add a line from the last point to the specified point (x,y). If no
+ moveTo() call has been made for this contour, the first point is
+ automatically set to (0,0).
+
+ @param x The x-coordinate of the end of a line
+ @param y The y-coordinate of the end of a line
+ */
+ void lineTo(SkScalar x, SkScalar y);
+
+ /** Add a line from the last point to the specified point. If no moveTo()
+ call has been made for this contour, the first point is automatically
+ set to (0,0).
+
+ @param p The end of a line
+ */
+ void lineTo(const SkPoint& p) {
+ this->lineTo(p.fX, p.fY);
+ }
+
+ /** Same as lineTo, but the coordinates are considered relative to the last
+ point on this contour. If there is no previous point, then a moveTo(0,0)
+ is inserted automatically.
+
+ @param dx The amount to add to the x-coordinate of the previous point
+ on this contour, to specify a line
+ @param dy The amount to add to the y-coordinate of the previous point
+ on this contour, to specify a line
+ */
+ void rLineTo(SkScalar dx, SkScalar dy);
+
+ /** Add a quadratic bezier from the last point, approaching control point
+ (x1,y1), and ending at (x2,y2). If no moveTo() call has been made for
+ this contour, the first point is automatically set to (0,0).
+
+ @param x1 The x-coordinate of the control point on a quadratic curve
+ @param y1 The y-coordinate of the control point on a quadratic curve
+ @param x2 The x-coordinate of the end point on a quadratic curve
+ @param y2 The y-coordinate of the end point on a quadratic curve
+ */
+ void quadTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2);
+
+ /** Add a quadratic bezier from the last point, approaching control point
+ p1, and ending at p2. If no moveTo() call has been made for this
+ contour, the first point is automatically set to (0,0).
+
+ @param p1 The control point on a quadratic curve
+ @param p2 The end point on a quadratic curve
+ */
+ void quadTo(const SkPoint& p1, const SkPoint& p2) {
+ this->quadTo(p1.fX, p1.fY, p2.fX, p2.fY);
+ }
+
+ /** Same as quadTo, but the coordinates are considered relative to the last
+ point on this contour. If there is no previous point, then a moveTo(0,0)
+ is inserted automatically.
+
+ @param dx1 The amount to add to the x-coordinate of the last point on
+ this contour, to specify the control point of a quadratic curve
+ @param dy1 The amount to add to the y-coordinate of the last point on
+ this contour, to specify the control point of a quadratic curve
+ @param dx2 The amount to add to the x-coordinate of the last point on
+ this contour, to specify the end point of a quadratic curve
+ @param dy2 The amount to add to the y-coordinate of the last point on
+ this contour, to specify the end point of a quadratic curve
+ */
+ void rQuadTo(SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2);
+
+ void conicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
+ SkScalar w);
+ void conicTo(const SkPoint& p1, const SkPoint& p2, SkScalar w) {
+ this->conicTo(p1.fX, p1.fY, p2.fX, p2.fY, w);
+ }
+ void rConicTo(SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2,
+ SkScalar w);
+
+ /** Add a cubic bezier from the last point, approaching control points
+ (x1,y1) and (x2,y2), and ending at (x3,y3). If no moveTo() call has been
+ made for this contour, the first point is automatically set to (0,0).
+
+ @param x1 The x-coordinate of the 1st control point on a cubic curve
+ @param y1 The y-coordinate of the 1st control point on a cubic curve
+ @param x2 The x-coordinate of the 2nd control point on a cubic curve
+ @param y2 The y-coordinate of the 2nd control point on a cubic curve
+ @param x3 The x-coordinate of the end point on a cubic curve
+ @param y3 The y-coordinate of the end point on a cubic curve
+ */
+ void cubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
+ SkScalar x3, SkScalar y3);
+
+ /** Add a cubic bezier from the last point, approaching control points p1
+ and p2, and ending at p3. If no moveTo() call has been made for this
+ contour, the first point is automatically set to (0,0).
+
+ @param p1 The 1st control point on a cubic curve
+ @param p2 The 2nd control point on a cubic curve
+ @param p3 The end point on a cubic curve
+ */
+ void cubicTo(const SkPoint& p1, const SkPoint& p2, const SkPoint& p3) {
+ this->cubicTo(p1.fX, p1.fY, p2.fX, p2.fY, p3.fX, p3.fY);
+ }
+
+ /** Same as cubicTo, but the coordinates are considered relative to the
+ current point on this contour. If there is no previous point, then a
+ moveTo(0,0) is inserted automatically.
+
+ @param dx1 The amount to add to the x-coordinate of the last point on
+ this contour, to specify the 1st control point of a cubic curve
+ @param dy1 The amount to add to the y-coordinate of the last point on
+ this contour, to specify the 1st control point of a cubic curve
+ @param dx2 The amount to add to the x-coordinate of the last point on
+ this contour, to specify the 2nd control point of a cubic curve
+ @param dy2 The amount to add to the y-coordinate of the last point on
+ this contour, to specify the 2nd control point of a cubic curve
+ @param dx3 The amount to add to the x-coordinate of the last point on
+ this contour, to specify the end point of a cubic curve
+ @param dy3 The amount to add to the y-coordinate of the last point on
+ this contour, to specify the end point of a cubic curve
+ */
+ void rCubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
+ SkScalar x3, SkScalar y3);
+
+ /** Append the specified arc to the path as a new contour. If the start of
+ the path is different from the path's current last point, then an
+ automatic lineTo() is added to connect the current contour to the start
+ of the arc. However, if the path is empty, then we call moveTo() with
+ the first point of the arc. The sweep angle is treated mod 360.
+
+ @param oval The bounding oval defining the shape and size of the arc
+ @param startAngle Starting angle (in degrees) where the arc begins
+ @param sweepAngle Sweep angle (in degrees) measured clockwise. This is
+ treated mod 360.
+ @param forceMoveTo If true, always begin a new contour with the arc
+ */
+ void arcTo(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle,
+ bool forceMoveTo);
+
+ /** Append a line and arc to the current path. This is the same as the
+ PostScript call "arct".
+ */
+ void arcTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
+ SkScalar radius);
+
+ /** Append a line and arc to the current path. This is the same as the
+ PostScript call "arct".
+ */
+ void arcTo(const SkPoint p1, const SkPoint p2, SkScalar radius) {
+ this->arcTo(p1.fX, p1.fY, p2.fX, p2.fY, radius);
+ }
+
+ /** Close the current contour. If the current point is not equal to the
+ first point of the contour, a line segment is automatically added.
+ */
+ void close();
+
+ enum Direction {
+ /** Direction either has not been or could not be computed */
+ kUnknown_Direction,
+ /** clockwise direction for adding closed contours */
+ kCW_Direction,
+ /** counter-clockwise direction for adding closed contours */
+ kCCW_Direction,
+ };
+
+ /**
+ * Return the opposite of the specified direction. kUnknown is its own
+ * opposite.
+ */
+ static Direction OppositeDirection(Direction dir) {
+ static const Direction gOppositeDir[] = {
+ kUnknown_Direction, kCCW_Direction, kCW_Direction
+ };
+ return gOppositeDir[dir];
+ }
+
+ /**
+ * Returns whether or not a fill type is inverted
+ *
+ * kWinding_FillType -> false
+ * kEvenOdd_FillType -> false
+ * kInverseWinding_FillType -> true
+ * kInverseEvenOdd_FillType -> true
+ */
+ static bool IsInverseFillType(FillType fill) {
+ SK_COMPILE_ASSERT(0 == kWinding_FillType, fill_type_mismatch);
+ SK_COMPILE_ASSERT(1 == kEvenOdd_FillType, fill_type_mismatch);
+ SK_COMPILE_ASSERT(2 == kInverseWinding_FillType, fill_type_mismatch);
+ SK_COMPILE_ASSERT(3 == kInverseEvenOdd_FillType, fill_type_mismatch);
+ return (fill & 2) != 0;
+ }
+
+ /**
+ * Returns the equivalent non-inverted fill type to the given fill type
+ *
+ * kWinding_FillType -> kWinding_FillType
+ * kEvenOdd_FillType -> kEvenOdd_FillType
+ * kInverseWinding_FillType -> kWinding_FillType
+ * kInverseEvenOdd_FillType -> kEvenOdd_FillType
+ */
+ static FillType ConvertToNonInverseFillType(FillType fill) {
+ SK_COMPILE_ASSERT(0 == kWinding_FillType, fill_type_mismatch);
+ SK_COMPILE_ASSERT(1 == kEvenOdd_FillType, fill_type_mismatch);
+ SK_COMPILE_ASSERT(2 == kInverseWinding_FillType, fill_type_mismatch);
+ SK_COMPILE_ASSERT(3 == kInverseEvenOdd_FillType, fill_type_mismatch);
+ return (FillType)(fill & 1);
+ }
+
+ /**
+ * Tries to quickly compute the direction of the first non-degenerate
+ * contour. If it can be computed, return true and set dir to that
+ * direction. If it cannot be (quickly) determined, return false and ignore
+ * the dir parameter. If the direction was determined, it is cached to make
+ * subsequent calls return quickly.
+ */
+ bool cheapComputeDirection(Direction* dir) const;
+
+ /**
+ * Returns true if the path's direction can be computed via
+ * cheapComputDirection() and if that computed direction matches the
+ * specified direction. If dir is kUnknown, returns true if the direction
+ * cannot be computed.
+ */
+ bool cheapIsDirection(Direction dir) const {
+ Direction computedDir = kUnknown_Direction;
+ (void)this->cheapComputeDirection(&computedDir);
+ return computedDir == dir;
+ }
+
+ /** Returns true if the path specifies a rectangle. If so, and if isClosed is
+ not null, set isClosed to true if the path is closed. Also, if returning true
+ and direction is not null, return the rect direction. If the path does not
+ specify a rectangle, return false and ignore isClosed and direction.
+
+ @param isClosed If not null, set to true if the path is closed
+ @param direction If not null, set to the rectangle's direction
+ @return true if the path specifies a rectangle
+ */
+ bool isRect(bool* isClosed, Direction* direction) const;
+
+ /** Returns true if the path specifies a pair of nested rectangles. If so, and if
+ rect is not null, set rect[0] to the outer rectangle and rect[1] to the inner
+ rectangle. If so, and dirs is not null, set dirs[0] to the direction of
+ the outer rectangle and dirs[1] to the direction of the inner rectangle. If
+ the path does not specify a pair of nested rectangles, return
+ false and ignore rect and dirs.
+
+ @param rect If not null, returns the path as a pair of nested rectangles
+ @param dirs If not null, returns the direction of the rects
+ @return true if the path describes a pair of nested rectangles
+ */
+ bool isNestedRects(SkRect rect[2], Direction dirs[2] = NULL) const;
+
+ /**
+ * Add a closed rectangle contour to the path
+ * @param rect The rectangle to add as a closed contour to the path
+ * @param dir The direction to wind the rectangle's contour. Cannot be
+ * kUnknown_Direction.
+ */
+ void addRect(const SkRect& rect, Direction dir = kCW_Direction);
+
+ /**
+ * Add a closed rectangle contour to the path
+ *
+ * @param left The left side of a rectangle to add as a closed contour
+ * to the path
+ * @param top The top of a rectangle to add as a closed contour to the
+ * path
+ * @param right The right side of a rectangle to add as a closed contour
+ * to the path
+ * @param bottom The bottom of a rectangle to add as a closed contour to
+ * the path
+ * @param dir The direction to wind the rectangle's contour. Cannot be
+ * kUnknown_Direction.
+ */
+ void addRect(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom,
+ Direction dir = kCW_Direction);
+
+ /**
+ * Add a closed oval contour to the path
+ *
+ * @param oval The bounding oval to add as a closed contour to the path
+ * @param dir The direction to wind the oval's contour. Cannot be
+ * kUnknown_Direction.
+ */
+ void addOval(const SkRect& oval, Direction dir = kCW_Direction);
+
+ /**
+ * Add a closed circle contour to the path
+ *
+ * @param x The x-coordinate of the center of a circle to add as a
+ * closed contour to the path
+ * @param y The y-coordinate of the center of a circle to add as a
+ * closed contour to the path
+ * @param radius The radius of a circle to add as a closed contour to the
+ * path
+ * @param dir The direction to wind the circle's contour. Cannot be
+ * kUnknown_Direction.
+ */
+ void addCircle(SkScalar x, SkScalar y, SkScalar radius,
+ Direction dir = kCW_Direction);
+
+ /** Add the specified arc to the path as a new contour.
+
+ @param oval The bounds of oval used to define the size of the arc
+ @param startAngle Starting angle (in degrees) where the arc begins
+ @param sweepAngle Sweep angle (in degrees) measured clockwise
+ */
+ void addArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle);
+
+ /**
+ * Add a closed round-rectangle contour to the path
+ * @param rect The bounds of a round-rectangle to add as a closed contour
+ * @param rx The x-radius of the rounded corners on the round-rectangle
+ * @param ry The y-radius of the rounded corners on the round-rectangle
+ * @param dir The direction to wind the rectangle's contour. Cannot be
+ * kUnknown_Direction.
+ */
+ void addRoundRect(const SkRect& rect, SkScalar rx, SkScalar ry,
+ Direction dir = kCW_Direction);
+
+ /**
+ * Add a closed round-rectangle contour to the path. Each corner receives
+ * two radius values [X, Y]. The corners are ordered top-left, top-right,
+ * bottom-right, bottom-left.
+ * @param rect The bounds of a round-rectangle to add as a closed contour
+ * @param radii Array of 8 scalars, 4 [X,Y] pairs for each corner
+ * @param dir The direction to wind the rectangle's contour. Cannot be
+ * kUnknown_Direction.
+ * Note: The radii here now go through the same constraint handling as the
+ * SkRRect radii (i.e., either radii at a corner being 0 implies a
+ * sqaure corner and oversized radii are proportionally scaled down).
+ */
+ void addRoundRect(const SkRect& rect, const SkScalar radii[],
+ Direction dir = kCW_Direction);
+
+ /**
+ * Add an SkRRect contour to the path
+ * @param rrect The rounded rect to add as a closed contour
+ * @param dir The winding direction for the new contour. Cannot be
+ * kUnknown_Direction.
+ */
+ void addRRect(const SkRRect& rrect, Direction dir = kCW_Direction);
+
+ /**
+ * Add a new contour made of just lines. This is just a fast version of
+ * the following:
+ * this->moveTo(pts[0]);
+ * for (int i = 1; i < count; ++i) {
+ * this->lineTo(pts[i]);
+ * }
+ * if (close) {
+ * this->close();
+ * }
+ */
+ void addPoly(const SkPoint pts[], int count, bool close);
+
+ /** Add a copy of src to the path, offset by (dx,dy)
+ @param src The path to add as a new contour
+ @param dx The amount to translate the path in X as it is added
+ @param dx The amount to translate the path in Y as it is added
+ */
+ void addPath(const SkPath& src, SkScalar dx, SkScalar dy);
+
+ /** Add a copy of src to the path
+ */
+ void addPath(const SkPath& src) {
+ SkMatrix m;
+ m.reset();
+ this->addPath(src, m);
+ }
+
+ /** Add a copy of src to the path, transformed by matrix
+ @param src The path to add as a new contour
+ */
+ void addPath(const SkPath& src, const SkMatrix& matrix);
+
+ /**
+ * Same as addPath(), but reverses the src input
+ */
+ void reverseAddPath(const SkPath& src);
+
+ /** Offset the path by (dx,dy), returning true on success
+
+ @param dx The amount in the X direction to offset the entire path
+ @param dy The amount in the Y direction to offset the entire path
+ @param dst The translated path is written here
+ */
+ void offset(SkScalar dx, SkScalar dy, SkPath* dst) const;
+
+ /** Offset the path by (dx,dy), returning true on success
+
+ @param dx The amount in the X direction to offset the entire path
+ @param dy The amount in the Y direction to offset the entire path
+ */
+ void offset(SkScalar dx, SkScalar dy) {
+ this->offset(dx, dy, this);
+ }
+
+ /** Transform the points in this path by matrix, and write the answer into
+ dst.
+
+ @param matrix The matrix to apply to the path
+ @param dst The transformed path is written here
+ */
+ void transform(const SkMatrix& matrix, SkPath* dst) const;
+
+ /** Transform the points in this path by matrix
+
+ @param matrix The matrix to apply to the path
+ */
+ void transform(const SkMatrix& matrix) {
+ this->transform(matrix, this);
+ }
+
+ /** Return the last point on the path. If no points have been added, (0,0)
+ is returned. If there are no points, this returns false, otherwise it
+ returns true.
+
+ @param lastPt The last point on the path is returned here
+ */
+ bool getLastPt(SkPoint* lastPt) const;
+
+ /** Set the last point on the path. If no points have been added,
+ moveTo(x,y) is automatically called.
+
+ @param x The new x-coordinate for the last point
+ @param y The new y-coordinate for the last point
+ */
+ void setLastPt(SkScalar x, SkScalar y);
+
+ /** Set the last point on the path. If no points have been added, moveTo(p)
+ is automatically called.
+
+ @param p The new location for the last point
+ */
+ void setLastPt(const SkPoint& p) {
+ this->setLastPt(p.fX, p.fY);
+ }
+
+ enum SegmentMask {
+ kLine_SegmentMask = 1 << 0,
+ kQuad_SegmentMask = 1 << 1,
+ kConic_SegmentMask = 1 << 2,
+ kCubic_SegmentMask = 1 << 3,
+ };
+
+ /**
+ * Returns a mask, where each bit corresponding to a SegmentMask is
+ * set if the path contains 1 or more segments of that type.
+ * Returns 0 for an empty path (no segments).
+ */
+ uint32_t getSegmentMasks() const { return fSegmentMask; }
+
+ enum Verb {
+ kMove_Verb, //!< iter.next returns 1 point
+ kLine_Verb, //!< iter.next returns 2 points
+ kQuad_Verb, //!< iter.next returns 3 points
+ kConic_Verb, //!< iter.next returns 3 points + iter.conicWeight()
+ kCubic_Verb, //!< iter.next returns 4 points
+ kClose_Verb, //!< iter.next returns 1 point (contour's moveTo pt)
+ kDone_Verb, //!< iter.next returns 0 points
+ };
+
+ /** Iterate through all of the segments (lines, quadratics, cubics) of
+ each contours in a path.
+
+ The iterator cleans up the segments along the way, removing degenerate
+ segments and adding close verbs where necessary. When the forceClose
+ argument is provided, each contour (as defined by a new starting
+ move command) will be completed with a close verb regardless of the
+ contour's contents.
+ */
+ class SK_API Iter {
+ public:
+ Iter();
+ Iter(const SkPath&, bool forceClose);
+
+ void setPath(const SkPath&, bool forceClose);
+
+ /** Return the next verb in this iteration of the path. When all
+ segments have been visited, return kDone_Verb.
+
+ @param pts The points representing the current verb and/or segment
+ @param doConsumeDegerates If true, first scan for segments that are
+ deemed degenerate (too short) and skip those.
+ @return The verb for the current segment
+ */
+ Verb next(SkPoint pts[4], bool doConsumeDegerates = true) {
+ if (doConsumeDegerates) {
+ this->consumeDegenerateSegments();
+ }
+ return this->doNext(pts);
+ }
+
+ /**
+ * Return the weight for the current conic. Only valid if the current
+ * segment return by next() was a conic.
+ */
+ SkScalar conicWeight() const { return *fConicWeights; }
+
+ /** If next() returns kLine_Verb, then this query returns true if the
+ line was the result of a close() command (i.e. the end point is the
+ initial moveto for this contour). If next() returned a different
+ verb, this returns an undefined value.
+
+ @return If the last call to next() returned kLine_Verb, return true
+ if it was the result of an explicit close command.
+ */
+ bool isCloseLine() const { return SkToBool(fCloseLine); }
+
+ /** Returns true if the current contour is closed (has a kClose_Verb)
+ @return true if the current contour is closed (has a kClose_Verb)
+ */
+ bool isClosedContour() const;
+
+ private:
+ const SkPoint* fPts;
+ const uint8_t* fVerbs;
+ const uint8_t* fVerbStop;
+ const SkScalar* fConicWeights;
+ SkPoint fMoveTo;
+ SkPoint fLastPt;
+ SkBool8 fForceClose;
+ SkBool8 fNeedClose;
+ SkBool8 fCloseLine;
+ SkBool8 fSegmentState;
+
+ inline const SkPoint& cons_moveTo();
+ Verb autoClose(SkPoint pts[2]);
+ void consumeDegenerateSegments();
+ Verb doNext(SkPoint pts[4]);
+ };
+
+ /** Iterate through the verbs in the path, providing the associated points.
+ */
+ class SK_API RawIter {
+ public:
+ RawIter();
+ RawIter(const SkPath&);
+
+ void setPath(const SkPath&);
+
+ /** Return the next verb in this iteration of the path. When all
+ segments have been visited, return kDone_Verb.
+
+ @param pts The points representing the current verb and/or segment
+ This must not be NULL.
+ @return The verb for the current segment
+ */
+ Verb next(SkPoint pts[4]);
+
+ SkScalar conicWeight() const { return *fConicWeights; }
+
+ private:
+ const SkPoint* fPts;
+ const uint8_t* fVerbs;
+ const uint8_t* fVerbStop;
+ const SkScalar* fConicWeights;
+ SkPoint fMoveTo;
+ SkPoint fLastPt;
+ };
+
+ /**
+ * Returns true if the point { x, y } is contained by the path, taking into
+ * account the FillType.
+ */
+ bool contains(SkScalar x, SkScalar y) const;
+
+ void dump(bool forceClose, const char title[] = NULL) const;
+ void dump() const;
+
+ /**
+ * Write the region to the buffer, and return the number of bytes written.
+ * If buffer is NULL, it still returns the number of bytes.
+ */
+ uint32_t writeToMemory(void* buffer) const;
+ /**
+ * Initialized the region from the buffer, returning the number
+ * of bytes actually read.
+ */
+ uint32_t readFromMemory(const void* buffer);
+
+#ifdef SK_BUILD_FOR_ANDROID
+ uint32_t getGenerationID() const;
+ const SkPath* getSourcePath() const;
+ void setSourcePath(const SkPath* path);
+#endif
+
+ SkDEBUGCODE(void validate() const;)
+
+private:
+ enum SerializationOffsets {
+ kDirection_SerializationShift = 26, // requires 2 bits
+ kIsFinite_SerializationShift = 25, // requires 1 bit
+ kIsOval_SerializationShift = 24, // requires 1 bit
+ kConvexity_SerializationShift = 16, // requires 2 bits
+ kFillType_SerializationShift = 8, // requires 2 bits
+ kSegmentMask_SerializationShift = 0 // requires 4 bits
+ };
+
+ SkAutoTUnref<SkPathRef> fPathRef;
+
+ mutable SkRect fBounds;
+ int fLastMoveToIndex;
+ uint8_t fFillType;
+ uint8_t fSegmentMask;
+ mutable uint8_t fBoundsIsDirty;
+ mutable uint8_t fConvexity;
+ mutable uint8_t fDirection;
+ mutable SkBool8 fIsFinite; // only meaningful if bounds are valid
+ mutable SkBool8 fIsOval;
+#ifdef SK_BUILD_FOR_ANDROID
+ uint32_t fGenerationID;
+ const SkPath* fSourcePath;
+#endif
+
+ /** Resets all fields other than fPathRef to their initial 'empty' values.
+ * Assumes the caller has already emptied fPathRef.
+ * On Android increments fGenerationID without reseting it.
+ */
+ void resetFields();
+
+ /** Sets all fields other than fPathRef to the values in 'that'.
+ * Assumes the caller has already set fPathRef.
+ * Doesn't change fGenerationID or fSourcePath on Android.
+ */
+ void copyFields(const SkPath& that);
+
+ // called, if dirty, by getBounds()
+ void computeBounds() const;
+
+ friend class Iter;
+
+ friend class SkPathStroker;
+ /* Append the first contour of path, ignoring path's initial point. If no
+ moveTo() call has been made for this contour, the first point is
+ automatically set to (0,0).
+ */
+ void pathTo(const SkPath& path);
+
+ /* Append, in reverse order, the first contour of path, ignoring path's
+ last point. If no moveTo() call has been made for this contour, the
+ first point is automatically set to (0,0).
+ */
+ void reversePathTo(const SkPath&);
+
+ // called before we add points for lineTo, quadTo, cubicTo, checking to see
+ // if we need to inject a leading moveTo first
+ //
+ // SkPath path; path.lineTo(...); <--- need a leading moveTo(0, 0)
+ // SkPath path; ... path.close(); path.lineTo(...) <-- need a moveTo(previous moveTo)
+ //
+ inline void injectMoveToIfNeeded();
+
+ inline bool hasOnlyMoveTos() const;
+
+ Convexity internalGetConvexity() const;
+
+ bool isRectContour(bool allowPartial, int* currVerb, const SkPoint** pts,
+ bool* isClosed, Direction* direction) const;
+
+ friend class SkAutoPathBoundsUpdate;
+ friend class SkAutoDisableOvalCheck;
+ friend class SkAutoDisableDirectionCheck;
+ friend class SkBench_AddPathTest; // perf test pathTo/reversePathTo
+};
+
+#endif
diff --git a/core/SkPathEffect.h b/core/SkPathEffect.h
new file mode 100644
index 0000000..3b4541d
--- /dev/null
+++ b/core/SkPathEffect.h
@@ -0,0 +1,204 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkPathEffect_DEFINED
+#define SkPathEffect_DEFINED
+
+#include "SkFlattenable.h"
+#include "SkPath.h"
+#include "SkPoint.h"
+#include "SkRect.h"
+#include "SkStrokeRec.h"
+#include "SkTDArray.h"
+
+class SkPath;
+
+/** \class SkPathEffect
+
+ SkPathEffect is the base class for objects in the SkPaint that affect
+ the geometry of a drawing primitive before it is transformed by the
+ canvas' matrix and drawn.
+
+ Dashing is implemented as a subclass of SkPathEffect.
+*/
+class SK_API SkPathEffect : public SkFlattenable {
+public:
+ SK_DECLARE_INST_COUNT(SkPathEffect)
+
+ SkPathEffect() {}
+
+ /**
+ * Given a src path (input) and a stroke-rec (input and output), apply
+ * this effect to the src path, returning the new path in dst, and return
+ * true. If this effect cannot be applied, return false and ignore dst
+ * and stroke-rec.
+ *
+ * The stroke-rec specifies the initial request for stroking (if any).
+ * The effect can treat this as input only, or it can choose to change
+ * the rec as well. For example, the effect can decide to change the
+ * stroke's width or join, or the effect can change the rec from stroke
+ * to fill (or fill to stroke) in addition to returning a new (dst) path.
+ *
+ * If this method returns true, the caller will apply (as needed) the
+ * resulting stroke-rec to dst and then draw.
+ */
+ virtual bool filterPath(SkPath* dst, const SkPath& src,
+ SkStrokeRec*, const SkRect* cullR) const = 0;
+
+ /**
+ * Compute a conservative bounds for its effect, given the src bounds.
+ * The baseline implementation just assigns src to dst.
+ */
+ virtual void computeFastBounds(SkRect* dst, const SkRect& src) const;
+
+ /** \class PointData
+
+ PointData aggregates all the information needed to draw the point
+ primitives returned by an 'asPoints' call.
+ */
+ class PointData {
+ public:
+ PointData()
+ : fFlags(0)
+ , fPoints(NULL)
+ , fNumPoints(0) {
+ fSize.set(SK_Scalar1, SK_Scalar1);
+ // 'asPoints' needs to initialize/fill-in 'fClipRect' if it sets
+ // the kUseClip flag
+ };
+ ~PointData() {
+ delete [] fPoints;
+ }
+
+ // TODO: consider using passed-in flags to limit the work asPoints does.
+ // For example, a kNoPath flag could indicate don't bother generating
+ // stamped solutions.
+
+ // Currently none of these flags are supported.
+ enum PointFlags {
+ kCircles_PointFlag = 0x01, // draw points as circles (instead of rects)
+ kUsePath_PointFlag = 0x02, // draw points as stamps of the returned path
+ kUseClip_PointFlag = 0x04, // apply 'fClipRect' before drawing the points
+ };
+
+ uint32_t fFlags; // flags that impact the drawing of the points
+ SkPoint* fPoints; // the center point of each generated point
+ int fNumPoints; // number of points in fPoints
+ SkVector fSize; // the size to draw the points
+ SkRect fClipRect; // clip required to draw the points (if kUseClip is set)
+ SkPath fPath; // 'stamp' to be used at each point (if kUsePath is set)
+
+ SkPath fFirst; // If not empty, contains geometry for first point
+ SkPath fLast; // If not empty, contains geometry for last point
+ };
+
+ /**
+ * Does applying this path effect to 'src' yield a set of points? If so,
+ * optionally return the points in 'results'.
+ */
+ virtual bool asPoints(PointData* results, const SkPath& src,
+ const SkStrokeRec&, const SkMatrix&,
+ const SkRect* cullR) const;
+
+protected:
+ SkPathEffect(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {}
+
+private:
+ // illegal
+ SkPathEffect(const SkPathEffect&);
+ SkPathEffect& operator=(const SkPathEffect&);
+
+ typedef SkFlattenable INHERITED;
+};
+
+/** \class SkPairPathEffect
+
+ Common baseclass for Compose and Sum. This subclass manages two pathEffects,
+ including flattening them. It does nothing in filterPath, and is only useful
+ for managing the lifetimes of its two arguments.
+*/
+class SkPairPathEffect : public SkPathEffect {
+public:
+ SkPairPathEffect(SkPathEffect* pe0, SkPathEffect* pe1);
+ virtual ~SkPairPathEffect();
+
+protected:
+ SkPairPathEffect(SkFlattenableReadBuffer&);
+ virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
+
+ // these are visible to our subclasses
+ SkPathEffect* fPE0, *fPE1;
+
+private:
+ typedef SkPathEffect INHERITED;
+};
+
+/** \class SkComposePathEffect
+
+ This subclass of SkPathEffect composes its two arguments, to create
+ a compound pathEffect.
+*/
+class SkComposePathEffect : public SkPairPathEffect {
+public:
+ /** Construct a pathEffect whose effect is to apply first the inner pathEffect
+ and the the outer pathEffect (e.g. outer(inner(path)))
+ The reference counts for outer and inner are both incremented in the constructor,
+ and decremented in the destructor.
+ */
+ SkComposePathEffect(SkPathEffect* outer, SkPathEffect* inner)
+ : INHERITED(outer, inner) {}
+
+ virtual bool filterPath(SkPath* dst, const SkPath& src,
+ SkStrokeRec*, const SkRect*) const SK_OVERRIDE;
+
+ SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkComposePathEffect)
+
+protected:
+ SkComposePathEffect(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {}
+
+private:
+ // illegal
+ SkComposePathEffect(const SkComposePathEffect&);
+ SkComposePathEffect& operator=(const SkComposePathEffect&);
+
+ typedef SkPairPathEffect INHERITED;
+};
+
+/** \class SkSumPathEffect
+
+ This subclass of SkPathEffect applies two pathEffects, one after the other.
+ Its filterPath() returns true if either of the effects succeeded.
+*/
+class SkSumPathEffect : public SkPairPathEffect {
+public:
+ /** Construct a pathEffect whose effect is to apply two effects, in sequence.
+ (e.g. first(path) + second(path))
+ The reference counts for first and second are both incremented in the constructor,
+ and decremented in the destructor.
+ */
+ SkSumPathEffect(SkPathEffect* first, SkPathEffect* second)
+ : INHERITED(first, second) {}
+
+ virtual bool filterPath(SkPath* dst, const SkPath& src,
+ SkStrokeRec*, const SkRect*) const SK_OVERRIDE;
+
+ SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkSumPathEffect)
+
+protected:
+ SkSumPathEffect(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {}
+
+private:
+ // illegal
+ SkSumPathEffect(const SkSumPathEffect&);
+ SkSumPathEffect& operator=(const SkSumPathEffect&);
+
+ typedef SkPairPathEffect INHERITED;
+};
+
+#endif
diff --git a/core/SkPathMeasure.h b/core/SkPathMeasure.h
new file mode 100644
index 0000000..bc46b4a
--- /dev/null
+++ b/core/SkPathMeasure.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkPathMeasure_DEFINED
+#define SkPathMeasure_DEFINED
+
+#include "SkPath.h"
+#include "SkTDArray.h"
+
+class SK_API SkPathMeasure : SkNoncopyable {
+public:
+ SkPathMeasure();
+ /** Initialize the pathmeasure with the specified path. The path must remain valid
+ for the lifetime of the measure object, or until setPath() is called with
+ a different path (or null), since the measure object keeps a pointer to the
+ path object (does not copy its data).
+ */
+ SkPathMeasure(const SkPath& path, bool forceClosed);
+ ~SkPathMeasure();
+
+ /** Reset the pathmeasure with the specified path. The path must remain valid
+ for the lifetime of the measure object, or until setPath() is called with
+ a different path (or null), since the measure object keeps a pointer to the
+ path object (does not copy its data).
+ */
+ void setPath(const SkPath*, bool forceClosed);
+
+ /** Return the total length of the current contour, or 0 if no path
+ is associated (e.g. resetPath(null))
+ */
+ SkScalar getLength();
+
+ /** Pins distance to 0 <= distance <= getLength(), and then computes
+ the corresponding position and tangent.
+ Returns false if there is no path, or a zero-length path was specified, in which case
+ position and tangent are unchanged.
+ */
+ bool SK_WARN_UNUSED_RESULT getPosTan(SkScalar distance, SkPoint* position,
+ SkVector* tangent);
+
+ enum MatrixFlags {
+ kGetPosition_MatrixFlag = 0x01,
+ kGetTangent_MatrixFlag = 0x02,
+ kGetPosAndTan_MatrixFlag = kGetPosition_MatrixFlag | kGetTangent_MatrixFlag
+ };
+
+ /** Pins distance to 0 <= distance <= getLength(), and then computes
+ the corresponding matrix (by calling getPosTan).
+ Returns false if there is no path, or a zero-length path was specified, in which case
+ matrix is unchanged.
+ */
+ bool SK_WARN_UNUSED_RESULT getMatrix(SkScalar distance, SkMatrix* matrix,
+ MatrixFlags flags = kGetPosAndTan_MatrixFlag);
+
+ /** Given a start and stop distance, return in dst the intervening segment(s).
+ If the segment is zero-length, return false, else return true.
+ startD and stopD are pinned to legal values (0..getLength()). If startD <= stopD
+ then return false (and leave dst untouched).
+ Begin the segment with a moveTo if startWithMoveTo is true
+ */
+ bool getSegment(SkScalar startD, SkScalar stopD, SkPath* dst, bool startWithMoveTo);
+
+ /** Return true if the current contour is closed()
+ */
+ bool isClosed();
+
+ /** Move to the next contour in the path. Return true if one exists, or false if
+ we're done with the path.
+ */
+ bool nextContour();
+
+#ifdef SK_DEBUG
+ void dump();
+#endif
+
+private:
+ SkPath::Iter fIter;
+ const SkPath* fPath;
+ SkScalar fLength; // relative to the current contour
+ int fFirstPtIndex; // relative to the current contour
+ bool fIsClosed; // relative to the current contour
+ bool fForceClosed;
+
+ struct Segment {
+ SkScalar fDistance; // total distance up to this point
+ unsigned fPtIndex : 15; // index into the fPts array
+ unsigned fTValue : 15;
+ unsigned fType : 2;
+
+ SkScalar getScalarT() const;
+ };
+ SkTDArray<Segment> fSegments;
+ SkTDArray<SkPoint> fPts; // Points used to define the segments
+
+ static const Segment* NextSegment(const Segment*);
+
+ void buildSegments();
+ SkScalar compute_quad_segs(const SkPoint pts[3], SkScalar distance,
+ int mint, int maxt, int ptIndex);
+ SkScalar compute_cubic_segs(const SkPoint pts[3], SkScalar distance,
+ int mint, int maxt, int ptIndex);
+ const Segment* distanceToSegment(SkScalar distance, SkScalar* t);
+};
+
+#endif
diff --git a/core/SkPicture.h b/core/SkPicture.h
new file mode 100644
index 0000000..0bac3f7
--- /dev/null
+++ b/core/SkPicture.h
@@ -0,0 +1,278 @@
+
+/*
+ * Copyright 2007 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkPicture_DEFINED
+#define SkPicture_DEFINED
+
+#include "SkBitmap.h"
+#include "SkImageDecoder.h"
+#include "SkRefCnt.h"
+
+class SkBBoxHierarchy;
+class SkCanvas;
+class SkDrawPictureCallback;
+class SkData;
+class SkPicturePlayback;
+class SkPictureRecord;
+class SkStream;
+class SkWStream;
+
+struct SkPictInfo;
+
+/** \class SkPicture
+
+ The SkPicture class records the drawing commands made to a canvas, to
+ be played back at a later time.
+*/
+class SK_API SkPicture : public SkRefCnt {
+public:
+ SK_DECLARE_INST_COUNT(SkPicture)
+
+ /** The constructor prepares the picture to record.
+ @param width the width of the virtual device the picture records.
+ @param height the height of the virtual device the picture records.
+ */
+ SkPicture();
+ /** Make a copy of the contents of src. If src records more drawing after
+ this call, those elements will not appear in this picture.
+ */
+ SkPicture(const SkPicture& src);
+
+ /**
+ * Function signature defining a function that sets up an SkBitmap from encoded data. On
+ * success, the SkBitmap should have its Config, width, height, rowBytes and pixelref set.
+ * If the installed pixelref has decoded the data into pixels, then the src buffer need not be
+ * copied. If the pixelref defers the actual decode until its lockPixels() is called, then it
+ * must make a copy of the src buffer.
+ * @param src Encoded data.
+ * @param length Size of the encoded data, in bytes.
+ * @param dst SkBitmap to install the pixel ref on.
+ * @param bool Whether or not a pixel ref was successfully installed.
+ */
+ typedef bool (*InstallPixelRefProc)(const void* src, size_t length, SkBitmap* dst);
+
+ /**
+ * Recreate a picture that was serialized into a stream.
+ * @param SkStream Serialized picture data.
+ * @param proc Function pointer for installing pixelrefs on SkBitmaps representing the
+ * encoded bitmap data from the stream.
+ * @return A new SkPicture representing the serialized data, or NULL if the stream is
+ * invalid.
+ */
+ static SkPicture* CreateFromStream(SkStream*,
+ InstallPixelRefProc proc = &SkImageDecoder::DecodeMemory);
+
+ virtual ~SkPicture();
+
+ /**
+ * Swap the contents of the two pictures. Guaranteed to succeed.
+ */
+ void swap(SkPicture& other);
+
+ /**
+ * Creates a thread-safe clone of the picture that is ready for playback.
+ */
+ SkPicture* clone() const;
+
+ /**
+ * Creates multiple thread-safe clones of this picture that are ready for
+ * playback. The resulting clones are stored in the provided array of
+ * SkPictures.
+ */
+ void clone(SkPicture* pictures, int count) const;
+
+ enum RecordingFlags {
+ /* This flag specifies that when clipPath() is called, the path will
+ be faithfully recorded, but the recording canvas' current clip will
+ only see the path's bounds. This speeds up the recording process
+ without compromising the fidelity of the playback. The only side-
+ effect for recording is that calling getTotalClip() or related
+ clip-query calls will reflect the path's bounds, not the actual
+ path.
+ */
+ kUsePathBoundsForClip_RecordingFlag = 0x01,
+ /* This flag causes the picture to compute bounding boxes and build
+ up a spatial hierarchy (currently an R-Tree), plus a tree of Canvas'
+ usually stack-based clip/etc state. This requires an increase in
+ recording time (often ~2x; likely more for very complex pictures),
+ but allows us to perform much faster culling at playback time, and
+ completely avoid some unnecessary clips and other operations. This
+ is ideal for tiled rendering, or any other situation where you're
+ drawing a fraction of a large scene into a smaller viewport.
+
+ In most cases the record cost is offset by the playback improvement
+ after a frame or two of tiled rendering (and complex pictures that
+ induce the worst record times will generally get the largest
+ speedups at playback time).
+
+ Note: Currently this is not serializable, the bounding data will be
+ discarded if you serialize into a stream and then deserialize.
+ */
+ kOptimizeForClippedPlayback_RecordingFlag = 0x02,
+ /*
+ This flag disables all the picture recording optimizations (i.e.,
+ those in SkPictureRecord). It is mainly intended for testing the
+ existing optimizations (i.e., to actually have the pattern
+ appear in an .skp we have to disable the optimization). This
+ option doesn't affect the optimizations controlled by
+ 'kOptimizeForClippedPlayback_RecordingFlag'.
+ */
+ kDisableRecordOptimizations_RecordingFlag = 0x04
+ };
+
+ /** Returns the canvas that records the drawing commands.
+ @param width the base width for the picture, as if the recording
+ canvas' bitmap had this width.
+ @param height the base width for the picture, as if the recording
+ canvas' bitmap had this height.
+ @param recordFlags optional flags that control recording.
+ @return the picture canvas.
+ */
+ SkCanvas* beginRecording(int width, int height, uint32_t recordFlags = 0);
+
+ /** Returns the recording canvas if one is active, or NULL if recording is
+ not active. This does not alter the refcnt on the canvas (if present).
+ */
+ SkCanvas* getRecordingCanvas() const;
+ /** Signal that the caller is done recording. This invalidates the canvas
+ returned by beginRecording/getRecordingCanvas, and prepares the picture
+ for drawing. Note: this happens implicitly the first time the picture
+ is drawn.
+ */
+ void endRecording();
+
+ /** Replays the drawing commands on the specified canvas. This internally
+ calls endRecording() if that has not already been called.
+ @param canvas the canvas receiving the drawing commands.
+ */
+ void draw(SkCanvas* canvas, SkDrawPictureCallback* = NULL);
+
+ /** Return the width of the picture's recording canvas. This
+ value reflects what was passed to setSize(), and does not necessarily
+ reflect the bounds of what has been recorded into the picture.
+ @return the width of the picture's recording canvas
+ */
+ int width() const { return fWidth; }
+
+ /** Return the height of the picture's recording canvas. This
+ value reflects what was passed to setSize(), and does not necessarily
+ reflect the bounds of what has been recorded into the picture.
+ @return the height of the picture's recording canvas
+ */
+ int height() const { return fHeight; }
+
+ /**
+ * Function to encode an SkBitmap to an SkData. A function with this
+ * signature can be passed to serialize() and SkOrderedWriteBuffer.
+ * Returning NULL will tell the SkOrderedWriteBuffer to use
+ * SkBitmap::flatten() to store the bitmap.
+ * @param pixelRefOffset Output parameter, telling the deserializer what
+ * offset in the bm's pixelRef corresponds to the encoded data.
+ * @return SkData If non-NULL, holds encoded data representing the passed
+ * in bitmap. The caller is responsible for calling unref().
+ */
+ typedef SkData* (*EncodeBitmap)(size_t* pixelRefOffset, const SkBitmap& bm);
+
+ /**
+ * Serialize to a stream. If non NULL, encoder will be used to encode
+ * any bitmaps in the picture.
+ * encoder will never be called with a NULL pixelRefOffset.
+ */
+ void serialize(SkWStream*, EncodeBitmap encoder = NULL) const;
+
+#ifdef SK_BUILD_FOR_ANDROID
+ /** Signals that the caller is prematurely done replaying the drawing
+ commands. This can be called from a canvas virtual while the picture
+ is drawing. Has no effect if the picture is not drawing.
+ @deprecated preserving for legacy purposes
+ */
+ void abortPlayback();
+#endif
+
+protected:
+ // V2 : adds SkPixelRef's generation ID.
+ // V3 : PictInfo tag at beginning, and EOF tag at the end
+ // V4 : move SkPictInfo to be the header
+ // V5 : don't read/write FunctionPtr on cross-process (we can detect that)
+ // V6 : added serialization of SkPath's bounds (and packed its flags tighter)
+ // V7 : changed drawBitmapRect(IRect) to drawBitmapRectToRect(Rect)
+ // V8 : Add an option for encoding bitmaps
+ // V9 : Allow the reader and writer of an SKP disagree on whether to support
+ // SK_SUPPORT_HINTING_SCALE_FACTOR
+ // V10: add drawRRect, drawOval, clipRRect
+ // V11: modify how readBitmap and writeBitmap store their info.
+ // V12: add conics to SkPath, use new SkPathRef flattening
+ static const uint32_t PICTURE_VERSION = 12;
+
+ // fPlayback, fRecord, fWidth & fHeight are protected to allow derived classes to
+ // install their own SkPicturePlayback-derived players,SkPictureRecord-derived
+ // recorders and set the picture size
+ SkPicturePlayback* fPlayback;
+ SkPictureRecord* fRecord;
+ int fWidth, fHeight;
+
+ // Create a new SkPicture from an existing SkPicturePlayback. Ref count of
+ // playback is unchanged.
+ SkPicture(SkPicturePlayback*, int width, int height);
+
+ // For testing. Derived classes may instantiate an alternate
+ // SkBBoxHierarchy implementation
+ virtual SkBBoxHierarchy* createBBoxHierarchy() const;
+
+ // Return true if the SkStream represents a serialized picture, and fills out
+ // SkPictInfo. After this function returns, the SkStream is not rewound; it
+ // will be ready to be parsed to create an SkPicturePlayback.
+ // If false is returned, SkPictInfo is unmodified.
+ static bool StreamIsSKP(SkStream*, SkPictInfo*);
+private:
+ friend class SkFlatPicture;
+ friend class SkPicturePlayback;
+
+ typedef SkRefCnt INHERITED;
+};
+
+class SkAutoPictureRecord : SkNoncopyable {
+public:
+ SkAutoPictureRecord(SkPicture* pict, int width, int height,
+ uint32_t recordingFlags = 0) {
+ fPicture = pict;
+ fCanvas = pict->beginRecording(width, height, recordingFlags);
+ }
+ ~SkAutoPictureRecord() {
+ fPicture->endRecording();
+ }
+
+ /** Return the canvas to draw into for recording into the picture.
+ */
+ SkCanvas* getRecordingCanvas() const { return fCanvas; }
+
+private:
+ SkPicture* fPicture;
+ SkCanvas* fCanvas;
+};
+
+/**
+ * Subclasses of this can be passed to canvas.drawPicture. During the drawing
+ * of the picture, this callback will periodically be invoked. If its
+ * abortDrawing() returns true, then picture playback will be interrupted.
+ *
+ * The resulting drawing is undefined, as there is no guarantee how often the
+ * callback will be invoked. If the abort happens inside some level of nested
+ * calls to save(), restore will automatically be called to return the state
+ * to the same level it was before the drawPicture call was made.
+ */
+class SK_API SkDrawPictureCallback {
+public:
+ SkDrawPictureCallback() {}
+ virtual ~SkDrawPictureCallback() {}
+
+ virtual bool abortDrawing() = 0;
+};
+
+#endif
diff --git a/core/SkPixelRef.h b/core/SkPixelRef.h
new file mode 100644
index 0000000..0487e42
--- /dev/null
+++ b/core/SkPixelRef.h
@@ -0,0 +1,243 @@
+
+/*
+ * Copyright 2008 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkPixelRef_DEFINED
+#define SkPixelRef_DEFINED
+
+#include "SkBitmap.h"
+#include "SkRefCnt.h"
+#include "SkString.h"
+#include "SkFlattenable.h"
+
+#ifdef SK_DEBUG
+ /**
+ * Defining SK_IGNORE_PIXELREF_SETPRELOCKED will force all pixelref
+ * subclasses to correctly handle lock/unlock pixels. For performance
+ * reasons, simple malloc-based subclasses call setPreLocked() to skip
+ * the overhead of implementing these calls.
+ *
+ * This build-flag disables that optimization, to add in debugging our
+ * call-sites, to ensure that they correctly balance their calls of
+ * lock and unlock.
+ */
+// #define SK_IGNORE_PIXELREF_SETPRELOCKED
+#endif
+
+class SkColorTable;
+class SkData;
+struct SkIRect;
+class SkMutex;
+
+class GrTexture;
+
+/** \class SkPixelRef
+
+ This class is the smart container for pixel memory, and is used with
+ SkBitmap. A pixelref is installed into a bitmap, and then the bitmap can
+ access the actual pixel memory by calling lockPixels/unlockPixels.
+
+ This class can be shared/accessed between multiple threads.
+*/
+class SK_API SkPixelRef : public SkFlattenable {
+public:
+ SK_DECLARE_INST_COUNT(SkPixelRef)
+
+ explicit SkPixelRef(SkBaseMutex* mutex = NULL);
+
+ /** Return the pixel memory returned from lockPixels, or null if the
+ lockCount is 0.
+ */
+ void* pixels() const { return fPixels; }
+
+ /** Return the current colorTable (if any) if pixels are locked, or null.
+ */
+ SkColorTable* colorTable() const { return fColorTable; }
+
+ /**
+ * Returns true if the lockcount > 0
+ */
+ bool isLocked() const { return fLockCount > 0; }
+
+ SkDEBUGCODE(int getLockCount() const { return fLockCount; })
+
+ /** Call to access the pixel memory, which is returned. Balance with a call
+ to unlockPixels().
+ */
+ void lockPixels();
+ /** Call to balanace a previous call to lockPixels(). Returns the pixels
+ (or null) after the unlock. NOTE: lock calls can be nested, but the
+ matching number of unlock calls must be made in order to free the
+ memory (if the subclass implements caching/deferred-decoding.)
+ */
+ void unlockPixels();
+
+ /**
+ * Some bitmaps can return a copy of their pixels for lockPixels(), but
+ * that copy, if modified, will not be pushed back. These bitmaps should
+ * not be used as targets for a raster device/canvas (since all pixels
+ * modifications will be lost when unlockPixels() is called.)
+ */
+ bool lockPixelsAreWritable() const;
+
+ /** Returns a non-zero, unique value corresponding to the pixels in this
+ pixelref. Each time the pixels are changed (and notifyPixelsChanged is
+ called), a different generation ID will be returned.
+ */
+ uint32_t getGenerationID() const;
+
+ /** Call this if you have changed the contents of the pixels. This will in-
+ turn cause a different generation ID value to be returned from
+ getGenerationID().
+ */
+ void notifyPixelsChanged();
+
+ /** Returns true if this pixelref is marked as immutable, meaning that the
+ contents of its pixels will not change for the lifetime of the pixelref.
+ */
+ bool isImmutable() const { return fIsImmutable; }
+
+ /** Marks this pixelref is immutable, meaning that the contents of its
+ pixels will not change for the lifetime of the pixelref. This state can
+ be set on a pixelref, but it cannot be cleared once it is set.
+ */
+ void setImmutable();
+
+ /** Return the optional URI string associated with this pixelref. May be
+ null.
+ */
+ const char* getURI() const { return fURI.size() ? fURI.c_str() : NULL; }
+
+ /** Copy a URI string to this pixelref, or clear the URI if the uri is null
+ */
+ void setURI(const char uri[]) {
+ fURI.set(uri);
+ }
+
+ /** Copy a URI string to this pixelref
+ */
+ void setURI(const char uri[], size_t len) {
+ fURI.set(uri, len);
+ }
+
+ /** Assign a URI string to this pixelref.
+ */
+ void setURI(const SkString& uri) { fURI = uri; }
+
+ /**
+ * If the pixelRef has an encoded (i.e. compressed) representation,
+ * return a ref to its data. If the pixelRef
+ * is uncompressed or otherwise does not have this form, return NULL.
+ *
+ * If non-null is returned, the caller is responsible for calling unref()
+ * on the data when it is finished.
+ */
+ SkData* refEncodedData() {
+ return this->onRefEncodedData();
+ }
+
+ /** Are we really wrapping a texture instead of a bitmap?
+ */
+ virtual GrTexture* getTexture() { return NULL; }
+
+ bool readPixels(SkBitmap* dst, const SkIRect* subset = NULL);
+
+ /**
+ * Makes a deep copy of this PixelRef, respecting the requested config.
+ * @param config Desired config.
+ * @param subset Subset of this PixelRef to copy. Must be fully contained within the bounds of
+ * of this PixelRef.
+ * @return A new SkPixelRef, or NULL if either there is an error (e.g. the destination could
+ * not be created with the given config), or this PixelRef does not support deep
+ * copies.
+ */
+ virtual SkPixelRef* deepCopy(SkBitmap::Config config, const SkIRect* subset = NULL) {
+ return NULL;
+ }
+
+#ifdef SK_BUILD_FOR_ANDROID
+ /**
+ * Acquire a "global" ref on this object.
+ * The default implementation just calls ref(), but subclasses can override
+ * this method to implement additional behavior.
+ */
+ virtual void globalRef(void* data=NULL);
+
+ /**
+ * Release a "global" ref on this object.
+ * The default implementation just calls unref(), but subclasses can override
+ * this method to implement additional behavior.
+ */
+ virtual void globalUnref();
+#endif
+
+protected:
+ /** Called when the lockCount goes from 0 to 1. The caller will have already
+ acquire a mutex for thread safety, so this method need not do that.
+ */
+ virtual void* onLockPixels(SkColorTable**) = 0;
+ /** Called when the lock count goes from 1 to 0. The caller will have
+ already acquire a mutex for thread safety, so this method need not do
+ that.
+ */
+ virtual void onUnlockPixels() = 0;
+
+ /** Default impl returns true */
+ virtual bool onLockPixelsAreWritable() const;
+
+ /**
+ * For pixelrefs that don't have access to their raw pixels, they may be
+ * able to make a copy of them (e.g. if the pixels are on the GPU).
+ *
+ * The base class implementation returns false;
+ */
+ virtual bool onReadPixels(SkBitmap* dst, const SkIRect* subsetOrNull);
+
+ // default impl returns NULL.
+ virtual SkData* onRefEncodedData();
+
+ /** Return the mutex associated with this pixelref. This value is assigned
+ in the constructor, and cannot change during the lifetime of the object.
+ */
+ SkBaseMutex* mutex() const { return fMutex; }
+
+ // serialization
+ SkPixelRef(SkFlattenableReadBuffer&, SkBaseMutex*);
+ virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
+
+ // only call from constructor. Flags this to always be locked, removing
+ // the need to grab the mutex and call onLockPixels/onUnlockPixels.
+ // Performance tweak to avoid those calls (esp. in multi-thread use case).
+ void setPreLocked(void* pixels, SkColorTable* ctable);
+
+private:
+
+ SkBaseMutex* fMutex; // must remain in scope for the life of this object
+ void* fPixels;
+ SkColorTable* fColorTable; // we do not track ownership, subclass does
+ int fLockCount;
+
+ mutable uint32_t fGenerationID;
+
+ // SkBitmap is only a friend so that when copying, it can modify the new SkPixelRef to have the
+ // same fGenerationID as the original.
+ friend class SkBitmap;
+
+ SkString fURI;
+
+ // can go from false to true, but never from true to false
+ bool fIsImmutable;
+ // only ever set in constructor, const after that
+ bool fPreLocked;
+
+ void setMutex(SkBaseMutex* mutex);
+
+ typedef SkFlattenable INHERITED;
+};
+
+#endif
diff --git a/core/SkPoint.h b/core/SkPoint.h
new file mode 100644
index 0000000..5eca72f
--- /dev/null
+++ b/core/SkPoint.h
@@ -0,0 +1,516 @@
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkPoint_DEFINED
+#define SkPoint_DEFINED
+
+#include "SkMath.h"
+#include "SkScalar.h"
+
+/** \struct SkIPoint
+
+ SkIPoint holds two 32 bit integer coordinates
+*/
+struct SkIPoint {
+ int32_t fX, fY;
+
+ static SkIPoint Make(int32_t x, int32_t y) {
+ SkIPoint pt;
+ pt.set(x, y);
+ return pt;
+ }
+
+ int32_t x() const { return fX; }
+ int32_t y() const { return fY; }
+ void setX(int32_t x) { fX = x; }
+ void setY(int32_t y) { fY = y; }
+
+ /**
+ * Returns true iff fX and fY are both zero.
+ */
+ bool isZero() const { return (fX | fY) == 0; }
+
+ /**
+ * Set both fX and fY to zero. Same as set(0, 0)
+ */
+ void setZero() { fX = fY = 0; }
+
+ /** Set the x and y values of the point. */
+ void set(int32_t x, int32_t y) { fX = x; fY = y; }
+
+ /** Rotate the point clockwise, writing the new point into dst
+ It is legal for dst == this
+ */
+ void rotateCW(SkIPoint* dst) const;
+
+ /** Rotate the point clockwise, writing the new point back into the point
+ */
+
+ void rotateCW() { this->rotateCW(this); }
+
+ /** Rotate the point counter-clockwise, writing the new point into dst.
+ It is legal for dst == this
+ */
+ void rotateCCW(SkIPoint* dst) const;
+
+ /** Rotate the point counter-clockwise, writing the new point back into
+ the point
+ */
+ void rotateCCW() { this->rotateCCW(this); }
+
+ /** Negate the X and Y coordinates of the point.
+ */
+ void negate() { fX = -fX; fY = -fY; }
+
+ /** Return a new point whose X and Y coordinates are the negative of the
+ original point's
+ */
+ SkIPoint operator-() const {
+ SkIPoint neg;
+ neg.fX = -fX;
+ neg.fY = -fY;
+ return neg;
+ }
+
+ /** Add v's coordinates to this point's */
+ void operator+=(const SkIPoint& v) {
+ fX += v.fX;
+ fY += v.fY;
+ }
+
+ /** Subtract v's coordinates from this point's */
+ void operator-=(const SkIPoint& v) {
+ fX -= v.fX;
+ fY -= v.fY;
+ }
+
+ /** Returns true if the point's coordinates equal (x,y) */
+ bool equals(int32_t x, int32_t y) const {
+ return fX == x && fY == y;
+ }
+
+ friend bool operator==(const SkIPoint& a, const SkIPoint& b) {
+ return a.fX == b.fX && a.fY == b.fY;
+ }
+
+ friend bool operator!=(const SkIPoint& a, const SkIPoint& b) {
+ return a.fX != b.fX || a.fY != b.fY;
+ }
+
+ /** Returns a new point whose coordinates are the difference between
+ a and b (i.e. a - b)
+ */
+ friend SkIPoint operator-(const SkIPoint& a, const SkIPoint& b) {
+ SkIPoint v;
+ v.set(a.fX - b.fX, a.fY - b.fY);
+ return v;
+ }
+
+ /** Returns a new point whose coordinates are the sum of a and b (a + b)
+ */
+ friend SkIPoint operator+(const SkIPoint& a, const SkIPoint& b) {
+ SkIPoint v;
+ v.set(a.fX + b.fX, a.fY + b.fY);
+ return v;
+ }
+
+ /** Returns the dot product of a and b, treating them as 2D vectors
+ */
+ static int32_t DotProduct(const SkIPoint& a, const SkIPoint& b) {
+ return a.fX * b.fX + a.fY * b.fY;
+ }
+
+ /** Returns the cross product of a and b, treating them as 2D vectors
+ */
+ static int32_t CrossProduct(const SkIPoint& a, const SkIPoint& b) {
+ return a.fX * b.fY - a.fY * b.fX;
+ }
+};
+
+struct SK_API SkPoint {
+ SkScalar fX, fY;
+
+ static SkPoint Make(SkScalar x, SkScalar y) {
+ SkPoint pt;
+ pt.set(x, y);
+ return pt;
+ }
+
+ SkScalar x() const { return fX; }
+ SkScalar y() const { return fY; }
+
+ /**
+ * Returns true iff fX and fY are both zero.
+ */
+ bool isZero() const { return (0 == fX) & (0 == fY); }
+
+ /** Set the point's X and Y coordinates */
+ void set(SkScalar x, SkScalar y) { fX = x; fY = y; }
+
+ /** Set the point's X and Y coordinates by automatically promoting (x,y) to
+ SkScalar values.
+ */
+ void iset(int32_t x, int32_t y) {
+ fX = SkIntToScalar(x);
+ fY = SkIntToScalar(y);
+ }
+
+ /** Set the point's X and Y coordinates by automatically promoting p's
+ coordinates to SkScalar values.
+ */
+ void iset(const SkIPoint& p) {
+ fX = SkIntToScalar(p.fX);
+ fY = SkIntToScalar(p.fY);
+ }
+
+ void setAbs(const SkPoint& pt) {
+ fX = SkScalarAbs(pt.fX);
+ fY = SkScalarAbs(pt.fY);
+ }
+
+ // counter-clockwise fan
+ void setIRectFan(int l, int t, int r, int b) {
+ SkPoint* v = this;
+ v[0].set(SkIntToScalar(l), SkIntToScalar(t));
+ v[1].set(SkIntToScalar(l), SkIntToScalar(b));
+ v[2].set(SkIntToScalar(r), SkIntToScalar(b));
+ v[3].set(SkIntToScalar(r), SkIntToScalar(t));
+ }
+ void setIRectFan(int l, int t, int r, int b, size_t stride);
+
+ // counter-clockwise fan
+ void setRectFan(SkScalar l, SkScalar t, SkScalar r, SkScalar b) {
+ SkPoint* v = this;
+ v[0].set(l, t);
+ v[1].set(l, b);
+ v[2].set(r, b);
+ v[3].set(r, t);
+ }
+ void setRectFan(SkScalar l, SkScalar t, SkScalar r, SkScalar b, size_t stride);
+
+ static void Offset(SkPoint points[], int count, const SkPoint& offset) {
+ Offset(points, count, offset.fX, offset.fY);
+ }
+
+ static void Offset(SkPoint points[], int count, SkScalar dx, SkScalar dy) {
+ for (int i = 0; i < count; ++i) {
+ points[i].offset(dx, dy);
+ }
+ }
+
+ void offset(SkScalar dx, SkScalar dy) {
+ fX += dx;
+ fY += dy;
+ }
+
+ /** Return the euclidian distance from (0,0) to the point
+ */
+ SkScalar length() const { return SkPoint::Length(fX, fY); }
+ SkScalar distanceToOrigin() const { return this->length(); }
+
+ /**
+ * Return true if the computed length of the vector is >= the internal
+ * tolerance (used to avoid dividing by tiny values).
+ */
+ static bool CanNormalize(SkScalar dx, SkScalar dy)
+#ifdef SK_SCALAR_IS_FLOAT
+ // Simple enough (and performance critical sometimes) so we inline it.
+ { return (dx*dx + dy*dy) > (SK_ScalarNearlyZero * SK_ScalarNearlyZero); }
+#else
+ ;
+#endif
+
+ bool canNormalize() const {
+ return CanNormalize(fX, fY);
+ }
+
+ /** Set the point (vector) to be unit-length in the same direction as it
+ already points. If the point has a degenerate length (i.e. nearly 0)
+ then return false and do nothing; otherwise return true.
+ */
+ bool normalize();
+
+ /** Set the point (vector) to be unit-length in the same direction as the
+ x,y params. If the vector (x,y) has a degenerate length (i.e. nearly 0)
+ then return false and do nothing, otherwise return true.
+ */
+ bool setNormalize(SkScalar x, SkScalar y);
+
+ /** Scale the point (vector) to have the specified length, and return that
+ length. If the original length is degenerately small (nearly zero),
+ do nothing and return false, otherwise return true.
+ */
+ bool setLength(SkScalar length);
+
+ /** Set the point (vector) to have the specified length in the same
+ direction as (x,y). If the vector (x,y) has a degenerate length
+ (i.e. nearly 0) then return false and do nothing, otherwise return true.
+ */
+ bool setLength(SkScalar x, SkScalar y, SkScalar length);
+
+ /** Scale the point's coordinates by scale, writing the answer into dst.
+ It is legal for dst == this.
+ */
+ void scale(SkScalar scale, SkPoint* dst) const;
+
+ /** Scale the point's coordinates by scale, writing the answer back into
+ the point.
+ */
+ void scale(SkScalar value) { this->scale(value, this); }
+
+ /** Rotate the point clockwise by 90 degrees, writing the answer into dst.
+ It is legal for dst == this.
+ */
+ void rotateCW(SkPoint* dst) const;
+
+ /** Rotate the point clockwise by 90 degrees, writing the answer back into
+ the point.
+ */
+ void rotateCW() { this->rotateCW(this); }
+
+ /** Rotate the point counter-clockwise by 90 degrees, writing the answer
+ into dst. It is legal for dst == this.
+ */
+ void rotateCCW(SkPoint* dst) const;
+
+ /** Rotate the point counter-clockwise by 90 degrees, writing the answer
+ back into the point.
+ */
+ void rotateCCW() { this->rotateCCW(this); }
+
+ /** Negate the point's coordinates
+ */
+ void negate() {
+ fX = -fX;
+ fY = -fY;
+ }
+
+ /** Returns a new point whose coordinates are the negative of the point's
+ */
+ SkPoint operator-() const {
+ SkPoint neg;
+ neg.fX = -fX;
+ neg.fY = -fY;
+ return neg;
+ }
+
+ /** Add v's coordinates to the point's
+ */
+ void operator+=(const SkPoint& v) {
+ fX += v.fX;
+ fY += v.fY;
+ }
+
+ /** Subtract v's coordinates from the point's
+ */
+ void operator-=(const SkPoint& v) {
+ fX -= v.fX;
+ fY -= v.fY;
+ }
+
+ /**
+ * Returns true if both X and Y are finite (not infinity or NaN)
+ */
+ bool isFinite() const {
+#ifdef SK_SCALAR_IS_FLOAT
+ SkScalar accum = 0;
+ accum *= fX;
+ accum *= fY;
+
+ // accum is either NaN or it is finite (zero).
+ SkASSERT(0 == accum || !(accum == accum));
+
+ // value==value will be true iff value is not NaN
+ // TODO: is it faster to say !accum or accum==accum?
+ return accum == accum;
+#else
+ // use bit-or for speed, since we don't care about short-circuting the
+ // tests, and we expect the common case will be that we need to check all.
+ int isNaN = (SK_FixedNaN == fX) | (SK_FixedNaN == fX));
+ return !isNaN;
+#endif
+ }
+
+ /**
+ * Returns true if the point's coordinates equal (x,y)
+ */
+ bool equals(SkScalar x, SkScalar y) const {
+ return fX == x && fY == y;
+ }
+
+ friend bool operator==(const SkPoint& a, const SkPoint& b) {
+ return a.fX == b.fX && a.fY == b.fY;
+ }
+
+ friend bool operator!=(const SkPoint& a, const SkPoint& b) {
+ return a.fX != b.fX || a.fY != b.fY;
+ }
+
+ /** Return true if this point and the given point are far enough apart
+ such that a vector between them would be non-degenerate.
+
+ WARNING: Unlike the deprecated version of equalsWithinTolerance(),
+ this method does not use componentwise comparison. Instead, it
+ uses a comparison designed to match judgments elsewhere regarding
+ degeneracy ("points A and B are so close that the vector between them
+ is essentially zero").
+ */
+ bool equalsWithinTolerance(const SkPoint& p) const {
+ return !CanNormalize(fX - p.fX, fY - p.fY);
+ }
+
+ /** DEPRECATED: Return true if this and the given point are componentwise
+ within tolerance "tol".
+
+ WARNING: There is no guarantee that the result will reflect judgments
+ elsewhere regarding degeneracy ("points A and B are so close that the
+ vector between them is essentially zero").
+ */
+ bool equalsWithinTolerance(const SkPoint& p, SkScalar tol) const {
+ return SkScalarNearlyZero(fX - p.fX, tol)
+ && SkScalarNearlyZero(fY - p.fY, tol);
+ }
+
+ /** Returns a new point whose coordinates are the difference between
+ a's and b's (a - b)
+ */
+ friend SkPoint operator-(const SkPoint& a, const SkPoint& b) {
+ SkPoint v;
+ v.set(a.fX - b.fX, a.fY - b.fY);
+ return v;
+ }
+
+ /** Returns a new point whose coordinates are the sum of a's and b's (a + b)
+ */
+ friend SkPoint operator+(const SkPoint& a, const SkPoint& b) {
+ SkPoint v;
+ v.set(a.fX + b.fX, a.fY + b.fY);
+ return v;
+ }
+
+ /** Returns the euclidian distance from (0,0) to (x,y)
+ */
+ static SkScalar Length(SkScalar x, SkScalar y);
+
+ /** Normalize pt, returning its previous length. If the prev length is too
+ small (degenerate), return 0 and leave pt unchanged. This uses the same
+ tolerance as CanNormalize.
+
+ Note that this method may be significantly more expensive than
+ the non-static normalize(), because it has to return the previous length
+ of the point. If you don't need the previous length, call the
+ non-static normalize() method instead.
+ */
+ static SkScalar Normalize(SkPoint* pt);
+
+ /** Returns the euclidian distance between a and b
+ */
+ static SkScalar Distance(const SkPoint& a, const SkPoint& b) {
+ return Length(a.fX - b.fX, a.fY - b.fY);
+ }
+
+ /** Returns the dot product of a and b, treating them as 2D vectors
+ */
+ static SkScalar DotProduct(const SkPoint& a, const SkPoint& b) {
+ return SkScalarMul(a.fX, b.fX) + SkScalarMul(a.fY, b.fY);
+ }
+
+ /** Returns the cross product of a and b, treating them as 2D vectors
+ */
+ static SkScalar CrossProduct(const SkPoint& a, const SkPoint& b) {
+ return SkScalarMul(a.fX, b.fY) - SkScalarMul(a.fY, b.fX);
+ }
+
+ SkScalar cross(const SkPoint& vec) const {
+ return CrossProduct(*this, vec);
+ }
+
+ SkScalar dot(const SkPoint& vec) const {
+ return DotProduct(*this, vec);
+ }
+
+ SkScalar lengthSqd() const {
+ return DotProduct(*this, *this);
+ }
+
+ SkScalar distanceToSqd(const SkPoint& pt) const {
+ SkScalar dx = fX - pt.fX;
+ SkScalar dy = fY - pt.fY;
+ return SkScalarMul(dx, dx) + SkScalarMul(dy, dy);
+ }
+
+ /**
+ * The side of a point relative to a line. If the line is from a to b then
+ * the values are consistent with the sign of (b-a) cross (pt-a)
+ */
+ enum Side {
+ kLeft_Side = -1,
+ kOn_Side = 0,
+ kRight_Side = 1
+ };
+
+ /**
+ * Returns the squared distance to the infinite line between two pts. Also
+ * optionally returns the side of the line that the pt falls on (looking
+ * along line from a to b)
+ */
+ SkScalar distanceToLineBetweenSqd(const SkPoint& a,
+ const SkPoint& b,
+ Side* side = NULL) const;
+
+ /**
+ * Returns the distance to the infinite line between two pts. Also
+ * optionally returns the side of the line that the pt falls on (looking
+ * along the line from a to b)
+ */
+ SkScalar distanceToLineBetween(const SkPoint& a,
+ const SkPoint& b,
+ Side* side = NULL) const {
+ return SkScalarSqrt(this->distanceToLineBetweenSqd(a, b, side));
+ }
+
+ /**
+ * Returns the squared distance to the line segment between pts a and b
+ */
+ SkScalar distanceToLineSegmentBetweenSqd(const SkPoint& a,
+ const SkPoint& b) const;
+
+ /**
+ * Returns the distance to the line segment between pts a and b.
+ */
+ SkScalar distanceToLineSegmentBetween(const SkPoint& a,
+ const SkPoint& b) const {
+ return SkScalarSqrt(this->distanceToLineSegmentBetweenSqd(a, b));
+ }
+
+ /**
+ * Make this vector be orthogonal to vec. Looking down vec the
+ * new vector will point in direction indicated by side (which
+ * must be kLeft_Side or kRight_Side).
+ */
+ void setOrthog(const SkPoint& vec, Side side = kLeft_Side) {
+ // vec could be this
+ SkScalar tmp = vec.fX;
+ if (kRight_Side == side) {
+ fX = -vec.fY;
+ fY = tmp;
+ } else {
+ SkASSERT(kLeft_Side == side);
+ fX = vec.fY;
+ fY = -tmp;
+ }
+ }
+
+ /**
+ * cast-safe way to treat the point as an array of (2) SkScalars.
+ */
+ const SkScalar* asScalars() const { return &fX; }
+};
+
+typedef SkPoint SkVector;
+
+#endif
diff --git a/core/SkPostConfig.h b/core/SkPostConfig.h
new file mode 100644
index 0000000..4a819d3
--- /dev/null
+++ b/core/SkPostConfig.h
@@ -0,0 +1,393 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkPostConfig_DEFINED
+#define SkPostConfig_DEFINED
+
+#if defined(SK_BUILD_FOR_WIN32) || defined(SK_BUILD_FOR_WINCE)
+ #define SK_BUILD_FOR_WIN
+#endif
+
+#if defined(SK_DEBUG) && defined(SK_RELEASE)
+ #error "cannot define both SK_DEBUG and SK_RELEASE"
+#elif !defined(SK_DEBUG) && !defined(SK_RELEASE)
+ #error "must define either SK_DEBUG or SK_RELEASE"
+#endif
+
+#if defined SK_SUPPORT_UNITTEST && !defined(SK_DEBUG)
+ #error "can't have unittests without debug"
+#endif
+
+#if defined(SK_SCALAR_IS_FIXED) && defined(SK_SCALAR_IS_FLOAT)
+ #error "cannot define both SK_SCALAR_IS_FIXED and SK_SCALAR_IS_FLOAT"
+#elif !defined(SK_SCALAR_IS_FIXED) && !defined(SK_SCALAR_IS_FLOAT)
+ #define SK_SCALAR_IS_FLOAT
+#endif
+
+#if defined(SK_MSCALAR_IS_DOUBLE) && defined(SK_MSCALAR_IS_FLOAT)
+ #error "cannot define both SK_MSCALAR_IS_DOUBLE and SK_MSCALAR_IS_FLOAT"
+#elif !defined(SK_MSCALAR_IS_DOUBLE) && !defined(SK_MSCALAR_IS_FLOAT)
+ // default is double, as that is faster given our impl uses doubles
+ // for intermediate calculations.
+ #define SK_MSCALAR_IS_DOUBLE
+#endif
+
+#if defined(SK_CPU_LENDIAN) && defined(SK_CPU_BENDIAN)
+ #error "cannot define both SK_CPU_LENDIAN and SK_CPU_BENDIAN"
+#elif !defined(SK_CPU_LENDIAN) && !defined(SK_CPU_BENDIAN)
+ #error "must define either SK_CPU_LENDIAN or SK_CPU_BENDIAN"
+#endif
+
+// ensure the port has defined all of these, or none of them
+#ifdef SK_A32_SHIFT
+ #if !defined(SK_R32_SHIFT) || !defined(SK_G32_SHIFT) || !defined(SK_B32_SHIFT)
+ #error "all or none of the 32bit SHIFT amounts must be defined"
+ #endif
+#else
+ #if defined(SK_R32_SHIFT) || defined(SK_G32_SHIFT) || defined(SK_B32_SHIFT)
+ #error "all or none of the 32bit SHIFT amounts must be defined"
+ #endif
+#endif
+
+#if !defined(SK_HAS_COMPILER_FEATURE)
+ #if defined(__has_feature)
+ #define SK_HAS_COMPILER_FEATURE(x) __has_feature(x)
+ #else
+ #define SK_HAS_COMPILER_FEATURE(x) 0
+ #endif
+#endif
+
+#if !defined(SK_ATTRIBUTE)
+ #if defined(__clang__) || defined(__GNUC__)
+ #define SK_ATTRIBUTE(attr) __attribute__((attr))
+ #else
+ #define SK_ATTRIBUTE(attr)
+ #endif
+#endif
+
+#if !defined(SK_SUPPORT_GPU)
+ #define SK_SUPPORT_GPU 1
+#endif
+
+/**
+ * The clang static analyzer likes to know that when the program is not
+ * expected to continue (crash, assertion failure, etc). It will notice that
+ * some combination of parameters lead to a function call that does not return.
+ * It can then make appropriate assumptions about the parameters in code
+ * executed only if the non-returning function was *not* called.
+ */
+#if !defined(SkNO_RETURN_HINT)
+ #if SK_HAS_COMPILER_FEATURE(attribute_analyzer_noreturn)
+ static inline void SkNO_RETURN_HINT() __attribute__((analyzer_noreturn));
+ static inline void SkNO_RETURN_HINT() {}
+ #else
+ #define SkNO_RETURN_HINT() do {} while (false)
+ #endif
+#endif
+
+#if defined(SK_ZLIB_INCLUDE) && defined(SK_SYSTEM_ZLIB)
+ #error "cannot define both SK_ZLIB_INCLUDE and SK_SYSTEM_ZLIB"
+#elif defined(SK_ZLIB_INCLUDE) || defined(SK_SYSTEM_ZLIB)
+ #define SK_HAS_ZLIB
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef SkNEW
+ #define SkNEW(type_name) (new type_name)
+ #define SkNEW_ARGS(type_name, args) (new type_name args)
+ #define SkNEW_ARRAY(type_name, count) (new type_name[(count)])
+ #define SkNEW_PLACEMENT(buf, type_name) (new (buf) type_name)
+ #define SkNEW_PLACEMENT_ARGS(buf, type_name, args) \
+ (new (buf) type_name args)
+ #define SkDELETE(obj) (delete (obj))
+ #define SkDELETE_ARRAY(array) (delete[] (array))
+#endif
+
+#ifndef SK_CRASH
+#if 1 // set to 0 for infinite loop, which can help connecting gdb
+ #define SK_CRASH() do { SkNO_RETURN_HINT(); *(int *)(uintptr_t)0xbbadbeef = 0; } while (false)
+#else
+ #define SK_CRASH() do { SkNO_RETURN_HINT(); } while (true)
+#endif
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+
+// SK_ENABLE_INST_COUNT defaults to 1 in DEBUG and 0 in RELEASE
+#ifndef SK_ENABLE_INST_COUNT
+ #ifdef SK_DEBUG
+ // FIXME: fails if multiple threads run at once (see skbug.com/1219 )
+ #define SK_ENABLE_INST_COUNT 0
+ #else
+ #define SK_ENABLE_INST_COUNT 0
+ #endif
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+
+#if defined(SK_SOFTWARE_FLOAT) && defined(SK_SCALAR_IS_FLOAT)
+ // if this is defined, we convert floats to 2scompliment ints for compares
+ #ifndef SK_SCALAR_SLOW_COMPARES
+ #define SK_SCALAR_SLOW_COMPARES
+ #endif
+ #ifndef SK_USE_FLOATBITS
+ #define SK_USE_FLOATBITS
+ #endif
+#endif
+
+#ifdef SK_BUILD_FOR_WIN
+ // we want lean_and_mean when we include windows.h
+ #ifndef WIN32_LEAN_AND_MEAN
+ #define WIN32_LEAN_AND_MEAN
+ #define WIN32_IS_MEAN_WAS_LOCALLY_DEFINED
+ #endif
+ #ifndef NOMINMAX
+ #define NOMINMAX
+ #define NOMINMAX_WAS_LOCALLY_DEFINED
+ #endif
+
+ #include <windows.h>
+
+ #ifdef WIN32_IS_MEAN_WAS_LOCALLY_DEFINED
+ #undef WIN32_IS_MEAN_WAS_LOCALLY_DEFINED
+ #undef WIN32_LEAN_AND_MEAN
+ #endif
+
+ #ifdef NOMINMAX_WAS_LOCALLY_DEFINED
+ #undef NOMINMAX_WAS_LOCALLY_DEFINED
+ #undef NOMINMAX
+ #endif
+
+ #ifndef SK_DEBUGBREAK
+ #define SK_DEBUGBREAK(cond) do { if (!(cond)) { SkNO_RETURN_HINT(); __debugbreak(); }} while (false)
+ #endif
+
+ #ifndef SK_A32_SHIFT
+ #define SK_A32_SHIFT 24
+ #define SK_R32_SHIFT 16
+ #define SK_G32_SHIFT 8
+ #define SK_B32_SHIFT 0
+ #endif
+
+#else
+ #ifdef SK_DEBUG
+ #include <stdio.h>
+ #ifndef SK_DEBUGBREAK
+ #define SK_DEBUGBREAK(cond) do { if (cond) break; \
+ SkDebugf("%s:%d: failed assertion \"%s\"\n", \
+ __FILE__, __LINE__, #cond); SK_CRASH(); } while (false)
+ #endif
+ #endif
+#endif
+
+/*
+ * We check to see if the SHIFT value has already been defined.
+ * if not, we define it ourself to some default values. We default to OpenGL
+ * order (in memory: r,g,b,a)
+ */
+#ifndef SK_A32_SHIFT
+ #ifdef SK_CPU_BENDIAN
+ #define SK_R32_SHIFT 24
+ #define SK_G32_SHIFT 16
+ #define SK_B32_SHIFT 8
+ #define SK_A32_SHIFT 0
+ #else
+ #define SK_R32_SHIFT 0
+ #define SK_G32_SHIFT 8
+ #define SK_B32_SHIFT 16
+ #define SK_A32_SHIFT 24
+ #endif
+#endif
+
+/**
+ * SK_PMCOLOR_BYTE_ORDER can be used to query the byte order of SkPMColor at compile time. The
+ * relationship between the byte order and shift values depends on machine endianness. If the shift
+ * order is R=0, G=8, B=16, A=24 then ((char*)&pmcolor)[0] will produce the R channel on a little
+ * endian machine and the A channel on a big endian machine. Thus, given those shifts values,
+ * SK_PMCOLOR_BYTE_ORDER(R,G,B,A) will be true on a little endian machine and
+ * SK_PMCOLOR_BYTE_ORDER(A,B,G,R) will be true on a big endian machine.
+ */
+#ifdef SK_CPU_BENDIAN
+ #define SK_PMCOLOR_BYTE_ORDER(C0, C1, C2, C3) \
+ (SK_ ## C3 ## 32_SHIFT == 0 && \
+ SK_ ## C2 ## 32_SHIFT == 8 && \
+ SK_ ## C1 ## 32_SHIFT == 16 && \
+ SK_ ## C0 ## 32_SHIFT == 24)
+#else
+ #define SK_PMCOLOR_BYTE_ORDER(C0, C1, C2, C3) \
+ (SK_ ## C0 ## 32_SHIFT == 0 && \
+ SK_ ## C1 ## 32_SHIFT == 8 && \
+ SK_ ## C2 ## 32_SHIFT == 16 && \
+ SK_ ## C3 ## 32_SHIFT == 24)
+#endif
+
+// stdlib macros
+
+#if 0
+#if !defined(strlen) && defined(SK_DEBUG)
+ extern size_t sk_strlen(const char*);
+ #define strlen(s) sk_strlen(s)
+#endif
+#ifndef sk_strcpy
+ #define sk_strcpy(dst, src) strcpy(dst, src)
+#endif
+#ifndef sk_strchr
+ #define sk_strchr(s, c) strchr(s, c)
+#endif
+#ifndef sk_strrchr
+ #define sk_strrchr(s, c) strrchr(s, c)
+#endif
+#ifndef sk_strcmp
+ #define sk_strcmp(s, t) strcmp(s, t)
+#endif
+#ifndef sk_strncmp
+ #define sk_strncmp(s, t, n) strncmp(s, t, n)
+#endif
+#ifndef sk_memcpy
+ #define sk_memcpy(dst, src, n) memcpy(dst, src, n)
+#endif
+#ifndef memmove
+ #define memmove(dst, src, n) memmove(dst, src, n)
+#endif
+#ifndef sk_memset
+ #define sk_memset(dst, val, n) memset(dst, val, n)
+#endif
+#ifndef sk_memcmp
+ #define sk_memcmp(s, t, n) memcmp(s, t, n)
+#endif
+
+#define sk_strequal(s, t) (!sk_strcmp(s, t))
+#define sk_strnequal(s, t, n) (!sk_strncmp(s, t, n))
+#endif
+
+//////////////////////////////////////////////////////////////////////
+
+#if defined(SK_BUILD_FOR_WIN32) || defined(SK_BUILD_FOR_MAC)
+ #ifndef SkLONGLONG
+ #ifdef SK_BUILD_FOR_WIN32
+ #define SkLONGLONG __int64
+ #else
+ #define SkLONGLONG long long
+ #endif
+ #endif
+#endif
+
+//////////////////////////////////////////////////////////////////////////////////////////////
+#ifndef SK_BUILD_FOR_WINCE
+#include <string.h>
+#include <stdlib.h>
+#else
+#define _CMNINTRIN_DECLARE_ONLY
+#include "cmnintrin.h"
+#endif
+
+#if defined SK_DEBUG && defined SK_BUILD_FOR_WIN32
+//#define _CRTDBG_MAP_ALLOC
+#ifdef free
+#undef free
+#endif
+#include <crtdbg.h>
+#undef free
+
+#ifdef SK_DEBUGx
+#if defined(SK_SIMULATE_FAILED_MALLOC) && defined(__cplusplus)
+ void * operator new(
+ size_t cb,
+ int nBlockUse,
+ const char * szFileName,
+ int nLine,
+ int foo
+ );
+ void * operator new[](
+ size_t cb,
+ int nBlockUse,
+ const char * szFileName,
+ int nLine,
+ int foo
+ );
+ void operator delete(
+ void *pUserData,
+ int, const char*, int, int
+ );
+ void operator delete(
+ void *pUserData
+ );
+ void operator delete[]( void * p );
+ #define DEBUG_CLIENTBLOCK new( _CLIENT_BLOCK, __FILE__, __LINE__, 0)
+#else
+ #define DEBUG_CLIENTBLOCK new( _CLIENT_BLOCK, __FILE__, __LINE__)
+#endif
+ #define new DEBUG_CLIENTBLOCK
+#else
+#define DEBUG_CLIENTBLOCK
+#endif // _DEBUG
+
+
+#endif
+
+#endif
+
+//////////////////////////////////////////////////////////////////////
+
+#ifndef SK_OVERRIDE
+ #if defined(_MSC_VER)
+ #define SK_OVERRIDE override
+ #elif defined(__clang__)
+ // Clang defaults to C++03 and warns about using override. Squelch that. Intentionally no
+ // push/pop here so all users of SK_OVERRIDE ignore the warning too. This is like passing
+ // -Wno-c++11-extensions, except that GCC won't die (because it won't see this pragma).
+ #pragma clang diagnostic ignored "-Wc++11-extensions"
+
+ #if __has_feature(cxx_override_control)
+ // Some documentation suggests we should be using __attribute__((override)),
+ // but it doesn't work.
+ #define SK_OVERRIDE override
+ #elif defined(__has_extension)
+ #if __has_extension(cxx_override_control)
+ #define SK_OVERRIDE override
+ #endif
+ #endif
+ #endif
+ #ifndef SK_OVERRIDE
+ #define SK_OVERRIDE
+ #endif
+#endif
+
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(SK_UNUSED)
+ #define SK_UNUSED SK_ATTRIBUTE(unused)
+#endif
+
+//////////////////////////////////////////////////////////////////////
+
+#ifndef SK_PRINTF_LIKE
+#if defined(__clang__) || defined(__GNUC__)
+#define SK_PRINTF_LIKE(A, B) __attribute__((format(printf, (A), (B))))
+#else
+#define SK_PRINTF_LIKE(A, B)
+#endif
+#endif
+
+//////////////////////////////////////////////////////////////////////
+
+#ifndef SK_SIZE_T_SPECIFIER
+#if defined(_MSC_VER)
+#define SK_SIZE_T_SPECIFIER "%Iu"
+#else
+#define SK_SIZE_T_SPECIFIER "%zu"
+#endif
+#endif
+
+//////////////////////////////////////////////////////////////////////
+
+#ifndef SK_ALLOW_STATIC_GLOBAL_INITIALIZERS
+#define SK_ALLOW_STATIC_GLOBAL_INITIALIZERS 1
+#endif
diff --git a/core/SkPreConfig.h b/core/SkPreConfig.h
new file mode 100644
index 0000000..fbaa69e
--- /dev/null
+++ b/core/SkPreConfig.h
@@ -0,0 +1,261 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkPreConfig_DEFINED
+#define SkPreConfig_DEFINED
+
+#ifdef WEBKIT_VERSION_MIN_REQUIRED
+ #include "config.h"
+#endif
+
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(SK_BUILD_FOR_ANDROID) && !defined(SK_BUILD_FOR_IOS) && !defined(SK_BUILD_FOR_PALM) && !defined(SK_BUILD_FOR_WINCE) && !defined(SK_BUILD_FOR_WIN32) && !defined(SK_BUILD_FOR_UNIX) && !defined(SK_BUILD_FOR_MAC) && !defined(SK_BUILD_FOR_SDL) && !defined(SK_BUILD_FOR_BREW) && !defined(SK_BUILD_FOR_NACL)
+
+ #ifdef __APPLE__
+ #include "TargetConditionals.h"
+ #endif
+
+ #if defined(PALMOS_SDK_VERSION)
+ #define SK_BUILD_FOR_PALM
+ #elif defined(UNDER_CE)
+ #define SK_BUILD_FOR_WINCE
+ #elif defined(WIN32)
+ #define SK_BUILD_FOR_WIN32
+ #elif defined(__SYMBIAN32__)
+ #define SK_BUILD_FOR_WIN32
+ #elif defined(ANDROID)
+ #define SK_BUILD_FOR_ANDROID
+ #elif defined(linux) || defined(__FreeBSD__) || defined(__OpenBSD__) || \
+ defined(__sun) || defined(__NetBSD__) || defined(__DragonFly__) || \
+ defined(__GLIBC__) || defined(__GNU__)
+ #define SK_BUILD_FOR_UNIX
+ #elif TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR
+ #define SK_BUILD_FOR_IOS
+ #else
+ #define SK_BUILD_FOR_MAC
+ #endif
+
+#endif
+
+/* Even if the user only defined the framework variant we still need to build
+ * the default (NDK-compliant) Android code. Therefore, when attempting to
+ * include/exclude something from the framework variant check first that we are
+ * building for Android then check the status of the framework define.
+ */
+#if defined(SK_BUILD_FOR_ANDROID_FRAMEWORK) && !defined(SK_BUILD_FOR_ANDROID)
+ #define SK_BUILD_FOR_ANDROID
+#endif
+
+
+// USE_CHROMIUM_SKIA is defined when building Skia for the Chromium
+// browser.
+#if defined(USE_CHROMIUM_SKIA)
+ #define SK_BUILD_FOR_CHROMIUM
+#endif
+
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(SK_DEBUG) && !defined(SK_RELEASE)
+ #ifdef NDEBUG
+ #define SK_RELEASE
+ #else
+ #define SK_DEBUG
+ #endif
+#endif
+
+#ifdef SK_BUILD_FOR_WIN32
+ #if !defined(SK_RESTRICT)
+ #define SK_RESTRICT __restrict
+ #endif
+ #if !defined(SK_WARN_UNUSED_RESULT)
+ #define SK_WARN_UNUSED_RESULT
+ #endif
+ #include "sk_stdint.h"
+#endif
+
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(SK_RESTRICT)
+ #define SK_RESTRICT __restrict__
+#endif
+
+#if !defined(SK_WARN_UNUSED_RESULT)
+ #define SK_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
+#endif
+
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(SK_SCALAR_IS_FLOAT) && !defined(SK_SCALAR_IS_FIXED)
+ #define SK_SCALAR_IS_FLOAT
+#endif
+
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(SK_CPU_BENDIAN) && !defined(SK_CPU_LENDIAN)
+ #if defined (__ppc__) || defined(__PPC__) || defined(__ppc64__) \
+ || defined(__PPC64__)
+ #define SK_CPU_BENDIAN
+ #else
+ #define SK_CPU_LENDIAN
+ #endif
+#endif
+
+//////////////////////////////////////////////////////////////////////
+
+#ifndef SK_MMAP_SUPPORT
+ #ifdef SK_BUILD_FOR_WIN32
+ // by default, if we're windows, we assume we don't have mmap
+ #define SK_MMAP_SUPPORT 0
+ #else
+ #define SK_MMAP_SUPPORT 1
+ #endif
+#endif
+
+//////////////////////////////////////////////////////////////////////
+
+/**
+ * SK_CPU_SSE_LEVEL
+ *
+ * If defined, SK_CPU_SSE_LEVEL should be set to the highest supported level.
+ * On non-intel CPU this should be undefined.
+ */
+
+#define SK_CPU_SSE_LEVEL_SSE1 10
+#define SK_CPU_SSE_LEVEL_SSE2 20
+#define SK_CPU_SSE_LEVEL_SSE3 30
+#define SK_CPU_SSE_LEVEL_SSSE3 31
+
+// Are we in GCC?
+#ifndef SK_CPU_SSE_LEVEL
+ #if defined(__SSE2__)
+ #define SK_CPU_SSE_LEVEL SK_CPU_SSE_LEVEL_SSE2
+ #elif defined(__SSE3__)
+ #define SK_CPU_SSE_LEVEL SK_CPU_SSE_LEVEL_SSE3
+ #elif defined(__SSSE3__)
+ #define SK_CPU_SSE_LEVEL SK_CPU_SSE_LEVEL_SSSE3
+ #endif
+#endif
+
+// Are we in VisualStudio?
+#ifndef SK_CPU_SSE_LEVEL
+ #if _M_IX86_FP == 1
+ #define SK_CPU_SSE_LEVEL SK_CPU_SSE_LEVEL_SSE1
+ #elif _M_IX86_FP >= 2
+ #define SK_CPU_SSE_LEVEL SK_CPU_SSE_LEVEL_SSE2
+ #endif
+#endif
+
+// 64bit intel guarantees at least SSE2
+#if defined(__x86_64__) || defined(_WIN64)
+ #if !defined(SK_CPU_SSE_LEVEL) || (SK_CPU_SSE_LEVEL < SK_CPU_SSE_LEVEL_SSE2)
+ #undef SK_CPU_SSE_LEVEL
+ #define SK_CPU_SSE_LEVEL SK_CPU_SSE_LEVEL_SSE2
+ #endif
+#endif
+
+//////////////////////////////////////////////////////////////////////
+// ARM defines
+
+#if defined(__arm__) && (!defined(__APPLE__) || !TARGET_IPHONE_SIMULATOR)
+ #define SK_CPU_ARM
+
+ #if defined(__GNUC__)
+ #if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) \
+ || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) \
+ || defined(__ARM_ARCH_7EM__) || defined(_ARM_ARCH_7)
+ #define SK_ARM_ARCH 7
+ #elif defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \
+ || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) \
+ || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) \
+ || defined(__ARM_ARCH_6M__) || defined(_ARM_ARCH_6)
+ #define SK_ARM_ARCH 6
+ #elif defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5T__) \
+ || defined(__ARM_ARCH_5E__) || defined(__ARM_ARCH_5TE__) \
+ || defined(__ARM_ARCH_5TEJ__) || defined(_ARM_ARCH_5)
+ #define SK_ARM_ARCH 5
+ #elif defined(__ARM_ARCH_4__) || defined(__ARM_ARCH_4T__) || defined(_ARM_ARCH_4)
+ #define SK_ARM_ARCH 4
+ #else
+ #define SK_ARM_ARCH 3
+ #endif
+
+ #if defined(__thumb2__) && (SK_ARM_ARCH >= 6) \
+ || !defined(__thumb__) && ((SK_ARM_ARCH > 5) || defined(__ARM_ARCH_5E__) \
+ || defined(__ARM_ARCH_5TE__) || defined(__ARM_ARCH_5TEJ__))
+ #define SK_ARM_HAS_EDSP
+ #endif
+ #endif
+#endif
+
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(SKIA_IMPLEMENTATION)
+ #define SKIA_IMPLEMENTATION 0
+#endif
+
+#if defined(SKIA_DLL)
+ #if defined(WIN32)
+ #if SKIA_IMPLEMENTATION
+ #define SK_API __declspec(dllexport)
+ #else
+ #define SK_API __declspec(dllimport)
+ #endif
+ #else
+ #define SK_API __attribute__((visibility("default")))
+ #endif
+#else
+ #define SK_API
+#endif
+
+//////////////////////////////////////////////////////////////////////
+
+/**
+ * Use SK_PURE_FUNC as an attribute to indicate that a function's
+ * return value only depends on the value of its parameters. This
+ * can help the compiler optimize out successive calls.
+ *
+ * Usage:
+ * void function(int params) SK_PURE_FUNC;
+ */
+#if defined(__GNUC__)
+# define SK_PURE_FUNC __attribute__((pure))
+#else
+# define SK_PURE_FUNC /* nothing */
+#endif
+
+//////////////////////////////////////////////////////////////////////
+
+/**
+ * SK_HAS_ATTRIBUTE(<name>) should return true iff the compiler
+ * supports __attribute__((<name>)). Mostly important because
+ * Clang doesn't support all of GCC attributes.
+ */
+#if defined(__has_attribute)
+# define SK_HAS_ATTRIBUTE(x) __has_attribute(x)
+#elif defined(__GNUC__)
+# define SK_HAS_ATTRIBUTE(x) 1
+#else
+# define SK_HAS_ATTRIBUTE(x) 0
+#endif
+
+/**
+ * SK_ATTRIBUTE_OPTIMIZE_O1 can be used as a function attribute
+ * to specify individual optimization level of -O1, if the compiler
+ * supports it.
+ *
+ * NOTE: Clang/ARM (r161757) does not support the 'optimize' attribute.
+ */
+#if SK_HAS_ATTRIBUTE(optimize)
+# define SK_ATTRIBUTE_OPTIMIZE_O1 __attribute__((optimize("O1")))
+#else
+# define SK_ATTRIBUTE_OPTIMIZE_O1 /* nothing */
+#endif
+
+#endif
diff --git a/core/SkRRect.h b/core/SkRRect.h
new file mode 100644
index 0000000..bce896a
--- /dev/null
+++ b/core/SkRRect.h
@@ -0,0 +1,295 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkRRect_DEFINED
+#define SkRRect_DEFINED
+
+#include "SkRect.h"
+#include "SkPoint.h"
+
+class SkPath;
+
+// Path forward:
+// core work
+// add validate method (all radii positive, all radii sums < rect size, etc.)
+// add contains(SkRect&) - for clip stack
+// add contains(SkRRect&) - for clip stack
+// add heart rect computation (max rect inside RR)
+// add 9patch rect computation
+// add growToInclude(SkPath&)
+// analysis
+// use growToInclude to fit skp round rects & generate stats (RRs vs. real paths)
+// check on # of rectorus's the RRs could handle
+// rendering work
+// add entry points (clipRRect, drawRRect) - plumb down to SkDevice
+// update SkPath.addRRect() to take an SkRRect - only use quads
+// -- alternatively add addRRectToPath here
+// add GM and bench
+// clipping opt
+// update SkClipStack to perform logic with RRs
+// further out
+// add RR rendering shader to Ganesh (akin to cicle drawing code)
+// - only for simple RRs
+// detect and triangulate RRectorii rather than falling back to SW in Ganesh
+//
+
+/** \class SkRRect
+
+ The SkRRect class represents a rounded rect with a potentially different
+ radii for each corner. It does not have a constructor so must be
+ initialized with one of the initialization functions (e.g., setEmpty,
+ setRectRadii, etc.)
+
+ This class is intended to roughly match CSS' border-*-*-radius capabilities.
+ This means:
+ If either of a corner's radii are 0 the corner will be square.
+ Negative radii are not allowed (they are clamped to zero).
+ If the corner curves overlap they will be proportionally reduced to fit.
+*/
+class SK_API SkRRect {
+public:
+ /**
+ * Enum to capture the various possible subtypes of RR. Accessed
+ * by type(). The subtypes become progressively less restrictive.
+ */
+ enum Type {
+ // !< Internal indicator that the sub type must be computed.
+ kUnknown_Type = -1,
+
+ // !< The RR is empty
+ kEmpty_Type,
+
+ //!< The RR is actually a (non-empty) rect (i.e., at least one radius
+ //!< at each corner is zero)
+ kRect_Type,
+
+ //!< The RR is actually a (non-empty) oval (i.e., all x radii are equal
+ //!< and >= width/2 and all the y radii are equal and >= height/2
+ kOval_Type,
+
+ //!< The RR is non-empty and all the x radii are equal & all y radii
+ //!< are equal but it is not an oval (i.e., there are lines between
+ //!< the curves) nor a rect (i.e., both radii are non-zero)
+ kSimple_Type,
+
+ //!< A fully general (non-empty) RR. Some of the x and/or y radii are
+ //!< different from the others and there must be one corner where
+ //!< both radii are non-zero.
+ kComplex_Type,
+ };
+
+ /**
+ * Returns the RR's sub type.
+ */
+ Type getType() const {
+ SkDEBUGCODE(this->validate();)
+
+ if (kUnknown_Type == fType) {
+ this->computeType();
+ }
+ SkASSERT(kUnknown_Type != fType);
+ return fType;
+ }
+
+ Type type() const { return this->getType(); }
+
+ inline bool isEmpty() const { return kEmpty_Type == this->getType(); }
+ inline bool isRect() const { return kRect_Type == this->getType(); }
+ inline bool isOval() const { return kOval_Type == this->getType(); }
+ inline bool isSimple() const { return kSimple_Type == this->getType(); }
+ inline bool isComplex() const { return kComplex_Type == this->getType(); }
+
+ SkScalar width() const { return fRect.width(); }
+ SkScalar height() const { return fRect.height(); }
+
+ /**
+ * Set this RR to the empty rectangle (0,0,0,0) with 0 x & y radii.
+ */
+ void setEmpty() {
+ fRect.setEmpty();
+ memset(fRadii, 0, sizeof(fRadii));
+ fType = kEmpty_Type;
+
+ SkDEBUGCODE(this->validate();)
+ }
+
+ /**
+ * Set this RR to match the supplied rect. All radii will be 0.
+ */
+ void setRect(const SkRect& rect) {
+ if (rect.isEmpty()) {
+ this->setEmpty();
+ return;
+ }
+
+ fRect = rect;
+ memset(fRadii, 0, sizeof(fRadii));
+ fType = kRect_Type;
+
+ SkDEBUGCODE(this->validate();)
+ }
+
+ /**
+ * Set this RR to match the supplied oval. All x radii will equal half the
+ * width and all y radii will equal half the height.
+ */
+ void setOval(const SkRect& oval) {
+ if (oval.isEmpty()) {
+ this->setEmpty();
+ return;
+ }
+
+ SkScalar xRad = SkScalarHalf(oval.width());
+ SkScalar yRad = SkScalarHalf(oval.height());
+
+ fRect = oval;
+ for (int i = 0; i < 4; ++i) {
+ fRadii[i].set(xRad, yRad);
+ }
+ fType = kOval_Type;
+
+ SkDEBUGCODE(this->validate();)
+ }
+
+ /**
+ * Initialize the RR with the same radii for all four corners.
+ */
+ void setRectXY(const SkRect& rect, SkScalar xRad, SkScalar yRad);
+
+ /**
+ * Initialize the RR with potentially different radii for all four corners.
+ */
+ void setRectRadii(const SkRect& rect, const SkVector radii[4]);
+
+ // The radii are stored in UL, UR, LR, LL order.
+ enum Corner {
+ kUpperLeft_Corner,
+ kUpperRight_Corner,
+ kLowerRight_Corner,
+ kLowerLeft_Corner
+ };
+
+ const SkRect& rect() const { return fRect; }
+ const SkVector& radii(Corner corner) const { return fRadii[corner]; }
+ const SkRect& getBounds() const { return fRect; }
+
+ /**
+ * When a rrect is simple, all of its radii are equal. This returns one
+ * of those radii. This call requires the rrect to be non-complex.
+ */
+ const SkVector& getSimpleRadii() const {
+ SkASSERT(!this->isComplex());
+ return fRadii[0];
+ }
+
+ friend bool operator==(const SkRRect& a, const SkRRect& b) {
+ return a.fRect == b.fRect &&
+ SkScalarsEqual(a.fRadii[0].asScalars(),
+ b.fRadii[0].asScalars(), 8);
+ }
+
+ friend bool operator!=(const SkRRect& a, const SkRRect& b) {
+ return a.fRect != b.fRect ||
+ !SkScalarsEqual(a.fRadii[0].asScalars(),
+ b.fRadii[0].asScalars(), 8);
+ }
+
+ /**
+ * Returns true if (p.fX,p.fY) is inside the RR, and the RR
+ * is not empty.
+ *
+ * Contains treats the left and top differently from the right and bottom.
+ * The left and top coordinates of the RR are themselves considered
+ * to be inside, while the right and bottom are not. All the points on the
+ * edges of the corners are considered to be inside.
+ */
+ bool contains(const SkPoint& p) const {
+ return contains(p.fX, p.fY);
+ }
+
+ /**
+ * Returns true if (x,y) is inside the RR, and the RR
+ * is not empty.
+ *
+ * Contains treats the left and top differently from the right and bottom.
+ * The left and top coordinates of the RR are themselves considered
+ * to be inside, while the right and bottom are not. All the points on the
+ * edges of the corners are considered to be inside.
+ */
+ bool contains(SkScalar x, SkScalar y) const;
+
+ /**
+ * Call inset on the bounds, and adjust the radii to reflect what happens
+ * in stroking: If the corner is sharp (no curvature), leave it alone,
+ * otherwise we grow/shrink the radii by the amount of the inset. If a
+ * given radius becomes negative, it is pinned to 0.
+ *
+ * It is valid for dst == this.
+ */
+ void inset(SkScalar dx, SkScalar dy, SkRRect* dst) const;
+
+ void inset(SkScalar dx, SkScalar dy) {
+ this->inset(dx, dy, this);
+ }
+
+ /**
+ * Call outset on the bounds, and adjust the radii to reflect what happens
+ * in stroking: If the corner is sharp (no curvature), leave it alone,
+ * otherwise we grow/shrink the radii by the amount of the inset. If a
+ * given radius becomes negative, it is pinned to 0.
+ *
+ * It is valid for dst == this.
+ */
+ void outset(SkScalar dx, SkScalar dy, SkRRect* dst) const {
+ this->inset(-dx, -dy, dst);
+ }
+ void outset(SkScalar dx, SkScalar dy) {
+ this->inset(-dx, -dy, this);
+ }
+
+ /**
+ * Returns true if 'rect' is wholy inside the RR, and both
+ * are not empty.
+ */
+ bool contains(const SkRect& rect) const;
+
+ SkDEBUGCODE(void validate() const;)
+
+ enum {
+ kSizeInMemory = 12 * sizeof(SkScalar)
+ };
+
+ /**
+ * Write the rrect into the specified buffer. This is guaranteed to always
+ * write kSizeInMemory bytes, and that value is guaranteed to always be
+ * a multiple of 4. Return kSizeInMemory.
+ */
+ uint32_t writeToMemory(void* buffer) const;
+
+ /**
+ * Read the rrect from the specified buffer. This is guaranteed to always
+ * read kSizeInMemory bytes, and that value is guaranteed to always be
+ * a multiple of 4. Return kSizeInMemory.
+ */
+ uint32_t readFromMemory(const void* buffer);
+
+private:
+ SkRect fRect;
+ // Radii order is UL, UR, LR, LL. Use Corner enum to index into fRadii[]
+ SkVector fRadii[4];
+ mutable Type fType;
+ // TODO: add padding so we can use memcpy for flattening and not copy
+ // uninitialized data
+
+ void computeType() const;
+ bool checkCornerContainment(SkScalar x, SkScalar y) const;
+
+ // to access fRadii directly
+ friend class SkPath;
+};
+
+#endif
diff --git a/core/SkRasterizer.h b/core/SkRasterizer.h
new file mode 100644
index 0000000..3e662ab
--- /dev/null
+++ b/core/SkRasterizer.h
@@ -0,0 +1,44 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkRasterizer_DEFINED
+#define SkRasterizer_DEFINED
+
+#include "SkFlattenable.h"
+#include "SkMask.h"
+
+class SkMaskFilter;
+class SkMatrix;
+class SkPath;
+struct SkIRect;
+
+class SK_API SkRasterizer : public SkFlattenable {
+public:
+ SK_DECLARE_INST_COUNT(SkRasterizer)
+
+ SkRasterizer() {}
+
+ /** Turn the path into a mask, respecting the specified local->device matrix.
+ */
+ bool rasterize(const SkPath& path, const SkMatrix& matrix,
+ const SkIRect* clipBounds, SkMaskFilter* filter,
+ SkMask* mask, SkMask::CreateMode mode) const;
+
+protected:
+ SkRasterizer(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {}
+
+ virtual bool onRasterize(const SkPath& path, const SkMatrix& matrix,
+ const SkIRect* clipBounds,
+ SkMask* mask, SkMask::CreateMode mode) const;
+
+private:
+ typedef SkFlattenable INHERITED;
+};
+
+#endif
diff --git a/core/SkReader32.h b/core/SkReader32.h
new file mode 100644
index 0000000..7a8d22a
--- /dev/null
+++ b/core/SkReader32.h
@@ -0,0 +1,158 @@
+
+/*
+ * Copyright 2008 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkReader32_DEFINED
+#define SkReader32_DEFINED
+
+#include "SkMatrix.h"
+#include "SkPath.h"
+#include "SkRegion.h"
+#include "SkRRect.h"
+#include "SkScalar.h"
+
+class SkString;
+
+class SkReader32 : SkNoncopyable {
+public:
+ SkReader32() : fCurr(NULL), fStop(NULL), fBase(NULL) {}
+ SkReader32(const void* data, size_t size) {
+ this->setMemory(data, size);
+ }
+
+ void setMemory(const void* data, size_t size) {
+ SkASSERT(ptr_align_4(data));
+ SkASSERT(SkAlign4(size) == size);
+
+ fBase = fCurr = (const char*)data;
+ fStop = (const char*)data + size;
+ }
+
+ uint32_t size() const { return SkToU32(fStop - fBase); }
+ uint32_t offset() const { return SkToU32(fCurr - fBase); }
+ bool eof() const { return fCurr >= fStop; }
+ const void* base() const { return fBase; }
+ const void* peek() const { return fCurr; }
+
+ uint32_t available() const { return SkToU32(fStop - fCurr); }
+ bool isAvailable(uint32_t size) const { return fCurr + size <= fStop; }
+
+ void rewind() { fCurr = fBase; }
+
+ void setOffset(size_t offset) {
+ SkASSERT(SkAlign4(offset) == offset);
+ SkASSERT(offset <= this->size());
+ fCurr = fBase + offset;
+ }
+
+ bool readBool() { return this->readInt() != 0; }
+
+ int32_t readInt() {
+ SkASSERT(ptr_align_4(fCurr));
+ int32_t value = *(const int32_t*)fCurr;
+ fCurr += sizeof(value);
+ SkASSERT(fCurr <= fStop);
+ return value;
+ }
+
+ void* readPtr() {
+ void* ptr;
+ // we presume this "if" is resolved at compile-time
+ if (4 == sizeof(void*)) {
+ ptr = *(void**)fCurr;
+ } else {
+ memcpy(&ptr, fCurr, sizeof(void*));
+ }
+ fCurr += sizeof(void*);
+ return ptr;
+ }
+
+ SkScalar readScalar() {
+ SkASSERT(ptr_align_4(fCurr));
+ SkScalar value = *(const SkScalar*)fCurr;
+ fCurr += sizeof(value);
+ SkASSERT(fCurr <= fStop);
+ return value;
+ }
+
+ const void* skip(size_t size) {
+ SkASSERT(ptr_align_4(fCurr));
+ const void* addr = fCurr;
+ fCurr += SkAlign4(size);
+ SkASSERT(fCurr <= fStop);
+ return addr;
+ }
+
+ template <typename T> const T& skipT() {
+ SkASSERT(SkAlign4(sizeof(T)) == sizeof(T));
+ return *(const T*)this->skip(sizeof(T));
+ }
+
+ void read(void* dst, size_t size) {
+ SkASSERT(0 == size || dst != NULL);
+ SkASSERT(ptr_align_4(fCurr));
+ memcpy(dst, fCurr, size);
+ fCurr += SkAlign4(size);
+ SkASSERT(fCurr <= fStop);
+ }
+
+ uint8_t readU8() { return (uint8_t)this->readInt(); }
+ uint16_t readU16() { return (uint16_t)this->readInt(); }
+ int32_t readS32() { return this->readInt(); }
+ uint32_t readU32() { return this->readInt(); }
+
+ void readPath(SkPath* path) {
+ size_t size = path->readFromMemory(this->peek());
+ SkASSERT(SkAlign4(size) == size);
+ (void)this->skip(size);
+ }
+
+ void readMatrix(SkMatrix* matrix) {
+ size_t size = matrix->readFromMemory(this->peek());
+ SkASSERT(SkAlign4(size) == size);
+ (void)this->skip(size);
+ }
+
+ SkRRect* readRRect(SkRRect* rrect) {
+ rrect->readFromMemory(this->skip(SkRRect::kSizeInMemory));
+ return rrect;
+ }
+
+ void readRegion(SkRegion* rgn) {
+ size_t size = rgn->readFromMemory(this->peek());
+ SkASSERT(SkAlign4(size) == size);
+ (void)this->skip(size);
+ }
+
+ /**
+ * Read the length of a string (written by SkWriter32::writeString) into
+ * len (if len is not NULL) and return the null-ternimated address of the
+ * string within the reader's buffer.
+ */
+ const char* readString(size_t* len = NULL);
+
+ /**
+ * Read the string (written by SkWriter32::writeString) and return it in
+ * copy (if copy is not null). Return the length of the string.
+ */
+ size_t readIntoString(SkString* copy);
+
+private:
+ // these are always 4-byte aligned
+ const char* fCurr; // current position within buffer
+ const char* fStop; // end of buffer
+ const char* fBase; // beginning of buffer
+
+#ifdef SK_DEBUG
+ static bool ptr_align_4(const void* ptr) {
+ return (((const char*)ptr - (const char*)NULL) & 3) == 0;
+ }
+#endif
+};
+
+#endif
diff --git a/core/SkRect.h b/core/SkRect.h
new file mode 100644
index 0000000..9f3b59a
--- /dev/null
+++ b/core/SkRect.h
@@ -0,0 +1,790 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkRect_DEFINED
+#define SkRect_DEFINED
+
+#include "SkPoint.h"
+#include "SkSize.h"
+
+/** \struct SkIRect
+
+ SkIRect holds four 32 bit integer coordinates for a rectangle
+*/
+struct SK_API SkIRect {
+ int32_t fLeft, fTop, fRight, fBottom;
+
+ static SkIRect SK_WARN_UNUSED_RESULT MakeEmpty() {
+ SkIRect r;
+ r.setEmpty();
+ return r;
+ }
+
+ static SkIRect SK_WARN_UNUSED_RESULT MakeLargest() {
+ SkIRect r;
+ r.setLargest();
+ return r;
+ }
+
+ static SkIRect SK_WARN_UNUSED_RESULT MakeWH(int32_t w, int32_t h) {
+ SkIRect r;
+ r.set(0, 0, w, h);
+ return r;
+ }
+
+ static SkIRect SK_WARN_UNUSED_RESULT MakeSize(const SkISize& size) {
+ SkIRect r;
+ r.set(0, 0, size.width(), size.height());
+ return r;
+ }
+
+ static SkIRect SK_WARN_UNUSED_RESULT MakeLTRB(int32_t l, int32_t t, int32_t r, int32_t b) {
+ SkIRect rect;
+ rect.set(l, t, r, b);
+ return rect;
+ }
+
+ static SkIRect SK_WARN_UNUSED_RESULT MakeXYWH(int32_t x, int32_t y, int32_t w, int32_t h) {
+ SkIRect r;
+ r.set(x, y, x + w, y + h);
+ return r;
+ }
+
+ int left() const { return fLeft; }
+ int top() const { return fTop; }
+ int right() const { return fRight; }
+ int bottom() const { return fBottom; }
+
+ /** return the left edge of the rect */
+ int x() const { return fLeft; }
+ /** return the top edge of the rect */
+ int y() const { return fTop; }
+ /**
+ * Returns the rectangle's width. This does not check for a valid rect
+ * (i.e. left <= right) so the result may be negative.
+ */
+ int width() const { return fRight - fLeft; }
+
+ /**
+ * Returns the rectangle's height. This does not check for a valid rect
+ * (i.e. top <= bottom) so the result may be negative.
+ */
+ int height() const { return fBottom - fTop; }
+
+ /**
+ * Since the center of an integer rect may fall on a factional value, this
+ * method is defined to return (right + left) >> 1.
+ *
+ * This is a specific "truncation" of the average, which is different than
+ * (right + left) / 2 when the sum is negative.
+ */
+ int centerX() const { return (fRight + fLeft) >> 1; }
+
+ /**
+ * Since the center of an integer rect may fall on a factional value, this
+ * method is defined to return (bottom + top) >> 1
+ *
+ * This is a specific "truncation" of the average, which is different than
+ * (bottom + top) / 2 when the sum is negative.
+ */
+ int centerY() const { return (fBottom + fTop) >> 1; }
+
+ /**
+ * Return true if the rectangle's width or height are <= 0
+ */
+ bool isEmpty() const { return fLeft >= fRight || fTop >= fBottom; }
+
+ bool isLargest() const { return SK_MinS32 == fLeft &&
+ SK_MinS32 == fTop &&
+ SK_MaxS32 == fRight &&
+ SK_MaxS32 == fBottom; }
+
+ friend bool operator==(const SkIRect& a, const SkIRect& b) {
+ return !memcmp(&a, &b, sizeof(a));
+ }
+
+ friend bool operator!=(const SkIRect& a, const SkIRect& b) {
+ return !(a == b);
+ }
+
+ bool is16Bit() const {
+ return SkIsS16(fLeft) && SkIsS16(fTop) &&
+ SkIsS16(fRight) && SkIsS16(fBottom);
+ }
+
+ /** Set the rectangle to (0,0,0,0)
+ */
+ void setEmpty() { memset(this, 0, sizeof(*this)); }
+
+ void set(int32_t left, int32_t top, int32_t right, int32_t bottom) {
+ fLeft = left;
+ fTop = top;
+ fRight = right;
+ fBottom = bottom;
+ }
+ // alias for set(l, t, r, b)
+ void setLTRB(int32_t left, int32_t top, int32_t right, int32_t bottom) {
+ this->set(left, top, right, bottom);
+ }
+
+ void setXYWH(int32_t x, int32_t y, int32_t width, int32_t height) {
+ fLeft = x;
+ fTop = y;
+ fRight = x + width;
+ fBottom = y + height;
+ }
+
+ /**
+ * Make the largest representable rectangle
+ */
+ void setLargest() {
+ fLeft = fTop = SK_MinS32;
+ fRight = fBottom = SK_MaxS32;
+ }
+
+ /**
+ * Make the largest representable rectangle, but inverted (e.g. fLeft will
+ * be max 32bit and right will be min 32bit).
+ */
+ void setLargestInverted() {
+ fLeft = fTop = SK_MaxS32;
+ fRight = fBottom = SK_MinS32;
+ }
+
+ /** Offset set the rectangle by adding dx to its left and right,
+ and adding dy to its top and bottom.
+ */
+ void offset(int32_t dx, int32_t dy) {
+ fLeft += dx;
+ fTop += dy;
+ fRight += dx;
+ fBottom += dy;
+ }
+
+ void offset(const SkIPoint& delta) {
+ this->offset(delta.fX, delta.fY);
+ }
+
+ /**
+ * Offset this rect such its new x() and y() will equal newX and newY.
+ */
+ void offsetTo(int32_t newX, int32_t newY) {
+ fRight += newX - fLeft;
+ fBottom += newY - fTop;
+ fLeft = newX;
+ fTop = newY;
+ }
+
+ /** Inset the rectangle by (dx,dy). If dx is positive, then the sides are moved inwards,
+ making the rectangle narrower. If dx is negative, then the sides are moved outwards,
+ making the rectangle wider. The same holds true for dy and the top and bottom.
+ */
+ void inset(int32_t dx, int32_t dy) {
+ fLeft += dx;
+ fTop += dy;
+ fRight -= dx;
+ fBottom -= dy;
+ }
+
+ /** Outset the rectangle by (dx,dy). If dx is positive, then the sides are
+ moved outwards, making the rectangle wider. If dx is negative, then the
+ sides are moved inwards, making the rectangle narrower. The same holds
+ true for dy and the top and bottom.
+ */
+ void outset(int32_t dx, int32_t dy) { this->inset(-dx, -dy); }
+
+ bool quickReject(int l, int t, int r, int b) const {
+ return l >= fRight || fLeft >= r || t >= fBottom || fTop >= b;
+ }
+
+ /** Returns true if (x,y) is inside the rectangle and the rectangle is not
+ empty. The left and top are considered to be inside, while the right
+ and bottom are not. Thus for the rectangle (0, 0, 5, 10), the
+ points (0,0) and (0,9) are inside, while (-1,0) and (5,9) are not.
+ */
+ bool contains(int32_t x, int32_t y) const {
+ return (unsigned)(x - fLeft) < (unsigned)(fRight - fLeft) &&
+ (unsigned)(y - fTop) < (unsigned)(fBottom - fTop);
+ }
+
+ /** Returns true if the 4 specified sides of a rectangle are inside or equal to this rectangle.
+ If either rectangle is empty, contains() returns false.
+ */
+ bool contains(int32_t left, int32_t top, int32_t right, int32_t bottom) const {
+ return left < right && top < bottom && !this->isEmpty() && // check for empties
+ fLeft <= left && fTop <= top &&
+ fRight >= right && fBottom >= bottom;
+ }
+
+ /** Returns true if the specified rectangle r is inside or equal to this rectangle.
+ */
+ bool contains(const SkIRect& r) const {
+ return !r.isEmpty() && !this->isEmpty() && // check for empties
+ fLeft <= r.fLeft && fTop <= r.fTop &&
+ fRight >= r.fRight && fBottom >= r.fBottom;
+ }
+
+ /** Return true if this rectangle contains the specified rectangle.
+ For speed, this method does not check if either this or the specified
+ rectangles are empty, and if either is, its return value is undefined.
+ In the debugging build however, we assert that both this and the
+ specified rectangles are non-empty.
+ */
+ bool containsNoEmptyCheck(int32_t left, int32_t top,
+ int32_t right, int32_t bottom) const {
+ SkASSERT(fLeft < fRight && fTop < fBottom);
+ SkASSERT(left < right && top < bottom);
+
+ return fLeft <= left && fTop <= top &&
+ fRight >= right && fBottom >= bottom;
+ }
+
+ bool containsNoEmptyCheck(const SkIRect& r) const {
+ return containsNoEmptyCheck(r.fLeft, r.fTop, r.fRight, r.fBottom);
+ }
+
+ /** If r intersects this rectangle, return true and set this rectangle to that
+ intersection, otherwise return false and do not change this rectangle.
+ If either rectangle is empty, do nothing and return false.
+ */
+ bool intersect(const SkIRect& r) {
+ SkASSERT(&r);
+ return this->intersect(r.fLeft, r.fTop, r.fRight, r.fBottom);
+ }
+
+ /** If rectangles a and b intersect, return true and set this rectangle to
+ that intersection, otherwise return false and do not change this
+ rectangle. If either rectangle is empty, do nothing and return false.
+ */
+ bool intersect(const SkIRect& a, const SkIRect& b) {
+ SkASSERT(&a && &b);
+
+ if (!a.isEmpty() && !b.isEmpty() &&
+ a.fLeft < b.fRight && b.fLeft < a.fRight &&
+ a.fTop < b.fBottom && b.fTop < a.fBottom) {
+ fLeft = SkMax32(a.fLeft, b.fLeft);
+ fTop = SkMax32(a.fTop, b.fTop);
+ fRight = SkMin32(a.fRight, b.fRight);
+ fBottom = SkMin32(a.fBottom, b.fBottom);
+ return true;
+ }
+ return false;
+ }
+
+ /** If rectangles a and b intersect, return true and set this rectangle to
+ that intersection, otherwise return false and do not change this
+ rectangle. For speed, no check to see if a or b are empty is performed.
+ If either is, then the return result is undefined. In the debug build,
+ we assert that both rectangles are non-empty.
+ */
+ bool intersectNoEmptyCheck(const SkIRect& a, const SkIRect& b) {
+ SkASSERT(&a && &b);
+ SkASSERT(!a.isEmpty() && !b.isEmpty());
+
+ if (a.fLeft < b.fRight && b.fLeft < a.fRight &&
+ a.fTop < b.fBottom && b.fTop < a.fBottom) {
+ fLeft = SkMax32(a.fLeft, b.fLeft);
+ fTop = SkMax32(a.fTop, b.fTop);
+ fRight = SkMin32(a.fRight, b.fRight);
+ fBottom = SkMin32(a.fBottom, b.fBottom);
+ return true;
+ }
+ return false;
+ }
+
+ /** If the rectangle specified by left,top,right,bottom intersects this rectangle,
+ return true and set this rectangle to that intersection,
+ otherwise return false and do not change this rectangle.
+ If either rectangle is empty, do nothing and return false.
+ */
+ bool intersect(int32_t left, int32_t top, int32_t right, int32_t bottom) {
+ if (left < right && top < bottom && !this->isEmpty() &&
+ fLeft < right && left < fRight && fTop < bottom && top < fBottom) {
+ if (fLeft < left) fLeft = left;
+ if (fTop < top) fTop = top;
+ if (fRight > right) fRight = right;
+ if (fBottom > bottom) fBottom = bottom;
+ return true;
+ }
+ return false;
+ }
+
+ /** Returns true if a and b are not empty, and they intersect
+ */
+ static bool Intersects(const SkIRect& a, const SkIRect& b) {
+ return !a.isEmpty() && !b.isEmpty() && // check for empties
+ a.fLeft < b.fRight && b.fLeft < a.fRight &&
+ a.fTop < b.fBottom && b.fTop < a.fBottom;
+ }
+
+ /**
+ * Returns true if a and b intersect. debug-asserts that neither are empty.
+ */
+ static bool IntersectsNoEmptyCheck(const SkIRect& a, const SkIRect& b) {
+ SkASSERT(!a.isEmpty());
+ SkASSERT(!b.isEmpty());
+ return a.fLeft < b.fRight && b.fLeft < a.fRight &&
+ a.fTop < b.fBottom && b.fTop < a.fBottom;
+ }
+
+ /** Update this rectangle to enclose itself and the specified rectangle.
+ If this rectangle is empty, just set it to the specified rectangle. If the specified
+ rectangle is empty, do nothing.
+ */
+ void join(int32_t left, int32_t top, int32_t right, int32_t bottom);
+
+ /** Update this rectangle to enclose itself and the specified rectangle.
+ If this rectangle is empty, just set it to the specified rectangle. If the specified
+ rectangle is empty, do nothing.
+ */
+ void join(const SkIRect& r) {
+ this->join(r.fLeft, r.fTop, r.fRight, r.fBottom);
+ }
+
+ /** Swap top/bottom or left/right if there are flipped.
+ This can be called if the edges are computed separately,
+ and may have crossed over each other.
+ When this returns, left <= right && top <= bottom
+ */
+ void sort();
+
+ static const SkIRect& SK_WARN_UNUSED_RESULT EmptyIRect() {
+ static const SkIRect gEmpty = { 0, 0, 0, 0 };
+ return gEmpty;
+ }
+};
+
+/** \struct SkRect
+*/
+struct SK_API SkRect {
+ SkScalar fLeft, fTop, fRight, fBottom;
+
+ static SkRect SK_WARN_UNUSED_RESULT MakeEmpty() {
+ SkRect r;
+ r.setEmpty();
+ return r;
+ }
+
+ static SkRect SK_WARN_UNUSED_RESULT MakeWH(SkScalar w, SkScalar h) {
+ SkRect r;
+ r.set(0, 0, w, h);
+ return r;
+ }
+
+ static SkRect SK_WARN_UNUSED_RESULT MakeSize(const SkSize& size) {
+ SkRect r;
+ r.set(0, 0, size.width(), size.height());
+ return r;
+ }
+
+ static SkRect SK_WARN_UNUSED_RESULT MakeLTRB(SkScalar l, SkScalar t, SkScalar r, SkScalar b) {
+ SkRect rect;
+ rect.set(l, t, r, b);
+ return rect;
+ }
+
+ static SkRect SK_WARN_UNUSED_RESULT MakeXYWH(SkScalar x, SkScalar y, SkScalar w, SkScalar h) {
+ SkRect r;
+ r.set(x, y, x + w, y + h);
+ return r;
+ }
+
+ // DEPRECATED: call Make(r)
+ static SkRect SK_WARN_UNUSED_RESULT MakeFromIRect(const SkIRect& irect) {
+ SkRect r;
+ r.set(SkIntToScalar(irect.fLeft),
+ SkIntToScalar(irect.fTop),
+ SkIntToScalar(irect.fRight),
+ SkIntToScalar(irect.fBottom));
+ return r;
+ }
+
+ static SkRect SK_WARN_UNUSED_RESULT Make(const SkIRect& irect) {
+ SkRect r;
+ r.set(SkIntToScalar(irect.fLeft),
+ SkIntToScalar(irect.fTop),
+ SkIntToScalar(irect.fRight),
+ SkIntToScalar(irect.fBottom));
+ return r;
+ }
+
+ /**
+ * Return true if the rectangle's width or height are <= 0
+ */
+ bool isEmpty() const { return fLeft >= fRight || fTop >= fBottom; }
+
+ /**
+ * Returns true iff all values in the rect are finite. If any are
+ * infinite or NaN (or SK_FixedNaN when SkScalar is fixed) then this
+ * returns false.
+ */
+ bool isFinite() const {
+#ifdef SK_SCALAR_IS_FLOAT
+ float accum = 0;
+ accum *= fLeft;
+ accum *= fTop;
+ accum *= fRight;
+ accum *= fBottom;
+
+ // accum is either NaN or it is finite (zero).
+ SkASSERT(0 == accum || !(accum == accum));
+
+ // value==value will be true iff value is not NaN
+ // TODO: is it faster to say !accum or accum==accum?
+ return accum == accum;
+#else
+ // use bit-or for speed, since we don't care about short-circuting the
+ // tests, and we expect the common case will be that we need to check all.
+ int isNaN = (SK_FixedNaN == fLeft) | (SK_FixedNaN == fTop) |
+ (SK_FixedNaN == fRight) | (SK_FixedNaN == fBottom);
+ return !isNaN;
+#endif
+ }
+
+ SkScalar x() const { return fLeft; }
+ SkScalar y() const { return fTop; }
+ SkScalar left() const { return fLeft; }
+ SkScalar top() const { return fTop; }
+ SkScalar right() const { return fRight; }
+ SkScalar bottom() const { return fBottom; }
+ SkScalar width() const { return fRight - fLeft; }
+ SkScalar height() const { return fBottom - fTop; }
+ SkScalar centerX() const { return SkScalarHalf(fLeft + fRight); }
+ SkScalar centerY() const { return SkScalarHalf(fTop + fBottom); }
+
+ friend bool operator==(const SkRect& a, const SkRect& b) {
+ return SkScalarsEqual((SkScalar*)&a, (SkScalar*)&b, 4);
+ }
+
+ friend bool operator!=(const SkRect& a, const SkRect& b) {
+ return !SkScalarsEqual((SkScalar*)&a, (SkScalar*)&b, 4);
+ }
+
+ /** return the 4 points that enclose the rectangle
+ */
+ void toQuad(SkPoint quad[4]) const;
+
+ /** Set this rectangle to the empty rectangle (0,0,0,0)
+ */
+ void setEmpty() { memset(this, 0, sizeof(*this)); }
+
+ void set(const SkIRect& src) {
+ fLeft = SkIntToScalar(src.fLeft);
+ fTop = SkIntToScalar(src.fTop);
+ fRight = SkIntToScalar(src.fRight);
+ fBottom = SkIntToScalar(src.fBottom);
+ }
+
+ void set(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom) {
+ fLeft = left;
+ fTop = top;
+ fRight = right;
+ fBottom = bottom;
+ }
+ // alias for set(l, t, r, b)
+ void setLTRB(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom) {
+ this->set(left, top, right, bottom);
+ }
+
+ /** Initialize the rect with the 4 specified integers. The routine handles
+ converting them to scalars (by calling SkIntToScalar)
+ */
+ void iset(int left, int top, int right, int bottom) {
+ fLeft = SkIntToScalar(left);
+ fTop = SkIntToScalar(top);
+ fRight = SkIntToScalar(right);
+ fBottom = SkIntToScalar(bottom);
+ }
+
+ /**
+ * Set this rectangle to be left/top at 0,0, and have the specified width
+ * and height (automatically converted to SkScalar).
+ */
+ void isetWH(int width, int height) {
+ fLeft = fTop = 0;
+ fRight = SkIntToScalar(width);
+ fBottom = SkIntToScalar(height);
+ }
+
+ /** Set this rectangle to be the bounds of the array of points.
+ If the array is empty (count == 0), then set this rectangle
+ to the empty rectangle (0,0,0,0)
+ */
+ void set(const SkPoint pts[], int count) {
+ // set() had been checking for non-finite values, so keep that behavior
+ // for now. Now that we have setBoundsCheck(), we may decide to make
+ // set() be simpler/faster, and not check for those.
+ (void)this->setBoundsCheck(pts, count);
+ }
+
+ // alias for set(pts, count)
+ void setBounds(const SkPoint pts[], int count) {
+ (void)this->setBoundsCheck(pts, count);
+ }
+
+ /**
+ * Compute the bounds of the array of points, and set this rect to that
+ * bounds and return true... unless a non-finite value is encountered,
+ * in which case this rect is set to empty and false is returned.
+ */
+ bool setBoundsCheck(const SkPoint pts[], int count);
+
+ void set(const SkPoint& p0, const SkPoint& p1) {
+ fLeft = SkMinScalar(p0.fX, p1.fX);
+ fRight = SkMaxScalar(p0.fX, p1.fX);
+ fTop = SkMinScalar(p0.fY, p1.fY);
+ fBottom = SkMaxScalar(p0.fY, p1.fY);
+ }
+
+ void setXYWH(SkScalar x, SkScalar y, SkScalar width, SkScalar height) {
+ fLeft = x;
+ fTop = y;
+ fRight = x + width;
+ fBottom = y + height;
+ }
+
+ void setWH(SkScalar width, SkScalar height) {
+ fLeft = 0;
+ fTop = 0;
+ fRight = width;
+ fBottom = height;
+ }
+
+ /**
+ * Make the largest representable rectangle
+ */
+ void setLargest() {
+ fLeft = fTop = SK_ScalarMin;
+ fRight = fBottom = SK_ScalarMax;
+ }
+
+ /**
+ * Make the largest representable rectangle, but inverted (e.g. fLeft will
+ * be max and right will be min).
+ */
+ void setLargestInverted() {
+ fLeft = fTop = SK_ScalarMax;
+ fRight = fBottom = SK_ScalarMin;
+ }
+
+ /** Offset set the rectangle by adding dx to its left and right,
+ and adding dy to its top and bottom.
+ */
+ void offset(SkScalar dx, SkScalar dy) {
+ fLeft += dx;
+ fTop += dy;
+ fRight += dx;
+ fBottom += dy;
+ }
+
+ void offset(const SkPoint& delta) {
+ this->offset(delta.fX, delta.fY);
+ }
+
+ /**
+ * Offset this rect such its new x() and y() will equal newX and newY.
+ */
+ void offsetTo(SkScalar newX, SkScalar newY) {
+ fRight += newX - fLeft;
+ fBottom += newY - fTop;
+ fLeft = newX;
+ fTop = newY;
+ }
+
+ /** Inset the rectangle by (dx,dy). If dx is positive, then the sides are
+ moved inwards, making the rectangle narrower. If dx is negative, then
+ the sides are moved outwards, making the rectangle wider. The same holds
+ true for dy and the top and bottom.
+ */
+ void inset(SkScalar dx, SkScalar dy) {
+ fLeft += dx;
+ fTop += dy;
+ fRight -= dx;
+ fBottom -= dy;
+ }
+
+ /** Outset the rectangle by (dx,dy). If dx is positive, then the sides are
+ moved outwards, making the rectangle wider. If dx is negative, then the
+ sides are moved inwards, making the rectangle narrower. The same holds
+ true for dy and the top and bottom.
+ */
+ void outset(SkScalar dx, SkScalar dy) { this->inset(-dx, -dy); }
+
+ /** If this rectangle intersects r, return true and set this rectangle to that
+ intersection, otherwise return false and do not change this rectangle.
+ If either rectangle is empty, do nothing and return false.
+ */
+ bool intersect(const SkRect& r);
+
+ /** If this rectangle intersects the rectangle specified by left, top, right, bottom,
+ return true and set this rectangle to that intersection, otherwise return false
+ and do not change this rectangle.
+ If either rectangle is empty, do nothing and return false.
+ */
+ bool intersect(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom);
+
+ /**
+ * Return true if this rectangle is not empty, and the specified sides of
+ * a rectangle are not empty, and they intersect.
+ */
+ bool intersects(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom) const {
+ return // first check that both are not empty
+ left < right && top < bottom &&
+ fLeft < fRight && fTop < fBottom &&
+ // now check for intersection
+ fLeft < right && left < fRight &&
+ fTop < bottom && top < fBottom;
+ }
+
+ /** If rectangles a and b intersect, return true and set this rectangle to
+ * that intersection, otherwise return false and do not change this
+ * rectangle. If either rectangle is empty, do nothing and return false.
+ */
+ bool intersect(const SkRect& a, const SkRect& b);
+
+ /**
+ * Return true if rectangles a and b are not empty and intersect.
+ */
+ static bool Intersects(const SkRect& a, const SkRect& b) {
+ return !a.isEmpty() && !b.isEmpty() &&
+ a.fLeft < b.fRight && b.fLeft < a.fRight &&
+ a.fTop < b.fBottom && b.fTop < a.fBottom;
+ }
+
+ /**
+ * Update this rectangle to enclose itself and the specified rectangle.
+ * If this rectangle is empty, just set it to the specified rectangle.
+ * If the specified rectangle is empty, do nothing.
+ */
+ void join(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom);
+
+ /** Update this rectangle to enclose itself and the specified rectangle.
+ If this rectangle is empty, just set it to the specified rectangle. If the specified
+ rectangle is empty, do nothing.
+ */
+ void join(const SkRect& r) {
+ this->join(r.fLeft, r.fTop, r.fRight, r.fBottom);
+ }
+ // alias for join()
+ void growToInclude(const SkRect& r) { this->join(r); }
+
+ /**
+ * Grow the rect to include the specified (x,y). After this call, the
+ * following will be true: fLeft <= x <= fRight && fTop <= y <= fBottom.
+ *
+ * This is close, but not quite the same contract as contains(), since
+ * contains() treats the left and top different from the right and bottom.
+ * contains(x,y) -> fLeft <= x < fRight && fTop <= y < fBottom. Also note
+ * that contains(x,y) always returns false if the rect is empty.
+ */
+ void growToInclude(SkScalar x, SkScalar y) {
+ fLeft = SkMinScalar(x, fLeft);
+ fRight = SkMaxScalar(x, fRight);
+ fTop = SkMinScalar(y, fTop);
+ fBottom = SkMaxScalar(y, fBottom);
+ }
+
+ /**
+ * Returns true if (p.fX,p.fY) is inside the rectangle, and the rectangle
+ * is not empty.
+ *
+ * Contains treats the left and top differently from the right and bottom.
+ * The left and top coordinates of the rectangle are themselves considered
+ * to be inside, while the right and bottom are not. Thus for the rectangle
+ * {0, 0, 5, 10}, (0,0) is contained, but (0,10), (5,0) and (5,10) are not.
+ */
+ bool contains(const SkPoint& p) const {
+ return !this->isEmpty() &&
+ fLeft <= p.fX && p.fX < fRight && fTop <= p.fY && p.fY < fBottom;
+ }
+
+ /**
+ * Returns true if (x,y) is inside the rectangle, and the rectangle
+ * is not empty.
+ *
+ * Contains treats the left and top differently from the right and bottom.
+ * The left and top coordinates of the rectangle are themselves considered
+ * to be inside, while the right and bottom are not. Thus for the rectangle
+ * {0, 0, 5, 10}, (0,0) is contained, but (0,10), (5,0) and (5,10) are not.
+ */
+ bool contains(SkScalar x, SkScalar y) const {
+ return !this->isEmpty() &&
+ fLeft <= x && x < fRight && fTop <= y && y < fBottom;
+ }
+
+ /**
+ * Return true if this rectangle contains r, and if both rectangles are
+ * not empty.
+ */
+ bool contains(const SkRect& r) const {
+ return !r.isEmpty() && !this->isEmpty() &&
+ fLeft <= r.fLeft && fTop <= r.fTop &&
+ fRight >= r.fRight && fBottom >= r.fBottom;
+ }
+
+ /**
+ * Set the dst rectangle by rounding this rectangle's coordinates to their
+ * nearest integer values using SkScalarRound.
+ */
+ void round(SkIRect* dst) const {
+ SkASSERT(dst);
+ dst->set(SkScalarRoundToInt(fLeft), SkScalarRoundToInt(fTop),
+ SkScalarRoundToInt(fRight), SkScalarRoundToInt(fBottom));
+ }
+
+ /**
+ * Set the dst rectangle by rounding "out" this rectangle, choosing the
+ * SkScalarFloor of top and left, and the SkScalarCeil of right and bottom.
+ */
+ void roundOut(SkIRect* dst) const {
+ SkASSERT(dst);
+ dst->set(SkScalarFloorToInt(fLeft), SkScalarFloorToInt(fTop),
+ SkScalarCeilToInt(fRight), SkScalarCeilToInt(fBottom));
+ }
+
+ /**
+ * Expand this rectangle by rounding its coordinates "out", choosing the
+ * floor of top and left, and the ceil of right and bottom. If this rect
+ * is already on integer coordinates, then it will be unchanged.
+ */
+ void roundOut() {
+ this->set(SkScalarFloorToScalar(fLeft),
+ SkScalarFloorToScalar(fTop),
+ SkScalarCeilToScalar(fRight),
+ SkScalarCeilToScalar(fBottom));
+ }
+
+ /**
+ * Set the dst rectangle by rounding "in" this rectangle, choosing the
+ * ceil of top and left, and the floor of right and bottom. This does *not*
+ * call sort(), so it is possible that the resulting rect is inverted...
+ * e.g. left >= right or top >= bottom. Call isEmpty() to detect that.
+ */
+ void roundIn(SkIRect* dst) const {
+ SkASSERT(dst);
+ dst->set(SkScalarCeilToInt(fLeft), SkScalarCeilToInt(fTop),
+ SkScalarFloorToInt(fRight), SkScalarFloorToInt(fBottom));
+ }
+
+
+ /**
+ * Swap top/bottom or left/right if there are flipped (i.e. if width()
+ * or height() would have returned a negative value.) This should be called
+ * if the edges are computed separately, and may have crossed over each
+ * other. When this returns, left <= right && top <= bottom
+ */
+ void sort();
+
+ /**
+ * cast-safe way to treat the rect as an array of (4) SkScalars.
+ */
+ const SkScalar* asScalars() const { return &fLeft; }
+};
+
+#endif
diff --git a/core/SkRefCnt.h b/core/SkRefCnt.h
new file mode 100644
index 0000000..87ff7db
--- /dev/null
+++ b/core/SkRefCnt.h
@@ -0,0 +1,274 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkRefCnt_DEFINED
+#define SkRefCnt_DEFINED
+
+#include "SkThread.h"
+#include "SkInstCnt.h"
+#include "SkTemplates.h"
+
+/** \class SkRefCnt
+
+ SkRefCnt is the base class for objects that may be shared by multiple
+ objects. When an existing owner wants to share a reference, it calls ref().
+ When an owner wants to release its reference, it calls unref(). When the
+ shared object's reference count goes to zero as the result of an unref()
+ call, its (virtual) destructor is called. It is an error for the
+ destructor to be called explicitly (or via the object going out of scope on
+ the stack or calling delete) if getRefCnt() > 1.
+*/
+class SK_API SkRefCnt : SkNoncopyable {
+public:
+ SK_DECLARE_INST_COUNT_ROOT(SkRefCnt)
+
+ /** Default construct, initializing the reference count to 1.
+ */
+ SkRefCnt() : fRefCnt(1) {}
+
+ /** Destruct, asserting that the reference count is 1.
+ */
+ virtual ~SkRefCnt() {
+#ifdef SK_DEBUG
+ SkASSERT(fRefCnt == 1);
+ fRefCnt = 0; // illegal value, to catch us if we reuse after delete
+#endif
+ }
+
+ /** Return the reference count. Use only for debugging. */
+ int32_t getRefCnt() const { return fRefCnt; }
+
+ /** Returns true if the caller is the only owner.
+ * Ensures that all previous owner's actions are complete.
+ */
+ bool unique() const {
+ bool const unique = (1 == fRefCnt);
+ if (unique) {
+ // Aquire barrier (L/SL), if not provided by load of fRefCnt.
+ // Prevents user's 'unique' code from happening before decrements.
+ //TODO: issue the barrier.
+ }
+ return unique;
+ }
+
+ /** Increment the reference count. Must be balanced by a call to unref().
+ */
+ void ref() const {
+ SkASSERT(fRefCnt > 0);
+ sk_atomic_inc(&fRefCnt); // No barrier required.
+ }
+
+ /** Decrement the reference count. If the reference count is 1 before the
+ decrement, then delete the object. Note that if this is the case, then
+ the object needs to have been allocated via new, and not on the stack.
+ */
+ void unref() const {
+ SkASSERT(fRefCnt > 0);
+ // Release barrier (SL/S), if not provided below.
+ if (sk_atomic_dec(&fRefCnt) == 1) {
+ // Aquire barrier (L/SL), if not provided above.
+ // Prevents code in dispose from happening before the decrement.
+ sk_membar_aquire__after_atomic_dec();
+ internal_dispose();
+ }
+ }
+
+ void validate() const {
+ SkASSERT(fRefCnt > 0);
+ }
+
+ /**
+ * Alias for unref(), for compatibility with WTF::RefPtr.
+ */
+ void deref() { this->unref(); }
+
+protected:
+ /**
+ * Allow subclasses to call this if they've overridden internal_dispose
+ * so they can reset fRefCnt before the destructor is called. Should only
+ * be called right before calling through to inherited internal_dispose()
+ * or before calling the destructor.
+ */
+ void internal_dispose_restore_refcnt_to_1() const {
+#ifdef SK_DEBUG
+ SkASSERT(0 == fRefCnt);
+ fRefCnt = 1;
+#endif
+ }
+
+private:
+ /**
+ * Called when the ref count goes to 0.
+ */
+ virtual void internal_dispose() const {
+ this->internal_dispose_restore_refcnt_to_1();
+ SkDELETE(this);
+ }
+
+ // The following friends are those which override internal_dispose()
+ // and conditionally call SkRefCnt::internal_dispose().
+ friend class GrTexture;
+ friend class SkWeakRefCnt;
+
+ mutable int32_t fRefCnt;
+
+ typedef SkNoncopyable INHERITED;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+/** Helper macro to safely assign one SkRefCnt[TS]* to another, checking for
+ null in on each side of the assignment, and ensuring that ref() is called
+ before unref(), in case the two pointers point to the same object.
+ */
+#define SkRefCnt_SafeAssign(dst, src) \
+ do { \
+ if (src) src->ref(); \
+ if (dst) dst->unref(); \
+ dst = src; \
+ } while (0)
+
+
+/** Call obj->ref() and return obj. The obj must not be NULL.
+ */
+template <typename T> static inline T* SkRef(T* obj) {
+ SkASSERT(obj);
+ obj->ref();
+ return obj;
+}
+
+/** Check if the argument is non-null, and if so, call obj->ref() and return obj.
+ */
+template <typename T> static inline T* SkSafeRef(T* obj) {
+ if (obj) {
+ obj->ref();
+ }
+ return obj;
+}
+
+/** Check if the argument is non-null, and if so, call obj->unref()
+ */
+template <typename T> static inline void SkSafeUnref(T* obj) {
+ if (obj) {
+ obj->unref();
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Utility class that simply unref's its argument in the destructor.
+ */
+template <typename T> class SkAutoTUnref : SkNoncopyable {
+public:
+ explicit SkAutoTUnref(T* obj = NULL) : fObj(obj) {}
+ ~SkAutoTUnref() { SkSafeUnref(fObj); }
+
+ T* get() const { return fObj; }
+
+ T* reset(T* obj) {
+ SkSafeUnref(fObj);
+ fObj = obj;
+ return obj;
+ }
+
+ void swap(SkAutoTUnref* other) {
+ T* tmp = fObj;
+ fObj = other->fObj;
+ other->fObj = tmp;
+ }
+
+ /**
+ * Return the hosted object (which may be null), transferring ownership.
+ * The reference count is not modified, and the internal ptr is set to NULL
+ * so unref() will not be called in our destructor. A subsequent call to
+ * detach() will do nothing and return null.
+ */
+ T* detach() {
+ T* obj = fObj;
+ fObj = NULL;
+ return obj;
+ }
+
+ /**
+ * BlockRef<B> is a type which inherits from B, cannot be created,
+ * cannot be deleted, and makes ref and unref private.
+ */
+ template<typename B> class BlockRef : public B {
+ private:
+ BlockRef();
+ ~BlockRef();
+ void ref() const;
+ void unref() const;
+ };
+
+ /** If T is const, the type returned from operator-> will also be const. */
+ typedef typename SkTConstType<BlockRef<T>, SkTIsConst<T>::value>::type BlockRefType;
+
+ /**
+ * SkAutoTUnref assumes ownership of the ref. As a result, it is an error
+ * for the user to ref or unref through SkAutoTUnref. Therefore
+ * SkAutoTUnref::operator-> returns BlockRef<T>*. This prevents use of
+ * skAutoTUnrefInstance->ref() and skAutoTUnrefInstance->unref().
+ */
+ BlockRefType *operator->() const {
+ return static_cast<BlockRefType*>(fObj);
+ }
+ operator T*() { return fObj; }
+
+private:
+ T* fObj;
+};
+
+class SkAutoUnref : public SkAutoTUnref<SkRefCnt> {
+public:
+ SkAutoUnref(SkRefCnt* obj) : SkAutoTUnref<SkRefCnt>(obj) {}
+};
+
+class SkAutoRef : SkNoncopyable {
+public:
+ SkAutoRef(SkRefCnt* obj) : fObj(obj) { SkSafeRef(obj); }
+ ~SkAutoRef() { SkSafeUnref(fObj); }
+private:
+ SkRefCnt* fObj;
+};
+
+/** Wrapper class for SkRefCnt pointers. This manages ref/unref of a pointer to
+ a SkRefCnt (or subclass) object.
+ */
+template <typename T> class SkRefPtr {
+public:
+ SkRefPtr() : fObj(NULL) {}
+ SkRefPtr(T* obj) : fObj(obj) { SkSafeRef(fObj); }
+ SkRefPtr(const SkRefPtr& o) : fObj(o.fObj) { SkSafeRef(fObj); }
+ ~SkRefPtr() { SkSafeUnref(fObj); }
+
+ SkRefPtr& operator=(const SkRefPtr& rp) {
+ SkRefCnt_SafeAssign(fObj, rp.fObj);
+ return *this;
+ }
+ SkRefPtr& operator=(T* obj) {
+ SkRefCnt_SafeAssign(fObj, obj);
+ return *this;
+ }
+
+ T* get() const { return fObj; }
+ T& operator*() const { return *fObj; }
+ T* operator->() const { return fObj; }
+
+ typedef T* SkRefPtr::*unspecified_bool_type;
+ operator unspecified_bool_type() const {
+ return fObj ? &SkRefPtr::fObj : NULL;
+ }
+
+private:
+ T* fObj;
+};
+
+#endif
diff --git a/core/SkRegion.h b/core/SkRegion.h
new file mode 100644
index 0000000..a088d54
--- /dev/null
+++ b/core/SkRegion.h
@@ -0,0 +1,446 @@
+
+/*
+ * Copyright 2005 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkRegion_DEFINED
+#define SkRegion_DEFINED
+
+#include "SkRect.h"
+
+class SkPath;
+class SkRgnBuilder;
+
+namespace android {
+ class Region;
+}
+
+#define SkRegion_gEmptyRunHeadPtr ((SkRegion::RunHead*)-1)
+#define SkRegion_gRectRunHeadPtr 0
+
+/** \class SkRegion
+
+ The SkRegion class encapsulates the geometric region used to specify
+ clipping areas for drawing.
+*/
+class SK_API SkRegion {
+public:
+ typedef int32_t RunType;
+ enum {
+ kRunTypeSentinel = 0x7FFFFFFF
+ };
+
+ SkRegion();
+ SkRegion(const SkRegion&);
+ explicit SkRegion(const SkIRect&);
+ ~SkRegion();
+
+ SkRegion& operator=(const SkRegion&);
+
+ /**
+ * Return true if the two regions are equal. i.e. The enclose exactly
+ * the same area.
+ */
+ bool operator==(const SkRegion& other) const;
+
+ /**
+ * Return true if the two regions are not equal.
+ */
+ bool operator!=(const SkRegion& other) const {
+ return !(*this == other);
+ }
+
+ /**
+ * Replace this region with the specified region, and return true if the
+ * resulting region is non-empty.
+ */
+ bool set(const SkRegion& src) {
+ SkASSERT(&src);
+ *this = src;
+ return !this->isEmpty();
+ }
+
+ /**
+ * Swap the contents of this and the specified region. This operation
+ * is gauarenteed to never fail.
+ */
+ void swap(SkRegion&);
+
+ /** Return true if this region is empty */
+ bool isEmpty() const { return fRunHead == SkRegion_gEmptyRunHeadPtr; }
+
+ /** Return true if this region is a single, non-empty rectangle */
+ bool isRect() const { return fRunHead == SkRegion_gRectRunHeadPtr; }
+
+ /** Return true if this region consists of more than 1 rectangular area */
+ bool isComplex() const { return !this->isEmpty() && !this->isRect(); }
+
+ /**
+ * Return the bounds of this region. If the region is empty, returns an
+ * empty rectangle.
+ */
+ const SkIRect& getBounds() const { return fBounds; }
+
+ /**
+ * Returns a value that grows approximately linearly with the number of
+ * intervals comprised in the region. Empty region will return 0, Rect
+ * will return 1, Complex will return a value > 1.
+ *
+ * Use this to compare two regions, where the larger count likely
+ * indicates a more complex region.
+ */
+ int computeRegionComplexity() const;
+
+ /**
+ * Returns true if the region is non-empty, and if so, appends the
+ * boundary(s) of the region to the specified path.
+ * If the region is empty, returns false, and path is left unmodified.
+ */
+ bool getBoundaryPath(SkPath* path) const;
+
+ /**
+ * Set the region to be empty, and return false, since the resulting
+ * region is empty
+ */
+ bool setEmpty();
+
+ /**
+ * If rect is non-empty, set this region to that rectangle and return true,
+ * otherwise set this region to empty and return false.
+ */
+ bool setRect(const SkIRect&);
+
+ /**
+ * If left < right and top < bottom, set this region to that rectangle and
+ * return true, otherwise set this region to empty and return false.
+ */
+ bool setRect(int32_t left, int32_t top, int32_t right, int32_t bottom);
+
+ /**
+ * Set this region to the union of an array of rects. This is generally
+ * faster than calling region.op(rect, kUnion_Op) in a loop. If count is
+ * 0, then this region is set to the empty region.
+ * @return true if the resulting region is non-empty
+ */
+ bool setRects(const SkIRect rects[], int count);
+
+ /**
+ * Set this region to the specified region, and return true if it is
+ * non-empty.
+ */
+ bool setRegion(const SkRegion&);
+
+ /**
+ * Set this region to the area described by the path, clipped.
+ * Return true if the resulting region is non-empty.
+ * This produces a region that is identical to the pixels that would be
+ * drawn by the path (with no antialiasing) with the specified clip.
+ */
+ bool setPath(const SkPath&, const SkRegion& clip);
+
+ /**
+ * Returns true if the specified rectangle has a non-empty intersection
+ * with this region.
+ */
+ bool intersects(const SkIRect&) const;
+
+ /**
+ * Returns true if the specified region has a non-empty intersection
+ * with this region.
+ */
+ bool intersects(const SkRegion&) const;
+
+ /**
+ * Return true if the specified x,y coordinate is inside the region.
+ */
+ bool contains(int32_t x, int32_t y) const;
+
+ /**
+ * Return true if the specified rectangle is completely inside the region.
+ * This works for simple (rectangular) and complex regions, and always
+ * returns the correct result. Note: if either this region or the rectangle
+ * is empty, contains() returns false.
+ */
+ bool contains(const SkIRect&) const;
+
+ /**
+ * Return true if the specified region is completely inside the region.
+ * This works for simple (rectangular) and complex regions, and always
+ * returns the correct result. Note: if either region is empty, contains()
+ * returns false.
+ */
+ bool contains(const SkRegion&) const;
+
+ /**
+ * Return true if this region is a single rectangle (not complex) and the
+ * specified rectangle is contained by this region. Returning false is not
+ * a guarantee that the rectangle is not contained by this region, but
+ * return true is a guarantee that the rectangle is contained by this region.
+ */
+ bool quickContains(const SkIRect& r) const {
+ return this->quickContains(r.fLeft, r.fTop, r.fRight, r.fBottom);
+ }
+
+ /**
+ * Return true if this region is a single rectangle (not complex) and the
+ * specified rectangle is contained by this region. Returning false is not
+ * a guarantee that the rectangle is not contained by this region, but
+ * return true is a guarantee that the rectangle is contained by this
+ * region.
+ */
+ bool quickContains(int32_t left, int32_t top, int32_t right,
+ int32_t bottom) const {
+ SkASSERT(this->isEmpty() == fBounds.isEmpty()); // valid region
+
+ return left < right && top < bottom &&
+ fRunHead == SkRegion_gRectRunHeadPtr && // this->isRect()
+ /* fBounds.contains(left, top, right, bottom); */
+ fBounds.fLeft <= left && fBounds.fTop <= top &&
+ fBounds.fRight >= right && fBounds.fBottom >= bottom;
+ }
+
+ /**
+ * Return true if this region is empty, or if the specified rectangle does
+ * not intersect the region. Returning false is not a guarantee that they
+ * intersect, but returning true is a guarantee that they do not.
+ */
+ bool quickReject(const SkIRect& rect) const {
+ return this->isEmpty() || rect.isEmpty() ||
+ !SkIRect::Intersects(fBounds, rect);
+ }
+
+ /**
+ * Return true if this region, or rgn, is empty, or if their bounds do not
+ * intersect. Returning false is not a guarantee that they intersect, but
+ * returning true is a guarantee that they do not.
+ */
+ bool quickReject(const SkRegion& rgn) const {
+ return this->isEmpty() || rgn.isEmpty() ||
+ !SkIRect::Intersects(fBounds, rgn.fBounds);
+ }
+
+ /** Translate the region by the specified (dx, dy) amount. */
+ void translate(int dx, int dy) { this->translate(dx, dy, this); }
+
+ /**
+ * Translate the region by the specified (dx, dy) amount, writing the
+ * resulting region into dst. Note: it is legal to pass this region as the
+ * dst parameter, effectively translating the region in place. If dst is
+ * null, nothing happens.
+ */
+ void translate(int dx, int dy, SkRegion* dst) const;
+
+ /**
+ * The logical operations that can be performed when combining two regions.
+ */
+ enum Op {
+ kDifference_Op, //!< subtract the op region from the first region
+ kIntersect_Op, //!< intersect the two regions
+ kUnion_Op, //!< union (inclusive-or) the two regions
+ kXOR_Op, //!< exclusive-or the two regions
+ /** subtract the first region from the op region */
+ kReverseDifference_Op,
+ kReplace_Op //!< replace the dst region with the op region
+ };
+
+ /**
+ * Set this region to the result of applying the Op to this region and the
+ * specified rectangle: this = (this op rect).
+ * Return true if the resulting region is non-empty.
+ */
+ bool op(const SkIRect& rect, Op op) { return this->op(*this, rect, op); }
+
+ /**
+ * Set this region to the result of applying the Op to this region and the
+ * specified rectangle: this = (this op rect).
+ * Return true if the resulting region is non-empty.
+ */
+ bool op(int left, int top, int right, int bottom, Op op) {
+ SkIRect rect;
+ rect.set(left, top, right, bottom);
+ return this->op(*this, rect, op);
+ }
+
+ /**
+ * Set this region to the result of applying the Op to this region and the
+ * specified region: this = (this op rgn).
+ * Return true if the resulting region is non-empty.
+ */
+ bool op(const SkRegion& rgn, Op op) { return this->op(*this, rgn, op); }
+
+ /**
+ * Set this region to the result of applying the Op to the specified
+ * rectangle and region: this = (rect op rgn).
+ * Return true if the resulting region is non-empty.
+ */
+ bool op(const SkIRect& rect, const SkRegion& rgn, Op);
+
+ /**
+ * Set this region to the result of applying the Op to the specified
+ * region and rectangle: this = (rgn op rect).
+ * Return true if the resulting region is non-empty.
+ */
+ bool op(const SkRegion& rgn, const SkIRect& rect, Op);
+
+ /**
+ * Set this region to the result of applying the Op to the specified
+ * regions: this = (rgna op rgnb).
+ * Return true if the resulting region is non-empty.
+ */
+ bool op(const SkRegion& rgna, const SkRegion& rgnb, Op op);
+
+#ifdef SK_BUILD_FOR_ANDROID
+ /** Returns a new char* containing the list of rectangles in this region
+ */
+ char* toString();
+#endif
+
+ /**
+ * Returns the sequence of rectangles, sorted in Y and X, that make up
+ * this region.
+ */
+ class SK_API Iterator {
+ public:
+ Iterator() : fRgn(NULL), fDone(true) {}
+ Iterator(const SkRegion&);
+ // if we have a region, reset to it and return true, else return false
+ bool rewind();
+ // reset the iterator, using the new region
+ void reset(const SkRegion&);
+ bool done() const { return fDone; }
+ void next();
+ const SkIRect& rect() const { return fRect; }
+ // may return null
+ const SkRegion* rgn() const { return fRgn; }
+
+ private:
+ const SkRegion* fRgn;
+ const RunType* fRuns;
+ SkIRect fRect;
+ bool fDone;
+ };
+
+ /**
+ * Returns the sequence of rectangles, sorted in Y and X, that make up
+ * this region intersected with the specified clip rectangle.
+ */
+ class SK_API Cliperator {
+ public:
+ Cliperator(const SkRegion&, const SkIRect& clip);
+ bool done() { return fDone; }
+ void next();
+ const SkIRect& rect() const { return fRect; }
+
+ private:
+ Iterator fIter;
+ SkIRect fClip;
+ SkIRect fRect;
+ bool fDone;
+ };
+
+ /**
+ * Returns the sequence of runs that make up this region for the specified
+ * Y scanline, clipped to the specified left and right X values.
+ */
+ class Spanerator {
+ public:
+ Spanerator(const SkRegion&, int y, int left, int right);
+ bool next(int* left, int* right);
+
+ private:
+ const SkRegion::RunType* fRuns;
+ int fLeft, fRight;
+ bool fDone;
+ };
+
+ /**
+ * Write the region to the buffer, and return the number of bytes written.
+ * If buffer is NULL, it still returns the number of bytes.
+ */
+ uint32_t writeToMemory(void* buffer) const;
+
+ /**
+ * Initialized the region from the buffer, returning the number
+ * of bytes actually read.
+ */
+ uint32_t readFromMemory(const void* buffer);
+
+ /**
+ * Returns a reference to a global empty region. Just a convenience for
+ * callers that need a const empty region.
+ */
+ static const SkRegion& GetEmptyRegion();
+
+ SkDEBUGCODE(void dump() const;)
+ SkDEBUGCODE(void validate() const;)
+ SkDEBUGCODE(static void UnitTest();)
+
+ // expose this to allow for regression test on complex regions
+ SkDEBUGCODE(bool debugSetRuns(const RunType runs[], int count);)
+
+private:
+ enum {
+ kOpCount = kReplace_Op + 1
+ };
+
+ enum {
+ // T
+ // [B N L R S]
+ // S
+ kRectRegionRuns = 7
+ };
+
+ friend class android::Region; // needed for marshalling efficiently
+
+ struct RunHead;
+
+ // allocate space for count runs
+ void allocateRuns(int count);
+ void allocateRuns(int count, int ySpanCount, int intervalCount);
+ void allocateRuns(const RunHead& src);
+
+ SkIRect fBounds;
+ RunHead* fRunHead;
+
+ void freeRuns();
+
+ /**
+ * Return the runs from this region, consing up fake runs if the region
+ * is empty or a rect. In those 2 cases, we use tmpStorage to hold the
+ * run data.
+ */
+ const RunType* getRuns(RunType tmpStorage[], int* intervals) const;
+
+ // This is called with runs[] that do not yet have their interval-count
+ // field set on each scanline. That is computed as part of this call
+ // (inside ComputeRunBounds).
+ bool setRuns(RunType runs[], int count);
+
+ int count_runtype_values(int* itop, int* ibot) const;
+
+ static void BuildRectRuns(const SkIRect& bounds,
+ RunType runs[kRectRegionRuns]);
+
+ // If the runs define a simple rect, return true and set bounds to that
+ // rect. If not, return false and ignore bounds.
+ static bool RunsAreARect(const SkRegion::RunType runs[], int count,
+ SkIRect* bounds);
+
+ /**
+ * If the last arg is null, just return if the result is non-empty,
+ * else store the result in the last arg.
+ */
+ static bool Oper(const SkRegion&, const SkRegion&, SkRegion::Op, SkRegion*);
+
+ friend struct RunHead;
+ friend class Iterator;
+ friend class Spanerator;
+ friend class SkRgnBuilder;
+ friend class SkFlatRegion;
+};
+
+#endif
diff --git a/core/SkScalar.h b/core/SkScalar.h
new file mode 100644
index 0000000..2dd7a62
--- /dev/null
+++ b/core/SkScalar.h
@@ -0,0 +1,341 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkScalar_DEFINED
+#define SkScalar_DEFINED
+
+#include "SkFixed.h"
+#include "SkFloatingPoint.h"
+
+/** \file SkScalar.h
+
+ Types and macros for the data type SkScalar. This is the fractional numeric type
+ that, depending on the compile-time flag SK_SCALAR_IS_FLOAT, may be implemented
+ either as an IEEE float, or as a 16.16 SkFixed. The macros in this file are written
+ to allow the calling code to manipulate SkScalar values without knowing which representation
+ is in effect.
+*/
+
+#ifdef SK_SCALAR_IS_FLOAT
+
+ /** SkScalar is our type for fractional values and coordinates. Depending on
+ compile configurations, it is either represented as an IEEE float, or
+ as a 16.16 fixed point integer.
+ */
+ typedef float SkScalar;
+
+ /** SK_Scalar1 is defined to be 1.0 represented as an SkScalar
+ */
+ #define SK_Scalar1 (1.0f)
+ /** SK_Scalar1 is defined to be 1/2 represented as an SkScalar
+ */
+ #define SK_ScalarHalf (0.5f)
+ /** SK_ScalarInfinity is defined to be infinity as an SkScalar
+ */
+ #define SK_ScalarInfinity SK_FloatInfinity
+ /** SK_ScalarNegativeInfinity is defined to be negative infinity as an SkScalar
+ */
+ #define SK_ScalarNegativeInfinity SK_FloatNegativeInfinity
+ /** SK_ScalarMax is defined to be the largest value representable as an SkScalar
+ */
+ #define SK_ScalarMax (3.402823466e+38f)
+ /** SK_ScalarMin is defined to be the smallest value representable as an SkScalar
+ */
+ #define SK_ScalarMin (-SK_ScalarMax)
+ /** SK_ScalarNaN is defined to be 'Not a Number' as an SkScalar
+ */
+ #define SK_ScalarNaN SK_FloatNaN
+ /** SkScalarIsNaN(n) returns true if argument is not a number
+ */
+ static inline bool SkScalarIsNaN(float x) { return x != x; }
+
+ /** Returns true if x is not NaN and not infinite */
+ static inline bool SkScalarIsFinite(float x) {
+ // We rely on the following behavior of infinities and nans
+ // 0 * finite --> 0
+ // 0 * infinity --> NaN
+ // 0 * NaN --> NaN
+ float prod = x * 0;
+ // At this point, prod will either be NaN or 0
+ // Therefore we can return (prod == prod) or (0 == prod).
+ return prod == prod;
+ }
+
+ /** SkIntToScalar(n) returns its integer argument as an SkScalar
+ */
+ #define SkIntToScalar(n) ((float)(n))
+ /** SkFixedToScalar(n) returns its SkFixed argument as an SkScalar
+ */
+ #define SkFixedToScalar(x) SkFixedToFloat(x)
+ /** SkScalarToFixed(n) returns its SkScalar argument as an SkFixed
+ */
+ #define SkScalarToFixed(x) SkFloatToFixed(x)
+
+ #define SkScalarToFloat(n) (n)
+ #define SkFloatToScalar(n) (n)
+
+ #define SkScalarToDouble(n) (double)(n)
+ #define SkDoubleToScalar(n) (float)(n)
+
+ /** SkScalarFraction(x) returns the signed fractional part of the argument
+ */
+ #define SkScalarFraction(x) sk_float_mod(x, 1.0f)
+
+ #define SkScalarFloorToScalar(x) sk_float_floor(x)
+ #define SkScalarCeilToScalar(x) sk_float_ceil(x)
+ #define SkScalarRoundToScalar(x) sk_float_floor((x) + 0.5f)
+
+ #define SkScalarFloorToInt(x) sk_float_floor2int(x)
+ #define SkScalarCeilToInt(x) sk_float_ceil2int(x)
+ #define SkScalarRoundToInt(x) sk_float_round2int(x)
+ #define SkScalarTruncToInt(x) static_cast<int>(x)
+
+ /** Returns the absolute value of the specified SkScalar
+ */
+ #define SkScalarAbs(x) sk_float_abs(x)
+ /** Return x with the sign of y
+ */
+ #define SkScalarCopySign(x, y) sk_float_copysign(x, y)
+ /** Returns the value pinned between 0 and max inclusive
+ */
+ inline SkScalar SkScalarClampMax(SkScalar x, SkScalar max) {
+ return x < 0 ? 0 : x > max ? max : x;
+ }
+ /** Returns the value pinned between min and max inclusive
+ */
+ inline SkScalar SkScalarPin(SkScalar x, SkScalar min, SkScalar max) {
+ return x < min ? min : x > max ? max : x;
+ }
+ /** Returns the specified SkScalar squared (x*x)
+ */
+ inline SkScalar SkScalarSquare(SkScalar x) { return x * x; }
+ /** Returns the product of two SkScalars
+ */
+ #define SkScalarMul(a, b) ((float)(a) * (b))
+ /** Returns the product of two SkScalars plus a third SkScalar
+ */
+ #define SkScalarMulAdd(a, b, c) ((float)(a) * (b) + (c))
+ /** Returns the product of a SkScalar and an int rounded to the nearest integer value
+ */
+ #define SkScalarMulRound(a, b) SkScalarRound((float)(a) * (b))
+ /** Returns the product of a SkScalar and an int promoted to the next larger int
+ */
+ #define SkScalarMulCeil(a, b) SkScalarCeil((float)(a) * (b))
+ /** Returns the product of a SkScalar and an int truncated to the next smaller int
+ */
+ #define SkScalarMulFloor(a, b) SkScalarFloor((float)(a) * (b))
+ /** Returns the quotient of two SkScalars (a/b)
+ */
+ #define SkScalarDiv(a, b) ((float)(a) / (b))
+ /** Returns the mod of two SkScalars (a mod b)
+ */
+ #define SkScalarMod(x,y) sk_float_mod(x,y)
+ /** Returns the product of the first two arguments, divided by the third argument
+ */
+ #define SkScalarMulDiv(a, b, c) ((float)(a) * (b) / (c))
+ /** Returns the multiplicative inverse of the SkScalar (1/x)
+ */
+ #define SkScalarInvert(x) (SK_Scalar1 / (x))
+ #define SkScalarFastInvert(x) (SK_Scalar1 / (x))
+ /** Returns the square root of the SkScalar
+ */
+ #define SkScalarSqrt(x) sk_float_sqrt(x)
+ /** Returns b to the e
+ */
+ #define SkScalarPow(b, e) sk_float_pow(b, e)
+ /** Returns the average of two SkScalars (a+b)/2
+ */
+ #define SkScalarAve(a, b) (((a) + (b)) * 0.5f)
+ /** Returns the geometric mean of two SkScalars
+ */
+ #define SkScalarMean(a, b) sk_float_sqrt((float)(a) * (b))
+ /** Returns one half of the specified SkScalar
+ */
+ #define SkScalarHalf(a) ((a) * 0.5f)
+
+ #define SK_ScalarSqrt2 1.41421356f
+ #define SK_ScalarPI 3.14159265f
+ #define SK_ScalarTanPIOver8 0.414213562f
+ #define SK_ScalarRoot2Over2 0.707106781f
+
+ #define SkDegreesToRadians(degrees) ((degrees) * (SK_ScalarPI / 180))
+ float SkScalarSinCos(SkScalar radians, SkScalar* cosValue);
+ #define SkScalarSin(radians) (float)sk_float_sin(radians)
+ #define SkScalarCos(radians) (float)sk_float_cos(radians)
+ #define SkScalarTan(radians) (float)sk_float_tan(radians)
+ #define SkScalarASin(val) (float)sk_float_asin(val)
+ #define SkScalarACos(val) (float)sk_float_acos(val)
+ #define SkScalarATan2(y, x) (float)sk_float_atan2(y,x)
+ #define SkScalarExp(x) (float)sk_float_exp(x)
+ #define SkScalarLog(x) (float)sk_float_log(x)
+
+ inline SkScalar SkMaxScalar(SkScalar a, SkScalar b) { return a > b ? a : b; }
+ inline SkScalar SkMinScalar(SkScalar a, SkScalar b) { return a < b ? a : b; }
+
+ static inline bool SkScalarIsInt(SkScalar x) {
+ return x == (float)(int)x;
+ }
+#else
+ typedef SkFixed SkScalar;
+
+ #define SK_Scalar1 SK_Fixed1
+ #define SK_ScalarHalf SK_FixedHalf
+ #define SK_ScalarInfinity SK_FixedMax
+ #define SK_ScalarNegativeInfinity SK_FixedMin
+ #define SK_ScalarMax SK_FixedMax
+ #define SK_ScalarMin SK_FixedMin
+ #define SK_ScalarNaN SK_FixedNaN
+ #define SkScalarIsNaN(x) ((x) == SK_FixedNaN)
+ #define SkScalarIsFinite(x) ((x) != SK_FixedNaN)
+
+ #define SkIntToScalar(n) SkIntToFixed(n)
+ #define SkFixedToScalar(x) (x)
+ #define SkScalarToFixed(x) (x)
+ #define SkScalarToFloat(n) SkFixedToFloat(n)
+ #define SkFloatToScalar(n) SkFloatToFixed(n)
+
+ #define SkScalarToDouble(n) SkFixedToDouble(n)
+ #define SkDoubleToScalar(n) SkDoubleToFixed(n)
+ #define SkScalarFraction(x) SkFixedFraction(x)
+
+ #define SkScalarFloorToScalar(x) SkFixedFloorToFixed(x)
+ #define SkScalarCeilToScalar(x) SkFixedCeilToFixed(x)
+ #define SkScalarRoundToScalar(x) SkFixedRoundToFixed(x)
+
+ #define SkScalarFloorToInt(x) SkFixedFloorToInt(x)
+ #define SkScalarCeilToInt(x) SkFixedCeilToInt(x)
+ #define SkScalarRoundToInt(x) SkFixedRoundToInt(x)
+ #define SkScalarTruncToInt(x) (((x) < 0) ? SkScalarCeilToInt(x) : SkScalarFloorToInt(x))
+
+ #define SkScalarAbs(x) SkFixedAbs(x)
+ #define SkScalarCopySign(x, y) SkCopySign32(x, y)
+ #define SkScalarClampMax(x, max) SkClampMax(x, max)
+ #define SkScalarPin(x, min, max) SkPin32(x, min, max)
+ #define SkScalarSquare(x) SkFixedSquare(x)
+ #define SkScalarMul(a, b) SkFixedMul(a, b)
+ #define SkScalarMulAdd(a, b, c) SkFixedMulAdd(a, b, c)
+ #define SkScalarMulRound(a, b) SkFixedMulCommon(a, b, SK_FixedHalf)
+ #define SkScalarMulCeil(a, b) SkFixedMulCommon(a, b, SK_Fixed1 - 1)
+ #define SkScalarMulFloor(a, b) SkFixedMulCommon(a, b, 0)
+ #define SkScalarDiv(a, b) SkFixedDiv(a, b)
+ #define SkScalarMod(a, b) SkFixedMod(a, b)
+ #define SkScalarMulDiv(a, b, c) SkMulDiv(a, b, c)
+ #define SkScalarInvert(x) SkFixedInvert(x)
+ #define SkScalarFastInvert(x) SkFixedFastInvert(x)
+ #define SkScalarSqrt(x) SkFixedSqrt(x)
+ #define SkScalarAve(a, b) SkFixedAve(a, b)
+ #define SkScalarMean(a, b) SkFixedMean(a, b)
+ #define SkScalarHalf(a) ((a) >> 1)
+
+ #define SK_ScalarSqrt2 SK_FixedSqrt2
+ #define SK_ScalarPI SK_FixedPI
+ #define SK_ScalarTanPIOver8 SK_FixedTanPIOver8
+ #define SK_ScalarRoot2Over2 SK_FixedRoot2Over2
+
+ #define SkDegreesToRadians(degrees) SkFractMul(degrees, SK_FractPIOver180)
+ #define SkScalarSinCos(radians, cosPtr) SkFixedSinCos(radians, cosPtr)
+ #define SkScalarSin(radians) SkFixedSin(radians)
+ #define SkScalarCos(radians) SkFixedCos(radians)
+ #define SkScalarTan(val) SkFixedTan(val)
+ #define SkScalarASin(val) SkFixedASin(val)
+ #define SkScalarACos(val) SkFixedACos(val)
+ #define SkScalarATan2(y, x) SkFixedATan2(y,x)
+ #define SkScalarExp(x) SkFixedExp(x)
+ #define SkScalarLog(x) SkFixedLog(x)
+
+ #define SkMaxScalar(a, b) SkMax32(a, b)
+ #define SkMinScalar(a, b) SkMin32(a, b)
+
+ static inline bool SkScalarIsInt(SkFixed x) {
+ return 0 == (x & 0xffff);
+ }
+#endif
+
+// DEPRECATED : use ToInt or ToScalar variant
+#define SkScalarFloor(x) SkScalarFloorToInt(x)
+#define SkScalarCeil(x) SkScalarCeilToInt(x)
+#define SkScalarRound(x) SkScalarRoundToInt(x)
+
+/**
+ * Returns -1 || 0 || 1 depending on the sign of value:
+ * -1 if x < 0
+ * 0 if x == 0
+ * 1 if x > 0
+ */
+static inline int SkScalarSignAsInt(SkScalar x) {
+ return x < 0 ? -1 : (x > 0);
+}
+
+// Scalar result version of above
+static inline SkScalar SkScalarSignAsScalar(SkScalar x) {
+ return x < 0 ? -SK_Scalar1 : ((x > 0) ? SK_Scalar1 : 0);
+}
+
+#define SK_ScalarNearlyZero (SK_Scalar1 / (1 << 12))
+
+static inline bool SkScalarNearlyZero(SkScalar x,
+ SkScalar tolerance = SK_ScalarNearlyZero) {
+ SkASSERT(tolerance >= 0);
+ return SkScalarAbs(x) <= tolerance;
+}
+
+static inline bool SkScalarNearlyEqual(SkScalar x, SkScalar y,
+ SkScalar tolerance = SK_ScalarNearlyZero) {
+ SkASSERT(tolerance >= 0);
+ return SkScalarAbs(x-y) <= tolerance;
+}
+
+/** Linearly interpolate between A and B, based on t.
+ If t is 0, return A
+ If t is 1, return B
+ else interpolate.
+ t must be [0..SK_Scalar1]
+*/
+static inline SkScalar SkScalarInterp(SkScalar A, SkScalar B, SkScalar t) {
+ SkASSERT(t >= 0 && t <= SK_Scalar1);
+ return A + SkScalarMul(B - A, t);
+}
+
+static inline SkScalar SkScalarLog2(SkScalar x) {
+ static const SkScalar log2_conversion_factor = SkScalarDiv(1, SkScalarLog(2));
+
+ return SkScalarMul(SkScalarLog(x), log2_conversion_factor);
+}
+
+/** Interpolate along the function described by (keys[length], values[length])
+ for the passed searchKey. SearchKeys outside the range keys[0]-keys[Length]
+ clamp to the min or max value. This function was inspired by a desire
+ to change the multiplier for thickness in fakeBold; therefore it assumes
+ the number of pairs (length) will be small, and a linear search is used.
+ Repeated keys are allowed for discontinuous functions (so long as keys is
+ monotonically increasing), and if key is the value of a repeated scalar in
+ keys, the first one will be used. However, that may change if a binary
+ search is used.
+*/
+SkScalar SkScalarInterpFunc(SkScalar searchKey, const SkScalar keys[],
+ const SkScalar values[], int length);
+
+/*
+ * Helper to compare an array of scalars.
+ */
+static inline bool SkScalarsEqual(const SkScalar a[], const SkScalar b[], int n) {
+#ifdef SK_SCALAR_IS_FLOAT
+ SkASSERT(n >= 0);
+ for (int i = 0; i < n; ++i) {
+ if (a[i] != b[i]) {
+ return false;
+ }
+ }
+ return true;
+#else
+ return 0 == memcmp(a, b, n * sizeof(SkScalar));
+#endif
+}
+
+#endif
diff --git a/core/SkScalarCompare.h b/core/SkScalarCompare.h
new file mode 100644
index 0000000..5361294
--- /dev/null
+++ b/core/SkScalarCompare.h
@@ -0,0 +1,38 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkScalarCompare_DEFINED
+#define SkScalarCompare_DEFINED
+
+#include "SkFloatBits.h"
+#include "SkRect.h"
+
+/** Skia can spend a lot of time just comparing scalars (e.g. quickReject).
+ When scalar==fixed, this is very fast, and when scalar==hardware-float, this
+ is also reasonable, but if scalar==software-float, then each compare can be
+ a function call and take real time. To account for that, we have the flag
+ SK_SCALAR_SLOW_COMPARES.
+
+ If this is defined, we have a special trick where we quickly convert floats
+ to a 2's compliment form, and then treat them as signed 32bit integers. In
+ this form we lose a few subtlties (e.g. NaNs always comparing false) but
+ we gain the speed of integer compares.
+ */
+
+#ifdef SK_SCALAR_SLOW_COMPARES
+ typedef int32_t SkScalarCompareType;
+ typedef SkIRect SkRectCompareType;
+ #define SkScalarToCompareType(x) SkScalarAs2sCompliment(x)
+#else
+ typedef SkScalar SkScalarCompareType;
+ typedef SkRect SkRectCompareType;
+ #define SkScalarToCompareType(x) (x)
+#endif
+
+#endif
diff --git a/core/SkShader.h b/core/SkShader.h
new file mode 100644
index 0000000..e1cab96
--- /dev/null
+++ b/core/SkShader.h
@@ -0,0 +1,377 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkShader_DEFINED
+#define SkShader_DEFINED
+
+#include "SkBitmap.h"
+#include "SkFlattenable.h"
+#include "SkMask.h"
+#include "SkMatrix.h"
+#include "SkPaint.h"
+
+class SkPath;
+class GrContext;
+class GrEffectRef;
+
+/** \class SkShader
+ *
+ * Shaders specify the source color(s) for what is being drawn. If a paint
+ * has no shader, then the paint's color is used. If the paint has a
+ * shader, then the shader's color(s) are use instead, but they are
+ * modulated by the paint's alpha. This makes it easy to create a shader
+ * once (e.g. bitmap tiling or gradient) and then change its transparency
+ * w/o having to modify the original shader... only the paint's alpha needs
+ * to be modified.
+ */
+class SK_API SkShader : public SkFlattenable {
+public:
+ SK_DECLARE_INST_COUNT(SkShader)
+
+ SkShader();
+ virtual ~SkShader();
+
+ /**
+ * Returns true if the local matrix is not an identity matrix.
+ */
+ bool hasLocalMatrix() const { return !fLocalMatrix.isIdentity(); }
+
+ /**
+ * Returns the local matrix.
+ */
+ const SkMatrix& getLocalMatrix() const { return fLocalMatrix; }
+
+ /**
+ * Set the shader's local matrix.
+ * @param localM The shader's new local matrix.
+ */
+ void setLocalMatrix(const SkMatrix& localM) { fLocalMatrix = localM; }
+
+ /**
+ * Reset the shader's local matrix to identity.
+ */
+ void resetLocalMatrix() { fLocalMatrix.reset(); }
+
+ enum TileMode {
+ /** replicate the edge color if the shader draws outside of its
+ * original bounds
+ */
+ kClamp_TileMode,
+
+ /** repeat the shader's image horizontally and vertically */
+ kRepeat_TileMode,
+
+ /** repeat the shader's image horizontally and vertically, alternating
+ * mirror images so that adjacent images always seam
+ */
+ kMirror_TileMode,
+
+#if 0
+ /** only draw within the original domain, return 0 everywhere else */
+ kDecal_TileMode,
+#endif
+
+ kTileModeCount
+ };
+
+ // override these in your subclass
+
+ enum Flags {
+ //!< set if all of the colors will be opaque
+ kOpaqueAlpha_Flag = 0x01,
+
+ //! set if this shader's shadeSpan16() method can be called
+ kHasSpan16_Flag = 0x02,
+
+ /** Set this bit if the shader's native data type is instrinsically 16
+ bit, meaning that calling the 32bit shadeSpan() entry point will
+ mean the the impl has to up-sample 16bit data into 32bit. Used as a
+ a means of clearing a dither request if the it will have no effect
+ */
+ kIntrinsicly16_Flag = 0x04,
+
+ /** set (after setContext) if the spans only vary in X (const in Y).
+ e.g. an Nx1 bitmap that is being tiled in Y, or a linear-gradient
+ that varies from left-to-right. This flag specifies this for
+ shadeSpan().
+ */
+ kConstInY32_Flag = 0x08,
+
+ /** same as kConstInY32_Flag, but is set if this is true for shadeSpan16
+ which may not always be the case, since shadeSpan16 may be
+ predithered, which would mean it was not const in Y, even though
+ the 32bit shadeSpan() would be const.
+ */
+ kConstInY16_Flag = 0x10
+ };
+
+ /**
+ * Called sometimes before drawing with this shader. Return the type of
+ * alpha your shader will return. The default implementation returns 0.
+ * Your subclass should override if it can (even sometimes) report a
+ * non-zero value, since that will enable various blitters to perform
+ * faster.
+ */
+ virtual uint32_t getFlags() { return 0; }
+
+ /**
+ * Returns true if the shader is guaranteed to produce only opaque
+ * colors, subject to the SkPaint using the shader to apply an opaque
+ * alpha value. Subclasses should override this to allow some
+ * optimizations. isOpaque() can be called at any time, unlike getFlags,
+ * which only works properly when the context is set.
+ */
+ virtual bool isOpaque() const { return false; }
+
+ /**
+ * Return the alpha associated with the data returned by shadeSpan16(). If
+ * kHasSpan16_Flag is not set, this value is meaningless.
+ */
+ virtual uint8_t getSpan16Alpha() const { return fPaintAlpha; }
+
+ /**
+ * Called once before drawing, with the current paint and device matrix.
+ * Return true if your shader supports these parameters, or false if not.
+ * If false is returned, nothing will be drawn. If true is returned, then
+ * a balancing call to endContext() will be made before the next call to
+ * setContext.
+ *
+ * Subclasses should be sure to call their INHERITED::setContext() if they
+ * override this method.
+ */
+ virtual bool setContext(const SkBitmap& device, const SkPaint& paint,
+ const SkMatrix& matrix);
+
+ /**
+ * Assuming setContext returned true, endContext() will be called when
+ * the draw using the shader has completed. It is an error for setContext
+ * to be called twice w/o an intervening call to endContext().
+ *
+ * Subclasses should be sure to call their INHERITED::endContext() if they
+ * override this method.
+ */
+ virtual void endContext();
+
+ SkDEBUGCODE(bool setContextHasBeenCalled() const { return SkToBool(fInSetContext); })
+
+ /**
+ * Called for each span of the object being drawn. Your subclass should
+ * set the appropriate colors (with premultiplied alpha) that correspond
+ * to the specified device coordinates.
+ */
+ virtual void shadeSpan(int x, int y, SkPMColor[], int count) = 0;
+
+ typedef void (*ShadeProc)(void* ctx, int x, int y, SkPMColor[], int count);
+ virtual ShadeProc asAShadeProc(void** ctx);
+
+ /**
+ * Called only for 16bit devices when getFlags() returns
+ * kOpaqueAlphaFlag | kHasSpan16_Flag
+ */
+ virtual void shadeSpan16(int x, int y, uint16_t[], int count);
+
+ /**
+ * Similar to shadeSpan, but only returns the alpha-channel for a span.
+ * The default implementation calls shadeSpan() and then extracts the alpha
+ * values from the returned colors.
+ */
+ virtual void shadeSpanAlpha(int x, int y, uint8_t alpha[], int count);
+
+ /**
+ * Helper function that returns true if this shader's shadeSpan16() method
+ * can be called.
+ */
+ bool canCallShadeSpan16() {
+ return SkShader::CanCallShadeSpan16(this->getFlags());
+ }
+
+ /**
+ * Helper to check the flags to know if it is legal to call shadeSpan16()
+ */
+ static bool CanCallShadeSpan16(uint32_t flags) {
+ return (flags & kHasSpan16_Flag) != 0;
+ }
+
+ /**
+ Gives method bitmap should be read to implement a shader.
+ Also determines number and interpretation of "extra" parameters returned
+ by asABitmap
+ */
+ enum BitmapType {
+ kNone_BitmapType, //<! Shader is not represented as a bitmap
+ kDefault_BitmapType,//<! Access bitmap using local coords transformed
+ // by matrix. No extras
+ kRadial_BitmapType, //<! Access bitmap by transforming local coordinates
+ // by the matrix and taking the distance of result
+ // from (0,0) as bitmap column. Bitmap is 1 pixel
+ // tall. No extras
+ kSweep_BitmapType, //<! Access bitmap by transforming local coordinates
+ // by the matrix and taking the angle of result
+ // to (0,0) as bitmap x coord, where angle = 0 is
+ // bitmap left edge of bitmap = 2pi is the
+ // right edge. Bitmap is 1 pixel tall. No extras
+ kTwoPointRadial_BitmapType,
+ //<! Matrix transforms to space where (0,0) is
+ // the center of the starting circle. The second
+ // circle will be centered (x, 0) where x may be
+ // 0. The post-matrix space is normalized such
+ // that 1 is the second radius - first radius.
+ // Three extra parameters are returned:
+ // 0: x-offset of second circle center
+ // to first.
+ // 1: radius of first circle in post-matrix
+ // space
+ // 2: the second radius minus the first radius
+ // in pre-transformed space.
+ kTwoPointConical_BitmapType,
+ //<! Matrix transforms to space where (0,0) is
+ // the center of the starting circle. The second
+ // circle will be centered (x, 0) where x may be
+ // 0.
+ // Three extra parameters are returned:
+ // 0: x-offset of second circle center
+ // to first.
+ // 1: radius of first circle
+ // 2: the second radius minus the first radius
+ kLinear_BitmapType, //<! Access bitmap using local coords transformed
+ // by matrix. No extras
+
+ kLast_BitmapType = kLinear_BitmapType
+ };
+ /** Optional methods for shaders that can pretend to be a bitmap/texture
+ to play along with opengl. Default just returns kNone_BitmapType and
+ ignores the out parameters.
+
+ @param outTexture if non-NULL will be the bitmap representing the shader
+ after return.
+ @param outMatrix if non-NULL will be the matrix to apply to vertices
+ to access the bitmap after return.
+ @param xy if non-NULL will be the tile modes that should be
+ used to access the bitmap after return.
+ @param twoPointRadialParams Two extra return values needed for two point
+ radial bitmaps. The first is the x-offset of
+ the second point and the second is the radius
+ about the first point.
+ */
+ virtual BitmapType asABitmap(SkBitmap* outTexture, SkMatrix* outMatrix,
+ TileMode xy[2]) const;
+
+ /**
+ * If the shader subclass can be represented as a gradient, asAGradient
+ * returns the matching GradientType enum (or kNone_GradientType if it
+ * cannot). Also, if info is not null, asAGradient populates info with
+ * the relevant (see below) parameters for the gradient. fColorCount
+ * is both an input and output parameter. On input, it indicates how
+ * many entries in fColors and fColorOffsets can be used, if they are
+ * non-NULL. After asAGradient has run, fColorCount indicates how
+ * many color-offset pairs there are in the gradient. If there is
+ * insufficient space to store all of the color-offset pairs, fColors
+ * and fColorOffsets will not be altered. fColorOffsets specifies
+ * where on the range of 0 to 1 to transition to the given color.
+ * The meaning of fPoint and fRadius is dependant on the type of gradient.
+ *
+ * None:
+ * info is ignored.
+ * Color:
+ * fColorOffsets[0] is meaningless.
+ * Linear:
+ * fPoint[0] and fPoint[1] are the end-points of the gradient
+ * Radial:
+ * fPoint[0] and fRadius[0] are the center and radius
+ * Radial2:
+ * fPoint[0] and fRadius[0] are the center and radius of the 1st circle
+ * fPoint[1] and fRadius[1] are the center and radius of the 2nd circle
+ * Sweep:
+ * fPoint[0] is the center of the sweep.
+ */
+
+ enum GradientType {
+ kNone_GradientType,
+ kColor_GradientType,
+ kLinear_GradientType,
+ kRadial_GradientType,
+ kRadial2_GradientType,
+ kSweep_GradientType,
+ kConical_GradientType,
+ kLast_GradientType = kConical_GradientType
+ };
+
+ struct GradientInfo {
+ int fColorCount; //!< In-out parameter, specifies passed size
+ // of fColors/fColorOffsets on input, and
+ // actual number of colors/offsets on
+ // output.
+ SkColor* fColors; //!< The colors in the gradient.
+ SkScalar* fColorOffsets; //!< The unit offset for color transitions.
+ SkPoint fPoint[2]; //!< Type specific, see above.
+ SkScalar fRadius[2]; //!< Type specific, see above.
+ TileMode fTileMode; //!< The tile mode used.
+ uint32_t fGradientFlags; //!< see SkGradientShader::Flags
+ };
+
+ virtual GradientType asAGradient(GradientInfo* info) const;
+
+ /**
+ * If the shader subclass has a GrEffect implementation, this installs an effect on the stage.
+ * The GrContext may be used by the effect to create textures. The GPU device does not call
+ * setContext. Instead we pass the paint here in case the shader needs paint info.
+ */
+ virtual GrEffectRef* asNewEffect(GrContext* context, const SkPaint& paint) const;
+
+ //////////////////////////////////////////////////////////////////////////
+ // Factory methods for stock shaders
+
+ /** Call this to create a new shader that will draw with the specified bitmap.
+ *
+ * If the bitmap cannot be used (e.g. has no pixels, or its dimensions
+ * exceed implementation limits (currently at 64K - 1)) then SkEmptyShader
+ * may be returned.
+ *
+ * @param src The bitmap to use inside the shader
+ * @param tmx The tiling mode to use when sampling the bitmap in the x-direction.
+ * @param tmy The tiling mode to use when sampling the bitmap in the y-direction.
+ * @return Returns a new shader object. Note: this function never returns null.
+ */
+ static SkShader* CreateBitmapShader(const SkBitmap& src,
+ TileMode tmx, TileMode tmy);
+
+ SkDEVCODE(virtual void toString(SkString* str) const;)
+
+protected:
+ enum MatrixClass {
+ kLinear_MatrixClass, // no perspective
+ kFixedStepInX_MatrixClass, // fast perspective, need to call fixedStepInX() each scanline
+ kPerspective_MatrixClass // slow perspective, need to mappoints each pixel
+ };
+ static MatrixClass ComputeMatrixClass(const SkMatrix&);
+
+ // These can be called by your subclass after setContext() has been called
+ uint8_t getPaintAlpha() const { return fPaintAlpha; }
+ SkBitmap::Config getDeviceConfig() const { return (SkBitmap::Config)fDeviceConfig; }
+ const SkMatrix& getTotalInverse() const { return fTotalInverse; }
+ MatrixClass getInverseClass() const { return (MatrixClass)fTotalInverseClass; }
+
+ SkShader(SkFlattenableReadBuffer& );
+ virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
+private:
+ SkMatrix fLocalMatrix;
+ SkMatrix fTotalInverse;
+ uint8_t fPaintAlpha;
+ uint8_t fDeviceConfig;
+ uint8_t fTotalInverseClass;
+ SkDEBUGCODE(SkBool8 fInSetContext;)
+
+ static SkShader* CreateBitmapShader(const SkBitmap& src,
+ TileMode, TileMode,
+ void* storage, size_t storageSize);
+ friend class SkAutoBitmapShaderInstall;
+ typedef SkFlattenable INHERITED;
+};
+
+#endif
diff --git a/core/SkSize.h b/core/SkSize.h
new file mode 100644
index 0000000..01c6e35
--- /dev/null
+++ b/core/SkSize.h
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkSize_DEFINED
+#define SkSize_DEFINED
+
+#include "SkScalar.h"
+
+template <typename T> struct SkTSize {
+ T fWidth;
+ T fHeight;
+
+ static SkTSize Make(T w, T h) {
+ SkTSize s;
+ s.fWidth = w;
+ s.fHeight = h;
+ return s;
+ }
+
+ void set(T w, T h) {
+ fWidth = w;
+ fHeight = h;
+ }
+
+ /** Returns true iff fWidth == 0 && fHeight == 0
+ */
+ bool isZero() const {
+ return 0 == fWidth && 0 == fHeight;
+ }
+
+ /** Returns true if either widht or height are <= 0 */
+ bool isEmpty() const {
+ return fWidth <= 0 || fHeight <= 0;
+ }
+
+ /** Set the width and height to 0 */
+ void setEmpty() {
+ fWidth = fHeight = 0;
+ }
+
+ T width() const { return fWidth; }
+ T height() const { return fHeight; }
+
+ /** If width or height is < 0, it is set to 0 */
+ void clampNegToZero() {
+ if (fWidth < 0) {
+ fWidth = 0;
+ }
+ if (fHeight < 0) {
+ fHeight = 0;
+ }
+ }
+
+ bool equals(T w, T h) const {
+ return fWidth == w && fHeight == h;
+ }
+};
+
+template <typename T>
+static inline bool operator==(const SkTSize<T>& a, const SkTSize<T>& b) {
+ return a.fWidth == b.fWidth && a.fHeight == b.fHeight;
+}
+
+template <typename T>
+static inline bool operator!=(const SkTSize<T>& a, const SkTSize<T>& b) {
+ return !(a == b);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+typedef SkTSize<int32_t> SkISize;
+
+struct SkSize : public SkTSize<SkScalar> {
+ static SkSize Make(SkScalar w, SkScalar h) {
+ SkSize s;
+ s.fWidth = w;
+ s.fHeight = h;
+ return s;
+ }
+
+
+ SkSize& operator=(const SkISize& src) {
+ this->set(SkIntToScalar(src.fWidth), SkIntToScalar(src.fHeight));
+ return *this;
+ }
+
+ SkISize toRound() const {
+ SkISize s;
+ s.set(SkScalarRound(fWidth), SkScalarRound(fHeight));
+ return s;
+ }
+
+ SkISize toCeil() const {
+ SkISize s;
+ s.set(SkScalarCeil(fWidth), SkScalarCeil(fHeight));
+ return s;
+ }
+
+ SkISize toFloor() const {
+ SkISize s;
+ s.set(SkScalarFloor(fWidth), SkScalarFloor(fHeight));
+ return s;
+ }
+};
+
+#endif
diff --git a/core/SkStream.h b/core/SkStream.h
new file mode 100644
index 0000000..d7a105d
--- /dev/null
+++ b/core/SkStream.h
@@ -0,0 +1,467 @@
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkStream_DEFINED
+#define SkStream_DEFINED
+
+#include "SkRefCnt.h"
+#include "SkScalar.h"
+
+class SkData;
+
+class SkStream;
+class SkStreamRewindable;
+class SkStreamSeekable;
+class SkStreamAsset;
+class SkStreamMemory;
+
+/**
+ * SkStream -- abstraction for a source of bytes. Subclasses can be backed by
+ * memory, or a file, or something else.
+ *
+ * NOTE:
+ *
+ * Classic "streams" APIs are sort of async, in that on a request for N
+ * bytes, they may return fewer than N bytes on a given call, in which case
+ * the caller can "try again" to get more bytes, eventually (modulo an error)
+ * receiving their total N bytes.
+ *
+ * Skia streams behave differently. They are effectively synchronous, and will
+ * always return all N bytes of the request if possible. If they return fewer
+ * (the read() call returns the number of bytes read) then that means there is
+ * no more data (at EOF or hit an error). The caller should *not* call again
+ * in hopes of fulfilling more of the request.
+ */
+class SK_API SkStream : public SkRefCnt { //TODO: remove SkRefCnt
+public:
+ /**
+ * Attempts to open the specified file, and return a stream to it (using
+ * mmap if available). On success, the caller must call unref() on the
+ * returned object. On failure, returns NULL.
+ */
+ static SkStreamAsset* NewFromFile(const char path[]);
+
+ SK_DECLARE_INST_COUNT(SkStream)
+
+ /** Reads or skips size number of bytes.
+ * If buffer == NULL, skip size bytes, return how many were skipped.
+ * If buffer != NULL, copy size bytes into buffer, return how many were copied.
+ * @param buffer when NULL skip size bytes, otherwise copy size bytes into buffer
+ * @param size the number of bytes to skip or copy
+ * @return the number of bytes actually read.
+ */
+ virtual size_t read(void* buffer, size_t size) = 0;
+
+ /** Skip size number of bytes.
+ * @return the actual number bytes that could be skipped.
+ */
+ size_t skip(size_t size) {
+ //return this->read(NULL, size);
+ //TODO: remove this old logic after updating existing implementations
+ return 0 == size ? 0 : this->read(NULL, size);
+ }
+
+ /** Returns true when all the bytes in the stream have been read.
+ * This may return true early (when there are no more bytes to be read)
+ * or late (after the first unsuccessful read).
+ *
+ * In Progress: do not use until all implementations are updated.
+ * TODO: after this is implemented everywhere, make pure virtual.
+ */
+ virtual bool isAtEnd() const {
+ SkASSERT(false);
+ return true;
+ }
+
+ int8_t readS8();
+ int16_t readS16();
+ int32_t readS32();
+
+ uint8_t readU8() { return (uint8_t)this->readS8(); }
+ uint16_t readU16() { return (uint16_t)this->readS16(); }
+ uint32_t readU32() { return (uint32_t)this->readS32(); }
+
+ bool readBool() { return this->readU8() != 0; }
+ SkScalar readScalar();
+ size_t readPackedUInt();
+
+ /**
+ * Reconstitute an SkData object that was written to the stream
+ * using SkWStream::writeData().
+ */
+ SkData* readData();
+
+//SkStreamRewindable
+ /** Rewinds to the beginning of the stream. If this cannot be done, return false. */
+ virtual bool rewind() { return false; }
+
+ /** Duplicates this stream. If this cannot be done, returns NULL.
+ * The returned stream will be positioned at the beginning of its data.
+ */
+ virtual SkStreamRewindable* duplicate() const { return NULL; }
+
+//SkStreamSeekable
+ /** Returns true if this stream can report it's current position. */
+ virtual bool hasPosition() const { return false; }
+ /** Returns the current position in the stream. If this cannot be done, returns 0. */
+ virtual size_t getPosition() const { return 0; }
+
+ /** Seeks to an absolute position in the stream. If this cannot be done, returns false.
+ * If an attempt is made to seek past the end of the stream, the position will be set
+ * to the end of the stream.
+ */
+ virtual bool seek(size_t position) { return false; }
+
+ /** Seeks to an relative offset in the stream. If this cannot be done, returns false.
+ * If an attempt is made to move to a position outside the stream, the position will be set
+ * to the closest point within the stream (beginning or end).
+ */
+ virtual bool move(long offset) { return false; }
+
+ /** Duplicates this stream. If this cannot be done, returns NULL.
+ * The returned stream will be positioned the same as this stream.
+ */
+ virtual SkStreamSeekable* fork() const { return NULL; }
+
+//SkStreamAsset
+ /** Returns true if this stream can report it's total length. */
+ virtual bool hasLength() const { return false; }
+ /** Returns the total length of the stream. If this cannot be done, returns 0. */
+ virtual size_t getLength() const {
+ //return 0;
+ //TODO: remove the following after everyone is updated.
+ return ((SkStream*)this)->read(NULL, 0);
+ }
+
+//SkStreamMemory
+ /** Returns the starting address for the data. If this cannot be done, returns NULL. */
+ //TODO: replace with virtual const SkData* getData()
+ virtual const void* getMemoryBase() { return NULL; }
+
+private:
+ typedef SkRefCnt INHERITED;
+};
+
+/** SkStreamRewindable is a SkStream for which rewind and duplicate are required. */
+class SK_API SkStreamRewindable : public SkStream {
+public:
+ //TODO: remove the following after everyone is updated (ensures new behavior on new classes).
+ virtual bool isAtEnd() const SK_OVERRIDE = 0;
+ //TODO: remove the following after everyone is updated (ensures new behavior on new classes).
+ virtual size_t getLength() const SK_OVERRIDE { return 0; }
+
+ virtual bool rewind() SK_OVERRIDE = 0;
+ virtual SkStreamRewindable* duplicate() const SK_OVERRIDE = 0;
+};
+
+/** SkStreamSeekable is a SkStreamRewindable for which position, seek, move, and fork are required. */
+class SK_API SkStreamSeekable : public SkStreamRewindable {
+public:
+ virtual SkStreamSeekable* duplicate() const SK_OVERRIDE = 0;
+
+ virtual bool hasPosition() const SK_OVERRIDE { return true; }
+ virtual size_t getPosition() const SK_OVERRIDE = 0;
+ virtual bool seek(size_t position) SK_OVERRIDE = 0;
+ virtual bool move(long offset) SK_OVERRIDE = 0;
+ virtual SkStreamSeekable* fork() const SK_OVERRIDE = 0;
+};
+
+/** SkStreamAsset is a SkStreamSeekable for which getLength is required. */
+class SK_API SkStreamAsset : public SkStreamSeekable {
+public:
+ virtual SkStreamAsset* duplicate() const SK_OVERRIDE = 0;
+ virtual SkStreamAsset* fork() const SK_OVERRIDE = 0;
+
+ virtual bool hasLength() const SK_OVERRIDE { return true; }
+ virtual size_t getLength() const SK_OVERRIDE = 0;
+};
+
+/** SkStreamMemory is a SkStreamAsset for which getMemoryBase is required. */
+class SK_API SkStreamMemory : public SkStreamAsset {
+public:
+ virtual SkStreamMemory* duplicate() const SK_OVERRIDE = 0;
+ virtual SkStreamMemory* fork() const SK_OVERRIDE = 0;
+
+ virtual const void* getMemoryBase() SK_OVERRIDE = 0;
+};
+
+class SK_API SkWStream : SkNoncopyable {
+public:
+ SK_DECLARE_INST_COUNT_ROOT(SkWStream)
+
+ virtual ~SkWStream();
+
+ /** Called to write bytes to a SkWStream. Returns true on success
+ @param buffer the address of at least size bytes to be written to the stream
+ @param size The number of bytes in buffer to write to the stream
+ @return true on success
+ */
+ virtual bool write(const void* buffer, size_t size) = 0;
+ virtual void newline();
+ virtual void flush();
+
+ // helpers
+
+ bool write8(U8CPU);
+ bool write16(U16CPU);
+ bool write32(uint32_t);
+
+ bool writeText(const char text[]);
+ bool writeDecAsText(int32_t);
+ bool writeBigDecAsText(int64_t, int minDigits = 0);
+ bool writeHexAsText(uint32_t, int minDigits = 0);
+ bool writeScalarAsText(SkScalar);
+
+ bool writeBool(bool v) { return this->write8(v); }
+ bool writeScalar(SkScalar);
+ bool writePackedUInt(size_t);
+
+ bool writeStream(SkStream* input, size_t length);
+
+ /**
+ * Append an SkData object to the stream, such that it can be read
+ * out of the stream using SkStream::readData().
+ *
+ * Note that the encoding method used to write the SkData object
+ * to the stream may change over time. This method DOES NOT
+ * just write the raw content of the SkData object to the stream.
+ */
+ bool writeData(const SkData*);
+};
+
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include "SkString.h"
+
+struct SkFILE;
+
+/** A stream that wraps a C FILE* file stream. */
+class SK_API SkFILEStream : public SkStreamAsset {
+public:
+ SK_DECLARE_INST_COUNT(SkFILEStream)
+
+ /** Initialize the stream by calling sk_fopen on the specified path.
+ * This internal stream will be closed in the destructor.
+ */
+ explicit SkFILEStream(const char path[] = NULL);
+
+ enum Ownership {
+ kCallerPasses_Ownership,
+ kCallerRetains_Ownership
+ };
+ /** Initialize the stream with an existing C file stream.
+ * While this stream exists, it assumes exclusive access to the C file stream.
+ * The C file stream will be closed in the destructor unless the caller specifies
+ * kCallerRetains_Ownership.
+ */
+ explicit SkFILEStream(FILE* file, Ownership ownership = kCallerPasses_Ownership);
+
+ virtual ~SkFILEStream();
+
+ /** Returns true if the current path could be opened. */
+ bool isValid() const { return fFILE != NULL; }
+
+ /** Close the current file, and open a new file with the specified path.
+ * If path is NULL, just close the current file.
+ */
+ void setPath(const char path[]);
+
+ virtual size_t read(void* buffer, size_t size) SK_OVERRIDE;
+ virtual bool isAtEnd() const SK_OVERRIDE;
+
+ virtual bool rewind() SK_OVERRIDE;
+ virtual SkStreamAsset* duplicate() const SK_OVERRIDE;
+
+ virtual size_t getPosition() const SK_OVERRIDE;
+ virtual bool seek(size_t position) SK_OVERRIDE;
+ virtual bool move(long offset) SK_OVERRIDE;
+ virtual SkStreamAsset* fork() const SK_OVERRIDE;
+
+ virtual size_t getLength() const SK_OVERRIDE;
+
+ virtual const void* getMemoryBase() SK_OVERRIDE;
+
+private:
+ SkFILE* fFILE;
+ SkString fName;
+ Ownership fOwnership;
+ // fData is lazilly initialized when needed.
+ mutable SkAutoTUnref<SkData> fData;
+
+ typedef SkStreamAsset INHERITED;
+};
+
+class SK_API SkMemoryStream : public SkStreamMemory {
+public:
+ SK_DECLARE_INST_COUNT(SkMemoryStream)
+
+ SkMemoryStream();
+
+ /** We allocate (and free) the memory. Write to it via getMemoryBase() */
+ SkMemoryStream(size_t length);
+
+ /** If copyData is true, the stream makes a private copy of the data. */
+ SkMemoryStream(const void* data, size_t length, bool copyData = false);
+
+ /** Use the specified data as the memory for this stream.
+ * The stream will call ref() on the data (assuming it is not NULL).
+ */
+ SkMemoryStream(SkData*);
+
+ virtual ~SkMemoryStream();
+
+ /** Resets the stream to the specified data and length,
+ just like the constructor.
+ if copyData is true, the stream makes a private copy of the data
+ */
+ virtual void setMemory(const void* data, size_t length,
+ bool copyData = false);
+ /** Replace any memory buffer with the specified buffer. The caller
+ must have allocated data with sk_malloc or sk_realloc, since it
+ will be freed with sk_free.
+ */
+ void setMemoryOwned(const void* data, size_t length);
+
+ /** Return the stream's data in a SkData.
+ * The caller must call unref() when it is finished using the data.
+ */
+ SkData* copyToData() const;
+
+ /**
+ * Use the specified data as the memory for this stream.
+ * The stream will call ref() on the data (assuming it is not NULL).
+ * The function returns the data parameter as a convenience.
+ */
+ SkData* setData(SkData*);
+
+ void skipToAlign4();
+ const void* getAtPos();
+ size_t peek() const { return fOffset; }
+
+ virtual size_t read(void* buffer, size_t size) SK_OVERRIDE;
+ virtual bool isAtEnd() const SK_OVERRIDE;
+
+ virtual bool rewind() SK_OVERRIDE;
+ virtual SkMemoryStream* duplicate() const SK_OVERRIDE;
+
+ virtual size_t getPosition() const SK_OVERRIDE;
+ virtual bool seek(size_t position) SK_OVERRIDE;
+ virtual bool move(long offset) SK_OVERRIDE;
+ virtual SkMemoryStream* fork() const SK_OVERRIDE;
+
+ virtual size_t getLength() const SK_OVERRIDE;
+
+ virtual const void* getMemoryBase() SK_OVERRIDE;
+
+private:
+ SkData* fData;
+ size_t fOffset;
+
+ typedef SkStreamMemory INHERITED;
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+
+class SK_API SkFILEWStream : public SkWStream {
+public:
+ SK_DECLARE_INST_COUNT(SkFILEWStream)
+
+ SkFILEWStream(const char path[]);
+ virtual ~SkFILEWStream();
+
+ /** Returns true if the current path could be opened.
+ */
+ bool isValid() const { return fFILE != NULL; }
+
+ virtual bool write(const void* buffer, size_t size) SK_OVERRIDE;
+ virtual void flush() SK_OVERRIDE;
+
+private:
+ SkFILE* fFILE;
+
+ typedef SkWStream INHERITED;
+};
+
+class SkMemoryWStream : public SkWStream {
+public:
+ SK_DECLARE_INST_COUNT(SkMemoryWStream)
+
+ SkMemoryWStream(void* buffer, size_t size);
+ virtual bool write(const void* buffer, size_t size) SK_OVERRIDE;
+ size_t bytesWritten() const { return fBytesWritten; }
+
+private:
+ char* fBuffer;
+ size_t fMaxLength;
+ size_t fBytesWritten;
+
+ typedef SkWStream INHERITED;
+};
+
+class SK_API SkDynamicMemoryWStream : public SkWStream {
+public:
+ SK_DECLARE_INST_COUNT(SkDynamicMemoryWStream)
+
+ SkDynamicMemoryWStream();
+ virtual ~SkDynamicMemoryWStream();
+
+ virtual bool write(const void* buffer, size_t size) SK_OVERRIDE;
+ // random access write
+ // modifies stream and returns true if offset + size is less than or equal to getOffset()
+ bool write(const void* buffer, size_t offset, size_t size);
+ bool read(void* buffer, size_t offset, size_t size);
+ size_t getOffset() const { return fBytesWritten; }
+ size_t bytesWritten() const { return fBytesWritten; }
+
+ // copy what has been written to the stream into dst
+ void copyTo(void* dst) const;
+
+ /**
+ * Return a copy of the data written so far. This call is responsible for
+ * calling unref() when they are finished with the data.
+ */
+ SkData* copyToData() const;
+
+ /** Reset, returning a reader stream with the current content. */
+ SkStreamAsset* detachAsStream();
+
+ /** Reset the stream to its original, empty, state. */
+ void reset();
+ void padToAlign4();
+private:
+ struct Block;
+ Block* fHead;
+ Block* fTail;
+ size_t fBytesWritten;
+ mutable SkData* fCopy; // is invalidated if we write after it is created
+
+ void invalidateCopy();
+
+ // For access to the Block type.
+ friend class SkBlockMemoryStream;
+ friend class SkBlockMemoryRefCnt;
+
+ typedef SkWStream INHERITED;
+};
+
+
+class SK_API SkDebugWStream : public SkWStream {
+public:
+ SK_DECLARE_INST_COUNT(SkDebugWStream)
+
+ // overrides
+ virtual bool write(const void* buffer, size_t size) SK_OVERRIDE;
+ virtual void newline() SK_OVERRIDE;
+
+private:
+ typedef SkWStream INHERITED;
+};
+
+// for now
+typedef SkFILEStream SkURLStream;
+
+#endif
diff --git a/core/SkString.h b/core/SkString.h
new file mode 100644
index 0000000..5d97533
--- /dev/null
+++ b/core/SkString.h
@@ -0,0 +1,265 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkString_DEFINED
+#define SkString_DEFINED
+
+#include "SkScalar.h"
+
+#include <stdarg.h>
+
+/* Some helper functions for C strings
+*/
+
+static bool SkStrStartsWith(const char string[], const char prefixStr[]) {
+ SkASSERT(string);
+ SkASSERT(prefixStr);
+ return !strncmp(string, prefixStr, strlen(prefixStr));
+}
+static bool SkStrStartsWith(const char string[], const char prefixChar) {
+ SkASSERT(string);
+ return (prefixChar == *string);
+}
+
+bool SkStrEndsWith(const char string[], const char suffixStr[]);
+bool SkStrEndsWith(const char string[], const char suffixChar);
+
+int SkStrStartsWithOneOf(const char string[], const char prefixes[]);
+
+static int SkStrFind(const char string[], const char substring[]) {
+ const char *first = strstr(string, substring);
+ if (NULL == first) return -1;
+ return SkToS32(first - &string[0]);
+}
+
+static bool SkStrContains(const char string[], const char substring[]) {
+ SkASSERT(string);
+ SkASSERT(substring);
+ return (-1 != SkStrFind(string, substring));
+}
+static bool SkStrContains(const char string[], const char subchar) {
+ SkASSERT(string);
+ char tmp[2];
+ tmp[0] = subchar;
+ tmp[1] = '\0';
+ return (-1 != SkStrFind(string, tmp));
+}
+
+static inline char *SkStrDup(const char string[]) {
+ char *ret = (char *) sk_malloc_throw(strlen(string)+1);
+ memcpy(ret,string,strlen(string)+1);
+ return ret;
+}
+
+
+
+#define SkStrAppendU32_MaxSize 10
+char* SkStrAppendU32(char buffer[], uint32_t);
+#define SkStrAppendU64_MaxSize 20
+char* SkStrAppendU64(char buffer[], uint64_t, int minDigits);
+
+#define SkStrAppendS32_MaxSize (SkStrAppendU32_MaxSize + 1)
+char* SkStrAppendS32(char buffer[], int32_t);
+#define SkStrAppendS64_MaxSize (SkStrAppendU64_MaxSize + 1)
+char* SkStrAppendS64(char buffer[], int64_t, int minDigits);
+
+/**
+ * Floats have at most 8 significant digits, so we limit our %g to that.
+ * However, the total string could be 15 characters: -1.2345678e-005
+ *
+ * In theory we should only expect up to 2 digits for the exponent, but on
+ * some platforms we have seen 3 (as in the example above).
+ */
+#define SkStrAppendScalar_MaxSize 15
+
+/**
+ * Write the scaler in decimal format into buffer, and return a pointer to
+ * the next char after the last one written. Note: a terminating 0 is not
+ * written into buffer, which must be at least SkStrAppendScalar_MaxSize.
+ * Thus if the caller wants to add a 0 at the end, buffer must be at least
+ * SkStrAppendScalar_MaxSize + 1 bytes large.
+ */
+#ifdef SK_SCALAR_IS_FLOAT
+ #define SkStrAppendScalar SkStrAppendFloat
+#else
+ #define SkStrAppendScalar SkStrAppendFixed
+#endif
+
+char* SkStrAppendFloat(char buffer[], float);
+char* SkStrAppendFixed(char buffer[], SkFixed);
+
+/** \class SkString
+
+ Light weight class for managing strings. Uses reference
+ counting to make string assignments and copies very fast
+ with no extra RAM cost. Assumes UTF8 encoding.
+*/
+class SK_API SkString {
+public:
+ SkString();
+ explicit SkString(size_t len);
+ explicit SkString(const char text[]);
+ SkString(const char text[], size_t len);
+ SkString(const SkString&);
+ ~SkString();
+
+ bool isEmpty() const { return 0 == fRec->fLength; }
+ size_t size() const { return (size_t) fRec->fLength; }
+ const char* c_str() const { return fRec->data(); }
+ char operator[](size_t n) const { return this->c_str()[n]; }
+
+ bool equals(const SkString&) const;
+ bool equals(const char text[]) const;
+ bool equals(const char text[], size_t len) const;
+
+ bool startsWith(const char prefixStr[]) const {
+ return SkStrStartsWith(fRec->data(), prefixStr);
+ }
+ bool startsWith(const char prefixChar) const {
+ return SkStrStartsWith(fRec->data(), prefixChar);
+ }
+ bool endsWith(const char suffixStr[]) const {
+ return SkStrEndsWith(fRec->data(), suffixStr);
+ }
+ bool endsWith(const char suffixChar) const {
+ return SkStrEndsWith(fRec->data(), suffixChar);
+ }
+ bool contains(const char substring[]) const {
+ return SkStrContains(fRec->data(), substring);
+ }
+ bool contains(const char subchar) const {
+ return SkStrContains(fRec->data(), subchar);
+ }
+ int find(const char substring[]) const {
+ return SkStrFind(fRec->data(), substring);
+ }
+
+ friend bool operator==(const SkString& a, const SkString& b) {
+ return a.equals(b);
+ }
+ friend bool operator!=(const SkString& a, const SkString& b) {
+ return !a.equals(b);
+ }
+
+ // these methods edit the string
+
+ SkString& operator=(const SkString&);
+ SkString& operator=(const char text[]);
+
+ char* writable_str();
+ char& operator[](size_t n) { return this->writable_str()[n]; }
+
+ void reset();
+ void resize(size_t len) { this->set(NULL, len); }
+ void set(const SkString& src) { *this = src; }
+ void set(const char text[]);
+ void set(const char text[], size_t len);
+ void setUTF16(const uint16_t[]);
+ void setUTF16(const uint16_t[], size_t len);
+
+ void insert(size_t offset, const SkString& src) { this->insert(offset, src.c_str(), src.size()); }
+ void insert(size_t offset, const char text[]);
+ void insert(size_t offset, const char text[], size_t len);
+ void insertUnichar(size_t offset, SkUnichar);
+ void insertS32(size_t offset, int32_t value);
+ void insertS64(size_t offset, int64_t value, int minDigits = 0);
+ void insertU32(size_t offset, uint32_t value);
+ void insertU64(size_t offset, uint64_t value, int minDigits = 0);
+ void insertHex(size_t offset, uint32_t value, int minDigits = 0);
+ void insertScalar(size_t offset, SkScalar);
+
+ void append(const SkString& str) { this->insert((size_t)-1, str); }
+ void append(const char text[]) { this->insert((size_t)-1, text); }
+ void append(const char text[], size_t len) { this->insert((size_t)-1, text, len); }
+ void appendUnichar(SkUnichar uni) { this->insertUnichar((size_t)-1, uni); }
+ void appendS32(int32_t value) { this->insertS32((size_t)-1, value); }
+ void appendS64(int64_t value, int minDigits = 0) { this->insertS64((size_t)-1, value, minDigits); }
+ void appendU32(uint32_t value) { this->insertU32((size_t)-1, value); }
+ void appendU64(uint64_t value, int minDigits = 0) { this->insertU64((size_t)-1, value, minDigits); }
+ void appendHex(uint32_t value, int minDigits = 0) { this->insertHex((size_t)-1, value, minDigits); }
+ void appendScalar(SkScalar value) { this->insertScalar((size_t)-1, value); }
+
+ void prepend(const SkString& str) { this->insert(0, str); }
+ void prepend(const char text[]) { this->insert(0, text); }
+ void prepend(const char text[], size_t len) { this->insert(0, text, len); }
+ void prependUnichar(SkUnichar uni) { this->insertUnichar(0, uni); }
+ void prependS32(int32_t value) { this->insertS32(0, value); }
+ void prependS64(int32_t value, int minDigits = 0) { this->insertS64(0, value, minDigits); }
+ void prependHex(uint32_t value, int minDigits = 0) { this->insertHex(0, value, minDigits); }
+ void prependScalar(SkScalar value) { this->insertScalar((size_t)-1, value); }
+
+ void printf(const char format[], ...) SK_PRINTF_LIKE(2, 3);
+ void appendf(const char format[], ...) SK_PRINTF_LIKE(2, 3);
+ void appendf(const char format[], va_list);
+ void prependf(const char format[], ...) SK_PRINTF_LIKE(2, 3);
+
+ void remove(size_t offset, size_t length);
+
+ SkString& operator+=(const SkString& s) { this->append(s); return *this; }
+ SkString& operator+=(const char text[]) { this->append(text); return *this; }
+ SkString& operator+=(const char c) { this->append(&c, 1); return *this; }
+
+ /**
+ * Swap contents between this and other. This function is guaranteed
+ * to never fail or throw.
+ */
+ void swap(SkString& other);
+
+private:
+ struct Rec {
+ public:
+ uint32_t fLength; // logically size_t, but we want it to stay 32bits
+ int32_t fRefCnt;
+ char fBeginningOfData;
+
+ char* data() { return &fBeginningOfData; }
+ const char* data() const { return &fBeginningOfData; }
+ };
+ Rec* fRec;
+
+#ifdef SK_DEBUG
+ const char* fStr;
+ void validate() const;
+#else
+ void validate() const {}
+#endif
+
+ static const Rec gEmptyRec;
+ static Rec* AllocRec(const char text[], size_t len);
+ static Rec* RefRec(Rec*);
+};
+
+class SkAutoUCS2 {
+public:
+ SkAutoUCS2(const char utf8[]);
+ ~SkAutoUCS2();
+
+ /** This returns the number of ucs2 characters
+ */
+ int count() const { return fCount; }
+
+ /** This returns a null terminated ucs2 string
+ */
+ const uint16_t* getUCS2() const { return fUCS2; }
+
+private:
+ int fCount;
+ uint16_t* fUCS2;
+};
+
+/// Creates a new string and writes into it using a printf()-style format.
+SkString SkStringPrintf(const char* format, ...);
+
+// Specialized to take advantage of SkString's fast swap path. The unspecialized function is
+// declared in SkTypes.h and called by SkTSort.
+template <> inline void SkTSwap(SkString& a, SkString& b) {
+ a.swap(b);
+}
+
+#endif
diff --git a/core/SkStringUtils.h b/core/SkStringUtils.h
new file mode 100644
index 0000000..aa5c809
--- /dev/null
+++ b/core/SkStringUtils.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkStringUtils_DEFINED
+#define SkStringUtils_DEFINED
+
+class SkString;
+
+/**
+ * Add 'flagStr' to 'string' and set 'needSeparator' to true only if 'flag' is
+ * true. If 'needSeparator' is true append a '|' before 'flagStr'. This method
+ * is used to streamline the creation of ASCII flag strings within the toString
+ * methods.
+ */
+void SkAddFlagToString(SkString* string, bool flag,
+ const char* flagStr, bool* needSeparator);
+
+
+#endif
diff --git a/core/SkStrokeRec.h b/core/SkStrokeRec.h
new file mode 100644
index 0000000..c5b47c2
--- /dev/null
+++ b/core/SkStrokeRec.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkStrokeRec_DEFINED
+#define SkStrokeRec_DEFINED
+
+#include "SkPaint.h"
+
+class SkPath;
+
+class SkStrokeRec {
+public:
+ enum InitStyle {
+ kHairline_InitStyle,
+ kFill_InitStyle
+ };
+ SkStrokeRec(InitStyle style);
+
+ SkStrokeRec(const SkStrokeRec&);
+ explicit SkStrokeRec(const SkPaint&);
+
+ enum Style {
+ kHairline_Style,
+ kFill_Style,
+ kStroke_Style,
+ kStrokeAndFill_Style
+ };
+
+ Style getStyle() const;
+ SkScalar getWidth() const { return fWidth; }
+ SkScalar getMiter() const { return fMiterLimit; }
+ SkPaint::Cap getCap() const { return fCap; }
+ SkPaint::Join getJoin() const { return fJoin; }
+
+ bool isHairlineStyle() const {
+ return kHairline_Style == this->getStyle();
+ }
+
+ bool isFillStyle() const {
+ return kFill_Style == this->getStyle();
+ }
+
+ void setFillStyle();
+ void setHairlineStyle();
+ /**
+ * Specify the strokewidth, and optionally if you want stroke + fill.
+ * Note, if width==0, then this request is taken to mean:
+ * strokeAndFill==true -> new style will be Fill
+ * strokeAndFill==false -> new style will be Hairline
+ */
+ void setStrokeStyle(SkScalar width, bool strokeAndFill = false);
+
+ void setStrokeParams(SkPaint::Cap cap, SkPaint::Join join, SkScalar miterLimit) {
+ fCap = cap;
+ fJoin = join;
+ fMiterLimit = miterLimit;
+ }
+
+ /**
+ * Returns true if this specifes any thick stroking, i.e. applyToPath()
+ * will return true.
+ */
+ bool needToApply() const {
+ Style style = this->getStyle();
+ return (kStroke_Style == style) || (kStrokeAndFill_Style == style);
+ }
+
+ /**
+ * Apply these stroke parameters to the src path, returning the result
+ * in dst.
+ *
+ * If there was no change (i.e. style == hairline or fill) this returns
+ * false and dst is unchanged. Otherwise returns true and the result is
+ * stored in dst.
+ *
+ * src and dst may be the same path.
+ */
+ bool applyToPath(SkPath* dst, const SkPath& src) const;
+
+private:
+ SkScalar fWidth;
+ SkScalar fMiterLimit;
+ SkPaint::Cap fCap;
+ SkPaint::Join fJoin;
+ bool fStrokeAndFill;
+};
+
+#endif
diff --git a/core/SkSurface.h b/core/SkSurface.h
new file mode 100644
index 0000000..a713277
--- /dev/null
+++ b/core/SkSurface.h
@@ -0,0 +1,158 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkSurface_DEFINED
+#define SkSurface_DEFINED
+
+#include "SkRefCnt.h"
+#include "SkImage.h"
+
+class SkCanvas;
+class SkPaint;
+class GrContext;
+class GrRenderTarget;
+
+/**
+ * SkSurface represents the backend/results of drawing to a canvas. For raster
+ * drawing, the surface will be pixels, but (for example) when drawing into
+ * a PDF or Picture canvas, the surface stores the recorded commands.
+ *
+ * To draw into a canvas, first create the appropriate type of Surface, and
+ * then request the canvas from the surface.
+ */
+class SK_API SkSurface : public SkRefCnt {
+public:
+ SK_DECLARE_INST_COUNT(SkSurface)
+
+ /**
+ * Create a new surface, using the specified pixels/rowbytes as its
+ * backend.
+ *
+ * If the requested surface cannot be created, or the request is not a
+ * supported configuration, NULL will be returned.
+ */
+ static SkSurface* NewRasterDirect(const SkImage::Info&, void* pixels, size_t rowBytes);
+
+ /**
+ * Return a new surface, with the memory for the pixels automatically
+ * allocated.
+ *
+ * If the requested surface cannot be created, or the request is not a
+ * supported configuration, NULL will be returned.
+ */
+ static SkSurface* NewRaster(const SkImage::Info&);
+
+ /**
+ * Return a new surface whose contents will be recorded into a picture.
+ * When this surface is drawn into another canvas, its contents will be
+ * "replayed" into that canvas.
+ */
+ static SkSurface* NewPicture(int width, int height);
+
+ /**
+ * Return a new surface using the specified render target.
+ */
+ static SkSurface* NewRenderTargetDirect(GrContext*, GrRenderTarget*);
+
+ /**
+ * Return a new surface whose contents will be drawn to an offscreen
+ * render target, allocated by the surface.
+ */
+ static SkSurface* NewRenderTarget(GrContext*, const SkImage::Info&, int sampleCount = 0);
+
+ int width() const { return fWidth; }
+ int height() const { return fHeight; }
+
+ /**
+ * Returns a unique non-zero, unique value identifying the content of this
+ * surface. Each time the content is changed changed, either by drawing
+ * into this surface, or explicitly calling notifyContentChanged()) this
+ * method will return a new value.
+ *
+ * If this surface is empty (i.e. has a zero-dimention), this will return
+ * 0.
+ */
+ uint32_t generationID();
+
+ /**
+ * Modes that can be passed to notifyContentWillChange
+ */
+ enum ContentChangeMode {
+ /**
+ * Use this mode if it is known that the upcoming content changes will
+ * clear or overwrite prior contents, thus making them discardable.
+ */
+ kDiscard_ContentChangeMode,
+ /**
+ * Use this mode if prior surface contents need to be preserved or
+ * if in doubt.
+ */
+ kRetain_ContentChangeMode,
+ };
+
+ /**
+ * Call this if the contents are about to change. This will (lazily) force a new
+ * value to be returned from generationID() when it is called next.
+ */
+ void notifyContentWillChange(ContentChangeMode mode);
+
+ /**
+ * Return a canvas that will draw into this surface. This will always
+ * return the same canvas for a given surface, and is manged/owned by the
+ * surface. It should not be used when its parent surface has gone out of
+ * scope.
+ */
+ SkCanvas* getCanvas();
+
+ /**
+ * Return a new surface that is "compatible" with this one, in that it will
+ * efficiently be able to be drawn into this surface. Typical calling
+ * pattern:
+ *
+ * SkSurface* A = SkSurface::New...();
+ * SkCanvas* canvasA = surfaceA->newCanvas();
+ * ...
+ * SkSurface* surfaceB = surfaceA->newSurface(...);
+ * SkCanvas* canvasB = surfaceB->newCanvas();
+ * ... // draw using canvasB
+ * canvasA->drawSurface(surfaceB); // <--- this will always be optimal!
+ */
+ SkSurface* newSurface(const SkImage::Info&);
+
+ /**
+ * Returns an image of the current state of the surface pixels up to this
+ * point. Subsequent changes to the surface (by drawing into its canvas)
+ * will not be reflected in this image.
+ */
+ SkImage* newImageSnapshot();
+
+ /**
+ * Thought the caller could get a snapshot image explicitly, and draw that,
+ * it seems that directly drawing a surface into another canvas might be
+ * a common pattern, and that we could possibly be more efficient, since
+ * we'd know that the "snapshot" need only live until we've handed it off
+ * to the canvas.
+ */
+ void draw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*);
+
+protected:
+ SkSurface(int width, int height);
+
+ // called by subclass if their contents have changed
+ void dirtyGenerationID() {
+ fGenerationID = 0;
+ }
+
+private:
+ const int fWidth;
+ const int fHeight;
+ uint32_t fGenerationID;
+
+ typedef SkRefCnt INHERITED;
+};
+
+#endif
diff --git a/core/SkTArray.h b/core/SkTArray.h
new file mode 100644
index 0000000..b5ecdc9
--- /dev/null
+++ b/core/SkTArray.h
@@ -0,0 +1,506 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkTArray_DEFINED
+#define SkTArray_DEFINED
+
+#include <new>
+#include "SkTypes.h"
+#include "SkTemplates.h"
+
+template <typename T, bool MEM_COPY = false> class SkTArray;
+
+namespace SkTArrayExt {
+
+template<typename T>
+inline void copy(SkTArray<T, true>* self, const T* array) {
+ memcpy(self->fMemArray, array, self->fCount * sizeof(T));
+}
+template<typename T>
+inline void copyAndDelete(SkTArray<T, true>* self, char* newMemArray) {
+ memcpy(newMemArray, self->fMemArray, self->fCount * sizeof(T));
+}
+
+template<typename T>
+inline void copy(SkTArray<T, false>* self, const T* array) {
+ for (int i = 0; i < self->fCount; ++i) {
+ SkNEW_PLACEMENT_ARGS(self->fItemArray + i, T, (array[i]));
+ }
+}
+template<typename T>
+inline void copyAndDelete(SkTArray<T, false>* self, char* newMemArray) {
+ for (int i = 0; i < self->fCount; ++i) {
+ SkNEW_PLACEMENT_ARGS(newMemArray + sizeof(T) * i, T, (self->fItemArray[i]));
+ self->fItemArray[i].~T();
+ }
+}
+
+}
+
+template <typename T, bool MEM_COPY> void* operator new(size_t, SkTArray<T, MEM_COPY>*, int);
+
+/** When MEM_COPY is true T will be bit copied when moved.
+ When MEM_COPY is false, T will be copy constructed / destructed.
+ In all cases T's constructor will be called on allocation,
+ and its destructor will be called from this object's destructor.
+*/
+template <typename T, bool MEM_COPY> class SkTArray {
+public:
+ /**
+ * Creates an empty array with no initial storage
+ */
+ SkTArray() {
+ fCount = 0;
+ fReserveCount = gMIN_ALLOC_COUNT;
+ fAllocCount = 0;
+ fMemArray = NULL;
+ fPreAllocMemArray = NULL;
+ }
+
+ /**
+ * Creates an empty array that will preallocate space for reserveCount
+ * elements.
+ */
+ explicit SkTArray(int reserveCount) {
+ this->init(NULL, 0, NULL, reserveCount);
+ }
+
+ /**
+ * Copies one array to another. The new array will be heap allocated.
+ */
+ explicit SkTArray(const SkTArray& array) {
+ this->init(array.fItemArray, array.fCount, NULL, 0);
+ }
+
+ /**
+ * Creates a SkTArray by copying contents of a standard C array. The new
+ * array will be heap allocated. Be careful not to use this constructor
+ * when you really want the (void*, int) version.
+ */
+ SkTArray(const T* array, int count) {
+ this->init(array, count, NULL, 0);
+ }
+
+ /**
+ * assign copy of array to this
+ */
+ SkTArray& operator =(const SkTArray& array) {
+ for (int i = 0; i < fCount; ++i) {
+ fItemArray[i].~T();
+ }
+ fCount = 0;
+ this->checkRealloc((int)array.count());
+ fCount = array.count();
+ SkTArrayExt::copy(this, static_cast<const T*>(array.fMemArray));
+ return *this;
+ }
+
+ virtual ~SkTArray() {
+ for (int i = 0; i < fCount; ++i) {
+ fItemArray[i].~T();
+ }
+ if (fMemArray != fPreAllocMemArray) {
+ sk_free(fMemArray);
+ }
+ }
+
+ /**
+ * Resets to count() == 0
+ */
+ void reset() { this->pop_back_n(fCount); }
+
+ /**
+ * Resets to count() = n newly constructed T objects.
+ */
+ void reset(int n) {
+ SkASSERT(n >= 0);
+ for (int i = 0; i < fCount; ++i) {
+ fItemArray[i].~T();
+ }
+ // set fCount to 0 before calling checkRealloc so that no copy cons. are called.
+ fCount = 0;
+ this->checkRealloc(n);
+ fCount = n;
+ for (int i = 0; i < fCount; ++i) {
+ SkNEW_PLACEMENT(fItemArray + i, T);
+ }
+ }
+
+ /**
+ * Resets to a copy of a C array.
+ */
+ void reset(const T* array, int count) {
+ for (int i = 0; i < fCount; ++i) {
+ fItemArray[i].~T();
+ }
+ int delta = count - fCount;
+ this->checkRealloc(delta);
+ fCount = count;
+ for (int i = 0; i < count; ++i) {
+ SkTArrayExt::copy(this, array);
+ }
+ }
+
+ /**
+ * Number of elements in the array.
+ */
+ int count() const { return fCount; }
+
+ /**
+ * Is the array empty.
+ */
+ bool empty() const { return !fCount; }
+
+ /**
+ * Adds 1 new default-constructed T value and returns in by reference. Note
+ * the reference only remains valid until the next call that adds or removes
+ * elements.
+ */
+ T& push_back() {
+ T* newT = reinterpret_cast<T*>(this->push_back_raw(1));
+ SkNEW_PLACEMENT(newT, T);
+ return *newT;
+ }
+
+ /**
+ * Version of above that uses a copy constructor to initialize the new item
+ */
+ T& push_back(const T& t) {
+ T* newT = reinterpret_cast<T*>(this->push_back_raw(1));
+ SkNEW_PLACEMENT_ARGS(newT, T, (t));
+ return *newT;
+ }
+
+ /**
+ * Allocates n more default T values, and returns the address of the start
+ * of that new range. Note: this address is only valid until the next API
+ * call made on the array that might add or remove elements.
+ */
+ T* push_back_n(int n) {
+ SkASSERT(n >= 0);
+ T* newTs = reinterpret_cast<T*>(this->push_back_raw(n));
+ for (int i = 0; i < n; ++i) {
+ SkNEW_PLACEMENT(newTs + i, T);
+ }
+ return newTs;
+ }
+
+ /**
+ * Version of above that uses a copy constructor to initialize all n items
+ * to the same T.
+ */
+ T* push_back_n(int n, const T& t) {
+ SkASSERT(n >= 0);
+ T* newTs = reinterpret_cast<T*>(this->push_back_raw(n));
+ for (int i = 0; i < n; ++i) {
+ SkNEW_PLACEMENT_ARGS(newTs[i], T, (t));
+ }
+ return newTs;
+ }
+
+ /**
+ * Version of above that uses a copy constructor to initialize the n items
+ * to separate T values.
+ */
+ T* push_back_n(int n, const T t[]) {
+ SkASSERT(n >= 0);
+ this->checkRealloc(n);
+ for (int i = 0; i < n; ++i) {
+ SkNEW_PLACEMENT_ARGS(fItemArray + fCount + i, T, (t[i]));
+ }
+ fCount += n;
+ return fItemArray + fCount - n;
+ }
+
+ /**
+ * Removes the last element. Not safe to call when count() == 0.
+ */
+ void pop_back() {
+ SkASSERT(fCount > 0);
+ --fCount;
+ fItemArray[fCount].~T();
+ this->checkRealloc(0);
+ }
+
+ /**
+ * Removes the last n elements. Not safe to call when count() < n.
+ */
+ void pop_back_n(int n) {
+ SkASSERT(n >= 0);
+ SkASSERT(fCount >= n);
+ fCount -= n;
+ for (int i = 0; i < n; ++i) {
+ fItemArray[fCount + i].~T();
+ }
+ this->checkRealloc(0);
+ }
+
+ /**
+ * Pushes or pops from the back to resize. Pushes will be default
+ * initialized.
+ */
+ void resize_back(int newCount) {
+ SkASSERT(newCount >= 0);
+
+ if (newCount > fCount) {
+ this->push_back_n(newCount - fCount);
+ } else if (newCount < fCount) {
+ this->pop_back_n(fCount - newCount);
+ }
+ }
+
+ T* begin() {
+ return fItemArray;
+ }
+ const T* begin() const {
+ return fItemArray;
+ }
+ T* end() {
+ return fItemArray ? fItemArray + fCount : NULL;
+ }
+ const T* end() const {
+ return fItemArray ? fItemArray + fCount : NULL;;
+ }
+
+ /**
+ * Get the i^th element.
+ */
+ T& operator[] (int i) {
+ SkASSERT(i < fCount);
+ SkASSERT(i >= 0);
+ return fItemArray[i];
+ }
+
+ const T& operator[] (int i) const {
+ SkASSERT(i < fCount);
+ SkASSERT(i >= 0);
+ return fItemArray[i];
+ }
+
+ /**
+ * equivalent to operator[](0)
+ */
+ T& front() { SkASSERT(fCount > 0); return fItemArray[0];}
+
+ const T& front() const { SkASSERT(fCount > 0); return fItemArray[0];}
+
+ /**
+ * equivalent to operator[](count() - 1)
+ */
+ T& back() { SkASSERT(fCount); return fItemArray[fCount - 1];}
+
+ const T& back() const { SkASSERT(fCount > 0); return fItemArray[fCount - 1];}
+
+ /**
+ * equivalent to operator[](count()-1-i)
+ */
+ T& fromBack(int i) {
+ SkASSERT(i >= 0);
+ SkASSERT(i < fCount);
+ return fItemArray[fCount - i - 1];
+ }
+
+ const T& fromBack(int i) const {
+ SkASSERT(i >= 0);
+ SkASSERT(i < fCount);
+ return fItemArray[fCount - i - 1];
+ }
+
+ bool operator==(const SkTArray<T, MEM_COPY>& right) const {
+ int leftCount = this->count();
+ if (leftCount != right.count()) {
+ return false;
+ }
+ for (int index = 0; index < leftCount; ++index) {
+ if (fItemArray[index] != right.fItemArray[index]) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ bool operator!=(const SkTArray<T, MEM_COPY>& right) const {
+ return !(*this == right);
+ }
+
+protected:
+ /**
+ * Creates an empty array that will use the passed storage block until it
+ * is insufficiently large to hold the entire array.
+ */
+ template <int N>
+ SkTArray(SkAlignedSTStorage<N,T>* storage) {
+ this->init(NULL, 0, storage->get(), N);
+ }
+
+ /**
+ * Copy another array, using preallocated storage if preAllocCount >=
+ * array.count(). Otherwise storage will only be used when array shrinks
+ * to fit.
+ */
+ template <int N>
+ SkTArray(const SkTArray& array, SkAlignedSTStorage<N,T>* storage) {
+ this->init(array.fItemArray, array.fCount, storage->get(), N);
+ }
+
+ /**
+ * Copy a C array, using preallocated storage if preAllocCount >=
+ * count. Otherwise storage will only be used when array shrinks
+ * to fit.
+ */
+ template <int N>
+ SkTArray(const T* array, int count, SkAlignedSTStorage<N,T>* storage) {
+ this->init(array, count, storage->get(), N);
+ }
+
+ void init(const T* array, int count,
+ void* preAllocStorage, int preAllocOrReserveCount) {
+ SkASSERT(count >= 0);
+ SkASSERT(preAllocOrReserveCount >= 0);
+ fCount = count;
+ fReserveCount = (preAllocOrReserveCount > 0) ?
+ preAllocOrReserveCount :
+ gMIN_ALLOC_COUNT;
+ fPreAllocMemArray = preAllocStorage;
+ if (fReserveCount >= fCount &&
+ NULL != preAllocStorage) {
+ fAllocCount = fReserveCount;
+ fMemArray = preAllocStorage;
+ } else {
+ fAllocCount = SkMax32(fCount, fReserveCount);
+ fMemArray = sk_malloc_throw(fAllocCount * sizeof(T));
+ }
+
+ SkTArrayExt::copy(this, array);
+ }
+
+private:
+
+ static const int gMIN_ALLOC_COUNT = 8;
+
+ // Helper function that makes space for n objects, adjusts the count, but does not initialize
+ // the new objects.
+ void* push_back_raw(int n) {
+ this->checkRealloc(n);
+ void* ptr = fItemArray + fCount;
+ fCount += n;
+ return ptr;
+ }
+
+ inline void checkRealloc(int delta) {
+ SkASSERT(fCount >= 0);
+ SkASSERT(fAllocCount >= 0);
+
+ SkASSERT(-delta <= fCount);
+
+ int newCount = fCount + delta;
+ int newAllocCount = fAllocCount;
+
+ if (newCount > fAllocCount || newCount < (fAllocCount / 3)) {
+ // whether we're growing or shrinking, we leave at least 50% extra space for future
+ // growth (clamped to the reserve count).
+ newAllocCount = SkMax32(newCount + ((newCount + 1) >> 1), fReserveCount);
+ }
+ if (newAllocCount != fAllocCount) {
+
+ fAllocCount = newAllocCount;
+ char* newMemArray;
+
+ if (fAllocCount == fReserveCount && NULL != fPreAllocMemArray) {
+ newMemArray = (char*) fPreAllocMemArray;
+ } else {
+ newMemArray = (char*) sk_malloc_throw(fAllocCount*sizeof(T));
+ }
+
+ SkTArrayExt::copyAndDelete<T>(this, newMemArray);
+
+ if (fMemArray != fPreAllocMemArray) {
+ sk_free(fMemArray);
+ }
+ fMemArray = newMemArray;
+ }
+ }
+
+ friend void* operator new<T>(size_t, SkTArray*, int);
+
+ template<typename X> friend void SkTArrayExt::copy(SkTArray<X, true>* that, const X*);
+ template<typename X> friend void SkTArrayExt::copyAndDelete(SkTArray<X, true>* that, char*);
+
+ template<typename X> friend void SkTArrayExt::copy(SkTArray<X, false>* that, const X*);
+ template<typename X> friend void SkTArrayExt::copyAndDelete(SkTArray<X, false>* that, char*);
+
+ int fReserveCount;
+ int fCount;
+ int fAllocCount;
+ void* fPreAllocMemArray;
+ union {
+ T* fItemArray;
+ void* fMemArray;
+ };
+};
+
+// Use the below macro (SkNEW_APPEND_TO_TARRAY) rather than calling this directly
+template <typename T, bool MEM_COPY>
+void* operator new(size_t, SkTArray<T, MEM_COPY>* array, int atIndex) {
+ // Currently, we only support adding to the end of the array. When the array class itself
+ // supports random insertion then this should be updated.
+ // SkASSERT(atIndex >= 0 && atIndex <= array->count());
+ SkASSERT(atIndex == array->count());
+ return array->push_back_raw(1);
+}
+
+// Skia doesn't use C++ exceptions but it may be compiled with them enabled. Having an op delete
+// to match the op new silences warnings about missing op delete when a constructor throws an
+// exception.
+template <typename T, bool MEM_COPY>
+void operator delete(void*, SkTArray<T, MEM_COPY>* array, int atIndex) {
+ SK_CRASH();
+}
+
+// Constructs a new object as the last element of an SkTArray.
+#define SkNEW_APPEND_TO_TARRAY(array_ptr, type_name, args) \
+ (new ((array_ptr), (array_ptr)->count()) type_name args)
+
+
+/**
+ * Subclass of SkTArray that contains a preallocated memory block for the array.
+ */
+template <int N, typename T, bool MEM_COPY = false>
+class SkSTArray : public SkTArray<T, MEM_COPY> {
+private:
+ typedef SkTArray<T, MEM_COPY> INHERITED;
+
+public:
+ SkSTArray() : INHERITED(&fStorage) {
+ }
+
+ SkSTArray(const SkSTArray& array)
+ : INHERITED(array, &fStorage) {
+ }
+
+ explicit SkSTArray(const INHERITED& array)
+ : INHERITED(array, &fStorage) {
+ }
+
+ SkSTArray(const T* array, int count)
+ : INHERITED(array, count, &fStorage) {
+ }
+
+ SkSTArray& operator= (const SkSTArray& array) {
+ return *this = *(const INHERITED*)&array;
+ }
+
+ SkSTArray& operator= (const INHERITED& array) {
+ INHERITED::operator=(array);
+ return *this;
+ }
+
+private:
+ SkAlignedSTStorage<N,T> fStorage;
+};
+
+#endif
diff --git a/core/SkTDArray.h b/core/SkTDArray.h
new file mode 100644
index 0000000..8b8bb01
--- /dev/null
+++ b/core/SkTDArray.h
@@ -0,0 +1,368 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkTDArray_DEFINED
+#define SkTDArray_DEFINED
+
+#include "SkTypes.h"
+
+template <typename T> class SK_API SkTDArray {
+public:
+ SkTDArray() {
+ fReserve = fCount = 0;
+ fArray = NULL;
+#ifdef SK_DEBUG
+ fData = NULL;
+#endif
+ }
+ SkTDArray(const T src[], size_t count) {
+ SkASSERT(src || count == 0);
+
+ fReserve = fCount = 0;
+ fArray = NULL;
+#ifdef SK_DEBUG
+ fData = NULL;
+#endif
+ if (count) {
+ fArray = (T*)sk_malloc_throw(count * sizeof(T));
+#ifdef SK_DEBUG
+ fData = (ArrayT*)fArray;
+#endif
+ memcpy(fArray, src, sizeof(T) * count);
+ fReserve = fCount = count;
+ }
+ }
+ SkTDArray(const SkTDArray<T>& src) {
+ fReserve = fCount = 0;
+ fArray = NULL;
+#ifdef SK_DEBUG
+ fData = NULL;
+#endif
+ SkTDArray<T> tmp(src.fArray, src.fCount);
+ this->swap(tmp);
+ }
+ ~SkTDArray() {
+ sk_free(fArray);
+ }
+
+ SkTDArray<T>& operator=(const SkTDArray<T>& src) {
+ if (this != &src) {
+ if (src.fCount > fReserve) {
+ SkTDArray<T> tmp(src.fArray, src.fCount);
+ this->swap(tmp);
+ } else {
+ memcpy(fArray, src.fArray, sizeof(T) * src.fCount);
+ fCount = src.fCount;
+ }
+ }
+ return *this;
+ }
+
+ friend bool operator==(const SkTDArray<T>& a, const SkTDArray<T>& b) {
+ return a.fCount == b.fCount &&
+ (a.fCount == 0 ||
+ !memcmp(a.fArray, b.fArray, a.fCount * sizeof(T)));
+ }
+ friend bool operator!=(const SkTDArray<T>& a, const SkTDArray<T>& b) {
+ return !(a == b);
+ }
+
+ void swap(SkTDArray<T>& other) {
+ SkTSwap(fArray, other.fArray);
+#ifdef SK_DEBUG
+ SkTSwap(fData, other.fData);
+#endif
+ SkTSwap(fReserve, other.fReserve);
+ SkTSwap(fCount, other.fCount);
+ }
+
+ /** Return a ptr to the array of data, to be freed with sk_free. This also
+ resets the SkTDArray to be empty.
+ */
+ T* detach() {
+ T* array = fArray;
+ fArray = NULL;
+ fReserve = fCount = 0;
+ SkDEBUGCODE(fData = NULL;)
+ return array;
+ }
+
+ bool isEmpty() const { return fCount == 0; }
+
+ /**
+ * Return the number of elements in the array
+ */
+ int count() const { return (int)fCount; }
+
+ /**
+ * return the number of bytes in the array: count * sizeof(T)
+ */
+ size_t bytes() const { return fCount * sizeof(T); }
+
+ T* begin() { return fArray; }
+ const T* begin() const { return fArray; }
+ T* end() { return fArray ? fArray + fCount : NULL; }
+ const T* end() const { return fArray ? fArray + fCount : NULL; }
+
+ T& operator[](int index) {
+ SkASSERT((unsigned)index < fCount);
+ return fArray[index];
+ }
+ const T& operator[](int index) const {
+ SkASSERT((unsigned)index < fCount);
+ return fArray[index];
+ }
+
+ T& getAt(int index) {
+ return (*this)[index];
+ }
+ const T& getAt(int index) const {
+ return (*this)[index];
+ }
+
+ void reset() {
+ if (fArray) {
+ sk_free(fArray);
+ fArray = NULL;
+#ifdef SK_DEBUG
+ fData = NULL;
+#endif
+ fReserve = fCount = 0;
+ } else {
+ SkASSERT(fReserve == 0 && fCount == 0);
+ }
+ }
+
+ void rewind() {
+ // same as setCount(0)
+ fCount = 0;
+ }
+
+ void setCount(size_t count) {
+ if (count > fReserve) {
+ this->growBy(count - fCount);
+ } else {
+ fCount = count;
+ }
+ }
+
+ void setReserve(size_t reserve) {
+ if (reserve > fReserve) {
+ SkASSERT(reserve > fCount);
+ size_t count = fCount;
+ this->growBy(reserve - fCount);
+ fCount = count;
+ }
+ }
+
+ T* prepend() {
+ this->growBy(1);
+ memmove(fArray + 1, fArray, (fCount - 1) * sizeof(T));
+ return fArray;
+ }
+
+ T* append() {
+ return this->append(1, NULL);
+ }
+ T* append(size_t count, const T* src = NULL) {
+ size_t oldCount = fCount;
+ if (count) {
+ SkASSERT(src == NULL || fArray == NULL ||
+ src + count <= fArray || fArray + oldCount <= src);
+
+ this->growBy(count);
+ if (src) {
+ memcpy(fArray + oldCount, src, sizeof(T) * count);
+ }
+ }
+ return fArray + oldCount;
+ }
+
+ T* appendClear() {
+ T* result = this->append();
+ *result = 0;
+ return result;
+ }
+
+ T* insert(size_t index) {
+ return this->insert(index, 1, NULL);
+ }
+ T* insert(size_t index, size_t count, const T* src = NULL) {
+ SkASSERT(count);
+ SkASSERT(index <= fCount);
+ size_t oldCount = fCount;
+ this->growBy(count);
+ T* dst = fArray + index;
+ memmove(dst + count, dst, sizeof(T) * (oldCount - index));
+ if (src) {
+ memcpy(dst, src, sizeof(T) * count);
+ }
+ return dst;
+ }
+
+ void remove(size_t index, size_t count = 1) {
+ SkASSERT(index + count <= fCount);
+ fCount = fCount - count;
+ memmove(fArray + index, fArray + index + count, sizeof(T) * (fCount - index));
+ }
+
+ void removeShuffle(size_t index) {
+ SkASSERT(index < fCount);
+ size_t newCount = fCount - 1;
+ fCount = newCount;
+ if (index != newCount) {
+ memcpy(fArray + index, fArray + newCount, sizeof(T));
+ }
+ }
+
+ int find(const T& elem) const {
+ const T* iter = fArray;
+ const T* stop = fArray + fCount;
+
+ for (; iter < stop; iter++) {
+ if (*iter == elem) {
+ return (int) (iter - fArray);
+ }
+ }
+ return -1;
+ }
+
+ int rfind(const T& elem) const {
+ const T* iter = fArray + fCount;
+ const T* stop = fArray;
+
+ while (iter > stop) {
+ if (*--iter == elem) {
+ return iter - stop;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Returns true iff the array contains this element.
+ */
+ bool contains(const T& elem) const {
+ return (this->find(elem) >= 0);
+ }
+
+ /**
+ * Copies up to max elements into dst. The number of items copied is
+ * capped by count - index. The actual number copied is returned.
+ */
+ int copyRange(T* dst, size_t index, int max) const {
+ SkASSERT(max >= 0);
+ SkASSERT(!max || dst);
+ if (index >= fCount) {
+ return 0;
+ }
+ int count = SkMin32(max, fCount - index);
+ memcpy(dst, fArray + index, sizeof(T) * count);
+ return count;
+ }
+
+ void copy(T* dst) const {
+ this->copyRange(dst, 0, fCount);
+ }
+
+ // routines to treat the array like a stack
+ T* push() { return this->append(); }
+ void push(const T& elem) { *this->append() = elem; }
+ const T& top() const { return (*this)[fCount - 1]; }
+ T& top() { return (*this)[fCount - 1]; }
+ void pop(T* elem) { if (elem) *elem = (*this)[fCount - 1]; --fCount; }
+ void pop() { --fCount; }
+
+ void deleteAll() {
+ T* iter = fArray;
+ T* stop = fArray + fCount;
+ while (iter < stop) {
+ SkDELETE (*iter);
+ iter += 1;
+ }
+ this->reset();
+ }
+
+ void freeAll() {
+ T* iter = fArray;
+ T* stop = fArray + fCount;
+ while (iter < stop) {
+ sk_free(*iter);
+ iter += 1;
+ }
+ this->reset();
+ }
+
+ void unrefAll() {
+ T* iter = fArray;
+ T* stop = fArray + fCount;
+ while (iter < stop) {
+ (*iter)->unref();
+ iter += 1;
+ }
+ this->reset();
+ }
+
+ void safeUnrefAll() {
+ T* iter = fArray;
+ T* stop = fArray + fCount;
+ while (iter < stop) {
+ SkSafeUnref(*iter);
+ iter += 1;
+ }
+ this->reset();
+ }
+
+ void visitAll(void visitor(T&)) {
+ T* stop = this->end();
+ for (T* curr = this->begin(); curr < stop; curr++) {
+ if (*curr) {
+ visitor(*curr);
+ }
+ }
+ }
+
+#ifdef SK_DEBUG
+ void validate() const {
+ SkASSERT((fReserve == 0 && fArray == NULL) ||
+ (fReserve > 0 && fArray != NULL));
+ SkASSERT(fCount <= fReserve);
+ SkASSERT(fData == (ArrayT*)fArray);
+ }
+#endif
+
+private:
+#ifdef SK_DEBUG
+ enum {
+ kDebugArraySize = 16
+ };
+ typedef T ArrayT[kDebugArraySize];
+ ArrayT* fData;
+#endif
+ T* fArray;
+ size_t fReserve, fCount;
+
+ void growBy(size_t extra) {
+ SkASSERT(extra);
+
+ if (fCount + extra > fReserve) {
+ size_t size = fCount + extra + 4;
+ size += size >> 2;
+
+ fArray = (T*)sk_realloc_throw(fArray, size * sizeof(T));
+#ifdef SK_DEBUG
+ fData = (ArrayT*)fArray;
+#endif
+ fReserve = size;
+ }
+ fCount += extra;
+ }
+};
+
+#endif
diff --git a/core/SkTDStack.h b/core/SkTDStack.h
new file mode 100644
index 0000000..e286e4a
--- /dev/null
+++ b/core/SkTDStack.h
@@ -0,0 +1,110 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkTDStack_DEFINED
+#define SkTDStack_DEFINED
+
+#include "SkTypes.h"
+
+template <typename T> class SkTDStack : SkNoncopyable {
+public:
+ SkTDStack() : fCount(0), fTotalCount(0) {
+ fInitialRec.fNext = NULL;
+ fRec = &fInitialRec;
+
+ // fCount = kSlotCount;
+ }
+
+ ~SkTDStack() {
+ Rec* rec = fRec;
+ while (rec != &fInitialRec) {
+ Rec* next = rec->fNext;
+ sk_free(rec);
+ rec = next;
+ }
+ }
+
+ int count() const { return fTotalCount; }
+ int depth() const { return fTotalCount; }
+ bool empty() const { return fTotalCount == 0; }
+
+ T* push() {
+ SkASSERT(fCount <= kSlotCount);
+ if (fCount == kSlotCount) {
+ Rec* rec = (Rec*)sk_malloc_throw(sizeof(Rec));
+ rec->fNext = fRec;
+ fRec = rec;
+ fCount = 0;
+ }
+ ++fTotalCount;
+ return &fRec->fSlots[fCount++];
+ }
+
+ void push(const T& elem) { *this->push() = elem; }
+
+ const T& index(int idx) const {
+ SkASSERT(fRec && fCount > idx);
+ return fRec->fSlots[fCount - idx - 1];
+ }
+
+ T& index(int idx) {
+ SkASSERT(fRec && fCount > idx);
+ return fRec->fSlots[fCount - idx - 1];
+ }
+
+ const T& top() const {
+ SkASSERT(fRec && fCount > 0);
+ return fRec->fSlots[fCount - 1];
+ }
+
+ T& top() {
+ SkASSERT(fRec && fCount > 0);
+ return fRec->fSlots[fCount - 1];
+ }
+
+ void pop(T* elem) {
+ if (elem) {
+ *elem = fRec->fSlots[fCount - 1];
+ }
+ this->pop();
+ }
+
+ void pop() {
+ SkASSERT(fCount > 0 && fRec);
+ --fTotalCount;
+ if (--fCount == 0) {
+ if (fRec != &fInitialRec) {
+ Rec* rec = fRec->fNext;
+ sk_free(fRec);
+ fCount = kSlotCount;
+ fRec = rec;
+ } else {
+ SkASSERT(fTotalCount == 0);
+ }
+ }
+ }
+
+private:
+ enum {
+ kSlotCount = 8
+ };
+
+ struct Rec;
+ friend struct Rec;
+
+ struct Rec {
+ Rec* fNext;
+ T fSlots[kSlotCount];
+ };
+ Rec fInitialRec;
+ Rec* fRec;
+ int fCount, fTotalCount;
+};
+
+#endif
diff --git a/core/SkTDict.h b/core/SkTDict.h
new file mode 100644
index 0000000..49d07d4
--- /dev/null
+++ b/core/SkTDict.h
@@ -0,0 +1,161 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkTDict_DEFINED
+#define SkTDict_DEFINED
+
+#include "SkChunkAlloc.h"
+#include "SkTSearch.h"
+#include "SkTDArray.h"
+
+template <typename T> class SkTDict : SkNoncopyable {
+public:
+ SkTDict(size_t minStringAlloc) : fStrings(minStringAlloc) {}
+
+ void reset()
+ {
+ fArray.reset();
+ fStrings.reset();
+ }
+
+ int count() const { return fArray.count(); }
+
+ bool set(const char name[], const T& value)
+ {
+ return set(name, strlen(name), value);
+ }
+
+ bool set(const char name[], size_t len, const T& value)
+ {
+ SkASSERT(name);
+
+ int index = this->find_index(name, len);
+
+ if (index >= 0)
+ {
+ fArray[index].fValue = value;
+ return false;
+ }
+ else
+ {
+ Pair* pair = fArray.insert(~index);
+ char* copy = (char*)fStrings.alloc(len + 1, SkChunkAlloc::kThrow_AllocFailType);
+ memcpy(copy, name, len);
+ copy[len] = '\0';
+ pair->fName = copy;
+ pair->fValue = value;
+ return true;
+ }
+ }
+
+ bool find(const char name[]) const
+ {
+ return this->find_index(name) >= 0;
+ }
+
+ bool find(const char name[], size_t len) const
+ {
+ return this->find_index(name, len) >= 0;
+ }
+
+ bool find(const char name[], T* value) const
+ {
+ return find(name, strlen(name), value);
+ }
+
+ bool find(const char name[], size_t len, T* value) const
+ {
+ int index = this->find_index(name, len);
+
+ if (index >= 0)
+ {
+ if (value)
+ *value = fArray[index].fValue;
+ return true;
+ }
+ return false;
+ }
+
+ bool findKey(T& value, const char** name) const
+ {
+ const Pair* end = fArray.end();
+ for (const Pair* pair = fArray.begin(); pair < end; pair++) {
+ if (pair->fValue != value)
+ continue;
+ *name = pair->fName;
+ return true;
+ }
+ return false;
+ }
+
+public:
+ struct Pair {
+ const char* fName;
+ T fValue;
+
+ friend int operator<(const Pair& a, const Pair& b)
+ {
+ return strcmp(a.fName, b.fName);
+ }
+ friend int operator!=(const Pair& a, const Pair& b)
+ {
+ return strcmp(a.fName, b.fName);
+ }
+ };
+ friend class Iter;
+
+public:
+ class Iter {
+ public:
+ Iter(const SkTDict<T>& dict)
+ {
+ fIter = dict.fArray.begin();
+ fStop = dict.fArray.end();
+ }
+ const char* next(T* value)
+ {
+ const char* name = NULL;
+ if (fIter < fStop)
+ {
+ name = fIter->fName;
+ if (value)
+ *value = fIter->fValue;
+ fIter += 1;
+ }
+ return name;
+ }
+ private:
+ const Pair* fIter;
+ const Pair* fStop;
+ };
+
+private:
+ SkTDArray<Pair> fArray;
+ SkChunkAlloc fStrings;
+
+ int find_index(const char name[]) const
+ {
+ return find_index(name, strlen(name));
+ }
+
+ int find_index(const char name[], size_t len) const
+ {
+ SkASSERT(name);
+
+ int count = fArray.count();
+ int index = ~0;
+
+ if (count)
+ index = SkStrSearch(&fArray.begin()->fName, count, name, len, sizeof(Pair));
+ return index;
+ }
+ friend class Iter;
+};
+
+#endif
diff --git a/core/SkTInternalLList.h b/core/SkTInternalLList.h
new file mode 100644
index 0000000..a6b6f15
--- /dev/null
+++ b/core/SkTInternalLList.h
@@ -0,0 +1,272 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkTInternalLList_DEFINED
+#define SkTInternalLList_DEFINED
+
+#include "SkTypes.h"
+
+/**
+ * Helper class to automatically initialize the doubly linked list created pointers.
+ */
+template <typename T> class SkPtrWrapper {
+ public:
+ SkPtrWrapper() : fPtr(NULL) {}
+ SkPtrWrapper& operator =(T* ptr) { fPtr = ptr; return *this; }
+ operator T*() const { return fPtr; }
+ T* operator->() { return fPtr; }
+ private:
+ T* fPtr;
+};
+
+
+/**
+ * This macro creates the member variables required by the SkTInternalLList class. It should be
+ * placed in the private section of any class that will be stored in a double linked list.
+ */
+#define SK_DECLARE_INTERNAL_LLIST_INTERFACE(ClassName) \
+ friend class SkTInternalLList<ClassName>; \
+ /* back pointer to the owning list - for debugging */ \
+ SkDEBUGCODE(SkPtrWrapper<SkTInternalLList<ClassName> > fList;) \
+ SkPtrWrapper<ClassName> fPrev; \
+ SkPtrWrapper<ClassName> fNext
+
+/**
+ * This class implements a templated internal doubly linked list data structure.
+ */
+template <class T> class SkTInternalLList : public SkNoncopyable {
+public:
+ SkTInternalLList()
+ : fHead(NULL)
+ , fTail(NULL) {
+ }
+
+ void remove(T* entry) {
+ SkASSERT(NULL != fHead && NULL != fTail);
+ SkASSERT(this->isInList(entry));
+
+ T* prev = entry->fPrev;
+ T* next = entry->fNext;
+
+ if (NULL != prev) {
+ prev->fNext = next;
+ } else {
+ fHead = next;
+ }
+ if (NULL != next) {
+ next->fPrev = prev;
+ } else {
+ fTail = prev;
+ }
+
+ entry->fPrev = NULL;
+ entry->fNext = NULL;
+
+#ifdef SK_DEBUG
+ entry->fList = NULL;
+#endif
+ }
+
+ void addToHead(T* entry) {
+ SkASSERT(NULL == entry->fPrev && NULL == entry->fNext);
+ SkASSERT(NULL == entry->fList);
+
+ entry->fPrev = NULL;
+ entry->fNext = fHead;
+ if (NULL != fHead) {
+ fHead->fPrev = entry;
+ }
+ fHead = entry;
+ if (NULL == fTail) {
+ fTail = entry;
+ }
+
+#ifdef SK_DEBUG
+ entry->fList = this;
+#endif
+ }
+
+ void addToTail(T* entry) {
+ SkASSERT(NULL == entry->fPrev && NULL == entry->fNext);
+ SkASSERT(NULL == entry->fList);
+
+ entry->fPrev = fTail;
+ entry->fNext = NULL;
+ if (NULL != fTail) {
+ fTail->fNext = entry;
+ }
+ fTail = entry;
+ if (NULL == fHead) {
+ fHead = entry;
+ }
+
+#ifdef SK_DEBUG
+ entry->fList = this;
+#endif
+ }
+
+ /**
+ * Inserts a new list entry before an existing list entry. The new entry must not already be
+ * a member of this or any other list. If existingEntry is NULL then the new entry is added
+ * at the tail.
+ */
+ void addBefore(T* newEntry, T* existingEntry) {
+ SkASSERT(NULL != newEntry);
+
+ if (NULL == existingEntry) {
+ this->addToTail(newEntry);
+ return;
+ }
+
+ SkASSERT(this->isInList(existingEntry));
+ newEntry->fNext = existingEntry;
+ T* prev = existingEntry->fPrev;
+ existingEntry->fPrev = newEntry;
+ newEntry->fPrev = prev;
+ if (NULL == prev) {
+ SkASSERT(fHead == existingEntry);
+ fHead = newEntry;
+ } else {
+ prev->fNext = newEntry;
+ }
+#ifdef SK_DEBUG
+ newEntry->fList = this;
+#endif
+ }
+
+ /**
+ * Inserts a new list entry after an existing list entry. The new entry must not already be
+ * a member of this or any other list. If existingEntry is NULL then the new entry is added
+ * at the head.
+ */
+ void addAfter(T* newEntry, T* existingEntry) {
+ SkASSERT(NULL != newEntry);
+
+ if (NULL == existingEntry) {
+ this->addToHead(newEntry);
+ return;
+ }
+
+ SkASSERT(this->isInList(existingEntry));
+ newEntry->fPrev = existingEntry;
+ T* next = existingEntry->fNext;
+ existingEntry->fNext = newEntry;
+ newEntry->fNext = next;
+ if (NULL == next) {
+ SkASSERT(fTail == existingEntry);
+ fTail = newEntry;
+ } else {
+ next->fPrev = newEntry;
+ }
+#ifdef SK_DEBUG
+ newEntry->fList = this;
+#endif
+ }
+
+ bool isEmpty() const {
+ return NULL == fHead && NULL == fTail;
+ }
+
+ T* head() { return fHead; }
+ T* tail() { return fTail; }
+
+ class Iter {
+ public:
+ enum IterStart {
+ kHead_IterStart,
+ kTail_IterStart
+ };
+
+ Iter() : fCurr(NULL) {}
+ Iter(const Iter& iter) : fCurr(iter.fCurr) {}
+ Iter& operator= (const Iter& iter) { fCurr = iter.fCurr; return *this; }
+
+ T* init(const SkTInternalLList& list, IterStart startLoc) {
+ if (kHead_IterStart == startLoc) {
+ fCurr = list.fHead;
+ } else {
+ SkASSERT(kTail_IterStart == startLoc);
+ fCurr = list.fTail;
+ }
+
+ return fCurr;
+ }
+
+ T* get() { return fCurr; }
+
+ /**
+ * Return the next/previous element in the list or NULL if at the end.
+ */
+ T* next() {
+ if (NULL == fCurr) {
+ return NULL;
+ }
+
+ fCurr = fCurr->fNext;
+ return fCurr;
+ }
+
+ T* prev() {
+ if (NULL == fCurr) {
+ return NULL;
+ }
+
+ fCurr = fCurr->fPrev;
+ return fCurr;
+ }
+
+ private:
+ T* fCurr;
+ };
+
+#ifdef SK_DEBUG
+ void validate() const {
+ SkASSERT(!fHead == !fTail);
+ Iter iter;
+ for (T* item = iter.init(*this, Iter::kHead_IterStart); NULL != (item = iter.next()); ) {
+ SkASSERT(this->isInList(item));
+ if (NULL == item->fPrev) {
+ SkASSERT(fHead == item);
+ } else {
+ SkASSERT(item->fPrev->fNext == item);
+ }
+ if (NULL == item->fNext) {
+ SkASSERT(fTail == item);
+ } else {
+ SkASSERT(item->fNext->fPrev == item);
+ }
+ }
+ }
+
+ /**
+ * Debugging-only method that uses the list back pointer to check if 'entry' is indeed in 'this'
+ * list.
+ */
+ bool isInList(const T* entry) const {
+ return entry->fList == this;
+ }
+
+ /**
+ * Debugging-only method that laboriously counts the list entries.
+ */
+ int countEntries() const {
+ int count = 0;
+ for (T* entry = fHead; NULL != entry; entry = entry->fNext) {
+ ++count;
+ }
+ return count;
+ }
+#endif // SK_DEBUG
+
+private:
+ T* fHead;
+ T* fTail;
+
+ typedef SkNoncopyable INHERITED;
+};
+
+#endif
diff --git a/core/SkTLazy.h b/core/SkTLazy.h
new file mode 100644
index 0000000..2147b66
--- /dev/null
+++ b/core/SkTLazy.h
@@ -0,0 +1,182 @@
+
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+
+#ifndef SkTLazy_DEFINED
+#define SkTLazy_DEFINED
+
+#include "SkTypes.h"
+#include <new>
+
+template <typename T> class SkTLazy;
+template <typename T> void* operator new(size_t, SkTLazy<T>* lazy);
+
+/**
+ * Efficient way to defer allocating/initializing a class until it is needed
+ * (if ever).
+ */
+template <typename T> class SkTLazy {
+public:
+ SkTLazy() : fPtr(NULL) {}
+
+ explicit SkTLazy(const T* src) : fPtr(NULL) {
+ if (src) {
+ fPtr = new (fStorage) T(*src);
+ }
+ }
+
+ SkTLazy(const SkTLazy<T>& src) : fPtr(NULL) {
+ if (src.isValid()) {
+ fPtr = new (fStorage) T(*src->get());
+ } else {
+ fPtr = NULL;
+ }
+ }
+
+ ~SkTLazy() {
+ if (this->isValid()) {
+ fPtr->~T();
+ }
+ }
+
+ /**
+ * Return a pointer to a default-initialized instance of the class. If a
+ * previous instance had been initialized (either from init() or set()) it
+ * will first be destroyed, so that a freshly initialized instance is
+ * always returned.
+ */
+ T* init() {
+ if (this->isValid()) {
+ fPtr->~T();
+ }
+ fPtr = new (SkTCast<T*>(fStorage)) T;
+ return fPtr;
+ }
+
+ /**
+ * Copy src into this, and return a pointer to a copy of it. Note this
+ * will always return the same pointer, so if it is called on a lazy that
+ * has already been initialized, then this will copy over the previous
+ * contents.
+ */
+ T* set(const T& src) {
+ if (this->isValid()) {
+ *fPtr = src;
+ } else {
+ fPtr = new (SkTCast<T*>(fStorage)) T(src);
+ }
+ return fPtr;
+ }
+
+ /**
+ * Returns true if a valid object has been initialized in the SkTLazy,
+ * false otherwise.
+ */
+ bool isValid() const { return NULL != fPtr; }
+
+ /**
+ * Returns the object. This version should only be called when the caller
+ * knows that the object has been initialized.
+ */
+ T* get() const { SkASSERT(this->isValid()); return fPtr; }
+
+ /**
+ * Like above but doesn't assert if object isn't initialized (in which case
+ * NULL is returned).
+ */
+ T* getMaybeNull() const { return fPtr; }
+
+private:
+ friend void* operator new<T>(size_t, SkTLazy* lazy);
+
+ T* fPtr; // NULL or fStorage
+ char fStorage[sizeof(T)];
+};
+
+// Use the below macro (SkNEW_IN_TLAZY) rather than calling this directly
+template <typename T> void* operator new(size_t, SkTLazy<T>* lazy) {
+ SkASSERT(!lazy->isValid());
+ lazy->fPtr = reinterpret_cast<T*>(lazy->fStorage);
+ return lazy->fPtr;
+}
+
+// Skia doesn't use C++ exceptions but it may be compiled with them enabled. Having an op delete
+// to match the op new silences warnings about missing op delete when a constructor throws an
+// exception.
+template <typename T> void operator delete(void*, SkTLazy<T>*) { SK_CRASH(); }
+
+// Use this to construct a T inside an SkTLazy using a non-default constructor.
+#define SkNEW_IN_TLAZY(tlazy_ptr, type_name, args) (new (tlazy_ptr) type_name args)
+
+/**
+ * A helper built on top of SkTLazy to do copy-on-first-write. The object is initialized
+ * with a const pointer but provides a non-const pointer accessor. The first time the
+ * accessor is called (if ever) the object is cloned.
+ *
+ * In the following example at most one copy of constThing is made:
+ *
+ * SkTCopyOnFirstWrite<Thing> thing(&constThing);
+ * ...
+ * function_that_takes_a_const_thing_ptr(thing); // constThing is passed
+ * ...
+ * if (need_to_modify_thing()) {
+ * thing.writable()->modifyMe(); // makes a copy of constThing
+ * }
+ * ...
+ * x = thing->readSomething();
+ * ...
+ * if (need_to_modify_thing_now()) {
+ * thing.writable()->changeMe(); // makes a copy of constThing if we didn't call modifyMe()
+ * }
+ *
+ * consume_a_thing(thing); // could be constThing or a modified copy.
+ */
+template <typename T>
+class SkTCopyOnFirstWrite {
+public:
+ SkTCopyOnFirstWrite(const T& initial) : fObj(&initial) {}
+
+ // Constructor for delayed initialization.
+ SkTCopyOnFirstWrite() : fObj(NULL) {}
+
+ // Should only be called once, and only if the default constructor was used.
+ void init(const T& initial) {
+ SkASSERT(NULL == fObj);
+ SkASSERT(!fLazy.isValid());
+ fObj = &initial;
+ }
+
+ /**
+ * Returns a writable T*. The first time this is called the initial object is cloned.
+ */
+ T* writable() {
+ SkASSERT(NULL != fObj);
+ if (!fLazy.isValid()) {
+ fLazy.set(*fObj);
+ fObj = fLazy.get();
+ }
+ return const_cast<T*>(fObj);
+ }
+
+ /**
+ * Operators for treating this as though it were a const pointer.
+ */
+
+ const T *operator->() const { return fObj; }
+
+ operator const T*() const { return fObj; }
+
+ const T& operator *() const { return *fObj; }
+
+private:
+ const T* fObj;
+ SkTLazy<T> fLazy;
+};
+
+#endif
diff --git a/core/SkTRegistry.h b/core/SkTRegistry.h
new file mode 100644
index 0000000..34fcffd
--- /dev/null
+++ b/core/SkTRegistry.h
@@ -0,0 +1,56 @@
+
+/*
+ * Copyright 2009 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkTRegistry_DEFINED
+#define SkTRegistry_DEFINED
+
+#include "SkTypes.h"
+
+/** Template class that registers itself (in the constructor) into a linked-list
+ and provides a function-pointer. This can be used to auto-register a set of
+ services, e.g. a set of image codecs.
+ */
+template <typename T, typename P> class SkTRegistry : SkNoncopyable {
+public:
+ typedef T (*Factory)(P);
+
+ SkTRegistry(Factory fact) {
+#ifdef SK_BUILD_FOR_ANDROID
+ // work-around for double-initialization bug
+ {
+ SkTRegistry* reg = gHead;
+ while (reg) {
+ if (reg == this) {
+ return;
+ }
+ reg = reg->fChain;
+ }
+ }
+#endif
+ fFact = fact;
+ fChain = gHead;
+ gHead = this;
+ }
+
+ static const SkTRegistry* Head() { return gHead; }
+
+ const SkTRegistry* next() const { return fChain; }
+ Factory factory() const { return fFact; }
+
+private:
+ Factory fFact;
+ SkTRegistry* fChain;
+
+ static SkTRegistry* gHead;
+};
+
+// The caller still needs to declare an instance of this somewhere
+template <typename T, typename P> SkTRegistry<T, P>* SkTRegistry<T, P>::gHead;
+
+#endif
diff --git a/core/SkTScopedPtr.h b/core/SkTScopedPtr.h
new file mode 100644
index 0000000..580d72f
--- /dev/null
+++ b/core/SkTScopedPtr.h
@@ -0,0 +1,76 @@
+
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkTScopedPtr_DEFINED
+#define SkTScopedPtr_DEFINED
+
+#include "SkTypes.h"
+
+/** \class SkTScopedPtr
+ A SkTScopedPtr<T> is like a T*, except that the destructor of SkTScopedPtr<T>
+ automatically deletes the pointer it holds (if any). That is, SkTScopedPtr<T>
+ owns the T object that it points to. Like a T*, a SkTScopedPtr<T> may hold
+ either NULL or a pointer to a T object. Also like T*, SkTScopedPtr<T> is
+ thread-compatible, and once you dereference it, you get the threadsafety
+ guarantees of T.
+
+ The size of a SkTScopedPtr is small: sizeof(SkTScopedPtr<T>) == sizeof(T*)
+*/
+template <typename T> class SkTScopedPtr : SkNoncopyable {
+public:
+ explicit SkTScopedPtr(T* o = NULL) : fObj(o) {}
+ ~SkTScopedPtr() {
+ enum { kTypeMustBeComplete = sizeof(T) };
+ delete fObj;
+ }
+
+ /** Delete the current object, if any. Then take ownership of the
+ passed object.
+ */
+ void reset(T* o = NULL) {
+ if (o != fObj) {
+ enum { kTypeMustBeComplete = sizeof(T) };
+ delete fObj;
+ fObj = o;
+ }
+ }
+
+ /** Without deleting the current object, return it and forget about it.
+ Similar to calling get() and reset(), but the object is not deleted.
+ */
+ T* release() {
+ T* retVal = fObj;
+ fObj = NULL;
+ return retVal;
+ }
+
+ T& operator*() const {
+ SkASSERT(fObj != NULL);
+ return *fObj;
+ }
+ T* operator->() const {
+ SkASSERT(fObj != NULL);
+ return fObj;
+ }
+ T* get() const { return fObj; }
+
+ bool operator==(T* o) const { return fObj == o; }
+ bool operator!=(T* o) const { return fObj != o; }
+
+private:
+ T* fObj;
+
+ // Forbid comparison of SkTScopedPtr types. If T2 != T, it doesn't make
+ // sense, and if T2 == T, it still doesn't make sense because the same
+ // object can't be owned by two different scoped_ptrs.
+ template <class T2> bool operator==(SkTScopedPtr<T2> const& o2) const;
+ template <class T2> bool operator!=(SkTScopedPtr<T2> const& o2) const;
+};
+
+#endif
diff --git a/core/SkTSearch.h b/core/SkTSearch.h
new file mode 100644
index 0000000..a4e4994
--- /dev/null
+++ b/core/SkTSearch.h
@@ -0,0 +1,146 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkTSearch_DEFINED
+#define SkTSearch_DEFINED
+
+#include "SkTypes.h"
+
+/**
+ * All of the SkTSearch variants want to return the index (0...N-1) of the
+ * found element, or the bit-not of where to insert the element.
+ *
+ * At a simple level, if the return value is negative, it was not found.
+ *
+ * For clients that want to insert the new element if it was not found, use
+ * the following logic:
+ *
+ * int index = SkTSearch(...);
+ * if (index >= 0) {
+ * // found at index
+ * } else {
+ * index = ~index; // now we are positive
+ * // insert at index
+ * }
+ */
+
+
+// The most general form of SkTSearch takes an array of T and a key of type K. A functor, less, is
+// used to perform comparisons. It has two function operators:
+// bool operator() (const T& t, const K& k)
+// bool operator() (const K& t, const T& k)
+template <typename T, typename K, typename LESS>
+int SkTSearch(const T base[], int count, const K& key, size_t elemSize, LESS& less)
+{
+ SkASSERT(count >= 0);
+ if (count <= 0) {
+ return ~0;
+ }
+
+ SkASSERT(base != NULL); // base may be NULL if count is zero
+
+ int lo = 0;
+ int hi = count - 1;
+
+ while (lo < hi) {
+ int mid = (hi + lo) >> 1;
+ const T* elem = (const T*)((const char*)base + mid * elemSize);
+
+ if (less(*elem, key))
+ lo = mid + 1;
+ else
+ hi = mid;
+ }
+
+ const T* elem = (const T*)((const char*)base + hi * elemSize);
+ if (less(*elem, key)) {
+ hi += 1;
+ hi = ~hi;
+ } else if (less(key, *elem)) {
+ hi = ~hi;
+ }
+ return hi;
+}
+
+// Adapts a less-than function to a functor.
+template <typename T, bool (LESS)(const T&, const T&)> struct SkTLessFunctionToFunctorAdaptor {
+ bool operator()(const T& a, const T& b) { return LESS(a, b); }
+};
+
+// Specialization for case when T==K and the caller wants to use a function rather than functor.
+template <typename T, bool (LESS)(const T&, const T&)>
+int SkTSearch(const T base[], int count, const T& target, size_t elemSize) {
+ static SkTLessFunctionToFunctorAdaptor<T, LESS> functor;
+ return SkTSearch(base, count, target, elemSize, functor);
+}
+
+// Adapts operator < to a functor.
+template <typename T> struct SkTLessFunctor {
+ bool operator()(const T& a, const T& b) { return a < b; }
+};
+
+// Specialization for T==K, compare using op <.
+template <typename T>
+int SkTSearch(const T base[], int count, const T& target, size_t elemSize) {
+ static SkTLessFunctor<T> functor;
+ return SkTSearch(base, count, target, elemSize, functor);
+}
+
+// Similar to SkLessFunctionToFunctorAdaptor but makes the functor interface take T* rather than T.
+template <typename T, bool (LESS)(const T&, const T&)> struct SkTLessFunctionToPtrFunctorAdaptor {
+ bool operator() (const T* t, const T* k) { return LESS(*t, *k); }
+};
+
+// Specialization for case where domain is an array of T* and the key value is a T*, and you want
+// to compare the T objects, not the pointers.
+template <typename T, bool (LESS)(const T&, const T&)>
+int SkTSearch(T* base[], int count, T* target, size_t elemSize) {
+ static SkTLessFunctionToPtrFunctorAdaptor<T, LESS> functor;
+ return SkTSearch(base, count, target, elemSize, functor);
+}
+
+int SkStrSearch(const char*const* base, int count, const char target[],
+ size_t target_len, size_t elemSize);
+int SkStrSearch(const char*const* base, int count, const char target[],
+ size_t elemSize);
+
+/** Like SkStrSearch, but treats target as if it were all lower-case. Assumes that
+ base points to a table of lower-case strings.
+*/
+int SkStrLCSearch(const char*const* base, int count, const char target[],
+ size_t target_len, size_t elemSize);
+int SkStrLCSearch(const char*const* base, int count, const char target[],
+ size_t elemSize);
+
+/** Helper class to convert a string to lower-case, but only modifying the ascii
+ characters. This makes the routine very fast and never changes the string
+ length, but it is not suitable for linguistic purposes. Normally this is
+ used for buiding and searching string tables.
+*/
+class SkAutoAsciiToLC {
+public:
+ SkAutoAsciiToLC(const char str[], size_t len = (size_t)-1);
+ ~SkAutoAsciiToLC();
+
+ const char* lc() const { return fLC; }
+ size_t length() const { return fLength; }
+
+private:
+ char* fLC; // points to either the heap or fStorage
+ size_t fLength;
+ enum {
+ STORAGE = 64
+ };
+ char fStorage[STORAGE+1];
+};
+
+// Helper when calling qsort with a compare proc that has typed its arguments
+#define SkCastForQSort(compare) reinterpret_cast<int (*)(const void*, const void*)>(compare)
+
+#endif
diff --git a/core/SkTemplates.h b/core/SkTemplates.h
new file mode 100644
index 0000000..e49cc47
--- /dev/null
+++ b/core/SkTemplates.h
@@ -0,0 +1,457 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkTemplates_DEFINED
+#define SkTemplates_DEFINED
+
+#include "SkTypes.h"
+#include <new>
+
+/** \file SkTemplates.h
+
+ This file contains light-weight template classes for type-safe and exception-safe
+ resource management.
+*/
+
+/**
+ * Marks a local variable as known to be unused (to avoid warnings).
+ * Note that this does *not* prevent the local variable from being optimized away.
+ */
+template<typename T> inline void sk_ignore_unused_variable(const T&) { }
+
+/**
+ * SkTIsConst<T>::value is true if the type T is const.
+ * The type T is constrained not to be an array or reference type.
+ */
+template <typename T> struct SkTIsConst {
+ static T* t;
+ static uint16_t test(const volatile void*);
+ static uint32_t test(volatile void *);
+ static const bool value = (sizeof(uint16_t) == sizeof(test(t)));
+};
+
+///@{
+/** SkTConstType<T, CONST>::type will be 'const T' if CONST is true, 'T' otherwise. */
+template <typename T, bool CONST> struct SkTConstType {
+ typedef T type;
+};
+template <typename T> struct SkTConstType<T, true> {
+ typedef const T type;
+};
+///@}
+
+/**
+ * Returns a pointer to a D which comes immediately after S[count].
+ */
+template <typename D, typename S> static D* SkTAfter(S* ptr, size_t count = 1) {
+ return reinterpret_cast<D*>(ptr + count);
+}
+
+/**
+ * Returns a pointer to a D which comes byteOffset bytes after S.
+ */
+template <typename D, typename S> static D* SkTAddOffset(S* ptr, size_t byteOffset) {
+ // The intermediate char* has the same const-ness as D as this produces better error messages.
+ // This relies on the fact that reinterpret_cast can add constness, but cannot remove it.
+ return reinterpret_cast<D*>(
+ reinterpret_cast<typename SkTConstType<char, SkTIsConst<D>::value>::type*>(ptr) + byteOffset
+ );
+}
+
+/** \class SkAutoTCallVProc
+
+ Call a function when this goes out of scope. The template uses two
+ parameters, the object, and a function that is to be called in the destructor.
+ If detach() is called, the object reference is set to null. If the object
+ reference is null when the destructor is called, we do not call the
+ function.
+*/
+template <typename T, void (*P)(T*)> class SkAutoTCallVProc : SkNoncopyable {
+public:
+ SkAutoTCallVProc(T* obj): fObj(obj) {}
+ ~SkAutoTCallVProc() { if (fObj) P(fObj); }
+ T* detach() { T* obj = fObj; fObj = NULL; return obj; }
+private:
+ T* fObj;
+};
+
+/** \class SkAutoTCallIProc
+
+Call a function when this goes out of scope. The template uses two
+parameters, the object, and a function that is to be called in the destructor.
+If detach() is called, the object reference is set to null. If the object
+reference is null when the destructor is called, we do not call the
+function.
+*/
+template <typename T, int (*P)(T*)> class SkAutoTCallIProc : SkNoncopyable {
+public:
+ SkAutoTCallIProc(T* obj): fObj(obj) {}
+ ~SkAutoTCallIProc() { if (fObj) P(fObj); }
+ T* detach() { T* obj = fObj; fObj = NULL; return obj; }
+private:
+ T* fObj;
+};
+
+template <typename T> class SkAutoTDelete : SkNoncopyable {
+public:
+ SkAutoTDelete(T* obj = NULL) : fObj(obj) {}
+ ~SkAutoTDelete() { SkDELETE(fObj); }
+
+ T* get() const { return fObj; }
+ T& operator*() const { SkASSERT(fObj); return *fObj; }
+ T* operator->() const { SkASSERT(fObj); return fObj; }
+
+ void reset(T* obj) {
+ if (fObj != obj) {
+ SkDELETE(fObj);
+ fObj = obj;
+ }
+ }
+
+ /**
+ * Delete the owned object, setting the internal pointer to NULL.
+ */
+ void free() {
+ SkDELETE(fObj);
+ fObj = NULL;
+ }
+
+ /**
+ * Transfer ownership of the object to the caller, setting the internal
+ * pointer to NULL. Note that this differs from get(), which also returns
+ * the pointer, but it does not transfer ownership.
+ */
+ T* detach() {
+ T* obj = fObj;
+ fObj = NULL;
+ return obj;
+ }
+
+private:
+ T* fObj;
+};
+
+// Calls ~T() in the destructor.
+template <typename T> class SkAutoTDestroy : SkNoncopyable {
+public:
+ SkAutoTDestroy(T* obj = NULL) : fObj(obj) {}
+ ~SkAutoTDestroy() {
+ if (NULL != fObj) {
+ fObj->~T();
+ }
+ }
+
+ T* get() const { return fObj; }
+ T& operator*() const { SkASSERT(fObj); return *fObj; }
+ T* operator->() const { SkASSERT(fObj); return fObj; }
+
+private:
+ T* fObj;
+};
+
+template <typename T> class SkAutoTDeleteArray : SkNoncopyable {
+public:
+ SkAutoTDeleteArray(T array[]) : fArray(array) {}
+ ~SkAutoTDeleteArray() { SkDELETE_ARRAY(fArray); }
+
+ T* get() const { return fArray; }
+ void free() { SkDELETE_ARRAY(fArray); fArray = NULL; }
+ T* detach() { T* array = fArray; fArray = NULL; return array; }
+
+private:
+ T* fArray;
+};
+
+/** Allocate an array of T elements, and free the array in the destructor
+ */
+template <typename T> class SkAutoTArray : SkNoncopyable {
+public:
+ SkAutoTArray() {
+ fArray = NULL;
+ SkDEBUGCODE(fCount = 0;)
+ }
+ /** Allocate count number of T elements
+ */
+ explicit SkAutoTArray(int count) {
+ SkASSERT(count >= 0);
+ fArray = NULL;
+ if (count) {
+ fArray = SkNEW_ARRAY(T, count);
+ }
+ SkDEBUGCODE(fCount = count;)
+ }
+
+ /** Reallocates given a new count. Reallocation occurs even if new count equals old count.
+ */
+ void reset(int count) {
+ SkDELETE_ARRAY(fArray);
+ SkASSERT(count >= 0);
+ fArray = NULL;
+ if (count) {
+ fArray = SkNEW_ARRAY(T, count);
+ }
+ SkDEBUGCODE(fCount = count;)
+ }
+
+ ~SkAutoTArray() {
+ SkDELETE_ARRAY(fArray);
+ }
+
+ /** Return the array of T elements. Will be NULL if count == 0
+ */
+ T* get() const { return fArray; }
+
+ /** Return the nth element in the array
+ */
+ T& operator[](int index) const {
+ SkASSERT((unsigned)index < (unsigned)fCount);
+ return fArray[index];
+ }
+
+private:
+ T* fArray;
+ SkDEBUGCODE(int fCount;)
+};
+
+/** Wraps SkAutoTArray, with room for up to N elements preallocated
+ */
+template <size_t N, typename T> class SkAutoSTArray : SkNoncopyable {
+public:
+ /** Initialize with no objects */
+ SkAutoSTArray() {
+ fArray = NULL;
+ fCount = 0;
+ }
+
+ /** Allocate count number of T elements
+ */
+ SkAutoSTArray(size_t count) {
+ fArray = NULL;
+ fCount = 0;
+ this->reset(count);
+ }
+
+ ~SkAutoSTArray() {
+ this->reset(0);
+ }
+
+ /** Destroys previous objects in the array and default constructs count number of objects */
+ void reset(size_t count) {
+ T* start = fArray;
+ T* iter = start + fCount;
+ while (iter > start) {
+ (--iter)->~T();
+ }
+
+ if (fCount != count) {
+ if (fCount > N) {
+ // 'fArray' was allocated last time so free it now
+ SkASSERT((T*) fStorage != fArray);
+ sk_free(fArray);
+ }
+
+ if (count > N) {
+ fArray = (T*) sk_malloc_throw(count * sizeof(T));
+ } else if (count > 0) {
+ fArray = (T*) fStorage;
+ } else {
+ fArray = NULL;
+ }
+
+ fCount = count;
+ }
+
+ iter = fArray;
+ T* stop = fArray + count;
+ while (iter < stop) {
+ SkNEW_PLACEMENT(iter++, T);
+ }
+ }
+
+ /** Return the number of T elements in the array
+ */
+ size_t count() const { return fCount; }
+
+ /** Return the array of T elements. Will be NULL if count == 0
+ */
+ T* get() const { return fArray; }
+
+ /** Return the nth element in the array
+ */
+ T& operator[](int index) const {
+ SkASSERT((unsigned)index < fCount);
+ return fArray[index];
+ }
+
+private:
+ size_t fCount;
+ T* fArray;
+ // since we come right after fArray, fStorage should be properly aligned
+ char fStorage[N * sizeof(T)];
+};
+
+/** Manages an array of T elements, freeing the array in the destructor.
+ * Does NOT call any constructors/destructors on T (T must be POD).
+ */
+template <typename T> class SkAutoTMalloc : SkNoncopyable {
+public:
+ /** Takes ownership of the ptr. The ptr must be a value which can be passed to sk_free. */
+ explicit SkAutoTMalloc(T* ptr = NULL) {
+ fPtr = ptr;
+ }
+
+ /** Allocates space for 'count' Ts. */
+ explicit SkAutoTMalloc(size_t count) {
+ fPtr = (T*)sk_malloc_flags(count * sizeof(T), SK_MALLOC_THROW | SK_MALLOC_TEMP);
+ }
+
+ ~SkAutoTMalloc() {
+ sk_free(fPtr);
+ }
+
+ /** Resize the memory area pointed to by the current ptr preserving contents. */
+ void realloc(size_t count) {
+ fPtr = reinterpret_cast<T*>(sk_realloc_throw(fPtr, count * sizeof(T)));
+ }
+
+ /** Resize the memory area pointed to by the current ptr without preserving contents. */
+ void reset(size_t count) {
+ sk_free(fPtr);
+ fPtr = (T*)sk_malloc_flags(count * sizeof(T), SK_MALLOC_THROW | SK_MALLOC_TEMP);
+ }
+
+ T* get() const { return fPtr; }
+
+ operator T*() {
+ return fPtr;
+ }
+
+ operator const T*() const {
+ return fPtr;
+ }
+
+ T& operator[](int index) {
+ return fPtr[index];
+ }
+
+ const T& operator[](int index) const {
+ return fPtr[index];
+ }
+
+ /**
+ * Transfer ownership of the ptr to the caller, setting the internal
+ * pointer to NULL. Note that this differs from get(), which also returns
+ * the pointer, but it does not transfer ownership.
+ */
+ T* detach() {
+ T* ptr = fPtr;
+ fPtr = NULL;
+ return ptr;
+ }
+
+private:
+ T* fPtr;
+};
+
+template <size_t N, typename T> class SK_API SkAutoSTMalloc : SkNoncopyable {
+public:
+ SkAutoSTMalloc() {
+ fPtr = NULL;
+ }
+
+ SkAutoSTMalloc(size_t count) {
+ if (count > N) {
+ fPtr = (T*)sk_malloc_flags(count * sizeof(T), SK_MALLOC_THROW | SK_MALLOC_TEMP);
+ } else if (count) {
+ fPtr = fTStorage;
+ } else {
+ fPtr = NULL;
+ }
+ }
+
+ ~SkAutoSTMalloc() {
+ if (fPtr != fTStorage) {
+ sk_free(fPtr);
+ }
+ }
+
+ // doesn't preserve contents
+ T* reset(size_t count) {
+ if (fPtr != fTStorage) {
+ sk_free(fPtr);
+ }
+ if (count > N) {
+ fPtr = (T*)sk_malloc_flags(count * sizeof(T), SK_MALLOC_THROW | SK_MALLOC_TEMP);
+ } else if (count) {
+ fPtr = fTStorage;
+ } else {
+ fPtr = NULL;
+ }
+ return fPtr;
+ }
+
+ T* get() const { return fPtr; }
+
+ operator T*() {
+ return fPtr;
+ }
+
+ operator const T*() const {
+ return fPtr;
+ }
+
+ T& operator[](int index) {
+ return fPtr[index];
+ }
+
+ const T& operator[](int index) const {
+ return fPtr[index];
+ }
+
+private:
+ T* fPtr;
+ union {
+ uint32_t fStorage32[(N*sizeof(T) + 3) >> 2];
+ T fTStorage[1]; // do NOT want to invoke T::T()
+ };
+};
+
+/**
+ * Reserves memory that is aligned on double and pointer boundaries.
+ * Hopefully this is sufficient for all practical purposes.
+ */
+template <size_t N> class SkAlignedSStorage : SkNoncopyable {
+public:
+ void* get() { return fData; }
+private:
+ union {
+ void* fPtr;
+ double fDouble;
+ char fData[N];
+ };
+};
+
+/**
+ * Reserves memory that is aligned on double and pointer boundaries.
+ * Hopefully this is sufficient for all practical purposes. Otherwise,
+ * we have to do some arcane trickery to determine alignment of non-POD
+ * types. Lifetime of the memory is the lifetime of the object.
+ */
+template <int N, typename T> class SkAlignedSTStorage : SkNoncopyable {
+public:
+ /**
+ * Returns void* because this object does not initialize the
+ * memory. Use placement new for types that require a cons.
+ */
+ void* get() { return fStorage.get(); }
+private:
+ SkAlignedSStorage<sizeof(T)*N> fStorage;
+};
+
+#endif
diff --git a/core/SkThread.h b/core/SkThread.h
new file mode 100644
index 0000000..4a2499a
--- /dev/null
+++ b/core/SkThread.h
@@ -0,0 +1,68 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkThread_DEFINED
+#define SkThread_DEFINED
+
+#include "SkTypes.h"
+#include "SkThread_platform.h"
+
+/****** SkThread_platform needs to define the following...
+
+int32_t sk_atomic_inc(int32_t*);
+int32_t sk_atomic_add(int32_t*, int32_t);
+int32_t sk_atomic_dec(int32_t*);
+int32_t sk_atomic_conditional_inc(int32_t*);
+
+class SkMutex {
+public:
+ SkMutex();
+ ~SkMutex();
+
+ void acquire();
+ void release();
+};
+
+****************/
+
+class SkAutoMutexAcquire : SkNoncopyable {
+public:
+ explicit SkAutoMutexAcquire(SkBaseMutex& mutex) : fMutex(&mutex) {
+ SkASSERT(fMutex != NULL);
+ mutex.acquire();
+ }
+
+ SkAutoMutexAcquire(SkBaseMutex* mutex) : fMutex(mutex) {
+ if (mutex) {
+ mutex->acquire();
+ }
+ }
+
+ /** If the mutex has not been release, release it now.
+ */
+ ~SkAutoMutexAcquire() {
+ if (fMutex) {
+ fMutex->release();
+ }
+ }
+
+ /** If the mutex has not been release, release it now.
+ */
+ void release() {
+ if (fMutex) {
+ fMutex->release();
+ fMutex = NULL;
+ }
+ }
+
+private:
+ SkBaseMutex* fMutex;
+};
+
+#endif
diff --git a/core/SkThread_platform.h b/core/SkThread_platform.h
new file mode 100644
index 0000000..7df778c
--- /dev/null
+++ b/core/SkThread_platform.h
@@ -0,0 +1,194 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkThread_platform_DEFINED
+#define SkThread_platform_DEFINED
+
+#if defined(SK_BUILD_FOR_ANDROID)
+
+#if !defined(SK_BUILD_FOR_ANDROID_FRAMEWORK)
+
+#include <stdint.h>
+
+/* Just use the GCC atomic intrinsics. They're supported by the NDK toolchain,
+ * have reasonable performance, and provide full memory barriers
+ */
+static inline __attribute__((always_inline)) int32_t sk_atomic_inc(int32_t *addr) {
+ return __sync_fetch_and_add(addr, 1);
+}
+
+static inline __attribute__((always_inline)) int32_t sk_atomic_add(int32_t *addr, int32_t inc) {
+ return __sync_fetch_and_add(addr, inc);
+}
+
+static inline __attribute__((always_inline)) int32_t sk_atomic_dec(int32_t *addr) {
+ return __sync_fetch_and_add(addr, -1);
+}
+static inline __attribute__((always_inline)) void sk_membar_aquire__after_atomic_dec() { }
+
+static inline __attribute__((always_inline)) int32_t sk_atomic_conditional_inc(int32_t* addr) {
+ int32_t value = *addr;
+
+ while (true) {
+ if (value == 0) {
+ return 0;
+ }
+
+ int32_t before = __sync_val_compare_and_swap(addr, value, value + 1);
+
+ if (before == value) {
+ return value;
+ } else {
+ value = before;
+ }
+ }
+}
+static inline __attribute__((always_inline)) void sk_membar_aquire__after_atomic_conditional_inc() { }
+
+#else // SK_BUILD_FOR_ANDROID_FRAMEWORK
+
+/* The platform atomics operations are slightly more efficient than the
+ * GCC built-ins, so use them.
+ */
+#include <utils/Atomic.h>
+
+#define sk_atomic_inc(addr) android_atomic_inc(addr)
+#define sk_atomic_add(addr, inc) android_atomic_add(inc, addr)
+#define sk_atomic_dec(addr) android_atomic_dec(addr)
+
+static inline __attribute__((always_inline)) void sk_membar_aquire__after_atomic_dec() {
+ //HACK: Android is actually using full memory barriers.
+ // Should this change, uncomment below.
+ //int dummy;
+ //android_atomic_aquire_store(0, &dummy);
+}
+static inline __attribute__((always_inline)) int32_t sk_atomic_conditional_inc(int32_t* addr) {
+ while (true) {
+ int32_t value = *addr;
+ if (value == 0) {
+ return 0;
+ }
+ if (0 == android_atomic_release_cas(value, value + 1, addr)) {
+ return value;
+ }
+ }
+}
+static inline __attribute__((always_inline)) void sk_membar_aquire__after_atomic_conditional_inc() {
+ //HACK: Android is actually using full memory barriers.
+ // Should this change, uncomment below.
+ //int dummy;
+ //android_atomic_aquire_store(0, &dummy);
+}
+
+#endif // SK_BUILD_FOR_ANDROID_FRAMEWORK
+
+#else // !SK_BUILD_FOR_ANDROID
+
+/** Implemented by the porting layer, this function adds one to the int
+ specified by the address (in a thread-safe manner), and returns the
+ previous value.
+ No additional memory barrier is required.
+ This must act as a compiler barrier.
+*/
+SK_API int32_t sk_atomic_inc(int32_t* addr);
+
+/** Implemented by the porting layer, this function adds inc to the int
+ specified by the address (in a thread-safe manner), and returns the
+ previous value.
+ No additional memory barrier is required.
+ This must act as a compiler barrier.
+ */
+SK_API int32_t sk_atomic_add(int32_t* addr, int32_t inc);
+
+/** Implemented by the porting layer, this function subtracts one from the int
+ specified by the address (in a thread-safe manner), and returns the
+ previous value.
+ Expected to act as a release (SL/S) memory barrier and a compiler barrier.
+*/
+SK_API int32_t sk_atomic_dec(int32_t* addr);
+/** If sk_atomic_dec does not act as an aquire (L/SL) barrier, this is expected
+ to act as an aquire (L/SL) memory barrier and as a compiler barrier.
+*/
+SK_API void sk_membar_aquire__after_atomic_dec();
+
+/** Implemented by the porting layer, this function adds one to the int
+ specified by the address iff the int specified by the address is not zero
+ (in a thread-safe manner), and returns the previous value.
+ No additional memory barrier is required.
+ This must act as a compiler barrier.
+*/
+SK_API int32_t sk_atomic_conditional_inc(int32_t*);
+/** If sk_atomic_conditional_inc does not act as an aquire (L/SL) barrier, this
+ is expected to act as an aquire (L/SL) memory barrier and as a compiler
+ barrier.
+*/
+SK_API void sk_membar_aquire__after_atomic_conditional_inc();
+
+#endif // !SK_BUILD_FOR_ANDROID
+
+#ifdef SK_USE_POSIX_THREADS
+
+#include <pthread.h>
+
+// A SkBaseMutex is a POD structure that can be directly initialized
+// at declaration time with SK_DECLARE_STATIC/GLOBAL_MUTEX. This avoids the
+// generation of a static initializer in the final machine code (and
+// a corresponding static finalizer).
+//
+struct SkBaseMutex {
+ void acquire() { pthread_mutex_lock(&fMutex); }
+ void release() { pthread_mutex_unlock(&fMutex); }
+ pthread_mutex_t fMutex;
+};
+
+// Using POD-style initialization prevents the generation of a static initializer
+// and keeps the acquire() implementation small and fast.
+#define SK_DECLARE_STATIC_MUTEX(name) static SkBaseMutex name = { PTHREAD_MUTEX_INITIALIZER }
+
+// Special case used when the static mutex must be available globally.
+#define SK_DECLARE_GLOBAL_MUTEX(name) SkBaseMutex name = { PTHREAD_MUTEX_INITIALIZER }
+
+// A normal mutex that requires to be initialized through normal C++ construction,
+// i.e. when it's a member of another class, or allocated on the heap.
+class SK_API SkMutex : public SkBaseMutex, SkNoncopyable {
+public:
+ SkMutex();
+ ~SkMutex();
+};
+
+#else // !SK_USE_POSIX_THREADS
+
+// In the generic case, SkBaseMutex and SkMutex are the same thing, and we
+// can't easily get rid of static initializers.
+//
+class SK_API SkMutex : SkNoncopyable {
+public:
+ SkMutex();
+ ~SkMutex();
+
+ void acquire();
+ void release();
+
+private:
+ bool fIsGlobal;
+ enum {
+ kStorageIntCount = 64
+ };
+ uint32_t fStorage[kStorageIntCount];
+};
+
+typedef SkMutex SkBaseMutex;
+
+#define SK_DECLARE_STATIC_MUTEX(name) static SkBaseMutex name
+#define SK_DECLARE_GLOBAL_MUTEX(name) SkBaseMutex name
+
+#endif // !SK_USE_POSIX_THREADS
+
+
+#endif
diff --git a/core/SkTileGridPicture.h b/core/SkTileGridPicture.h
new file mode 100644
index 0000000..af7f0e2
--- /dev/null
+++ b/core/SkTileGridPicture.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkTileGridPicture_DEFINED
+#define SkTileGridPicture_DEFINED
+
+#include "SkPicture.h"
+#include "SkPoint.h"
+#include "SkSize.h"
+
+/**
+ * Subclass of SkPicture that override the behavior of the
+ * kOptimizeForClippedPlayback_RecordingFlag by creating an SkTileGrid
+ * structure rather than an R-Tree. The tile grid has lower recording
+ * and playback costs, but is less effective at eliminating extraneous
+ * primitives for arbitrary query rectangles. It is most effective for
+ * tiled playback when the tile structure is known at record time.
+ */
+class SK_API SkTileGridPicture : public SkPicture {
+public:
+ struct TileGridInfo {
+ /** Tile placement interval */
+ SkISize fTileInterval;
+
+ /** Pixel coverage overlap between adjacent tiles */
+ SkISize fMargin;
+
+ /** Offset added to device-space bounding box positions to convert
+ * them to tile-grid space. This can be used to adjust the "phase"
+ * of the tile grid to match probable query rectangles that will be
+ * used to search into the tile grid. As long as the offset is smaller
+ * or equal to the margin, there is no need to extend the domain of
+ * the tile grid to prevent data loss.
+ */
+ SkIPoint fOffset;
+ };
+ /**
+ * Constructor
+ * @param width recording canvas width in device pixels
+ * @param height recording canvas height in device pixels
+ * @param info description of the tiling layout
+ */
+ SkTileGridPicture(int width, int height, const TileGridInfo& info);
+
+ virtual SkBBoxHierarchy* createBBoxHierarchy() const SK_OVERRIDE;
+
+private:
+ int fXTileCount, fYTileCount;
+ TileGridInfo fInfo;
+};
+
+#endif
diff --git a/core/SkTime.h b/core/SkTime.h
new file mode 100644
index 0000000..7f3c270
--- /dev/null
+++ b/core/SkTime.h
@@ -0,0 +1,64 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkTime_DEFINED
+#define SkTime_DEFINED
+
+#include "SkTypes.h"
+
+/** \class SkTime
+ Platform-implemented utilities to return time of day, and millisecond counter.
+*/
+class SkTime {
+public:
+ struct DateTime {
+ uint16_t fYear; //!< e.g. 2005
+ uint8_t fMonth; //!< 1..12
+ uint8_t fDayOfWeek; //!< 0..6, 0==Sunday
+ uint8_t fDay; //!< 1..31
+ uint8_t fHour; //!< 0..23
+ uint8_t fMinute; //!< 0..59
+ uint8_t fSecond; //!< 0..59
+ };
+ static void GetDateTime(DateTime*);
+
+ static SkMSec GetMSecs();
+};
+
+#if defined(SK_DEBUG) && defined(SK_BUILD_FOR_WIN32)
+ extern SkMSec gForceTickCount;
+#endif
+
+#define SK_TIME_FACTOR 1
+
+///////////////////////////////////////////////////////////////////////////////
+
+class SkAutoTime {
+public:
+ // The label is not deep-copied, so its address must remain valid for the
+ // lifetime of this object
+ SkAutoTime(const char* label = NULL, SkMSec minToDump = 0) : fLabel(label)
+ {
+ fNow = SkTime::GetMSecs();
+ fMinToDump = minToDump;
+ }
+ ~SkAutoTime()
+ {
+ SkMSec dur = SkTime::GetMSecs() - fNow;
+ if (dur >= fMinToDump) {
+ SkDebugf("%s %d\n", fLabel ? fLabel : "", dur);
+ }
+ }
+private:
+ const char* fLabel;
+ SkMSec fNow;
+ SkMSec fMinToDump;
+};
+
+#endif
diff --git a/core/SkTrace.h b/core/SkTrace.h
new file mode 100644
index 0000000..e6e7e2c
--- /dev/null
+++ b/core/SkTrace.h
@@ -0,0 +1,45 @@
+
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkTrace_DEFINED
+#define SkTrace_DEFINED
+
+#ifdef SK_USER_TRACE_INCLUDE_FILE
+
+/* If your system embeds skia and has complex event logging, in
+ src/config/SkUserConfig.h:
+ - define the three SK_TRACE_EVENT macros to map to your system's
+ equivalents,
+ - define the name of the include file in SK_USER_TRACE_INCLUDE_FILE
+ A trivial example is given in src/utils/SkDebugTrace.h.
+
+ All arguments are const char*. Skia typically passes the name of
+ the object and function (and sometimes region of interest within
+ the function) separated by double colons for 'event'.
+
+ SK_TRACE_EVENT1 and SK_TRACE_EVENT2 take one or two arbitrary
+ name-value pairs that you also want to log. SkStringPrintf() is useful
+ for formatting these values.
+
+ For example:
+ SK_TRACE_EVENT0("GrContext::createAndLockTexture");
+ SK_TRACE_EVENT1("GrDefaultPathRenderer::onDrawPath::renderPasses",
+ "verts", SkStringPrintf("%i", vert - base).c_str());
+*/
+
+ #include SK_USER_TRACE_INCLUDE_FILE
+
+#else
+
+ #define SK_TRACE_EVENT0(event)
+ #define SK_TRACE_EVENT1(event, name1, value1)
+ #define SK_TRACE_EVENT2(event, name1, value1, name2, value2)
+
+#endif
+
+#endif
diff --git a/core/SkTypeface.h b/core/SkTypeface.h
new file mode 100644
index 0000000..ca88a1b
--- /dev/null
+++ b/core/SkTypeface.h
@@ -0,0 +1,336 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkTypeface_DEFINED
+#define SkTypeface_DEFINED
+
+#include "SkAdvancedTypefaceMetrics.h"
+#include "SkWeakRefCnt.h"
+
+class SkDescriptor;
+class SkFontDescriptor;
+class SkScalerContext;
+struct SkScalerContextRec;
+class SkStream;
+class SkAdvancedTypefaceMetrics;
+class SkWStream;
+
+typedef uint32_t SkFontID;
+/** Machine endian. */
+typedef uint32_t SkFontTableTag;
+
+/** \class SkTypeface
+
+ The SkTypeface class specifies the typeface and intrinsic style of a font.
+ This is used in the paint, along with optionally algorithmic settings like
+ textSize, textSkewX, textScaleX, kFakeBoldText_Mask, to specify
+ how text appears when drawn (and measured).
+
+ Typeface objects are immutable, and so they can be shared between threads.
+*/
+class SK_API SkTypeface : public SkWeakRefCnt {
+public:
+ SK_DECLARE_INST_COUNT(SkTypeface)
+
+ /** Style specifies the intrinsic style attributes of a given typeface
+ */
+ enum Style {
+ kNormal = 0,
+ kBold = 0x01,
+ kItalic = 0x02,
+
+ // helpers
+ kBoldItalic = 0x03
+ };
+
+ /** Returns the typeface's intrinsic style attributes
+ */
+ Style style() const { return fStyle; }
+
+ /** Returns true if getStyle() has the kBold bit set.
+ */
+ bool isBold() const { return (fStyle & kBold) != 0; }
+
+ /** Returns true if getStyle() has the kItalic bit set.
+ */
+ bool isItalic() const { return (fStyle & kItalic) != 0; }
+
+ /** Returns true if the typeface claims to be fixed-pitch.
+ * This is a style bit, advance widths may vary even if this returns true.
+ */
+ bool isFixedPitch() const { return fIsFixedPitch; }
+
+ /** Return a 32bit value for this typeface, unique for the underlying font
+ data. Will never return 0.
+ */
+ SkFontID uniqueID() const { return fUniqueID; }
+
+ /** Return the uniqueID for the specified typeface. If the face is null,
+ resolve it to the default font and return its uniqueID. Will never
+ return 0.
+ */
+ static SkFontID UniqueID(const SkTypeface* face);
+
+ /** Returns true if the two typefaces reference the same underlying font,
+ handling either being null (treating null as the default font)
+ */
+ static bool Equal(const SkTypeface* facea, const SkTypeface* faceb);
+
+ /**
+ * Returns a ref() to the default typeface. The caller must call unref()
+ * when they are done referencing the object. Never returns NULL.
+ */
+ static SkTypeface* RefDefault(Style style = SkTypeface::kNormal);
+
+ /** Return a new reference to the typeface that most closely matches the
+ requested familyName and style. Pass null as the familyName to return
+ the default font for the requested style. Will never return null
+
+ @param familyName May be NULL. The name of the font family.
+ @param style The style (normal, bold, italic) of the typeface.
+ @return reference to the closest-matching typeface. Call must call
+ unref() when they are done.
+ */
+ static SkTypeface* CreateFromName(const char familyName[], Style style);
+
+ /** Return a new reference to the typeface that most closely matches the
+ requested typeface and specified Style. Use this call if you want to
+ pick a new style from the same family of the existing typeface.
+ If family is NULL, this selects from the default font's family.
+
+ @param family May be NULL. The name of the existing type face.
+ @param s The style (normal, bold, italic) of the type face.
+ @return reference to the closest-matching typeface. Call must call
+ unref() when they are done.
+ */
+ static SkTypeface* CreateFromTypeface(const SkTypeface* family, Style s);
+
+ /** Return a new typeface given a file. If the file does not exist, or is
+ not a valid font file, returns null.
+ */
+ static SkTypeface* CreateFromFile(const char path[]);
+
+ /** Return a new typeface given a stream. If the stream is
+ not a valid font file, returns null. Ownership of the stream is
+ transferred, so the caller must not reference it again.
+ */
+ static SkTypeface* CreateFromStream(SkStream* stream);
+
+ /** Write a unique signature to a stream, sufficient to reconstruct a
+ typeface referencing the same font when Deserialize is called.
+ */
+ void serialize(SkWStream*) const;
+
+ /** Given the data previously written by serialize(), return a new instance
+ to a typeface referring to the same font. If that font is not available,
+ return null. If an instance is returned, the caller is responsible for
+ calling unref() when they are done with it.
+ */
+ static SkTypeface* Deserialize(SkStream*);
+
+ /** Retrieve detailed typeface metrics. Used by the PDF backend.
+ @param perGlyphInfo Indicate what glyph specific information (advances,
+ names, etc.) should be populated.
+ @param glyphIDs For per-glyph info, specify subset of the font by
+ giving glyph ids. Each integer represents a glyph
+ id. Passing NULL means all glyphs in the font.
+ @param glyphIDsCount Number of elements in subsetGlyphIds. Ignored if
+ glyphIDs is NULL.
+ @return The returned object has already been referenced.
+ */
+ SkAdvancedTypefaceMetrics* getAdvancedTypefaceMetrics(
+ SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo,
+ const uint32_t* glyphIDs = NULL,
+ uint32_t glyphIDsCount = 0) const;
+
+ enum Encoding {
+ kUTF8_Encoding,
+ kUTF16_Encoding,
+ kUTF32_Encoding
+ };
+
+ /**
+ * Given an array of character codes, of the specified encoding,
+ * optionally return their corresponding glyph IDs (if glyphs is not NULL).
+ *
+ * @param chars pointer to the array of character codes
+ * @param encoding how the characteds are encoded
+ * @param glyphs (optional) returns the corresponding glyph IDs for each
+ * character code, up to glyphCount values. If a character code is
+ * not found in the typeface, the corresponding glyph ID will be 0.
+ * @param glyphCount number of code points in 'chars' to process. If glyphs
+ * is not NULL, then it must point sufficient memory to write
+ * glyphCount values into it.
+ * @return the number of number of continuous non-zero glyph IDs computed
+ * from the beginning of chars. This value is valid, even if the
+ * glyphs parameter is NULL.
+ */
+ int charsToGlyphs(const void* chars, Encoding encoding, uint16_t glyphs[],
+ int glyphCount) const;
+
+ /**
+ * Return the number of glyphs in the typeface.
+ */
+ int countGlyphs() const;
+
+ // Table getters -- may fail if the underlying font format is not organized
+ // as 4-byte tables.
+
+ /** Return the number of tables in the font. */
+ int countTables() const;
+
+ /** Copy into tags[] (allocated by the caller) the list of table tags in
+ * the font, and return the number. This will be the same as CountTables()
+ * or 0 if an error occured. If tags == NULL, this only returns the count
+ * (the same as calling countTables()).
+ */
+ int getTableTags(SkFontTableTag tags[]) const;
+
+ /** Given a table tag, return the size of its contents, or 0 if not present
+ */
+ size_t getTableSize(SkFontTableTag) const;
+
+ /** Copy the contents of a table into data (allocated by the caller). Note
+ * that the contents of the table will be in their native endian order
+ * (which for most truetype tables is big endian). If the table tag is
+ * not found, or there is an error copying the data, then 0 is returned.
+ * If this happens, it is possible that some or all of the memory pointed
+ * to by data may have been written to, even though an error has occured.
+ *
+ * @param fontID the font to copy the table from
+ * @param tag The table tag whose contents are to be copied
+ * @param offset The offset in bytes into the table's contents where the
+ * copy should start from.
+ * @param length The number of bytes, starting at offset, of table data
+ * to copy.
+ * @param data storage address where the table contents are copied to
+ * @return the number of bytes actually copied into data. If offset+length
+ * exceeds the table's size, then only the bytes up to the table's
+ * size are actually copied, and this is the value returned. If
+ * offset > the table's size, or tag is not a valid table,
+ * then 0 is returned.
+ */
+ size_t getTableData(SkFontTableTag tag, size_t offset, size_t length,
+ void* data) const;
+
+ /**
+ * Return the units-per-em value for this typeface, or zero if there is an
+ * error.
+ */
+ int getUnitsPerEm() const;
+
+ struct LocalizedString {
+ SkString fString;
+ SkString fLanguage;
+ };
+ class LocalizedStrings : ::SkNoncopyable {
+ public:
+ virtual ~LocalizedStrings() { }
+ virtual bool next(LocalizedString* localizedString) = 0;
+ void unref() { SkDELETE(this); }
+ };
+ /**
+ * Returns an iterator which will attempt to enumerate all of the
+ * family names specified by the font.
+ * It is the caller's responsibility to unref() the returned pointer.
+ */
+ LocalizedStrings* createFamilyNameIterator() const;
+
+ /**
+ * Return the family name for this typeface. It will always be returned
+ * encoded as UTF8, but the language of the name is whatever the host
+ * platform chooses.
+ */
+ void getFamilyName(SkString* name) const;
+
+ /**
+ * Return a stream for the contents of the font data, or NULL on failure.
+ * If ttcIndex is not null, it is set to the TrueTypeCollection index
+ * of this typeface within the stream, or 0 if the stream is not a
+ * collection.
+ */
+ SkStream* openStream(int* ttcIndex) const;
+
+ /**
+ * Search within this typeface's family for a best match to the
+ * specified style, and return a ref to that typeface. Note: the
+ * returned object could be this, if it is the best match, or it
+ * could be a different typeface. Either way, the caller must balance
+ * this call with unref() on the returned object.
+ *
+ * Will never return NULL.
+ */
+ SkTypeface* refMatchingStyle(Style) const;
+
+ /**
+ * Return a scalercontext for the given descriptor. If this fails, then
+ * if allowFailure is true, this returns NULL, else it returns a
+ * dummy scalercontext that will not crash, but will draw nothing.
+ */
+ SkScalerContext* createScalerContext(const SkDescriptor*,
+ bool allowFailure = false) const;
+
+ // PRIVATE / EXPERIMENTAL -- do not call
+ void filterRec(SkScalerContextRec* rec) const {
+ this->onFilterRec(rec);
+ }
+ // PRIVATE / EXPERIMENTAL -- do not call
+ void getFontDescriptor(SkFontDescriptor* desc, bool* isLocal) const {
+ this->onGetFontDescriptor(desc, isLocal);
+ }
+
+protected:
+ /** uniqueID must be unique and non-zero
+ */
+ SkTypeface(Style style, SkFontID uniqueID, bool isFixedPitch = false);
+ virtual ~SkTypeface();
+
+ /** Sets the fixedPitch bit. If used, must be called in the constructor. */
+ void setIsFixedPitch(bool isFixedPitch) { fIsFixedPitch = isFixedPitch; }
+
+ friend class SkScalerContext;
+ static SkTypeface* GetDefaultTypeface(Style style = SkTypeface::kNormal);
+
+ virtual SkScalerContext* onCreateScalerContext(const SkDescriptor*) const = 0;
+ virtual void onFilterRec(SkScalerContextRec*) const = 0;
+ virtual SkAdvancedTypefaceMetrics* onGetAdvancedTypefaceMetrics(
+ SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo,
+ const uint32_t* glyphIDs,
+ uint32_t glyphIDsCount) const = 0;
+ virtual SkStream* onOpenStream(int* ttcIndex) const = 0;
+ virtual void onGetFontDescriptor(SkFontDescriptor*, bool* isLocal) const = 0;
+
+ virtual int onCharsToGlyphs(const void* chars, Encoding, uint16_t glyphs[],
+ int glyphCount) const;
+ virtual int onCountGlyphs() const = 0;
+
+ virtual int onGetUPEM() const = 0;
+
+ virtual LocalizedStrings* onCreateFamilyNameIterator() const = 0;
+
+ virtual int onGetTableTags(SkFontTableTag tags[]) const = 0;
+ virtual size_t onGetTableData(SkFontTableTag, size_t offset,
+ size_t length, void* data) const = 0;
+
+ virtual SkTypeface* onRefMatchingStyle(Style styleBits) const = 0;
+
+private:
+ SkFontID fUniqueID;
+ Style fStyle;
+ bool fIsFixedPitch;
+
+ friend class SkPaint;
+ friend class SkGlyphCache; // GetDefaultTypeface
+ // just so deprecated fonthost can call protected methods
+ friend class SkFontHost;
+
+ typedef SkWeakRefCnt INHERITED;
+};
+
+#endif
diff --git a/core/SkTypes.h b/core/SkTypes.h
new file mode 100644
index 0000000..0393691
--- /dev/null
+++ b/core/SkTypes.h
@@ -0,0 +1,607 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkTypes_DEFINED
+#define SkTypes_DEFINED
+
+#include "SkPreConfig.h"
+#include "SkUserConfig.h"
+#include "SkPostConfig.h"
+
+#ifndef SK_IGNORE_STDINT_DOT_H
+ #include <stdint.h>
+#endif
+
+#include <stdio.h>
+
+/** \file SkTypes.h
+*/
+
+/** See SkGraphics::GetVersion() to retrieve these at runtime
+ */
+#define SKIA_VERSION_MAJOR 1
+#define SKIA_VERSION_MINOR 0
+#define SKIA_VERSION_PATCH 0
+
+/*
+ memory wrappers to be implemented by the porting layer (platform)
+*/
+
+/** Called internally if we run out of memory. The platform implementation must
+ not return, but should either throw an exception or otherwise exit.
+*/
+SK_API extern void sk_out_of_memory(void);
+/** Called internally if we hit an unrecoverable error.
+ The platform implementation must not return, but should either throw
+ an exception or otherwise exit.
+*/
+SK_API extern void sk_throw(void);
+
+enum {
+ SK_MALLOC_TEMP = 0x01, //!< hint to sk_malloc that the requested memory will be freed in the scope of the stack frame
+ SK_MALLOC_THROW = 0x02 //!< instructs sk_malloc to call sk_throw if the memory cannot be allocated.
+};
+/** Return a block of memory (at least 4-byte aligned) of at least the
+ specified size. If the requested memory cannot be returned, either
+ return null (if SK_MALLOC_TEMP bit is clear) or call sk_throw()
+ (if SK_MALLOC_TEMP bit is set). To free the memory, call sk_free().
+*/
+SK_API extern void* sk_malloc_flags(size_t size, unsigned flags);
+/** Same as sk_malloc(), but hard coded to pass SK_MALLOC_THROW as the flag
+*/
+SK_API extern void* sk_malloc_throw(size_t size);
+/** Same as standard realloc(), but this one never returns null on failure. It will throw
+ an exception if it fails.
+*/
+SK_API extern void* sk_realloc_throw(void* buffer, size_t size);
+/** Free memory returned by sk_malloc(). It is safe to pass null.
+*/
+SK_API extern void sk_free(void*);
+
+// bzero is safer than memset, but we can't rely on it, so... sk_bzero()
+static inline void sk_bzero(void* buffer, size_t size) {
+ memset(buffer, 0, size);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+#ifdef SK_OVERRIDE_GLOBAL_NEW
+#include <new>
+
+inline void* operator new(size_t size) {
+ return sk_malloc_throw(size);
+}
+
+inline void operator delete(void* p) {
+ sk_free(p);
+}
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+
+#define SK_INIT_TO_AVOID_WARNING = 0
+
+#ifndef SkDebugf
+ void SkDebugf(const char format[], ...);
+#endif
+
+#ifdef SK_DEBUG
+ #define SkASSERT(cond) SK_DEBUGBREAK(cond)
+ #define SkDEBUGFAIL(message) SkASSERT(false && message)
+ #define SkDEBUGCODE(code) code
+ #define SkDECLAREPARAM(type, var) , type var
+ #define SkPARAM(var) , var
+// #define SkDEBUGF(args ) SkDebugf##args
+ #define SkDEBUGF(args ) SkDebugf args
+ #define SkAssertResult(cond) SkASSERT(cond)
+#else
+ #define SkASSERT(cond)
+ #define SkDEBUGFAIL(message)
+ #define SkDEBUGCODE(code)
+ #define SkDEBUGF(args)
+ #define SkDECLAREPARAM(type, var)
+ #define SkPARAM(var)
+
+ // unlike SkASSERT, this guy executes its condition in the non-debug build
+ #define SkAssertResult(cond) cond
+#endif
+
+#ifdef SK_DEVELOPER
+ #define SkDEVCODE(code) code
+ // the 'toString' helper functions convert Sk* objects to human-readable
+ // form in developer mode
+ #define SK_DEVELOPER_TO_STRING() virtual void toString(SkString* str) const SK_OVERRIDE;
+#else
+ #define SkDEVCODE(code)
+ #define SK_DEVELOPER_TO_STRING()
+#endif
+
+template <bool>
+struct SkCompileAssert {
+};
+
+#define SK_COMPILE_ASSERT(expr, msg) \
+ typedef SkCompileAssert<(bool(expr))> msg[bool(expr) ? 1 : -1] SK_UNUSED
+
+/*
+ * Usage: SK_MACRO_CONCAT(a, b) to construct the symbol ab
+ *
+ * SK_MACRO_CONCAT_IMPL_PRIV just exists to make this work. Do not use directly
+ *
+ */
+#define SK_MACRO_CONCAT(X, Y) SK_MACRO_CONCAT_IMPL_PRIV(X, Y)
+#define SK_MACRO_CONCAT_IMPL_PRIV(X, Y) X ## Y
+
+/*
+ * Usage: SK_MACRO_APPEND_LINE(foo) to make foo123, where 123 is the current
+ * line number. Easy way to construct
+ * unique names for local functions or
+ * variables.
+ */
+#define SK_MACRO_APPEND_LINE(name) SK_MACRO_CONCAT(name, __LINE__)
+
+///////////////////////////////////////////////////////////////////////
+
+/**
+ * Fast type for signed 8 bits. Use for parameter passing and local variables,
+ * not for storage.
+ */
+typedef int S8CPU;
+
+/**
+ * Fast type for unsigned 8 bits. Use for parameter passing and local
+ * variables, not for storage
+ */
+typedef unsigned U8CPU;
+
+/**
+ * Fast type for signed 16 bits. Use for parameter passing and local variables,
+ * not for storage
+ */
+typedef int S16CPU;
+
+/**
+ * Fast type for unsigned 16 bits. Use for parameter passing and local
+ * variables, not for storage
+ */
+typedef unsigned U16CPU;
+
+/**
+ * Meant to be faster than bool (doesn't promise to be 0 or 1,
+ * just 0 or non-zero
+ */
+typedef int SkBool;
+
+/**
+ * Meant to be a small version of bool, for storage purposes. Will be 0 or 1
+ */
+typedef uint8_t SkBool8;
+
+#ifdef SK_DEBUG
+ SK_API int8_t SkToS8(intmax_t);
+ SK_API uint8_t SkToU8(uintmax_t);
+ SK_API int16_t SkToS16(intmax_t);
+ SK_API uint16_t SkToU16(uintmax_t);
+ SK_API int32_t SkToS32(intmax_t);
+ SK_API uint32_t SkToU32(uintmax_t);
+#else
+ #define SkToS8(x) ((int8_t)(x))
+ #define SkToU8(x) ((uint8_t)(x))
+ #define SkToS16(x) ((int16_t)(x))
+ #define SkToU16(x) ((uint16_t)(x))
+ #define SkToS32(x) ((int32_t)(x))
+ #define SkToU32(x) ((uint32_t)(x))
+#endif
+
+/** Returns 0 or 1 based on the condition
+*/
+#define SkToBool(cond) ((cond) != 0)
+
+#define SK_MaxS16 32767
+#define SK_MinS16 -32767
+#define SK_MaxU16 0xFFFF
+#define SK_MinU16 0
+#define SK_MaxS32 0x7FFFFFFF
+#define SK_MinS32 -SK_MaxS32
+#define SK_MaxU32 0xFFFFFFFF
+#define SK_MinU32 0
+#define SK_NaN32 (1 << 31)
+
+/** Returns true if the value can be represented with signed 16bits
+ */
+static inline bool SkIsS16(long x) {
+ return (int16_t)x == x;
+}
+
+/** Returns true if the value can be represented with unsigned 16bits
+ */
+static inline bool SkIsU16(long x) {
+ return (uint16_t)x == x;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+#ifndef SK_OFFSETOF
+ #define SK_OFFSETOF(type, field) (size_t)((char*)&(((type*)1)->field) - (char*)1)
+#endif
+
+/** Returns the number of entries in an array (not a pointer)
+*/
+#define SK_ARRAY_COUNT(array) (sizeof(array) / sizeof(array[0]))
+
+#define SkAlign2(x) (((x) + 1) >> 1 << 1)
+#define SkIsAlign2(x) (0 == ((x) & 1))
+
+#define SkAlign4(x) (((x) + 3) >> 2 << 2)
+#define SkIsAlign4(x) (0 == ((x) & 3))
+
+#define SkAlign8(x) (((x) + 7) >> 3 << 3)
+#define SkIsAlign8(x) (0 == ((x) & 7))
+
+typedef uint32_t SkFourByteTag;
+#define SkSetFourByteTag(a, b, c, d) (((a) << 24) | ((b) << 16) | ((c) << 8) | (d))
+
+/** 32 bit integer to hold a unicode value
+*/
+typedef int32_t SkUnichar;
+/** 32 bit value to hold a millisecond count
+*/
+typedef uint32_t SkMSec;
+/** 1 second measured in milliseconds
+*/
+#define SK_MSec1 1000
+/** maximum representable milliseconds
+*/
+#define SK_MSecMax 0x7FFFFFFF
+/** Returns a < b for milliseconds, correctly handling wrap-around from 0xFFFFFFFF to 0
+*/
+#define SkMSec_LT(a, b) ((int32_t)(a) - (int32_t)(b) < 0)
+/** Returns a <= b for milliseconds, correctly handling wrap-around from 0xFFFFFFFF to 0
+*/
+#define SkMSec_LE(a, b) ((int32_t)(a) - (int32_t)(b) <= 0)
+
+/****************************************************************************
+ The rest of these only build with C++
+*/
+#ifdef __cplusplus
+
+/** Faster than SkToBool for integral conditions. Returns 0 or 1
+*/
+static inline int Sk32ToBool(uint32_t n) {
+ return (n | (0-n)) >> 31;
+}
+
+/** Generic swap function. Classes with efficient swaps should specialize this function to take
+ their fast path. This function is used by SkTSort. */
+template <typename T> inline void SkTSwap(T& a, T& b) {
+ T c(a);
+ a = b;
+ b = c;
+}
+
+static inline int32_t SkAbs32(int32_t value) {
+ if (value < 0) {
+ value = -value;
+ }
+ return value;
+}
+
+template <typename T> inline T SkTAbs(T value) {
+ if (value < 0) {
+ value = -value;
+ }
+ return value;
+}
+
+static inline int32_t SkMax32(int32_t a, int32_t b) {
+ if (a < b)
+ a = b;
+ return a;
+}
+
+static inline int32_t SkMin32(int32_t a, int32_t b) {
+ if (a > b)
+ a = b;
+ return a;
+}
+
+template <typename T> const T& SkTMin(const T& a, const T& b) {
+ return (a < b) ? a : b;
+}
+
+template <typename T> const T& SkTMax(const T& a, const T& b) {
+ return (b < a) ? a : b;
+}
+
+static inline int32_t SkSign32(int32_t a) {
+ return (a >> 31) | ((unsigned) -a >> 31);
+}
+
+static inline int32_t SkFastMin32(int32_t value, int32_t max) {
+ if (value > max) {
+ value = max;
+ }
+ return value;
+}
+
+/** Returns signed 32 bit value pinned between min and max, inclusively
+*/
+static inline int32_t SkPin32(int32_t value, int32_t min, int32_t max) {
+ if (value < min) {
+ value = min;
+ }
+ if (value > max) {
+ value = max;
+ }
+ return value;
+}
+
+static inline uint32_t SkSetClearShift(uint32_t bits, bool cond,
+ unsigned shift) {
+ SkASSERT((int)cond == 0 || (int)cond == 1);
+ return (bits & ~(1 << shift)) | ((int)cond << shift);
+}
+
+static inline uint32_t SkSetClearMask(uint32_t bits, bool cond,
+ uint32_t mask) {
+ return cond ? bits | mask : bits & ~mask;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+/** Use to combine multiple bits in a bitmask in a type safe way.
+ */
+template <typename T>
+T SkTBitOr(T a, T b) {
+ return (T)(a | b);
+}
+
+/**
+ * Use to cast a pointer to a different type, and maintaining strict-aliasing
+ */
+template <typename Dst> Dst SkTCast(const void* ptr) {
+ union {
+ const void* src;
+ Dst dst;
+ } data;
+ data.src = ptr;
+ return data.dst;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+/** \class SkNoncopyable
+
+SkNoncopyable is the base class for objects that may do not want to
+be copied. It hides its copy-constructor and its assignment-operator.
+*/
+class SK_API SkNoncopyable {
+public:
+ SkNoncopyable() {}
+
+private:
+ SkNoncopyable(const SkNoncopyable&);
+ SkNoncopyable& operator=(const SkNoncopyable&);
+};
+
+class SkAutoFree : SkNoncopyable {
+public:
+ SkAutoFree() : fPtr(NULL) {}
+ explicit SkAutoFree(void* ptr) : fPtr(ptr) {}
+ ~SkAutoFree() { sk_free(fPtr); }
+
+ /** Return the currently allocate buffer, or null
+ */
+ void* get() const { return fPtr; }
+
+ /** Assign a new ptr allocated with sk_malloc (or null), and return the
+ previous ptr. Note it is the caller's responsibility to sk_free the
+ returned ptr.
+ */
+ void* set(void* ptr) {
+ void* prev = fPtr;
+ fPtr = ptr;
+ return prev;
+ }
+
+ /** Transfer ownership of the current ptr to the caller, setting the
+ internal reference to null. Note the caller is reponsible for calling
+ sk_free on the returned address.
+ */
+ void* detach() { return this->set(NULL); }
+
+ /** Free the current buffer, and set the internal reference to NULL. Same
+ as calling sk_free(detach())
+ */
+ void free() {
+ sk_free(fPtr);
+ fPtr = NULL;
+ }
+
+private:
+ void* fPtr;
+ // illegal
+ SkAutoFree(const SkAutoFree&);
+ SkAutoFree& operator=(const SkAutoFree&);
+};
+
+/**
+ * Manage an allocated block of heap memory. This object is the sole manager of
+ * the lifetime of the block, so the caller must not call sk_free() or delete
+ * on the block, unless detach() was called.
+ */
+class SkAutoMalloc : public SkNoncopyable {
+public:
+ explicit SkAutoMalloc(size_t size = 0) {
+ fPtr = size ? sk_malloc_throw(size) : NULL;
+ fSize = size;
+ }
+
+ ~SkAutoMalloc() {
+ sk_free(fPtr);
+ }
+
+ /**
+ * Passed to reset to specify what happens if the requested size is smaller
+ * than the current size (and the current block was dynamically allocated).
+ */
+ enum OnShrink {
+ /**
+ * If the requested size is smaller than the current size, and the
+ * current block is dynamically allocated, free the old block and
+ * malloc a new block of the smaller size.
+ */
+ kAlloc_OnShrink,
+
+ /**
+ * If the requested size is smaller than the current size, and the
+ * current block is dynamically allocated, just return the old
+ * block.
+ */
+ kReuse_OnShrink
+ };
+
+ /**
+ * Reallocates the block to a new size. The ptr may or may not change.
+ */
+ void* reset(size_t size, OnShrink shrink = kAlloc_OnShrink, bool* didChangeAlloc = NULL) {
+ if (size == fSize || (kReuse_OnShrink == shrink && size < fSize)) {
+ if (NULL != didChangeAlloc) {
+ *didChangeAlloc = false;
+ }
+ return fPtr;
+ }
+
+ sk_free(fPtr);
+ fPtr = size ? sk_malloc_throw(size) : NULL;
+ fSize = size;
+ if (NULL != didChangeAlloc) {
+ *didChangeAlloc = true;
+ }
+
+ return fPtr;
+ }
+
+ /**
+ * Releases the block back to the heap
+ */
+ void free() {
+ this->reset(0);
+ }
+
+ /**
+ * Return the allocated block.
+ */
+ void* get() { return fPtr; }
+ const void* get() const { return fPtr; }
+
+ /** Transfer ownership of the current ptr to the caller, setting the
+ internal reference to null. Note the caller is reponsible for calling
+ sk_free on the returned address.
+ */
+ void* detach() {
+ void* ptr = fPtr;
+ fPtr = NULL;
+ fSize = 0;
+ return ptr;
+ }
+
+private:
+ void* fPtr;
+ size_t fSize; // can be larger than the requested size (see kReuse)
+};
+
+/**
+ * Manage an allocated block of memory. If the requested size is <= kSize, then
+ * the allocation will come from the stack rather than the heap. This object
+ * is the sole manager of the lifetime of the block, so the caller must not
+ * call sk_free() or delete on the block.
+ */
+template <size_t kSize> class SkAutoSMalloc : SkNoncopyable {
+public:
+ /**
+ * Creates initially empty storage. get() returns a ptr, but it is to
+ * a zero-byte allocation. Must call reset(size) to return an allocated
+ * block.
+ */
+ SkAutoSMalloc() {
+ fPtr = fStorage;
+ fSize = kSize;
+ }
+
+ /**
+ * Allocate a block of the specified size. If size <= kSize, then the
+ * allocation will come from the stack, otherwise it will be dynamically
+ * allocated.
+ */
+ explicit SkAutoSMalloc(size_t size) {
+ fPtr = fStorage;
+ fSize = kSize;
+ this->reset(size);
+ }
+
+ /**
+ * Free the allocated block (if any). If the block was small enought to
+ * have been allocated on the stack (size <= kSize) then this does nothing.
+ */
+ ~SkAutoSMalloc() {
+ if (fPtr != (void*)fStorage) {
+ sk_free(fPtr);
+ }
+ }
+
+ /**
+ * Return the allocated block. May return non-null even if the block is
+ * of zero size. Since this may be on the stack or dynamically allocated,
+ * the caller must not call sk_free() on it, but must rely on SkAutoSMalloc
+ * to manage it.
+ */
+ void* get() const { return fPtr; }
+
+ /**
+ * Return a new block of the requested size, freeing (as necessary) any
+ * previously allocated block. As with the constructor, if size <= kSize
+ * then the return block may be allocated locally, rather than from the
+ * heap.
+ */
+ void* reset(size_t size,
+ SkAutoMalloc::OnShrink shrink = SkAutoMalloc::kAlloc_OnShrink,
+ bool* didChangeAlloc = NULL) {
+ size = (size < kSize) ? kSize : size;
+ bool alloc = size != fSize && (SkAutoMalloc::kAlloc_OnShrink == shrink || size > fSize);
+ if (NULL != didChangeAlloc) {
+ *didChangeAlloc = alloc;
+ }
+ if (alloc) {
+ if (fPtr != (void*)fStorage) {
+ sk_free(fPtr);
+ }
+
+ if (size == kSize) {
+ SkASSERT(fPtr != fStorage); // otherwise we lied when setting didChangeAlloc.
+ fPtr = fStorage;
+ } else {
+ fPtr = sk_malloc_flags(size, SK_MALLOC_THROW | SK_MALLOC_TEMP);
+ }
+
+ fSize = size;
+ }
+ SkASSERT(fSize >= size && fSize >= kSize);
+ SkASSERT((fPtr == fStorage) || fSize > kSize);
+ return fPtr;
+ }
+
+private:
+ void* fPtr;
+ size_t fSize; // can be larger than the requested size (see kReuse)
+ uint32_t fStorage[(kSize + 3) >> 2];
+};
+
+#endif /* C++ */
+
+#endif
diff --git a/core/SkUnPreMultiply.h b/core/SkUnPreMultiply.h
new file mode 100644
index 0000000..4fa5d57
--- /dev/null
+++ b/core/SkUnPreMultiply.h
@@ -0,0 +1,56 @@
+
+/*
+ * Copyright 2008 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+
+
+
+#ifndef SkUnPreMultiply_DEFINED
+#define SkUnPreMultiply_DEFINED
+
+#include "SkColor.h"
+
+class SK_API SkUnPreMultiply {
+public:
+ typedef uint32_t Scale;
+
+ // index this table with alpha [0..255]
+ static const Scale* GetScaleTable() {
+ return gTable;
+ }
+
+ static Scale GetScale(U8CPU alpha) {
+ SkASSERT(alpha <= 255);
+ return gTable[alpha];
+ }
+
+ /** Usage:
+
+ const Scale* table = SkUnPreMultiply::GetScaleTable();
+
+ for (...) {
+ unsigned a = ...
+ SkUnPreMultiply::Scale scale = table[a];
+
+ red = SkUnPreMultiply::ApplyScale(scale, red);
+ ...
+ // now red is unpremultiplied
+ }
+ */
+ static U8CPU ApplyScale(Scale scale, U8CPU component) {
+ SkASSERT(component <= 255);
+ return (scale * component + (1 << 23)) >> 24;
+ }
+
+ static SkColor PMColorToColor(SkPMColor c);
+
+private:
+ static const uint32_t gTable[256];
+};
+
+#endif
diff --git a/core/SkUnitMapper.h b/core/SkUnitMapper.h
new file mode 100644
index 0000000..754be26
--- /dev/null
+++ b/core/SkUnitMapper.h
@@ -0,0 +1,35 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkUnitMapper_DEFINED
+#define SkUnitMapper_DEFINED
+
+#include "SkRefCnt.h"
+#include "SkScalar.h"
+
+#include "SkFlattenable.h"
+
+class SkUnitMapper : public SkFlattenable {
+public:
+ SK_DECLARE_INST_COUNT(SkUnitMapper)
+
+ SkUnitMapper() {}
+
+ /** Given a value in [0..0xFFFF], return a value in the same range.
+ */
+ virtual uint16_t mapUnit16(uint16_t x) = 0;
+
+protected:
+ SkUnitMapper(SkFlattenableReadBuffer& rb) : SkFlattenable(rb) {}
+
+private:
+ typedef SkFlattenable INHERITED;
+};
+
+#endif
diff --git a/core/SkUtils.h b/core/SkUtils.h
new file mode 100644
index 0000000..e29367d
--- /dev/null
+++ b/core/SkUtils.h
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkUtils_DEFINED
+#define SkUtils_DEFINED
+
+#include "SkTypes.h"
+
+///////////////////////////////////////////////////////////////////////////////
+
+/** Similar to memset(), but it assigns a 16bit value into the buffer.
+ @param buffer The memory to have value copied into it
+ @param value The 16bit value to be copied into buffer
+ @param count The number of times value should be copied into the buffer.
+*/
+void sk_memset16_portable(uint16_t dst[], uint16_t value, int count);
+typedef void (*SkMemset16Proc)(uint16_t dst[], uint16_t value, int count);
+SkMemset16Proc SkMemset16GetPlatformProc();
+
+/** Similar to memset(), but it assigns a 32bit value into the buffer.
+ @param buffer The memory to have value copied into it
+ @param value The 32bit value to be copied into buffer
+ @param count The number of times value should be copied into the buffer.
+*/
+void sk_memset32_portable(uint32_t dst[], uint32_t value, int count);
+typedef void (*SkMemset32Proc)(uint32_t dst[], uint32_t value, int count);
+SkMemset32Proc SkMemset32GetPlatformProc();
+
+#ifndef sk_memset16
+extern SkMemset16Proc sk_memset16;
+#endif
+
+#ifndef sk_memset32
+extern SkMemset32Proc sk_memset32;
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+
+#define kMaxBytesInUTF8Sequence 4
+
+#ifdef SK_DEBUG
+ int SkUTF8_LeadByteToCount(unsigned c);
+#else
+ #define SkUTF8_LeadByteToCount(c) ((((0xE5 << 24) >> ((unsigned)c >> 4 << 1)) & 3) + 1)
+#endif
+
+inline int SkUTF8_CountUTF8Bytes(const char utf8[]) {
+ SkASSERT(utf8);
+ return SkUTF8_LeadByteToCount(*(const uint8_t*)utf8);
+}
+
+int SkUTF8_CountUnichars(const char utf8[]);
+int SkUTF8_CountUnichars(const char utf8[], size_t byteLength);
+SkUnichar SkUTF8_ToUnichar(const char utf8[]);
+SkUnichar SkUTF8_NextUnichar(const char**);
+SkUnichar SkUTF8_PrevUnichar(const char**);
+
+/** Return the number of bytes need to convert a unichar
+ into a utf8 sequence. Will be 1..kMaxBytesInUTF8Sequence,
+ or 0 if uni is illegal.
+*/
+size_t SkUTF8_FromUnichar(SkUnichar uni, char utf8[] = NULL);
+
+///////////////////////////////////////////////////////////////////////////////
+
+#define SkUTF16_IsHighSurrogate(c) (((c) & 0xFC00) == 0xD800)
+#define SkUTF16_IsLowSurrogate(c) (((c) & 0xFC00) == 0xDC00)
+
+int SkUTF16_CountUnichars(const uint16_t utf16[]);
+int SkUTF16_CountUnichars(const uint16_t utf16[],
+ int numberOf16BitValues);
+// returns the current unichar and then moves past it (*p++)
+SkUnichar SkUTF16_NextUnichar(const uint16_t**);
+// this guy backs up to the previus unichar value, and returns it (*--p)
+SkUnichar SkUTF16_PrevUnichar(const uint16_t**);
+size_t SkUTF16_FromUnichar(SkUnichar uni, uint16_t utf16[] = NULL);
+
+size_t SkUTF16_ToUTF8(const uint16_t utf16[], int numberOf16BitValues,
+ char utf8[] = NULL);
+
+inline bool SkUnichar_IsVariationSelector(SkUnichar uni) {
+/* The 'true' ranges are:
+ * 0x180B <= uni <= 0x180D
+ * 0xFE00 <= uni <= 0xFE0F
+ * 0xE0100 <= uni <= 0xE01EF
+ */
+ if (uni < 0x180B || uni > 0xE01EF) {
+ return false;
+ }
+ if ((uni > 0x180D && uni < 0xFE00) || (uni > 0xFE0F && uni < 0xE0100)) {
+ return false;
+ }
+ return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+class SkAutoTrace {
+public:
+ /** NOTE: label contents are not copied, just the ptr is
+ retained, so DON'T DELETE IT.
+ */
+ SkAutoTrace(const char label[]) : fLabel(label) {
+ SkDebugf("--- trace: %s Enter\n", fLabel);
+ }
+ ~SkAutoTrace() {
+ SkDebugf("--- trace: %s Leave\n", fLabel);
+ }
+private:
+ const char* fLabel;
+};
+
+#endif
diff --git a/core/SkWeakRefCnt.h b/core/SkWeakRefCnt.h
new file mode 100644
index 0000000..e6871fe
--- /dev/null
+++ b/core/SkWeakRefCnt.h
@@ -0,0 +1,159 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkWeakRefCnt_DEFINED
+#define SkWeakRefCnt_DEFINED
+
+#include "SkRefCnt.h"
+#include "SkThread.h"
+
+/** \class SkWeakRefCnt
+
+ SkWeakRefCnt is the base class for objects that may be shared by multiple
+ objects. When an existing strong owner wants to share a reference, it calls
+ ref(). When a strong owner wants to release its reference, it calls
+ unref(). When the shared object's strong reference count goes to zero as
+ the result of an unref() call, its (virtual) weak_dispose method is called.
+ It is an error for the destructor to be called explicitly (or via the
+ object going out of scope on the stack or calling delete) if
+ getRefCnt() > 1.
+
+ In addition to strong ownership, an owner may instead obtain a weak
+ reference by calling weak_ref(). A call to weak_ref() must be balanced my a
+ call to weak_unref(). To obtain a strong reference from a weak reference,
+ call try_ref(). If try_ref() returns true, the owner's pointer is now also
+ a strong reference on which unref() must be called. Note that this does not
+ affect the original weak reference, weak_unref() must still be called. When
+ the weak reference count goes to zero, the object is deleted. While the
+ weak reference count is positive and the strong reference count is zero the
+ object still exists, but will be in the disposed state. It is up to the
+ object to define what this means.
+
+ Note that a strong reference implicitly implies a weak reference. As a
+ result, it is allowable for the owner of a strong ref to call try_ref().
+ This will have the same effect as calling ref(), but may be more expensive.
+
+ Example:
+
+ SkWeakRefCnt myRef = strongRef.weak_ref();
+ ... // strongRef.unref() may or may not be called
+ if (myRef.try_ref()) {
+ ... // use myRef
+ myRef.unref();
+ } else {
+ // myRef is in the disposed state
+ }
+ myRef.weak_unref();
+*/
+class SK_API SkWeakRefCnt : public SkRefCnt {
+public:
+ SK_DECLARE_INST_COUNT(SkWeakRefCnt)
+
+ /** Default construct, initializing the reference counts to 1.
+ The strong references collectively hold one weak reference. When the
+ strong reference count goes to zero, the collectively held weak
+ reference is released.
+ */
+ SkWeakRefCnt() : SkRefCnt(), fWeakCnt(1) {}
+
+ /** Destruct, asserting that the weak reference count is 1.
+ */
+ virtual ~SkWeakRefCnt() {
+#ifdef SK_DEBUG
+ SkASSERT(fWeakCnt == 1);
+ fWeakCnt = 0;
+#endif
+ }
+
+ /** Return the weak reference count.
+ */
+ int32_t getWeakCnt() const { return fWeakCnt; }
+
+ void validate() const {
+ SkRefCnt::validate();
+ SkASSERT(fWeakCnt > 0);
+ }
+
+ /** Creates a strong reference from a weak reference, if possible. The
+ caller must already be an owner. If try_ref() returns true the owner
+ is in posession of an additional strong reference. Both the original
+ reference and new reference must be properly unreferenced. If try_ref()
+ returns false, no strong reference could be created and the owner's
+ reference is in the same state as before the call.
+ */
+ bool SK_WARN_UNUSED_RESULT try_ref() const {
+ if (sk_atomic_conditional_inc(&fRefCnt) != 0) {
+ // Aquire barrier (L/SL), if not provided above.
+ // Prevents subsequent code from happening before the increment.
+ sk_membar_aquire__after_atomic_conditional_inc();
+ return true;
+ }
+ return false;
+ }
+
+ /** Increment the weak reference count. Must be balanced by a call to
+ weak_unref().
+ */
+ void weak_ref() const {
+ SkASSERT(fRefCnt > 0);
+ SkASSERT(fWeakCnt > 0);
+ sk_atomic_inc(&fWeakCnt); // No barrier required.
+ }
+
+ /** Decrement the weak reference count. If the weak reference count is 1
+ before the decrement, then call delete on the object. Note that if this
+ is the case, then the object needs to have been allocated via new, and
+ not on the stack.
+ */
+ void weak_unref() const {
+ SkASSERT(fWeakCnt > 0);
+ // Release barrier (SL/S), if not provided below.
+ if (sk_atomic_dec(&fWeakCnt) == 1) {
+ // Aquire barrier (L/SL), if not provided above.
+ // Prevents code in destructor from happening before the decrement.
+ sk_membar_aquire__after_atomic_dec();
+#ifdef SK_DEBUG
+ // so our destructor won't complain
+ fWeakCnt = 1;
+#endif
+ SkRefCnt::internal_dispose();
+ }
+ }
+
+ /** Returns true if there are no strong references to the object. When this
+ is the case all future calls to try_ref() will return false.
+ */
+ bool weak_expired() const {
+ return fRefCnt == 0;
+ }
+
+protected:
+ /** Called when the strong reference count goes to zero. This allows the
+ object to free any resources it may be holding. Weak references may
+ still exist and their level of allowed access to the object is defined
+ by the object's class.
+ */
+ virtual void weak_dispose() const {
+ }
+
+private:
+ /** Called when the strong reference count goes to zero. Calls weak_dispose
+ on the object and releases the implicit weak reference held
+ collectively by the strong references.
+ */
+ virtual void internal_dispose() const SK_OVERRIDE {
+ weak_dispose();
+ weak_unref();
+ }
+
+ /* Invariant: fWeakCnt = #weak + (fRefCnt > 0 ? 1 : 0) */
+ mutable int32_t fWeakCnt;
+
+ typedef SkRefCnt INHERITED;
+};
+
+#endif
diff --git a/core/SkWriter32.h b/core/SkWriter32.h
new file mode 100644
index 0000000..b07c080
--- /dev/null
+++ b/core/SkWriter32.h
@@ -0,0 +1,303 @@
+
+/*
+ * Copyright 2008 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkWriter32_DEFINED
+#define SkWriter32_DEFINED
+
+#include "SkTypes.h"
+
+#include "SkScalar.h"
+#include "SkPath.h"
+#include "SkPoint.h"
+#include "SkRect.h"
+#include "SkRRect.h"
+#include "SkMatrix.h"
+#include "SkRegion.h"
+
+class SkStream;
+class SkWStream;
+
+class SkWriter32 : SkNoncopyable {
+ struct BlockHeader;
+public:
+ /**
+ * The caller can specify an initial block of storage, which the caller manages.
+ * SkWriter32 will not attempt to free this in its destructor. It is up to the
+ * implementation to decide if, and how much, of the storage to utilize, and it
+ * is possible that it may be ignored entirely.
+ */
+ SkWriter32(size_t minSize, void* initialStorage, size_t storageSize);
+
+ SkWriter32(size_t minSize)
+ : fHead(NULL)
+ , fTail(NULL)
+ , fMinSize(minSize)
+ , fSize(0)
+ , fWrittenBeforeLastBlock(0)
+ {}
+
+ ~SkWriter32();
+
+ // return the current offset (will always be a multiple of 4)
+ uint32_t bytesWritten() const { return fSize; }
+ // DEPRECATED: use bytesWritten instead TODO(mtklein): clean up
+ uint32_t size() const { return this->bytesWritten(); }
+
+ // Returns true if we've written only into the storage passed into constructor or reset.
+ // (You may be able to use this to avoid a call to flatten.)
+ bool wroteOnlyToStorage() const {
+ return fHead == &fExternalBlock && this->bytesWritten() <= fExternalBlock.fSizeOfBlock;
+ }
+
+ void reset();
+ void reset(void* storage, size_t size);
+
+ // size MUST be multiple of 4
+ uint32_t* reserve(size_t size) {
+ SkASSERT(SkAlign4(size) == size);
+
+ Block* block = fTail;
+ if (NULL == block || block->available() < size) {
+ block = this->doReserve(size);
+ }
+ fSize += size;
+ return block->alloc(size);
+ }
+
+ bool writeBool(bool value) {
+ this->writeInt(value);
+ return value;
+ }
+
+ void writeInt(int32_t value) {
+ *(int32_t*)this->reserve(sizeof(value)) = value;
+ }
+
+ void write8(int32_t value) {
+ *(int32_t*)this->reserve(sizeof(value)) = value & 0xFF;
+ }
+
+ void write16(int32_t value) {
+ *(int32_t*)this->reserve(sizeof(value)) = value & 0xFFFF;
+ }
+
+ void write32(int32_t value) {
+ *(int32_t*)this->reserve(sizeof(value)) = value;
+ }
+
+ void writePtr(void* ptr) {
+ // Since we "know" that we're always 4-byte aligned, we can tell the
+ // compiler that here, by assigning to an int32 ptr.
+ int32_t* addr = (int32_t*)this->reserve(sizeof(void*));
+ if (4 == sizeof(void*)) {
+ *(void**)addr = ptr;
+ } else {
+ memcpy(addr, &ptr, sizeof(void*));
+ }
+ }
+
+ void writeScalar(SkScalar value) {
+ *(SkScalar*)this->reserve(sizeof(value)) = value;
+ }
+
+ void writePoint(const SkPoint& pt) {
+ *(SkPoint*)this->reserve(sizeof(pt)) = pt;
+ }
+
+ void writeRect(const SkRect& rect) {
+ *(SkRect*)this->reserve(sizeof(rect)) = rect;
+ }
+
+ void writeIRect(const SkIRect& rect) {
+ *(SkIRect*)this->reserve(sizeof(rect)) = rect;
+ }
+
+ void writeRRect(const SkRRect& rrect) {
+ rrect.writeToMemory(this->reserve(SkRRect::kSizeInMemory));
+ }
+
+ void writePath(const SkPath& path) {
+ size_t size = path.writeToMemory(NULL);
+ SkASSERT(SkAlign4(size) == size);
+ path.writeToMemory(this->reserve(size));
+ }
+
+ void writeMatrix(const SkMatrix& matrix) {
+ size_t size = matrix.writeToMemory(NULL);
+ SkASSERT(SkAlign4(size) == size);
+ matrix.writeToMemory(this->reserve(size));
+ }
+
+ void writeRegion(const SkRegion& rgn) {
+ size_t size = rgn.writeToMemory(NULL);
+ SkASSERT(SkAlign4(size) == size);
+ rgn.writeToMemory(this->reserve(size));
+ }
+
+ // write count bytes (must be a multiple of 4)
+ void writeMul4(const void* values, size_t size) {
+ this->write(values, size);
+ }
+
+ /**
+ * Write size bytes from values. size must be a multiple of 4, though
+ * values need not be 4-byte aligned.
+ */
+ void write(const void* values, size_t size) {
+ SkASSERT(SkAlign4(size) == size);
+ // if we could query how much is avail in the current block, we might
+ // copy that much, and then alloc the rest. That would reduce the waste
+ // in the current block
+ memcpy(this->reserve(size), values, size);
+ }
+
+ /**
+ * Reserve size bytes. Does not need to be 4 byte aligned. The remaining space (if any) will be
+ * filled in with zeroes.
+ */
+ uint32_t* reservePad(size_t size);
+
+ /**
+ * Write size bytes from src, and pad to 4 byte alignment with zeroes.
+ */
+ void writePad(const void* src, size_t size);
+
+ /**
+ * Writes a string to the writer, which can be retrieved with
+ * SkReader32::readString().
+ * The length can be specified, or if -1 is passed, it will be computed by
+ * calling strlen(). The length must be < 0xFFFF
+ */
+ void writeString(const char* str, size_t len = (size_t)-1);
+
+ /**
+ * Computes the size (aligned to multiple of 4) need to write the string
+ * in a call to writeString(). If the length is not specified, it will be
+ * computed by calling strlen().
+ */
+ static size_t WriteStringSize(const char* str, size_t len = (size_t)-1);
+
+ // return the address of the 4byte int at the specified offset (which must
+ // be a multiple of 4. This does not allocate any new space, so the returned
+ // address is only valid for 1 int.
+ uint32_t* peek32(size_t offset);
+
+ /**
+ * Move the cursor back to offset bytes from the beginning.
+ * This has the same restrictions as peek32: offset must be <= size() and
+ * offset must be a multiple of 4.
+ */
+ void rewindToOffset(size_t offset);
+
+ // copy into a single buffer (allocated by caller). Must be at least size()
+ void flatten(void* dst) const;
+
+ // read from the stream, and write up to length bytes. Return the actual
+ // number of bytes written.
+ size_t readFromStream(SkStream*, size_t length);
+
+ bool writeToStream(SkWStream*);
+
+private:
+ struct Block {
+ Block* fNext;
+ char* fBasePtr;
+ size_t fSizeOfBlock; // total space allocated (after this)
+ size_t fAllocatedSoFar; // space used so far
+
+ size_t available() const { return fSizeOfBlock - fAllocatedSoFar; }
+ char* base() { return fBasePtr; }
+ const char* base() const { return fBasePtr; }
+
+ uint32_t* alloc(size_t size) {
+ SkASSERT(SkAlign4(size) == size);
+ SkASSERT(this->available() >= size);
+ void* ptr = this->base() + fAllocatedSoFar;
+ fAllocatedSoFar += size;
+ SkASSERT(fAllocatedSoFar <= fSizeOfBlock);
+ return (uint32_t*)ptr;
+ }
+
+ uint32_t* peek32(size_t offset) {
+ SkASSERT(offset <= fAllocatedSoFar + 4);
+ void* ptr = this->base() + offset;
+ return (uint32_t*)ptr;
+ }
+
+ void rewind() {
+ fNext = NULL;
+ fAllocatedSoFar = 0;
+ // keep fSizeOfBlock as is
+ }
+
+ static Block* Create(size_t size) {
+ SkASSERT(SkIsAlign4(size));
+ Block* block = (Block*)sk_malloc_throw(sizeof(Block) + size);
+ block->fNext = NULL;
+ block->fBasePtr = (char*)(block + 1);
+ block->fSizeOfBlock = size;
+ block->fAllocatedSoFar = 0;
+ return block;
+ }
+
+ Block* initFromStorage(void* storage, size_t size) {
+ SkASSERT(SkIsAlign4((intptr_t)storage));
+ SkASSERT(SkIsAlign4(size));
+ Block* block = this;
+ block->fNext = NULL;
+ block->fBasePtr = (char*)storage;
+ block->fSizeOfBlock = size;
+ block->fAllocatedSoFar = 0;
+ return block;
+ }
+ };
+
+ enum {
+ MIN_BLOCKSIZE = sizeof(SkWriter32::Block) + sizeof(intptr_t)
+ };
+
+ Block fExternalBlock;
+ Block* fHead;
+ Block* fTail;
+ size_t fMinSize;
+ uint32_t fSize;
+ // sum of bytes written in all blocks *before* fTail
+ uint32_t fWrittenBeforeLastBlock;
+
+ bool isHeadExternallyAllocated() const {
+ return fHead == &fExternalBlock;
+ }
+
+ Block* newBlock(size_t bytes);
+
+ // only call from reserve()
+ Block* doReserve(size_t bytes);
+
+ SkDEBUGCODE(void validate() const;)
+};
+
+/**
+ * Helper class to allocated SIZE bytes as part of the writer, and to provide
+ * that storage to the constructor as its initial storage buffer.
+ *
+ * This wrapper ensures proper alignment rules are met for the storage.
+ */
+template <size_t SIZE> class SkSWriter32 : public SkWriter32 {
+public:
+ SkSWriter32(size_t minSize) : SkWriter32(minSize, fData.fStorage, SIZE) {}
+
+private:
+ union {
+ void* fPtrAlignment;
+ double fDoubleAlignment;
+ char fStorage[SIZE];
+ } fData;
+};
+
+#endif
diff --git a/core/SkXfermode.h b/core/SkXfermode.h
new file mode 100644
index 0000000..ef00f71
--- /dev/null
+++ b/core/SkXfermode.h
@@ -0,0 +1,280 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkXfermode_DEFINED
+#define SkXfermode_DEFINED
+
+#include "SkFlattenable.h"
+#include "SkColor.h"
+
+class GrContext;
+class GrEffectRef;
+class GrTexture;
+class SkString;
+
+/** \class SkXfermode
+
+ SkXfermode is the base class for objects that are called to implement custom
+ "transfer-modes" in the drawing pipeline. The static function Create(Modes)
+ can be called to return an instance of any of the predefined subclasses as
+ specified in the Modes enum. When an SkXfermode is assigned to an SkPaint,
+ then objects drawn with that paint have the xfermode applied.
+*/
+class SK_API SkXfermode : public SkFlattenable {
+public:
+ SK_DECLARE_INST_COUNT(SkXfermode)
+
+ SkXfermode() {}
+
+ virtual void xfer32(SkPMColor dst[], const SkPMColor src[], int count,
+ const SkAlpha aa[]) const;
+ virtual void xfer16(uint16_t dst[], const SkPMColor src[], int count,
+ const SkAlpha aa[]) const;
+ virtual void xferA8(SkAlpha dst[], const SkPMColor src[], int count,
+ const SkAlpha aa[]) const;
+
+ /** Enum of possible coefficients to describe some xfermodes
+ */
+ enum Coeff {
+ kZero_Coeff, /** 0 */
+ kOne_Coeff, /** 1 */
+ kSC_Coeff, /** src color */
+ kISC_Coeff, /** inverse src color (i.e. 1 - sc) */
+ kDC_Coeff, /** dst color */
+ kIDC_Coeff, /** inverse dst color (i.e. 1 - dc) */
+ kSA_Coeff, /** src alpha */
+ kISA_Coeff, /** inverse src alpha (i.e. 1 - sa) */
+ kDA_Coeff, /** dst alpha */
+ kIDA_Coeff, /** inverse dst alpha (i.e. 1 - da) */
+
+ kCoeffCount
+ };
+
+ /** If the xfermode can be expressed as an equation using the coefficients
+ in Coeff, then asCoeff() returns true, and sets (if not null) src and
+ dst accordingly.
+
+ result = src_coeff * src_color + dst_coeff * dst_color;
+
+ As examples, here are some of the porterduff coefficients
+
+ MODE SRC_COEFF DST_COEFF
+ clear zero zero
+ src one zero
+ dst zero one
+ srcover one isa
+ dstover ida one
+ */
+ virtual bool asCoeff(Coeff* src, Coeff* dst) const;
+
+ /**
+ * The same as calling xfermode->asCoeff(..), except that this also checks
+ * if the xfermode is NULL, and if so, treats it as kSrcOver_Mode.
+ */
+ static bool AsCoeff(const SkXfermode*, Coeff* src, Coeff* dst);
+
+ /** List of predefined xfermodes.
+ The algebra for the modes uses the following symbols:
+ Sa, Sc - source alpha and color
+ Da, Dc - destination alpha and color (before compositing)
+ [a, c] - Resulting (alpha, color) values
+ For these equations, the colors are in premultiplied state.
+ If no xfermode is specified, kSrcOver is assumed.
+ The modes are ordered by those that can be expressed as a pair of Coeffs, followed by those
+ that aren't Coeffs but have separable r,g,b computations, and finally
+ those that are not separable.
+ */
+ enum Mode {
+ kClear_Mode, //!< [0, 0]
+ kSrc_Mode, //!< [Sa, Sc]
+ kDst_Mode, //!< [Da, Dc]
+ kSrcOver_Mode, //!< [Sa + Da - Sa*Da, Rc = Sc + (1 - Sa)*Dc]
+ kDstOver_Mode, //!< [Sa + Da - Sa*Da, Rc = Dc + (1 - Da)*Sc]
+ kSrcIn_Mode, //!< [Sa * Da, Sc * Da]
+ kDstIn_Mode, //!< [Sa * Da, Sa * Dc]
+ kSrcOut_Mode, //!< [Sa * (1 - Da), Sc * (1 - Da)]
+ kDstOut_Mode, //!< [Da * (1 - Sa), Dc * (1 - Sa)]
+ kSrcATop_Mode, //!< [Da, Sc * Da + (1 - Sa) * Dc]
+ kDstATop_Mode, //!< [Sa, Sa * Dc + Sc * (1 - Da)]
+ kXor_Mode, //!< [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + (1 - Sa) * Dc]
+ kPlus_Mode, //!< [Sa + Da, Sc + Dc]
+ kModulate_Mode, // multiplies all components (= alpha and color)
+
+ // Following blend modes are defined in the CSS Compositing standard:
+ // https://dvcs.w3.org/hg/FXTF/rawfile/tip/compositing/index.html#blending
+ kScreen_Mode,
+ kLastCoeffMode = kScreen_Mode,
+
+ kOverlay_Mode,
+ kDarken_Mode,
+ kLighten_Mode,
+ kColorDodge_Mode,
+ kColorBurn_Mode,
+ kHardLight_Mode,
+ kSoftLight_Mode,
+ kDifference_Mode,
+ kExclusion_Mode,
+ kMultiply_Mode,
+ kLastSeparableMode = kMultiply_Mode,
+
+ kHue_Mode,
+ kSaturation_Mode,
+ kColor_Mode,
+ kLuminosity_Mode,
+ kLastMode = kLuminosity_Mode
+ };
+
+ /**
+ * Gets the name of the Mode as a string.
+ */
+ static const char* ModeName(Mode);
+
+ /**
+ * If the xfermode is one of the modes in the Mode enum, then asMode()
+ * returns true and sets (if not null) mode accordingly. Otherwise it
+ * returns false and ignores the mode parameter.
+ */
+ virtual bool asMode(Mode* mode) const;
+
+ /**
+ * The same as calling xfermode->asMode(mode), except that this also checks
+ * if the xfermode is NULL, and if so, treats it as kSrcOver_Mode.
+ */
+ static bool AsMode(const SkXfermode*, Mode* mode);
+
+ /**
+ * Returns true if the xfermode claims to be the specified Mode. This works
+ * correctly even if the xfermode is NULL (which equates to kSrcOver.) Thus
+ * you can say this without checking for a null...
+ *
+ * If (SkXfermode::IsMode(paint.getXfermode(),
+ * SkXfermode::kDstOver_Mode)) {
+ * ...
+ * }
+ */
+ static bool IsMode(const SkXfermode* xfer, Mode mode);
+
+ /** Return an SkXfermode object for the specified mode.
+ */
+ static SkXfermode* Create(Mode mode);
+
+ /** Return a function pointer to a routine that applies the specified
+ porter-duff transfer mode.
+ */
+ static SkXfermodeProc GetProc(Mode mode);
+
+ /** Return a function pointer to a routine that applies the specified
+ porter-duff transfer mode and srcColor to a 16bit device color. Note,
+ if the mode+srcColor might return a non-opaque color, then there is not
+ 16bit proc, and this will return NULL.
+ */
+ static SkXfermodeProc16 GetProc16(Mode mode, SkColor srcColor);
+
+ /**
+ * If the specified mode can be represented by a pair of Coeff, then return
+ * true and set (if not NULL) the corresponding coeffs. If the mode is
+ * not representable as a pair of Coeffs, return false and ignore the
+ * src and dst parameters.
+ */
+ static bool ModeAsCoeff(Mode mode, Coeff* src, Coeff* dst);
+
+ // DEPRECATED: call AsMode(...)
+ static bool IsMode(const SkXfermode* xfer, Mode* mode) {
+ return AsMode(xfer, mode);
+ }
+
+ /** A subclass may implement this factory function to work with the GPU backend. It is legal
+ to call this with all but the context param NULL to simply test the return value. effect,
+ src, and dst must all be NULL or all non-NULL. If effect is non-NULL then the xfermode may
+ optionally allocate an effect to return and the caller as *effect. The caller will install
+ it and own a ref to it. Since the xfermode may or may not assign *effect, the caller should
+ set *effect to NULL beforehand. If the function returns true and *effect is NULL then the
+ src and dst coeffs will be applied to the draw. When *effect is non-NULL the coeffs are
+ ignored. background specifies the texture to use as the background for compositing, and
+ should be accessed in the effect's fragment shader. If NULL, the effect should request
+ access to destination color (setWillReadDstColor()), and use that in the fragment shader
+ (builder->dstColor()).
+ */
+ virtual bool asNewEffectOrCoeff(GrContext*,
+ GrEffectRef** effect,
+ Coeff* src,
+ Coeff* dst,
+ GrTexture* background = NULL) const;
+
+ /**
+ * The same as calling xfermode->asNewEffect(...), except that this also checks if the xfermode
+ * is NULL, and if so, treats it as kSrcOver_Mode.
+ */
+ static bool AsNewEffectOrCoeff(SkXfermode*,
+ GrContext*,
+ GrEffectRef** effect,
+ Coeff* src,
+ Coeff* dst,
+ GrTexture* background = NULL);
+
+ SkDEVCODE(virtual void toString(SkString* str) const = 0;)
+ SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP()
+protected:
+ SkXfermode(SkFlattenableReadBuffer& rb) : SkFlattenable(rb) {}
+
+ /** The default implementation of xfer32/xfer16/xferA8 in turn call this
+ method, 1 color at a time (upscaled to a SkPMColor). The default
+ implmentation of this method just returns dst. If performance is
+ important, your subclass should override xfer32/xfer16/xferA8 directly.
+
+ This method will not be called directly by the client, so it need not
+ be implemented if your subclass has overridden xfer32/xfer16/xferA8
+ */
+ virtual SkPMColor xferColor(SkPMColor src, SkPMColor dst) const;
+
+private:
+ enum {
+ kModeCount = kLastMode + 1
+ };
+ typedef SkFlattenable INHERITED;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+/** \class SkProcXfermode
+
+ SkProcXfermode is a xfermode that applies the specified proc to its colors.
+ This class is not exported to java.
+*/
+class SkProcXfermode : public SkXfermode {
+public:
+ SkProcXfermode(SkXfermodeProc proc) : fProc(proc) {}
+
+ // overrides from SkXfermode
+ virtual void xfer32(SkPMColor dst[], const SkPMColor src[], int count,
+ const SkAlpha aa[]) const SK_OVERRIDE;
+ virtual void xfer16(uint16_t dst[], const SkPMColor src[], int count,
+ const SkAlpha aa[]) const SK_OVERRIDE;
+ virtual void xferA8(SkAlpha dst[], const SkPMColor src[], int count,
+ const SkAlpha aa[]) const SK_OVERRIDE;
+
+ SK_DEVELOPER_TO_STRING()
+ SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkProcXfermode)
+
+protected:
+ SkProcXfermode(SkFlattenableReadBuffer&);
+ virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
+
+ // allow subclasses to update this after we unflatten
+ void setProc(SkXfermodeProc proc) {
+ fProc = proc;
+ }
+
+private:
+ SkXfermodeProc fProc;
+
+ typedef SkXfermode INHERITED;
+};
+
+#endif
diff --git a/device/xps/SkConstexprMath.h b/device/xps/SkConstexprMath.h
new file mode 100644
index 0000000..9625d51
--- /dev/null
+++ b/device/xps/SkConstexprMath.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkConstexprMath_DEFINED
+#define SkConstexprMath_DEFINED
+
+#include "SkTypes.h"
+#include <limits.h>
+
+template <uintmax_t N, uintmax_t B>
+struct SK_LOG {
+ //! Compile-time constant ceiling(logB(N)).
+ static const uintmax_t value = 1 + SK_LOG<N/B, B>::value;
+};
+template <uintmax_t B>
+struct SK_LOG<1, B> {
+ static const uintmax_t value = 0;
+};
+template <uintmax_t B>
+struct SK_LOG<0, B> {
+ static const uintmax_t value = 0;
+};
+
+template<uintmax_t N>
+struct SK_2N1 {
+ //! Compile-time constant (2^N)-1.
+ static const uintmax_t value = (SK_2N1<N-1>::value << 1) + 1;
+};
+template<>
+struct SK_2N1<1> {
+ static const uintmax_t value = 1;
+};
+
+/** Compile-time constant number of base n digits in type t
+ if the bits of type t are considered as unsigned base two.
+*/
+#define SK_BASE_N_DIGITS_IN(n, t) (\
+ SK_LOG<SK_2N1<(sizeof(t) * CHAR_BIT)>::value, n>::value\
+)
+/** Compile-time constant number of base 10 digits in type t
+ if the bits of type t are considered as unsigned base two.
+*/
+#define SK_DIGITS_IN(t) SK_BASE_N_DIGITS_IN(10, (t))
+
+// Compile-time constant maximum value of two unsigned values.
+template <uintmax_t a, uintmax_t b> struct SkTUMax {
+ static const uintmax_t value = (b < a) ? a : b;
+};
+
+#endif
diff --git a/device/xps/SkXPSDevice.h b/device/xps/SkXPSDevice.h
new file mode 100644
index 0000000..dab8d1f
--- /dev/null
+++ b/device/xps/SkXPSDevice.h
@@ -0,0 +1,324 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkXPSDevice_DEFINED
+#define SkXPSDevice_DEFINED
+
+#include "SkTypes.h"
+#include <ObjBase.h>
+#include <XpsObjectModel.h>
+
+#include "SkAutoCoInitialize.h"
+#include "SkBitSet.h"
+#include "SkCanvas.h"
+#include "SkColor.h"
+#include "SkDevice.h"
+#include "SkPaint.h"
+#include "SkPath.h"
+#include "SkPoint.h"
+#include "SkShader.h"
+#include "SkSize.h"
+#include "SkTArray.h"
+#include "SkTScopedComPtr.h"
+#include "SkTypeface.h"
+
+/** \class SkXPSDevice
+
+ The drawing context for the XPS backend.
+*/
+class SkXPSDevice : public SkDevice {
+public:
+ SK_API SkXPSDevice();
+ SK_API virtual ~SkXPSDevice();
+
+ virtual bool beginPortfolio(SkWStream* outputStream);
+ /**
+ @param unitsPerMeter converts geometry units into physical units.
+ @param pixelsPerMeter resolution to use when geometry must be rasterized.
+ @param trimSize final page size in physical units.
+ The top left of the trim is the origin of physical space.
+ @param mediaBox The size of the physical media in physical units.
+ The top and left must be less than zero.
+ The bottom and right must be greater than the trimSize.
+ The default is to coincide with the trimSize.
+ @param bleedBox The size of the bleed box in physical units.
+ Must be contained within the mediaBox.
+ The default is to coincide with the mediaBox.
+ @param artBox The size of the content box in physical units.
+ Must be contained within the trimSize.
+ The default is to coincide with the trimSize.
+ @param cropBox The size of the recommended view port in physical units.
+ Must be contained within the mediaBox.
+ The default is to coincide with the mediaBox.
+ */
+ virtual bool beginSheet(
+ const SkVector& unitsPerMeter,
+ const SkVector& pixelsPerMeter,
+ const SkSize& trimSize,
+ const SkRect* mediaBox = NULL,
+ const SkRect* bleedBox = NULL,
+ const SkRect* artBox = NULL,
+ const SkRect* cropBox = NULL);
+
+ virtual bool endSheet();
+ virtual bool endPortfolio();
+
+ virtual uint32_t getDeviceCapabilities() SK_OVERRIDE;
+
+protected:
+ virtual void clear(SkColor color) SK_OVERRIDE;
+
+ virtual void drawPaint(const SkDraw&, const SkPaint& paint) SK_OVERRIDE;
+
+ virtual void drawPoints(
+ const SkDraw&,
+ SkCanvas::PointMode mode,
+ size_t count, const SkPoint[],
+ const SkPaint& paint) SK_OVERRIDE;
+
+ virtual void drawRect(
+ const SkDraw&,
+ const SkRect& r,
+ const SkPaint& paint) SK_OVERRIDE;
+
+ virtual void drawPath(
+ const SkDraw&,
+ const SkPath& platonicPath,
+ const SkPaint& paint,
+ const SkMatrix* prePathMatrix,
+ bool pathIsMutable) SK_OVERRIDE;
+
+ virtual void drawBitmap(
+ const SkDraw&,
+ const SkBitmap& bitmap,
+ const SkMatrix& matrix,
+ const SkPaint& paint) SK_OVERRIDE;
+
+ virtual void drawSprite(
+ const SkDraw&,
+ const SkBitmap& bitmap,
+ int x, int y,
+ const SkPaint& paint) SK_OVERRIDE;
+
+ virtual void drawText(
+ const SkDraw&,
+ const void* text, size_t len,
+ SkScalar x, SkScalar y,
+ const SkPaint& paint) SK_OVERRIDE;
+
+ virtual void drawPosText(
+ const SkDraw&,
+ const void* text, size_t len,
+ const SkScalar pos[], SkScalar constY, int scalarsPerPos,
+ const SkPaint& paint) SK_OVERRIDE;
+
+ virtual void drawTextOnPath(
+ const SkDraw&,
+ const void* text, size_t len,
+ const SkPath& path,
+ const SkMatrix* matrix,
+ const SkPaint& paint) SK_OVERRIDE;
+
+ virtual void drawVertices(
+ const SkDraw&,
+ SkCanvas::VertexMode,
+ int vertexCount, const SkPoint verts[],
+ const SkPoint texs[], const SkColor colors[],
+ SkXfermode* xmode,
+ const uint16_t indices[], int indexCount,
+ const SkPaint& paint) SK_OVERRIDE;
+
+ virtual void drawDevice(
+ const SkDraw&,
+ SkDevice* device,
+ int x, int y,
+ const SkPaint& paint) SK_OVERRIDE;
+
+ virtual bool onReadPixels(const SkBitmap& bitmap,
+ int x,
+ int y,
+ SkCanvas::Config8888) SK_OVERRIDE;
+
+ virtual bool allowImageFilter(SkImageFilter*) SK_OVERRIDE;
+
+private:
+ class TypefaceUse : ::SkNoncopyable {
+ public:
+ SkFontID typefaceId;
+ int ttcIndex;
+ SkStream* fontData;
+ IXpsOMFontResource* xpsFont;
+ SkBitSet* glyphsUsed;
+
+ explicit TypefaceUse();
+ ~TypefaceUse();
+ };
+ friend static HRESULT subset_typeface(TypefaceUse* current);
+
+ SkXPSDevice(IXpsOMObjectFactory* xpsFactory);
+
+ SkAutoCoInitialize fAutoCo;
+ SkTScopedComPtr<IXpsOMObjectFactory> fXpsFactory;
+ SkTScopedComPtr<IStream> fOutputStream;
+ SkTScopedComPtr<IXpsOMPackageWriter> fPackageWriter;
+
+ unsigned int fCurrentPage;
+ SkTScopedComPtr<IXpsOMCanvas> fCurrentXpsCanvas;
+ SkSize fCurrentCanvasSize;
+ SkVector fCurrentUnitsPerMeter;
+ SkVector fCurrentPixelsPerMeter;
+
+ SkTArray<TypefaceUse, true> fTypefaces;
+
+ HRESULT initXpsDocumentWriter(IXpsOMImageResource* image);
+
+ HRESULT createXpsPage(
+ const XPS_SIZE& pageSize,
+ IXpsOMPage** page);
+
+ HRESULT createXpsThumbnail(
+ IXpsOMPage* page, const unsigned int pageNumber,
+ IXpsOMImageResource** image);
+
+ void internalDrawRect(
+ const SkDraw&,
+ const SkRect& r,
+ bool transformRect,
+ const SkPaint& paint);
+
+ HRESULT createXpsBrush(
+ const SkPaint& skPaint,
+ IXpsOMBrush** xpsBrush,
+ const SkMatrix* parentTransform = NULL);
+
+ HRESULT createXpsSolidColorBrush(
+ const SkColor skColor, const SkAlpha alpha,
+ IXpsOMBrush** xpsBrush);
+
+ HRESULT createXpsImageBrush(
+ const SkBitmap& bitmap,
+ const SkMatrix& localMatrix,
+ const SkShader::TileMode (&xy)[2],
+ const SkAlpha alpha,
+ IXpsOMTileBrush** xpsBrush);
+
+ HRESULT createXpsLinearGradient(
+ SkShader::GradientInfo info,
+ const SkAlpha alpha,
+ const SkMatrix& localMatrix,
+ IXpsOMMatrixTransform* xpsMatrixToUse,
+ IXpsOMBrush** xpsBrush);
+
+ HRESULT createXpsRadialGradient(
+ SkShader::GradientInfo info,
+ const SkAlpha alpha,
+ const SkMatrix& localMatrix,
+ IXpsOMMatrixTransform* xpsMatrixToUse,
+ IXpsOMBrush** xpsBrush);
+
+ HRESULT createXpsGradientStop(
+ const SkColor skColor,
+ const SkScalar offset,
+ IXpsOMGradientStop** xpsGradStop);
+
+ HRESULT createXpsTransform(
+ const SkMatrix& matrix,
+ IXpsOMMatrixTransform ** xpsTransform);
+
+ HRESULT createXpsRect(
+ const SkRect& rect,
+ BOOL stroke, BOOL fill,
+ IXpsOMGeometryFigure** xpsRect);
+
+ HRESULT createXpsQuad(
+ const SkPoint (&points)[4],
+ BOOL stroke, BOOL fill,
+ IXpsOMGeometryFigure** xpsQuad);
+
+ HRESULT CreateTypefaceUse(
+ const SkPaint& paint,
+ TypefaceUse** fontResource);
+
+ HRESULT AddGlyphs(
+ const SkDraw& d,
+ IXpsOMObjectFactory* xpsFactory,
+ IXpsOMCanvas* canvas,
+ TypefaceUse* font,
+ LPCWSTR text,
+ XPS_GLYPH_INDEX* xpsGlyphs,
+ UINT32 xpsGlyphsLen,
+ XPS_POINT *origin,
+ FLOAT fontSize,
+ XPS_STYLE_SIMULATION sims,
+ const SkMatrix& transform,
+ const SkPaint& paint);
+
+ HRESULT addXpsPathGeometry(
+ IXpsOMGeometryFigureCollection* figures,
+ BOOL stroke, BOOL fill, const SkPath& path);
+
+ HRESULT createPath(
+ IXpsOMGeometryFigure* figure,
+ IXpsOMVisualCollection* visuals,
+ IXpsOMPath** path);
+
+ HRESULT sideOfClamp(
+ const SkRect& leftPoints, const XPS_RECT& left,
+ IXpsOMImageResource* imageResource,
+ IXpsOMVisualCollection* visuals);
+
+ HRESULT cornerOfClamp(
+ const SkRect& tlPoints,
+ const SkColor color,
+ IXpsOMVisualCollection* visuals);
+
+ HRESULT clip(
+ IXpsOMVisual* xpsVisual,
+ const SkDraw& d);
+ HRESULT clipToPath(
+ IXpsOMVisual* xpsVisual,
+ const SkPath& clipPath,
+ XPS_FILL_RULE fillRule);
+
+ HRESULT drawInverseWindingPath(
+ const SkDraw& d,
+ const SkPath& devicePath,
+ IXpsOMPath* xpsPath);
+
+ HRESULT shadePath(
+ IXpsOMPath* shadedPath,
+ const SkPaint& shaderPaint,
+ const SkMatrix& matrix,
+ BOOL* fill, BOOL* stroke);
+
+ void convertToPpm(
+ const SkMaskFilter* filter,
+ SkMatrix* matrix,
+ SkVector* ppuScale,
+ const SkIRect& clip, SkIRect* clipIRect);
+
+ HRESULT applyMask(
+ const SkDraw& d,
+ const SkMask& mask,
+ const SkVector& ppuScale,
+ IXpsOMPath* shadedPath);
+
+ // override from SkDevice
+ virtual SkDevice* onCreateCompatibleDevice(
+ SkBitmap::Config config,
+ int width, int height,
+ bool isOpaque,
+ Usage usage) SK_OVERRIDE;
+
+ // Disable the default copy and assign implementation.
+ SkXPSDevice(const SkXPSDevice&);
+ void operator=(const SkXPSDevice&);
+
+ typedef SkDevice INHERITED;
+};
+
+#endif
diff --git a/effects/Sk1DPathEffect.h b/effects/Sk1DPathEffect.h
new file mode 100644
index 0000000..4599276
--- /dev/null
+++ b/effects/Sk1DPathEffect.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef Sk1DPathEffect_DEFINED
+#define Sk1DPathEffect_DEFINED
+
+#include "SkPathEffect.h"
+#include "SkPath.h"
+
+class SkPathMeasure;
+
+// This class is not exported to java.
+class SK_API Sk1DPathEffect : public SkPathEffect {
+public:
+ virtual bool filterPath(SkPath* dst, const SkPath& src,
+ SkStrokeRec*, const SkRect*) const SK_OVERRIDE;
+
+protected:
+ /** Called at the start of each contour, returns the initial offset
+ into that contour.
+ */
+ virtual SkScalar begin(SkScalar contourLength) const = 0;
+ /** Called with the current distance along the path, with the current matrix
+ for the point/tangent at the specified distance.
+ Return the distance to travel for the next call. If return <= 0, then that
+ contour is done.
+ */
+ virtual SkScalar next(SkPath* dst, SkScalar dist, SkPathMeasure&) const = 0;
+
+private:
+ typedef SkPathEffect INHERITED;
+};
+
+class SK_API SkPath1DPathEffect : public Sk1DPathEffect {
+public:
+ enum Style {
+ kTranslate_Style, // translate the shape to each position
+ kRotate_Style, // rotate the shape about its center
+ kMorph_Style, // transform each point, and turn lines into curves
+
+ kStyleCount
+ };
+
+ /** Dash by replicating the specified path.
+ @param path The path to replicate (dash)
+ @param advance The space between instances of path
+ @param phase distance (mod advance) along path for its initial position
+ @param style how to transform path at each point (based on the current
+ position and tangent)
+ */
+ SkPath1DPathEffect(const SkPath& path, SkScalar advance, SkScalar phase, Style);
+
+ virtual bool filterPath(SkPath*, const SkPath&,
+ SkStrokeRec*, const SkRect*) const SK_OVERRIDE;
+
+ SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkPath1DPathEffect)
+
+protected:
+ SkPath1DPathEffect(SkFlattenableReadBuffer& buffer);
+ virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
+
+ // overrides from Sk1DPathEffect
+ virtual SkScalar begin(SkScalar contourLength) const SK_OVERRIDE;
+ virtual SkScalar next(SkPath*, SkScalar, SkPathMeasure&) const SK_OVERRIDE;
+
+private:
+ SkPath fPath; // copied from constructor
+ SkScalar fAdvance; // copied from constructor
+ SkScalar fInitialOffset; // computed from phase
+ Style fStyle; // copied from constructor
+
+ typedef Sk1DPathEffect INHERITED;
+};
+
+#endif
diff --git a/effects/Sk2DPathEffect.h b/effects/Sk2DPathEffect.h
new file mode 100644
index 0000000..ed7f674
--- /dev/null
+++ b/effects/Sk2DPathEffect.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef Sk2DPathEffect_DEFINED
+#define Sk2DPathEffect_DEFINED
+
+#include "SkPath.h"
+#include "SkPathEffect.h"
+#include "SkMatrix.h"
+
+class SK_API Sk2DPathEffect : public SkPathEffect {
+public:
+ Sk2DPathEffect(const SkMatrix& mat);
+
+ virtual bool filterPath(SkPath*, const SkPath&,
+ SkStrokeRec*, const SkRect*) const SK_OVERRIDE;
+
+ SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(Sk2DPathEffect)
+
+protected:
+ /** New virtual, to be overridden by subclasses.
+ This is called once from filterPath, and provides the
+ uv parameter bounds for the path. Subsequent calls to
+ next() will receive u and v values within these bounds,
+ and then a call to end() will signal the end of processing.
+ */
+ virtual void begin(const SkIRect& uvBounds, SkPath* dst) const;
+ virtual void next(const SkPoint& loc, int u, int v, SkPath* dst) const;
+ virtual void end(SkPath* dst) const;
+
+ /** Low-level virtual called per span of locations in the u-direction.
+ The default implementation calls next() repeatedly with each
+ location.
+ */
+ virtual void nextSpan(int u, int v, int ucount, SkPath* dst) const;
+
+ const SkMatrix& getMatrix() const { return fMatrix; }
+
+ // protected so that subclasses can call this during unflattening
+ Sk2DPathEffect(SkFlattenableReadBuffer&);
+ virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
+
+private:
+ SkMatrix fMatrix, fInverse;
+ bool fMatrixIsInvertible;
+
+ // illegal
+ Sk2DPathEffect(const Sk2DPathEffect&);
+ Sk2DPathEffect& operator=(const Sk2DPathEffect&);
+
+ friend class Sk2DPathEffectBlitter;
+ typedef SkPathEffect INHERITED;
+};
+
+class SK_API SkLine2DPathEffect : public Sk2DPathEffect {
+public:
+ SkLine2DPathEffect(SkScalar width, const SkMatrix& matrix)
+ : Sk2DPathEffect(matrix), fWidth(width) {}
+
+ virtual bool filterPath(SkPath* dst, const SkPath& src,
+ SkStrokeRec*, const SkRect*) const SK_OVERRIDE;
+
+ SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkLine2DPathEffect)
+
+protected:
+ virtual void nextSpan(int u, int v, int ucount, SkPath*) const SK_OVERRIDE;
+
+ SkLine2DPathEffect(SkFlattenableReadBuffer&);
+
+ virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
+
+private:
+ SkScalar fWidth;
+
+ typedef Sk2DPathEffect INHERITED;
+};
+
+class SK_API SkPath2DPathEffect : public Sk2DPathEffect {
+public:
+ /**
+ * Stamp the specified path to fill the shape, using the matrix to define
+ * the latice.
+ */
+ SkPath2DPathEffect(const SkMatrix&, const SkPath&);
+
+ SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkPath2DPathEffect)
+
+protected:
+ SkPath2DPathEffect(SkFlattenableReadBuffer& buffer);
+ virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
+
+ virtual void next(const SkPoint&, int u, int v, SkPath*) const SK_OVERRIDE;
+
+private:
+ SkPath fPath;
+
+ typedef Sk2DPathEffect INHERITED;
+};
+
+#endif
diff --git a/effects/SkArithmeticMode.h b/effects/SkArithmeticMode.h
new file mode 100644
index 0000000..9de332c
--- /dev/null
+++ b/effects/SkArithmeticMode.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkArithmeticMode_DEFINED
+#define SkArithmeticMode_DEFINED
+
+#include "SkXfermode.h"
+
+class SK_API SkArithmeticMode : public SkXfermode {
+public:
+ /**
+ * result = clamp[k1 * src * dst + k2 * src + k3 * dst + k4]
+ *
+ * src and dst are treated as being [0.0 .. 1.0]. The polynomial is
+ * evaluated on their unpremultiplied components.
+ *
+ * k1=k2=k3=0, k4=1.0 results in returning opaque white
+ * k1=k3=k4=0, k2=1.0 results in returning the src
+ * k1=k2=k4=0, k3=1.0 results in returning the dst
+ */
+ static SkXfermode* Create(SkScalar k1, SkScalar k2,
+ SkScalar k3, SkScalar k4);
+
+ SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP();
+
+private:
+ typedef SkXfermode INHERITED;
+};
+
+#endif
diff --git a/effects/SkAvoidXfermode.h b/effects/SkAvoidXfermode.h
new file mode 100644
index 0000000..4950b64
--- /dev/null
+++ b/effects/SkAvoidXfermode.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkAvoidXfermode_DEFINED
+#define SkAvoidXfermode_DEFINED
+
+#include "SkXfermode.h"
+
+/** \class SkAvoidXfermode
+
+ This xfermode will draw the src everywhere except on top of the specified
+ color.
+*/
+class SK_API SkAvoidXfermode : public SkXfermode {
+public:
+ enum Mode {
+ kAvoidColor_Mode, //!< draw everywhere except on the opColor
+ kTargetColor_Mode //!< draw only on top of the opColor
+ };
+
+ /** This xfermode draws, or doesn't draw, based on the destination's
+ distance from an op-color.
+
+ There are two modes, and each mode interprets a tolerance value.
+
+ Avoid: In this mode, drawing is allowed only on destination pixels that
+ are different from the op-color.
+ Tolerance near 0: avoid any colors even remotely similar to the op-color
+ Tolerance near 255: avoid only colors nearly identical to the op-color
+
+ Target: In this mode, drawing only occurs on destination pixels that
+ are similar to the op-color
+ Tolerance near 0: draw only on colors that are nearly identical to the op-color
+ Tolerance near 255: draw on any colors even remotely similar to the op-color
+ */
+ SkAvoidXfermode(SkColor opColor, U8CPU tolerance, Mode mode);
+
+ // overrides from SkXfermode
+ virtual void xfer32(SkPMColor dst[], const SkPMColor src[], int count,
+ const SkAlpha aa[]) const SK_OVERRIDE;
+ virtual void xfer16(uint16_t dst[], const SkPMColor src[], int count,
+ const SkAlpha aa[]) const SK_OVERRIDE;
+ virtual void xferA8(SkAlpha dst[], const SkPMColor src[], int count,
+ const SkAlpha aa[]) const SK_OVERRIDE;
+
+ SK_DEVELOPER_TO_STRING()
+ SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkAvoidXfermode)
+
+protected:
+ SkAvoidXfermode(SkFlattenableReadBuffer&);
+ virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
+
+private:
+ SkColor fOpColor;
+ uint32_t fDistMul; // x.14
+ Mode fMode;
+
+ typedef SkXfermode INHERITED;
+};
+
+#endif
diff --git a/effects/SkBicubicImageFilter.h b/effects/SkBicubicImageFilter.h
new file mode 100644
index 0000000..bd918eb
--- /dev/null
+++ b/effects/SkBicubicImageFilter.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2013 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkBicubicImageFilter_DEFINED
+#define SkBicubicImageFilter_DEFINED
+
+#include "SkImageFilter.h"
+#include "SkScalar.h"
+#include "SkSize.h"
+#include "SkPoint.h"
+
+/*! \class SkBicubicImageFilter
+ Bicubic resampling image filter. This filter does a 16-tap bicubic
+ filter using the given matrix.
+ */
+
+class SK_API SkBicubicImageFilter : public SkImageFilter {
+public:
+ /** Construct a (scaling-only) bicubic resampling image filter.
+ @param scale How much to scale the image.
+ @param coefficients The 16 coefficients of the bicubic matrix.
+ @param input The input image filter. If NULL, the src bitmap
+ passed to filterImage() is used instead.
+ */
+
+ SkBicubicImageFilter(const SkSize& scale, const SkScalar coefficients[16],
+ SkImageFilter* input = NULL);
+ static SkBicubicImageFilter* CreateMitchell(const SkSize& scale, SkImageFilter* input = NULL);
+ virtual ~SkBicubicImageFilter();
+
+ SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkBicubicImageFilter)
+
+protected:
+ SkBicubicImageFilter(SkFlattenableReadBuffer& buffer);
+ virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
+
+ virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&,
+ SkBitmap* result, SkIPoint* loc) SK_OVERRIDE;
+
+#if SK_SUPPORT_GPU
+ virtual bool canFilterImageGPU() const SK_OVERRIDE { return true; }
+ virtual bool filterImageGPU(Proxy* proxy, const SkBitmap& src, const SkMatrix& ctm,
+ SkBitmap* result, SkIPoint* offset) SK_OVERRIDE;
+#endif
+
+private:
+ SkSize fScale;
+ SkScalar fCoefficients[16];
+ typedef SkImageFilter INHERITED;
+};
+
+#endif
diff --git a/effects/SkBitmapSource.h b/effects/SkBitmapSource.h
new file mode 100644
index 0000000..138987e
--- /dev/null
+++ b/effects/SkBitmapSource.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2012 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkBitmapSource_DEFINED
+#define SkBitmapSource_DEFINED
+
+#include "SkImageFilter.h"
+#include "SkBitmap.h"
+
+class SK_API SkBitmapSource : public SkImageFilter {
+public:
+ explicit SkBitmapSource(const SkBitmap& bitmap);
+
+ SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkBitmapSource)
+
+protected:
+ explicit SkBitmapSource(SkFlattenableReadBuffer& buffer);
+ virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
+ virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&,
+ SkBitmap* result, SkIPoint* offset) SK_OVERRIDE;
+
+private:
+ SkBitmap fBitmap;
+ typedef SkImageFilter INHERITED;
+};
+
+#endif
diff --git a/effects/SkBlurDrawLooper.h b/effects/SkBlurDrawLooper.h
new file mode 100644
index 0000000..e968857
--- /dev/null
+++ b/effects/SkBlurDrawLooper.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2008 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkBlurDrawLooper_DEFINED
+#define SkBlurDrawLooper_DEFINED
+
+#include "SkDrawLooper.h"
+#include "SkColor.h"
+
+class SkMaskFilter;
+class SkColorFilter;
+
+/** \class SkBlurDrawLooper
+ This class draws a shadow of the object (possibly offset), and then draws
+ the original object in its original position.
+ should there be an option to just draw the shadow/blur layer? webkit?
+*/
+class SK_API SkBlurDrawLooper : public SkDrawLooper {
+public:
+ enum BlurFlags {
+ kNone_BlurFlag = 0x00,
+ /**
+ The blur layer's dx/dy/radius aren't affected by the canvas
+ transform.
+ */
+ kIgnoreTransform_BlurFlag = 0x01,
+ kOverrideColor_BlurFlag = 0x02,
+ kHighQuality_BlurFlag = 0x04,
+ /** mask for all blur flags */
+ kAll_BlurFlag = 0x07
+ };
+
+ SkBlurDrawLooper(SkScalar radius, SkScalar dx, SkScalar dy, SkColor color,
+ uint32_t flags = kNone_BlurFlag);
+ virtual ~SkBlurDrawLooper();
+
+ // overrides from SkDrawLooper
+ virtual void init(SkCanvas*);
+ virtual bool next(SkCanvas*, SkPaint* paint);
+
+ SK_DEVELOPER_TO_STRING()
+ SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkBlurDrawLooper)
+
+protected:
+ SkBlurDrawLooper(SkFlattenableReadBuffer&);
+ virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
+
+private:
+ SkMaskFilter* fBlur;
+ SkColorFilter* fColorFilter;
+ SkScalar fDx, fDy;
+ SkColor fBlurColor;
+ uint32_t fBlurFlags;
+
+ enum State {
+ kBeforeEdge,
+ kAfterEdge,
+ kDone
+ };
+ State fState;
+
+ typedef SkDrawLooper INHERITED;
+};
+
+#endif
diff --git a/effects/SkBlurImageFilter.h b/effects/SkBlurImageFilter.h
new file mode 100644
index 0000000..ef03a99
--- /dev/null
+++ b/effects/SkBlurImageFilter.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2011 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkBlurImageFilter_DEFINED
+#define SkBlurImageFilter_DEFINED
+
+#include "SkImageFilter.h"
+#include "SkSize.h"
+
+class SK_API SkBlurImageFilter : public SkImageFilter {
+public:
+ SkBlurImageFilter(SkScalar sigmaX,
+ SkScalar sigmaY,
+ SkImageFilter* input = NULL,
+ const SkIRect* cropRect = NULL);
+
+ SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkBlurImageFilter)
+
+protected:
+ explicit SkBlurImageFilter(SkFlattenableReadBuffer& buffer);
+ virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
+
+ virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&,
+ SkBitmap* result, SkIPoint* offset) SK_OVERRIDE;
+
+ bool canFilterImageGPU() const SK_OVERRIDE { return true; }
+ virtual bool filterImageGPU(Proxy* proxy, const SkBitmap& src, const SkMatrix& ctm,
+ SkBitmap* result, SkIPoint* offset) SK_OVERRIDE;
+
+private:
+ SkSize fSigma;
+ typedef SkImageFilter INHERITED;
+};
+
+#endif
diff --git a/effects/SkBlurMaskFilter.h b/effects/SkBlurMaskFilter.h
new file mode 100644
index 0000000..2ab321a
--- /dev/null
+++ b/effects/SkBlurMaskFilter.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkBlurMaskFilter_DEFINED
+#define SkBlurMaskFilter_DEFINED
+
+// we include this since our callers will need to at least be able to ref/unref
+#include "SkMaskFilter.h"
+#include "SkScalar.h"
+
+class SK_API SkBlurMaskFilter {
+public:
+ enum BlurStyle {
+ kNormal_BlurStyle, //!< fuzzy inside and outside
+ kSolid_BlurStyle, //!< solid inside, fuzzy outside
+ kOuter_BlurStyle, //!< nothing inside, fuzzy outside
+ kInner_BlurStyle, //!< fuzzy inside, nothing outside
+
+ kBlurStyleCount
+ };
+
+ enum BlurFlags {
+ kNone_BlurFlag = 0x00,
+ /** The blur layer's radius is not affected by transforms */
+ kIgnoreTransform_BlurFlag = 0x01,
+ /** Use a smother, higher qulity blur algorithm */
+ kHighQuality_BlurFlag = 0x02,
+ /** mask for all blur flags */
+ kAll_BlurFlag = 0x03
+ };
+
+ /** Create a blur maskfilter.
+ @param radius The radius to extend the blur from the original mask. Must be > 0.
+ @param style The BlurStyle to use
+ @param flags Flags to use - defaults to none
+ @return The new blur maskfilter
+ */
+ static SkMaskFilter* Create(SkScalar radius, BlurStyle style,
+ uint32_t flags = kNone_BlurFlag);
+
+ /** Create an emboss maskfilter
+ @param direction array of 3 scalars [x, y, z] specifying the direction of the light source
+ @param ambient 0...1 amount of ambient light
+ @param specular coefficient for specular highlights (e.g. 8)
+ @param blurRadius amount to blur before applying lighting (e.g. 3)
+ @return the emboss maskfilter
+ */
+ static SkMaskFilter* CreateEmboss( const SkScalar direction[3],
+ SkScalar ambient, SkScalar specular,
+ SkScalar blurRadius);
+
+ SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP()
+private:
+ SkBlurMaskFilter(); // can't be instantiated
+};
+
+#endif
diff --git a/effects/SkColorFilterImageFilter.h b/effects/SkColorFilterImageFilter.h
new file mode 100755
index 0000000..314ab07
--- /dev/null
+++ b/effects/SkColorFilterImageFilter.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2012 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkColorFilterImageFilter_DEFINED
+#define SkColorFilterImageFilter_DEFINED
+
+#include "SkImageFilter.h"
+
+class SkColorFilter;
+
+class SK_API SkColorFilterImageFilter : public SkImageFilter {
+public:
+ static SkColorFilterImageFilter* Create(SkColorFilter* cf,
+ SkImageFilter* input = NULL,
+ const SkIRect* cropRect = NULL);
+ virtual ~SkColorFilterImageFilter();
+
+ SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkColorFilterImageFilter)
+
+protected:
+ SkColorFilterImageFilter(SkFlattenableReadBuffer& buffer);
+ virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
+
+ virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&,
+ SkBitmap* result, SkIPoint* loc) SK_OVERRIDE;
+
+ virtual bool asColorFilter(SkColorFilter**) const SK_OVERRIDE;
+
+private:
+ SkColorFilterImageFilter(SkColorFilter* cf,
+ SkImageFilter* input,
+ const SkIRect* cropRect = NULL);
+ SkColorFilter* fColorFilter;
+
+ typedef SkImageFilter INHERITED;
+};
+
+#endif
diff --git a/effects/SkColorMatrix.h b/effects/SkColorMatrix.h
new file mode 100644
index 0000000..84a3b7c
--- /dev/null
+++ b/effects/SkColorMatrix.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2007 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkColorMatrix_DEFINED
+#define SkColorMatrix_DEFINED
+
+#include "SkScalar.h"
+
+class SK_API SkColorMatrix {
+public:
+ SkScalar fMat[20];
+
+ void setIdentity();
+ void setScale(SkScalar rScale, SkScalar gScale, SkScalar bScale,
+ SkScalar aScale = SK_Scalar1);
+ void preScale(SkScalar rScale, SkScalar gScale, SkScalar bScale,
+ SkScalar aScale = SK_Scalar1);
+ void postScale(SkScalar rScale, SkScalar gScale, SkScalar bScale,
+ SkScalar aScale = SK_Scalar1);
+
+ enum Axis {
+ kR_Axis = 0,
+ kG_Axis = 1,
+ kB_Axis = 2
+ };
+ void setRotate(Axis, SkScalar degrees);
+ void setSinCos(Axis, SkScalar sine, SkScalar cosine);
+ void preRotate(Axis, SkScalar degrees);
+ void postRotate(Axis, SkScalar degrees);
+
+ void setConcat(const SkColorMatrix& a, const SkColorMatrix& b);
+ void preConcat(const SkColorMatrix& mat) { this->setConcat(*this, mat); }
+ void postConcat(const SkColorMatrix& mat) { this->setConcat(mat, *this); }
+
+ void setSaturation(SkScalar sat);
+ void setRGB2YUV();
+ void setYUV2RGB();
+
+ bool operator==(const SkColorMatrix& other) const {
+ return 0 == memcmp(fMat, other.fMat, sizeof(fMat));
+ }
+
+ bool operator!=(const SkColorMatrix& other) const { return !((*this) == other); }
+};
+
+#endif
diff --git a/effects/SkColorMatrixFilter.h b/effects/SkColorMatrixFilter.h
new file mode 100644
index 0000000..ca7c086
--- /dev/null
+++ b/effects/SkColorMatrixFilter.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2007 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkColorMatrixFilter_DEFINED
+#define SkColorMatrixFilter_DEFINED
+
+#include "SkColorFilter.h"
+#include "SkColorMatrix.h"
+
+class SK_API SkColorMatrixFilter : public SkColorFilter {
+public:
+ explicit SkColorMatrixFilter(const SkColorMatrix&);
+ SkColorMatrixFilter(const SkScalar array[20]);
+
+ // overrides from SkColorFilter
+ virtual void filterSpan(const SkPMColor src[], int count, SkPMColor[]) const SK_OVERRIDE;
+ virtual void filterSpan16(const uint16_t src[], int count, uint16_t[]) const SK_OVERRIDE;
+ virtual uint32_t getFlags() const SK_OVERRIDE;
+ virtual bool asColorMatrix(SkScalar matrix[20]) const SK_OVERRIDE;
+#if SK_SUPPORT_GPU
+ virtual GrEffectRef* asNewEffect(GrContext*) const SK_OVERRIDE;
+#endif
+
+ struct State {
+ int32_t fArray[20];
+ int fShift;
+ };
+
+ SkDEVCODE(virtual void toString(SkString* str) const SK_OVERRIDE;)
+
+ SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkColorMatrixFilter)
+
+protected:
+ SkColorMatrixFilter(SkFlattenableReadBuffer& buffer);
+ virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
+
+private:
+ SkColorMatrix fMatrix;
+
+ typedef void (*Proc)(const State&, unsigned r, unsigned g, unsigned b,
+ unsigned a, int32_t result[4]);
+
+ Proc fProc;
+ State fState;
+ uint32_t fFlags;
+
+ void initState(const SkScalar array[20]);
+
+ typedef SkColorFilter INHERITED;
+};
+
+#endif
diff --git a/effects/SkComposeImageFilter.h b/effects/SkComposeImageFilter.h
new file mode 100644
index 0000000..45f530b
--- /dev/null
+++ b/effects/SkComposeImageFilter.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkComposeImageFilter_DEFINED
+#define SkComposeImageFilter_DEFINED
+
+#include "SkImageFilter.h"
+
+class SK_API SkComposeImageFilter : public SkImageFilter {
+public:
+ SkComposeImageFilter(SkImageFilter* outer, SkImageFilter* inner) : INHERITED(outer, inner) {}
+ virtual ~SkComposeImageFilter();
+
+ SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkComposeImageFilter)
+
+protected:
+ explicit SkComposeImageFilter(SkFlattenableReadBuffer& buffer);
+
+ virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&,
+ SkBitmap* result, SkIPoint* loc) SK_OVERRIDE;
+ virtual bool onFilterBounds(const SkIRect&, const SkMatrix&, SkIRect*) SK_OVERRIDE;
+
+private:
+ typedef SkImageFilter INHERITED;
+};
+
+#endif
diff --git a/effects/SkCornerPathEffect.h b/effects/SkCornerPathEffect.h
new file mode 100644
index 0000000..704b7fb
--- /dev/null
+++ b/effects/SkCornerPathEffect.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkCornerPathEffect_DEFINED
+#define SkCornerPathEffect_DEFINED
+
+#include "SkPathEffect.h"
+
+/** \class SkCornerPathEffect
+
+ SkCornerPathEffect is a subclass of SkPathEffect that can turn sharp corners
+ into various treatments (e.g. rounded corners)
+*/
+class SK_API SkCornerPathEffect : public SkPathEffect {
+public:
+ /** radius must be > 0 to have an effect. It specifies the distance from each corner
+ that should be "rounded".
+ */
+ SkCornerPathEffect(SkScalar radius);
+ virtual ~SkCornerPathEffect();
+
+ virtual bool filterPath(SkPath* dst, const SkPath& src,
+ SkStrokeRec*, const SkRect*) const SK_OVERRIDE;
+
+ SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkCornerPathEffect)
+
+protected:
+ SkCornerPathEffect(SkFlattenableReadBuffer&);
+ virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
+
+private:
+ SkScalar fRadius;
+
+ typedef SkPathEffect INHERITED;
+};
+
+#endif
diff --git a/effects/SkDashPathEffect.h b/effects/SkDashPathEffect.h
new file mode 100644
index 0000000..9c0775d
--- /dev/null
+++ b/effects/SkDashPathEffect.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkDashPathEffect_DEFINED
+#define SkDashPathEffect_DEFINED
+
+#include "SkPathEffect.h"
+
+/** \class SkDashPathEffect
+
+ SkDashPathEffect is a subclass of SkPathEffect that implements dashing
+*/
+class SK_API SkDashPathEffect : public SkPathEffect {
+public:
+ /** intervals: array containing an even number of entries (>=2), with
+ the even indices specifying the length of "on" intervals, and the odd
+ indices specifying the length of "off" intervals.
+ count: number of elements in the intervals array
+ phase: offset into the intervals array (mod the sum of all of the
+ intervals).
+
+ For example: if intervals[] = {10, 20}, count = 2, and phase = 25,
+ this will set up a dashed path like so:
+ 5 pixels off
+ 10 pixels on
+ 20 pixels off
+ 10 pixels on
+ 20 pixels off
+ ...
+ A phase of -5, 25, 55, 85, etc. would all result in the same path,
+ because the sum of all the intervals is 30.
+
+ Note: only affects stroked paths.
+ */
+ SkDashPathEffect(const SkScalar intervals[], int count, SkScalar phase,
+ bool scaleToFit = false);
+ virtual ~SkDashPathEffect();
+
+ virtual bool filterPath(SkPath* dst, const SkPath& src,
+ SkStrokeRec*, const SkRect*) const SK_OVERRIDE;
+
+ virtual bool asPoints(PointData* results, const SkPath& src,
+ const SkStrokeRec&, const SkMatrix&,
+ const SkRect*) const SK_OVERRIDE;
+
+ virtual Factory getFactory() SK_OVERRIDE;
+
+ static SkFlattenable* CreateProc(SkFlattenableReadBuffer&);
+
+protected:
+ SkDashPathEffect(SkFlattenableReadBuffer&);
+ virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
+
+private:
+ SkScalar* fIntervals;
+ int32_t fCount;
+ // computed from phase
+ SkScalar fInitialDashLength;
+ int32_t fInitialDashIndex;
+ SkScalar fIntervalLength;
+ bool fScaleToFit;
+
+ typedef SkPathEffect INHERITED;
+};
+
+#endif
diff --git a/effects/SkDiscretePathEffect.h b/effects/SkDiscretePathEffect.h
new file mode 100644
index 0000000..999ea04
--- /dev/null
+++ b/effects/SkDiscretePathEffect.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkDiscretePathEffect_DEFINED
+#define SkDiscretePathEffect_DEFINED
+
+#include "SkPathEffect.h"
+
+/** \class SkDiscretePathEffect
+
+ This path effect chops a path into discrete segments, and randomly displaces them.
+*/
+class SK_API SkDiscretePathEffect : public SkPathEffect {
+public:
+ /** Break the path into segments of segLength length, and randomly move the endpoints
+ away from the original path by a maximum of deviation.
+ Note: works on filled or framed paths
+ */
+ SkDiscretePathEffect(SkScalar segLength, SkScalar deviation);
+
+ virtual bool filterPath(SkPath* dst, const SkPath& src,
+ SkStrokeRec*, const SkRect*) const SK_OVERRIDE;
+
+ SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDiscretePathEffect)
+
+protected:
+ SkDiscretePathEffect(SkFlattenableReadBuffer&);
+ virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
+
+private:
+ SkScalar fSegLength, fPerterb;
+
+ typedef SkPathEffect INHERITED;
+};
+
+#endif
diff --git a/effects/SkDisplacementMapEffect.h b/effects/SkDisplacementMapEffect.h
new file mode 100644
index 0000000..ed9d15b
--- /dev/null
+++ b/effects/SkDisplacementMapEffect.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkDisplacementMapEffect_DEFINED
+#define SkDisplacementMapEffect_DEFINED
+
+#include "SkImageFilter.h"
+#include "SkBitmap.h"
+
+class SK_API SkDisplacementMapEffect : public SkImageFilter {
+public:
+ enum ChannelSelectorType {
+ kUnknown_ChannelSelectorType,
+ kR_ChannelSelectorType,
+ kG_ChannelSelectorType,
+ kB_ChannelSelectorType,
+ kA_ChannelSelectorType,
+ kKeyBits = 3 // Max value is 4, so 3 bits are required at most
+ };
+
+ SkDisplacementMapEffect(ChannelSelectorType xChannelSelector,
+ ChannelSelectorType yChannelSelector,
+ SkScalar scale, SkImageFilter* displacement,
+ SkImageFilter* color = NULL);
+
+ ~SkDisplacementMapEffect();
+
+ SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDisplacementMapEffect)
+
+ virtual bool onFilterImage(Proxy* proxy,
+ const SkBitmap& src,
+ const SkMatrix& ctm,
+ SkBitmap* dst,
+ SkIPoint* offset) SK_OVERRIDE;
+#if SK_SUPPORT_GPU
+ virtual bool canFilterImageGPU() const SK_OVERRIDE { return true; }
+ virtual bool filterImageGPU(Proxy* proxy, const SkBitmap& src, const SkMatrix& ctm,
+ SkBitmap* result, SkIPoint* offset) SK_OVERRIDE;
+#endif
+
+protected:
+ explicit SkDisplacementMapEffect(SkFlattenableReadBuffer& buffer);
+ virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
+
+private:
+ ChannelSelectorType fXChannelSelector;
+ ChannelSelectorType fYChannelSelector;
+ SkScalar fScale;
+ typedef SkImageFilter INHERITED;
+ SkImageFilter* getDisplacementInput() { return getInput(0); }
+ SkImageFilter* getColorInput() { return getInput(1); }
+};
+
+#endif
diff --git a/effects/SkDrawExtraPathEffect.h b/effects/SkDrawExtraPathEffect.h
new file mode 100644
index 0000000..392a46b
--- /dev/null
+++ b/effects/SkDrawExtraPathEffect.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright 2008 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SK_DRAW_EXTRA_PATH_EFFECT_H
+#define SK_DRAW_EXTRA_PATH_EFFECT_H
+
+class SkAnimator;
+
+void InitializeSkExtraPathEffects(SkAnimator* animator);
+
+#endif
diff --git a/effects/SkDropShadowImageFilter.h b/effects/SkDropShadowImageFilter.h
new file mode 100644
index 0000000..501df7c
--- /dev/null
+++ b/effects/SkDropShadowImageFilter.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkColor.h"
+#include "SkImageFilter.h"
+#include "SkScalar.h"
+
+class SK_API SkDropShadowImageFilter : public SkImageFilter {
+public:
+ SkDropShadowImageFilter(SkScalar dx, SkScalar dy, SkScalar sigma, SkColor, SkImageFilter* input = NULL);
+ SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDropShadowImageFilter)
+
+protected:
+ explicit SkDropShadowImageFilter(SkFlattenableReadBuffer&);
+ virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
+ virtual bool onFilterImage(Proxy*, const SkBitmap& source, const SkMatrix&, SkBitmap* result, SkIPoint* loc) SK_OVERRIDE;
+
+private:
+ SkScalar fDx, fDy, fSigma;
+ SkColor fColor;
+ typedef SkImageFilter INHERITED;
+};
diff --git a/effects/SkEmbossMaskFilter.h b/effects/SkEmbossMaskFilter.h
new file mode 100644
index 0000000..c667920
--- /dev/null
+++ b/effects/SkEmbossMaskFilter.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkEmbossMaskFilter_DEFINED
+#define SkEmbossMaskFilter_DEFINED
+
+#include "SkMaskFilter.h"
+
+/** \class SkEmbossMaskFilter
+
+ This mask filter creates a 3D emboss look, by specifying a light and blur amount.
+*/
+class SK_API SkEmbossMaskFilter : public SkMaskFilter {
+public:
+ struct Light {
+ SkScalar fDirection[3]; // x,y,z
+ uint16_t fPad;
+ uint8_t fAmbient;
+ uint8_t fSpecular; // exponent, 4.4 right now
+ };
+
+ SkEmbossMaskFilter(const Light& light, SkScalar blurRadius);
+
+ // overrides from SkMaskFilter
+ // This method is not exported to java.
+ virtual SkMask::Format getFormat() const SK_OVERRIDE;
+ // This method is not exported to java.
+ virtual bool filterMask(SkMask* dst, const SkMask& src, const SkMatrix&,
+ SkIPoint* margin) const SK_OVERRIDE;
+
+ SkDEVCODE(virtual void toString(SkString* str) const SK_OVERRIDE;)
+ SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkEmbossMaskFilter)
+
+protected:
+ SkEmbossMaskFilter(SkFlattenableReadBuffer&);
+ virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
+
+private:
+ Light fLight;
+ SkScalar fBlurRadius;
+
+ typedef SkMaskFilter INHERITED;
+};
+
+#endif
diff --git a/effects/SkGradientShader.h b/effects/SkGradientShader.h
new file mode 100644
index 0000000..ed0f1bf
--- /dev/null
+++ b/effects/SkGradientShader.h
@@ -0,0 +1,147 @@
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkGradientShader_DEFINED
+#define SkGradientShader_DEFINED
+
+#include "SkShader.h"
+
+class SkUnitMapper;
+
+/** \class SkGradientShader
+
+ SkGradientShader hosts factories for creating subclasses of SkShader that
+ render linear and radial gradients.
+*/
+class SK_API SkGradientShader {
+public:
+ enum Flags {
+ /** By default gradients will interpolate their colors in unpremul space
+ * and then premultiply each of the results. By setting this flag, the
+ * gradients will premultiply their colors first, and then interpolate
+ * between them.
+ */
+ kInterpolateColorsInPremul_Flag = 1 << 0,
+ };
+
+ /** Returns a shader that generates a linear gradient between the two
+ specified points.
+ <p />
+ CreateLinear returns a shader with a reference count of 1.
+ The caller should decrement the shader's reference count when done with the shader.
+ It is an error for count to be < 2.
+ @param pts The start and end points for the gradient.
+ @param colors The array[count] of colors, to be distributed between the two points
+ @param pos May be NULL. array[count] of SkScalars, or NULL, of the relative position of
+ each corresponding color in the colors array. If this is NULL,
+ the the colors are distributed evenly between the start and end point.
+ If this is not null, the values must begin with 0, end with 1.0, and
+ intermediate values must be strictly increasing.
+ @param count Must be >=2. The number of colors (and pos if not NULL) entries.
+ @param mode The tiling mode
+ @param mapper May be NULL. Callback to modify the spread of the colors.
+ */
+ static SkShader* CreateLinear(const SkPoint pts[2],
+ const SkColor colors[], const SkScalar pos[], int count,
+ SkShader::TileMode mode,
+ SkUnitMapper* mapper = NULL,
+ uint32_t flags = 0);
+
+ /** Returns a shader that generates a radial gradient given the center and radius.
+ <p />
+ CreateRadial returns a shader with a reference count of 1.
+ The caller should decrement the shader's reference count when done with the shader.
+ It is an error for colorCount to be < 2, or for radius to be <= 0.
+ @param center The center of the circle for this gradient
+ @param radius Must be positive. The radius of the circle for this gradient
+ @param colors The array[count] of colors, to be distributed between the center and edge of the circle
+ @param pos May be NULL. The array[count] of SkScalars, or NULL, of the relative position of
+ each corresponding color in the colors array. If this is NULL,
+ the the colors are distributed evenly between the center and edge of the circle.
+ If this is not null, the values must begin with 0, end with 1.0, and
+ intermediate values must be strictly increasing.
+ @param count Must be >= 2. The number of colors (and pos if not NULL) entries
+ @param mode The tiling mode
+ @param mapper May be NULL. Callback to modify the spread of the colors.
+ */
+ static SkShader* CreateRadial(const SkPoint& center, SkScalar radius,
+ const SkColor colors[], const SkScalar pos[], int count,
+ SkShader::TileMode mode,
+ SkUnitMapper* mapper = NULL,
+ uint32_t flags = 0);
+
+ /** Returns a shader that generates a radial gradient given the start position, start radius, end position and end radius.
+ <p />
+ CreateTwoPointRadial returns a shader with a reference count of 1.
+ The caller should decrement the shader's reference count when done with the shader.
+ It is an error for colorCount to be < 2, for startRadius or endRadius to be < 0, or for
+ startRadius to be equal to endRadius.
+ @param start The center of the start circle for this gradient
+ @param startRadius Must be positive. The radius of the start circle for this gradient.
+ @param end The center of the end circle for this gradient
+ @param endRadius Must be positive. The radius of the end circle for this gradient.
+ @param colors The array[count] of colors, to be distributed between the center and edge of the circle
+ @param pos May be NULL. The array[count] of SkScalars, or NULL, of the relative position of
+ each corresponding color in the colors array. If this is NULL,
+ the the colors are distributed evenly between the center and edge of the circle.
+ If this is not null, the values must begin with 0, end with 1.0, and
+ intermediate values must be strictly increasing.
+ @param count Must be >= 2. The number of colors (and pos if not NULL) entries
+ @param mode The tiling mode
+ @param mapper May be NULL. Callback to modify the spread of the colors.
+ */
+ static SkShader* CreateTwoPointRadial(const SkPoint& start,
+ SkScalar startRadius,
+ const SkPoint& end,
+ SkScalar endRadius,
+ const SkColor colors[],
+ const SkScalar pos[], int count,
+ SkShader::TileMode mode,
+ SkUnitMapper* mapper = NULL,
+ uint32_t flags = 0);
+
+ /**
+ * Returns a shader that generates a conical gradient given two circles, or
+ * returns NULL if the inputs are invalid. The gradient interprets the
+ * two circles according to the following HTML spec.
+ * http://dev.w3.org/html5/2dcontext/#dom-context-2d-createradialgradient
+ */
+ static SkShader* CreateTwoPointConical(const SkPoint& start,
+ SkScalar startRadius,
+ const SkPoint& end,
+ SkScalar endRadius,
+ const SkColor colors[],
+ const SkScalar pos[], int count,
+ SkShader::TileMode mode,
+ SkUnitMapper* mapper = NULL,
+ uint32_t flags = 0);
+
+ /** Returns a shader that generates a sweep gradient given a center.
+ <p />
+ CreateSweep returns a shader with a reference count of 1.
+ The caller should decrement the shader's reference count when done with the shader.
+ It is an error for colorCount to be < 2.
+ @param cx The X coordinate of the center of the sweep
+ @param cx The Y coordinate of the center of the sweep
+ @param colors The array[count] of colors, to be distributed around the center.
+ @param pos May be NULL. The array[count] of SkScalars, or NULL, of the relative position of
+ each corresponding color in the colors array. If this is NULL,
+ the the colors are distributed evenly between the center and edge of the circle.
+ If this is not null, the values must begin with 0, end with 1.0, and
+ intermediate values must be strictly increasing.
+ @param count Must be >= 2. The number of colors (and pos if not NULL) entries
+ @param mapper May be NULL. Callback to modify the spread of the colors.
+ */
+ static SkShader* CreateSweep(SkScalar cx, SkScalar cy,
+ const SkColor colors[], const SkScalar pos[],
+ int count, SkUnitMapper* mapper = NULL,
+ uint32_t flags = 0);
+
+ SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP()
+};
+
+#endif
diff --git a/effects/SkKernel33MaskFilter.h b/effects/SkKernel33MaskFilter.h
new file mode 100644
index 0000000..3404b73
--- /dev/null
+++ b/effects/SkKernel33MaskFilter.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2008 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkKernel33MaskFilter_DEFINED
+#define SkKernel33MaskFilter_DEFINED
+
+#include "SkMaskFilter.h"
+
+class SK_API SkKernel33ProcMaskFilter : public SkMaskFilter {
+public:
+ SkKernel33ProcMaskFilter(unsigned percent256 = 256)
+ : fPercent256(percent256) {}
+
+ virtual uint8_t computeValue(uint8_t* const* srcRows) const = 0;
+
+ virtual SkMask::Format getFormat() const SK_OVERRIDE;
+ virtual bool filterMask(SkMask*, const SkMask&, const SkMatrix&,
+ SkIPoint*) const SK_OVERRIDE;
+
+ SkDEVCODE(virtual void toString(SkString* str) const SK_OVERRIDE;)
+
+protected:
+ SkKernel33ProcMaskFilter(SkFlattenableReadBuffer& rb);
+ virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
+
+private:
+ int fPercent256;
+
+ typedef SkMaskFilter INHERITED;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+class SK_API SkKernel33MaskFilter : public SkKernel33ProcMaskFilter {
+public:
+ SkKernel33MaskFilter(const int coeff[3][3], int shift, int percent256 = 256)
+ : SkKernel33ProcMaskFilter(percent256) {
+ memcpy(fKernel, coeff, 9 * sizeof(int));
+ fShift = shift;
+ }
+
+ // override from SkKernel33ProcMaskFilter
+ virtual uint8_t computeValue(uint8_t* const* srcRows) const SK_OVERRIDE;
+
+ SkDEVCODE(virtual void toString(SkString* str) const SK_OVERRIDE;)
+ SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkKernel33MaskFilter)
+
+private:
+ int fKernel[3][3];
+ int fShift;
+
+ SkKernel33MaskFilter(SkFlattenableReadBuffer& rb);
+ virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
+
+ typedef SkKernel33ProcMaskFilter INHERITED;
+};
+
+#endif
diff --git a/effects/SkLayerDrawLooper.h b/effects/SkLayerDrawLooper.h
new file mode 100644
index 0000000..adf07a9
--- /dev/null
+++ b/effects/SkLayerDrawLooper.h
@@ -0,0 +1,139 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkLayerDrawLooper_DEFINED
+#define SkLayerDrawLooper_DEFINED
+
+#include "SkDrawLooper.h"
+#include "SkPaint.h"
+#include "SkPoint.h"
+#include "SkXfermode.h"
+
+class SK_API SkLayerDrawLooper : public SkDrawLooper {
+public:
+ SK_DECLARE_INST_COUNT(SkLayerDrawLooper)
+
+ SkLayerDrawLooper();
+ virtual ~SkLayerDrawLooper();
+
+ /**
+ * Bits specifies which aspects of the layer's paint should replace the
+ * corresponding aspects on the draw's paint.
+ * kEntirePaint_Bits means use the layer's paint completely.
+ * 0 means ignore the layer's paint... except that LayerInfo's fFlagsMask
+ * and fColorMode are always applied.
+ */
+ enum Bits {
+ kStyle_Bit = 1 << 0, //!< use this layer's Style/stroke settings
+ kTextSkewX_Bit = 1 << 1, //!< use this layer's textskewx
+ kPathEffect_Bit = 1 << 2, //!< use this layer's patheffect
+ kMaskFilter_Bit = 1 << 3, //!< use this layer's maskfilter
+ kShader_Bit = 1 << 4, //!< use this layer's shader
+ kColorFilter_Bit = 1 << 5, //!< use this layer's colorfilter
+ kXfermode_Bit = 1 << 6, //!< use this layer's xfermode
+
+ /**
+ * Use the layer's paint entirely, with these exceptions:
+ * - We never override the draw's paint's text_encoding, since that is
+ * used to interpret the text/len parameters in draw[Pos]Text.
+ * - Flags and Color are always computed using the LayerInfo's
+ * fFlagsMask and fColorMode.
+ */
+ kEntirePaint_Bits = -1
+
+ };
+ typedef int32_t BitFlags;
+
+ /**
+ * Info for how to apply the layer's paint and offset.
+ *
+ * fFlagsMask selects which flags in the layer's paint should be applied.
+ * result = (draw-flags & ~fFlagsMask) | (layer-flags & fFlagsMask)
+ * In the extreme:
+ * If fFlagsMask is 0, we ignore all of the layer's flags
+ * If fFlagsMask is -1, we use all of the layer's flags
+ *
+ * fColorMode controls how we compute the final color for the layer:
+ * The layer's paint's color is treated as the SRC
+ * The draw's paint's color is treated as the DST
+ * final-color = Mode(layers-color, draws-color);
+ * Any SkXfermode::Mode will work. Two common choices are:
+ * kSrc_Mode: to use the layer's color, ignoring the draw's
+ * kDst_Mode: to just keep the draw's color, ignoring the layer's
+ */
+ struct SK_API LayerInfo {
+ uint32_t fFlagsMask; // SkPaint::Flags
+ BitFlags fPaintBits;
+ SkXfermode::Mode fColorMode;
+ SkVector fOffset;
+ bool fPostTranslate; //!< applies to fOffset
+
+ /**
+ * Initial the LayerInfo. Defaults to settings that will draw the
+ * layer with no changes: e.g.
+ * fPaintBits == 0
+ * fColorMode == kDst_Mode
+ * fOffset == (0, 0)
+ */
+ LayerInfo();
+ };
+
+ /**
+ * Call for each layer you want to add (from top to bottom).
+ * This returns a paint you can modify, but that ptr is only valid until
+ * the next call made to addLayer().
+ */
+ SkPaint* addLayer(const LayerInfo&);
+
+ /**
+ * This layer will draw with the original paint, at the specified offset
+ */
+ void addLayer(SkScalar dx, SkScalar dy);
+
+ /**
+ * This layer will with the original paint and no offset.
+ */
+ void addLayer() { this->addLayer(0, 0); }
+
+ /// Similar to addLayer, but adds a layer to the top.
+ SkPaint* addLayerOnTop(const LayerInfo&);
+
+ // overrides from SkDrawLooper
+ virtual void init(SkCanvas*);
+ virtual bool next(SkCanvas*, SkPaint* paint);
+
+ SK_DEVELOPER_TO_STRING()
+ SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkLayerDrawLooper)
+
+protected:
+ SkLayerDrawLooper(SkFlattenableReadBuffer&);
+ virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
+
+private:
+ struct Rec {
+ Rec* fNext;
+ SkPaint fPaint;
+ LayerInfo fInfo;
+ };
+ Rec* fRecs;
+ Rec* fTopRec;
+ int fCount;
+
+ // state-machine during the init/next cycle
+ Rec* fCurrRec;
+
+ static void ApplyInfo(SkPaint* dst, const SkPaint& src, const LayerInfo&);
+
+ class MyRegistrar : public SkFlattenable::Registrar {
+ public:
+ MyRegistrar();
+ };
+
+ typedef SkDrawLooper INHERITED;
+};
+
+#endif
diff --git a/effects/SkLayerRasterizer.h b/effects/SkLayerRasterizer.h
new file mode 100644
index 0000000..65d1be0
--- /dev/null
+++ b/effects/SkLayerRasterizer.h
@@ -0,0 +1,52 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkLayerRasterizer_DEFINED
+#define SkLayerRasterizer_DEFINED
+
+#include "SkRasterizer.h"
+#include "SkDeque.h"
+#include "SkScalar.h"
+
+class SkPaint;
+
+class SK_API SkLayerRasterizer : public SkRasterizer {
+public:
+ SkLayerRasterizer();
+ virtual ~SkLayerRasterizer();
+
+ void addLayer(const SkPaint& paint) {
+ this->addLayer(paint, 0, 0);
+ }
+
+ /** Add a new layer (above any previous layers) to the rasterizer.
+ The layer will extract those fields that affect the mask from
+ the specified paint, but will not retain a reference to the paint
+ object itself, so it may be reused without danger of side-effects.
+ */
+ void addLayer(const SkPaint& paint, SkScalar dx, SkScalar dy);
+
+ SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkLayerRasterizer)
+
+protected:
+ SkLayerRasterizer(SkFlattenableReadBuffer&);
+ virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
+
+ // override from SkRasterizer
+ virtual bool onRasterize(const SkPath& path, const SkMatrix& matrix,
+ const SkIRect* clipBounds,
+ SkMask* mask, SkMask::CreateMode mode) const;
+
+private:
+ SkDeque fLayers;
+
+ typedef SkRasterizer INHERITED;
+};
+
+#endif
diff --git a/effects/SkLerpXfermode.h b/effects/SkLerpXfermode.h
new file mode 100644
index 0000000..6151f3d
--- /dev/null
+++ b/effects/SkLerpXfermode.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkLerpXfermode_DEFINED
+#define SkLerpXfermode_DEFINED
+
+#include "SkXfermode.h"
+
+class SK_API SkLerpXfermode : public SkXfermode {
+public:
+ /**
+ * result = scale * src + (1 - scale) * dst
+ *
+ * When scale == 1, this is the same as kSrc_Mode
+ * When scale == 0, this is the same as kDst_Mode
+ */
+ static SkXfermode* Create(SkScalar scale);
+
+ // overrides from SkXfermode
+ virtual void xfer32(SkPMColor dst[], const SkPMColor src[], int count,
+ const SkAlpha aa[]) const SK_OVERRIDE;
+ virtual void xfer16(uint16_t dst[], const SkPMColor src[], int count,
+ const SkAlpha aa[]) const SK_OVERRIDE;
+ virtual void xferA8(SkAlpha dst[], const SkPMColor src[], int count,
+ const SkAlpha aa[]) const SK_OVERRIDE;
+
+ SK_DEVELOPER_TO_STRING()
+ SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkLerpXfermode)
+
+protected:
+ SkLerpXfermode(SkFlattenableReadBuffer&);
+ virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
+
+private:
+ SkLerpXfermode(unsigned scale256);
+
+ unsigned fScale256; // 0..256
+
+ typedef SkXfermode INHERITED;
+};
+
+#endif
diff --git a/effects/SkLightingImageFilter.h b/effects/SkLightingImageFilter.h
new file mode 100644
index 0000000..07f713b
--- /dev/null
+++ b/effects/SkLightingImageFilter.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2012 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkLightingImageFilter_DEFINED
+#define SkLightingImageFilter_DEFINED
+
+#include "SkImageFilter.h"
+#include "SkColor.h"
+
+class SK_API SkPoint3 {
+public:
+ SkPoint3() {}
+ SkPoint3(SkScalar x, SkScalar y, SkScalar z)
+ : fX(x), fY(y), fZ(z) {}
+ SkScalar dot(const SkPoint3& other) const {
+ return SkScalarMul(fX, other.fX)
+ + SkScalarMul(fY, other.fY)
+ + SkScalarMul(fZ, other.fZ);
+ }
+ SkScalar maxComponent() const {
+ return fX > fY ? (fX > fZ ? fX : fZ) : (fY > fZ ? fY : fZ);
+ }
+ void normalize() {
+ SkScalar scale = SkScalarInvert(SkScalarSqrt(dot(*this)));
+ fX = SkScalarMul(fX, scale);
+ fY = SkScalarMul(fY, scale);
+ fZ = SkScalarMul(fZ, scale);
+ }
+ SkPoint3 operator*(SkScalar scalar) const {
+ return SkPoint3(SkScalarMul(fX, scalar),
+ SkScalarMul(fY, scalar),
+ SkScalarMul(fZ, scalar));
+ }
+ SkPoint3 operator-(const SkPoint3& other) const {
+ return SkPoint3(fX - other.fX, fY - other.fY, fZ - other.fZ);
+ }
+ bool operator==(const SkPoint3& other) const {
+ return fX == other.fX && fY == other.fY && fZ == other.fZ;
+ }
+ SkScalar fX, fY, fZ;
+};
+
+class SkLight;
+
+class SK_API SkLightingImageFilter : public SkImageFilter {
+public:
+ static SkImageFilter* CreateDistantLitDiffuse(const SkPoint3& direction,
+ SkColor lightColor, SkScalar surfaceScale, SkScalar kd,
+ SkImageFilter* input = NULL, const SkIRect* cropRect = NULL);
+ static SkImageFilter* CreatePointLitDiffuse(const SkPoint3& location,
+ SkColor lightColor, SkScalar surfaceScale, SkScalar kd,
+ SkImageFilter* input = NULL, const SkIRect* cropRect = NULL);
+ static SkImageFilter* CreateSpotLitDiffuse(const SkPoint3& location,
+ const SkPoint3& target, SkScalar specularExponent, SkScalar cutoffAngle,
+ SkColor lightColor, SkScalar surfaceScale, SkScalar kd,
+ SkImageFilter* input = NULL, const SkIRect* cropRect = NULL);
+ static SkImageFilter* CreateDistantLitSpecular(const SkPoint3& direction,
+ SkColor lightColor, SkScalar surfaceScale, SkScalar ks,
+ SkScalar shininess, SkImageFilter* input = NULL, const SkIRect* cropRect = NULL);
+ static SkImageFilter* CreatePointLitSpecular(const SkPoint3& location,
+ SkColor lightColor, SkScalar surfaceScale, SkScalar ks,
+ SkScalar shininess, SkImageFilter* input = NULL, const SkIRect* cropRect = NULL);
+ static SkImageFilter* CreateSpotLitSpecular(const SkPoint3& location,
+ const SkPoint3& target, SkScalar specularExponent, SkScalar cutoffAngle,
+ SkColor lightColor, SkScalar surfaceScale, SkScalar ks,
+ SkScalar shininess, SkImageFilter* input = NULL, const SkIRect* cropRect = NULL);
+ ~SkLightingImageFilter();
+
+ SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP()
+
+protected:
+ SkLightingImageFilter(SkLight* light,
+ SkScalar surfaceScale,
+ SkImageFilter* input,
+ const SkIRect* cropRect = NULL);
+ explicit SkLightingImageFilter(SkFlattenableReadBuffer& buffer);
+ virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
+ const SkLight* light() const { return fLight; }
+ SkScalar surfaceScale() const { return fSurfaceScale; }
+
+private:
+ typedef SkImageFilter INHERITED;
+ SkLight* fLight;
+ SkScalar fSurfaceScale;
+};
+
+#endif
diff --git a/effects/SkMagnifierImageFilter.h b/effects/SkMagnifierImageFilter.h
new file mode 100644
index 0000000..b5cbd74
--- /dev/null
+++ b/effects/SkMagnifierImageFilter.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2012 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkMagnifierImageFilter_DEFINED
+#define SkMagnifierImageFilter_DEFINED
+
+#include "SkRect.h"
+#include "SkImageFilter.h"
+
+class SK_API SkMagnifierImageFilter : public SkImageFilter {
+public:
+ SkMagnifierImageFilter(SkRect srcRect, SkScalar inset);
+
+#if SK_SUPPORT_GPU
+ virtual bool asNewEffect(GrEffectRef** effect, GrTexture* texture, const SkIPoint& offset) const SK_OVERRIDE;
+#endif
+
+ SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkMagnifierImageFilter)
+
+protected:
+ explicit SkMagnifierImageFilter(SkFlattenableReadBuffer& buffer);
+ virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
+
+ virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&,
+ SkBitmap* result, SkIPoint* offset) SK_OVERRIDE;
+
+private:
+ SkRect fSrcRect;
+ SkScalar fInset;
+ typedef SkImageFilter INHERITED;
+};
+
+#endif
diff --git a/effects/SkMatrixConvolutionImageFilter.h b/effects/SkMatrixConvolutionImageFilter.h
new file mode 100644
index 0000000..71c8938
--- /dev/null
+++ b/effects/SkMatrixConvolutionImageFilter.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2012 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkMatrixConvolutionImageFilter_DEFINED
+#define SkMatrixConvolutionImageFilter_DEFINED
+
+#include "SkImageFilter.h"
+#include "SkScalar.h"
+#include "SkSize.h"
+#include "SkPoint.h"
+
+/*! \class SkMatrixConvolutionImageFilter
+ Matrix convolution image filter. This filter applies an NxM image
+ processing kernel to a given input image. This can be used to produce
+ effects such as sharpening, blurring, edge detection, etc.
+ */
+
+class SK_API SkMatrixConvolutionImageFilter : public SkImageFilter {
+public:
+ /*! \enum TileMode */
+ enum TileMode {
+ kClamp_TileMode, /*!< Clamp to the image's edge pixels. */
+ kRepeat_TileMode, /*!< Wrap around to the image's opposite edge. */
+ kClampToBlack_TileMode, /*!< Fill with transparent black. */
+ };
+
+ /** Construct a matrix convolution image filter.
+ @param kernelSize The kernel size in pixels, in each dimension (N by M).
+ @param kernel The image processing kernel. Must contain N * M
+ elements, in row order.
+ @param gain A scale factor applied to each pixel after
+ convolution. This can be used to normalize the
+ kernel, if it does not sum to 1.
+ @param bias A bias factor added to each pixel after convolution.
+ @param target An offset applied to each pixel coordinate before
+ convolution. This can be used to center the kernel
+ over the image (e.g., a 3x3 kernel should have a
+ target of {1, 1}).
+ @param tileMode How accesses outside the image are treated. (@see
+ TileMode).
+ @param convolveAlpha If true, all channels are convolved. If false,
+ only the RGB channels are convolved, and
+ alpha is copied from the source image.
+ @param input The input image filter. If NULL, the src bitmap
+ passed to filterImage() is used instead.
+ */
+
+ SkMatrixConvolutionImageFilter(const SkISize& kernelSize, const SkScalar* kernel, SkScalar gain, SkScalar bias, const SkIPoint& target, TileMode tileMode, bool convolveAlpha, SkImageFilter* input = NULL);
+ virtual ~SkMatrixConvolutionImageFilter();
+
+ SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkMatrixConvolutionImageFilter)
+
+protected:
+ SkMatrixConvolutionImageFilter(SkFlattenableReadBuffer& buffer);
+ virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
+
+ virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&,
+ SkBitmap* result, SkIPoint* loc) SK_OVERRIDE;
+
+#if SK_SUPPORT_GPU
+ virtual bool asNewEffect(GrEffectRef** effect, GrTexture*, const SkIPoint& offset) const SK_OVERRIDE;
+#endif
+
+private:
+ SkISize fKernelSize;
+ SkScalar* fKernel;
+ SkScalar fGain;
+ SkScalar fBias;
+ SkIPoint fTarget;
+ TileMode fTileMode;
+ bool fConvolveAlpha;
+ typedef SkImageFilter INHERITED;
+
+ template <class PixelFetcher, bool convolveAlpha>
+ void filterPixels(const SkBitmap& src, SkBitmap* result, const SkIRect& rect);
+ template <class PixelFetcher>
+ void filterPixels(const SkBitmap& src, SkBitmap* result, const SkIRect& rect);
+ void filterInteriorPixels(const SkBitmap& src, SkBitmap* result, const SkIRect& rect);
+ void filterBorderPixels(const SkBitmap& src, SkBitmap* result, const SkIRect& rect);
+};
+
+#endif
diff --git a/effects/SkMergeImageFilter.h b/effects/SkMergeImageFilter.h
new file mode 100755
index 0000000..8c4313d
--- /dev/null
+++ b/effects/SkMergeImageFilter.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2012 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkMergeImageFilter_DEFINED
+#define SkMergeImageFilter_DEFINED
+
+#include "SkImageFilter.h"
+
+#include "SkXfermode.h"
+
+class SK_API SkMergeImageFilter : public SkImageFilter {
+public:
+ SkMergeImageFilter(SkImageFilter* first, SkImageFilter* second,
+ SkXfermode::Mode = SkXfermode::kSrcOver_Mode);
+ SkMergeImageFilter(SkImageFilter* filters[], int count,
+ const SkXfermode::Mode modes[] = NULL);
+ virtual ~SkMergeImageFilter();
+
+ SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkMergeImageFilter)
+
+protected:
+ SkMergeImageFilter(SkFlattenableReadBuffer& buffer);
+ virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
+
+ virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&,
+ SkBitmap* result, SkIPoint* loc) SK_OVERRIDE;
+ virtual bool onFilterBounds(const SkIRect&, const SkMatrix&, SkIRect*) SK_OVERRIDE;
+
+private:
+ uint8_t* fModes; // SkXfermode::Mode
+
+ // private storage, to avoid dynamically allocating storage for our copy
+ // of the modes (unless the count is so large we can't fit).
+ intptr_t fStorage[16];
+
+ void initAllocModes();
+ void initModes(const SkXfermode::Mode []);
+
+ typedef SkImageFilter INHERITED;
+};
+
+#endif
diff --git a/effects/SkMorphologyImageFilter.h b/effects/SkMorphologyImageFilter.h
new file mode 100644
index 0000000..def01e8
--- /dev/null
+++ b/effects/SkMorphologyImageFilter.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2012 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkMorphologyImageFilter_DEFINED
+#define SkMorphologyImageFilter_DEFINED
+
+#include "SkImageFilter.h"
+#include "SkSize.h"
+
+class SK_API SkMorphologyImageFilter : public SkImageFilter {
+public:
+ SkMorphologyImageFilter(int radiusX, int radiusY, SkImageFilter* input);
+
+protected:
+ SkMorphologyImageFilter(SkFlattenableReadBuffer& buffer);
+ virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
+#if SK_SUPPORT_GPU
+ virtual bool canFilterImageGPU() const SK_OVERRIDE { return true; }
+#endif
+
+ SkISize radius() const { return fRadius; }
+
+private:
+ SkISize fRadius;
+ typedef SkImageFilter INHERITED;
+};
+
+class SK_API SkDilateImageFilter : public SkMorphologyImageFilter {
+public:
+ SkDilateImageFilter(int radiusX, int radiusY, SkImageFilter* input = NULL)
+ : INHERITED(radiusX, radiusY, input) {}
+
+ virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&,
+ SkBitmap* result, SkIPoint* offset) SK_OVERRIDE;
+#if SK_SUPPORT_GPU
+ virtual bool filterImageGPU(Proxy* proxy, const SkBitmap& src, const SkMatrix& ctm,
+ SkBitmap* result, SkIPoint* offset) SK_OVERRIDE;
+#endif
+
+ SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDilateImageFilter)
+
+protected:
+ SkDilateImageFilter(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {}
+
+private:
+ typedef SkMorphologyImageFilter INHERITED;
+};
+
+class SK_API SkErodeImageFilter : public SkMorphologyImageFilter {
+public:
+ SkErodeImageFilter(int radiusX, int radiusY, SkImageFilter* input = NULL)
+ : INHERITED(radiusX, radiusY, input) {}
+
+ virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&,
+ SkBitmap* result, SkIPoint* offset) SK_OVERRIDE;
+#if SK_SUPPORT_GPU
+ virtual bool filterImageGPU(Proxy* proxy, const SkBitmap& src, const SkMatrix& ctm,
+ SkBitmap* result, SkIPoint* offset) SK_OVERRIDE;
+#endif
+
+ SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkErodeImageFilter)
+
+protected:
+ SkErodeImageFilter(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {}
+
+private:
+ typedef SkMorphologyImageFilter INHERITED;
+};
+
+#endif
diff --git a/effects/SkOffsetImageFilter.h b/effects/SkOffsetImageFilter.h
new file mode 100644
index 0000000..62b5fa6
--- /dev/null
+++ b/effects/SkOffsetImageFilter.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2012 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkOffsetImageFilter_DEFINED
+#define SkOffsetImageFilter_DEFINED
+
+#include "SkImageFilter.h"
+#include "SkPoint.h"
+
+class SK_API SkOffsetImageFilter : public SkImageFilter {
+public:
+ SkOffsetImageFilter(SkScalar dx, SkScalar dy, SkImageFilter* input = NULL);
+ SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkOffsetImageFilter)
+
+protected:
+ SkOffsetImageFilter(SkFlattenableReadBuffer& buffer);
+ virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
+
+ virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&,
+ SkBitmap* result, SkIPoint* loc) SK_OVERRIDE;
+ virtual bool onFilterBounds(const SkIRect&, const SkMatrix&, SkIRect*) SK_OVERRIDE;
+
+private:
+ SkVector fOffset;
+
+ typedef SkImageFilter INHERITED;
+};
+
+#endif
diff --git a/effects/SkPaintFlagsDrawFilter.h b/effects/SkPaintFlagsDrawFilter.h
new file mode 100644
index 0000000..cb2a8b7
--- /dev/null
+++ b/effects/SkPaintFlagsDrawFilter.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2008 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkPaintFlagsDrawFilter_DEFINED
+#define SkPaintFlagsDrawFilter_DEFINED
+
+#include "SkDrawFilter.h"
+
+class SK_API SkPaintFlagsDrawFilter : public SkDrawFilter {
+public:
+ SkPaintFlagsDrawFilter(uint32_t clearFlags, uint32_t setFlags);
+
+ virtual bool filter(SkPaint*, Type) SK_OVERRIDE;
+
+private:
+ uint16_t fClearFlags; // user specified
+ uint16_t fSetFlags; // user specified
+};
+
+#endif
diff --git a/effects/SkPerlinNoiseShader.h b/effects/SkPerlinNoiseShader.h
new file mode 100644
index 0000000..22cb892
--- /dev/null
+++ b/effects/SkPerlinNoiseShader.h
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkPerlinNoiseShader_DEFINED
+#define SkPerlinNoiseShader_DEFINED
+
+#include "SkShader.h"
+
+/** \class SkPerlinNoiseShader
+
+ SkPerlinNoiseShader creates an image using the Perlin turbulence function.
+
+ It can produce tileable noise if asked to stitch tiles and provided a tile size.
+ In order to fill a large area with repeating noise, set the stitchTiles flag to
+ true, and render exactly a single tile of noise. Without this flag, the result
+ will contain visible seams between tiles.
+
+ The algorithm used is described here :
+ http://www.w3.org/TR/SVG/filters.html#feTurbulenceElement
+*/
+class SK_API SkPerlinNoiseShader : public SkShader {
+ struct PaintingData;
+public:
+ struct StitchData;
+
+ /**
+ * About the noise types : the difference between the 2 is just minor tweaks to the algorithm,
+ * they're not 2 entirely different noises. The output looks different, but once the noise is
+ * generated in the [1, -1] range, the output is brought back in the [0, 1] range by doing :
+ * kFractalNoise_Type : noise * 0.5 + 0.5
+ * kTurbulence_Type : abs(noise)
+ * Very little differences between the 2 types, although you can tell the difference visually.
+ */
+ enum Type {
+ kFractalNoise_Type,
+ kTurbulence_Type,
+ kFirstType = kFractalNoise_Type,
+ kLastType = kTurbulence_Type
+ };
+ /**
+ * This will construct Perlin noise of the given type (Fractal Noise or Turbulence).
+ *
+ * Both base frequencies (X and Y) have a usual range of (0..1).
+ *
+ * The number of octaves provided should be fairly small, although no limit is enforced.
+ * Each octave doubles the frequency, so 10 octaves would produce noise from
+ * baseFrequency * 1, * 2, * 4, ..., * 512, which quickly yields insignificantly small
+ * periods and resembles regular unstructured noise rather than Perlin noise.
+ *
+ * If tileSize isn't NULL or an empty size, the tileSize parameter will be used to modify
+ * the frequencies so that the noise will be tileable for the given tile size. If tileSize
+ * is NULL or an empty size, the frequencies will be used as is without modification.
+ */
+ static SkShader* CreateFractalNoise(SkScalar baseFrequencyX, SkScalar baseFrequencyY,
+ int numOctaves, SkScalar seed,
+ const SkISize* tileSize = NULL);
+ static SkShader* CreateTubulence(SkScalar baseFrequencyX, SkScalar baseFrequencyY,
+ int numOctaves, SkScalar seed,
+ const SkISize* tileSize = NULL);
+
+ virtual bool setContext(const SkBitmap& device, const SkPaint& paint,
+ const SkMatrix& matrix);
+ virtual void shadeSpan(int x, int y, SkPMColor[], int count) SK_OVERRIDE;
+ virtual void shadeSpan16(int x, int y, uint16_t[], int count) SK_OVERRIDE;
+
+ virtual GrEffectRef* asNewEffect(GrContext* context, const SkPaint&) const SK_OVERRIDE;
+
+ SK_DEVELOPER_TO_STRING()
+ SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkPerlinNoiseShader)
+
+protected:
+ SkPerlinNoiseShader(SkFlattenableReadBuffer&);
+ virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
+
+private:
+ SkPerlinNoiseShader(SkPerlinNoiseShader::Type type, SkScalar baseFrequencyX,
+ SkScalar baseFrequencyY, int numOctaves, SkScalar seed,
+ const SkISize* tileSize = NULL);
+ virtual ~SkPerlinNoiseShader();
+
+ void setTileSize(const SkISize&);
+
+ void initPaint(PaintingData& paintingData);
+
+ SkScalar noise2D(int channel, const PaintingData& paintingData,
+ const StitchData& stitchData, const SkPoint& noiseVector);
+
+ SkScalar calculateTurbulenceValueForPoint(int channel, const PaintingData& paintingData,
+ StitchData& stitchData, const SkPoint& point);
+
+ SkPMColor shade(const SkPoint& point, StitchData& stitchData);
+
+ SkPerlinNoiseShader::Type fType;
+ SkScalar fBaseFrequencyX;
+ SkScalar fBaseFrequencyY;
+ int fNumOctaves;
+ SkScalar fSeed;
+ SkISize fTileSize;
+ bool fStitchTiles;
+ SkMatrix fMatrix;
+
+ PaintingData* fPaintingData;
+
+ typedef SkShader INHERITED;
+};
+
+#endif
diff --git a/effects/SkPixelXorXfermode.h b/effects/SkPixelXorXfermode.h
new file mode 100644
index 0000000..5411b12
--- /dev/null
+++ b/effects/SkPixelXorXfermode.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2007 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkPixelXorXfermode_DEFINED
+#define SkPixelXorXfermode_DEFINED
+
+#include "SkXfermode.h"
+
+/** SkPixelXorXfermode implements a simple pixel xor (op ^ src ^ dst).
+ This transformation does not follow premultiplied conventions, therefore
+ this proc *always* returns an opaque color (alpha == 255). Thus it is
+ not really usefull for operating on blended colors.
+*/
+class SK_API SkPixelXorXfermode : public SkXfermode {
+public:
+ SkPixelXorXfermode(SkColor opColor) : fOpColor(opColor) {}
+
+ SK_DEVELOPER_TO_STRING()
+ SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkPixelXorXfermode)
+
+protected:
+ SkPixelXorXfermode(SkFlattenableReadBuffer& rb);
+ virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
+
+ // override from SkXfermode
+ virtual SkPMColor xferColor(SkPMColor src, SkPMColor dst) const;
+
+private:
+ SkColor fOpColor;
+
+ typedef SkXfermode INHERITED;
+};
+
+#endif
diff --git a/effects/SkPorterDuff.h b/effects/SkPorterDuff.h
new file mode 100644
index 0000000..c5f5492
--- /dev/null
+++ b/effects/SkPorterDuff.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkPorterDuff_DEFINED
+#define SkPorterDuff_DEFINED
+
+#include "SkColor.h"
+#include "SkXfermode.h"
+
+class SkXfermode;
+
+/** DEPRECATED - use SkXfermode::Mode instead
+ */
+class SK_API SkPorterDuff {
+public:
+ /** List of predefined xfermodes. In general, the algebra for the modes
+ uses the following symbols:
+ Sa, Sc - source alpha and color
+ Da, Dc - destination alpha and color (before compositing)
+ [a, c] - Resulting (alpha, color) values
+ For these equations, the colors are in premultiplied state.
+ If no xfermode is specified, kSrcOver is assumed.
+ */
+ enum Mode {
+ kClear_Mode, //!< [0, 0]
+ kSrc_Mode, //!< [Sa, Sc]
+ kDst_Mode, //!< [Da, Dc]
+ kSrcOver_Mode, //!< [Sa + Da - Sa*Da, Rc = Sc + (1 - Sa)*Dc]
+ kDstOver_Mode, //!< [Sa + Da - Sa*Da, Rc = Dc + (1 - Da)*Sc]
+ kSrcIn_Mode, //!< [Sa * Da, Sc * Da]
+ kDstIn_Mode, //!< [Sa * Da, Sa * Dc]
+ kSrcOut_Mode, //!< [Sa * (1 - Da), Sc * (1 - Da)]
+ kDstOut_Mode, //!< [Da * (1 - Sa), Dc * (1 - Sa)]
+ kSrcATop_Mode, //!< [Da, Sc * Da + (1 - Sa) * Dc]
+ kDstATop_Mode, //!< [Sa, Sa * Dc + Sc * (1 - Da)]
+ kXor_Mode, //!< [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + (1 - Sa) * Dc]
+ kDarken_Mode, //!< [Sa + Da - Sa*Da, Sc*(1 - Da) + Dc*(1 - Sa) + min(Sc, Dc)]
+ kLighten_Mode, //!< [Sa + Da - Sa*Da, Sc*(1 - Da) + Dc*(1 - Sa) + max(Sc, Dc)]
+ kModulate_Mode, //!< [Sa * Da, Sc * Dc] multiplies all components
+ kScreen_Mode, //!< [Sa + Da - Sa * Da, Sc + Dc - Sc * Dc]
+ kAdd_Mode, //!< Saturate(S + D)
+#ifdef SK_BUILD_FOR_ANDROID
+ kOverlay_Mode,
+#endif
+
+ kModeCount
+ };
+
+ /** Return an SkXfermode object for the specified mode.
+ */
+ static SkXfermode* CreateXfermode(Mode mode);
+
+ /** Return a function pointer to a routine that applies the specified
+ porter-duff transfer mode.
+ */
+ static SkXfermodeProc GetXfermodeProc(Mode mode);
+
+ /** Return a function pointer to a routine that applies the specified
+ porter-duff transfer mode and srcColor to a 16bit device color. Note,
+ if the mode+srcColor might return a non-opaque color, then there is not
+ 16bit proc, and this will return NULL.
+ */
+ static SkXfermodeProc16 GetXfermodeProc16(Mode mode, SkColor srcColor);
+
+ /** If the specified xfermode advertises itself as one of the porterduff
+ modes (via SkXfermode::Coeff), return true and if not null, set mode
+ to the corresponding porterduff mode. If it is not recognized as a one,
+ return false and ignore the mode parameter.
+ */
+ static bool IsMode(SkXfermode*, Mode* mode);
+
+ /** Return the corersponding SkXfermode::Mode
+ */
+ static SkXfermode::Mode ToXfermodeMode(Mode);
+};
+
+#endif
diff --git a/effects/SkRectShaderImageFilter.h b/effects/SkRectShaderImageFilter.h
new file mode 100644
index 0000000..a71ee42
--- /dev/null
+++ b/effects/SkRectShaderImageFilter.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkRectShaderImageFilter_DEFINED
+#define SkRectShaderImageFilter_DEFINED
+
+#include "SkImageFilter.h"
+#include "SkRect.h"
+
+class SkShader;
+
+class SK_API SkRectShaderImageFilter : public SkImageFilter {
+public:
+ /**
+ * The SkShader object will have its refcnt increased as it becomes a member of the
+ * SkRectShaderImageFilter object returned by this function. It cannot be NULL.
+ * The region parameter is used to specify on which region the shader is applied.
+ */
+ static SkRectShaderImageFilter* Create(SkShader* s, const SkRect& rect);
+ virtual ~SkRectShaderImageFilter();
+
+ SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkRectShaderImageFilter)
+
+protected:
+ SkRectShaderImageFilter(SkFlattenableReadBuffer& buffer);
+ virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
+
+ virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&,
+ SkBitmap* result, SkIPoint* loc) SK_OVERRIDE;
+
+private:
+ SkRectShaderImageFilter(SkShader* s, const SkRect& rect);
+ SkShader* fShader;
+ SkRect fRect;
+
+ typedef SkImageFilter INHERITED;
+};
+
+#endif
diff --git a/effects/SkStippleMaskFilter.h b/effects/SkStippleMaskFilter.h
new file mode 100644
index 0000000..8f6d20d
--- /dev/null
+++ b/effects/SkStippleMaskFilter.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkStippleMaskFilter_DEFINED
+#define SkStippleMaskFilter_DEFINED
+
+#include "SkMaskFilter.h"
+
+/**
+ * Simple MaskFilter that creates a screen door stipple pattern.
+ */
+class SK_API SkStippleMaskFilter : public SkMaskFilter {
+public:
+ SkStippleMaskFilter() : INHERITED() {
+ }
+
+ virtual bool filterMask(SkMask* dst, const SkMask& src,
+ const SkMatrix& matrix,
+ SkIPoint* margin) const SK_OVERRIDE;
+
+ // getFormat is from SkMaskFilter
+ virtual SkMask::Format getFormat() const SK_OVERRIDE {
+ return SkMask::kA8_Format;
+ }
+
+ SkDEVCODE(virtual void toString(SkString* str) const SK_OVERRIDE;)
+ SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkStippleMaskFilter);
+
+protected:
+ SkStippleMaskFilter(SkFlattenableReadBuffer& buffer)
+ : SkMaskFilter(buffer) {
+ }
+
+private:
+ typedef SkMaskFilter INHERITED;
+};
+
+#endif // SkStippleMaskFilter_DEFINED
diff --git a/effects/SkTableColorFilter.h b/effects/SkTableColorFilter.h
new file mode 100644
index 0000000..5714d07
--- /dev/null
+++ b/effects/SkTableColorFilter.h
@@ -0,0 +1,36 @@
+
+#ifndef SkTableColorFilter_DEFINED
+#define SkTableColorFilter_DEFINED
+
+#include "SkColorFilter.h"
+
+class SK_API SkTableColorFilter {
+public:
+ /**
+ * Create a table colorfilter, copying the table into the filter, and
+ * applying it to all 4 components.
+ * a' = table[a];
+ * r' = table[r];
+ * g' = table[g];
+ * b' = table[b];
+ * Compoents are operated on in unpremultiplied space. If the incomming
+ * colors are premultiplied, they are temporarily unpremultiplied, then
+ * the table is applied, and then the result is remultiplied.
+ */
+ static SkColorFilter* Create(const uint8_t table[256]);
+
+ /**
+ * Create a table colorfilter, with a different table for each
+ * component [A, R, G, B]. If a given table is NULL, then it is
+ * treated as identity, with the component left unchanged. If a table
+ * is not null, then its contents are copied into the filter.
+ */
+ static SkColorFilter* CreateARGB(const uint8_t tableA[256],
+ const uint8_t tableR[256],
+ const uint8_t tableG[256],
+ const uint8_t tableB[256]);
+
+ SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP()
+};
+
+#endif
diff --git a/effects/SkTableMaskFilter.h b/effects/SkTableMaskFilter.h
new file mode 100644
index 0000000..ac33266
--- /dev/null
+++ b/effects/SkTableMaskFilter.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkTableMaskFilter_DEFINED
+#define SkTableMaskFilter_DEFINED
+
+#include "SkMaskFilter.h"
+#include "SkScalar.h"
+
+/** \class SkTableMaskFilter
+
+ Applies a table lookup on each of the alpha values in the mask.
+ Helper methods create some common tables (e.g. gamma, clipping)
+ */
+class SK_API SkTableMaskFilter : public SkMaskFilter {
+public:
+ SkTableMaskFilter();
+ SkTableMaskFilter(const uint8_t table[256]);
+ virtual ~SkTableMaskFilter();
+
+ /** Utility that sets the gamma table
+ */
+ static void MakeGammaTable(uint8_t table[256], SkScalar gamma);
+
+ /** Utility that creates a clipping table: clamps values below min to 0
+ and above max to 255, and rescales the remaining into 0..255
+ */
+ static void MakeClipTable(uint8_t table[256], uint8_t min, uint8_t max);
+
+ static SkTableMaskFilter* CreateGamma(SkScalar gamma) {
+ uint8_t table[256];
+ MakeGammaTable(table, gamma);
+ return SkNEW_ARGS(SkTableMaskFilter, (table));
+ }
+
+ static SkTableMaskFilter* CreateClip(uint8_t min, uint8_t max) {
+ uint8_t table[256];
+ MakeClipTable(table, min, max);
+ return SkNEW_ARGS(SkTableMaskFilter, (table));
+ }
+
+ virtual SkMask::Format getFormat() const SK_OVERRIDE;
+ virtual bool filterMask(SkMask*, const SkMask&, const SkMatrix&,
+ SkIPoint*) const SK_OVERRIDE;
+
+ SkDEVCODE(virtual void toString(SkString* str) const SK_OVERRIDE;)
+ SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkTableMaskFilter)
+
+protected:
+ SkTableMaskFilter(SkFlattenableReadBuffer& rb);
+ virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
+
+private:
+ uint8_t fTable[256];
+
+ typedef SkMaskFilter INHERITED;
+};
+
+#endif
diff --git a/effects/SkTestImageFilters.h b/effects/SkTestImageFilters.h
new file mode 100755
index 0000000..e848ff1
--- /dev/null
+++ b/effects/SkTestImageFilters.h
@@ -0,0 +1,27 @@
+#ifndef _SkTestImageFilters_h
+#define _SkTestImageFilters_h
+
+#include "SkImageFilter.h"
+#include "SkPoint.h"
+
+// Fun mode that scales down (only) and then scales back up to look pixelated
+class SK_API SkDownSampleImageFilter : public SkImageFilter {
+public:
+ SkDownSampleImageFilter(SkScalar scale) : INHERITED(0), fScale(scale) {}
+
+ SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDownSampleImageFilter)
+
+protected:
+ SkDownSampleImageFilter(SkFlattenableReadBuffer& buffer);
+ virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
+
+ virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&,
+ SkBitmap* result, SkIPoint* loc) SK_OVERRIDE;
+
+private:
+ SkScalar fScale;
+
+ typedef SkImageFilter INHERITED;
+};
+
+#endif
diff --git a/effects/SkTransparentShader.h b/effects/SkTransparentShader.h
new file mode 100644
index 0000000..bee9a02
--- /dev/null
+++ b/effects/SkTransparentShader.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkTransparentShader_DEFINED
+#define SkTransparentShader_DEFINED
+
+#include "SkShader.h"
+
+class SK_API SkTransparentShader : public SkShader {
+public:
+ SkTransparentShader() {}
+
+ virtual uint32_t getFlags() SK_OVERRIDE;
+ virtual bool setContext(const SkBitmap& device,
+ const SkPaint& paint,
+ const SkMatrix& matrix) SK_OVERRIDE;
+ virtual void shadeSpan(int x, int y, SkPMColor[], int count) SK_OVERRIDE;
+ virtual void shadeSpan16(int x, int y, uint16_t span[], int count) SK_OVERRIDE;
+
+ SK_DEVELOPER_TO_STRING()
+ SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkTransparentShader)
+
+private:
+ // these are a cache from the call to setContext()
+ const SkBitmap* fDevice;
+ uint8_t fAlpha;
+
+ SkTransparentShader(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {}
+
+ typedef SkShader INHERITED;
+};
+
+#endif
diff --git a/effects/SkXfermodeImageFilter.h b/effects/SkXfermodeImageFilter.h
new file mode 100644
index 0000000..89a2773
--- /dev/null
+++ b/effects/SkXfermodeImageFilter.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2013 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkXfermodeImageFilter_DEFINED
+#define SkXfermodeImageFilter_DEFINED
+
+#include "SkImageFilter.h"
+
+class SkBitmap;
+class SkXfermode;
+
+class SK_API SkXfermodeImageFilter : public SkImageFilter {
+ /**
+ * This filter takes an xfermode, and uses it to composite the foreground
+ * over the background. If foreground or background is NULL, the input
+ * bitmap (src) is used instead.
+ */
+
+public:
+ SkXfermodeImageFilter(SkXfermode* mode, SkImageFilter* background,
+ SkImageFilter* foreground = NULL);
+
+ virtual ~SkXfermodeImageFilter();
+
+ SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkXfermodeImageFilter)
+
+ virtual bool onFilterImage(Proxy* proxy,
+ const SkBitmap& src,
+ const SkMatrix& ctm,
+ SkBitmap* dst,
+ SkIPoint* offset) SK_OVERRIDE;
+#if SK_SUPPORT_GPU
+ virtual bool canFilterImageGPU() const SK_OVERRIDE { return true; }
+ virtual bool filterImageGPU(Proxy* proxy, const SkBitmap& src, const SkMatrix& ctm,
+ SkBitmap* result, SkIPoint* offset) SK_OVERRIDE;
+#endif
+
+protected:
+ explicit SkXfermodeImageFilter(SkFlattenableReadBuffer& buffer);
+ virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
+
+private:
+ SkXfermode* fMode;
+ typedef SkImageFilter INHERITED;
+};
+
+#endif
diff --git a/gpu/GrAARectRenderer.h b/gpu/GrAARectRenderer.h
new file mode 100644
index 0000000..607329a
--- /dev/null
+++ b/gpu/GrAARectRenderer.h
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef GrAARectRenderer_DEFINED
+#define GrAARectRenderer_DEFINED
+
+#include "GrRefCnt.h"
+#include "SkMatrix.h"
+#include "SkRect.h"
+
+class GrGpu;
+class GrDrawTarget;
+class GrIndexBuffer;
+
+/*
+ * This class wraps helper functions that draw AA rects (filled & stroked)
+ */
+class GrAARectRenderer : public GrRefCnt {
+public:
+ SK_DECLARE_INST_COUNT(GrAARectRenderer)
+
+ GrAARectRenderer()
+ : fAAFillRectIndexBuffer(NULL)
+ , fAAStrokeRectIndexBuffer(NULL) {
+ }
+
+ void reset();
+
+ ~GrAARectRenderer() {
+ this->reset();
+ }
+
+ // TODO: potentialy fuse the fill & stroke methods and differentiate
+ // between them by passing in strokeWidth (<0 means fill).
+
+ void fillAARect(GrGpu* gpu,
+ GrDrawTarget* target,
+ const SkRect& rect,
+ const SkMatrix& combinedMatrix,
+ const SkRect& devRect,
+ bool useVertexCoverage) {
+#ifdef SHADER_AA_FILL_RECT
+ if (combinedMatrix.rectStaysRect()) {
+ this->shaderFillAlignedAARect(gpu, target,
+ rect, combinedMatrix);
+ } else {
+ this->shaderFillAARect(gpu, target,
+ rect, combinedMatrix);
+ }
+#else
+ this->geometryFillAARect(gpu, target,
+ rect, combinedMatrix,
+ devRect, useVertexCoverage);
+#endif
+ }
+
+ void strokeAARect(GrGpu* gpu,
+ GrDrawTarget* target,
+ const SkRect& rect,
+ const SkMatrix& combinedMatrix,
+ const SkRect& devRect,
+ SkScalar width,
+ bool useVertexCoverage);
+
+ // First rect is outer; second rect is inner
+ void fillAANestedRects(GrGpu* gpu,
+ GrDrawTarget* target,
+ const SkRect rects[2],
+ const SkMatrix& combinedMatrix,
+ bool useVertexCoverage);
+
+private:
+ GrIndexBuffer* fAAFillRectIndexBuffer;
+ GrIndexBuffer* fAAStrokeRectIndexBuffer;
+
+ GrIndexBuffer* aaFillRectIndexBuffer(GrGpu* gpu);
+
+ static int aaStrokeRectIndexCount();
+ GrIndexBuffer* aaStrokeRectIndexBuffer(GrGpu* gpu);
+
+ // TODO: Remove the useVertexCoverage boolean. Just use it all the time
+ // since we now have a coverage vertex attribute
+ void geometryFillAARect(GrGpu* gpu,
+ GrDrawTarget* target,
+ const SkRect& rect,
+ const SkMatrix& combinedMatrix,
+ const SkRect& devRect,
+ bool useVertexCoverage);
+
+ void shaderFillAARect(GrGpu* gpu,
+ GrDrawTarget* target,
+ const SkRect& rect,
+ const SkMatrix& combinedMatrix);
+
+ void shaderFillAlignedAARect(GrGpu* gpu,
+ GrDrawTarget* target,
+ const SkRect& rect,
+ const SkMatrix& combinedMatrix);
+
+ void geometryStrokeAARect(GrGpu* gpu,
+ GrDrawTarget* target,
+ const SkRect& devOutside,
+ const SkRect& devInside,
+ bool useVertexCoverage);
+
+ typedef GrRefCnt INHERITED;
+};
+
+#endif // GrAARectRenderer_DEFINED
diff --git a/gpu/GrBackendEffectFactory.h b/gpu/GrBackendEffectFactory.h
new file mode 100644
index 0000000..2811443
--- /dev/null
+++ b/gpu/GrBackendEffectFactory.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrBackendEffectFactory_DEFINED
+#define GrBackendEffectFactory_DEFINED
+
+#include "GrTypes.h"
+#include "SkTemplates.h"
+#include "SkThread_platform.h"
+#include "GrNoncopyable.h"
+
+/** Given a GrEffect of a particular type, creates the corresponding graphics-backend-specific
+ effect object. Also tracks equivalence of shaders generated via a key. Each factory instance
+ is assigned a generation ID at construction. The ID of the return of GrEffect::getFactory()
+ is used as a type identifier. Thus a GrEffect subclass must return a singleton from
+ getFactory(). GrEffect subclasses should use the derived class GrTBackendEffectFactory that is
+ templated on the GrEffect subclass as their factory object. It requires that the GrEffect
+ subclass has a nested class (or typedef) GLEffect which is its GL implementation and a subclass
+ of GrGLEffect.
+ */
+
+class GrEffectRef;
+class GrGLEffect;
+class GrGLCaps;
+class GrDrawEffect;
+
+class GrBackendEffectFactory : public GrNoncopyable {
+public:
+ typedef uint32_t EffectKey;
+ enum {
+ kNoEffectKey = 0,
+ kEffectKeyBits = 15,
+ /**
+ * Some aspects of the generated code may be determined by the particular textures that are
+ * associated with the effect. These manipulations are performed by GrGLShaderBuilder beyond
+ * GrGLEffects' control. So there is a dedicated part of the key which is combined
+ * automatically with the bits produced by GrGLEffect::GenKey().
+ */
+ kTextureKeyBits = 6,
+ kAttribKeyBits = 6
+ };
+
+ virtual EffectKey glEffectKey(const GrDrawEffect&, const GrGLCaps&) const = 0;
+ virtual GrGLEffect* createGLInstance(const GrDrawEffect&) const = 0;
+
+ bool operator ==(const GrBackendEffectFactory& b) const {
+ return fEffectClassID == b.fEffectClassID;
+ }
+ bool operator !=(const GrBackendEffectFactory& b) const {
+ return !(*this == b);
+ }
+
+ virtual const char* name() const = 0;
+
+protected:
+ enum {
+ kIllegalEffectClassID = 0,
+ };
+
+ GrBackendEffectFactory() {
+ fEffectClassID = kIllegalEffectClassID;
+ }
+ virtual ~GrBackendEffectFactory() {}
+
+ static EffectKey GenID() {
+ GR_DEBUGCODE(static const int32_t kClassIDBits = 8 * sizeof(EffectKey) -
+ kTextureKeyBits - kEffectKeyBits - kAttribKeyBits);
+ // fCurrEffectClassID has been initialized to kIllegalEffectClassID. The
+ // atomic inc returns the old value not the incremented value. So we add
+ // 1 to the returned value.
+ int32_t id = sk_atomic_inc(&fCurrEffectClassID) + 1;
+ GrAssert(id < (1 << kClassIDBits));
+ return static_cast<EffectKey>(id);
+ }
+
+ EffectKey fEffectClassID;
+
+private:
+ static int32_t fCurrEffectClassID;
+};
+
+#endif
diff --git a/gpu/GrClipData.h b/gpu/GrClipData.h
new file mode 100644
index 0000000..bced741
--- /dev/null
+++ b/gpu/GrClipData.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrClip_DEFINED
+#define GrClip_DEFINED
+
+#include "SkClipStack.h"
+
+class GrSurface;
+struct SkIRect;
+
+/**
+ * GrClipData encapsulates the information required to construct the clip
+ * masks. 'fOrigin' is only non-zero when saveLayer has been called
+ * with an offset bounding box. The clips in 'fClipStack' are in
+ * device coordinates (i.e., they have been translated by -fOrigin w.r.t.
+ * the canvas' device coordinates).
+ */
+class GrClipData : public SkNoncopyable {
+public:
+ const SkClipStack* fClipStack;
+ SkIPoint fOrigin;
+
+ GrClipData()
+ : fClipStack(NULL) {
+ fOrigin.setZero();
+ }
+
+ bool operator==(const GrClipData& other) const {
+ if (fOrigin != other.fOrigin) {
+ return false;
+ }
+
+ if (NULL != fClipStack && NULL != other.fClipStack) {
+ return *fClipStack == *other.fClipStack;
+ }
+
+ return fClipStack == other.fClipStack;
+ }
+
+ bool operator!=(const GrClipData& other) const {
+ return !(*this == other);
+ }
+
+ void getConservativeBounds(const GrSurface* surface,
+ SkIRect* devResult,
+ bool* isIntersectionOfRects = NULL) const;
+};
+
+#endif
diff --git a/gpu/GrColor.h b/gpu/GrColor.h
new file mode 100644
index 0000000..3ded8fb
--- /dev/null
+++ b/gpu/GrColor.h
@@ -0,0 +1,127 @@
+
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+
+#ifndef GrColor_DEFINED
+#define GrColor_DEFINED
+
+#include "GrTypes.h"
+
+/**
+ * GrColor is 4 bytes for R, G, B, A, in a compile-time specific order. The
+ * components are stored premultiplied.
+ */
+typedef uint32_t GrColor;
+
+
+// shift amount to assign a component to a GrColor int
+// These shift values are chosen for compatibility with GL attrib arrays
+// ES doesn't allow BGRA vertex attrib order so if they were not in this order
+// we'd have to swizzle in shaders. Note the assumption that the cpu is little
+// endian.
+#define GrColor_SHIFT_R 0
+#define GrColor_SHIFT_G 8
+#define GrColor_SHIFT_B 16
+#define GrColor_SHIFT_A 24
+
+/**
+ * Pack 4 components (RGBA) into a GrColor int
+ */
+static inline GrColor GrColorPackRGBA(unsigned r, unsigned g,
+ unsigned b, unsigned a) {
+ GrAssert((uint8_t)r == r);
+ GrAssert((uint8_t)g == g);
+ GrAssert((uint8_t)b == b);
+ GrAssert((uint8_t)a == a);
+ return (r << GrColor_SHIFT_R) |
+ (g << GrColor_SHIFT_G) |
+ (b << GrColor_SHIFT_B) |
+ (a << GrColor_SHIFT_A);
+}
+
+// extract a component (byte) from a GrColor int
+
+#define GrColorUnpackR(color) (((color) >> GrColor_SHIFT_R) & 0xFF)
+#define GrColorUnpackG(color) (((color) >> GrColor_SHIFT_G) & 0xFF)
+#define GrColorUnpackB(color) (((color) >> GrColor_SHIFT_B) & 0xFF)
+#define GrColorUnpackA(color) (((color) >> GrColor_SHIFT_A) & 0xFF)
+
+/**
+ * Since premultiplied means that alpha >= color, we construct a color with
+ * each component==255 and alpha == 0 to be "illegal"
+ */
+#define GrColor_ILLEGAL (~(0xFF << GrColor_SHIFT_A))
+
+/** Converts a GrColor to an rgba array of GrGLfloat */
+static inline void GrColorToRGBAFloat(GrColor color, float rgba[4]) {
+ static const float ONE_OVER_255 = 1.f / 255.f;
+ rgba[0] = GrColorUnpackR(color) * ONE_OVER_255;
+ rgba[1] = GrColorUnpackG(color) * ONE_OVER_255;
+ rgba[2] = GrColorUnpackB(color) * ONE_OVER_255;
+ rgba[3] = GrColorUnpackA(color) * ONE_OVER_255;
+}
+
+/**
+ * Flags used for bitfields of color components. They are defined so that the bit order reflects the
+ * GrColor shift order.
+ */
+enum GrColorComponentFlags {
+ kR_GrColorComponentFlag = 1 << (GrColor_SHIFT_R / 8),
+ kG_GrColorComponentFlag = 1 << (GrColor_SHIFT_G / 8),
+ kB_GrColorComponentFlag = 1 << (GrColor_SHIFT_B / 8),
+ kA_GrColorComponentFlag = 1 << (GrColor_SHIFT_A / 8),
+
+ kRGB_GrColorComponentFlags = (kR_GrColorComponentFlag | kG_GrColorComponentFlag |
+ kB_GrColorComponentFlag),
+
+ kRGBA_GrColorComponentFlags = (kR_GrColorComponentFlag | kG_GrColorComponentFlag |
+ kB_GrColorComponentFlag | kA_GrColorComponentFlag)
+};
+
+static inline char GrColorComponentFlagToChar(GrColorComponentFlags component) {
+ GrAssert(GrIsPow2(component));
+ switch (component) {
+ case kR_GrColorComponentFlag:
+ return 'r';
+ case kG_GrColorComponentFlag:
+ return 'g';
+ case kB_GrColorComponentFlag:
+ return 'b';
+ case kA_GrColorComponentFlag:
+ return 'a';
+ default:
+ GrCrash("Invalid color component flag.");
+ return '\0';
+ }
+}
+
+static inline uint32_t GrPixelConfigComponentMask(GrPixelConfig config) {
+ GrAssert(config >= 0 && config < kGrPixelConfigCnt);
+ static const uint32_t kFlags[] = {
+ 0, // kUnknown_GrPixelConfig
+ kA_GrColorComponentFlag, // kAlpha_8_GrPixelConfig
+ kRGBA_GrColorComponentFlags, // kIndex_8_GrPixelConfig
+ kRGB_GrColorComponentFlags, // kRGB_565_GrPixelConfig
+ kRGBA_GrColorComponentFlags, // kRGBA_4444_GrPixelConfig
+ kRGBA_GrColorComponentFlags, // kRGBA_8888_GrPixelConfig
+ kRGBA_GrColorComponentFlags, // kBGRA_8888_GrPixelConfig
+ };
+ return kFlags[config];
+
+ GR_STATIC_ASSERT(0 == kUnknown_GrPixelConfig);
+ GR_STATIC_ASSERT(1 == kAlpha_8_GrPixelConfig);
+ GR_STATIC_ASSERT(2 == kIndex_8_GrPixelConfig);
+ GR_STATIC_ASSERT(3 == kRGB_565_GrPixelConfig);
+ GR_STATIC_ASSERT(4 == kRGBA_4444_GrPixelConfig);
+ GR_STATIC_ASSERT(5 == kRGBA_8888_GrPixelConfig);
+ GR_STATIC_ASSERT(6 == kBGRA_8888_GrPixelConfig);
+ GR_STATIC_ASSERT(SK_ARRAY_COUNT(kFlags) == kGrPixelConfigCnt);
+}
+
+#endif
diff --git a/gpu/GrConfig.h b/gpu/GrConfig.h
new file mode 100644
index 0000000..95e518a
--- /dev/null
+++ b/gpu/GrConfig.h
@@ -0,0 +1,387 @@
+
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+
+#ifndef GrConfig_DEFINED
+#define GrConfig_DEFINED
+
+#include "SkTypes.h"
+
+///////////////////////////////////////////////////////////////////////////////
+// preconfig section:
+//
+// All the work before including GrUserConfig.h should center around guessing
+// what platform we're on, and defining low-level symbols based on that.
+//
+// A build environment may have already defined symbols, so we first check
+// for that
+//
+
+// hack to ensure we know what sort of Apple platform we're on
+#if defined(__APPLE_CPP__) || defined(__APPLE_CC__)
+ #include <TargetConditionals.h>
+#endif
+
+/**
+ * Gr defines are set to 0 or 1, rather than being undefined or defined
+ */
+
+#if !defined(GR_ANDROID_BUILD)
+ #define GR_ANDROID_BUILD 0
+#endif
+#if !defined(GR_IOS_BUILD)
+ #define GR_IOS_BUILD 0
+#endif
+#if !defined(GR_LINUX_BUILD)
+ #define GR_LINUX_BUILD 0
+#endif
+#if !defined(GR_MAC_BUILD)
+ #define GR_MAC_BUILD 0
+#endif
+#if !defined(GR_WIN32_BUILD)
+ #define GR_WIN32_BUILD 0
+#endif
+#if !defined(GR_QNX_BUILD)
+ #define GR_QNX_BUILD 0
+#endif
+#if !defined(GR_CACHE_STATS)
+ #define GR_CACHE_STATS 0
+#endif
+
+/**
+ * If no build target has been defined, attempt to infer.
+ */
+#if !GR_ANDROID_BUILD && !GR_IOS_BUILD && !GR_LINUX_BUILD && !GR_MAC_BUILD && !GR_WIN32_BUILD && !GR_QNX_BUILD
+ #if defined(_WIN32)
+ #undef GR_WIN32_BUILD
+ #define GR_WIN32_BUILD 1
+// #error "WIN"
+ #elif TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR
+ #undef GR_IOS_BUILD
+ #define GR_IOS_BUILD 1
+// #error "IOS"
+ #elif defined(SK_BUILD_FOR_ANDROID)
+ #undef GR_ANDROID_BUILD
+ #define GR_ANDROID_BUILD 1
+// #error "ANDROID"
+ #elif TARGET_OS_MAC
+ #undef GR_MAC_BUILD
+ #define GR_MAC_BUILD 1
+// #error "MAC"
+ #elif TARGET_OS_QNX || defined(__QNXNTO__)
+ #undef GR_QNX_BUILD
+ #define GR_QNX_BUILD 1
+// #error "QNX"
+ #else
+ #undef GR_LINUX_BUILD
+ #define GR_LINUX_BUILD 1
+// #error "LINUX"
+ #endif
+#endif
+
+// we need both GR_DEBUG and GR_RELEASE to be defined as 0 or 1
+//
+#ifndef GR_DEBUG
+ #ifdef GR_RELEASE
+ #define GR_DEBUG !GR_RELEASE
+ #else
+ #ifdef NDEBUG
+ #define GR_DEBUG 0
+ #else
+ #define GR_DEBUG 1
+ #endif
+ #endif
+#endif
+
+#ifndef GR_RELEASE
+ #define GR_RELEASE !GR_DEBUG
+#endif
+
+#if GR_DEBUG == GR_RELEASE
+ #error "GR_DEBUG and GR_RELEASE must not be the same"
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+#if GR_WIN32_BUILD
+// VC8 doesn't support stdint.h, so we define those types here.
+typedef signed char int8_t;
+typedef unsigned char uint8_t;
+typedef short int16_t;
+typedef unsigned short uint16_t;
+typedef int int32_t;
+typedef unsigned uint32_t;
+typedef __int64 int64_t;
+typedef unsigned __int64 uint64_t;
+#else
+/*
+ * Include stdint.h with defines that trigger declaration of C99 limit/const
+ * macros here before anyone else has a chance to include stdint.h without
+ * these.
+ */
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS
+#endif
+#ifndef __STDC_CONSTANT_MACROS
+#define __STDC_CONSTANT_MACROS
+#endif
+#include <stdint.h>
+#endif
+
+/*
+ * The "user config" file can be empty, and everything should work. It is
+ * meant to store a given platform/client's overrides of our guess-work.
+ *
+ * A alternate user config file can be specified by defining
+ * GR_USER_CONFIG_FILE. It should be defined relative to GrConfig.h
+ *
+ * e.g. it can specify GR_DEBUG/GR_RELEASE as it please, change the BUILD
+ * target, or supply its own defines for anything else (e.g. GR_DEFAULT_TEXTURE_CACHE_MB_LIMIT)
+ */
+#if !defined(GR_USER_CONFIG_FILE)
+ #include "GrUserConfig.h"
+#else
+ #include GR_USER_CONFIG_FILE
+#endif
+
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+// postconfig section:
+//
+
+// GR_IMPLEMENTATION should be define to 1 when building Gr and 0 when including
+// it in another dependent build. The Gr makefile/ide-project should define this
+// to 1.
+#if !defined(GR_IMPLEMENTATION)
+ #define GR_IMPLEMENTATION 0
+#endif
+
+// If Gr is built as a shared library then GR_DLL should be defined to 1 (both
+// when building Gr and when including its headers in dependent builds). Only
+// currently supported minimally for Chrome's Win32 Multi-DLL build (TODO:
+// correctly exort all of the public API correctly and support shared lib on
+// other platforms).
+#if !defined(GR_DLL)
+ #define GR_DLL 0
+#endif
+
+#if GR_DLL
+ #if GR_WIN32_BUILD
+ #if GR_IMPLEMENTATION
+ #define GR_API __declspec(dllexport)
+ #else
+ #define GR_API __declspec(dllimport)
+ #endif
+ #else
+ #define GR_API __attribute__((visibility("default")))
+ #endif
+#else
+ #define GR_API
+#endif
+
+// By now we must have a GR_..._BUILD symbol set to 1, and a decision about
+// debug -vs- release
+//
+
+#define GrPrintf SkDebugf
+
+/**
+ * GR_STRING makes a string of X where X is expanded before conversion to a string
+ * if X itself contains macros.
+ */
+#define GR_STRING(X) GR_STRING_IMPL(X)
+#define GR_STRING_IMPL(X) #X
+
+/**
+ * GR_CONCAT concatenates X and Y where each is expanded before
+ * contanenation if either contains macros.
+ */
+#define GR_CONCAT(X,Y) GR_CONCAT_IMPL(X,Y)
+#define GR_CONCAT_IMPL(X,Y) X##Y
+
+/**
+ * Creates a string of the form "<filename>(<linenumber>) : "
+ */
+#define GR_FILE_AND_LINE_STR __FILE__ "(" GR_STRING(__LINE__) ") : "
+
+/**
+ * Compilers have different ways of issuing warnings. This macro
+ * attempts to abstract them, but may need to be specialized for your
+ * particular compiler.
+ * To insert compiler warnings use "#pragma message GR_WARN(<string>)"
+ */
+#if defined(_MSC_VER) && _MSC_VER
+ #define GR_WARN(MSG) (GR_FILE_AND_LINE_STR "WARNING: " MSG)
+#else//__GNUC__ - may need other defines for different compilers
+ #define GR_WARN(MSG) ("WARNING: " MSG)
+#endif
+
+/**
+ * GR_ALWAYSBREAK is an unconditional break in all builds.
+ */
+#if !defined(GR_ALWAYSBREAK)
+ #if GR_WIN32_BUILD
+ #define GR_ALWAYSBREAK SkNO_RETURN_HINT(); __debugbreak()
+ #else
+ // TODO: do other platforms really not have continuable breakpoints?
+ // sign extend for 64bit architectures to be sure this is
+ // in the high address range
+ #define GR_ALWAYSBREAK SkNO_RETURN_HINT(); *((int*)(int64_t)(int32_t)0xbeefcafe) = 0;
+ #endif
+#endif
+
+/**
+ * GR_DEBUGBREAK is an unconditional break in debug builds.
+ */
+#if !defined(GR_DEBUGBREAK)
+ #if GR_DEBUG
+ #define GR_DEBUGBREAK GR_ALWAYSBREAK
+ #else
+ #define GR_DEBUGBREAK
+ #endif
+#endif
+
+/**
+ * GR_ALWAYSASSERT is an assertion in all builds.
+ */
+#if !defined(GR_ALWAYSASSERT)
+ #define GR_ALWAYSASSERT(COND) \
+ do { \
+ if (!(COND)) { \
+ GrPrintf("%s %s failed\n", GR_FILE_AND_LINE_STR, #COND); \
+ GR_ALWAYSBREAK; \
+ } \
+ } while (false)
+#endif
+
+/**
+ * GR_DEBUGASSERT is an assertion in debug builds only.
+ */
+#if !defined(GR_DEBUGASSERT)
+ #if GR_DEBUG
+ #define GR_DEBUGASSERT(COND) GR_ALWAYSASSERT(COND)
+ #else
+ #define GR_DEBUGASSERT(COND)
+ #endif
+#endif
+
+/**
+ * Prettier forms of the above macros.
+ */
+#define GrAssert(COND) GR_DEBUGASSERT(COND)
+#define GrAlwaysAssert(COND) GR_ALWAYSASSERT(COND)
+
+/**
+ * Crash from unrecoverable condition, optionally with a message. The debug variants only
+ * crash in a debug build. The message versions print the message regardless of release vs debug.
+ */
+inline void GrCrash() { GrAlwaysAssert(false); }
+inline void GrCrash(const char* msg) { GrPrintf(msg); GrAlwaysAssert(false); }
+inline void GrDebugCrash() { GrAssert(false); }
+inline void GrDebugCrash(const char* msg) { GrPrintf(msg); GrAssert(false); }
+
+/**
+ * GR_DEBUGCODE compiles the code X in debug builds only
+ */
+#if !defined(GR_DEBUGCODE)
+ #if GR_DEBUG
+ #define GR_DEBUGCODE(X) X
+ #else
+ #define GR_DEBUGCODE(X)
+ #endif
+#endif
+
+/**
+ * GR_STATIC_ASSERT is a compile time assertion. Depending on the platform
+ * it may print the message in the compiler log. Obviously, the condition must
+ * be evaluatable at compile time.
+ */
+// VS 2010 and GCC compiled with c++0x or gnu++0x support the new
+// static_assert.
+#if !defined(GR_STATIC_ASSERT)
+ #if (defined(_MSC_VER) && _MSC_VER >= 1600) || (defined(__GXX_EXPERIMENTAL_CXX0X__) && __GXX_EXPERIMENTAL_CXX0X__)
+ #define GR_STATIC_ASSERT(CONDITION) static_assert(CONDITION, "bug")
+ #else
+ template <bool> class GR_STATIC_ASSERT_FAILURE;
+ template <> class GR_STATIC_ASSERT_FAILURE<true> {};
+ #define GR_STATIC_ASSERT(CONDITION) \
+ enum {GR_CONCAT(X,__LINE__) = \
+ sizeof(GR_STATIC_ASSERT_FAILURE<CONDITION>)}
+ #endif
+#endif
+
+/**
+ * GR_GEOM_BUFFER_LOCK_THRESHOLD gives a threshold (in bytes) for when Gr should
+ * lock a GrGeometryBuffer to update its contents. It will use lock() if the
+ * size of the updated region is greater than the threshold. Otherwise it will
+ * use updateData().
+ */
+#if !defined(GR_GEOM_BUFFER_LOCK_THRESHOLD)
+ #define GR_GEOM_BUFFER_LOCK_THRESHOLD (1 << 15)
+#endif
+
+/**
+ * GR_DEFAULT_TEXTURE_CACHE_MB_LIMIT gives a threshold (in megabytes) for the
+ * maximum size of the texture cache in vram. The value is only a default and
+ * can be overridden at runtime.
+ */
+#if !defined(GR_DEFAULT_TEXTURE_CACHE_MB_LIMIT)
+ #define GR_DEFAULT_TEXTURE_CACHE_MB_LIMIT 96
+#endif
+
+/**
+ * GR_STROKE_PATH_RENDERING controls whether or not the GrStrokePathRenderer can be selected
+ * as a path renderer. GrStrokePathRenderer is currently an experimental path renderer.
+ */
+#if !defined(GR_STROKE_PATH_RENDERING)
+ #define GR_STROKE_PATH_RENDERING 0
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// tail section:
+//
+// Now we just assert if we are missing some required define, or if we detect
+// and inconsistent combination of defines
+//
+
+
+/**
+ * Only one build target macro should be 1 and the rest should be 0.
+ */
+#define GR_BUILD_SUM (GR_WIN32_BUILD + GR_MAC_BUILD + GR_IOS_BUILD + GR_ANDROID_BUILD + GR_LINUX_BUILD + GR_QNX_BUILD)
+#if 0 == GR_BUILD_SUM
+ #error "Missing a GR_BUILD define"
+#elif 1 != GR_BUILD_SUM
+ #error "More than one GR_BUILD defined"
+#endif
+
+#if 0
+#if GR_WIN32_BUILD
+// #pragma message GR_WARN("GR_WIN32_BUILD")
+#endif
+#if GR_MAC_BUILD
+// #pragma message GR_WARN("GR_MAC_BUILD")
+#endif
+#if GR_IOS_BUILD
+// #pragma message GR_WARN("GR_IOS_BUILD")
+#endif
+#if GR_ANDROID_BUILD
+// #pragma message GR_WARN("GR_ANDROID_BUILD")
+#endif
+#if GR_LINUX_BUILD
+// #pragma message GR_WARN("GR_LINUX_BUILD")
+#endif
+#if GR_QNX_BUILD
+// #pragma message GR_WARN("GR_QNX_BUILD")
+#endif
+#endif
+
+#endif
diff --git a/gpu/GrContext.h b/gpu/GrContext.h
new file mode 100644
index 0000000..ced251b
--- /dev/null
+++ b/gpu/GrContext.h
@@ -0,0 +1,1021 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrContext_DEFINED
+#define GrContext_DEFINED
+
+#include "GrColor.h"
+#include "GrAARectRenderer.h"
+#include "GrClipData.h"
+#include "SkMatrix.h"
+#include "GrPaint.h"
+#include "GrPathRendererChain.h"
+#include "GrPoint.h"
+#include "GrRenderTarget.h"
+#include "GrRefCnt.h"
+#include "GrTexture.h"
+
+class GrAutoScratchTexture;
+class GrDrawState;
+class GrDrawTarget;
+class GrEffect;
+class GrFontCache;
+class GrGpu;
+class GrIndexBuffer;
+class GrIndexBufferAllocPool;
+class GrInOrderDrawBuffer;
+class GrOvalRenderer;
+class GrPathRenderer;
+class GrResourceEntry;
+class GrResourceCache;
+class GrStencilBuffer;
+class GrTextureParams;
+class GrVertexBuffer;
+class GrVertexBufferAllocPool;
+class GrSoftwarePathRenderer;
+class SkStrokeRec;
+
+class GR_API GrContext : public GrRefCnt {
+public:
+ SK_DECLARE_INST_COUNT(GrContext)
+
+ /**
+ * Creates a GrContext for a backend context.
+ */
+ static GrContext* Create(GrBackend, GrBackendContext);
+
+ /**
+ * Returns the number of GrContext instances for the current thread.
+ */
+ static int GetThreadInstanceCount();
+
+ virtual ~GrContext();
+
+ /**
+ * The GrContext normally assumes that no outsider is setting state
+ * within the underlying 3D API's context/device/whatever. This call informs
+ * the context that the state was modified and it should resend. Shouldn't
+ * be called frequently for good performance.
+ * The flag bits, state, is dpendent on which backend is used by the
+ * context, either GL or D3D (possible in future).
+ */
+ void resetContext(uint32_t state = kAll_GrBackendState);
+
+ /**
+ * Callback function to allow classes to cleanup on GrContext destruction.
+ * The 'info' field is filled in with the 'info' passed to addCleanUp.
+ */
+ typedef void (*PFCleanUpFunc)(const GrContext* context, void* info);
+
+ /**
+ * Add a function to be called from within GrContext's destructor.
+ * This gives classes a chance to free resources held on a per context basis.
+ * The 'info' parameter will be stored and passed to the callback function.
+ */
+ void addCleanUp(PFCleanUpFunc cleanUp, void* info) {
+ CleanUpData* entry = fCleanUpData.push();
+
+ entry->fFunc = cleanUp;
+ entry->fInfo = info;
+ }
+
+ /**
+ * Abandons all GPU resources, assumes 3D API state is unknown. Call this
+ * if you have lost the associated GPU context, and thus internal texture,
+ * buffer, etc. references/IDs are now invalid. Should be called even when
+ * GrContext is no longer going to be used for two reasons:
+ * 1) ~GrContext will not try to free the objects in the 3D API.
+ * 2) If you've created GrResources that outlive the GrContext they will
+ * be marked as invalid (GrResource::isValid()) and won't attempt to
+ * free their underlying resource in the 3D API.
+ * Content drawn since the last GrContext::flush() may be lost.
+ */
+ void contextLost();
+
+ /**
+ * Similar to contextLost, but makes no attempt to reset state.
+ * Use this method when GrContext destruction is pending, but
+ * the graphics context is destroyed first.
+ */
+ void contextDestroyed();
+
+ /**
+ * Frees GPU created by the context. Can be called to reduce GPU memory
+ * pressure.
+ */
+ void freeGpuResources();
+
+ /**
+ * Returns the number of bytes of GPU memory hosted by the texture cache.
+ */
+ size_t getGpuTextureCacheBytes() const;
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Textures
+
+ /**
+ * Creates a new entry, based on the specified key and texture and returns it. The caller owns a
+ * ref on the returned texture which must be balanced by a call to unref.
+ *
+ * @param params The texture params used to draw a texture may help determine
+ * the cache entry used. (e.g. different versions may exist
+ * for different wrap modes on GPUs with limited NPOT
+ * texture support). NULL implies clamp wrap modes.
+ * @param desc Description of the texture properties.
+ * @param cacheID Cache-specific properties (e.g., texture gen ID)
+ * @param srcData Pointer to the pixel values.
+ * @param rowBytes The number of bytes between rows of the texture. Zero
+ * implies tightly packed rows.
+ */
+ GrTexture* createTexture(const GrTextureParams* params,
+ const GrTextureDesc& desc,
+ const GrCacheID& cacheID,
+ void* srcData, size_t rowBytes);
+
+ /**
+ * Search for an entry based on key and dimensions. If found, ref it and return it. The return
+ * value will be NULL if not found. The caller must balance with a call to unref.
+ *
+ * @param desc Description of the texture properties.
+ * @param cacheID Cache-specific properties (e.g., texture gen ID)
+ * @param params The texture params used to draw a texture may help determine
+ * the cache entry used. (e.g. different versions may exist
+ * for different wrap modes on GPUs with limited NPOT
+ * texture support). NULL implies clamp wrap modes.
+ */
+ GrTexture* findAndRefTexture(const GrTextureDesc& desc,
+ const GrCacheID& cacheID,
+ const GrTextureParams* params);
+ /**
+ * Determines whether a texture is in the cache. If the texture is found it
+ * will not be locked or returned. This call does not affect the priority of
+ * the texture for deletion.
+ */
+ bool isTextureInCache(const GrTextureDesc& desc,
+ const GrCacheID& cacheID,
+ const GrTextureParams* params) const;
+
+ /**
+ * Enum that determines how closely a returned scratch texture must match
+ * a provided GrTextureDesc.
+ */
+ enum ScratchTexMatch {
+ /**
+ * Finds a texture that exactly matches the descriptor.
+ */
+ kExact_ScratchTexMatch,
+ /**
+ * Finds a texture that approximately matches the descriptor. Will be
+ * at least as large in width and height as desc specifies. If desc
+ * specifies that texture is a render target then result will be a
+ * render target. If desc specifies a render target and doesn't set the
+ * no stencil flag then result will have a stencil. Format and aa level
+ * will always match.
+ */
+ kApprox_ScratchTexMatch
+ };
+
+ /**
+ * Returns a texture matching the desc. It's contents are unknown. Subsequent
+ * requests with the same descriptor are not guaranteed to return the same
+ * texture. The same texture is guaranteed not be returned again until it is
+ * unlocked. Call must be balanced with an unlockTexture() call. The caller
+ * owns a ref on the returned texture and must balance with a call to unref.
+ *
+ * Textures created by createAndLockTexture() hide the complications of
+ * tiling non-power-of-two textures on APIs that don't support this (e.g.
+ * unextended GLES2). Tiling a NPOT texture created by lockScratchTexture on
+ * such an API will create gaps in the tiling pattern. This includes clamp
+ * mode. (This may be addressed in a future update.)
+ */
+ GrTexture* lockAndRefScratchTexture(const GrTextureDesc&, ScratchTexMatch match);
+
+ /**
+ * When done with an entry, call unlockScratchTexture(entry) on it, which returns
+ * it to the cache, where it may be purged. This does not unref the texture.
+ */
+ void unlockScratchTexture(GrTexture* texture);
+
+ /**
+ * This method should be called whenever a GrTexture is unreffed or
+ * switched from exclusive to non-exclusive. This
+ * gives the resource cache a chance to discard unneeded textures.
+ * Note: this entry point will be removed once totally ref-driven
+ * cache maintenance is implemented
+ */
+ void purgeCache();
+
+ /**
+ * Creates a texture that is outside the cache. Does not count against
+ * cache's budget.
+ */
+ GrTexture* createUncachedTexture(const GrTextureDesc& desc,
+ void* srcData,
+ size_t rowBytes);
+
+ /**
+ * Returns true if the specified use of an indexed texture is supported.
+ * Support may depend upon whether the texture params indicate that the
+ * texture will be tiled. Passing NULL for the texture params indicates
+ * clamp mode.
+ */
+ bool supportsIndex8PixelConfig(const GrTextureParams*,
+ int width,
+ int height) const;
+
+ /**
+ * Return the current texture cache limits.
+ *
+ * @param maxTextures If non-null, returns maximum number of textures that
+ * can be held in the cache.
+ * @param maxTextureBytes If non-null, returns maximum number of bytes of
+ * texture memory that can be held in the cache.
+ */
+ void getTextureCacheLimits(int* maxTextures, size_t* maxTextureBytes) const;
+
+ /**
+ * Specify the texture cache limits. If the current cache exceeds either
+ * of these, it will be purged (LRU) to keep the cache within these limits.
+ *
+ * @param maxTextures The maximum number of textures that can be held in
+ * the cache.
+ * @param maxTextureBytes The maximum number of bytes of texture memory
+ * that can be held in the cache.
+ */
+ void setTextureCacheLimits(int maxTextures, size_t maxTextureBytes);
+
+ /**
+ * Return the max width or height of a texture supported by the current GPU.
+ */
+ int getMaxTextureSize() const;
+
+ /**
+ * Temporarily override the true max texture size. Note: an override
+ * larger then the true max texture size will have no effect.
+ * This entry point is mainly meant for testing texture size dependent
+ * features and is only available if defined outside of Skia (see
+ * bleed GM.
+ */
+ void setMaxTextureSizeOverride(int maxTextureSizeOverride);
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Render targets
+
+ /**
+ * Sets the render target.
+ * @param target the render target to set.
+ */
+ void setRenderTarget(GrRenderTarget* target) {
+ fRenderTarget.reset(SkSafeRef(target));
+ }
+
+ /**
+ * Gets the current render target.
+ * @return the currently bound render target.
+ */
+ const GrRenderTarget* getRenderTarget() const { return fRenderTarget.get(); }
+ GrRenderTarget* getRenderTarget() { return fRenderTarget.get(); }
+
+ GrAARectRenderer* getAARectRenderer() { return fAARectRenderer; }
+
+ /**
+ * Can the provided configuration act as a color render target?
+ */
+ bool isConfigRenderable(GrPixelConfig config) const;
+
+ /**
+ * Return the max width or height of a render target supported by the
+ * current GPU.
+ */
+ int getMaxRenderTargetSize() const;
+
+ /**
+ * Returns the max sample count for a render target. It will be 0 if MSAA
+ * is not supported.
+ */
+ int getMaxSampleCount() const;
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Backend Surfaces
+
+ /**
+ * Wraps an existing texture with a GrTexture object.
+ *
+ * OpenGL: if the object is a texture Gr may change its GL texture params
+ * when it is drawn.
+ *
+ * @param desc description of the object to create.
+ *
+ * @return GrTexture object or NULL on failure.
+ */
+ GrTexture* wrapBackendTexture(const GrBackendTextureDesc& desc);
+
+ /**
+ * Wraps an existing render target with a GrRenderTarget object. It is
+ * similar to wrapBackendTexture but can be used to draw into surfaces
+ * that are not also textures (e.g. FBO 0 in OpenGL, or an MSAA buffer that
+ * the client will resolve to a texture).
+ *
+ * @param desc description of the object to create.
+ *
+ * @return GrTexture object or NULL on failure.
+ */
+ GrRenderTarget* wrapBackendRenderTarget(const GrBackendRenderTargetDesc& desc);
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Matrix state
+
+ /**
+ * Gets the current transformation matrix.
+ * @return the current matrix.
+ */
+ const SkMatrix& getMatrix() const { return fViewMatrix; }
+
+ /**
+ * Sets the transformation matrix.
+ * @param m the matrix to set.
+ */
+ void setMatrix(const SkMatrix& m) { fViewMatrix = m; }
+
+ /**
+ * Sets the current transformation matrix to identity.
+ */
+ void setIdentityMatrix() { fViewMatrix.reset(); }
+
+ /**
+ * Concats the current matrix. The passed matrix is applied before the
+ * current matrix.
+ * @param m the matrix to concat.
+ */
+ void concatMatrix(const SkMatrix& m) { fViewMatrix.preConcat(m); }
+
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Clip state
+ /**
+ * Gets the current clip.
+ * @return the current clip.
+ */
+ const GrClipData* getClip() const { return fClip; }
+
+ /**
+ * Sets the clip.
+ * @param clipData the clip to set.
+ */
+ void setClip(const GrClipData* clipData) { fClip = clipData; }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Draws
+
+ /**
+ * Clear the entire or rect of the render target, ignoring any clips.
+ * @param rect the rect to clear or the whole thing if rect is NULL.
+ * @param color the color to clear to.
+ * @param target if non-NULL, the render target to clear otherwise clear
+ * the current render target
+ */
+ void clear(const SkIRect* rect, GrColor color,
+ GrRenderTarget* target = NULL);
+
+ /**
+ * Draw everywhere (respecting the clip) with the paint.
+ */
+ void drawPaint(const GrPaint& paint);
+
+ /**
+ * Draw the rect using a paint.
+ * @param paint describes how to color pixels.
+ * @param strokeWidth If strokeWidth < 0, then the rect is filled, else
+ * the rect is mitered stroked based on strokeWidth. If
+ * strokeWidth == 0, then the stroke is always a single
+ * pixel thick.
+ * @param matrix Optional matrix applied to the rect. Applied before
+ * context's matrix or the paint's matrix.
+ * The rects coords are used to access the paint (through texture matrix)
+ */
+ void drawRect(const GrPaint& paint,
+ const SkRect&,
+ SkScalar strokeWidth = -1,
+ const SkMatrix* matrix = NULL);
+
+ /**
+ * Maps a rect of local coordinates onto the a rect of destination
+ * coordinates. Each rect can optionally be transformed. The localRect
+ * is stretched over the dstRect. The dstRect is transformed by the
+ * context's matrix. Additional optional matrices for both rects can be
+ * provided by parameters.
+ *
+ * @param paint describes how to color pixels.
+ * @param dstRect the destination rect to draw.
+ * @param localRect rect of local coordinates to be mapped onto dstRect
+ * @param dstMatrix Optional matrix to transform dstRect. Applied before context's matrix.
+ * @param localMatrix Optional matrix to transform localRect.
+ */
+ void drawRectToRect(const GrPaint& paint,
+ const SkRect& dstRect,
+ const SkRect& localRect,
+ const SkMatrix* dstMatrix = NULL,
+ const SkMatrix* localMatrix = NULL);
+
+ /**
+ * Draw a roundrect using a paint.
+ *
+ * @param paint describes how to color pixels.
+ * @param rrect the roundrect to draw
+ * @param stroke the stroke information (width, join, cap)
+ */
+ void drawRRect(const GrPaint& paint,
+ const SkRRect& rrect,
+ const SkStrokeRec& stroke);
+
+ /**
+ * Draws a path.
+ *
+ * @param paint describes how to color pixels.
+ * @param path the path to draw
+ * @param stroke the stroke information (width, join, cap)
+ */
+ void drawPath(const GrPaint& paint, const SkPath& path, const SkStrokeRec& stroke);
+
+ /**
+ * Draws vertices with a paint.
+ *
+ * @param paint describes how to color pixels.
+ * @param primitiveType primitives type to draw.
+ * @param vertexCount number of vertices.
+ * @param positions array of vertex positions, required.
+ * @param texCoords optional array of texture coordinates used
+ * to access the paint.
+ * @param colors optional array of per-vertex colors, supercedes
+ * the paint's color field.
+ * @param indices optional array of indices. If NULL vertices
+ * are drawn non-indexed.
+ * @param indexCount if indices is non-null then this is the
+ * number of indices.
+ */
+ void drawVertices(const GrPaint& paint,
+ GrPrimitiveType primitiveType,
+ int vertexCount,
+ const GrPoint positions[],
+ const GrPoint texs[],
+ const GrColor colors[],
+ const uint16_t indices[],
+ int indexCount);
+
+ /**
+ * Draws an oval.
+ *
+ * @param paint describes how to color pixels.
+ * @param oval the bounding rect of the oval.
+ * @param stroke the stroke information (width, style)
+ */
+ void drawOval(const GrPaint& paint,
+ const SkRect& oval,
+ const SkStrokeRec& stroke);
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Misc.
+
+ /**
+ * Flags that affect flush() behavior.
+ */
+ enum FlushBits {
+ /**
+ * A client may reach a point where it has partially rendered a frame
+ * through a GrContext that it knows the user will never see. This flag
+ * causes the flush to skip submission of deferred content to the 3D API
+ * during the flush.
+ */
+ kDiscard_FlushBit = 0x2,
+ };
+
+ /**
+ * Call to ensure all drawing to the context has been issued to the
+ * underlying 3D API.
+ * @param flagsBitfield flags that control the flushing behavior. See
+ * FlushBits.
+ */
+ void flush(int flagsBitfield = 0);
+
+ /**
+ * These flags can be used with the read/write pixels functions below.
+ */
+ enum PixelOpsFlags {
+ /** The GrContext will not be flushed. This means that the read or write may occur before
+ previous draws have executed. */
+ kDontFlush_PixelOpsFlag = 0x1,
+ /** The src for write or dst read is unpremultiplied. This is only respected if both the
+ config src and dst configs are an RGBA/BGRA 8888 format. */
+ kUnpremul_PixelOpsFlag = 0x2,
+ };
+
+ /**
+ * Reads a rectangle of pixels from a render target.
+ * @param target the render target to read from. NULL means the current render target.
+ * @param left left edge of the rectangle to read (inclusive)
+ * @param top top edge of the rectangle to read (inclusive)
+ * @param width width of rectangle to read in pixels.
+ * @param height height of rectangle to read in pixels.
+ * @param config the pixel config of the destination buffer
+ * @param buffer memory to read the rectangle into.
+ * @param rowBytes number of bytes bewtween consecutive rows. Zero means rows are tightly
+ * packed.
+ * @param pixelOpsFlags see PixelOpsFlags enum above.
+ *
+ * @return true if the read succeeded, false if not. The read can fail because of an unsupported
+ * pixel config or because no render target is currently set and NULL was passed for
+ * target.
+ */
+ bool readRenderTargetPixels(GrRenderTarget* target,
+ int left, int top, int width, int height,
+ GrPixelConfig config, void* buffer,
+ size_t rowBytes = 0,
+ uint32_t pixelOpsFlags = 0);
+
+ /**
+ * Copy the src pixels [buffer, row bytes, pixel config] into a render target at the specified
+ * rectangle.
+ * @param target the render target to write into. NULL means the current render target.
+ * @param left left edge of the rectangle to write (inclusive)
+ * @param top top edge of the rectangle to write (inclusive)
+ * @param width width of rectangle to write in pixels.
+ * @param height height of rectangle to write in pixels.
+ * @param config the pixel config of the source buffer
+ * @param buffer memory to read the rectangle from.
+ * @param rowBytes number of bytes between consecutive rows. Zero means rows are tightly
+ * packed.
+ * @param pixelOpsFlags see PixelOpsFlags enum above.
+ *
+ * @return true if the write succeeded, false if not. The write can fail because of an
+ * unsupported combination of target and pixel configs.
+ */
+ bool writeRenderTargetPixels(GrRenderTarget* target,
+ int left, int top, int width, int height,
+ GrPixelConfig config, const void* buffer,
+ size_t rowBytes = 0,
+ uint32_t pixelOpsFlags = 0);
+
+ /**
+ * Reads a rectangle of pixels from a texture.
+ * @param texture the texture to read from.
+ * @param left left edge of the rectangle to read (inclusive)
+ * @param top top edge of the rectangle to read (inclusive)
+ * @param width width of rectangle to read in pixels.
+ * @param height height of rectangle to read in pixels.
+ * @param config the pixel config of the destination buffer
+ * @param buffer memory to read the rectangle into.
+ * @param rowBytes number of bytes between consecutive rows. Zero means rows are tightly
+ * packed.
+ * @param pixelOpsFlags see PixelOpsFlags enum above.
+ *
+ * @return true if the read succeeded, false if not. The read can fail because of an unsupported
+ * pixel config.
+ */
+ bool readTexturePixels(GrTexture* texture,
+ int left, int top, int width, int height,
+ GrPixelConfig config, void* buffer,
+ size_t rowBytes = 0,
+ uint32_t pixelOpsFlags = 0);
+
+ /**
+ * Writes a rectangle of pixels to a texture.
+ * @param texture the render target to read from.
+ * @param left left edge of the rectangle to write (inclusive)
+ * @param top top edge of the rectangle to write (inclusive)
+ * @param width width of rectangle to write in pixels.
+ * @param height height of rectangle to write in pixels.
+ * @param config the pixel config of the source buffer
+ * @param buffer memory to read pixels from
+ * @param rowBytes number of bytes between consecutive rows. Zero
+ * means rows are tightly packed.
+ * @param pixelOpsFlags see PixelOpsFlags enum above.
+ * @return true if the write succeeded, false if not. The write can fail because of an
+ * unsupported combination of texture and pixel configs.
+ */
+ bool writeTexturePixels(GrTexture* texture,
+ int left, int top, int width, int height,
+ GrPixelConfig config, const void* buffer,
+ size_t rowBytes,
+ uint32_t pixelOpsFlags = 0);
+
+
+ /**
+ * Copies a rectangle of texels from src to dst. The size of dst is the size of the rectangle
+ * copied and topLeft is the position of the rect in src. The rectangle is clipped to src's
+ * bounds.
+ * @param src the texture to copy from.
+ * @param dst the render target to copy to.
+ * @param topLeft the point in src that will be copied to the top-left of dst. If NULL,
+ * (0, 0) will be used.
+ */
+ void copyTexture(GrTexture* src, GrRenderTarget* dst, const SkIPoint* topLeft = NULL);
+
+ /**
+ * Resolves a render target that has MSAA. The intermediate MSAA buffer is
+ * down-sampled to the associated GrTexture (accessible via
+ * GrRenderTarget::asTexture()). Any pending draws to the render target will
+ * be executed before the resolve.
+ *
+ * This is only necessary when a client wants to access the object directly
+ * using the backend API directly. GrContext will detect when it must
+ * perform a resolve to a GrTexture used as the source of a draw or before
+ * reading pixels back from a GrTexture or GrRenderTarget.
+ */
+ void resolveRenderTarget(GrRenderTarget* target);
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Helpers
+
+ class AutoRenderTarget : public ::GrNoncopyable {
+ public:
+ AutoRenderTarget(GrContext* context, GrRenderTarget* target) {
+ fPrevTarget = context->getRenderTarget();
+ GrSafeRef(fPrevTarget);
+ context->setRenderTarget(target);
+ fContext = context;
+ }
+ AutoRenderTarget(GrContext* context) {
+ fPrevTarget = context->getRenderTarget();
+ GrSafeRef(fPrevTarget);
+ fContext = context;
+ }
+ ~AutoRenderTarget() {
+ if (NULL != fContext) {
+ fContext->setRenderTarget(fPrevTarget);
+ }
+ GrSafeUnref(fPrevTarget);
+ }
+ private:
+ GrContext* fContext;
+ GrRenderTarget* fPrevTarget;
+ };
+
+ /**
+ * Save/restore the view-matrix in the context. It can optionally adjust a paint to account
+ * for a coordinate system change. Here is an example of how the paint param can be used:
+ *
+ * A GrPaint is setup with GrEffects. The stages will have access to the pre-matrix source
+ * geometry positions when the draw is executed. Later on a decision is made to transform the
+ * geometry to device space on the CPU. The effects now need to know that the space in which
+ * the geometry will be specified has changed.
+ *
+ * Note that when restore is called (or in the destructor) the context's matrix will be
+ * restored. However, the paint will not be restored. The caller must make a copy of the
+ * paint if necessary. Hint: use SkTCopyOnFirstWrite if the AutoMatrix is conditionally
+ * initialized.
+ */
+ class AutoMatrix : GrNoncopyable {
+ public:
+ AutoMatrix() : fContext(NULL) {}
+
+ ~AutoMatrix() { this->restore(); }
+
+ /**
+ * Initializes by pre-concat'ing the context's current matrix with the preConcat param.
+ */
+ void setPreConcat(GrContext* context, const SkMatrix& preConcat, GrPaint* paint = NULL) {
+ GrAssert(NULL != context);
+
+ this->restore();
+
+ fContext = context;
+ fMatrix = context->getMatrix();
+ this->preConcat(preConcat, paint);
+ }
+
+ /**
+ * Sets the context's matrix to identity. Returns false if the inverse matrix is required to
+ * update a paint but the matrix cannot be inverted.
+ */
+ bool setIdentity(GrContext* context, GrPaint* paint = NULL) {
+ GrAssert(NULL != context);
+
+ this->restore();
+
+ if (NULL != paint) {
+ if (!paint->localCoordChangeInverse(context->getMatrix())) {
+ return false;
+ }
+ }
+ fMatrix = context->getMatrix();
+ fContext = context;
+ context->setIdentityMatrix();
+ return true;
+ }
+
+ /**
+ * Replaces the context's matrix with a new matrix. Returns false if the inverse matrix is
+ * required to update a paint but the matrix cannot be inverted.
+ */
+ bool set(GrContext* context, const SkMatrix& newMatrix, GrPaint* paint = NULL) {
+ if (NULL != paint) {
+ if (!this->setIdentity(context, paint)) {
+ return false;
+ }
+ this->preConcat(newMatrix, paint);
+ } else {
+ this->restore();
+ fContext = context;
+ fMatrix = context->getMatrix();
+ context->setMatrix(newMatrix);
+ }
+ return true;
+ }
+
+ /**
+ * If this has been initialized then the context's matrix will be further updated by
+ * pre-concat'ing the preConcat param. The matrix that will be restored remains unchanged.
+ * The paint is assumed to be relative to the context's matrix at the time this call is
+ * made, not the matrix at the time AutoMatrix was first initialized. In other words, this
+ * performs an incremental update of the paint.
+ */
+ void preConcat(const SkMatrix& preConcat, GrPaint* paint = NULL) {
+ if (NULL != paint) {
+ paint->localCoordChange(preConcat);
+ }
+ fContext->concatMatrix(preConcat);
+ }
+
+ /**
+ * Returns false if never initialized or the inverse matrix was required to update a paint
+ * but the matrix could not be inverted.
+ */
+ bool succeeded() const { return NULL != fContext; }
+
+ /**
+ * If this has been initialized then the context's original matrix is restored.
+ */
+ void restore() {
+ if (NULL != fContext) {
+ fContext->setMatrix(fMatrix);
+ fContext = NULL;
+ }
+ }
+
+ private:
+ GrContext* fContext;
+ SkMatrix fMatrix;
+ };
+
+ class AutoClip : GrNoncopyable {
+ public:
+ // This enum exists to require a caller of the constructor to acknowledge that the clip will
+ // initially be wide open. It also could be extended if there are other desirable initial
+ // clip states.
+ enum InitialClip {
+ kWideOpen_InitialClip,
+ };
+
+ AutoClip(GrContext* context, InitialClip initialState)
+ : fContext(context) {
+ GrAssert(kWideOpen_InitialClip == initialState);
+ fNewClipData.fClipStack = &fNewClipStack;
+
+ fOldClip = context->getClip();
+ context->setClip(&fNewClipData);
+ }
+
+ AutoClip(GrContext* context, const SkRect& newClipRect)
+ : fContext(context)
+ , fNewClipStack(newClipRect) {
+ fNewClipData.fClipStack = &fNewClipStack;
+
+ fOldClip = fContext->getClip();
+ fContext->setClip(&fNewClipData);
+ }
+
+ ~AutoClip() {
+ if (NULL != fContext) {
+ fContext->setClip(fOldClip);
+ }
+ }
+ private:
+ GrContext* fContext;
+ const GrClipData* fOldClip;
+
+ SkClipStack fNewClipStack;
+ GrClipData fNewClipData;
+ };
+
+ class AutoWideOpenIdentityDraw {
+ public:
+ AutoWideOpenIdentityDraw(GrContext* ctx, GrRenderTarget* rt)
+ : fAutoClip(ctx, AutoClip::kWideOpen_InitialClip)
+ , fAutoRT(ctx, rt) {
+ fAutoMatrix.setIdentity(ctx);
+ // should never fail with no paint param.
+ GrAssert(fAutoMatrix.succeeded());
+ }
+
+ private:
+ AutoClip fAutoClip;
+ AutoRenderTarget fAutoRT;
+ AutoMatrix fAutoMatrix;
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Functions intended for internal use only.
+ GrGpu* getGpu() { return fGpu; }
+ const GrGpu* getGpu() const { return fGpu; }
+ GrFontCache* getFontCache() { return fFontCache; }
+ GrDrawTarget* getTextTarget();
+ const GrIndexBuffer* getQuadIndexBuffer() const;
+
+ /**
+ * Stencil buffers add themselves to the cache using addStencilBuffer. findStencilBuffer is
+ * called to check the cache for a SB that matches an RT's criteria.
+ */
+ void addStencilBuffer(GrStencilBuffer* sb);
+ GrStencilBuffer* findStencilBuffer(int width, int height, int sampleCnt);
+
+ GrPathRenderer* getPathRenderer(
+ const SkPath& path,
+ const SkStrokeRec& stroke,
+ const GrDrawTarget* target,
+ bool allowSW,
+ GrPathRendererChain::DrawType drawType = GrPathRendererChain::kColor_DrawType,
+ GrPathRendererChain::StencilSupport* stencilSupport = NULL);
+
+#if GR_CACHE_STATS
+ void printCacheStats() const;
+#endif
+
+private:
+ // Used to indicate whether a draw should be performed immediately or queued in fDrawBuffer.
+ enum BufferedDraw {
+ kYes_BufferedDraw,
+ kNo_BufferedDraw,
+ };
+ BufferedDraw fLastDrawWasBuffered;
+
+ GrGpu* fGpu;
+ SkMatrix fViewMatrix;
+ SkAutoTUnref<GrRenderTarget> fRenderTarget;
+ const GrClipData* fClip; // TODO: make this ref counted
+ GrDrawState* fDrawState;
+
+ GrResourceCache* fTextureCache;
+ GrFontCache* fFontCache;
+
+ GrPathRendererChain* fPathRendererChain;
+ GrSoftwarePathRenderer* fSoftwarePathRenderer;
+
+ GrVertexBufferAllocPool* fDrawBufferVBAllocPool;
+ GrIndexBufferAllocPool* fDrawBufferIBAllocPool;
+ GrInOrderDrawBuffer* fDrawBuffer;
+
+ GrAARectRenderer* fAARectRenderer;
+ GrOvalRenderer* fOvalRenderer;
+
+ bool fDidTestPMConversions;
+ int fPMToUPMConversion;
+ int fUPMToPMConversion;
+
+ struct CleanUpData {
+ PFCleanUpFunc fFunc;
+ void* fInfo;
+ };
+
+ SkTDArray<CleanUpData> fCleanUpData;
+
+ int fMaxTextureSizeOverride;
+
+ GrContext(); // init must be called after the constructor.
+ bool init(GrBackend, GrBackendContext);
+
+ void setupDrawBuffer();
+
+ class AutoRestoreEffects;
+ /// Sets the paint and returns the target to draw into. The paint can be NULL in which case the
+ /// draw state is left unmodified.
+ GrDrawTarget* prepareToDraw(const GrPaint*, BufferedDraw, AutoRestoreEffects*);
+
+ void internalDrawPath(GrDrawTarget* target, bool useAA, const SkPath& path,
+ const SkStrokeRec& stroke);
+
+ GrTexture* createResizedTexture(const GrTextureDesc& desc,
+ const GrCacheID& cacheID,
+ void* srcData,
+ size_t rowBytes,
+ bool filter);
+
+ // Needed so GrTexture's returnToCache helper function can call
+ // addExistingTextureToCache
+ friend class GrTexture;
+
+ // Add an existing texture to the texture cache. This is intended solely
+ // for use with textures released from an GrAutoScratchTexture.
+ void addExistingTextureToCache(GrTexture* texture);
+
+ /**
+ * These functions create premul <-> unpremul effects if it is possible to generate a pair
+ * of effects that make a readToUPM->writeToPM->readToUPM cycle invariant. Otherwise, they
+ * return NULL.
+ */
+ const GrEffectRef* createPMToUPMEffect(GrTexture* texture,
+ bool swapRAndB,
+ const SkMatrix& matrix);
+ const GrEffectRef* createUPMToPMEffect(GrTexture* texture,
+ bool swapRAndB,
+ const SkMatrix& matrix);
+
+ /**
+ * This callback allows the resource cache to callback into the GrContext
+ * when the cache is still overbudget after a purge.
+ */
+ static bool OverbudgetCB(void* data);
+
+ typedef GrRefCnt INHERITED;
+};
+
+/**
+ * Gets and locks a scratch texture from a descriptor using either exact or approximate criteria.
+ * Unlocks texture in the destructor.
+ */
+class GrAutoScratchTexture : ::GrNoncopyable {
+public:
+ GrAutoScratchTexture()
+ : fContext(NULL)
+ , fTexture(NULL) {
+ }
+
+ GrAutoScratchTexture(GrContext* context,
+ const GrTextureDesc& desc,
+ GrContext::ScratchTexMatch match = GrContext::kApprox_ScratchTexMatch)
+ : fContext(NULL)
+ , fTexture(NULL) {
+ this->set(context, desc, match);
+ }
+
+ ~GrAutoScratchTexture() {
+ this->reset();
+ }
+
+ void reset() {
+ if (NULL != fContext && NULL != fTexture) {
+ fContext->unlockScratchTexture(fTexture);
+ fTexture->unref();
+ fTexture = NULL;
+ }
+ }
+
+ /*
+ * When detaching a texture we do not unlock it in the texture cache but
+ * we do set the returnToCache flag. In this way the texture remains
+ * "locked" in the texture cache until it is freed and recycled in
+ * GrTexture::internal_dispose. In reality, the texture has been removed
+ * from the cache (because this is in AutoScratchTexture) and by not
+ * calling unlockScratchTexture we simply don't re-add it. It will be
+ * reattached in GrTexture::internal_dispose.
+ *
+ * Note that the caller is assumed to accept and manage the ref to the
+ * returned texture.
+ */
+ GrTexture* detach() {
+ if (NULL == fTexture) {
+ return NULL;
+ }
+ GrTexture* texture = fTexture;
+ fTexture = NULL;
+
+ // This GrAutoScratchTexture has a ref from lockAndRefScratchTexture, which we give up now.
+ // The cache also has a ref which we are lending to the caller of detach(). When the caller
+ // lets go of the ref and the ref count goes to 0 internal_dispose will see this flag is
+ // set and re-ref the texture, thereby restoring the cache's ref.
+ GrAssert(texture->getRefCnt() > 1);
+ texture->setFlag((GrTextureFlags) GrTexture::kReturnToCache_FlagBit);
+ texture->unref();
+ GrAssert(NULL != texture->getCacheEntry());
+
+ return texture;
+ }
+
+ GrTexture* set(GrContext* context,
+ const GrTextureDesc& desc,
+ GrContext::ScratchTexMatch match = GrContext::kApprox_ScratchTexMatch) {
+ this->reset();
+
+ fContext = context;
+ if (NULL != fContext) {
+ fTexture = fContext->lockAndRefScratchTexture(desc, match);
+ if (NULL == fTexture) {
+ fContext = NULL;
+ }
+ return fTexture;
+ } else {
+ return NULL;
+ }
+ }
+
+ GrTexture* texture() { return fTexture; }
+
+private:
+ GrContext* fContext;
+ GrTexture* fTexture;
+};
+
+#endif
diff --git a/gpu/GrContextFactory.h b/gpu/GrContextFactory.h
new file mode 100644
index 0000000..3d9f1a3
--- /dev/null
+++ b/gpu/GrContextFactory.h
@@ -0,0 +1,172 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrContextFactory_DEFINED
+#define GrContextFactory_DEFINED
+
+#if SK_ANGLE
+ #include "gl/SkANGLEGLContext.h"
+#endif
+#include "gl/SkDebugGLContext.h"
+#if SK_MESA
+ #include "gl/SkMesaGLContext.h"
+#endif
+#include "gl/SkNativeGLContext.h"
+#include "gl/SkNullGLContext.h"
+
+#include "GrContext.h"
+#include "SkTArray.h"
+
+/**
+ * This is a simple class that is useful in test apps that use different
+ * GrContexts backed by different types of GL contexts. It manages creating the
+ * GL context and a GrContext that uses it. The GL/Gr contexts persist until the
+ * factory is destroyed (though the caller can always grab a ref on the returned
+ * GrContext to make it outlive the factory).
+ */
+class GrContextFactory : GrNoncopyable {
+public:
+ /**
+ * Types of GL contexts supported.
+ */
+ enum GLContextType {
+ kNative_GLContextType,
+#if SK_ANGLE
+ kANGLE_GLContextType,
+#endif
+#if SK_MESA
+ kMESA_GLContextType,
+#endif
+ kNull_GLContextType,
+ kDebug_GLContextType,
+
+ kLastGLContextType = kDebug_GLContextType
+ };
+
+ static const int kGLContextTypeCnt = kLastGLContextType + 1;
+
+ static bool IsRenderingGLContext(GLContextType type) {
+ switch (type) {
+ case kNull_GLContextType:
+ case kDebug_GLContextType:
+ return false;
+ default:
+ return true;
+ }
+ }
+
+ static const char* GLContextTypeName(GLContextType type) {
+ switch (type) {
+ case kNative_GLContextType:
+ return "native";
+ case kNull_GLContextType:
+ return "null";
+#if SK_ANGLE
+ case kANGLE_GLContextType:
+ return "angle";
+#endif
+#if SK_MESA
+ case kMESA_GLContextType:
+ return "mesa";
+#endif
+ case kDebug_GLContextType:
+ return "debug";
+ default:
+ GrCrash("Unknown GL Context type.");
+ }
+ }
+
+ GrContextFactory() {
+ }
+
+ ~GrContextFactory() { this->destroyContexts(); }
+
+ void destroyContexts() {
+ for (int i = 0; i < fContexts.count(); ++i) {
+ fContexts[i].fGrContext->unref();
+ fContexts[i].fGLContext->unref();
+ }
+ fContexts.reset();
+ }
+
+ /**
+ * Get a GrContext initialized with a type of GL context. It also makes the GL context current.
+ */
+ GrContext* get(GLContextType type) {
+
+ for (int i = 0; i < fContexts.count(); ++i) {
+ if (fContexts[i].fType == type) {
+ fContexts[i].fGLContext->makeCurrent();
+ return fContexts[i].fGrContext;
+ }
+ }
+ SkAutoTUnref<SkGLContextHelper> glCtx;
+ SkAutoTUnref<GrContext> grCtx;
+ switch (type) {
+ case kNative_GLContextType:
+ glCtx.reset(SkNEW(SkNativeGLContext));
+ break;
+#ifdef SK_ANGLE
+ case kANGLE_GLContextType:
+ glCtx.reset(SkNEW(SkANGLEGLContext));
+ break;
+#endif
+#ifdef SK_MESA
+ case kMESA_GLContextType:
+ glCtx.reset(SkNEW(SkMesaGLContext));
+ break;
+#endif
+ case kNull_GLContextType:
+ glCtx.reset(SkNEW(SkNullGLContext));
+ break;
+ case kDebug_GLContextType:
+ glCtx.reset(SkNEW(SkDebugGLContext));
+ break;
+ }
+ static const int kBogusSize = 1;
+ if (!glCtx.get()) {
+ return NULL;
+ }
+ if (!glCtx.get()->init(kBogusSize, kBogusSize)) {
+ return NULL;
+ }
+ GrBackendContext p3dctx = reinterpret_cast<GrBackendContext>(glCtx.get()->gl());
+ grCtx.reset(GrContext::Create(kOpenGL_GrBackend, p3dctx));
+ if (!grCtx.get()) {
+ return NULL;
+ }
+ GPUContext& ctx = fContexts.push_back();
+ ctx.fGLContext = glCtx.get();
+ ctx.fGLContext->ref();
+ ctx.fGrContext = grCtx.get();
+ ctx.fGrContext->ref();
+ ctx.fType = type;
+ return ctx.fGrContext;
+ }
+
+ // Returns the GLContext of the given type. If it has not been created yet,
+ // NULL is returned instead.
+ SkGLContextHelper* getGLContext(GLContextType type) {
+ for (int i = 0; i < fContexts.count(); ++i) {
+ if (fContexts[i].fType == type) {
+ return fContexts[i].fGLContext;
+ }
+ }
+
+ return NULL;
+ }
+
+private:
+ struct GPUContext {
+ GLContextType fType;
+ SkGLContextHelper* fGLContext;
+ GrContext* fGrContext;
+ };
+ SkTArray<GPUContext, true> fContexts;
+};
+
+#endif
diff --git a/gpu/GrDrawEffect.h b/gpu/GrDrawEffect.h
new file mode 100644
index 0000000..005de41
--- /dev/null
+++ b/gpu/GrDrawEffect.h
@@ -0,0 +1,51 @@
+
+#ifndef GrDrawEffect_DEFINED
+#define GrDrawEffect_DEFINED
+
+#include "GrEffectStage.h"
+
+/**
+ * This class is used to communicate the particular GrEffect used in a draw to the backend-specific
+ * effect subclass (e.g. GrGLEffect). It is used to by the backend-specific class to generate a
+ * cache key for the effect, generate code on a program cache miss, and to upload uniform values to
+ * the program.
+ * In addition to the effect, it also communicates any changes between the relationship between
+ * the view matrix and local coordinate system since the effect was installed in its GrDrawState.
+ * The typical use case is that sometime after an effect was installed a decision was made to draw
+ * in device coordinates (i.e. use an identity view-matrix). In such a case the GrDrawEffect's
+ * coord-change-matrix would be the inverse of the view matrix that was set when the effect was
+ * installed. GrGLEffectMatrix is a handy class that implements a local coordinate matrix that
+ * automatically accounts for the coord-change matrix.
+ */
+class GrDrawEffect {
+public:
+ GrDrawEffect(const GrEffectStage& stage, bool explicitLocalCoords)
+ : fEffectStage(&stage)
+ , fExplicitLocalCoords(explicitLocalCoords) {
+ GrAssert(NULL != fEffectStage);
+ GrAssert(NULL != fEffectStage->getEffect());
+ }
+ const GrEffectRef* effect() const { return fEffectStage->getEffect(); }
+
+ template <typename T>
+ const T& castEffect() const { return *static_cast<const T*>(this->effect()->get()); }
+
+ const SkMatrix& getCoordChangeMatrix() const {
+ if (fExplicitLocalCoords) {
+ return SkMatrix::I();
+ } else {
+ return fEffectStage->getCoordChangeMatrix();
+ }
+ }
+
+ bool programHasExplicitLocalCoords() const { return fExplicitLocalCoords; }
+
+ const int* getVertexAttribIndices() const { return fEffectStage->getVertexAttribIndices(); }
+ int getVertexAttribIndexCount() const { return fEffectStage->getVertexAttribIndexCount(); }
+
+private:
+ const GrEffectStage* fEffectStage;
+ bool fExplicitLocalCoords;
+};
+
+#endif
diff --git a/gpu/GrEffect.h b/gpu/GrEffect.h
new file mode 100644
index 0000000..20dc5da
--- /dev/null
+++ b/gpu/GrEffect.h
@@ -0,0 +1,345 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrEffect_DEFINED
+#define GrEffect_DEFINED
+
+#include "GrColor.h"
+#include "GrEffectUnitTest.h"
+#include "GrNoncopyable.h"
+#include "GrRefCnt.h"
+#include "GrTexture.h"
+#include "GrTextureAccess.h"
+#include "GrTypesPriv.h"
+
+class GrBackendEffectFactory;
+class GrContext;
+class GrEffect;
+class SkString;
+
+/**
+ * A Wrapper class for GrEffect. Its ref-count will track owners that may use effects to enqueue
+ * new draw operations separately from ownership within a deferred drawing queue. When the
+ * GrEffectRef ref count reaches zero the scratch GrResources owned by the effect can be recycled
+ * in service of later draws. However, the deferred draw queue may still own direct references to
+ * the underlying GrEffect.
+ *
+ * GrEffectRefs created by new are placed in a per-thread managed pool. The pool is destroyed when
+ * the thread ends. Therefore, all dynamically allocated GrEffectRefs must be unreffed before thread
+ * termination.
+ */
+class GrEffectRef : public SkRefCnt {
+public:
+ SK_DECLARE_INST_COUNT(GrEffectRef);
+ virtual ~GrEffectRef();
+
+ GrEffect* get() { return fEffect; }
+ const GrEffect* get() const { return fEffect; }
+
+ const GrEffect* operator-> () { return fEffect; }
+ const GrEffect* operator-> () const { return fEffect; }
+
+ void* operator new(size_t size);
+ void operator delete(void* target);
+
+ void* operator new(size_t size, void* placement) {
+ return ::operator new(size, placement);
+ }
+ void operator delete(void* target, void* placement) {
+ ::operator delete(target, placement);
+ }
+
+private:
+ friend class GrEffect; // to construct these
+
+ explicit GrEffectRef(GrEffect* effect);
+
+ GrEffect* fEffect;
+
+ typedef SkRefCnt INHERITED;
+};
+
+/** Provides custom vertex shader, fragment shader, uniform data for a particular stage of the
+ Ganesh shading pipeline.
+ Subclasses must have a function that produces a human-readable name:
+ static const char* Name();
+ GrEffect objects *must* be immutable: after being constructed, their fields may not change.
+
+ GrEffect subclass objects should be created by factory functions that return GrEffectRef.
+ There is no public way to wrap a GrEffect in a GrEffectRef. Thus, a factory should be a static
+ member function of a GrEffect subclass.
+
+ Because almost no code should ever handle a GrEffect directly outside of a GrEffectRef, we
+ privately inherit from GrRefCnt to help prevent accidental direct ref'ing/unref'ing of effects.
+
+ Dynamically allocated GrEffects and their corresponding GrEffectRefs are managed by a per-thread
+ memory pool. The ref count of an effect must reach 0 before the thread terminates and the pool
+ is destroyed. To create a static effect use the macro GR_CREATE_STATIC_EFFECT declared below.
+ */
+class GrEffect : private GrRefCnt {
+public:
+ SK_DECLARE_INST_COUNT(GrEffect)
+
+ /**
+ * The types of vertex coordinates available to an effect in the vertex shader. Effects can
+ * require their own vertex attribute but these coordinates are made available by the framework
+ * in all programs. kCustom_CoordsType is provided to signify that an alternative set of coords
+ * is used (usually an explicit vertex attribute) but its meaning is determined by the effect
+ * subclass.
+ */
+ enum CoordsType {
+ kLocal_CoordsType,
+ kPosition_CoordsType,
+
+ kCustom_CoordsType,
+ };
+
+ virtual ~GrEffect();
+
+ /**
+ * This function is used to perform optimizations. When called the color and validFlags params
+ * indicate whether the input components to this effect in the FS will have known values.
+ * validFlags is a bitfield of GrColorComponentFlags. The function updates both params to
+ * indicate known values of its output. A component of the color param only has meaning if the
+ * corresponding bit in validFlags is set.
+ */
+ virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags) const = 0;
+
+ /** This object, besides creating back-end-specific helper objects, is used for run-time-type-
+ identification. The factory should be an instance of templated class,
+ GrTBackendEffectFactory. It is templated on the subclass of GrEffect. The subclass must have
+ a nested type (or typedef) named GLEffect which will be the subclass of GrGLEffect created
+ by the factory.
+
+ Example:
+ class MyCustomEffect : public GrEffect {
+ ...
+ virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE {
+ return GrTBackendEffectFactory<MyCustomEffect>::getInstance();
+ }
+ ...
+ };
+ */
+ virtual const GrBackendEffectFactory& getFactory() const = 0;
+
+ /** Returns true if this and other effect conservatively draw identically. It can only return
+ true when the two effects are of the same subclass (i.e. they return the same object from
+ from getFactory()).
+
+ A return value of true from isEqual() should not be used to test whether the effects would
+ generate the same shader code. To test for identical code generation use the EffectKey
+ computed by the GrBackendEffectFactory:
+ effectA.getFactory().glEffectKey(effectA) == effectB.getFactory().glEffectKey(effectB).
+ */
+ bool isEqual(const GrEffectRef& other) const {
+ return this->isEqual(*other.get());
+ }
+
+ /** Human-meaningful string to identify this effect; may be embedded
+ in generated shader code. */
+ const char* name() const;
+
+ int numTextures() const { return fTextureAccesses.count(); }
+
+ /** Returns the access pattern for the texture at index. index must be valid according to
+ numTextures(). */
+ const GrTextureAccess& textureAccess(int index) const { return *fTextureAccesses[index]; }
+
+ /** Shortcut for textureAccess(index).texture(); */
+ GrTexture* texture(int index) const { return this->textureAccess(index).getTexture(); }
+
+ /** Will this effect read the destination pixel value? */
+ bool willReadDstColor() const { return fWillReadDstColor; }
+
+ /** Will this effect read the fragment position? */
+ bool willReadFragmentPosition() const { return fWillReadFragmentPosition; }
+
+ int numVertexAttribs() const { return fVertexAttribTypes.count(); }
+
+ GrSLType vertexAttribType(int index) const { return fVertexAttribTypes[index]; }
+
+ static const int kMaxVertexAttribs = 2;
+
+ /** Useful for effects that want to insert a texture matrix that is implied by the texture
+ dimensions */
+ static inline SkMatrix MakeDivByTextureWHMatrix(const GrTexture* texture) {
+ GrAssert(NULL != texture);
+ SkMatrix mat;
+ mat.setIDiv(texture->width(), texture->height());
+ return mat;
+ }
+
+ void* operator new(size_t size);
+ void operator delete(void* target);
+
+ void* operator new(size_t size, void* placement) {
+ return ::operator new(size, placement);
+ }
+ void operator delete(void* target, void* placement) {
+ ::operator delete(target, placement);
+ }
+
+ /** These functions are used when recording effects into a deferred drawing queue. The inc call
+ keeps the effect alive outside of GrEffectRef while allowing any resources owned by the
+ effect to be returned to the cache for reuse. The dec call must balance the inc call. */
+ void incDeferredRefCounts() const {
+ this->ref();
+ int count = fTextureAccesses.count();
+ for (int t = 0; t < count; ++t) {
+ fTextureAccesses[t]->getTexture()->incDeferredRefCount();
+ }
+ }
+ void decDeferredRefCounts() const {
+ int count = fTextureAccesses.count();
+ for (int t = 0; t < count; ++t) {
+ fTextureAccesses[t]->getTexture()->decDeferredRefCount();
+ }
+ this->unref();
+ }
+
+protected:
+ /**
+ * Subclasses call this from their constructor to register GrTextureAccesses. The effect
+ * subclass manages the lifetime of the accesses (this function only stores a pointer). This
+ * must only be called from the constructor because GrEffects are immutable.
+ */
+ void addTextureAccess(const GrTextureAccess* textureAccess);
+
+ /**
+ * Subclasses call this from their constructor to register vertex attributes (at most
+ * kMaxVertexAttribs). This must only be called from the constructor because GrEffects are
+ * immutable.
+ */
+ void addVertexAttrib(GrSLType type);
+
+ GrEffect() : fWillReadDstColor(false), fWillReadFragmentPosition(false), fEffectRef(NULL) {}
+
+ /** This should be called by GrEffect subclass factories. See the comment on AutoEffectUnref for
+ an example factory function. */
+ static GrEffectRef* CreateEffectRef(GrEffect* effect) {
+ if (NULL == effect->fEffectRef) {
+ effect->fEffectRef = SkNEW_ARGS(GrEffectRef, (effect));
+ } else {
+ effect->fEffectRef->ref();
+ }
+ return effect->fEffectRef;
+ }
+
+ static const GrEffectRef* CreateEffectRef(const GrEffect* effect) {
+ return CreateEffectRef(const_cast<GrEffect*>(effect));
+ }
+
+ /** Used by GR_CREATE_STATIC_EFFECT below */
+ static GrEffectRef* CreateStaticEffectRef(void* refStorage, GrEffect* effect) {
+ GrAssert(NULL == effect->fEffectRef);
+ effect->fEffectRef = SkNEW_PLACEMENT_ARGS(refStorage, GrEffectRef, (effect));
+ return effect->fEffectRef;
+ }
+
+
+ /** Helper used in subclass factory functions to unref the effect after it has been wrapped in a
+ GrEffectRef. E.g.:
+
+ class EffectSubclass : public GrEffect {
+ public:
+ GrEffectRef* Create(ParamType1 param1, ParamType2 param2, ...) {
+ AutoEffectUnref effect(SkNEW_ARGS(EffectSubclass, (param1, param2, ...)));
+ return CreateEffectRef(effect);
+ }
+ */
+ class AutoEffectUnref {
+ public:
+ AutoEffectUnref(GrEffect* effect) : fEffect(effect) { }
+ ~AutoEffectUnref() { fEffect->unref(); }
+ operator GrEffect*() { return fEffect; }
+ private:
+ GrEffect* fEffect;
+ };
+
+ /** Helper for getting the GrEffect out of a GrEffectRef and down-casting to a GrEffect subclass
+ */
+ template <typename T>
+ static const T& CastEffect(const GrEffect& effectRef) {
+ return *static_cast<const T*>(&effectRef);
+ }
+
+ /**
+ * If the effect subclass will read the destination pixel value then it must call this function
+ * from its constructor. Otherwise, when its generated backend-specific effect class attempts
+ * to generate code that reads the destination pixel it will fail.
+ */
+ void setWillReadDstColor() { fWillReadDstColor = true; }
+
+ /**
+ * If the effect will generate a backend-specific effect that will read the fragment position
+ * in the FS then it must call this method from its constructor. Otherwise, the request to
+ * access the fragment position will be denied.
+ */
+ void setWillReadFragmentPosition() { fWillReadFragmentPosition = true; }
+
+private:
+ bool isEqual(const GrEffect& other) const {
+ if (&this->getFactory() != &other.getFactory()) {
+ return false;
+ }
+ bool result = this->onIsEqual(other);
+#if GR_DEBUG
+ if (result) {
+ GrAssert(this->numTextures() == other.numTextures());
+ for (int i = 0; i < this->numTextures(); ++i) {
+ GrAssert(*fTextureAccesses[i] == *other.fTextureAccesses[i]);
+ }
+ }
+#endif
+ return result;
+ }
+
+ /** Subclass implements this to support isEqual(). It will only be called if it is known that
+ the two effects are of the same subclass (i.e. they return the same object from
+ getFactory()).*/
+ virtual bool onIsEqual(const GrEffect& other) const = 0;
+
+ void EffectRefDestroyed() { fEffectRef = NULL; }
+
+ friend class GrEffectRef; // to call EffectRefDestroyed()
+ friend class GrEffectStage; // to rewrap GrEffect in GrEffectRef when restoring an effect-stage
+ // from deferred state, to call isEqual on naked GrEffects, and
+ // to inc/dec deferred ref counts.
+
+ SkSTArray<4, const GrTextureAccess*, true> fTextureAccesses;
+ SkSTArray<kMaxVertexAttribs, GrSLType, true> fVertexAttribTypes;
+ bool fWillReadDstColor;
+ bool fWillReadFragmentPosition;
+ GrEffectRef* fEffectRef;
+
+ typedef GrRefCnt INHERITED;
+};
+
+inline GrEffectRef::GrEffectRef(GrEffect* effect) {
+ GrAssert(NULL != effect);
+ effect->ref();
+ fEffect = effect;
+}
+
+/**
+ * This creates an effect outside of the effect memory pool. The effect's destructor will be called
+ * at global destruction time. NAME will be the name of the created GrEffectRef.
+ */
+#define GR_CREATE_STATIC_EFFECT(NAME, EFFECT_CLASS, ARGS) \
+enum { \
+ k_##NAME##_EffectRefOffset = GR_CT_ALIGN_UP(sizeof(EFFECT_CLASS), 8), \
+ k_##NAME##_StorageSize = k_##NAME##_EffectRefOffset + sizeof(GrEffectRef) \
+}; \
+static SkAlignedSStorage<k_##NAME##_StorageSize> g_##NAME##_Storage; \
+static void* NAME##_RefLocation = (char*)g_##NAME##_Storage.get() + k_##NAME##_EffectRefOffset; \
+static GrEffect* NAME##_Effect SkNEW_PLACEMENT_ARGS(g_##NAME##_Storage.get(), EFFECT_CLASS, ARGS);\
+static SkAutoTDestroy<GrEffect> NAME##_ad(NAME##_Effect); \
+static GrEffectRef* NAME(GrEffect::CreateStaticEffectRef(NAME##_RefLocation, NAME##_Effect)); \
+static SkAutoTDestroy<GrEffectRef> NAME##_Ref_ad(NAME)
+
+
+#endif
diff --git a/gpu/GrEffectStage.h b/gpu/GrEffectStage.h
new file mode 100644
index 0000000..08fb159
--- /dev/null
+++ b/gpu/GrEffectStage.h
@@ -0,0 +1,223 @@
+
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+
+#ifndef GrEffectStage_DEFINED
+#define GrEffectStage_DEFINED
+
+#include "GrBackendEffectFactory.h"
+#include "GrEffect.h"
+#include "SkMatrix.h"
+#include "GrTypes.h"
+
+#include "SkShader.h"
+
+class GrEffectStage {
+public:
+ explicit GrEffectStage(const GrEffectRef* effectRef, int attrIndex0 = -1, int attrIndex1 = -1)
+ : fEffectRef(SkRef(effectRef)) {
+ fCoordChangeMatrixSet = false;
+ fVertexAttribIndices[0] = attrIndex0;
+ fVertexAttribIndices[1] = attrIndex1;
+ }
+
+ GrEffectStage(const GrEffectStage& other) {
+ *this = other;
+ }
+
+ class DeferredStage;
+ // This constructor balances DeferredStage::saveFrom().
+ explicit GrEffectStage(const DeferredStage& deferredStage) {
+ deferredStage.restoreTo(this);
+ }
+
+ GrEffectStage& operator= (const GrEffectStage& other) {
+ fCoordChangeMatrixSet = other.fCoordChangeMatrixSet;
+ if (other.fCoordChangeMatrixSet) {
+ fCoordChangeMatrix = other.fCoordChangeMatrix;
+ }
+ fEffectRef.reset(SkRef(other.fEffectRef.get()));
+ memcpy(fVertexAttribIndices, other.fVertexAttribIndices, sizeof(fVertexAttribIndices));
+ return *this;
+ }
+
+ bool operator== (const GrEffectStage& other) const {
+ GrAssert(NULL != fEffectRef.get());
+ GrAssert(NULL != other.fEffectRef.get());
+
+ if (!(*this->getEffect())->isEqual(*other.getEffect())) {
+ return false;
+ }
+
+ if (fCoordChangeMatrixSet != other.fCoordChangeMatrixSet) {
+ return false;
+ }
+
+ if (!fCoordChangeMatrixSet) {
+ return true;
+ }
+
+ return fCoordChangeMatrix == other.fCoordChangeMatrix;
+ }
+
+ bool operator!= (const GrEffectStage& s) const { return !(*this == s); }
+
+ /**
+ * This is called when the coordinate system in which the geometry is specified will change.
+ *
+ * @param matrix The transformation from the old coord system in which geometry is specified
+ * to the new one from which it will actually be drawn.
+ */
+ void localCoordChange(const SkMatrix& matrix) {
+ if (fCoordChangeMatrixSet) {
+ fCoordChangeMatrix.preConcat(matrix);
+ } else {
+ fCoordChangeMatrixSet = true;
+ fCoordChangeMatrix = matrix;
+ }
+ }
+
+ class SavedCoordChange {
+ private:
+ bool fCoordChangeMatrixSet;
+ SkMatrix fCoordChangeMatrix;
+ GR_DEBUGCODE(mutable SkAutoTUnref<const GrEffectRef> fEffectRef;)
+
+ friend class GrEffectStage;
+ };
+
+ /**
+ * This gets the current coordinate system change. It is the accumulation of
+ * localCoordChange calls since the effect was installed. It is used when then caller
+ * wants to temporarily change the source geometry coord system, draw something, and then
+ * restore the previous coord system (e.g. temporarily draw in device coords).
+ */
+ void saveCoordChange(SavedCoordChange* savedCoordChange) const {
+ savedCoordChange->fCoordChangeMatrixSet = fCoordChangeMatrixSet;
+ if (fCoordChangeMatrixSet) {
+ savedCoordChange->fCoordChangeMatrix = fCoordChangeMatrix;
+ }
+ GrAssert(NULL == savedCoordChange->fEffectRef.get());
+ GR_DEBUGCODE(SkRef(fEffectRef.get());)
+ GR_DEBUGCODE(savedCoordChange->fEffectRef.reset(fEffectRef.get());)
+ }
+
+ /**
+ * This balances the saveCoordChange call.
+ */
+ void restoreCoordChange(const SavedCoordChange& savedCoordChange) {
+ fCoordChangeMatrixSet = savedCoordChange.fCoordChangeMatrixSet;
+ if (fCoordChangeMatrixSet) {
+ fCoordChangeMatrix = savedCoordChange.fCoordChangeMatrix;
+ }
+ GrAssert(savedCoordChange.fEffectRef.get() == fEffectRef);
+ GR_DEBUGCODE(savedCoordChange.fEffectRef.reset(NULL);)
+ }
+
+ /**
+ * Used when storing a deferred GrDrawState. The DeferredStage allows resources owned by its
+ * GrEffect to be recycled through the cache.
+ */
+ class DeferredStage {
+ public:
+ DeferredStage() : fEffect(NULL) {
+ SkDEBUGCODE(fInitialized = false;)
+ }
+
+ ~DeferredStage() {
+ if (NULL != fEffect) {
+ fEffect->decDeferredRefCounts();
+ }
+ }
+
+ void saveFrom(const GrEffectStage& stage) {
+ GrAssert(!fInitialized);
+ GrAssert(NULL != stage.fEffectRef.get());
+ stage.fEffectRef->get()->incDeferredRefCounts();
+ fEffect = stage.fEffectRef->get();
+ fCoordChangeMatrixSet = stage.fCoordChangeMatrixSet;
+ if (fCoordChangeMatrixSet) {
+ fCoordChangeMatrix = stage.fCoordChangeMatrix;
+ }
+ fVertexAttribIndices[0] = stage.fVertexAttribIndices[0];
+ fVertexAttribIndices[1] = stage.fVertexAttribIndices[1];
+ SkDEBUGCODE(fInitialized = true;)
+ }
+
+ void restoreTo(GrEffectStage* stage) const {
+ GrAssert(fInitialized);
+ stage->fEffectRef.reset(GrEffect::CreateEffectRef(fEffect));
+ stage->fCoordChangeMatrixSet = fCoordChangeMatrixSet;
+ if (fCoordChangeMatrixSet) {
+ stage->fCoordChangeMatrix = fCoordChangeMatrix;
+ }
+ stage->fVertexAttribIndices[0] = fVertexAttribIndices[0];
+ stage->fVertexAttribIndices[1] = fVertexAttribIndices[1];
+ }
+
+ bool isEqual(const GrEffectStage& stage, bool ignoreCoordChange) const {
+ if (fVertexAttribIndices[0] != stage.fVertexAttribIndices[0] ||
+ fVertexAttribIndices[1] != stage.fVertexAttribIndices[1]) {
+ return false;
+ }
+
+ if (!(*stage.getEffect())->isEqual(*fEffect)) {
+ return false;
+ }
+
+ if (ignoreCoordChange) {
+ // ignore the coordinate change matrix since there are
+ // explicit uv coordinates
+ return true;
+ }
+
+ if (fCoordChangeMatrixSet != stage.fCoordChangeMatrixSet) {
+ return false;
+ }
+
+ if (!fCoordChangeMatrixSet) {
+ return true;
+ }
+
+ return fCoordChangeMatrix == stage.fCoordChangeMatrix;
+ }
+
+ private:
+ const GrEffect* fEffect;
+ bool fCoordChangeMatrixSet;
+ SkMatrix fCoordChangeMatrix;
+ int fVertexAttribIndices[2];
+ SkDEBUGCODE(bool fInitialized;)
+ };
+
+ /**
+ * Gets the matrix representing all changes of coordinate system since the GrEffect was
+ * installed in the stage.
+ */
+ const SkMatrix& getCoordChangeMatrix() const {
+ if (fCoordChangeMatrixSet) {
+ return fCoordChangeMatrix;
+ } else {
+ return SkMatrix::I();
+ }
+ }
+
+ const GrEffectRef* getEffect() const { return fEffectRef.get(); }
+
+ const int* getVertexAttribIndices() const { return fVertexAttribIndices; }
+ int getVertexAttribIndexCount() const { return fEffectRef->get()->numVertexAttribs(); }
+
+private:
+ bool fCoordChangeMatrixSet;
+ SkMatrix fCoordChangeMatrix;
+ SkAutoTUnref<const GrEffectRef> fEffectRef;
+ int fVertexAttribIndices[2];
+};
+
+#endif
diff --git a/gpu/GrEffectUnitTest.h b/gpu/GrEffectUnitTest.h
new file mode 100644
index 0000000..557602f
--- /dev/null
+++ b/gpu/GrEffectUnitTest.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrEffectUnitTest_DEFINED
+#define GrEffectUnitTest_DEFINED
+
+#include "GrNoncopyable.h"
+#include "SkRandom.h"
+#include "SkTArray.h"
+
+class SkMatrix;
+class GrDrawTargetCaps;
+
+namespace GrEffectUnitTest {
+// Used to access the dummy textures in TestCreate procs.
+enum {
+ kSkiaPMTextureIdx = 0,
+ kAlphaTextureIdx = 1,
+};
+
+/**
+ * A helper for use in GrEffect::TestCreate functions.
+ */
+const SkMatrix& TestMatrix(SkMWCRandom*);
+
+}
+
+#if SK_ALLOW_STATIC_GLOBAL_INITIALIZERS
+
+class GrContext;
+class GrEffectRef;
+class GrTexture;
+
+class GrEffectTestFactory : GrNoncopyable {
+public:
+
+ typedef GrEffectRef* (*CreateProc)(SkMWCRandom*,
+ GrContext*,
+ const GrDrawTargetCaps& caps,
+ GrTexture* dummyTextures[]);
+
+ GrEffectTestFactory(CreateProc createProc) {
+ fCreateProc = createProc;
+ GetFactories()->push_back(this);
+ }
+
+ static GrEffectRef* CreateStage(SkMWCRandom* random,
+ GrContext* context,
+ const GrDrawTargetCaps& caps,
+ GrTexture* dummyTextures[]) {
+ uint32_t idx = random->nextRangeU(0, GetFactories()->count() - 1);
+ GrEffectTestFactory* factory = (*GetFactories())[idx];
+ return factory->fCreateProc(random, context, caps, dummyTextures);
+ }
+
+private:
+ CreateProc fCreateProc;
+ static SkTArray<GrEffectTestFactory*, true>* GetFactories();
+};
+
+/** GrEffect subclasses should insert this macro in their declaration to be included in the
+ * program generation unit test.
+ */
+#define GR_DECLARE_EFFECT_TEST \
+ static GrEffectTestFactory gTestFactory; \
+ static GrEffectRef* TestCreate(SkMWCRandom*, \
+ GrContext*, \
+ const GrDrawTargetCaps&, \
+ GrTexture* dummyTextures[2])
+
+/** GrEffect subclasses should insert this macro in their implementation file. They must then
+ * also implement this static function:
+ * GrEffect* TestCreate(SkMWCRandom*,
+ * GrContext*,
+ * const GrDrawTargetCaps&,
+ * GrTexture* dummyTextures[2]);
+ * dummyTextures[] are valid textures that can optionally be used to construct GrTextureAccesses.
+ * The first texture has config kSkia8888_GrPixelConfig and the second has
+ * kAlpha_8_GrPixelConfig. TestCreate functions are also free to create additional textures using
+ * the GrContext.
+ */
+#define GR_DEFINE_EFFECT_TEST(Effect) \
+ GrEffectTestFactory Effect :: gTestFactory(Effect :: TestCreate)
+
+#else // !SK_ALLOW_STATIC_GLOBAL_INITIALIZERS
+
+// The unit test relies on static initializers. Just declare the TestCreate function so that
+// its definitions will compile.
+#define GR_DECLARE_EFFECT_TEST \
+ static GrEffectRef* TestCreate(SkMWCRandom*, \
+ GrContext*, \
+ const GrDrawTargetCaps&, \
+ GrTexture* dummyTextures[2])
+#define GR_DEFINE_EFFECT_TEST(X)
+
+#endif // !SK_ALLOW_STATIC_GLOBAL_INITIALIZERS
+#endif
diff --git a/gpu/GrFontScaler.h b/gpu/GrFontScaler.h
new file mode 100644
index 0000000..f5dcf53
--- /dev/null
+++ b/gpu/GrFontScaler.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrFontScaler_DEFINED
+#define GrFontScaler_DEFINED
+
+#include "GrGlyph.h"
+#include "GrKey.h"
+
+class SkPath;
+
+/**
+ * This is a virtual base class which Gr's interface to the host platform's
+ * font scaler.
+ *
+ * The client is responsible for subclassing, and instantiating this. The
+ * instance is create for a specific font+size+matrix.
+ */
+class GrFontScaler : public GrRefCnt {
+public:
+ SK_DECLARE_INST_COUNT(GrFontScaler)
+
+ virtual const GrKey* getKey() = 0;
+ virtual GrMaskFormat getMaskFormat() = 0;
+ virtual bool getPackedGlyphBounds(GrGlyph::PackedID, SkIRect* bounds) = 0;
+ virtual bool getPackedGlyphImage(GrGlyph::PackedID, int width, int height,
+ int rowBytes, void* image) = 0;
+ virtual bool getGlyphPath(uint16_t glyphID, SkPath*) = 0;
+
+private:
+ typedef GrRefCnt INHERITED;
+};
+
+#endif
diff --git a/gpu/GrGlyph.h b/gpu/GrGlyph.h
new file mode 100644
index 0000000..c730f24
--- /dev/null
+++ b/gpu/GrGlyph.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrGlyph_DEFINED
+#define GrGlyph_DEFINED
+
+#include "GrRect.h"
+#include "SkPath.h"
+
+class GrAtlas;
+
+/* Need this to be quad-state:
+ - complete w/ image
+ - just metrics
+ - failed to get image, but has metrics
+ - failed to get metrics
+ */
+struct GrGlyph {
+ typedef uint32_t PackedID;
+
+ GrAtlas* fAtlas;
+ SkPath* fPath;
+ PackedID fPackedID;
+ GrIRect16 fBounds;
+ GrIPoint16 fAtlasLocation;
+
+ void init(GrGlyph::PackedID packed, const SkIRect& bounds) {
+ fAtlas = NULL;
+ fPath = NULL;
+ fPackedID = packed;
+ fBounds.set(bounds);
+ fAtlasLocation.set(0, 0);
+ }
+
+ void free() {
+ if (fPath) {
+ delete fPath;
+ fPath = NULL;
+ }
+ }
+
+ int width() const { return fBounds.width(); }
+ int height() const { return fBounds.height(); }
+ bool isEmpty() const { return fBounds.isEmpty(); }
+ uint16_t glyphID() const { return UnpackID(fPackedID); }
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ static inline unsigned ExtractSubPixelBitsFromFixed(GrFixed pos) {
+ // two most significant fraction bits from fixed-point
+ return (pos >> 14) & 3;
+ }
+
+ static inline PackedID Pack(uint16_t glyphID, GrFixed x, GrFixed y) {
+ x = ExtractSubPixelBitsFromFixed(x);
+ y = ExtractSubPixelBitsFromFixed(y);
+ return (x << 18) | (y << 16) | glyphID;
+ }
+
+ static inline GrFixed UnpackFixedX(PackedID packed) {
+ return ((packed >> 18) & 3) << 14;
+ }
+
+ static inline GrFixed UnpackFixedY(PackedID packed) {
+ return ((packed >> 16) & 3) << 14;
+ }
+
+ static inline uint16_t UnpackID(PackedID packed) {
+ return (uint16_t)packed;
+ }
+};
+
+
+#endif
diff --git a/gpu/GrKey.h b/gpu/GrKey.h
new file mode 100644
index 0000000..80eb537
--- /dev/null
+++ b/gpu/GrKey.h
@@ -0,0 +1,43 @@
+
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+
+#ifndef GrKey_DEFINED
+#define GrKey_DEFINED
+
+#include "GrRefCnt.h"
+
+class GrKey : public GrRefCnt {
+public:
+ SK_DECLARE_INST_COUNT(GrKey)
+
+ typedef intptr_t Hash;
+
+ explicit GrKey(Hash hash) : fHash(hash) {}
+
+ intptr_t getHash() const { return fHash; }
+
+ bool operator<(const GrKey& rh) const {
+ return fHash < rh.fHash || (fHash == rh.fHash && this->lt(rh));
+ }
+ bool operator==(const GrKey& rh) const {
+ return fHash == rh.fHash && this->eq(rh);
+ }
+
+protected:
+ virtual bool lt(const GrKey& rh) const = 0;
+ virtual bool eq(const GrKey& rh) const = 0;
+
+private:
+ const Hash fHash;
+
+ typedef GrRefCnt INHERITED;
+};
+
+#endif
diff --git a/gpu/GrNoncopyable.h b/gpu/GrNoncopyable.h
new file mode 100644
index 0000000..3d47170
--- /dev/null
+++ b/gpu/GrNoncopyable.h
@@ -0,0 +1,30 @@
+
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+
+#ifndef GrNoncopyable_DEFINED
+#define GrNoncopyable_DEFINED
+
+#include "GrTypes.h"
+
+/**
+ * Base for classes that want to disallow copying themselves. It makes its
+ * copy-constructor and assignment operators private (and unimplemented).
+ */
+class GR_API GrNoncopyable {
+public:
+ GrNoncopyable() {}
+
+private:
+ // illegal
+ GrNoncopyable(const GrNoncopyable&);
+ GrNoncopyable& operator=(const GrNoncopyable&);
+};
+
+#endif
diff --git a/gpu/GrOvalRenderer.h b/gpu/GrOvalRenderer.h
new file mode 100644
index 0000000..08d3d3d
--- /dev/null
+++ b/gpu/GrOvalRenderer.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrOvalRenderer_DEFINED
+#define GrOvalRenderer_DEFINED
+
+#include "GrContext.h"
+#include "GrPaint.h"
+#include "GrRefCnt.h"
+
+class GrContext;
+class GrDrawTarget;
+class GrPaint;
+struct SkRect;
+class SkStrokeRec;
+
+/*
+ * This class wraps helper functions that draw ovals and roundrects (filled & stroked)
+ */
+class GrOvalRenderer : public GrRefCnt {
+public:
+ SK_DECLARE_INST_COUNT(GrOvalRenderer)
+
+ GrOvalRenderer() : fRRectIndexBuffer(NULL) {}
+ ~GrOvalRenderer() {
+ this->reset();
+ }
+
+ void reset();
+
+ bool drawOval(GrDrawTarget* target, const GrContext* context, bool useAA,
+ const SkRect& oval, const SkStrokeRec& stroke);
+ bool drawSimpleRRect(GrDrawTarget* target, GrContext* context, bool useAA,
+ const SkRRect& rrect, const SkStrokeRec& stroke);
+
+private:
+ bool drawEllipse(GrDrawTarget* target, bool useAA,
+ const SkRect& ellipse,
+ const SkStrokeRec& stroke);
+ void drawCircle(GrDrawTarget* target, bool useAA,
+ const SkRect& circle,
+ const SkStrokeRec& stroke);
+
+ GrIndexBuffer* rRectIndexBuffer(GrGpu* gpu);
+
+ GrIndexBuffer* fRRectIndexBuffer;
+
+ typedef GrRefCnt INHERITED;
+};
+
+#endif // GrOvalRenderer_DEFINED
diff --git a/gpu/GrPaint.h b/gpu/GrPaint.h
new file mode 100644
index 0000000..9e326f0
--- /dev/null
+++ b/gpu/GrPaint.h
@@ -0,0 +1,254 @@
+
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef GrPaint_DEFINED
+#define GrPaint_DEFINED
+
+#include "GrColor.h"
+#include "GrEffectStage.h"
+
+#include "SkXfermode.h"
+
+/**
+ * The paint describes how color and coverage are computed at each pixel by GrContext draw
+ * functions and the how color is blended with the destination pixel.
+ *
+ * The paint allows installation of custom color and coverage stages. New types of stages are
+ * created by subclassing GrEffect.
+ *
+ * The primitive color computation starts with the color specified by setColor(). This color is the
+ * input to the first color stage. Each color stage feeds its output to the next color stage. The
+ * final color stage's output color is input to the color filter specified by
+ * setXfermodeColorFilter which produces the final source color, S.
+ *
+ * Fractional pixel coverage follows a similar flow. The coverage is initially the value specified
+ * by setCoverage(). This is input to the first coverage stage. Coverage stages are chained
+ * together in the same manner as color stages. The output of the last stage is modulated by any
+ * fractional coverage produced by anti-aliasing. This last step produces the final coverage, C.
+ *
+ * setBlendFunc() specifies blending coefficients for S (described above) and D, the initial value
+ * of the destination pixel, labeled Bs and Bd respectively. The final value of the destination
+ * pixel is then D' = (1-C)*D + C*(Bd*D + Bs*S).
+ *
+ * Note that the coverage is applied after the blend. This is why they are computed as distinct
+ * values.
+ *
+ * TODO: Encapsulate setXfermodeColorFilter in a GrEffect and remove from GrPaint.
+ */
+class GrPaint {
+public:
+ GrPaint() { this->reset(); }
+
+ GrPaint(const GrPaint& paint) { *this = paint; }
+
+ ~GrPaint() {}
+
+ /**
+ * Sets the blending coefficients to use to blend the final primitive color with the
+ * destination color. Defaults to kOne for src and kZero for dst (i.e. src mode).
+ */
+ void setBlendFunc(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) {
+ fSrcBlendCoeff = srcCoeff;
+ fDstBlendCoeff = dstCoeff;
+ }
+ GrBlendCoeff getSrcBlendCoeff() const { return fSrcBlendCoeff; }
+ GrBlendCoeff getDstBlendCoeff() const { return fDstBlendCoeff; }
+
+ /**
+ * The initial color of the drawn primitive. Defaults to solid white.
+ */
+ void setColor(GrColor color) { fColor = color; }
+ GrColor getColor() const { return fColor; }
+
+ /**
+ * Applies fractional coverage to the entire drawn primitive. Defaults to 0xff.
+ */
+ void setCoverage(uint8_t coverage) { fCoverage = coverage; }
+ uint8_t getCoverage() const { return fCoverage; }
+
+ /**
+ * Should primitives be anti-aliased or not. Defaults to false.
+ */
+ void setAntiAlias(bool aa) { fAntiAlias = aa; }
+ bool isAntiAlias() const { return fAntiAlias; }
+
+ /**
+ * Should dithering be applied. Defaults to false.
+ */
+ void setDither(bool dither) { fDither = dither; }
+ bool isDither() const { return fDither; }
+
+ /**
+ * Enables a SkXfermode::Mode-based color filter applied to the primitive color. The constant
+ * color passed to this function is considered the "src" color and the primitive's color is
+ * considered the "dst" color. Defaults to kDst_Mode which equates to simply passing through
+ * the primitive color unmodified.
+ */
+ void setXfermodeColorFilter(SkXfermode::Mode mode, GrColor color) {
+ fColorFilterColor = color;
+ fColorFilterXfermode = mode;
+ }
+ SkXfermode::Mode getColorFilterMode() const { return fColorFilterXfermode; }
+ GrColor getColorFilterColor() const { return fColorFilterColor; }
+
+ /**
+ * Disables the SkXfermode::Mode color filter.
+ */
+ void resetColorFilter() {
+ fColorFilterXfermode = SkXfermode::kDst_Mode;
+ fColorFilterColor = GrColorPackRGBA(0xff, 0xff, 0xff, 0xff);
+ }
+
+ /**
+ * Appends an additional color effect to the color computation.
+ */
+ const GrEffectRef* addColorEffect(const GrEffectRef* effect, int attr0 = -1, int attr1 = -1) {
+ GrAssert(NULL != effect);
+ SkNEW_APPEND_TO_TARRAY(&fColorStages, GrEffectStage, (effect, attr0, attr1));
+ return effect;
+ }
+
+ /**
+ * Appends an additional coverage effect to the coverage computation.
+ */
+ const GrEffectRef* addCoverageEffect(const GrEffectRef* effect, int attr0 = -1, int attr1 = -1) {
+ GrAssert(NULL != effect);
+ SkNEW_APPEND_TO_TARRAY(&fCoverageStages, GrEffectStage, (effect, attr0, attr1));
+ return effect;
+ }
+
+ /**
+ * Helpers for adding color or coverage effects that sample a texture. The matrix is applied
+ * to the src space position to compute texture coordinates.
+ */
+ void addColorTextureEffect(GrTexture* texture, const SkMatrix& matrix);
+ void addCoverageTextureEffect(GrTexture* texture, const SkMatrix& matrix);
+
+ void addColorTextureEffect(GrTexture* texture,
+ const SkMatrix& matrix,
+ const GrTextureParams& params);
+ void addCoverageTextureEffect(GrTexture* texture,
+ const SkMatrix& matrix,
+ const GrTextureParams& params);
+
+ int numColorStages() const { return fColorStages.count(); }
+ int numCoverageStages() const { return fCoverageStages.count(); }
+ int numTotalStages() const { return this->numColorStages() + this->numCoverageStages(); }
+
+ const GrEffectStage& getColorStage(int s) const { return fColorStages[s]; }
+ const GrEffectStage& getCoverageStage(int s) const { return fCoverageStages[s]; }
+
+ GrPaint& operator=(const GrPaint& paint) {
+ fSrcBlendCoeff = paint.fSrcBlendCoeff;
+ fDstBlendCoeff = paint.fDstBlendCoeff;
+ fAntiAlias = paint.fAntiAlias;
+ fDither = paint.fDither;
+
+ fColor = paint.fColor;
+ fCoverage = paint.fCoverage;
+
+ fColorFilterColor = paint.fColorFilterColor;
+ fColorFilterXfermode = paint.fColorFilterXfermode;
+
+ fColorStages = paint.fColorStages;
+ fCoverageStages = paint.fCoverageStages;
+
+ return *this;
+ }
+
+ /**
+ * Resets the paint to the defaults.
+ */
+ void reset() {
+ this->resetBlend();
+ this->resetOptions();
+ this->resetColor();
+ this->resetCoverage();
+ this->resetStages();
+ this->resetColorFilter();
+ }
+
+private:
+ /**
+ * Called when the source coord system from which geometry is rendered changes. It ensures that
+ * the local coordinates seen by effects remains unchanged. oldToNew gives the transformation
+ * from the previous coord system to the new coord system.
+ */
+ void localCoordChange(const SkMatrix& oldToNew) {
+ for (int i = 0; i < fColorStages.count(); ++i) {
+ fColorStages[i].localCoordChange(oldToNew);
+ }
+ for (int i = 0; i < fCoverageStages.count(); ++i) {
+ fCoverageStages[i].localCoordChange(oldToNew);
+ }
+ }
+
+ bool localCoordChangeInverse(const SkMatrix& newToOld) {
+ SkMatrix oldToNew;
+ bool computed = false;
+ for (int i = 0; i < fColorStages.count(); ++i) {
+ if (!computed && !newToOld.invert(&oldToNew)) {
+ return false;
+ } else {
+ computed = true;
+ }
+ fColorStages[i].localCoordChange(oldToNew);
+ }
+ for (int i = 0; i < fCoverageStages.count(); ++i) {
+ if (!computed && !newToOld.invert(&oldToNew)) {
+ return false;
+ } else {
+ computed = true;
+ }
+ fCoverageStages[i].localCoordChange(oldToNew);
+ }
+ return true;
+ }
+
+ friend class GrContext; // To access above two functions
+
+ SkSTArray<4, GrEffectStage> fColorStages;
+ SkSTArray<2, GrEffectStage> fCoverageStages;
+
+ GrBlendCoeff fSrcBlendCoeff;
+ GrBlendCoeff fDstBlendCoeff;
+ bool fAntiAlias;
+ bool fDither;
+
+ GrColor fColor;
+ uint8_t fCoverage;
+
+ GrColor fColorFilterColor;
+ SkXfermode::Mode fColorFilterXfermode;
+
+ void resetBlend() {
+ fSrcBlendCoeff = kOne_GrBlendCoeff;
+ fDstBlendCoeff = kZero_GrBlendCoeff;
+ }
+
+ void resetOptions() {
+ fAntiAlias = false;
+ fDither = false;
+ }
+
+ void resetColor() {
+ fColor = GrColorPackRGBA(0xff, 0xff, 0xff, 0xff);
+ }
+
+ void resetCoverage() {
+ fCoverage = 0xff;
+ }
+
+ void resetStages() {
+ fColorStages.reset();
+ fCoverageStages.reset();
+ }
+};
+
+#endif
diff --git a/gpu/GrPathRendererChain.h b/gpu/GrPathRendererChain.h
new file mode 100644
index 0000000..d51a4bb
--- /dev/null
+++ b/gpu/GrPathRendererChain.h
@@ -0,0 +1,83 @@
+
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef GrPathRendererChain_DEFINED
+#define GrPathRendererChain_DEFINED
+
+#include "GrRefCnt.h"
+#include "SkTArray.h"
+
+class GrContext;
+class GrDrawTarget;
+class GrPathRenderer;
+class SkPath;
+class SkStrokeRec;
+
+/**
+ * Keeps track of an ordered list of path renderers. When a path needs to be
+ * drawn this list is scanned to find the most preferred renderer. To add your
+ * path renderer to the list implement the GrPathRenderer::AddPathRenderers
+ * function.
+ */
+class GrPathRendererChain : public SkRefCnt {
+public:
+ // See comments in GrPathRenderer.h
+ enum StencilSupport {
+ kNoSupport_StencilSupport,
+ kStencilOnly_StencilSupport,
+ kNoRestriction_StencilSupport,
+ };
+
+ SK_DECLARE_INST_COUNT(GrPathRendererChain)
+
+ GrPathRendererChain(GrContext* context);
+
+ ~GrPathRendererChain();
+
+ // takes a ref and unrefs in destructor
+ GrPathRenderer* addPathRenderer(GrPathRenderer* pr);
+
+ /** Documents how the caller plans to use a GrPathRenderer to draw a path. It affects the PR
+ returned by getPathRenderer */
+ enum DrawType {
+ kColor_DrawType, // draw to the color buffer, no AA
+ kColorAntiAlias_DrawType, // draw to color buffer, with partial coverage AA
+ kStencilOnly_DrawType, // draw just to the stencil buffer
+ kStencilAndColor_DrawType, // draw the stencil and color buffer, no AA
+ kStencilAndColorAntiAlias_DrawType // draw the stencil and color buffer, with partial
+ // coverage AA.
+ };
+ /** Returns a GrPathRenderer compatible with the request if one is available. If the caller
+ is drawing the path to the stencil buffer then stencilSupport can be used to determine
+ whether the path can be rendered with arbitrary stencil rules or not. See comments on
+ StencilSupport in GrPathRenderer.h. */
+ GrPathRenderer* getPathRenderer(const SkPath& path,
+ const SkStrokeRec& rec,
+ const GrDrawTarget* target,
+ DrawType drawType,
+ StencilSupport* stencilSupport);
+
+private:
+
+ GrPathRendererChain();
+
+ void init();
+
+ enum {
+ kPreAllocCount = 8,
+ };
+ bool fInit;
+ GrContext* fOwner;
+ SkSTArray<kPreAllocCount, GrPathRenderer*, true> fChain;
+
+ typedef SkRefCnt INHERITED;
+};
+
+
+#endif
diff --git a/gpu/GrPoint.h b/gpu/GrPoint.h
new file mode 100644
index 0000000..c987b01
--- /dev/null
+++ b/gpu/GrPoint.h
@@ -0,0 +1,30 @@
+
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+
+#ifndef GrPoint_DEFINED
+#define GrPoint_DEFINED
+
+#include "GrTypes.h"
+#include "SkScalar.h"
+#include "SkPoint.h"
+
+#define GrPoint SkPoint
+#define GrVec SkVector
+
+struct GrIPoint16 {
+ int16_t fX, fY;
+
+ void set(intptr_t x, intptr_t y) {
+ fX = GrToS16(x);
+ fY = GrToS16(y);
+ }
+};
+
+#endif
diff --git a/gpu/GrRect.h b/gpu/GrRect.h
new file mode 100644
index 0000000..cacc511
--- /dev/null
+++ b/gpu/GrRect.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrRect_DEFINED
+#define GrRect_DEFINED
+
+#include "SkTypes.h"
+#include "SkRect.h"
+
+struct GrIRect16 {
+ int16_t fLeft, fTop, fRight, fBottom;
+
+ int width() const { return fRight - fLeft; }
+ int height() const { return fBottom - fTop; }
+ int area() const { return this->width() * this->height(); }
+ bool isEmpty() const { return fLeft >= fRight || fTop >= fBottom; }
+
+ void set(const SkIRect& r) {
+ fLeft = SkToS16(r.fLeft);
+ fTop = SkToS16(r.fTop);
+ fRight = SkToS16(r.fRight);
+ fBottom = SkToS16(r.fBottom);
+ }
+};
+
+#endif
diff --git a/gpu/GrRefCnt.h b/gpu/GrRefCnt.h
new file mode 100644
index 0000000..31aa80d
--- /dev/null
+++ b/gpu/GrRefCnt.h
@@ -0,0 +1,33 @@
+
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+
+#ifndef GrRefCnt_DEFINED
+#define GrRefCnt_DEFINED
+
+#include "GrTypes.h"
+#include "SkRefCnt.h"
+
+typedef SkRefCnt GrRefCnt;
+typedef SkAutoRef GrAutoRef;
+typedef SkAutoUnref GrAutoUnref;
+
+#define GrSafeRef SkSafeRef
+#define GrSafeUnref SkSafeUnref
+#define GrSafeAssign(a, b) SkRefCnt_SafeAssign(a, b)
+
+template<typename T>
+static inline void GrSafeSetNull(T*& obj) {
+ if (NULL != obj) {
+ obj->unref();
+ obj = NULL;
+ }
+}
+
+#endif
diff --git a/gpu/GrRenderTarget.h b/gpu/GrRenderTarget.h
new file mode 100644
index 0000000..eab65b5
--- /dev/null
+++ b/gpu/GrRenderTarget.h
@@ -0,0 +1,171 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrRenderTarget_DEFINED
+#define GrRenderTarget_DEFINED
+
+#include "GrSurface.h"
+#include "SkRect.h"
+
+class GrStencilBuffer;
+class GrTexture;
+
+/**
+ * GrRenderTarget represents a 2D buffer of pixels that can be rendered to.
+ * A context's render target is set by setRenderTarget(). Render targets are
+ * created by a createTexture with the kRenderTarget_TextureFlag flag.
+ * Additionally, GrContext provides methods for creating GrRenderTargets
+ * that wrap externally created render targets.
+ */
+class GrRenderTarget : public GrSurface {
+public:
+ SK_DECLARE_INST_COUNT(GrRenderTarget)
+
+ // GrResource overrides
+ virtual size_t sizeInBytes() const SK_OVERRIDE;
+
+ // GrSurface overrides
+ /**
+ * @return the texture associated with the render target, may be NULL.
+ */
+ virtual GrTexture* asTexture() SK_OVERRIDE { return fTexture; }
+ virtual const GrTexture* asTexture() const SK_OVERRIDE { return fTexture; }
+
+ /**
+ * @return this render target.
+ */
+ virtual GrRenderTarget* asRenderTarget() SK_OVERRIDE { return this; }
+ virtual const GrRenderTarget* asRenderTarget() const SK_OVERRIDE {
+ return this;
+ }
+
+ virtual bool readPixels(int left, int top, int width, int height,
+ GrPixelConfig config,
+ void* buffer,
+ size_t rowBytes = 0,
+ uint32_t pixelOpsFlags = 0) SK_OVERRIDE;
+
+ virtual void writePixels(int left, int top, int width, int height,
+ GrPixelConfig config,
+ const void* buffer,
+ size_t rowBytes = 0,
+ uint32_t pixelOpsFlags = 0) SK_OVERRIDE;
+
+ // GrRenderTarget
+ /**
+ * If this RT is multisampled, this is the multisample buffer
+ * @return the 3D API's handle to this object (e.g. FBO ID in OpenGL)
+ */
+ virtual GrBackendObject getRenderTargetHandle() const = 0;
+
+ /**
+ * If this RT is multisampled, this is the buffer it is resolved to.
+ * Otherwise, same as getRenderTargetHandle().
+ * (In GL a separate FBO ID is used for the MSAA and resolved buffers)
+ * @return the 3D API's handle to this object (e.g. FBO ID in OpenGL)
+ */
+ virtual GrBackendObject getRenderTargetResolvedHandle() const = 0;
+
+ /**
+ * @return true if the surface is multisampled, false otherwise
+ */
+ bool isMultisampled() const { return 0 != fDesc.fSampleCnt; }
+
+ /**
+ * @return the number of samples-per-pixel or zero if non-MSAA.
+ */
+ int numSamples() const { return fDesc.fSampleCnt; }
+
+ /**
+ * Call to indicate the multisample contents were modified such that the
+ * render target needs to be resolved before it can be used as texture. Gr
+ * tracks this for its own drawing and thus this only needs to be called
+ * when the render target has been modified outside of Gr. This has no
+ * effect on wrapped backend render targets.
+ *
+ * @param rect a rect bounding the area needing resolve. NULL indicates
+ * the whole RT needs resolving.
+ */
+ void flagAsNeedingResolve(const SkIRect* rect = NULL);
+
+ /**
+ * Call to override the region that needs to be resolved.
+ */
+ void overrideResolveRect(const SkIRect rect);
+
+ /**
+ * Call to indicate that GrRenderTarget was externally resolved. This may
+ * allow Gr to skip a redundant resolve step.
+ */
+ void flagAsResolved() { fResolveRect.setLargestInverted(); }
+
+ /**
+ * @return true if the GrRenderTarget requires MSAA resolving
+ */
+ bool needsResolve() const { return !fResolveRect.isEmpty(); }
+
+ /**
+ * Returns a rect bounding the region needing resolving.
+ */
+ const SkIRect& getResolveRect() const { return fResolveRect; }
+
+ /**
+ * If the render target is multisampled this will perform a multisample
+ * resolve. Any pending draws to the target are first flushed. This only
+ * applies to render targets that are associated with GrTextures. After the
+ * function returns the GrTexture will contain the resolved pixels.
+ */
+ void resolve();
+
+ // a MSAA RT may require explicit resolving , it may auto-resolve (e.g. FBO
+ // 0 in GL), or be unresolvable because the client didn't give us the
+ // resolve destination.
+ enum ResolveType {
+ kCanResolve_ResolveType,
+ kAutoResolves_ResolveType,
+ kCantResolve_ResolveType,
+ };
+ virtual ResolveType getResolveType() const = 0;
+
+ /**
+ * GrStencilBuffer is not part of the public API.
+ */
+ GrStencilBuffer* getStencilBuffer() const { return fStencilBuffer; }
+ void setStencilBuffer(GrStencilBuffer* stencilBuffer);
+
+protected:
+ GrRenderTarget(GrGpu* gpu,
+ bool isWrapped,
+ GrTexture* texture,
+ const GrTextureDesc& desc)
+ : INHERITED(gpu, isWrapped, desc)
+ , fStencilBuffer(NULL)
+ , fTexture(texture) {
+ fResolveRect.setLargestInverted();
+ }
+
+ // override of GrResource
+ virtual void onAbandon() SK_OVERRIDE;
+ virtual void onRelease() SK_OVERRIDE;
+
+private:
+ friend class GrTexture;
+ // called by ~GrTexture to remove the non-ref'ed back ptr.
+ void owningTextureDestroyed() {
+ GrAssert(NULL != fTexture);
+ fTexture = NULL;
+ }
+
+ GrStencilBuffer* fStencilBuffer;
+ GrTexture* fTexture; // not ref'ed
+
+ SkIRect fResolveRect;
+
+ typedef GrSurface INHERITED;
+};
+
+#endif
diff --git a/gpu/GrResource.h b/gpu/GrResource.h
new file mode 100644
index 0000000..72e6928
--- /dev/null
+++ b/gpu/GrResource.h
@@ -0,0 +1,117 @@
+
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef GrResource_DEFINED
+#define GrResource_DEFINED
+
+#include "GrRefCnt.h"
+
+#include "SkTInternalLList.h"
+
+class GrGpu;
+class GrContext;
+class GrResourceEntry;
+
+/**
+ * Base class for the GPU resources created by a GrContext.
+ */
+class GrResource : public GrRefCnt {
+public:
+ SK_DECLARE_INST_COUNT(GrResource)
+
+ /**
+ * Frees the resource in the underlying 3D API. It must be safe to call this
+ * when the resource has been previously abandoned.
+ */
+ void release();
+
+ /**
+ * Removes references to objects in the underlying 3D API without freeing
+ * them. Used when the API context has been torn down before the GrContext.
+ */
+ void abandon();
+
+ /**
+ * Tests whether a resource has been abandoned or released. All resources
+ * will be in this state after their creating GrContext is destroyed or has
+ * contextLost called. It's up to the client to test isValid() before
+ * attempting to use a resource if it holds refs on resources across
+ * ~GrContext, freeResources with the force flag, or contextLost.
+ *
+ * @return true if the resource has been released or abandoned,
+ * false otherwise.
+ */
+ bool isValid() const { return NULL != fGpu; }
+
+ /**
+ * Retrieves the size of the object in GPU memory. This is approximate since
+ * we aren't aware of additional padding or copies made by the driver.
+ *
+ * @return the size of the buffer in bytes
+ */
+ virtual size_t sizeInBytes() const = 0;
+
+ /**
+ * Retrieves the context that owns the resource. Note that it is possible
+ * for this to return NULL. When resources have been release()ed or
+ * abandon()ed they no longer have an owning context. Destroying a
+ * GrContext automatically releases all its resources.
+ */
+ const GrContext* getContext() const;
+ GrContext* getContext();
+
+ void setCacheEntry(GrResourceEntry* cacheEntry) { fCacheEntry = cacheEntry; }
+ GrResourceEntry* getCacheEntry() { return fCacheEntry; }
+
+ void incDeferredRefCount() const { GrAssert(fDeferredRefCount >= 0); ++fDeferredRefCount; }
+ void decDeferredRefCount() const { GrAssert(fDeferredRefCount > 0); --fDeferredRefCount; }
+
+protected:
+ /**
+ * isWrapped indicates we have wrapped a client-created backend resource in a GrResource. If it
+ * is true then the client is responsible for the lifetime of the underlying backend resource.
+ * Otherwise, our onRelease() should free the resource.
+ */
+ GrResource(GrGpu* gpu, bool isWrapped);
+ virtual ~GrResource();
+
+ GrGpu* getGpu() const { return fGpu; }
+
+ // Derived classes should always call their parent class' onRelease
+ // and onAbandon methods in their overrides.
+ virtual void onRelease() {};
+ virtual void onAbandon() {};
+
+ bool isInCache() const { return NULL != fCacheEntry; }
+ bool isWrapped() const { return kWrapped_Flag & fFlags; }
+
+private:
+#if GR_DEBUG
+ friend class GrGpu; // for assert in GrGpu to access getGpu
+#endif
+
+ // We're in an internal doubly linked list
+ SK_DECLARE_INTERNAL_LLIST_INTERFACE(GrResource);
+
+ GrGpu* fGpu; // not reffed. The GrGpu can be deleted while there
+ // are still live GrResources. It will call
+ // release() on all such resources in its
+ // destructor.
+ GrResourceEntry* fCacheEntry; // NULL if not in cache
+ mutable int fDeferredRefCount; // How many references in deferred drawing buffers.
+
+ enum Flags {
+ kWrapped_Flag = 0x1,
+ };
+ uint32_t fFlags;
+
+ typedef GrRefCnt INHERITED;
+};
+
+#endif
diff --git a/gpu/GrSurface.h b/gpu/GrSurface.h
new file mode 100644
index 0000000..52a5665
--- /dev/null
+++ b/gpu/GrSurface.h
@@ -0,0 +1,134 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef GrSurface_DEFINED
+#define GrSurface_DEFINED
+
+#include "GrTypes.h"
+#include "GrResource.h"
+
+class GrTexture;
+class GrRenderTarget;
+
+class GrSurface : public GrResource {
+public:
+ SK_DECLARE_INST_COUNT(GrSurface);
+
+ /**
+ * Retrieves the width of the surface.
+ *
+ * @return the width in texels
+ */
+ int width() const { return fDesc.fWidth; }
+
+ /**
+ * Retrieves the height of the surface.
+ *
+ * @return the height in texels
+ */
+ int height() const { return fDesc.fHeight; }
+
+ GrSurfaceOrigin origin() const {
+ GrAssert(kTopLeft_GrSurfaceOrigin == fDesc.fOrigin || kBottomLeft_GrSurfaceOrigin == fDesc.fOrigin);
+ return fDesc.fOrigin;
+ }
+
+ /**
+ * Retrieves the pixel config specified when the surface was created.
+ * For render targets this can be kUnknown_GrPixelConfig
+ * if client asked us to render to a target that has a pixel
+ * config that isn't equivalent with one of our configs.
+ */
+ GrPixelConfig config() const { return fDesc.fConfig; }
+
+ /**
+ * Return the descriptor describing the surface
+ */
+ const GrTextureDesc& desc() const { return fDesc; }
+
+ /**
+ * @return the texture associated with the surface, may be NULL.
+ */
+ virtual GrTexture* asTexture() = 0;
+ virtual const GrTexture* asTexture() const = 0;
+
+ /**
+ * @return the render target underlying this surface, may be NULL.
+ */
+ virtual GrRenderTarget* asRenderTarget() = 0;
+ virtual const GrRenderTarget* asRenderTarget() const = 0;
+
+ /**
+ * Checks whether this GrSurface refers to the same GPU object as other. This
+ * catches the case where a GrTexture and GrRenderTarget refer to the same
+ * GPU memory.
+ */
+ bool isSameAs(const GrSurface* other) const {
+ const GrRenderTarget* thisRT = this->asRenderTarget();
+ if (NULL != thisRT) {
+ return thisRT == other->asRenderTarget();
+ } else {
+ const GrTexture* thisTex = this->asTexture();
+ GrAssert(NULL != thisTex); // We must be one or the other
+ return thisTex == other->asTexture();
+ }
+ }
+
+ /**
+ * Reads a rectangle of pixels from the surface.
+ * @param left left edge of the rectangle to read (inclusive)
+ * @param top top edge of the rectangle to read (inclusive)
+ * @param width width of rectangle to read in pixels.
+ * @param height height of rectangle to read in pixels.
+ * @param config the pixel config of the destination buffer
+ * @param buffer memory to read the rectangle into.
+ * @param rowBytes number of bytes between consecutive rows. Zero means rows are tightly
+ * packed.
+ * @param pixelOpsFlags See the GrContext::PixelOpsFlags enum.
+ *
+ * @return true if the read succeeded, false if not. The read can fail because of an unsupported
+ * pixel config.
+ */
+ virtual bool readPixels(int left, int top, int width, int height,
+ GrPixelConfig config,
+ void* buffer,
+ size_t rowBytes = 0,
+ uint32_t pixelOpsFlags = 0) = 0;
+
+ /**
+ * Copy the src pixels [buffer, rowbytes, pixelconfig] into the surface at the specified
+ * rectangle.
+ * @param left left edge of the rectangle to write (inclusive)
+ * @param top top edge of the rectangle to write (inclusive)
+ * @param width width of rectangle to write in pixels.
+ * @param height height of rectangle to write in pixels.
+ * @param config the pixel config of the source buffer
+ * @param buffer memory to read the rectangle from.
+ * @param rowBytes number of bytes between consecutive rows. Zero means rows are tightly
+ * packed.
+ * @param pixelOpsFlags See the GrContext::PixelOpsFlags enum.
+ */
+ virtual void writePixels(int left, int top, int width, int height,
+ GrPixelConfig config,
+ const void* buffer,
+ size_t rowBytes = 0,
+ uint32_t pixelOpsFlags = 0) = 0;
+
+protected:
+ GrSurface(GrGpu* gpu, bool isWrapped, const GrTextureDesc& desc)
+ : INHERITED(gpu, isWrapped)
+ , fDesc(desc) {
+ }
+
+ GrTextureDesc fDesc;
+
+private:
+ typedef GrResource INHERITED;
+};
+
+#endif // GrSurface_DEFINED
diff --git a/gpu/GrTBackendEffectFactory.h b/gpu/GrTBackendEffectFactory.h
new file mode 100644
index 0000000..813f54b
--- /dev/null
+++ b/gpu/GrTBackendEffectFactory.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrTBackendEffectFactory_DEFINED
+#define GrTBackendEffectFactory_DEFINED
+
+#include "GrBackendEffectFactory.h"
+#include "GrDrawEffect.h"
+
+/**
+ * Implements GrBackendEffectFactory for a GrEffect subclass as a singleton.
+ */
+template <typename EffectClass>
+class GrTBackendEffectFactory : public GrBackendEffectFactory {
+
+public:
+ typedef typename EffectClass::GLEffect GLEffect;
+
+ /** Returns a human-readable name that is accessible via GrEffect or
+ GrGLEffect and is consistent between the two of them.
+ */
+ virtual const char* name() const SK_OVERRIDE { return EffectClass::Name(); }
+
+ /** Returns a value that identifies the GLSL shader code generated by
+ a GrEffect. This enables caching of generated shaders. Part of the
+ id identifies the GrEffect subclass. The remainder is based
+ on the aspects of the GrEffect object's configuration that affect
+ GLSL code generation. */
+ virtual EffectKey glEffectKey(const GrDrawEffect& drawEffect,
+ const GrGLCaps& caps) const SK_OVERRIDE {
+ GrAssert(kIllegalEffectClassID != fEffectClassID);
+ EffectKey effectKey = GLEffect::GenKey(drawEffect, caps);
+ EffectKey textureKey = GLEffect::GenTextureKey(drawEffect, caps);
+ EffectKey attribKey = GLEffect::GenAttribKey(drawEffect);
+#if GR_DEBUG
+ static const EffectKey kIllegalIDMask = (uint16_t) (~((1U << kEffectKeyBits) - 1));
+ GrAssert(!(kIllegalIDMask & effectKey));
+
+ static const EffectKey kIllegalTextureKeyMask = (uint16_t) (~((1U << kTextureKeyBits) - 1));
+ GrAssert(!(kIllegalTextureKeyMask & textureKey));
+
+ static const EffectKey kIllegalAttribKeyMask = (uint16_t) (~((1U << kAttribKeyBits) - 1));
+ GrAssert(!(kIllegalAttribKeyMask & textureKey));
+#endif
+ return fEffectClassID | (attribKey << (kEffectKeyBits+kTextureKeyBits)) |
+ (textureKey << kEffectKeyBits) | effectKey;
+ }
+
+ /** Returns a new instance of the appropriate *GL* implementation class
+ for the given GrEffect; caller is responsible for deleting
+ the object. */
+ virtual GLEffect* createGLInstance(const GrDrawEffect& drawEffect) const SK_OVERRIDE {
+ return SkNEW_ARGS(GLEffect, (*this, drawEffect));
+ }
+
+ /** This class is a singleton. This function returns the single instance.
+ */
+ static const GrBackendEffectFactory& getInstance() {
+ static SkAlignedSTStorage<1, GrTBackendEffectFactory> gInstanceMem;
+ static const GrTBackendEffectFactory* gInstance;
+ if (!gInstance) {
+ gInstance = SkNEW_PLACEMENT(gInstanceMem.get(),
+ GrTBackendEffectFactory);
+ }
+ return *gInstance;
+ }
+
+protected:
+ GrTBackendEffectFactory() {
+ fEffectClassID = GenID() << (kAttribKeyBits + kEffectKeyBits + kTextureKeyBits) ;
+ }
+};
+
+#endif
diff --git a/gpu/GrTextContext.h b/gpu/GrTextContext.h
new file mode 100644
index 0000000..5204da4
--- /dev/null
+++ b/gpu/GrTextContext.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrTextContext_DEFINED
+#define GrTextContext_DEFINED
+
+#include "GrContext.h"
+#include "GrGlyph.h"
+#include "GrPaint.h"
+
+class GrContext;
+class GrTextStrike;
+class GrFontScaler;
+class GrDrawTarget;
+
+class GrTextContext {
+public:
+ GrTextContext(GrContext*, const GrPaint&);
+ ~GrTextContext();
+
+ void drawPackedGlyph(GrGlyph::PackedID, GrFixed left, GrFixed top,
+ GrFontScaler*);
+
+ void flush(); // optional; automatically called by destructor
+
+private:
+ GrPaint fPaint;
+ GrContext* fContext;
+ GrDrawTarget* fDrawTarget;
+
+ GrFontScaler* fScaler;
+ GrTextStrike* fStrike;
+
+ inline void flushGlyphs();
+ void setupDrawTarget();
+
+ enum {
+ kMinRequestedGlyphs = 1,
+ kDefaultRequestedGlyphs = 64,
+ kMinRequestedVerts = kMinRequestedGlyphs * 4,
+ kDefaultRequestedVerts = kDefaultRequestedGlyphs * 4,
+ };
+
+ SkPoint* fVertices;
+ int32_t fMaxVertices;
+ GrTexture* fCurrTexture;
+ int fCurrVertex;
+
+ SkIRect fClipRect;
+ GrContext::AutoMatrix fAutoMatrix;
+};
+
+#endif
diff --git a/gpu/GrTexture.h b/gpu/GrTexture.h
new file mode 100644
index 0000000..1fb575c
--- /dev/null
+++ b/gpu/GrTexture.h
@@ -0,0 +1,213 @@
+
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrTexture_DEFINED
+#define GrTexture_DEFINED
+
+#include "GrSurface.h"
+#include "SkPoint.h"
+#include "GrRenderTarget.h"
+
+class GrResourceKey;
+class GrTextureParams;
+
+class GrTexture : public GrSurface {
+
+public:
+ SK_DECLARE_INST_COUNT(GrTexture)
+ // from GrResource
+ /**
+ * Informational texture flags
+ */
+ enum FlagBits {
+ kFirstBit = (kLastPublic_GrTextureFlagBit << 1),
+
+ /**
+ * This texture should be returned to the texture cache when
+ * it is no longer reffed
+ */
+ kReturnToCache_FlagBit = kFirstBit,
+ };
+
+ void setFlag(GrTextureFlags flags) {
+ fDesc.fFlags = fDesc.fFlags | flags;
+ }
+ void resetFlag(GrTextureFlags flags) {
+ fDesc.fFlags = fDesc.fFlags & ~flags;
+ }
+ bool isSetFlag(GrTextureFlags flags) const {
+ return 0 != (fDesc.fFlags & flags);
+ }
+
+ void dirtyMipMaps(bool mipMapsDirty) {
+ fMipMapsDirty = mipMapsDirty;
+ }
+
+ bool mipMapsAreDirty() const {
+ return fMipMapsDirty;
+ }
+
+ /**
+ * Approximate number of bytes used by the texture
+ */
+ virtual size_t sizeInBytes() const SK_OVERRIDE {
+ return (size_t) fDesc.fWidth *
+ fDesc.fHeight *
+ GrBytesPerPixel(fDesc.fConfig);
+ }
+
+ // GrSurface overrides
+ virtual bool readPixels(int left, int top, int width, int height,
+ GrPixelConfig config,
+ void* buffer,
+ size_t rowBytes = 0,
+ uint32_t pixelOpsFlags = 0) SK_OVERRIDE;
+
+ virtual void writePixels(int left, int top, int width, int height,
+ GrPixelConfig config,
+ const void* buffer,
+ size_t rowBytes = 0,
+ uint32_t pixelOpsFlags = 0) SK_OVERRIDE;
+
+ /**
+ * @return this texture
+ */
+ virtual GrTexture* asTexture() SK_OVERRIDE { return this; }
+ virtual const GrTexture* asTexture() const SK_OVERRIDE { return this; }
+
+ /**
+ * Retrieves the render target underlying this texture that can be passed to
+ * GrGpu::setRenderTarget().
+ *
+ * @return handle to render target or NULL if the texture is not a
+ * render target
+ */
+ virtual GrRenderTarget* asRenderTarget() SK_OVERRIDE {
+ return fRenderTarget.get();
+ }
+ virtual const GrRenderTarget* asRenderTarget() const SK_OVERRIDE {
+ return fRenderTarget.get();
+ }
+
+ // GrTexture
+ /**
+ * Convert from texels to normalized texture coords for POT textures
+ * only.
+ */
+ GrFixed normalizeFixedX(GrFixed x) const {
+ GrAssert(GrIsPow2(fDesc.fWidth));
+ return x >> fShiftFixedX;
+ }
+ GrFixed normalizeFixedY(GrFixed y) const {
+ GrAssert(GrIsPow2(fDesc.fHeight));
+ return y >> fShiftFixedY;
+ }
+
+ /**
+ * Return the native ID or handle to the texture, depending on the
+ * platform. e.g. on OpenGL, return the texture ID.
+ */
+ virtual GrBackendObject getTextureHandle() const = 0;
+
+ /**
+ * Call this when the state of the native API texture object is
+ * altered directly, without being tracked by skia.
+ */
+ virtual void invalidateCachedState() = 0;
+
+#if GR_DEBUG
+ void validate() const {
+ this->INHERITED::validate();
+
+ this->validateDesc();
+ }
+#else
+ void validate() const {}
+#endif
+ static GrResourceKey ComputeKey(const GrGpu* gpu,
+ const GrTextureParams* params,
+ const GrTextureDesc& desc,
+ const GrCacheID& cacheID);
+ static GrResourceKey ComputeScratchKey(const GrTextureDesc& desc);
+ static bool NeedsResizing(const GrResourceKey& key);
+ static bool NeedsBilerp(const GrResourceKey& key);
+
+protected:
+ // A texture refs its rt representation but not vice-versa. It is up to
+ // the subclass constructor to initialize this pointer.
+ SkAutoTUnref<GrRenderTarget> fRenderTarget;
+
+ GrTexture(GrGpu* gpu, bool isWrapped, const GrTextureDesc& desc)
+ : INHERITED(gpu, isWrapped, desc)
+ , fRenderTarget(NULL)
+ , fMipMapsDirty(true) {
+
+ // only make sense if alloc size is pow2
+ fShiftFixedX = 31 - SkCLZ(fDesc.fWidth);
+ fShiftFixedY = 31 - SkCLZ(fDesc.fHeight);
+ }
+ virtual ~GrTexture();
+
+ // GrResource overrides
+ virtual void onRelease() SK_OVERRIDE;
+ virtual void onAbandon() SK_OVERRIDE;
+
+ void validateDesc() const;
+
+private:
+ // these two shift a fixed-point value into normalized coordinates
+ // for this texture if the texture is power of two sized.
+ int fShiftFixedX;
+ int fShiftFixedY;
+
+ bool fMipMapsDirty;
+
+ virtual void internal_dispose() const SK_OVERRIDE;
+
+ typedef GrSurface INHERITED;
+};
+
+/**
+ * Represents a texture that is intended to be accessed in device coords with an offset.
+ */
+class GrDeviceCoordTexture {
+public:
+ GrDeviceCoordTexture() { fOffset.set(0, 0); }
+
+ GrDeviceCoordTexture(const GrDeviceCoordTexture& other) {
+ *this = other;
+ }
+
+ GrDeviceCoordTexture(GrTexture* texture, const SkIPoint& offset)
+ : fTexture(SkSafeRef(texture))
+ , fOffset(offset) {
+ }
+
+ GrDeviceCoordTexture& operator=(const GrDeviceCoordTexture& other) {
+ fTexture.reset(SkSafeRef(other.fTexture.get()));
+ fOffset = other.fOffset;
+ return *this;
+ }
+
+ const SkIPoint& offset() const { return fOffset; }
+
+ void setOffset(const SkIPoint& offset) { fOffset = offset; }
+ void setOffset(int ox, int oy) { fOffset.set(ox, oy); }
+
+ GrTexture* texture() const { return fTexture.get(); }
+
+ GrTexture* setTexture(GrTexture* texture) {
+ fTexture.reset(SkSafeRef(texture));
+ return texture;
+ }
+private:
+ SkAutoTUnref<GrTexture> fTexture;
+ SkIPoint fOffset;
+};
+
+#endif
diff --git a/gpu/GrTextureAccess.h b/gpu/GrTextureAccess.h
new file mode 100644
index 0000000..8100b7a
--- /dev/null
+++ b/gpu/GrTextureAccess.h
@@ -0,0 +1,188 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrTextureAccess_DEFINED
+#define GrTextureAccess_DEFINED
+
+#include "GrNoncopyable.h"
+#include "SkRefCnt.h"
+#include "SkShader.h"
+
+class GrTexture;
+
+/**
+ * Represents the filtering and tile modes used to access a texture. It is mostly used with
+ * GrTextureAccess (defined below). Also, some of the texture cache methods require knowledge about
+ * filtering and tiling to perform a cache lookup. If it wasn't for this latter usage this would
+ * be folded into GrTextureAccess.
+ */
+class GrTextureParams {
+public:
+ GrTextureParams() {
+ this->reset();
+ }
+
+ enum FilterMode {
+ kNone_FilterMode,
+ kBilerp_FilterMode,
+ kMipMap_FilterMode
+ };
+
+ GrTextureParams(SkShader::TileMode tileXAndY, FilterMode filterMode) {
+ this->reset(tileXAndY, filterMode);
+ }
+
+ GrTextureParams(SkShader::TileMode tileModes[2], FilterMode filterMode) {
+ this->reset(tileModes, filterMode);
+ }
+
+ GrTextureParams(const GrTextureParams& params) {
+ *this = params;
+ }
+
+ GrTextureParams& operator= (const GrTextureParams& params) {
+ fTileModes[0] = params.fTileModes[0];
+ fTileModes[1] = params.fTileModes[1];
+ fFilterMode = params.fFilterMode;
+ return *this;
+ }
+
+ void reset() {
+ this->reset(SkShader::kClamp_TileMode, kNone_FilterMode);
+ }
+
+ void reset(SkShader::TileMode tileXAndY, FilterMode filterMode) {
+ fTileModes[0] = fTileModes[1] = tileXAndY;
+ fFilterMode = filterMode;
+ }
+
+ void reset(SkShader::TileMode tileModes[2], FilterMode filterMode) {
+ fTileModes[0] = tileModes[0];
+ fTileModes[1] = tileModes[1];
+ fFilterMode = filterMode;
+ }
+
+ void setClampNoFilter() {
+ fTileModes[0] = fTileModes[1] = SkShader::kClamp_TileMode;
+ fFilterMode = kNone_FilterMode;
+ }
+
+ void setClamp() {
+ fTileModes[0] = fTileModes[1] = SkShader::kClamp_TileMode;
+ }
+
+ void setFilterMode(FilterMode filterMode) { fFilterMode = filterMode; }
+
+ void setTileModeX(const SkShader::TileMode tm) { fTileModes[0] = tm; }
+ void setTileModeY(const SkShader::TileMode tm) { fTileModes[1] = tm; }
+ void setTileModeXAndY(const SkShader::TileMode tm) { fTileModes[0] = fTileModes[1] = tm; }
+
+ SkShader::TileMode getTileModeX() const { return fTileModes[0]; }
+
+ SkShader::TileMode getTileModeY() const { return fTileModes[1]; }
+
+ bool isTiled() const {
+ return SkShader::kClamp_TileMode != fTileModes[0] ||
+ SkShader::kClamp_TileMode != fTileModes[1];
+ }
+
+ FilterMode filterMode() const { return fFilterMode; }
+
+ bool operator== (const GrTextureParams& other) const {
+ return fTileModes[0] == other.fTileModes[0] &&
+ fTileModes[1] == other.fTileModes[1] &&
+ fFilterMode == other.fFilterMode;
+ }
+
+ bool operator!= (const GrTextureParams& other) const { return !(*this == other); }
+
+private:
+
+ SkShader::TileMode fTileModes[2];
+ FilterMode fFilterMode;
+};
+
+/** A class representing the swizzle access pattern for a texture. Note that if the texture is
+ * an alpha-only texture then the alpha channel is substituted for other components. Any mangling
+ * to handle the r,g,b->a conversions for alpha textures is automatically included in the stage
+ * key. However, if a GrEffect uses different swizzles based on its input then it must
+ * consider that variation in its key-generation.
+ */
+class GrTextureAccess : GrNoncopyable {
+public:
+ /**
+ * A default GrTextureAccess must have reset() called on it in a GrEffect subclass's
+ * constructor if it will be accessible via GrEffect::textureAccess().
+ */
+ GrTextureAccess();
+
+ /**
+ * Uses the default swizzle, "rgba".
+ */
+ GrTextureAccess(GrTexture*, const GrTextureParams&);
+ explicit GrTextureAccess(GrTexture*,
+ GrTextureParams::FilterMode = GrTextureParams::kNone_FilterMode,
+ SkShader::TileMode tileXAndY = SkShader::kClamp_TileMode);
+
+ /**
+ * swizzle must be a string between one and four (inclusive) characters containing only 'r',
+ * 'g', 'b', and/or 'a'.
+ */
+ GrTextureAccess(GrTexture*, const char* swizzle, const GrTextureParams&);
+ GrTextureAccess(GrTexture*,
+ const char* swizzle,
+ GrTextureParams::FilterMode = GrTextureParams::kNone_FilterMode,
+ SkShader::TileMode tileXAndY = SkShader::kClamp_TileMode);
+
+ void reset(GrTexture*, const GrTextureParams&);
+ void reset(GrTexture*,
+ GrTextureParams::FilterMode = GrTextureParams::kNone_FilterMode,
+ SkShader::TileMode tileXAndY = SkShader::kClamp_TileMode);
+ void reset(GrTexture*, const char* swizzle, const GrTextureParams&);
+ void reset(GrTexture*,
+ const char* swizzle,
+ GrTextureParams::FilterMode = GrTextureParams::kNone_FilterMode,
+ SkShader::TileMode tileXAndY = SkShader::kClamp_TileMode);
+
+ bool operator== (const GrTextureAccess& other) const {
+#if GR_DEBUG
+ // below assumes all chars in fSwizzle are initialized even if string is < 4 chars long.
+ GrAssert(memcmp(fSwizzle, other.fSwizzle, sizeof(fSwizzle)-1) ==
+ strcmp(fSwizzle, other.fSwizzle));
+#endif
+ return fParams == other.fParams &&
+ (fTexture.get() == other.fTexture.get()) &&
+ (0 == memcmp(fSwizzle, other.fSwizzle, sizeof(fSwizzle)-1));
+ }
+
+ bool operator!= (const GrTextureAccess& other) const { return !(*this == other); }
+
+ GrTexture* getTexture() const { return fTexture.get(); }
+
+ /**
+ * Returns a string representing the swizzle. The string is is null-terminated.
+ */
+ const char* getSwizzle() const { return fSwizzle; }
+
+ /** Returns a mask indicating which components are referenced in the swizzle. The return
+ is a bitfield of GrColorComponentFlags. */
+ uint32_t swizzleMask() const { return fSwizzleMask; }
+
+ const GrTextureParams& getParams() const { return fParams; }
+
+private:
+ void setSwizzle(const char*);
+
+ GrTextureParams fParams;
+ SkAutoTUnref<GrTexture> fTexture;
+ uint32_t fSwizzleMask;
+ char fSwizzle[5];
+
+ typedef GrNoncopyable INHERITED;
+};
+
+#endif
diff --git a/gpu/GrTypes.h b/gpu/GrTypes.h
new file mode 100644
index 0000000..18aedc5
--- /dev/null
+++ b/gpu/GrTypes.h
@@ -0,0 +1,630 @@
+
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+
+#ifndef GrTypes_DEFINED
+#define GrTypes_DEFINED
+
+#include "SkTypes.h"
+#include "GrConfig.h"
+#include "SkMath.h"
+
+////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Defines overloaded bitwise operators to make it easier to use an enum as a
+ * bitfield.
+ */
+#define GR_MAKE_BITFIELD_OPS(X) \
+ inline X operator | (X a, X b) { \
+ return (X) (+a | +b); \
+ } \
+ \
+ inline X operator & (X a, X b) { \
+ return (X) (+a & +b); \
+ } \
+ template <typename T> \
+ inline X operator & (T a, X b) { \
+ return (X) (+a & +b); \
+ } \
+ template <typename T> \
+ inline X operator & (X a, T b) { \
+ return (X) (+a & +b); \
+ } \
+
+#define GR_DECL_BITFIELD_OPS_FRIENDS(X) \
+ friend X operator | (X a, X b); \
+ \
+ friend X operator & (X a, X b); \
+ \
+ template <typename T> \
+ friend X operator & (T a, X b); \
+ \
+ template <typename T> \
+ friend X operator & (X a, T b); \
+////////////////////////////////////////////////////////////////////////////////
+
+
+/**
+ * Macro to round n up to the next multiple of 4, or return it unchanged if
+ * n is already a multiple of 4
+ */
+#define GrALIGN4(n) SkAlign4(n)
+#define GrIsALIGN4(n) SkIsAlign4(n)
+
+template <typename T> const T& GrMin(const T& a, const T& b) {
+ return (a < b) ? a : b;
+}
+
+template <typename T> const T& GrMax(const T& a, const T& b) {
+ return (b < a) ? a : b;
+}
+
+// compile time versions of min/max
+#define GR_CT_MAX(a, b) (((b) < (a)) ? (a) : (b))
+#define GR_CT_MIN(a, b) (((b) < (a)) ? (b) : (a))
+
+/**
+ * divide, rounding up
+ */
+static inline int32_t GrIDivRoundUp(int x, int y) {
+ GrAssert(y > 0);
+ return (x + (y-1)) / y;
+}
+static inline uint32_t GrUIDivRoundUp(uint32_t x, uint32_t y) {
+ return (x + (y-1)) / y;
+}
+static inline size_t GrSizeDivRoundUp(size_t x, size_t y) {
+ return (x + (y-1)) / y;
+}
+
+// compile time, evaluates Y multiple times
+#define GR_CT_DIV_ROUND_UP(X, Y) (((X) + ((Y)-1)) / (Y))
+
+/**
+ * align up
+ */
+static inline uint32_t GrUIAlignUp(uint32_t x, uint32_t alignment) {
+ return GrUIDivRoundUp(x, alignment) * alignment;
+}
+static inline size_t GrSizeAlignUp(size_t x, size_t alignment) {
+ return GrSizeDivRoundUp(x, alignment) * alignment;
+}
+
+// compile time, evaluates A multiple times
+#define GR_CT_ALIGN_UP(X, A) (GR_CT_DIV_ROUND_UP((X),(A)) * (A))
+
+/**
+ * amount of pad needed to align up
+ */
+static inline uint32_t GrUIAlignUpPad(uint32_t x, uint32_t alignment) {
+ return (alignment - x % alignment) % alignment;
+}
+static inline size_t GrSizeAlignUpPad(size_t x, size_t alignment) {
+ return (alignment - x % alignment) % alignment;
+}
+
+/**
+ * align down
+ */
+static inline uint32_t GrUIAlignDown(uint32_t x, uint32_t alignment) {
+ return (x / alignment) * alignment;
+}
+static inline size_t GrSizeAlignDown(size_t x, uint32_t alignment) {
+ return (x / alignment) * alignment;
+}
+
+/**
+ * Count elements in an array
+ */
+#define GR_ARRAY_COUNT(array) SK_ARRAY_COUNT(array)
+
+//!< allocate a block of memory, will never return NULL
+extern void* GrMalloc(size_t bytes);
+
+//!< free block allocated by GrMalloc. ptr may be NULL
+extern void GrFree(void* ptr);
+
+static inline void Gr_bzero(void* dst, size_t size) {
+ memset(dst, 0, size);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Return true if n is a power of 2
+ */
+static inline bool GrIsPow2(unsigned n) {
+ return n && 0 == (n & (n - 1));
+}
+
+/**
+ * Return the next power of 2 >= n.
+ */
+static inline uint32_t GrNextPow2(uint32_t n) {
+ return n ? (1 << (32 - SkCLZ(n - 1))) : 1;
+}
+
+static inline int GrNextPow2(int n) {
+ GrAssert(n >= 0); // this impl only works for non-neg.
+ return n ? (1 << (32 - SkCLZ(n - 1))) : 1;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+/**
+ * 16.16 fixed point type
+ */
+typedef int32_t GrFixed;
+
+#if GR_DEBUG
+
+static inline int16_t GrToS16(intptr_t x) {
+ GrAssert((int16_t)x == x);
+ return (int16_t)x;
+}
+
+#else
+
+#define GrToS16(x) x
+
+#endif
+
+
+///////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Possible 3D APIs that may be used by Ganesh.
+ */
+enum GrBackend {
+ kOpenGL_GrBackend,
+};
+
+/**
+ * Backend-specific 3D context handle
+ * GrGLInterface* for OpenGL. If NULL will use the default GL interface.
+ */
+typedef intptr_t GrBackendContext;
+
+///////////////////////////////////////////////////////////////////////////////
+
+/**
+* Geometric primitives used for drawing.
+*/
+enum GrPrimitiveType {
+ kTriangles_GrPrimitiveType,
+ kTriangleStrip_GrPrimitiveType,
+ kTriangleFan_GrPrimitiveType,
+ kPoints_GrPrimitiveType,
+ kLines_GrPrimitiveType, // 1 pix wide only
+ kLineStrip_GrPrimitiveType // 1 pix wide only
+};
+
+static inline bool GrIsPrimTypeLines(GrPrimitiveType type) {
+ return kLines_GrPrimitiveType == type || kLineStrip_GrPrimitiveType == type;
+}
+
+static inline bool GrIsPrimTypeTris(GrPrimitiveType type) {
+ return kTriangles_GrPrimitiveType == type ||
+ kTriangleStrip_GrPrimitiveType == type ||
+ kTriangleFan_GrPrimitiveType == type;
+}
+
+/**
+ * Coeffecients for alpha-blending.
+ */
+enum GrBlendCoeff {
+ kInvalid_GrBlendCoeff = -1,
+
+ kZero_GrBlendCoeff, //<! 0
+ kOne_GrBlendCoeff, //<! 1
+ kSC_GrBlendCoeff, //<! src color
+ kISC_GrBlendCoeff, //<! one minus src color
+ kDC_GrBlendCoeff, //<! dst color
+ kIDC_GrBlendCoeff, //<! one minus dst color
+ kSA_GrBlendCoeff, //<! src alpha
+ kISA_GrBlendCoeff, //<! one minus src alpha
+ kDA_GrBlendCoeff, //<! dst alpha
+ kIDA_GrBlendCoeff, //<! one minus dst alpha
+ kConstC_GrBlendCoeff, //<! constant color
+ kIConstC_GrBlendCoeff, //<! one minus constant color
+ kConstA_GrBlendCoeff, //<! constant color alpha
+ kIConstA_GrBlendCoeff, //<! one minus constant color alpha
+
+ kPublicGrBlendCoeffCount
+};
+
+/**
+ * Formats for masks, used by the font cache.
+ * Important that these are 0-based.
+ */
+enum GrMaskFormat {
+ kA8_GrMaskFormat, //!< 1-byte per pixel
+ kA565_GrMaskFormat, //!< 2-bytes per pixel
+ kA888_GrMaskFormat, //!< 4-bytes per pixel
+
+ kCount_GrMaskFormats //!< used to allocate arrays sized for mask formats
+};
+
+/**
+ * Return the number of bytes-per-pixel for the specified mask format.
+ */
+static inline int GrMaskFormatBytesPerPixel(GrMaskFormat format) {
+ GrAssert((unsigned)format <= 2);
+ // kA8 (0) -> 1
+ // kA565 (1) -> 2
+ // kA888 (2) -> 4
+ return 1 << (int)format;
+}
+
+/**
+ * Pixel configurations.
+ */
+enum GrPixelConfig {
+ kUnknown_GrPixelConfig,
+ kAlpha_8_GrPixelConfig,
+ kIndex_8_GrPixelConfig,
+ kRGB_565_GrPixelConfig,
+ /**
+ * Premultiplied
+ */
+ kRGBA_4444_GrPixelConfig,
+ /**
+ * Premultiplied. Byte order is r,g,b,a.
+ */
+ kRGBA_8888_GrPixelConfig,
+ /**
+ * Premultiplied. Byte order is b,g,r,a.
+ */
+ kBGRA_8888_GrPixelConfig,
+
+ kLast_GrPixelConfig = kBGRA_8888_GrPixelConfig
+};
+static const int kGrPixelConfigCnt = kLast_GrPixelConfig + 1;
+
+// Aliases for pixel configs that match skia's byte order.
+#ifndef SK_CPU_LENDIAN
+ #error "Skia gpu currently assumes little endian"
+#endif
+#if SK_PMCOLOR_BYTE_ORDER(B,G,R,A)
+ static const GrPixelConfig kSkia8888_GrPixelConfig = kBGRA_8888_GrPixelConfig;
+#elif SK_PMCOLOR_BYTE_ORDER(R,G,B,A)
+ static const GrPixelConfig kSkia8888_GrPixelConfig = kRGBA_8888_GrPixelConfig;
+#else
+ #error "SK_*32_SHIFT values must correspond to GL_BGRA or GL_RGBA format."
+#endif
+
+// Returns true if the pixel config is 32 bits per pixel
+static inline bool GrPixelConfigIs8888(GrPixelConfig config) {
+ switch (config) {
+ case kRGBA_8888_GrPixelConfig:
+ case kBGRA_8888_GrPixelConfig:
+ return true;
+ default:
+ return false;
+ }
+}
+
+// Takes a config and returns the equivalent config with the R and B order
+// swapped if such a config exists. Otherwise, kUnknown_GrPixelConfig
+static inline GrPixelConfig GrPixelConfigSwapRAndB(GrPixelConfig config) {
+ switch (config) {
+ case kBGRA_8888_GrPixelConfig:
+ return kRGBA_8888_GrPixelConfig;
+ case kRGBA_8888_GrPixelConfig:
+ return kBGRA_8888_GrPixelConfig;
+ default:
+ return kUnknown_GrPixelConfig;
+ }
+}
+
+static inline size_t GrBytesPerPixel(GrPixelConfig config) {
+ switch (config) {
+ case kAlpha_8_GrPixelConfig:
+ case kIndex_8_GrPixelConfig:
+ return 1;
+ case kRGB_565_GrPixelConfig:
+ case kRGBA_4444_GrPixelConfig:
+ return 2;
+ case kRGBA_8888_GrPixelConfig:
+ case kBGRA_8888_GrPixelConfig:
+ return 4;
+ default:
+ return 0;
+ }
+}
+
+static inline bool GrPixelConfigIsOpaque(GrPixelConfig config) {
+ switch (config) {
+ case kRGB_565_GrPixelConfig:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static inline bool GrPixelConfigIsAlphaOnly(GrPixelConfig config) {
+ switch (config) {
+ case kAlpha_8_GrPixelConfig:
+ return true;
+ default:
+ return false;
+ }
+}
+
+/**
+ * Optional bitfield flags that can be passed to createTexture.
+ */
+enum GrTextureFlags {
+ kNone_GrTextureFlags = 0x0,
+ /**
+ * Creates a texture that can be rendered to as a GrRenderTarget. Use
+ * GrTexture::asRenderTarget() to access.
+ */
+ kRenderTarget_GrTextureFlagBit = 0x1,
+ /**
+ * By default all render targets have an associated stencil buffer that
+ * may be required for path filling. This flag overrides stencil buffer
+ * creation.
+ * MAKE THIS PRIVATE?
+ */
+ kNoStencil_GrTextureFlagBit = 0x2,
+ /**
+ * Hint that the CPU may modify this texture after creation.
+ */
+ kDynamicUpdate_GrTextureFlagBit = 0x4,
+ /**
+ * Indicates that all allocations (color buffer, FBO completeness, etc)
+ * should be verified.
+ */
+ kCheckAllocation_GrTextureFlagBit = 0x8,
+
+ kDummy_GrTextureFlagBit,
+ kLastPublic_GrTextureFlagBit = kDummy_GrTextureFlagBit-1,
+};
+
+GR_MAKE_BITFIELD_OPS(GrTextureFlags)
+
+enum {
+ /**
+ * For Index8 pixel config, the colortable must be 256 entries
+ */
+ kGrColorTableSize = 256 * 4 //sizeof(GrColor)
+};
+
+/**
+ * Some textures will be stored such that the upper and left edges of the content meet at the
+ * the origin (in texture coord space) and for other textures the lower and left edges meet at
+ * the origin. kDefault_GrSurfaceOrigin sets textures to TopLeft, and render targets
+ * to BottomLeft.
+ */
+
+enum GrSurfaceOrigin {
+ kDefault_GrSurfaceOrigin, // DEPRECATED; to be removed
+ kTopLeft_GrSurfaceOrigin,
+ kBottomLeft_GrSurfaceOrigin,
+};
+
+/**
+ * Describes a texture to be created.
+ */
+struct GrTextureDesc {
+ GrTextureDesc()
+ : fFlags(kNone_GrTextureFlags)
+ , fOrigin(kDefault_GrSurfaceOrigin)
+ , fWidth(0)
+ , fHeight(0)
+ , fConfig(kUnknown_GrPixelConfig)
+ , fSampleCnt(0) {
+ }
+
+ GrTextureFlags fFlags; //!< bitfield of TextureFlags
+ GrSurfaceOrigin fOrigin; //!< origin of the texture
+ int fWidth; //!< Width of the texture
+ int fHeight; //!< Height of the texture
+
+ /**
+ * Format of source data of the texture. Not guaranteed to be the same as
+ * internal format used by 3D API.
+ */
+ GrPixelConfig fConfig;
+
+ /**
+ * The number of samples per pixel or 0 to disable full scene AA. This only
+ * applies if the kRenderTarget_GrTextureFlagBit is set. The actual number
+ * of samples may not exactly match the request. The request will be rounded
+ * up to the next supported sample count, or down if it is larger than the
+ * max supported count.
+ */
+ int fSampleCnt;
+};
+
+/**
+ * GrCacheID is used create and find cached GrResources (e.g. GrTextures). The ID has two parts:
+ * the domain and the key. Domains simply allow multiple clients to use 0-based indices as their
+ * cache key without colliding. The key uniquely identifies a GrResource within the domain.
+ * Users of the cache must obtain a domain via GenerateDomain().
+ */
+struct GrCacheID {
+public:
+ typedef uint8_t Domain;
+
+ struct Key {
+ union {
+ uint8_t fData8[16];
+ uint32_t fData32[4];
+ uint64_t fData64[2];
+ };
+ };
+
+ /**
+ * A default cache ID is invalid; a set method must be called before the object is used.
+ */
+ GrCacheID() { fDomain = kInvalid_Domain; }
+
+ /**
+ * Initialize the cache ID to a domain and key.
+ */
+ GrCacheID(Domain domain, const Key& key) {
+ GrAssert(kInvalid_Domain != domain);
+ this->reset(domain, key);
+ }
+
+ void reset(Domain domain, const Key& key) {
+ fDomain = domain;
+ memcpy(&fKey, &key, sizeof(Key));
+ }
+
+ /** Has this been initialized to a valid domain */
+ bool isValid() const { return kInvalid_Domain != fDomain; }
+
+ const Key& getKey() const { GrAssert(this->isValid()); return fKey; }
+ Domain getDomain() const { GrAssert(this->isValid()); return fDomain; }
+
+ /** Creates a new unique ID domain. */
+ static Domain GenerateDomain();
+
+private:
+ Key fKey;
+ Domain fDomain;
+
+ static const Domain kInvalid_Domain = 0;
+};
+
+/**
+ * Clips are composed from these objects.
+ */
+enum GrClipType {
+ kRect_ClipType,
+ kPath_ClipType
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+// opaque type for 3D API object handles
+typedef intptr_t GrBackendObject;
+
+/**
+ * Gr can wrap an existing texture created by the client with a GrTexture
+ * object. The client is responsible for ensuring that the texture lives at
+ * least as long as the GrTexture object wrapping it. We require the client to
+ * explicitly provide information about the texture, such as width, height,
+ * and pixel config, rather than querying the 3D APIfor these values. We expect
+ * these to be immutable even if the 3D API doesn't require this (OpenGL).
+ *
+ * Textures that are also render targets are supported as well. Gr will manage
+ * any ancillary 3D API (stencil buffer, FBO id, etc) objects necessary for
+ * Gr to draw into the render target. To access the render target object
+ * call GrTexture::asRenderTarget().
+ *
+ * If in addition to the render target flag, the caller also specifies a sample
+ * count Gr will create an MSAA buffer that resolves into the texture. Gr auto-
+ * resolves when it reads from the texture. The client can explictly resolve
+ * using the GrRenderTarget interface.
+ *
+ * Note: These flags currently form a subset of GrTexture's flags.
+ */
+
+enum GrBackendTextureFlags {
+ /**
+ * No flags enabled
+ */
+ kNone_GrBackendTextureFlag = kNone_GrTextureFlags,
+ /**
+ * Indicates that the texture is also a render target, and thus should have
+ * a GrRenderTarget object.
+ *
+ * D3D (future): client must have created the texture with flags that allow
+ * it to be used as a render target.
+ */
+ kRenderTarget_GrBackendTextureFlag = kRenderTarget_GrTextureFlagBit,
+};
+GR_MAKE_BITFIELD_OPS(GrBackendTextureFlags)
+
+struct GrBackendTextureDesc {
+ GrBackendTextureDesc() { memset(this, 0, sizeof(*this)); }
+ GrBackendTextureFlags fFlags;
+ GrSurfaceOrigin fOrigin;
+ int fWidth; //<! width in pixels
+ int fHeight; //<! height in pixels
+ GrPixelConfig fConfig; //<! color format
+ /**
+ * If the render target flag is set and sample count is greater than 0
+ * then Gr will create an MSAA buffer that resolves to the texture.
+ */
+ int fSampleCnt;
+ /**
+ * Handle to the 3D API object.
+ * OpenGL: Texture ID.
+ */
+ GrBackendObject fTextureHandle;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Gr can wrap an existing render target created by the client in the 3D API
+ * with a GrRenderTarget object. The client is responsible for ensuring that the
+ * underlying 3D API object lives at least as long as the GrRenderTarget object
+ * wrapping it. We require the client to explicitly provide information about
+ * the target, such as width, height, and pixel config rather than querying the
+ * 3D API for these values. We expect these properties to be immutable even if
+ * the 3D API doesn't require this (OpenGL).
+ */
+
+struct GrBackendRenderTargetDesc {
+ GrBackendRenderTargetDesc() { memset(this, 0, sizeof(*this)); }
+ int fWidth; //<! width in pixels
+ int fHeight; //<! height in pixels
+ GrPixelConfig fConfig; //<! color format
+ GrSurfaceOrigin fOrigin; //<! pixel origin
+ /**
+ * The number of samples per pixel. Gr uses this to influence decisions
+ * about applying other forms of anti-aliasing.
+ */
+ int fSampleCnt;
+ /**
+ * Number of bits of stencil per-pixel.
+ */
+ int fStencilBits;
+ /**
+ * Handle to the 3D API object.
+ * OpenGL: FBO ID
+ */
+ GrBackendObject fRenderTargetHandle;
+};
+
+/**
+ * The GrContext's cache of backend context state can be partially invalidated.
+ * These enums are specific to the GL backend and we'd add a new set for an alternative backend.
+ */
+enum GrGLBackendState {
+ kRenderTarget_GrGLBackendState = 1 << 0,
+ kTextureBinding_GrGLBackendState = 1 << 1,
+ // View state stands for scissor and viewport
+ kView_GrGLBackendState = 1 << 2,
+ kBlend_GrGLBackendState = 1 << 3,
+ kAA_GrGLBackendState = 1 << 4,
+ kVertex_GrGLBackendState = 1 << 5,
+ kStencil_GrGLBackendState = 1 << 6,
+ kPixelStore_GrGLBackendState = 1 << 7,
+ kProgram_GrGLBackendState = 1 << 8,
+ kPathStencil_GrGLBackendState = 1 << 9,
+ kMisc_GrGLBackendState = 1 << 10,
+ kALL_GrGLBackendState = 0xffff
+};
+
+/**
+ * This value translates to reseting all the context state for any backend.
+ */
+static const uint32_t kAll_GrBackendState = 0xffffffff;
+
+///////////////////////////////////////////////////////////////////////////////
+
+#endif
diff --git a/gpu/GrTypesPriv.h b/gpu/GrTypesPriv.h
new file mode 100644
index 0000000..3538f38
--- /dev/null
+++ b/gpu/GrTypesPriv.h
@@ -0,0 +1,169 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrTypesPriv_DEFINED
+#define GrTypesPriv_DEFINED
+
+#include "GrTypes.h"
+#include "SkTArray.h"
+
+/**
+ * Types of shader-language-specific boxed variables we can create. (Currently only GrGLShaderVars,
+ * but should be applicable to other shader languages.)
+ */
+enum GrSLType {
+ kVoid_GrSLType,
+ kFloat_GrSLType,
+ kVec2f_GrSLType,
+ kVec3f_GrSLType,
+ kVec4f_GrSLType,
+ kMat33f_GrSLType,
+ kMat44f_GrSLType,
+ kSampler2D_GrSLType,
+
+ kLast_GrSLType = kSampler2D_GrSLType
+};
+static const int kGrSLTypeCount = kLast_GrSLType + 1;
+
+/**
+ * Gets the vector size of the SLType. Returns -1 for void, matrices, and samplers.
+ */
+static inline int GrSLTypeVectorCount(GrSLType type) {
+ GrAssert(type >= 0 && type < static_cast<GrSLType>(kGrSLTypeCount));
+ static const int kCounts[] = { -1, 1, 2, 3, 4, -1, -1, -1 };
+ return kCounts[type];
+
+ GR_STATIC_ASSERT(0 == kVoid_GrSLType);
+ GR_STATIC_ASSERT(1 == kFloat_GrSLType);
+ GR_STATIC_ASSERT(2 == kVec2f_GrSLType);
+ GR_STATIC_ASSERT(3 == kVec3f_GrSLType);
+ GR_STATIC_ASSERT(4 == kVec4f_GrSLType);
+ GR_STATIC_ASSERT(5 == kMat33f_GrSLType);
+ GR_STATIC_ASSERT(6 == kMat44f_GrSLType);
+ GR_STATIC_ASSERT(7 == kSampler2D_GrSLType);
+ GR_STATIC_ASSERT(GR_ARRAY_COUNT(kCounts) == kGrSLTypeCount);
+}
+
+/** Return the type enum for a vector of floats of length n (1..4),
+ e.g. 1 -> kFloat_GrSLType, 2 -> kVec2_GrSLType, ... */
+static inline GrSLType GrSLFloatVectorType(int count) {
+ GrAssert(count > 0 && count <= 4);
+ return (GrSLType)(count);
+
+ GR_STATIC_ASSERT(kFloat_GrSLType == 1);
+ GR_STATIC_ASSERT(kVec2f_GrSLType == 2);
+ GR_STATIC_ASSERT(kVec3f_GrSLType == 3);
+ GR_STATIC_ASSERT(kVec4f_GrSLType == 4);
+}
+
+/**
+ * Types used to describe format of vertices in arrays.
+ */
+enum GrVertexAttribType {
+ kFloat_GrVertexAttribType = 0,
+ kVec2f_GrVertexAttribType,
+ kVec3f_GrVertexAttribType,
+ kVec4f_GrVertexAttribType,
+ kVec4ub_GrVertexAttribType, // vector of 4 unsigned bytes, e.g. colors
+
+ kLast_GrVertexAttribType = kVec4ub_GrVertexAttribType
+};
+static const int kGrVertexAttribTypeCount = kLast_GrVertexAttribType + 1;
+
+/**
+ * Returns the vector size of the type.
+ */
+static inline int GrVertexAttribTypeVectorCount(GrVertexAttribType type) {
+ GrAssert(type >= 0 && type < kGrVertexAttribTypeCount);
+ static const int kCounts[] = { 1, 2, 3, 4, 4 };
+ return kCounts[type];
+
+ GR_STATIC_ASSERT(0 == kFloat_GrVertexAttribType);
+ GR_STATIC_ASSERT(1 == kVec2f_GrVertexAttribType);
+ GR_STATIC_ASSERT(2 == kVec3f_GrVertexAttribType);
+ GR_STATIC_ASSERT(3 == kVec4f_GrVertexAttribType);
+ GR_STATIC_ASSERT(4 == kVec4ub_GrVertexAttribType);
+ GR_STATIC_ASSERT(GR_ARRAY_COUNT(kCounts) == kGrVertexAttribTypeCount);
+}
+
+/**
+ * Returns the size of the attrib type in bytes.
+ */
+static inline size_t GrVertexAttribTypeSize(GrVertexAttribType type) {
+ GrAssert(type >= 0 && type < kGrVertexAttribTypeCount);
+ static const size_t kSizes[] = {
+ sizeof(float), // kFloat_GrVertexAttribType
+ 2*sizeof(float), // kVec2f_GrVertexAttribType
+ 3*sizeof(float), // kVec3f_GrVertexAttribType
+ 4*sizeof(float), // kVec4f_GrVertexAttribType
+ 4*sizeof(char) // kVec4ub_GrVertexAttribType
+ };
+ return kSizes[type];
+
+ GR_STATIC_ASSERT(0 == kFloat_GrVertexAttribType);
+ GR_STATIC_ASSERT(1 == kVec2f_GrVertexAttribType);
+ GR_STATIC_ASSERT(2 == kVec3f_GrVertexAttribType);
+ GR_STATIC_ASSERT(3 == kVec4f_GrVertexAttribType);
+ GR_STATIC_ASSERT(4 == kVec4ub_GrVertexAttribType);
+ GR_STATIC_ASSERT(GR_ARRAY_COUNT(kSizes) == kGrVertexAttribTypeCount);
+}
+
+/**
+ * Semantic bindings for vertex attributes. kEffect means that the attribute is input to a GrEffect.
+ * Each binding other than kEffect may not appear more than once in the current set of attributes.
+ * kPosition must be appear for exactly one attribute.
+ */
+enum GrVertexAttribBinding {
+ kPosition_GrVertexAttribBinding, // required, must have vector count of 2
+ kLocalCoord_GrVertexAttribBinding, // must have vector count of 2
+ kColor_GrVertexAttribBinding, // must have vector count of 4
+ kCoverage_GrVertexAttribBinding, // must have vector count of 4
+
+ kLastFixedFunction_GrVertexAttribBinding = kCoverage_GrVertexAttribBinding,
+
+ kEffect_GrVertexAttribBinding, // vector length must agree with
+ // GrEffect::vertexAttribType() for each effect input to
+ // which the attribute is mapped by GrDrawState::setEffect()
+ kLast_GrVertexAttribBinding = kEffect_GrVertexAttribBinding
+};
+
+static const int kGrVertexAttribBindingCnt = kLast_GrVertexAttribBinding + 1;
+static const int kGrFixedFunctionVertexAttribBindingCnt =
+ kLastFixedFunction_GrVertexAttribBinding + 1;
+
+static inline int GrFixedFunctionVertexAttribVectorCount(GrVertexAttribBinding binding) {
+ GrAssert(binding >= 0 && binding < kGrFixedFunctionVertexAttribBindingCnt);
+ static const int kVecCounts[] = { 2, 2, 4, 4 };
+
+ return kVecCounts[binding];
+
+ GR_STATIC_ASSERT(0 == kPosition_GrVertexAttribBinding);
+ GR_STATIC_ASSERT(1 == kLocalCoord_GrVertexAttribBinding);
+ GR_STATIC_ASSERT(2 == kColor_GrVertexAttribBinding);
+ GR_STATIC_ASSERT(3 == kCoverage_GrVertexAttribBinding);
+ GR_STATIC_ASSERT(kGrFixedFunctionVertexAttribBindingCnt == SK_ARRAY_COUNT(kVecCounts));
+}
+
+struct GrVertexAttrib {
+ inline void set(GrVertexAttribType type, size_t offset, GrVertexAttribBinding binding) {
+ fType = type;
+ fOffset = offset;
+ fBinding = binding;
+ }
+ bool operator==(const GrVertexAttrib& other) const {
+ return fType == other.fType && fOffset == other.fOffset && fBinding == other.fBinding;
+ };
+ bool operator!=(const GrVertexAttrib& other) const { return !(*this == other); }
+
+ GrVertexAttribType fType;
+ size_t fOffset;
+ GrVertexAttribBinding fBinding;
+};
+
+template <int N> class GrVertexAttribArray : public SkSTArray<N, GrVertexAttrib, true> {};
+
+#endif
diff --git a/gpu/GrUserConfig.h b/gpu/GrUserConfig.h
new file mode 100644
index 0000000..a10d339
--- /dev/null
+++ b/gpu/GrUserConfig.h
@@ -0,0 +1,37 @@
+
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef GrUserConfig_DEFINED
+#define GrUserConfig_DEFINED
+
+#if defined(GR_USER_CONFIG_FILE)
+ #error "default user config pulled in but GR_USER_CONFIG_FILE is defined."
+#endif
+
+#if 0
+ #undef GR_RELEASE
+ #undef GR_DEBUG
+ #define GR_RELEASE 0
+ #define GR_DEBUG 1
+#endif
+
+/**
+ * This gives a threshold in bytes of when to lock a GrGeometryBuffer vs using
+ * updateData. (Note the depending on the underlying 3D API the update functions
+ * may always be implemented using a lock)
+ */
+//#define GR_GEOM_BUFFER_LOCK_THRESHOLD (1<<15)
+
+/**
+ * This gives a threshold in megabytes for the maximum size of the texture cache
+ * in vram. The value is only a default and can be overridden at runtime.
+ */
+//#define GR_DEFAULT_TEXTURE_CACHE_MB_LIMIT 96
+
+#endif
diff --git a/gpu/SkGpuDevice.h b/gpu/SkGpuDevice.h
new file mode 100644
index 0000000..32f8749
--- /dev/null
+++ b/gpu/SkGpuDevice.h
@@ -0,0 +1,194 @@
+
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+
+#ifndef SkGpuDevice_DEFINED
+#define SkGpuDevice_DEFINED
+
+#include "SkGr.h"
+#include "SkBitmap.h"
+#include "SkDevice.h"
+#include "SkRegion.h"
+#include "GrContext.h"
+
+struct SkDrawProcs;
+struct GrSkDrawProcs;
+class GrTextContext;
+
+/**
+ * Subclass of SkDevice, which directs all drawing to the GrGpu owned by the
+ * canvas.
+ */
+class SK_API SkGpuDevice : public SkDevice {
+public:
+
+ /**
+ * Creates an SkGpuDevice from a GrSurface. This will fail if the surface is not a render
+ * target. The caller owns a ref on the returned device.
+ */
+ static SkGpuDevice* Create(GrSurface* surface);
+
+ /**
+ * New device that will create an offscreen renderTarget based on the
+ * config, width, height, and sampleCount. The device's storage will not
+ * count against the GrContext's texture cache budget. The device's pixels
+ * will be uninitialized. TODO: This can fail, replace with a factory function.
+ */
+ SkGpuDevice(GrContext*, SkBitmap::Config, int width, int height, int sampleCount = 0);
+
+ /**
+ * New device that will render to the specified renderTarget.
+ * DEPRECATED: Use Create(surface)
+ */
+ SkGpuDevice(GrContext*, GrRenderTarget*);
+
+ /**
+ * New device that will render to the texture (as a rendertarget).
+ * The GrTexture's asRenderTarget() must be non-NULL or device will not
+ * function.
+ * DEPRECATED: Use Create(surface)
+ */
+ SkGpuDevice(GrContext*, GrTexture*);
+
+ virtual ~SkGpuDevice();
+
+ GrContext* context() const { return fContext; }
+
+ virtual GrRenderTarget* accessRenderTarget() SK_OVERRIDE;
+
+ // overrides from SkDevice
+
+ virtual void clear(SkColor color) SK_OVERRIDE;
+ virtual void writePixels(const SkBitmap& bitmap, int x, int y,
+ SkCanvas::Config8888 config8888) SK_OVERRIDE;
+
+ virtual void drawPaint(const SkDraw&, const SkPaint& paint) SK_OVERRIDE;
+ virtual void drawPoints(const SkDraw&, SkCanvas::PointMode mode, size_t count,
+ const SkPoint[], const SkPaint& paint) SK_OVERRIDE;
+ virtual void drawRect(const SkDraw&, const SkRect& r,
+ const SkPaint& paint) SK_OVERRIDE;
+ virtual void drawRRect(const SkDraw&, const SkRRect& r,
+ const SkPaint& paint) SK_OVERRIDE;
+ virtual void drawOval(const SkDraw&, const SkRect& oval,
+ const SkPaint& paint) SK_OVERRIDE;
+ virtual void drawPath(const SkDraw&, const SkPath& path,
+ const SkPaint& paint, const SkMatrix* prePathMatrix,
+ bool pathIsMutable) SK_OVERRIDE;
+ virtual void drawBitmap(const SkDraw&, const SkBitmap& bitmap,
+ const SkMatrix&, const SkPaint&) SK_OVERRIDE;
+ virtual void drawBitmapRect(const SkDraw&, const SkBitmap&,
+ const SkRect* srcOrNull, const SkRect& dst,
+ const SkPaint& paint) SK_OVERRIDE;
+ virtual void drawSprite(const SkDraw&, const SkBitmap& bitmap,
+ int x, int y, const SkPaint& paint);
+ virtual void drawText(const SkDraw&, const void* text, size_t len,
+ SkScalar x, SkScalar y, const SkPaint&) SK_OVERRIDE;
+ virtual void drawPosText(const SkDraw&, const void* text, size_t len,
+ const SkScalar pos[], SkScalar constY,
+ int scalarsPerPos, const SkPaint&) SK_OVERRIDE;
+ virtual void drawTextOnPath(const SkDraw&, const void* text, size_t len,
+ const SkPath& path, const SkMatrix* matrix,
+ const SkPaint&) SK_OVERRIDE;
+ virtual void drawVertices(const SkDraw&, SkCanvas::VertexMode, int vertexCount,
+ const SkPoint verts[], const SkPoint texs[],
+ const SkColor colors[], SkXfermode* xmode,
+ const uint16_t indices[], int indexCount,
+ const SkPaint&) SK_OVERRIDE;
+ virtual void drawDevice(const SkDraw&, SkDevice*, int x, int y,
+ const SkPaint&) SK_OVERRIDE;
+ virtual bool filterTextFlags(const SkPaint&, TextFlags*) SK_OVERRIDE;
+
+ virtual void flush();
+
+ virtual void onAttachToCanvas(SkCanvas* canvas) SK_OVERRIDE;
+ virtual void onDetachFromCanvas() SK_OVERRIDE;
+
+ /**
+ * Make's this device's rendertarget current in the underlying 3D API.
+ * Also implicitly flushes.
+ */
+ virtual void makeRenderTargetCurrent();
+
+ virtual bool canHandleImageFilter(SkImageFilter*) SK_OVERRIDE;
+ virtual bool filterImage(SkImageFilter*, const SkBitmap&, const SkMatrix&,
+ SkBitmap*, SkIPoint*) SK_OVERRIDE;
+
+ class SkAutoCachedTexture; // used internally
+
+protected:
+ // overrides from SkDevice
+ virtual bool onReadPixels(const SkBitmap& bitmap,
+ int x, int y,
+ SkCanvas::Config8888 config8888) SK_OVERRIDE;
+
+private:
+ GrContext* fContext;
+
+ GrSkDrawProcs* fDrawProcs;
+
+ GrClipData fClipData;
+
+ // state for our render-target
+ GrRenderTarget* fRenderTarget;
+ bool fNeedClear;
+
+ // called from rt and tex cons
+ void initFromRenderTarget(GrContext*, GrRenderTarget*, bool cached);
+
+ // used by createCompatibleDevice
+ SkGpuDevice(GrContext*, GrTexture* texture, bool needClear);
+
+ // override from SkDevice
+ virtual SkDevice* onCreateCompatibleDevice(SkBitmap::Config config,
+ int width, int height,
+ bool isOpaque,
+ Usage usage) SK_OVERRIDE;
+
+ SkDrawProcs* initDrawForText(GrTextContext*);
+
+ // sets the render target, clip, and matrix on GrContext. Use forceIdenity to override
+ // SkDraw's matrix and draw in device coords.
+ void prepareDraw(const SkDraw&, bool forceIdentity);
+
+ /**
+ * Implementation for both drawBitmap and drawBitmapRect.
+ */
+ void drawBitmapCommon(const SkDraw&,
+ const SkBitmap& bitmap,
+ const SkRect* srcRectPtr,
+ const SkMatrix&,
+ const SkPaint&);
+
+ /**
+ * Helper functions called by drawBitmapCommon. By the time these are called the SkDraw's
+ * matrix has already been set on GrContext
+ */
+ bool shouldTileBitmap(const SkBitmap& bitmap,
+ const GrTextureParams& sampler,
+ const SkRect* srcRectPtr) const;
+ void internalDrawBitmap(const SkBitmap&,
+ const SkRect&,
+ const SkMatrix&,
+ const GrTextureParams& params,
+ const SkPaint& paint);
+ void drawTiledBitmap(const SkBitmap& bitmap,
+ const SkRect& srcRect,
+ const SkMatrix& m,
+ const GrTextureParams& params,
+ const SkPaint& paint);
+
+ /**
+ * Returns non-initialized instance.
+ */
+ GrTextContext* getTextContext();
+
+ typedef SkDevice INHERITED;
+};
+
+#endif
diff --git a/gpu/SkGr.h b/gpu/SkGr.h
new file mode 100644
index 0000000..1f72fbc
--- /dev/null
+++ b/gpu/SkGr.h
@@ -0,0 +1,101 @@
+
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+
+#ifndef SkGr_DEFINED
+#define SkGr_DEFINED
+
+#include <stddef.h>
+
+// Gr headers
+#include "GrTypes.h"
+#include "GrContext.h"
+#include "GrFontScaler.h"
+
+// skia headers
+#include "SkBitmap.h"
+#include "SkPath.h"
+#include "SkPoint.h"
+#include "SkRegion.h"
+#include "SkClipStack.h"
+
+#if (GR_DEBUG && defined(SK_RELEASE)) || (GR_RELEASE && defined(SK_DEBUG))
+// #error "inconsistent GR_DEBUG and SK_DEBUG"
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+// Sk to Gr Type conversions
+
+GR_STATIC_ASSERT((int)kZero_GrBlendCoeff == (int)SkXfermode::kZero_Coeff);
+GR_STATIC_ASSERT((int)kOne_GrBlendCoeff == (int)SkXfermode::kOne_Coeff);
+GR_STATIC_ASSERT((int)kSC_GrBlendCoeff == (int)SkXfermode::kSC_Coeff);
+GR_STATIC_ASSERT((int)kISC_GrBlendCoeff == (int)SkXfermode::kISC_Coeff);
+GR_STATIC_ASSERT((int)kDC_GrBlendCoeff == (int)SkXfermode::kDC_Coeff);
+GR_STATIC_ASSERT((int)kIDC_GrBlendCoeff == (int)SkXfermode::kIDC_Coeff);
+GR_STATIC_ASSERT((int)kSA_GrBlendCoeff == (int)SkXfermode::kSA_Coeff);
+GR_STATIC_ASSERT((int)kISA_GrBlendCoeff == (int)SkXfermode::kISA_Coeff);
+GR_STATIC_ASSERT((int)kDA_GrBlendCoeff == (int)SkXfermode::kDA_Coeff);
+GR_STATIC_ASSERT((int)kIDA_GrBlendCoeff == (int)SkXfermode::kIDA_Coeff);
+
+#define sk_blend_to_grblend(X) ((GrBlendCoeff)(X))
+
+///////////////////////////////////////////////////////////////////////////////
+
+#include "SkColorPriv.h"
+
+/**
+ * Convert the SkBitmap::Config to the corresponding PixelConfig, or
+ * kUnknown_PixelConfig if the conversion cannot be done.
+ */
+GrPixelConfig SkBitmapConfig2GrPixelConfig(SkBitmap::Config);
+
+static inline GrColor SkColor2GrColor(SkColor c) {
+ SkPMColor pm = SkPreMultiplyColor(c);
+ unsigned r = SkGetPackedR32(pm);
+ unsigned g = SkGetPackedG32(pm);
+ unsigned b = SkGetPackedB32(pm);
+ unsigned a = SkGetPackedA32(pm);
+ return GrColorPackRGBA(r, g, b, a);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+bool GrIsBitmapInCache(const GrContext*, const SkBitmap&, const GrTextureParams*);
+
+GrTexture* GrLockAndRefCachedBitmapTexture(GrContext*, const SkBitmap&, const GrTextureParams*);
+
+void GrUnlockAndUnrefCachedBitmapTexture(GrTexture*);
+
+////////////////////////////////////////////////////////////////////////////////
+// Classes
+
+class SkGlyphCache;
+
+class SkGrFontScaler : public GrFontScaler {
+public:
+ explicit SkGrFontScaler(SkGlyphCache* strike);
+ virtual ~SkGrFontScaler();
+
+ // overrides
+ virtual const GrKey* getKey();
+ virtual GrMaskFormat getMaskFormat();
+ virtual bool getPackedGlyphBounds(GrGlyph::PackedID, SkIRect* bounds);
+ virtual bool getPackedGlyphImage(GrGlyph::PackedID, int width, int height,
+ int rowBytes, void* image);
+ virtual bool getGlyphPath(uint16_t glyphID, SkPath*);
+
+private:
+ SkGlyphCache* fStrike;
+ GrKey* fKey;
+// DECLARE_INSTANCE_COUNTER(SkGrFontScaler);
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+#endif
diff --git a/gpu/SkGrPixelRef.h b/gpu/SkGrPixelRef.h
new file mode 100644
index 0000000..da4b8fa
--- /dev/null
+++ b/gpu/SkGrPixelRef.h
@@ -0,0 +1,70 @@
+
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+
+#ifndef SkGrPixelRef_DEFINED
+#define SkGrPixelRef_DEFINED
+
+#include "SkBitmap.h"
+#include "SkPixelRef.h"
+#include "GrTexture.h"
+#include "GrRenderTarget.h"
+
+
+/**
+ * Common baseclass that implements onLockPixels() by calling onReadPixels().
+ * Since it has a copy, it always returns false for onLockPixelsAreWritable().
+ */
+class SK_API SkROLockPixelsPixelRef : public SkPixelRef {
+public:
+ SkROLockPixelsPixelRef();
+ virtual ~SkROLockPixelsPixelRef();
+
+protected:
+ // override from SkPixelRef
+ virtual void* onLockPixels(SkColorTable** ptr);
+ virtual void onUnlockPixels();
+ virtual bool onLockPixelsAreWritable() const; // return false;
+
+private:
+ SkBitmap fBitmap;
+ typedef SkPixelRef INHERITED;
+};
+
+/**
+ * PixelRef that wraps a GrSurface
+ */
+class SK_API SkGrPixelRef : public SkROLockPixelsPixelRef {
+public:
+ /**
+ * Constructs a pixel ref around a GrSurface. If the caller has locked the GrSurface in the
+ * cache and would like the pixel ref to unlock it in its destructor then transferCacheLock
+ * should be set to true.
+ */
+ SkGrPixelRef(GrSurface* surface, bool transferCacheLock = false);
+ virtual ~SkGrPixelRef();
+
+ // override from SkPixelRef
+ virtual GrTexture* getTexture() SK_OVERRIDE;
+
+ SK_DECLARE_UNFLATTENABLE_OBJECT()
+
+protected:
+ // overrides from SkPixelRef
+ virtual bool onReadPixels(SkBitmap* dst, const SkIRect* subset) SK_OVERRIDE;
+ virtual SkPixelRef* deepCopy(SkBitmap::Config dstConfig, const SkIRect* subset) SK_OVERRIDE;
+
+private:
+ GrSurface* fSurface;
+ bool fUnlock; // if true the pixel ref owns a texture cache lock on fSurface
+
+ typedef SkROLockPixelsPixelRef INHERITED;
+};
+
+#endif
diff --git a/gpu/SkGrTexturePixelRef.h b/gpu/SkGrTexturePixelRef.h
new file mode 100644
index 0000000..7129512
--- /dev/null
+++ b/gpu/SkGrTexturePixelRef.h
@@ -0,0 +1,19 @@
+
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+
+#ifndef SkGrTexturePixelRef_DEFINED
+#define SkGrTexturePixelRef_DEFINED
+
+#include "SkGrPixelRef.h"
+
+typedef SkGrPixelRef SkGrTexturePixelRef;
+typedef SkGrPixelRef SkGrRenderTargetPixelRef;
+
+#endif
diff --git a/gpu/gl/GrGLConfig.h b/gpu/gl/GrGLConfig.h
new file mode 100644
index 0000000..81cba1b
--- /dev/null
+++ b/gpu/gl/GrGLConfig.h
@@ -0,0 +1,194 @@
+
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+
+#ifndef GrGLConfig_DEFINED
+#define GrGLConfig_DEFINED
+
+#include "GrTypes.h"
+
+/**
+ * Optional GL config file.
+ */
+#ifdef GR_GL_CUSTOM_SETUP_HEADER
+ #include GR_GL_CUSTOM_SETUP_HEADER
+#endif
+
+#if !defined(GR_GL_FUNCTION_TYPE)
+ #define GR_GL_FUNCTION_TYPE
+#endif
+
+/**
+ * The following are optional defines that can be enabled at the compiler
+ * command line, in a IDE project, in a GrUserConfig.h file, or in a GL custom
+ * file (if one is in use). If a GR_GL_CUSTOM_SETUP_HEADER is used they can
+ * also be placed there.
+ *
+ * GR_GL_LOG_CALLS: if 1 Gr can print every GL call using GrPrintf. Defaults to
+ * 0. Logging can be enabled and disabled at runtime using a debugger via to
+ * global gLogCallsGL. The initial value of gLogCallsGL is controlled by
+ * GR_GL_LOG_CALLS_START.
+ *
+ * GR_GL_LOG_CALLS_START: controls the initial value of gLogCallsGL when
+ * GR_GL_LOG_CALLS is 1. Defaults to 0.
+ *
+ * GR_GL_CHECK_ERROR: if enabled Gr can do a glGetError() after every GL call.
+ * Defaults to 1 if GR_DEBUG is set, otherwise 0. When GR_GL_CHECK_ERROR is 1
+ * this can be toggled in a debugger using the gCheckErrorGL global. The initial
+ * value of gCheckErrorGL is controlled by by GR_GL_CHECK_ERROR_START.
+ *
+ * GR_GL_CHECK_ERROR_START: controls the initial value of gCheckErrorGL
+ * when GR_GL_CHECK_ERROR is 1. Defaults to 1.
+ *
+ * GR_GL_NO_CONSTANT_ATTRIBUTES: if this evaluates to true then the GL backend
+ * will use uniforms instead of attributes in all cases when there is not
+ * per-vertex data. This is important when the underlying GL implementation
+ * doesn't actually support immediate style attribute values (e.g. when
+ * the GL stream is converted to DX as in ANGLE on Chrome). Defaults to 0.
+ *
+ * GR_GL_USE_BUFFER_DATA_NULL_HINT: When specifing new data for a vertex/index
+ * buffer that replaces old data Ganesh can give a hint to the driver that the
+ * previous data will not be used in future draws like this:
+ * glBufferData(GL_..._BUFFER, size, NULL, usage); //<--hint, NULL means
+ * glBufferSubData(GL_..._BUFFER, 0, lessThanSize, data) // old data can't be
+ * // used again.
+ * However, this can be an unoptimization on some platforms, esp. Chrome.
+ * Chrome's cmd buffer will create a new allocation and memset the whole thing
+ * to zero (for security reasons). Defaults to 1 (enabled).
+ *
+ * GR_GL_PER_GL_FUNC_CALLBACK: When set to 1 the GrGLInterface object provides
+ * a function pointer that is called just before every gl function. The ptr must
+ * be valid (i.e. there is no NULL check). However, by default the callback will
+ * be set to a function that does nothing. The signature of the function is:
+ * void function(const GrGLInterface*)
+ * It is not extern "C".
+ * The GrGLInterface field fCallback specifies the function ptr and there is an
+ * additional field fCallbackData of type intptr_t for client data.
+ *
+ * GR_GL_RGBA_8888_PIXEL_OPS_SLOW: Set this to 1 if it is known that performing
+ * glReadPixels / glTex(Sub)Image with format=GL_RGBA, type=GL_UNISIGNED_BYTE is
+ * significantly slower than format=GL_BGRA, type=GL_UNISIGNED_BYTE.
+ *
+ * GR_GL_FULL_READPIXELS_FASTER_THAN_PARTIAL: Set this to 1 if calling
+ * glReadPixels to read the entire framebuffer is faster than calling it with
+ * the same sized rectangle but with a framebuffer bound that is larger than
+ * the rectangle read.
+ *
+ * GR_GL_CHECK_ALLOC_WITH_GET_ERROR: If set to 1 this will then glTexImage,
+ * glBufferData, glRenderbufferStorage, etc will be checked for errors. This
+ * amounts to ensuring the error is GL_NO_ERROR, calling the allocating
+ * function, and then checking that the error is still GL_NO_ERROR. When the
+ * value is 0 we will assume no error was generated without checking.
+ *
+ * GR_GL_CHECK_FBO_STATUS_ONCE_PER_FORMAT: We will normally check the FBO status
+ * every time we bind a texture or renderbuffer to an FBO. However, in some
+ * environments CheckFrameBufferStatus is very expensive. If this is set we will
+ * check the first time we use a color format or a combination of color /
+ * stencil formats as attachments. If the FBO is complete we will assume
+ * subsequent attachments with the same formats are complete as well.
+ *
+ * GR_GL_USE_NV_PATH_RENDERING: Enable experimental support for
+ * GL_NV_path_rendering. There are known issues with clipping, non-AA paths, and
+ * perspective.
+ *
+ * GR_GL_MUST_USE_VBO: Indicates that all vertices and indices must be rendered
+ * from VBOs. Chromium's command buffer doesn't allow glVertexAttribArray with
+ * ARARY_BUFFER 0 bound or glDrawElements with ELEMENT_ARRAY_BUFFER 0 bound.
+ *
+ * GR_GL_USE_NEW_SHADER_SOURCE_SIGNATURE is for compatibility with the new version
+ * of the OpenGLES2.0 headers from Khronos. glShaderSource now takes a const char * const *,
+ * instead of a const char
+ */
+
+#if !defined(GR_GL_LOG_CALLS)
+ #define GR_GL_LOG_CALLS GR_DEBUG
+#endif
+
+#if !defined(GR_GL_LOG_CALLS_START)
+ #define GR_GL_LOG_CALLS_START 0
+#endif
+
+#if !defined(GR_GL_CHECK_ERROR)
+ #define GR_GL_CHECK_ERROR GR_DEBUG
+#endif
+
+#if !defined(GR_GL_CHECK_ERROR_START)
+ #define GR_GL_CHECK_ERROR_START 1
+#endif
+
+#if !defined(GR_GL_NO_CONSTANT_ATTRIBUTES)
+ #define GR_GL_NO_CONSTANT_ATTRIBUTES 0
+#endif
+
+#if !defined(GR_GL_USE_BUFFER_DATA_NULL_HINT)
+ #define GR_GL_USE_BUFFER_DATA_NULL_HINT 1
+#endif
+
+#if !defined(GR_GL_PER_GL_FUNC_CALLBACK)
+ #define GR_GL_PER_GL_FUNC_CALLBACK 0
+#endif
+
+#if !defined(GR_GL_RGBA_8888_PIXEL_OPS_SLOW)
+ #define GR_GL_RGBA_8888_PIXEL_OPS_SLOW 0
+#endif
+
+#if !defined(GR_GL_FULL_READPIXELS_FASTER_THAN_PARTIAL)
+ #define GR_GL_FULL_READPIXELS_FASTER_THAN_PARTIAL 0
+#endif
+
+#if !defined(GR_GL_CHECK_ALLOC_WITH_GET_ERROR)
+ #define GR_GL_CHECK_ALLOC_WITH_GET_ERROR 1
+#endif
+
+#if !defined(GR_GL_CHECK_FBO_STATUS_ONCE_PER_FORMAT)
+ #define GR_GL_CHECK_FBO_STATUS_ONCE_PER_FORMAT 0
+#endif
+
+#if !defined(GR_GL_USE_NV_PATH_RENDERING)
+ #define GR_GL_USE_NV_PATH_RENDERING 0
+#endif
+
+#if !defined(GR_GL_MUST_USE_VBO)
+ #define GR_GL_MUST_USE_VBO 0
+#endif
+
+#if !defined(GR_GL_USE_NEW_SHADER_SOURCE_SIGNATURE)
+ #define GR_GL_USE_NEW_SHADER_SOURCE_SIGNATURE 0
+#endif
+
+/**
+ * There is a strange bug that occurs on Macs with NVIDIA GPUs. We don't
+ * fully understand it. When (element) array buffers are continually
+ * respecified using glBufferData performance can fall off of a cliff. The
+ * driver winds up performing many DMA mapping / unmappings and chews up ~50% of
+ * the core. However, it has been observed that occaisonally respecifiying the
+ * buffer using glBufferData and then writing data using glBufferSubData
+ * prevents the bad behavior.
+ *
+ * There is a lot of uncertainty around this issue. In Chrome backgrounding
+ * the tab somehow initiates this behavior and we don't know what the connection
+ * is. Another observation is that Chrome's cmd buffer server will actually
+ * create a buffer full of zeros when it sees a NULL data param (for security
+ * reasons). If this is disabled and NULL is actually passed all the way to the
+ * driver then the workaround doesn't help.
+ *
+ * The issue is tracked at:
+ * http://code.google.com/p/chromium/issues/detail?id=114865
+ *
+ * When the workaround is enabled we will use the glBufferData / glBufferSubData
+ * trick every 128 array buffer uploads.
+ *
+ * Hopefully we will understand this better and have a cleaner fix or get a
+ * OS/driver level fix.
+ */
+#define GR_GL_MAC_BUFFER_OBJECT_PERFOMANCE_WORKAROUND \
+ (GR_MAC_BUILD && \
+ !GR_GL_USE_BUFFER_DATA_NULL_HINT)
+
+#endif
diff --git a/gpu/gl/GrGLConfig_chrome.h b/gpu/gl/GrGLConfig_chrome.h
new file mode 100644
index 0000000..e08692f
--- /dev/null
+++ b/gpu/gl/GrGLConfig_chrome.h
@@ -0,0 +1,44 @@
+
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#ifndef GrGLConfig_chrome_DEFINED
+#define GrGLConfig_chrome_DEFINED
+
+// glGetError() forces a sync with gpu process on chrome
+#define GR_GL_CHECK_ERROR_START 0
+
+// ANGLE creates a temp VB for vertex attributes not specified per-vertex.
+#define GR_GL_NO_CONSTANT_ATTRIBUTES GR_WIN32_BUILD
+
+// For RGBA teximage/readpixels ANGLE will sw-convert to/from BGRA.
+#define GR_GL_RGBA_8888_PIXEL_OPS_SLOW GR_WIN32_BUILD
+
+// ANGLE can go faster if the entire fbo is read rather than a subrect
+#define GR_GL_FULL_READPIXELS_FASTER_THAN_PARTIAL GR_WIN32_BUILD
+
+// cmd buffer allocates memory and memsets it to zero when it sees glBufferData
+// with NULL.
+#define GR_GL_USE_BUFFER_DATA_NULL_HINT 0
+
+// chrome uses this to set the context on each GL call.
+#define GR_GL_PER_GL_FUNC_CALLBACK 1
+
+// Check error is even more expensive in chrome (cmd buffer flush). The
+// compositor also doesn't check its allocations.
+#define GR_GL_CHECK_ALLOC_WITH_GET_ERROR 0
+
+// CheckFramebufferStatus in chrome synchronizes the gpu and renderer processes.
+#define GR_GL_CHECK_FBO_STATUS_ONCE_PER_FORMAT 1
+
+// Non-VBO vertices and indices are not allowed in Chromium.
+#define GR_GL_MUST_USE_VBO 1
+
+// Use updated Khronos signature for glShaderSource
+// (const char* const instead of char**).
+#define GR_GL_USE_NEW_SHADER_SOURCE_SIGNATURE 1
+
+#endif
diff --git a/gpu/gl/GrGLExtensions.h b/gpu/gl/GrGLExtensions.h
new file mode 100644
index 0000000..f4e950a
--- /dev/null
+++ b/gpu/gl/GrGLExtensions.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrGLExtensions_DEFINED
+#define GrGLExtensions_DEFINED
+
+#include "GrGLInterface.h"
+#include "SkString.h"
+#include "SkTArray.h"
+
+/**
+ * This helper queries the current GL context for its extensions, remembers them, and can be
+ * queried. It supports both glGetString- and glGetStringi-style extension string APIs and will
+ * use the latter if it is available.
+ */
+class GrGLExtensions {
+public:
+ bool init(GrGLBinding binding, const GrGLInterface* iface) {
+ GrAssert(binding & iface->fBindingsExported);
+ return this->init(binding, iface->fGetString, iface->fGetStringi, iface->fGetIntegerv);
+ }
+ /**
+ * We sometimes need to use this class without having yet created a GrGLInterface. This version
+ * of init expects that getString is always non-NULL while getIntegerv and getStringi are non-
+ * NULL if on desktop GL with version 3.0 or higher. Otherwise it will fail.
+ */
+ bool init(GrGLBinding binding,
+ GrGLGetStringProc getString,
+ GrGLGetStringiProc getStringi,
+ GrGLGetIntegervProc getIntegerv);
+
+ /**
+ * Queries whether an extension is present. This will fail if init() has not been called.
+ */
+ bool has(const char*) const;
+
+ void reset() { fStrings.reset(); }
+
+ void print(const char* sep = "\n") const;
+
+private:
+ SkTArray<SkString> fStrings;
+};
+
+#endif
diff --git a/gpu/gl/GrGLFunctions.h b/gpu/gl/GrGLFunctions.h
new file mode 100644
index 0000000..b30ef3a
--- /dev/null
+++ b/gpu/gl/GrGLFunctions.h
@@ -0,0 +1,231 @@
+
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrGLFunctions_DEFINED
+#define GrGLFunctions_DEFINED
+
+#include "GrGLConfig.h"
+
+/**
+ * Declares typedefs for all the GL functions used in GrGLInterface
+ */
+
+///////////////////////////////////////////////////////////////////////////////
+
+typedef unsigned int GrGLenum;
+typedef unsigned char GrGLboolean;
+typedef unsigned int GrGLbitfield;
+typedef signed char GrGLbyte;
+typedef char GrGLchar;
+typedef short GrGLshort;
+typedef int GrGLint;
+typedef int GrGLsizei;
+typedef int64_t GrGLint64;
+typedef unsigned char GrGLubyte;
+typedef unsigned short GrGLushort;
+typedef unsigned int GrGLuint;
+typedef uint64_t GrGLuint64;
+typedef float GrGLfloat;
+typedef float GrGLclampf;
+typedef double GrGLdouble;
+typedef double GrGLclampd;
+typedef void GrGLvoid;
+typedef long GrGLintptr;
+typedef long GrGLsizeiptr;
+
+///////////////////////////////////////////////////////////////////////////////
+
+extern "C" {
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLActiveTextureProc)(GrGLenum texture);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLAttachShaderProc)(GrGLuint program, GrGLuint shader);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLBeginQueryProc)(GrGLenum target, GrGLuint id);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLBindAttribLocationProc)(GrGLuint program, GrGLuint index, const char* name);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLBindBufferProc)(GrGLenum target, GrGLuint buffer);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLBindFramebufferProc)(GrGLenum target, GrGLuint framebuffer);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLBindRenderbufferProc)(GrGLenum target, GrGLuint renderbuffer);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLBindTextureProc)(GrGLenum target, GrGLuint texture);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLBlendColorProc)(GrGLclampf red, GrGLclampf green, GrGLclampf blue, GrGLclampf alpha);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLBindFragDataLocationProc)(GrGLuint program, GrGLuint colorNumber, const GrGLchar* name);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLBindFragDataLocationIndexedProc)(GrGLuint program, GrGLuint colorNumber, GrGLuint index, const GrGLchar * name);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLBindVertexArrayProc)(GrGLuint array);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLBlendFuncProc)(GrGLenum sfactor, GrGLenum dfactor);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLBlitFramebufferProc)(GrGLint srcX0, GrGLint srcY0, GrGLint srcX1, GrGLint srcY1, GrGLint dstX0, GrGLint dstY0, GrGLint dstX1, GrGLint dstY1, GrGLbitfield mask, GrGLenum filter);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLBufferDataProc)(GrGLenum target, GrGLsizeiptr size, const GrGLvoid* data, GrGLenum usage);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLBufferSubDataProc)(GrGLenum target, GrGLintptr offset, GrGLsizeiptr size, const GrGLvoid* data);
+ typedef GrGLenum (GR_GL_FUNCTION_TYPE* GrGLCheckFramebufferStatusProc)(GrGLenum target);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLClearProc)(GrGLbitfield mask);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLClearColorProc)(GrGLclampf red, GrGLclampf green, GrGLclampf blue, GrGLclampf alpha);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLClearStencilProc)(GrGLint s);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLColorMaskProc)(GrGLboolean red, GrGLboolean green, GrGLboolean blue, GrGLboolean alpha);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLCompileShaderProc)(GrGLuint shader);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLCompressedTexImage2DProc)(GrGLenum target, GrGLint level, GrGLenum internalformat, GrGLsizei width, GrGLsizei height, GrGLint border, GrGLsizei imageSize, const GrGLvoid* data);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLCopyTexSubImage2DProc)(GrGLenum target, GrGLint level, GrGLint xoffset, GrGLint yoffset, GrGLint x, GrGLint y, GrGLsizei width, GrGLsizei height);
+ typedef GrGLuint (GR_GL_FUNCTION_TYPE* GrGLCreateProgramProc)(void);
+ typedef GrGLuint (GR_GL_FUNCTION_TYPE* GrGLCreateShaderProc)(GrGLenum type);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLCullFaceProc)(GrGLenum mode);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLDeleteBuffersProc)(GrGLsizei n, const GrGLuint* buffers);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLDeleteFramebuffersProc)(GrGLsizei n, const GrGLuint *framebuffers);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLDeleteProgramProc)(GrGLuint program);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLDeleteQueriesProc)(GrGLsizei n, const GrGLuint *ids);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLDeleteRenderbuffersProc)(GrGLsizei n, const GrGLuint *renderbuffers);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLDeleteShaderProc)(GrGLuint shader);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLDeleteTexturesProc)(GrGLsizei n, const GrGLuint* textures);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLDeleteVertexArraysProc)(GrGLsizei n, const GrGLuint *arrays);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLDepthMaskProc)(GrGLboolean flag);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLDisableProc)(GrGLenum cap);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLDisableVertexAttribArrayProc)(GrGLuint index);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLDrawArraysProc)(GrGLenum mode, GrGLint first, GrGLsizei count);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLDrawBufferProc)(GrGLenum mode);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLDrawBuffersProc)(GrGLsizei n, const GrGLenum* bufs);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLDrawElementsProc)(GrGLenum mode, GrGLsizei count, GrGLenum type, const GrGLvoid* indices);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLEnableProc)(GrGLenum cap);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLEnableVertexAttribArrayProc)(GrGLuint index);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLEndQueryProc)(GrGLenum target);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLFinishProc)();
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLFlushProc)();
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLFramebufferRenderbufferProc)(GrGLenum target, GrGLenum attachment, GrGLenum renderbuffertarget, GrGLuint renderbuffer);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLFramebufferTexture2DProc)(GrGLenum target, GrGLenum attachment, GrGLenum textarget, GrGLuint texture, GrGLint level);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLFramebufferTexture2DMultisampleProc)(GrGLenum target, GrGLenum attachment, GrGLenum textarget, GrGLuint texture, GrGLint level, GrGLsizei samples);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLFrontFaceProc)(GrGLenum mode);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLGenBuffersProc)(GrGLsizei n, GrGLuint* buffers);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLGenFramebuffersProc)(GrGLsizei n, GrGLuint *framebuffers);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLGenerateMipmapProc)(GrGLenum target);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLGenQueriesProc)(GrGLsizei n, GrGLuint *ids);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLGenRenderbuffersProc)(GrGLsizei n, GrGLuint *renderbuffers);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLGenTexturesProc)(GrGLsizei n, GrGLuint* textures);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLGenVertexArraysProc)(GrGLsizei n, GrGLuint *arrays);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLGetBufferParameterivProc)(GrGLenum target, GrGLenum pname, GrGLint* params);
+ typedef GrGLenum (GR_GL_FUNCTION_TYPE* GrGLGetErrorProc)();
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLGetFramebufferAttachmentParameterivProc)(GrGLenum target, GrGLenum attachment, GrGLenum pname, GrGLint* params);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLGetIntegervProc)(GrGLenum pname, GrGLint* params);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLGetProgramInfoLogProc)(GrGLuint program, GrGLsizei bufsize, GrGLsizei* length, char* infolog);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLGetProgramivProc)(GrGLuint program, GrGLenum pname, GrGLint* params);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLGetQueryivProc)(GrGLenum GLtarget, GrGLenum pname, GrGLint *params);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLGetQueryObjecti64vProc)(GrGLuint id, GrGLenum pname, GrGLint64 *params);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLGetQueryObjectivProc)(GrGLuint id, GrGLenum pname, GrGLint *params);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLGetQueryObjectui64vProc)(GrGLuint id, GrGLenum pname, GrGLuint64 *params);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLGetQueryObjectuivProc)(GrGLuint id, GrGLenum pname, GrGLuint *params);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLGetRenderbufferParameterivProc)(GrGLenum target, GrGLenum pname, GrGLint* params);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLGetShaderInfoLogProc)(GrGLuint shader, GrGLsizei bufsize, GrGLsizei* length, char* infolog);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLGetShaderivProc)(GrGLuint shader, GrGLenum pname, GrGLint* params);
+ typedef const GrGLubyte* (GR_GL_FUNCTION_TYPE* GrGLGetStringProc)(GrGLenum name);
+ typedef const GrGLubyte* (GR_GL_FUNCTION_TYPE* GrGLGetStringiProc)(GrGLenum name, GrGLuint index);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLGetTexLevelParameterivProc)(GrGLenum target, GrGLint level, GrGLenum pname, GrGLint* params);
+ typedef GrGLint (GR_GL_FUNCTION_TYPE* GrGLGetUniformLocationProc)(GrGLuint program, const char* name);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLLineWidthProc)(GrGLfloat width);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLLinkProgramProc)(GrGLuint program);
+ typedef GrGLvoid* (GR_GL_FUNCTION_TYPE* GrGLMapBufferProc)(GrGLenum target, GrGLenum access);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLPixelStoreiProc)(GrGLenum pname, GrGLint param);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLQueryCounterProc)(GrGLuint id, GrGLenum target);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLReadBufferProc)(GrGLenum src);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLReadPixelsProc)(GrGLint x, GrGLint y, GrGLsizei width, GrGLsizei height, GrGLenum format, GrGLenum type, GrGLvoid* pixels);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLRenderbufferStorageProc)(GrGLenum target, GrGLenum internalformat, GrGLsizei width, GrGLsizei height);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLRenderbufferStorageMultisampleProc)(GrGLenum target, GrGLsizei samples, GrGLenum internalformat, GrGLsizei width, GrGLsizei height);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLRenderbufferStorageMultisampleCoverageProc)(GrGLenum target, GrGLsizei coverageSamples, GrGLsizei colorSamples, GrGLenum internalformat, GrGLsizei width, GrGLsizei height);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLResolveMultisampleFramebufferProc)();
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLScissorProc)(GrGLint x, GrGLint y, GrGLsizei width, GrGLsizei height);
+#if GR_GL_USE_NEW_SHADER_SOURCE_SIGNATURE
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLShaderSourceProc)(GrGLuint shader, GrGLsizei count, const char* const * str, const GrGLint* length);
+#else
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLShaderSourceProc)(GrGLuint shader, GrGLsizei count, const char** str, const GrGLint* length);
+#endif
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLStencilFuncProc)(GrGLenum func, GrGLint ref, GrGLuint mask);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLStencilFuncSeparateProc)(GrGLenum face, GrGLenum func, GrGLint ref, GrGLuint mask);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLStencilMaskProc)(GrGLuint mask);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLStencilMaskSeparateProc)(GrGLenum face, GrGLuint mask);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLStencilOpProc)(GrGLenum fail, GrGLenum zfail, GrGLenum zpass);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLStencilOpSeparateProc)(GrGLenum face, GrGLenum fail, GrGLenum zfail, GrGLenum zpass);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLTexImage2DProc)(GrGLenum target, GrGLint level, GrGLint internalformat, GrGLsizei width, GrGLsizei height, GrGLint border, GrGLenum format, GrGLenum type, const GrGLvoid* pixels);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLTexParameteriProc)(GrGLenum target, GrGLenum pname, GrGLint param);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLTexParameterivProc)(GrGLenum target, GrGLenum pname, const GrGLint* params);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLTexStorage2DProc)(GrGLenum target, GrGLsizei levels, GrGLenum internalformat, GrGLsizei width, GrGLsizei height);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLDiscardFramebufferProc)(GrGLenum target, GrGLsizei numAttachments, const GrGLenum* attachments);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLTexSubImage2DProc)(GrGLenum target, GrGLint level, GrGLint xoffset, GrGLint yoffset, GrGLsizei width, GrGLsizei height, GrGLenum format, GrGLenum type, const GrGLvoid* pixels);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLUniform1fProc)(GrGLint location, GrGLfloat v0);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLUniform1iProc)(GrGLint location, GrGLint v0);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLUniform1fvProc)(GrGLint location, GrGLsizei count, const GrGLfloat* v);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLUniform1ivProc)(GrGLint location, GrGLsizei count, const GrGLint* v);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLUniform2fProc)(GrGLint location, GrGLfloat v0, GrGLfloat v1);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLUniform2iProc)(GrGLint location, GrGLint v0, GrGLint v1);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLUniform2fvProc)(GrGLint location, GrGLsizei count, const GrGLfloat* v);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLUniform2ivProc)(GrGLint location, GrGLsizei count, const GrGLint* v);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLUniform3fProc)(GrGLint location, GrGLfloat v0, GrGLfloat v1, GrGLfloat v2);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLUniform3iProc)(GrGLint location, GrGLint v0, GrGLint v1, GrGLint v2);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLUniform3fvProc)(GrGLint location, GrGLsizei count, const GrGLfloat* v);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLUniform3ivProc)(GrGLint location, GrGLsizei count, const GrGLint* v);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLUniform4fProc)(GrGLint location, GrGLfloat v0, GrGLfloat v1, GrGLfloat v2, GrGLfloat v3);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLUniform4iProc)(GrGLint location, GrGLint v0, GrGLint v1, GrGLint v2, GrGLint v3);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLUniform4fvProc)(GrGLint location, GrGLsizei count, const GrGLfloat* v);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLUniform4ivProc)(GrGLint location, GrGLsizei count, const GrGLint* v);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLUniformMatrix2fvProc)(GrGLint location, GrGLsizei count, GrGLboolean transpose, const GrGLfloat* value);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLUniformMatrix3fvProc)(GrGLint location, GrGLsizei count, GrGLboolean transpose, const GrGLfloat* value);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLUniformMatrix4fvProc)(GrGLint location, GrGLsizei count, GrGLboolean transpose, const GrGLfloat* value);
+ typedef GrGLboolean (GR_GL_FUNCTION_TYPE* GrGLUnmapBufferProc)(GrGLenum target);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLUseProgramProc)(GrGLuint program);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLVertexAttrib4fvProc)(GrGLuint indx, const GrGLfloat* values);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLVertexAttribPointerProc)(GrGLuint indx, GrGLint size, GrGLenum type, GrGLboolean normalized, GrGLsizei stride, const GrGLvoid* ptr);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLViewportProc)(GrGLint x, GrGLint y, GrGLsizei width, GrGLsizei height);
+
+ // Experimental: Functions for GL_NV_path_rendering. These will be
+ // alphabetized with the above functions once this is fully supported
+ // (and functions we are unlikely to use will possibly be omitted).
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLMatrixModeProc)(GrGLenum);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLLoadIdentityProc)();
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLLoadMatrixfProc)(const GrGLfloat* m);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLPathCommandsProc)(GrGLuint path, GrGLsizei numCommands, const GrGLubyte *commands, GrGLsizei numCoords, GrGLenum coordType, const GrGLvoid *coords);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLPathCoordsProc)(GrGLuint path, GrGLsizei numCoords, GrGLenum coordType, const GrGLvoid *coords);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLPathSubCommandsProc)(GrGLuint path, GrGLsizei commandStart, GrGLsizei commandsToDelete, GrGLsizei numCommands, const GrGLubyte *commands, GrGLsizei numCoords, GrGLenum coordType, const GrGLvoid *coords);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLPathSubCoordsProc)(GrGLuint path, GrGLsizei coordStart, GrGLsizei numCoords, GrGLenum coordType, const GrGLvoid *coords);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLPathStringProc)(GrGLuint path, GrGLenum format, GrGLsizei length, const GrGLvoid *pathString);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLPathGlyphsProc)(GrGLuint firstPathName, GrGLenum fontTarget, const GrGLvoid *fontName, GrGLbitfield fontStyle, GrGLsizei numGlyphs, GrGLenum type, const GrGLvoid *charcodes, GrGLenum handleMissingGlyphs, GrGLuint pathParameterTemplate, GrGLfloat emScale);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLPathGlyphRangeProc)(GrGLuint firstPathName, GrGLenum fontTarget, const GrGLvoid *fontName, GrGLbitfield fontStyle, GrGLuint firstGlyph, GrGLsizei numGlyphs, GrGLenum handleMissingGlyphs, GrGLuint pathParameterTemplate, GrGLfloat emScale);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLWeightPathsProc)(GrGLuint resultPath, GrGLsizei numPaths, const GrGLuint paths[], const GrGLfloat weights[]);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLCopyPathProc)(GrGLuint resultPath, GrGLuint srcPath);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLInterpolatePathsProc)(GrGLuint resultPath, GrGLuint pathA, GrGLuint pathB, GrGLfloat weight);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLTransformPathProc)(GrGLuint resultPath, GrGLuint srcPath, GrGLenum transformType, const GrGLfloat *transformValues);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLPathParameterivProc)(GrGLuint path, GrGLenum pname, const GrGLint *value);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLPathParameteriProc)(GrGLuint path, GrGLenum pname, GrGLint value);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLPathParameterfvProc)(GrGLuint path, GrGLenum pname, const GrGLfloat *value);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLPathParameterfProc)(GrGLuint path, GrGLenum pname, GrGLfloat value);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLPathDashArrayProc)(GrGLuint path, GrGLsizei dashCount, const GrGLfloat *dashArray);
+ typedef GrGLuint (GR_GL_FUNCTION_TYPE* GrGLGenPathsProc)(GrGLsizei range);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLDeletePathsProc)(GrGLuint path, GrGLsizei range);
+ typedef GrGLboolean (GR_GL_FUNCTION_TYPE* GrGLIsPathProc)(GrGLuint path);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLPathStencilFuncProc)(GrGLenum func, GrGLint ref, GrGLuint mask);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLPathStencilDepthOffsetProc)(GrGLfloat factor, GrGLfloat units);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLStencilFillPathProc)(GrGLuint path, GrGLenum fillMode, GrGLuint mask);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLStencilStrokePathProc)(GrGLuint path, GrGLint reference, GrGLuint mask);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLStencilFillPathInstancedProc)(GrGLsizei numPaths, GrGLenum pathNameType, const GrGLvoid *paths, GrGLuint pathBase, GrGLenum fillMode, GrGLuint mask, GrGLenum transformType, const GrGLfloat *transformValues);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLStencilStrokePathInstancedProc)(GrGLsizei numPaths, GrGLenum pathNameType, const GrGLvoid *paths, GrGLuint pathBase, GrGLint reference, GrGLuint mask, GrGLenum transformType, const GrGLfloat *transformValues);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLPathCoverDepthFuncProc)(GrGLenum zfunc);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLPathColorGenProc)(GrGLenum color, GrGLenum genMode, GrGLenum colorFormat, const GrGLfloat *coeffs);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLPathTexGenProc)(GrGLenum texCoordSet, GrGLenum genMode, GrGLint components, const GrGLfloat *coeffs);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLPathFogGenProc)(GrGLenum genMode);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLCoverFillPathProc)(GrGLuint path, GrGLenum coverMode);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLCoverStrokePathProc)(GrGLuint name, GrGLenum coverMode);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLCoverFillPathInstancedProc)(GrGLsizei numPaths, GrGLenum pathNameType, const GrGLvoid *paths, GrGLuint pathBase, GrGLenum coverMode, GrGLenum transformType, const GrGLfloat *transformValues);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLCoverStrokePathInstancedProc)(GrGLsizei numPaths, GrGLenum pathNameType, const GrGLvoid *paths, GrGLuint pathBase, GrGLenum coverMode, GrGLenum transformType, const GrGLfloat* transformValues);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLGetPathParameterivProc)(GrGLuint name, GrGLenum param, GrGLint *value);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLGetPathParameterfvProc)(GrGLuint name, GrGLenum param, GrGLfloat *value);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLGetPathCommandsProc)(GrGLuint name, GrGLubyte *commands);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLGetPathCoordsProc)(GrGLuint name, GrGLfloat *coords);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLGetPathDashArrayProc)(GrGLuint name, GrGLfloat *dashArray);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLGetPathMetricsProc)(GrGLbitfield metricQueryMask, GrGLsizei numPaths, GrGLenum pathNameType, const GrGLvoid *paths, GrGLuint pathBase, GrGLsizei stride, GrGLfloat *metrics);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLGetPathMetricRangeProc)(GrGLbitfield metricQueryMask, GrGLuint fistPathName, GrGLsizei numPaths, GrGLsizei stride, GrGLfloat *metrics);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLGetPathSpacingProc)(GrGLenum pathListMode, GrGLsizei numPaths, GrGLenum pathNameType, const GrGLvoid *paths, GrGLuint pathBase, GrGLfloat advanceScale, GrGLfloat kerningScale, GrGLenum transformType, GrGLfloat *returnedSpacing);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLGetPathColorGenivProc)(GrGLenum color, GrGLenum pname, GrGLint *value);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLGetPathColorGenfvProc)(GrGLenum color, GrGLenum pname, GrGLfloat *value);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLGetPathTexGenivProc)(GrGLenum texCoordSet, GrGLenum pname, GrGLint *value);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLGetPathTexGenfvProc)(GrGLenum texCoordSet, GrGLenum pname, GrGLfloat *value);
+ typedef GrGLboolean (GR_GL_FUNCTION_TYPE* GrGLIsPointInFillPathProc)(GrGLuint path, GrGLuint mask, GrGLfloat x, GrGLfloat y);
+ typedef GrGLboolean (GR_GL_FUNCTION_TYPE* GrGLIsPointInStrokePathProc)(GrGLuint path, GrGLfloat x, GrGLfloat y);
+ typedef GrGLfloat (GR_GL_FUNCTION_TYPE* GrGLGetPathLengthProc)(GrGLuint path, GrGLsizei startSegment, GrGLsizei numSegments);
+ typedef GrGLboolean (GR_GL_FUNCTION_TYPE* GrGLPointAlongPathProc)(GrGLuint path, GrGLsizei startSegment, GrGLsizei numSegments, GrGLfloat distance, GrGLfloat *x, GrGLfloat *y, GrGLfloat *tangentX, GrGLfloat *tangentY);
+} // extern "C"
+
+#endif
diff --git a/gpu/gl/GrGLInterface.h b/gpu/gl/GrGLInterface.h
new file mode 100644
index 0000000..6a51adc
--- /dev/null
+++ b/gpu/gl/GrGLInterface.h
@@ -0,0 +1,329 @@
+
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef GrGLInterface_DEFINED
+#define GrGLInterface_DEFINED
+
+#include "GrGLFunctions.h"
+#include "GrRefCnt.h"
+
+////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Classifies GL contexts (currently as Desktop vs. ES2). This is a bitfield.
+ * A GrGLInterface (defined below) may support multiple bindings.
+ */
+enum GrGLBinding {
+ kNone_GrGLBinding = 0x0,
+
+ kDesktop_GrGLBinding = 0x01,
+ kES2_GrGLBinding = 0x02,
+
+ // for iteration of GrGLBindings
+ kFirstGrGLBinding = kDesktop_GrGLBinding,
+ kLastGrGLBinding = kES2_GrGLBinding
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Rather than depend on platform-specific GL headers and libraries, we require
+ * the client to provide a struct of GL function pointers. This struct can be
+ * specified per-GrContext as a parameter to GrContext::Create. If NULL is
+ * passed to Create then the "default" GL interface is used. If the default is
+ * also NULL GrContext creation will fail.
+ *
+ * The default interface is returned by GrGLDefaultInterface. This function's
+ * implementation is platform-specific. Several have been provided, along with
+ * an implementation that simply returns NULL. It is implementation-specific
+ * whether the same GrGLInterface is returned or whether a new one is created
+ * at each call. Some platforms may not be able to use a single GrGLInterface
+ * because extension function ptrs vary across contexts. Note that GrGLInterface
+ * is ref-counted. So if the same object is returned by multiple calls to
+ * GrGLDefaultInterface, each should bump the ref count.
+ *
+ * By defining GR_GL_PER_GL_CALL_IFACE_CALLBACK to 1 the client can specify a
+ * callback function that will be called prior to each GL function call. See
+ * comments in GrGLConfig.h
+ */
+
+struct GrGLInterface;
+
+const GrGLInterface* GrGLDefaultInterface();
+
+/**
+ * Creates a GrGLInterface for a "native" GL context (e.g. WGL on windows,
+ * GLX on linux, AGL on Mac). On platforms that have context-specific function
+ * pointers for GL extensions (e.g. windows) the returned interface is only
+ * valid for the context that was current at creation.
+ */
+const GrGLInterface* GrGLCreateNativeInterface();
+
+#if SK_MESA
+/**
+ * Creates a GrGLInterface for an OSMesa context.
+ */
+const GrGLInterface* GrGLCreateMesaInterface();
+#endif
+
+#if SK_ANGLE
+/**
+ * Creates a GrGLInterface for an ANGLE context.
+ */
+const GrGLInterface* GrGLCreateANGLEInterface();
+#endif
+
+/**
+ * Creates a null GrGLInterface that doesn't draw anything. Used for measuring
+ * CPU overhead.
+ */
+const GrGLInterface* GrGLCreateNullInterface();
+
+/**
+ * Creates a debugging GrGLInterface that doesn't draw anything. Used for
+ * finding memory leaks and invalid memory accesses.
+ */
+const GrGLInterface* GrGLCreateDebugInterface();
+
+#if GR_GL_PER_GL_FUNC_CALLBACK
+typedef void (*GrGLInterfaceCallbackProc)(const GrGLInterface*);
+typedef intptr_t GrGLInterfaceCallbackData;
+#endif
+
+/*
+ * GrContext uses the following interface to make all calls into OpenGL. When a
+ * GrContext is created it is given a GrGLInterface. The interface's function
+ * pointers must be valid for the OpenGL context associated with the GrContext.
+ * On some platforms, such as Windows, function pointers for OpenGL extensions
+ * may vary between OpenGL contexts. So the caller must be careful to use a
+ * GrGLInterface initialized for the correct context. All functions that should
+ * be available based on the OpenGL's version and extension string must be
+ * non-NULL or GrContext creation will fail. This can be tested with the
+ * validate() method when the OpenGL context has been made current.
+ */
+struct GR_API GrGLInterface : public GrRefCnt {
+private:
+ // simple wrapper class that exists only to initialize a pointer to NULL
+ template <typename FNPTR_TYPE> class GLPtr {
+ public:
+ GLPtr() : fPtr(NULL) {}
+ GLPtr operator =(FNPTR_TYPE ptr) { fPtr = ptr; return *this; }
+ operator FNPTR_TYPE() const { return fPtr; }
+ private:
+ FNPTR_TYPE fPtr;
+ };
+
+ typedef GrRefCnt INHERITED;
+
+public:
+ SK_DECLARE_INST_COUNT(GrGLInterface)
+
+ GrGLInterface();
+
+ // Validates that the GrGLInterface supports a binding. This means that
+ // the GrGLinterface advertises the binding in fBindingsExported and all
+ // the necessary function pointers have been initialized. The interface is
+ // validated for the current OpenGL context.
+ bool validate(GrGLBinding binding) const;
+
+ // Indicator variable specifying the type of GL implementation
+ // exported: GLES2 and/or Desktop.
+ GrGLBinding fBindingsExported;
+
+ GLPtr<GrGLActiveTextureProc> fActiveTexture;
+ GLPtr<GrGLAttachShaderProc> fAttachShader;
+ GLPtr<GrGLBeginQueryProc> fBeginQuery;
+ GLPtr<GrGLBindAttribLocationProc> fBindAttribLocation;
+ GLPtr<GrGLBindBufferProc> fBindBuffer;
+ GLPtr<GrGLBindFragDataLocationProc> fBindFragDataLocation;
+ GLPtr<GrGLBindFragDataLocationIndexedProc> fBindFragDataLocationIndexed;
+ GLPtr<GrGLBindFramebufferProc> fBindFramebuffer;
+ GLPtr<GrGLBindRenderbufferProc> fBindRenderbuffer;
+ GLPtr<GrGLBindTextureProc> fBindTexture;
+ GLPtr<GrGLBindVertexArrayProc> fBindVertexArray;
+ GLPtr<GrGLBlendColorProc> fBlendColor;
+ GLPtr<GrGLBlendFuncProc> fBlendFunc;
+ GLPtr<GrGLBlitFramebufferProc> fBlitFramebuffer;
+ GLPtr<GrGLBufferDataProc> fBufferData;
+ GLPtr<GrGLBufferSubDataProc> fBufferSubData;
+ GLPtr<GrGLCheckFramebufferStatusProc> fCheckFramebufferStatus;
+ GLPtr<GrGLClearProc> fClear;
+ GLPtr<GrGLClearColorProc> fClearColor;
+ GLPtr<GrGLClearStencilProc> fClearStencil;
+ GLPtr<GrGLColorMaskProc> fColorMask;
+ GLPtr<GrGLCompileShaderProc> fCompileShader;
+ GLPtr<GrGLCompressedTexImage2DProc> fCompressedTexImage2D;
+ GLPtr<GrGLCopyTexSubImage2DProc> fCopyTexSubImage2D;
+ GLPtr<GrGLCreateProgramProc> fCreateProgram;
+ GLPtr<GrGLCreateShaderProc> fCreateShader;
+ GLPtr<GrGLCullFaceProc> fCullFace;
+ GLPtr<GrGLDeleteBuffersProc> fDeleteBuffers;
+ GLPtr<GrGLDeleteFramebuffersProc> fDeleteFramebuffers;
+ GLPtr<GrGLDeleteProgramProc> fDeleteProgram;
+ GLPtr<GrGLDeleteQueriesProc> fDeleteQueries;
+ GLPtr<GrGLDeleteRenderbuffersProc> fDeleteRenderbuffers;
+ GLPtr<GrGLDeleteShaderProc> fDeleteShader;
+ GLPtr<GrGLDeleteTexturesProc> fDeleteTextures;
+ GLPtr<GrGLDeleteVertexArraysProc> fDeleteVertexArrays;
+ GLPtr<GrGLDepthMaskProc> fDepthMask;
+ GLPtr<GrGLDisableProc> fDisable;
+ GLPtr<GrGLDisableVertexAttribArrayProc> fDisableVertexAttribArray;
+ GLPtr<GrGLDrawArraysProc> fDrawArrays;
+ GLPtr<GrGLDrawBufferProc> fDrawBuffer;
+ GLPtr<GrGLDrawBuffersProc> fDrawBuffers;
+ GLPtr<GrGLDrawElementsProc> fDrawElements;
+ GLPtr<GrGLEnableProc> fEnable;
+ GLPtr<GrGLEnableVertexAttribArrayProc> fEnableVertexAttribArray;
+ GLPtr<GrGLEndQueryProc> fEndQuery;
+ GLPtr<GrGLFinishProc> fFinish;
+ GLPtr<GrGLFlushProc> fFlush;
+ GLPtr<GrGLFramebufferRenderbufferProc> fFramebufferRenderbuffer;
+ GLPtr<GrGLFramebufferTexture2DProc> fFramebufferTexture2D;
+ GLPtr<GrGLFramebufferTexture2DMultisampleProc> fFramebufferTexture2DMultisample;
+ GLPtr<GrGLFrontFaceProc> fFrontFace;
+ GLPtr<GrGLGenBuffersProc> fGenBuffers;
+ GLPtr<GrGLGenFramebuffersProc> fGenFramebuffers;
+ GLPtr<GrGLGenerateMipmapProc> fGenerateMipmap;
+ GLPtr<GrGLGenQueriesProc> fGenQueries;
+ GLPtr<GrGLGenRenderbuffersProc> fGenRenderbuffers;
+ GLPtr<GrGLGenTexturesProc> fGenTextures;
+ GLPtr<GrGLGenVertexArraysProc> fGenVertexArrays;
+ GLPtr<GrGLGetBufferParameterivProc> fGetBufferParameteriv;
+ GLPtr<GrGLGetErrorProc> fGetError;
+ GLPtr<GrGLGetFramebufferAttachmentParameterivProc> fGetFramebufferAttachmentParameteriv;
+ GLPtr<GrGLGetIntegervProc> fGetIntegerv;
+ GLPtr<GrGLGetQueryObjecti64vProc> fGetQueryObjecti64v;
+ GLPtr<GrGLGetQueryObjectivProc> fGetQueryObjectiv;
+ GLPtr<GrGLGetQueryObjectui64vProc> fGetQueryObjectui64v;
+ GLPtr<GrGLGetQueryObjectuivProc> fGetQueryObjectuiv;
+ GLPtr<GrGLGetQueryivProc> fGetQueryiv;
+ GLPtr<GrGLGetProgramInfoLogProc> fGetProgramInfoLog;
+ GLPtr<GrGLGetProgramivProc> fGetProgramiv;
+ GLPtr<GrGLGetRenderbufferParameterivProc> fGetRenderbufferParameteriv;
+ GLPtr<GrGLGetShaderInfoLogProc> fGetShaderInfoLog;
+ GLPtr<GrGLGetShaderivProc> fGetShaderiv;
+ GLPtr<GrGLGetStringProc> fGetString;
+ GLPtr<GrGLGetStringiProc> fGetStringi;
+ GLPtr<GrGLGetTexLevelParameterivProc> fGetTexLevelParameteriv;
+ GLPtr<GrGLGetUniformLocationProc> fGetUniformLocation;
+ GLPtr<GrGLLineWidthProc> fLineWidth;
+ GLPtr<GrGLLinkProgramProc> fLinkProgram;
+ GLPtr<GrGLMapBufferProc> fMapBuffer;
+ GLPtr<GrGLPixelStoreiProc> fPixelStorei;
+ GLPtr<GrGLQueryCounterProc> fQueryCounter;
+ GLPtr<GrGLReadBufferProc> fReadBuffer;
+ GLPtr<GrGLReadPixelsProc> fReadPixels;
+ GLPtr<GrGLRenderbufferStorageProc> fRenderbufferStorage;
+ GLPtr<GrGLRenderbufferStorageMultisampleProc> fRenderbufferStorageMultisample;
+ GLPtr<GrGLRenderbufferStorageMultisampleCoverageProc> fRenderbufferStorageMultisampleCoverage;
+ GLPtr<GrGLResolveMultisampleFramebufferProc> fResolveMultisampleFramebuffer;
+ GLPtr<GrGLScissorProc> fScissor;
+ GLPtr<GrGLShaderSourceProc> fShaderSource;
+ GLPtr<GrGLStencilFuncProc> fStencilFunc;
+ GLPtr<GrGLStencilFuncSeparateProc> fStencilFuncSeparate;
+ GLPtr<GrGLStencilMaskProc> fStencilMask;
+ GLPtr<GrGLStencilMaskSeparateProc> fStencilMaskSeparate;
+ GLPtr<GrGLStencilOpProc> fStencilOp;
+ GLPtr<GrGLStencilOpSeparateProc> fStencilOpSeparate;
+ GLPtr<GrGLTexImage2DProc> fTexImage2D;
+ GLPtr<GrGLTexParameteriProc> fTexParameteri;
+ GLPtr<GrGLTexParameterivProc> fTexParameteriv;
+ GLPtr<GrGLTexSubImage2DProc> fTexSubImage2D;
+ GLPtr<GrGLTexStorage2DProc> fTexStorage2D;
+ GLPtr<GrGLDiscardFramebufferProc> fDiscardFramebuffer;
+ GLPtr<GrGLUniform1fProc> fUniform1f;
+ GLPtr<GrGLUniform1iProc> fUniform1i;
+ GLPtr<GrGLUniform1fvProc> fUniform1fv;
+ GLPtr<GrGLUniform1ivProc> fUniform1iv;
+ GLPtr<GrGLUniform2fProc> fUniform2f;
+ GLPtr<GrGLUniform2iProc> fUniform2i;
+ GLPtr<GrGLUniform2fvProc> fUniform2fv;
+ GLPtr<GrGLUniform2ivProc> fUniform2iv;
+ GLPtr<GrGLUniform3fProc> fUniform3f;
+ GLPtr<GrGLUniform3iProc> fUniform3i;
+ GLPtr<GrGLUniform3fvProc> fUniform3fv;
+ GLPtr<GrGLUniform3ivProc> fUniform3iv;
+ GLPtr<GrGLUniform4fProc> fUniform4f;
+ GLPtr<GrGLUniform4iProc> fUniform4i;
+ GLPtr<GrGLUniform4fvProc> fUniform4fv;
+ GLPtr<GrGLUniform4ivProc> fUniform4iv;
+ GLPtr<GrGLUniformMatrix2fvProc> fUniformMatrix2fv;
+ GLPtr<GrGLUniformMatrix3fvProc> fUniformMatrix3fv;
+ GLPtr<GrGLUniformMatrix4fvProc> fUniformMatrix4fv;
+ GLPtr<GrGLUnmapBufferProc> fUnmapBuffer;
+ GLPtr<GrGLUseProgramProc> fUseProgram;
+ GLPtr<GrGLVertexAttrib4fvProc> fVertexAttrib4fv;
+ GLPtr<GrGLVertexAttribPointerProc> fVertexAttribPointer;
+ GLPtr<GrGLViewportProc> fViewport;
+
+ // Experimental: Functions for GL_NV_path_rendering. These will be
+ // alphabetized with the above functions once this is fully supported
+ // (and functions we are unlikely to use will possibly be omitted).
+ GLPtr<GrGLMatrixModeProc> fMatrixMode;
+ GLPtr<GrGLLoadIdentityProc> fLoadIdentity;
+ GLPtr<GrGLLoadMatrixfProc> fLoadMatrixf;
+ GLPtr<GrGLPathCommandsProc> fPathCommands;
+ GLPtr<GrGLPathCoordsProc> fPathCoords;
+ GLPtr<GrGLPathSubCommandsProc> fPathSubCommands;
+ GLPtr<GrGLPathSubCoordsProc> fPathSubCoords;
+ GLPtr<GrGLPathStringProc> fPathString;
+ GLPtr<GrGLPathGlyphsProc> fPathGlyphs;
+ GLPtr<GrGLPathGlyphRangeProc> fPathGlyphRange;
+ GLPtr<GrGLWeightPathsProc> fWeightPaths;
+ GLPtr<GrGLCopyPathProc> fCopyPath;
+ GLPtr<GrGLInterpolatePathsProc> fInterpolatePaths;
+ GLPtr<GrGLTransformPathProc> fTransformPath;
+ GLPtr<GrGLPathParameterivProc> fPathParameteriv;
+ GLPtr<GrGLPathParameteriProc> fPathParameteri;
+ GLPtr<GrGLPathParameterfvProc> fPathParameterfv;
+ GLPtr<GrGLPathParameterfProc> fPathParameterf;
+ GLPtr<GrGLPathDashArrayProc> fPathDashArray;
+ GLPtr<GrGLGenPathsProc> fGenPaths;
+ GLPtr<GrGLDeletePathsProc> fDeletePaths;
+ GLPtr<GrGLIsPathProc> fIsPath;
+ GLPtr<GrGLPathStencilFuncProc> fPathStencilFunc;
+ GLPtr<GrGLPathStencilDepthOffsetProc> fPathStencilDepthOffset;
+ GLPtr<GrGLStencilFillPathProc> fStencilFillPath;
+ GLPtr<GrGLStencilStrokePathProc> fStencilStrokePath;
+ GLPtr<GrGLStencilFillPathInstancedProc> fStencilFillPathInstanced;
+ GLPtr<GrGLStencilStrokePathInstancedProc> fStencilStrokePathInstanced;
+ GLPtr<GrGLPathCoverDepthFuncProc> fPathCoverDepthFunc;
+ GLPtr<GrGLPathColorGenProc> fPathColorGen;
+ GLPtr<GrGLPathTexGenProc> fPathTexGen;
+ GLPtr<GrGLPathFogGenProc> fPathFogGen;
+ GLPtr<GrGLCoverFillPathProc> fCoverFillPath;
+ GLPtr<GrGLCoverStrokePathProc> fCoverStrokePath;
+ GLPtr<GrGLCoverFillPathInstancedProc> fCoverFillPathInstanced;
+ GLPtr<GrGLCoverStrokePathInstancedProc> fCoverStrokePathInstanced;
+ GLPtr<GrGLGetPathParameterivProc> fGetPathParameteriv;
+ GLPtr<GrGLGetPathParameterfvProc> fGetPathParameterfv;
+ GLPtr<GrGLGetPathCommandsProc> fGetPathCommands;
+ GLPtr<GrGLGetPathCoordsProc> fGetPathCoords;
+ GLPtr<GrGLGetPathDashArrayProc> fGetPathDashArray;
+ GLPtr<GrGLGetPathMetricsProc> fGetPathMetrics;
+ GLPtr<GrGLGetPathMetricRangeProc> fGetPathMetricRange;
+ GLPtr<GrGLGetPathSpacingProc> fGetPathSpacing;
+ GLPtr<GrGLGetPathColorGenivProc> fGetPathColorGeniv;
+ GLPtr<GrGLGetPathColorGenfvProc> fGetPathColorGenfv;
+ GLPtr<GrGLGetPathTexGenivProc> fGetPathTexGeniv;
+ GLPtr<GrGLGetPathTexGenfvProc> fGetPathTexGenfv;
+ GLPtr<GrGLIsPointInFillPathProc> fIsPointInFillPath;
+ GLPtr<GrGLIsPointInStrokePathProc> fIsPointInStrokePath;
+ GLPtr<GrGLGetPathLengthProc> fGetPathLength;
+ GLPtr<GrGLPointAlongPathProc> fPointAlongPath;
+
+ // Per-GL func callback
+#if GR_GL_PER_GL_FUNC_CALLBACK
+ GrGLInterfaceCallbackProc fCallback;
+ GrGLInterfaceCallbackData fCallbackData;
+#endif
+
+};
+
+#endif
diff --git a/gpu/gl/SkANGLEGLContext.h b/gpu/gl/SkANGLEGLContext.h
new file mode 100644
index 0000000..63765a0
--- /dev/null
+++ b/gpu/gl/SkANGLEGLContext.h
@@ -0,0 +1,49 @@
+
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#ifndef SkANGLEGLContext_DEFINED
+#define SkANGLEGLContext_DEFINED
+
+#if SK_ANGLE
+
+#include "SkGLContextHelper.h"
+
+#include <GLES2/gl2.h>
+#include <EGL/egl.h>
+
+class SkANGLEGLContext : public SkGLContextHelper {
+public:
+ SkANGLEGLContext();
+
+ virtual ~SkANGLEGLContext();
+
+ virtual void makeCurrent() const SK_OVERRIDE;
+
+ class AutoContextRestore {
+ public:
+ AutoContextRestore();
+ ~AutoContextRestore();
+
+ private:
+ EGLContext fOldEGLContext;
+ EGLDisplay fOldDisplay;
+ EGLSurface fOldSurface;
+ };
+
+protected:
+ virtual const GrGLInterface* createGLContext() SK_OVERRIDE;
+ virtual void destroyGLContext() SK_OVERRIDE;
+
+private:
+ EGLContext fContext;
+ EGLDisplay fDisplay;
+ EGLSurface fSurface;
+};
+
+#endif
+
+#endif
diff --git a/gpu/gl/SkDebugGLContext.h b/gpu/gl/SkDebugGLContext.h
new file mode 100644
index 0000000..2437aae
--- /dev/null
+++ b/gpu/gl/SkDebugGLContext.h
@@ -0,0 +1,26 @@
+
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#ifndef SkDebugGLContext_DEFINED
+#define SkDebugGLContext_DEFINED
+
+#include "SkGLContextHelper.h"
+
+class SkDebugGLContext : public SkGLContextHelper {
+
+public:
+ SkDebugGLContext() {};
+
+ virtual void makeCurrent() const SK_OVERRIDE {};
+
+protected:
+ virtual const GrGLInterface* createGLContext() SK_OVERRIDE;
+
+ virtual void destroyGLContext() SK_OVERRIDE {};
+};
+
+#endif
diff --git a/gpu/gl/SkGLContextHelper.h b/gpu/gl/SkGLContextHelper.h
new file mode 100644
index 0000000..386a695
--- /dev/null
+++ b/gpu/gl/SkGLContextHelper.h
@@ -0,0 +1,77 @@
+
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#ifndef SkGLContextHelper_DEFINED
+#define SkGLContextHelper_DEFINED
+
+#include "GrGLExtensions.h"
+#include "GrGLInterface.h"
+
+/**
+ * Create an offscreen opengl context with an RGBA8 / 8bit stencil FBO.
+ * Provides a GrGLInterface struct of function pointers for the context.
+ */
+
+class SkGLContextHelper : public SkRefCnt {
+public:
+ SK_DECLARE_INST_COUNT(SkGLContextHelper)
+
+ SkGLContextHelper();
+ virtual ~SkGLContextHelper();
+
+ /**
+ * Initializes the context and makes it current.
+ */
+ bool init(const int width, const int height);
+
+ int getFBOID() const { return fFBO; }
+
+ const GrGLInterface* gl() const { return fGL; }
+
+ virtual void makeCurrent() const = 0;
+
+ bool hasExtension(const char* extensionName) const {
+ GrAssert(NULL != fGL);
+ return fExtensions.has(extensionName);
+ }
+
+protected:
+ /**
+ * Subclass implements this to make a GL context. The returned GrGLInterface
+ * should be populated with functions compatible with the context. The
+ * format and size of backbuffers does not matter since an FBO will be
+ * created.
+ */
+ virtual const GrGLInterface* createGLContext() = 0;
+
+ /**
+ * Subclass should destroy the underlying GL context.
+ */
+ virtual void destroyGLContext() = 0;
+
+private:
+ GrGLExtensions fExtensions;
+ GrGLuint fFBO;
+ GrGLuint fColorBufferID;
+ GrGLuint fDepthStencilBufferID;
+ const GrGLInterface* fGL;
+
+ typedef SkRefCnt INHERITED;
+};
+
+/**
+ * Helper macros for using the GL context through the GrGLInterface. Example:
+ * SK_GL(glCtx, GenTextures(1, &texID));
+ */
+#define SK_GL(ctx, X) (ctx).gl()->f ## X; \
+ SkASSERT(GR_GL_NO_ERROR == (ctx).gl()->fGetError())
+#define SK_GL_RET(ctx, RET, X) (RET) = (ctx).gl()->f ## X; \
+ SkASSERT(GR_GL_NO_ERROR == (ctx).gl()->fGetError())
+#define SK_GL_NOERRCHECK(ctx, X) (ctx).gl()->f ## X
+#define SK_GL_RET_NOERRCHECK(ctx, RET, X) (RET) = (ctx).gl()->f ## X
+
+#endif
diff --git a/gpu/gl/SkMesaGLContext.h b/gpu/gl/SkMesaGLContext.h
new file mode 100644
index 0000000..6470d2e
--- /dev/null
+++ b/gpu/gl/SkMesaGLContext.h
@@ -0,0 +1,50 @@
+
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#ifndef SkMesaGLContext_DEFINED
+#define SkMesaGLContext_DEFINED
+
+#include "SkGLContextHelper.h"
+
+#if SK_MESA
+
+class SkMesaGLContext : public SkGLContextHelper {
+private:
+ typedef intptr_t Context;
+
+public:
+ SkMesaGLContext();
+
+ virtual ~SkMesaGLContext();
+
+ virtual void makeCurrent() const SK_OVERRIDE;
+
+ class AutoContextRestore {
+ public:
+ AutoContextRestore();
+ ~AutoContextRestore();
+
+ private:
+ Context fOldContext;
+ GrGLint fOldWidth;
+ GrGLint fOldHeight;
+ GrGLint fOldFormat;
+ void* fOldImage;
+ };
+
+protected:
+ virtual const GrGLInterface* createGLContext() SK_OVERRIDE;
+ virtual void destroyGLContext() SK_OVERRIDE;
+
+private:
+ Context fContext;
+ GrGLubyte *fImage;
+};
+
+#endif
+
+#endif
diff --git a/gpu/gl/SkNativeGLContext.h b/gpu/gl/SkNativeGLContext.h
new file mode 100644
index 0000000..27a8f09
--- /dev/null
+++ b/gpu/gl/SkNativeGLContext.h
@@ -0,0 +1,85 @@
+
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#ifndef SkNativeGLContext_DEFINED
+#define SkNativeGLContext_DEFINED
+
+#include "SkGLContextHelper.h"
+
+#if defined(SK_BUILD_FOR_MAC)
+ #include <OpenGL/OpenGL.h>
+#elif defined(SK_BUILD_FOR_ANDROID) || defined(SK_BUILD_FOR_NACL)
+ #include <GLES2/gl2.h>
+ #include <EGL/egl.h>
+#elif defined(SK_BUILD_FOR_UNIX)
+ #include <X11/Xlib.h>
+ #include <GL/glx.h>
+#elif defined(SK_BUILD_FOR_WIN32)
+ #include <Windows.h>
+ #include <GL/GL.h>
+#endif
+
+class SkNativeGLContext : public SkGLContextHelper {
+public:
+ SkNativeGLContext();
+
+ virtual ~SkNativeGLContext();
+
+ virtual void makeCurrent() const SK_OVERRIDE;
+
+ class AutoContextRestore {
+ public:
+ AutoContextRestore();
+ ~AutoContextRestore();
+
+ private:
+ #if defined(SK_BUILD_FOR_MAC)
+ CGLContextObj fOldCGLContext;
+ #elif defined(SK_BUILD_FOR_ANDROID) || defined(SK_BUILD_FOR_NACL)
+ EGLContext fOldEGLContext;
+ EGLDisplay fOldDisplay;
+ EGLSurface fOldSurface;
+ #elif defined(SK_BUILD_FOR_UNIX)
+ GLXContext fOldGLXContext;
+ Display* fOldDisplay;
+ GLXDrawable fOldDrawable;
+ #elif defined(SK_BUILD_FOR_WIN32)
+ HDC fOldHDC;
+ HGLRC fOldHGLRC;
+
+ #elif defined(SK_BUILD_FOR_IOS)
+ void* fEAGLContext;
+ #endif
+ };
+
+protected:
+ virtual const GrGLInterface* createGLContext() SK_OVERRIDE;
+ virtual void destroyGLContext() SK_OVERRIDE;
+
+private:
+#if defined(SK_BUILD_FOR_MAC)
+ CGLContextObj fContext;
+#elif defined(SK_BUILD_FOR_ANDROID) || defined(SK_BUILD_FOR_NACL)
+ EGLContext fContext;
+ EGLDisplay fDisplay;
+ EGLSurface fSurface;
+#elif defined(SK_BUILD_FOR_UNIX)
+ GLXContext fContext;
+ Display* fDisplay;
+ Pixmap fPixmap;
+ GLXPixmap fGlxPixmap;
+#elif defined(SK_BUILD_FOR_WIN32)
+ HWND fWindow;
+ HDC fDeviceContext;
+ HGLRC fGlRenderContext;
+ static ATOM gWC;
+#elif defined(SK_BUILD_FOR_IOS)
+ void* fEAGLContext;
+#endif
+};
+
+#endif
diff --git a/gpu/gl/SkNullGLContext.h b/gpu/gl/SkNullGLContext.h
new file mode 100644
index 0000000..4f2639c
--- /dev/null
+++ b/gpu/gl/SkNullGLContext.h
@@ -0,0 +1,26 @@
+
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#ifndef SkNullGLContext_DEFINED
+#define SkNullGLContext_DEFINED
+
+#include "SkGLContextHelper.h"
+
+class SkNullGLContext : public SkGLContextHelper {
+
+public:
+ SkNullGLContext() {};
+
+ virtual void makeCurrent() const SK_OVERRIDE {};
+
+protected:
+ virtual const GrGLInterface* createGLContext() SK_OVERRIDE;
+
+ virtual void destroyGLContext() SK_OVERRIDE {};
+};
+
+#endif
diff --git a/images/SkForceLinking.h b/images/SkForceLinking.h
new file mode 100644
index 0000000..39901f6
--- /dev/null
+++ b/images/SkForceLinking.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/**
+ * This function's sole purpose is to trick the linker into not discarding
+ * SkImageDecoder subclasses just because we do not directly call them.
+ * This is necessary in applications that will create image decoders from
+ * a stream.
+ * Call this function with an expression that evaluates to false to ensure
+ * that the linker includes the subclasses.
+ * Passing true will result in leaked objects.
+ */
+int SkForceLinking(bool doNotPassTrue);
+
+#define __SK_FORCE_IMAGE_DECODER_LINKING \
+static int linking_forced = SkForceLinking(false)
diff --git a/images/SkImageRef.h b/images/SkImageRef.h
new file mode 100644
index 0000000..bca4305
--- /dev/null
+++ b/images/SkImageRef.h
@@ -0,0 +1,104 @@
+
+/*
+ * Copyright 2008 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkImageRef_DEFINED
+#define SkImageRef_DEFINED
+
+#include "SkPixelRef.h"
+#include "SkBitmap.h"
+#include "SkImageDecoder.h"
+#include "SkString.h"
+
+class SkImageRefPool;
+class SkStream;
+
+// define this to enable dumping whenever we add/remove/purge an imageref
+//#define DUMP_IMAGEREF_LIFECYCLE
+
+class SkImageRef : public SkPixelRef {
+public:
+ /** Create a new imageref from a stream. NOTE: the stream is not copied, but
+ since it may be accessed from another thread, the caller must ensure
+ that this imageref is the only owner of the stream. i.e. - sole
+ ownership of the stream object is transferred to this imageref object.
+
+ @param stream The stream containing the encoded image data. This may be
+ retained (by calling ref()), so the caller should not
+ explicitly delete it.
+ @param config The preferred config of the decoded bitmap.
+ @param sampleSize Requested sampleSize for decoding. Defaults to 1.
+ */
+ SkImageRef(SkStream*, SkBitmap::Config config, int sampleSize = 1, SkBaseMutex* mutex = NULL);
+ virtual ~SkImageRef();
+
+ /** this value is passed onto the decoder. Default is true
+ */
+ void setDitherImage(bool dither) { fDoDither = dither; }
+
+ /** Return true if the image can be decoded. If so, and bitmap is non-null,
+ call its setConfig() with the corresponding values, but explicitly will
+ not set its pixels or colortable. Use SkPixelRef::lockPixels() for that.
+
+ If there has been an error decoding the bitmap, this will return false
+ and ignore the bitmap parameter.
+ */
+ bool getInfo(SkBitmap* bm);
+
+ /** Return true if the image can be decoded and is opaque. Calling this
+ method will decode and set the pixels in the specified bitmap and
+ sets the isOpaque flag.
+ */
+ bool isOpaque(SkBitmap* bm);
+
+ SkImageDecoderFactory* getDecoderFactory() const { return fFactory; }
+ // returns the factory parameter
+ SkImageDecoderFactory* setDecoderFactory(SkImageDecoderFactory*);
+
+protected:
+ /** Override if you want to install a custom allocator.
+ When this is called we will have already acquired the mutex!
+ */
+ virtual bool onDecode(SkImageDecoder* codec, SkStream*, SkBitmap*,
+ SkBitmap::Config, SkImageDecoder::Mode);
+
+ /* Overrides from SkPixelRef
+ When these are called, we will have already acquired the mutex!
+ */
+
+ virtual void* onLockPixels(SkColorTable**);
+ // override this in your subclass to clean up when we're unlocking pixels
+ virtual void onUnlockPixels() {}
+
+ SkImageRef(SkFlattenableReadBuffer&, SkBaseMutex* mutex = NULL);
+ virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
+
+ SkBitmap fBitmap;
+
+private:
+ SkStream* setStream(SkStream*);
+ // called with mutex already held. returns true if the bitmap is in the
+ // requested state (or further, i.e. has pixels)
+ bool prepareBitmap(SkImageDecoder::Mode);
+
+ SkImageDecoderFactory* fFactory; // may be null
+ SkStream* fStream;
+ SkBitmap::Config fConfig;
+ int fSampleSize;
+ bool fDoDither;
+ bool fErrorInDecoding;
+
+ friend class SkImageRefPool;
+
+ SkImageRef* fPrev, *fNext;
+ size_t ramUsed() const;
+
+ typedef SkPixelRef INHERITED;
+};
+
+#endif
diff --git a/images/SkImageRef_GlobalPool.h b/images/SkImageRef_GlobalPool.h
new file mode 100644
index 0000000..914b0eb
--- /dev/null
+++ b/images/SkImageRef_GlobalPool.h
@@ -0,0 +1,61 @@
+
+/*
+ * Copyright 2008 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkImageRef_GlobalPool_DEFINED
+#define SkImageRef_GlobalPool_DEFINED
+
+#include "SkImageRef.h"
+
+class SkImageRef_GlobalPool : public SkImageRef {
+public:
+ // if pool is null, use the global pool
+ SkImageRef_GlobalPool(SkStream*, SkBitmap::Config, int sampleSize = 1);
+ virtual ~SkImageRef_GlobalPool();
+
+ SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkImageRef_GlobalPool)
+
+ // API to control the global pool
+
+ /** Return the amount specified as the budget for the cache (in bytes).
+ */
+ static size_t GetRAMBudget();
+
+ /** Set a new budget value for the cache.
+ */
+ static void SetRAMBudget(size_t);
+
+ /** Return how much ram is currently in use by the global cache.
+ */
+ static size_t GetRAMUsed();
+
+ /** Free up (approximately) enough such that the amount used by the cache
+ is <= the specified amount. Since some images may be "in use", the
+ amount actually freed may not always result in a ram usage value <=
+ to the requested amount. In addition, because of the
+ chunky nature of the cache, the resulting usage may be < the requested
+ amount.
+ */
+ static void SetRAMUsed(size_t usageInBytes);
+
+ static void DumpPool();
+
+protected:
+ virtual bool onDecode(SkImageDecoder* codec, SkStream* stream,
+ SkBitmap* bitmap, SkBitmap::Config config,
+ SkImageDecoder::Mode mode);
+
+ virtual void onUnlockPixels();
+
+ SkImageRef_GlobalPool(SkFlattenableReadBuffer&);
+
+private:
+ typedef SkImageRef INHERITED;
+};
+
+#endif
diff --git a/images/SkImages.h b/images/SkImages.h
new file mode 100644
index 0000000..abe10da
--- /dev/null
+++ b/images/SkImages.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+class SkImages {
+public:
+ /**
+ * Initializes flattenables in the images project.
+ */
+ static void InitializeFlattenables();
+};
diff --git a/images/SkMovie.h b/images/SkMovie.h
new file mode 100644
index 0000000..f32d609
--- /dev/null
+++ b/images/SkMovie.h
@@ -0,0 +1,80 @@
+
+/*
+ * Copyright 2008 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkMovie_DEFINED
+#define SkMovie_DEFINED
+
+#include "SkRefCnt.h"
+#include "SkCanvas.h"
+
+class SkStream;
+
+class SkMovie : public SkRefCnt {
+public:
+ SK_DECLARE_INST_COUNT(SkMovie)
+
+ /** Try to create a movie from the stream. If the stream format is not
+ supported, return NULL.
+ */
+ static SkMovie* DecodeStream(SkStream*);
+ /** Try to create a movie from the specified file path. If the file is not
+ found, or the format is not supported, return NULL. If a movie is
+ returned, the stream may be retained by the movie (via ref()) until
+ the movie is finished with it (by calling unref()).
+ */
+ static SkMovie* DecodeFile(const char path[]);
+ /** Try to create a movie from the specified memory.
+ If the format is not supported, return NULL. If a movie is returned,
+ the data will have been read or copied, and so the caller may free
+ it.
+ */
+ static SkMovie* DecodeMemory(const void* data, size_t length);
+
+ SkMSec duration();
+ int width();
+ int height();
+ int isOpaque();
+
+ /** Specify the time code (between 0...duration) to sample a bitmap
+ from the movie. Returns true if this time code generated a different
+ bitmap/frame from the previous state (i.e. true means you need to
+ redraw).
+ */
+ bool setTime(SkMSec);
+
+ // return the right bitmap for the current time code
+ const SkBitmap& bitmap();
+
+protected:
+ struct Info {
+ SkMSec fDuration;
+ int fWidth;
+ int fHeight;
+ bool fIsOpaque;
+ };
+
+ virtual bool onGetInfo(Info*) = 0;
+ virtual bool onSetTime(SkMSec) = 0;
+ virtual bool onGetBitmap(SkBitmap*) = 0;
+
+ // visible for subclasses
+ SkMovie();
+
+private:
+ Info fInfo;
+ SkMSec fCurrTime;
+ SkBitmap fBitmap;
+ bool fNeedBitmap;
+
+ void ensureInfo();
+
+ typedef SkRefCnt INHERITED;
+};
+
+#endif
diff --git a/images/SkPageFlipper.h b/images/SkPageFlipper.h
new file mode 100644
index 0000000..7779c30
--- /dev/null
+++ b/images/SkPageFlipper.h
@@ -0,0 +1,62 @@
+
+/*
+ * Copyright 2008 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkPageFlipper_DEFINED
+#define SkPageFlipper_DEFINED
+
+#include "SkRegion.h"
+
+/** SkPageFlipper manages alternating inval/dirty regions for a rectangular area
+ (like a bitmap). You call inval() to accumulate inval areas, and then when
+ you're ready to "flip" pages (i.e. draw into the one you've been
+ invalidating) you call update, which swaps the inval regions, and returns
+ two things to you: 1) the final inval region to be drawn into, and 2) the
+ region of pixels that should be copied from the "front" page onto the one
+ you're about to draw into. This copyBits region will be disjoint from the
+ inval region, so both need to be handled.
+ */
+class SkPageFlipper {
+public:
+ SkPageFlipper();
+ SkPageFlipper(int width, int height);
+
+ int width() const { return fWidth; }
+ int height() const { return fHeight; }
+
+ void resize(int width, int height);
+
+ bool isDirty() const { return !fDirty1->isEmpty(); }
+ const SkRegion& dirtyRgn() const { return *fDirty1; }
+
+ void inval();
+ void inval(const SkIRect&);
+ void inval(const SkRegion&);
+ void inval(const SkRect&, bool antialias);
+
+ /** When you're ready to write to the back page, call update. The returned
+ region is the invalidate are that needs to be drawn to. The copyBits
+ region (provided by the caller) is the area that should be copied from
+ the front page to the back page (will not intersect with the returned
+ inval region.
+
+ Once this is called, the two internal regions are swapped, so the *new*
+ back inval region is ready to receive new inval calls.
+ */
+ const SkRegion& update(SkRegion* copyBits);
+
+private:
+ SkRegion* fDirty0;
+ SkRegion* fDirty1;
+ SkRegion fDirty0Storage;
+ SkRegion fDirty1Storage;
+ int fWidth;
+ int fHeight;
+};
+
+#endif
diff --git a/lazy/SkBitmapFactory.h b/lazy/SkBitmapFactory.h
new file mode 100644
index 0000000..e967a91
--- /dev/null
+++ b/lazy/SkBitmapFactory.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkBitmapFactory_DEFINED
+#define SkBitmapFactory_DEFINED
+
+#include "SkImage.h"
+#include "SkTypes.h"
+
+class SkBitmap;
+class SkData;
+class SkImageCache;
+
+/**
+ * Factory for creating a bitmap from encoded data.
+ */
+class SkBitmapFactory {
+
+public:
+ /**
+ * Struct containing information about a pixel destination.
+ */
+ struct Target {
+ /**
+ * Pre-allocated memory.
+ */
+ void* fAddr;
+
+ /**
+ * Rowbytes of the allocated memory.
+ */
+ size_t fRowBytes;
+ };
+
+ /**
+ * Signature for a function to decode an image from encoded data.
+ */
+ typedef bool (*DecodeProc)(const void* data, size_t length, SkImage::Info*, const Target*);
+
+ /**
+ * Create a bitmap factory which uses DecodeProc for decoding.
+ * @param DecodeProc Must not be NULL.
+ */
+ SkBitmapFactory(DecodeProc);
+
+ ~SkBitmapFactory();
+
+ /**
+ * Set an image cache to use on pixelrefs provided by installPixelRef. Mutually exclusive
+ * with fCacheSelector.
+ */
+ void setImageCache(SkImageCache* cache);
+
+ /**
+ * Sets up an SkBitmap from encoded data. On success, the SkBitmap will have its Config,
+ * width, height, rowBytes and pixelref set. If fImageCache is non-NULL, or if fCacheSelector
+ * is set and returns non-NULL, the pixelref will lazily decode, and that SkImageCache will
+ * handle the pixel memory. Otherwise installPixelRef will do an immediate decode.
+ * @param SkData Encoded data.
+ * @param SkBitmap to install the pixel ref on.
+ * @return bool Whether or not a pixel ref was successfully installed.
+ */
+ bool installPixelRef(SkData*, SkBitmap*);
+
+ /**
+ * An object for selecting an SkImageCache to use based on an SkImage::Info.
+ */
+ class CacheSelector : public SkRefCnt {
+
+ public:
+ SK_DECLARE_INST_COUNT(CacheSelector)
+ /**
+ * Return an SkImageCache to use based on the provided SkImage::Info. If the caller decides
+ * to hang on to the result, it will call ref, so the implementation should not add a ref
+ * as a result of this call.
+ */
+ virtual SkImageCache* selectCache(const SkImage::Info&) = 0;
+
+ private:
+ typedef SkRefCnt INHERITED;
+ };
+
+ /**
+ * Set the function to be used to select which SkImageCache to use. Mutually exclusive with
+ * fImageCache.
+ */
+ void setCacheSelector(CacheSelector*);
+
+private:
+ DecodeProc fDecodeProc;
+ SkImageCache* fImageCache;
+ CacheSelector* fCacheSelector;
+};
+
+#endif // SkBitmapFactory_DEFINED
diff --git a/lazy/SkImageCache.h b/lazy/SkImageCache.h
new file mode 100644
index 0000000..6d30ae7
--- /dev/null
+++ b/lazy/SkImageCache.h
@@ -0,0 +1,132 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkImageCache_DEFINED
+#define SkImageCache_DEFINED
+
+#include "SkRefCnt.h"
+#include "SkTypes.h"
+
+/**
+ * Interface for a cache that manages pixel memory.
+ */
+class SkImageCache : public SkRefCnt {
+
+public:
+ SK_DECLARE_INST_COUNT(SkImageCache)
+
+ typedef intptr_t ID;
+
+ /**
+ * Allocate memory whose lifetime is managed by the cache. On success, MUST be balanced with a
+ * call to releaseCache and a call to throwAwayCache.
+ * @param bytes Number of bytes needed.
+ * @param ID Output parameter which must not be NULL. On success, ID will be set to a value
+ * associated with that memory which can be used as a parameter to the other functions
+ * in SkImageCache. On failure, ID is unchanged.
+ * @return Pointer to the newly allocated memory, or NULL. This memory is safe to use until
+ * releaseCache is called with ID.
+ */
+ virtual void* allocAndPinCache(size_t bytes, ID*) = 0;
+
+ /**
+ * Output parameter for pinCache, stating whether the memory still contains the data it held
+ * when releaseCache was last called for the same ID.
+ */
+ enum DataStatus {
+ /**
+ * The data has been purged, and therefore needs to be rewritten to the returned memory.
+ */
+ kUninitialized_DataStatus,
+
+ /**
+ * The memory still contains the data it held when releaseCache was last called with the
+ * same ID.
+ */
+ kRetained_DataStatus,
+ };
+
+ /**
+ * Re-request the memory associated with ID and pin it so that it will not be reclaimed until
+ * the next call to releaseCache with the same ID.
+ * @param ID Unique ID for the memory block.
+ * @param status Output parameter which must not be NULL. On success (i.e. the return value is
+ * not NULL), status will be set to one of two states representing the cached memory. If
+ * status is set to kRetained_DataStatus, the memory contains the same data it did
+ * before releaseCache was called with this ID. If status is set to
+ * kUninitialized_DataStatus, the memory is still pinned, but the previous data is no
+ * longer available. If the return value is NULL, status is unchanged.
+ * @return Pointer: If non-NULL, points to the previously allocated memory, in which case
+ * this call must be balanced with a call to releaseCache. If NULL, the memory
+ * has been reclaimed, and throwAwayCache MUST NOT be called.
+ */
+ virtual void* pinCache(ID, DataStatus* status) = 0;
+
+ /**
+ * Inform the cache that it is safe to free the block of memory corresponding to ID. After
+ * calling this function, the pointer returned by allocAndPinCache or pinCache must not be
+ * used again. In order to access the same memory after this, pinCache must be called with
+ * the same ID.
+ * @param ID Unique ID for the memory block which is now safe to age out of the cache.
+ */
+ virtual void releaseCache(ID) = 0;
+
+ /**
+ * Inform the cache that the block of memory associated with ID will not be asked for again.
+ * After this call, ID is no longer valid. Must not be called while the associated memory is
+ * pinned. Must be called to balance a successful allocAndPinCache.
+ */
+ virtual void throwAwayCache(ID) = 0;
+
+ /**
+ * ID which does not correspond to any valid cache.
+ */
+ static const ID UNINITIALIZED_ID = 0;
+
+#ifdef SK_DEBUG
+ /**
+ * Debug only status of a memory block.
+ */
+ enum MemoryStatus {
+ /**
+ * It is safe to use the pointer returned by the most recent of allocAndPinCache(ID) or
+ * pinCache(ID) with the same ID.
+ */
+ kPinned_MemoryStatus,
+
+ /**
+ * The pointer returned by the most recent call to allocAndPinCache(ID) or pinCache(ID) has
+ * since been released by releaseCache(ID). In order to reuse it, pinCache(ID) must be
+ * called again. Note that after calling releaseCache(ID), the status of that particular
+ * ID may not be kUnpinned_MemoryStatus, depending on the implementation, but it will not
+ * be kPinned_MemoryStatus.
+ */
+ kUnpinned_MemoryStatus,
+
+ /**
+ * The memory associated with ID has been thrown away. No calls should be made using the
+ * same ID.
+ */
+ kFreed_MemoryStatus,
+ };
+
+ /**
+ * Debug only function to get the status of a particular block of memory. Safe to call after
+ * throwAwayCache has been called with this ID.
+ */
+ virtual MemoryStatus getMemoryStatus(intptr_t ID) const = 0;
+
+ /**
+ * Debug only function to clear all unpinned caches.
+ */
+ virtual void purgeAllUnpinnedCaches() = 0;
+#endif
+
+private:
+ typedef SkRefCnt INHERITED;
+};
+#endif // SkImageCache_DEFINED
diff --git a/lazy/SkLruImageCache.h b/lazy/SkLruImageCache.h
new file mode 100644
index 0000000..5170a05
--- /dev/null
+++ b/lazy/SkLruImageCache.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkLruImageCache_DEFINED
+#define SkLruImageCache_DEFINED
+
+#include "SkImageCache.h"
+#include "SkThread.h"
+#include "SkTInternalLList.h"
+
+class CachedPixels;
+
+/**
+ * SkImageCache implementation that uses an LRU cache to age out old images.
+ */
+class SkLruImageCache : public SkImageCache {
+
+public:
+ SK_DECLARE_INST_COUNT(SkLruImageCache)
+
+ SkLruImageCache(size_t budget);
+
+ virtual ~SkLruImageCache();
+
+#ifdef SK_DEBUG
+ virtual MemoryStatus getMemoryStatus(ID) const SK_OVERRIDE;
+ virtual void purgeAllUnpinnedCaches() SK_OVERRIDE;
+#endif
+
+ /**
+ * Set the byte limit on cached pixels. If more bytes are used than this, the cache will free
+ * unpinned memory until under the new limit or until all unpinned memory is freed. This will
+ * never free pinned memory, so the cache can potentially remain over the limit. The limit is
+ * enforced each time memory is allocated or released.
+ * 0 is a special flag for an infinite budget.
+ * @return size_t The previous limit.
+ */
+ size_t setImageCacheLimit(size_t newLimit);
+
+ /**
+ * Return the number of bytes of memory currently in use by the cache. Can include memory that
+ * is no longer pinned, but has not been freed.
+ */
+ size_t getImageCacheUsed() const { return fRamUsed; }
+
+ virtual void* allocAndPinCache(size_t bytes, ID*) SK_OVERRIDE;
+ virtual void* pinCache(ID, SkImageCache::DataStatus*) SK_OVERRIDE;
+ virtual void releaseCache(ID) SK_OVERRIDE;
+ virtual void throwAwayCache(ID) SK_OVERRIDE;
+
+private:
+ // Linked list of recently used. Head is the most recently used, and tail is the least.
+ SkTInternalLList<CachedPixels> fLRU;
+ typedef SkTInternalLList<CachedPixels>::Iter Iter;
+
+#ifdef SK_DEBUG
+ // fMutex is mutable so that getMemoryStatus can be const
+ mutable
+#endif
+ SkMutex fMutex;
+ size_t fRamBudget;
+ size_t fRamUsed;
+
+ /**
+ * Find the CachedPixels represented by ID, or NULL if not in the cache. Mutex must be locked
+ * before calling.
+ */
+ CachedPixels* findByID(ID) const;
+
+ /**
+ * If over budget, throw away pixels which are not currently in use until below budget or there
+ * are no more pixels eligible to be thrown away. Mutex must be locked before calling.
+ */
+ void purgeIfNeeded();
+
+ /**
+ * Purge until below limit. Mutex must be locked before calling.
+ */
+ void purgeTilAtOrBelow(size_t limit);
+
+ /**
+ * Remove a set of CachedPixels. Mutex must be locked before calling.
+ */
+ void removePixels(CachedPixels*);
+};
+
+#endif // SkLruImageCache_DEFINED
diff --git a/lazy/SkPurgeableImageCache.h b/lazy/SkPurgeableImageCache.h
new file mode 100644
index 0000000..24525b0
--- /dev/null
+++ b/lazy/SkPurgeableImageCache.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkPurgeableImageCache_DEFINED
+#define SkPurgeableImageCache_DEFINED
+
+#include "SkImageCache.h"
+
+#ifdef SK_DEBUG
+ #include "SkTDArray.h"
+#endif
+
+/**
+ * Implementation for SkImageCache that uses system defined purgeable memory.
+ */
+class SkPurgeableImageCache : public SkImageCache {
+
+public:
+ SK_DECLARE_INST_COUNT(SkPurgeableImageCache)
+
+ static SkImageCache* Create();
+
+ virtual void* allocAndPinCache(size_t bytes, ID*) SK_OVERRIDE;
+ virtual void* pinCache(ID, SkImageCache::DataStatus*) SK_OVERRIDE;
+ virtual void releaseCache(ID) SK_OVERRIDE;
+ virtual void throwAwayCache(ID) SK_OVERRIDE;
+
+#ifdef SK_DEBUG
+ virtual MemoryStatus getMemoryStatus(ID) const SK_OVERRIDE;
+ virtual void purgeAllUnpinnedCaches() SK_OVERRIDE;
+ virtual ~SkPurgeableImageCache();
+#endif
+
+private:
+ SkPurgeableImageCache();
+
+#ifdef SK_DEBUG
+ SkTDArray<ID> fRecs;
+ int findRec(ID) const;
+#endif
+ void removeRec(ID);
+};
+#endif // SkPurgeableImageCache_DEFINED
diff --git a/pathops/SkPathOps.h b/pathops/SkPathOps.h
new file mode 100644
index 0000000..a98f4ea
--- /dev/null
+++ b/pathops/SkPathOps.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#ifndef SkPathOps_DEFINED
+#define SkPathOps_DEFINED
+
+#include "SkPreConfig.h"
+
+class SkPath;
+
+// FIXME: move everything below into the SkPath class
+/**
+ * The logical operations that can be performed when combining two paths.
+ */
+enum SkPathOp {
+ kDifference_PathOp, //!< subtract the op path from the first path
+ kIntersect_PathOp, //!< intersect the two paths
+ kUnion_PathOp, //!< union (inclusive-or) the two paths
+ kXOR_PathOp, //!< exclusive-or the two paths
+ kReverseDifference_PathOp, //!< subtract the first path from the op path
+};
+
+/** Set this path to the result of applying the Op to this path and the
+ specified path: this = (this op operand).
+ The resulting path will be constructed from non-overlapping contours.
+ The curve order is reduced where possible so that cubics may be turned
+ into quadratics, and quadratics maybe turned into lines.
+
+ Returns true if operation was able to produce a result;
+ otherwise, result is unmodified.
+
+ @param one The first operand (for difference, the minuend)
+ @param two The second operand (for difference, the subtrahend)
+ @param result The product of the operands. The result may be one of the
+ inputs.
+ @return True if operation succeeded.
+ */
+bool SK_API Op(const SkPath& one, const SkPath& two, SkPathOp op, SkPath* result);
+
+/** Set this path to a set of non-overlapping contours that describe the
+ same area as the original path.
+ The curve order is reduced where possible so that cubics may
+ be turned into quadratics, and quadratics maybe turned into lines.
+
+ Returns true if operation was able to produce a result;
+ otherwise, result is unmodified.
+
+ @param path The path to simplify.
+ @param result The simplified path. The result may be the input.
+ @return True if simplification succeeded.
+ */
+bool SK_API Simplify(const SkPath& path, SkPath* result);
+
+#endif
diff --git a/pdf/SkPDFDevice.h b/pdf/SkPDFDevice.h
new file mode 100644
index 0000000..207b2b2
--- /dev/null
+++ b/pdf/SkPDFDevice.h
@@ -0,0 +1,315 @@
+
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkPDFDevice_DEFINED
+#define SkPDFDevice_DEFINED
+
+#include "SkCanvas.h"
+#include "SkDevice.h"
+#include "SkPaint.h"
+#include "SkPath.h"
+#include "SkRect.h"
+#include "SkRefCnt.h"
+#include "SkStream.h"
+#include "SkTDArray.h"
+#include "SkTScopedPtr.h"
+
+class SkPDFArray;
+class SkPDFDevice;
+class SkPDFDict;
+class SkPDFFont;
+class SkPDFFormXObject;
+class SkPDFGlyphSetMap;
+class SkPDFGraphicState;
+class SkPDFObject;
+class SkPDFResourceDict;
+class SkPDFShader;
+class SkPDFStream;
+template <typename T> class SkTSet;
+
+// Private classes.
+struct ContentEntry;
+struct GraphicStateEntry;
+struct NamedDestination;
+
+typedef bool (*EncodeToDCTStream)(SkWStream* stream, const SkBitmap& bitmap, const SkIRect& rect);
+
+/** \class SkPDFDevice
+
+ The drawing context for the PDF backend.
+*/
+class SkPDFDevice : public SkDevice {
+public:
+ /** Create a PDF drawing context with the given width and height.
+ * 72 points/in means letter paper is 612x792.
+ * @param pageSize Page size in points.
+ * @param contentSize The content size of the page in points. This will be
+ * combined with the initial transform to determine the drawing area
+ * (as reported by the width and height methods). Anything outside
+ * of the drawing area will be clipped.
+ * @param initialTransform The initial transform to apply to the page.
+ * This may be useful to, for example, move the origin in and
+ * over a bit to account for a margin, scale the canvas,
+ * or apply a rotation. Note1: the SkPDFDevice also applies
+ * a scale+translate transform to move the origin from the
+ * bottom left (PDF default) to the top left. Note2: drawDevice
+ * (used by layer restore) draws the device after this initial
+ * transform is applied, so the PDF device does an
+ * inverse scale+translate to accommodate the one that SkPDFDevice
+ * always does.
+ */
+ // TODO(vandebo): The sizes should be SkSize and not SkISize.
+ SK_API SkPDFDevice(const SkISize& pageSize, const SkISize& contentSize,
+ const SkMatrix& initialTransform);
+ SK_API virtual ~SkPDFDevice();
+
+ virtual uint32_t getDeviceCapabilities() SK_OVERRIDE;
+
+ virtual void clear(SkColor color) SK_OVERRIDE;
+
+ /** These are called inside the per-device-layer loop for each draw call.
+ When these are called, we have already applied any saveLayer operations,
+ and are handling any looping from the paint, and any effects from the
+ DrawFilter.
+ */
+ virtual void drawPaint(const SkDraw&, const SkPaint& paint) SK_OVERRIDE;
+ virtual void drawPoints(const SkDraw&, SkCanvas::PointMode mode,
+ size_t count, const SkPoint[],
+ const SkPaint& paint) SK_OVERRIDE;
+ virtual void drawRect(const SkDraw&, const SkRect& r, const SkPaint& paint);
+ virtual void drawPath(const SkDraw&, const SkPath& origpath,
+ const SkPaint& paint, const SkMatrix* prePathMatrix,
+ bool pathIsMutable) SK_OVERRIDE;
+ virtual void drawBitmapRect(const SkDraw& draw, const SkBitmap& bitmap,
+ const SkRect* src, const SkRect& dst,
+ const SkPaint& paint) SK_OVERRIDE;
+ virtual void drawBitmap(const SkDraw&, const SkBitmap& bitmap,
+ const SkMatrix& matrix, const SkPaint&) SK_OVERRIDE;
+ virtual void drawSprite(const SkDraw&, const SkBitmap& bitmap, int x, int y,
+ const SkPaint& paint) SK_OVERRIDE;
+ virtual void drawText(const SkDraw&, const void* text, size_t len,
+ SkScalar x, SkScalar y, const SkPaint&) SK_OVERRIDE;
+ virtual void drawPosText(const SkDraw&, const void* text, size_t len,
+ const SkScalar pos[], SkScalar constY,
+ int scalarsPerPos, const SkPaint&) SK_OVERRIDE;
+ virtual void drawTextOnPath(const SkDraw&, const void* text, size_t len,
+ const SkPath& path, const SkMatrix* matrix,
+ const SkPaint& paint) SK_OVERRIDE;
+ virtual void drawVertices(const SkDraw&, SkCanvas::VertexMode,
+ int vertexCount, const SkPoint verts[],
+ const SkPoint texs[], const SkColor colors[],
+ SkXfermode* xmode, const uint16_t indices[],
+ int indexCount, const SkPaint& paint) SK_OVERRIDE;
+ virtual void drawDevice(const SkDraw&, SkDevice*, int x, int y,
+ const SkPaint&) SK_OVERRIDE;
+
+ virtual void onAttachToCanvas(SkCanvas* canvas) SK_OVERRIDE;
+ virtual void onDetachFromCanvas() SK_OVERRIDE;
+
+ enum DrawingArea {
+ kContent_DrawingArea, // Drawing area for the page content.
+ kMargin_DrawingArea, // Drawing area for the margin content.
+ };
+
+ /** Sets the drawing area for the device. Subsequent draw calls are directed
+ * to the specific drawing area (margin or content). The default drawing
+ * area is the content drawing area.
+ *
+ * Currently if margin content is drawn and then a complex (for PDF) xfer
+ * mode is used, like SrcIn, Clear, etc, the margin content will get
+ * clipped. A simple way to avoid the bug is to always draw the margin
+ * content last.
+ */
+ SK_API void setDrawingArea(DrawingArea drawingArea);
+
+ /** Sets the DCTEncoder for images.
+ * @param encoder The encoder to encode a bitmap as JPEG (DCT).
+ * Result of encodings are cached, if the encoder changes the
+ * behaivor dynamically and an image is added to a second catalog,
+ * we will likely use the result of the first encoding call.
+ * By returning false from the encoder function, the encoder result
+ * is not used.
+ * Callers might not want to encode small images, as the time spent
+ * encoding and decoding might not be worth the space savings,
+ * if any at all.
+ */
+ void setDCTEncoder(EncodeToDCTStream encoder) {
+ fEncoder = encoder;
+ }
+
+ // PDF specific methods.
+
+ /** Returns the resource dictionary for this device.
+ */
+ SK_API SkPDFResourceDict* getResourceDict();
+
+ /** Get the fonts used on this device.
+ */
+ SK_API const SkTDArray<SkPDFFont*>& getFontResources() const;
+
+ /** Add our named destinations to the supplied dictionary.
+ * @param dict Dictionary to add destinations to.
+ * @param page The PDF object representing the page for this device.
+ */
+ void appendDestinations(SkPDFDict* dict, SkPDFObject* page);
+
+ /** Returns a copy of the media box for this device. The caller is required
+ * to unref() this when it is finished.
+ */
+ SK_API SkPDFArray* copyMediaBox() const;
+
+ /** Get the annotations from this page, or NULL if there are none.
+ */
+ SK_API SkPDFArray* getAnnotations() const { return fAnnotations; }
+
+ /** Returns a SkStream with the page contents. The caller is responsible
+ for a reference to the returned value.
+ DEPRECATED: use copyContentToData()
+ */
+ SK_API SkStream* content() const;
+
+ /** Returns a SkStream with the page contents. The caller is responsible
+ * for calling data->unref() when it is finished.
+ */
+ SK_API SkData* copyContentToData() const;
+
+ SK_API const SkMatrix& initialTransform() const {
+ return fInitialTransform;
+ }
+
+ /** Returns a SkPDFGlyphSetMap which represents glyph usage of every font
+ * that shows on this device.
+ */
+ const SkPDFGlyphSetMap& getFontGlyphUsage() const {
+ return *(fFontGlyphUsage.get());
+ }
+
+protected:
+ virtual bool onReadPixels(const SkBitmap& bitmap, int x, int y,
+ SkCanvas::Config8888) SK_OVERRIDE;
+
+ virtual bool allowImageFilter(SkImageFilter*) SK_OVERRIDE;
+
+private:
+ // TODO(vandebo): push most of SkPDFDevice's state into a core object in
+ // order to get the right access levels without using friend.
+ friend class ScopedContentEntry;
+
+ SkISize fPageSize;
+ SkISize fContentSize;
+ SkMatrix fInitialTransform;
+ SkClipStack fExistingClipStack;
+ SkRegion fExistingClipRegion;
+ SkPDFArray* fAnnotations;
+ SkPDFResourceDict* fResourceDict;
+ SkTDArray<NamedDestination*> fNamedDestinations;
+
+ SkTDArray<SkPDFGraphicState*> fGraphicStateResources;
+ SkTDArray<SkPDFObject*> fXObjectResources;
+ SkTDArray<SkPDFFont*> fFontResources;
+ SkTDArray<SkPDFObject*> fShaderResources;
+
+ SkTScopedPtr<ContentEntry> fContentEntries;
+ ContentEntry* fLastContentEntry;
+ SkTScopedPtr<ContentEntry> fMarginContentEntries;
+ ContentEntry* fLastMarginContentEntry;
+ DrawingArea fDrawingArea;
+
+ const SkClipStack* fClipStack;
+
+ // Accessor and setter functions based on the current DrawingArea.
+ SkTScopedPtr<ContentEntry>* getContentEntries();
+ ContentEntry* getLastContentEntry();
+ void setLastContentEntry(ContentEntry* contentEntry);
+
+ // Glyph ids used for each font on this device.
+ SkTScopedPtr<SkPDFGlyphSetMap> fFontGlyphUsage;
+
+ EncodeToDCTStream fEncoder;
+
+ SkPDFDevice(const SkISize& layerSize, const SkClipStack& existingClipStack,
+ const SkRegion& existingClipRegion);
+
+ // override from SkDevice
+ virtual SkDevice* onCreateCompatibleDevice(SkBitmap::Config config,
+ int width, int height,
+ bool isOpaque,
+ Usage usage) SK_OVERRIDE;
+
+ void init();
+ void cleanUp(bool clearFontUsage);
+ SkPDFFormXObject* createFormXObjectFromDevice();
+
+ // Clear the passed clip from all existing content entries.
+ void clearClipFromContent(const SkClipStack* clipStack,
+ const SkRegion& clipRegion);
+ void drawFormXObjectWithClip(SkPDFFormXObject* form,
+ const SkClipStack* clipStack,
+ const SkRegion& clipRegion,
+ bool invertClip);
+
+ // If the paint or clip is such that we shouldn't draw anything, this
+ // returns NULL and does not create a content entry.
+ // setUpContentEntry and finishContentEntry can be used directly, but
+ // the preferred method is to use the ScopedContentEntry helper class.
+ ContentEntry* setUpContentEntry(const SkClipStack* clipStack,
+ const SkRegion& clipRegion,
+ const SkMatrix& matrix,
+ const SkPaint& paint,
+ bool hasText,
+ SkPDFFormXObject** dst);
+ void finishContentEntry(SkXfermode::Mode xfermode,
+ SkPDFFormXObject* dst);
+ bool isContentEmpty();
+
+ void populateGraphicStateEntryFromPaint(const SkMatrix& matrix,
+ const SkClipStack& clipStack,
+ const SkRegion& clipRegion,
+ const SkPaint& paint,
+ bool hasText,
+ GraphicStateEntry* entry);
+ int addGraphicStateResource(SkPDFGraphicState* gs);
+
+ void updateFont(const SkPaint& paint, uint16_t glyphID,
+ ContentEntry* contentEntry);
+ int getFontResourceIndex(SkTypeface* typeface, uint16_t glyphID);
+
+ void internalDrawPaint(const SkPaint& paint, ContentEntry* contentEntry);
+ void internalDrawBitmap(const SkMatrix& matrix,
+ const SkClipStack* clipStack,
+ const SkRegion& clipRegion,
+ const SkBitmap& bitmap,
+ const SkIRect* srcRect,
+ const SkPaint& paint);
+
+ /** Helper method for copyContentToData. It is responsible for copying the
+ * list of content entries |entry| to |data|.
+ */
+ void copyContentEntriesToData(ContentEntry* entry, SkWStream* data) const;
+
+#ifdef SK_PDF_USE_PATHOPS
+ bool handleInversePath(const SkDraw& d, const SkPath& origPath,
+ const SkPaint& paint, bool pathIsMutable);
+#endif
+ bool handleRectAnnotation(const SkRect& r, const SkMatrix& matrix,
+ const SkPaint& paint);
+ bool handlePointAnnotation(const SkPoint* points, size_t count,
+ const SkMatrix& matrix, const SkPaint& paint);
+ SkPDFDict* createLinkAnnotation(const SkRect& r, const SkMatrix& matrix);
+ void handleLinkToURL(SkData* urlData, const SkRect& r,
+ const SkMatrix& matrix);
+ void handleLinkToNamedDest(SkData* nameData, const SkRect& r,
+ const SkMatrix& matrix);
+ void defineNamedDestination(SkData* nameData, const SkPoint& point,
+ const SkMatrix& matrix);
+
+ typedef SkDevice INHERITED;
+};
+
+#endif
diff --git a/pdf/SkPDFDocument.h b/pdf/SkPDFDocument.h
new file mode 100644
index 0000000..31c6f9b
--- /dev/null
+++ b/pdf/SkPDFDocument.h
@@ -0,0 +1,105 @@
+
+/*
+ * Copyright 2010 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkPDFDocument_DEFINED
+#define SkPDFDocument_DEFINED
+
+#include "SkAdvancedTypefaceMetrics.h"
+#include "SkRefCnt.h"
+#include "SkTDArray.h"
+#include "SkTScopedPtr.h"
+
+class SkPDFCatalog;
+class SkPDFDevice;
+class SkPDFDict;
+class SkPDFPage;
+class SkPDFObject;
+class SkWStream;
+template <typename T> class SkTSet;
+
+/** \class SkPDFDocument
+
+ A SkPDFDocument assembles pages together and generates the final PDF file.
+*/
+class SkPDFDocument {
+public:
+ enum Flags {
+ kNoCompression_Flags = 0x01, //!< DEPRECATED.
+ kFavorSpeedOverSize_Flags = 0x01, //!< Don't compress the stream, but
+ // if it is already compressed return
+ // the compressed stream.
+ kNoLinks_Flags = 0x02, //!< do not honor link annotations.
+
+ kDraftMode_Flags = 0x01,
+ };
+ /** Create a PDF document.
+ */
+ explicit SK_API SkPDFDocument(Flags flags = (Flags)0);
+ SK_API ~SkPDFDocument();
+
+ /** Output the PDF to the passed stream. It is an error to call this (it
+ * will return false and not modify stream) if no pages have been added
+ * or there are pages missing (i.e. page 1 and 3 have been added, but not
+ * page 2).
+ *
+ * @param stream The writable output stream to send the PDF to.
+ */
+ SK_API bool emitPDF(SkWStream* stream);
+
+ /** Sets the specific page to the passed PDF device. If the specified
+ * page is already set, this overrides it. Returns true if successful.
+ * Will fail if the document has already been emitted.
+ *
+ * @param pageNumber The position to add the passed device (1 based).
+ * @param pdfDevice The page to add to this document.
+ */
+ SK_API bool setPage(int pageNumber, SkPDFDevice* pdfDevice);
+
+ /** Append the passed pdf device to the document as a new page. Returns
+ * true if successful. Will fail if the document has already been emitted.
+ *
+ * @param pdfDevice The page to add to this document.
+ */
+ SK_API bool appendPage(SkPDFDevice* pdfDevice);
+
+ /** Get the count of unique font types used in the document.
+ */
+ SK_API void getCountOfFontTypes(
+ int counts[SkAdvancedTypefaceMetrics::kNotEmbeddable_Font + 1]) const;
+
+private:
+ SkTScopedPtr<SkPDFCatalog> fCatalog;
+ int64_t fXRefFileOffset;
+
+ SkTDArray<SkPDFPage*> fPages;
+ SkTDArray<SkPDFDict*> fPageTree;
+ SkPDFDict* fDocCatalog;
+ SkTSet<SkPDFObject*>* fFirstPageResources;
+ SkTSet<SkPDFObject*>* fOtherPageResources;
+ SkTDArray<SkPDFObject*> fSubstitutes;
+
+ SkPDFDict* fTrailerDict;
+
+ /** Output the PDF header to the passed stream.
+ * @param stream The writable output stream to send the header to.
+ */
+ void emitHeader(SkWStream* stream);
+
+ /** Get the size of the header.
+ */
+ size_t headerSize();
+
+ /** Output the PDF footer to the passed stream.
+ * @param stream The writable output stream to send the footer to.
+ * @param objCount The number of objects in the PDF.
+ */
+ void emitFooter(SkWStream* stream, int64_t objCount);
+};
+
+#endif
diff --git a/pipe/SkGPipe.h b/pipe/SkGPipe.h
new file mode 100644
index 0000000..879ab04
--- /dev/null
+++ b/pipe/SkGPipe.h
@@ -0,0 +1,168 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+
+#ifndef SkGPipe_DEFINED
+#define SkGPipe_DEFINED
+
+#include "SkFlattenable.h"
+#include "SkPicture.h"
+#include "SkWriter32.h"
+
+class SkCanvas;
+
+// XLib.h might have defined Status already (ugh)
+#ifdef Status
+ #undef Status
+#endif
+
+class SkGPipeReader {
+public:
+ SkGPipeReader();
+ SkGPipeReader(SkCanvas* target);
+ ~SkGPipeReader();
+
+ enum Status {
+ kDone_Status, //!< no more data expected from reader
+ kEOF_Status, //!< need more data from reader
+ kError_Status, //!< encountered error
+ kReadAtom_Status//!< finished reading an atom
+ };
+
+ enum PlaybackFlags {
+ kReadAtom_PlaybackFlag = 0x1, //!< playback a single command from the stream
+ kSilent_PlaybackFlag = 0x2, //!< playback without drawing
+ };
+
+ void setCanvas(SkCanvas*);
+
+ /**
+ * Set a function for decoding bitmaps that have encoded data.
+ */
+ void setBitmapDecoder(SkPicture::InstallPixelRefProc proc) { fProc = proc; }
+
+ // data must be 4-byte aligned
+ // length must be a multiple of 4
+ Status playback(const void* data, size_t length, uint32_t playbackFlags = 0,
+ size_t* bytesRead = NULL);
+private:
+ SkCanvas* fCanvas;
+ class SkGPipeState* fState;
+ SkPicture::InstallPixelRefProc fProc;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+class SkGPipeCanvas;
+
+class SkGPipeController {
+public:
+ SkGPipeController() : fCanvas(NULL) {}
+ virtual ~SkGPipeController();
+
+ /**
+ * Called periodically by the writer, to get a working buffer of RAM to
+ * write into. The actual size of the block is also returned, and must be
+ * actual >= minRequest. If NULL is returned, then actual is ignored and
+ * writing will stop.
+ *
+ * The returned block must be 4-byte aligned, and actual must be a
+ * multiple of 4.
+ * minRequest will always be a multiple of 4.
+ */
+ virtual void* requestBlock(size_t minRequest, size_t* actual) = 0;
+
+ /**
+ * This is called each time some atomic portion of the data has been
+ * written to the block (most recently returned by requestBlock()).
+ * If bytes == 0, then the writer has finished.
+ *
+ * bytes will always be a multiple of 4.
+ */
+ virtual void notifyWritten(size_t bytes) = 0;
+ virtual int numberOfReaders() const { return 1; }
+
+private:
+ friend class SkGPipeWriter;
+ void setCanvas(SkGPipeCanvas*);
+
+ SkGPipeCanvas* fCanvas;
+};
+
+class SkGPipeWriter {
+public:
+ SkGPipeWriter();
+ ~SkGPipeWriter();
+
+ bool isRecording() const { return NULL != fCanvas; }
+
+ enum Flags {
+ /**
+ * Tells the writer that the reader will be in a different process, so
+ * (for example) we cannot put function pointers in the stream.
+ */
+ kCrossProcess_Flag = 1 << 0,
+
+ /**
+ * Only meaningful if kCrossProcess_Flag is set. Tells the writer that
+ * in spite of being cross process, it will have shared address space
+ * with the reader, so the two can share large objects (like SkBitmaps).
+ */
+ kSharedAddressSpace_Flag = 1 << 1,
+
+ /**
+ * Tells the writer that there will be multiple threads reading the stream
+ * simultaneously.
+ */
+ kSimultaneousReaders_Flag = 1 << 2,
+ };
+
+ SkCanvas* startRecording(SkGPipeController*, uint32_t flags = 0,
+ uint32_t width = kDefaultRecordingCanvasSize,
+ uint32_t height = kDefaultRecordingCanvasSize);
+
+ // called in destructor, but can be called sooner once you know there
+ // should be no more drawing calls made into the recording canvas.
+ void endRecording();
+
+ /**
+ * Tells the writer to commit all recorded draw commands to the
+ * controller immediately.
+ * @param detachCurrentBlock Set to true to request that the next draw
+ * command be recorded in a new block.
+ */
+ void flushRecording(bool detachCurrentBlock);
+
+ /**
+ * Return the amount of bytes being used for recording. Note that this
+ * does not include the amount of storage written to the stream, which is
+ * controlled by the SkGPipeController.
+ * Currently only returns the amount used for SkBitmaps, since they are
+ * potentially unbounded (if the client is not calling playback).
+ */
+ size_t storageAllocatedForRecording() const;
+
+ /**
+ * Attempt to reduce the storage allocated for recording by evicting
+ * cache resources.
+ * @param bytesToFree minimum number of bytes that should be attempted to
+ * be freed.
+ * @return number of bytes actually freed.
+ */
+ size_t freeMemoryIfPossible(size_t bytesToFree);
+
+private:
+ enum {
+ kDefaultRecordingCanvasSize = 32767,
+ };
+
+ SkGPipeCanvas* fCanvas;
+ SkWriter32 fWriter;
+};
+
+#endif
diff --git a/ports/SkFontConfigInterface.h b/ports/SkFontConfigInterface.h
new file mode 100644
index 0000000..661c3be
--- /dev/null
+++ b/ports/SkFontConfigInterface.h
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkFontConfigInterface_DEFINED
+#define SkFontConfigInterface_DEFINED
+
+#include "SkDataTable.h"
+#include "SkFontStyle.h"
+#include "SkRefCnt.h"
+#include "SkTArray.h"
+#include "SkTypeface.h"
+
+/**
+ * \class SkFontConfigInterface
+ *
+ * Provides SkFontHost clients with access to fontconfig services. They will
+ * access the global instance found in RefGlobal().
+ */
+class SK_API SkFontConfigInterface : public SkRefCnt {
+public:
+ SK_DECLARE_INST_COUNT(SkFontConfigInterface)
+
+ /**
+ * Returns the global SkFontConfigInterface instance, and if it is not
+ * NULL, calls ref() on it. The caller must balance this with a call to
+ * unref().
+ */
+ static SkFontConfigInterface* RefGlobal();
+
+ /**
+ * Replace the current global instance with the specified one, safely
+ * ref'ing the new instance, and unref'ing the previous. Returns its
+ * parameter (the new global instance).
+ */
+ static SkFontConfigInterface* SetGlobal(SkFontConfigInterface*);
+
+ /**
+ * This should be treated as private to the impl of SkFontConfigInterface.
+ * Callers should not change or expect any particular values. It is meant
+ * to be a union of possible storage types to aid the impl.
+ */
+ struct FontIdentity {
+ FontIdentity() : fID(0), fTTCIndex(0) {}
+
+ bool operator==(const FontIdentity& other) const {
+ return fID == other.fID &&
+ fTTCIndex == other.fTTCIndex &&
+ fString == other.fString;
+ }
+ bool operator!=(const FontIdentity& other) const {
+ return !(*this == other);
+ }
+
+ uint32_t fID;
+ int32_t fTTCIndex;
+ SkString fString;
+ SkFontStyle fStyle;
+
+ // If buffer is NULL, just return the number of bytes that would have
+ // been written. Will pad contents to a multiple of 4.
+ size_t writeToMemory(void* buffer = NULL) const;
+
+ // Recreate from a flattened buffer, returning the number of bytes read.
+ size_t readFromMemory(const void* buffer, size_t length);
+ };
+
+ /**
+ * Given a familyName and style, find the best match.
+ *
+ * If a match is found, return true and set its outFontIdentifier.
+ * If outFamilyName is not null, assign the found familyName to it
+ * (which may differ from the requested familyName).
+ * If outStyle is not null, assign the found style to it
+ * (which may differ from the requested style).
+ *
+ * If a match is not found, return false, and ignore all out parameters.
+ */
+ virtual bool matchFamilyName(const char familyName[],
+ SkTypeface::Style requested,
+ FontIdentity* outFontIdentifier,
+ SkString* outFamilyName,
+ SkTypeface::Style* outStyle) = 0;
+
+ /**
+ * Given a FontRef, open a stream to access its data, or return null
+ * if the FontRef's data is not available. The caller is responsible for
+ * calling stream->unref() when it is done accessing the data.
+ */
+ virtual SkStream* openStream(const FontIdentity&) = 0;
+
+ /**
+ * Return a singleton instance of a direct subclass that calls into
+ * libfontconfig. This does not affect the refcnt of the returned instance.
+ */
+ static SkFontConfigInterface* GetSingletonDirectInterface();
+
+ // New APIS, which have default impls for now (which do nothing)
+
+ virtual SkDataTable* getFamilyNames() { return SkDataTable::NewEmpty(); }
+ virtual bool matchFamilySet(const char inFamilyName[],
+ SkString* outFamilyName,
+ SkTArray<FontIdentity>*) {
+ return false;
+ }
+};
+
+#endif
diff --git a/ports/SkFontMgr.h b/ports/SkFontMgr.h
new file mode 100644
index 0000000..d243825
--- /dev/null
+++ b/ports/SkFontMgr.h
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkFontMgr_DEFINED
+#define SkFontMgr_DEFINED
+
+#include "SkRefCnt.h"
+#include "SkFontStyle.h"
+
+class SkData;
+class SkStream;
+class SkString;
+class SkTypeface;
+
+class SK_API SkFontStyleSet : public SkRefCnt {
+public:
+ SK_DECLARE_INST_COUNT(SkFontStyleSet)
+
+ virtual int count() = 0;
+ virtual void getStyle(int index, SkFontStyle*, SkString* style) = 0;
+ virtual SkTypeface* createTypeface(int index) = 0;
+ virtual SkTypeface* matchStyle(const SkFontStyle& pattern) = 0;
+
+ static SkFontStyleSet* CreateEmpty();
+
+private:
+ typedef SkRefCnt INHERITED;
+};
+
+class SkTypeface;
+
+class SK_API SkFontMgr : public SkRefCnt {
+public:
+ SK_DECLARE_INST_COUNT(SkFontMgr)
+
+ int countFamilies();
+ void getFamilyName(int index, SkString* familyName);
+ SkFontStyleSet* createStyleSet(int index);
+
+ SkFontStyleSet* matchFamily(const char familyName[]);
+
+ /**
+ * Find the closest matching typeface to the specified familyName and style
+ * and return a ref to it. The caller must call unref() on the returned
+ * object. Will never return NULL, as it will return the default font if
+ * no matching font is found.
+ */
+ SkTypeface* matchFamilyStyle(const char familyName[], const SkFontStyle&);
+
+ SkTypeface* matchFaceStyle(const SkTypeface*, const SkFontStyle&);
+
+ /**
+ * Create a typeface for the specified data and TTC index (pass 0 for none)
+ * or NULL if the data is not recognized. The caller must call unref() on
+ * the returned object if it is not null.
+ */
+ SkTypeface* createFromData(SkData*, int ttcIndex = 0);
+
+ /**
+ * Create a typeface for the specified stream and TTC index
+ * (pass 0 for none) or NULL if the stream is not recognized. The caller
+ * must call unref() on the returned object if it is not null.
+ */
+ SkTypeface* createFromStream(SkStream*, int ttcIndex = 0);
+
+ /**
+ * Create a typeface for the specified fileName and TTC index
+ * (pass 0 for none) or NULL if the file is not found, or its contents are
+ * not recognized. The caller must call unref() on the returned object
+ * if it is not null.
+ */
+ SkTypeface* createFromFile(const char path[], int ttcIndex = 0);
+
+ SkTypeface* legacyCreateTypeface(const char familyName[],
+ unsigned typefaceStyleBits);
+
+ /**
+ * Return a ref to the default fontmgr. The caller must call unref() on
+ * the returned object.
+ */
+ static SkFontMgr* RefDefault();
+
+protected:
+ virtual int onCountFamilies() = 0;
+ virtual void onGetFamilyName(int index, SkString* familyName) = 0;
+ virtual SkFontStyleSet* onCreateStyleSet(int index) = 0;
+
+ virtual SkFontStyleSet* onMatchFamily(const char familyName[]) = 0;
+
+ virtual SkTypeface* onMatchFamilyStyle(const char familyName[],
+ const SkFontStyle&) = 0;
+ virtual SkTypeface* onMatchFaceStyle(const SkTypeface*,
+ const SkFontStyle&) = 0;
+
+ virtual SkTypeface* onCreateFromData(SkData*, int ttcIndex) = 0;
+ virtual SkTypeface* onCreateFromStream(SkStream*, int ttcIndex) = 0;
+ virtual SkTypeface* onCreateFromFile(const char path[], int ttcIndex) = 0;
+
+ // TODO: make this pure-virtual once all ports know about it
+ virtual SkTypeface* onLegacyCreateTypeface(const char familyName[],
+ unsigned styleBits);
+private:
+ static SkFontMgr* Factory(); // implemented by porting layer
+
+ typedef SkRefCnt INHERITED;
+};
+
+#endif
diff --git a/ports/SkFontStyle.h b/ports/SkFontStyle.h
new file mode 100644
index 0000000..9d9a912
--- /dev/null
+++ b/ports/SkFontStyle.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkFontStyle_DEFINED
+#define SkFontStyle_DEFINED
+
+#include "SkTypes.h"
+
+class SK_API SkFontStyle {
+public:
+ enum Weight {
+ kThin_Weight = 100,
+ kExtraLight_Weight = 200,
+ kLight_Weight = 300,
+ kNormal_Weight = 400,
+ kMedium_Weight = 500,
+ kSemiBold_Weight = 600,
+ kBold_Weight = 700,
+ kExtraBold_Weight = 800,
+ kBlack_Weight = 900
+ };
+
+ enum Width {
+ kUltraCondensed_Width = 1,
+ kExtraCondensed_Width = 2,
+ kCondensed_Width = 3,
+ kSemiCondensed_Width = 4,
+ kNormal_Width = 5,
+ kSemiExpanded_Width = 6,
+ kExpanded_Width = 7,
+ kExtraExpanded_Width = 8,
+ kUltaExpanded_Width = 9
+ };
+
+ enum Slant {
+ kUpright_Slant,
+ kItalic_Slant,
+ };
+
+ SkFontStyle();
+ SkFontStyle(int weight, int width, Slant);
+
+ bool operator==(const SkFontStyle& rhs) const {
+ return fUnion.fU32 == rhs.fUnion.fU32;
+ }
+
+ int weight() const { return fUnion.fR.fWeight; }
+ int width() const { return fUnion.fR.fWidth; }
+ Slant slant() const { return (Slant)fUnion.fR.fSlant; }
+
+ bool isItalic() const {
+ return kItalic_Slant == fUnion.fR.fSlant;
+ }
+
+private:
+ union {
+ struct {
+ uint16_t fWeight; // 100 .. 900
+ uint8_t fWidth; // 1 .. 9
+ uint8_t fSlant; // 0 .. 2
+ } fR;
+ uint32_t fU32;
+ } fUnion;
+};
+
+#endif
diff --git a/ports/SkHarfBuzzFont.h b/ports/SkHarfBuzzFont.h
new file mode 100644
index 0000000..22749af
--- /dev/null
+++ b/ports/SkHarfBuzzFont.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2009 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkHarfBuzzFont_DEFINED
+#define SkHarfBuzzFont_DEFINED
+
+extern "C" {
+#include "harfbuzz-shaper.h"
+//#include "harfbuzz-unicode.h"
+}
+
+#include "SkTypes.h"
+
+class SkPaint;
+class SkTypeface;
+
+class SkHarfBuzzFont {
+public:
+ /** The subclass returns the typeface for this font, or NULL
+ */
+ virtual SkTypeface* getTypeface() const = 0;
+ /** The subclass sets the text related attributes of the paint.
+ e.g. textSize, typeface, textSkewX, etc.
+ All of the attributes that could effect how the text is measured.
+ Color information (e.g. color, xfermode, shader, etc.) are not required.
+ */
+ virtual void setupPaint(SkPaint*) const = 0;
+
+ /** Implementation of HB_GetFontTableFunc, using SkHarfBuzzFont* as
+ the first parameter.
+ */
+ static HB_Error GetFontTableFunc(void* skharfbuzzfont, const HB_Tag tag,
+ HB_Byte* buffer, HB_UInt* len);
+
+ static const HB_FontClass& GetFontClass();
+};
+
+#endif
diff --git a/ports/SkTypeface_android.h b/ports/SkTypeface_android.h
new file mode 100644
index 0000000..655670f
--- /dev/null
+++ b/ports/SkTypeface_android.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkTypeface_android_DEFINED
+#define SkTypeface_android_DEFINED
+
+#include "SkTypeface.h"
+
+#ifdef SK_BUILD_FOR_ANDROID
+
+class SkPaintOptionsAndroid;
+
+/**
+ * Get the family name of the font in the fallback font list containing
+ * the specified character. if no font is found, returns false.
+ */
+SK_API bool SkGetFallbackFamilyNameForChar(SkUnichar uni, SkString* name);
+
+/**
+ * For test only.
+ * Load font config from given xml files, instead of those from Android system.
+ */
+SK_API void SkUseTestFontConfigFile(const char* mainconf, const char* fallbackconf,
+ const char* fontsdir);
+
+/**
+ * Given a "current" fontID, return a ref to the next logical typeface
+ * when searching fonts for a given unicode value. Typically the caller
+ * will query a given font, and if a unicode value is not supported, they
+ * will call this, and if 0 is not returned, will search that font, and so
+ * on. This process must be finite, and when the fonthost sees a
+ * font with no logical successor, it must return NULL.
+ *
+ * The original fontID is also provided. This is the initial font that was
+ * stored in the typeface of the caller. It is provided as an aid to choose
+ * the best next logical font. e.g. If the original font was bold or serif,
+ * but the 2nd in the logical chain was plain, then a subsequent call to
+ * get the 3rd can still inspect the original, and try to match its
+ * stylistic attributes.
+ */
+SkTypeface* SkAndroidNextLogicalTypeface(SkFontID currFontID, SkFontID origFontID,
+ const SkPaintOptionsAndroid& options);
+
+#endif // #ifdef SK_BUILD_FOR_ANDROID
+#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
+
+#include "SkPaintOptionsAndroid.h"
+#include "../harfbuzz/src/harfbuzz-shaper.h"
+#include "../harfbuzz_ng/src/hb.h"
+
+/**
+ * Return a new typeface for a fallback script. If the script is
+ * not valid, or can not map to a font, returns null.
+ * @param script The harfbuzz script id.
+ * @param style The font style, for example bold
+ * @param elegant true if we want the web friendly elegant version of the font
+ * @return reference to the matching typeface. Caller must call
+ * unref() when they are done.
+ */
+SK_API SkTypeface* SkCreateTypefaceForScriptNG(hb_script_t script, SkTypeface::Style style,
+ SkPaintOptionsAndroid::FontVariant fontVariant = SkPaintOptionsAndroid::kDefault_Variant);
+
+SK_API SkTypeface* SkCreateTypefaceForScript(HB_Script script, SkTypeface::Style style,
+ SkPaintOptionsAndroid::FontVariant fontVariant = SkPaintOptionsAndroid::kDefault_Variant);
+
+#endif // #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
+#endif // #ifndef SkTypeface_android_DEFINED
diff --git a/ports/SkTypeface_mac.h b/ports/SkTypeface_mac.h
new file mode 100644
index 0000000..0166ee5
--- /dev/null
+++ b/ports/SkTypeface_mac.h
@@ -0,0 +1,29 @@
+
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+
+#ifndef SkTypeface_mac_DEFINED
+#define SkTypeface_mac_DEFINED
+
+#include "SkTypeface.h"
+#ifdef SK_BUILD_FOR_MAC
+#import <ApplicationServices/ApplicationServices.h>
+#endif
+
+#ifdef SK_BUILD_FOR_IOS
+#include <CoreText/CoreText.h>
+#endif
+/**
+ * Like the other Typeface create methods, this returns a new reference to the
+ * corresponding typeface for the specified CTFontRef. The caller must call
+ * unref() when it is finished.
+ */
+SK_API extern SkTypeface* SkCreateTypefaceFromCTFont(CTFontRef);
+
+#endif
diff --git a/ports/SkTypeface_win.h b/ports/SkTypeface_win.h
new file mode 100644
index 0000000..fea5f47
--- /dev/null
+++ b/ports/SkTypeface_win.h
@@ -0,0 +1,39 @@
+
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+
+#ifndef SkTypeface_win_DEFINED
+#define SkTypeface_win_DEFINED
+
+#include "SkTypeface.h"
+
+/**
+ * Like the other Typeface create methods, this returns a new reference to the
+ * corresponding typeface for the specified logfont. The caller is responsible
+ * for calling unref() when it is finished.
+ */
+SK_API SkTypeface* SkCreateTypefaceFromLOGFONT(const LOGFONT&);
+
+/**
+ * Copy the LOGFONT associated with this typeface into the lf parameter. Note
+ * that the lfHeight will need to be set afterwards, since the typeface does
+ * not track this (the paint does).
+ * typeface may be NULL, in which case we return the logfont for the default font.
+ */
+SK_API void SkLOGFONTFromTypeface(const SkTypeface* typeface, LOGFONT* lf);
+
+/**
+ * Set an optional callback to ensure that the data behind a LOGFONT is loaded.
+ * This will get called if Skia tries to access the data but hits a failure.
+ * Normally this is null, and is only required if the font data needs to be
+ * remotely (re)loaded.
+ */
+SK_API void SkTypeface_SetEnsureLOGFONTAccessibleProc(void (*)(const LOGFONT&));
+
+#endif
diff --git a/svg/SkSVGAttribute.h b/svg/SkSVGAttribute.h
new file mode 100644
index 0000000..940ca5a
--- /dev/null
+++ b/svg/SkSVGAttribute.h
@@ -0,0 +1,42 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkSVGAttribute_DEFINED
+#define SkSVGAttribute_DEFINED
+
+#include "SkTypes.h"
+
+struct SkSVGAttribute {
+ const char* fName;
+#ifdef SK_DEBUG
+ size_t fOffset;
+#endif
+};
+
+#ifndef SK_OFFSETOF
+#define SK_OFFSETOF(a, b) (((size_t) (&(((a*) 1)->b)))-1)
+#endif
+
+#ifdef SK_DEBUG
+#define SVG_ATTRIBUTE(attr) { #attr, SK_OFFSETOF(BASE_CLASS, f_##attr) }
+#define SVG_LITERAL_ATTRIBUTE(svgAttr, cAttr) { #svgAttr, SK_OFFSETOF(BASE_CLASS, cAttr) }
+#else
+#define SVG_ATTRIBUTE(attr) { #attr }
+#define SVG_LITERAL_ATTRIBUTE(svgAttr, cAttr) { #svgAttr }
+#endif
+
+#define SVG_ADD_ATTRIBUTE(attr) \
+ if (f_##attr.size() > 0) \
+ parser._addAttributeLen(#attr, f_##attr.c_str(), f_##attr.size())
+
+#define SVG_ADD_ATTRIBUTE_ALIAS(attr, alias) \
+ if (f_##alias.size() > 0) \
+ parser._addAttributeLen(#attr, f_##alias.c_str(), f_##alias.size())
+
+#endif // SkSVGAttribute_DEFINED
diff --git a/svg/SkSVGBase.h b/svg/SkSVGBase.h
new file mode 100644
index 0000000..6bfc39d
--- /dev/null
+++ b/svg/SkSVGBase.h
@@ -0,0 +1,25 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkSVGBase_DEFINED
+#define SkSVGBase_DEFINED
+
+#include "SkSVGAttribute.h"
+
+class SkSVGParser;
+
+class SkSVGBase {
+public:
+ virtual ~SkSVGBase();
+ virtual void addAttribute(SkSVGParser& parser, int attrIndex,
+ const char* attrValue, size_t attrLength);
+ virtual int getAttributes(const SkSVGAttribute** attrPtr) = 0;
+};
+
+#endif // SkSVGBase_DEFINEDes(const SkSVGAttribute** attrPtr) = 0;
diff --git a/svg/SkSVGPaintState.h b/svg/SkSVGPaintState.h
new file mode 100644
index 0000000..211e9cf
--- /dev/null
+++ b/svg/SkSVGPaintState.h
@@ -0,0 +1,89 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkSVGPaintState_DEFINED
+#define SkSVGPaintState_DEFINED
+
+#include "SkSVGBase.h"
+#include "SkString.h"
+
+class SkSVGPaint : public SkSVGBase {
+public:
+ enum Field {
+ kInitial = -1,
+ kClipPath,
+ kClipRule,
+ kEnableBackground,
+ kFill,
+ kFillRule,
+ kFilter,
+ kFontFamily,
+ kFontSize,
+ kLetterSpacing,
+ kMask,
+ kOpacity,
+ kStopColor,
+ kStopOpacity,
+ kStroke,
+ kStroke_Dasharray,
+ kStroke_Linecap,
+ kStroke_Linejoin,
+ kStroke_Miterlimit,
+ kStroke_Width,
+ kStyle,
+ kTransform,
+ kTerminal
+ };
+
+ SkSVGPaint();
+ virtual void addAttribute(SkSVGParser& parser, int attrIndex,
+ const char* attrValue, size_t attrLength);
+ bool flush(SkSVGParser& , bool isFlushable, bool isDef);
+ virtual int getAttributes(const SkSVGAttribute** attrPtr);
+ static void Push(SkSVGPaint** head, SkSVGPaint* add);
+ static void Pop(SkSVGPaint** head);
+ SkString* operator[](int index);
+ SkString fInitial;
+ SkString f_clipPath;
+ SkString f_clipRule;
+ SkString f_enableBackground;
+ SkString f_fill;
+ SkString f_fillRule;
+ SkString f_filter;
+ SkString f_fontFamily;
+ SkString f_fontSize;
+ SkString f_letterSpacing;
+ SkString f_mask;
+ SkString f_opacity;
+ SkString f_stopColor;
+ SkString f_stopOpacity;
+ SkString f_stroke;
+ SkString f_strokeDasharray;
+ SkString f_strokeLinecap;
+ SkString f_strokeLinejoin;
+ SkString f_strokeMiterlimit;
+ SkString f_strokeWidth;
+ SkString f_style; // unused, but allows array access to the rest
+ SkString f_transform;
+#ifdef SK_DEBUG
+ SkString fTerminal;
+#endif
+ SkString fTransformID;
+ static SkSVGAttribute gAttributes[];
+ static const int kAttributesSize;
+private:
+ void setSave(SkSVGParser& );
+ bool writeChangedAttributes(SkSVGParser& , SkSVGPaint& , bool* changed);
+ bool writeChangedElements(SkSVGParser& , SkSVGPaint& , bool* changed);
+ SkSVGPaint* fNext;
+ friend class SkSVGParser;
+ typedef SkSVGPaint BASE_CLASS;
+};
+
+#endif // SkSVGPaintState_DEFINED
diff --git a/svg/SkSVGParser.h b/svg/SkSVGParser.h
new file mode 100644
index 0000000..c2f9112
--- /dev/null
+++ b/svg/SkSVGParser.h
@@ -0,0 +1,74 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkSVGParser_DEFINED
+#define SkSVGParser_DEFINED
+
+#include "SkMatrix.h"
+#include "SkTDict.h"
+#include "SkTDStack.h"
+#include "SkSVGPaintState.h"
+#include "SkSVGTypes.h"
+#include "SkStream.h"
+#include "SkString.h"
+#include "SkXMLParser.h"
+#include "SkXMLWriter.h"
+
+class SkSVGBase;
+class SkSVGElement;
+
+class SkSVGParser : public SkXMLParser {
+public:
+ SkSVGParser(SkXMLParserError* err = NULL);
+ virtual ~SkSVGParser();
+ void _addAttribute(const char* attrName, const char* attrValue) {
+ fXMLWriter.addAttribute(attrName, attrValue); }
+ void _addAttribute(const char* attrName, SkString& attrValue) {
+ fXMLWriter.addAttribute(attrName, attrValue.c_str()); }
+ void _addAttributeLen(const char* attrName, const char* attrValue, size_t len) {
+ fXMLWriter.addAttributeLen(attrName, attrValue, len); }
+ void _endElement() { fXMLWriter.endElement(); }
+ int findAttribute(SkSVGBase* , const char* attrValue, size_t len, bool isPaint);
+// const char* getFinal();
+ SkTDict<SkSVGElement*>& getIDs() { return fIDs; }
+ SkString& getPaintLast(SkSVGPaint::Field field);
+ void _startElement(const char name[]) { fXMLWriter.startElement(name); }
+ void translate(SkSVGElement*, bool isDef);
+ void translateMatrix(SkString& , SkString* id);
+ static void ConvertToArray(SkString& vals);
+protected:
+ virtual bool onAddAttribute(const char name[], const char value[]);
+ bool onAddAttributeLen(const char name[], const char value[], size_t len);
+ virtual bool onEndElement(const char elem[]);
+ virtual bool onStartElement(const char elem[]);
+ bool onStartElementLen(const char elem[], size_t len);
+ virtual bool onText(const char text[], int len);
+private:
+ bool isStrokeAndFill(SkSVGPaint** stroke, SkSVGPaint** fill);
+ static SkSVGElement* CreateElement(SkSVGTypes type, SkSVGElement* parent);
+ static void Delete(SkTDArray<SkSVGElement*>& fChildren);
+ static SkSVGTypes GetType(const char name[], size_t len);
+ SkSVGPaint* fHead;
+ SkSVGPaint fEmptyPaint;
+ SkSVGPaint fLastFlush;
+ SkString fLastColor;
+ SkMatrix fLastTransform;
+ SkTDArray<SkSVGElement*> fChildren;
+ SkTDict<SkSVGElement*> fIDs;
+ SkTDArray<SkSVGElement*> fParents;
+ SkDynamicMemoryWStream fStream;
+ SkXMLStreamWriter fXMLWriter;
+ SkSVGElement* fCurrElement;
+ SkBool8 fInSVG;
+ SkBool8 fSuppressPaint;
+ friend class SkSVGPaint;
+ friend class SkSVGGradient;
+};
+
+#endif // SkSVGParser_DEFINED
diff --git a/svg/SkSVGTypes.h b/svg/SkSVGTypes.h
new file mode 100644
index 0000000..b13bc6e
--- /dev/null
+++ b/svg/SkSVGTypes.h
@@ -0,0 +1,40 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkSVGTypes_DEFINED
+#define SkSVGTypes_DEFINED
+
+enum SkSVGTypes {
+ SkSVGType_Circle,
+ SkSVGType_ClipPath,
+ SkSVGType_Defs,
+ SkSVGType_Ellipse,
+ SkSVGType_FeColorMatrix,
+ SkSVGType_Filter,
+ SkSVGType_G,
+ SkSVGType_Image,
+ SkSVGType_Line,
+ SkSVGType_LinearGradient,
+ SkSVGType_Mask,
+ SkSVGType_Metadata,
+ SkSVGType_Path,
+ SkSVGType_Polygon,
+ SkSVGType_Polyline,
+ SkSVGType_RadialGradient,
+ SkSVGType_Rect,
+ SkSVGType_SVG,
+ SkSVGType_Stop,
+ SkSVGType_Symbol,
+ SkSVGType_Text,
+ SkSVGType_Tspan,
+ SkSVGType_Unknown,
+ SkSVGType_Use
+};
+
+#endif // SkSVGTypes_DEFINED
diff --git a/text/SkTextLayout.h b/text/SkTextLayout.h
new file mode 100644
index 0000000..718acdb
--- /dev/null
+++ b/text/SkTextLayout.h
@@ -0,0 +1,60 @@
+
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#ifndef SkTextLayout_DEFINED
+#define SkTextLayout_DEFINED
+
+#include "SkPaint.h"
+#include "SkRefCnt.h"
+
+class SkTextStyle : public SkRefCnt {
+public:
+ SK_DECLARE_INST_COUNT(SkTextStyle)
+
+ SkTextStyle();
+ SkTextStyle(const SkTextStyle&);
+ explicit SkTextStyle(const SkPaint&);
+ virtual ~SkTextStyle();
+
+ const SkPaint& paint() const { return fPaint; }
+ SkPaint& paint() { return fPaint; }
+
+ // todo: bidi-override, language
+
+private:
+ SkPaint fPaint;
+
+ typedef SkRefCnt INHERITED;
+};
+
+class SkTextLayout {
+public:
+ SkTextLayout();
+ ~SkTextLayout();
+
+ void setText(const char text[], size_t length);
+ void setBounds(const SkRect& bounds);
+
+ SkTextStyle* getDefaultStyle() const { return fDefaultStyle; }
+ SkTextStyle* setDefaultStyle(SkTextStyle*);
+
+// SkTextStyle* setStyle(SkTextStyle*, size_t offset, size_t length);
+
+ void draw(SkCanvas* canvas);
+
+private:
+ SkTDArray<char> fText;
+ SkTextStyle* fDefaultStyle;
+ SkRect fBounds;
+
+ // cache
+ struct Line;
+ struct GlyphRun;
+ SkTDArray<Line*> fLines;
+};
+
+#endif
diff --git a/utils/SkBoundaryPatch.h b/utils/SkBoundaryPatch.h
new file mode 100644
index 0000000..cf001d5
--- /dev/null
+++ b/utils/SkBoundaryPatch.h
@@ -0,0 +1,66 @@
+
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#ifndef SkBoundaryPatch_DEFINED
+#define SkBoundaryPatch_DEFINED
+
+#include "SkPoint.h"
+#include "SkRefCnt.h"
+
+class SkBoundary : public SkRefCnt {
+public:
+ SK_DECLARE_INST_COUNT(SkBoundary)
+
+ // These must be 0, 1, 2, 3 for efficiency in the subclass implementations
+ enum Edge {
+ kTop = 0,
+ kRight = 1,
+ kBottom = 2,
+ kLeft = 3
+ };
+ // Edge index goes clockwise around the boundary, beginning at the "top"
+ virtual SkPoint eval(Edge, SkScalar unitInterval) = 0;
+
+private:
+ typedef SkRefCnt INHERITED;
+};
+
+class SkBoundaryPatch {
+public:
+ SkBoundaryPatch();
+ ~SkBoundaryPatch();
+
+ SkBoundary* getBoundary() const { return fBoundary; }
+ SkBoundary* setBoundary(SkBoundary*);
+
+ SkPoint eval(SkScalar unitU, SkScalar unitV);
+ bool evalPatch(SkPoint verts[], int rows, int cols);
+
+private:
+ SkBoundary* fBoundary;
+};
+
+////////////////////////////////////////////////////////////////////////
+
+class SkLineBoundary : public SkBoundary {
+public:
+ SkPoint fPts[4];
+
+ // override
+ virtual SkPoint eval(Edge, SkScalar);
+};
+
+class SkCubicBoundary : public SkBoundary {
+public:
+ // the caller sets the first 12 entries. The 13th is used by the impl.
+ SkPoint fPts[13];
+
+ // override
+ virtual SkPoint eval(Edge, SkScalar);
+};
+
+#endif
diff --git a/utils/SkCamera.h b/utils/SkCamera.h
new file mode 100644
index 0000000..eafacbc
--- /dev/null
+++ b/utils/SkCamera.h
@@ -0,0 +1,175 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+
+
+// Inspired by Rob Johnson's most excellent QuickDraw GX sample code
+
+#ifndef SkCamera_DEFINED
+#define SkCamera_DEFINED
+
+#include "Sk64.h"
+#include "SkMatrix.h"
+
+class SkCanvas;
+
+#ifdef SK_SCALAR_IS_FIXED
+ typedef SkFract SkUnitScalar;
+ #define SK_UnitScalar1 SK_Fract1
+ #define SkUnitScalarMul(a, b) SkFractMul(a, b)
+ #define SkUnitScalarDiv(a, b) SkFractDiv(a, b)
+#else
+ typedef float SkUnitScalar;
+ #define SK_UnitScalar1 SK_Scalar1
+ #define SkUnitScalarMul(a, b) SkScalarMul(a, b)
+ #define SkUnitScalarDiv(a, b) SkScalarDiv(a, b)
+#endif
+
+struct SkUnit3D {
+ SkUnitScalar fX, fY, fZ;
+
+ void set(SkUnitScalar x, SkUnitScalar y, SkUnitScalar z)
+ {
+ fX = x; fY = y; fZ = z;
+ }
+ static SkUnitScalar Dot(const SkUnit3D&, const SkUnit3D&);
+ static void Cross(const SkUnit3D&, const SkUnit3D&, SkUnit3D* cross);
+};
+
+struct SkPoint3D {
+ SkScalar fX, fY, fZ;
+
+ void set(SkScalar x, SkScalar y, SkScalar z)
+ {
+ fX = x; fY = y; fZ = z;
+ }
+ SkScalar normalize(SkUnit3D*) const;
+};
+typedef SkPoint3D SkVector3D;
+
+struct SkMatrix3D {
+ SkScalar fMat[3][4];
+
+ void reset();
+
+ void setRow(int row, SkScalar a, SkScalar b, SkScalar c, SkScalar d = 0)
+ {
+ SkASSERT((unsigned)row < 3);
+ fMat[row][0] = a;
+ fMat[row][1] = b;
+ fMat[row][2] = c;
+ fMat[row][3] = d;
+ }
+
+ void setRotateX(SkScalar deg);
+ void setRotateY(SkScalar deg);
+ void setRotateZ(SkScalar deg);
+ void setTranslate(SkScalar x, SkScalar y, SkScalar z);
+
+ void preRotateX(SkScalar deg);
+ void preRotateY(SkScalar deg);
+ void preRotateZ(SkScalar deg);
+ void preTranslate(SkScalar x, SkScalar y, SkScalar z);
+
+ void setConcat(const SkMatrix3D& a, const SkMatrix3D& b);
+ void mapPoint(const SkPoint3D& src, SkPoint3D* dst) const;
+ void mapVector(const SkVector3D& src, SkVector3D* dst) const;
+
+ void mapPoint(SkPoint3D* v) const
+ {
+ this->mapPoint(*v, v);
+ }
+ void mapVector(SkVector3D* v) const
+ {
+ this->mapVector(*v, v);
+ }
+};
+
+class SkPatch3D {
+public:
+ SkPatch3D();
+
+ void reset();
+ void transform(const SkMatrix3D&, SkPatch3D* dst = NULL) const;
+
+ // dot a unit vector with the patch's normal
+ SkScalar dotWith(SkScalar dx, SkScalar dy, SkScalar dz) const;
+ SkScalar dotWith(const SkVector3D& v) const
+ {
+ return this->dotWith(v.fX, v.fY, v.fZ);
+ }
+
+ // deprecated, but still here for animator (for now)
+ void rotate(SkScalar x, SkScalar y, SkScalar z) {}
+ void rotateDegrees(SkScalar x, SkScalar y, SkScalar z) {}
+
+private:
+public: // make public for SkDraw3D for now
+ SkVector3D fU, fV;
+ SkPoint3D fOrigin;
+
+ friend class SkCamera3D;
+};
+
+class SkCamera3D {
+public:
+ SkCamera3D();
+
+ void reset();
+ void update();
+ void patchToMatrix(const SkPatch3D&, SkMatrix* matrix) const;
+
+ SkPoint3D fLocation;
+ SkPoint3D fAxis;
+ SkPoint3D fZenith;
+ SkPoint3D fObserver;
+
+private:
+ mutable SkMatrix fOrientation;
+ mutable bool fNeedToUpdate;
+
+ void doUpdate() const;
+};
+
+class Sk3DView : SkNoncopyable {
+public:
+ Sk3DView();
+ ~Sk3DView();
+
+ void save();
+ void restore();
+
+ void translate(SkScalar x, SkScalar y, SkScalar z);
+ void rotateX(SkScalar deg);
+ void rotateY(SkScalar deg);
+ void rotateZ(SkScalar deg);
+
+#ifdef SK_BUILD_FOR_ANDROID
+ void setCameraLocation(SkScalar x, SkScalar y, SkScalar z);
+ SkScalar getCameraLocationX();
+ SkScalar getCameraLocationY();
+ SkScalar getCameraLocationZ();
+#endif
+
+ void getMatrix(SkMatrix*) const;
+ void applyToCanvas(SkCanvas*) const;
+
+ SkScalar dotWithNormal(SkScalar dx, SkScalar dy, SkScalar dz) const;
+
+private:
+ struct Rec {
+ Rec* fNext;
+ SkMatrix3D fMatrix;
+ };
+ Rec* fRec;
+ Rec fInitialRec;
+ SkCamera3D fCamera;
+};
+
+#endif
diff --git a/utils/SkCanvasStateUtils.h b/utils/SkCanvasStateUtils.h
new file mode 100644
index 0000000..f8266c9
--- /dev/null
+++ b/utils/SkCanvasStateUtils.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkCanvasStateUtils_DEFINED
+#define SkCanvasStateUtils_DEFINED
+
+#include "SkCanvas.h"
+
+class SkCanvasState;
+
+/**
+ * A set of functions that are useful for copying an SkCanvas across a library
+ * boundary where the Skia libraries on either side of the boundary may not be
+ * version identical. The expected usage is outline below...
+ *
+ * Lib Boundary
+ * CaptureCanvasState(...) |||
+ * SkCanvas --> SkCanvasState |||
+ * ||| CreateFromCanvasState(...)
+ * ||| SkCanvasState --> SkCanvas`
+ * ||| Draw into SkCanvas`
+ * ||| Unref SkCanvas`
+ * ReleaseCanvasState(...) |||
+ *
+ */
+namespace SkCanvasStateUtils {
+ /**
+ * Captures the current state of the canvas into an opaque ptr that is safe
+ * to pass between different instances of Skia (which may or may not be the
+ * same version). The function will return NULL in the event that one of the
+ * following conditions are true.
+ * 1) the canvas device type is not supported (currently only raster is supported)
+ * 2) the canvas clip type is not supported (currently only non-AA clips are supported)
+ *
+ * It is recommended that the original canvas also not be used until all
+ * canvases that have been created using its captured state have been dereferenced.
+ *
+ * Finally, it is important to note that any draw filters attached to the
+ * canvas are NOT currently captured.
+ *
+ * @param canvas The canvas you wish to capture the current state of.
+ * @return NULL or an opaque ptr that can be passed to CreateFromCanvasState
+ * to reconstruct the canvas. The caller is responsible for calling
+ * ReleaseCanvasState to free the memory associated with this state.
+ */
+ SK_API SkCanvasState* CaptureCanvasState(SkCanvas* canvas);
+
+ /**
+ * Create a new SkCanvas from the captured state of another SkCanvas. The
+ * function will return NULL in the event that one of the
+ * following conditions are true.
+ * 1) the captured state is in an unrecognized format
+ * 2) the captured canvas device type is not supported
+ *
+ * @param canvas The canvas you wish to capture the current state of.
+ * @return NULL or an SkCanvas* whose devices and matrix/clip state are
+ * identical to the captured canvas. The caller is responsible for
+ * calling unref on the SkCanvas.
+ */
+ SK_API SkCanvas* CreateFromCanvasState(const SkCanvasState* state);
+
+ /**
+ * Free the memory associated with the captured canvas state. The state
+ * should not be released until all SkCanvas objects created using that
+ * state have been dereferenced.
+ *
+ * @param state The captured state you wish to dispose of.
+ */
+ SK_API void ReleaseCanvasState(SkCanvasState* state);
+};
+
+#endif
diff --git a/utils/SkCondVar.h b/utils/SkCondVar.h
new file mode 100644
index 0000000..15f16e6
--- /dev/null
+++ b/utils/SkCondVar.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkCondVar_DEFINED
+#define SkCondVar_DEFINED
+
+#ifdef SK_USE_POSIX_THREADS
+#include <pthread.h>
+#elif defined(SK_BUILD_FOR_WIN32)
+#include <Windows.h>
+#endif
+
+/**
+ * Condition variable for blocking access to shared data from other threads and
+ * controlling which threads are awake.
+ *
+ * Currently only supported on platforms with posix threads and Windows Vista and
+ * above.
+ */
+class SkCondVar {
+public:
+ SkCondVar();
+ ~SkCondVar();
+
+ /**
+ * Lock a mutex. Must be done before calling the other functions on this object.
+ */
+ void lock();
+
+ /**
+ * Unlock the mutex.
+ */
+ void unlock();
+
+ /**
+ * Pause the calling thread. Will be awoken when signal() or broadcast() is called.
+ * Must be called while lock() is held (but gives it up while waiting). Once awoken,
+ * the calling thread will hold the lock once again.
+ */
+ void wait();
+
+ /**
+ * Wake one thread waiting on this condition. Must be called while lock()
+ * is held.
+ */
+ void signal();
+
+ /**
+ * Wake all threads waiting on this condition. Must be called while lock()
+ * is held.
+ */
+ void broadcast();
+
+private:
+#ifdef SK_USE_POSIX_THREADS
+ pthread_mutex_t fMutex;
+ pthread_cond_t fCond;
+#elif defined(SK_BUILD_FOR_WIN32)
+ CRITICAL_SECTION fCriticalSection;
+ CONDITION_VARIABLE fCondition;
+#endif
+};
+
+#endif
diff --git a/utils/SkCountdown.h b/utils/SkCountdown.h
new file mode 100644
index 0000000..6bcec7d
--- /dev/null
+++ b/utils/SkCountdown.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkCountdown_DEFINED
+#define SkCountdown_DEFINED
+
+#include "SkCondVar.h"
+#include "SkRunnable.h"
+#include "SkTypes.h"
+
+class SkCountdown : public SkRunnable {
+public:
+ explicit SkCountdown(int32_t count);
+
+ /**
+ * Resets the countdown to the count provided.
+ */
+ void reset(int32_t count);
+
+ virtual void run() SK_OVERRIDE;
+
+ /**
+ * Blocks until run() has been called count times.
+ */
+ void wait();
+
+private:
+ SkCondVar fReady;
+ int32_t fCount;
+};
+
+#endif
diff --git a/utils/SkCubicInterval.h b/utils/SkCubicInterval.h
new file mode 100644
index 0000000..64d63cf
--- /dev/null
+++ b/utils/SkCubicInterval.h
@@ -0,0 +1,22 @@
+
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#ifndef SkCubicInterval_DEFINED
+#define SkCubicInterval_DEFINED
+
+#include "SkPoint.h"
+
+SkScalar SkEvalCubicInterval(SkScalar x1, SkScalar y1,
+ SkScalar x2, SkScalar y2,
+ SkScalar unitX);
+
+static inline SkScalar SkEvalCubicInterval(const SkPoint pts[2], SkScalar x) {
+ return SkEvalCubicInterval(pts[0].fX, pts[0].fY,
+ pts[1].fX, pts[1].fY, x);
+}
+
+#endif
diff --git a/utils/SkCullPoints.h b/utils/SkCullPoints.h
new file mode 100644
index 0000000..fafa0fc
--- /dev/null
+++ b/utils/SkCullPoints.h
@@ -0,0 +1,71 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkCullPoints_DEFINED
+#define SkCullPoints_DEFINED
+
+#include "SkRect.h"
+
+class SkCullPoints {
+public:
+ SkCullPoints();
+ SkCullPoints(const SkIRect& r);
+
+ void reset(const SkIRect& r);
+
+ /** Start a contour at (x,y). Follow this with call(s) to lineTo(...)
+ */
+ void moveTo(int x, int y);
+
+ enum LineToResult {
+ kNo_Result, //!< line segment was completely clipped out
+ kLineTo_Result, //!< path.lineTo(pts[1]);
+ kMoveToLineTo_Result //!< path.moveTo(pts[0]); path.lineTo(pts[1]);
+ };
+ /** Connect a line to the previous call to lineTo (or moveTo).
+ */
+ LineToResult lineTo(int x, int y, SkIPoint pts[2]);
+
+private:
+ SkIRect fR; // the caller's rectangle
+ SkIPoint fAsQuad[4]; // cache of fR as 4 points
+ SkIPoint fPrevPt; // private state
+ LineToResult fPrevResult; // private state
+
+ bool sect_test(int x0, int y0, int x1, int y1) const;
+};
+
+/////////////////////////////////////////////////////////////////////////////////
+
+class SkPath;
+
+/** \class SkCullPointsPath
+
+ Similar to SkCullPoints, but this class handles the return values
+ from lineTo, and automatically builds a SkPath with the result(s).
+*/
+class SkCullPointsPath {
+public:
+ SkCullPointsPath();
+ SkCullPointsPath(const SkIRect& r, SkPath* dst);
+
+ void reset(const SkIRect& r, SkPath* dst);
+
+ void moveTo(int x, int y);
+ void lineTo(int x, int y);
+
+private:
+ SkCullPoints fCP;
+ SkPath* fPath;
+};
+
+bool SkHitTestPath(const SkPath&, SkRect& target, bool hires);
+bool SkHitTestPath(const SkPath&, SkScalar x, SkScalar y, bool hires);
+
+#endif
diff --git a/utils/SkDebugUtils.h b/utils/SkDebugUtils.h
new file mode 100644
index 0000000..2fa6d41
--- /dev/null
+++ b/utils/SkDebugUtils.h
@@ -0,0 +1,94 @@
+
+/*
+ * Copyright 2013 Google, Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkDebugUtils_DEFINED
+#define SkDebugUtils_DEFINED
+
+#include "SkTypes.h"
+
+// These functions dump 0, 1, and 2d arrays of data in a format that's
+// compatible with Mathematica for quick visualization
+
+
+template<class T>
+inline void SkDebugDumpMathematica( const T val ) {
+ SkDEBUGFAIL("Need to specialize SkDebugDumpMathematica for your type, sorry.");
+}
+
+template<class T>
+inline void SkDebugDumpMathematica(const char *name, const T *array, int size) {
+ SkDebugf(name);
+ SkDebugf(" = {");
+ for (int i=0 ; i < size ; i++) {
+ SkDebugDumpMathematica<T>(array[i]);
+ if (i != size-1) SkDebugf(", ");
+ }
+ SkDebugf("};\n");
+}
+
+template<class T>
+inline void SkDebugDumpMathematica(const char *name, const T *array, int width, int height) {
+ SkDebugf(name);
+ SkDebugf(" = {\n");
+ for (int i=0 ; i < height ; i++) {
+ SkDebugf(" {");
+ for (int j = 0 ; j < width ; j++) {
+ SkDebugDumpMathematica<T>(array[i*width + j]);
+ if (j != width-1) {
+ SkDebugf(", ");
+ }
+ }
+ SkDebugf("}");
+ if (i != height-1) {
+ SkDebugf(", \n");
+ }
+ }
+ SkDebugf("\n};\n");
+}
+
+template<class T>
+inline void SkDebugDumpMathematica( const char *name, const T val ) {
+ SkDebugf(name);
+ SkDebugf(" = ");
+ SkDebugDumpMathematica<T>(val);
+ SkDebugf(";\n");
+}
+
+template<>
+inline void SkDebugDumpMathematica<uint8_t>( const uint8_t val ) {
+ SkDebugf("%u", val);
+}
+
+template<>
+inline void SkDebugDumpMathematica<unsigned int>( const unsigned int val ) {
+ SkDebugf("%u", val);
+}
+
+template<>
+inline void SkDebugDumpMathematica<int>( const int val ) {
+ SkDebugf("%d", val);
+}
+
+template<>
+inline void SkDebugDumpMathematica<size_t>( const size_t val ) {
+ SkDebugf("%u", val);
+}
+
+template<>
+void SkDebugDumpMathematica<const char *>( const char * val ) {
+ SkDebugf("%s", val);
+}
+
+template<>
+inline void SkDebugDumpMathematica<float>( float val ) {
+ SkDebugf("%f", val);
+}
+
+
+#endif
diff --git a/utils/SkDeferredCanvas.h b/utils/SkDeferredCanvas.h
new file mode 100644
index 0000000..77229a7
--- /dev/null
+++ b/utils/SkDeferredCanvas.h
@@ -0,0 +1,256 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkDeferredCanvas_DEFINED
+#define SkDeferredCanvas_DEFINED
+
+#include "SkCanvas.h"
+#include "SkPixelRef.h"
+
+class DeferredDevice;
+class SkImage;
+class SkSurface;
+
+/** \class SkDeferredCanvas
+ Subclass of SkCanvas that encapsulates an SkPicture or SkGPipe for deferred
+ drawing. The main difference between this class and SkPictureRecord (the
+ canvas provided by SkPicture) is that this is a full drop-in replacement
+ for SkCanvas, while SkPictureRecord only supports draw operations.
+ SkDeferredCanvas will transparently trigger the flushing of deferred
+ draw operations when an attempt is made to access the pixel data.
+*/
+class SK_API SkDeferredCanvas : public SkCanvas {
+public:
+ class NotificationClient;
+
+ /** Construct a canvas with the specified surface to draw into.
+ This factory must be used for newImageSnapshot to work.
+ @param surface Specifies a surface for the canvas to draw into.
+ */
+ static SkDeferredCanvas* Create(SkSurface* surface);
+
+ static SkDeferredCanvas* Create(SkDevice* device);
+
+ virtual ~SkDeferredCanvas();
+
+ /**
+ * Specify the surface to be used by this canvas. Calling setSurface will
+ * release the previously set surface or device. Takes a reference on the
+ * surface.
+ *
+ * @param surface The surface that the canvas will raw into
+ * @return The surface argument, for convenience.
+ */
+ SkSurface* setSurface(SkSurface* surface);
+
+ /**
+ * Specify a NotificationClient to be used by this canvas. Calling
+ * setNotificationClient will release the previously set
+ * NotificationClient, if any. SkDeferredCanvas does not take ownership
+ * of the notification client. Therefore user code is resposible
+ * for its destruction. The notification client must be unregistered
+ * by calling setNotificationClient(NULL) if it is destroyed before
+ * this canvas.
+ * Note: Must be called after the device is set with setDevice.
+ *
+ * @param notificationClient interface for dispatching notifications
+ * @return The notificationClient argument, for convenience.
+ */
+ NotificationClient* setNotificationClient(NotificationClient* notificationClient);
+
+ /**
+ * Enable or disable deferred drawing. When deferral is disabled,
+ * pending draw operations are immediately flushed and from then on,
+ * the SkDeferredCanvas behaves just like a regular SkCanvas.
+ * This method must not be called while the save/restore stack is in use.
+ * @param deferred true/false
+ */
+ void setDeferredDrawing(bool deferred);
+
+ /**
+ * Returns true if deferred drawing is currenlty enabled.
+ */
+ bool isDeferredDrawing() const;
+
+ /**
+ * Returns true if the canvas contains a fresh frame. A frame is
+ * considered fresh when its content do not depend on the contents
+ * of the previous frame. For example, if a canvas is cleared before
+ * drawing each frame, the frames will all be considered fresh.
+ * A frame is defined as the graphics image produced by as a result
+ * of all the canvas draws operation executed between two successive
+ * calls to isFreshFrame. The result of isFreshFrame is computed
+ * conservatively, so it may report false negatives.
+ */
+ bool isFreshFrame() const;
+
+ /**
+ * Returns true if the canvas has recorded draw commands that have
+ * not yet been played back.
+ */
+ bool hasPendingCommands() const;
+
+ /**
+ * Flushes pending draw commands, if any, and returns an image of the
+ * current state of the surface pixels up to this point. Subsequent
+ * changes to the surface (by drawing into its canvas) will not be
+ * reflected in this image. Will return NULL if the deferred canvas
+ * was not constructed from an SkSurface.
+ */
+ SkImage* newImageSnapshot();
+
+ /**
+ * Specify the maximum number of bytes to be allocated for the purpose
+ * of recording draw commands to this canvas. The default limit, is
+ * 64MB.
+ * @param maxStorage The maximum number of bytes to be allocated.
+ */
+ void setMaxRecordingStorage(size_t maxStorage);
+
+ /**
+ * Returns the number of bytes currently allocated for the purpose of
+ * recording draw commands.
+ */
+ size_t storageAllocatedForRecording() const;
+
+ /**
+ * Attempt to reduce the storage allocated for recording by evicting
+ * cache resources.
+ * @param bytesToFree minimum number of bytes that should be attempted to
+ * be freed.
+ * @return number of bytes actually freed.
+ */
+ size_t freeMemoryIfPossible(size_t bytesToFree);
+
+ /**
+ * Specifies the maximum size (in bytes) allowed for a given image to be
+ * rendered using the deferred canvas.
+ */
+ void setBitmapSizeThreshold(size_t sizeThreshold);
+
+ /**
+ * Executes all pending commands without drawing
+ */
+ void silentFlush();
+
+ // Overrides of the SkCanvas interface
+ virtual int save(SaveFlags flags) SK_OVERRIDE;
+ virtual int saveLayer(const SkRect* bounds, const SkPaint* paint,
+ SaveFlags flags) SK_OVERRIDE;
+ virtual void restore() SK_OVERRIDE;
+ virtual bool isDrawingToLayer() const SK_OVERRIDE;
+ virtual bool translate(SkScalar dx, SkScalar dy) SK_OVERRIDE;
+ virtual bool scale(SkScalar sx, SkScalar sy) SK_OVERRIDE;
+ virtual bool rotate(SkScalar degrees) SK_OVERRIDE;
+ virtual bool skew(SkScalar sx, SkScalar sy) SK_OVERRIDE;
+ virtual bool concat(const SkMatrix& matrix) SK_OVERRIDE;
+ virtual void setMatrix(const SkMatrix& matrix) SK_OVERRIDE;
+ virtual bool clipRect(const SkRect& rect, SkRegion::Op op,
+ bool doAntiAlias) SK_OVERRIDE;
+ virtual bool clipRRect(const SkRRect& rect, SkRegion::Op op,
+ bool doAntiAlias) SK_OVERRIDE;
+ virtual bool clipPath(const SkPath& path, SkRegion::Op op,
+ bool doAntiAlias) SK_OVERRIDE;
+ virtual bool clipRegion(const SkRegion& deviceRgn,
+ SkRegion::Op op) SK_OVERRIDE;
+ virtual void clear(SkColor) SK_OVERRIDE;
+ virtual void drawPaint(const SkPaint& paint) SK_OVERRIDE;
+ virtual void drawPoints(PointMode mode, size_t count, const SkPoint pts[],
+ const SkPaint& paint) SK_OVERRIDE;
+ virtual void drawOval(const SkRect&, const SkPaint& paint) SK_OVERRIDE;
+ virtual void drawRect(const SkRect& rect, const SkPaint& paint) SK_OVERRIDE;
+ virtual void drawRRect(const SkRRect&, const SkPaint& paint) SK_OVERRIDE;
+ virtual void drawPath(const SkPath& path, const SkPaint& paint)
+ SK_OVERRIDE;
+ virtual void drawBitmap(const SkBitmap& bitmap, SkScalar left,
+ SkScalar top, const SkPaint* paint)
+ SK_OVERRIDE;
+ virtual void drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src,
+ const SkRect& dst, const SkPaint* paint)
+ SK_OVERRIDE;
+
+ virtual void drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& m,
+ const SkPaint* paint) SK_OVERRIDE;
+ virtual void drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
+ const SkRect& dst, const SkPaint* paint)
+ SK_OVERRIDE;
+ virtual void drawSprite(const SkBitmap& bitmap, int left, int top,
+ const SkPaint* paint) SK_OVERRIDE;
+ virtual void drawText(const void* text, size_t byteLength, SkScalar x,
+ SkScalar y, const SkPaint& paint) SK_OVERRIDE;
+ virtual void drawPosText(const void* text, size_t byteLength,
+ const SkPoint pos[], const SkPaint& paint)
+ SK_OVERRIDE;
+ virtual void drawPosTextH(const void* text, size_t byteLength,
+ const SkScalar xpos[], SkScalar constY,
+ const SkPaint& paint) SK_OVERRIDE;
+ virtual void drawTextOnPath(const void* text, size_t byteLength,
+ const SkPath& path, const SkMatrix* matrix,
+ const SkPaint& paint) SK_OVERRIDE;
+ virtual void drawPicture(SkPicture& picture) SK_OVERRIDE;
+ virtual void drawVertices(VertexMode vmode, int vertexCount,
+ const SkPoint vertices[], const SkPoint texs[],
+ const SkColor colors[], SkXfermode* xmode,
+ const uint16_t indices[], int indexCount,
+ const SkPaint& paint) SK_OVERRIDE;
+ virtual SkBounder* setBounder(SkBounder* bounder) SK_OVERRIDE;
+ virtual SkDrawFilter* setDrawFilter(SkDrawFilter* filter) SK_OVERRIDE;
+
+public:
+ class NotificationClient {
+ public:
+ virtual ~NotificationClient() {}
+
+ /**
+ * Called before executing one or several draw commands, which means
+ * once per flush when deferred rendering is enabled.
+ */
+ virtual void prepareForDraw() {}
+
+ /**
+ * Called after a recording a draw command if additional memory
+ * had to be allocated for recording.
+ * @param newAllocatedStorage same value as would be returned by
+ * storageAllocatedForRecording(), for convenience.
+ */
+ virtual void storageAllocatedForRecordingChanged(
+ size_t newAllocatedStorage) {}
+
+ /**
+ * Called after pending draw commands have been flushed
+ */
+ virtual void flushedDrawCommands() {}
+
+ /**
+ * Called after pending draw commands have been skipped, meaning
+ * that they were optimized-out because the canvas is cleared
+ * or completely overwritten by the command currently being recorded.
+ */
+ virtual void skippedPendingDrawCommands() {}
+ };
+
+protected:
+ virtual SkCanvas* canvasForDrawIter();
+ DeferredDevice* getDeferredDevice() const;
+
+private:
+ SkDeferredCanvas(DeferredDevice*);
+
+ void recordedDrawCommand();
+ SkCanvas* drawingCanvas() const;
+ SkCanvas* immediateCanvas() const;
+ bool isFullFrame(const SkRect*, const SkPaint*) const;
+ void validate() const;
+ void init();
+ bool fDeferredDrawing;
+
+ friend class SkDeferredCanvasTester; // for unit testing
+ typedef SkCanvas INHERITED;
+};
+
+
+#endif
diff --git a/utils/SkDumpCanvas.h b/utils/SkDumpCanvas.h
new file mode 100644
index 0000000..cdb1f19
--- /dev/null
+++ b/utils/SkDumpCanvas.h
@@ -0,0 +1,168 @@
+
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#ifndef SkDumpCanvas_DEFINED
+#define SkDumpCanvas_DEFINED
+
+#include "SkCanvas.h"
+
+#ifdef SK_DEVELOPER
+
+/** This class overrides all the draw methods on SkCanvas, and formats them
+ as text, and then sends that to a Dumper helper object.
+
+ Typical use might be to dump a display list to a log file to see what is
+ being drawn.
+ */
+class SkDumpCanvas : public SkCanvas {
+public:
+ class Dumper;
+
+ explicit SkDumpCanvas(Dumper* = 0);
+ virtual ~SkDumpCanvas();
+
+ enum Verb {
+ kNULL_Verb,
+
+ kSave_Verb,
+ kRestore_Verb,
+
+ kMatrix_Verb,
+
+ kClip_Verb,
+
+ kDrawPaint_Verb,
+ kDrawPoints_Verb,
+ kDrawOval_Verb,
+ kDrawRect_Verb,
+ kDrawRRect_Verb,
+ kDrawPath_Verb,
+ kDrawBitmap_Verb,
+ kDrawText_Verb,
+ kDrawPicture_Verb,
+ kDrawVertices_Verb,
+ kDrawData_Verb,
+
+ kBeginCommentGroup_Verb,
+ kAddComment_Verb,
+ kEndCommentGroup_Verb
+ };
+
+ /** Subclasses of this are installed on the DumpCanvas, and then called for
+ each drawing command.
+ */
+ class Dumper : public SkRefCnt {
+ public:
+ SK_DECLARE_INST_COUNT(Dumper)
+
+ virtual void dump(SkDumpCanvas*, SkDumpCanvas::Verb, const char str[],
+ const SkPaint*) = 0;
+
+ private:
+ typedef SkRefCnt INHERITED;
+ };
+
+ Dumper* getDumper() const { return fDumper; }
+ void setDumper(Dumper*);
+
+ int getNestLevel() const { return fNestLevel; }
+
+ virtual int save(SaveFlags) SK_OVERRIDE;
+ virtual int saveLayer(const SkRect* bounds, const SkPaint* paint,
+ SaveFlags) SK_OVERRIDE;
+ virtual void restore() SK_OVERRIDE;
+
+ virtual bool translate(SkScalar dx, SkScalar dy) SK_OVERRIDE;
+ virtual bool scale(SkScalar sx, SkScalar sy) SK_OVERRIDE;
+ virtual bool rotate(SkScalar degrees) SK_OVERRIDE;
+ virtual bool skew(SkScalar sx, SkScalar sy) SK_OVERRIDE;
+ virtual bool concat(const SkMatrix& matrix) SK_OVERRIDE;
+ virtual void setMatrix(const SkMatrix& matrix) SK_OVERRIDE;
+
+ virtual bool clipRect(const SkRect&, SkRegion::Op, bool) SK_OVERRIDE;
+ virtual bool clipRRect(const SkRRect&, SkRegion::Op, bool) SK_OVERRIDE;
+ virtual bool clipPath(const SkPath&, SkRegion::Op, bool) SK_OVERRIDE;
+ virtual bool clipRegion(const SkRegion& deviceRgn,
+ SkRegion::Op) SK_OVERRIDE;
+
+ virtual void drawPaint(const SkPaint& paint) SK_OVERRIDE;
+ virtual void drawPoints(PointMode mode, size_t count, const SkPoint pts[],
+ const SkPaint& paint) SK_OVERRIDE;
+ virtual void drawOval(const SkRect&, const SkPaint& paint) SK_OVERRIDE;
+ virtual void drawRect(const SkRect&, const SkPaint& paint) SK_OVERRIDE;
+ virtual void drawRRect(const SkRRect&, const SkPaint& paint) SK_OVERRIDE;
+ virtual void drawPath(const SkPath& path, const SkPaint& paint) SK_OVERRIDE;
+ virtual void drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
+ const SkPaint* paint) SK_OVERRIDE;
+ virtual void drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src,
+ const SkRect& dst, const SkPaint* paint) SK_OVERRIDE;
+ virtual void drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& m,
+ const SkPaint* paint) SK_OVERRIDE;
+ virtual void drawSprite(const SkBitmap& bitmap, int left, int top,
+ const SkPaint* paint) SK_OVERRIDE;
+ virtual void drawText(const void* text, size_t byteLength, SkScalar x,
+ SkScalar y, const SkPaint& paint) SK_OVERRIDE;
+ virtual void drawPosText(const void* text, size_t byteLength,
+ const SkPoint pos[], const SkPaint& paint) SK_OVERRIDE;
+ virtual void drawPosTextH(const void* text, size_t byteLength,
+ const SkScalar xpos[], SkScalar constY,
+ const SkPaint& paint) SK_OVERRIDE;
+ virtual void drawTextOnPath(const void* text, size_t byteLength,
+ const SkPath& path, const SkMatrix* matrix,
+ const SkPaint& paint) SK_OVERRIDE;
+ virtual void drawPicture(SkPicture&) SK_OVERRIDE;
+ virtual void drawVertices(VertexMode vmode, int vertexCount,
+ const SkPoint vertices[], const SkPoint texs[],
+ const SkColor colors[], SkXfermode* xmode,
+ const uint16_t indices[], int indexCount,
+ const SkPaint& paint) SK_OVERRIDE;
+ virtual void drawData(const void*, size_t) SK_OVERRIDE;
+ virtual void beginCommentGroup(const char* description) SK_OVERRIDE;
+ virtual void addComment(const char* kywd, const char* value) SK_OVERRIDE;
+ virtual void endCommentGroup() SK_OVERRIDE;
+
+private:
+ Dumper* fDumper;
+ int fNestLevel; // for nesting recursive elements like pictures
+
+ void dump(Verb, const SkPaint*, const char format[], ...);
+
+ typedef SkCanvas INHERITED;
+};
+
+/** Formats the draw commands, and send them to a function-pointer provided
+ by the caller.
+ */
+class SkFormatDumper : public SkDumpCanvas::Dumper {
+public:
+ SkFormatDumper(void (*)(const char text[], void* refcon), void* refcon);
+
+ // override from baseclass that does the formatting, and in turn calls
+ // the function pointer that was passed to the constructor
+ virtual void dump(SkDumpCanvas*, SkDumpCanvas::Verb, const char str[],
+ const SkPaint*) SK_OVERRIDE;
+
+private:
+ void (*fProc)(const char*, void*);
+ void* fRefcon;
+
+ typedef SkDumpCanvas::Dumper INHERITED;
+};
+
+/** Subclass of Dumper that dumps the drawing command to SkDebugf
+ */
+class SkDebugfDumper : public SkFormatDumper {
+public:
+ SkDebugfDumper();
+
+private:
+ typedef SkFormatDumper INHERITED;
+};
+
+#endif
+
+#endif
diff --git a/utils/SkInterpolator.h b/utils/SkInterpolator.h
new file mode 100644
index 0000000..74789c8
--- /dev/null
+++ b/utils/SkInterpolator.h
@@ -0,0 +1,131 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkInterpolator_DEFINED
+#define SkInterpolator_DEFINED
+
+#include "SkScalar.h"
+
+class SkInterpolatorBase : SkNoncopyable {
+public:
+ enum Result {
+ kNormal_Result,
+ kFreezeStart_Result,
+ kFreezeEnd_Result
+ };
+protected:
+ SkInterpolatorBase();
+ ~SkInterpolatorBase();
+public:
+ void reset(int elemCount, int frameCount);
+
+ /** Return the start and end time for this interpolator.
+ If there are no key frames, return false.
+ @param startTime If not null, returns the time (in milliseconds) of the
+ first keyframe. If there are no keyframes, this param
+ is ignored (left unchanged).
+ @param endTime If not null, returns the time (in milliseconds) of the
+ last keyframe. If there are no keyframes, this parameter
+ is ignored (left unchanged).
+ @return True if there are key frames, or false if there are none.
+ */
+ bool getDuration(SkMSec* startTime, SkMSec* endTime) const;
+
+
+ /** Set the whether the repeat is mirrored.
+ @param mirror If true, the odd repeats interpolate from the last key
+ frame and the first.
+ */
+ void setMirror(bool mirror) {
+ fFlags = SkToU8((fFlags & ~kMirror) | (int)mirror);
+ }
+
+ /** Set the repeat count. The repeat count may be fractional.
+ @param repeatCount Multiplies the total time by this scalar.
+ */
+ void setRepeatCount(SkScalar repeatCount) { fRepeat = repeatCount; }
+
+ /** Set the whether the repeat is mirrored.
+ @param reset If true, the odd repeats interpolate from the last key
+ frame and the first.
+ */
+ void setReset(bool reset) {
+ fFlags = SkToU8((fFlags & ~kReset) | (int)reset);
+ }
+
+ Result timeToT(SkMSec time, SkScalar* T, int* index, SkBool* exact) const;
+
+protected:
+ enum Flags {
+ kMirror = 1,
+ kReset = 2,
+ kHasBlend = 4
+ };
+ static SkScalar ComputeRelativeT(SkMSec time, SkMSec prevTime,
+ SkMSec nextTime, const SkScalar blend[4] = NULL);
+ int16_t fFrameCount;
+ uint8_t fElemCount;
+ uint8_t fFlags;
+ SkScalar fRepeat;
+ struct SkTimeCode {
+ SkMSec fTime;
+ SkScalar fBlend[4];
+ };
+ SkTimeCode* fTimes; // pointer into fStorage
+ void* fStorage;
+#ifdef SK_DEBUG
+ SkTimeCode(* fTimesArray)[10];
+#endif
+};
+
+class SkInterpolator : public SkInterpolatorBase {
+public:
+ SkInterpolator();
+ SkInterpolator(int elemCount, int frameCount);
+ void reset(int elemCount, int frameCount);
+
+ /** Add or replace a key frame, copying the values[] data into the
+ interpolator.
+ @param index The index of this frame (frames must be ordered by time)
+ @param time The millisecond time for this frame
+ @param values The array of values [elemCount] for this frame. The data
+ is copied into the interpolator.
+ @param blend A positive scalar specifying how to blend between this
+ and the next key frame. [0...1) is a cubic lag/log/lag
+ blend (slow to change at the beginning and end)
+ 1 is a linear blend (default)
+ */
+ bool setKeyFrame(int index, SkMSec time, const SkScalar values[],
+ const SkScalar blend[4] = NULL);
+
+ /** Return the computed values given the specified time. Return whether
+ those values are the result of pinning to either the first
+ (kFreezeStart) or last (kFreezeEnd), or from interpolated the two
+ nearest key values (kNormal).
+ @param time The time to sample (in milliseconds)
+ @param (may be null) where to write the computed values.
+ */
+ Result timeToValues(SkMSec time, SkScalar values[] = NULL) const;
+
+ SkDEBUGCODE(static void UnitTest();)
+private:
+ SkScalar* fValues; // pointer into fStorage
+#ifdef SK_DEBUG
+ SkScalar(* fScalarsArray)[10];
+#endif
+ typedef SkInterpolatorBase INHERITED;
+};
+
+/** Given all the parameters are [0...1], apply the cubic specified by (0,0)
+ (bx,by) (cx,cy) (1,1) to value, returning the answer, also [0...1].
+*/
+SkScalar SkUnitCubicInterp(SkScalar value, SkScalar bx, SkScalar by,
+ SkScalar cx, SkScalar cy);
+
+#endif
diff --git a/utils/SkJSON.h b/utils/SkJSON.h
new file mode 100644
index 0000000..c601fa8
--- /dev/null
+++ b/utils/SkJSON.h
@@ -0,0 +1,285 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkJSON_DEFINED
+#define SkJSON_DEFINED
+
+#include "SkTypes.h"
+
+class SkStream;
+class SkString;
+
+class SkJSON {
+public:
+ enum Type {
+ kObject,
+ kArray,
+ kString,
+ kInt,
+ kFloat,
+ kBool,
+ };
+
+ class Array;
+
+ class Object {
+ private:
+ struct Slot;
+
+ public:
+ Object();
+ Object(const Object&);
+ ~Object();
+
+ /**
+ * Create a new slot with the specified name and value. The name
+ * parameter is copied, but ownership of the Object parameter is
+ * transferred. The Object parameter may be null, but the name must
+ * not be null.
+ */
+ void addObject(const char name[], Object* value);
+
+ /**
+ * Create a new slot with the specified name and value. The name
+ * parameter is copied, but ownership of the Array parameter is
+ * transferred. The Array parameter may be null, but the name must
+ * not be null.
+ */
+ void addArray(const char name[], Array* value);
+
+ /**
+ * Create a new slot with the specified name and value. Both parameters
+ * are copied. The value parameter may be null, but the name must
+ * not be null.
+ */
+ void addString(const char name[], const char value[]);
+
+ /**
+ * Create a new slot with the specified name and value. The name
+ * parameter is copied, and must not be null.
+ */
+ void addInt(const char name[], int32_t value);
+
+ /**
+ * Create a new slot with the specified name and value. The name
+ * parameter is copied, and must not be null.
+ */
+ void addFloat(const char name[], float value);
+
+ /**
+ * Create a new slot with the specified name and value. The name
+ * parameter is copied, and must not be null.
+ */
+ void addBool(const char name[], bool value);
+
+ /**
+ * Return the number of slots/fields in this object. These can be
+ * iterated using Iter.
+ */
+ int count() const;
+
+ /**
+ * Returns true if a slot matching the name and Type is found.
+ */
+ bool find(const char name[], Type) const;
+ bool findObject(const char name[], Object** = NULL) const;
+ bool findArray(const char name[], Array** = NULL) const;
+ bool findString(const char name[], SkString* = NULL) const;
+ bool findInt(const char name[], int32_t* = NULL) const;
+ bool findFloat(const char name[], float* = NULL) const;
+ bool findBool(const char name[], bool* = NULL) const;
+
+ /**
+ * Finds the first slot matching the name and Type and removes it.
+ * Returns true if found, false if not.
+ */
+ bool remove(const char name[], Type);
+
+ void toDebugf() const;
+
+ /**
+ * Iterator class which returns all of the fields/slots in an Object,
+ * in the order that they were added.
+ */
+ class Iter {
+ public:
+ Iter(const Object&);
+
+ /**
+ * Returns true when there are no more entries in the iterator.
+ * In this case, no other methods should be called.
+ */
+ bool done() const;
+
+ /**
+ * Moves the iterator to the next element. Should only be called
+ * if done() returns false.
+ */
+ void next();
+
+ /**
+ * Returns the type of the current element. Should only be called
+ * if done() returns false.
+ */
+ Type type() const;
+
+ /**
+ * Returns the name of the current element. Should only be called
+ * if done() returns false.
+ */
+ const char* name() const;
+
+ /**
+ * Returns the type of the current element. Should only be called
+ * if done() returns false and type() returns kObject.
+ */
+ Object* objectValue() const;
+
+ /**
+ * Returns the type of the current element. Should only be called
+ * if done() returns false and type() returns kArray.
+ */
+ Array* arrayValue() const;
+
+ /**
+ * Returns the type of the current element. Should only be called
+ * if done() returns false and type() returns kString.
+ */
+ const char* stringValue() const;
+
+ /**
+ * Returns the type of the current element. Should only be called
+ * if done() returns false and type() returns kInt.
+ */
+ int32_t intValue() const;
+
+ /**
+ * Returns the type of the current element. Should only be called
+ * if done() returns false and type() returns kFloat.
+ */
+ float floatValue() const;
+
+ /**
+ * Returns the type of the current element. Should only be called
+ * if done() returns false and type() returns kBool.
+ */
+ bool boolValue() const;
+
+ private:
+ Slot* fSlot;
+ };
+
+ private:
+ Slot* fHead;
+ Slot* fTail;
+
+ const Slot* findSlot(const char name[], Type) const;
+ Slot* addSlot(Slot*);
+ void dumpLevel(int level) const;
+
+ friend class Array;
+ };
+
+ class Array {
+ public:
+ /**
+ * Creates an array with the specified Type and element count. All
+ * entries are initialized to NULL/0/false.
+ */
+ Array(Type, int count);
+
+ /**
+ * Creates an array of ints, initialized by copying the specified
+ * values.
+ */
+ Array(const int32_t values[], int count);
+
+ /**
+ * Creates an array of floats, initialized by copying the specified
+ * values.
+ */
+ Array(const float values[], int count);
+
+ /**
+ * Creates an array of bools, initialized by copying the specified
+ * values.
+ */
+ Array(const bool values[], int count);
+
+ Array(const Array&);
+ ~Array();
+
+ int count() const { return fCount; }
+ Type type() const { return fType; }
+
+ /**
+ * Replace the element at the specified index with the specified
+ * Object (which may be null). Ownership of the Object is transferred.
+ * Should only be called if the Array's type is kObject.
+ */
+ void setObject(int index, Object*);
+
+ /**
+ * Replace the element at the specified index with the specified
+ * Array (which may be null). Ownership of the Array is transferred.
+ * Should only be called if the Array's type is kArray.
+ */
+ void setArray(int index, Array*);
+
+ /**
+ * Replace the element at the specified index with a copy of the
+ * specified string (which may be null). Should only be called if the
+ * Array's type is kString.
+ */
+ void setString(int index, const char str[]);
+
+ Object* const* objects() const {
+ SkASSERT(kObject == fType);
+ return fArray.fObjects;
+ }
+ Array* const* arrays() const {
+ SkASSERT(kObject == fType);
+ return fArray.fArrays;
+ }
+ const char* const* strings() const {
+ SkASSERT(kString == fType);
+ return fArray.fStrings;
+ }
+ int32_t* ints() const {
+ SkASSERT(kInt == fType);
+ return fArray.fInts;
+ }
+ float* floats() const {
+ SkASSERT(kFloat == fType);
+ return fArray.fFloats;
+ }
+ bool* bools() const {
+ SkASSERT(kBool == fType);
+ return fArray.fBools;
+ }
+
+ private:
+ int fCount;
+ Type fType;
+ union {
+ void* fVoids;
+ Object** fObjects;
+ Array** fArrays;
+ char** fStrings;
+ int32_t* fInts;
+ float* fFloats;
+ bool* fBools;
+ } fArray;
+
+ void init(Type, int count, const void* src);
+ void dumpLevel(int level) const;
+
+ friend class Object;
+ };
+};
+
+#endif
diff --git a/utils/SkLayer.h b/utils/SkLayer.h
new file mode 100644
index 0000000..70fa01b
--- /dev/null
+++ b/utils/SkLayer.h
@@ -0,0 +1,130 @@
+
+/*
+ * Copyright 2010 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkLayer_DEFINED
+#define SkLayer_DEFINED
+
+#include "SkRefCnt.h"
+#include "SkTDArray.h"
+#include "SkColor.h"
+#include "SkMatrix.h"
+#include "SkPoint.h"
+#include "SkRect.h"
+#include "SkSize.h"
+
+class SkCanvas;
+
+class SkLayer : public SkRefCnt {
+
+public:
+ SK_DECLARE_INST_COUNT(SkLayer)
+
+ SkLayer();
+ SkLayer(const SkLayer&);
+ virtual ~SkLayer();
+
+ bool isInheritFromRootTransform() const;
+ SkScalar getOpacity() const { return m_opacity; }
+ const SkSize& getSize() const { return m_size; }
+ const SkPoint& getPosition() const { return m_position; }
+ const SkPoint& getAnchorPoint() const { return m_anchorPoint; }
+ const SkMatrix& getMatrix() const { return fMatrix; }
+ const SkMatrix& getChildrenMatrix() const { return fChildrenMatrix; }
+
+ SkScalar getWidth() const { return m_size.width(); }
+ SkScalar getHeight() const { return m_size.height(); }
+
+ void setInheritFromRootTransform(bool);
+ void setOpacity(SkScalar opacity) { m_opacity = opacity; }
+ void setSize(SkScalar w, SkScalar h) { m_size.set(w, h); }
+ void setPosition(SkScalar x, SkScalar y) { m_position.set(x, y); }
+ void setAnchorPoint(SkScalar x, SkScalar y) { m_anchorPoint.set(x, y); }
+ void setMatrix(const SkMatrix&);
+ void setChildrenMatrix(const SkMatrix&);
+
+ // children
+
+ /** Return the number of layers in our child list.
+ */
+ int countChildren() const;
+
+ /** Return the child at the specified index (starting at 0). This does not
+ affect the reference count of the child.
+ */
+ SkLayer* getChild(int index) const;
+
+ /** Add this layer to our child list at the end (top-most), and ref() it.
+ If it was already in another hierarchy, remove it from that list.
+ Return the new child.
+ */
+ SkLayer* addChild(SkLayer* child);
+
+ /** Remove this layer from its parent's list (or do nothing if it has no
+ parent.) If it had a parent, then unref() is called.
+ */
+ void detachFromParent();
+
+ /** Remove, and unref(), all of the layers in our child list.
+ */
+ void removeChildren();
+
+ /** Return our parent layer, or NULL if we have none.
+ */
+ SkLayer* getParent() const { return fParent; }
+
+ /** Return the root layer in this hiearchy. If this layer is the root
+ (i.e. has no parent), then this returns itself.
+ */
+ SkLayer* getRootLayer() const;
+
+ // coordinate system transformations
+
+ /** Return, in matrix, the matix transfomations that are applied locally
+ when this layer draws (i.e. its position and matrix/anchorPoint).
+ This does not include the childrenMatrix, since that is only applied
+ after this layer draws (but before its children draw).
+ */
+ void getLocalTransform(SkMatrix* matrix) const;
+
+ /** Return, in matrix, the concatenation of transforms that are applied
+ from this layer's root parent to the layer itself.
+ This is the matrix that is applied to the layer during drawing.
+ */
+ void localToGlobal(SkMatrix* matrix) const;
+
+ // paint method
+
+ void draw(SkCanvas*, SkScalar opacity);
+ void draw(SkCanvas* canvas) {
+ this->draw(canvas, SK_Scalar1);
+ }
+
+protected:
+ virtual void onDraw(SkCanvas*, SkScalar opacity);
+
+private:
+ enum Flags {
+ kInheritFromRootTransform_Flag = 0x01
+ };
+
+ SkLayer* fParent;
+ SkScalar m_opacity;
+ SkSize m_size;
+ SkPoint m_position;
+ SkPoint m_anchorPoint;
+ SkMatrix fMatrix;
+ SkMatrix fChildrenMatrix;
+ uint32_t fFlags;
+
+ SkTDArray<SkLayer*> m_children;
+
+ typedef SkRefCnt INHERITED;
+};
+
+#endif
diff --git a/utils/SkLua.h b/utils/SkLua.h
new file mode 100644
index 0000000..c609746
--- /dev/null
+++ b/utils/SkLua.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkLua_DEFINED
+#define SkLua_DEFINED
+
+#include "SkColor.h"
+#include "SkScalar.h"
+#include "SkString.h"
+
+struct lua_State;
+
+class SkCanvas;
+class SkMatrix;
+class SkPaint;
+class SkPath;
+struct SkRect;
+class SkRRect;
+
+#define SkScalarToLua(x) SkScalarToDouble(x)
+#define SkLuaToScalar(x) SkDoubleToScalar(x)
+
+class SkLua {
+public:
+ static void Load(lua_State*);
+
+ SkLua(const char termCode[] = NULL); // creates a new L, will close it
+ SkLua(lua_State*); // uses L, will not close it
+ ~SkLua();
+
+ lua_State* get() const { return fL; }
+ lua_State* operator*() const { return fL; }
+ lua_State* operator->() const { return fL; }
+
+ bool runCode(const char code[]);
+ bool runCode(const void* code, size_t size);
+
+ void pushBool(bool, const char tableKey[] = NULL);
+ void pushString(const char[], const char tableKey[] = NULL);
+ void pushString(const char[], size_t len, const char tableKey[] = NULL);
+ void pushString(const SkString&, const char tableKey[] = NULL);
+ void pushArrayU16(const uint16_t[], int count, const char tableKey[] = NULL);
+ void pushColor(SkColor, const char tableKey[] = NULL);
+ void pushU32(uint32_t, const char tableKey[] = NULL);
+ void pushScalar(SkScalar, const char tableKey[] = NULL);
+ void pushRect(const SkRect&, const char tableKey[] = NULL);
+ void pushRRect(const SkRRect&, const char tableKey[] = NULL);
+ void pushMatrix(const SkMatrix&, const char tableKey[] = NULL);
+ void pushPaint(const SkPaint&, const char tableKey[] = NULL);
+ void pushPath(const SkPath&, const char tableKey[] = NULL);
+ void pushCanvas(SkCanvas*, const char tableKey[] = NULL);
+
+private:
+ lua_State* fL;
+ SkString fTermCode;
+ bool fWeOwnL;
+};
+
+#endif
diff --git a/utils/SkLuaCanvas.h b/utils/SkLuaCanvas.h
new file mode 100644
index 0000000..e41e58c
--- /dev/null
+++ b/utils/SkLuaCanvas.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkLuaCanvas_DEFINED
+#define SkLuaCanvas_DEFINED
+
+#include "SkCanvas.h"
+#include "SkString.h"
+
+struct lua_State;
+
+class SkLuaCanvas : public SkCanvas {
+public:
+ void pushThis();
+
+ SkLuaCanvas(int width, int height, lua_State*, const char function[]);
+ virtual ~SkLuaCanvas();
+
+ virtual int save(SaveFlags flags) SK_OVERRIDE;
+ virtual int saveLayer(const SkRect* bounds, const SkPaint* paint,
+ SaveFlags flags) SK_OVERRIDE;
+ virtual void restore() SK_OVERRIDE;
+
+ virtual bool translate(SkScalar dx, SkScalar dy) SK_OVERRIDE;
+ virtual bool scale(SkScalar sx, SkScalar sy) SK_OVERRIDE;
+ virtual bool rotate(SkScalar degrees) SK_OVERRIDE;
+ virtual bool skew(SkScalar sx, SkScalar sy) SK_OVERRIDE;
+ virtual bool concat(const SkMatrix& matrix) SK_OVERRIDE;
+ virtual void setMatrix(const SkMatrix& matrix) SK_OVERRIDE;
+
+ virtual bool clipRect(const SkRect&, SkRegion::Op, bool) SK_OVERRIDE;
+ virtual bool clipRRect(const SkRRect&, SkRegion::Op, bool) SK_OVERRIDE;
+ virtual bool clipPath(const SkPath&, SkRegion::Op, bool) SK_OVERRIDE;
+ virtual bool clipRegion(const SkRegion& deviceRgn,
+ SkRegion::Op) SK_OVERRIDE;
+
+ virtual void drawPaint(const SkPaint& paint) SK_OVERRIDE;
+ virtual void drawPoints(PointMode mode, size_t count, const SkPoint pts[],
+ const SkPaint& paint) SK_OVERRIDE;
+ virtual void drawOval(const SkRect&, const SkPaint& paint) SK_OVERRIDE;
+ virtual void drawRect(const SkRect&, const SkPaint& paint) SK_OVERRIDE;
+ virtual void drawRRect(const SkRRect&, const SkPaint& paint) SK_OVERRIDE;
+ virtual void drawPath(const SkPath& path, const SkPaint& paint) SK_OVERRIDE;
+ virtual void drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
+ const SkPaint* paint) SK_OVERRIDE;
+ virtual void drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src,
+ const SkRect& dst, const SkPaint* paint) SK_OVERRIDE;
+ virtual void drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& m,
+ const SkPaint* paint) SK_OVERRIDE;
+ virtual void drawSprite(const SkBitmap& bitmap, int left, int top,
+ const SkPaint* paint) SK_OVERRIDE;
+ virtual void drawText(const void* text, size_t byteLength, SkScalar x,
+ SkScalar y, const SkPaint& paint) SK_OVERRIDE;
+ virtual void drawPosText(const void* text, size_t byteLength,
+ const SkPoint pos[], const SkPaint& paint) SK_OVERRIDE;
+ virtual void drawPosTextH(const void* text, size_t byteLength,
+ const SkScalar xpos[], SkScalar constY,
+ const SkPaint& paint) SK_OVERRIDE;
+ virtual void drawTextOnPath(const void* text, size_t byteLength,
+ const SkPath& path, const SkMatrix* matrix,
+ const SkPaint& paint) SK_OVERRIDE;
+ virtual void drawPicture(SkPicture&) SK_OVERRIDE;
+ virtual void drawVertices(VertexMode vmode, int vertexCount,
+ const SkPoint vertices[], const SkPoint texs[],
+ const SkColor colors[], SkXfermode* xmode,
+ const uint16_t indices[], int indexCount,
+ const SkPaint& paint) SK_OVERRIDE;
+ virtual void drawData(const void* data, size_t length) SK_OVERRIDE;
+
+private:
+ lua_State* fL;
+ SkString fFunc;
+
+ void sendverb(const char verb[]);
+
+ typedef SkCanvas INHERITED;
+};
+
+#endif
diff --git a/utils/SkMatrix44.h b/utils/SkMatrix44.h
new file mode 100644
index 0000000..9d9b6e0
--- /dev/null
+++ b/utils/SkMatrix44.h
@@ -0,0 +1,405 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkMatrix44_DEFINED
+#define SkMatrix44_DEFINED
+
+#include "SkMatrix.h"
+#include "SkScalar.h"
+
+#ifdef SK_MSCALAR_IS_DOUBLE
+#ifdef SK_MSCALAR_IS_FLOAT
+ #error "can't define MSCALAR both as DOUBLE and FLOAT"
+#endif
+ typedef double SkMScalar;
+
+ static inline double SkFloatToMScalar(float x) {
+ return static_cast<double>(x);
+ }
+ static inline float SkMScalarToFloat(double x) {
+ return static_cast<float>(x);
+ }
+ static inline double SkDoubleToMScalar(double x) {
+ return x;
+ }
+ static inline double SkMScalarToDouble(double x) {
+ return x;
+ }
+ static const SkMScalar SK_MScalarPI = 3.141592653589793;
+#elif defined SK_MSCALAR_IS_FLOAT
+#ifdef SK_MSCALAR_IS_DOUBLE
+ #error "can't define MSCALAR both as DOUBLE and FLOAT"
+#endif
+ typedef float SkMScalar;
+
+ static inline float SkFloatToMScalar(float x) {
+ return x;
+ }
+ static inline float SkMScalarToFloat(float x) {
+ return x;
+ }
+ static inline float SkDoubleToMScalar(double x) {
+ return static_cast<float>(x);
+ }
+ static inline double SkMScalarToDouble(float x) {
+ return static_cast<double>(x);
+ }
+ static const SkMScalar SK_MScalarPI = 3.14159265f;
+#endif
+
+#define SkMScalarToScalar SkMScalarToFloat
+#define SkScalarToMScalar SkFloatToMScalar
+
+static const SkMScalar SK_MScalar1 = 1;
+
+///////////////////////////////////////////////////////////////////////////////
+
+struct SkVector4 {
+ SkScalar fData[4];
+
+ SkVector4() {
+ this->set(0, 0, 0, 1);
+ }
+ SkVector4(const SkVector4& src) {
+ memcpy(fData, src.fData, sizeof(fData));
+ }
+ SkVector4(SkScalar x, SkScalar y, SkScalar z, SkScalar w = SK_Scalar1) {
+ fData[0] = x;
+ fData[1] = y;
+ fData[2] = z;
+ fData[3] = w;
+ }
+
+ SkVector4& operator=(const SkVector4& src) {
+ memcpy(fData, src.fData, sizeof(fData));
+ return *this;
+ }
+
+ bool operator==(const SkVector4& v) {
+ return fData[0] == v.fData[0] && fData[1] == v.fData[1] &&
+ fData[2] == v.fData[2] && fData[3] == v.fData[3];
+ }
+ bool operator!=(const SkVector4& v) {
+ return !(*this == v);
+ }
+ bool equals(SkScalar x, SkScalar y, SkScalar z, SkScalar w = SK_Scalar1) {
+ return fData[0] == x && fData[1] == y &&
+ fData[2] == z && fData[3] == w;
+ }
+
+ void set(SkScalar x, SkScalar y, SkScalar z, SkScalar w = SK_Scalar1) {
+ fData[0] = x;
+ fData[1] = y;
+ fData[2] = z;
+ fData[3] = w;
+ }
+};
+
+class SK_API SkMatrix44 {
+public:
+
+ enum Uninitialized_Constructor {
+ kUninitialized_Constructor
+ };
+ enum Identity_Constructor {
+ kIdentity_Constructor
+ };
+
+ SkMatrix44(Uninitialized_Constructor) { }
+ SkMatrix44(Identity_Constructor) { this->setIdentity(); }
+
+ // DEPRECATED: use the constructors that take an enum
+ SkMatrix44() { this->setIdentity(); }
+
+ SkMatrix44(const SkMatrix44& src) {
+ memcpy(fMat, src.fMat, sizeof(fMat));
+ fTypeMask = src.fTypeMask;
+ }
+
+ SkMatrix44(const SkMatrix44& a, const SkMatrix44& b) {
+ this->setConcat(a, b);
+ }
+
+ SkMatrix44& operator=(const SkMatrix44& src) {
+ if (&src != this) {
+ memcpy(fMat, src.fMat, sizeof(fMat));
+ fTypeMask = src.fTypeMask;
+ }
+ return *this;
+ }
+
+ bool operator==(const SkMatrix44& other) const;
+ bool operator!=(const SkMatrix44& other) const {
+ return !(other == *this);
+ }
+
+ SkMatrix44(const SkMatrix&);
+ SkMatrix44& operator=(const SkMatrix& src);
+ operator SkMatrix() const;
+
+ /**
+ * Return a reference to a const identity matrix
+ */
+ static const SkMatrix44& I();
+
+ enum TypeMask {
+ kIdentity_Mask = 0,
+ kTranslate_Mask = 0x01, //!< set if the matrix has translation
+ kScale_Mask = 0x02, //!< set if the matrix has any scale != 1
+ kAffine_Mask = 0x04, //!< set if the matrix skews or rotates
+ kPerspective_Mask = 0x08 //!< set if the matrix is in perspective
+ };
+
+ /**
+ * Returns a bitfield describing the transformations the matrix may
+ * perform. The bitfield is computed conservatively, so it may include
+ * false positives. For example, when kPerspective_Mask is true, all
+ * other bits may be set to true even in the case of a pure perspective
+ * transform.
+ */
+ inline TypeMask getType() const {
+ if (fTypeMask & kUnknown_Mask) {
+ fTypeMask = this->computeTypeMask();
+ }
+ SkASSERT(!(fTypeMask & kUnknown_Mask));
+ return (TypeMask)fTypeMask;
+ }
+
+ /**
+ * Return true if the matrix is identity.
+ */
+ inline bool isIdentity() const {
+ return kIdentity_Mask == this->getType();
+ }
+
+ /**
+ * Return true if the matrix contains translate or is identity.
+ */
+ inline bool isTranslate() const {
+ return !(this->getType() & ~kTranslate_Mask);
+ }
+
+ /**
+ * Return true if the matrix only contains scale or translate or is identity.
+ */
+ inline bool isScaleTranslate() const {
+ return !(this->getType() & ~(kScale_Mask | kTranslate_Mask));
+ }
+
+ void setIdentity();
+ inline void reset() { this->setIdentity();}
+
+ /**
+ * get a value from the matrix. The row,col parameters work as follows:
+ * (0, 0) scale-x
+ * (0, 3) translate-x
+ * (3, 0) perspective-x
+ */
+ inline SkMScalar get(int row, int col) const {
+ SkASSERT((unsigned)row <= 3);
+ SkASSERT((unsigned)col <= 3);
+ return fMat[col][row];
+ }
+
+ /**
+ * set a value in the matrix. The row,col parameters work as follows:
+ * (0, 0) scale-x
+ * (0, 3) translate-x
+ * (3, 0) perspective-x
+ */
+ inline void set(int row, int col, SkMScalar value) {
+ SkASSERT((unsigned)row <= 3);
+ SkASSERT((unsigned)col <= 3);
+ fMat[col][row] = value;
+ this->dirtyTypeMask();
+ }
+
+ inline double getDouble(int row, int col) const {
+ return SkMScalarToDouble(this->get(row, col));
+ }
+ inline void setDouble(int row, int col, double value) {
+ this->set(row, col, SkDoubleToMScalar(value));
+ }
+
+ /** These methods allow one to efficiently read matrix entries into an
+ * array. The given array must have room for exactly 16 entries. Whenever
+ * possible, they will try to use memcpy rather than an entry-by-entry
+ * copy.
+ */
+ void asColMajorf(float[]) const;
+ void asColMajord(double[]) const;
+ void asRowMajorf(float[]) const;
+ void asRowMajord(double[]) const;
+
+ /** These methods allow one to efficiently set all matrix entries from an
+ * array. The given array must have room for exactly 16 entries. Whenever
+ * possible, they will try to use memcpy rather than an entry-by-entry
+ * copy.
+ */
+ void setColMajorf(const float[]);
+ void setColMajord(const double[]);
+ void setRowMajorf(const float[]);
+ void setRowMajord(const double[]);
+
+#ifdef SK_MSCALAR_IS_FLOAT
+ void setColMajor(const SkMScalar data[]) { this->setColMajorf(data); }
+ void setRowMajor(const SkMScalar data[]) { this->setRowMajorf(data); }
+#else
+ void setColMajor(const SkMScalar data[]) { this->setColMajord(data); }
+ void setRowMajor(const SkMScalar data[]) { this->setRowMajord(data); }
+#endif
+
+ void set3x3(SkMScalar m00, SkMScalar m01, SkMScalar m02,
+ SkMScalar m10, SkMScalar m11, SkMScalar m12,
+ SkMScalar m20, SkMScalar m21, SkMScalar m22);
+
+ void setTranslate(SkMScalar dx, SkMScalar dy, SkMScalar dz);
+ void preTranslate(SkMScalar dx, SkMScalar dy, SkMScalar dz);
+ void postTranslate(SkMScalar dx, SkMScalar dy, SkMScalar dz);
+
+ void setScale(SkMScalar sx, SkMScalar sy, SkMScalar sz);
+ void preScale(SkMScalar sx, SkMScalar sy, SkMScalar sz);
+ void postScale(SkMScalar sx, SkMScalar sy, SkMScalar sz);
+
+ inline void setScale(SkMScalar scale) {
+ this->setScale(scale, scale, scale);
+ }
+ inline void preScale(SkMScalar scale) {
+ this->preScale(scale, scale, scale);
+ }
+ inline void postScale(SkMScalar scale) {
+ this->postScale(scale, scale, scale);
+ }
+
+ void setRotateDegreesAbout(SkMScalar x, SkMScalar y, SkMScalar z,
+ SkMScalar degrees) {
+ this->setRotateAbout(x, y, z, degrees * SK_MScalarPI / 180);
+ }
+
+ /** Rotate about the vector [x,y,z]. If that vector is not unit-length,
+ it will be automatically resized.
+ */
+ void setRotateAbout(SkMScalar x, SkMScalar y, SkMScalar z,
+ SkMScalar radians);
+ /** Rotate about the vector [x,y,z]. Does not check the length of the
+ vector, assuming it is unit-length.
+ */
+ void setRotateAboutUnit(SkMScalar x, SkMScalar y, SkMScalar z,
+ SkMScalar radians);
+
+ void setConcat(const SkMatrix44& a, const SkMatrix44& b);
+ inline void preConcat(const SkMatrix44& m) {
+ this->setConcat(*this, m);
+ }
+ inline void postConcat(const SkMatrix44& m) {
+ this->setConcat(m, *this);
+ }
+
+ friend SkMatrix44 operator*(const SkMatrix44& a, const SkMatrix44& b) {
+ return SkMatrix44(a, b);
+ }
+
+ /** If this is invertible, return that in inverse and return true. If it is
+ not invertible, return false and ignore the inverse parameter.
+ */
+ bool invert(SkMatrix44* inverse) const;
+
+ /** Transpose this matrix in place. */
+ void transpose();
+
+ /** Apply the matrix to the src vector, returning the new vector in dst.
+ It is legal for src and dst to point to the same memory.
+ */
+ void mapScalars(const SkScalar src[4], SkScalar dst[4]) const;
+ inline void mapScalars(SkScalar vec[4]) const {
+ this->mapScalars(vec, vec);
+ }
+
+ // DEPRECATED: call mapScalars()
+ void map(const SkScalar src[4], SkScalar dst[4]) const {
+ this->mapScalars(src, dst);
+ }
+ // DEPRECATED: call mapScalars()
+ void map(SkScalar vec[4]) const {
+ this->mapScalars(vec, vec);
+ }
+
+#ifdef SK_MSCALAR_IS_DOUBLE
+ void mapMScalars(const SkMScalar src[4], SkMScalar dst[4]) const;
+#elif defined SK_MSCALAR_IS_FLOAT
+ inline void mapMScalars(const SkMScalar src[4], SkMScalar dst[4]) const {
+ this->mapScalars(src, dst);
+ }
+#endif
+ inline void mapMScalars(SkMScalar vec[4]) const {
+ this->mapMScalars(vec, vec);
+ }
+
+ friend SkVector4 operator*(const SkMatrix44& m, const SkVector4& src) {
+ SkVector4 dst;
+ m.map(src.fData, dst.fData);
+ return dst;
+ }
+
+ /**
+ * map an array of [x, y, 0, 1] through the matrix, returning an array
+ * of [x', y', z', w'].
+ *
+ * @param src2 array of [x, y] pairs, with implied z=0 and w=1
+ * @param count number of [x, y] pairs in src2
+ * @param dst4 array of [x', y', z', w'] quads as the output.
+ */
+ void map2(const float src2[], int count, float dst4[]) const;
+ void map2(const double src2[], int count, double dst4[]) const;
+
+ void dump() const;
+
+ double determinant() const;
+
+private:
+ SkMScalar fMat[4][4];
+ mutable unsigned fTypeMask;
+
+ enum {
+ kUnknown_Mask = 0x80,
+
+ kAllPublic_Masks = 0xF
+ };
+
+ SkMScalar transX() const { return fMat[3][0]; }
+ SkMScalar transY() const { return fMat[3][1]; }
+ SkMScalar transZ() const { return fMat[3][2]; }
+
+ SkMScalar scaleX() const { return fMat[0][0]; }
+ SkMScalar scaleY() const { return fMat[1][1]; }
+ SkMScalar scaleZ() const { return fMat[2][2]; }
+
+ SkMScalar perspX() const { return fMat[0][3]; }
+ SkMScalar perspY() const { return fMat[1][3]; }
+ SkMScalar perspZ() const { return fMat[2][3]; }
+
+ int computeTypeMask() const;
+
+ inline void dirtyTypeMask() {
+ fTypeMask = kUnknown_Mask;
+ }
+
+ inline void setTypeMask(int mask) {
+ SkASSERT(0 == (~(kAllPublic_Masks | kUnknown_Mask) & mask));
+ fTypeMask = mask;
+ }
+
+ /**
+ * Does not take the time to 'compute' the typemask. Only returns true if
+ * we already know that this matrix is identity.
+ */
+ inline bool isTriviallyIdentity() const {
+ return 0 == fTypeMask;
+ }
+};
+
+#endif
diff --git a/utils/SkMeshUtils.h b/utils/SkMeshUtils.h
new file mode 100644
index 0000000..564df67
--- /dev/null
+++ b/utils/SkMeshUtils.h
@@ -0,0 +1,50 @@
+
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#ifndef SkMeshUtils_DEFINED
+#define SkMeshUtils_DEFINED
+
+#include "SkPoint.h"
+#include "SkColor.h"
+
+class SkBitmap;
+class SkCanvas;
+class SkPaint;
+
+class SkMeshIndices {
+public:
+ SkMeshIndices();
+ ~SkMeshIndices();
+
+ bool init(int texW, int texH, int rows, int cols) {
+ return this->init(NULL, NULL, texW, texH, rows, cols);
+ }
+
+ bool init(SkPoint tex[], uint16_t indices[],
+ int texW, int texH, int rows, int cols);
+
+ size_t indexCount() const { return fIndexCount; }
+ const uint16_t* indices() const { return fIndices; }
+
+ size_t texCount() const { return fTexCount; }
+ const SkPoint* tex() const { return fTex; }
+
+private:
+ size_t fIndexCount, fTexCount;
+ SkPoint* fTex;
+ uint16_t* fIndices;
+ void* fStorage; // may be null
+};
+
+class SkMeshUtils {
+public:
+ static void Draw(SkCanvas*, const SkBitmap&, int rows, int cols,
+ const SkPoint verts[], const SkColor colors[],
+ const SkPaint& paint);
+};
+
+#endif
diff --git a/utils/SkNWayCanvas.h b/utils/SkNWayCanvas.h
new file mode 100644
index 0000000..de78f8a
--- /dev/null
+++ b/utils/SkNWayCanvas.h
@@ -0,0 +1,91 @@
+
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkNWayCanvas_DEFINED
+#define SkNWayCanvas_DEFINED
+
+#include "SkCanvas.h"
+
+class SK_API SkNWayCanvas : public SkCanvas {
+public:
+ SkNWayCanvas(int width, int height);
+ virtual ~SkNWayCanvas();
+
+ virtual void addCanvas(SkCanvas*);
+ virtual void removeCanvas(SkCanvas*);
+ virtual void removeAll();
+
+ ///////////////////////////////////////////////////////////////////////////
+ // These are forwarded to the N canvases we're referencing
+
+ virtual int save(SaveFlags) SK_OVERRIDE;
+ virtual int saveLayer(const SkRect* bounds, const SkPaint*,
+ SaveFlags) SK_OVERRIDE;
+ virtual void restore() SK_OVERRIDE;
+ virtual bool translate(SkScalar dx, SkScalar dy) SK_OVERRIDE;
+ virtual bool scale(SkScalar sx, SkScalar sy) SK_OVERRIDE;
+ virtual bool rotate(SkScalar degrees) SK_OVERRIDE;
+ virtual bool skew(SkScalar sx, SkScalar sy) SK_OVERRIDE;
+ virtual bool concat(const SkMatrix& matrix) SK_OVERRIDE;
+ virtual void setMatrix(const SkMatrix& matrix) SK_OVERRIDE;
+ virtual bool clipRect(const SkRect&, SkRegion::Op, bool) SK_OVERRIDE;
+ virtual bool clipRRect(const SkRRect&, SkRegion::Op, bool) SK_OVERRIDE;
+ virtual bool clipPath(const SkPath&, SkRegion::Op, bool) SK_OVERRIDE;
+ virtual bool clipRegion(const SkRegion& deviceRgn,
+ SkRegion::Op) SK_OVERRIDE;
+
+ virtual void drawPaint(const SkPaint& paint) SK_OVERRIDE;
+ virtual void drawPoints(PointMode mode, size_t count, const SkPoint pts[],
+ const SkPaint&) SK_OVERRIDE;
+ virtual void drawOval(const SkRect&, const SkPaint&) SK_OVERRIDE;
+ virtual void drawRect(const SkRect&, const SkPaint&) SK_OVERRIDE;
+ virtual void drawRRect(const SkRRect&, const SkPaint&) SK_OVERRIDE;
+ virtual void drawPath(const SkPath& path, const SkPaint&) SK_OVERRIDE;
+ virtual void drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
+ const SkPaint*) SK_OVERRIDE;
+ virtual void drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src,
+ const SkRect& dst, const SkPaint*) SK_OVERRIDE;
+ virtual void drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& m,
+ const SkPaint*) SK_OVERRIDE;
+ virtual void drawSprite(const SkBitmap& bitmap, int left, int top,
+ const SkPaint*) SK_OVERRIDE;
+ virtual void drawText(const void* text, size_t byteLength, SkScalar x,
+ SkScalar y, const SkPaint&) SK_OVERRIDE;
+ virtual void drawPosText(const void* text, size_t byteLength,
+ const SkPoint pos[], const SkPaint&) SK_OVERRIDE;
+ virtual void drawPosTextH(const void* text, size_t byteLength,
+ const SkScalar xpos[], SkScalar constY,
+ const SkPaint&) SK_OVERRIDE;
+ virtual void drawTextOnPath(const void* text, size_t byteLength,
+ const SkPath& path, const SkMatrix* matrix,
+ const SkPaint&) SK_OVERRIDE;
+ virtual void drawPicture(SkPicture&) SK_OVERRIDE;
+ virtual void drawVertices(VertexMode vmode, int vertexCount,
+ const SkPoint vertices[], const SkPoint texs[],
+ const SkColor colors[], SkXfermode* xmode,
+ const uint16_t indices[], int indexCount,
+ const SkPaint&) SK_OVERRIDE;
+
+ virtual SkBounder* setBounder(SkBounder*) SK_OVERRIDE;
+ virtual SkDrawFilter* setDrawFilter(SkDrawFilter*) SK_OVERRIDE;
+
+ virtual void beginCommentGroup(const char* description) SK_OVERRIDE;
+ virtual void addComment(const char* kywd, const char* value) SK_OVERRIDE;
+ virtual void endCommentGroup() SK_OVERRIDE;
+
+protected:
+ SkTDArray<SkCanvas*> fList;
+
+ class Iter;
+
+private:
+ typedef SkCanvas INHERITED;
+};
+
+
+#endif
diff --git a/utils/SkNinePatch.h b/utils/SkNinePatch.h
new file mode 100644
index 0000000..4d8788b
--- /dev/null
+++ b/utils/SkNinePatch.h
@@ -0,0 +1,33 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkNinePatch_DEFINED
+#define SkNinePatch_DEFINED
+
+#include "SkRect.h"
+#include "SkRegion.h"
+
+class SkBitmap;
+class SkCanvas;
+class SkPaint;
+
+class SkNinePatch {
+public:
+ static void DrawNine(SkCanvas* canvas, const SkRect& dst,
+ const SkBitmap& bitmap, const SkIRect& margins,
+ const SkPaint* paint = NULL);
+
+ static void DrawMesh(SkCanvas* canvas, const SkRect& dst,
+ const SkBitmap& bitmap,
+ const int32_t xDivs[], int numXDivs,
+ const int32_t yDivs[], int numYDivs,
+ const SkPaint* paint = NULL);
+};
+
+#endif
diff --git a/utils/SkNullCanvas.h b/utils/SkNullCanvas.h
new file mode 100644
index 0000000..99a26da
--- /dev/null
+++ b/utils/SkNullCanvas.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkNullCanvas_DEFINED
+#define SkNullCanvas_DEFINED
+
+#include "SkBitmap.h"
+
+class SkCanvas;
+
+/**
+ * Creates a canvas that draws nothing. This is useful for performance testing.
+ */
+SK_API SkCanvas* SkCreateNullCanvas();
+
+#endif
diff --git a/utils/SkParse.h b/utils/SkParse.h
new file mode 100644
index 0000000..c5aac7d
--- /dev/null
+++ b/utils/SkParse.h
@@ -0,0 +1,36 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkParse_DEFINED
+#define SkParse_DEFINED
+
+#include "SkColor.h"
+
+class SkParse {
+public:
+ static int Count(const char str[]); // number of scalars or int values
+ static int Count(const char str[], char separator);
+ static const char* FindColor(const char str[], SkColor* value);
+ static const char* FindHex(const char str[], uint32_t* value);
+ static const char* FindMSec(const char str[], SkMSec* value);
+ static const char* FindNamedColor(const char str[], size_t len, SkColor* color);
+ static const char* FindS32(const char str[], int32_t* value);
+ static const char* FindScalar(const char str[], SkScalar* value);
+ static const char* FindScalars(const char str[], SkScalar value[], int count);
+
+ static bool FindBool(const char str[], bool* value);
+ // return the index of str in list[], or -1 if not found
+ static int FindList(const char str[], const char list[]);
+#ifdef SK_SUPPORT_UNITTEST
+ static void TestColor();
+ static void UnitTest();
+#endif
+};
+
+#endif
diff --git a/utils/SkParsePaint.h b/utils/SkParsePaint.h
new file mode 100644
index 0000000..066292f
--- /dev/null
+++ b/utils/SkParsePaint.h
@@ -0,0 +1,26 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkParsePaint_DEFINED
+#define SkParsePaint_DEFINED
+
+#include "SkPaint.h"
+#include "SkDOM.h"
+
+/** "color" color
+ "opacity" scalar [0..1]
+ "stroke-width" scalar (0...inf)
+ "text-size" scalar (0..inf)
+ "is-stroke" bool
+ "is-antialias" bool
+ "is-lineartext" bool
+*/
+void SkPaint_Inflate(SkPaint*, const SkDOM&, const SkDOM::Node*);
+
+#endif
diff --git a/utils/SkParsePath.h b/utils/SkParsePath.h
new file mode 100644
index 0000000..c52b3c0
--- /dev/null
+++ b/utils/SkParsePath.h
@@ -0,0 +1,23 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkParsePath_DEFINED
+#define SkParsePath_DEFINED
+
+#include "SkPath.h"
+
+class SkString;
+
+class SkParsePath {
+public:
+ static bool FromSVGString(const char str[], SkPath*);
+ static void ToSVGString(const SkPath&, SkString*);
+};
+
+#endif
diff --git a/utils/SkPathUtils.h b/utils/SkPathUtils.h
new file mode 100644
index 0000000..a27cbb8
--- /dev/null
+++ b/utils/SkPathUtils.h
@@ -0,0 +1,40 @@
+/*
+ * CAUTION: EXPERIMENTAL CODE
+ *
+ * This code is not to be used and will not be supported
+ * if it fails on you. DO NOT USE!
+ *
+ */
+
+#ifndef SkPathUtils_DEFINED
+#define SkPathUtils_DEFINED
+
+#include "SkPath.h"
+
+/*
+ * The following methods return the boundary path given a 1-bit bitmap, specified
+ * by width/height and stride. The bits are interpreted as 1 being "in" the path,
+ * and 0 being "out". The bits are interpreted as MSB on the left, and LSB on the right.
+ */
+
+class SK_API SkPathUtils {
+public:
+ /**
+ This variation iterates the binary data sequentially (as in scanline fashion)
+ and will add each run of 1's to the path as a rectangular path. Upon parsing
+ all binary data the path is simplified using the PathOps::Simplify() method.
+ */
+ static void BitsToPath_Path(SkPath* path, const char* bitmap,
+ int w, int h, int rowBytes);
+
+ /**
+ This variation utilizes the SkRegion class to generate paths, adding
+ each run of 1's to the SkRegion as an SkIRect. Upon parsing the entirety
+ of the binary the SkRegion is converted to a Path via getBoundaryPath().
+ */
+ static void BitsToPath_Region(SkPath* path, const char* bitmap,
+ int w, int h, int rowBytes);
+
+};
+
+#endif
diff --git a/utils/SkPictureUtils.h b/utils/SkPictureUtils.h
new file mode 100644
index 0000000..5e6b051
--- /dev/null
+++ b/utils/SkPictureUtils.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkPictureUtils_DEFINED
+#define SkPictureUtils_DEFINED
+
+#include "SkPicture.h"
+
+class SkData;
+struct SkRect;
+
+class SK_API SkPictureUtils {
+public:
+ /**
+ * Given a rectangular visible "window" into the picture, return an array
+ * of SkPixelRefs that might intersect that area. To keep the call fast,
+ * the returned list is not guaranteed to be exact, so it may miss some,
+ * and it may return false positives.
+ *
+ * The pixelrefs returned in the SkData are already owned by the picture,
+ * so the returned pointers are only valid while the picture is in scope
+ * and remains unchanged.
+ */
+ static SkData* GatherPixelRefs(SkPicture* pict, const SkRect& area);
+};
+
+#endif
diff --git a/utils/SkProxyCanvas.h b/utils/SkProxyCanvas.h
new file mode 100644
index 0000000..4091636
--- /dev/null
+++ b/utils/SkProxyCanvas.h
@@ -0,0 +1,93 @@
+
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#ifndef SkProxyCanvas_DEFINED
+#define SkProxyCanvas_DEFINED
+
+#include "SkCanvas.h"
+
+/** This class overrides all virtual methods on SkCanvas, and redirects them
+ to a "proxy", another SkCanvas instance. It can be the basis for
+ intercepting (and possibly modifying) calls to a canvas.
+
+ There must be a proxy installed before the proxycanvas can be used (i.e.
+ before its virtual methods can be called).
+ */
+class SK_API SkProxyCanvas : public SkCanvas {
+public:
+ SkProxyCanvas() : fProxy(NULL) {}
+ SkProxyCanvas(SkCanvas* proxy);
+ virtual ~SkProxyCanvas();
+
+ SkCanvas* getProxy() const { return fProxy; }
+ void setProxy(SkCanvas* proxy);
+
+ virtual int save(SaveFlags flags = kMatrixClip_SaveFlag) SK_OVERRIDE;
+ virtual int saveLayer(const SkRect* bounds, const SkPaint* paint,
+ SaveFlags flags = kARGB_ClipLayer_SaveFlag) SK_OVERRIDE;
+ virtual void restore() SK_OVERRIDE;
+
+ virtual bool translate(SkScalar dx, SkScalar dy) SK_OVERRIDE;
+ virtual bool scale(SkScalar sx, SkScalar sy) SK_OVERRIDE;
+ virtual bool rotate(SkScalar degrees) SK_OVERRIDE;
+ virtual bool skew(SkScalar sx, SkScalar sy) SK_OVERRIDE;
+ virtual bool concat(const SkMatrix& matrix) SK_OVERRIDE;
+ virtual void setMatrix(const SkMatrix& matrix) SK_OVERRIDE;
+
+ virtual bool clipRect(const SkRect&, SkRegion::Op, bool) SK_OVERRIDE;
+ virtual bool clipRRect(const SkRRect&, SkRegion::Op, bool) SK_OVERRIDE;
+ virtual bool clipPath(const SkPath&, SkRegion::Op, bool) SK_OVERRIDE;
+ virtual bool clipRegion(const SkRegion& deviceRgn,
+ SkRegion::Op op = SkRegion::kIntersect_Op) SK_OVERRIDE;
+
+ virtual void drawPaint(const SkPaint& paint) SK_OVERRIDE;
+ virtual void drawPoints(PointMode mode, size_t count, const SkPoint pts[],
+ const SkPaint& paint) SK_OVERRIDE;
+ virtual void drawOval(const SkRect&, const SkPaint& paint) SK_OVERRIDE;
+ virtual void drawRect(const SkRect&, const SkPaint& paint) SK_OVERRIDE;
+ virtual void drawRRect(const SkRRect&, const SkPaint& paint) SK_OVERRIDE;
+ virtual void drawPath(const SkPath& path, const SkPaint& paint) SK_OVERRIDE;
+ virtual void drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
+ const SkPaint* paint = NULL) SK_OVERRIDE;
+ virtual void drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src,
+ const SkRect& dst, const SkPaint* paint = NULL) SK_OVERRIDE;
+ virtual void drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& m,
+ const SkPaint* paint = NULL) SK_OVERRIDE;
+ virtual void drawSprite(const SkBitmap& bitmap, int left, int top,
+ const SkPaint* paint = NULL) SK_OVERRIDE;
+ virtual void drawText(const void* text, size_t byteLength, SkScalar x,
+ SkScalar y, const SkPaint& paint) SK_OVERRIDE;
+ virtual void drawPosText(const void* text, size_t byteLength,
+ const SkPoint pos[], const SkPaint& paint) SK_OVERRIDE;
+ virtual void drawPosTextH(const void* text, size_t byteLength,
+ const SkScalar xpos[], SkScalar constY,
+ const SkPaint& paint) SK_OVERRIDE;
+ virtual void drawTextOnPath(const void* text, size_t byteLength,
+ const SkPath& path, const SkMatrix* matrix,
+ const SkPaint& paint) SK_OVERRIDE;
+ virtual void drawPicture(SkPicture&) SK_OVERRIDE;
+ virtual void drawVertices(VertexMode vmode, int vertexCount,
+ const SkPoint vertices[], const SkPoint texs[],
+ const SkColor colors[], SkXfermode* xmode,
+ const uint16_t indices[], int indexCount,
+ const SkPaint& paint) SK_OVERRIDE;
+ virtual void drawData(const void* data, size_t length) SK_OVERRIDE;
+
+ virtual void beginCommentGroup(const char* description) SK_OVERRIDE;
+ virtual void addComment(const char* kywd, const char* value) SK_OVERRIDE;
+ virtual void endCommentGroup() SK_OVERRIDE;
+
+ virtual SkBounder* setBounder(SkBounder* bounder) SK_OVERRIDE;
+ virtual SkDrawFilter* setDrawFilter(SkDrawFilter* filter) SK_OVERRIDE;
+
+private:
+ SkCanvas* fProxy;
+
+ typedef SkCanvas INHERITED;
+};
+
+#endif
diff --git a/utils/SkRTConf.h b/utils/SkRTConf.h
new file mode 100644
index 0000000..ea6e99e
--- /dev/null
+++ b/utils/SkRTConf.h
@@ -0,0 +1,172 @@
+/*
+ * Copyright 2013 Google, Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkRTConf_DEFINED
+#define SkRTConf_DEFINED
+
+#include "SkString.h"
+#include "SkStream.h"
+
+#include "SkTDict.h"
+#include "SkTArray.h"
+
+/** \class SkRTConfBase
+ Non-templated base class for the runtime configs
+*/
+
+class SkRTConfBase {
+public:
+ SkRTConfBase(const char *name) : fName(name) {}
+ virtual ~SkRTConfBase() {}
+ virtual const char *getName() const { return fName.c_str(); }
+ virtual bool isDefault() const = 0;
+ virtual void print(SkWStream *o) const = 0;
+ virtual bool equals(const SkRTConfBase *conf) const = 0;
+protected:
+ SkString fName;
+};
+
+/** \class SkRTConf
+ A class to provide runtime configurability.
+*/
+template<typename T> class SkRTConf: public SkRTConfBase {
+public:
+ SkRTConf(const char *name, const T &defaultValue, const char *description);
+ operator const T&() const { return fValue; }
+ void print(SkWStream *o) const;
+ bool equals(const SkRTConfBase *conf) const;
+ bool isDefault() const { return fDefault == fValue; }
+ void set(const T& value) { fValue = value; }
+protected:
+ void doPrint(char *s) const;
+
+ T fValue;
+ T fDefault;
+ SkString fDescription;
+};
+
+#ifdef SK_DEVELOPER
+#define SK_CONF_DECLARE(confType, varName, confName, defaultValue, description) static SkRTConf<confType> varName(confName, defaultValue, description)
+#define SK_CONF_SET(confname, value) skRTConfRegistry().set(confname, value)
+#else
+#define SK_CONF_DECLARE(confType, varName, confName, defaultValue, description) static confType varName = defaultValue
+#define SK_CONF_SET(confname, value) (void) confname, (void) value
+#endif
+
+/** \class SkRTConfRegistry
+ A class that maintains a systemwide registry of all runtime configuration
+ parameters. Mainly used for printing them out and handling multiply-defined
+ knobs.
+*/
+
+class SkRTConfRegistry {
+public:
+ SkRTConfRegistry();
+ void printAll(const char *fname = NULL) const;
+ void printNonDefault(const char *fname = NULL) const;
+ const char *configFileLocation() const;
+ void possiblyDumpFile() const;
+ void validate() const;
+ template <typename T> void set(const char *confname, T value);
+private:
+ template<typename T> friend class SkRTConf;
+
+ void registerConf(SkRTConfBase *conf);
+ template <typename T> bool parse(const char *name, T* value);
+
+ SkTDArray<SkString *> fConfigFileKeys, fConfigFileValues;
+ typedef SkTDict< SkTDArray<SkRTConfBase *> * > ConfMap;
+ ConfMap fConfs;
+};
+
+// our singleton registry
+
+SkRTConfRegistry &skRTConfRegistry();
+
+template<typename T>
+SkRTConf<T>::SkRTConf(const char *name, const T &defaultValue, const char *description)
+ : SkRTConfBase(name)
+ , fValue(defaultValue)
+ , fDefault(defaultValue)
+ , fDescription(description) {
+
+ T value;
+ if (skRTConfRegistry().parse(fName.c_str(), &value)) {
+ fValue = value;
+ }
+ skRTConfRegistry().registerConf(this);
+}
+
+template<typename T>
+void SkRTConf<T>::print(SkWStream *o) const {
+ char outline[200]; // should be ok because we specify a max. width for everything here.
+
+ sprintf(outline, "%-30.30s", getName());
+ doPrint(&(outline[30]));
+ sprintf(&(outline[60]), " %.128s", fDescription.c_str());
+ if (' ' == outline[strlen(outline)-1]) {
+ for (int i = strlen(outline)-1 ; ' ' == outline[i] ; i--) {
+ outline[i] = '\0';
+ }
+ }
+ o->writeText(outline);
+}
+
+template<typename T>
+void SkRTConf<T>::doPrint(char *s) const {
+ sprintf(s, "%-30.30s", "How do I print myself??");
+}
+
+template<> inline void SkRTConf<bool>::doPrint(char *s) const {
+ char tmp[30];
+ sprintf(tmp, "%s # [%s]", fValue ? "true" : "false", fDefault ? "true" : "false");
+ sprintf(s, "%-30.30s", tmp);
+}
+
+template<> inline void SkRTConf<int>::doPrint(char *s) const {
+ char tmp[30];
+ sprintf(tmp, "%d # [%d]", fValue, fDefault);
+ sprintf(s, "%-30.30s", tmp);
+}
+
+template<> inline void SkRTConf<unsigned int>::doPrint(char *s) const {
+ char tmp[30];
+ sprintf(tmp, "%u # [%u]", fValue, fDefault);
+ sprintf(s, "%-30.30s", tmp);
+}
+
+template<> inline void SkRTConf<float>::doPrint(char *s) const {
+ char tmp[30];
+ sprintf(tmp, "%6.6f # [%6.6f]", fValue, fDefault);
+ sprintf(s, "%-30.30s", tmp);
+}
+
+template<> inline void SkRTConf<double>::doPrint(char *s) const {
+ char tmp[30];
+ sprintf(tmp, "%6.6f # [%6.6f]", fValue, fDefault);
+ sprintf(s, "%-30.30s", tmp);
+}
+
+template<> inline void SkRTConf<const char *>::doPrint(char *s) const {
+ char tmp[30];
+ sprintf(tmp, "%s # [%s]", fValue, fDefault);
+ sprintf(s, "%-30.30s", tmp);
+}
+
+template<typename T>
+bool SkRTConf<T>::equals(const SkRTConfBase *conf) const {
+ // static_cast here is okay because there's only one kind of child class.
+ const SkRTConf<T> *child_pointer = static_cast<const SkRTConf<T> *>(conf);
+ return child_pointer &&
+ fName == child_pointer->fName &&
+ fDescription == child_pointer->fDescription &&
+ fValue == child_pointer->fValue &&
+ fDefault == child_pointer->fDefault;
+}
+
+#endif
diff --git a/utils/SkRandom.h b/utils/SkRandom.h
new file mode 100644
index 0000000..3e2ef20
--- /dev/null
+++ b/utils/SkRandom.h
@@ -0,0 +1,323 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkRandom_DEFINED
+#define SkRandom_DEFINED
+
+#include "Sk64.h"
+#include "SkScalar.h"
+
+/** \class SkRandom
+
+ Utility class that implements pseudo random 32bit numbers using a fast
+ linear equation. Unlike rand(), this class holds its own seed (initially
+ set to 0), so that multiple instances can be used with no side-effects.
+*/
+class SkRandom {
+public:
+ SkRandom() : fSeed(0) {}
+ SkRandom(uint32_t seed) : fSeed(seed) {}
+
+ /** Return the next pseudo random number as an unsigned 32bit value.
+ */
+ uint32_t nextU() { uint32_t r = fSeed * kMul + kAdd; fSeed = r; return r; }
+
+ /** Return the next pseudo random number as a signed 32bit value.
+ */
+ int32_t nextS() { return (int32_t)this->nextU(); }
+
+ /** Return the next pseudo random number as an unsigned 16bit value.
+ */
+ U16CPU nextU16() { return this->nextU() >> 16; }
+
+ /** Return the next pseudo random number as a signed 16bit value.
+ */
+ S16CPU nextS16() { return this->nextS() >> 16; }
+
+ /**
+ * Returns value [0...1) as a float
+ */
+ float nextF() {
+ // const is 1 / (2^32 - 1)
+ return (float)(this->nextU() * 2.32830644e-10);
+ }
+
+ /**
+ * Returns value [min...max) as a float
+ */
+ float nextRangeF(float min, float max) {
+ return min + this->nextF() * (max - min);
+ }
+
+ /** Return the next pseudo random number, as an unsigned value of
+ at most bitCount bits.
+ @param bitCount The maximum number of bits to be returned
+ */
+ uint32_t nextBits(unsigned bitCount) {
+ SkASSERT(bitCount > 0 && bitCount <= 32);
+ return this->nextU() >> (32 - bitCount);
+ }
+
+ /** Return the next pseudo random unsigned number, mapped to lie within
+ [min, max] inclusive.
+ */
+ uint32_t nextRangeU(uint32_t min, uint32_t max) {
+ SkASSERT(min <= max);
+ uint32_t range = max - min + 1;
+ if (0 == range) {
+ return this->nextU();
+ } else {
+ return min + this->nextU() % range;
+ }
+ }
+
+ /** Return the next pseudo random unsigned number, mapped to lie within
+ [0, count).
+ */
+ uint32_t nextULessThan(uint32_t count) {
+ SkASSERT(count > 0);
+ return this->nextRangeU(0, count - 1);
+ }
+
+ /** Return the next pseudo random number expressed as an unsigned SkFixed
+ in the range [0..SK_Fixed1).
+ */
+ SkFixed nextUFixed1() { return this->nextU() >> 16; }
+
+ /** Return the next pseudo random number expressed as a signed SkFixed
+ in the range (-SK_Fixed1..SK_Fixed1).
+ */
+ SkFixed nextSFixed1() { return this->nextS() >> 15; }
+
+ /** Return the next pseudo random number expressed as a SkScalar
+ in the range [0..SK_Scalar1).
+ */
+ SkScalar nextUScalar1() { return SkFixedToScalar(this->nextUFixed1()); }
+
+ /** Return the next pseudo random number expressed as a SkScalar
+ in the range [min..max).
+ */
+ SkScalar nextRangeScalar(SkScalar min, SkScalar max) {
+ return SkScalarMul(this->nextUScalar1(), (max - min)) + min;
+ }
+
+ /** Return the next pseudo random number expressed as a SkScalar
+ in the range (-SK_Scalar1..SK_Scalar1).
+ */
+ SkScalar nextSScalar1() { return SkFixedToScalar(this->nextSFixed1()); }
+
+ /** Return the next pseudo random number as a bool.
+ */
+ bool nextBool() { return this->nextU() >= 0x80000000; }
+
+ /** A biased version of nextBool().
+ */
+ bool nextBiasedBool(SkScalar fractionTrue) {
+ SkASSERT(fractionTrue >= 0 && fractionTrue <= SK_Scalar1);
+ return this->nextUScalar1() <= fractionTrue;
+ }
+
+ /** Return the next pseudo random number as a signed 64bit value.
+ */
+ void next64(Sk64* a) {
+ SkASSERT(a);
+ a->set(this->nextS(), this->nextU());
+ }
+
+ /**
+ * Return the current seed. This allows the caller to later reset to the
+ * same seed (using setSeed) so it can generate the same sequence.
+ */
+ int32_t getSeed() const { return fSeed; }
+
+ /** Set the seed of the random object. The seed is initialized to 0 when the
+ object is first created, and is updated each time the next pseudo random
+ number is requested.
+ */
+ void setSeed(int32_t seed) { fSeed = (uint32_t)seed; }
+
+private:
+ // See "Numerical Recipes in C", 1992 page 284 for these constants
+ enum {
+ kMul = 1664525,
+ kAdd = 1013904223
+ };
+ uint32_t fSeed;
+};
+
+/** \class SkMWCRandom
+
+ Utility class that implements pseudo random 32bit numbers using Marsaglia's
+ multiply-with-carry "mother of all" algorithm. Unlike rand(), this class holds
+ its own state, so that multiple instances can be used with no side-effects.
+
+ Has a large period and all bits are well-randomized.
+ */
+class SkMWCRandom {
+public:
+ SkMWCRandom() { init(0); }
+ SkMWCRandom(uint32_t seed) { init(seed); }
+ SkMWCRandom(const SkMWCRandom& rand) : fK(rand.fK), fJ(rand.fJ) {}
+
+ SkMWCRandom& operator=(const SkMWCRandom& rand) {
+ fK = rand.fK;
+ fJ = rand.fJ;
+
+ return *this;
+ }
+
+ /** Return the next pseudo random number as an unsigned 32bit value.
+ */
+ uint32_t nextU() {
+ fK = kKMul*(fK & 0xffff) + (fK >> 16);
+ fJ = kJMul*(fJ & 0xffff) + (fJ >> 16);
+ return (((fK << 16) | (fK >> 16)) + fJ);
+ }
+
+ /** Return the next pseudo random number as a signed 32bit value.
+ */
+ int32_t nextS() { return (int32_t)this->nextU(); }
+
+ /** Return the next pseudo random number as an unsigned 16bit value.
+ */
+ U16CPU nextU16() { return this->nextU() >> 16; }
+
+ /** Return the next pseudo random number as a signed 16bit value.
+ */
+ S16CPU nextS16() { return this->nextS() >> 16; }
+
+ /**
+ * Returns value [0...1) as an IEEE float
+ */
+ float nextF() {
+ unsigned int floatint = 0x3f800000 | (this->nextU() >> 9);
+ float f = SkBits2Float(floatint) - 1.0f;
+ return f;
+ }
+
+ /**
+ * Returns value [min...max) as a float
+ */
+ float nextRangeF(float min, float max) {
+ return min + this->nextF() * (max - min);
+ }
+
+ /** Return the next pseudo random number, as an unsigned value of
+ at most bitCount bits.
+ @param bitCount The maximum number of bits to be returned
+ */
+ uint32_t nextBits(unsigned bitCount) {
+ SkASSERT(bitCount > 0 && bitCount <= 32);
+ return this->nextU() >> (32 - bitCount);
+ }
+
+ /** Return the next pseudo random unsigned number, mapped to lie within
+ [min, max] inclusive.
+ */
+ uint32_t nextRangeU(uint32_t min, uint32_t max) {
+ SkASSERT(min <= max);
+ uint32_t range = max - min + 1;
+ if (0 == range) {
+ return this->nextU();
+ } else {
+ return min + this->nextU() % range;
+ }
+ }
+
+ /** Return the next pseudo random unsigned number, mapped to lie within
+ [0, count).
+ */
+ uint32_t nextULessThan(uint32_t count) {
+ SkASSERT(count > 0);
+ return this->nextRangeU(0, count - 1);
+ }
+
+ /** Return the next pseudo random number expressed as an unsigned SkFixed
+ in the range [0..SK_Fixed1).
+ */
+ SkFixed nextUFixed1() { return this->nextU() >> 16; }
+
+ /** Return the next pseudo random number expressed as a signed SkFixed
+ in the range (-SK_Fixed1..SK_Fixed1).
+ */
+ SkFixed nextSFixed1() { return this->nextS() >> 15; }
+
+ /** Return the next pseudo random number expressed as a SkScalar
+ in the range [0..SK_Scalar1).
+ */
+ SkScalar nextUScalar1() { return SkFixedToScalar(this->nextUFixed1()); }
+
+ /** Return the next pseudo random number expressed as a SkScalar
+ in the range [min..max).
+ */
+ SkScalar nextRangeScalar(SkScalar min, SkScalar max) {
+ return SkScalarMul(this->nextUScalar1(), (max - min)) + min;
+ }
+
+ /** Return the next pseudo random number expressed as a SkScalar
+ in the range (-SK_Scalar1..SK_Scalar1).
+ */
+ SkScalar nextSScalar1() { return SkFixedToScalar(this->nextSFixed1()); }
+
+ /** Return the next pseudo random number as a bool.
+ */
+ bool nextBool() { return this->nextU() >= 0x80000000; }
+
+ /** A biased version of nextBool().
+ */
+ bool nextBiasedBool(SkScalar fractionTrue) {
+ SkASSERT(fractionTrue >= 0 && fractionTrue <= SK_Scalar1);
+ return this->nextUScalar1() <= fractionTrue;
+ }
+
+ /** Return the next pseudo random number as a signed 64bit value.
+ */
+ void next64(Sk64* a) {
+ SkASSERT(a);
+ a->set(this->nextS(), this->nextU());
+ }
+
+ /** Reset the random object.
+ */
+ void setSeed(uint32_t seed) { init(seed); }
+
+private:
+ // Initialize state variables with LCG.
+ // We must ensure that both J and K are non-zero, otherwise the
+ // multiply-with-carry step will forevermore return zero.
+ void init(uint32_t seed) {
+ fK = NextLCG(seed);
+ if (0 == fK) {
+ fK = NextLCG(fK);
+ }
+ fJ = NextLCG(fK);
+ if (0 == fJ) {
+ fJ = NextLCG(fJ);
+ }
+ SkASSERT(0 != fK && 0 != fJ);
+ }
+ static uint32_t NextLCG(uint32_t seed) { return kMul*seed + kAdd; }
+
+ // See "Numerical Recipes in C", 1992 page 284 for these constants
+ // For the LCG that sets the initial state from a seed
+ enum {
+ kMul = 1664525,
+ kAdd = 1013904223
+ };
+ // Constants for the multiply-with-carry steps
+ enum {
+ kKMul = 30345,
+ kJMul = 18000,
+ };
+
+ uint32_t fK;
+ uint32_t fJ;
+};
+
+#endif
diff --git a/utils/SkRunnable.h b/utils/SkRunnable.h
new file mode 100644
index 0000000..84e4375
--- /dev/null
+++ b/utils/SkRunnable.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkRunnable_DEFINED
+#define SkRunnable_DEFINED
+
+class SkRunnable {
+public:
+ virtual ~SkRunnable() {};
+ virtual void run() = 0;
+};
+
+#endif
diff --git a/utils/SkThreadPool.h b/utils/SkThreadPool.h
new file mode 100644
index 0000000..3c86158
--- /dev/null
+++ b/utils/SkThreadPool.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkThreadPool_DEFINED
+#define SkThreadPool_DEFINED
+
+#include "SkCondVar.h"
+#include "SkTDArray.h"
+#include "SkTInternalLList.h"
+
+class SkRunnable;
+class SkThread;
+
+class SkThreadPool {
+
+public:
+ /**
+ * Create a threadpool with count threads, or one thread per core if kThreadPerCore.
+ */
+ static const int kThreadPerCore = -1;
+ explicit SkThreadPool(int count);
+ ~SkThreadPool();
+
+ /**
+ * Queues up an SkRunnable to run when a thread is available, or immediately if
+ * count is 0. NULL is a safe no-op. Does not take ownership.
+ */
+ void add(SkRunnable*);
+
+ private:
+ struct LinkedRunnable {
+ // Unowned pointer.
+ SkRunnable* fRunnable;
+
+ private:
+ SK_DECLARE_INTERNAL_LLIST_INTERFACE(LinkedRunnable);
+ };
+
+ SkTInternalLList<LinkedRunnable> fQueue;
+ SkCondVar fReady;
+ SkTDArray<SkThread*> fThreads;
+ bool fDone;
+
+ static void Loop(void*); // Static because we pass in this.
+};
+
+#endif
diff --git a/utils/SkUnitMappers.h b/utils/SkUnitMappers.h
new file mode 100644
index 0000000..64aab5d
--- /dev/null
+++ b/utils/SkUnitMappers.h
@@ -0,0 +1,55 @@
+
+/*
+ * Copyright 2008 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkUnitMappers_DEFINED
+#define SkUnitMappers_DEFINED
+
+#include "SkUnitMapper.h"
+
+/** This discretizes the range [0...1) into N discret values.
+*/
+class SkDiscreteMapper : public SkUnitMapper {
+public:
+ SkDiscreteMapper(int segments);
+ // override from SkUnitMapper
+ virtual uint16_t mapUnit16(uint16_t x);
+
+ SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDiscreteMapper)
+
+protected:
+ SkDiscreteMapper(SkFlattenableReadBuffer& );
+ virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
+
+private:
+ int fSegments;
+ SkFract fScale; // computed from fSegments
+
+ typedef SkUnitMapper INHERITED;
+};
+
+/** This returns cos(x), to simulate lighting a sphere, where 0 maps to the
+ center of the sphere, and 1 maps to the edge.
+*/
+class SkCosineMapper : public SkUnitMapper {
+public:
+ SkCosineMapper() {}
+ // override from SkUnitMapper
+ virtual uint16_t mapUnit16(uint16_t x);
+
+ SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkCosineMapper)
+
+protected:
+ SkCosineMapper(SkFlattenableReadBuffer&);
+
+private:
+
+ typedef SkUnitMapper INHERITED;
+};
+
+#endif
diff --git a/utils/SkWGL.h b/utils/SkWGL.h
new file mode 100644
index 0000000..3d94174
--- /dev/null
+++ b/utils/SkWGL.h
@@ -0,0 +1,117 @@
+
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkRefCnt.h"
+
+#ifndef SkWGL_DEFINED
+#define SkWGL_DEFINED
+
+/**
+ * Working with WGL extensions can be a pain. Among the reasons is that You must
+ * have a GL context to get the proc addresses, but you want to use the procs to
+ * create a context in the first place. So you have to create a dummy GL ctx to
+ * get the proc addresses.
+ *
+ * This file helps by providing SkCreateWGLInterface(). It returns a struct of
+ * function pointers that it initializes. It also has a helper function to query
+ * for WGL extensions. It handles the fact that wglGetExtensionsString is itself
+ * an extension.
+ */
+
+#if !defined(WIN32_LEAN_AND_MEAN)
+ #define WIN32_LEAN_AND_MEAN
+ #define SK_LOCAL_LEAN_AND_MEAN
+#endif
+#include <Windows.h>
+#if defined(SK_LOCAL_LEAN_AND_MEAN)
+ #undef WIN32_LEAN_AND_MEAN
+ #undef SK_LOCAL_LEAN_AND_MEAN
+#endif
+
+#define SK_WGL_DRAW_TO_WINDOW 0x2001
+#define SK_WGL_ACCELERATION 0x2003
+#define SK_WGL_SUPPORT_OPENGL 0x2010
+#define SK_WGL_DOUBLE_BUFFER 0x2011
+#define SK_WGL_COLOR_BITS 0x2014
+#define SK_WGL_ALPHA_BITS 0x201B
+#define SK_WGL_STENCIL_BITS 0x2023
+#define SK_WGL_FULL_ACCELERATION 0x2027
+#define SK_WGL_SAMPLE_BUFFERS 0x2041
+#define SK_WGL_SAMPLES 0x2042
+#define SK_WGL_COVERAGE_SAMPLES 0x2042 /* same as SAMPLES */
+#define SK_WGL_COLOR_SAMPLES 0x20B9
+#define SK_WGL_CONTEXT_MAJOR_VERSION 0x2091
+#define SK_WGL_CONTEXT_MINOR_VERSION 0x2092
+#define SK_WGL_CONTEXT_LAYER_PLANE 0x2093
+#define SK_WGL_CONTEXT_FLAGS 0x2094
+#define SK_WGL_CONTEXT_PROFILE_MASK 0x9126
+#define SK_WGL_CONTEXT_DEBUG_BIT 0x0001
+#define SK_WGL_CONTEXT_FORWARD_COMPATIBLE_BIT 0x0002
+#define SK_WGL_CONTEXT_CORE_PROFILE_BIT 0x00000001
+#define SK_WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT 0x00000002
+#define SK_WGL_CONTEXT_ES2_PROFILE_BIT 0x00000004
+#define SK_ERROR_INVALID_VERSION 0x2095
+#define SK_ERROR_INVALID_PROFILE 0x2096
+
+class SkWGLExtensions {
+public:
+ SkWGLExtensions();
+ /**
+ * Determines if an extensions is available for a given DC.
+ * WGL_extensions_string is considered a prerequisite for all other
+ * extensions. It is necessary to check this before calling other class
+ * functions.
+ */
+ bool hasExtension(HDC dc, const char* ext) const;
+
+ const char* getExtensionsString(HDC hdc) const;
+ BOOL choosePixelFormat(HDC hdc, const int*, const FLOAT*, UINT, int*, UINT*) const;
+ BOOL getPixelFormatAttribiv(HDC, int, int, UINT, const int*, int*) const;
+ BOOL getPixelFormatAttribfv(HDC hdc, int, int, UINT, const int*, FLOAT*) const;
+ HGLRC createContextAttribs(HDC, HGLRC, const int *) const;
+
+ /**
+ * WGL doesn't have precise rules for the ordering of formats returned
+ * by wglChoosePixelFormat. This function helps choose among the set of
+ * formats returned by wglChoosePixelFormat. The rules in decreasing
+ * priority are:
+ * * Choose formats with the smallest sample count that is >=
+ * desiredSampleCount (or the largest sample count if all formats have
+ * fewer samples than desiredSampleCount.)
+ * * Choose formats with the fewest color samples when coverage sampling
+ * is available.
+ * * If the above rules leave multiple formats, choose the one that
+ * appears first in the formats array parameter.
+ */
+ int selectFormat(const int formats[],
+ int formatCount,
+ HDC dc,
+ int desiredSampleCount);
+private:
+ typedef const char* (WINAPI *GetExtensionsStringProc)(HDC hdc);
+ typedef BOOL (WINAPI *ChoosePixelFormatProc)(HDC hdc, const int *, const FLOAT *, UINT, int *, UINT *);
+ typedef BOOL (WINAPI *GetPixelFormatAttribivProc)(HDC, int, int, UINT, const int*, int*);
+ typedef BOOL (WINAPI *GetPixelFormatAttribfvProc)(HDC hdc, int, int, UINT, const int*, FLOAT*);
+ typedef HGLRC (WINAPI *CreateContextAttribsProc)(HDC hDC, HGLRC, const int *);
+
+ GetExtensionsStringProc fGetExtensionsString;
+ ChoosePixelFormatProc fChoosePixelFormat;
+ GetPixelFormatAttribfvProc fGetPixelFormatAttribfv;
+ GetPixelFormatAttribivProc fGetPixelFormatAttribiv;
+ CreateContextAttribsProc fCreateContextAttribs;
+};
+
+/**
+ * Helper to create an OpenGL context for a DC using WGL. Configs with a sample count >= to
+ * msaaSampleCount are preferred but if none is available then a context with a lower sample count
+ * (including non-MSAA) will be created. If preferCoreProfile is true but a core profile cannot be
+ * created then a compatible profile context will be created.
+ */
+HGLRC SkCreateWGLContext(HDC dc, int msaaSampleCount, bool preferCoreProfile);
+
+#endif
diff --git a/utils/ios/SkStream_NSData.h b/utils/ios/SkStream_NSData.h
new file mode 100755
index 0000000..8e6f064
--- /dev/null
+++ b/utils/ios/SkStream_NSData.h
@@ -0,0 +1,41 @@
+
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#ifndef SkStream_NSData_DEFINED
+#define SkStream_NSData_DEFINED
+
+#import <UIKit/UIKit.h>
+#include "SkStream.h"
+
+/** Returns an NSData with a copy of the stream's data. The caller must call
+ retain if it intends to keep the data object beyond the current stack-frame
+ (i.e. internally we're calling [NSData dataWithBytes...]
+ */
+NSData* NSData_dataWithStream(SkStream* stream);
+
+/** Returns an NSData from the named resource (from main bundle).
+ The caller must call retain if it intends to keep the data object beyond
+ the current stack-frame
+ (i.e. internally we're calling [NSData dataWithContentsOfMappedFile...]
+ */
+NSData* NSData_dataFromResource(const char name[], const char suffix[]);
+
+/** Wrap a stream around NSData.
+ */
+class SkStream_NSData : public SkMemoryStream {
+public:
+ SkStream_NSData(NSData* data);
+ virtual ~SkStream_NSData();
+
+ static SkStream_NSData* CreateFromResource(const char name[],
+ const char suffix[]);
+
+private:
+ NSData* fNSData;
+};
+
+#endif
diff --git a/utils/mac/SkCGUtils.h b/utils/mac/SkCGUtils.h
new file mode 100644
index 0000000..54c858c
--- /dev/null
+++ b/utils/mac/SkCGUtils.h
@@ -0,0 +1,67 @@
+
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#ifndef SkCGUtils_DEFINED
+#define SkCGUtils_DEFINED
+
+#include "SkTypes.h"
+
+#ifdef SK_BUILD_FOR_MAC
+#include <ApplicationServices/ApplicationServices.h>
+#endif
+
+#ifdef SK_BUILD_FOR_IOS
+#include <CoreGraphics/CoreGraphics.h>
+#endif
+
+class SkBitmap;
+class SkData;
+class SkStream;
+
+/**
+ * Create an imageref from the specified bitmap using the specified colorspace.
+ * If space is NULL, then CGColorSpaceCreateDeviceRGB() is used.
+ */
+SK_API CGImageRef SkCreateCGImageRefWithColorspace(const SkBitmap& bm,
+ CGColorSpaceRef space);
+
+/**
+ * Create an imageref from the specified bitmap using the colorspace returned
+ * by CGColorSpaceCreateDeviceRGB()
+ */
+static inline CGImageRef SkCreateCGImageRef(const SkBitmap& bm) {
+ return SkCreateCGImageRefWithColorspace(bm, NULL);
+}
+
+/**
+ * Draw the bitmap into the specified CG context. The bitmap will be converted
+ * to a CGImage using the generic RGB colorspace. (x,y) specifies the position
+ * of the top-left corner of the bitmap. The bitmap is converted using the
+ * colorspace returned by CGColorSpaceCreateDeviceRGB()
+ */
+void SkCGDrawBitmap(CGContextRef, const SkBitmap&, float x, float y);
+
+bool SkPDFDocumentToBitmap(SkStream* stream, SkBitmap* output);
+
+/**
+ * Return a provider that wraps the specified stream. It will become an
+ * owner of the stream, so the caller must still manage its ownership.
+ *
+ * To hand-off ownership of the stream to the provider, the caller must do
+ * something like the following:
+ *
+ * SkStream* stream = new ...;
+ * CGDataProviderRef provider = SkStreamToDataProvider(stream);
+ * stream->unref();
+ *
+ * Now when the provider is finally deleted, it will delete the stream.
+ */
+CGDataProviderRef SkCreateDataProviderFromStream(SkStream*);
+
+CGDataProviderRef SkCreateDataProviderFromData(SkData*);
+
+#endif
diff --git a/utils/win/SkAutoCoInitialize.h b/utils/win/SkAutoCoInitialize.h
new file mode 100644
index 0000000..709fa6b
--- /dev/null
+++ b/utils/win/SkAutoCoInitialize.h
@@ -0,0 +1,30 @@
+
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkAutoCo_DEFINED
+#define SkAutoCo_DEFINED
+
+#define WIN32_LEAN_AND_MEAN
+#include <Windows.h>
+#include "SkTemplates.h"
+
+/**
+ * An instance of this class initializes COM on creation
+ * and closes the COM library on destruction.
+ */
+class SkAutoCoInitialize : SkNoncopyable {
+private:
+ HRESULT fHR;
+public:
+ SkAutoCoInitialize();
+ ~SkAutoCoInitialize();
+ bool succeeded();
+};
+
+#endif
diff --git a/utils/win/SkHRESULT.h b/utils/win/SkHRESULT.h
new file mode 100644
index 0000000..9738f74
--- /dev/null
+++ b/utils/win/SkHRESULT.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkHRESULT_DEFINED
+#define SkHRESULT_DEFINED
+
+#include "SkTypes.h"
+
+void SkTraceHR(const char* file, unsigned long line,
+ HRESULT hr, const char* msg);
+
+#ifdef SK_DEBUG
+#define SK_TRACEHR(_hr, _msg) SkTraceHR(__FILE__, __LINE__, _hr, _msg)
+#else
+#define SK_TRACEHR(_hr, _msg) _hr
+#endif
+
+#define HR_GENERAL(_ex, _msg, _ret) {\
+ HRESULT _hr = _ex;\
+ if (FAILED(_hr)) {\
+ SK_TRACEHR(_hr, _msg);\
+ return _ret;\
+ }\
+}
+
+//@{
+/**
+These macros are for reporting HRESULT errors.
+The expression will be evaluated.
+If the resulting HRESULT SUCCEEDED then execution will continue normally.
+If the HRESULT FAILED then the macro will return from the current function.
+In variants ending with 'M' the given message will be traced when FAILED.
+The HR variants will return the HRESULT when FAILED.
+The HRB variants will return false when FAILED.
+The HRN variants will return NULL when FAILED.
+The HRV variants will simply return when FAILED.
+*/
+#define HR(ex) HR_GENERAL(ex, NULL, _hr)
+#define HRM(ex, msg) HR_GENERAL(ex, msg, _hr)
+
+#define HRB(ex) HR_GENERAL(ex, NULL, false)
+#define HRBM(ex, msg) HR_GENERAL(ex, msg, false)
+
+#define HRN(ex) HR_GENERAL(ex, NULL, NULL)
+#define HRNM(ex, msg) HR_GENERAL(ex, msg, NULL)
+
+#define HRV(ex) HR_GENERAL(ex, NULL, )
+#define HRVM(ex, msg) HR_GENERAL(ex, msg, )
+//@}
+#endif
diff --git a/utils/win/SkIStream.h b/utils/win/SkIStream.h
new file mode 100644
index 0000000..e4e045c
--- /dev/null
+++ b/utils/win/SkIStream.h
@@ -0,0 +1,131 @@
+
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkIStream_DEFINED
+#define SkIStream_DEFINED
+
+#define WIN32_LEAN_AND_MEAN
+#include <Windows.h>
+#include <ole2.h>
+
+class SkStream;
+class SkWStream;
+
+/**
+ * A bare IStream implementation which properly reference counts
+ * but returns E_NOTIMPL for all ISequentialStream and IStream methods.
+ */
+class SkBaseIStream : public IStream {
+private:
+ LONG _refcount;
+
+protected:
+ explicit SkBaseIStream();
+ virtual ~SkBaseIStream();
+
+public:
+ virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid
+ , void ** ppvObject);
+ virtual ULONG STDMETHODCALLTYPE AddRef(void);
+ virtual ULONG STDMETHODCALLTYPE Release(void);
+
+ // ISequentialStream Interface
+public:
+ virtual HRESULT STDMETHODCALLTYPE Read(void* pv, ULONG cb, ULONG* pcbRead);
+
+ virtual HRESULT STDMETHODCALLTYPE Write(void const* pv
+ , ULONG cb
+ , ULONG* pcbWritten);
+
+ // IStream Interface
+public:
+ virtual HRESULT STDMETHODCALLTYPE SetSize(ULARGE_INTEGER);
+
+ virtual HRESULT STDMETHODCALLTYPE CopyTo(IStream*
+ , ULARGE_INTEGER
+ , ULARGE_INTEGER*
+ , ULARGE_INTEGER*);
+
+ virtual HRESULT STDMETHODCALLTYPE Commit(DWORD);
+
+ virtual HRESULT STDMETHODCALLTYPE Revert(void);
+
+ virtual HRESULT STDMETHODCALLTYPE LockRegion(ULARGE_INTEGER
+ , ULARGE_INTEGER
+ , DWORD);
+
+ virtual HRESULT STDMETHODCALLTYPE UnlockRegion(ULARGE_INTEGER
+ , ULARGE_INTEGER
+ , DWORD);
+
+ virtual HRESULT STDMETHODCALLTYPE Clone(IStream **);
+
+ virtual HRESULT STDMETHODCALLTYPE Seek(LARGE_INTEGER liDistanceToMove
+ , DWORD dwOrigin
+ , ULARGE_INTEGER* lpNewFilePointer);
+
+ virtual HRESULT STDMETHODCALLTYPE Stat(STATSTG* pStatstg
+ , DWORD grfStatFlag);
+};
+
+/**
+ * A minimal read-only IStream implementation which wraps an SkIStream.
+ */
+class SkIStream : public SkBaseIStream {
+private:
+ SkStream *fSkStream;
+ bool fUnrefOnRelease;
+ ULARGE_INTEGER fLocation;
+
+ SkIStream(SkStream* stream, bool unrefOnRelease);
+ virtual ~SkIStream();
+
+public:
+ HRESULT static CreateFromSkStream(SkStream* stream
+ , bool unrefOnRelease
+ , IStream ** ppStream);
+
+ virtual HRESULT STDMETHODCALLTYPE Read(void* pv, ULONG cb, ULONG* pcbRead);
+
+ virtual HRESULT STDMETHODCALLTYPE Write(void const* pv
+ , ULONG cb
+ , ULONG* pcbWritten);
+
+ virtual HRESULT STDMETHODCALLTYPE Seek(LARGE_INTEGER liDistanceToMove
+ , DWORD dwOrigin
+ , ULARGE_INTEGER* lpNewFilePointer);
+
+ virtual HRESULT STDMETHODCALLTYPE Stat(STATSTG* pStatstg
+ , DWORD grfStatFlag);
+};
+
+/**
+ * A minimal write-only IStream implementation which wraps an SkWIStream.
+ */
+class SkWIStream : public SkBaseIStream {
+private:
+ SkWStream *fSkWStream;
+
+ SkWIStream(SkWStream* stream);
+ virtual ~SkWIStream();
+
+public:
+ HRESULT static CreateFromSkWStream(SkWStream* stream, IStream ** ppStream);
+
+ virtual HRESULT STDMETHODCALLTYPE Write(void const* pv
+ , ULONG cb
+ , ULONG* pcbWritten);
+
+ virtual HRESULT STDMETHODCALLTYPE Commit(DWORD);
+
+ virtual HRESULT STDMETHODCALLTYPE Stat(STATSTG* pStatstg
+ , DWORD grfStatFlag);
+};
+
+#endif
diff --git a/utils/win/SkTScopedComPtr.h b/utils/win/SkTScopedComPtr.h
new file mode 100644
index 0000000..8f3c22a
--- /dev/null
+++ b/utils/win/SkTScopedComPtr.h
@@ -0,0 +1,76 @@
+
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkSkTScopedPtr_DEFINED
+#define SkSkTScopedPtr_DEFINED
+
+#include "SkTypes.h"
+#include "SkTemplates.h"
+
+template<typename T>
+class SkBlockComRef : public T {
+private:
+ virtual ULONG STDMETHODCALLTYPE AddRef(void) = 0;
+ virtual ULONG STDMETHODCALLTYPE Release(void) = 0;
+};
+
+template<typename T> T* SkRefComPtr(T* ptr) {
+ ptr->AddRef();
+ return ptr;
+}
+
+template<typename T> T* SkSafeRefComPtr(T* ptr) {
+ if (ptr) {
+ ptr->AddRef();
+ }
+ return ptr;
+}
+
+template<typename T>
+class SkTScopedComPtr : SkNoncopyable {
+private:
+ T *fPtr;
+
+public:
+ explicit SkTScopedComPtr(T *ptr = NULL) : fPtr(ptr) { }
+ ~SkTScopedComPtr() {
+ this->reset();
+ }
+ T &operator*() const { SkASSERT(fPtr != NULL); return *fPtr; }
+ SkBlockComRef<T> *operator->() const {
+ return static_cast<SkBlockComRef<T>*>(fPtr);
+ }
+ /**
+ * Returns the address of the underlying pointer.
+ * This is dangerous -- it breaks encapsulation and the reference escapes.
+ * Must only be used on instances currently pointing to NULL,
+ * and only to initialize the instance.
+ */
+ T **operator&() { SkASSERT(fPtr == NULL); return &fPtr; }
+ T *get() const { return fPtr; }
+ void reset() {
+ if (NULL != this->fPtr) {
+ this->fPtr->Release();
+ this->fPtr = NULL;
+ }
+ }
+
+ void swap(SkTScopedComPtr<T>& that) {
+ T* temp = this->fPtr;
+ this->fPtr = that.fPtr;
+ that.fPtr = temp;
+ }
+
+ T* release() {
+ T* temp = this->fPtr;
+ this->fPtr = NULL;
+ return temp;
+ }
+};
+
+#endif
diff --git a/views/SkApplication.h b/views/SkApplication.h
new file mode 100644
index 0000000..8369f68
--- /dev/null
+++ b/views/SkApplication.h
@@ -0,0 +1,19 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkApplication_DEFINED
+#define SkApplication_DEFINED
+
+class SkOSWindow;
+
+extern SkOSWindow* create_sk_window(void* hwnd, int argc, char** argv);
+extern void application_init();
+extern void application_term();
+
+#endif // SkApplication_DEFINED
diff --git a/views/SkBGViewArtist.h b/views/SkBGViewArtist.h
new file mode 100644
index 0000000..33054c8
--- /dev/null
+++ b/views/SkBGViewArtist.h
@@ -0,0 +1,33 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkBGViewArtist_DEFINED
+#define SkBGViewArtist_DEFINED
+
+#include "SkView.h"
+#include "SkPaint.h"
+
+class SkBGViewArtist : public SkView::Artist {
+public:
+ SkBGViewArtist(SkColor c = SK_ColorWHITE);
+ virtual ~SkBGViewArtist();
+
+ const SkPaint& paint() const { return fPaint; }
+ SkPaint& paint() { return fPaint; }
+
+protected:
+ // overrides
+ virtual void onDraw(SkView*, SkCanvas*);
+ virtual void onInflate(const SkDOM&, const SkDOM::Node*);
+
+private:
+ SkPaint fPaint;
+};
+
+#endif
diff --git a/views/SkEvent.h b/views/SkEvent.h
new file mode 100644
index 0000000..f4df448
--- /dev/null
+++ b/views/SkEvent.h
@@ -0,0 +1,284 @@
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkEvent_DEFINED
+#define SkEvent_DEFINED
+
+#include "SkDOM.h"
+#include "SkMetaData.h"
+#include "SkString.h"
+
+/** Unique 32bit id used to identify an instance of SkEventSink. When events are
+ posted, they are posted to a specific sinkID. When it is time to dispatch the
+ event, the sinkID is used to find the specific SkEventSink object. If it is found,
+ its doEvent() method is called with the event.
+*/
+typedef uint32_t SkEventSinkID;
+
+/**
+ * \class SkEvent
+ *
+ * When an event is dispatched from the event queue, it is either sent to
+ * the eventsink matching the target ID (if not 0), or the target proc is
+ * called (if not NULL).
+ */
+class SkEvent {
+public:
+ /**
+ * Function pointer that takes an event, returns true if it "handled" it.
+ */
+ typedef bool (*Proc)(const SkEvent& evt);
+
+ SkEvent();
+ explicit SkEvent(const SkString& type, SkEventSinkID = 0);
+ explicit SkEvent(const char type[], SkEventSinkID = 0);
+ SkEvent(const SkEvent& src);
+ ~SkEvent();
+
+ /** Copy the event's type into the specified SkString parameter */
+ void getType(SkString* str) const;
+
+ /** Returns true if the event's type matches exactly the specified type (case sensitive) */
+ bool isType(const SkString& str) const;
+
+ /** Returns true if the event's type matches exactly the specified type (case sensitive) */
+ bool isType(const char type[], size_t len = 0) const;
+
+ /**
+ * Set the event's type to the specified string.
+ */
+ void setType(const SkString&);
+
+ /**
+ * Set the event's type to the specified string.
+ */
+ void setType(const char type[], size_t len = 0);
+
+ /**
+ * Return the target ID, or 0 if there is none.
+ *
+ * When an event is dispatched from the event queue, it is either sent to
+ * the eventsink matching the targetID (if not 0), or the target proc is
+ * called (if not NULL).
+ */
+ SkEventSinkID getTargetID() const { return fTargetID; }
+
+ /**
+ * Set the target ID for this event. 0 means none. Calling this will
+ * automatically clear the targetProc to null.
+ *
+ * When an event is dispatched from the event queue, it is either sent to
+ * the eventsink matching the targetID (if not 0), or the target proc is
+ * called (if not NULL).
+ */
+ SkEvent* setTargetID(SkEventSinkID targetID) {
+ fTargetProc = NULL;
+ fTargetID = targetID;
+ return this;
+ }
+
+ /**
+ * Return the target proc, or NULL if it has none.
+ *
+ * When an event is dispatched from the event queue, it is either sent to
+ * the eventsink matching the targetID (if not 0), or the target proc is
+ * called (if not NULL).
+ */
+ Proc getTargetProc() const { return fTargetProc; }
+
+ /**
+ * Set the target ID for this event. NULL means none. Calling this will
+ * automatically clear the targetID to 0.
+ *
+ * When an event is dispatched from the event queue, it is either sent to
+ * the eventsink matching the targetID (if not 0), or the target proc is
+ * called (if not NULL).
+ */
+ SkEvent* setTargetProc(Proc proc) {
+ fTargetID = 0;
+ fTargetProc = proc;
+ return this;
+ }
+
+ /**
+ * Return the event's unnamed 32bit field. Default value is 0
+ */
+ uint32_t getFast32() const { return f32; }
+
+ /**
+ * Set the event's unnamed 32bit field.
+ */
+ void setFast32(uint32_t x) { f32 = x; }
+
+ /** Return true if the event contains the named 32bit field, and return the field
+ in value (if value is non-null). If there is no matching named field, return false
+ and ignore the value parameter.
+ */
+ bool findS32(const char name[], int32_t* value = NULL) const { return fMeta.findS32(name, value); }
+ /** Return true if the event contains the named SkScalar field, and return the field
+ in value (if value is non-null). If there is no matching named field, return false
+ and ignore the value parameter.
+ */
+ bool findScalar(const char name[], SkScalar* value = NULL) const { return fMeta.findScalar(name, value); }
+ /** Return true if the event contains the named SkScalar field, and return the fields
+ in value[] (if value is non-null), and return the number of SkScalars in count (if count is non-null).
+ If there is no matching named field, return false and ignore the value and count parameters.
+ */
+ const SkScalar* findScalars(const char name[], int* count, SkScalar values[] = NULL) const { return fMeta.findScalars(name, count, values); }
+ /** Return the value of the named string field, or if no matching named field exists, return null.
+ */
+ const char* findString(const char name[]) const { return fMeta.findString(name); }
+ /** Return true if the event contains the named pointer field, and return the field
+ in value (if value is non-null). If there is no matching named field, return false
+ and ignore the value parameter.
+ */
+ bool findPtr(const char name[], void** value) const { return fMeta.findPtr(name, value); }
+ bool findBool(const char name[], bool* value) const { return fMeta.findBool(name, value); }
+ const void* findData(const char name[], size_t* byteCount = NULL) const {
+ return fMeta.findData(name, byteCount);
+ }
+
+ /** Returns true if ethe event contains the named 32bit field, and if it equals the specified value */
+ bool hasS32(const char name[], int32_t value) const { return fMeta.hasS32(name, value); }
+ /** Returns true if ethe event contains the named SkScalar field, and if it equals the specified value */
+ bool hasScalar(const char name[], SkScalar value) const { return fMeta.hasScalar(name, value); }
+ /** Returns true if ethe event contains the named string field, and if it equals (using strcmp) the specified value */
+ bool hasString(const char name[], const char value[]) const { return fMeta.hasString(name, value); }
+ /** Returns true if ethe event contains the named pointer field, and if it equals the specified value */
+ bool hasPtr(const char name[], void* value) const { return fMeta.hasPtr(name, value); }
+ bool hasBool(const char name[], bool value) const { return fMeta.hasBool(name, value); }
+ bool hasData(const char name[], const void* data, size_t byteCount) const {
+ return fMeta.hasData(name, data, byteCount);
+ }
+
+ /** Add/replace the named 32bit field to the event. In XML use the subelement <data name=... s32=... /> */
+ void setS32(const char name[], int32_t value) { fMeta.setS32(name, value); }
+ /** Add/replace the named SkScalar field to the event. In XML use the subelement <data name=... scalar=... /> */
+ void setScalar(const char name[], SkScalar value) { fMeta.setScalar(name, value); }
+ /** Add/replace the named SkScalar[] field to the event. */
+ SkScalar* setScalars(const char name[], int count, const SkScalar values[] = NULL) { return fMeta.setScalars(name, count, values); }
+ /** Add/replace the named string field to the event. In XML use the subelement <data name=... string=... */
+ void setString(const char name[], const SkString& value) { fMeta.setString(name, value.c_str()); }
+ /** Add/replace the named string field to the event. In XML use the subelement <data name=... string=... */
+ void setString(const char name[], const char value[]) { fMeta.setString(name, value); }
+ /** Add/replace the named pointer field to the event. There is no XML equivalent for this call */
+ void setPtr(const char name[], void* value) { fMeta.setPtr(name, value); }
+ void setBool(const char name[], bool value) { fMeta.setBool(name, value); }
+ void setData(const char name[], const void* data, size_t byteCount) {
+ fMeta.setData(name, data, byteCount);
+ }
+
+ /** Return the underlying metadata object */
+ SkMetaData& getMetaData() { return fMeta; }
+ /** Return the underlying metadata object */
+ const SkMetaData& getMetaData() const { return fMeta; }
+
+ /** Call this to initialize the event from the specified XML node */
+ void inflate(const SkDOM&, const SkDOM::Node*);
+
+ SkDEBUGCODE(void dump(const char title[] = NULL);)
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ /**
+ * Post to the event queue using the event's targetID or target-proc.
+ *
+ * The event must be dynamically allocated, as ownership is transferred to
+ * the event queue. It cannot be allocated on the stack or in a global.
+ */
+ void post() {
+ return this->postDelay(0);
+ }
+
+ /**
+ * Post to the event queue using the event's targetID or target-proc and
+ * the specifed millisecond delay.
+ *
+ * The event must be dynamically allocated, as ownership is transferred to
+ * the event queue. It cannot be allocated on the stack or in a global.
+ */
+ void postDelay(SkMSec delay);
+
+ /**
+ * Post to the event queue using the event's targetID or target-proc.
+ * The event will be delivered no sooner than the specified millisecond
+ * time, as measured by SkTime::GetMSecs().
+ *
+ * The event must be dynamically allocated, as ownership is transferred to
+ * the event queue. It cannot be allocated on the stack or in a global.
+ */
+ void postTime(SkMSec time);
+
+ ///////////////////////////////////////////////
+ /** Porting layer must call these functions **/
+ ///////////////////////////////////////////////
+
+ /** Global initialization function for the SkEvent system. Should be called exactly
+ once before any other event method is called, and should be called after the
+ call to SkGraphics::Init().
+ */
+ static void Init();
+ /** Global cleanup function for the SkEvent system. Should be called exactly once after
+ all event methods have been called, and should be called before calling SkGraphics::Term().
+ */
+ static void Term();
+
+ /** Call this to process one event from the queue. If it returns true, there are more events
+ to process.
+ */
+ static bool ProcessEvent();
+ /** Call this whenever the requested timer has expired (requested by a call to SetQueueTimer).
+ It will post any delayed events whose time as "expired" onto the event queue.
+ It may also call SignalQueueTimer() and SignalNonEmptyQueue().
+ */
+ static void ServiceQueueTimer();
+
+ /** Return the number of queued events. note that this value may be obsolete
+ upon return, since another thread may have called ProcessEvent() or
+ Post() after the count was made.
+ */
+ static int CountEventsOnQueue();
+
+ ////////////////////////////////////////////////////
+ /** Porting layer must implement these functions **/
+ ////////////////////////////////////////////////////
+
+ /** Called whenever an SkEvent is posted to an empty queue, so that the OS
+ can be told to later call Dequeue().
+ */
+ static void SignalNonEmptyQueue();
+ /** Called whenever the delay until the next delayed event changes. If zero is
+ passed, then there are no more queued delay events.
+ */
+ static void SignalQueueTimer(SkMSec delay);
+
+#if defined(SK_BUILD_FOR_WIN)
+ static bool WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
+#endif
+
+private:
+ SkMetaData fMeta;
+ mutable char* fType; // may be characters with low bit set to know that it is not a pointer
+ uint32_t f32;
+
+ // 'there can be only one' (non-zero) between target-id and target-proc
+ SkEventSinkID fTargetID;
+ Proc fTargetProc;
+
+ // these are for our implementation of the event queue
+ SkMSec fTime;
+ SkEvent* fNextEvent; // either in the delay or normal event queue
+
+ void initialize(const char* type, size_t typeLen, SkEventSinkID);
+
+ static bool Enqueue(SkEvent* evt);
+ static SkMSec EnqueueTime(SkEvent* evt, SkMSec time);
+ static SkEvent* Dequeue();
+ static bool QHasEvents();
+};
+
+#endif
diff --git a/views/SkEventSink.h b/views/SkEventSink.h
new file mode 100644
index 0000000..01d4f7a
--- /dev/null
+++ b/views/SkEventSink.h
@@ -0,0 +1,112 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkEventSink_DEFINED
+#define SkEventSink_DEFINED
+
+#include "SkRefCnt.h"
+#include "SkEvent.h"
+
+struct SkTagList;
+
+/** \class SkEventSink
+
+ SkEventSink is the base class for all objects that receive SkEvents.
+*/
+class SkEventSink : public SkRefCnt {
+public:
+ SK_DECLARE_INST_COUNT(SkEventSink)
+
+ SkEventSink();
+ virtual ~SkEventSink();
+
+ /**
+ * Returns this eventsink's unique ID. Use this to post SkEvents to
+ * this eventsink.
+ */
+ SkEventSinkID getSinkID() const { return fID; }
+
+ /**
+ * Call this to pass an event to this object for processing. Returns true if the
+ * event was handled.
+ */
+ bool doEvent(const SkEvent&);
+
+ /** Returns true if the sink (or one of its subclasses) understands the event as a query.
+ If so, the sink may modify the event to communicate its "answer".
+ */
+ bool doQuery(SkEvent* query);
+
+ /**
+ * Add sinkID to the list of listeners, to receive events from calls to sendToListeners()
+ * and postToListeners(). If sinkID already exists in the listener list, no change is made.
+ */
+ void addListenerID(SkEventSinkID sinkID);
+
+ /**
+ * Copy listeners from one event sink to another, typically from parent to child.
+ * @param from the event sink to copy the listeners from
+ */
+ void copyListeners(const SkEventSink& from);
+
+ /**
+ * Remove sinkID from the list of listeners. If sinkID does not appear in the list,
+ * no change is made.
+ */
+ void removeListenerID(SkEventSinkID);
+
+ /**
+ * Returns true if there are 1 or more listeners attached to this eventsink
+ */
+ bool hasListeners() const;
+
+ /**
+ * Posts a copy of evt to each of the eventsinks in the lisener list.
+ * This ignores the targetID and target proc in evt.
+ */
+ void postToListeners(const SkEvent& evt, SkMSec delay = 0);
+
+ enum EventResult {
+ kHandled_EventResult, //!< the eventsink returned true from its doEvent method
+ kNotHandled_EventResult, //!< the eventsink returned false from its doEvent method
+ kSinkNotFound_EventResult //!< no matching eventsink was found for the event's getSink().
+ };
+
+ /**
+ * DoEvent handles dispatching the event to its target ID or proc.
+ */
+ static EventResult DoEvent(const SkEvent&);
+
+ /**
+ * Returns the matching eventsink, or null if not found
+ */
+ static SkEventSink* FindSink(SkEventSinkID);
+
+protected:
+ /** Override this to handle events in your subclass. Be sure to call the inherited version
+ for events that you don't handle.
+ */
+ virtual bool onEvent(const SkEvent&);
+ virtual bool onQuery(SkEvent*);
+
+ SkTagList* findTagList(U8CPU tag) const;
+ void addTagList(SkTagList*);
+ void removeTagList(U8CPU tag);
+
+private:
+ SkEventSinkID fID;
+ SkTagList* fTagHead;
+
+ // for our private link-list
+ SkEventSink* fNextSink;
+
+ typedef SkRefCnt INHERITED;
+};
+
+#endif
diff --git a/views/SkKey.h b/views/SkKey.h
new file mode 100644
index 0000000..036e2c3
--- /dev/null
+++ b/views/SkKey.h
@@ -0,0 +1,62 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkKey_DEFINED
+#define SkKey_DEFINED
+
+#include "SkTypes.h"
+
+enum SkKey {
+ //reordering these to match android.app.KeyEvent
+ kNONE_SkKey, //corresponds to android's UNKNOWN
+
+ kLeftSoftKey_SkKey,
+ kRightSoftKey_SkKey,
+
+ kHome_SkKey, //!< the home key - added to match android
+ kBack_SkKey, //!< (CLR)
+ kSend_SkKey, //!< the green (talk) key
+ kEnd_SkKey, //!< the red key
+
+ k0_SkKey,
+ k1_SkKey,
+ k2_SkKey,
+ k3_SkKey,
+ k4_SkKey,
+ k5_SkKey,
+ k6_SkKey,
+ k7_SkKey,
+ k8_SkKey,
+ k9_SkKey,
+ kStar_SkKey, //!< the * key
+ kHash_SkKey, //!< the # key
+
+ kUp_SkKey,
+ kDown_SkKey,
+ kLeft_SkKey,
+ kRight_SkKey,
+
+ kOK_SkKey, //!< the center key
+
+ kVolUp_SkKey, //!< volume up - match android
+ kVolDown_SkKey, //!< volume down - same
+ kPower_SkKey, //!< power button - same
+ kCamera_SkKey, //!< camera - same
+
+ kSkKeyCount
+};
+
+enum SkModifierKeys {
+ kShift_SkModifierKey = 1 << 0,
+ kControl_SkModifierKey = 1 << 1,
+ kOption_SkModifierKey = 1 << 2, // same as ALT
+ kCommand_SkModifierKey = 1 << 3,
+};
+
+#endif
diff --git a/views/SkOSMenu.h b/views/SkOSMenu.h
new file mode 100644
index 0000000..8801a52
--- /dev/null
+++ b/views/SkOSMenu.h
@@ -0,0 +1,182 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkOSMenu_DEFINED
+#define SkOSMenu_DEFINED
+
+#include "SkEvent.h"
+#include "SkTDArray.h"
+
+class SkOSMenu {
+public:
+ explicit SkOSMenu(const char title[] = "");
+ ~SkOSMenu();
+
+ /**
+ * Each of these (except action) has an associated value, which is stored in
+ * the event payload for the item.
+ * Each type has a specific type for its value...
+ * Action : none
+ * List : int (selected index)
+ * Segmented : int (selected index)
+ * Slider : float
+ * Switch : bool
+ * TextField : string
+ * TriState : TriState
+ * Custom : custom object/value
+ */
+ enum Type {
+ kAction_Type,
+ kList_Type,
+ kSlider_Type,
+ kSwitch_Type,
+ kTriState_Type,
+ kTextField_Type,
+ kCustom_Type
+ };
+
+ enum TriState {
+ kMixedState = -1,
+ kOffState = 0,
+ kOnState = 1
+ };
+
+ class Item {
+ public:
+ /**
+ * Auto increments a global to generate an unique ID for each new item
+ * Note: Thread safe
+ */
+ Item(const char label[], SkOSMenu::Type type, const char slotName[],
+ SkEvent* evt);
+ ~Item() { delete fEvent; }
+
+ SkEvent* getEvent() const { return fEvent; }
+ int getID() const { return fID; }
+ const char* getLabel() const { return fLabel.c_str(); }
+ const char* getSlotName() const { return fSlotName.c_str(); }
+ Type getType() const { return fType; }
+ void setKeyEquivalent(SkUnichar key) { fKey = key; }
+ SkUnichar getKeyEquivalent() const { return fKey; }
+
+ /**
+ * Helper functions for predefined types
+ */
+ void setBool(bool value) const; //For Switch
+ void setScalar(SkScalar value) const; //For Slider
+ void setInt(int value) const; //For List
+ void setTriState(TriState value) const; //For Tristate
+ void setString(const char value[]) const; //For TextField
+
+ /**
+ * Post event associated with the menu item to target, any changes to
+ * the associated event must be made prior to calling this method
+ */
+ void postEvent() const { (new SkEvent(*(fEvent)))->post(); }
+
+ private:
+ int fID;
+ SkEvent* fEvent;
+ SkString fLabel;
+ SkString fSlotName;
+ Type fType;
+ SkUnichar fKey;
+ };
+
+ void reset();
+ const char* getTitle() const { return fTitle.c_str(); }
+ void setTitle (const char title[]) { fTitle.set(title); }
+ int getCount() const { return fItems.count(); }
+ const Item* getItemByID(int itemID) const;
+ void getItems(const Item* items[]) const;
+
+ /**
+ * Assign key to the menu item with itemID, will do nothing if there's no
+ * item with the id given
+ */
+ void assignKeyEquivalentToItem(int itemID, SkUnichar key);
+ /**
+ * Call this in a SkView's onHandleChar to trigger any menu items with the
+ * given key equivalent. If such an item is found, the method will return
+ * true and its corresponding event will be triggered (default behavior
+ * defined for switches(toggling), tristates(cycle), and lists(cycle),
+ * for anything else, the event attached is posted without state changes)
+ * If no menu item can be matched with the key, false will be returned
+ */
+ bool handleKeyEquivalent(SkUnichar key);
+
+ /**
+ * The following functions append new items to the menu and returns their
+ * associated unique id, which can be used to by the client to refer to
+ * the menu item created and change its state. slotName specifies the string
+ * identifier of any state/value to be returned in the item's SkEvent object
+ * NOTE: evt must be dynamically allocated
+ */
+ int appendItem(const char label[], Type type, const char slotName[],
+ SkEvent* evt);
+
+ /**
+ * Create predefined items with the given parameters. To be used with the
+ * other helper functions below to retrive/update state information.
+ * Note: the helper functions below assume that slotName is UNIQUE for all
+ * menu items of the same type since it's used to identify the event
+ */
+ int appendAction(const char label[], SkEventSinkID target);
+ int appendList(const char label[], const char slotName[],
+ SkEventSinkID target, int defaultIndex, const char[] ...);
+ int appendSlider(const char label[], const char slotName[],
+ SkEventSinkID target, SkScalar min, SkScalar max,
+ SkScalar defaultValue);
+ int appendSwitch(const char label[], const char slotName[],
+ SkEventSinkID target, bool defaultState = false);
+ int appendTriState(const char label[], const char slotName[],
+ SkEventSinkID target, TriState defaultState = kOffState);
+ int appendTextField(const char label[], const char slotName[],
+ SkEventSinkID target, const char placeholder[] = "");
+
+
+ /**
+ * Helper functions to retrieve information other than the stored value for
+ * some predefined types
+ */
+ static bool FindListItemCount(const SkEvent& evt, int* count);
+ /**
+ * Ensure that the items array can store n SkStrings where n is the count
+ * extracted using FindListItemCount
+ */
+ static bool FindListItems(const SkEvent& evt, SkString items[]);
+ static bool FindSliderMin(const SkEvent& evt, SkScalar* min);
+ static bool FindSliderMax(const SkEvent& evt, SkScalar* max);
+
+ /**
+ * Returns true if an action with the given label is found, false otherwise
+ */
+ static bool FindAction(const SkEvent& evt, const char label[]);
+ /**
+ * The following helper functions will return true if evt is generated from
+ * a predefined item type and retrieve the corresponding state information.
+ * They will return false and leave value unchanged if there's a type
+ * mismatch or slotName is incorrect
+ */
+ static bool FindListIndex(const SkEvent& evt, const char slotName[], int* value);
+ static bool FindSliderValue(const SkEvent& evt, const char slotName[], SkScalar* value);
+ static bool FindSwitchState(const SkEvent& evt, const char slotName[], bool* value);
+ static bool FindTriState(const SkEvent& evt, const char slotName[], TriState* value);
+ static bool FindText(const SkEvent& evt, const char slotName[], SkString* value);
+
+private:
+ SkString fTitle;
+ SkTDArray<Item*> fItems;
+
+ // illegal
+ SkOSMenu(const SkOSMenu&);
+ SkOSMenu& operator=(const SkOSMenu&);
+};
+
+#endif
diff --git a/views/SkOSWindow_Android.h b/views/SkOSWindow_Android.h
new file mode 100644
index 0000000..77c156c
--- /dev/null
+++ b/views/SkOSWindow_Android.h
@@ -0,0 +1,53 @@
+
+/*
+ * Copyright 2011 Skia
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkOSWindow_Android_DEFINED
+#define SkOSWindow_Android_DEFINED
+
+#include "SkWindow.h"
+
+class SkIRect;
+
+class SkOSWindow : public SkWindow {
+public:
+ SkOSWindow(void*) {}
+ ~SkOSWindow() {}
+
+ enum SkBackEndTypes {
+ kNone_BackEndType,
+ kNativeGL_BackEndType,
+ };
+
+ struct AttachmentInfo {
+ int fSampleCount;
+ int fStencilBits;
+ };
+
+ bool attach(SkBackEndTypes /* attachType */, int /* msaaSampleCount */, AttachmentInfo* info) {
+ // These are the values requested in SkiaSampleView.java
+ info->fSampleCount = 0;
+ info->fStencilBits = 8;
+ return true;
+ }
+ void detach() {}
+ void present() {}
+
+ virtual void onPDFSaved(const char title[], const char desc[],
+ const char path[]);
+
+protected:
+ // overrides from SkWindow
+ virtual void onHandleInval(const SkIRect&);
+ virtual void onSetTitle(const char title[]);
+
+private:
+ typedef SkWindow INHERITED;
+};
+
+#endif
diff --git a/views/SkOSWindow_Mac.h b/views/SkOSWindow_Mac.h
new file mode 100644
index 0000000..5dea2fc
--- /dev/null
+++ b/views/SkOSWindow_Mac.h
@@ -0,0 +1,58 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkOSWindow_MacCocoa_DEFINED
+#define SkOSWindow_MacCocoa_DEFINED
+
+#include "SkWindow.h"
+
+class SkOSWindow : public SkWindow {
+public:
+ SkOSWindow(void* hwnd);
+ ~SkOSWindow();
+ void* getHWND() const { return fHWND; }
+
+ virtual bool onDispatchClick(int x, int y, Click::State state,
+ void* owner, unsigned modi);
+ enum SkBackEndTypes {
+ kNone_BackEndType,
+#if SK_SUPPORT_GPU
+ kNativeGL_BackEndType,
+#endif
+ };
+
+ struct AttachmentInfo {
+ int fSampleCount;
+ int fStencilBits;
+ };
+
+ void detach();
+ bool attach(SkBackEndTypes attachType, int msaaSampleCount, AttachmentInfo*);
+ void present();
+
+protected:
+ // overrides from SkEventSink
+ virtual bool onEvent(const SkEvent& evt);
+ // overrides from SkWindow
+ virtual void onHandleInval(const SkIRect&);
+ // overrides from SkView
+ virtual void onAddMenu(const SkOSMenu*);
+ virtual void onUpdateMenu(const SkOSMenu*);
+ virtual void onSetTitle(const char[]);
+
+private:
+ void* fHWND;
+ bool fInvalEventIsPending;
+ void* fNotifier;
+#if SK_SUPPORT_GPU
+ void* fGLContext;
+#endif
+ typedef SkWindow INHERITED;
+};
+
+#endif
diff --git a/views/SkOSWindow_NaCl.h b/views/SkOSWindow_NaCl.h
new file mode 100644
index 0000000..2296023
--- /dev/null
+++ b/views/SkOSWindow_NaCl.h
@@ -0,0 +1,52 @@
+
+/*
+ * Copyright 2012 Skia
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkOSWindow_NaCl_DEFINED
+#define SkOSWindow_NaCl_DEFINED
+
+#include "SkWindow.h"
+
+class SkIRect;
+
+class SkOSWindow : public SkWindow {
+public:
+ SkOSWindow(void*) {}
+ ~SkOSWindow() {}
+
+ enum SkBackEndTypes {
+ kNone_BackEndType,
+ kNativeGL_BackEndType,
+ };
+
+ struct AttachmentInfo {
+ int fSampleCount;
+ int fStencilBits;
+ };
+
+ bool attach(SkBackEndTypes /* attachType */, int /* msaaSampleCount */, AttachmentInfo* info) {
+ info->fSampleCount = 0;
+ info->fStencilBits = 0;
+ return true;
+ }
+ void detach() {}
+ void present() {}
+
+ virtual void onPDFSaved(const char title[], const char desc[],
+ const char path[]);
+
+protected:
+ // overrides from SkWindow
+ virtual void onHandleInval(const SkIRect&);
+ virtual void onSetTitle(const char title[]);
+
+private:
+ typedef SkWindow INHERITED;
+};
+
+#endif
diff --git a/views/SkOSWindow_SDL.h b/views/SkOSWindow_SDL.h
new file mode 100644
index 0000000..e6b59e6
--- /dev/null
+++ b/views/SkOSWindow_SDL.h
@@ -0,0 +1,44 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkOSWindow_SDL_DEFINED
+#define SkOSWindow_SDL_DEFINED
+
+#include "SDL.h"
+#include "SkWindow.h"
+
+class SkGLCanvas;
+
+class SkOSWindow : public SkWindow {
+public:
+ SkOSWindow(void* screen);
+ virtual ~SkOSWindow();
+
+ static bool PostEvent(SkEvent* evt, SkEventSinkID, SkMSec delay);
+
+ void handleSDLEvent(const SDL_Event& event);
+
+protected:
+ // overrides from SkWindow
+ virtual void onHandleInval(const SkIRect&);
+ // overrides from SkView
+ virtual void onAddMenu(const SkOSMenu*);
+ virtual void onSetTitle(const char[]);
+
+private:
+ SDL_Surface* fScreen;
+ SDL_Surface* fSurface;
+ SkGLCanvas* fGLCanvas;
+
+ void doDraw();
+
+ typedef SkWindow INHERITED;
+};
+
+#endif
diff --git a/views/SkOSWindow_Unix.h b/views/SkOSWindow_Unix.h
new file mode 100644
index 0000000..8a55ef4
--- /dev/null
+++ b/views/SkOSWindow_Unix.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkOSWindow_Unix_DEFINED
+#define SkOSWindow_Unix_DEFINED
+
+#include <GL/glx.h>
+#include <X11/Xlib.h>
+
+#include "SkWindow.h"
+
+class SkEvent;
+
+struct SkUnixWindow {
+ Display* fDisplay;
+ Window fWin;
+ size_t fOSWin;
+ GC fGc;
+ GLXContext fGLContext;
+};
+
+class SkOSWindow : public SkWindow {
+public:
+ SkOSWindow(void*);
+ ~SkOSWindow();
+
+ void* getHWND() const { return (void*)fUnixWindow.fWin; }
+ void* getDisplay() const { return (void*)fUnixWindow.fDisplay; }
+ void* getUnixWindow() const { return (void*)&fUnixWindow; }
+ void loop();
+
+ enum SkBackEndTypes {
+ kNone_BackEndType,
+ kNativeGL_BackEndType,
+ };
+
+ struct AttachmentInfo {
+ int fSampleCount;
+ int fStencilBits;
+ };
+
+ bool attach(SkBackEndTypes attachType, int msaaSampleCount, AttachmentInfo*);
+ void detach();
+ void present();
+
+ int getMSAASampleCount() const { return fMSAASampleCount; }
+
+ //static bool PostEvent(SkEvent* evt, SkEventSinkID, SkMSec delay);
+
+protected:
+ // Overridden from from SkWindow:
+ virtual void onSetTitle(const char title[]) SK_OVERRIDE;
+
+private:
+ enum NextXEventResult {
+ kContinue_NextXEventResult,
+ kQuitRequest_NextXEventResult,
+ kPaintRequest_NextXEventResult
+ };
+
+ NextXEventResult nextXEvent();
+ void doPaint();
+ void mapWindowAndWait();
+
+ void closeWindow();
+ void initWindow(int newMSAASampleCount, AttachmentInfo* info);
+
+ SkUnixWindow fUnixWindow;
+
+ // Needed for GL
+ XVisualInfo* fVi;
+ // we recreate the underlying xwindow if this changes
+ int fMSAASampleCount;
+
+ typedef SkWindow INHERITED;
+};
+
+#endif
diff --git a/views/SkOSWindow_Win.h b/views/SkOSWindow_Win.h
new file mode 100644
index 0000000..6b5977c
--- /dev/null
+++ b/views/SkOSWindow_Win.h
@@ -0,0 +1,101 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkOSWindow_Win_DEFINED
+#define SkOSWindow_Win_DEFINED
+
+#include "SkWindow.h"
+
+#if SK_ANGLE
+#include "EGL/egl.h"
+#endif
+
+class SkOSWindow : public SkWindow {
+public:
+ SkOSWindow(void* hwnd);
+ virtual ~SkOSWindow();
+
+ void* getHWND() const { return fHWND; }
+ void setSize(int width, int height);
+ void updateSize();
+
+ static bool PostEvent(SkEvent* evt, SkEventSinkID, SkMSec delay);
+
+ enum SkBackEndTypes {
+ kNone_BackEndType,
+#if SK_SUPPORT_GPU
+ kNativeGL_BackEndType,
+#if SK_ANGLE
+ kANGLE_BackEndType,
+#endif // SK_ANGLE
+#endif // SK_SUPPORT_GPU
+ };
+
+ struct AttachmentInfo {
+ int fSampleCount;
+ int fStencilBits;
+ };
+
+ bool attach(SkBackEndTypes attachType, int msaaSampleCount, AttachmentInfo*);
+ void detach();
+ void present();
+
+ bool wndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
+ static bool QuitOnDeactivate(HWND hWnd);
+
+ enum {
+ SK_WM_SkEvent = WM_APP + 1000,
+ SK_WM_SkTimerID = 0xFFFF // just need a non-zero value
+ };
+
+protected:
+ virtual bool quitOnDeactivate() { return true; }
+
+ // overrides from SkWindow
+ virtual void onHandleInval(const SkIRect&);
+ // overrides from SkView
+ virtual void onAddMenu(const SkOSMenu*);
+
+ virtual void onSetTitle(const char title[]);
+
+private:
+ void* fHWND;
+
+ void doPaint(void* ctx);
+
+#if SK_SUPPORT_GPU
+ void* fHGLRC;
+#if SK_ANGLE
+ EGLDisplay fDisplay;
+ EGLContext fContext;
+ EGLSurface fSurface;
+ EGLConfig fConfig;
+#endif // SK_ANGLE
+#endif // SK_SUPPORT_GPU
+
+ HMENU fMBar;
+
+ SkBackEndTypes fAttached;
+
+#if SK_SUPPORT_GPU
+ bool attachGL(int msaaSampleCount, AttachmentInfo* info);
+ void detachGL();
+ void presentGL();
+
+#if SK_ANGLE
+ bool attachANGLE(int msaaSampleCount, AttachmentInfo* info);
+ void detachANGLE();
+ void presentANGLE();
+#endif // SK_ANGLE
+#endif // SK_SUPPORT_GPU
+
+ typedef SkWindow INHERITED;
+};
+
+#endif
diff --git a/views/SkOSWindow_iOS.h b/views/SkOSWindow_iOS.h
new file mode 100755
index 0000000..1984900
--- /dev/null
+++ b/views/SkOSWindow_iOS.h
@@ -0,0 +1,50 @@
+
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#ifndef SkOSWindow_iOS_DEFINED
+#define SkOSWindow_iOS_DEFINED
+
+#include "SkWindow.h"
+
+class SkOSWindow : public SkWindow {
+public:
+ SkOSWindow(void* hwnd);
+ ~SkOSWindow();
+ void* getHWND() const { return fHWND; }
+
+ enum SkBackEndTypes {
+ kNone_BackEndType,
+ kNativeGL_BackEndType,
+ };
+
+ struct AttachmentInfo {
+ int fSampleCount;
+ int fStencilBits;
+ };
+
+ void detach();
+ bool attach(SkBackEndTypes attachType, int msaaSampleCount, AttachmentInfo*);
+ void present();
+
+protected:
+ // overrides from SkEventSink
+ virtual bool onEvent(const SkEvent& evt);
+ // overrides from SkWindow
+ virtual void onHandleInval(const SkIRect&);
+ // overrides from SkView
+ virtual void onAddMenu(const SkOSMenu*);
+ virtual void onUpdateMenu(SkOSMenu*);
+ virtual void onSetTitle(const char[]);
+
+private:
+ void* fHWND;
+ bool fInvalEventIsPending;
+ void* fNotifier;
+ typedef SkWindow INHERITED;
+};
+
+#endif
diff --git a/views/SkStackViewLayout.h b/views/SkStackViewLayout.h
new file mode 100644
index 0000000..f2a7cf0
--- /dev/null
+++ b/views/SkStackViewLayout.h
@@ -0,0 +1,88 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkStackViewLayout_DEFINED
+#define SkStackViewLayout_DEFINED
+
+#include "SkView.h"
+
+class SkStackViewLayout : public SkView::Layout {
+public:
+ SkStackViewLayout();
+
+ enum Orient {
+ kHorizontal_Orient,
+ kVertical_Orient,
+
+ kOrientCount
+ };
+ Orient getOrient() const { return (Orient)fOrient; }
+ void setOrient(Orient);
+
+ void getMargin(SkRect*) const;
+ void setMargin(const SkRect&);
+
+ SkScalar getSpacer() const { return fSpacer; }
+ void setSpacer(SkScalar);
+
+ /** Controls the posititioning in the same direction as the orientation
+ */
+ enum Pack {
+ kStart_Pack,
+ kCenter_Pack,
+ kEnd_Pack,
+
+ kPackCount
+ };
+ Pack getPack() const { return (Pack)fPack; }
+ void setPack(Pack);
+
+ /** Controls the posititioning at right angles to the orientation
+ */
+ enum Align {
+ kStart_Align,
+ kCenter_Align,
+ kEnd_Align,
+ kStretch_Align,
+
+ kAlignCount
+ };
+ Align getAlign() const { return (Align)fAlign; }
+ void setAlign(Align);
+
+ bool getRound() const { return SkToBool(fRound); }
+ void setRound(bool);
+
+protected:
+ virtual void onLayoutChildren(SkView* parent);
+ virtual void onInflate(const SkDOM&, const SkDOM::Node*);
+
+private:
+ SkRect fMargin;
+ SkScalar fSpacer;
+ uint8_t fOrient, fPack, fAlign, fRound;
+};
+
+class SkFillViewLayout : public SkView::Layout {
+public:
+ SkFillViewLayout();
+ void getMargin(SkRect*) const;
+ void setMargin(const SkRect&);
+
+protected:
+ // overrides;
+ virtual void onLayoutChildren(SkView* parent);
+ virtual void onInflate(const SkDOM& dom, const SkDOM::Node* node);
+
+private:
+ SkRect fMargin;
+ typedef SkView::Layout INHERITED;
+};
+
+#endif
diff --git a/views/SkSystemEventTypes.h b/views/SkSystemEventTypes.h
new file mode 100644
index 0000000..bb2b5d5
--- /dev/null
+++ b/views/SkSystemEventTypes.h
@@ -0,0 +1,25 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkSystemEventTypes_DEFINED
+#define SkSystemEventTypes_DEFINED
+
+/*
+ The goal of these strings is two-fold:
+ 1) make funny strings (containing at least one char < 32) to avoid colliding with "user" strings
+ 2) keep them <= 4 bytes, so we can avoid an allocation in SkEvent::setType()
+*/
+#define SK_EventType_Delay "\xd" "lay"
+#define SK_EventType_Inval "nv" "\xa" "l"
+#define SK_EventType_Key "key" "\x1"
+#define SK_EventType_OnEnd "on" "\xe" "n"
+#define SK_EventType_Unichar "\xc" "har"
+#define SK_EventType_KeyUp "key" "\xf"
+
+#endif
diff --git a/views/SkTextBox.h b/views/SkTextBox.h
new file mode 100644
index 0000000..e217076
--- /dev/null
+++ b/views/SkTextBox.h
@@ -0,0 +1,77 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkTextBox_DEFINED
+#define SkTextBox_DEFINED
+
+#include "SkCanvas.h"
+
+/** \class SkTextBox
+
+ SkTextBox is a helper class for drawing 1 or more lines of text
+ within a rectangle. The textbox is positioned and clipped by its Frame.
+ The Margin rectangle controls where the text is drawn relative to
+ the Frame. Line-breaks occur inside the Margin rectangle.
+
+ Spacing is a linear equation used to compute the distance between lines
+ of text. Spacing consists of two scalars: mul and add, and the spacing
+ between lines is computed as: spacing = paint.getTextSize() * mul + add
+*/
+class SkTextBox {
+public:
+ SkTextBox();
+
+ enum Mode {
+ kOneLine_Mode,
+ kLineBreak_Mode,
+
+ kModeCount
+ };
+ Mode getMode() const { return (Mode)fMode; }
+ void setMode(Mode);
+
+ enum SpacingAlign {
+ kStart_SpacingAlign,
+ kCenter_SpacingAlign,
+ kEnd_SpacingAlign,
+
+ kSpacingAlignCount
+ };
+ SpacingAlign getSpacingAlign() const { return (SpacingAlign)fSpacingAlign; }
+ void setSpacingAlign(SpacingAlign);
+
+ void getBox(SkRect*) const;
+ void setBox(const SkRect&);
+ void setBox(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom);
+
+ void getSpacing(SkScalar* mul, SkScalar* add) const;
+ void setSpacing(SkScalar mul, SkScalar add);
+
+ void draw(SkCanvas*, const char text[], size_t len, const SkPaint&);
+
+ void setText(const char text[], size_t len, const SkPaint&);
+ void draw(SkCanvas*);
+ int countLines() const;
+ SkScalar getTextHeight() const;
+
+private:
+ SkRect fBox;
+ SkScalar fSpacingMul, fSpacingAdd;
+ uint8_t fMode, fSpacingAlign;
+ const char* fText;
+ size_t fLen;
+ const SkPaint* fPaint;
+};
+
+class SkTextLineBreaker {
+public:
+ static int CountLines(const char text[], size_t len, const SkPaint&, SkScalar width);
+};
+
+#endif
diff --git a/views/SkTouchGesture.h b/views/SkTouchGesture.h
new file mode 100644
index 0000000..3a0cfce
--- /dev/null
+++ b/views/SkTouchGesture.h
@@ -0,0 +1,77 @@
+
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#ifndef SkTouchGesture_DEFINED
+#define SkTouchGesture_DEFINED
+
+#include "SkTDArray.h"
+#include "SkMatrix.h"
+
+struct SkFlingState {
+ SkFlingState() : fActive(false) {}
+
+ bool isActive() const { return fActive; }
+ void stop() { fActive = false; }
+
+ void reset(float sx, float sy);
+ bool evaluateMatrix(SkMatrix* matrix);
+
+private:
+ SkPoint fDirection;
+ SkScalar fSpeed0;
+ double fTime0;
+ bool fActive;
+};
+
+class SkTouchGesture {
+public:
+ SkTouchGesture();
+ ~SkTouchGesture();
+
+ void touchBegin(void* owner, float x, float y);
+ void touchMoved(void* owner, float x, float y);
+ void touchEnd(void* owner);
+ void reset();
+
+ bool isActive() { return fFlinger.isActive(); }
+ void stop() { fFlinger.stop(); }
+
+ const SkMatrix& localM();
+ const SkMatrix& globalM() const { return fGlobalM; }
+
+private:
+ enum State {
+ kEmpty_State,
+ kTranslate_State,
+ kZoom_State,
+ };
+
+ struct Rec {
+ void* fOwner;
+ float fStartX, fStartY;
+ float fPrevX, fPrevY;
+ float fLastX, fLastY;
+ SkMSec fPrevT, fLastT;
+ };
+ SkTDArray<Rec> fTouches;
+
+ State fState;
+ SkMatrix fLocalM, fGlobalM;
+ SkFlingState fFlinger;
+ SkMSec fLastUpT;
+ SkPoint fLastUpP;
+
+
+ void flushLocalM();
+ int findRec(void* owner) const;
+ void appendNewRec(void* owner, float x, float y);
+ float computePinch(const Rec&, const Rec&);
+ float limitTotalZoom(float scale) const;
+ bool handleDblTap(float, float);
+};
+
+#endif
diff --git a/views/SkView.h b/views/SkView.h
new file mode 100644
index 0000000..d03c741
--- /dev/null
+++ b/views/SkView.h
@@ -0,0 +1,405 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkView_DEFINED
+#define SkView_DEFINED
+
+#include "SkEventSink.h"
+#include "SkRect.h"
+#include "SkDOM.h"
+#include "SkTDict.h"
+#include "SkMatrix.h"
+#include "SkMetaData.h"
+
+class SkCanvas;
+class SkLayerView;
+
+/** \class SkView
+
+ SkView is the base class for screen management. All widgets and controls inherit
+ from SkView.
+*/
+class SkView : public SkEventSink {
+public:
+ enum Flag_Shift {
+ kVisible_Shift,
+ kEnabled_Shift,
+ kFocusable_Shift,
+ kFlexH_Shift,
+ kFlexV_Shift,
+ kNoClip_Shift,
+
+ kFlagShiftCount
+ };
+ enum Flag_Mask {
+ kVisible_Mask = 1 << kVisible_Shift, //!< set if the view is visible
+ kEnabled_Mask = 1 << kEnabled_Shift, //!< set if the view is enabled
+ kFocusable_Mask = 1 << kFocusable_Shift, //!< set if the view can receive focus
+ kFlexH_Mask = 1 << kFlexH_Shift, //!< set if the view's width is stretchable
+ kFlexV_Mask = 1 << kFlexV_Shift, //!< set if the view's height is stretchable
+ kNoClip_Mask = 1 << kNoClip_Shift, //!< set if the view is not clipped to its bounds
+
+ kAllFlagMasks = (uint32_t)(0 - 1) >> (32 - kFlagShiftCount)
+ };
+
+ SkView(uint32_t flags = 0);
+ virtual ~SkView();
+
+ /** Return the flags associated with the view
+ */
+ uint32_t getFlags() const { return fFlags; }
+ /** Set the flags associated with the view
+ */
+ void setFlags(uint32_t flags);
+
+ /** Helper that returns non-zero if the kVisible_Mask bit is set in the view's flags
+ */
+ int isVisible() const { return fFlags & kVisible_Mask; }
+ int isEnabled() const { return fFlags & kEnabled_Mask; }
+ int isFocusable() const { return fFlags & kFocusable_Mask; }
+ int isClipToBounds() const { return !(fFlags & kNoClip_Mask); }
+ /** Helper to set/clear the view's kVisible_Mask flag */
+ void setVisibleP(bool);
+ void setEnabledP(bool);
+ void setFocusableP(bool);
+ void setClipToBounds(bool);
+
+ /** Return the view's width */
+ SkScalar width() const { return fWidth; }
+ /** Return the view's height */
+ SkScalar height() const { return fHeight; }
+ /** Set the view's width and height. These must both be >= 0. This does not affect the view's loc */
+ void setSize(SkScalar width, SkScalar height);
+ void setSize(const SkPoint& size) { this->setSize(size.fX, size.fY); }
+ void setWidth(SkScalar width) { this->setSize(width, fHeight); }
+ void setHeight(SkScalar height) { this->setSize(fWidth, height); }
+ /** Return a rectangle set to [0, 0, width, height] */
+ void getLocalBounds(SkRect* bounds) const;
+
+ /** Loc - the view's offset with respect to its parent in its view hiearchy.
+ NOTE: For more complex transforms, use Local Matrix. The tranformations
+ are applied in the following order:
+ canvas->translate(fLoc.fX, fLoc.fY);
+ canvas->concat(fMatrix);
+ */
+ /** Return the view's left edge */
+ SkScalar locX() const { return fLoc.fX; }
+ /** Return the view's top edge */
+ SkScalar locY() const { return fLoc.fY; }
+ /** Set the view's left and top edge. This does not affect the view's size */
+ void setLoc(SkScalar x, SkScalar y);
+ void setLoc(const SkPoint& loc) { this->setLoc(loc.fX, loc.fY); }
+ void setLocX(SkScalar x) { this->setLoc(x, fLoc.fY); }
+ void setLocY(SkScalar y) { this->setLoc(fLoc.fX, y); }
+
+ /** Local Matrix - matrix used to tranform the view with respect to its
+ parent in its view hiearchy. Use setLocalMatrix to apply matrix
+ transformations to the current view and in turn affect its children.
+ NOTE: For simple offsets, use Loc. The transformations are applied in
+ the following order:
+ canvas->translate(fLoc.fX, fLoc.fY);
+ canvas->concat(fMatrix);
+ */
+ const SkMatrix& getLocalMatrix() const { return fMatrix; }
+ void setLocalMatrix(const SkMatrix& matrix);
+
+ /** Offset (move) the view by the specified dx and dy. This does not affect the view's size */
+ void offset(SkScalar dx, SkScalar dy);
+
+ /** Call this to have the view draw into the specified canvas. */
+ virtual void draw(SkCanvas* canvas);
+
+ /** Call this to invalidate part of all of a view, requesting that the view's
+ draw method be called. The rectangle parameter specifies the part of the view
+ that should be redrawn. If it is null, it specifies the entire view bounds.
+ */
+ void inval(SkRect* rectOrNull);
+
+ // Focus management
+
+ SkView* getFocusView() const;
+ bool hasFocus() const;
+
+ enum FocusDirection {
+ kNext_FocusDirection,
+ kPrev_FocusDirection,
+
+ kFocusDirectionCount
+ };
+ bool acceptFocus();
+ SkView* moveFocus(FocusDirection);
+
+ // Click handling
+
+ class Click {
+ public:
+ Click(SkView* target);
+ virtual ~Click();
+
+ const char* getType() const { return fType; }
+ bool isType(const char type[]) const;
+ void setType(const char type[]); // does NOT make a copy of the string
+ void copyType(const char type[]); // makes a copy of the string
+
+ enum State {
+ kDown_State,
+ kMoved_State,
+ kUp_State
+ };
+ SkPoint fOrig, fPrev, fCurr;
+ SkIPoint fIOrig, fIPrev, fICurr;
+ State fState;
+ void* fOwner;
+ unsigned fModifierKeys;
+
+ SkMetaData fMeta;
+ private:
+ SkEventSinkID fTargetID;
+ char* fType;
+ bool fWeOwnTheType;
+
+ void resetType();
+
+ friend class SkView;
+ };
+ Click* findClickHandler(SkScalar x, SkScalar y, unsigned modifierKeys);
+
+ static void DoClickDown(Click*, int x, int y, unsigned modi);
+ static void DoClickMoved(Click*, int x, int y, unsigned modi);
+ static void DoClickUp(Click*, int x, int y, unsigned modi);
+
+ /** Send the event to the view's parent, and its parent etc. until one of them
+ returns true from its onEvent call. This view is returned. If no parent handles
+ the event, null is returned.
+ */
+ SkView* sendEventToParents(const SkEvent&);
+ /** Send the query to the view's parent, and its parent etc. until one of them
+ returns true from its onQuery call. This view is returned. If no parent handles
+ the query, null is returned.
+ */
+ SkView* sendQueryToParents(SkEvent*);
+
+ // View hierarchy management
+
+ /** Return the view's parent, or null if it has none. This does not affect the parent's reference count. */
+ SkView* getParent() const { return fParent; }
+ SkView* attachChildToFront(SkView* child);
+ /** Attach the child view to this view, and increment the child's reference count. The child view is added
+ such that it will be drawn before all other child views.
+ The child view parameter is returned.
+ */
+ SkView* attachChildToBack(SkView* child);
+ /** If the view has a parent, detach the view from its parent and decrement the view's reference count.
+ If the parent was the only owner of the view, this will cause the view to be deleted.
+ */
+ void detachFromParent();
+ /** Attach the child view to this view, and increment the child's reference count. The child view is added
+ such that it will be drawn after all other child views.
+ The child view parameter is returned.
+ */
+ /** Detach all child views from this view. */
+ void detachAllChildren();
+
+ /** Convert the specified point from global coordinates into view-local coordinates
+ * Return true on success; false on failure
+ */
+ bool globalToLocal(SkPoint* pt) const {
+ if (NULL != pt) {
+ return this->globalToLocal(pt->fX, pt->fY, pt);
+ }
+ return true; // nothing to do so return true
+ }
+ /** Convert the specified x,y from global coordinates into view-local coordinates, returning
+ the answer in the local parameter.
+ */
+ bool globalToLocal(SkScalar globalX, SkScalar globalY, SkPoint* local) const;
+
+ /** \class F2BIter
+
+ Iterator that will return each of this view's children, in
+ front-to-back order (the order used for clicking). The first
+ call to next() returns the front-most child view. When
+ next() returns null, there are no more child views.
+ */
+ class F2BIter {
+ public:
+ F2BIter(const SkView* parent);
+ SkView* next();
+ private:
+ SkView* fFirstChild, *fChild;
+ };
+
+ /** \class B2FIter
+
+ Iterator that will return each of this view's children, in
+ back-to-front order (the order they are drawn). The first
+ call to next() returns the back-most child view. When
+ next() returns null, there are no more child views.
+ */
+ class B2FIter {
+ public:
+ B2FIter(const SkView* parent);
+ SkView* next();
+ private:
+ SkView* fFirstChild, *fChild;
+ };
+
+ /** \class Artist
+
+ Install a subclass of this in a view (calling setArtist()), and then the
+ default implementation of that view's onDraw() will invoke this object
+ automatically.
+ */
+ class Artist : public SkRefCnt {
+ public:
+ SK_DECLARE_INST_COUNT(Artist)
+
+ void draw(SkView*, SkCanvas*);
+ void inflate(const SkDOM&, const SkDOM::Node*);
+ protected:
+ virtual void onDraw(SkView*, SkCanvas*) = 0;
+ virtual void onInflate(const SkDOM&, const SkDOM::Node*);
+ private:
+ typedef SkRefCnt INHERITED;
+ };
+ /** Return the artist attached to this view (or null). The artist's reference
+ count is not affected.
+ */
+ Artist* getArtist() const;
+ /** Attach the specified artist (or null) to the view, replacing any existing
+ artist. If the new artist is not null, its reference count is incremented.
+ The artist parameter is returned.
+ */
+ Artist* setArtist(Artist* artist);
+
+ /** \class Layout
+
+ Install a subclass of this in a view (calling setLayout()), and then the
+ default implementation of that view's onLayoutChildren() will invoke
+ this object automatically.
+ */
+ class Layout : public SkRefCnt {
+ public:
+ SK_DECLARE_INST_COUNT(Layout)
+
+ void layoutChildren(SkView* parent);
+ void inflate(const SkDOM&, const SkDOM::Node*);
+ protected:
+ virtual void onLayoutChildren(SkView* parent) = 0;
+ virtual void onInflate(const SkDOM&, const SkDOM::Node*);
+ private:
+ typedef SkRefCnt INHERITED;
+ };
+
+ /** Return the layout attached to this view (or null). The layout's reference
+ count is not affected.
+ */
+ Layout* getLayout() const;
+ /** Attach the specified layout (or null) to the view, replacing any existing
+ layout. If the new layout is not null, its reference count is incremented.
+ The layout parameter is returned.
+ */
+ Layout* setLayout(Layout*, bool invokeLayoutNow = true);
+ /** If a layout is attached to this view, call its layoutChildren() method
+ */
+ void invokeLayout();
+
+ /** Call this to initialize this view based on the specified XML node
+ */
+ void inflate(const SkDOM& dom, const SkDOM::Node* node);
+ /** After a view hierarchy is inflated, this may be called with a dictionary
+ containing pairs of <name, view*>, where the name string was the view's
+ "id" attribute when it was inflated.
+
+ This will call the virtual onPostInflate for this view, and the recursively
+ call postInflate on all of the view's children.
+ */
+ void postInflate(const SkTDict<SkView*>& ids);
+
+ SkDEBUGCODE(void dump(bool recurse) const;)
+
+protected:
+ /** Override this to draw inside the view. Be sure to call the inherited version too */
+ virtual void onDraw(SkCanvas*);
+ /** Override this to be notified when the view's size changes. Be sure to call the inherited version too */
+ virtual void onSizeChange();
+ /** Override this if you want to handle an inval request from this view or one of its children.
+ Tyically this is only overridden by the by the "window". If your subclass does handle the
+ request, return true so the request will not continue to propogate to the parent.
+ */
+ virtual bool handleInval(const SkRect*);
+ //! called once before all of the children are drawn (or clipped/translated)
+ virtual SkCanvas* beforeChildren(SkCanvas* c) { return c; }
+ //! called once after all of the children are drawn (or clipped/translated)
+ virtual void afterChildren(SkCanvas* orig) {}
+
+ //! called right before this child's onDraw is called
+ virtual void beforeChild(SkView* child, SkCanvas* canvas) {}
+ //! called right after this child's onDraw is called
+ virtual void afterChild(SkView* child, SkCanvas* canvas) {}
+
+ /** Override this if you might handle the click
+ */
+ virtual Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned modi);
+ /** Override this to decide if your children are targets for a click.
+ The default returns true, in which case your children views will be
+ candidates for onFindClickHandler. Returning false wil skip the children
+ and just call your onFindClickHandler.
+ */
+ virtual bool onSendClickToChildren(SkScalar x, SkScalar y, unsigned modi);
+ /** Override this to track clicks, returning true as long as you want to track
+ the pen/mouse.
+ */
+ virtual bool onClick(Click*);
+ /** Override this to initialize your subclass from the XML node. Be sure to call the inherited version too */
+ virtual void onInflate(const SkDOM& dom, const SkDOM::Node* node);
+ /** Override this if you want to perform post initialization work based on the ID dictionary built
+ during XML parsing. Be sure to call the inherited version too.
+ */
+ virtual void onPostInflate(const SkTDict<SkView*>&);
+
+public:
+#ifdef SK_DEBUG
+ void validate() const;
+#else
+ void validate() const {}
+#endif
+ // default action is to inval the view
+ virtual void onFocusChange(bool gainFocusP);
+
+protected:
+
+ // override these if you're acting as a layer/host
+ virtual bool onGetFocusView(SkView**) const { return false; }
+ virtual bool onSetFocusView(SkView*) { return false; }
+
+private:
+ SkScalar fWidth, fHeight;
+ SkMatrix fMatrix;
+ SkPoint fLoc;
+ SkView* fParent;
+ SkView* fFirstChild;
+ SkView* fNextSibling;
+ SkView* fPrevSibling;
+ uint8_t fFlags;
+ uint8_t fContainsFocus;
+
+ friend class B2FIter;
+ friend class F2BIter;
+
+ friend class SkLayerView;
+
+ bool setFocusView(SkView* fvOrNull);
+ SkView* acceptFocus(FocusDirection);
+ void detachFromParent_NoLayout();
+ /** Compute the matrix to transform view-local coordinates into global ones */
+ void localToGlobal(SkMatrix* matrix) const;
+};
+
+#endif
diff --git a/views/SkViewInflate.h b/views/SkViewInflate.h
new file mode 100644
index 0000000..db3689a
--- /dev/null
+++ b/views/SkViewInflate.h
@@ -0,0 +1,71 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkViewInflate_DEFINED
+#define SkViewInflate_DEFINED
+
+#include "SkDOM.h"
+#include "SkTDict.h"
+#include "SkEvent.h"
+
+class SkView;
+
+class SkViewInflate {
+public:
+ SkViewInflate();
+ virtual ~SkViewInflate();
+
+ /** Return the tree of inflated views. If root is null, create the root element
+ as a view, otherwise assume root is that view, and just "inflate" it.
+
+ Returns null if the tree cannot be built.
+ */
+ SkView* inflate(const SkDOM& dom, const SkDOM::Node* node, SkView* root = NULL);
+ SkView* inflate(const char xml[], size_t len, SkView* root = NULL);
+
+ /** Given an id attribute value, return the corresponding view, or null
+ if no match is found.
+ */
+ SkView* findViewByID(const char id[]) const;
+
+ SkDEBUGCODE(void dump() const;)
+
+protected:
+ /* Override this in your subclass to handle instantiating views
+ Call the inherited version for nodes you don't recognize.
+
+ Do not call "inflate" on the view, just return it. This will
+ get called automatically after createView returns.
+ */
+ virtual SkView* createView(const SkDOM& dom, const SkDOM::Node* node);
+ /** Base implementation calls view->inflate(dom, node). Subclasses may override this
+ to perform additional initializations to view, either before or after calling
+ the inherited version.
+ */
+ virtual void inflateView(SkView* view, const SkDOM& dom, const SkDOM::Node* node);
+
+private:
+ enum {
+ kMinIDStrAlloc = 64
+ };
+ SkTDict<SkView*> fIDs;
+
+ struct IDStr {
+ SkView* fView;
+ char* fStr;
+ };
+ SkTDArray<IDStr> fListenTo, fBroadcastTo;
+ SkChunkAlloc fStrings;
+
+ void addIDStr(SkTDArray<IDStr>* list, SkView*, const char* str);
+
+ void rInflate(const SkDOM& dom, const SkDOM::Node* node, SkView* parent);
+};
+
+#endif
diff --git a/views/SkWidget.h b/views/SkWidget.h
new file mode 100644
index 0000000..115e9a4
--- /dev/null
+++ b/views/SkWidget.h
@@ -0,0 +1,412 @@
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkWidget_DEFINED
+#define SkWidget_DEFINED
+
+#include "SkBitmap.h"
+#include "SkDOM.h"
+#include "SkPaint.h"
+#include "SkString.h"
+#include "SkTDArray.h"
+#include "SkTextBox.h"
+#include "SkView.h"
+
+class SkEvent;
+class SkInterpolator;
+class SkShader;
+
+////////////////////////////////////////////////////////////////////////////////
+
+class SkWidget : public SkView {
+public:
+ SkWidget(uint32_t flags = 0) : SkView(flags | kFocusable_Mask | kEnabled_Mask) {}
+
+ /** Call this to post the widget's event to its listeners */
+ void postWidgetEvent();
+
+ static void Init();
+ static void Term();
+protected:
+ // override to add slots to an event before posting
+ virtual void prepareWidgetEvent(SkEvent*);
+ virtual void onEnabledChange();
+
+ // <event ...> to initialize the event from XML
+ virtual void onInflate(const SkDOM& dom, const SkDOM::Node* node);
+
+private:
+ SkEvent fEvent;
+ typedef SkView INHERITED;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+class SkHasLabelWidget : public SkWidget {
+public:
+ SkHasLabelWidget(uint32_t flags = 0) : SkWidget(flags) {}
+
+ size_t getLabel(SkString* label = NULL) const;
+ size_t getLabel(char lable[] = NULL) const;
+ void setLabel(const SkString&);
+ void setLabel(const char label[]);
+ void setLabel(const char label[], size_t len);
+
+protected:
+ // called when the label changes
+ virtual void onLabelChange();
+
+ // overrides
+ virtual void onInflate(const SkDOM& dom, const SkDOM::Node*);
+
+private:
+ SkString fLabel;
+ typedef SkWidget INHERITED;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+class SkButtonWidget : public SkHasLabelWidget {
+public:
+ SkButtonWidget(uint32_t flags = 0) : SkHasLabelWidget(flags), fState(kOff_State) {}
+
+ enum State {
+ kOff_State, //!< XML: buttonState="off"
+ kOn_State, //!< XML: buttonState="on"
+ kUnknown_State //!< XML: buttonState="unknown"
+ };
+ State getButtonState() const { return fState; }
+ void setButtonState(State);
+
+protected:
+ /** called when the label changes. default behavior is to inval the widget */
+ virtual void onButtonStateChange();
+
+ // overrides
+ virtual void onInflate(const SkDOM& dom, const SkDOM::Node*);
+
+private:
+ State fState;
+ typedef SkHasLabelWidget INHERITED;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+class SkPushButtonWidget : public SkButtonWidget {
+public:
+ SkPushButtonWidget(uint32_t flags = 0) : SkButtonWidget(flags) {}
+
+protected:
+ virtual bool onEvent(const SkEvent&);
+ virtual void onDraw(SkCanvas*);
+ virtual Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) SK_OVERRIDE;
+ virtual bool onClick(Click* click);
+
+private:
+ typedef SkButtonWidget INHERITED;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+class SkCheckBoxWidget : public SkButtonWidget {
+public:
+ SkCheckBoxWidget(uint32_t flags = 0);
+
+protected:
+ virtual bool onEvent(const SkEvent&);
+ virtual void onDraw(SkCanvas*);
+ virtual void onInflate(const SkDOM& dom, const SkDOM::Node*);
+
+private:
+ typedef SkButtonWidget INHERITED;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+class SkStaticTextView : public SkView {
+public:
+ SkStaticTextView(uint32_t flags = 0);
+ virtual ~SkStaticTextView();
+
+ enum Mode {
+ kFixedSize_Mode,
+ kAutoWidth_Mode,
+ kAutoHeight_Mode,
+
+ kModeCount
+ };
+ Mode getMode() const { return (Mode)fMode; }
+ void setMode(Mode);
+
+ SkTextBox::SpacingAlign getSpacingAlign() const { return (SkTextBox::SpacingAlign)fSpacingAlign; }
+ void setSpacingAlign(SkTextBox::SpacingAlign);
+
+ void getMargin(SkPoint* margin) const;
+ void setMargin(SkScalar dx, SkScalar dy);
+
+ size_t getText(SkString* text = NULL) const;
+ size_t getText(char text[] = NULL) const;
+ void setText(const SkString&);
+ void setText(const char text[]);
+ void setText(const char text[], size_t len);
+
+ void getPaint(SkPaint*) const;
+ void setPaint(const SkPaint&);
+
+protected:
+ // overrides
+ virtual void onDraw(SkCanvas*);
+ virtual void onInflate(const SkDOM& dom, const SkDOM::Node*);
+
+private:
+ SkPoint fMargin;
+ SkString fText;
+ SkPaint fPaint;
+ uint8_t fMode;
+ uint8_t fSpacingAlign;
+
+ void computeSize();
+
+ typedef SkView INHERITED;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+class SkBitmapView : public SkView {
+public:
+ SkBitmapView(uint32_t flags = 0);
+ virtual ~SkBitmapView();
+
+ bool getBitmap(SkBitmap*) const;
+ void setBitmap(const SkBitmap*, bool viewOwnsPixels);
+ bool loadBitmapFromFile(const char path[]);
+
+protected:
+ virtual void onDraw(SkCanvas*);
+ virtual void onInflate(const SkDOM&, const SkDOM::Node*);
+
+private:
+ SkBitmap fBitmap;
+ typedef SkView INHERITED;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+class SkHasLabelView : public SkView {
+public:
+ void getLabel(SkString*) const;
+ void setLabel(const SkString&);
+ void setLabel(const char label[]);
+
+protected:
+ SkString fLabel;
+
+ // called when the label changes
+ virtual void onLabelChange();
+
+ // overrides
+ virtual void onInflate(const SkDOM& dom, const SkDOM::Node*);
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+class SkPushButtonView : public SkHasLabelView {
+public:
+ SkPushButtonView(uint32_t flags = 0);
+
+protected:
+ virtual void onDraw(SkCanvas*);
+ virtual void onInflate(const SkDOM& dom, const SkDOM::Node*);
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+class SkCheckBoxView : public SkHasLabelView {
+public:
+ SkCheckBoxView(uint32_t flags = 0);
+
+ enum State {
+ kOff_State,
+ kOn_State,
+ kMaybe_State
+ };
+ State getState() const { return fState; }
+ void setState(State);
+
+protected:
+ virtual void onDraw(SkCanvas*);
+ virtual void onInflate(const SkDOM& dom, const SkDOM::Node*);
+
+private:
+ State fState;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+class SkProgressView : public SkView {
+public:
+ SkProgressView(uint32_t flags = 0);
+ virtual ~SkProgressView();
+
+ uint16_t getValue() const { return fValue; }
+ uint16_t getMax() const { return fMax; }
+
+ void setMax(U16CPU max);
+ void setValue(U16CPU value);
+
+protected:
+ virtual void onDraw(SkCanvas*);
+ virtual void onInflate(const SkDOM& dom, const SkDOM::Node* node);
+
+private:
+ uint16_t fValue, fMax;
+ SkShader* fOnShader, *fOffShader;
+ SkInterpolator* fInterp;
+ bool fDoInterp;
+
+ typedef SkView INHERITED;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+class SkListSource : public SkEventSink {
+public:
+ virtual int countRows() = 0;
+ virtual void getRow(int index, SkString* left, SkString* right) = 0;
+ virtual SkEvent* getEvent(int index);
+
+ static SkListSource* CreateFromDir(const char path[], const char suffix[],
+ const char targetPrefix[]);
+ static SkListSource* CreateFromDOM(const SkDOM& dom, const SkDOM::Node* node);
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+class SkListView : public SkView {
+public:
+ SkListView(uint32_t flags = 0);
+ virtual ~SkListView();
+
+ SkScalar getRowHeight() const { return fRowHeight; }
+ void setRowHeight(SkScalar);
+
+ /** Return the index of the selected row, or -1 if none
+ */
+ int getSelection() const { return fCurrIndex; }
+ /** Set the index of the selected row, or -1 for none
+ */
+ void setSelection(int);
+
+ void moveSelectionUp();
+ void moveSelectionDown();
+
+ enum Attr {
+ kBG_Attr,
+ kNormalText_Attr,
+ kHiliteText_Attr,
+ kHiliteCell_Attr,
+ kAttrCount
+ };
+ SkPaint& paint(Attr);
+
+ SkListSource* getListSource() const { return fSource; }
+ SkListSource* setListSource(SkListSource*);
+
+#if 0
+ enum Action {
+ kSelectionChange_Action,
+ kSelectionPicked_Action,
+ kActionCount
+ };
+ /** If event is not null, it is retained by the view, and a copy
+ of the event will be posted to its listeners when the specified
+ action occurs. If event is null, then no event will be posted for
+ the specified action.
+ */
+ void setActionEvent(Action, SkEvent* event);
+#endif
+
+protected:
+ virtual void onDraw(SkCanvas*);
+ virtual void onSizeChange();
+ virtual bool onEvent(const SkEvent&);
+ virtual void onInflate(const SkDOM& dom, const SkDOM::Node* node);
+
+private:
+ SkPaint fPaint[kAttrCount];
+ SkListSource* fSource;
+ SkScalar fRowHeight;
+ int fCurrIndex; // logical index
+ int fScrollIndex; // logical index of top-most visible row
+ int fVisibleRowCount;
+ SkString* fStrCache;
+
+ void dirtyStrCache();
+ void ensureStrCache(int visibleCount);
+
+ int logicalToVisualIndex(int index) const { return index - fScrollIndex; }
+ void invalSelection();
+ bool getRowRect(int index, SkRect*) const;
+ void ensureSelectionIsVisible();
+
+ typedef SkView INHERITED;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+class SkGridView : public SkView {
+public:
+ SkGridView(uint32_t flags = 0);
+ virtual ~SkGridView();
+
+ void getCellSize(SkPoint*) const;
+ void setCellSize(SkScalar x, SkScalar y);
+
+ /** Return the index of the selected item, or -1 if none
+ */
+ int getSelection() const { return fCurrIndex; }
+ /** Set the index of the selected row, or -1 for none
+ */
+ void setSelection(int);
+
+ void moveSelectionUp();
+ void moveSelectionDown();
+
+ enum Attr {
+ kBG_Attr,
+ kHiliteCell_Attr,
+ kAttrCount
+ };
+ SkPaint& paint(Attr);
+
+ SkListSource* getListSource() const { return fSource; }
+ SkListSource* setListSource(SkListSource*);
+
+protected:
+ virtual void onDraw(SkCanvas*);
+ virtual void onSizeChange();
+ virtual bool onEvent(const SkEvent&);
+ virtual void onInflate(const SkDOM& dom, const SkDOM::Node* node);
+
+private:
+ SkView* fScrollBar;
+ SkPaint fPaint[kAttrCount];
+ SkListSource* fSource;
+ int fCurrIndex; // logical index
+
+ SkPoint fCellSize;
+ SkIPoint fVisibleCount;
+
+ int logicalToVisualIndex(int index) const { return index; }
+ void invalSelection();
+ bool getCellRect(int index, SkRect*) const;
+ void ensureSelectionIsVisible();
+
+ typedef SkView INHERITED;
+};
+
+#endif
diff --git a/views/SkWindow.h b/views/SkWindow.h
new file mode 100644
index 0000000..ca68e75
--- /dev/null
+++ b/views/SkWindow.h
@@ -0,0 +1,121 @@
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkWindow_DEFINED
+#define SkWindow_DEFINED
+
+#include "SkView.h"
+#include "SkBitmap.h"
+#include "SkMatrix.h"
+#include "SkRegion.h"
+#include "SkEvent.h"
+#include "SkKey.h"
+#include "SkTDArray.h"
+
+#ifdef SK_BUILD_FOR_WINCEx
+ #define SHOW_FPS
+#endif
+//#define USE_GX_SCREEN
+
+class SkCanvas;
+
+class SkOSMenu;
+
+class SkWindow : public SkView {
+public:
+ SkWindow();
+ virtual ~SkWindow();
+
+ const SkBitmap& getBitmap() const { return fBitmap; }
+
+ void setConfig(SkBitmap::Config);
+ void resize(int width, int height, SkBitmap::Config config = SkBitmap::kNo_Config);
+ void eraseARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b);
+ void eraseRGB(U8CPU r, U8CPU g, U8CPU b);
+
+ bool isDirty() const { return !fDirtyRgn.isEmpty(); }
+ bool update(SkIRect* updateArea);
+ // does not call through to onHandleInval(), but does force the fDirtyRgn
+ // to be wide open. Call before update() to ensure we redraw everything.
+ void forceInvalAll();
+ // return the bounds of the dirty/inval rgn, or [0,0,0,0] if none
+ const SkIRect& getDirtyBounds() const { return fDirtyRgn.getBounds(); }
+
+ bool handleClick(int x, int y, Click::State, void* owner, unsigned modi = 0);
+ bool handleChar(SkUnichar);
+ bool handleKey(SkKey);
+ bool handleKeyUp(SkKey);
+
+ void addMenu(SkOSMenu*);
+ const SkTDArray<SkOSMenu*>* getMenus() { return &fMenus; }
+
+ const char* getTitle() const { return fTitle.c_str(); }
+ void setTitle(const char title[]);
+
+ const SkMatrix& getMatrix() const { return fMatrix; }
+ void setMatrix(const SkMatrix&);
+ void preConcat(const SkMatrix&);
+ void postConcat(const SkMatrix&);
+
+ virtual SkCanvas* createCanvas();
+
+ virtual void onPDFSaved(const char title[], const char desc[],
+ const char path[]) {}
+protected:
+ virtual bool onEvent(const SkEvent&);
+ virtual bool onDispatchClick(int x, int y, Click::State, void* owner, unsigned modi);
+ // called if part of our bitmap is invalidated
+ virtual void onHandleInval(const SkIRect&);
+ virtual bool onHandleChar(SkUnichar);
+ virtual bool onHandleKey(SkKey);
+ virtual bool onHandleKeyUp(SkKey);
+ virtual void onAddMenu(const SkOSMenu*) {};
+ virtual void onUpdateMenu(const SkOSMenu*) {};
+ virtual void onSetTitle(const char title[]) {}
+
+ // overrides from SkView
+ virtual bool handleInval(const SkRect*);
+ virtual bool onGetFocusView(SkView** focus) const;
+ virtual bool onSetFocusView(SkView* focus);
+
+private:
+ SkBitmap::Config fConfig;
+ SkBitmap fBitmap;
+ SkRegion fDirtyRgn;
+
+ SkTDArray<Click*> fClicks; // to track clicks
+
+ SkTDArray<SkOSMenu*> fMenus;
+
+ SkView* fFocusView;
+ bool fWaitingOnInval;
+
+ SkString fTitle;
+ SkMatrix fMatrix;
+
+ typedef SkView INHERITED;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+#if defined(SK_BUILD_FOR_NACL)
+ #include "SkOSWindow_NaCl.h"
+#elif defined(SK_BUILD_FOR_MAC)
+ #include "SkOSWindow_Mac.h"
+#elif defined(SK_BUILD_FOR_WIN)
+ #include "SkOSWindow_Win.h"
+#elif defined(SK_BUILD_FOR_ANDROID)
+ #include "SkOSWindow_Android.h"
+#elif defined(SK_BUILD_FOR_UNIX)
+ #include "SkOSWindow_Unix.h"
+#elif defined(SK_BUILD_FOR_SDL)
+ #include "SkOSWindow_SDL.h"
+#elif defined(SK_BUILD_FOR_IOS)
+ #include "SkOSWindow_iOS.h"
+#endif
+
+#endif
diff --git a/views/android/AndroidKeyToSkKey.h b/views/android/AndroidKeyToSkKey.h
new file mode 100644
index 0000000..6bcb148
--- /dev/null
+++ b/views/android/AndroidKeyToSkKey.h
@@ -0,0 +1,35 @@
+
+/*
+ * Copyright 2011 Skia
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef _ANDROID_TO_SKIA_KEYCODES_H
+#define _ANDROID_TO_SKIA_KEYCODES_H
+
+#include "android/keycodes.h"
+#include "SkKey.h"
+
+// Convert an Android keycode to an SkKey. This is an incomplete list, only
+// including keys used by the sample app.
+SkKey AndroidKeycodeToSkKey(int keycode) {
+ switch (keycode) {
+ case AKEYCODE_DPAD_LEFT:
+ return kLeft_SkKey;
+ case AKEYCODE_DPAD_RIGHT:
+ return kRight_SkKey;
+ case AKEYCODE_DPAD_UP:
+ return kUp_SkKey;
+ case AKEYCODE_DPAD_DOWN:
+ return kDown_SkKey;
+ case AKEYCODE_BACK:
+ return kBack_SkKey;
+ default:
+ return kNONE_SkKey;
+ }
+}
+
+#endif
diff --git a/views/animated/SkBorderView.h b/views/animated/SkBorderView.h
new file mode 100644
index 0000000..8b1e537
--- /dev/null
+++ b/views/animated/SkBorderView.h
@@ -0,0 +1,40 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkBorderView_DEFINED
+#define SkBorderView_DEFINED
+
+#include "SkView.h"
+#include "SkWidgetViews.h"
+#include "SkAnimator.h"
+
+class SkBorderView : public SkWidgetView {
+public:
+ SkBorderView();
+ ~SkBorderView();
+ void setSkin(const char skin[]);
+ SkScalar getLeft() const { return fLeft; }
+ SkScalar getRight() const { return fRight; }
+ SkScalar getTop() const { return fTop; }
+ SkScalar getBottom() const { return fBottom; }
+protected:
+ //overrides
+ virtual void onInflate(const SkDOM& dom, const SkDOM::Node* node);
+ virtual void onSizeChange();
+ virtual void onDraw(SkCanvas* canvas);
+ virtual bool onEvent(const SkEvent& evt);
+private:
+ SkAnimator fAnim;
+ SkScalar fLeft, fRight, fTop, fBottom; //margin on each side
+ SkRect fMargin;
+
+ typedef SkWidgetView INHERITED;
+};
+
+#endif
diff --git a/views/animated/SkImageView.h b/views/animated/SkImageView.h
new file mode 100644
index 0000000..a21da0b
--- /dev/null
+++ b/views/animated/SkImageView.h
@@ -0,0 +1,68 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkImageView_DEFINED
+#define SkImageView_DEFINED
+
+#include "SkView.h"
+#include "SkString.h"
+
+class SkAnimator;
+class SkBitmap;
+class SkMatrix;
+
+class SkImageView : public SkView {
+public:
+ SkImageView();
+ virtual ~SkImageView();
+
+ void getUri(SkString*) const;
+ void setUri(const char []);
+ void setUri(const SkString&);
+
+
+ enum ScaleType {
+ kMatrix_ScaleType,
+ kFitXY_ScaleType,
+ kFitStart_ScaleType,
+ kFitCenter_ScaleType,
+ kFitEnd_ScaleType
+ };
+ ScaleType getScaleType() const { return (ScaleType)fScaleType; }
+ void setScaleType(ScaleType);
+
+ bool getImageMatrix(SkMatrix*) const;
+ void setImageMatrix(const SkMatrix*);
+
+protected:
+ // overrides
+ virtual bool onEvent(const SkEvent&);
+ virtual void onDraw(SkCanvas*);
+ virtual void onInflate(const SkDOM&, const SkDOMNode*);
+
+private:
+ SkString fUri;
+ SkMatrix* fMatrix; // null or copy of caller's matrix ,,,,,
+ union {
+ SkAnimator* fAnim;
+ SkBitmap* fBitmap;
+ } fData;
+ uint8_t fScaleType;
+ SkBool8 fDataIsAnim; // as opposed to bitmap
+ SkBool8 fUriIsValid;
+
+ void onUriChange();
+ bool getDataBounds(SkRect* bounds);
+ bool freeData();
+ bool ensureUriIsLoaded();
+
+ typedef SkView INHERITED;
+};
+
+#endif
diff --git a/views/animated/SkProgressBarView.h b/views/animated/SkProgressBarView.h
new file mode 100644
index 0000000..7e670a9
--- /dev/null
+++ b/views/animated/SkProgressBarView.h
@@ -0,0 +1,50 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkProgressBarView_DEFINED
+#define SkProgressBarView_DEFINED
+
+#include "SkView.h"
+#include "SkWidgetViews.h"
+#include "SkAnimator.h"
+
+class SkProgressBarView : public SkWidgetView {
+ public:
+ SkProgressBarView();
+ //SkProgressBarView(int max);
+
+ //inflate: "sk-progress"
+
+ void reset(); //reset progress to zero
+ void setProgress(int progress);
+ void changeProgress(int diff);
+ void setMax(int max);
+
+ int getProgress() const { return fProgress; }
+ int getMax() const { return fMax; }
+
+ protected:
+ //overrides
+ virtual void onInflate(const SkDOM& dom, const SkDOM::Node* node);
+ virtual void onSizeChange();
+ virtual void onDraw(SkCanvas* canvas);
+ virtual bool onEvent(const SkEvent& evt);
+
+ private:
+ SkAnimator fAnim;
+ int fProgress;
+ int fMax;
+
+ typedef SkWidgetView INHERITED;
+};
+
+
+
+
+#endif
diff --git a/views/animated/SkScrollBarView.h b/views/animated/SkScrollBarView.h
new file mode 100644
index 0000000..05042f0
--- /dev/null
+++ b/views/animated/SkScrollBarView.h
@@ -0,0 +1,44 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkScrollBarView_DEFINED
+#define SkScrollBarView_DEFINED
+
+#include "SkView.h"
+#include "SkWidgetViews.h"
+#include "SkAnimator.h"
+
+class SkScrollBarView : public SkWidgetView {
+public:
+ SkScrollBarView();
+
+ unsigned getStart() const { return fStartPoint; }
+ unsigned getShown() const { return fShownLength; }
+ unsigned getTotal() const { return fTotalLength; }
+
+ void setStart(unsigned start);
+ void setShown(unsigned shown);
+ void setTotal(unsigned total);
+
+protected:
+ //overrides
+ virtual void onInflate(const SkDOM& dom, const SkDOM::Node* node);
+ virtual void onSizeChange();
+ virtual void onDraw(SkCanvas* canvas);
+ virtual bool onEvent(const SkEvent& evt);
+
+private:
+ SkAnimator fAnim;
+ unsigned fTotalLength, fStartPoint, fShownLength;
+
+ void adjust();
+
+ typedef SkWidgetView INHERITED;
+};
+#endif
diff --git a/views/animated/SkWidgetViews.h b/views/animated/SkWidgetViews.h
new file mode 100644
index 0000000..4034660
--- /dev/null
+++ b/views/animated/SkWidgetViews.h
@@ -0,0 +1,309 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkWidgetViews_DEFINED
+#define SkWidgetViews_DEFINED
+
+#include "SkView.h"
+
+
+enum SkWidgetEnum {
+ kBorder_WidgetEnum, //!< <sk-border>
+ kButton_WidgetEnum, //!< <sk-button>
+ kImage_WidgetEnum, //!< <sk-image>
+ kList_WidgetEnum, //!< <sk-list>
+ kProgress_WidgetEnum, //!< <sk-progress>
+ kScroll_WidgetEnum, //!< <sk-scroll>
+ kText_WidgetEnum, //!< <sk-text>
+
+ kWidgetEnumCount
+};
+
+//determines which skin to use
+enum SkinEnum {
+ kBorder_SkinEnum,
+ kButton_SkinEnum,
+ kProgress_SkinEnum,
+ kScroll_SkinEnum,
+ kStaticText_SkinEnum,
+
+ kSkinEnumCount
+};
+
+#include "SkAnimator.h"
+//used for inflates
+const char* get_skin_enum_path(SkinEnum se);
+void init_skin_anim(const char path[], SkAnimator* anim);
+void init_skin_anim(SkinEnum se, SkAnimator* anim);
+void init_skin_paint(SkinEnum se, SkPaint* paint);
+void inflate_paint(const SkDOM& dom, const SkDOM::Node* node, SkPaint* paint);
+
+/** Given an enum value, return an instance of the specified widget.
+ If the enum is out of range, returns null
+*/
+SkView* SkWidgetFactory(SkWidgetEnum);
+/** Given the inflate/element name of a widget, return an instance of
+ the specified widget, or null if name does not match any known
+ widget type.
+*/
+SkView* SkWidgetFactory(const char name[]);
+
+////////////////////////////////////////////////////////////////////////////////////////////////
+
+class SkWidgetView : public SkView {
+public:
+ SkWidgetView();
+
+ const char* getLabel() const;
+ void getLabel(SkString* label) const;
+
+ void setLabel(const char[]);
+ void setLabel(const char[], size_t len);
+ void setLabel(const SkString&);
+
+ SkEvent& event() { return fEvent; }
+ const SkEvent& event() const { return fEvent; }
+
+ /** Returns true if the widget can post its event to its listeners.
+ */
+ bool postWidgetEvent();
+
+ /** Returns the sinkID of the widgetview that posted the event, or 0
+ */
+ static SkEventSinkID GetWidgetEventSinkID(const SkEvent&);
+
+protected:
+ /** called when the label changes. override in subclasses. default action invals the view's bounds.
+ called with the old and new labels, before the label has actually changed.
+ */
+ virtual void onLabelChange(const char oldLabel[], const char newLabel[]);
+ /** called before posting the event to our listeners. Override to add slots to the event
+ before posting. Return true to proceed with posting, or false to not post the event to any
+ listener. Note: the event passed in may not be the same as calling this->event().
+ Be sure to call your INHERITED method as well, so that all classes in the hierarchy get a shot
+ at modifying the event (and possibly returning false to abort).
+ */
+ virtual bool onPrepareWidgetEvent(SkEvent* evt);
+
+ // overrides
+ virtual void onInflate(const SkDOM& dom, const SkDOM::Node*);
+
+private:
+ SkString fLabel;
+ SkEvent fEvent;
+
+ typedef SkView INHERITED;
+};
+
+////////////////////////////////////////////////////////////////////////////////////////////////
+
+class SkButtonView : public SkWidgetView {
+public:
+ // inflate: "sk-button"
+
+protected:
+ // overrides
+ virtual bool onEvent(const SkEvent&);
+private:
+ typedef SkWidgetView INHERITED;
+};
+
+////////////////////////////////////////////////////////////////////////////////////////////////
+
+class SkCheckButtonView : public SkWidgetView {
+public:
+ SkCheckButtonView();
+
+ // inflate: "sk-checkbutton"
+
+ enum CheckState {
+ kOff_CheckState, //!< inflate: check-state="off"
+ kOn_CheckState, //!< inflate: check-state="on"
+ kUnknown_CheckState //!< inflate: check-state="unknown"
+ };
+ CheckState getCheckState() const { return (CheckState)fCheckState; }
+ void setCheckState(CheckState);
+
+ /** use this to extract the CheckState from an event (i.e. one that as posted
+ by a SkCheckButtonView). Returns true if the proper slot was present in the event,
+ and sets state to that value. If no proper slot is found, returns false and does not
+ modify state.
+ */
+ static bool GetWidgetEventCheckState(const SkEvent&, CheckState* state);
+
+protected:
+ // called when the check-state is about to change, but before it actually has
+ virtual void onCheckStateChange(CheckState oldState, CheckState newState);
+
+ // overrides
+ virtual void onInflate(const SkDOM& dom, const SkDOM::Node*);
+ virtual bool onPrepareWidgetEvent(SkEvent* evt);
+
+private:
+ uint8_t fCheckState;
+
+ typedef SkWidgetView INHERITED;
+};
+
+////////////////////////////////////////////////////////////////////////////////////////////////
+#include "SkTextBox.h"
+
+class SkStaticTextView : public SkView {
+public:
+ SkStaticTextView();
+ virtual ~SkStaticTextView();
+
+ enum Mode {
+ kFixedSize_Mode,
+ kAutoWidth_Mode,
+ kAutoHeight_Mode,
+
+ kModeCount
+ };
+ Mode getMode() const { return (Mode)fMode; }
+ void setMode(Mode);
+
+ SkTextBox::SpacingAlign getSpacingAlign() const { return (SkTextBox::SpacingAlign)fSpacingAlign; }
+ void setSpacingAlign(SkTextBox::SpacingAlign);
+
+ void getMargin(SkPoint* margin) const;
+ void setMargin(SkScalar dx, SkScalar dy);
+
+ size_t getText(SkString* text = NULL) const;
+ size_t getText(char text[] = NULL) const;
+ void setText(const SkString&);
+ void setText(const char text[]);
+ void setText(const char text[], size_t len);
+
+ void getPaint(SkPaint*) const;
+ void setPaint(const SkPaint&);
+
+protected:
+ // overrides
+ virtual void onDraw(SkCanvas*);
+ virtual void onInflate(const SkDOM& dom, const SkDOM::Node*);
+
+private:
+ SkPoint fMargin;
+ SkString fText;
+ SkPaint fPaint;
+ uint8_t fMode;
+ uint8_t fSpacingAlign;
+
+ void computeSize();
+
+ typedef SkView INHERITED;
+};
+
+////////////////////////////////////////////////////////////////////////////////////////////////
+
+class SkAnimator;
+class SkListSource;
+class SkScrollBarView;
+
+class SkListView : public SkWidgetView {
+public:
+ SkListView();
+ virtual ~SkListView();
+
+ bool hasScrollBar() const { return fScrollBar != NULL; }
+ void setHasScrollBar(bool);
+
+ /** Return the number of visible rows
+ */
+ int getVisibleRowCount() const { return fVisibleRowCount; }
+ /** Return the index of the selected row, or -1 if none
+ */
+ int getSelection() const { return fCurrIndex; }
+ /** Set the index of the selected row, or -1 for none
+ */
+ void setSelection(int);
+ /** If possible, move the selection up and return true,
+ else do nothing and return false
+ If nothing is selected, select the last item (unless there are no items).
+ */
+ bool moveSelectionUp();
+ /** If possible, move the selection down and return true,
+ else do nothing and return false.
+ If nothing is selected, select the first item (unless there are no items).
+ */
+ bool moveSelectionDown();
+
+ SkListSource* getListSource() const { return fSource; }
+ SkListSource* setListSource(SkListSource*);
+
+ /** Call this in your event handler. If the specified event is from a SkListView,
+ then it returns the index of the selected item in this list, otherwise it
+ returns -1
+ */
+ static int GetWidgetEventListIndex(const SkEvent&);
+
+protected:
+ // overrides
+ virtual void onDraw(SkCanvas*);
+ virtual void onSizeChange();
+ virtual bool onEvent(const SkEvent&);
+ virtual void onInflate(const SkDOM& dom, const SkDOM::Node* node);
+ virtual bool onPrepareWidgetEvent(SkEvent*);
+
+private:
+ enum DirtyFlags {
+ kAnimCount_DirtyFlag = 0x01,
+ kAnimContent_DirtyFlag = 0x02
+ };
+ void dirtyCache(unsigned dirtyFlags);
+ bool ensureCache();
+
+ int logicalToVisualIndex(int index) const { return index - fScrollIndex; }
+ void invalSelection();
+ SkScalar getContentWidth() const;
+ bool getRowRect(int index, SkRect*) const;
+ void ensureSelectionIsVisible();
+ void ensureVisibleRowCount();
+
+ struct BindingRec;
+
+ enum Heights {
+ kNormal_Height,
+ kSelected_Height
+ };
+ SkListSource* fSource;
+ SkScrollBarView* fScrollBar;
+ SkAnimator* fAnims;
+ BindingRec* fBindings;
+ SkString fSkinName;
+ SkScalar fHeights[2];
+ int16_t fScrollIndex, fCurrIndex;
+ uint16_t fVisibleRowCount, fBindingCount;
+ SkBool8 fAnimContentDirty;
+ SkBool8 fAnimFocusDirty;
+
+ typedef SkWidgetView INHERITED;
+};
+
+class SkListSource : public SkRefCnt {
+public:
+ SK_DECLARE_INST_COUNT(SkListSource)
+
+ virtual int countFields();
+ virtual void getFieldName(int index, SkString* field);
+ /** Return the index of the named field, or -1 if not found */
+ virtual int findFieldIndex(const char field[]);
+
+ virtual int countRecords();
+ virtual void getRecord(int rowIndex, int fieldIndex, SkString* data);
+
+ virtual bool prepareWidgetEvent(SkEvent*, int rowIndex);
+
+ static SkListSource* Factory(const char name[]);
+private:
+ typedef SkRefCnt INHERITED;
+};
+
+#endif
diff --git a/views/unix/XkeysToSkKeys.h b/views/unix/XkeysToSkKeys.h
new file mode 100644
index 0000000..30eb97d
--- /dev/null
+++ b/views/unix/XkeysToSkKeys.h
@@ -0,0 +1,38 @@
+
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#include "X11/Xlib.h"
+#include "X11/keysym.h"
+
+#include "SkKey.h"
+
+#ifndef XKEYS_TOSKKEYS_H
+#define XKEYS_TOSKKEYS_H
+
+SkKey XKeyToSkKey(KeySym keysym) {
+ switch (keysym) {
+ case XK_BackSpace:
+ return kBack_SkKey;
+ case XK_Return:
+ return kOK_SkKey;
+ case XK_Home:
+ return kHome_SkKey;
+ case XK_End:
+ return kEnd_SkKey;
+ case XK_Right:
+ return kRight_SkKey;
+ case XK_Left:
+ return kLeft_SkKey;
+ case XK_Down:
+ return kDown_SkKey;
+ case XK_Up:
+ return kUp_SkKey;
+ default:
+ return kNONE_SkKey;
+ }
+}
+#endif
diff --git a/views/unix/keysym2ucs.h b/views/unix/keysym2ucs.h
new file mode 100644
index 0000000..255a930
--- /dev/null
+++ b/views/unix/keysym2ucs.h
@@ -0,0 +1,15 @@
+
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+/*
+ * This module converts keysym values into the corresponding ISO 10646-1
+ * (UCS, Unicode) values.
+ */
+
+#include <X11/X.h>
+
+long keysym2ucs(KeySym keysym);
diff --git a/xml/SkBML_WXMLParser.h b/xml/SkBML_WXMLParser.h
new file mode 100644
index 0000000..74f164c
--- /dev/null
+++ b/xml/SkBML_WXMLParser.h
@@ -0,0 +1,46 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkBML_WXMLParser_DEFINED
+#define SkBML_WXMLParser_DEFINED
+
+#include "SkString.h"
+#include "SkXMLParser.h"
+
+class SkStream;
+class SkWStream;
+
+class BML_WXMLParser : public SkXMLParser {
+public:
+ BML_WXMLParser(SkWStream& writer);
+ virtual ~BML_WXMLParser();
+ static void Write(SkStream& s, const char filename[]);
+
+ /** @cond UNIT_TEST */
+ SkDEBUGCODE(static void UnitTest();)
+ /** @endcond */
+private:
+ virtual bool onAddAttribute(const char name[], const char value[]);
+ virtual bool onEndElement(const char name[]);
+ virtual bool onStartElement(const char name[]);
+ BML_WXMLParser& operator=(const BML_WXMLParser& src);
+#ifdef SK_DEBUG
+ int fElemsCount, fElemsReused;
+ int fAttrsCount, fNamesReused, fValuesReused;
+#endif
+ SkWStream& fWriter;
+ char* fElems[256];
+ char* fAttrNames[256];
+ char* fAttrValues[256];
+
+ // important that these are U8, so we get automatic wrap-around
+ U8 fNextElem, fNextAttrName, fNextAttrValue;
+};
+
+#endif // SkBML_WXMLParser_DEFINED
diff --git a/xml/SkBML_XMLParser.h b/xml/SkBML_XMLParser.h
new file mode 100644
index 0000000..9bdbf51
--- /dev/null
+++ b/xml/SkBML_XMLParser.h
@@ -0,0 +1,31 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkBML_XMLParser_DEFINED
+#define SkBML_XMLParser_DEFINED
+
+class SkStream;
+class SkWStream;
+class SkXMLParser;
+class SkXMLWriter;
+
+class BML_XMLParser {
+public:
+ /** Read the byte XML stream and write the decompressed XML.
+ */
+ static void Read(SkStream& s, SkXMLWriter& writer);
+ /** Read the byte XML stream and write the decompressed XML into a writable stream.
+ */
+ static void Read(SkStream& s, SkWStream& output);
+ /** Read the byte XML stream and write the decompressed XML into an XML parser.
+ */
+ static void Read(SkStream& s, SkXMLParser& output);
+};
+
+#endif // SkBML_XMLParser_DEFINED
diff --git a/xml/SkDOM.h b/xml/SkDOM.h
new file mode 100644
index 0000000..e0bb744
--- /dev/null
+++ b/xml/SkDOM.h
@@ -0,0 +1,91 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkDOM_DEFINED
+#define SkDOM_DEFINED
+
+#include "SkChunkAlloc.h"
+#include "SkScalar.h"
+#include "SkTemplates.h"
+
+struct SkDOMNode;
+struct SkDOMAttr;
+
+class SkDOM {
+public:
+ SkDOM();
+ ~SkDOM();
+
+ typedef SkDOMNode Node;
+ typedef SkDOMAttr Attr;
+
+ /** Returns null on failure
+ */
+ const Node* build(const char doc[], size_t len);
+ const Node* copy(const SkDOM& dom, const Node* node);
+
+ const Node* getRootNode() const;
+
+ enum Type {
+ kElement_Type,
+ kText_Type
+ };
+ Type getType(const Node*) const;
+
+ const char* getName(const Node*) const;
+ const Node* getFirstChild(const Node*, const char elem[] = NULL) const;
+ const Node* getNextSibling(const Node*, const char elem[] = NULL) const;
+
+ const char* findAttr(const Node*, const char attrName[]) const;
+ const Attr* getFirstAttr(const Node*) const;
+ const Attr* getNextAttr(const Node*, const Attr*) const;
+ const char* getAttrName(const Node*, const Attr*) const;
+ const char* getAttrValue(const Node*, const Attr*) const;
+
+ // helpers for walking children
+ int countChildren(const Node* node, const char elem[] = NULL) const;
+
+ // helpers for calling SkParse
+ bool findS32(const Node*, const char name[], int32_t* value) const;
+ bool findScalars(const Node*, const char name[], SkScalar value[], int count) const;
+ bool findHex(const Node*, const char name[], uint32_t* value) const;
+ bool findBool(const Node*, const char name[], bool*) const;
+ int findList(const Node*, const char name[], const char list[]) const;
+
+ bool findScalar(const Node* node, const char name[], SkScalar value[]) const
+ {
+ return this->findScalars(node, name, value, 1);
+ }
+
+ bool hasAttr(const Node*, const char name[], const char value[]) const;
+ bool hasS32(const Node*, const char name[], int32_t value) const;
+ bool hasScalar(const Node*, const char name[], SkScalar value) const;
+ bool hasHex(const Node*, const char name[], uint32_t value) const;
+ bool hasBool(const Node*, const char name[], bool value) const;
+
+ class AttrIter {
+ public:
+ AttrIter(const class SkDOM&, const Node*);
+ const char* next(const char** value);
+ private:
+ const Attr* fAttr;
+ const Attr* fStop;
+ };
+
+ SkDEBUGCODE(void dump(const Node* node = NULL, int tabLevel = 0) const;)
+ SkDEBUGCODE(static void UnitTest();)
+
+private:
+ SkChunkAlloc fAlloc;
+ Node* fRoot;
+ friend class AttrIter;
+ friend class SkDOMParser;
+};
+
+#endif
diff --git a/xml/SkJS.h b/xml/SkJS.h
new file mode 100644
index 0000000..8a11097
--- /dev/null
+++ b/xml/SkJS.h
@@ -0,0 +1,39 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#include "SkTypes.h"
+#include "SkWindow.h"
+
+extern "C" {
+ typedef long JSWord;
+ typedef JSWord jsword;
+ typedef jsword jsval;
+ typedef struct JSRuntime JSRuntime;
+ typedef struct JSContext JSContext;
+ typedef struct JSObject JSObject;
+}
+
+class SkString;
+
+class SkJS : public SkOSWindow {
+public:
+ SkJS(void* hwnd);
+ ~SkJS();
+ SkBool EvaluateScript(const char* script, jsval* rVal);
+ SkBool ValueToString(jsval value, SkString* string);
+#ifdef SK_DEBUG
+ static void Test(void* hwnd);
+#endif
+protected:
+ void InitializeDisplayables(const SkBitmap& , JSContext *, JSObject *, JSObject *);
+ void DisposeDisplayables();
+ JSRuntime *fRuntime;
+ JSContext *fContext;
+ JSObject *fGlobal;
+};
diff --git a/xml/SkXMLParser.h b/xml/SkXMLParser.h
new file mode 100644
index 0000000..1a90bf7
--- /dev/null
+++ b/xml/SkXMLParser.h
@@ -0,0 +1,155 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkXMLParser_DEFINED
+#define SkXMLParser_DEFINED
+
+#include "SkString.h"
+
+class SkStream;
+
+class SkDOM;
+struct SkDOMNode;
+
+class SkXMLParserError {
+public:
+ enum ErrorCode {
+ kNoError,
+ kEmptyFile,
+ kUnknownElement,
+ kUnknownAttributeName,
+ kErrorInAttributeValue,
+ kDuplicateIDs,
+ kUnknownError
+ };
+
+ SkXMLParserError();
+ virtual ~SkXMLParserError();
+ ErrorCode getErrorCode() const { return fCode; }
+ virtual void getErrorString(SkString* str) const;
+ int getLineNumber() const { return fLineNumber; }
+ int getNativeCode() const { return fNativeCode; }
+ bool hasError() const { return fCode != kNoError || fNativeCode != -1; }
+ bool hasNoun() const { return fNoun.size() > 0; }
+ void reset();
+ void setCode(ErrorCode code) { fCode = code; }
+ void setNoun(const SkString& str) { fNoun.set(str); }
+ void setNoun(const char* ch) { fNoun.set(ch); }
+ void setNoun(const char* ch, size_t len) { fNoun.set(ch, len); }
+protected:
+ ErrorCode fCode;
+private:
+ int fLineNumber;
+ int fNativeCode;
+ SkString fNoun;
+ friend class SkXMLParser;
+};
+
+class SkXMLParser {
+public:
+ SkXMLParser(SkXMLParserError* parserError = NULL);
+ virtual ~SkXMLParser();
+
+ /** Returns true for success
+ */
+ bool parse(const char doc[], size_t len);
+ bool parse(SkStream& docStream);
+ bool parse(const SkDOM&, const SkDOMNode*);
+
+ static void GetNativeErrorString(int nativeErrorCode, SkString* str);
+
+protected:
+ // override in subclasses; return true to stop parsing
+ virtual bool onStartElement(const char elem[]);
+ virtual bool onAddAttribute(const char name[], const char value[]);
+ virtual bool onEndElement(const char elem[]);
+ virtual bool onText(const char text[], int len);
+
+public:
+ // public for ported implementation, not meant for clients to call
+ virtual bool startElement(const char elem[]);
+ virtual bool addAttribute(const char name[], const char value[]);
+ virtual bool endElement(const char elem[]);
+ virtual bool text(const char text[], int len);
+ void* fParser;
+protected:
+ SkXMLParserError* fError;
+private:
+ void reportError(void* parser);
+};
+
+#if 0
+class SkXMLPullParser {
+public:
+ SkXMLPullParser();
+ explicit SkXMLPullParser(SkStream*);
+ virtual ~SkXMLPullParser();
+
+ SkStream* getStream() const { return fStream; }
+ SkStream* setStream(SkStream* stream);
+
+ enum EventType {
+ ERROR = -1,
+ START_DOCUMENT,
+ END_DOCUMENT,
+ START_TAG,
+ END_TAG,
+ TEXT,
+ CDSECT,
+ ENTITY_REF,
+ IGNORABLE_WHITESPACE,
+ PROCESSING_INSTRUCTION,
+ COMMENT,
+ DOCDECL
+ };
+
+ EventType nextToken();
+ EventType getEventType() const { return fCurr.fEventType; }
+
+ struct AttrInfo {
+ const char* fName;
+ const char* fValue;
+ };
+
+ int getDepth() const { return fDepth; }
+ const char* getName();
+ int getAttributeCount();
+ void getAttributeInfo(int, AttrInfo*);
+ const char* getText();
+ bool isWhitespace();
+
+protected:
+ virtual bool onEntityReplacement(const char name[],
+ SkString* replacement);
+
+public:
+ struct Curr {
+ EventType fEventType;
+ const char* fName;
+ AttrInfo* fAttrInfos;
+ int fAttrInfoCount;
+ bool fIsWhitespace;
+ };
+
+private:
+ // implemented in the porting layer
+ bool onInit(); // return false on failure
+ EventType onNextToken();
+ void onExit();
+
+ SkStream* fStream;
+ Curr fCurr;
+ int fDepth;
+
+ struct Impl;
+ Impl* fImpl;
+};
+#endif
+
+#endif
diff --git a/xml/SkXMLWriter.h b/xml/SkXMLWriter.h
new file mode 100644
index 0000000..214fefe
--- /dev/null
+++ b/xml/SkXMLWriter.h
@@ -0,0 +1,85 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkXMLWriter_DEFINED
+#define SkXMLWriter_DEFINED
+
+#include "SkTDArray.h"
+#include "SkString.h"
+#include "SkDOM.h"
+
+class SkWStream;
+class SkXMLParser;
+
+class SkXMLWriter {
+public:
+ SkXMLWriter(bool doEscapeMarkup = true);
+ virtual ~SkXMLWriter();
+
+ void addS32Attribute(const char name[], int32_t value);
+ void addAttribute(const char name[], const char value[]);
+ void addAttributeLen(const char name[], const char value[], size_t length);
+ void addHexAttribute(const char name[], uint32_t value, int minDigits = 0);
+ void addScalarAttribute(const char name[], SkScalar value);
+ void endElement() { this->onEndElement(); }
+ void startElement(const char elem[]);
+ void startElementLen(const char elem[], size_t length);
+ void writeDOM(const SkDOM&, const SkDOM::Node*, bool skipRoot);
+ void flush();
+ virtual void writeHeader();
+
+protected:
+ virtual void onStartElementLen(const char elem[], size_t length) = 0;
+ virtual void onAddAttributeLen(const char name[], const char value[], size_t length) = 0;
+ virtual void onEndElement() = 0;
+
+ struct Elem {
+ SkString fName;
+ bool fHasChildren;
+ };
+ void doEnd(Elem* elem);
+ bool doStart(const char name[], size_t length);
+ Elem* getEnd();
+ const char* getHeader();
+ SkTDArray<Elem*> fElems;
+
+private:
+ bool fDoEscapeMarkup;
+ // illegal
+ SkXMLWriter& operator=(const SkXMLWriter&);
+};
+
+class SkXMLStreamWriter : public SkXMLWriter {
+public:
+ SkXMLStreamWriter(SkWStream*);
+ virtual ~SkXMLStreamWriter();
+ virtual void writeHeader();
+ SkDEBUGCODE(static void UnitTest();)
+protected:
+ virtual void onStartElementLen(const char elem[], size_t length);
+ virtual void onEndElement();
+ virtual void onAddAttributeLen(const char name[], const char value[], size_t length);
+private:
+ SkWStream& fStream;
+};
+
+class SkXMLParserWriter : public SkXMLWriter {
+public:
+ SkXMLParserWriter(SkXMLParser*);
+ virtual ~SkXMLParserWriter();
+protected:
+ virtual void onStartElementLen(const char elem[], size_t length);
+ virtual void onEndElement();
+ virtual void onAddAttributeLen(const char name[], const char value[], size_t length);
+private:
+ SkXMLParser& fParser;
+};
+
+
+#endif